pnp: add PNP resource range checking function
Subsystems (4)
PATCH 1/1 pnp: add PNP resource range checking function
This patch adds a new export from the ACPI PNP core, is_acpi_pnp_reserved, which is intended for use by drivers to check whether a given range is already reserved (and therefore likely safe to use) or not (indicating that new resource space should probably be allocated).
If it looks reasonable, there's code in arch/x86/pci that could probably be moved over to this as well.
drivers/pnp/pnpacpi/core.c +35 -0
@@ -27,6 +27,94 @@#include "../base.h" #include "pnpacpi.h" +/* +* Check the given resource against our test range +*/ +static acpi_status check_pnp_resource (struct acpi_resource *res, +void *data) +{ +struct resource *test_res = data; +struct acpi_resource_address64 address; +acpi_status status; + +if (res->type ==ACPI_RESOURCE_TYPE_FIXED_MEMORY32 ) { +struct acpi_resource_fixed_memory32 *fixmem32 = + &res->data.fixed_memory32; +if (!fixmem32) +return AE_OK ; + +if ((test_res->start >= fixmem32->address) && + (test_res->end < (fixmem32->address + + fixmem32->address_length))) { + test_res->flags =1 ; +return AE_CTRL_TERMINATE ; + } + } +if ((res->type !=ACPI_RESOURCE_TYPE_ADDRESS32 ) && + (res->type !=ACPI_RESOURCE_TYPE_ADDRESS64 )) +return AE_OK ; + + status =acpi_resource_to_address64 (res, &address); +if (ACPI_FAILURE (status) || + (address.address_length <=0 ) || + (address.resource_type !=ACPI_MEMORY_RANGE )) +return AE_OK ; + + if ((test_res->start >= address.minimum) && + (test_res->end < (address.minimum +
address.address_length))) {
+ test_res->flags = 1;
+ return AE_CTRL_TERMINATE;
+ }
+ return AE_OK;
+}
+
+/*
+ * Walk the current resource settings and check status
+ */
+static acpi_status find_pnp_resource(acpi_handle handle, u32 lvl,
+ void *context, void **rv)
+{
+ struct resource *res = context;
+
+ acpi_walk_resources(handle, METHOD_NAME__CRS,
+ check_pnp_resource, context);
+
+ if (res->flags)
+ return AE_CTRL_TERMINATE;
+
+ return AE_OK;
+}
+
+/**
+ * is_acpi_pnp_reserved - check whether a given range is reserved
+ * @start: start of range
+ * @end: end of range
+ *
+ * Check the given range (specified by @start and @end) against the current
+ * PNP resource settings.
+ *
+ * RETURNS:
+ * Zero if the range is not currently reserved.
+ * Nonzero if the range is reserved.
+ */
+int is_acpi_pnp_reserved(u64 start, u64 end)
+{
+ struct resource res;
+
+ res.start = start;
+ res.end = end;
+ res.flags = 0;
+
+ acpi_get_devices("PNP0C01", find_pnp_resource, &res, NULL);
+
+ if (!res.flags)
+ acpi_get_devices("PNP0C02", find_pnp_resource, &res,
+ NULL);
+
+ return res.flags;
+}
+EXPORT_SYMBOL(is_acpi_pnp_reserved);
+
static int num = 0;
/* We need only to blacklist devices that have already an acpi driver
that diff --git a/include/linux/pnp.h b/include/linux/pnp.h index ca3c887..2bc9cfc 100644
include/linux/pnp.h +1 -0
@@ -446,6 +446,7 @@ int pnp_start_dev(struct pnp_dev *dev);int pnp_stop_dev (struct pnp_dev *dev);int pnp_activate_dev (struct pnp_dev *dev);int pnp_disable_dev (struct pnp_dev *dev); +int is_acpi_pnp_reserved (u64 start,u64 end);/* protocol helpers */ int pnp_is_active (struct pnp_dev *dev);
@@ -476,6 +477,7 @@ static inline int pnp_start_dev(struct pnp_dev
*dev) { return -ENODEV; } static inline int pnp_stop_dev(struct pnp_dev *dev) { return -ENODEV; } static inline int pnp_activate_dev(struct pnp_dev *dev) { return -ENODEV; } static inline int pnp_disable_dev(struct pnp_dev *dev) { return -ENODEV; } +static inline int is_acpi_pnp_reserved(u64 start, u64 end) { return FALSE; }
/* protocol helpers */
static inline int pnp_is_active(struct pnp_dev *dev) { return 0; }
PATCH 1/1 i915: enable MCHBAR if needed
Using the new PNP resource checking code, this patch allows the i915 driver to allocate MCHBAR space if needed and use the BAR to determine current memory settings.
Testing & feedback welcome.
drivers/gpu/drm/i915/i915_drv.h +2 -0
@@ -143,6 +143,8 @@ typedef struct drm_i915_private {drm_local_map_t hws_map;struct drm_gem_object *hws_obj; +struct resource mch_res; +unsigned int cpp;int back_offset;int front_offset;
drivers/gpu/drm/i915/i915_gem_tiling.c +145 -0
175 lines not on this page · raw message
Quoted 5 lines · Jesse Barnes
This patch adds a new export from the ACPI PNP core,
is_acpi_pnp_reserved, which is intended for use by drivers to check whether a given range is already reserved (and therefore likely safe to use) or not (indicating that new resource space should probably be allocated).
This doesn't really need to be ACPI-specific, does it? And can't you use the pre-parsed resources in pnp_dev->resources? And wouldn't you just look at all resources for all PNP devices, not just the PNP0C01/2 ones?
Sorry I don't have time to code up an example right now; maybe next week, though, if you remind me :-)
Bjorn
Quoted 127 lines
If it looks reasonable, there's code in
arch/x86/pcithat could probably be moved over to this as well.Signed-off-by Jesse Barnes <[email protected]>drivers/pnp/pnpacpi/core.c +64
-0@@ -27,6 +27,94 @@#include "../base.h" #include "pnpacpi.h" +/* +* Check the given resource against our test range +*/ +static acpi_status check_pnp_resource (struct acpi_resource *res, +void *data) +{ +struct resource *test_res = data; +struct acpi_resource_address64 address; +acpi_status status; + +if (res->type ==ACPI_RESOURCE_TYPE_FIXED_MEMORY32 ) { +struct acpi_resource_fixed_memory32 *fixmem32 = + &res->data.fixed_memory32; +if (!fixmem32) +return AE_OK ; + +if ((test_res->start >= fixmem32->address) && + (test_res->end < (fixmem32->address + + fixmem32->address_length))) { + test_res->flags =1 ; +return AE_CTRL_TERMINATE ; + } + } +if ((res->type !=ACPI_RESOURCE_TYPE_ADDRESS32 ) && + (res->type !=ACPI_RESOURCE_TYPE_ADDRESS64 )) +return AE_OK ; + + status =acpi_resource_to_address64 (res, &address); +if (ACPI_FAILURE (status) || + (address.address_length <=0 ) || + (address.resource_type !=ACPI_MEMORY_RANGE )) +return AE_OK ; + +if ((test_res->start >= address.minimum) && + (test_res->end < (address.minimum + address.address_length))) { + test_res->flags =1 ; +return AE_CTRL_TERMINATE ; + } +return AE_OK ; +} + +/* +* Walk the current resource settings and check status +*/ +static acpi_status find_pnp_resource (acpi_handle handle,u32 lvl, +void *context,void **rv) +{ +struct resource *res = context; + +acpi_walk_resources (handle,METHOD_NAME__CRS , + check_pnp_resource, context); + +if (res->flags) +return AE_CTRL_TERMINATE ; + +return AE_OK ; +} + +/** +* is_acpi_pnp_reserved - check whether a given range is reserved +* @start: start of range +* @end: end of range +* +* Check the given range (specified by @start and @end) against the current
+ * PNP resource settings.
+ *
+ * RETURNS:
+ * Zero if the range is not currently reserved.
+ * Nonzero if the range is reserved.
+ */drivers/pnp/pnpacpi/core.c +18
-0+int is_acpi_pnp_reserved (u64 start,u64 end) +{ +struct resource res; + + res.start = start; + res.end = end; + res.flags =0 ; + +acpi_get_devices ("PNP0C01" , find_pnp_resource, &res,NULL ); + +if (!res.flags) +acpi_get_devices ("PNP0C02" , find_pnp_resource, &res, +NULL ); + +return res.flags; +} +EXPORT_SYMBOL (is_acpi_pnp_reserved); +static int num =0 ;/* We need only to blacklist devices that have already an acpi driver that diff --git
a/include/linux/pnp.hb/include/linux/pnp.hindex ca3c887..2bc9cfc 100644include/linux/pnp.h +1
-0@@ -446,6 +446,7 @@ int pnp_start_dev(struct pnp_dev *dev);int pnp_stop_dev (struct pnp_dev *dev);int pnp_activate_dev (struct pnp_dev *dev);int pnp_disable_dev (struct pnp_dev *dev); +int is_acpi_pnp_reserved (u64 start,u64 end);/* protocol helpers */ int pnp_is_active (struct pnp_dev *dev);@@ -476,6 +477,7 @@ static inline int pnp_start_dev(struct pnp_dev *dev) { return -ENODEV; } static inline int pnp_stop_dev(struct pnp_dev *dev) { return -ENODEV; } static inline int pnp_activate_dev(struct
pnp_dev*dev) { return-ENODEV; } static inline intpnp_disable_dev(struct pnp_dev *dev){ return-ENODEV; } +static inline intis_acpi_pnp_reserved(u64 start, u64 end){ return FALSE; }
/* protocol helpers */
static inline intpnp_is_active(struct pnp_dev *dev){ return 0; }
Quoted 7 lines · On Tue, 14 Apr 2009 16:53:11 -0600 Bjorn Helgaas <[email protected]> wrote:
Quoted 5 lines · Jesse Barnes
This patch adds a new export from the ACPI PNP core,
is_acpi_pnp_reserved, which is intended for use by drivers to check whether a given range is already reserved (and therefore likely safe to use) or not (indicating that new resource space should probably be allocated).
Quoted 7 lines
This doesn't really need to be ACPI-specific, does it? And can't you use the pre-parsed resources in
pnp_dev->resources? And wouldn't you just look at all resources for all PNP devices, not just the PNP0C01/2 ones?Sorry I don't have time to code up an example right now; maybe next week, though, if you remind me :-)
Sure, that all sounds reasonable... I'll try to remind you. :)
Signature · 1 line
Jesse Barnes, Intel Open Source Technology Center
Quoted 15 lines · Jesse Barnes
Quoted 12 lines · On Tue, 14 Apr 2009 16:53:11 -0600 Bjorn Helgaas <[email protected]> wrote:
Quoted 5 lines · Jesse Barnes
This patch adds a new export from the ACPI PNP core,
is_acpi_pnp_reserved, which is intended for use by drivers to check whether a given range is already reserved (and therefore likely safe to use) or not (indicating that new resource space should probably be allocated).This doesn't really need to be ACPI-specific, does it? And can't you use the pre-parsed resources in
pnp_dev->resources? And wouldn't you just look at all resources for all PNP devices, not just the PNP0C01/2 ones?
Quoted 4 lines
Quoted 2 lines
Sorry I don't have time to code up an example right now; maybe next week, though, if you remind me :-)
Sure, that all sounds reasonable... I'll try to remind you. :)
Here's the sort of thing I was thinking (untested).
--- drivers/pnp/resource.c | 17 +++++++++++++++++ 1 files changed, 17 insertions(+), 0 deletions(-)
drivers/pnp/resource.c +17 -0
@@ -638,6 +638,23 @@ int pnp_possible_config(struct pnp_dev *dev, int type, resource_size_t start, }EXPORT_SYMBOL (pnp_possible_config); +int pnp_range_reserved (resource_size_t start,resource_size_t end) +{ +struct pnp_dev *dev; +struct pnp_resource *pnp_res; +resource_size_t *dev_start, *dev_end; + +pnp_for_each_dev (dev) { +list_for_each_entry (pnp_res, &dev->resources, list) { + dev_start = &pnp_res->res.start; + dev_end = &pnp_res->res.end; +if (ranged_conflict (&start, &end, dev_start, dev_end)) +return 1 ; + } + } +return 0 ; +} +/* format is: pnp_reserve_irq=irq1[,irq2] .... */ static int __init pnp_setup_reserve_irq (char *str) {