Skip to content

Commit 8f8027c

Browse files
Al Stonerafaeljw
authored andcommitted
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 <[email protected]> Reviewed-by: Prashanth Prakash <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 58e1c03 commit 8f8027c

File tree

1 file changed

+38
-43
lines changed

1 file changed

+38
-43
lines changed

drivers/mailbox/pcc.c

Lines changed: 38 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -373,33 +373,24 @@ static const struct mbox_chan_ops pcc_chan_ops = {
373373
};
374374

375375
/**
376-
* parse_pcc_subspace - Parse the PCC table and verify PCC subspace
377-
* entries. There should be one entry per PCC client.
376+
* parse_pcc_subspaces -- Count PCC subspaces defined
378377
* @header: Pointer to the ACPI subtable header under the PCCT.
379378
* @end: End of subtable entry.
380379
*
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.
382382
*
383383
* This gets called for each entry in the PCC table.
384384
*/
385385
static int parse_pcc_subspace(struct acpi_subtable_header *header,
386386
const unsigned long end)
387387
{
388-
struct acpi_pcct_hw_reduced *pcct_ss;
389-
390-
if (pcc_mbox_ctrl.num_chans <= MAX_PCC_SUBSPACES) {
391-
pcct_ss = (struct acpi_pcct_hw_reduced *) header;
388+
struct acpi_pcct_subspace *ss = (struct acpi_pcct_subspace *) header;
392389

393-
if ((pcct_ss->header.type !=
394-
ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE)
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-
}
390+
if (ss->header.type < ACPI_PCCT_TYPE_RESERVED)
391+
return 0;
401392

402-
return 0;
393+
return -EINVAL;
403394
}
404395

405396
/**
@@ -449,8 +440,8 @@ static int __init acpi_pcc_probe(void)
449440
struct acpi_table_header *pcct_tbl;
450441
struct acpi_subtable_header *pcct_entry;
451442
struct acpi_table_pcct *acpi_pcct_tbl;
443+
struct acpi_subtable_proc proc[ACPI_PCCT_TYPE_RESERVED];
452444
int count, i, rc;
453-
int sum = 0;
454445
acpi_status status = AE_OK;
455446

456447
/* Search for PCCT */
@@ -459,43 +450,41 @@ static int __init acpi_pcc_probe(void)
459450
if (ACPI_FAILURE(status) || !pcct_tbl)
460451
return -ENODEV;
461452

462-
count = acpi_table_parse_entries(ACPI_SIG_PCCT,
463-
sizeof(struct acpi_table_pcct),
464-
ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE,
465-
parse_pcc_subspace, MAX_PCC_SUBSPACES);
466-
sum += (count > 0) ? count : 0;
467-
468-
count = acpi_table_parse_entries(ACPI_SIG_PCCT,
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;
453+
/* Set up the subtable handlers */
454+
for (i = ACPI_PCCT_TYPE_GENERIC_SUBSPACE;
455+
i < ACPI_PCCT_TYPE_RESERVED; i++) {
456+
proc[i].id = i;
457+
proc[i].count = 0;
458+
proc[i].handler = parse_pcc_subspace;
459+
}
473460

474-
if (sum == 0 || sum >= MAX_PCC_SUBSPACES) {
475-
pr_err("Error parsing PCC subspaces from PCCT\n");
461+
count = acpi_table_parse_entries_array(ACPI_SIG_PCCT,
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);
476466
return -EINVAL;
477467
}
478468

479-
pcc_mbox_channels = kzalloc(sizeof(struct mbox_chan) *
480-
sum, GFP_KERNEL);
469+
pcc_mbox_channels = kzalloc(sizeof(struct mbox_chan) * count, GFP_KERNEL);
481470
if (!pcc_mbox_channels) {
482471
pr_err("Could not allocate space for PCC mbox channels\n");
483472
return -ENOMEM;
484473
}
485474

486-
pcc_doorbell_vaddr = kcalloc(sum, sizeof(void *), GFP_KERNEL);
475+
pcc_doorbell_vaddr = kcalloc(count, sizeof(void *), GFP_KERNEL);
487476
if (!pcc_doorbell_vaddr) {
488477
rc = -ENOMEM;
489478
goto err_free_mbox;
490479
}
491480

492-
pcc_doorbell_ack_vaddr = kcalloc(sum, sizeof(void *), GFP_KERNEL);
481+
pcc_doorbell_ack_vaddr = kcalloc(count, sizeof(void *), GFP_KERNEL);
493482
if (!pcc_doorbell_ack_vaddr) {
494483
rc = -ENOMEM;
495484
goto err_free_db_vaddr;
496485
}
497486

498-
pcc_doorbell_irq = kcalloc(sum, sizeof(int), GFP_KERNEL);
487+
pcc_doorbell_irq = kcalloc(count, sizeof(int), GFP_KERNEL);
499488
if (!pcc_doorbell_irq) {
500489
rc = -ENOMEM;
501490
goto err_free_db_ack_vaddr;
@@ -509,18 +498,24 @@ static int __init acpi_pcc_probe(void)
509498
if (acpi_pcct_tbl->flags & ACPI_PCCT_DOORBELL)
510499
pcc_mbox_ctrl.txdone_irq = true;
511500

512-
for (i = 0; i < sum; i++) {
501+
for (i = 0; i < count; i++) {
513502
struct acpi_generic_address *db_reg;
514-
struct acpi_pcct_hw_reduced *pcct_ss;
503+
struct acpi_pcct_subspace *pcct_ss;
515504
pcc_mbox_channels[i].con_priv = pcct_entry;
516505

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;
518511

519-
if (pcc_mbox_ctrl.txdone_irq) {
520-
rc = pcc_parse_subspace_irq(i, pcct_ss);
521-
if (rc < 0)
522-
goto err;
512+
if (pcc_mbox_ctrl.txdone_irq) {
513+
rc = pcc_parse_subspace_irq(i, pcct_hrss);
514+
if (rc < 0)
515+
goto err;
516+
}
523517
}
518+
pcct_ss = (struct acpi_pcct_subspace *) pcct_entry;
524519

525520
/* If doorbell is in system memory cache the virt address */
526521
db_reg = &pcct_ss->doorbell_register;
@@ -531,7 +526,7 @@ static int __init acpi_pcc_probe(void)
531526
((unsigned long) pcct_entry + pcct_entry->length);
532527
}
533528

534-
pcc_mbox_ctrl.num_chans = sum;
529+
pcc_mbox_ctrl.num_chans = count;
535530

536531
pr_info("Detected %d PCC Subspaces\n", pcc_mbox_ctrl.num_chans);
537532

0 commit comments

Comments
 (0)