|
@@ -88,6 +88,7 @@ struct acpi_res_list {
|
|
char name[5]; /* only can have a length of 4 chars, make use of this
|
|
char name[5]; /* only can have a length of 4 chars, make use of this
|
|
one instead of res->name, no need to kalloc then */
|
|
one instead of res->name, no need to kalloc then */
|
|
struct list_head resource_list;
|
|
struct list_head resource_list;
|
|
|
|
+ int count;
|
|
};
|
|
};
|
|
|
|
|
|
static LIST_HEAD(resource_list_head);
|
|
static LIST_HEAD(resource_list_head);
|
|
@@ -1358,6 +1359,89 @@ acpi_os_validate_interface (char *interface)
|
|
return AE_SUPPORT;
|
|
return AE_SUPPORT;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static inline int acpi_res_list_add(struct acpi_res_list *res)
|
|
|
|
+{
|
|
|
|
+ struct acpi_res_list *res_list_elem;
|
|
|
|
+
|
|
|
|
+ list_for_each_entry(res_list_elem, &resource_list_head,
|
|
|
|
+ resource_list) {
|
|
|
|
+
|
|
|
|
+ if (res->resource_type == res_list_elem->resource_type &&
|
|
|
|
+ res->start == res_list_elem->start &&
|
|
|
|
+ res->end == res_list_elem->end) {
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * The Region(addr,len) already exist in the list,
|
|
|
|
+ * just increase the count
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ res_list_elem->count++;
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ res->count = 1;
|
|
|
|
+ list_add(&res->resource_list, &resource_list_head);
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static inline void acpi_res_list_del(struct acpi_res_list *res)
|
|
|
|
+{
|
|
|
|
+ struct acpi_res_list *res_list_elem;
|
|
|
|
+
|
|
|
|
+ list_for_each_entry(res_list_elem, &resource_list_head,
|
|
|
|
+ resource_list) {
|
|
|
|
+
|
|
|
|
+ if (res->resource_type == res_list_elem->resource_type &&
|
|
|
|
+ res->start == res_list_elem->start &&
|
|
|
|
+ res->end == res_list_elem->end) {
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * If the res count is decreased to 0,
|
|
|
|
+ * remove and free it
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ if (--res_list_elem->count == 0) {
|
|
|
|
+ list_del(&res_list_elem->resource_list);
|
|
|
|
+ kfree(res_list_elem);
|
|
|
|
+ }
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+acpi_status
|
|
|
|
+acpi_os_invalidate_address(
|
|
|
|
+ u8 space_id,
|
|
|
|
+ acpi_physical_address address,
|
|
|
|
+ acpi_size length)
|
|
|
|
+{
|
|
|
|
+ struct acpi_res_list res;
|
|
|
|
+
|
|
|
|
+ switch (space_id) {
|
|
|
|
+ case ACPI_ADR_SPACE_SYSTEM_IO:
|
|
|
|
+ case ACPI_ADR_SPACE_SYSTEM_MEMORY:
|
|
|
|
+ /* Only interference checks against SystemIO and SytemMemory
|
|
|
|
+ are needed */
|
|
|
|
+ res.start = address;
|
|
|
|
+ res.end = address + length - 1;
|
|
|
|
+ res.resource_type = space_id;
|
|
|
|
+ spin_lock(&acpi_res_lock);
|
|
|
|
+ acpi_res_list_del(&res);
|
|
|
|
+ spin_unlock(&acpi_res_lock);
|
|
|
|
+ break;
|
|
|
|
+ case ACPI_ADR_SPACE_PCI_CONFIG:
|
|
|
|
+ case ACPI_ADR_SPACE_EC:
|
|
|
|
+ case ACPI_ADR_SPACE_SMBUS:
|
|
|
|
+ case ACPI_ADR_SPACE_CMOS:
|
|
|
|
+ case ACPI_ADR_SPACE_PCI_BAR_TARGET:
|
|
|
|
+ case ACPI_ADR_SPACE_DATA_TABLE:
|
|
|
|
+ case ACPI_ADR_SPACE_FIXED_HARDWARE:
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ return AE_OK;
|
|
|
|
+}
|
|
|
|
+
|
|
/******************************************************************************
|
|
/******************************************************************************
|
|
*
|
|
*
|
|
* FUNCTION: acpi_os_validate_address
|
|
* FUNCTION: acpi_os_validate_address
|
|
@@ -1382,6 +1466,7 @@ acpi_os_validate_address (
|
|
char *name)
|
|
char *name)
|
|
{
|
|
{
|
|
struct acpi_res_list *res;
|
|
struct acpi_res_list *res;
|
|
|
|
+ int added;
|
|
if (acpi_enforce_resources == ENFORCE_RESOURCES_NO)
|
|
if (acpi_enforce_resources == ENFORCE_RESOURCES_NO)
|
|
return AE_OK;
|
|
return AE_OK;
|
|
|
|
|
|
@@ -1399,14 +1484,17 @@ acpi_os_validate_address (
|
|
res->end = address + length - 1;
|
|
res->end = address + length - 1;
|
|
res->resource_type = space_id;
|
|
res->resource_type = space_id;
|
|
spin_lock(&acpi_res_lock);
|
|
spin_lock(&acpi_res_lock);
|
|
- list_add(&res->resource_list, &resource_list_head);
|
|
|
|
|
|
+ added = acpi_res_list_add(res);
|
|
spin_unlock(&acpi_res_lock);
|
|
spin_unlock(&acpi_res_lock);
|
|
- pr_debug("Added %s resource: start: 0x%llx, end: 0x%llx, "
|
|
|
|
- "name: %s\n", (space_id == ACPI_ADR_SPACE_SYSTEM_IO)
|
|
|
|
|
|
+ pr_debug("%s %s resource: start: 0x%llx, end: 0x%llx, "
|
|
|
|
+ "name: %s\n", added ? "Added" : "Already exist",
|
|
|
|
+ (space_id == ACPI_ADR_SPACE_SYSTEM_IO)
|
|
? "SystemIO" : "System Memory",
|
|
? "SystemIO" : "System Memory",
|
|
(unsigned long long)res->start,
|
|
(unsigned long long)res->start,
|
|
(unsigned long long)res->end,
|
|
(unsigned long long)res->end,
|
|
res->name);
|
|
res->name);
|
|
|
|
+ if (!added)
|
|
|
|
+ kfree(res);
|
|
break;
|
|
break;
|
|
case ACPI_ADR_SPACE_PCI_CONFIG:
|
|
case ACPI_ADR_SPACE_PCI_CONFIG:
|
|
case ACPI_ADR_SPACE_EC:
|
|
case ACPI_ADR_SPACE_EC:
|