Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mailbox: pcc: Check before sending MCTP PCC response ACK

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>

authored by

Adam Young and committed by
Jassi Brar
7f9e19f2 81f939db

+60 -8
+53 -8
drivers/mailbox/pcc.c
··· 269 269 return !!val; 270 270 } 271 271 272 + static void check_and_ack(struct pcc_chan_info *pchan, struct mbox_chan *chan) 273 + { 274 + struct acpi_pcct_ext_pcc_shared_memory pcc_hdr; 275 + 276 + if (pchan->type != ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE) 277 + return; 278 + /* If the memory region has not been mapped, we cannot 279 + * determine if we need to send the message, but we still 280 + * need to set the cmd_update flag before returning. 281 + */ 282 + if (pchan->chan.shmem == NULL) { 283 + pcc_chan_reg_read_modify_write(&pchan->cmd_update); 284 + return; 285 + } 286 + memcpy_fromio(&pcc_hdr, pchan->chan.shmem, 287 + sizeof(struct acpi_pcct_ext_pcc_shared_memory)); 288 + /* 289 + * The PCC slave subspace channel needs to set the command complete bit 290 + * after processing message. If the PCC_ACK_FLAG is set, it should also 291 + * ring the doorbell. 292 + * 293 + * The PCC master subspace channel clears chan_in_use to free channel. 294 + */ 295 + if (le32_to_cpup(&pcc_hdr.flags) & PCC_ACK_FLAG_MASK) 296 + pcc_send_data(chan, NULL); 297 + else 298 + pcc_chan_reg_read_modify_write(&pchan->cmd_update); 299 + } 300 + 272 301 /** 273 302 * pcc_mbox_irq - PCC mailbox interrupt handler 274 303 * @irq: interrupt number ··· 335 306 336 307 mbox_chan_received_data(chan, NULL); 337 308 338 - /* 339 - * The PCC slave subspace channel needs to set the command complete bit 340 - * and ring doorbell after processing message. 341 - * 342 - * The PCC master subspace channel clears chan_in_use to free channel. 343 - */ 344 - if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE) 345 - pcc_send_data(chan, NULL); 309 + check_and_ack(pchan, chan); 346 310 pchan->chan_in_use = false; 347 311 348 312 return IRQ_HANDLED; ··· 387 365 void pcc_mbox_free_channel(struct pcc_mbox_chan *pchan) 388 366 { 389 367 struct mbox_chan *chan = pchan->mchan; 368 + struct pcc_chan_info *pchan_info; 369 + struct pcc_mbox_chan *pcc_mbox_chan; 390 370 391 371 if (!chan || !chan->cl) 392 372 return; 373 + pchan_info = chan->con_priv; 374 + pcc_mbox_chan = &pchan_info->chan; 375 + if (pcc_mbox_chan->shmem) { 376 + iounmap(pcc_mbox_chan->shmem); 377 + pcc_mbox_chan->shmem = NULL; 378 + } 393 379 394 380 mbox_free_channel(chan); 395 381 } 396 382 EXPORT_SYMBOL_GPL(pcc_mbox_free_channel); 383 + 384 + int pcc_mbox_ioremap(struct mbox_chan *chan) 385 + { 386 + struct pcc_chan_info *pchan_info; 387 + struct pcc_mbox_chan *pcc_mbox_chan; 388 + 389 + if (!chan || !chan->cl) 390 + return -1; 391 + pchan_info = chan->con_priv; 392 + pcc_mbox_chan = &pchan_info->chan; 393 + pcc_mbox_chan->shmem = ioremap(pcc_mbox_chan->shmem_base_addr, 394 + pcc_mbox_chan->shmem_size); 395 + return 0; 396 + } 397 + EXPORT_SYMBOL_GPL(pcc_mbox_ioremap); 397 398 398 399 /** 399 400 * pcc_send_data - Called from Mailbox Controller code. Used
+7
include/acpi/pcc.h
··· 12 12 struct pcc_mbox_chan { 13 13 struct mbox_chan *mchan; 14 14 u64 shmem_base_addr; 15 + void __iomem *shmem; 15 16 u64 shmem_size; 16 17 u32 latency; 17 18 u32 max_access_rate; ··· 32 31 #define PCC_CMD_COMPLETION_NOTIFY BIT(0) 33 32 34 33 #define MAX_PCC_SUBSPACES 256 34 + #define PCC_ACK_FLAG_MASK 0x1 35 35 36 36 #ifdef CONFIG_PCC 37 37 extern struct pcc_mbox_chan * 38 38 pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id); 39 39 extern void pcc_mbox_free_channel(struct pcc_mbox_chan *chan); 40 + extern int pcc_mbox_ioremap(struct mbox_chan *chan); 40 41 #else 41 42 static inline struct pcc_mbox_chan * 42 43 pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id) ··· 46 43 return ERR_PTR(-ENODEV); 47 44 } 48 45 static inline void pcc_mbox_free_channel(struct pcc_mbox_chan *chan) { } 46 + static inline int pcc_mbox_ioremap(struct mbox_chan *chan) 47 + { 48 + return 0; 49 + }; 49 50 #endif 50 51 51 52 #endif /* _PCC_H */