From 2c0ef634912b31677b70a615f3eb1348fb6faac4 Mon Sep 17 00:00:00 2001 From: Tom Saeger Date: Thu, 27 Apr 2023 18:43:56 +0800 Subject: [PATCH 01/18] mailbox: fix various typos in comments mainline inclusion from mainline-v5.13-rc1 commit 9d2e8b93236a45f20ae0b71cc507301111cc2f58 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I6Z91B CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.3-rc2&id=9d2e8b93236a45f20ae0b71cc507301111cc2f58 -------------------------------- Fix trivial typos in mailbox driver comments. s/Intergrated/Integrated/ s/extenstion/extension/ s/atleast/at least/ s/commnunication/communication/ s/assgined/assigned/ s/commnunication/communication/ s/recevied/received/ s/succeded/succeeded/ s/implmentation/implementation/ s/definiation/definition/ s/traget/target/ s/wont/won't/ Cc: trivial@kernel.org Signed-off-by: Tom Saeger Reviewed-by: Randy Dunlap Signed-off-by: Jassi Brar --- drivers/mailbox/Kconfig | 2 +- drivers/mailbox/bcm-flexrm-mailbox.c | 4 ++-- drivers/mailbox/mailbox-xgene-slimpro.c | 6 +++--- drivers/mailbox/mailbox.h | 2 +- drivers/mailbox/pcc.c | 2 +- drivers/mailbox/pl320-ipc.c | 2 +- drivers/mailbox/sprd-mailbox.c | 12 ++++++------ drivers/mailbox/ti-msgmgr.c | 2 +- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index 05b1009e2820..6e3ef446b0c9 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -71,7 +71,7 @@ config OMAP_MBOX_KFIFO_SIZE module parameter). config ROCKCHIP_MBOX - bool "Rockchip Soc Intergrated Mailbox Support" + bool "Rockchip Soc Integrated Mailbox Support" depends on ARCH_ROCKCHIP || COMPILE_TEST help This driver provides support for inter-processor communication diff --git a/drivers/mailbox/bcm-flexrm-mailbox.c b/drivers/mailbox/bcm-flexrm-mailbox.c index bee33abb5308..b4f33dc399a0 100644 --- a/drivers/mailbox/bcm-flexrm-mailbox.c +++ b/drivers/mailbox/bcm-flexrm-mailbox.c @@ -423,7 +423,7 @@ static void flexrm_enqueue_desc(u32 nhpos, u32 nhcnt, u32 reqid, * * In general use, number of non-HEADER descriptors can easily go * beyond 31. To tackle this situation, we have packet (or request) - * extenstion bits (STARTPKT and ENDPKT) in the HEADER descriptor. + * extension bits (STARTPKT and ENDPKT) in the HEADER descriptor. * * To use packet extension, the first HEADER descriptor of request * (or packet) will have STARTPKT=1 and ENDPKT=0. The intermediate @@ -1095,7 +1095,7 @@ static int flexrm_process_completions(struct flexrm_ring *ring) /* * Get current completion read and write offset * - * Note: We should read completion write pointer atleast once + * Note: We should read completion write pointer at least once * after we get a MSI interrupt because HW maintains internal * MSI status which will allow next MSI interrupt only after * completion write pointer is read. diff --git a/drivers/mailbox/mailbox-xgene-slimpro.c b/drivers/mailbox/mailbox-xgene-slimpro.c index de260799f1b9..5b3a2dcd5955 100644 --- a/drivers/mailbox/mailbox-xgene-slimpro.c +++ b/drivers/mailbox/mailbox-xgene-slimpro.c @@ -51,10 +51,10 @@ struct slimpro_mbox_chan { /** * X-Gene SlimPRO Mailbox controller data * - * X-Gene SlimPRO Mailbox controller has 8 commnunication channels. - * Each channel has a separate IRQ number assgined to it. + * X-Gene SlimPRO Mailbox controller has 8 communication channels. + * Each channel has a separate IRQ number assigned to it. * - * @mb_ctrl: Representation of the commnunication channel controller + * @mb_ctrl: Representation of the communication channel controller * @mc: Array of SlimPRO mailbox channels of the controller * @chans: Array of mailbox communication channels * diff --git a/drivers/mailbox/mailbox.h b/drivers/mailbox/mailbox.h index 4e3cc4426513..046d6d258b32 100644 --- a/drivers/mailbox/mailbox.h +++ b/drivers/mailbox/mailbox.h @@ -5,6 +5,6 @@ #define TXDONE_BY_IRQ BIT(0) /* controller has remote RTR irq */ #define TXDONE_BY_POLL BIT(1) /* controller can read status of last TX */ -#define TXDONE_BY_ACK BIT(2) /* S/W ACK recevied by Client ticks the TX */ +#define TXDONE_BY_ACK BIT(2) /* S/W ACK received by Client ticks the TX */ #endif /* __MAILBOX_H */ diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c index ef9ecd1f5958..9cb1dcf47661 100644 --- a/drivers/mailbox/pcc.c +++ b/drivers/mailbox/pcc.c @@ -32,7 +32,7 @@ * * Client writes WRITE cmd in communication region cmd address. * * Client issues mbox_send_message() which rings the PCC doorbell * for its PCC channel. - * * If command completes, then writes have succeded and it can release + * * If command completes, then writes have succeeded and it can release * the channel lock. * * There is a Nominal latency defined for each channel which indicates diff --git a/drivers/mailbox/pl320-ipc.c b/drivers/mailbox/pl320-ipc.c index 25e0b6f7a10f..fbcf07930390 100644 --- a/drivers/mailbox/pl320-ipc.c +++ b/drivers/mailbox/pl320-ipc.c @@ -73,7 +73,7 @@ static u32 __ipc_rcv(int mbox, u32 *data) return data[1]; } -/* blocking implmentation from the A9 side, not usuable in interrupts! */ +/* blocking implementation from the A9 side, not usable in interrupts! */ int pl320_ipc_transmit(u32 *data) { int ret; diff --git a/drivers/mailbox/sprd-mailbox.c b/drivers/mailbox/sprd-mailbox.c index 94d9067dc8d0..be0bca9837c4 100644 --- a/drivers/mailbox/sprd-mailbox.c +++ b/drivers/mailbox/sprd-mailbox.c @@ -25,28 +25,28 @@ #define SPRD_MBOX_LOCK 0x20 #define SPRD_MBOX_FIFO_DEPTH 0x24 -/* Bit and mask definiation for inbox's SPRD_MBOX_FIFO_STS register */ +/* Bit and mask definition for inbox's SPRD_MBOX_FIFO_STS register */ #define SPRD_INBOX_FIFO_DELIVER_MASK GENMASK(23, 16) #define SPRD_INBOX_FIFO_OVERLOW_MASK GENMASK(15, 8) #define SPRD_INBOX_FIFO_DELIVER_SHIFT 16 #define SPRD_INBOX_FIFO_BUSY_MASK GENMASK(7, 0) -/* Bit and mask definiation for SPRD_MBOX_IRQ_STS register */ +/* Bit and mask definition for SPRD_MBOX_IRQ_STS register */ #define SPRD_MBOX_IRQ_CLR BIT(0) -/* Bit and mask definiation for outbox's SPRD_MBOX_FIFO_STS register */ +/* Bit and mask definition for outbox's SPRD_MBOX_FIFO_STS register */ #define SPRD_OUTBOX_FIFO_FULL BIT(2) #define SPRD_OUTBOX_FIFO_WR_SHIFT 16 #define SPRD_OUTBOX_FIFO_RD_SHIFT 24 #define SPRD_OUTBOX_FIFO_POS_MASK GENMASK(7, 0) -/* Bit and mask definiation for inbox's SPRD_MBOX_IRQ_MSK register */ +/* Bit and mask definition for inbox's SPRD_MBOX_IRQ_MSK register */ #define SPRD_INBOX_FIFO_BLOCK_IRQ BIT(0) #define SPRD_INBOX_FIFO_OVERFLOW_IRQ BIT(1) #define SPRD_INBOX_FIFO_DELIVER_IRQ BIT(2) #define SPRD_INBOX_FIFO_IRQ_MASK GENMASK(2, 0) -/* Bit and mask definiation for outbox's SPRD_MBOX_IRQ_MSK register */ +/* Bit and mask definition for outbox's SPRD_MBOX_IRQ_MSK register */ #define SPRD_OUTBOX_FIFO_NOT_EMPTY_IRQ BIT(0) #define SPRD_OUTBOX_FIFO_IRQ_MASK GENMASK(4, 0) @@ -156,7 +156,7 @@ static irqreturn_t sprd_mbox_inbox_isr(int irq, void *data) chan = &priv->chan[id]; /* - * Check if the message was fetched by remote traget, if yes, + * Check if the message was fetched by remote target, if yes, * that means the transmission has been completed. */ busy = fifo_sts & SPRD_INBOX_FIFO_BUSY_MASK; diff --git a/drivers/mailbox/ti-msgmgr.c b/drivers/mailbox/ti-msgmgr.c index 0130628f4d9d..efb43b038596 100644 --- a/drivers/mailbox/ti-msgmgr.c +++ b/drivers/mailbox/ti-msgmgr.c @@ -239,7 +239,7 @@ static irqreturn_t ti_msgmgr_queue_rx_interrupt(int irq, void *p) /* * I have no idea about the protocol being used to communicate with the - * remote producer - 0 could be valid data, so I wont make a judgement + * remote producer - 0 could be valid data, so I won't make a judgement * of how many bytes I should be reading. Let the client figure this * out.. I just read the full message and pass it on.. */ -- Gitee From 55d7ee6b634d7030fc1cce5dac7a5b00085bb0db Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Thu, 27 Apr 2023 18:43:57 +0800 Subject: [PATCH 02/18] mailbox: pcc: Refactor all PCC channel information into a structure mainline inclusion from mainline-v5.16-rc1 commit 80b2bdde002c521284ce472a849784f599626276 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I6Z91B CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.3-rc2&id=80b2bdde002c521284ce472a849784f599626276 -------------------------------- 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 Signed-off-by: Jassi Brar --- 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 9cb1dcf47661..b53297ad8436 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 = {}; /** @@ -179,6 +187,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; @@ -193,17 +202,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); @@ -228,8 +237,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; @@ -247,6 +257,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; @@ -260,14 +271,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); } @@ -286,6 +297,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) @@ -296,8 +308,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; @@ -325,6 +338,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; @@ -336,19 +350,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) @@ -394,12 +409,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; @@ -409,10 +425,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; } @@ -470,24 +486,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)); @@ -497,6 +501,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; @@ -518,8 +523,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); } @@ -531,11 +536,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: -- Gitee From 9c6959eccf0c11f991e10043a4b671e72e6fa21c Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Thu, 27 Apr 2023 18:43:58 +0800 Subject: [PATCH 03/18] mailbox: pcc: Consolidate subspace interrupt information parsing mainline inclusion from mainline-v5.16-rc1 commit 319bfb35bd1dbc1b67e577c9893b9e8b29650b19 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I6Z91B CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.3-rc2&id=319bfb35bd1dbc1b67e577c9893b9e8b29650b19 -------------------------------- 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 Signed-off-by: Sudeep Holla Signed-off-by: Jassi Brar --- 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 b53297ad8436..e3aa67f7b183 100644 --- a/drivers/mailbox/pcc.c +++ b/drivers/mailbox/pcc.c @@ -401,18 +401,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) { @@ -421,8 +429,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 = @@ -506,17 +513,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; -- Gitee From 33a989a1b1c2090b69d8957792879e2708e34ef9 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Thu, 27 Apr 2023 18:43:59 +0800 Subject: [PATCH 04/18] mailbox: pcc: Consolidate subspace doorbell register parsing mainline inclusion from mainline-v5.16-rc1 commit 4e3c96ff950ed2bf0f8ef24bd54ec134e2717c55 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I6Z91B CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.3-rc2&id=4e3c96ff950ed2bf0f8ef24bd54ec134e2717c55 -------------------------------- 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 Signed-off-by: Sudeep Holla Signed-off-by: Jassi Brar --- 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 e3aa67f7b183..98f9a0c0bcdf 100644 --- a/drivers/mailbox/pcc.c +++ b/drivers/mailbox/pcc.c @@ -444,6 +444,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. * @@ -509,8 +531,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) { @@ -518,13 +538,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); } -- Gitee From c94687ac98919645332c54d121982f2d5add091d Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Thu, 27 Apr 2023 18:44:00 +0800 Subject: [PATCH 05/18] mailbox: pcc: Add pcc_mbox_chan structure to hold shared memory region info mainline inclusion from mainline-v5.16-rc1 commit 0f2591e21b2e85c05e2aa74d4703189fd3a57526 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I6Z91B CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.3-rc2&id=0f2591e21b2e85c05e2aa74d4703189fd3a57526 -------------------------------- 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 Signed-off-by: Sudeep Holla Signed-off-by: Jassi Brar --- 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 98f9a0c0bcdf..2909136c4cc4 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; @@ -466,6 +468,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. * @@ -533,6 +556,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) @@ -540,6 +565,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 #include +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, -- Gitee From 94e62591cc3bc63746ffb48486bf8069f64fe880 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Thu, 27 Apr 2023 18:44:01 +0800 Subject: [PATCH 06/18] mailbox: pcc: Use PCC mailbox channel pointer instead of standard mainline inclusion from mainline-v5.16-rc1 commit 7b6da7fe7bba1cdccdda871bf393b855e59404c3 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I6Z91B CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.3-rc2&id=7b6da7fe7bba1cdccdda871bf393b855e59404c3 -------------------------------- 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 Signed-off-by: Sudeep Holla Acked-by: Wolfram Sang Acked-by: Guenter Roeck Signed-off-by: Jassi Brar --- 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 a190634b338e..43342146824a 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c @@ -43,7 +43,7 @@ #include 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) { @@ -598,46 +598,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 f5d3cf86753f..9c37e2afc557 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); @@ -774,7 +765,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 63cbb9c7c1b0..a7c24396f764 100644 --- a/drivers/i2c/busses/i2c-xgene-slimpro.c +++ b/drivers/i2c/busses/i2c-xgene-slimpro.c @@ -104,6 +104,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; @@ -467,7 +468,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; @@ -484,24 +485,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"); @@ -513,17 +504,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"); @@ -562,7 +553,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; } @@ -576,7 +567,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 2909136c4cc4..01e4824da1b6 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 @@ -235,31 +220,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; @@ -281,38 +260,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 */ -- Gitee From 76b5c1381d9118ef2c333af173ac5621fc57d6dd Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Thu, 27 Apr 2023 18:44:02 +0800 Subject: [PATCH 07/18] mailbox: pcc: Rename doorbell ack to platform interrupt ack register mainline inclusion from mainline-v5.16-rc1 commit f92ae90e52bb09d6856ef2785773be59dd633f85 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I6Z91B CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.3-rc2&id=f92ae90e52bb09d6856ef2785773be59dd633f85 -------------------------------- 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 Signed-off-by: Jassi Brar --- 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 01e4824da1b6..777a7b38bb6c 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) @@ -194,12 +195,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); @@ -252,14 +253,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); } @@ -284,8 +285,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; @@ -396,9 +397,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; @@ -407,10 +408,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; } -- Gitee From d7aab10853bba6f08beffa9ab14d593bdbf53e4e Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Thu, 27 Apr 2023 18:44:03 +0800 Subject: [PATCH 08/18] mailbox: pcc: Add PCC register bundle and associated accessor functions mainline inclusion from mainline-v5.16-rc1 commit 800cda7b63f22be62e67142f1202d2ead2dff2e8 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I6Z91B CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.3-rc2&id=800cda7b63f22be62e67142f1202d2ead2dff2e8 -------------------------------- 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 Signed-off-by: Jassi Brar --- drivers/mailbox/pcc.c | 90 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c index 777a7b38bb6c..0f230ae3c49b 100644 --- a/drivers/mailbox/pcc.c +++ b/drivers/mailbox/pcc.c @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -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. @@ -375,6 +440,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 * -- Gitee From 0ccf8aa8333a6309f18f8744a7595d5a7492636d Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Thu, 27 Apr 2023 18:44:04 +0800 Subject: [PATCH 09/18] mailbox: pcc: Avoid accessing PCCT table in pcc_send_data and pcc_mbox_irq mainline inclusion from mainline-v5.16-rc1 commit bf18123e78f4d13fc0105b1ddb4b46c1665dd025 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I6Z91B CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.3-rc2&id=bf18123e78f4d13fc0105b1ddb4b46c1665dd025 -------------------------------- 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 Signed-off-by: Sudeep Holla Signed-off-by: Jassi Brar --- 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 0f230ae3c49b..002216a4a008 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; }; @@ -238,40 +238,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; } @@ -377,42 +352,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 = { @@ -480,6 +422,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 || @@ -498,16 +441,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; } /** @@ -516,20 +457,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; } /** @@ -618,8 +561,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) { @@ -627,7 +570,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); -- Gitee From 538efe978bdad1e6e262cb9a1d8233e8040d0ca2 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Thu, 27 Apr 2023 18:44:05 +0800 Subject: [PATCH 10/18] mailbox: pcc: Drop handling invalid bit-width in {read,write}_register mainline inclusion from mainline-v5.16-rc1 commit 45ec2dafb1775f7d806fbd2387e3f2cc2f56142d category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I6Z91B CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.3-rc2&id=45ec2dafb1775f7d806fbd2387e3f2cc2f56142d -------------------------------- 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 Signed-off-by: Jassi Brar --- 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 002216a4a008..3c9e7c9679a2 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); -- Gitee From 749238e0ed252ce3811a51d3facf1fc57e7441b6 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Thu, 27 Apr 2023 18:44:06 +0800 Subject: [PATCH 11/18] mailbox: pcc: Add support for PCCT extended PCC subspaces(type 3/4) mainline inclusion from mainline-v5.16-rc1 commit c45ded7e11352d7ba0bfe3cbf2625f96f94c7d92 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I6Z91B CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.3-rc2&id=c45ded7e11352d7ba0bfe3cbf2625f96f94c7d92 -------------------------------- 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 Signed-off-by: Jassi Brar --- 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 3c9e7c9679a2..9c3519e0a7c3 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; }; @@ -224,9 +230,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; @@ -336,8 +362,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); } @@ -430,6 +461,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; @@ -448,14 +489,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; } @@ -469,15 +544,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; + } } /** @@ -549,6 +634,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) -- Gitee From 78d38847d97740da36e732d11abec61bcca7a520 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Thu, 27 Apr 2023 18:44:07 +0800 Subject: [PATCH 12/18] mailbox: pcc: Move bulk of PCCT parsing into pcc_mbox_probe mainline inclusion from mainline-v5.16-rc1 commit ce028702ddbc69743d958f9e20ad0306e4a428fe category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I6Z91B CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.3-rc2&id=ce028702ddbc69743d958f9e20ad0306e4a428fe -------------------------------- 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 Signed-off-by: Jassi Brar --- 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 9c3519e0a7c3..43fb124463f5 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 @@ -277,11 +275,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; @@ -290,6 +288,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; @@ -572,16 +571,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; @@ -603,21 +598,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 */ @@ -626,7 +660,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; @@ -635,13 +669,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; @@ -656,51 +690,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 = { -- Gitee From 2f4c1fc1f72b18c2c2b11ec970949ba92a1c1ab4 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Thu, 27 Apr 2023 18:44:08 +0800 Subject: [PATCH 13/18] mailbox: pcc: Avoid using the uninitialized variable 'dev' mainline inclusion from mainline-v5.17-rc1 commit 960c4056aadcf61983f8eaac159927a052f8cf01 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I6Z91B CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.3-rc2&id=960c4056aadcf61983f8eaac159927a052f8cf01 -------------------------------- Smatch static checker warns: | drivers/mailbox/pcc.c:292 pcc_mbox_request_channel() | error: uninitialized symbol 'dev'. Fix the same by using pr_err instead of dev_err as the variable 'dev' is uninitialized at that stage. Fixes: ce028702ddbc ("mailbox: pcc: Move bulk of PCCT parsing into pcc_mbox_probe") Cc: Jassi Brar Reported-by: Dan Carpenter Signed-off-by: Sudeep Holla Signed-off-by: Jassi Brar --- drivers/mailbox/pcc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c index 43fb124463f5..52ffa79c91a8 100644 --- a/drivers/mailbox/pcc.c +++ b/drivers/mailbox/pcc.c @@ -285,7 +285,7 @@ pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id) 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); + pr_err("Channel not found for idx: %d\n", subspace_id); return ERR_PTR(-EBUSY); } dev = chan->mbox->dev; -- Gitee From 88e27f53612eaf675da3a1a6e3359b7a0ec1eab5 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Thu, 27 Apr 2023 18:44:09 +0800 Subject: [PATCH 14/18] mailbox: pcc: Handle all PCC subtypes correctly in pcc_mbox_irq mainline inclusion from mainline-v5.17-rc1 commit 7215a7857e796c655ae1184b313556102fa8bc40 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I6Z91B CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.3-rc2&id=7215a7857e796c655ae1184b313556102fa8bc40 -------------------------------- Commit c45ded7e1135 ("mailbox: pcc: Add support for PCCT extended PCC subspaces(type 3/4)") enabled the type3/4 of PCCT, but the change in pcc_mbox_irq breaks the other PCC subtypes. The kernel reports a warning on an Ampere eMag server -->8 CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.16.0-rc4 #127 Hardware name: MiTAC RAPTOR EV-883832-X3-0001/RAPTOR, BIOS 0.14 02/22/2019 Call trace: dump_backtrace+0x0/0x200 show_stack+0x20/0x30 dump_stack_lvl+0x68/0x84 dump_stack+0x18/0x34 __report_bad_irq+0x54/0x17c note_interrupt+0x330/0x428 handle_irq_event_percpu+0x90/0x98 handle_irq_event+0x4c/0x148 handle_fasteoi_irq+0xc4/0x188 generic_handle_domain_irq+0x44/0x68 gic_handle_irq+0x84/0x2ec call_on_irq_stack+0x28/0x34 do_interrupt_handler+0x88/0x90 el1_interrupt+0x48/0xb0 el1h_64_irq_handler+0x18/0x28 el1h_64_irq+0x7c/0x80 Fixes: c45ded7e1135 ("mailbox: pcc: Add support for PCCT extended PCC subspaces(type 3/4)") Reported-by: Justin He Tested-by: Justin He Signed-off-by: Sudeep Holla Signed-off-by: Jassi Brar --- drivers/mailbox/pcc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c index 52ffa79c91a8..e2ebcf09dcb3 100644 --- a/drivers/mailbox/pcc.c +++ b/drivers/mailbox/pcc.c @@ -237,9 +237,11 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p) if (ret) return IRQ_NONE; - val &= pchan->cmd_complete.status_mask; - if (!val) - return IRQ_NONE; + if (val) { /* Ensure GAS exists and value is non-zero */ + val &= pchan->cmd_complete.status_mask; + if (!val) + return IRQ_NONE; + } ret = pcc_chan_reg_read(&pchan->error, &val); if (ret) -- Gitee From 4bfb77c30b73fa890ebb1adc02ed0e8037ffb12a Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 27 Apr 2023 18:44:10 +0800 Subject: [PATCH 15/18] mailbox: pcc: Fix an invalid-load caught by the address sanitizer mainline inclusion from mainline-v5.19-rc1 commit 369e4ef87a8f5da7c348ec2c61ec5cd726e8337a category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I6Z91B CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.3-rc2&id=369e4ef87a8f5da7c348ec2c61ec5cd726e8337a -------------------------------- `pcc_mailbox_probe` doesn't initialize all memory that has been allocated before the first time that one of it's members `txdone_irq` may be accessed. This leads to a an invalid load any time that this member is accessed: [ 2.429769] UBSAN: invalid-load in drivers/mailbox/pcc.c:684:22 [ 2.430324] UBSAN: invalid-load in drivers/mailbox/mailbox.c:486:12 [ 4.276782] UBSAN: invalid-load in drivers/acpi/cppc_acpi.c:314:45 Link: https://bugzilla.kernel.org/show_bug.cgi?id=215587 Fixes: ce028702ddbc ("mailbox: pcc: Move bulk of PCCT parsing into pcc_mbox_probe") Signed-off-by: Mario Limonciello Reviewed-by: Sudeep Holla Signed-off-by: Jassi Brar --- drivers/mailbox/pcc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c index e2ebcf09dcb3..fdc086cdf4a3 100644 --- a/drivers/mailbox/pcc.c +++ b/drivers/mailbox/pcc.c @@ -650,7 +650,7 @@ static int pcc_mbox_probe(struct platform_device *pdev) goto err; } - pcc_mbox_ctrl = devm_kmalloc(dev, sizeof(*pcc_mbox_ctrl), GFP_KERNEL); + pcc_mbox_ctrl = devm_kzalloc(dev, sizeof(*pcc_mbox_ctrl), GFP_KERNEL); if (!pcc_mbox_ctrl) { rc = -ENOMEM; goto err; -- Gitee From 0ace3001b3034bfbe919c9c5ffbeab8a2aff5d6d Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 27 Apr 2023 18:44:11 +0800 Subject: [PATCH 16/18] mailbox: pcc: Fix spelling mistake "Plaform" -> "Platform" mainline inclusion from mainline-v6.1-rc1 commit 8ac1111055afc863c78e389b051d843babbf2ca9 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I6Z91B CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.3-rc2&id=8ac1111055afc863c78e389b051d843babbf2ca9 -------------------------------- There is a spelling mistake in a pr_err message. Fix it. Signed-off-by: Colin Ian King Signed-off-by: Jassi Brar --- drivers/mailbox/pcc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c index fdc086cdf4a3..dfb74feaf64a 100644 --- a/drivers/mailbox/pcc.c +++ b/drivers/mailbox/pcc.c @@ -672,7 +672,7 @@ static int pcc_mbox_probe(struct platform_device *pdev) 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"); + pr_err("Platform Interrupt flag must be set to 1"); rc = -EINVAL; goto err; } -- Gitee From c0dfceed1f71093a6e815c76978326d8fed8271f Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 27 Apr 2023 18:44:12 +0800 Subject: [PATCH 17/18] i2c: xgene-slimpro: Fix wrong pointer passed to PTR_ERR() mainline inclusion from mainline-v5.16-rc1 commit c80be257a4cd0f72c083e6056ff0ce2da871e9dc category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I6Z91B CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.3-rc2&id=c80be257a4cd0f72c083e6056ff0ce2da871e9dc -------------------------------- PTR_ERR should access the value just tested by IS_ERR, otherwise the wrong error code will be returned. Fixes: 7b6da7fe7bba ("mailbox: pcc: Use PCC mailbox channel pointer instead of standard") Reported-by: Hulk Robot Signed-off-by: Wei Yongjun Reviewed-by: Sudeep Holla Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-xgene-slimpro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-xgene-slimpro.c b/drivers/i2c/busses/i2c-xgene-slimpro.c index a7c24396f764..35b0e1313aab 100644 --- a/drivers/i2c/busses/i2c-xgene-slimpro.c +++ b/drivers/i2c/busses/i2c-xgene-slimpro.c @@ -488,7 +488,7 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev) 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->pcc_chan); + return PTR_ERR(pcc_chan); } ctx->pcc_chan = pcc_chan; -- Gitee From 1fc023e354c725fa3f232dcdd728a8e069639f56 Mon Sep 17 00:00:00 2001 From: Huisong Li Date: Thu, 27 Apr 2023 18:44:13 +0800 Subject: [PATCH 18/18] mailbox: pcc: Reset pcc_chan_count to zero in case of PCC probe failure mainline inclusion from mainline-v6.2-rc1 commit 6d7d3c287410c0ad499e478e2338dc3d7e3392b1 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I6Z91B CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.3-rc2&id=6d7d3c287410c0ad499e478e2338dc3d7e3392b1 -------------------------------- Currently, 'pcc_chan_count' is remains set to a non-zero value if PCC subspaces are parsed successfully but something else fail later during the initial PCC probing phase. This will result in pcc_mbox_request_channel trying to access the resources that are not initialised or allocated and may end up in a system crash. Reset pcc_chan_count to 0 when the PCC probe fails in order to prevent the possible issue as described above. Fixes: ce028702ddbc ("mailbox: pcc: Move bulk of PCCT parsing into pcc_mbox_probe") Signed-off-by: Huisong Li Reviewed-by: Sudeep Holla --- drivers/mailbox/pcc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c index dfb74feaf64a..a5d54311e02a 100644 --- a/drivers/mailbox/pcc.c +++ b/drivers/mailbox/pcc.c @@ -740,6 +740,7 @@ static int __init pcc_init(void) if (IS_ERR(pcc_pdev)) { pr_debug("Err creating PCC platform bundle\n"); + pcc_chan_count = 0; return PTR_ERR(pcc_pdev); } -- Gitee