aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Stone <ahs3@redhat.com>2018-05-16 18:01:41 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2018-05-18 06:08:15 -0400
commit8f8027c5f935bf02bdc8806c109ddbb0e402283c (patch)
treeaae71a582eea0537b617cfee855ac65e547afae6
parent58e1c03536c959e0d45fde8261cb9c15da893fe6 (diff)
mailbox: PCC: erroneous error message when parsing ACPI PCCT
There have been multiple reports of the following error message: [ 0.068293] Error parsing PCC subspaces from PCCT This error message is not correct. In multiple cases examined, the PCCT (Platform Communications Channel Table) concerned is actually properly constructed; the problem is that acpi_pcc_probe() which reads the PCCT is making the assumption that the only valid PCCT is one that contains subtables of one of two types: ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE or ACPI_PCCT_TYPE_HW_REDUCED_TYPE2. The number of subtables of these types are counted and as long as there is at least one of the desired types, the acpi_pcc_probe() succeeds. When no subtables of these types are found, regardless of whether or not any other subtable types are present, the error mentioned above is reported. In the cases reported to me personally, the PCCT contains exactly one subtable of type ACPI_PCCT_TYPE_GENERIC_SUBSPACE. The function acpi_pcc_probe() does not count it as a valid subtable, so believes there to be no valid subtables, and hence outputs the error message. An example of the PCCT being reported as erroneous yet perfectly fine is the following: Signature : "PCCT" Table Length : 0000006E Revision : 05 Checksum : A9 Oem ID : "XXXXXX" Oem Table ID : "XXXXX " Oem Revision : 00002280 Asl Compiler ID : "XXXX" Asl Compiler Revision : 00000002 Flags (decoded below) : 00000001 Platform : 1 Reserved : 0000000000000000 Subtable Type : 00 [Generic Communications Subspace] Length : 3E Reserved : 000000000000 Base Address : 00000000DCE43018 Address Length : 0000000000001000 Doorbell Register : [Generic Address Structure] Space ID : 01 [SystemIO] Bit Width : 08 Bit Offset : 00 Encoded Access Width : 01 [Byte Access:8] Address : 0000000000001842 Preserve Mask : 00000000000000FD Write Mask : 0000000000000002 Command Latency : 00001388 Maximum Access Rate : 00000000 Minimum Turnaround Time : 0000 To fix this, we count up all of the possible subtable types for the PCCT, and only report an error when there are none (which could mean either no subtables, or no valid subtables), or there are too many. We also change the logic so that if there is a valid subtable, we do try to initialize it per the PCCT subtable contents. This is a change in functionality; previously, the probe would have returned right after the error message and would not have tried to use any other subtable definition. Tested on my personal laptop which showed the error previously; the error message no longer appears and the laptop appears to operate normally. Signed-off-by: Al Stone <ahs3@redhat.com> Reviewed-by: Prashanth Prakash <pprakash@codeaurora.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/mailbox/pcc.c81
1 files changed, 38 insertions, 43 deletions
diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c
index 3ef7f036ceea..fc3c237daef2 100644
--- a/drivers/mailbox/pcc.c
+++ b/drivers/mailbox/pcc.c
@@ -373,33 +373,24 @@ static const struct mbox_chan_ops pcc_chan_ops = {
373}; 373};
374 374
375/** 375/**
376 * parse_pcc_subspace - Parse the PCC table and verify PCC subspace 376 * parse_pcc_subspaces -- Count PCC subspaces defined
377 * entries. There should be one entry per PCC client.
378 * @header: Pointer to the ACPI subtable header under the PCCT. 377 * @header: Pointer to the ACPI subtable header under the PCCT.
379 * @end: End of subtable entry. 378 * @end: End of subtable entry.
380 * 379 *
381 * Return: 0 for Success, else errno. 380 * Return: If we find a PCC subspace entry of a valid type, return 0.
381 * Otherwise, return -EINVAL.
382 * 382 *
383 * This gets called for each entry in the PCC table. 383 * This gets called for each entry in the PCC table.
384 */ 384 */
385static int parse_pcc_subspace(struct acpi_subtable_header *header, 385static int parse_pcc_subspace(struct acpi_subtable_header *header,
386 const unsigned long end) 386 const unsigned long end)
387{ 387{
388 struct acpi_pcct_hw_reduced *pcct_ss; 388 struct acpi_pcct_subspace *ss = (struct acpi_pcct_subspace *) header;
389
390 if (pcc_mbox_ctrl.num_chans <= MAX_PCC_SUBSPACES) {
391 pcct_ss = (struct acpi_pcct_hw_reduced *) header;
392 389
393 if ((pcct_ss->header.type != 390 if (ss->header.type < ACPI_PCCT_TYPE_RESERVED)
394 ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE) 391 return 0;
395 && (pcct_ss->header.type !=
396 ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2)) {
397 pr_err("Incorrect PCC Subspace type detected\n");
398 return -EINVAL;
399 }
400 }
401 392
402 return 0; 393 return -EINVAL;
403} 394}
404 395
405/** 396/**
@@ -449,8 +440,8 @@ static int __init acpi_pcc_probe(void)
449 struct acpi_table_header *pcct_tbl; 440 struct acpi_table_header *pcct_tbl;
450 struct acpi_subtable_header *pcct_entry; 441 struct acpi_subtable_header *pcct_entry;
451 struct acpi_table_pcct *acpi_pcct_tbl; 442 struct acpi_table_pcct *acpi_pcct_tbl;
443 struct acpi_subtable_proc proc[ACPI_PCCT_TYPE_RESERVED];
452 int count, i, rc; 444 int count, i, rc;
453 int sum = 0;
454 acpi_status status = AE_OK; 445 acpi_status status = AE_OK;
455 446
456 /* Search for PCCT */ 447 /* Search for PCCT */
@@ -459,43 +450,41 @@ static int __init acpi_pcc_probe(void)
459 if (ACPI_FAILURE(status) || !pcct_tbl) 450 if (ACPI_FAILURE(status) || !pcct_tbl)
460 return -ENODEV; 451 return -ENODEV;
461 452
462 count = acpi_table_parse_entries(ACPI_SIG_PCCT, 453 /* Set up the subtable handlers */
463 sizeof(struct acpi_table_pcct), 454 for (i = ACPI_PCCT_TYPE_GENERIC_SUBSPACE;
464 ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE, 455 i < ACPI_PCCT_TYPE_RESERVED; i++) {
465 parse_pcc_subspace, MAX_PCC_SUBSPACES); 456 proc[i].id = i;
466 sum += (count > 0) ? count : 0; 457 proc[i].count = 0;
467 458 proc[i].handler = parse_pcc_subspace;
468 count = acpi_table_parse_entries(ACPI_SIG_PCCT, 459 }
469 sizeof(struct acpi_table_pcct),
470 ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2,
471 parse_pcc_subspace, MAX_PCC_SUBSPACES);
472 sum += (count > 0) ? count : 0;
473 460
474 if (sum == 0 || sum >= MAX_PCC_SUBSPACES) { 461 count = acpi_table_parse_entries_array(ACPI_SIG_PCCT,
475 pr_err("Error parsing PCC subspaces from PCCT\n"); 462 sizeof(struct acpi_table_pcct), proc,
463 ACPI_PCCT_TYPE_RESERVED, MAX_PCC_SUBSPACES);
464 if (count == 0 || count > MAX_PCC_SUBSPACES) {
465 pr_warn("Invalid PCCT: %d PCC subspaces\n", count);
476 return -EINVAL; 466 return -EINVAL;
477 } 467 }
478 468
479 pcc_mbox_channels = kzalloc(sizeof(struct mbox_chan) * 469 pcc_mbox_channels = kzalloc(sizeof(struct mbox_chan) * count, GFP_KERNEL);
480 sum, GFP_KERNEL);
481 if (!pcc_mbox_channels) { 470 if (!pcc_mbox_channels) {
482 pr_err("Could not allocate space for PCC mbox channels\n"); 471 pr_err("Could not allocate space for PCC mbox channels\n");
483 return -ENOMEM; 472 return -ENOMEM;
484 } 473 }
485 474
486 pcc_doorbell_vaddr = kcalloc(sum, sizeof(void *), GFP_KERNEL); 475 pcc_doorbell_vaddr = kcalloc(count, sizeof(void *), GFP_KERNEL);
487 if (!pcc_doorbell_vaddr) { 476 if (!pcc_doorbell_vaddr) {
488 rc = -ENOMEM; 477 rc = -ENOMEM;
489 goto err_free_mbox; 478 goto err_free_mbox;
490 } 479 }
491 480
492 pcc_doorbell_ack_vaddr = kcalloc(sum, sizeof(void *), GFP_KERNEL); 481 pcc_doorbell_ack_vaddr = kcalloc(count, sizeof(void *), GFP_KERNEL);
493 if (!pcc_doorbell_ack_vaddr) { 482 if (!pcc_doorbell_ack_vaddr) {
494 rc = -ENOMEM; 483 rc = -ENOMEM;
495 goto err_free_db_vaddr; 484 goto err_free_db_vaddr;
496 } 485 }
497 486
498 pcc_doorbell_irq = kcalloc(sum, sizeof(int), GFP_KERNEL); 487 pcc_doorbell_irq = kcalloc(count, sizeof(int), GFP_KERNEL);
499 if (!pcc_doorbell_irq) { 488 if (!pcc_doorbell_irq) {
500 rc = -ENOMEM; 489 rc = -ENOMEM;
501 goto err_free_db_ack_vaddr; 490 goto err_free_db_ack_vaddr;
@@ -509,18 +498,24 @@ static int __init acpi_pcc_probe(void)
509 if (acpi_pcct_tbl->flags & ACPI_PCCT_DOORBELL) 498 if (acpi_pcct_tbl->flags & ACPI_PCCT_DOORBELL)
510 pcc_mbox_ctrl.txdone_irq = true; 499 pcc_mbox_ctrl.txdone_irq = true;
511 500
512 for (i = 0; i < sum; i++) { 501 for (i = 0; i < count; i++) {
513 struct acpi_generic_address *db_reg; 502 struct acpi_generic_address *db_reg;
514 struct acpi_pcct_hw_reduced *pcct_ss; 503 struct acpi_pcct_subspace *pcct_ss;
515 pcc_mbox_channels[i].con_priv = pcct_entry; 504 pcc_mbox_channels[i].con_priv = pcct_entry;
516 505
517 pcct_ss = (struct acpi_pcct_hw_reduced *) pcct_entry; 506 if (pcct_entry->type == ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE ||
507 pcct_entry->type == ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2) {
508 struct acpi_pcct_hw_reduced *pcct_hrss;
509
510 pcct_hrss = (struct acpi_pcct_hw_reduced *) pcct_entry;
518 511
519 if (pcc_mbox_ctrl.txdone_irq) { 512 if (pcc_mbox_ctrl.txdone_irq) {
520 rc = pcc_parse_subspace_irq(i, pcct_ss); 513 rc = pcc_parse_subspace_irq(i, pcct_hrss);
521 if (rc < 0) 514 if (rc < 0)
522 goto err; 515 goto err;
516 }
523 } 517 }
518 pcct_ss = (struct acpi_pcct_subspace *) pcct_entry;
524 519
525 /* If doorbell is in system memory cache the virt address */ 520 /* If doorbell is in system memory cache the virt address */
526 db_reg = &pcct_ss->doorbell_register; 521 db_reg = &pcct_ss->doorbell_register;
@@ -531,7 +526,7 @@ static int __init acpi_pcc_probe(void)
531 ((unsigned long) pcct_entry + pcct_entry->length); 526 ((unsigned long) pcct_entry + pcct_entry->length);
532 } 527 }
533 528
534 pcc_mbox_ctrl.num_chans = sum; 529 pcc_mbox_ctrl.num_chans = count;
535 530
536 pr_info("Detected %d PCC Subspaces\n", pcc_mbox_ctrl.num_chans); 531 pr_info("Detected %d PCC Subspaces\n", pcc_mbox_ctrl.num_chans);
537 532