On 2015/4/7 19:47, Rafael J. Wysocki wrote:
> On Tuesday, April 07, 2015 12:30:18 PM Jiang Liu wrote:
>> Before commit 593669c2ac0f("Use common ACPI resource interfaces to
>> simplify implementation"), arch/x86/pci/acpi.c applies following
>> rules when parsing ACPI resources for PCI host bridge:
>> 1) Ignore IO port resources defined by acpi_resource_io and
>>    acpi_resource_fixed_io, which should be used to define resource
>>    for PCI device instead of PCI bridge.
>> 2) Accept IOMEM resource defined by acpi_resource_memory24,
>>    acpi_resource_memory32 and acpi_resource_fixed_memory32.
>>    These IOMEM resources are accepted to workaround some BIOS issue,
>>    though they should be ignored. For example, PC Engines APU.1C
>>    platform defines PCI host bridge IOMEM resources as:
>>                 Memory32Fixed (ReadOnly,
>>                     0x000A0000,         // Address Base
>>                     0x00020000,         // Address Length
>>                     )
>>                 Memory32Fixed (ReadOnly,
>>                     0x00000000,         // Address Base
>>                     0x00000000,         // Address Length
>>                     _Y00)
>> 3) Accept all IO port and IOMEM resources defined by
>>    acpi_resource_address{16,32,64,extended64}, no matter it's marked as
>>    ACPI_CONSUMER or ACPI_PRODUCER.
>>
>> Commit 593669c2ac0f("Use common ACPI resource interfaces to
>> simplify implementation") accept all IO port and IOMEM resources
>> defined by acpi_resource_io, acpi_resource_fixed_io,
>> acpi_resource_memory24, acpi_resource_memory32,
>> acpi_resource_fixed_memory32 and
>> acpi_resource_address{16,32,64,extended64}, which causes IO port
>> resources consumed by host bridge itself are listed in to host bridge
>> resource list.
>>
>> Then commit 63f1789ec716("Ignore resources consumed by host bridge
>> itself") ignores resources consumed by host bridge itself by checking
>> IORESOURCE_WINDOW flag, which accidently removed the workaround in 2)
>> above for BIOS bug .
>>
>> It's really costed us much time to figure out this whole picture.
>> So we refine interface acpi_dev_filter_resource_type as below,
>> which should be easier for maintence:
>> 1) Caller specifies IORESOURCE_WINDOW flag to explicitly query resource
>>    for bridge(PRODUCER), otherwise it's querying resource for
>>    device(CONSUMER).
>> 2) Ignore IO port resources defined by acpi_resource_io and
>>    acpi_resource_fixed_io if IORESOURCE_WINDOW is specified.
>> 3) Accpet IOMEM resource defined by acpi_resource_memory24,
>>    acpi_resource_memory32 and acpi_resource_fixed_memory32 if both
>>    IORESOURCE_WINDOW and IORESOURCE_MEM_8AND16BIT are specified to work
>>    around BIOS issues.
>> 4) Accept IO port and IOMEM defined by acpi_resource_addressxx if
>>    a) IORESOURCE_WINDOW is specified and ACPI_PRODUCER is true
>>    b) IORESOURCE_WINDOW is not specified and ACPI_PRODUCER is false
>>
>> Currently acpi_dev_filter_resource_type() is only used by ACPI pci
>> host bridge and IOAPIC driver, so it shouldn't affect other drivers.
>>
>> Another possible fix is to only ignore IO resource consumed by host
>> bridge and keep IOMEM resource consumed by host bridge, please refer to:
>> http://www.spinics.net/lists/linux-pci/msg39706.html
>>
>> Sample ACPI table are archived at:
>> https://bugzilla.kernel.org/show_bug.cgi?id=94221
>>
>> V3->V4:
>> 1) Improve comments
>> 2) Use flag IORESOURCE_MEM_8AND16BIT to work around BIOS issue
> 
> OK, so how does that address the comments in the previous thread?
> 
> It would *really* help if you responded there instead of starting a new
> thread by sending a new patch version.  This makes it really difficult to
> follow the entire discussion, which is part of why we keep forgetting things.
Hi Rafael,
        Apologize:) I miss understood previous mail. Please ignore
this version.
Regards!
Gerry

> 
>> Fixes: 63f1789ec716("Ignore resources consumed by host bridge itself")
>> Reported-and-Tested-by: Bernhard Thaler <[email protected]>
>> Signed-off-by: Jiang Liu <[email protected]>
>> ---
>>  arch/x86/pci/acpi.c     |    8 +++++---
>>  drivers/acpi/resource.c |   52 
>> +++++++++++++++++++++++++++++++++++++++++------
>>  2 files changed, 51 insertions(+), 9 deletions(-)
>>
>> diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
>> index e4695985f9de..150774be0f3f 100644
>> --- a/arch/x86/pci/acpi.c
>> +++ b/arch/x86/pci/acpi.c
>> @@ -332,12 +332,15 @@ static void probe_pci_root_info(struct pci_root_info 
>> *info,
>>  {
>>      int ret;
>>      struct resource_entry *entry, *tmp;
>> +    unsigned long res_flags;
>>  
>>      sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
>>      info->bridge = device;
>> +    res_flags = IORESOURCE_IO | IORESOURCE_MEM |
>> +                IORESOURCE_WINDOW | IORESOURCE_MEM_8AND16BIT;
>>      ret = acpi_dev_get_resources(device, list,
>>                                   acpi_dev_filter_resource_type_cb,
>> -                                 (void *)(IORESOURCE_IO | IORESOURCE_MEM));
>> +                                 (void *)res_flags);
>>      if (ret < 0)
>>              dev_warn(&device->dev,
>>                       "failed to parse _CRS method, error code %d\n", ret);
>> @@ -346,8 +349,7 @@ static void probe_pci_root_info(struct pci_root_info 
>> *info,
>>                      "no IO and memory resources present in _CRS\n");
>>      else
>>              resource_list_for_each_entry_safe(entry, tmp, list) {
>> -                    if ((entry->res->flags & IORESOURCE_WINDOW) == 0 ||
>> -                        (entry->res->flags & IORESOURCE_DISABLED))
>> +                    if (entry->res->flags & IORESOURCE_DISABLED)
>>                              resource_list_destroy_entry(entry);
>>                      else
>>                              entry->res->name = info->name;
>> diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
>> index 5589a6e2a023..0187e0e11bb8 100644
>> --- a/drivers/acpi/resource.c
>> +++ b/drivers/acpi/resource.c
>> @@ -567,6 +567,12 @@ int acpi_dev_get_resources(struct acpi_device *adev, 
>> struct list_head *list,
>>  }
>>  EXPORT_SYMBOL_GPL(acpi_dev_get_resources);
>>  
>> +static bool acpi_dev_match_producer_consumer(unsigned long types, int 
>> producer)
>> +{
>> +    return ((types & IORESOURCE_WINDOW) && producer == ACPI_PRODUCER) ||
>> +            ((types & IORESOURCE_WINDOW) == 0 && producer == ACPI_CONSUMER);
>> +}
>> +
>>  /**
>>   * acpi_dev_filter_resource_type - Filter ACPI resource according to 
>> resource
>>   *                             types
>> @@ -574,7 +580,19 @@ EXPORT_SYMBOL_GPL(acpi_dev_get_resources);
>>   * @types: Valid resource types of IORESOURCE_XXX
>>   *
>>   * This is a hepler function to support acpi_dev_get_resources(), which 
>> filters
>> - * ACPI resource objects according to resource types.
>> + * ACPI resource objects according to resource types and flags as below:
>> + * 1) If flag IORESOURCE_WINDOW is not specified, it's querying resources
>> + *    consumed by device. That is to return:
>> + *  a) ACPI resources without producer_consumer flag
>> + *  b) ACPI resources with producer_consumer flag setting to CONSUMER.
> 
> OK, so what if the resource is not of an "extended" type, say DWORD address 
> space,
> but has a non-empty Resource Source field pointing to the device itself?
> 
> Shouldn't we treat that device as a "producer" too?
> 
>> + * 2) If flag IORESOURCE_WINDOW is specified, it's querying resources 
>> provided
>> + *    by device. That is to return:
>> + *  a) ACPI resources with producer_consumer flag setting to PRODUCER.
>> + * 3) But there's an exception. Some platforms, such as PC Engines APU.1C,
>> + *    report PCI host bridge resource provision by Memory32Fixed().
>> + *    Please refer to https://bugzilla.kernel.org/show_bug.cgi?id=94221
>> + *    So a special flag IORESOURCE_MEM_8AND16BIT is used to work around this
>> + *    BIOS issue.
> 
> This is a legitimate thing for the BIOS to do if my reading of the spec is
> correct, as the "producer" thing really is supposed to mean "this resource
> comes from the device itself".
> 
>>   */
>>  int acpi_dev_filter_resource_type(struct acpi_resource *ares,
>>                                unsigned long types)
>> @@ -585,27 +603,49 @@ int acpi_dev_filter_resource_type(struct acpi_resource 
>> *ares,
>>      case ACPI_RESOURCE_TYPE_MEMORY24:
>>      case ACPI_RESOURCE_TYPE_MEMORY32:
>>      case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
>> -            type = IORESOURCE_MEM;
>> +            /*
>> +             * These types of resource descriptor should be used to
>> +             * describe resource consumption instead of resource provision.
>> +             * But some platforms, such as PC Engines APU.1C, report
>> +             * resource provision by Memory32Fixed(). Please refer to:
>> +             * https://bugzilla.kernel.org/show_bug.cgi?id=94221
>> +             * So a special rule to work around BIOS issues.
>> +             */
>> +            if ((types & (IORESOURCE_WINDOW | IORESOURCE_MEM_8AND16BIT)) ==
>> +                (IORESOURCE_WINDOW | IORESOURCE_MEM_8AND16BIT) ||
>> +                acpi_dev_match_producer_consumer(types, ACPI_CONSUMER))
>> +                    type = IORESOURCE_MEM;
>>              break;
>>      case ACPI_RESOURCE_TYPE_IO:
>>      case ACPI_RESOURCE_TYPE_FIXED_IO:
>> -            type = IORESOURCE_IO;
>> +            if (acpi_dev_match_producer_consumer(types, ACPI_CONSUMER))
>> +                    type = IORESOURCE_IO;
>>              break;
>>      case ACPI_RESOURCE_TYPE_IRQ:
>> +            if (acpi_dev_match_producer_consumer(types, ACPI_CONSUMER))
>> +                    type = IORESOURCE_IRQ;
>> +            break;
>>      case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
>> -            type = IORESOURCE_IRQ;
>> +            if (acpi_dev_match_producer_consumer(types,
>> +                            ares->data.extended_irq.producer_consumer))
>> +                    type = IORESOURCE_IRQ;
>>              break;
>>      case ACPI_RESOURCE_TYPE_DMA:
>>      case ACPI_RESOURCE_TYPE_FIXED_DMA:
>> -            type = IORESOURCE_DMA;
>> +            if (acpi_dev_match_producer_consumer(types, ACPI_CONSUMER))
>> +                    type = IORESOURCE_DMA;
>>              break;
>>      case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
>> -            type = IORESOURCE_REG;
>> +            if (acpi_dev_match_producer_consumer(types, ACPI_CONSUMER))
>> +                    type = IORESOURCE_REG;
>>              break;
>>      case ACPI_RESOURCE_TYPE_ADDRESS16:
>>      case ACPI_RESOURCE_TYPE_ADDRESS32:
>>      case ACPI_RESOURCE_TYPE_ADDRESS64:
>>      case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
>> +            if (!acpi_dev_match_producer_consumer(types,
>> +                            ares->data.address.producer_consumer))
>> +                    break;
>>              if (ares->data.address.resource_type == ACPI_MEMORY_RANGE)
>>                      type = IORESOURCE_MEM;
>>              else if (ares->data.address.resource_type == ACPI_IO_RANGE)
>>
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to