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

mailbox/pcc: support mailbox management of the shared buffer

Define a new, optional, callback that allows the driver to
specify how the return data buffer is allocated. If that callback
is set, mailbox/pcc.c is now responsible for reading from and
writing to the PCC shared buffer.

This also allows for proper checks of the Commnand complete flag
between the PCC sender and receiver.

For Type 4 channels, initialize the command complete flag prior
to accepting messages.

Since the mailbox does not know what memory allocation scheme
to use for response messages, the client now has an optional
callback that allows it to allocate the buffer for a response
message.

When an outbound message is written to the buffer, the mailbox
checks for the flag indicating the client wants an tx complete
notification via IRQ. Upon receipt of the interrupt It will
pair it with the outgoing message. The expected use is to
free the kernel memory buffer for the previous outgoing message.

Signed-off-by: Adam Young <admiyo@os.amperecomputing.com>
Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>

authored by

Adam Young and committed by
Jassi Brar
5378bdf6 75f1fbc9

+127 -4
+98 -4
drivers/mailbox/pcc.c
··· 306 306 pcc_chan_reg_read_modify_write(&pchan->db); 307 307 } 308 308 309 + static void *write_response(struct pcc_chan_info *pchan) 310 + { 311 + struct pcc_header pcc_header; 312 + void *buffer; 313 + int data_len; 314 + 315 + memcpy_fromio(&pcc_header, pchan->chan.shmem, 316 + sizeof(pcc_header)); 317 + data_len = pcc_header.length - sizeof(u32) + sizeof(struct pcc_header); 318 + 319 + buffer = pchan->chan.rx_alloc(pchan->chan.mchan->cl, data_len); 320 + if (buffer != NULL) 321 + memcpy_fromio(buffer, pchan->chan.shmem, data_len); 322 + return buffer; 323 + } 324 + 309 325 /** 310 326 * pcc_mbox_irq - PCC mailbox interrupt handler 311 327 * @irq: interrupt number ··· 333 317 { 334 318 struct pcc_chan_info *pchan; 335 319 struct mbox_chan *chan = p; 320 + struct pcc_header *pcc_header = chan->active_req; 321 + void *handle = NULL; 336 322 337 323 pchan = chan->con_priv; 338 324 ··· 358 340 * required to avoid any possible race in updatation of this flag. 359 341 */ 360 342 pchan->chan_in_use = false; 361 - mbox_chan_received_data(chan, NULL); 343 + 344 + if (pchan->chan.rx_alloc) 345 + handle = write_response(pchan); 346 + 347 + if (chan->active_req) { 348 + pcc_header = chan->active_req; 349 + if (pcc_header->flags & PCC_CMD_COMPLETION_NOTIFY) 350 + mbox_chan_txdone(chan, 0); 351 + } 352 + 353 + mbox_chan_received_data(chan, handle); 362 354 363 355 pcc_chan_acknowledge(pchan); 364 356 ··· 412 384 pcc_mchan = &pchan->chan; 413 385 pcc_mchan->shmem = acpi_os_ioremap(pcc_mchan->shmem_base_addr, 414 386 pcc_mchan->shmem_size); 415 - if (pcc_mchan->shmem) 416 - return pcc_mchan; 387 + if (!pcc_mchan->shmem) 388 + goto err; 417 389 390 + pcc_mchan->manage_writes = false; 391 + 392 + /* This indicates that the channel is ready to accept messages. 393 + * This needs to happen after the channel has registered 394 + * its callback. There is no access point to do that in 395 + * the mailbox API. That implies that the mailbox client must 396 + * have set the allocate callback function prior to 397 + * sending any messages. 398 + */ 399 + if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE) 400 + pcc_chan_reg_read_modify_write(&pchan->cmd_update); 401 + 402 + return pcc_mchan; 403 + 404 + err: 418 405 mbox_free_channel(chan); 419 406 return ERR_PTR(-ENXIO); 420 407 } ··· 460 417 } 461 418 EXPORT_SYMBOL_GPL(pcc_mbox_free_channel); 462 419 420 + static int pcc_write_to_buffer(struct mbox_chan *chan, void *data) 421 + { 422 + struct pcc_chan_info *pchan = chan->con_priv; 423 + struct pcc_mbox_chan *pcc_mbox_chan = &pchan->chan; 424 + struct pcc_header *pcc_header = data; 425 + 426 + if (!pchan->chan.manage_writes) 427 + return 0; 428 + 429 + /* The PCC header length includes the command field 430 + * but not the other values from the header. 431 + */ 432 + int len = pcc_header->length - sizeof(u32) + sizeof(struct pcc_header); 433 + u64 val; 434 + 435 + pcc_chan_reg_read(&pchan->cmd_complete, &val); 436 + if (!val) { 437 + pr_info("%s pchan->cmd_complete not set", __func__); 438 + return -1; 439 + } 440 + memcpy_toio(pcc_mbox_chan->shmem, data, len); 441 + return 0; 442 + } 443 + 444 + 463 445 /** 464 - * pcc_send_data - Called from Mailbox Controller code. Used 446 + * pcc_send_data - Called from Mailbox Controller code. If 447 + * pchan->chan.rx_alloc is set, then the command complete 448 + * flag is checked and the data is written to the shared 449 + * buffer io memory. 450 + * 451 + * If pchan->chan.rx_alloc is not set, then it is used 465 452 * here only to ring the channel doorbell. The PCC client 466 453 * specific read/write is done in the client driver in 467 454 * order to maintain atomicity over PCC channel once ··· 507 434 int ret; 508 435 struct pcc_chan_info *pchan = chan->con_priv; 509 436 437 + ret = pcc_write_to_buffer(chan, data); 438 + if (ret) 439 + return ret; 440 + 510 441 ret = pcc_chan_reg_read_modify_write(&pchan->cmd_update); 511 442 if (ret) 512 443 return ret; 513 444 514 445 ret = pcc_chan_reg_read_modify_write(&pchan->db); 446 + 515 447 if (!ret && pchan->plat_irq > 0) 516 448 pchan->chan_in_use = true; 517 449 518 450 return ret; 519 451 } 452 + 453 + 454 + static bool pcc_last_tx_done(struct mbox_chan *chan) 455 + { 456 + struct pcc_chan_info *pchan = chan->con_priv; 457 + u64 val; 458 + 459 + pcc_chan_reg_read(&pchan->cmd_complete, &val); 460 + if (!val) 461 + return false; 462 + else 463 + return true; 464 + } 465 + 466 + 520 467 521 468 /** 522 469 * pcc_startup - Called from Mailbox Controller code. Used here ··· 583 490 .send_data = pcc_send_data, 584 491 .startup = pcc_startup, 585 492 .shutdown = pcc_shutdown, 493 + .last_tx_done = pcc_last_tx_done, 586 494 }; 587 495 588 496 /**
+29
include/acpi/pcc.h
··· 17 17 u32 latency; 18 18 u32 max_access_rate; 19 19 u16 min_turnaround_time; 20 + 21 + /* Set to true to indicate that the mailbox should manage 22 + * writing the dat to the shared buffer. This differs from 23 + * the case where the drivesr are writing to the buffer and 24 + * using send_data only to ring the doorbell. If this flag 25 + * is set, then the void * data parameter of send_data must 26 + * point to a kernel-memory buffer formatted in accordance with 27 + * the PCC specification. 28 + * 29 + * The active buffer management will include reading the 30 + * notify_on_completion flag, and will then 31 + * call mbox_chan_txdone when the acknowledgment interrupt is 32 + * received. 33 + */ 34 + bool manage_writes; 35 + 36 + /* Optional callback that allows the driver 37 + * to allocate the memory used for receiving 38 + * messages. The return value is the location 39 + * inside the buffer where the mailbox should write the data. 40 + */ 41 + void *(*rx_alloc)(struct mbox_client *cl, int size); 42 + }; 43 + 44 + struct pcc_header { 45 + u32 signature; 46 + u32 flags; 47 + u32 length; 48 + u32 command; 20 49 }; 21 50 22 51 /* Generic Communications Channel Shared Memory Region */