#ifdef CONFIG_X86 #define valid_IRQ(i) (((i) != 0) && ((i) != 2)) staticinlinebool acpi_iospace_resource_valid(struct resource *res)
{ /* On X86 IO space is limited to the [0 - 64K] IO port range */ return res->end < 0x10003;
} #else #define valid_IRQ(i) (true) /* * ACPI IO descriptors on arches other than X86 contain MMIO CPU physical * addresses mapping IO space in CPU physical address space, IO space * resources can be placed anywhere in the 64-bit physical address space.
*/ staticinlinebool
acpi_iospace_resource_valid(struct resource *res) { returntrue; } #endif
/* * CHECKME: len might be required to check versus a minimum * length as well. 1 for io is fine, but for memory it does * not make any sense at all. * Note: some BIOSes report incorrect length for ACPI address space * descriptor, so remove check of 'reslen == len' to avoid regression.
*/ if (len && reslen && start <= end) returntrue;
/** * acpi_dev_resource_memory - Extract ACPI memory resource information. * @ares: Input ACPI resource object. * @res: Output generic resource object. * * Check if the given ACPI resource object represents a memory resource and * if that's the case, use the information in it to populate the generic * resource object pointed to by @res. * * Return: * 1) false with res->flags setting to zero: not the expected resource type * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource * 3) true: valid assigned resource
*/ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)
{ struct acpi_resource_memory24 *memory24; struct acpi_resource_memory32 *memory32; struct acpi_resource_fixed_memory32 *fixed_memory32;
/** * acpi_dev_resource_io - Extract ACPI I/O resource information. * @ares: Input ACPI resource object. * @res: Output generic resource object. * * Check if the given ACPI resource object represents an I/O resource and * if that's the case, use the information in it to populate the generic * resource object pointed to by @res. * * Return: * 1) false with res->flags setting to zero: not the expected resource type * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource * 3) true: valid assigned resource
*/ bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res)
{ struct acpi_resource_io *io; struct acpi_resource_fixed_io *fixed_io;
/* * Filter out invalid descriptor according to ACPI Spec 5.0, section * 6.4.3.5 Address Space Resource Descriptors.
*/ if ((addr->min_address_fixed != addr->max_address_fixed && len) ||
(addr->min_address_fixed && addr->max_address_fixed && !len))
pr_debug("ACPI: Invalid address space min_addr_fix %d, max_addr_fix %d, len %llx\n",
addr->min_address_fixed, addr->max_address_fixed, len);
/* * For bridges that translate addresses across the bridge, * translation_offset is the offset that must be added to the * address on the secondary side to obtain the address on the * primary side. Non-bridge devices must list 0 for all Address * Translation offset bits.
*/ if (addr->producer_consumer == ACPI_PRODUCER)
offset = attr->translation_offset; elseif (attr->translation_offset)
pr_debug("ACPI: translation_offset(%lld) is invalid for non-bridge device.\n",
attr->translation_offset);
start = attr->minimum + offset;
end = attr->maximum + offset;
win->offset = offset;
res->start = start;
res->end = end; if (sizeof(resource_size_t) < sizeof(u64) &&
(offset != win->offset || start != res->start || end != res->end)) {
pr_warn("acpi resource window ([%#llx-%#llx] ignored, not CPU addressable)\n",
attr->minimum, attr->maximum); returnfalse;
}
switch (addr->resource_type) { case ACPI_MEMORY_RANGE:
acpi_dev_memresource_flags(res, len, wp);
if (addr->info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
res->flags |= IORESOURCE_PREFETCH; break; case ACPI_IO_RANGE:
acpi_dev_ioresource_flags(res, len, iodec,
addr->info.io.translation_type); break; case ACPI_BUS_NUMBER_RANGE:
res->flags = IORESOURCE_BUS; break; default: returnfalse;
}
if (addr->producer_consumer == ACPI_PRODUCER)
res->flags |= IORESOURCE_WINDOW;
return !(res->flags & IORESOURCE_DISABLED);
}
/** * acpi_dev_resource_address_space - Extract ACPI address space information. * @ares: Input ACPI resource object. * @win: Output generic resource object. * * Check if the given ACPI resource object represents an address space resource * and if that's the case, use the information in it to populate the generic * resource object pointed to by @win. * * Return: * 1) false with win->res.flags setting to zero: not the expected resource type * 2) false with IORESOURCE_DISABLED in win->res.flags: valid unassigned * resource * 3) true: valid assigned resource
*/ bool acpi_dev_resource_address_space(struct acpi_resource *ares, struct resource_win *win)
{ struct acpi_resource_address64 addr;
win->res.flags = 0; if (ACPI_FAILURE(acpi_resource_to_address64(ares, &addr))) returnfalse;
/** * acpi_dev_resource_ext_address_space - Extract ACPI address space information. * @ares: Input ACPI resource object. * @win: Output generic resource object. * * Check if the given ACPI resource object represents an extended address space * resource and if that's the case, use the information in it to populate the * generic resource object pointed to by @win. * * Return: * 1) false with win->res.flags setting to zero: not the expected resource type * 2) false with IORESOURCE_DISABLED in win->res.flags: valid unassigned * resource * 3) true: valid assigned resource
*/ bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares, struct resource_win *win)
{ struct acpi_resource_extended_address64 *ext_addr;
win->res.flags = 0; if (ares->type != ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64) returnfalse;
/** * acpi_dev_irq_flags - Determine IRQ resource flags. * @triggering: Triggering type as provided by ACPI. * @polarity: Interrupt polarity as provided by ACPI. * @shareable: Whether or not the interrupt is shareable. * @wake_capable: Wake capability as provided by ACPI.
*/ unsignedlong acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable, u8 wake_capable)
{ unsignedlong flags;
#ifdef CONFIG_X86 /* * Always use the MADT override info, except for the i8042 PS/2 ctrl * IRQs (1 and 12). For these the DSDT IRQ settings should sometimes * be used otherwise PS/2 keyboards / mice will not work.
*/ if (gsi != 1 && gsi != 12) returntrue;
/* If the override comes from an INT_SRC_OVR MADT entry, honor it. */ if (acpi_int_src_ovr[gsi]) returntrue;
/* * IRQ override isn't needed on modern AMD Zen systems and * this override breaks active low IRQs on AMD Ryzen 6000 and * newer systems. Skip it.
*/ if (boot_cpu_has(X86_FEATURE_ZEN)) returnfalse; #endif
if (!valid_IRQ(gsi)) {
irqresource_disabled(res, gsi); return;
}
/* * In IO-APIC mode, use overridden attribute. Two reasons: * 1. BIOS bug in DSDT * 2. BIOS uses IO-APIC mode Interrupt Source Override * * We do this only if we are dealing with IRQ() or IRQNoFlags() * resource (the legacy ISA resources). With modern ACPI 5 devices * using extended IRQ descriptors we take the IRQ configuration * from _CRS directly.
*/ if (check_override &&
acpi_dev_irq_override(gsi, triggering, polarity, shareable) &&
!acpi_get_override_irq(gsi, &t, &p)) {
u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
if (triggering != trig || polarity != pol) {
pr_warn("ACPI: IRQ %d override to %s%s, %s%s\n", gsi,
t ? "level" : "edge",
trig == triggering ? "" : "(!)",
p ? "low" : "high",
pol == polarity ? "" : "(!)");
triggering = trig;
polarity = pol;
}
}
/** * acpi_dev_resource_interrupt - Extract ACPI interrupt resource information. * @ares: Input ACPI resource object. * @index: Index into the array of GSIs represented by the resource. * @res: Output generic resource object. * * Check if the given ACPI resource object represents an interrupt resource * and @index does not exceed the resource's interrupt count (true is returned * in that case regardless of the results of the other checks)). If that's the * case, register the GSI corresponding to @index from the array of interrupts * represented by the resource and populate the generic resource object pointed * to by @res accordingly. If the registration of the GSI is not successful, * IORESOURCE_DISABLED will be set it that object's flags. * * Return: * 1) false with res->flags setting to zero: not the expected resource type * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource * 3) true: valid assigned resource
*/ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index, struct resource *res)
{ struct acpi_resource_irq *irq; struct acpi_resource_extended_irq *ext_irq;
switch (ares->type) { case ACPI_RESOURCE_TYPE_IRQ: /* * Per spec, only one interrupt per descriptor is allowed in * _CRS, but some firmware violates this, so parse them all.
*/
irq = &ares->data.irq; if (index >= irq->interrupt_count) {
irqresource_disabled(res, 0); returnfalse;
}
acpi_dev_get_irqresource(res, irq->interrupts[index],
irq->triggering, irq->polarity,
irq->shareable, irq->wake_capable, true); break; case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
ext_irq = &ares->data.extended_irq; if (index >= ext_irq->interrupt_count) {
irqresource_disabled(res, 0); returnfalse;
} if (is_gsi(ext_irq))
acpi_dev_get_irqresource(res, ext_irq->interrupts[index],
ext_irq->triggering, ext_irq->polarity,
ext_irq->shareable, ext_irq->wake_capable, false); else
irqresource_disabled(res, 0); break; default:
res->flags = 0; returnfalse;
}
/** * acpi_dev_free_resource_list - Free resource from %acpi_dev_get_resources(). * @list: The head of the resource list to free.
*/ void acpi_dev_free_resource_list(struct list_head *list)
{
resource_list_free(list);
}
EXPORT_SYMBOL_GPL(acpi_dev_free_resource_list);
struct res_proc_context { struct list_head *list; int (*preproc)(struct acpi_resource *, void *); void *preproc_data; int count; int error;
};
/** * acpi_dev_get_resources - Get current resources of a device. * @adev: ACPI device node to get the resources for. * @list: Head of the resultant list of resources (must be empty). * @preproc: The caller's preprocessing routine. * @preproc_data: Pointer passed to the caller's preprocessing routine. * * Evaluate the _CRS method for the given device node and process its output by * (1) executing the @preproc() routine provided by the caller, passing the * resource pointer and @preproc_data to it as arguments, for each ACPI resource * returned and (2) converting all of the returned ACPI resources into struct * resource objects if possible. If the return value of @preproc() in step (1) * is different from 0, step (2) is not applied to the given ACPI resource and * if that value is negative, the whole processing is aborted and that value is * returned as the final error code. * * The resultant struct resource objects are put on the list pointed to by * @list, that must be empty initially, as members of struct resource_entry * objects. Callers of this routine should use %acpi_dev_free_resource_list() to * free that list. * * The number of resources in the output list is returned on success, an error * code reflecting the error condition is returned otherwise.
*/ int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list, int (*preproc)(struct acpi_resource *, void *), void *preproc_data)
{ return __acpi_dev_get_resources(adev, list, preproc, preproc_data,
METHOD_NAME__CRS);
}
EXPORT_SYMBOL_GPL(acpi_dev_get_resources);
/** * acpi_dev_get_dma_resources - Get current DMA resources of a device. * @adev: ACPI device node to get the resources for. * @list: Head of the resultant list of resources (must be empty). * * Evaluate the _DMA method for the given device node and process its * output. * * The resultant struct resource objects are put on the list pointed to * by @list, that must be empty initially, as members of struct * resource_entry objects. Callers of this routine should use * %acpi_dev_free_resource_list() to free that list. * * The number of resources in the output list is returned on success, * an error code reflecting the error condition is returned otherwise.
*/ int acpi_dev_get_dma_resources(struct acpi_device *adev, struct list_head *list)
{ return __acpi_dev_get_resources(adev, list, is_memory, NULL,
METHOD_NAME__DMA);
}
EXPORT_SYMBOL_GPL(acpi_dev_get_dma_resources);
/** * acpi_dev_get_memory_resources - Get current memory resources of a device. * @adev: ACPI device node to get the resources for. * @list: Head of the resultant list of resources (must be empty). * * This is a helper function that locates all memory type resources of @adev * with acpi_dev_get_resources(). * * The number of resources in the output list is returned on success, an error * code reflecting the error condition is returned otherwise.
*/ int acpi_dev_get_memory_resources(struct acpi_device *adev, struct list_head *list)
{ return acpi_dev_get_resources(adev, list, is_memory, NULL);
}
EXPORT_SYMBOL_GPL(acpi_dev_get_memory_resources);
/** * acpi_dev_filter_resource_type - Filter ACPI resource according to resource * types * @ares: Input ACPI resource object. * @types: Valid resource types of IORESOURCE_XXX * * This is a helper function to support acpi_dev_get_resources(), which filters * ACPI resource objects according to resource types.
*/ int acpi_dev_filter_resource_type(struct acpi_resource *ares, unsignedlong types)
{ unsignedlong type = 0;
switch (ares->type) { case ACPI_RESOURCE_TYPE_MEMORY24: case ACPI_RESOURCE_TYPE_MEMORY32: case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
type = IORESOURCE_MEM; break; case ACPI_RESOURCE_TYPE_IO: case ACPI_RESOURCE_TYPE_FIXED_IO:
type = IORESOURCE_IO; break; case ACPI_RESOURCE_TYPE_IRQ: case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
type = IORESOURCE_IRQ; break; case ACPI_RESOURCE_TYPE_DMA: case ACPI_RESOURCE_TYPE_FIXED_DMA:
type = IORESOURCE_DMA; break; case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
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 (ares->data.address.resource_type == ACPI_MEMORY_RANGE)
type = IORESOURCE_MEM; elseif (ares->data.address.resource_type == ACPI_IO_RANGE)
type = IORESOURCE_IO; elseif (ares->data.address.resource_type ==
ACPI_BUS_NUMBER_RANGE)
type = IORESOURCE_BUS; break; default: break;
}
if (acpi_dev_consumes_res(adev, res)) {
*consumer = adev; return AE_CTRL_TERMINATE;
}
return AE_OK;
}
/** * acpi_resource_consumer - Find the ACPI device that consumes @res. * @res: Resource to search for. * * Search the current resource settings (_CRS) of every ACPI device node * for @res. If we find an ACPI device whose _CRS includes @res, return * it. Otherwise, return NULL.
*/ struct acpi_device *acpi_resource_consumer(struct resource *res)
{ struct acpi_device *consumer = NULL;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.