Correctly handle BIOS resources that are duplicated (!). There are many
systems that have overlapping regions specified in their sysresource objects. This patch fixes ATA DMA and acpi_timer allocation for such sysctems. It should eventually be moved to resource_list_add() if it is a valid generalized approach. The minimal approach for 5.3 is: "Loop through all current resources to see if the new one overlaps any existing ones. If so, the old one always takes precedence and the new one is adjusted (or rejected). We check for three cases: 1. Tail of new resource overlaps head of old resource: truncate the new resource so it is contiguous with the start of the old. 2. New resource wholly contained within the old resource: error. 3. Head of new resource overlaps tail of old resource: truncate the new resource so it is contiguous, following the old." Tested by: Radek Kozlowski <radek_at_raadradd.com> Discussed with: imp MFC after: 4 days
This commit is contained in:
parent
7500723246
commit
d22e9c6e0d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=134086
@ -504,6 +504,51 @@ struct acpi_res_context {
|
||||
void *ar_parent;
|
||||
};
|
||||
|
||||
/*
|
||||
* Add a resource to the device's resource list. We define our own function
|
||||
* for this since bus_set_resource() doesn't handle duplicates of any kind.
|
||||
*
|
||||
* XXX This should be merged into resource_list_add() eventually.
|
||||
*/
|
||||
static int
|
||||
acpi_reslist_add(device_t dev, int type, int rid, u_long start, u_long count)
|
||||
{
|
||||
struct resource_list_entry *rle;
|
||||
struct resource_list *rl;
|
||||
u_long end;
|
||||
|
||||
end = start + count - 1;
|
||||
rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev);
|
||||
|
||||
/*
|
||||
* Loop through all current resources to see if the new one overlaps
|
||||
* any existing ones. If so, the old one always takes precedence and
|
||||
* the new one is adjusted (or rejected). We check for three cases:
|
||||
*
|
||||
* 1. Tail of new resource overlaps head of old resource: truncate the
|
||||
* new resource so it is contiguous with the start of the old.
|
||||
* 2. New resource wholly contained within the old resource: error.
|
||||
* 3. Head of new resource overlaps tail of old resource: truncate the
|
||||
* new resource so it is contiguous, following the old.
|
||||
*/
|
||||
SLIST_FOREACH(rle, rl, link) {
|
||||
if (rle->type == type) {
|
||||
if (start < rle->start && end >= rle->start) {
|
||||
count = rle->start - start;
|
||||
break;
|
||||
} else if (start >= rle->start && start <= rle->end) {
|
||||
if (end > rle->end) {
|
||||
start = rle->end + 1;
|
||||
count = end - rle->end + 1;
|
||||
break;
|
||||
} else
|
||||
return (EEXIST);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (bus_set_resource(dev, type, rid, start, count));
|
||||
}
|
||||
|
||||
static void
|
||||
acpi_res_set_init(device_t dev, void *arg, void **context)
|
||||
{
|
||||
@ -534,7 +579,7 @@ acpi_res_set_ioport(device_t dev, void *context, u_int32_t base,
|
||||
|
||||
if (cp == NULL)
|
||||
return;
|
||||
bus_set_resource(dev, SYS_RES_IOPORT, cp->ar_nio++, base, length);
|
||||
acpi_reslist_add(dev, SYS_RES_IOPORT, cp->ar_nio++, base, length);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -557,7 +602,7 @@ acpi_res_set_memory(device_t dev, void *context, u_int32_t base,
|
||||
if (cp == NULL)
|
||||
return;
|
||||
|
||||
bus_set_resource(dev, SYS_RES_MEMORY, cp->ar_nmem++, base, length);
|
||||
acpi_reslist_add(dev, SYS_RES_MEMORY, cp->ar_nmem++, base, length);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -584,7 +629,7 @@ acpi_res_set_irq(device_t dev, void *context, u_int32_t *irq, int count,
|
||||
if (count != 1)
|
||||
return;
|
||||
|
||||
bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1);
|
||||
acpi_reslist_add(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -599,7 +644,7 @@ acpi_res_set_drq(device_t dev, void *context, u_int32_t *drq, int count)
|
||||
if (count != 1)
|
||||
return;
|
||||
|
||||
bus_set_resource(dev, SYS_RES_DRQ, cp->ar_ndrq++, *drq, 1);
|
||||
acpi_reslist_add(dev, SYS_RES_DRQ, cp->ar_ndrq++, *drq, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
|
Loading…
Reference in New Issue
Block a user