Skip to content
/ linux Public
forked from torvalds/linux

Commit

Permalink
mailbox: pcc: Check before sending MCTP PCC response ACK
Browse files Browse the repository at this point in the history
[ Upstream commit 7f9e19f ]

Type 4 PCC channels have an option to send back a response
to the platform when they are done processing the request.
The flag to indicate whether or not to respond is inside
the message body, and thus is not available to the pcc
mailbox.

If the flag is not set, still set command completion
bit after processing message.

In order to read the flag, this patch maps the shared
buffer to virtual memory. To avoid duplication of mapping
the shared buffer is then made available to be used by
the driver that uses the mailbox.

Signed-off-by: Adam Young <admiyo@os.amperecomputing.com>
Cc: Sudeep Holla <sudeep.holla@arm.com>
Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
Adam Young authored and gregkh committed Dec 12, 2024
1 parent dbf58f3 commit 009ce5d
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 8 deletions.
61 changes: 53 additions & 8 deletions drivers/mailbox/pcc.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,35 @@ static bool pcc_mbox_cmd_complete_check(struct pcc_chan_info *pchan)
return !!val;
}

static void check_and_ack(struct pcc_chan_info *pchan, struct mbox_chan *chan)
{
struct acpi_pcct_ext_pcc_shared_memory pcc_hdr;

if (pchan->type != ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE)
return;
/* If the memory region has not been mapped, we cannot
* determine if we need to send the message, but we still
* need to set the cmd_update flag before returning.
*/
if (pchan->chan.shmem == NULL) {
pcc_chan_reg_read_modify_write(&pchan->cmd_update);
return;
}
memcpy_fromio(&pcc_hdr, pchan->chan.shmem,
sizeof(struct acpi_pcct_ext_pcc_shared_memory));
/*
* The PCC slave subspace channel needs to set the command complete bit
* after processing message. If the PCC_ACK_FLAG is set, it should also
* ring the doorbell.
*
* The PCC master subspace channel clears chan_in_use to free channel.
*/
if (le32_to_cpup(&pcc_hdr.flags) & PCC_ACK_FLAG_MASK)
pcc_send_data(chan, NULL);
else
pcc_chan_reg_read_modify_write(&pchan->cmd_update);
}

/**
* pcc_mbox_irq - PCC mailbox interrupt handler
* @irq: interrupt number
Expand Down Expand Up @@ -306,14 +335,7 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p)

mbox_chan_received_data(chan, NULL);

/*
* The PCC slave subspace channel needs to set the command complete bit
* and ring doorbell after processing message.
*
* The PCC master subspace channel clears chan_in_use to free channel.
*/
if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE)
pcc_send_data(chan, NULL);
check_and_ack(pchan, chan);
pchan->chan_in_use = false;

return IRQ_HANDLED;
Expand Down Expand Up @@ -365,14 +387,37 @@ EXPORT_SYMBOL_GPL(pcc_mbox_request_channel);
void pcc_mbox_free_channel(struct pcc_mbox_chan *pchan)
{
struct mbox_chan *chan = pchan->mchan;
struct pcc_chan_info *pchan_info;
struct pcc_mbox_chan *pcc_mbox_chan;

if (!chan || !chan->cl)
return;
pchan_info = chan->con_priv;
pcc_mbox_chan = &pchan_info->chan;
if (pcc_mbox_chan->shmem) {
iounmap(pcc_mbox_chan->shmem);
pcc_mbox_chan->shmem = NULL;
}

mbox_free_channel(chan);
}
EXPORT_SYMBOL_GPL(pcc_mbox_free_channel);

int pcc_mbox_ioremap(struct mbox_chan *chan)
{
struct pcc_chan_info *pchan_info;
struct pcc_mbox_chan *pcc_mbox_chan;

if (!chan || !chan->cl)
return -1;
pchan_info = chan->con_priv;
pcc_mbox_chan = &pchan_info->chan;
pcc_mbox_chan->shmem = ioremap(pcc_mbox_chan->shmem_base_addr,
pcc_mbox_chan->shmem_size);
return 0;
}
EXPORT_SYMBOL_GPL(pcc_mbox_ioremap);

/**
* pcc_send_data - Called from Mailbox Controller code. Used
* here only to ring the channel doorbell. The PCC client
Expand Down
7 changes: 7 additions & 0 deletions include/acpi/pcc.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
struct pcc_mbox_chan {
struct mbox_chan *mchan;
u64 shmem_base_addr;
void __iomem *shmem;
u64 shmem_size;
u32 latency;
u32 max_access_rate;
Expand All @@ -31,18 +32,24 @@ struct pcc_mbox_chan {
#define PCC_CMD_COMPLETION_NOTIFY BIT(0)

#define MAX_PCC_SUBSPACES 256
#define PCC_ACK_FLAG_MASK 0x1

#ifdef CONFIG_PCC
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);
extern int pcc_mbox_ioremap(struct mbox_chan *chan);
#else
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 pcc_mbox_chan *chan) { }
static inline int pcc_mbox_ioremap(struct mbox_chan *chan)
{
return 0;
};
#endif

#endif /* _PCC_H */

0 comments on commit 009ce5d

Please sign in to comment.