Re: [PATCH v4 28/28] PCI, x86, ACPI: get ioapic address from acpi device

From: Lan Tianyu
Date: Fri Aug 23 2013 - 11:34:30 EST


2013/8/23 rui wang <ruiv.wang@xxxxxxxxx>:
> On 8/22/13, rui wang <ruiv.wang@xxxxxxxxx> wrote:
>> On 8/11/13, Yinghai Lu <yinghai@xxxxxxxxxx> wrote:
>>> Some ioapic controllers do not show up on pci config space,
>>> or pci device is there but no bar is used and is set by firmware in
>>> other non standard registers.
>>>
>>> We can get ioapic address from ACPI0009's _CRS.
>>>
>>> Signed-off-by: Yinghai Lu <yinghai@xxxxxxxxxx>
>>> ---
>>> drivers/pci/ioapic.c | 86
>>> +++++++++++++++++++++++++++++++++++++++++++---------
>>> 1 file changed, 71 insertions(+), 15 deletions(-)
>>>
>>> diff --git a/drivers/pci/ioapic.c b/drivers/pci/ioapic.c
>>> index 60351b2..41f7c69 100644
>>> --- a/drivers/pci/ioapic.c
>>> +++ b/drivers/pci/ioapic.c
>>> @@ -32,6 +32,36 @@ struct acpi_pci_ioapic {
>>> static LIST_HEAD(ioapic_list);
>>> static DEFINE_MUTEX(ioapic_list_lock);
>>>
>>> +static acpi_status setup_res(struct acpi_resource *acpi_res, void *data)
>>> +{
>>> + struct resource *res;
>>> + struct acpi_resource_address64 addr;
>>> + acpi_status status;
>>> + unsigned long flags;
>>> + u64 start, end;
>>> +
>>> + status = acpi_resource_to_address64(acpi_res, &addr);
>
> I worked around the problem by replacing acpi_resource_to_address64()
> with resource_to_addr(). But resource_to_addr() is a static function
> in arch/x86/pci/acpi.c, not very convenient to use. Here's what I did:
>

Hi Rui&Yinghai:
How about using the following code to translate struct
acpi_resource to struct resouce in this setup_res()?

if (acpi_dev_resource_address_space(...)
|| acpi_dev_resource_memory(..))
return AE_OK;




> diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
> index d641897..cb5940a 100644
> --- a/arch/x86/pci/acpi.c
> +++ b/arch/x86/pci/acpi.c
> @@ -218,7 +218,7 @@ static void teardown_mcfg_map(struct pci_root_info *info)
> }
> #endif
>
> -static acpi_status
> +acpi_status
> resource_to_addr(struct acpi_resource *resource,
> struct acpi_resource_address64 *addr)
> {
> diff --git a/drivers/pci/ioapic.c b/drivers/pci/ioapic.c
> index 41f7c69..68d7395 100644
> --- a/drivers/pci/ioapic.c
> +++ b/drivers/pci/ioapic.c
> @@ -40,7 +40,7 @@ static acpi_status setup_res(struct acpi_resource
> *acpi_res, void *data)
> unsigned long flags;
> u64 start, end;
>
> - status = acpi_resource_to_address64(acpi_res, &addr);
> + status = resource_to_addr(acpi_res, &addr);
> if (!ACPI_SUCCESS(status))
> return AE_OK;
> diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
> index 94383a7..ae7f759 100644
> --- a/include/acpi/acpi_bus.h
> +++ b/include/acpi/acpi_bus.h
> @@ -354,6 +354,10 @@ extern int unregister_acpi_notifier(struct
> notifier_block *);
>
> extern int register_acpi_bus_notifier(struct notifier_block *nb);
> extern void unregister_acpi_bus_notifier(struct notifier_block *nb);
> +extern acpi_status
> +resource_to_addr(struct acpi_resource *resource,
> + struct acpi_resource_address64 *addr);
> +
>
> Thanks
> Rui
>
>
>>
>> The above function fails on my machine because it does not handle
>> Memory32Fixed resources. Is the following _CRS declaration allowed for
>> IOAPIC?
>>
>> Device (APIC)
>> {
>> Name (_HID, "ACPI0009") // _HID: Hardware ID
>> Name (_CRS, ResourceTemplate () // _CRS: Current
>> Resource Settings
>> {
>> Memory32Fixed (ReadOnly,
>> 0xFEC01000, // Address Base
>> 0x00001000, // Address Length
>> )
>> })
>> Method(_GSB) {
>> return (0x18)
>> }
>> }
>>
>>
>> Thanks
>> Rui
>>
>>> + if (!ACPI_SUCCESS(status))
>>> + return AE_OK;
>>> +
>>> + if (addr.resource_type == ACPI_MEMORY_RANGE) {
>>> + if (addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
>>> + return AE_OK;
>>> + flags = IORESOURCE_MEM;
>>> + } else
>>> + return AE_OK;
>>> +
>>> + start = addr.minimum + addr.translation_offset;
>>> + end = addr.maximum + addr.translation_offset;
>>> +
>>> + res = data;
>>> + res->flags = flags;
>>> + res->start = start;
>>> + res->end = end;
>>> +
>>> + return AE_OK;
>>> +}
>>> +
>>> static void handle_ioapic_add(acpi_handle handle, struct pci_dev **pdev,
>>> u32 *pgsi_base)
>>> {
>>> @@ -54,33 +84,56 @@ static void handle_ioapic_add(acpi_handle handle,
>>> struct
>>> pci_dev **pdev,
>>> return;
>>>
>>> dev = acpi_get_pci_dev(handle);
>>> - if (!dev)
>>> - return;
>>> + if (!dev || !pci_resource_len(dev, 0)) {
>>> + struct acpi_device_info *info;
>>> + char *hid = NULL;
>>> +
>>> + status = acpi_get_object_info(handle, &info);
>>> + if (ACPI_FAILURE(status))
>>> + goto exit_put;
>>> + if (info->valid & ACPI_VALID_HID)
>>> + hid = info->hardware_id.string;
>>> + if (!hid || strcmp(hid, "ACPI0009")) {
>>> + kfree(info);
>>> + goto exit_put;
>>> + }
>>> + kfree(info);
>>> + memset(res, 0, sizeof(*res));
>>> + acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, res);
>>> + if (!res->flags)
>>> + goto exit_put;
>>> + }
>>>
>>> acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
>>>
>>> gsi_base = gsb;
>>> type = "IOxAPIC";
>>> + if (dev) {
>>> + ret = pci_enable_device(dev);
>>> + if (ret < 0)
>>> + goto exit_put;
>>>
>>> - ret = pci_enable_device(dev);
>>> - if (ret < 0)
>>> - goto exit_put;
>>> -
>>> - pci_set_master(dev);
>>> + pci_set_master(dev);
>>>
>>> - if (dev->class == PCI_CLASS_SYSTEM_PIC_IOAPIC)
>>> - type = "IOAPIC";
>>> + if (dev->class == PCI_CLASS_SYSTEM_PIC_IOAPIC)
>>> + type = "IOAPIC";
>>>
>>> - if (pci_request_region(dev, 0, type))
>>> - goto exit_disable;
>>> + if (pci_resource_len(dev, 0)) {
>>> + if (pci_request_region(dev, 0, type))
>>> + goto exit_disable;
>>>
>>> - res = &dev->resource[0];
>>> + res = &dev->resource[0];
>>> + }
>>> + }
>>>
>>> - if (acpi_register_ioapic(handle, res->start, gsi_base))
>>> - goto exit_release;
>>> + if (acpi_register_ioapic(handle, res->start, gsi_base)) {
>>> + if (dev)
>>> + goto exit_release;
>>> + return;
>>> + }
>>>
>>> pr_info("%s %s %s at %pR, GSI %u\n",
>>> - dev_name(&dev->dev), objname, type,
>>> + dev ? dev_name(&dev->dev) : "", objname, type,
>>> res, gsi_base);
>>>
>>> *pdev = dev;
>>> @@ -100,6 +153,9 @@ static void handle_ioapic_remove(acpi_handle handle,
>>> struct pci_dev *dev,
>>> {
>>> acpi_unregister_ioapic(handle, gsi_base);
>>>
>>> + if (!dev)
>>> + return;
>>> +
>>> pci_release_region(dev, 0);
>>> pci_disable_device(dev);
>>> pci_dev_put(dev);
>>> --
>>> 1.8.1.4
>>>
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-kernel"
>>> in
>>> the body of a message to majordomo@xxxxxxxxxxxxxxx
>>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>> Please read the FAQ at http://www.tux.org/lkml/
>>>
>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at http://vger.kernel.org/majordomo-info.html



--
Best regards
Tianyu Lan
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/