From 1071695f17daf050638e0bc550db647f8237c3bb Mon Sep 17 00:00:00 2001 From: David Brownell Date: Fri, 22 Feb 2008 21:54:24 -0800 Subject: ACPI: crosslink ACPI and "real" device nodes Add cross-links between ACPI device and "real" devices in sysfs, exposing otherwise-hidden interrelationships between the various device nodes for ACPI stuff. As a representative example, one hardware device is exposed as two logical devices (PNP and ACPI): .../pnp0/00:06/ .../LNXSYSTM:00/device:00/PNP0A03:00/device:15/PNP0B00:00/ The PNP device gets a "firmware_node" link pointing to the ACPI device, and is what a Linux device driver binds to. The ACPI device has instead a "physical_node" link pointing back to the PNP device. Other firmware frameworks, like OpenFirmware, could do the same thing to couple their firmware tables to the rest of the system. (Based on a patch from Zhang Rui. This version is modified to not depend on the patch makig ACPI initialize driver model wakeup flags.) Signed-off-by: David Brownell Cc: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/glue.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index eda0978b57c6..06f8634fe58b 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -142,6 +142,7 @@ EXPORT_SYMBOL(acpi_get_physical_device); static int acpi_bind_one(struct device *dev, acpi_handle handle) { + struct acpi_device *acpi_dev; acpi_status status; if (dev->archdata.acpi_handle) { @@ -157,6 +158,16 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle) } dev->archdata.acpi_handle = handle; + status = acpi_bus_get_device(handle, &acpi_dev); + if (!ACPI_FAILURE(status)) { + int ret; + + ret = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj, + "firmware_node"); + ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj, + "physical_node"); + } + return 0; } @@ -165,8 +176,17 @@ static int acpi_unbind_one(struct device *dev) if (!dev->archdata.acpi_handle) return 0; if (dev == acpi_get_physical_device(dev->archdata.acpi_handle)) { + struct acpi_device *acpi_dev; + /* acpi_get_physical_device increase refcnt by one */ put_device(dev); + + if (!acpi_bus_get_device(dev->archdata.acpi_handle, + &acpi_dev)) { + sysfs_remove_link(&dev->kobj, "firmware_node"); + sysfs_remove_link(&acpi_dev->dev.kobj, "physical_node"); + } + acpi_detach_data(dev->archdata.acpi_handle, acpi_glue_data_handler); dev->archdata.acpi_handle = NULL; -- cgit v1.2.2 From e6e82a3087e6dad619149246082c910623ea9c36 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Fri, 21 Mar 2008 17:06:57 +0300 Subject: ACPI: EC: Restore udelay in poll mode This fixes keyboard event handling on some systems. Note that this delay was thought unnecessary, and removed from linux-2.6.20 with 50c1e1138cb94f6aca0f8555777edbcefe0324e2 'ACPI: ec: Drop udelay() from poll mode. Loop by reading status field instead.' Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 7222a18a0319..828c75292cf6 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -73,6 +73,7 @@ enum ec_event { #define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */ #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ +#define ACPI_EC_UDELAY 100 /* Wait 100us before polling EC again */ enum { EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */ @@ -227,6 +228,7 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) while (time_before(jiffies, delay)) { if (acpi_ec_check_status(ec, event)) goto end; + udelay(ACPI_EC_UDELAY); } } pr_err(PREFIX "acpi_ec_wait timeout," -- cgit v1.2.2 From 845625cdcb17119d5f6c5c8dbe586f2f36e8008a Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Fri, 21 Mar 2008 17:07:03 +0300 Subject: ACPI: EC: Add poll timer If we can not use interrupt mode of EC for some reason, start polling EC for events periodically. Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 43 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 828c75292cf6..63e0ac2644ad 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -84,6 +84,7 @@ enum { EC_FLAGS_NO_WDATA_GPE, /* Don't expect WDATA GPE event */ EC_FLAGS_WDATA, /* Data is being written */ EC_FLAGS_NO_OBF1_GPE, /* Don't expect GPE before read */ + EC_FLAGS_RESCHEDULE_POLL /* Re-schedule poll */ }; static int acpi_ec_remove(struct acpi_device *device, int type); @@ -130,6 +131,7 @@ static struct acpi_ec { struct mutex lock; wait_queue_head_t wait; struct list_head list; + struct delayed_work work; u8 handlers_installed; } *boot_ec, *first_ec; @@ -178,6 +180,20 @@ static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event) return 0; } +static void ec_schedule_ec_poll(struct acpi_ec *ec) +{ + if (test_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags)) + schedule_delayed_work(&ec->work, + msecs_to_jiffies(ACPI_EC_DELAY)); +} + +static void ec_switch_to_poll_mode(struct acpi_ec *ec) +{ + clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); + acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); + set_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); +} + static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) { int ret = 0; @@ -218,7 +234,8 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) if (printk_ratelimit()) pr_info(PREFIX "missing confirmations, " "switch off interrupt mode.\n"); - clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); + ec_switch_to_poll_mode(ec); + ec_schedule_ec_poll(ec); } goto end; } @@ -529,28 +546,37 @@ static u32 acpi_ec_gpe_handler(void *data) { acpi_status status = AE_OK; struct acpi_ec *ec = data; + u8 state = acpi_ec_read_status(ec); pr_debug(PREFIX "~~~> interrupt\n"); clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) wake_up(&ec->wait); - if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_SCI) { + if (state & ACPI_EC_FLAG_SCI) { if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) status = acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec); - } else if (unlikely(!test_bit(EC_FLAGS_GPE_MODE, &ec->flags))) { + } else if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && + in_interrupt()) { /* this is non-query, must be confirmation */ if (printk_ratelimit()) pr_info(PREFIX "non-query interrupt received," " switching to interrupt mode\n"); set_bit(EC_FLAGS_GPE_MODE, &ec->flags); + clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); } - + ec_schedule_ec_poll(ec); return ACPI_SUCCESS(status) ? ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; } +static void do_ec_poll(struct work_struct *work) +{ + struct acpi_ec *ec = container_of(work, struct acpi_ec, work.work); + (void)acpi_ec_gpe_handler(ec); +} + /* -------------------------------------------------------------------------- Address Space Management -------------------------------------------------------------------------- */ @@ -711,6 +737,7 @@ static struct acpi_ec *make_acpi_ec(void) mutex_init(&ec->lock); init_waitqueue_head(&ec->wait); INIT_LIST_HEAD(&ec->list); + INIT_DELAYED_WORK_DEFERRABLE(&ec->work, do_ec_poll); return ec; } @@ -752,8 +779,15 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) return AE_CTRL_TERMINATE; } +static void ec_poll_stop(struct acpi_ec *ec) +{ + clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); + cancel_delayed_work(&ec->work); +} + static void ec_remove_handlers(struct acpi_ec *ec) { + ec_poll_stop(ec); if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler))) pr_err(PREFIX "failed to remove space handler\n"); @@ -899,6 +933,7 @@ static int acpi_ec_start(struct acpi_device *device) /* EC is fully operational, allow queries */ clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); + ec_schedule_ec_poll(ec); return ret; } -- cgit v1.2.2 From dc0e8490fe884a9378b8ee04a5b5f905f06f4633 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Fri, 21 Mar 2008 17:07:09 +0300 Subject: ACPI: EC: Improve debug output Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 63e0ac2644ad..1a7949c757b3 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -248,9 +248,9 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) udelay(ACPI_EC_UDELAY); } } - pr_err(PREFIX "acpi_ec_wait timeout," - " status = %d, expect_event = %d\n", - acpi_ec_read_status(ec), event); + pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n", + acpi_ec_read_status(ec), + (event == ACPI_EC_EVENT_OBF_1) ? "\"b0=1\"" : "\"b1=0\""); ret = -ETIME; end: clear_bit(EC_FLAGS_ADDRESS, &ec->flags); @@ -264,8 +264,8 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, { int result = 0; set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); - acpi_ec_write_cmd(ec, command); pr_debug(PREFIX "transaction start\n"); + acpi_ec_write_cmd(ec, command); for (; wdata_len > 0; --wdata_len) { result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); if (result) { -- cgit v1.2.2 From b77d81b2678950077088956da4638c26853389fc Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Fri, 21 Mar 2008 17:07:15 +0300 Subject: ACPI: EC: Replace broken controller workarounds with poll mode. Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 61 +++++++++++-------------------------------------------- 1 file changed, 12 insertions(+), 49 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 1a7949c757b3..7f07b6806ac0 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -79,11 +79,7 @@ enum { EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */ EC_FLAGS_QUERY_PENDING, /* Query is pending */ EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */ - EC_FLAGS_NO_ADDRESS_GPE, /* Expect GPE only for non-address event */ - EC_FLAGS_ADDRESS, /* Address is being written */ - EC_FLAGS_NO_WDATA_GPE, /* Don't expect WDATA GPE event */ - EC_FLAGS_WDATA, /* Data is being written */ - EC_FLAGS_NO_OBF1_GPE, /* Don't expect GPE before read */ + EC_FLAGS_NO_GPE, /* Don't use GPE mode */ EC_FLAGS_RESCHEDULE_POLL /* Re-schedule poll */ }; @@ -189,6 +185,7 @@ static void ec_schedule_ec_poll(struct acpi_ec *ec) static void ec_switch_to_poll_mode(struct acpi_ec *ec) { + set_bit(EC_FLAGS_NO_GPE, &ec->flags); clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); set_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); @@ -196,65 +193,34 @@ static void ec_switch_to_poll_mode(struct acpi_ec *ec) static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) { - int ret = 0; - - if (unlikely(event == ACPI_EC_EVENT_OBF_1 && - test_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags))) - force_poll = 1; - if (unlikely(test_bit(EC_FLAGS_ADDRESS, &ec->flags) && - test_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags))) - force_poll = 1; - if (unlikely(test_bit(EC_FLAGS_WDATA, &ec->flags) && - test_bit(EC_FLAGS_NO_WDATA_GPE, &ec->flags))) - force_poll = 1; if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) && likely(!force_poll)) { if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event), msecs_to_jiffies(ACPI_EC_DELAY))) - goto end; + return 0; clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); if (acpi_ec_check_status(ec, event)) { - if (event == ACPI_EC_EVENT_OBF_1) { - /* miss OBF_1 GPE, don't expect it */ - pr_info(PREFIX "missing OBF confirmation, " - "don't expect it any longer.\n"); - set_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags); - } else if (test_bit(EC_FLAGS_ADDRESS, &ec->flags)) { - /* miss address GPE, don't expect it anymore */ - pr_info(PREFIX "missing address confirmation, " - "don't expect it any longer.\n"); - set_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags); - } else if (test_bit(EC_FLAGS_WDATA, &ec->flags)) { - /* miss write data GPE, don't expect it */ - pr_info(PREFIX "missing write data confirmation, " - "don't expect it any longer.\n"); - set_bit(EC_FLAGS_NO_WDATA_GPE, &ec->flags); - } else { - /* missing GPEs, switch back to poll mode */ - if (printk_ratelimit()) - pr_info(PREFIX "missing confirmations, " + /* missing GPEs, switch back to poll mode */ + if (printk_ratelimit()) + pr_info(PREFIX "missing confirmations, " "switch off interrupt mode.\n"); - ec_switch_to_poll_mode(ec); - ec_schedule_ec_poll(ec); - } - goto end; + ec_switch_to_poll_mode(ec); + ec_schedule_ec_poll(ec); + return 0; } } else { unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); while (time_before(jiffies, delay)) { if (acpi_ec_check_status(ec, event)) - goto end; + return 0; udelay(ACPI_EC_UDELAY); } } pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n", acpi_ec_read_status(ec), (event == ACPI_EC_EVENT_OBF_1) ? "\"b0=1\"" : "\"b1=0\""); - ret = -ETIME; - end: - clear_bit(EC_FLAGS_ADDRESS, &ec->flags); - return ret; + return -ETIME; } static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, @@ -273,15 +239,11 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, "write_cmd timeout, command = %d\n", command); goto end; } - /* mark the address byte written to EC */ - if (rdata_len + wdata_len > 1) - set_bit(EC_FLAGS_ADDRESS, &ec->flags); set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); acpi_ec_write_data(ec, *(wdata++)); } if (!rdata_len) { - set_bit(EC_FLAGS_WDATA, &ec->flags); result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); if (result) { pr_err(PREFIX @@ -558,6 +520,7 @@ static u32 acpi_ec_gpe_handler(void *data) status = acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec); } else if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && + !test_bit(EC_FLAGS_NO_GPE, &ec->flags) && in_interrupt()) { /* this is non-query, must be confirmation */ if (printk_ratelimit()) -- cgit v1.2.2 From 223883b7aafa02410ed2e571d6032c876d0b23b8 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Fri, 21 Mar 2008 17:07:21 +0300 Subject: ACPI: EC: Switch off GPE mode during suspend/resume Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 60 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 7f07b6806ac0..da67d228c9ea 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -83,28 +83,6 @@ enum { EC_FLAGS_RESCHEDULE_POLL /* Re-schedule poll */ }; -static int acpi_ec_remove(struct acpi_device *device, int type); -static int acpi_ec_start(struct acpi_device *device); -static int acpi_ec_stop(struct acpi_device *device, int type); -static int acpi_ec_add(struct acpi_device *device); - -static const struct acpi_device_id ec_device_ids[] = { - {"PNP0C09", 0}, - {"", 0}, -}; - -static struct acpi_driver acpi_ec_driver = { - .name = "ec", - .class = ACPI_EC_CLASS, - .ids = ec_device_ids, - .ops = { - .add = acpi_ec_add, - .remove = acpi_ec_remove, - .start = acpi_ec_start, - .stop = acpi_ec_stop, - }, -}; - /* If we find an EC via the ECDT, we need to keep a ptr to its context */ /* External interfaces use first EC only, so remember */ typedef int (*acpi_ec_query_func) (void *data); @@ -924,6 +902,11 @@ int __init acpi_boot_ec_enable(void) return -EFAULT; } +static const struct acpi_device_id ec_device_ids[] = { + {"PNP0C09", 0}, + {"", 0}, +}; + int __init acpi_ec_ecdt_probe(void) { int ret; @@ -973,6 +956,39 @@ int __init acpi_ec_ecdt_probe(void) return -ENODEV; } +static int acpi_ec_suspend(struct acpi_device *device, pm_message_t state) +{ + struct acpi_ec *ec = acpi_driver_data(device); + /* Stop using GPE */ + set_bit(EC_FLAGS_NO_GPE, &ec->flags); + clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); + acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); + return 0; +} + +static int acpi_ec_resume(struct acpi_device *device) +{ + struct acpi_ec *ec = acpi_driver_data(device); + /* Enable use of GPE back */ + clear_bit(EC_FLAGS_NO_GPE, &ec->flags); + acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); + return 0; +} + +static struct acpi_driver acpi_ec_driver = { + .name = "ec", + .class = ACPI_EC_CLASS, + .ids = ec_device_ids, + .ops = { + .add = acpi_ec_add, + .remove = acpi_ec_remove, + .start = acpi_ec_start, + .stop = acpi_ec_stop, + .suspend = acpi_ec_suspend, + .resume = acpi_ec_resume, + }, +}; + static int __init acpi_ec_init(void) { int result = 0; -- cgit v1.2.2 From fa95ba04e6ba11d71e1b87becd054b38faf546c8 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Fri, 21 Mar 2008 19:36:02 +0300 Subject: ACPI: EC: Detect irq storm Problem seems to be that hw fails to clear GPE after we service it and write 1 into corresponding bit. Thus, as soon as we get interrupts enabled again, we receive a new one. Google gives too many results for "acer interrupt storm" for this being one-broken-machine case. Reference: http://bugzilla.kernel.org/show_bug.cgi?id=9998 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index da67d228c9ea..f0e82166bb5c 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -106,6 +106,7 @@ static struct acpi_ec { wait_queue_head_t wait; struct list_head list; struct delayed_work work; + atomic_t irq_count; u8 handlers_installed; } *boot_ec, *first_ec; @@ -171,6 +172,7 @@ static void ec_switch_to_poll_mode(struct acpi_ec *ec) static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) { + atomic_set(&ec->irq_count, 0); if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) && likely(!force_poll)) { if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event), @@ -489,6 +491,12 @@ static u32 acpi_ec_gpe_handler(void *data) u8 state = acpi_ec_read_status(ec); pr_debug(PREFIX "~~~> interrupt\n"); + atomic_inc(&ec->irq_count); + if (atomic_read(&ec->irq_count) > 5) { + pr_err(PREFIX "GPE storm detected, disabling EC GPE\n"); + ec_switch_to_poll_mode(ec); + goto end; + } clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) wake_up(&ec->wait); @@ -507,6 +515,7 @@ static u32 acpi_ec_gpe_handler(void *data) set_bit(EC_FLAGS_GPE_MODE, &ec->flags); clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); } +end: ec_schedule_ec_poll(ec); return ACPI_SUCCESS(status) ? ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; @@ -515,6 +524,7 @@ static u32 acpi_ec_gpe_handler(void *data) static void do_ec_poll(struct work_struct *work) { struct acpi_ec *ec = container_of(work, struct acpi_ec, work.work); + atomic_set(&ec->irq_count, 0); (void)acpi_ec_gpe_handler(ec); } @@ -679,6 +689,7 @@ static struct acpi_ec *make_acpi_ec(void) init_waitqueue_head(&ec->wait); INIT_LIST_HEAD(&ec->list); INIT_DELAYED_WORK_DEFERRABLE(&ec->work, do_ec_poll); + atomic_set(&ec->irq_count, 0); return ec; } -- cgit v1.2.2 From 6d9e11206371be370b153264934378a29b6afe9b Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Mon, 24 Mar 2008 23:22:29 +0300 Subject: ACPI: EC: Use default setup handler Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index f0e82166bb5c..167af373bab3 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -532,20 +532,6 @@ static void do_ec_poll(struct work_struct *work) Address Space Management -------------------------------------------------------------------------- */ -static acpi_status -acpi_ec_space_setup(acpi_handle region_handle, - u32 function, void *handler_context, void **return_context) -{ - /* - * The EC object is in the handler context and is needed - * when calling the acpi_ec_space_handler. - */ - *return_context = (function != ACPI_REGION_DEACTIVATE) ? - handler_context : NULL; - - return AE_OK; -} - static acpi_status acpi_ec_space_handler(u32 function, acpi_physical_address address, u32 bits, acpi_integer *value, @@ -858,7 +844,7 @@ static int ec_install_handlers(struct acpi_ec *ec) status = acpi_install_address_space_handler(ec->handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, - &acpi_ec_space_setup, ec); + NULL, ec); if (ACPI_FAILURE(status)) { acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler); return -ENODEV; -- cgit v1.2.2 From ce52ddf58cbc2c40f5f08d37d2217945e4d5adf3 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Mon, 24 Mar 2008 23:22:36 +0300 Subject: ACPI: EC: Don't delete boot EC Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 43 +++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 167af373bab3..3d9362140831 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -708,9 +708,6 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe); if (ACPI_FAILURE(status)) return status; - /* Find and register all query methods */ - acpi_walk_namespace(ACPI_TYPE_METHOD, handle, 1, - acpi_ec_register_query_methods, ec, NULL); /* Use the global lock for all EC transactions? */ acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock); ec->handle = handle; @@ -745,31 +742,28 @@ static int acpi_ec_add(struct acpi_device *device) strcpy(acpi_device_class(device), ACPI_EC_CLASS); /* Check for boot EC */ - if (boot_ec) { - if (boot_ec->handle == device->handle) { - /* Pre-loaded EC from DSDT, just move pointer */ - ec = boot_ec; - boot_ec = NULL; - goto end; - } else if (boot_ec->handle == ACPI_ROOT_OBJECT) { - /* ECDT-based EC, time to shut it down */ - ec_remove_handlers(boot_ec); - kfree(boot_ec); - first_ec = boot_ec = NULL; + if (boot_ec && + (boot_ec->handle == device->handle || + boot_ec->handle == ACPI_ROOT_OBJECT)) { + ec = boot_ec; + boot_ec = NULL; + } else { + ec = make_acpi_ec(); + if (!ec) + return -ENOMEM; + if (ec_parse_device(device->handle, 0, ec, NULL) != + AE_CTRL_TERMINATE) { + kfree(ec); + return -EINVAL; } } - ec = make_acpi_ec(); - if (!ec) - return -ENOMEM; - - if (ec_parse_device(device->handle, 0, ec, NULL) != - AE_CTRL_TERMINATE) { - kfree(ec); - return -EINVAL; - } ec->handle = device->handle; - end: + + /* Find and register all query methods */ + acpi_walk_namespace(ACPI_TYPE_METHOD, ec->handle, 1, + acpi_ec_register_query_methods, ec, NULL); + if (!first_ec) first_ec = ec; acpi_driver_data(device) = ec; @@ -924,6 +918,7 @@ int __init acpi_ec_ecdt_probe(void) boot_ec->data_addr = ecdt_ptr->data.address; boot_ec->gpe = ecdt_ptr->gpe; boot_ec->handle = ACPI_ROOT_OBJECT; + acpi_get_handle(ACPI_ROOT_OBJECT, ecdt_ptr->id, &boot_ec->handle); } else { /* This workaround is needed only on some broken machines, * which require early EC, but fail to provide ECDT */ -- cgit v1.2.2 From 729b2bdbfa19dd9be98dbd49caf2773b3271cc24 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 19 Mar 2008 13:26:54 +0800 Subject: ACPI : Disable the device's ability to wake the sleeping system in the boot phase In some machines some GPE is shared by several ACPI devices, for example: sleep button, keyboard, mouse. At the same time one of them is non-wake(runtime) device and the other are wake devices. In such case OSPM should call the _PSW object to disable the device's ability to wake the sleeping system in the boot phase. Otherwise there will be ACPI interrupt flood triggered by the GPE input. The _PSW object is depreciated in ACPI 3.0 and is replaced by _DSW. So it is necessary to call _DSW object first. Only when it is not present will the _PSW object used. http://bugzilla.kernel.org/show_bug.cgi?id=10224 Signed-off-by: Zhao Yakui Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/scan.c | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index e6ce262b5d44..bd32351854ac 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -692,6 +692,9 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) acpi_status status = 0; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *package = NULL; + union acpi_object in_arg[3]; + struct acpi_object_list arg_list = { 3, in_arg }; + acpi_status psw_status = AE_OK; struct acpi_device_id button_device_ids[] = { {"PNP0C0D", 0}, @@ -700,7 +703,6 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) {"", 0}, }; - /* _PRW */ status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer); if (ACPI_FAILURE(status)) { @@ -718,6 +720,45 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) kfree(buffer.pointer); device->wakeup.flags.valid = 1; + /* Call _PSW/_DSW object to disable its ability to wake the sleeping + * system for the ACPI device with the _PRW object. + * The _PSW object is depreciated in ACPI 3.0 and is replaced by _DSW. + * So it is necessary to call _DSW object first. Only when it is not + * present will the _PSW object used. + */ + /* + * Three agruments are needed for the _DSW object. + * Argument 0: enable/disable the wake capabilities + * When _DSW object is called to disable the wake capabilities, maybe + * the first argument is filled. The value of the other two agruments + * is meaningless. + */ + in_arg[0].type = ACPI_TYPE_INTEGER; + in_arg[0].integer.value = 0; + in_arg[1].type = ACPI_TYPE_INTEGER; + in_arg[1].integer.value = 0; + in_arg[2].type = ACPI_TYPE_INTEGER; + in_arg[2].integer.value = 0; + psw_status = acpi_evaluate_object(device->handle, "_DSW", + &arg_list, NULL); + if (ACPI_FAILURE(psw_status) && (psw_status != AE_NOT_FOUND)) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "error in evaluate _DSW\n")); + /* + * When the _DSW object is not present, OSPM will call _PSW object. + */ + if (psw_status == AE_NOT_FOUND) { + /* + * Only one agruments is required for the _PSW object. + * agrument 0: enable/disable the wake capabilities + */ + arg_list.count = 1; + in_arg[0].integer.value = 0; + psw_status = acpi_evaluate_object(device->handle, "_PSW", + &arg_list, NULL); + if (ACPI_FAILURE(psw_status) && (psw_status != AE_NOT_FOUND)) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "error in " + "evaluate _PSW\n")); + } /* Power button, Lid switch always enable wakeup */ if (!acpi_match_device_ids(device, button_device_ids)) device->wakeup.flags.run_wake = 1; -- cgit v1.2.2 From 6afe1a1fe8ff83f6ac2726b04665e76ba7b14f3e Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Thu, 13 Mar 2008 23:52:49 +0100 Subject: PM: Remove legacy PM AFAICT pm_send_all is a nop when noone uses pm_register... Hmm.. can we just force CONFIG_PM_LEGACY=n, and see what happens? Or maybe this is better idea? It may break build somewhere, but it should be easy to fix... (it builds here, i386 and x86-64). Signed-off-by: Pavel Machek Acked-by: Ralf Baechle Signed-off-by: Rafael J. Wysocki Signed-off-by: Len Brown --- arch/frv/kernel/pm.c | 8 -- arch/mips/au1000/common/power.c | 17 +--- arch/x86/kernel/apm_32.c | 15 --- kernel/power/Kconfig | 10 -- kernel/power/Makefile | 1 - kernel/power/pm.c | 205 ---------------------------------------- 6 files changed, 2 insertions(+), 254 deletions(-) delete mode 100644 kernel/power/pm.c diff --git a/arch/frv/kernel/pm.c b/arch/frv/kernel/pm.c index c57ce3f1f2e2..73f3aeefd203 100644 --- a/arch/frv/kernel/pm.c +++ b/arch/frv/kernel/pm.c @@ -163,14 +163,11 @@ static int sysctl_pm_do_suspend(ctl_table *ctl, int write, struct file *filp, if ((mode != 1) && (mode != 5)) return -EINVAL; - retval = pm_send_all(PM_SUSPEND, (void *)3); - if (retval == 0) { if (mode == 5) retval = pm_do_bus_sleep(); else retval = pm_do_suspend(); - pm_send_all(PM_RESUME, (void *)0); } return retval; @@ -183,9 +180,6 @@ static int try_set_cmode(int new_cmode) if (!(clock_cmodes_permitted & (1< 0x100) - set_system_power_state(APM_STATE_REJECT); - err = -EBUSY; - ignore_sys_suspend = 0; - printk(KERN_WARNING "apm: suspend was vetoed.\n"); - goto out; - } - printk(KERN_CRIT "apm: suspend was vetoed, but suspending anyway.\n"); - } - device_suspend(PMSG_SUSPEND); local_irq_disable(); device_power_down(PMSG_SUSPEND); @@ -1224,7 +1211,6 @@ static int suspend(int vetoable) device_power_up(); local_irq_enable(); device_resume(); - pm_send_all(PM_RESUME, (void *)0); queue_event(APM_NORMAL_RESUME, NULL); out: spin_lock(&user_list_lock); @@ -1337,7 +1323,6 @@ static void check_events(void) if ((event != APM_NORMAL_RESUME) || (ignore_normal_resume == 0)) { device_resume(); - pm_send_all(PM_RESUME, (void *)0); queue_event(event, NULL); } ignore_normal_resume = 0; diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 6233f3b4ae66..b45da40e8d25 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig @@ -19,16 +19,6 @@ config PM will issue the hlt instruction if nothing is to be done, thereby sending the processor to sleep and saving power. -config PM_LEGACY - bool "Legacy Power Management API (DEPRECATED)" - depends on PM - default n - ---help--- - Support for pm_register() and friends. This old API is obsoleted - by the driver model. - - If unsure, say N. - config PM_DEBUG bool "Power Management Debug Support" depends on PM diff --git a/kernel/power/Makefile b/kernel/power/Makefile index f7dfff28ecdb..597823b5b700 100644 --- a/kernel/power/Makefile +++ b/kernel/power/Makefile @@ -4,7 +4,6 @@ EXTRA_CFLAGS += -DDEBUG endif obj-y := main.o -obj-$(CONFIG_PM_LEGACY) += pm.o obj-$(CONFIG_PM_SLEEP) += process.o console.o obj-$(CONFIG_HIBERNATION) += swsusp.o disk.o snapshot.o swap.o user.o diff --git a/kernel/power/pm.c b/kernel/power/pm.c deleted file mode 100644 index 60c73fa670d5..000000000000 --- a/kernel/power/pm.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * pm.c - Power management interface - * - * Copyright (C) 2000 Andrew Henroid - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Locking notes: - * pm_devs_lock can be a semaphore providing pm ops are not called - * from an interrupt handler (already a bad idea so no change here). Each - * change must be protected so that an unlink of an entry doesn't clash - * with a pm send - which is permitted to sleep in the current architecture - * - * Module unloads clashing with pm events now work out safely, the module - * unload path will block until the event has been sent. It may well block - * until a resume but that will be fine. - */ - -static DEFINE_MUTEX(pm_devs_lock); -static LIST_HEAD(pm_devs); - -/** - * pm_register - register a device with power management - * @type: device type - * @id: device ID - * @callback: callback function - * - * Add a device to the list of devices that wish to be notified about - * power management events. A &pm_dev structure is returned on success, - * on failure the return is %NULL. - * - * The callback function will be called in process context and - * it may sleep. - */ - -struct pm_dev *pm_register(pm_dev_t type, - unsigned long id, - pm_callback callback) -{ - struct pm_dev *dev = kzalloc(sizeof(struct pm_dev), GFP_KERNEL); - if (dev) { - dev->type = type; - dev->id = id; - dev->callback = callback; - - mutex_lock(&pm_devs_lock); - list_add(&dev->entry, &pm_devs); - mutex_unlock(&pm_devs_lock); - } - return dev; -} - -/** - * pm_send - send request to a single device - * @dev: device to send to - * @rqst: power management request - * @data: data for the callback - * - * Issue a power management request to a given device. The - * %PM_SUSPEND and %PM_RESUME events are handled specially. The - * data field must hold the intended next state. No call is made - * if the state matches. - * - * BUGS: what stops two power management requests occurring in parallel - * and conflicting. - * - * WARNING: Calling pm_send directly is not generally recommended, in - * particular there is no locking against the pm_dev going away. The - * caller must maintain all needed locking or have 'inside knowledge' - * on the safety. Also remember that this function is not locked against - * pm_unregister. This means that you must handle SMP races on callback - * execution and unload yourself. - */ - -static int pm_send(struct pm_dev *dev, pm_request_t rqst, void *data) -{ - int status = 0; - unsigned long prev_state, next_state; - - if (in_interrupt()) - BUG(); - - switch (rqst) { - case PM_SUSPEND: - case PM_RESUME: - prev_state = dev->state; - next_state = (unsigned long) data; - if (prev_state != next_state) { - if (dev->callback) - status = (*dev->callback)(dev, rqst, data); - if (!status) { - dev->state = next_state; - dev->prev_state = prev_state; - } - } - else { - dev->prev_state = prev_state; - } - break; - default: - if (dev->callback) - status = (*dev->callback)(dev, rqst, data); - break; - } - return status; -} - -/* - * Undo incomplete request - */ -static void pm_undo_all(struct pm_dev *last) -{ - struct list_head *entry = last->entry.prev; - while (entry != &pm_devs) { - struct pm_dev *dev = list_entry(entry, struct pm_dev, entry); - if (dev->state != dev->prev_state) { - /* previous state was zero (running) resume or - * previous state was non-zero (suspended) suspend - */ - pm_request_t undo = (dev->prev_state - ? PM_SUSPEND:PM_RESUME); - pm_send(dev, undo, (void*) dev->prev_state); - } - entry = entry->prev; - } -} - -/** - * pm_send_all - send request to all managed devices - * @rqst: power management request - * @data: data for the callback - * - * Issue a power management request to a all devices. The - * %PM_SUSPEND events are handled specially. Any device is - * permitted to fail a suspend by returning a non zero (error) - * value from its callback function. If any device vetoes a - * suspend request then all other devices that have suspended - * during the processing of this request are restored to their - * previous state. - * - * WARNING: This function takes the pm_devs_lock. The lock is not dropped until - * the callbacks have completed. This prevents races against pm locking - * functions, races against module unload pm_unregister code. It does - * mean however that you must not issue pm_ functions within the callback - * or you will deadlock and users will hate you. - * - * Zero is returned on success. If a suspend fails then the status - * from the device that vetoes the suspend is returned. - * - * BUGS: what stops two power management requests occurring in parallel - * and conflicting. - */ - -int pm_send_all(pm_request_t rqst, void *data) -{ - struct list_head *entry; - - mutex_lock(&pm_devs_lock); - entry = pm_devs.next; - while (entry != &pm_devs) { - struct pm_dev *dev = list_entry(entry, struct pm_dev, entry); - if (dev->callback) { - int status = pm_send(dev, rqst, data); - if (status) { - /* return devices to previous state on - * failed suspend request - */ - if (rqst == PM_SUSPEND) - pm_undo_all(dev); - mutex_unlock(&pm_devs_lock); - return status; - } - } - entry = entry->next; - } - mutex_unlock(&pm_devs_lock); - return 0; -} - -EXPORT_SYMBOL(pm_register); -EXPORT_SYMBOL(pm_send_all); - -- cgit v1.2.2 From 5373fd72577ffc4689ade0a2a1a885293c32c711 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 27 Mar 2008 02:00:06 -0400 Subject: PM: arch/x86/kernel/apm_32.c: fix build warning arch/x86/kernel/apm_32.c:1215: warning: label 'out' defined but not used Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- arch/x86/kernel/apm_32.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index d7e92bfb8f66..bc8b57d119a1 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c @@ -1212,7 +1212,6 @@ static int suspend(int vetoable) local_irq_enable(); device_resume(); queue_event(APM_NORMAL_RESUME, NULL); - out: spin_lock(&user_list_lock); for (as = user_list; as != NULL; as = as->next) { as->suspend_wait = 0; -- cgit v1.2.2 From 99bda83e8b3140b7e81572a5aabc7dedb455b272 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 13 Mar 2008 23:54:09 +0100 Subject: MIPS Alchemy: Crapectomy after removal of pm_send_all calls. Signed-off-by: Ralf Baechle Acked-by: Pavel Machek Signed-off-by: Rafael J. Wysocki Signed-off-by: Len Brown --- arch/mips/au1000/common/power.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/arch/mips/au1000/common/power.c b/arch/mips/au1000/common/power.c index a9f7f6371e4b..725a52f364b0 100644 --- a/arch/mips/au1000/common/power.c +++ b/arch/mips/au1000/common/power.c @@ -283,18 +283,6 @@ static int pm_do_sleep(ctl_table * ctl, int write, struct file *file, return 0; } -static int pm_do_suspend(ctl_table * ctl, int write, struct file *file, - void __user *buffer, size_t * len, loff_t *ppos) -{ - if (!write) { - *len = 0; - } else { - suspend_mode = 1; - } - return 0; -} - - static int pm_do_freq(ctl_table * ctl, int write, struct file *file, void __user *buffer, size_t * len, loff_t *ppos) { @@ -407,14 +395,6 @@ static int pm_do_freq(ctl_table * ctl, int write, struct file *file, static struct ctl_table pm_table[] = { - { - .ctl_name = CTL_UNNUMBERED, - .procname = "suspend", - .data = NULL, - .maxlen = 0, - .mode = 0600, - .proc_handler = &pm_do_suspend - }, { .ctl_name = CTL_UNNUMBERED, .procname = "sleep", -- cgit v1.2.2 From 773069d48030e670cf2032a13ddf16a2e0034df3 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:36 +0400 Subject: ACPICA: Several fixes for internal method result stack fixes STACK_OVERFLOW exception on nested method calls. internal bugzilla 262 and 275. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/dispatcher/dsopcode.c | 9 +- drivers/acpi/dispatcher/dsutils.c | 52 +++- drivers/acpi/dispatcher/dswexec.c | 43 +--- drivers/acpi/dispatcher/dswstate.c | 513 ++++++++----------------------------- drivers/acpi/parser/psloop.c | 11 - drivers/acpi/parser/psparse.c | 15 +- include/acpi/acconfig.h | 13 +- include/acpi/acdispat.h | 16 +- include/acpi/aclocal.h | 5 +- include/acpi/acstruct.h | 3 + 10 files changed, 179 insertions(+), 501 deletions(-) diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c index f501e083aac7..0c4630dc09f3 100644 --- a/drivers/acpi/dispatcher/dsopcode.c +++ b/drivers/acpi/dispatcher/dsopcode.c @@ -808,6 +808,12 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, /* The first operand (for all of these data objects) is the length */ + /* + * Set proper index into operand stack for acpi_ds_obj_stack_push + * invoked inside acpi_ds_create_operand. + */ + walk_state->operand_index = walk_state->num_operands; + status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); @@ -1070,8 +1076,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, * is set to anything other than zero! */ walk_state->return_desc = walk_state->operands[0]; - } else if ((walk_state->results) && - (walk_state->results->results.num_results > 0)) { + } else if (walk_state->result_count) { /* Since we have a real Return(), delete any implicit return */ diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c index 71503c036f7c..d2a8cfdaec22 100644 --- a/drivers/acpi/dispatcher/dsutils.c +++ b/drivers/acpi/dispatcher/dsutils.c @@ -630,9 +630,7 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, * Use value that was already previously returned * by the evaluation of this argument */ - status = - acpi_ds_result_pop_from_bottom(&obj_desc, - walk_state); + status = acpi_ds_result_pop(&obj_desc, walk_state); if (ACPI_FAILURE(status)) { /* * Only error is underflow, and this indicates @@ -698,27 +696,54 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state, { acpi_status status = AE_OK; union acpi_parse_object *arg; - u32 arg_count = 0; + union acpi_parse_object *arguments[ACPI_OBJ_NUM_OPERANDS]; + u8 arg_count = 0; + u8 count = 0; + u8 index = walk_state->num_operands; + u8 i; ACPI_FUNCTION_TRACE_PTR(ds_create_operands, first_arg); - /* For all arguments in the list... */ + /* Get all arguments in the list */ arg = first_arg; while (arg) { - status = acpi_ds_create_operand(walk_state, arg, arg_count); - if (ACPI_FAILURE(status)) { - goto cleanup; + if (index >= ACPI_OBJ_NUM_OPERANDS) { + return_ACPI_STATUS(AE_BAD_DATA); } - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "Arg #%d (%p) done, Arg1=%p\n", arg_count, - arg, first_arg)); + arguments[index] = arg; + walk_state->operands[index] = NULL; /* Move on to next argument, if any */ arg = arg->common.next; arg_count++; + index++; + } + + index--; + + /* It is the appropriate order to get objects from the Result stack */ + + for (i = 0; i < arg_count; i++) { + arg = arguments[index]; + + /* Force the filling of the operand stack in inverse order */ + + walk_state->operand_index = index; + + status = acpi_ds_create_operand(walk_state, arg, index); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + count++; + index--; + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "Arg #%d (%p) done, Arg1=%p\n", index, arg, + first_arg)); } return_ACPI_STATUS(status); @@ -729,9 +754,8 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state, * pop everything off of the operand stack and delete those * objects */ - (void)acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state); + acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state); - ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %d", - (arg_count + 1))); + ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %d", index)); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c index 69693fa07224..12b148587e3d 100644 --- a/drivers/acpi/dispatcher/dswexec.c +++ b/drivers/acpi/dispatcher/dswexec.c @@ -285,11 +285,6 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, switch (opcode_class) { case AML_CLASS_CONTROL: - status = acpi_ds_result_stack_push(walk_state); - if (ACPI_FAILURE(status)) { - goto error_exit; - } - status = acpi_ds_exec_begin_control_op(walk_state, op); break; @@ -305,20 +300,11 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, status = acpi_ds_load2_begin_op(walk_state, NULL); } - if (op->common.aml_opcode == AML_REGION_OP) { - status = acpi_ds_result_stack_push(walk_state); - } break; case AML_CLASS_EXECUTE: case AML_CLASS_CREATE: - /* - * Most operators with arguments (except create_xxx_field operators) - * Start a new result/operand state - */ - if (walk_state->op_info->object_type != ACPI_TYPE_BUFFER_FIELD) { - status = acpi_ds_result_stack_push(walk_state); - } + break; default: @@ -374,6 +360,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) /* Init the walk state */ walk_state->num_operands = 0; + walk_state->operand_index = 0; walk_state->return_desc = NULL; walk_state->result_obj = NULL; @@ -400,13 +387,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) goto cleanup; } - /* Done with this result state (Now that operand stack is built) */ - - status = acpi_ds_result_stack_pop(walk_state); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - /* * All opcodes require operand resolution, with the only exceptions * being the object_type and size_of operators. @@ -487,16 +467,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) status = acpi_ds_exec_end_control_op(walk_state, op); - /* Make sure to properly pop the result stack */ - - if (ACPI_SUCCESS(status)) { - status = acpi_ds_result_stack_pop(walk_state); - } else if (status == AE_CTRL_PENDING) { - status = acpi_ds_result_stack_pop(walk_state); - if (ACPI_SUCCESS(status)) { - status = AE_CTRL_PENDING; - } - } break; case AML_TYPE_METHOD_CALL: @@ -632,13 +602,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) break; } - /* Done with result state (Now that operand stack is built) */ - - status = acpi_ds_result_stack_pop(walk_state); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - /* * If a result object was returned from above, push it on the * current result stack @@ -671,8 +634,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) if (ACPI_FAILURE(status)) { break; } - - status = acpi_ds_result_stack_pop(walk_state); } break; diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c index 5afcdd9c7449..698d2e1c219e 100644 --- a/drivers/acpi/dispatcher/dswstate.c +++ b/drivers/acpi/dispatcher/dswstate.c @@ -49,85 +49,9 @@ #define _COMPONENT ACPI_DISPATCHER ACPI_MODULE_NAME("dswstate") -/* Local prototypes */ -#ifdef ACPI_OBSOLETE_FUNCTIONS -acpi_status -acpi_ds_result_insert(void *object, - u32 index, struct acpi_walk_state *walk_state); - -acpi_status acpi_ds_obj_stack_delete_all(struct acpi_walk_state *walk_state); - -acpi_status -acpi_ds_obj_stack_pop_object(union acpi_operand_object **object, - struct acpi_walk_state *walk_state); - -void *acpi_ds_obj_stack_get_value(u32 index, - struct acpi_walk_state *walk_state); -#endif - -#ifdef ACPI_FUTURE_USAGE -/******************************************************************************* - * - * FUNCTION: acpi_ds_result_remove - * - * PARAMETERS: Object - Where to return the popped object - * Index - Where to extract the object - * walk_state - Current Walk state - * - * RETURN: Status - * - * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In - * other words, this is a FIFO. - * - ******************************************************************************/ - -acpi_status -acpi_ds_result_remove(union acpi_operand_object **object, - u32 index, struct acpi_walk_state *walk_state) -{ - union acpi_generic_state *state; - - ACPI_FUNCTION_NAME(ds_result_remove); - - state = walk_state->results; - if (!state) { - ACPI_ERROR((AE_INFO, "No result object pushed! State=%p", - walk_state)); - return (AE_NOT_EXIST); - } - - if (index >= ACPI_OBJ_MAX_OPERAND) { - ACPI_ERROR((AE_INFO, - "Index out of range: %X State=%p Num=%X", - index, walk_state, state->results.num_results)); - } - - /* Check for a valid result object */ - - if (!state->results.obj_desc[index]) { - ACPI_ERROR((AE_INFO, - "Null operand! State=%p #Ops=%X, Index=%X", - walk_state, state->results.num_results, index)); - return (AE_AML_NO_RETURN_VALUE); - } - - /* Remove the object */ - - state->results.num_results--; - - *object = state->results.obj_desc[index]; - state->results.obj_desc[index] = NULL; - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Obj=%p [%s] Index=%X State=%p Num=%X\n", - *object, - (*object) ? acpi_ut_get_object_type_name(*object) : - "NULL", index, walk_state, - state->results.num_results)); - - return (AE_OK); -} -#endif /* ACPI_FUTURE_USAGE */ + /* Local prototypes */ +static acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *ws); +static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *ws); /******************************************************************************* * @@ -138,122 +62,67 @@ acpi_ds_result_remove(union acpi_operand_object **object, * * RETURN: Status * - * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In - * other words, this is a FIFO. + * DESCRIPTION: Pop an object off the top of this walk's result stack * ******************************************************************************/ acpi_status -acpi_ds_result_pop(union acpi_operand_object ** object, - struct acpi_walk_state * walk_state) +acpi_ds_result_pop(union acpi_operand_object **object, + struct acpi_walk_state *walk_state) { acpi_native_uint index; union acpi_generic_state *state; + acpi_status status; ACPI_FUNCTION_NAME(ds_result_pop); state = walk_state->results; - if (!state) { - return (AE_OK); - } - - if (!state->results.num_results) { - ACPI_ERROR((AE_INFO, "Result stack is empty! State=%p", - walk_state)); - return (AE_AML_NO_RETURN_VALUE); - } - /* Remove top element */ + /* Incorrect state of result stack */ - state->results.num_results--; - - for (index = ACPI_OBJ_NUM_OPERANDS; index; index--) { - - /* Check for a valid result object */ - - if (state->results.obj_desc[index - 1]) { - *object = state->results.obj_desc[index - 1]; - state->results.obj_desc[index - 1] = NULL; - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Obj=%p [%s] Index=%X State=%p Num=%X\n", - *object, - (*object) ? - acpi_ut_get_object_type_name(*object) - : "NULL", (u32) index - 1, walk_state, - state->results.num_results)); - - return (AE_OK); - } + if (state && !walk_state->result_count) { + ACPI_ERROR((AE_INFO, "No results on result stack")); + return (AE_AML_INTERNAL); } - ACPI_ERROR((AE_INFO, "No result objects! State=%p", walk_state)); - return (AE_AML_NO_RETURN_VALUE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_result_pop_from_bottom - * - * PARAMETERS: Object - Where to return the popped object - * walk_state - Current Walk state - * - * RETURN: Status - * - * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In - * other words, this is a FIFO. - * - ******************************************************************************/ - -acpi_status -acpi_ds_result_pop_from_bottom(union acpi_operand_object ** object, - struct acpi_walk_state * walk_state) -{ - acpi_native_uint index; - union acpi_generic_state *state; + if (!state && walk_state->result_count) { + ACPI_ERROR((AE_INFO, "No result state for result stack")); + return (AE_AML_INTERNAL); + } - ACPI_FUNCTION_NAME(ds_result_pop_from_bottom); + /* Empty result stack */ - state = walk_state->results; if (!state) { - ACPI_ERROR((AE_INFO, - "No result object pushed! State=%p", walk_state)); - return (AE_NOT_EXIST); - } - - if (!state->results.num_results) { - ACPI_ERROR((AE_INFO, "No result objects! State=%p", + ACPI_ERROR((AE_INFO, "Result stack is empty! State=%p", walk_state)); return (AE_AML_NO_RETURN_VALUE); } - /* Remove Bottom element */ - - *object = state->results.obj_desc[0]; - - /* Push entire stack down one element */ - - for (index = 0; index < state->results.num_results; index++) { - state->results.obj_desc[index] = - state->results.obj_desc[index + 1]; - } + /* Return object of the top element and clean that top element result stack */ - state->results.num_results--; - - /* Check for a valid result object */ + walk_state->result_count--; + index = walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM; + *object = state->results.obj_desc[index]; if (!*object) { ACPI_ERROR((AE_INFO, - "Null operand! State=%p #Ops=%X Index=%X", - walk_state, state->results.num_results, - (u32) index)); + "No result objects on result stack, State=%p", + walk_state)); return (AE_AML_NO_RETURN_VALUE); } - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] Results=%p State=%p\n", - *object, - (*object) ? acpi_ut_get_object_type_name(*object) : - "NULL", state, walk_state)); + state->results.obj_desc[index] = NULL; + if (index == 0) { + status = acpi_ds_result_stack_pop(walk_state); + if (ACPI_FAILURE(status)) { + return (status); + } + } + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Obj=%p [%s] Index=%X State=%p Num=%X\n", *object, + acpi_ut_get_object_type_name(*object), + (u32) index, walk_state, walk_state->result_count)); return (AE_OK); } @@ -276,39 +145,56 @@ acpi_ds_result_push(union acpi_operand_object * object, struct acpi_walk_state * walk_state) { union acpi_generic_state *state; + acpi_status status; + acpi_native_uint index; ACPI_FUNCTION_NAME(ds_result_push); + if (walk_state->result_count > walk_state->result_size) { + ACPI_ERROR((AE_INFO, "Result stack is full")); + return (AE_AML_INTERNAL); + } else if (walk_state->result_count == walk_state->result_size) { + + /* Extend the result stack */ + + status = acpi_ds_result_stack_push(walk_state); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, + "Failed to extend the result stack")); + return (status); + } + } + + if (!(walk_state->result_count < walk_state->result_size)) { + ACPI_ERROR((AE_INFO, "No free elements in result stack")); + return (AE_AML_INTERNAL); + } + state = walk_state->results; if (!state) { ACPI_ERROR((AE_INFO, "No result stack frame during push")); return (AE_AML_INTERNAL); } - if (state->results.num_results == ACPI_OBJ_NUM_OPERANDS) { - ACPI_ERROR((AE_INFO, - "Result stack overflow: Obj=%p State=%p Num=%X", - object, walk_state, state->results.num_results)); - return (AE_STACK_OVERFLOW); - } - if (!object) { ACPI_ERROR((AE_INFO, "Null Object! Obj=%p State=%p Num=%X", - object, walk_state, state->results.num_results)); + object, walk_state, walk_state->result_count)); return (AE_BAD_PARAMETER); } - state->results.obj_desc[state->results.num_results] = object; - state->results.num_results++; + /* Assign the address of object to the top free element of result stack */ + + index = walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM; + state->results.obj_desc[index] = object; + walk_state->result_count++; ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p Num=%X Cur=%X\n", object, - object ? acpi_ut_get_object_type_name((union acpi_operand_object *) - object) : "NULL", - walk_state, state->results.num_results, + object), walk_state, + walk_state->result_count, walk_state->current_result)); return (AE_OK); @@ -322,16 +208,25 @@ acpi_ds_result_push(union acpi_operand_object * object, * * RETURN: Status * - * DESCRIPTION: Push an object onto the walk_state result stack. + * DESCRIPTION: Push an object onto the walk_state result stack * ******************************************************************************/ -acpi_status acpi_ds_result_stack_push(struct acpi_walk_state * walk_state) +static acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *walk_state) { union acpi_generic_state *state; ACPI_FUNCTION_NAME(ds_result_stack_push); + /* Check for stack overflow */ + + if ((walk_state->result_size + ACPI_RESULTS_FRAME_OBJ_NUM) > + ACPI_RESULTS_OBJ_NUM_MAX) { + ACPI_ERROR((AE_INFO, "Result stack overflow: State=%p Num=%X", + walk_state, walk_state->result_size)); + return (AE_STACK_OVERFLOW); + } + state = acpi_ut_create_generic_state(); if (!state) { return (AE_NO_MEMORY); @@ -340,6 +235,10 @@ acpi_status acpi_ds_result_stack_push(struct acpi_walk_state * walk_state) state->common.descriptor_type = ACPI_DESC_TYPE_STATE_RESULT; acpi_ut_push_generic_state(&walk_state->results, state); + /* Increase the length of the result stack by the length of frame */ + + walk_state->result_size += ACPI_RESULTS_FRAME_OBJ_NUM; + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Results=%p State=%p\n", state, walk_state)); @@ -354,11 +253,11 @@ acpi_status acpi_ds_result_stack_push(struct acpi_walk_state * walk_state) * * RETURN: Status * - * DESCRIPTION: Pop an object off of the walk_state result stack. + * DESCRIPTION: Pop an object off of the walk_state result stack * ******************************************************************************/ -acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state * walk_state) +static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *walk_state) { union acpi_generic_state *state; @@ -367,18 +266,27 @@ acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state * walk_state) /* Check for stack underflow */ if (walk_state->results == NULL) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Underflow - State=%p\n", + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Result stack underflow - State=%p\n", walk_state)); return (AE_AML_NO_OPERAND); } + if (walk_state->result_size < ACPI_RESULTS_FRAME_OBJ_NUM) { + ACPI_ERROR((AE_INFO, "Insufficient result stack size")); + return (AE_AML_INTERNAL); + } + state = acpi_ut_pop_generic_state(&walk_state->results); + acpi_ut_delete_generic_state(state); + + /* Decrease the length of result stack by the length of frame */ + + walk_state->result_size -= ACPI_RESULTS_FRAME_OBJ_NUM; ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Result=%p RemainingResults=%X State=%p\n", - state, state->results.num_results, walk_state)); - - acpi_ut_delete_generic_state(state); + state, walk_state->result_count, walk_state)); return (AE_OK); } @@ -412,9 +320,13 @@ acpi_ds_obj_stack_push(void *object, struct acpi_walk_state * walk_state) /* Put the object onto the stack */ - walk_state->operands[walk_state->num_operands] = object; + walk_state->operands[walk_state->operand_index] = object; walk_state->num_operands++; + /* For the usual order of filling the operand stack */ + + walk_state->operand_index++; + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n", object, acpi_ut_get_object_type_name((union @@ -484,43 +396,36 @@ acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state * walk_state) * ******************************************************************************/ -acpi_status +void acpi_ds_obj_stack_pop_and_delete(u32 pop_count, - struct acpi_walk_state * walk_state) + struct acpi_walk_state *walk_state) { u32 i; union acpi_operand_object *obj_desc; ACPI_FUNCTION_NAME(ds_obj_stack_pop_and_delete); - for (i = 0; i < pop_count; i++) { - - /* Check for stack underflow */ + if (pop_count == 0) { + return; + } + for (i = (pop_count - 1); i >= 0; i--) { if (walk_state->num_operands == 0) { - ACPI_ERROR((AE_INFO, - "Object stack underflow! Count=%X State=%p #Ops=%X", - pop_count, walk_state, - walk_state->num_operands)); - return (AE_STACK_UNDERFLOW); + return; } /* Pop the stack and delete an object if present in this stack entry */ walk_state->num_operands--; - obj_desc = walk_state->operands[walk_state->num_operands]; + obj_desc = walk_state->operands[i]; if (obj_desc) { - acpi_ut_remove_reference(walk_state-> - operands[walk_state-> - num_operands]); - walk_state->operands[walk_state->num_operands] = NULL; + acpi_ut_remove_reference(walk_state->operands[i]); + walk_state->operands[i] = NULL; } } ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n", pop_count, walk_state, walk_state->num_operands)); - - return (AE_OK); } /******************************************************************************* @@ -560,7 +465,7 @@ struct acpi_walk_state *acpi_ds_get_current_walk_state(struct acpi_thread_state * * RETURN: None * - * DESCRIPTION: Place the Thread state at the head of the state list. + * DESCRIPTION: Place the Thread state at the head of the state list * ******************************************************************************/ @@ -636,7 +541,6 @@ struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, union *thread) { struct acpi_walk_state *walk_state; - acpi_status status; ACPI_FUNCTION_TRACE(ds_create_walk_state); @@ -659,14 +563,6 @@ struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, union acpi_ds_method_data_init(walk_state); #endif - /* Create an initial result stack entry */ - - status = acpi_ds_result_stack_push(walk_state); - if (ACPI_FAILURE(status)) { - ACPI_FREE(walk_state); - return_PTR(NULL); - } - /* Put the new state at the head of the walk list */ if (thread) { @@ -860,190 +756,3 @@ void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state) ACPI_FREE(walk_state); return_VOID; } - -#ifdef ACPI_OBSOLETE_FUNCTIONS -/******************************************************************************* - * - * FUNCTION: acpi_ds_result_insert - * - * PARAMETERS: Object - Object to push - * Index - Where to insert the object - * walk_state - Current Walk state - * - * RETURN: Status - * - * DESCRIPTION: Insert an object onto this walk's result stack - * - ******************************************************************************/ - -acpi_status -acpi_ds_result_insert(void *object, - u32 index, struct acpi_walk_state *walk_state) -{ - union acpi_generic_state *state; - - ACPI_FUNCTION_NAME(ds_result_insert); - - state = walk_state->results; - if (!state) { - ACPI_ERROR((AE_INFO, "No result object pushed! State=%p", - walk_state)); - return (AE_NOT_EXIST); - } - - if (index >= ACPI_OBJ_NUM_OPERANDS) { - ACPI_ERROR((AE_INFO, - "Index out of range: %X Obj=%p State=%p Num=%X", - index, object, walk_state, - state->results.num_results)); - return (AE_BAD_PARAMETER); - } - - if (!object) { - ACPI_ERROR((AE_INFO, - "Null Object! Index=%X Obj=%p State=%p Num=%X", - index, object, walk_state, - state->results.num_results)); - return (AE_BAD_PARAMETER); - } - - state->results.obj_desc[index] = object; - state->results.num_results++; - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Obj=%p [%s] State=%p Num=%X Cur=%X\n", - object, - object ? - acpi_ut_get_object_type_name((union - acpi_operand_object *) - object) : "NULL", - walk_state, state->results.num_results, - walk_state->current_result)); - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_obj_stack_delete_all - * - * PARAMETERS: walk_state - Current Walk state - * - * RETURN: Status - * - * DESCRIPTION: Clear the object stack by deleting all objects that are on it. - * Should be used with great care, if at all! - * - ******************************************************************************/ - -acpi_status acpi_ds_obj_stack_delete_all(struct acpi_walk_state * walk_state) -{ - u32 i; - - ACPI_FUNCTION_TRACE_PTR(ds_obj_stack_delete_all, walk_state); - - /* The stack size is configurable, but fixed */ - - for (i = 0; i < ACPI_OBJ_NUM_OPERANDS; i++) { - if (walk_state->operands[i]) { - acpi_ut_remove_reference(walk_state->operands[i]); - walk_state->operands[i] = NULL; - } - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_obj_stack_pop_object - * - * PARAMETERS: Object - Where to return the popped object - * walk_state - Current Walk state - * - * RETURN: Status - * - * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT - * deleted by this routine. - * - ******************************************************************************/ - -acpi_status -acpi_ds_obj_stack_pop_object(union acpi_operand_object **object, - struct acpi_walk_state *walk_state) -{ - ACPI_FUNCTION_NAME(ds_obj_stack_pop_object); - - /* Check for stack underflow */ - - if (walk_state->num_operands == 0) { - ACPI_ERROR((AE_INFO, - "Missing operand/stack empty! State=%p #Ops=%X", - walk_state, walk_state->num_operands)); - *object = NULL; - return (AE_AML_NO_OPERAND); - } - - /* Pop the stack */ - - walk_state->num_operands--; - - /* Check for a valid operand */ - - if (!walk_state->operands[walk_state->num_operands]) { - ACPI_ERROR((AE_INFO, - "Null operand! State=%p #Ops=%X", - walk_state, walk_state->num_operands)); - *object = NULL; - return (AE_AML_NO_OPERAND); - } - - /* Get operand and set stack entry to null */ - - *object = walk_state->operands[walk_state->num_operands]; - walk_state->operands[walk_state->num_operands] = NULL; - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n", - *object, acpi_ut_get_object_type_name(*object), - walk_state, walk_state->num_operands)); - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_obj_stack_get_value - * - * PARAMETERS: Index - Stack index whose value is desired. Based - * on the top of the stack (index=0 == top) - * walk_state - Current Walk state - * - * RETURN: Pointer to the requested operand - * - * DESCRIPTION: Retrieve an object from this walk's operand stack. Index must - * be within the range of the current stack pointer. - * - ******************************************************************************/ - -void *acpi_ds_obj_stack_get_value(u32 index, struct acpi_walk_state *walk_state) -{ - - ACPI_FUNCTION_TRACE_PTR(ds_obj_stack_get_value, walk_state); - - /* Can't do it if the stack is empty */ - - if (walk_state->num_operands == 0) { - return_PTR(NULL); - } - - /* or if the index is past the top of the stack */ - - if (index > (walk_state->num_operands - (u32) 1)) { - return_PTR(NULL); - } - - return_PTR(walk_state-> - operands[(acpi_native_uint) (walk_state->num_operands - 1) - - index]); -} -#endif diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c index 773aee82fbb8..266dd0c10218 100644 --- a/drivers/acpi/parser/psloop.c +++ b/drivers/acpi/parser/psloop.c @@ -603,13 +603,6 @@ acpi_ps_complete_op(struct acpi_walk_state *walk_state, acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); - - if ((*op)->common.aml_opcode != AML_WHILE_OP) { - status2 = acpi_ds_result_stack_pop(walk_state); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - } } /* Close this iteration of the While loop */ @@ -640,10 +633,6 @@ acpi_ps_complete_op(struct acpi_walk_state *walk_state, if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } - status2 = acpi_ds_result_stack_pop(walk_state); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } acpi_ut_delete_generic_state (acpi_ut_pop_generic_state diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c index 5d63f48e56b5..ce3139a74f95 100644 --- a/drivers/acpi/parser/psparse.c +++ b/drivers/acpi/parser/psparse.c @@ -349,19 +349,13 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state, parser_state->aml = walk_state->aml_last_while; walk_state->control_state->common.value = FALSE; - status = acpi_ds_result_stack_pop(walk_state); - if (ACPI_SUCCESS(status)) { - status = AE_CTRL_BREAK; - } + status = AE_CTRL_BREAK; break; case AE_CTRL_CONTINUE: parser_state->aml = walk_state->aml_last_while; - status = acpi_ds_result_stack_pop(walk_state); - if (ACPI_SUCCESS(status)) { - status = AE_CTRL_CONTINUE; - } + status = AE_CTRL_CONTINUE; break; case AE_CTRL_PENDING: @@ -383,10 +377,7 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state, * Just close out this package */ parser_state->aml = acpi_ps_get_next_package_end(parser_state); - status = acpi_ds_result_stack_pop(walk_state); - if (ACPI_SUCCESS(status)) { - status = AE_CTRL_PENDING; - } + status = AE_CTRL_PENDING; break; case AE_CTRL_FALSE: diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index 422f29c06c77..d13bab452b83 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -63,7 +63,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20070126 +#define ACPI_CA_VERSION 0x20070307 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, @@ -150,6 +150,17 @@ #define ACPI_OBJ_NUM_OPERANDS 8 #define ACPI_OBJ_MAX_OPERAND 7 +/* Number of elements in the Result Stack frame, can be an arbitrary value */ + +#define ACPI_RESULTS_FRAME_OBJ_NUM 8 + +/* + * Maximal number of elements the Result Stack can contain, + * it may be an arbitray value not exceeding the types of + * result_size and result_count (now u8). + */ +#define ACPI_RESULTS_OBJ_NUM_MAX 255 + /* Names within the namespace are 4 bytes long */ #define ACPI_NAME_SIZE 4 diff --git a/include/acpi/acdispat.h b/include/acpi/acdispat.h index 7f690bb0f02f..70d649e92c41 100644 --- a/include/acpi/acdispat.h +++ b/include/acpi/acdispat.h @@ -303,7 +303,7 @@ acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state, u32 aml_length, struct acpi_evaluate_info *info, u8 pass_number); -acpi_status +void acpi_ds_obj_stack_pop_and_delete(u32 pop_count, struct acpi_walk_state *walk_state); @@ -316,21 +316,11 @@ void acpi_ds_push_walk_state(struct acpi_walk_state *walk_state, struct acpi_thread_state *thread); -acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *walk_state); - -acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *walk_state); - acpi_status acpi_ds_result_stack_clear(struct acpi_walk_state *walk_state); struct acpi_walk_state *acpi_ds_get_current_walk_state(struct acpi_thread_state *thread); -#ifdef ACPI_FUTURE_USAGE -acpi_status -acpi_ds_result_remove(union acpi_operand_object **object, - u32 index, struct acpi_walk_state *walk_state); -#endif - acpi_status acpi_ds_result_pop(union acpi_operand_object **object, struct acpi_walk_state *walk_state); @@ -339,8 +329,4 @@ acpi_status acpi_ds_result_push(union acpi_operand_object *object, struct acpi_walk_state *walk_state); -acpi_status -acpi_ds_result_pop_from_bottom(union acpi_operand_object **object, - struct acpi_walk_state *walk_state); - #endif /* _ACDISPAT_H_ */ diff --git a/include/acpi/aclocal.h b/include/acpi/aclocal.h index 202cd4242ba1..0b7c9a9e3c84 100644 --- a/include/acpi/aclocal.h +++ b/include/acpi/aclocal.h @@ -522,9 +522,8 @@ struct acpi_thread_state { * AML arguments */ struct acpi_result_values { - ACPI_STATE_COMMON u8 num_results; - u8 last_insert; - union acpi_operand_object *obj_desc[ACPI_OBJ_NUM_OPERANDS]; + ACPI_STATE_COMMON + union acpi_operand_object *obj_desc[ACPI_RESULTS_FRAME_OBJ_NUM]; }; typedef diff --git a/include/acpi/acstruct.h b/include/acpi/acstruct.h index 88482655407f..19b838dc1a16 100644 --- a/include/acpi/acstruct.h +++ b/include/acpi/acstruct.h @@ -80,12 +80,15 @@ struct acpi_walk_state { u16 opcode; /* Current AML opcode */ u8 next_op_info; /* Info about next_op */ u8 num_operands; /* Stack pointer for Operands[] array */ + u8 operand_index; /* Index into operand stack, to be used by acpi_ds_obj_stack_push */ acpi_owner_id owner_id; /* Owner of objects created during the walk */ u8 last_predicate; /* Result of last predicate */ u8 current_result; u8 return_used; u8 scope_depth; u8 pass_number; /* Parse pass during table load */ + u8 result_size; /* Total elements for the result stack */ + u8 result_count; /* Current number of occupied elements of result stack */ u32 aml_offset; u32 arg_types; u32 method_breakpoint; /* For single stepping */ -- cgit v1.2.2 From f654ecbfacb47d20e8cac087bbada1b947db846b Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:36 +0400 Subject: ACPICA: Removed unused code Handling of AML_NAME_OP as a Reference.Opcode is no longer needed. Kernel bugzilla 2874 Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/executer/exdump.c | 9 --------- drivers/acpi/executer/exresolv.c | 18 ------------------ drivers/acpi/executer/exresop.c | 11 ----------- drivers/acpi/executer/exstore.c | 1 - 4 files changed, 39 deletions(-) diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c index 51c9c29987c3..fcb1da0d1de7 100644 --- a/drivers/acpi/executer/exdump.c +++ b/drivers/acpi/executer/exdump.c @@ -500,15 +500,6 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) acpi_os_printf("Reference: Debug\n"); break; - case AML_NAME_OP: - - ACPI_DUMP_PATHNAME(obj_desc->reference.object, - "Reference: Name: ", ACPI_LV_INFO, - _COMPONENT); - ACPI_DUMP_ENTRY(obj_desc->reference.object, - ACPI_LV_INFO); - break; - case AML_INDEX_OP: acpi_os_printf("Reference: Index %p\n", diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c index 6c64e55dab0e..74ab220a5924 100644 --- a/drivers/acpi/executer/exresolv.c +++ b/drivers/acpi/executer/exresolv.c @@ -140,7 +140,6 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, { acpi_status status = AE_OK; union acpi_operand_object *stack_desc; - void *temp_node; union acpi_operand_object *obj_desc = NULL; u16 opcode; @@ -156,23 +155,6 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, opcode = stack_desc->reference.opcode; switch (opcode) { - case AML_NAME_OP: - - /* - * Convert name reference to a namespace node - * Then, acpi_ex_resolve_node_to_value can be used to get the value - */ - temp_node = stack_desc->reference.object; - - /* Delete the Reference Object */ - - acpi_ut_remove_reference(stack_desc); - - /* Return the namespace node */ - - (*stack_ptr) = temp_node; - break; - case AML_LOCAL_OP: case AML_ARG_OP: diff --git a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c index 09d897b3f6d5..259047a383c2 100644 --- a/drivers/acpi/executer/exresop.c +++ b/drivers/acpi/executer/exresop.c @@ -137,7 +137,6 @@ acpi_ex_resolve_operands(u16 opcode, union acpi_operand_object *obj_desc; acpi_status status = AE_OK; u8 object_type; - void *temp_node; u32 arg_types; const struct acpi_opcode_info *op_info; u32 this_arg_type; @@ -239,7 +238,6 @@ acpi_ex_resolve_operands(u16 opcode, /*lint -fallthrough */ - case AML_NAME_OP: case AML_INDEX_OP: case AML_REF_OF_OP: case AML_ARG_OP: @@ -332,15 +330,6 @@ acpi_ex_resolve_operands(u16 opcode, if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - - if (obj_desc->reference.opcode == AML_NAME_OP) { - - /* Convert a named reference to the actual named object */ - - temp_node = obj_desc->reference.object; - acpi_ut_remove_reference(obj_desc); - (*stack_ptr) = temp_node; - } goto next_operand; case ARGI_DATAREFOBJ: /* Store operator only */ diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c index f4b69a637820..97cb188d3b77 100644 --- a/drivers/acpi/executer/exstore.c +++ b/drivers/acpi/executer/exstore.c @@ -313,7 +313,6 @@ acpi_ex_store(union acpi_operand_object *source_desc, * 4) Store to the debug object */ switch (ref_desc->reference.opcode) { - case AML_NAME_OP: case AML_REF_OF_OP: /* Storing an object into a Name "container" */ -- cgit v1.2.2 From ba886cd4ac957608777fbc8d137f6b9f0450e775 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:37 +0400 Subject: ACPICA: Update for mutiple global lock acquisitions by same thread Allows AcpiAcquireGlobalLock external interface to be called multiple times by the same thread. Allows use of AML fields that require the global lock while the running AML is already holding the global lock. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/dispatcher/dsmethod.c | 12 +-- drivers/acpi/events/evmisc.c | 11 ++- drivers/acpi/events/evxface.c | 26 ++++- drivers/acpi/executer/exfield.c | 24 ++--- drivers/acpi/executer/exmutex.c | 194 ++++++++++++++++++++++++------------- drivers/acpi/executer/exutils.c | 58 +++++------ drivers/acpi/namespace/nsaccess.c | 3 +- drivers/acpi/utilities/utdelete.c | 2 +- include/acpi/acglobal.h | 20 ++-- include/acpi/acinterp.h | 11 ++- include/acpi/acobject.h | 3 +- 11 files changed, 219 insertions(+), 145 deletions(-) diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index 1cbe61905824..c50c0cd5d717 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c @@ -232,9 +232,9 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, * recursive call. */ if (!walk_state || - !obj_desc->method.mutex->mutex.owner_thread || - (walk_state->thread != - obj_desc->method.mutex->mutex.owner_thread)) { + !obj_desc->method.mutex->mutex.thread_id || + (walk_state->thread->thread_id != + obj_desc->method.mutex->mutex.thread_id)) { /* * Acquire the method mutex. This releases the interpreter if we * block (and reacquires it before it returns) @@ -254,8 +254,8 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, original_sync_level = walk_state->thread->current_sync_level; - obj_desc->method.mutex->mutex.owner_thread = - walk_state->thread; + obj_desc->method.mutex->mutex.thread_id = + walk_state->thread->thread_id; walk_state->thread->current_sync_level = obj_desc->method.sync_level; } else { @@ -569,7 +569,7 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, acpi_os_release_mutex(method_desc->method.mutex->mutex. os_mutex); - method_desc->method.mutex->mutex.owner_thread = NULL; + method_desc->method.mutex->mutex.thread_id = 0; } } diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c index 21cb749d0c75..2d34663dc1ed 100644 --- a/drivers/acpi/events/evmisc.c +++ b/drivers/acpi/events/evmisc.c @@ -439,7 +439,8 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout) * Only one thread can acquire the GL at a time, the global_lock_mutex * enforces this. This interface releases the interpreter if we must wait. */ - status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, 0); + status = acpi_ex_system_wait_mutex( + acpi_gbl_global_lock_mutex->mutex.os_mutex, 0); if (status == AE_TIME) { if (acpi_ev_global_lock_thread_id == acpi_os_get_thread_id()) { acpi_ev_global_lock_acquired++; @@ -448,9 +449,9 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout) } if (ACPI_FAILURE(status)) { - status = - acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, - timeout); + status = acpi_ex_system_wait_mutex( + acpi_gbl_global_lock_mutex->mutex.os_mutex, + timeout); } if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); @@ -555,7 +556,7 @@ acpi_status acpi_ev_release_global_lock(void) /* Release the local GL mutex */ acpi_ev_global_lock_thread_id = NULL; acpi_ev_global_lock_acquired = 0; - acpi_os_release_mutex(acpi_gbl_global_lock_mutex); + acpi_os_release_mutex(acpi_gbl_global_lock_mutex->mutex.os_mutex); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c index 6d866a01f5f4..dbf34a5fc1e0 100644 --- a/drivers/acpi/events/evxface.c +++ b/drivers/acpi/events/evxface.c @@ -758,6 +758,12 @@ ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler) * * DESCRIPTION: Acquire the ACPI Global Lock * + * Note: Allows callers with the same thread ID to acquire the global lock + * multiple times. In other words, externally, the behavior of the global lock + * is identical to an AML mutex. On the first acquire, a new handle is + * returned. On any subsequent calls to acquire by the same thread, the same + * handle is returned. + * ******************************************************************************/ acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle) { @@ -770,14 +776,26 @@ acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle) /* Must lock interpreter to prevent race conditions */ acpi_ex_enter_interpreter(); - status = acpi_ev_acquire_global_lock(timeout); - acpi_ex_exit_interpreter(); + + status = acpi_ex_acquire_mutex_object(timeout, + acpi_gbl_global_lock_mutex, + acpi_os_get_thread_id()); if (ACPI_SUCCESS(status)) { - acpi_gbl_global_lock_handle++; + /* + * If this was the first acquisition of the Global Lock by this thread, + * create a new handle. Otherwise, return the existing handle. + */ + if (acpi_gbl_global_lock_mutex->mutex.acquisition_depth == 1) { + acpi_gbl_global_lock_handle++; + } + + /* Return the global lock handle */ + *handle = acpi_gbl_global_lock_handle; } + acpi_ex_exit_interpreter(); return (status); } @@ -802,7 +820,7 @@ acpi_status acpi_release_global_lock(u32 handle) return (AE_NOT_ACQUIRED); } - status = acpi_ev_release_global_lock(); + status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex); return (status); } diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c index 2d88a3d8d1ad..e66b367c4fb6 100644 --- a/drivers/acpi/executer/exfield.c +++ b/drivers/acpi/executer/exfield.c @@ -71,7 +71,6 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, union acpi_operand_object *buffer_desc; acpi_size length; void *buffer; - u8 locked; ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc); @@ -111,9 +110,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, /* Lock entire transaction if requested */ - locked = - acpi_ex_acquire_global_lock(obj_desc->common_field. - field_flags); + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); /* * Perform the read. @@ -125,7 +122,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, buffer.pointer), ACPI_READ | (obj_desc->field. attribute << 16)); - acpi_ex_release_global_lock(locked); + acpi_ex_release_global_lock(); goto exit; } @@ -175,13 +172,12 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, /* Lock entire transaction if requested */ - locked = - acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); /* Read from the field */ status = acpi_ex_extract_from_field(obj_desc, buffer, (u32) length); - acpi_ex_release_global_lock(locked); + acpi_ex_release_global_lock(); exit: if (ACPI_FAILURE(status)) { @@ -217,7 +213,6 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, u32 required_length; void *buffer; void *new_buffer; - u8 locked; union acpi_operand_object *buffer_desc; ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc); @@ -278,9 +273,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, /* Lock entire transaction if requested */ - locked = - acpi_ex_acquire_global_lock(obj_desc->common_field. - field_flags); + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); /* * Perform the write (returns status and perhaps data in the @@ -291,7 +284,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, (acpi_integer *) buffer, ACPI_WRITE | (obj_desc->field. attribute << 16)); - acpi_ex_release_global_lock(locked); + acpi_ex_release_global_lock(); *result_desc = buffer_desc; return_ACPI_STATUS(status); @@ -366,13 +359,12 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, /* Lock entire transaction if requested */ - locked = - acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); /* Write to the field */ status = acpi_ex_insert_into_field(obj_desc, buffer, length); - acpi_ex_release_global_lock(locked); + acpi_ex_release_global_lock(); /* Free temporary buffer if we used one */ diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c index 6748e3ef0997..0bebe751aac5 100644 --- a/drivers/acpi/executer/exmutex.c +++ b/drivers/acpi/executer/exmutex.c @@ -124,6 +124,66 @@ acpi_ex_link_mutex(union acpi_operand_object *obj_desc, thread->acquired_mutex_list = obj_desc; } +/******************************************************************************* + * + * FUNCTION: acpi_ex_acquire_mutex_object + * + * PARAMETERS: time_desc - Timeout in milliseconds + * obj_desc - Mutex object + * Thread - Current thread state + * + * RETURN: Status + * + * DESCRIPTION: Acquire an AML mutex, low-level interface + * + ******************************************************************************/ + +acpi_status +acpi_ex_acquire_mutex_object(u16 timeout, + union acpi_operand_object *obj_desc, + acpi_thread_id thread_id) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE_PTR(ex_acquire_mutex_object, obj_desc); + + /* Support for multiple acquires by the owning thread */ + + if (obj_desc->mutex.thread_id == thread_id) { + /* + * The mutex is already owned by this thread, just increment the + * acquisition depth + */ + obj_desc->mutex.acquisition_depth++; + return_ACPI_STATUS(AE_OK); + } + + /* Acquire the mutex, wait if necessary. Special case for Global Lock */ + + if (obj_desc == acpi_gbl_global_lock_mutex) { + status = acpi_ev_acquire_global_lock(timeout); + } else { + status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex, + timeout); + } + + if (ACPI_FAILURE(status)) { + + /* Includes failure from a timeout on time_desc */ + + return_ACPI_STATUS(status); + } + + /* Have the mutex: update mutex and save the sync_level */ + + obj_desc->mutex.thread_id = thread_id; + obj_desc->mutex.acquisition_depth = 1; + obj_desc->mutex.original_sync_level = 0; + obj_desc->mutex.owner_thread = NULL; /* Used only for AML Acquire() */ + + return_ACPI_STATUS(AE_OK); +} + /******************************************************************************* * * FUNCTION: acpi_ex_acquire_mutex @@ -161,7 +221,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, } /* - * Current Sync must be less than or equal to the sync level of the + * Current Sync level must be less than or equal to the sync level of the * mutex. This mechanism provides some deadlock prevention */ if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) { @@ -172,51 +232,70 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, return_ACPI_STATUS(AE_AML_MUTEX_ORDER); } - /* Support for multiple acquires by the owning thread */ + status = acpi_ex_acquire_mutex_object((u16) time_desc->integer.value, + obj_desc, + walk_state->thread->thread_id); + if (ACPI_SUCCESS(status) && obj_desc->mutex.acquisition_depth == 1) { + obj_desc->mutex.owner_thread = walk_state->thread; + obj_desc->mutex.original_sync_level = + walk_state->thread->current_sync_level; + walk_state->thread->current_sync_level = + obj_desc->mutex.sync_level; - if (obj_desc->mutex.owner_thread) { - if (obj_desc->mutex.owner_thread->thread_id == - walk_state->thread->thread_id) { - /* - * The mutex is already owned by this thread, just increment the - * acquisition depth - */ - obj_desc->mutex.acquisition_depth++; - return_ACPI_STATUS(AE_OK); - } + /* Link the mutex to the current thread for force-unlock at method exit */ + + acpi_ex_link_mutex(obj_desc, walk_state->thread); } - /* Acquire the mutex, wait if necessary. Special case for Global Lock */ + return_ACPI_STATUS(status); +} - if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) { - status = - acpi_ev_acquire_global_lock((u16) time_desc->integer.value); - } else { - status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex, - (u16) time_desc->integer. - value); - } +/******************************************************************************* + * + * FUNCTION: acpi_ex_release_mutex_object + * + * PARAMETERS: obj_desc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Release a previously acquired Mutex, low level interface. + * + ******************************************************************************/ - if (ACPI_FAILURE(status)) { +acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc) +{ + acpi_status status = AE_OK; - /* Includes failure from a timeout on time_desc */ + ACPI_FUNCTION_TRACE(ex_release_mutex_object); - return_ACPI_STATUS(status); + /* Match multiple Acquires with multiple Releases */ + + obj_desc->mutex.acquisition_depth--; + if (obj_desc->mutex.acquisition_depth != 0) { + + /* Just decrement the depth and return */ + + return_ACPI_STATUS(AE_OK); } - /* Have the mutex: update mutex and walk info and save the sync_level */ + if (obj_desc->mutex.owner_thread) { - obj_desc->mutex.owner_thread = walk_state->thread; - obj_desc->mutex.acquisition_depth = 1; - obj_desc->mutex.original_sync_level = - walk_state->thread->current_sync_level; + /* Unlink the mutex from the owner's list */ + + acpi_ex_unlink_mutex(obj_desc); + obj_desc->mutex.owner_thread = NULL; + } - walk_state->thread->current_sync_level = obj_desc->mutex.sync_level; + /* Release the mutex, special case for Global Lock */ - /* Link the mutex to the current thread for force-unlock at method exit */ + if (obj_desc == acpi_gbl_global_lock_mutex) { + status = acpi_ev_release_global_lock(); + } else { + acpi_os_release_mutex(obj_desc->mutex.os_mutex); + } - acpi_ex_link_mutex(obj_desc, walk_state->thread); - return_ACPI_STATUS(AE_OK); + obj_desc->mutex.thread_id = 0; + return_ACPI_STATUS(status); } /******************************************************************************* @@ -253,22 +332,13 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED); } - /* Sanity check: we must have a valid thread ID */ - - if (!walk_state->thread) { - ACPI_ERROR((AE_INFO, - "Cannot release Mutex [%4.4s], null thread info", - acpi_ut_get_node_name(obj_desc->mutex.node))); - return_ACPI_STATUS(AE_AML_INTERNAL); - } - /* * The Mutex is owned, but this thread must be the owner. * Special case for Global Lock, any thread can release */ if ((obj_desc->mutex.owner_thread->thread_id != walk_state->thread->thread_id) - && (obj_desc->mutex.os_mutex != acpi_gbl_global_lock_mutex)) { + && (obj_desc != acpi_gbl_global_lock_mutex)) { ACPI_ERROR((AE_INFO, "Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX", (unsigned long)walk_state->thread->thread_id, @@ -278,6 +348,15 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_AML_NOT_OWNER); } + /* Sanity check: we must have a valid thread ID */ + + if (!walk_state->thread) { + ACPI_ERROR((AE_INFO, + "Cannot release Mutex [%4.4s], null thread info", + acpi_ut_get_node_name(obj_desc->mutex.node))); + return_ACPI_STATUS(AE_AML_INTERNAL); + } + /* * The sync level of the mutex must be less than or equal to the current * sync level @@ -289,34 +368,12 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_AML_MUTEX_ORDER); } - /* Match multiple Acquires with multiple Releases */ - - obj_desc->mutex.acquisition_depth--; - if (obj_desc->mutex.acquisition_depth != 0) { - - /* Just decrement the depth and return */ - - return_ACPI_STATUS(AE_OK); - } - - /* Unlink the mutex from the owner's list */ + status = acpi_ex_release_mutex_object(obj_desc); - acpi_ex_unlink_mutex(obj_desc); - - /* Release the mutex, special case for Global Lock */ + /* Restore sync_level */ - if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) { - status = acpi_ev_release_global_lock(); - } else { - acpi_os_release_mutex(obj_desc->mutex.os_mutex); - } - - /* Update the mutex and restore sync_level */ - - obj_desc->mutex.owner_thread = NULL; walk_state->thread->current_sync_level = obj_desc->mutex.original_sync_level; - return_ACPI_STATUS(status); } @@ -357,7 +414,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread) /* Release the mutex, special case for Global Lock */ - if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) { + if (obj_desc == acpi_gbl_global_lock_mutex) { /* Ignore errors */ @@ -369,6 +426,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread) /* Mark mutex unowned */ obj_desc->mutex.owner_thread = NULL; + obj_desc->mutex.thread_id = 0; /* Update Thread sync_level (Last mutex is the important one) */ diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c index 6b0aeccbb69b..c0837af0acb1 100644 --- a/drivers/acpi/executer/exutils.c +++ b/drivers/acpi/executer/exutils.c @@ -240,72 +240,66 @@ void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc) * PARAMETERS: field_flags - Flags with Lock rule: * always_lock or never_lock * - * RETURN: TRUE/FALSE indicating whether the lock was actually acquired + * RETURN: None * - * DESCRIPTION: Obtain the global lock and keep track of this fact via two - * methods. A global variable keeps the state of the lock, and - * the state is returned to the caller. + * DESCRIPTION: Obtain the ACPI hardware Global Lock, only if the field + * flags specifiy that it is to be obtained before field access. * ******************************************************************************/ -u8 acpi_ex_acquire_global_lock(u32 field_flags) +void acpi_ex_acquire_global_lock(u32 field_flags) { - u8 locked = FALSE; acpi_status status; ACPI_FUNCTION_TRACE(ex_acquire_global_lock); - /* Only attempt lock if the always_lock bit is set */ + /* Only use the lock if the always_lock bit is set */ + + if (!(field_flags & AML_FIELD_LOCK_RULE_MASK)) { + return_VOID; + } - if (field_flags & AML_FIELD_LOCK_RULE_MASK) { + /* Attempt to get the global lock, wait forever */ - /* We should attempt to get the lock, wait forever */ + status = acpi_ex_acquire_mutex_object(ACPI_WAIT_FOREVER, + acpi_gbl_global_lock_mutex, + acpi_os_get_thread_id()); - status = acpi_ev_acquire_global_lock(ACPI_WAIT_FOREVER); - if (ACPI_SUCCESS(status)) { - locked = TRUE; - } else { - ACPI_EXCEPTION((AE_INFO, status, - "Could not acquire Global Lock")); - } + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Could not acquire Global Lock")); } - return_UINT8(locked); + return_VOID; } /******************************************************************************* * * FUNCTION: acpi_ex_release_global_lock * - * PARAMETERS: locked_by_me - Return value from corresponding call to - * acquire_global_lock. + * PARAMETERS: None * * RETURN: None * - * DESCRIPTION: Release the global lock if it is locked. + * DESCRIPTION: Release the ACPI hardware Global Lock * ******************************************************************************/ -void acpi_ex_release_global_lock(u8 locked_by_me) +void acpi_ex_release_global_lock(void) { acpi_status status; ACPI_FUNCTION_TRACE(ex_release_global_lock); - /* Only attempt unlock if the caller locked it */ - - if (locked_by_me) { + /* Release the global lock */ - /* OK, now release the lock */ - - status = acpi_ev_release_global_lock(); - if (ACPI_FAILURE(status)) { + status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex); + if (ACPI_FAILURE(status)) { - /* Report the error, but there isn't much else we can do */ + /* Report the error, but there isn't much else we can do */ - ACPI_EXCEPTION((AE_INFO, status, - "Could not release ACPI Global Lock")); - } + ACPI_EXCEPTION((AE_INFO, status, + "Could not release Global Lock")); } return_VOID; diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c index 57faf598bad8..32a01673cae8 100644 --- a/drivers/acpi/namespace/nsaccess.c +++ b/drivers/acpi/namespace/nsaccess.c @@ -208,8 +208,7 @@ acpi_status acpi_ns_root_initialize(void) /* Special case for ACPI Global Lock */ if (ACPI_STRCMP(init_val->name, "_GL_") == 0) { - acpi_gbl_global_lock_mutex = - obj_desc->mutex.os_mutex; + acpi_gbl_global_lock_mutex = obj_desc; /* Create additional counting semaphore for global lock */ diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c index f777cebdc46d..dcb34f805714 100644 --- a/drivers/acpi/utilities/utdelete.c +++ b/drivers/acpi/utilities/utdelete.c @@ -158,7 +158,7 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) "***** Mutex %p, OS Mutex %p\n", object, object->mutex.os_mutex)); - if (object->mutex.os_mutex == acpi_gbl_global_lock_mutex) { + if (object == acpi_gbl_global_lock_mutex) { /* Global Lock has extra semaphore */ diff --git a/include/acpi/acglobal.h b/include/acpi/acglobal.h index 47a1fd8f2d8a..e91008eaef2d 100644 --- a/include/acpi/acglobal.h +++ b/include/acpi/acglobal.h @@ -170,10 +170,14 @@ ACPI_EXTERN u8 acpi_gbl_integer_nybble_width; ACPI_EXTERN struct acpi_mutex_info acpi_gbl_mutex_info[ACPI_NUM_MUTEX]; /* - * Global lock semaphore works in conjunction with the actual HW global lock + * Global lock mutex is an actual AML mutex object + * Global lock semaphore works in conjunction with the HW global lock */ -ACPI_EXTERN acpi_mutex acpi_gbl_global_lock_mutex; +ACPI_EXTERN union acpi_operand_object *acpi_gbl_global_lock_mutex; ACPI_EXTERN acpi_semaphore acpi_gbl_global_lock_semaphore; +ACPI_EXTERN u16 acpi_gbl_global_lock_handle; +ACPI_EXTERN u8 acpi_gbl_global_lock_acquired; +ACPI_EXTERN u8 acpi_gbl_global_lock_present; /* * Spinlocks are used for interfaces that can be possibly called at @@ -215,22 +219,22 @@ ACPI_EXTERN acpi_exception_handler acpi_gbl_exception_handler; ACPI_EXTERN acpi_init_handler acpi_gbl_init_handler; ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk; +/* Owner ID support */ + +ACPI_EXTERN u32 acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS]; +ACPI_EXTERN u8 acpi_gbl_last_owner_id_index; +ACPI_EXTERN u8 acpi_gbl_next_owner_id_offset; + /* Misc */ ACPI_EXTERN u32 acpi_gbl_original_mode; ACPI_EXTERN u32 acpi_gbl_rsdp_original_location; ACPI_EXTERN u32 acpi_gbl_ns_lookup_count; ACPI_EXTERN u32 acpi_gbl_ps_find_count; -ACPI_EXTERN u32 acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS]; ACPI_EXTERN u16 acpi_gbl_pm1_enable_register_save; -ACPI_EXTERN u16 acpi_gbl_global_lock_handle; -ACPI_EXTERN u8 acpi_gbl_last_owner_id_index; -ACPI_EXTERN u8 acpi_gbl_next_owner_id_offset; ACPI_EXTERN u8 acpi_gbl_debugger_configuration; -ACPI_EXTERN u8 acpi_gbl_global_lock_acquired; ACPI_EXTERN u8 acpi_gbl_step_to_next_call; ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present; -ACPI_EXTERN u8 acpi_gbl_global_lock_present; ACPI_EXTERN u8 acpi_gbl_events_initialized; ACPI_EXTERN u8 acpi_gbl_system_awake_and_running; diff --git a/include/acpi/acinterp.h b/include/acpi/acinterp.h index ce7c9d653910..23863886e808 100644 --- a/include/acpi/acinterp.h +++ b/include/acpi/acinterp.h @@ -247,10 +247,17 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, union acpi_operand_object *obj_desc, struct acpi_walk_state *walk_state); +acpi_status +acpi_ex_acquire_mutex_object(u16 timeout, + union acpi_operand_object *obj_desc, + acpi_thread_id thread_id); + acpi_status acpi_ex_release_mutex(union acpi_operand_object *obj_desc, struct acpi_walk_state *walk_state); +acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc); + void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread); void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc); @@ -455,9 +462,9 @@ void acpi_ex_relinquish_interpreter(void); void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc); -u8 acpi_ex_acquire_global_lock(u32 rule); +void acpi_ex_acquire_global_lock(u32 rule); -void acpi_ex_release_global_lock(u8 locked); +void acpi_ex_release_global_lock(void); void acpi_ex_eisa_id_to_string(u32 numeric_id, char *out_string); diff --git a/include/acpi/acobject.h b/include/acpi/acobject.h index 7e1211a8b8fa..2461bb9ab3e9 100644 --- a/include/acpi/acobject.h +++ b/include/acpi/acobject.h @@ -155,8 +155,9 @@ struct acpi_object_event { struct acpi_object_mutex { ACPI_OBJECT_COMMON_HEADER u8 sync_level; /* 0-15, specified in Mutex() call */ u16 acquisition_depth; /* Allow multiple Acquires, same thread */ - struct acpi_thread_state *owner_thread; /* Current owner of the mutex */ acpi_mutex os_mutex; /* Actual OS synchronization object */ + acpi_thread_id thread_id; /* Current owner of the mutex */ + struct acpi_thread_state *owner_thread; /* Current owner of the mutex */ union acpi_operand_object *prev; /* Link for list of acquired mutexes */ union acpi_operand_object *next; /* Link for list of acquired mutexes */ struct acpi_namespace_node *node; /* Containing namespace node */ -- cgit v1.2.2 From 4e3156b183aa087bc19804b3295c7c1a71f64752 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:37 +0400 Subject: ACPICA: changed order of interpretation of operand objects The interpreter now evaluates operands in the order that they appear (both in the AML and ASL), instead of in reverse order. This previously caused subtle incompatibilities with the MS interpreter as well as being non-intuitive. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/dispatcher/dsutils.c | 113 +++++++++++++++++++++++++++++++++++++- drivers/acpi/dispatcher/dswexec.c | 11 +++- drivers/acpi/executer/exutils.c | 3 +- drivers/acpi/parser/psloop.c | 23 +++++++- drivers/acpi/parser/psopcode.c | 26 +++++++++ drivers/acpi/parser/pstree.c | 2 + include/acpi/acdispat.h | 2 + include/acpi/aclocal.h | 3 + include/acpi/acparser.h | 2 + 9 files changed, 177 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c index d2a8cfdaec22..36518b4a79c2 100644 --- a/drivers/acpi/dispatcher/dsutils.c +++ b/drivers/acpi/dispatcher/dsutils.c @@ -472,7 +472,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, /* A valid name must be looked up in the namespace */ if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) && - (arg->common.value.string)) { + (arg->common.value.string) && + !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) { ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", arg)); @@ -595,7 +596,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, } else { /* Check for null name case */ - if (arg->common.aml_opcode == AML_INT_NAMEPATH_OP) { + if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) && + !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) { /* * If the name is null, this means that this is an * optional result parameter that was not specified @@ -617,7 +619,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, return_ACPI_STATUS(AE_NOT_IMPLEMENTED); } - if (op_info->flags & AML_HAS_RETVAL) { + if ((op_info->flags & AML_HAS_RETVAL) + || (arg->common.flags & ACPI_PARSEOP_IN_STACK)) { ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Argument previously created, already stacked\n")); @@ -759,3 +762,107 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state, ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %d", index)); return_ACPI_STATUS(status); } + +/***************************************************************************** + * + * FUNCTION: acpi_ds_evaluate_name_path + * + * PARAMETERS: walk_state - Current state of the parse tree walk, + * the opcode of current operation should be + * AML_INT_NAMEPATH_OP + * + * RETURN: Status + * + * DESCRIPTION: Translate the -name_path- parse tree object to the equivalent + * interpreter object, convert it to value, if needed, duplicate + * it, if needed, and push it onto the current result stack. + * + ****************************************************************************/ + +acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state) +{ + acpi_status status = AE_OK; + union acpi_parse_object *op = walk_state->op; + union acpi_operand_object **operand = &walk_state->operands[0]; + union acpi_operand_object *new_obj_desc; + u8 type; + + ACPI_FUNCTION_TRACE_PTR(ds_evaluate_name_path, walk_state); + + if (!op->common.parent) { + + /* This happens after certain exception processing */ + + goto exit; + } + + if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) || + (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP) || + (op->common.parent->common.aml_opcode == AML_REF_OF_OP)) { + + /* TBD: Should we specify this feature as a bit of op_info->Flags of these opcodes? */ + + goto exit; + } + + status = acpi_ds_create_operand(walk_state, op, 0); + if (ACPI_FAILURE(status)) { + goto exit; + } + + if (op->common.flags & ACPI_PARSEOP_TARGET) { + new_obj_desc = *operand; + goto push_result; + } + + type = ACPI_GET_OBJECT_TYPE(*operand); + + status = acpi_ex_resolve_to_value(operand, walk_state); + if (ACPI_FAILURE(status)) { + goto exit; + } + + if (type == ACPI_TYPE_INTEGER) { + + /* It was incremented by acpi_ex_resolve_to_value */ + + acpi_ut_remove_reference(*operand); + + status = + acpi_ut_copy_iobject_to_iobject(*operand, &new_obj_desc, + walk_state); + if (ACPI_FAILURE(status)) { + goto exit; + } + } else { + /* + * The object either was anew created or is + * a Namespace node - don't decrement it. + */ + new_obj_desc = *operand; + } + + /* Cleanup for name-path operand */ + + status = acpi_ds_obj_stack_pop(1, walk_state); + if (ACPI_FAILURE(status)) { + walk_state->result_obj = new_obj_desc; + goto exit; + } + + push_result: + + walk_state->result_obj = new_obj_desc; + + status = acpi_ds_result_push(walk_state->result_obj, walk_state); + if (ACPI_SUCCESS(status)) { + + /* Force to take it from stack */ + + op->common.flags |= ACPI_PARSEOP_IN_STACK; + } + + exit: + + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c index 12b148587e3d..514b9d2eb3a7 100644 --- a/drivers/acpi/dispatcher/dswexec.c +++ b/drivers/acpi/dispatcher/dswexec.c @@ -375,10 +375,17 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) /* Decode the Opcode Class */ switch (op_class) { - case AML_CLASS_ARGUMENT: /* constants, literals, etc. - do nothing */ + case AML_CLASS_ARGUMENT: /* Constants, literals, etc. */ + + if (walk_state->opcode == AML_INT_NAMEPATH_OP) { + status = acpi_ds_evaluate_name_path(walk_state); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + } break; - case AML_CLASS_EXECUTE: /* most operators with arguments */ + case AML_CLASS_EXECUTE: /* Most operators with arguments */ /* Build resolved operand stack */ diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c index c0837af0acb1..c40b191f70b5 100644 --- a/drivers/acpi/executer/exutils.c +++ b/drivers/acpi/executer/exutils.c @@ -217,9 +217,10 @@ void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc) /* * Object must be a valid number and we must be executing - * a control method + * a control method. NS node could be there for AML_INT_NAMEPATH_OP. */ if ((!obj_desc) || + (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) || (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER)) { return; } diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c index 266dd0c10218..4348b0530398 100644 --- a/drivers/acpi/parser/psloop.c +++ b/drivers/acpi/parser/psloop.c @@ -182,6 +182,7 @@ acpi_ps_build_named_op(struct acpi_walk_state *walk_state, ACPI_FUNCTION_TRACE_PTR(ps_build_named_op, walk_state); unnamed_op->common.value.arg = NULL; + unnamed_op->common.arg_list_length = 0; unnamed_op->common.aml_opcode = walk_state->opcode; /* @@ -280,6 +281,9 @@ acpi_ps_create_op(struct acpi_walk_state *walk_state, acpi_status status = AE_OK; union acpi_parse_object *op; union acpi_parse_object *named_op = NULL; + union acpi_parse_object *parent_scope; + u8 argument_count; + const struct acpi_opcode_info *op_info; ACPI_FUNCTION_TRACE_PTR(ps_create_op, walk_state); @@ -320,8 +324,23 @@ acpi_ps_create_op(struct acpi_walk_state *walk_state, op->named.length = 0; } - acpi_ps_append_arg(acpi_ps_get_parent_scope - (&(walk_state->parser_state)), op); + parent_scope = acpi_ps_get_parent_scope(&(walk_state->parser_state)); + acpi_ps_append_arg(parent_scope, op); + + if (parent_scope) { + op_info = + acpi_ps_get_opcode_info(parent_scope->common.aml_opcode); + if (op_info->flags & AML_HAS_TARGET) { + argument_count = + acpi_ps_get_argument_count(op_info->type); + if (parent_scope->common.arg_list_length > + argument_count) { + op->common.flags |= ACPI_PARSEOP_TARGET; + } + } else if (parent_scope->common.aml_opcode == AML_INCREMENT_OP) { + op->common.flags |= ACPI_PARSEOP_TARGET; + } + } if (walk_state->descending_callback != NULL) { /* diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c index 9296e86761d7..3bf8105d6348 100644 --- a/drivers/acpi/parser/psopcode.c +++ b/drivers/acpi/parser/psopcode.c @@ -49,6 +49,8 @@ #define _COMPONENT ACPI_PARSER ACPI_MODULE_NAME("psopcode") +const u8 acpi_gbl_argument_count[] = { 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 6 }; + /******************************************************************************* * * NAME: acpi_gbl_aml_op_info @@ -59,6 +61,7 @@ ACPI_MODULE_NAME("psopcode") * the operand type. * ******************************************************************************/ + /* * Summary of opcode types/flags * @@ -176,6 +179,7 @@ ACPI_MODULE_NAME("psopcode") AML_CREATE_QWORD_FIELD_OP ******************************************************************************/ + /* * Master Opcode information table. A summary of everything we know about each * opcode, all in one place. @@ -779,3 +783,25 @@ char *acpi_ps_get_opcode_name(u16 opcode) #endif } + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_argument_count + * + * PARAMETERS: op_type - Type associated with the AML opcode + * + * RETURN: Argument count + * + * DESCRIPTION: Obtain the number of expected arguments for an AML opcode + * + ******************************************************************************/ + +u8 acpi_ps_get_argument_count(u32 op_type) +{ + + if (op_type <= AML_TYPE_EXEC_6A_0T_1R) { + return (acpi_gbl_argument_count[op_type]); + } + + return (0); +} diff --git a/drivers/acpi/parser/pstree.c b/drivers/acpi/parser/pstree.c index 966e7ea2a0c4..0e1a3226665d 100644 --- a/drivers/acpi/parser/pstree.c +++ b/drivers/acpi/parser/pstree.c @@ -171,6 +171,8 @@ acpi_ps_append_arg(union acpi_parse_object *op, union acpi_parse_object *arg) while (arg) { arg->common.parent = op; arg = arg->common.next; + + op->common.arg_list_length++; } } diff --git a/include/acpi/acdispat.h b/include/acpi/acdispat.h index 70d649e92c41..3bffb4db4bce 100644 --- a/include/acpi/acdispat.h +++ b/include/acpi/acdispat.h @@ -269,6 +269,8 @@ acpi_status acpi_ds_resolve_operands(struct acpi_walk_state *walk_state); void acpi_ds_clear_operands(struct acpi_walk_state *walk_state); +acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state); + /* * dswscope - Scope Stack manipulation */ diff --git a/include/acpi/aclocal.h b/include/acpi/aclocal.h index 0b7c9a9e3c84..946da60e36e7 100644 --- a/include/acpi/aclocal.h +++ b/include/acpi/aclocal.h @@ -603,6 +603,7 @@ union acpi_parse_value { union acpi_parse_object *next; /* Next op */\ struct acpi_namespace_node *node; /* For use by interpreter */\ union acpi_parse_value value; /* Value or args associated with the opcode */\ + u8 arg_list_length; /* Number of elements in the arg list */\ ACPI_DISASM_ONLY_MEMBERS (\ u8 disasm_flags; /* Used during AML disassembly */\ u8 disasm_opcode; /* Subtype used for disassembly */\ @@ -695,6 +696,8 @@ struct acpi_parse_state { #define ACPI_PARSEOP_NAMED 0x02 #define ACPI_PARSEOP_DEFERRED 0x04 #define ACPI_PARSEOP_BYTELIST 0x08 +#define ACPI_PARSEOP_IN_STACK 0x10 +#define ACPI_PARSEOP_TARGET 0x20 #define ACPI_PARSEOP_IN_CACHE 0x80 /* Parse object disasm_flags */ diff --git a/include/acpi/acparser.h b/include/acpi/acparser.h index 85c358e21014..a3ae76b270af 100644 --- a/include/acpi/acparser.h +++ b/include/acpi/acparser.h @@ -109,6 +109,8 @@ const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode); char *acpi_ps_get_opcode_name(u16 opcode); +u8 acpi_ps_get_argument_count(u32 op_type); + /* * psparse - top level parsing routines */ -- cgit v1.2.2 From 4b6e16cf2bacbf328535097fa74f1494b1873c54 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:37 +0400 Subject: ACPICA: Avoid use of invalid pointers in returned object field During operand evaluation, ensure that the ReturnObj field is cleared on error and only valid pointers are stored there. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/executer/exoparg1.c | 1 + drivers/acpi/executer/exoparg2.c | 19 +++++++++++++------ drivers/acpi/executer/exoparg3.c | 1 + drivers/acpi/executer/exoparg6.c | 8 ++++++-- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c index 252f10acbbcc..ab5c03724527 100644 --- a/drivers/acpi/executer/exoparg1.c +++ b/drivers/acpi/executer/exoparg1.c @@ -121,6 +121,7 @@ acpi_status acpi_ex_opcode_0A_0T_1R(struct acpi_walk_state *walk_state) if ((ACPI_FAILURE(status)) || walk_state->result_obj) { acpi_ut_remove_reference(return_desc); + walk_state->result_obj = NULL; } else { /* Save the return value */ diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c index 17e652e65379..81c02b12d3f2 100644 --- a/drivers/acpi/executer/exoparg2.c +++ b/drivers/acpi/executer/exoparg2.c @@ -241,10 +241,6 @@ acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state) goto cleanup; } - /* Return the remainder */ - - walk_state->result_obj = return_desc1; - cleanup: /* * Since the remainder is not returned indirectly, remove a reference to @@ -259,6 +255,12 @@ acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state) acpi_ut_remove_reference(return_desc1); } + /* Save return object (the remainder) on success */ + + else { + walk_state->result_obj = return_desc1; + } + return_ACPI_STATUS(status); } @@ -490,6 +492,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) if (ACPI_FAILURE(status)) { acpi_ut_remove_reference(return_desc); + walk_state->result_obj = NULL; } return_ACPI_STATUS(status); @@ -583,8 +586,6 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state) return_desc->integer.value = ACPI_INTEGER_MAX; } - walk_state->result_obj = return_desc; - cleanup: /* Delete return object on error */ @@ -593,5 +594,11 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state) acpi_ut_remove_reference(return_desc); } + /* Save return object on success */ + + else { + walk_state->result_obj = return_desc; + } + return_ACPI_STATUS(status); } diff --git a/drivers/acpi/executer/exoparg3.c b/drivers/acpi/executer/exoparg3.c index 7fe67cf82cee..a573f5d260f7 100644 --- a/drivers/acpi/executer/exoparg3.c +++ b/drivers/acpi/executer/exoparg3.c @@ -260,6 +260,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state) if (ACPI_FAILURE(status) || walk_state->result_obj) { acpi_ut_remove_reference(return_desc); + walk_state->result_obj = NULL; } /* Set the return object and exit */ diff --git a/drivers/acpi/executer/exoparg6.c b/drivers/acpi/executer/exoparg6.c index bd80a9cb3d65..163b2b3d9ce2 100644 --- a/drivers/acpi/executer/exoparg6.c +++ b/drivers/acpi/executer/exoparg6.c @@ -322,8 +322,6 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state) goto cleanup; } - walk_state->result_obj = return_desc; - cleanup: /* Delete return object on error */ @@ -332,5 +330,11 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state) acpi_ut_remove_reference(return_desc); } + /* Save return object on success */ + + else { + walk_state->result_obj = return_desc; + } + return_ACPI_STATUS(status); } -- cgit v1.2.2 From dbaaa9567543191faa933e78f979f5ff7385918c Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:37 +0400 Subject: ACPICA: Fixed a couple compiler warnings for extra extern statements Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- include/acpi/acglobal.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/acpi/acglobal.h b/include/acpi/acglobal.h index e91008eaef2d..44e718ee1579 100644 --- a/include/acpi/acglobal.h +++ b/include/acpi/acglobal.h @@ -238,6 +238,10 @@ ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present; ACPI_EXTERN u8 acpi_gbl_events_initialized; ACPI_EXTERN u8 acpi_gbl_system_awake_and_running; +#ifndef DEFINE_ACPI_GLOBALS + +/* Other miscellaneous */ + extern u8 acpi_gbl_shutdown; extern u32 acpi_gbl_startup_flags; extern const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT]; @@ -245,6 +249,8 @@ extern const char *acpi_gbl_highest_dstate_names[4]; extern const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES]; extern const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS]; +#endif + /* Exception codes */ extern char const *acpi_gbl_exception_names_env[]; -- cgit v1.2.2 From 91e38d10b2b49b8a200111baa7714c4a7e658a4c Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:37 +0400 Subject: ACPICA: Update comments for acquire/release mutex interfaces pdate comments for acquire/release mutex interfaces Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/executer/exmutex.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c index 0bebe751aac5..32f24a8fba57 100644 --- a/drivers/acpi/executer/exmutex.c +++ b/drivers/acpi/executer/exmutex.c @@ -134,7 +134,16 @@ acpi_ex_link_mutex(union acpi_operand_object *obj_desc, * * RETURN: Status * - * DESCRIPTION: Acquire an AML mutex, low-level interface + * DESCRIPTION: Acquire an AML mutex, low-level interface. Provides a common + * path that supports multiple acquires by the same thread. + * + * MUTEX: Interpreter must be locked + * + * NOTE: This interface is called from three places: + * 1) From acpi_ex_acquire_mutex, via an AML Acquire() operator + * 2) From acpi_ex_acquire_global_lock when an AML Field access requires the + * global lock + * 3) From the external interface, acpi_acquire_global_lock * ******************************************************************************/ @@ -174,7 +183,7 @@ acpi_ex_acquire_mutex_object(u16 timeout, return_ACPI_STATUS(status); } - /* Have the mutex: update mutex and save the sync_level */ + /* Acquired the mutex: update mutex object */ obj_desc->mutex.thread_id = thread_id; obj_desc->mutex.acquisition_depth = 1; @@ -211,7 +220,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Sanity check: we must have a valid thread ID */ + /* Must have a valid thread ID */ if (!walk_state->thread) { ACPI_ERROR((AE_INFO, @@ -221,7 +230,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, } /* - * Current Sync level must be less than or equal to the sync level of the + * Current sync level must be less than or equal to the sync level of the * mutex. This mechanism provides some deadlock prevention */ if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) { @@ -236,6 +245,9 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, obj_desc, walk_state->thread->thread_id); if (ACPI_SUCCESS(status) && obj_desc->mutex.acquisition_depth == 1) { + + /* Save Thread object, original/current sync levels */ + obj_desc->mutex.owner_thread = walk_state->thread; obj_desc->mutex.original_sync_level = walk_state->thread->current_sync_level; @@ -259,6 +271,16 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, * RETURN: Status * * DESCRIPTION: Release a previously acquired Mutex, low level interface. + * Provides a common path that supports multiple releases (after + * previous multiple acquires) by the same thread. + * + * MUTEX: Interpreter must be locked + * + * NOTE: This interface is called from three places: + * 1) From acpi_ex_release_mutex, via an AML Acquire() operator + * 2) From acpi_ex_release_global_lock when an AML Field access requires the + * global lock + * 3) From the external interface, acpi_release_global_lock * ******************************************************************************/ @@ -294,6 +316,8 @@ acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc) acpi_os_release_mutex(obj_desc->mutex.os_mutex); } + /* Clear mutex info */ + obj_desc->mutex.thread_id = 0; return_ACPI_STATUS(status); } @@ -348,7 +372,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_AML_NOT_OWNER); } - /* Sanity check: we must have a valid thread ID */ + /* Must have a valid thread ID */ if (!walk_state->thread) { ACPI_ERROR((AE_INFO, @@ -370,7 +394,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, status = acpi_ex_release_mutex_object(obj_desc); - /* Restore sync_level */ + /* Restore the original sync_level */ walk_state->thread->current_sync_level = obj_desc->mutex.original_sync_level; -- cgit v1.2.2 From a69c77c72094bfda1ed02336ec9a1bae186fd2fc Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:37 +0400 Subject: ACPICA: Removed extraneous code Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/dispatcher/dsmethod.c | 7 ------- drivers/acpi/namespace/nswalk.c | 4 +--- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index c50c0cd5d717..3db651c7f582 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c @@ -535,7 +535,6 @@ void acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, struct acpi_walk_state *walk_state) { - struct acpi_namespace_node *method_node; acpi_status status; ACPI_FUNCTION_TRACE_PTR(ds_terminate_control_method, walk_state); @@ -574,12 +573,6 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, } if (walk_state) { - /* - * Delete any objects created by this method during execution. - * The method Node is stored in the walk state - */ - method_node = walk_state->method_node; - /* * Delete any namespace objects created anywhere within * the namespace by the execution of this method diff --git a/drivers/acpi/namespace/nswalk.c b/drivers/acpi/namespace/nswalk.c index 280b8357c46c..c7b5409e2cf8 100644 --- a/drivers/acpi/namespace/nswalk.c +++ b/drivers/acpi/namespace/nswalk.c @@ -77,9 +77,7 @@ struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type, struct /* It's really the parent's _scope_ that we want */ - if (parent_node->child) { - next_node = parent_node->child; - } + next_node = parent_node->child; } else { -- cgit v1.2.2 From a4df451a1055d97726ab890249bc3f941906fa75 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:37 +0400 Subject: ACPICA: Removed obsolete ACPI_NO_INTEGER64_SUPPORT define Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- include/acpi/acmacros.h | 12 +----------- include/acpi/actypes.h | 23 +++-------------------- 2 files changed, 4 insertions(+), 31 deletions(-) diff --git a/include/acpi/acmacros.h b/include/acpi/acmacros.h index 99d171c87c84..401228d34f13 100644 --- a/include/acpi/acmacros.h +++ b/include/acpi/acmacros.h @@ -61,21 +61,11 @@ #define ACPI_ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0])) -#ifdef ACPI_NO_INTEGER64_SUPPORT /* - * acpi_integer is 32-bits, no 64-bit support on this platform - */ -#define ACPI_LODWORD(l) ((u32)(l)) -#define ACPI_HIDWORD(l) ((u32)(0)) - -#else - -/* - * Full 64-bit address/integer on both 32-bit and 64-bit platforms + * Full 64-bit integer must be available on both 32-bit and 64-bit platforms */ #define ACPI_LODWORD(l) ((u32)(u64)(l)) #define ACPI_HIDWORD(l) ((u32)(((*(struct uint64_struct *)(void *)(&l))).hi)) -#endif /* * printf() format helpers diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index e73a38939120..6182b57590ef 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -323,27 +323,11 @@ struct uint32_struct { #define acpi_semaphore void * /* - * Acpi integer width. In ACPI version 1, integers are - * 32 bits. In ACPI version 2, integers are 64 bits. - * Note that this pertains to the ACPI integer type only, not - * other integers used in the implementation of the ACPI CA + * Acpi integer width. In ACPI version 1, integers are 32 bits. In ACPI + * version 2, integers are 64 bits. Note that this pertains to the ACPI integer + * type only, not other integers used in the implementation of the ACPI CA * subsystem. */ -#ifdef ACPI_NO_INTEGER64_SUPPORT - -/* 32-bit integers only, no 64-bit support */ - -typedef u32 acpi_integer; -#define ACPI_INTEGER_MAX ACPI_UINT32_MAX -#define ACPI_INTEGER_BIT_SIZE 32 -#define ACPI_MAX_DECIMAL_DIGITS 10 /* 2^32 = 4,294,967,296 */ - -#define ACPI_USE_NATIVE_DIVIDE /* Use compiler native 32-bit divide */ - -#else - -/* 64-bit integers */ - typedef unsigned long long acpi_integer; #define ACPI_INTEGER_MAX ACPI_UINT64_MAX #define ACPI_INTEGER_BIT_SIZE 64 @@ -352,7 +336,6 @@ typedef unsigned long long acpi_integer; #if ACPI_MACHINE_WIDTH == 64 #define ACPI_USE_NATIVE_DIVIDE /* Use compiler native 64-bit divide */ #endif -#endif #define ACPI_MAX64_DECIMAL_DIGITS 20 #define ACPI_MAX32_DECIMAL_DIGITS 10 -- cgit v1.2.2 From f02e9fa1ceee045f7d5c53d475032815752a2510 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:37 +0400 Subject: ACPICA: Misc fixes for recent global lock code update Fixes as a result of running full validation test suite. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/events/evxface.c | 2 +- drivers/acpi/executer/exfield.c | 8 ++++---- drivers/acpi/executer/exmutex.c | 23 ++++++++++++++++++----- drivers/acpi/executer/exutils.c | 11 +++++++++-- include/acpi/acinterp.h | 2 +- 5 files changed, 33 insertions(+), 13 deletions(-) diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c index dbf34a5fc1e0..e210aa2d76da 100644 --- a/drivers/acpi/events/evxface.c +++ b/drivers/acpi/events/evxface.c @@ -816,7 +816,7 @@ acpi_status acpi_release_global_lock(u32 handle) { acpi_status status; - if (handle != acpi_gbl_global_lock_handle) { + if (!handle || (handle != acpi_gbl_global_lock_handle)) { return (AE_NOT_ACQUIRED); } diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c index e66b367c4fb6..da772cb91d7f 100644 --- a/drivers/acpi/executer/exfield.c +++ b/drivers/acpi/executer/exfield.c @@ -122,7 +122,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, buffer.pointer), ACPI_READ | (obj_desc->field. attribute << 16)); - acpi_ex_release_global_lock(); + acpi_ex_release_global_lock(obj_desc->common_field.field_flags); goto exit; } @@ -177,7 +177,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, /* Read from the field */ status = acpi_ex_extract_from_field(obj_desc, buffer, (u32) length); - acpi_ex_release_global_lock(); + acpi_ex_release_global_lock(obj_desc->common_field.field_flags); exit: if (ACPI_FAILURE(status)) { @@ -284,7 +284,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, (acpi_integer *) buffer, ACPI_WRITE | (obj_desc->field. attribute << 16)); - acpi_ex_release_global_lock(); + acpi_ex_release_global_lock(obj_desc->common_field.field_flags); *result_desc = buffer_desc; return_ACPI_STATUS(status); @@ -364,7 +364,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, /* Write to the field */ status = acpi_ex_insert_into_field(obj_desc, buffer, length); - acpi_ex_release_global_lock(); + acpi_ex_release_global_lock(obj_desc->common_field.field_flags); /* Free temporary buffer if we used one */ diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c index 32f24a8fba57..b8d035c00b61 100644 --- a/drivers/acpi/executer/exmutex.c +++ b/drivers/acpi/executer/exmutex.c @@ -156,6 +156,10 @@ acpi_ex_acquire_mutex_object(u16 timeout, ACPI_FUNCTION_TRACE_PTR(ex_acquire_mutex_object, obj_desc); + if (!obj_desc) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + /* Support for multiple acquires by the owning thread */ if (obj_desc->mutex.thread_id == thread_id) { @@ -290,6 +294,10 @@ acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc) ACPI_FUNCTION_TRACE(ex_release_mutex_object); + if (obj_desc->mutex.acquisition_depth == 0) { + return (AE_NOT_ACQUIRED); + } + /* Match multiple Acquires with multiple Releases */ obj_desc->mutex.acquisition_depth--; @@ -387,17 +395,22 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, */ if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) { ACPI_ERROR((AE_INFO, - "Cannot release Mutex [%4.4s], incorrect SyncLevel", - acpi_ut_get_node_name(obj_desc->mutex.node))); + "Cannot release Mutex [%4.4s], SyncLevel mismatch: mutex %d current %d", + acpi_ut_get_node_name(obj_desc->mutex.node), + obj_desc->mutex.sync_level, + walk_state->thread->current_sync_level)); return_ACPI_STATUS(AE_AML_MUTEX_ORDER); } status = acpi_ex_release_mutex_object(obj_desc); - /* Restore the original sync_level */ + if (obj_desc->mutex.acquisition_depth == 0) { + + /* Restore the original sync_level */ - walk_state->thread->current_sync_level = - obj_desc->mutex.original_sync_level; + walk_state->thread->current_sync_level = + obj_desc->mutex.original_sync_level; + } return_ACPI_STATUS(status); } diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c index c40b191f70b5..fd543ee547ae 100644 --- a/drivers/acpi/executer/exutils.c +++ b/drivers/acpi/executer/exutils.c @@ -278,7 +278,8 @@ void acpi_ex_acquire_global_lock(u32 field_flags) * * FUNCTION: acpi_ex_release_global_lock * - * PARAMETERS: None + * PARAMETERS: field_flags - Flags with Lock rule: + * always_lock or never_lock * * RETURN: None * @@ -286,12 +287,18 @@ void acpi_ex_acquire_global_lock(u32 field_flags) * ******************************************************************************/ -void acpi_ex_release_global_lock(void) +void acpi_ex_release_global_lock(u32 field_flags) { acpi_status status; ACPI_FUNCTION_TRACE(ex_release_global_lock); + /* Only use the lock if the always_lock bit is set */ + + if (!(field_flags & AML_FIELD_LOCK_RULE_MASK)) { + return_VOID; + } + /* Release the global lock */ status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex); diff --git a/include/acpi/acinterp.h b/include/acpi/acinterp.h index 23863886e808..92eb0141ac81 100644 --- a/include/acpi/acinterp.h +++ b/include/acpi/acinterp.h @@ -464,7 +464,7 @@ void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc); void acpi_ex_acquire_global_lock(u32 rule); -void acpi_ex_release_global_lock(void); +void acpi_ex_release_global_lock(u32 rule); void acpi_ex_eisa_id_to_string(u32 numeric_id, char *out_string); -- cgit v1.2.2 From 422f4f90a23437e3e9de31eab5feb2a13f0cbb38 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:37 +0400 Subject: ACPICA: Increase maximum buffer size dumped to screen in buffer object dump Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/executer/exstore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c index 97cb188d3b77..f88b18163206 100644 --- a/drivers/acpi/executer/exstore.c +++ b/drivers/acpi/executer/exstore.c @@ -147,7 +147,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, (u32) source_desc->buffer.length)); ACPI_DUMP_BUFFER(source_desc->buffer.pointer, (source_desc->buffer.length < - 32) ? source_desc->buffer.length : 32); + 256) ? source_desc->buffer.length : 256); break; case ACPI_TYPE_STRING: -- cgit v1.2.2 From 91d02132fea3a60d3db7bd72933e38e36cd9e4c7 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:38 +0400 Subject: ACPICA: Fix for package reference counts Prevents infinite loop of 'Large Reference Count' messages in aslts-bdemo-b286 test. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/dispatcher/dsobject.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c index 954ac8ce958a..fe28b9aeb65c 100644 --- a/drivers/acpi/dispatcher/dsobject.c +++ b/drivers/acpi/dispatcher/dsobject.c @@ -370,6 +370,8 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, union acpi_operand_object *obj_desc = NULL; acpi_status status = AE_OK; acpi_native_uint i; + u16 index; + u16 reference_count; ACPI_FUNCTION_TRACE(ds_build_internal_package_obj); @@ -447,6 +449,26 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, package. elements[i]); } + + if (*obj_desc_ptr) { + + /* Existing package, get existing reference count */ + + reference_count = + (*obj_desc_ptr)->common.reference_count; + if (reference_count > 1) { + + /* Make new element ref count match original ref count */ + + for (index = 0; index < (reference_count - 1); + index++) { + acpi_ut_add_reference((obj_desc-> + package. + elements[i])); + } + } + } + arg = arg->common.next; } -- cgit v1.2.2 From 235eebbdb501261e9960deb2a9a3459af44ec0ea Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:38 +0400 Subject: ACPICA: Update version to 20070320 pdate version to 20070320 Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- include/acpi/acconfig.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index d13bab452b83..c1829a3805a5 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -63,7 +63,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20070307 +#define ACPI_CA_VERSION 0x20070320 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, -- cgit v1.2.2 From e5567afa5cfa19e45f93c9c8796e46187a2d12f4 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:38 +0400 Subject: ACPICA: Fix for update of the Global Lock Handle Fixed a problem where the global lock handle was not properly updated if a thread that acquired the global lock via executing AML code then attempted to acquire the lock via the AcpiAcquireGlobalLock interface. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/events/evmisc.c | 13 +++++++++++++ drivers/acpi/events/evxface.c | 9 +-------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c index 2d34663dc1ed..d075062f5b89 100644 --- a/drivers/acpi/events/evmisc.c +++ b/drivers/acpi/events/evmisc.c @@ -460,6 +460,19 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout) acpi_ev_global_lock_thread_id = acpi_os_get_thread_id(); acpi_ev_global_lock_acquired++; + /* + * Update the global lock handle and check for wraparound. The handle is + * only used for the external global lock interfaces, but it is updated + * here to properly handle the case where a single thread may acquire the + * lock via both the AML and the acpi_acquire_global_lock interfaces. The + * handle is therefore updated on the first acquire from a given thread + * regardless of where the acquisition request originated. + */ + acpi_gbl_global_lock_handle++; + if (acpi_gbl_global_lock_handle == 0) { + acpi_gbl_global_lock_handle = 1; + } + /* * Make sure that a global lock actually exists. If not, just treat * the lock as a standard mutex. diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c index e210aa2d76da..412cae698311 100644 --- a/drivers/acpi/events/evxface.c +++ b/drivers/acpi/events/evxface.c @@ -782,15 +782,8 @@ acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle) acpi_os_get_thread_id()); if (ACPI_SUCCESS(status)) { - /* - * If this was the first acquisition of the Global Lock by this thread, - * create a new handle. Otherwise, return the existing handle. - */ - if (acpi_gbl_global_lock_mutex->mutex.acquisition_depth == 1) { - acpi_gbl_global_lock_handle++; - } - /* Return the global lock handle */ + /* Return the global lock handle (updated in acpi_ev_acquire_global_lock) */ *handle = acpi_gbl_global_lock_handle; } -- cgit v1.2.2 From 5cc1b9b42663878330a4cc1d8020bb9289c46066 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:38 +0400 Subject: ACPICA: Update version to 20070508 Update version to 20070508. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- include/acpi/acconfig.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index c1829a3805a5..a45230dc9561 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -63,7 +63,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20070320 +#define ACPI_CA_VERSION 0x20070508 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, -- cgit v1.2.2 From 6deb65dd9d66ff70fa8f8665690295a1126f801a Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:38 +0400 Subject: ACPICA: Updated error message for dynamic method serialization Added more information to make the message clearer. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/parser/psparse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c index ce3139a74f95..1442e55c40d1 100644 --- a/drivers/acpi/parser/psparse.c +++ b/drivers/acpi/parser/psparse.c @@ -532,7 +532,7 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) if ((status == AE_ALREADY_EXISTS) && (!walk_state->method_desc->method.mutex)) { ACPI_INFO((AE_INFO, - "Marking method %4.4s as Serialized", + "Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error", walk_state->method_node->name. ascii)); -- cgit v1.2.2 From e20a679b4acf81a419bbe80beddedc988bf3bd51 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:38 +0400 Subject: ACPICA: Support for iASL - multiple files and wildcards Implemented support to allow multiple files to be compiled/disassembled in a single invocation. This includes command line wildcard support for both the Windows and Unix versions of the compiler. This feature simplifies the disassembly and compilation of multiple ACPI tables in a single directory. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/utilities/utinit.c | 3 +++ drivers/acpi/utilities/utxface.c | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/drivers/acpi/utilities/utinit.c b/drivers/acpi/utilities/utinit.c index ad3c0d0a5cf8..de44477be79f 100644 --- a/drivers/acpi/utilities/utinit.c +++ b/drivers/acpi/utilities/utinit.c @@ -125,9 +125,12 @@ void acpi_ut_subsystem_shutdown(void) acpi_gbl_startup_flags = 0; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n")); +#ifndef ACPI_ASL_COMPILER + /* Close the acpi_event Handling */ acpi_ev_terminate(); +#endif /* Close the Namespace */ diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c index 2d496918b3cd..15bd6ff547e7 100644 --- a/drivers/acpi/utilities/utxface.c +++ b/drivers/acpi/utilities/utxface.c @@ -49,6 +49,7 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utxface") +#ifndef ACPI_ASL_COMPILER /******************************************************************************* * * FUNCTION: acpi_initialize_subsystem @@ -292,6 +293,7 @@ acpi_status acpi_initialize_objects(u32 flags) ACPI_EXPORT_SYMBOL(acpi_initialize_objects) +#endif /******************************************************************************* * * FUNCTION: acpi_terminate @@ -335,6 +337,7 @@ acpi_status acpi_terminate(void) } ACPI_EXPORT_SYMBOL(acpi_terminate) +#ifndef ACPI_ASL_COMPILER #ifdef ACPI_FUTURE_USAGE /******************************************************************************* * @@ -490,3 +493,4 @@ acpi_status acpi_purge_cached_objects(void) } ACPI_EXPORT_SYMBOL(acpi_purge_cached_objects) +#endif -- cgit v1.2.2 From 698c0a0c299bd9389522e14dae1aff02070bac25 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:38 +0400 Subject: ACPICA: Add minimal disassembly support for the SLIC table SLIC - Software Licensing Description Table. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- include/acpi/acdisasm.h | 1 + include/acpi/actbl1.h | 1 + 2 files changed, 2 insertions(+) diff --git a/include/acpi/acdisasm.h b/include/acpi/acdisasm.h index 389d772c7d5b..75c354f7a024 100644 --- a/include/acpi/acdisasm.h +++ b/include/acpi/acdisasm.h @@ -180,6 +180,7 @@ extern struct acpi_dmtable_info acpi_dm_table_info_mcfg0[]; extern struct acpi_dmtable_info acpi_dm_table_info_rsdp1[]; extern struct acpi_dmtable_info acpi_dm_table_info_rsdp2[]; extern struct acpi_dmtable_info acpi_dm_table_info_sbst[]; +extern struct acpi_dmtable_info acpi_dm_table_info_slic[]; extern struct acpi_dmtable_info acpi_dm_table_info_slit[]; extern struct acpi_dmtable_info acpi_dm_table_info_spcr[]; extern struct acpi_dmtable_info acpi_dm_table_info_spmi[]; diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h index a1b1b2ee3e51..dd8e11e624fa 100644 --- a/include/acpi/actbl1.h +++ b/include/acpi/actbl1.h @@ -67,6 +67,7 @@ #define ACPI_SIG_MADT "APIC" /* Multiple APIC Description Table */ #define ACPI_SIG_MCFG "MCFG" /* PCI Memory Mapped Configuration table */ #define ACPI_SIG_SBST "SBST" /* Smart Battery Specification Table */ +#define ACPI_SIG_SLIC "SLIC" /* Software Licensing Description Table */ #define ACPI_SIG_SLIT "SLIT" /* System Locality Distance Information Table */ #define ACPI_SIG_SPCR "SPCR" /* Serial Port Console Redirection table */ #define ACPI_SIG_SPMI "SPMI" /* Server Platform Management Interface table */ -- cgit v1.2.2 From 3e08e2d2d6efb256aa035e300deb059bb333b6db Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Thu, 10 Apr 2008 19:06:38 +0400 Subject: ACPICA: New interfaces for table event handlers Designed and implemented new external interfaces to install and remove handlers for ACPI table-related events. Current events that are defined are LOAD and UNLOAD. These interfaces allow the host to track ACPI tables as they are dynamically loaded and unloaded. See AcpiInstallTableHandler and AcpiRemoveTableHandler. Signed-off-by: Lin Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/executer/exconfig.c | 29 ++++++++++++- drivers/acpi/tables/tbxface.c | 89 +++++++++++++++++++++++++++++++++++++++ drivers/acpi/utilities/utglobal.c | 3 +- include/acpi/acdisasm.h | 4 +- include/acpi/acglobal.h | 2 + include/acpi/acpixf.h | 5 +++ include/acpi/actypes.h | 11 +++++ 7 files changed, 139 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index 25802f302ffe..009aef5fcbfc 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -234,6 +234,13 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, table->oem_table_id)); } + /* Invoke table handler if present */ + + if (acpi_gbl_table_handler) { + (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table, + acpi_gbl_table_handler_context); + } + *return_desc = ddb_handle; return_ACPI_STATUS(status); } @@ -352,6 +359,14 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, return_ACPI_STATUS(status); } + /* Invoke table handler if present */ + + if (acpi_gbl_table_handler) { + (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, + table_desc.pointer, + acpi_gbl_table_handler_context); + } + cleanup: if (ACPI_FAILURE(status)) { acpi_tb_delete_table(&table_desc); @@ -376,6 +391,7 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) acpi_status status = AE_OK; union acpi_operand_object *table_desc = ddb_handle; acpi_native_uint table_index; + struct acpi_table_header *table; ACPI_FUNCTION_TRACE(ex_unload_table); @@ -395,6 +411,17 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) table_index = (acpi_native_uint) table_desc->reference.object; + /* Invoke table handler if present */ + + if (acpi_gbl_table_handler) { + status = acpi_get_table_by_index(table_index, &table); + if (ACPI_SUCCESS(status)) { + (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_UNLOAD, + table, + acpi_gbl_table_handler_context); + } + } + /* * Delete the entire namespace under this table Node * (Offset contains the table_id) @@ -407,5 +434,5 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) /* Delete the table descriptor (ddb_handle) */ acpi_ut_remove_reference(table_desc); - return_ACPI_STATUS(status); + return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c index a9e3331fee5d..5f2271542a96 100644 --- a/drivers/acpi/tables/tbxface.c +++ b/drivers/acpi/tables/tbxface.c @@ -635,6 +635,95 @@ acpi_status acpi_load_tables(void) ACPI_EXPORT_SYMBOL(acpi_load_tables) +/******************************************************************************* + * + * FUNCTION: acpi_install_table_handler + * + * PARAMETERS: Handler - Table event handler + * Context - Value passed to the handler on each event + * + * RETURN: Status + * + * DESCRIPTION: Install table event handler + * + ******************************************************************************/ +acpi_status +acpi_install_table_handler(acpi_tbl_handler handler, void *context) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_install_table_handler); + + if (!handler) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Don't allow more than one handler */ + + if (acpi_gbl_table_handler) { + status = AE_ALREADY_EXISTS; + goto cleanup; + } + + /* Install the handler */ + + acpi_gbl_table_handler = handler; + acpi_gbl_table_handler_context = context; + + cleanup: + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_install_table_handler) + +/******************************************************************************* + * + * FUNCTION: acpi_remove_table_handler + * + * PARAMETERS: Handler - Table event handler that was installed + * previously. + * + * RETURN: Status + * + * DESCRIPTION: Remove table event handler + * + ******************************************************************************/ +acpi_status acpi_remove_table_handler(acpi_tbl_handler handler) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_remove_table_handler); + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Make sure that the installed handler is the same */ + + if (!handler || handler != acpi_gbl_table_handler) { + status = AE_BAD_PARAMETER; + goto cleanup; + } + + /* Remove the handler */ + + acpi_gbl_table_handler = NULL; + + cleanup: + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_remove_table_handler) + + static int __init acpi_no_auto_ssdt_setup(char *s) { printk(KERN_NOTICE "ACPI: SSDT auto-load disabled\n"); diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index 630c9a2c5b7b..44425433075a 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c @@ -675,12 +675,13 @@ void acpi_ut_init_globals(void) acpi_gbl_gpe_fadt_blocks[0] = NULL; acpi_gbl_gpe_fadt_blocks[1] = NULL; - /* Global notify handlers */ + /* Global handlers */ acpi_gbl_system_notify.handler = NULL; acpi_gbl_device_notify.handler = NULL; acpi_gbl_exception_handler = NULL; acpi_gbl_init_handler = NULL; + acpi_gbl_table_handler = NULL; /* Global Lock support */ diff --git a/include/acpi/acdisasm.h b/include/acpi/acdisasm.h index 75c354f7a024..67d152e7fa44 100644 --- a/include/acpi/acdisasm.h +++ b/include/acpi/acdisasm.h @@ -104,12 +104,12 @@ typedef const struct acpi_dmtable_info { #define ACPI_DMT_SIG 27 typedef -void (*ACPI_TABLE_HANDLER) (struct acpi_table_header * table); +void (*acpi_dmtable_handler) (struct acpi_table_header * table); struct acpi_dmtable_data { char *signature; struct acpi_dmtable_info *table_info; - ACPI_TABLE_HANDLER table_handler; + acpi_dmtable_handler table_handler; char *name; }; diff --git a/include/acpi/acglobal.h b/include/acpi/acglobal.h index 44e718ee1579..862468616217 100644 --- a/include/acpi/acglobal.h +++ b/include/acpi/acglobal.h @@ -217,6 +217,8 @@ ACPI_EXTERN struct acpi_object_notify_handler acpi_gbl_device_notify; ACPI_EXTERN struct acpi_object_notify_handler acpi_gbl_system_notify; ACPI_EXTERN acpi_exception_handler acpi_gbl_exception_handler; ACPI_EXTERN acpi_init_handler acpi_gbl_init_handler; +ACPI_EXTERN acpi_tbl_handler acpi_gbl_table_handler; +ACPI_EXTERN void *acpi_gbl_table_handler_context; ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk; /* Owner ID support */ diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index d970f7f99549..c92acda1a77f 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -119,6 +119,11 @@ acpi_status acpi_get_table_by_index(acpi_native_uint table_index, struct acpi_table_header **out_table); +acpi_status +acpi_install_table_handler(acpi_tbl_handler handler, void *context); + +acpi_status acpi_remove_table_handler(acpi_tbl_handler handler); + /* * Namespace and name interfaces */ diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 6182b57590ef..766178c6cc81 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -730,6 +730,12 @@ struct acpi_system_info { u32 debug_layer; }; +/* Table Event Types */ + +#define ACPI_TABLE_EVENT_LOAD 0x0 +#define ACPI_TABLE_EVENT_UNLOAD 0x1 +#define ACPI_NUM_TABLE_EVENTS 2 + /* * Types specific to the OS service interfaces */ @@ -759,6 +765,11 @@ acpi_status(*acpi_exception_handler) (acpi_status aml_status, u16 opcode, u32 aml_offset, void *context); +/* Table Event handler (Load, load_table etc) and types */ + +typedef +acpi_status(*acpi_tbl_handler) (u32 event, void *table, void *context); + /* Address Spaces (For Operation Regions) */ typedef -- cgit v1.2.2 From 14808822a9cea782c2e6f8d39e438cc3891f6472 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Thu, 10 Apr 2008 19:06:38 +0400 Subject: ACPICA: Fix for namespace lookup problem Fixed a problem where objects of certain types (Device, ThermalZone, Processor, PowerResource) can be not found if they are declared and referenced from within the same control method http://www.acpica.org/bugzilla/show_bug.cgi?id=341. Signed-off-by: Lin Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/parser/psargs.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c index c2b9835c890b..442880f5600e 100644 --- a/drivers/acpi/parser/psargs.c +++ b/drivers/acpi/parser/psargs.c @@ -230,12 +230,11 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, struct acpi_parse_state *parser_state, union acpi_parse_object *arg, u8 possible_method_call) { + acpi_status status; char *path; union acpi_parse_object *name_op; - acpi_status status; union acpi_operand_object *method_desc; struct acpi_namespace_node *node; - union acpi_generic_state scope_info; ACPI_FUNCTION_TRACE(ps_get_next_namepath); @@ -249,25 +248,18 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, return_ACPI_STATUS(AE_OK); } - /* Setup search scope info */ - - scope_info.scope.node = NULL; - node = parser_state->start_node; - if (node) { - scope_info.scope.node = node; - } - /* - * Lookup the name in the internal namespace. We don't want to add - * anything new to the namespace here, however, so we use MODE_EXECUTE. + * Lookup the name in the internal namespace, starting with the current + * scope. We don't want to add anything new to the namespace here, + * however, so we use MODE_EXECUTE. * Allow searching of the parent tree, but don't open a new scope - * we just want to lookup the object (must be mode EXECUTE to perform * the upsearch) */ - status = - acpi_ns_lookup(&scope_info, path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, - ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, - NULL, &node); + status = acpi_ns_lookup(walk_state->scope_info, path, + ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, + NULL, &node); /* * If this name is a control method invocation, we must -- cgit v1.2.2 From 1c12a7dde1752f2c40fe170cabff463a0b362720 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:39 +0400 Subject: ACPICA: update version number to 20070919 Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- include/acpi/acconfig.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index a45230dc9561..65815009127a 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -63,7 +63,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20070508 +#define ACPI_CA_VERSION 0x20070919 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, -- cgit v1.2.2 From 53cf174409a24e8388e1d554d27436275fc81fe7 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:39 +0400 Subject: ACPICA: Fix for Alias operator to see target child objects Fixed a problem with the Alias operator when the target of the alias is a named ASL operator that opens a new scope -- Scope, Device, PowerResource, Processor, and ThermalZone. In these cases, any children of the original operator could not be accessed via the alias, potentially causing unexpected AE_NOT_FOUND exceptions. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/executer/excreate.c | 20 ++++++-- drivers/acpi/namespace/nsaccess.c | 96 ++++++++++++++++++++++++--------------- 2 files changed, 75 insertions(+), 41 deletions(-) diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c index 6e9a23e47fef..b3914395851b 100644 --- a/drivers/acpi/executer/excreate.c +++ b/drivers/acpi/executer/excreate.c @@ -96,16 +96,28 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) * to the original Node. */ switch (target_node->type) { + + /* For these types, the sub-object can change dynamically via a Store */ + case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: case ACPI_TYPE_PACKAGE: case ACPI_TYPE_BUFFER_FIELD: + /* + * These types open a new scope, so we need the NS node in order to access + * any children. + */ + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_POWER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + case ACPI_TYPE_LOCAL_SCOPE: + /* * The new alias has the type ALIAS and points to the original - * NS node, not the object itself. This is because for these - * types, the object can change dynamically via a Store. + * NS node, not the object itself. */ alias_node->type = ACPI_TYPE_LOCAL_ALIAS; alias_node->object = @@ -115,9 +127,7 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) case ACPI_TYPE_METHOD: /* - * The new alias has the type ALIAS and points to the original - * NS node, not the object itself. This is because for these - * types, the object can change dynamically via a Store. + * Control method aliases need to be differentiated */ alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS; alias_node->object = diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c index 32a01673cae8..54852fbfc878 100644 --- a/drivers/acpi/namespace/nsaccess.c +++ b/drivers/acpi/namespace/nsaccess.c @@ -581,44 +581,68 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, return_ACPI_STATUS(status); } - /* - * Sanity typecheck of the target object: - * - * If 1) This is the last segment (num_segments == 0) - * 2) And we are looking for a specific type - * (Not checking for TYPE_ANY) - * 3) Which is not an alias - * 4) Which is not a local type (TYPE_SCOPE) - * 5) And the type of target object is known (not TYPE_ANY) - * 6) And target object does not match what we are looking for - * - * Then we have a type mismatch. Just warn and ignore it. - */ - if ((num_segments == 0) && - (type_to_check_for != ACPI_TYPE_ANY) && - (type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) && - (type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS) && - (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) && - (this_node->type != ACPI_TYPE_ANY) && - (this_node->type != type_to_check_for)) { - - /* Complain about a type mismatch */ - - ACPI_WARNING((AE_INFO, - "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)", - ACPI_CAST_PTR(char, &simple_name), - acpi_ut_get_type_name(this_node->type), - acpi_ut_get_type_name - (type_to_check_for))); + /* More segments to follow? */ + + if (num_segments > 0) { + /* + * If we have an alias to an object that opens a scope (such as a + * device or processor), we need to dereference the alias here so that + * we can access any children of the original node (via the remaining + * segments). + */ + if (this_node->type == ACPI_TYPE_LOCAL_ALIAS) { + if (acpi_ns_opens_scope + (((struct acpi_namespace_node *)this_node-> + object)->type)) { + this_node = + (struct acpi_namespace_node *) + this_node->object; + } + } } - /* - * If this is the last name segment and we are not looking for a - * specific type, but the type of found object is known, use that type - * to see if it opens a scope. - */ - if ((num_segments == 0) && (type == ACPI_TYPE_ANY)) { - type = this_node->type; + /* Special handling for the last segment (num_segments == 0) */ + + else { + /* + * Sanity typecheck of the target object: + * + * If 1) This is the last segment (num_segments == 0) + * 2) And we are looking for a specific type + * (Not checking for TYPE_ANY) + * 3) Which is not an alias + * 4) Which is not a local type (TYPE_SCOPE) + * 5) And the type of target object is known (not TYPE_ANY) + * 6) And target object does not match what we are looking for + * + * Then we have a type mismatch. Just warn and ignore it. + */ + if ((type_to_check_for != ACPI_TYPE_ANY) && + (type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) && + (type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS) + && (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) + && (this_node->type != ACPI_TYPE_ANY) + && (this_node->type != type_to_check_for)) { + + /* Complain about a type mismatch */ + + ACPI_WARNING((AE_INFO, + "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)", + ACPI_CAST_PTR(char, &simple_name), + acpi_ut_get_type_name(this_node-> + type), + acpi_ut_get_type_name + (type_to_check_for))); + } + + /* + * If this is the last name segment and we are not looking for a + * specific type, but the type of found object is known, use that type + * to (later) see if it opens a scope. + */ + if (type == ACPI_TYPE_ANY) { + type = this_node->type; + } } /* Point to next name segment and make this node current */ -- cgit v1.2.2 From 5eb691805f7ec5960fe9d5d7fc57a7fc3097bbd0 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:39 +0400 Subject: ACPICA: Fix for fault if Load() fails Fixed a problem with the Load operator when loading a table from a buffer object. The input buffer was prematurely zeroed and/or deleted. http://www.acpica.org/bugzilla/show_bug.cgi?id=577 Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/executer/exconfig.c | 35 ++++++++++++++++++++++++----------- drivers/acpi/tables/tbinstal.c | 21 ++++++++++++++------- drivers/acpi/utilities/utdebug.c | 5 +++++ 3 files changed, 43 insertions(+), 18 deletions(-) diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index 009aef5fcbfc..8cc410ce9208 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -285,16 +285,16 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { case ACPI_TYPE_REGION: + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n", + obj_desc, + acpi_ut_get_object_type_name(obj_desc))); + /* Region must be system_memory (from ACPI spec) */ if (obj_desc->region.space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) { return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n", - obj_desc, - acpi_ut_get_object_type_name(obj_desc))); - /* * If the Region Address and Length have not been previously evaluated, * evaluate them now and save the results. @@ -306,6 +306,11 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, } } + /* + * We will simply map the memory region for the table. However, the + * memory region is technically not guaranteed to remain stable and + * we may eventually have to copy the table to a local buffer. + */ table_desc.address = obj_desc->region.address; table_desc.length = obj_desc->region.length; table_desc.flags = ACPI_TABLE_ORIGIN_MAPPED; @@ -313,18 +318,23 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */ - /* Simply extract the buffer from the buffer object */ - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Buffer or Field %p %s\n", obj_desc, acpi_ut_get_object_type_name(obj_desc))); - table_desc.pointer = ACPI_CAST_PTR(struct acpi_table_header, - obj_desc->buffer.pointer); - table_desc.length = table_desc.pointer->length; - table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; + /* + * We need to copy the buffer since the original buffer could be + * changed or deleted in the future + */ + table_desc.pointer = ACPI_ALLOCATE(obj_desc->buffer.length); + if (!table_desc.pointer) { + return_ACPI_STATUS(AE_NO_MEMORY); + } - obj_desc->buffer.pointer = NULL; + ACPI_MEMCPY(table_desc.pointer, obj_desc->buffer.pointer, + obj_desc->buffer.length); + table_desc.length = obj_desc->buffer.length; + table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; break; default: @@ -369,6 +379,9 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, cleanup: if (ACPI_FAILURE(status)) { + + /* Delete allocated buffer or mapping */ + acpi_tb_delete_table(&table_desc); } return_ACPI_STATUS(status); diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c index 3bc0c67a9283..6a6ee1f06c76 100644 --- a/drivers/acpi/tables/tbinstal.c +++ b/drivers/acpi/tables/tbinstal.c @@ -125,13 +125,20 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, /* The table must be either an SSDT or a PSDT or an OEMx */ - if ((!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_PSDT)) - && - (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT)) - && (strncmp(table_desc->pointer->signature, "OEM", 3))) { - ACPI_ERROR((AE_INFO, - "Table has invalid signature [%4.4s], must be SSDT, PSDT or OEMx", - table_desc->pointer->signature)); + if (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_PSDT)&& + !ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT)&& + strncmp(table_desc->pointer->signature, "OEM", 3)) { + /* Check for a printable name */ + if (acpi_ut_valid_acpi_name( + *(u32 *) table_desc->pointer->signature)) { + ACPI_ERROR((AE_INFO, "Table has invalid signature " + "[%4.4s], must be SSDT or PSDT", + table_desc->pointer->signature)); + } else { + ACPI_ERROR((AE_INFO, "Table has invalid signature " + "(0x%8.8X), must be SSDT or PSDT", + *(u32 *) table_desc->pointer->signature)); + } return_ACPI_STATUS(AE_BAD_SIGNATURE); } diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c index 7361204b1eef..a9148677f037 100644 --- a/drivers/acpi/utilities/utdebug.c +++ b/drivers/acpi/utilities/utdebug.c @@ -524,6 +524,11 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display) u32 temp32; u8 buf_char; + if (!buffer) { + acpi_os_printf("Null Buffer Pointer in DumpBuffer!\n"); + return; + } + if ((count < 4) || (count & 0x01)) { display = DB_BYTE_DISPLAY; } -- cgit v1.2.2 From 61ce421bb761f607b802c268bd8bd6a0c928a661 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:39 +0400 Subject: ACPICA: Fix a fault when storing DdbHandle to Debug object Fixed a problem with the Debug object where a store of a DdbHandle reference object to the Debug object could cause a fault. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/executer/exstore.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c index f88b18163206..912889ed45ed 100644 --- a/drivers/acpi/executer/exstore.c +++ b/drivers/acpi/executer/exstore.c @@ -123,6 +123,8 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, return_VOID; } + /* source_desc is of type ACPI_DESC_TYPE_OPERAND */ + switch (ACPI_GET_OBJECT_TYPE(source_desc)) { case ACPI_TYPE_INTEGER: @@ -180,11 +182,19 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, (source_desc->reference.opcode), source_desc->reference.offset)); } else { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s]\n", + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s]", acpi_ps_get_opcode_name (source_desc->reference.opcode))); } + if (source_desc->reference.opcode == AML_LOAD_OP) { /* Load and load_table */ + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, + " Table OwnerId %X\n", + source_desc->reference.object)); + break; + } + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "\n")); if (source_desc->reference.object) { if (ACPI_GET_DESCRIPTOR_TYPE (source_desc->reference.object) == -- cgit v1.2.2 From a13b8460c5b43a68192b599ce437168cc2ff04de Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:39 +0400 Subject: ACPICA: Fix for memory leak related to DdbHandle objects Fixed a memory leak where DdbHandle objects were not deleted automatically at control method exit. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/executer/exconfig.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index 8cc410ce9208..a0f34b467a22 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -366,6 +366,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, /* table_ptr was deallocated above */ + acpi_ut_remove_reference(ddb_handle); return_ACPI_STATUS(status); } -- cgit v1.2.2 From 98af37fba9b3e601ca4bded51ef51a2be4e8c97b Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:39 +0400 Subject: ACPICA: Add a table checksum verify for Load operator Added a table checksum verification for the Load operator, in the case where the load is from a buffer. http://www.acpica.org/bugzilla/show_bug.cgi?id=578 Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/executer/exconfig.c | 24 +++++++++++++++++++++--- drivers/acpi/tables/tbutils.c | 2 +- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index a0f34b467a22..dbf1e6f33bba 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -275,6 +275,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, struct acpi_table_desc table_desc; acpi_native_uint table_index; acpi_status status; + u32 length; ACPI_FUNCTION_TRACE(ex_load_op); @@ -322,18 +323,35 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, "Load from Buffer or Field %p %s\n", obj_desc, acpi_ut_get_object_type_name(obj_desc))); + length = obj_desc->buffer.length; + + /* Must have at least an ACPI table header */ + + if (length < sizeof(struct acpi_table_header)) { + return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); + } + + /* Validate checksum here. It won't get validated in tb_add_table */ + + status = acpi_tb_verify_checksum((struct acpi_table_header *) + obj_desc->buffer.pointer, + length); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + /* * We need to copy the buffer since the original buffer could be * changed or deleted in the future */ - table_desc.pointer = ACPI_ALLOCATE(obj_desc->buffer.length); + table_desc.pointer = ACPI_ALLOCATE(length); if (!table_desc.pointer) { return_ACPI_STATUS(AE_NO_MEMORY); } ACPI_MEMCPY(table_desc.pointer, obj_desc->buffer.pointer, - obj_desc->buffer.length); - table_desc.length = obj_desc->buffer.length; + length); + table_desc.length = length; table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; break; diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c index 010f19652f80..d04442fc4955 100644 --- a/drivers/acpi/tables/tbutils.c +++ b/drivers/acpi/tables/tbutils.c @@ -212,7 +212,7 @@ acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length) if (checksum) { ACPI_WARNING((AE_INFO, - "Incorrect checksum in table [%4.4s] - %2.2X, should be %2.2X", + "Incorrect checksum in table [%4.4s] - %2.2X, should be %2.2X", table->signature, table->checksum, (u8) (table->checksum - checksum))); -- cgit v1.2.2 From d8841647de7c4aa3f3ff5b8b8c4a3f042e848ff0 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:39 +0400 Subject: ACPICA: Add error checks to prevent faults Added additional error checking to prevent run-time faults. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/executer/exstore.c | 12 ++++++++++-- drivers/acpi/namespace/nsnames.c | 6 ++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c index 912889ed45ed..d860f9c6172c 100644 --- a/drivers/acpi/executer/exstore.c +++ b/drivers/acpi/executer/exstore.c @@ -209,8 +209,16 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, object, level + 4, 0); } } else if (source_desc->reference.node) { - acpi_ex_do_debug_object((source_desc->reference.node)-> - object, level + 4, 0); + if (ACPI_GET_DESCRIPTOR_TYPE + (source_desc->reference.node) != + ACPI_DESC_TYPE_NAMED) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, + " %p - Not a valid namespace node\n")); + } else { + acpi_ex_do_debug_object((source_desc->reference. + node)->object, + level + 4, 0); + } } break; diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c index cbd94af08cc5..e14a1412656b 100644 --- a/drivers/acpi/namespace/nsnames.c +++ b/drivers/acpi/namespace/nsnames.c @@ -180,6 +180,12 @@ acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node) next_node = node; while (next_node && (next_node != acpi_gbl_root_node)) { + if (ACPI_GET_DESCRIPTOR_TYPE(next_node) != ACPI_DESC_TYPE_NAMED) { + ACPI_ERROR((AE_INFO, + "Invalid NS Node (%X) while traversing path", + next_node)); + return 0; + } size += ACPI_PATH_SEGMENT_LENGTH; next_node = acpi_ns_get_parent_node(next_node); } -- cgit v1.2.2 From 7f4ac9f91383a0707de559dc8fbca986fc2d302f Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:39 +0400 Subject: ACPICA: Fix for Load/LoadTable to specify load location Fixed a problem with the Load and LoadTable operators where the table location within the namespace was ignored. Instead, the table was always loaded into the root or current scope. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/executer/exconfig.c | 3 ++- drivers/acpi/namespace/nsload.c | 2 +- drivers/acpi/namespace/nsparse.c | 18 +++++++++++++++--- include/acpi/acnamesp.h | 3 ++- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index dbf1e6f33bba..b9543a7f5d21 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -368,7 +368,8 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, } status = - acpi_ex_add_table(table_index, acpi_gbl_root_node, &ddb_handle); + acpi_ex_add_table(table_index, walk_state->scope_info->scope.node, + &ddb_handle); if (ACPI_FAILURE(status)) { /* On error, table_ptr was deallocated above */ diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c index d4f9654fd20f..545010dfd835 100644 --- a/drivers/acpi/namespace/nsload.c +++ b/drivers/acpi/namespace/nsload.c @@ -107,7 +107,7 @@ acpi_ns_load_table(acpi_native_uint table_index, goto unlock; } - status = acpi_ns_parse_table(table_index, node->child); + status = acpi_ns_parse_table(table_index, node); if (ACPI_SUCCESS(status)) { acpi_tb_set_table_loaded_flag(table_index, TRUE); } else { diff --git a/drivers/acpi/namespace/nsparse.c b/drivers/acpi/namespace/nsparse.c index e696aa847990..86bd6e5920c7 100644 --- a/drivers/acpi/namespace/nsparse.c +++ b/drivers/acpi/namespace/nsparse.c @@ -64,7 +64,8 @@ ACPI_MODULE_NAME("nsparse") ******************************************************************************/ acpi_status acpi_ns_one_complete_parse(acpi_native_uint pass_number, - acpi_native_uint table_index) + acpi_native_uint table_index, + struct acpi_namespace_node * start_node) { union acpi_parse_object *parse_root; acpi_status status; @@ -121,6 +122,13 @@ acpi_ns_one_complete_parse(acpi_native_uint pass_number, return_ACPI_STATUS(status); } + /* start_node is the default location to load the table */ + + if (start_node && start_node != acpi_gbl_root_node) { + acpi_ds_scope_stack_push(start_node, ACPI_TYPE_METHOD, + walk_state); + } + /* Parse the AML */ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "*PARSE* pass %d parse\n", @@ -163,7 +171,9 @@ acpi_ns_parse_table(acpi_native_uint table_index, * performs another complete parse of the AML. */ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n")); - status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS1, table_index); + status = + acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS1, table_index, + start_node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -178,7 +188,9 @@ acpi_ns_parse_table(acpi_native_uint table_index, * parse objects are all cached. */ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 2\n")); - status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS2, table_index); + status = + acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS2, table_index, + start_node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/include/acpi/acnamesp.h b/include/acpi/acnamesp.h index 5ef38a6c8a61..1cad10bd6df0 100644 --- a/include/acpi/acnamesp.h +++ b/include/acpi/acnamesp.h @@ -113,7 +113,8 @@ acpi_ns_parse_table(acpi_native_uint table_index, acpi_status acpi_ns_one_complete_parse(acpi_native_uint pass_number, - acpi_native_uint table_index); + acpi_native_uint table_index, + struct acpi_namespace_node *start_node); /* * nsaccess - Top-level namespace access -- cgit v1.2.2 From 9e41d93c975d403380b7debe05517d630c8e2836 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:39 +0400 Subject: ACPICA: Fixed a memory leak when Device or Thermal objects referenced in packages Problem introduced in fix for Package references. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/dispatcher/dsobject.c | 38 +++++++++++++++++++++----------------- drivers/acpi/utilities/utdelete.c | 8 +++++--- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c index fe28b9aeb65c..7556d919bf8b 100644 --- a/drivers/acpi/dispatcher/dsobject.c +++ b/drivers/acpi/dispatcher/dsobject.c @@ -172,7 +172,19 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, switch (op->common.node->type) { /* * For these types, we need the actual node, not the subobject. - * However, the subobject got an extra reference count above. + * However, the subobject did not get an extra reference count above. + * + * TBD: should ex_resolve_node_to_value be changed to fix this? + */ + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_THERMAL: + + acpi_ut_add_reference(op->common.node->object); + + /*lint -fallthrough */ + /* + * For these types, we need the actual node, not the subobject. + * The subobject got an extra reference count in ex_resolve_node_to_value. */ case ACPI_TYPE_MUTEX: case ACPI_TYPE_METHOD: @@ -180,25 +192,15 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_EVENT: case ACPI_TYPE_REGION: - case ACPI_TYPE_DEVICE: - case ACPI_TYPE_THERMAL: - obj_desc = - (union acpi_operand_object *)op->common. - node; + /* We will create a reference object for these types below */ break; default: - break; - } - - /* - * If above resolved to an operand object, we are done. Otherwise, - * we have a NS node, we must create the package entry as a named - * reference. - */ - if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != - ACPI_DESC_TYPE_NAMED) { + /* + * All other types - the node was resolved to an actual + * object, we are done. + */ goto exit; } } @@ -223,7 +225,7 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, exit: *obj_desc_ptr = obj_desc; - return_ACPI_STATUS(AE_OK); + return_ACPI_STATUS(status); } /******************************************************************************* @@ -743,6 +745,8 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, /* Node was saved in Op */ obj_desc->reference.node = op->common.node; + obj_desc->reference.object = + op->common.node->object; } obj_desc->reference.opcode = opcode; diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c index dcb34f805714..6a763cd85f8c 100644 --- a/drivers/acpi/utilities/utdelete.c +++ b/drivers/acpi/utilities/utdelete.c @@ -524,10 +524,12 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) case ACPI_TYPE_LOCAL_REFERENCE: /* - * The target of an Index (a package, string, or buffer) must track - * changes to the ref count of the index. + * The target of an Index (a package, string, or buffer) or a named + * reference must track changes to the ref count of the index or + * target object. */ - if (object->reference.opcode == AML_INDEX_OP) { + if ((object->reference.opcode == AML_INDEX_OP) || + (object->reference.opcode == AML_INT_NAMEPATH_OP)) { next_object = object->reference.object; } break; -- cgit v1.2.2 From fe4078af56a7b7f37391712cf188df3202b03776 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Thu, 10 Apr 2008 19:06:40 +0400 Subject: ACPICA: Fix for Increment/Decrement operator, incorrect type change Fixed a problem with the Increment and Decrement operators where the type of the target object could be unexpectedly and incorrectly changed. http://www.acpica.org/bugzilla/show_bug.cgi?id=353 Signed-off-by: Lin Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- include/acpi/acopcode.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/acpi/acopcode.h b/include/acpi/acopcode.h index e6f76a280a94..ab5434945807 100644 --- a/include/acpi/acopcode.h +++ b/include/acpi/acopcode.h @@ -233,7 +233,7 @@ #define ARGI_CREATE_WORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE) #define ARGI_DATA_REGION_OP ARGI_LIST3 (ARGI_STRING, ARGI_STRING, ARGI_STRING) #define ARGI_DEBUG_OP ARG_NONE -#define ARGI_DECREMENT_OP ARGI_LIST1 (ARGI_INTEGER_REF) +#define ARGI_DECREMENT_OP ARGI_LIST1 (ARGI_TARGETREF) #define ARGI_DEREF_OF_OP ARGI_LIST1 (ARGI_REF_OR_STRING) #define ARGI_DEVICE_OP ARGI_INVALID_OPCODE #define ARGI_DIVIDE_OP ARGI_LIST4 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF, ARGI_TARGETREF) @@ -246,7 +246,7 @@ #define ARGI_FIND_SET_RIGHT_BIT_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_TARGETREF) #define ARGI_FROM_BCD_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_FIXED_TARGET) #define ARGI_IF_OP ARGI_INVALID_OPCODE -#define ARGI_INCREMENT_OP ARGI_LIST1 (ARGI_INTEGER_REF) +#define ARGI_INCREMENT_OP ARGI_LIST1 (ARGI_TARGETREF) #define ARGI_INDEX_FIELD_OP ARGI_INVALID_OPCODE #define ARGI_INDEX_OP ARGI_LIST3 (ARGI_COMPLEXOBJ, ARGI_INTEGER, ARGI_TARGETREF) #define ARGI_LAND_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER) -- cgit v1.2.2 From 49718b1741cb74d86eb8b1bd8f52ad6a013b40df Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Thu, 10 Apr 2008 19:06:40 +0400 Subject: ACPICA: Added additional parameter validation for LoadTable Implemented additional parameter validation for the LoadTable operator. The length of the input strings SignatureString, OemIdString, and OemTableId are now checked for maximum lengths. http://www.acpica.org/bugzilla/show_bug.cgi?id=582 Signed-off-by: Lin Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/executer/exconfig.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index b9543a7f5d21..3370aad3ee14 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -138,6 +138,14 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, ACPI_FUNCTION_TRACE(ex_load_table_op); + /* Validate lengths for the signature_string, OEMIDString, OEMtable_iD */ + + if ((operand[0]->string.length > ACPI_NAME_SIZE) || + (operand[1]->string.length > ACPI_OEM_ID_SIZE) || + (operand[2]->string.length > ACPI_OEM_TABLE_ID_SIZE)) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + /* Find the ACPI table in the RSDT/XSDT */ status = acpi_tb_find_table(operand[0]->string.pointer, -- cgit v1.2.2 From 39adb11e56d8eef6169aeae38f65df26883ff49c Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:40 +0400 Subject: ACPICA: Update version to 20071019 Update version to 20071019. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- include/acpi/acconfig.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index 65815009127a..a2d4c877b1ac 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -63,7 +63,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20070919 +#define ACPI_CA_VERSION 0x20071019 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, -- cgit v1.2.2 From 1d18c05825c3f2b8933a7fc7f7528881e98deb04 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:40 +0400 Subject: ACPICA: Cosmetic changes only, no functional changes Lint changes, fix compiler warnings, etc. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/events/evmisc.c | 7 ++++--- drivers/acpi/events/evregion.c | 2 +- drivers/acpi/hardware/hwsleep.c | 14 ++++++++------ drivers/acpi/namespace/nsdump.c | 9 +++++---- drivers/acpi/namespace/nsload.c | 2 +- drivers/acpi/namespace/nsnames.c | 2 +- drivers/acpi/namespace/nsparse.c | 17 +++++++++++------ drivers/acpi/resources/rscalc.c | 6 +++--- drivers/acpi/resources/rsutils.c | 6 +++--- drivers/acpi/utilities/utalloc.c | 2 +- drivers/acpi/utilities/utcopy.c | 2 +- drivers/acpi/utilities/utdebug.c | 10 ++++------ drivers/acpi/utilities/utglobal.c | 2 +- 13 files changed, 44 insertions(+), 37 deletions(-) diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c index d075062f5b89..4e7a13afe80c 100644 --- a/drivers/acpi/events/evmisc.c +++ b/drivers/acpi/events/evmisc.c @@ -349,9 +349,10 @@ acpi_status acpi_ev_init_global_lock_handler(void) ACPI_FUNCTION_TRACE(ev_init_global_lock_handler); - status = - acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, - (struct acpi_table_header **)&facs); + status = acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, + ACPI_CAST_INDIRECT_PTR(struct + acpi_table_header, + &facs)); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c index 58ad09725dd2..03624e94778e 100644 --- a/drivers/acpi/events/evregion.c +++ b/drivers/acpi/events/evregion.c @@ -394,7 +394,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", ®ion_obj->region.handler->address_space, handler, - ACPI_FORMAT_UINT64(address), + ACPI_FORMAT_NATIVE_UINT(address), acpi_ut_get_region_name(region_obj->region. space_id))); diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c index 4290e0193097..202f11af3689 100644 --- a/drivers/acpi/hardware/hwsleep.c +++ b/drivers/acpi/hardware/hwsleep.c @@ -70,9 +70,10 @@ acpi_set_firmware_waking_vector(acpi_physical_address physical_address) /* Get the FACS */ - status = - acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, - (struct acpi_table_header **)&facs); + status = acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, + ACPI_CAST_INDIRECT_PTR(struct + acpi_table_header, + &facs)); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -124,9 +125,10 @@ acpi_get_firmware_waking_vector(acpi_physical_address * physical_address) /* Get the FACS */ - status = - acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, - (struct acpi_table_header **)&facs); + status = acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, + ACPI_CAST_INDIRECT_PTR(struct + acpi_table_header, + &facs)); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c index 1fc4f86676e1..3068e20911f4 100644 --- a/drivers/acpi/namespace/nsdump.c +++ b/drivers/acpi/namespace/nsdump.c @@ -249,7 +249,9 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, acpi_os_printf("ID %X Len %.4X Addr %p\n", obj_desc->processor.proc_id, obj_desc->processor.length, - (char *)obj_desc->processor.address); + ACPI_CAST_PTR(void, + obj_desc->processor. + address)); break; case ACPI_TYPE_DEVICE: @@ -320,9 +322,8 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, space_id)); if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { acpi_os_printf(" Addr %8.8X%8.8X Len %.4X\n", - ACPI_FORMAT_UINT64(obj_desc-> - region. - address), + ACPI_FORMAT_NATIVE_UINT + (obj_desc->region.address), obj_desc->region.length); } else { acpi_os_printf diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c index 545010dfd835..1bfcb6f3f44f 100644 --- a/drivers/acpi/namespace/nsload.c +++ b/drivers/acpi/namespace/nsload.c @@ -111,7 +111,7 @@ acpi_ns_load_table(acpi_native_uint table_index, if (ACPI_SUCCESS(status)) { acpi_tb_set_table_loaded_flag(table_index, TRUE); } else { - acpi_tb_release_owner_id(table_index); + (void)acpi_tb_release_owner_id(table_index); } unlock: diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c index e14a1412656b..ba1a4f00ba12 100644 --- a/drivers/acpi/namespace/nsnames.c +++ b/drivers/acpi/namespace/nsnames.c @@ -182,7 +182,7 @@ acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node) while (next_node && (next_node != acpi_gbl_root_node)) { if (ACPI_GET_DESCRIPTOR_TYPE(next_node) != ACPI_DESC_TYPE_NAMED) { ACPI_ERROR((AE_INFO, - "Invalid NS Node (%X) while traversing path", + "Invalid NS Node (%p) while traversing path", next_node)); return 0; } diff --git a/drivers/acpi/namespace/nsparse.c b/drivers/acpi/namespace/nsparse.c index 86bd6e5920c7..f260b6941c13 100644 --- a/drivers/acpi/namespace/nsparse.c +++ b/drivers/acpi/namespace/nsparse.c @@ -112,21 +112,25 @@ acpi_ns_one_complete_parse(acpi_native_uint pass_number, aml_start = (u8 *) table + sizeof(struct acpi_table_header); aml_length = table->length - sizeof(struct acpi_table_header); status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL, - aml_start, aml_length, NULL, - (u8) pass_number); + aml_start, (u32) aml_length, + NULL, (u8) pass_number); } if (ACPI_FAILURE(status)) { acpi_ds_delete_walk_state(walk_state); - acpi_ps_delete_parse_tree(parse_root); - return_ACPI_STATUS(status); + goto cleanup; } /* start_node is the default location to load the table */ if (start_node && start_node != acpi_gbl_root_node) { - acpi_ds_scope_stack_push(start_node, ACPI_TYPE_METHOD, - walk_state); + status = + acpi_ds_scope_stack_push(start_node, ACPI_TYPE_METHOD, + walk_state); + if (ACPI_FAILURE(status)) { + acpi_ds_delete_walk_state(walk_state); + goto cleanup; + } } /* Parse the AML */ @@ -135,6 +139,7 @@ acpi_ns_one_complete_parse(acpi_native_uint pass_number, (unsigned)pass_number)); status = acpi_ps_parse_aml(walk_state); + cleanup: acpi_ps_delete_parse_tree(parse_root); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c index 0dd2ce8a3475..dcc51e92ac92 100644 --- a/drivers/acpi/resources/rscalc.c +++ b/drivers/acpi/resources/rscalc.c @@ -73,7 +73,7 @@ acpi_rs_stream_option_length(u32 resource_length, u32 minimum_total_length); static u8 acpi_rs_count_set_bits(u16 bit_field) { - u8 bits_set; + acpi_native_uint bits_set; ACPI_FUNCTION_ENTRY(); @@ -81,10 +81,10 @@ static u8 acpi_rs_count_set_bits(u16 bit_field) /* Zero the least significant bit that is set */ - bit_field &= (bit_field - 1); + bit_field &= (u16) (bit_field - 1); } - return (bits_set); + return ((u8) bits_set); } /******************************************************************************* diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c index 11c0bd7b9cfd..935a4827e7ab 100644 --- a/drivers/acpi/resources/rsutils.c +++ b/drivers/acpi/resources/rsutils.c @@ -97,17 +97,17 @@ u8 acpi_rs_decode_bitmask(u16 mask, u8 * list) u16 acpi_rs_encode_bitmask(u8 * list, u8 count) { acpi_native_uint i; - u16 mask; + acpi_native_uint mask; ACPI_FUNCTION_ENTRY(); /* Encode the list into a single bitmask */ for (i = 0, mask = 0; i < count; i++) { - mask |= (0x0001 << list[i]); + mask |= (0x1 << list[i]); } - return (mask); + return ((u16) mask); } /******************************************************************************* diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c index 6e56d5f7c43a..181e66986fa9 100644 --- a/drivers/acpi/utilities/utalloc.c +++ b/drivers/acpi/utilities/utalloc.c @@ -147,7 +147,7 @@ acpi_status acpi_ut_delete_caches(void) if (acpi_gbl_display_final_mem_stats) { ACPI_STRCPY(buffer, "MEMORY"); - acpi_db_display_statistics(buffer); + (void)acpi_db_display_statistics(buffer); } #endif diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c index 879eaa10d3ae..b56953d2b59e 100644 --- a/drivers/acpi/utilities/utcopy.c +++ b/drivers/acpi/utilities/utcopy.c @@ -570,7 +570,7 @@ acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object, /* Truncate package and delete it */ - package_object->package.count = i; + package_object->package.count = (u32) i; package_elements[i] = NULL; acpi_ut_remove_reference(package_object); return_ACPI_STATUS(status); diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c index a9148677f037..2d6a78fb01cf 100644 --- a/drivers/acpi/utilities/utdebug.c +++ b/drivers/acpi/utilities/utdebug.c @@ -68,9 +68,9 @@ static const char *acpi_ut_trim_function_name(const char *function_name); void acpi_ut_init_stack_ptr_trace(void) { - u32 current_sp; + acpi_size current_sp; - acpi_gbl_entry_stack_pointer = ACPI_PTR_DIFF(¤t_sp, NULL); + acpi_gbl_entry_stack_pointer = ¤t_sp; } /******************************************************************************* @@ -89,10 +89,8 @@ void acpi_ut_track_stack_ptr(void) { acpi_size current_sp; - current_sp = ACPI_PTR_DIFF(¤t_sp, NULL); - - if (current_sp < acpi_gbl_lowest_stack_pointer) { - acpi_gbl_lowest_stack_pointer = current_sp; + if (¤t_sp < acpi_gbl_lowest_stack_pointer) { + acpi_gbl_lowest_stack_pointer = ¤t_sp; } if (acpi_gbl_nesting_level > acpi_gbl_deepest_nesting) { diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index 44425433075a..d2097ded262d 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c @@ -723,7 +723,7 @@ void acpi_ut_init_globals(void) acpi_gbl_root_node_struct.flags = ANOBJ_END_OF_PEER_LIST; #ifdef ACPI_DEBUG_OUTPUT - acpi_gbl_lowest_stack_pointer = ACPI_SIZE_MAX; + acpi_gbl_lowest_stack_pointer = ACPI_CAST_PTR(acpi_size, ACPI_SIZE_MAX); #endif #ifdef ACPI_DBG_TRACK_ALLOCATIONS -- cgit v1.2.2 From b7f9f04228eae2cf5adc2ffeb494d4970a8dd8a5 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:40 +0400 Subject: ACPICA: Cosmetic changes only, no functional changes Lint changes, fix compiler warnings, etc. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/dispatcher/dsmethod.c | 38 +++++++++++++++++--------------------- drivers/acpi/dispatcher/dsobject.c | 4 +++- drivers/acpi/dispatcher/dsopcode.c | 2 +- drivers/acpi/dispatcher/dsutils.c | 10 ++++------ drivers/acpi/dispatcher/dswstate.c | 6 +++--- drivers/acpi/executer/exconfig.c | 10 +++++----- drivers/acpi/executer/exdump.c | 10 ++++++++-- drivers/acpi/executer/exfldio.c | 3 ++- drivers/acpi/executer/exregion.c | 8 +++++--- drivers/acpi/executer/exstore.c | 6 ++++-- drivers/acpi/executer/exsystem.c | 1 - drivers/acpi/executer/exutils.c | 1 - drivers/acpi/parser/psopcode.c | 3 ++- include/acpi/acglobal.h | 8 +++----- include/acpi/acmacros.h | 10 ++++++++++ include/acpi/actypes.h | 2 ++ 16 files changed, 69 insertions(+), 53 deletions(-) diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index 3db651c7f582..7a99740248c7 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c @@ -42,7 +42,6 @@ */ #include -#include #include #include #include @@ -102,7 +101,7 @@ acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state) walk_state->opcode, walk_state->aml_offset, NULL); - (void)acpi_ex_enter_interpreter(); + acpi_ex_enter_interpreter(); } #ifdef ACPI_DISASSEMBLER if (ACPI_FAILURE(status)) { @@ -535,7 +534,6 @@ void acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, struct acpi_walk_state *walk_state) { - acpi_status status; ACPI_FUNCTION_TRACE_PTR(ds_terminate_control_method, walk_state); @@ -550,29 +548,27 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, /* Delete all arguments and locals */ acpi_ds_method_data_delete_all(walk_state); - } - /* - * If method is serialized, release the mutex and restore the - * current sync level for this thread - */ - if (method_desc->method.mutex) { + /* + * If method is serialized, release the mutex and restore the + * current sync level for this thread + */ + if (method_desc->method.mutex) { - /* Acquisition Depth handles recursive calls */ + /* Acquisition Depth handles recursive calls */ - method_desc->method.mutex->mutex.acquisition_depth--; - if (!method_desc->method.mutex->mutex.acquisition_depth) { - walk_state->thread->current_sync_level = - method_desc->method.mutex->mutex. - original_sync_level; + method_desc->method.mutex->mutex.acquisition_depth--; + if (!method_desc->method.mutex->mutex.acquisition_depth) { + walk_state->thread->current_sync_level = + method_desc->method.mutex->mutex. + original_sync_level; - acpi_os_release_mutex(method_desc->method.mutex->mutex. - os_mutex); - method_desc->method.mutex->mutex.thread_id = 0; + acpi_os_release_mutex(method_desc->method. + mutex->mutex.os_mutex); + method_desc->method.mutex->mutex.thread_id = 0; + } } - } - if (walk_state) { /* * Delete any namespace objects created anywhere within * the namespace by the execution of this method @@ -613,7 +609,7 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, */ if ((method_desc->method.method_flags & AML_METHOD_SERIALIZED) && (!method_desc->method.mutex)) { - status = acpi_ds_create_method_mutex(method_desc); + (void)acpi_ds_create_method_mutex(method_desc); } /* No more threads, we can free the owner_id */ diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c index 7556d919bf8b..58d4d91c8e97 100644 --- a/drivers/acpi/dispatcher/dsobject.c +++ b/drivers/acpi/dispatcher/dsobject.c @@ -157,7 +157,9 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, * will remain as named references. This behavior is not described * in the ACPI spec, but it appears to be an oversight. */ - obj_desc = (union acpi_operand_object *)op->common.node; + obj_desc = + ACPI_CAST_PTR(union acpi_operand_object, + op->common.node); status = acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c index 0c4630dc09f3..f0847eed5f3a 100644 --- a/drivers/acpi/dispatcher/dsopcode.c +++ b/drivers/acpi/dispatcher/dsopcode.c @@ -770,7 +770,7 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", obj_desc, - ACPI_FORMAT_UINT64(obj_desc->region.address), + ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address), obj_desc->region.length)); /* Now the address and length are valid for this opregion */ diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c index 36518b4a79c2..97d01dcdc972 100644 --- a/drivers/acpi/dispatcher/dsutils.c +++ b/drivers/acpi/dispatcher/dsutils.c @@ -700,10 +700,9 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state, acpi_status status = AE_OK; union acpi_parse_object *arg; union acpi_parse_object *arguments[ACPI_OBJ_NUM_OPERANDS]; - u8 arg_count = 0; - u8 count = 0; - u8 index = walk_state->num_operands; - u8 i; + u32 arg_count = 0; + u32 index = walk_state->num_operands; + u32 i; ACPI_FUNCTION_TRACE_PTR(ds_create_operands, first_arg); @@ -734,14 +733,13 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state, /* Force the filling of the operand stack in inverse order */ - walk_state->operand_index = index; + walk_state->operand_index = (u8) index; status = acpi_ds_create_operand(walk_state, arg, index); if (ACPI_FAILURE(status)) { goto cleanup; } - count++; index--; ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c index 698d2e1c219e..4c402be3c74a 100644 --- a/drivers/acpi/dispatcher/dswstate.c +++ b/drivers/acpi/dispatcher/dswstate.c @@ -220,7 +220,7 @@ static acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *walk_state) /* Check for stack overflow */ - if ((walk_state->result_size + ACPI_RESULTS_FRAME_OBJ_NUM) > + if (((u32) walk_state->result_size + ACPI_RESULTS_FRAME_OBJ_NUM) > ACPI_RESULTS_OBJ_NUM_MAX) { ACPI_ERROR((AE_INFO, "Result stack overflow: State=%p Num=%X", walk_state, walk_state->result_size)); @@ -400,7 +400,7 @@ void acpi_ds_obj_stack_pop_and_delete(u32 pop_count, struct acpi_walk_state *walk_state) { - u32 i; + acpi_native_int i; union acpi_operand_object *obj_desc; ACPI_FUNCTION_NAME(ds_obj_stack_pop_and_delete); @@ -409,7 +409,7 @@ acpi_ds_obj_stack_pop_and_delete(u32 pop_count, return; } - for (i = (pop_count - 1); i >= 0; i--) { + for (i = (acpi_native_int) (pop_count - 1); i >= 0; i--) { if (walk_state->num_operands == 0) { return; } diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index 3370aad3ee14..52b1e95837fa 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -45,7 +45,6 @@ #include #include #include -#include #include #include @@ -341,9 +340,10 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, /* Validate checksum here. It won't get validated in tb_add_table */ - status = acpi_tb_verify_checksum((struct acpi_table_header *) - obj_desc->buffer.pointer, - length); + status = + acpi_tb_verify_checksum(ACPI_CAST_PTR + (struct acpi_table_header, + obj_desc->buffer.pointer), length); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -468,7 +468,7 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) * (Offset contains the table_id) */ acpi_tb_delete_namespace_by_owner(table_index); - acpi_tb_release_owner_id(table_index); + (void)acpi_tb_release_owner_id(table_index); acpi_tb_set_table_loaded_flag(table_index, FALSE); diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c index fcb1da0d1de7..e48d91634295 100644 --- a/drivers/acpi/executer/exdump.c +++ b/drivers/acpi/executer/exdump.c @@ -506,6 +506,12 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) obj_desc->reference.object); break; + case AML_LOAD_OP: + + acpi_os_printf("Reference: [DdbHandle] TableIndex %p\n", + obj_desc->reference.object); + break; + case AML_REF_OF_OP: acpi_os_printf("Reference: (RefOf) %p\n", @@ -631,8 +637,8 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) acpi_os_printf("\n"); } else { acpi_os_printf(" base %8.8X%8.8X Length %X\n", - ACPI_FORMAT_UINT64(obj_desc->region. - address), + ACPI_FORMAT_NATIVE_UINT(obj_desc->region. + address), obj_desc->region.length); } break; diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c index 65a48b6170ee..1ece1c3fc375 100644 --- a/drivers/acpi/executer/exfldio.c +++ b/drivers/acpi/executer/exfldio.c @@ -263,7 +263,8 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc, rgn_desc->region.space_id, obj_desc->common_field.access_byte_width, obj_desc->common_field.base_byte_offset, - field_datum_byte_offset, (void *)address)); + field_datum_byte_offset, ACPI_CAST_PTR(void, + address))); /* Invoke the appropriate address_space/op_region handler */ diff --git a/drivers/acpi/executer/exregion.c b/drivers/acpi/executer/exregion.c index 3f51b7e84a17..cbc67884454f 100644 --- a/drivers/acpi/executer/exregion.c +++ b/drivers/acpi/executer/exregion.c @@ -160,7 +160,7 @@ acpi_ex_system_memory_space_handler(u32 function, if (!mem_info->mapped_logical_address) { ACPI_ERROR((AE_INFO, "Could not map memory at %8.8X%8.8X, size %X", - ACPI_FORMAT_UINT64(address), + ACPI_FORMAT_NATIVE_UINT(address), (u32) window_size)); mem_info->mapped_length = 0; return_ACPI_STATUS(AE_NO_MEMORY); @@ -182,7 +182,8 @@ acpi_ex_system_memory_space_handler(u32 function, ACPI_DEBUG_PRINT((ACPI_DB_INFO, "System-Memory (width %d) R/W %d Address=%8.8X%8.8X\n", - bit_width, function, ACPI_FORMAT_UINT64(address))); + bit_width, function, + ACPI_FORMAT_NATIVE_UINT(address))); /* * Perform the memory read or write @@ -284,7 +285,8 @@ acpi_ex_system_io_space_handler(u32 function, ACPI_DEBUG_PRINT((ACPI_DB_INFO, "System-IO (width %d) R/W %d Address=%8.8X%8.8X\n", - bit_width, function, ACPI_FORMAT_UINT64(address))); + bit_width, function, + ACPI_FORMAT_NATIVE_UINT(address))); /* Decode the function parameter */ diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c index d860f9c6172c..2408122cb3b2 100644 --- a/drivers/acpi/executer/exstore.c +++ b/drivers/acpi/executer/exstore.c @@ -189,7 +189,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, if (source_desc->reference.opcode == AML_LOAD_OP) { /* Load and load_table */ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, - " Table OwnerId %X\n", + " Table OwnerId %p\n", source_desc->reference.object)); break; } @@ -213,7 +213,9 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, (source_desc->reference.node) != ACPI_DESC_TYPE_NAMED) { ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, - " %p - Not a valid namespace node\n")); + " %p - Not a valid namespace node\n", + source_desc->reference. + node)); } else { acpi_ex_do_debug_object((source_desc->reference. node)->object, diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c index 9460baff3032..a20a974f7fac 100644 --- a/drivers/acpi/executer/exsystem.c +++ b/drivers/acpi/executer/exsystem.c @@ -44,7 +44,6 @@ #include #include -#include #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exsystem") diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c index fd543ee547ae..1b93f4dded4c 100644 --- a/drivers/acpi/executer/exutils.c +++ b/drivers/acpi/executer/exutils.c @@ -61,7 +61,6 @@ #include #include #include -#include #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exutils") diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c index 3bf8105d6348..153621d0c464 100644 --- a/drivers/acpi/parser/psopcode.c +++ b/drivers/acpi/parser/psopcode.c @@ -49,7 +49,8 @@ #define _COMPONENT ACPI_PARSER ACPI_MODULE_NAME("psopcode") -const u8 acpi_gbl_argument_count[] = { 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 6 }; +static const u8 acpi_gbl_argument_count[] = + { 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 6 }; /******************************************************************************* * diff --git a/include/acpi/acglobal.h b/include/acpi/acglobal.h index 862468616217..86cff21d9568 100644 --- a/include/acpi/acglobal.h +++ b/include/acpi/acglobal.h @@ -267,8 +267,6 @@ extern char const *acpi_gbl_exception_names_ctrl[]; * ****************************************************************************/ -#define NUM_NS_TYPES ACPI_TYPE_INVALID+1 - #if !defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY) #define NUM_PREDEFINED_NAMES 10 #else @@ -279,7 +277,7 @@ ACPI_EXTERN struct acpi_namespace_node acpi_gbl_root_node_struct; ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_root_node; ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_fadt_gpe_device; -extern const u8 acpi_gbl_ns_properties[NUM_NS_TYPES]; +extern const u8 acpi_gbl_ns_properties[ACPI_NUM_NS_TYPES]; extern const struct acpi_predefined_names acpi_gbl_pre_defined_names[NUM_PREDEFINED_NAMES]; @@ -287,8 +285,8 @@ extern const struct acpi_predefined_names ACPI_EXTERN u32 acpi_gbl_current_node_count; ACPI_EXTERN u32 acpi_gbl_current_node_size; ACPI_EXTERN u32 acpi_gbl_max_concurrent_node_count; -ACPI_EXTERN acpi_size acpi_gbl_entry_stack_pointer; -ACPI_EXTERN acpi_size acpi_gbl_lowest_stack_pointer; +ACPI_EXTERN acpi_size *acpi_gbl_entry_stack_pointer; +ACPI_EXTERN acpi_size *acpi_gbl_lowest_stack_pointer; ACPI_EXTERN u32 acpi_gbl_deepest_nesting; #endif diff --git a/include/acpi/acmacros.h b/include/acpi/acmacros.h index 401228d34f13..dc6a037311db 100644 --- a/include/acpi/acmacros.h +++ b/include/acpi/acmacros.h @@ -65,7 +65,11 @@ * Full 64-bit integer must be available on both 32-bit and 64-bit platforms */ #define ACPI_LODWORD(l) ((u32)(u64)(l)) +#define ACPI_HIDWORD(l) ((u16)((((u64)(l)) >> 32) & 0xFFFFFFFF)) + +#if 0 #define ACPI_HIDWORD(l) ((u32)(((*(struct uint64_struct *)(void *)(&l))).hi)) +#endif /* * printf() format helpers @@ -75,6 +79,12 @@ #define ACPI_FORMAT_UINT64(i) ACPI_HIDWORD(i),ACPI_LODWORD(i) +#if ACPI_MACHINE_WIDTH == 64 +#define ACPI_FORMAT_NATIVE_UINT(i) ACPI_FORMAT_UINT64(i) +#else +#define ACPI_FORMAT_NATIVE_UINT(i) 0, (i) +#endif + /* * Extract data using a pointer. Any more than a byte and we * get into potential aligment issues -- see the STORE macros below. diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 766178c6cc81..bb44700680a3 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -477,6 +477,8 @@ typedef u32 acpi_object_type; #define ACPI_TYPE_INVALID 0x1E #define ACPI_TYPE_NOT_FOUND 0xFF +#define ACPI_NUM_NS_TYPES (ACPI_TYPE_INVALID + 1) + /* * All I/O */ -- cgit v1.2.2 From f2d69559b31c368cfe3a51607d9cd5e8c0168875 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:40 +0400 Subject: ACPICA: Cleanup of debug output Improved output of object dump routine. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/executer/exdump.c | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c index e48d91634295..251d84ba79b3 100644 --- a/drivers/acpi/executer/exdump.c +++ b/drivers/acpi/executer/exdump.c @@ -514,8 +514,14 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) case AML_REF_OF_OP: - acpi_os_printf("Reference: (RefOf) %p\n", - obj_desc->reference.object); + acpi_os_printf("Reference: (RefOf) %p [%s]\n", + obj_desc->reference.object, + acpi_ut_get_type_name(((union + acpi_operand_object + *)obj_desc-> + reference. + object)->common. + type)); break; case AML_ARG_OP: @@ -556,8 +562,9 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) case AML_INT_NAMEPATH_OP: - acpi_os_printf("Reference.Node->Name %X\n", - obj_desc->reference.node->name.integer); + acpi_os_printf("Reference: Namepath %X [%4.4s]\n", + obj_desc->reference.node->name.integer, + obj_desc->reference.node->name.ascii); break; default: @@ -874,20 +881,32 @@ static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc) ret_buf.length = ACPI_ALLOCATE_LOCAL_BUFFER; if (obj_desc->reference.opcode == AML_INT_NAMEPATH_OP) { - acpi_os_printf("Named Object %p ", obj_desc->reference.node); + acpi_os_printf(" Named Object %p ", obj_desc->reference.node); status = acpi_ns_handle_to_pathname(obj_desc->reference.node, &ret_buf); if (ACPI_FAILURE(status)) { - acpi_os_printf("Could not convert name to pathname\n"); + acpi_os_printf(" Could not convert name to pathname\n"); } else { acpi_os_printf("%s\n", (char *)ret_buf.pointer); ACPI_FREE(ret_buf.pointer); } } else if (obj_desc->reference.object) { - acpi_os_printf("\nReferenced Object: %p\n", - obj_desc->reference.object); + if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == + ACPI_DESC_TYPE_OPERAND) { + acpi_os_printf(" Target: %p [%s]\n", + obj_desc->reference.object, + acpi_ut_get_type_name(((union + acpi_operand_object + *)obj_desc-> + reference. + object)->common. + type)); + } else { + acpi_os_printf(" Target: %p\n", + obj_desc->reference.object); + } } } @@ -973,7 +992,9 @@ acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc, case ACPI_TYPE_LOCAL_REFERENCE: - acpi_os_printf("[Object Reference] "); + acpi_os_printf("[Object Reference] %s", + (acpi_ps_get_opcode_info + (obj_desc->reference.opcode))->name); acpi_ex_dump_reference_obj(obj_desc); break; -- cgit v1.2.2 From b160987df7f49ee9c048a43b70ebae613a7e1437 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:40 +0400 Subject: ACPICA: Fixes a problem with control method references within packages Completes the package changes started with version 20071019. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/dispatcher/dswexec.c | 2 +- drivers/acpi/executer/exresnte.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c index 514b9d2eb3a7..6af4671e51a1 100644 --- a/drivers/acpi/dispatcher/dswexec.c +++ b/drivers/acpi/dispatcher/dswexec.c @@ -493,7 +493,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) op->common.node = (struct acpi_namespace_node *)op->asl.value. - arg->asl.node->object; + arg->asl.node; acpi_ut_add_reference(op->asl.value.arg->asl. node->object); return_ACPI_STATUS(AE_OK); diff --git a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c index 2b3a01cc4929..79a0d281f96b 100644 --- a/drivers/acpi/executer/exresnte.c +++ b/drivers/acpi/executer/exresnte.c @@ -116,9 +116,11 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, * Several object types require no further processing: * 1) Device/Thermal objects don't have a "real" subobject, return the Node * 2) Method locals and arguments have a pseudo-Node + * 3) 10/2007: Added method type to assist with Package construction. */ if ((entry_type == ACPI_TYPE_DEVICE) || (entry_type == ACPI_TYPE_THERMAL) || + (entry_type == ACPI_TYPE_METHOD) || (node->flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) { return_ACPI_STATUS(AE_OK); } @@ -214,7 +216,6 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, /* For these objects, just return the object attached to the Node */ case ACPI_TYPE_MUTEX: - case ACPI_TYPE_METHOD: case ACPI_TYPE_POWER: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_EVENT: -- cgit v1.2.2 From 1f549a240ccb2755066587e1e6ef9f74f485a46a Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:40 +0400 Subject: ACPICA: Fixed a problem with FromBCD and ToBCD with some compilers On some compilers, the ShortDivide function worked incorrectly, causing problems with the BCD functions with large input values. (Truncation from 64-bit to 32-bit occurred.) Internal http://www.acpica.org/bugzilla/show_bug.cgi?id=435 Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/utilities/utmath.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/utilities/utmath.c b/drivers/acpi/utilities/utmath.c index 0c56a0d20b29..16dbf665927b 100644 --- a/drivers/acpi/utilities/utmath.c +++ b/drivers/acpi/utilities/utmath.c @@ -276,7 +276,7 @@ acpi_ut_short_divide(acpi_integer in_dividend, *out_quotient = in_dividend / divisor; } if (out_remainder) { - *out_remainder = (u32) in_dividend % divisor; + *out_remainder = (u32) (in_dividend % divisor); } return_ACPI_STATUS(AE_OK); -- cgit v1.2.2 From e5bcc811f78f294e7be8a0721b3fb513028c5af4 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Thu, 10 Apr 2008 19:06:41 +0400 Subject: ACPICA: Fixed a problem with Index references passed as method arguments References passed as arguments to control methods were dereferenced immediately (before control was passed to the called method). The references are now correctly passed directly to the called method. http://bugzilla.kernel.org/show_bug.cgi?id=5389 Signed-off-by: Lin Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/executer/exresolv.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c index 74ab220a5924..795ec8c7363c 100644 --- a/drivers/acpi/executer/exresolv.c +++ b/drivers/acpi/executer/exresolv.c @@ -194,6 +194,12 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, case ACPI_TYPE_PACKAGE: + /* If method call - leave the Reference on the stack */ + + if (walk_state->opcode == AML_INT_METHODCALL_OP) { + break; + } + obj_desc = *stack_desc->reference.where; if (obj_desc) { /* @@ -210,7 +216,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, * the package, can't dereference it */ ACPI_ERROR((AE_INFO, - "Attempt to deref an Index to NULL pkg element Idx=%p", + "Attempt to dereference an Index to NULL package element Idx=%p", stack_desc)); status = AE_AML_UNINITIALIZED_ELEMENT; } @@ -221,7 +227,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, /* Invalid reference object */ ACPI_ERROR((AE_INFO, - "Unknown TargetType %X in Index/Reference obj %p", + "Unknown TargetType %X in Index/Reference object %p", stack_desc->reference.target_type, stack_desc)); status = AE_AML_INTERNAL; -- cgit v1.2.2 From 1cb2ef6606e0abd8565f66b5f95267de1b390694 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Thu, 10 Apr 2008 19:06:41 +0400 Subject: ACPICA: Fixed a problem with CopyObject used in conjunction with the Index operator The reference was incorrectly dereferenced before the copy. The reference is now correctly copied. http://bugzilla.kernel.org/show_bug.cgi?id=5391 Signed-off-by: Lin Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/executer/exresnte.c | 7 +++---- drivers/acpi/executer/exresolv.c | 16 ++++++++++------ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c index 79a0d281f96b..42c8a0f8894c 100644 --- a/drivers/acpi/executer/exresnte.c +++ b/drivers/acpi/executer/exresnte.c @@ -239,13 +239,12 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, case ACPI_TYPE_LOCAL_REFERENCE: switch (source_desc->reference.opcode) { - case AML_LOAD_OP: + case AML_LOAD_OP: /* This is a ddb_handle */ + case AML_REF_OF_OP: + case AML_INDEX_OP: - /* This is a ddb_handle */ /* Return an additional reference to the object */ - case AML_REF_OF_OP: - obj_desc = source_desc; acpi_ut_add_reference(obj_desc); break; diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c index 795ec8c7363c..9c3cdf61dc34 100644 --- a/drivers/acpi/executer/exresolv.c +++ b/drivers/acpi/executer/exresolv.c @@ -189,21 +189,25 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, switch (stack_desc->reference.target_type) { case ACPI_TYPE_BUFFER_FIELD: - /* Just return - leave the Reference on the stack */ + /* Just return - do not dereference */ break; case ACPI_TYPE_PACKAGE: - /* If method call - leave the Reference on the stack */ + /* If method call or copy_object - do not dereference */ - if (walk_state->opcode == AML_INT_METHODCALL_OP) { + if ((walk_state->opcode == + AML_INT_METHODCALL_OP) + || (walk_state->opcode == AML_COPY_OP)) { break; } + /* Otherwise, dereference the package_index to a package element */ + obj_desc = *stack_desc->reference.where; if (obj_desc) { /* - * Valid obj descriptor, copy pointer to return value + * Valid object descriptor, copy pointer to return value * (i.e., dereference the package index) * Delete the ref object, increment the returned object */ @@ -212,7 +216,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, *stack_ptr = obj_desc; } else { /* - * A NULL object descriptor means an unitialized element of + * A NULL object descriptor means an uninitialized element of * the package, can't dereference it */ ACPI_ERROR((AE_INFO, @@ -239,7 +243,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, case AML_DEBUG_OP: case AML_LOAD_OP: - /* Just leave the object as-is */ + /* Just leave the object as-is, do not dereference */ break; -- cgit v1.2.2 From 8a2e71a82375aa2aef571d5fa9064ba67c8856a5 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:41 +0400 Subject: ACPICA: Update version to 20071114 Update version to 20071114. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- include/acpi/acconfig.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index a2d4c877b1ac..c21e12d165fe 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -63,7 +63,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20071019 +#define ACPI_CA_VERSION 0x20071114 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, -- cgit v1.2.2 From 549f46044e1e207a2cbfdfb3f9a0d3fd5fd4105e Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:41 +0400 Subject: ACPICA: Fixed a problem with AcpiGetDevices where the search of a branch of the device tree could be terminated prematurely In accordance with the ACPI specification, the search is terminated if a device is both not present and not functional (instead of just not present.) Yakui Zhao. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/namespace/nsxfeval.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c index b92133faf5b7..cd97c80eb8ee 100644 --- a/drivers/acpi/namespace/nsxfeval.c +++ b/drivers/acpi/namespace/nsxfeval.c @@ -467,10 +467,13 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, return (AE_CTRL_DEPTH); } - if (!(flags & ACPI_STA_DEVICE_PRESENT)) { - - /* Don't examine children of the device if not present */ - + if (!(flags & ACPI_STA_DEVICE_PRESENT) && + !(flags & ACPI_STA_DEVICE_FUNCTIONING)) { + /* + * Don't examine the children of the device only when the + * device is neither present nor functional. See ACPI spec, + * description of _STA for more information. + */ return (AE_CTRL_DEPTH); } @@ -539,7 +542,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, * value is returned to the caller. * * This is a wrapper for walk_namespace, but the callback performs - * additional filtering. Please see acpi_get_device_callback. + * additional filtering. Please see acpi_ns_get_device_callback. * ******************************************************************************/ -- cgit v1.2.2 From 9aa6169f471771324b476a90d9392daa06d63a2d Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:41 +0400 Subject: ACPICA: Fixed a problem with Index Fields where the Index register was incorrectly limited to a maximum of 32 bits Now any size may be used. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/executer/exfield.c | 37 ------------------------------------- drivers/acpi/executer/exfldio.c | 41 ++++++++++++++++++++++++++++++++++------- 2 files changed, 34 insertions(+), 44 deletions(-) diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c index da772cb91d7f..aef8db82570a 100644 --- a/drivers/acpi/executer/exfield.c +++ b/drivers/acpi/executer/exfield.c @@ -210,9 +210,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, { acpi_status status; u32 length; - u32 required_length; void *buffer; - void *new_buffer; union acpi_operand_object *buffer_desc; ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc); @@ -312,35 +310,6 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } - /* - * We must have a buffer that is at least as long as the field - * we are writing to. This is because individual fields are - * indivisible and partial writes are not supported -- as per - * the ACPI specification. - */ - new_buffer = NULL; - required_length = - ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length); - - if (length < required_length) { - - /* We need to create a new buffer */ - - new_buffer = ACPI_ALLOCATE_ZEROED(required_length); - if (!new_buffer) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* - * Copy the original data to the new buffer, starting - * at Byte zero. All unused (upper) bytes of the - * buffer will be 0. - */ - ACPI_MEMCPY((char *)new_buffer, (char *)buffer, length); - buffer = new_buffer; - length = required_length; - } - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n", source_desc, @@ -366,11 +335,5 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, status = acpi_ex_insert_into_field(obj_desc, buffer, length); acpi_ex_release_global_lock(obj_desc->common_field.field_flags); - /* Free temporary buffer if we used one */ - - if (new_buffer) { - ACPI_FREE(new_buffer); - } - return_ACPI_STATUS(status); } diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c index 1ece1c3fc375..ae402949c357 100644 --- a/drivers/acpi/executer/exfldio.c +++ b/drivers/acpi/executer/exfldio.c @@ -806,18 +806,39 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, u32 datum_count; u32 field_datum_count; u32 i; + u32 required_length; + void *new_buffer; ACPI_FUNCTION_TRACE(ex_insert_into_field); /* Validate input buffer */ - if (buffer_length < - ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) { - ACPI_ERROR((AE_INFO, - "Field size %X (bits) is too large for buffer (%X)", - obj_desc->common_field.bit_length, buffer_length)); + new_buffer = NULL; + required_length = + ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length); + /* + * We must have a buffer that is at least as long as the field + * we are writing to. This is because individual fields are + * indivisible and partial writes are not supported -- as per + * the ACPI specification. + */ + if (buffer_length < required_length) { - return_ACPI_STATUS(AE_BUFFER_OVERFLOW); + /* We need to create a new buffer */ + + new_buffer = ACPI_ALLOCATE_ZEROED(required_length); + if (!new_buffer) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* + * Copy the original data to the new buffer, starting + * at Byte zero. All unused (upper) bytes of the + * buffer will be 0. + */ + ACPI_MEMCPY((char *)new_buffer, (char *)buffer, buffer_length); + buffer = new_buffer; + buffer_length = required_length; } /* @@ -867,7 +888,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, merged_datum, field_offset); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + goto exit; } field_offset += obj_desc->common_field.access_byte_width; @@ -925,5 +946,11 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, mask, merged_datum, field_offset); + exit: + /* Free temporary buffer if we used one */ + + if (new_buffer) { + ACPI_FREE(new_buffer); + } return_ACPI_STATUS(status); } -- cgit v1.2.2 From 941f48bb465b0b291f8435b1e3de95b0975b84bc Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Thu, 10 Apr 2008 19:06:41 +0400 Subject: ACPICA: Implemented full support for deferred execution for the TermArg string arguments for DataTableRegion This enables forward references and full operand resolution for the three string arguments. Similar to OperationRegion deferred argument execution.) http://www.acpica.org/bugzilla/show_bug.cgi?id=430 Signed-off-by: Lin Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/dispatcher/dsopcode.c | 103 +++++++++++++++++++++++++++++++++++++ drivers/acpi/dispatcher/dswexec.c | 11 ++++ drivers/acpi/dispatcher/dswload.c | 29 +++++++---- drivers/acpi/executer/excreate.c | 95 ---------------------------------- drivers/acpi/executer/exmutex.c | 16 ++++++ drivers/acpi/parser/psloop.c | 6 ++- drivers/acpi/parser/psopcode.c | 4 +- include/acpi/acdispat.h | 4 ++ include/acpi/acinterp.h | 2 - 9 files changed, 160 insertions(+), 110 deletions(-) diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c index f0847eed5f3a..a3f29798d1d1 100644 --- a/drivers/acpi/dispatcher/dsopcode.c +++ b/drivers/acpi/dispatcher/dsopcode.c @@ -49,6 +49,7 @@ #include #include #include +#include #define _COMPONENT ACPI_DISPATCHER ACPI_MODULE_NAME("dsopcode") @@ -780,6 +781,108 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, return_ACPI_STATUS(status); } +/******************************************************************************* + * + * FUNCTION: acpi_ds_eval_table_region_operands + * + * PARAMETERS: walk_state - Current walk + * Op - A valid region Op object + * + * RETURN: Status + * + * DESCRIPTION: Get region address and length + * Called from acpi_ds_exec_end_op during data_table_region parse tree walk + * + ******************************************************************************/ + +acpi_status +acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, + union acpi_parse_object *op) +{ + acpi_status status; + union acpi_operand_object *obj_desc; + union acpi_operand_object **operand; + struct acpi_namespace_node *node; + union acpi_parse_object *next_op; + acpi_native_uint table_index; + struct acpi_table_header *table; + + ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op); + + /* + * This is where we evaluate the signature_string and oem_iDString + * and oem_table_iDString of the data_table_region declaration + */ + node = op->common.node; + + /* next_op points to signature_string op */ + + next_op = op->common.value.arg; + + /* + * Evaluate/create the signature_string and oem_iDString + * and oem_table_iDString operands + */ + status = acpi_ds_create_operands(walk_state, next_op); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Resolve the signature_string and oem_iDString + * and oem_table_iDString operands + */ + status = acpi_ex_resolve_operands(op->common.aml_opcode, + ACPI_WALK_OPERANDS, walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE, + acpi_ps_get_opcode_name(op->common.aml_opcode), + 1, "after AcpiExResolveOperands"); + + operand = &walk_state->operands[0]; + + /* Find the ACPI table */ + + status = acpi_tb_find_table(operand[0]->string.pointer, + operand[1]->string.pointer, + operand[2]->string.pointer, &table_index); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + acpi_ut_remove_reference(operand[0]); + acpi_ut_remove_reference(operand[1]); + acpi_ut_remove_reference(operand[2]); + + status = acpi_get_table_by_index(table_index, &table); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + obj_desc = acpi_ns_get_attached_object(node); + if (!obj_desc) { + return_ACPI_STATUS(AE_NOT_EXIST); + } + + obj_desc->region.address = + (acpi_physical_address) ACPI_TO_INTEGER(table); + obj_desc->region.length = table->length; + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", + obj_desc, + ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address), + obj_desc->region.length)); + + /* Now the address and length are valid for this opregion */ + + obj_desc->region.flags |= AOPOBJ_DATA_VALID; + + return_ACPI_STATUS(status); +} + /******************************************************************************* * * FUNCTION: acpi_ds_eval_data_object_operands diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c index 6af4671e51a1..8ba4bb36af9f 100644 --- a/drivers/acpi/dispatcher/dswexec.c +++ b/drivers/acpi/dispatcher/dswexec.c @@ -641,6 +641,17 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) if (ACPI_FAILURE(status)) { break; } + } else if (op->common.aml_opcode == AML_DATA_REGION_OP) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Executing DataTableRegion Strings Op=%p\n", + op)); + + status = + acpi_ds_eval_table_region_operands + (walk_state, op); + if (ACPI_FAILURE(status)) { + break; + } } break; diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c index 8ab9d1b29a4c..ec68c1df3932 100644 --- a/drivers/acpi/dispatcher/dswload.c +++ b/drivers/acpi/dispatcher/dswload.c @@ -443,6 +443,15 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state) if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } + } else if (op->common.aml_opcode == AML_DATA_REGION_OP) { + status = + acpi_ex_create_region(op->named.data, + op->named.length, + REGION_DATA_TABLE, + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } } } #endif @@ -823,6 +832,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) struct acpi_namespace_node *new_node; #ifndef ACPI_NO_METHOD_EXECUTION u32 i; + u8 region_space; #endif ACPI_FUNCTION_TRACE(ds_load2_end_op); @@ -1003,11 +1013,6 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) status = acpi_ex_create_event(walk_state); break; - case AML_DATA_REGION_OP: - - status = acpi_ex_create_table_region(walk_state); - break; - case AML_ALIAS_OP: status = acpi_ex_create_alias(walk_state); @@ -1035,6 +1040,15 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) switch (op->common.aml_opcode) { #ifndef ACPI_NO_METHOD_EXECUTION case AML_REGION_OP: + case AML_DATA_REGION_OP: + + if (op->common.aml_opcode == AML_REGION_OP) { + region_space = (acpi_adr_space_type) + ((op->common.value.arg)->common.value. + integer); + } else { + region_space = REGION_DATA_TABLE; + } /* * If we are executing a method, initialize the region @@ -1043,10 +1057,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) status = acpi_ex_create_region(op->named.data, op->named.length, - (acpi_adr_space_type) - ((op->common.value. - arg)->common.value. - integer), + region_space, walk_state); if (ACPI_FAILURE(status)) { return (status); diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c index b3914395851b..0396bd4819f1 100644 --- a/drivers/acpi/executer/excreate.c +++ b/drivers/acpi/executer/excreate.c @@ -350,101 +350,6 @@ acpi_ex_create_region(u8 * aml_start, return_ACPI_STATUS(status); } -/******************************************************************************* - * - * FUNCTION: acpi_ex_create_table_region - * - * PARAMETERS: walk_state - Current state - * - * RETURN: Status - * - * DESCRIPTION: Create a new data_table_region object - * - ******************************************************************************/ - -acpi_status acpi_ex_create_table_region(struct acpi_walk_state *walk_state) -{ - acpi_status status; - union acpi_operand_object **operand = &walk_state->operands[0]; - union acpi_operand_object *obj_desc; - struct acpi_namespace_node *node; - union acpi_operand_object *region_obj2; - acpi_native_uint table_index; - struct acpi_table_header *table; - - ACPI_FUNCTION_TRACE(ex_create_table_region); - - /* Get the Node from the object stack */ - - node = walk_state->op->common.node; - - /* - * If the region object is already attached to this node, - * just return - */ - if (acpi_ns_get_attached_object(node)) { - return_ACPI_STATUS(AE_OK); - } - - /* Find the ACPI table */ - - status = acpi_tb_find_table(operand[1]->string.pointer, - operand[2]->string.pointer, - operand[3]->string.pointer, &table_index); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Create the region descriptor */ - - obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION); - if (!obj_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - region_obj2 = obj_desc->common.next_object; - region_obj2->extra.region_context = NULL; - - status = acpi_get_table_by_index(table_index, &table); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Init the region from the operands */ - - obj_desc->region.space_id = REGION_DATA_TABLE; - obj_desc->region.address = - (acpi_physical_address) ACPI_TO_INTEGER(table); - obj_desc->region.length = table->length; - obj_desc->region.node = node; - obj_desc->region.flags = AOPOBJ_DATA_VALID; - - /* Install the new region object in the parent Node */ - - status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_REGION); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - status = acpi_ev_initialize_region(obj_desc, FALSE); - if (ACPI_FAILURE(status)) { - if (status == AE_NOT_EXIST) { - status = AE_OK; - } else { - goto cleanup; - } - } - - obj_desc->region.flags |= AOPOBJ_SETUP_COMPLETE; - - cleanup: - - /* Remove local reference to the object */ - - acpi_ut_remove_reference(obj_desc); - return_ACPI_STATUS(status); -} - /******************************************************************************* * * FUNCTION: acpi_ex_create_processor diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c index b8d035c00b61..7c70938eef89 100644 --- a/drivers/acpi/executer/exmutex.c +++ b/drivers/acpi/executer/exmutex.c @@ -85,6 +85,7 @@ void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc) } else { thread->acquired_mutex_list = obj_desc->mutex.next; } + return; } /******************************************************************************* @@ -298,6 +299,17 @@ acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc) return (AE_NOT_ACQUIRED); } + /* No obj_desc->Mutex.owner_thread for Global Lock */ + + /* + * Mutex to be released must be at the head of acquired list to prevent + * deadlock. (The head of the list is the last mutex acquired.) + */ + if (obj_desc->mutex.owner_thread && + (obj_desc != obj_desc->mutex.owner_thread->acquired_mutex_list)) { + return (AE_AML_MUTEX_ORDER); + } + /* Match multiple Acquires with multiple Releases */ obj_desc->mutex.acquisition_depth--; @@ -403,6 +415,9 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, } status = acpi_ex_release_mutex_object(obj_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } if (obj_desc->mutex.acquisition_depth == 0) { @@ -411,6 +426,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, walk_state->thread->current_sync_level = obj_desc->mutex.original_sync_level; } + return_ACPI_STATUS(status); } diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c index 4348b0530398..a079975f671f 100644 --- a/drivers/acpi/parser/psloop.c +++ b/drivers/acpi/parser/psloop.c @@ -242,7 +242,8 @@ acpi_ps_build_named_op(struct acpi_walk_state *walk_state, acpi_ps_append_arg(*op, unnamed_op->common.value.arg); acpi_gbl_depth++; - if ((*op)->common.aml_opcode == AML_REGION_OP) { + if ((*op)->common.aml_opcode == AML_REGION_OP || + (*op)->common.aml_opcode == AML_DATA_REGION_OP) { /* * Defer final parsing of an operation_region body, because we don't * have enough info in the first pass to parse it correctly (i.e., @@ -1013,7 +1014,8 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) acpi_gbl_depth--; } - if (op->common.aml_opcode == AML_REGION_OP) { + if (op->common.aml_opcode == AML_REGION_OP || + op->common.aml_opcode == AML_DATA_REGION_OP) { /* * Skip parsing of control method or opregion body, * because we don't have enough info in the first pass diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c index 153621d0c464..b273a0a127e6 100644 --- a/drivers/acpi/parser/psopcode.c +++ b/drivers/acpi/parser/psopcode.c @@ -624,9 +624,9 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = { AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R), /* 7C */ ACPI_OP("DataTableRegion", ARGP_DATA_REGION_OP, ARGI_DATA_REGION_OP, ACPI_TYPE_REGION, - AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, + AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | - AML_NSNODE | AML_NAMED), + AML_NSNODE | AML_NAMED | AML_DEFER), /* 7D */ ACPI_OP("[EvalSubTree]", ARGP_SCOPE_OP, ARGI_SCOPE_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, diff --git a/include/acpi/acdispat.h b/include/acpi/acdispat.h index 3bffb4db4bce..d8dabe893973 100644 --- a/include/acpi/acdispat.h +++ b/include/acpi/acdispat.h @@ -67,6 +67,10 @@ acpi_status acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, union acpi_parse_object *op); +acpi_status +acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, + union acpi_parse_object *op); + acpi_status acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, union acpi_parse_object *op, diff --git a/include/acpi/acinterp.h b/include/acpi/acinterp.h index 92eb0141ac81..f4dd98fc96a3 100644 --- a/include/acpi/acinterp.h +++ b/include/acpi/acinterp.h @@ -215,8 +215,6 @@ acpi_ex_create_region(u8 * aml_start, u32 aml_length, u8 region_space, struct acpi_walk_state *walk_state); -acpi_status acpi_ex_create_table_region(struct acpi_walk_state *walk_state); - acpi_status acpi_ex_create_event(struct acpi_walk_state *walk_state); acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state); -- cgit v1.2.2 From 57345ee6b807d32e5eecf724a463378b80cc261c Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:41 +0400 Subject: ACPICA: Undo accidental checkin of not-fully-tested mutex changes Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/executer/exmutex.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c index 7c70938eef89..b8d035c00b61 100644 --- a/drivers/acpi/executer/exmutex.c +++ b/drivers/acpi/executer/exmutex.c @@ -85,7 +85,6 @@ void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc) } else { thread->acquired_mutex_list = obj_desc->mutex.next; } - return; } /******************************************************************************* @@ -299,17 +298,6 @@ acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc) return (AE_NOT_ACQUIRED); } - /* No obj_desc->Mutex.owner_thread for Global Lock */ - - /* - * Mutex to be released must be at the head of acquired list to prevent - * deadlock. (The head of the list is the last mutex acquired.) - */ - if (obj_desc->mutex.owner_thread && - (obj_desc != obj_desc->mutex.owner_thread->acquired_mutex_list)) { - return (AE_AML_MUTEX_ORDER); - } - /* Match multiple Acquires with multiple Releases */ obj_desc->mutex.acquisition_depth--; @@ -415,9 +403,6 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, } status = acpi_ex_release_mutex_object(obj_desc); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } if (obj_desc->mutex.acquisition_depth == 0) { @@ -426,7 +411,6 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, walk_state->thread->current_sync_level = obj_desc->mutex.original_sync_level; } - return_ACPI_STATUS(status); } -- cgit v1.2.2 From ef805d956320ffa36d068673d5c5eb2a7d13209b Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Thu, 10 Apr 2008 19:06:41 +0400 Subject: ACPICA: Implemented full argument resolution support for the BankValue argument to BankField Previously, only constants were supported, now any TermArg may be used. http://www.acpica.org/bugzilla/show_bug.cgi?id=387 http://www.acpica.org/bugzilla/show_bug.cgi?id=393 Signed-off-by: Lin Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/dispatcher/dsfield.c | 80 +++++++++++---------- drivers/acpi/dispatcher/dsopcode.c | 144 +++++++++++++++++++++++++++++++++++++ drivers/acpi/dispatcher/dsutils.c | 4 +- drivers/acpi/dispatcher/dswexec.c | 11 +++ drivers/acpi/executer/exprep.c | 15 ++++ drivers/acpi/namespace/nsinit.c | 10 +++ drivers/acpi/parser/psloop.c | 19 +++++ drivers/acpi/parser/psopcode.c | 5 +- drivers/acpi/parser/psparse.c | 2 + drivers/acpi/utilities/utdelete.c | 11 +++ drivers/acpi/utilities/utobject.c | 1 + include/acpi/acdispat.h | 7 ++ 12 files changed, 267 insertions(+), 42 deletions(-) diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c index f049639bac35..e87f6bfbfa5c 100644 --- a/drivers/acpi/dispatcher/dsfield.c +++ b/drivers/acpi/dispatcher/dsfield.c @@ -281,11 +281,17 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, arg->common.node = info->field_node; info->field_bit_length = arg->common.value.size; - /* Create and initialize an object for the new Field Node */ - - status = acpi_ex_prep_field_value(info); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + /* + * If there is no object attached to the node, this node was just created + * and we need to create the field object. Otherwise, this was a lookup + * of an existing node and we don't want to create the field object again. + */ + if (!acpi_ns_get_attached_object + (info->field_node)) { + status = acpi_ex_prep_field_value(info); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } } } @@ -399,9 +405,22 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, union acpi_parse_object *arg = NULL; struct acpi_namespace_node *node; u8 type = 0; + u32 flags; ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op); + /* + * During the load phase, we want to enter the name of the field into + * the namespace. During the execute phase (when we evaluate the bank_value + * operand), we want to lookup the name. + */ + if (walk_state->deferred_node) { + flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE; + } else { + flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | + ACPI_NS_ERROR_IF_FOUND; + } + switch (walk_state->opcode) { case AML_FIELD_OP: arg = acpi_ps_get_arg(op, 2); @@ -433,10 +452,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, status = acpi_ns_lookup(walk_state->scope_info, (char *)&arg->named.name, type, ACPI_IMODE_LOAD_PASS1, - ACPI_NS_NO_UPSEARCH | - ACPI_NS_DONT_OPEN_SCOPE | - ACPI_NS_ERROR_IF_FOUND, - walk_state, &node); + flags, walk_state, &node); if (ACPI_FAILURE(status)) { ACPI_ERROR_NAMESPACE((char *)&arg->named.name, status); @@ -466,7 +482,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, * * PARAMETERS: Op - Op containing the Field definition and args * region_node - Object for the containing Operation Region - * ` walk_state - Current method state + * walk_state - Current method state * * RETURN: Status * @@ -513,36 +529,13 @@ acpi_ds_create_bank_field(union acpi_parse_object *op, return_ACPI_STATUS(status); } - /* Third arg is the bank_value */ - - /* TBD: This arg is a term_arg, not a constant, and must be evaluated */ - + /* + * Third arg is the bank_value + * This arg is a term_arg, not a constant + * It will be evaluated later, by acpi_ds_eval_bank_field_operands + */ arg = arg->common.next; - /* Currently, only the following constants are supported */ - - switch (arg->common.aml_opcode) { - case AML_ZERO_OP: - info.bank_value = 0; - break; - - case AML_ONE_OP: - info.bank_value = 1; - break; - - case AML_BYTE_OP: - case AML_WORD_OP: - case AML_DWORD_OP: - case AML_QWORD_OP: - info.bank_value = (u32) arg->common.value.integer; - break; - - default: - info.bank_value = 0; - ACPI_ERROR((AE_INFO, - "Non-constant BankValue for BankField is not implemented")); - } - /* Fourth arg is the field flags */ arg = arg->common.next; @@ -553,8 +546,17 @@ acpi_ds_create_bank_field(union acpi_parse_object *op, info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD; info.region_node = region_node; - status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); + /* + * Use Info.data_register_node to store bank_field Op + * It's safe because data_register_node will never be used when create bank field + * We store aml_start and aml_length in the bank_field Op for late evaluation + * Used in acpi_ex_prep_field_value(Info) + * + * TBD: Or, should we add a field in struct acpi_create_field_info, like "void *ParentOp"? + */ + info.data_register_node = (struct acpi_namespace_node *)op; + status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c index a3f29798d1d1..35a7efdb5ad9 100644 --- a/drivers/acpi/dispatcher/dsopcode.c +++ b/drivers/acpi/dispatcher/dsopcode.c @@ -218,6 +218,50 @@ acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc) return_ACPI_STATUS(status); } +/******************************************************************************* + * + * FUNCTION: acpi_ds_get_bank_field_arguments + * + * PARAMETERS: obj_desc - A valid bank_field object + * + * RETURN: Status. + * + * DESCRIPTION: Get bank_field bank_value. This implements the late + * evaluation of these field attributes. + * + ******************************************************************************/ + +acpi_status +acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc) +{ + union acpi_operand_object *extra_desc; + struct acpi_namespace_node *node; + acpi_status status; + + ACPI_FUNCTION_TRACE_PTR(ds_get_bank_field_arguments, obj_desc); + + if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { + return_ACPI_STATUS(AE_OK); + } + + /* Get the AML pointer (method object) and bank_field node */ + + extra_desc = acpi_ns_get_secondary_object(obj_desc); + node = obj_desc->bank_field.node; + + ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname + (ACPI_TYPE_LOCAL_BANK_FIELD, node, NULL)); + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n", + acpi_ut_get_node_name(node))); + + /* Execute the AML code for the term_arg arguments */ + + status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node), + extra_desc->extra.aml_length, + extra_desc->extra.aml_start); + return_ACPI_STATUS(status); +} + /******************************************************************************* * * FUNCTION: acpi_ds_get_buffer_arguments @@ -985,6 +1029,106 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, return_ACPI_STATUS(status); } +/******************************************************************************* + * + * FUNCTION: acpi_ds_eval_bank_field_operands + * + * PARAMETERS: walk_state - Current walk + * Op - A valid bank_field Op object + * + * RETURN: Status + * + * DESCRIPTION: Get bank_field bank_value + * Called from acpi_ds_exec_end_op during bank_field parse tree walk + * + ******************************************************************************/ + +acpi_status +acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state, + union acpi_parse_object *op) +{ + acpi_status status; + union acpi_operand_object *obj_desc; + union acpi_operand_object *operand_desc; + struct acpi_namespace_node *node; + union acpi_parse_object *next_op; + union acpi_parse_object *arg; + + ACPI_FUNCTION_TRACE_PTR(ds_eval_bank_field_operands, op); + + /* + * This is where we evaluate the bank_value field of the + * bank_field declaration + */ + + /* next_op points to the op that holds the Region */ + + next_op = op->common.value.arg; + + /* next_op points to the op that holds the Bank Register */ + + next_op = next_op->common.next; + + /* next_op points to the op that holds the Bank Value */ + + next_op = next_op->common.next; + + /* + * Set proper index into operand stack for acpi_ds_obj_stack_push + * invoked inside acpi_ds_create_operand. + * + * We use walk_state->Operands[0] to store the evaluated bank_value + */ + walk_state->operand_index = 0; + + status = acpi_ds_create_operand(walk_state, next_op, 0); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + status = acpi_ex_resolve_to_value(&walk_state->operands[0], walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE, + acpi_ps_get_opcode_name(op->common.aml_opcode), + 1, "after AcpiExResolveOperands"); + + /* + * Get the bank_value operand and save it + * (at Top of stack) + */ + operand_desc = walk_state->operands[0]; + + /* Arg points to the start Bank Field */ + + arg = acpi_ps_get_arg(op, 4); + while (arg) { + + /* Ignore OFFSET and ACCESSAS terms here */ + + if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { + node = arg->common.node; + + obj_desc = acpi_ns_get_attached_object(node); + if (!obj_desc) { + return_ACPI_STATUS(AE_NOT_EXIST); + } + + obj_desc->bank_field.value = + (u32) operand_desc->integer.value; + } + + /* Move to next field in the list */ + + arg = arg->common.next; + } + + acpi_ut_remove_reference(operand_desc); + return_ACPI_STATUS(status); +} + /******************************************************************************* * * FUNCTION: acpi_ds_exec_begin_control_op diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c index 97d01dcdc972..f6c28d7b46c5 100644 --- a/drivers/acpi/dispatcher/dsutils.c +++ b/drivers/acpi/dispatcher/dsutils.c @@ -278,7 +278,9 @@ acpi_ds_is_result_used(union acpi_parse_object * op, AML_VAR_PACKAGE_OP) || (op->common.parent->common.aml_opcode == AML_BUFFER_OP) || (op->common.parent->common.aml_opcode == - AML_INT_EVAL_SUBTREE_OP)) { + AML_INT_EVAL_SUBTREE_OP) + || (op->common.parent->common.aml_opcode == + AML_BANK_FIELD_OP)) { /* * These opcodes allow term_arg(s) as operands and therefore * the operands can be method calls. The result is used. diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c index 8ba4bb36af9f..bfe4450fa588 100644 --- a/drivers/acpi/dispatcher/dswexec.c +++ b/drivers/acpi/dispatcher/dswexec.c @@ -652,6 +652,17 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) if (ACPI_FAILURE(status)) { break; } + } else if (op->common.aml_opcode == AML_BANK_FIELD_OP) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Executing BankField Op=%p\n", + op)); + + status = + acpi_ds_eval_bank_field_operands(walk_state, + op); + if (ACPI_FAILURE(status)) { + break; + } } break; diff --git a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c index efe5d4b461a4..6eb45bf355f1 100644 --- a/drivers/acpi/executer/exprep.c +++ b/drivers/acpi/executer/exprep.c @@ -412,6 +412,7 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc, acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) { union acpi_operand_object *obj_desc; + union acpi_operand_object *second_desc = NULL; u32 type; acpi_status status; @@ -494,6 +495,20 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) obj_desc->field.access_byte_width, obj_desc->bank_field.region_obj, obj_desc->bank_field.bank_obj)); + + /* + * Remember location in AML stream of the field unit + * opcode and operands -- since the bank_value + * operands must be evaluated. + */ + second_desc = obj_desc->common.next_object; + second_desc->extra.aml_start = + ((union acpi_parse_object *)(info->data_register_node))-> + named.data; + second_desc->extra.aml_length = + ((union acpi_parse_object *)(info->data_register_node))-> + named.length; + break; case ACPI_TYPE_LOCAL_INDEX_FIELD: diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c index 33db2241044e..72b32454ce3c 100644 --- a/drivers/acpi/namespace/nsinit.c +++ b/drivers/acpi/namespace/nsinit.c @@ -244,6 +244,10 @@ acpi_ns_init_one_object(acpi_handle obj_handle, info->field_count++; break; + case ACPI_TYPE_LOCAL_BANK_FIELD: + info->field_count++; + break; + case ACPI_TYPE_BUFFER: info->buffer_count++; break; @@ -287,6 +291,12 @@ acpi_ns_init_one_object(acpi_handle obj_handle, status = acpi_ds_get_buffer_field_arguments(obj_desc); break; + case ACPI_TYPE_LOCAL_BANK_FIELD: + + info->field_init++; + status = acpi_ds_get_bank_field_arguments(obj_desc); + break; + case ACPI_TYPE_BUFFER: info->buffer_init++; diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c index a079975f671f..a7c768860648 100644 --- a/drivers/acpi/parser/psloop.c +++ b/drivers/acpi/parser/psloop.c @@ -325,6 +325,15 @@ acpi_ps_create_op(struct acpi_walk_state *walk_state, op->named.length = 0; } + if (walk_state->opcode == AML_BANK_FIELD_OP) { + /* + * Backup to beginning of bank_field declaration + * body_length is unknown until we parse the body + */ + op->named.data = aml_op_start; + op->named.length = 0; + } + parent_scope = acpi_ps_get_parent_scope(&(walk_state->parser_state)); acpi_ps_append_arg(parent_scope, op); @@ -1040,6 +1049,16 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) (u32) (parser_state->aml - op->named.data); } + if (op->common.aml_opcode == AML_BANK_FIELD_OP) { + /* + * Backup to beginning of bank_field declaration + * + * body_length is unknown until we parse the body + */ + op->named.length = + (u32) (parser_state->aml - op->named.data); + } + /* This op complete, notify the dispatcher */ if (walk_state->ascending_callback != NULL) { diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c index b273a0a127e6..18ed59dd2a6e 100644 --- a/drivers/acpi/parser/psopcode.c +++ b/drivers/acpi/parser/psopcode.c @@ -520,9 +520,10 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = { AML_TYPE_NAMED_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD), /* 5F */ ACPI_OP("BankField", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP, - ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, + ACPI_TYPE_LOCAL_BANK_FIELD, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD), + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD | + AML_DEFER), /* Internal opcodes that map to invalid AML opcodes */ diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c index 1442e55c40d1..a8995ca52ee7 100644 --- a/drivers/acpi/parser/psparse.c +++ b/drivers/acpi/parser/psparse.c @@ -204,6 +204,8 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, AML_BUFFER_OP) || (op->common.parent->common.aml_opcode == AML_PACKAGE_OP) + || (op->common.parent->common.aml_opcode == + AML_BANK_FIELD_OP) || (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) { replacement_op = diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c index 6a763cd85f8c..f5b2f6a358b5 100644 --- a/drivers/acpi/utilities/utdelete.c +++ b/drivers/acpi/utilities/utdelete.c @@ -252,6 +252,17 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) } break; + case ACPI_TYPE_LOCAL_BANK_FIELD: + + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, + "***** Bank Field %p\n", object)); + + second_desc = acpi_ns_get_secondary_object(object); + if (second_desc) { + acpi_ut_delete_object_desc(second_desc); + } + break; + default: break; } diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c index e08b3fa6639f..1eccd3db876f 100644 --- a/drivers/acpi/utilities/utobject.c +++ b/drivers/acpi/utilities/utobject.c @@ -107,6 +107,7 @@ union acpi_operand_object *acpi_ut_create_internal_object_dbg(char *module_name, switch (type) { case ACPI_TYPE_REGION: case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: /* These types require a secondary object */ diff --git a/include/acpi/acdispat.h b/include/acpi/acdispat.h index d8dabe893973..a5b97f0f0133 100644 --- a/include/acpi/acdispat.h +++ b/include/acpi/acdispat.h @@ -53,6 +53,9 @@ acpi_status acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc); +acpi_status +acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc); + acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *rgn_desc); acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc); @@ -76,6 +79,10 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, union acpi_parse_object *op, union acpi_operand_object *obj_desc); +acpi_status +acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state, + union acpi_parse_object *op); + acpi_status acpi_ds_initialize_region(acpi_handle obj_handle); /* -- cgit v1.2.2 From c351f2dd542a3980e96cf128e06d19f784c5ea3e Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:41 +0400 Subject: ACPICA: Update version to 20071219 Update version to 20071219. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- include/acpi/acconfig.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index c21e12d165fe..010703e23866 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -63,7 +63,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20071114 +#define ACPI_CA_VERSION 0x20071219 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, -- cgit v1.2.2 From 8246934b7cf99d1f0c053d57890775e5d0df9c33 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Thu, 10 Apr 2008 19:06:41 +0400 Subject: ACPICA: Fix for SizeOf when used with Buffers and Packages Fixed a problem with the SizeOf operator when used with Package and Buffer objects. These objects have deferred execution for some arguments, and the execution is now completed before the SizeOf is executed. This problem caused unexpected AE_PACKAGE_LIMIT errors on some systems. http://bugzilla.kernel.org/show_bug.cgi?id=9558 Signed-off-by: Lin Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/executer/exoparg1.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c index ab5c03724527..313803b53125 100644 --- a/drivers/acpi/executer/exoparg1.c +++ b/drivers/acpi/executer/exoparg1.c @@ -740,26 +740,38 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) value = acpi_gbl_integer_byte_width; break; - case ACPI_TYPE_BUFFER: - value = temp_desc->buffer.length; - break; - case ACPI_TYPE_STRING: value = temp_desc->string.length; break; + case ACPI_TYPE_BUFFER: + + /* Buffer arguments may not be evaluated at this point */ + + status = acpi_ds_get_buffer_arguments(temp_desc); + value = temp_desc->buffer.length; + break; + case ACPI_TYPE_PACKAGE: + + /* Package arguments may not be evaluated at this point */ + + status = acpi_ds_get_package_arguments(temp_desc); value = temp_desc->package.count; break; default: ACPI_ERROR((AE_INFO, - "Operand is not Buf/Int/Str/Pkg - found type %s", + "Operand must be Buffer/Integer/String/Package - found type %s", acpi_ut_get_type_name(type))); status = AE_AML_OPERAND_TYPE; goto cleanup; } + if (ACPI_FAILURE(status)) { + goto cleanup; + } + /* * Now that we have the size of the object, create a result * object to hold the value -- cgit v1.2.2 From 9accd46459b8c068540451fdab07dbfcefaf7280 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Thu, 10 Apr 2008 19:06:42 +0400 Subject: ACPICA: Methods now implicitly return 0 in slack mode Implemented an enhancement to the interpreter "slack mode". In the absence of an explicit return or an implicitly returned object from the last executed opcode, a control method will now implicitly return an integer of value 0 for Microsoft compatibility. http://www.acpica.org/bugzilla/show_bug.cgi?id=392 Signed-off-by: Lin Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/parser/psparse.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c index a8995ca52ee7..a4c4020c40e9 100644 --- a/drivers/acpi/parser/psparse.c +++ b/drivers/acpi/parser/psparse.c @@ -594,6 +594,30 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) * The object is deleted */ if (!previous_walk_state->return_desc) { + /* + * In slack mode execution, if there is no return value + * we should implicitly return zero (0) as a default value. + */ + if (acpi_gbl_enable_interpreter_slack && + !previous_walk_state-> + implicit_return_obj) { + previous_walk_state-> + implicit_return_obj = + acpi_ut_create_internal_object + (ACPI_TYPE_INTEGER); + if (!previous_walk_state-> + implicit_return_obj) { + return_ACPI_STATUS + (AE_NO_MEMORY); + } + + previous_walk_state-> + implicit_return_obj-> + integer.value = 0; + } + + /* Restart the calling control method */ + status = acpi_ds_restart_control_method (walk_state, -- cgit v1.2.2 From 200cce6a75061a3bf8d2e6b27c5cdcc7730893f1 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Thu, 10 Apr 2008 19:06:42 +0400 Subject: ACPICA: Fix for Load operator Fixed a problem with the Load operator where an exception was not returned in the case where the table is already loaded. http://www.acpica.org/bugzilla/show_bug.cgi?id=463 Signed-off-by: Lin Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/tables/tbinstal.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c index 6a6ee1f06c76..c4a9abb072c0 100644 --- a/drivers/acpi/tables/tbinstal.c +++ b/drivers/acpi/tables/tbinstal.c @@ -169,6 +169,7 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, acpi_tb_delete_table(table_desc); *table_index = i; + status = AE_ALREADY_EXISTS; goto release; } -- cgit v1.2.2 From 47c08729bf1c60d522d020a7f8bc15d1c70e6ecb Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Thu, 10 Apr 2008 19:06:42 +0400 Subject: ACPICA: Fix for LoadTable operator, input strings Fixed a problem with the LoadTable operator where the OemId and OemTableId input strings could cause unexpected failures if they were shorter than the maximum lengths allowed. http://www.acpica.org/bugzilla/show_bug.cgi?id=576 Signed-off-by: Lin Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/executer/exconfig.c | 5 +---- drivers/acpi/tables/tbfind.c | 32 +++++++++++++++++++++++--------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index 52b1e95837fa..ed92fb5a1d2b 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -236,7 +236,7 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, status = acpi_get_table_by_index(table_index, &table); if (ACPI_SUCCESS(status)) { ACPI_INFO((AE_INFO, - "Dynamic OEM Table Load - [%4.4s] OemId [%6.6s] OemTableId [%8.8s]", + "Dynamic OEM Table Load - [%.4s] OemId [%.6s] OemTableId [%.8s]", table->signature, table->oem_id, table->oem_table_id)); } @@ -472,8 +472,5 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) acpi_tb_set_table_loaded_flag(table_index, FALSE); - /* Delete the table descriptor (ddb_handle) */ - - acpi_ut_remove_reference(table_desc); return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/tables/tbfind.c b/drivers/acpi/tables/tbfind.c index 058c064948e1..772ca41d840b 100644 --- a/drivers/acpi/tables/tbfind.c +++ b/drivers/acpi/tables/tbfind.c @@ -70,12 +70,22 @@ acpi_tb_find_table(char *signature, { acpi_native_uint i; acpi_status status; + struct acpi_table_header header; ACPI_FUNCTION_TRACE(tb_find_table); + /* Normalize the input strings */ + + ACPI_MEMSET(&header, 0, sizeof(struct acpi_table_header)); + ACPI_STRNCPY(header.signature, signature, ACPI_NAME_SIZE); + ACPI_STRNCPY(header.oem_id, oem_id, ACPI_OEM_ID_SIZE); + ACPI_STRNCPY(header.oem_table_id, oem_table_id, ACPI_OEM_TABLE_ID_SIZE); + + /* Search for the table */ + for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { if (ACPI_MEMCMP(&(acpi_gbl_root_table_list.tables[i].signature), - signature, ACPI_NAME_SIZE)) { + header.signature, ACPI_NAME_SIZE)) { /* Not the requested table */ @@ -104,20 +114,24 @@ acpi_tb_find_table(char *signature, if (!ACPI_MEMCMP (acpi_gbl_root_table_list.tables[i].pointer->signature, - signature, ACPI_NAME_SIZE) && (!oem_id[0] - || - !ACPI_MEMCMP - (acpi_gbl_root_table_list. - tables[i].pointer->oem_id, - oem_id, ACPI_OEM_ID_SIZE)) + header.signature, ACPI_NAME_SIZE) && (!oem_id[0] + || + !ACPI_MEMCMP + (acpi_gbl_root_table_list. + tables[i].pointer-> + oem_id, + header.oem_id, + ACPI_OEM_ID_SIZE)) && (!oem_table_id[0] || !ACPI_MEMCMP(acpi_gbl_root_table_list.tables[i]. - pointer->oem_table_id, oem_table_id, + pointer->oem_table_id, + header.oem_table_id, ACPI_OEM_TABLE_ID_SIZE))) { *table_index = i; ACPI_DEBUG_PRINT((ACPI_DB_TABLES, - "Found table [%4.4s]\n", signature)); + "Found table [%4.4s]\n", + header.signature)); return_ACPI_STATUS(AE_OK); } } -- cgit v1.2.2 From 970d9c9ec313daa1b41db0f8bdd1ca8cc2903822 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:42 +0400 Subject: ACPICA: Include file support for new ACPI tables Implemented header file support for new ACPI tables - BERT, ERST, EINJ, HEST, IBFT, UEFI, WDAT. Disassembler support is forthcoming. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- include/acpi/actbl1.h | 335 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 334 insertions(+), 1 deletion(-) diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h index dd8e11e624fa..5d39992314a9 100644 --- a/include/acpi/actbl1.h +++ b/include/acpi/actbl1.h @@ -58,12 +58,17 @@ * it more difficult to inadvertently type in the wrong signature. */ #define ACPI_SIG_ASF "ASF!" /* Alert Standard Format table */ +#define ACPI_SIG_BERT "BERT" /* Boot Error Record Table */ #define ACPI_SIG_BOOT "BOOT" /* Simple Boot Flag Table */ #define ACPI_SIG_CPEP "CPEP" /* Corrected Platform Error Polling table */ #define ACPI_SIG_DBGP "DBGP" /* Debug Port table */ #define ACPI_SIG_DMAR "DMAR" /* DMA Remapping table */ #define ACPI_SIG_ECDT "ECDT" /* Embedded Controller Boot Resources Table */ +#define ACPI_SIG_EINJ "EINJ" /* Error Injection table */ +#define ACPI_SIG_ERST "ERST" /* Error Record Serialization Table */ +#define ACPI_SIG_HEST "HEST" /* Hardware Error Source Table */ #define ACPI_SIG_HPET "HPET" /* High Precision Event Timer table */ +#define ACPI_SIG_IBFT "IBFT" /* i_sCSI Boot Firmware Table */ #define ACPI_SIG_MADT "APIC" /* Multiple APIC Description Table */ #define ACPI_SIG_MCFG "MCFG" /* PCI Memory Mapped Configuration table */ #define ACPI_SIG_SBST "SBST" /* Smart Battery Specification Table */ @@ -73,6 +78,8 @@ #define ACPI_SIG_SPMI "SPMI" /* Server Platform Management Interface table */ #define ACPI_SIG_SRAT "SRAT" /* System Resource Affinity Table */ #define ACPI_SIG_TCPA "TCPA" /* Trusted Computing Platform Alliance table */ +#define ACPI_SIG_UEFI "UEFI" /* Uefi Boot Optimization Table */ +#define ACPI_SIG_WDAT "WDAT" /* Watchdog Action Table */ #define ACPI_SIG_WDRT "WDRT" /* Watchdog Resource Table */ /* @@ -87,13 +94,25 @@ * portable, so do not use any other bitfield types. */ -/* Common Sub-table header (used in MADT, SRAT, etc.) */ +/* Common Subtable header (used in MADT, SRAT, etc.) */ struct acpi_subtable_header { u8 type; u8 length; }; +/* Common Subtable header for WHEA tables (EINJ, ERST, WDAT) */ + +struct acpi_whea_header { + u8 action; + u8 instruction; + u8 flags; + u8 reserved; + struct acpi_generic_address register_region; + u32 value; /* Value used with Read/Write register */ + u32 mask; /* Bitmask required for this register instruction */ +}; + /******************************************************************************* * * ASF - Alert Standard Format table (Signature "ASF!") @@ -203,6 +222,34 @@ struct acpi_asf_address { u8 devices; }; +/******************************************************************************* + * + * BERT - Boot Error Record Table + * + ******************************************************************************/ + +struct acpi_table_bert { + struct acpi_table_header header; /* Common ACPI table header */ + u32 region_length; /* Length of the boot error region */ + u64 address; /* Physical addresss of the error region */ +}; + +struct acpi_bert_region { + u32 block_status; + u32 raw_data_offset; + u32 raw_data_length; + u32 data_length; + u32 error_severity; + u8 error_data[1]; +}; + +/* block_status Flags */ + +#define ACPI_BERT_UNCORRECTABLE (1) +#define ACPI_BERT_CORRECTABLE (2) +#define ACPI_BERT_MULTIPLE_UNCORRECTABLE (4) +#define ACPI_BERT_MULTIPLE_CORRECTABLE (8) + /******************************************************************************* * * BOOT - Simple Boot Flag Table @@ -349,6 +396,130 @@ struct acpi_table_ecdt { u8 id[1]; /* Full namepath of the EC in the ACPI namespace */ }; +/******************************************************************************* + * + * EINJ - Error Injection Table + * + ******************************************************************************/ + +struct acpi_table_einj { + struct acpi_table_header header; /* Common ACPI table header */ + u32 header_length; + u32 reserved; + u32 entries; +}; + +/* EINJ Injection Instruction Entries (actions) */ + +struct acpi_einj_entry { + struct acpi_whea_header whea_header; /* Common header for WHEA tables */ +}; + +/* Values for Action field above */ + +enum acpi_einj_actions { + ACPI_EINJ_BEGIN_OPERATION = 0, + ACPI_EINJ_GET_TRIGGER_TABLE = 1, + ACPI_EINJ_SET_ERROR_TYPE = 2, + ACPI_EINJ_GET_ERROR_TYPE = 3, + ACPI_EINJ_END_OPERATION = 4, + ACPI_EINJ_EXECUTE_OPERATION = 5, + ACPI_EINJ_CHECK_BUSY_STATUS = 6, + ACPI_EINJ_GET_COMMAND_STATUS = 7, + ACPI_EINJ_ACTION_RESERVED = 8, /* 8 and greater are reserved */ + ACPI_EINJ_TRIGGER_ERROR = 0xFF /* Except for this value */ +}; + +/* Values for Instruction field above */ + +enum acpi_einj_instructions { + ACPI_EINJ_READ_REGISTER = 0, + ACPI_EINJ_READ_REGISTER_VALUE = 1, + ACPI_EINJ_WRITE_REGISTER = 2, + ACPI_EINJ_WRITE_REGISTER_VALUE = 3, + ACPI_EINJ_NOOP = 4, + ACPI_EINJ_INSTRUCTION_RESERVED = 5 /* 5 and greater are reserved */ +}; + +/******************************************************************************* + * + * ERST - Error Record Serialization Table + * + ******************************************************************************/ + +struct acpi_table_erst { + struct acpi_table_header header; /* Common ACPI table header */ + u32 header_length; + u32 reserved; + u32 entries; +}; + +/* ERST Serialization Entries (actions) */ + +struct acpi_erst_entry { + struct acpi_whea_header whea_header; /* Common header for WHEA tables */ +}; + +/* Values for Action field above */ + +enum acpi_erst_actions { + ACPI_ERST_BEGIN_WRITE_OPERATION = 0, + ACPI_ERST_BEGIN_READ_OPERATION = 1, + ACPI_ERST_BETGIN_CLEAR_OPERATION = 2, + ACPI_ERST_END_OPERATION = 3, + ACPI_ERST_SET_RECORD_OFFSET = 4, + ACPI_ERST_EXECUTE_OPERATION = 5, + ACPI_ERST_CHECK_BUSY_STATUS = 6, + ACPI_ERST_GET_COMMAND_STATUS = 7, + ACPI_ERST_GET_RECORD_IDENTIFIER = 8, + ACPI_ERST_SET_RECORD_IDENTIFIER = 9, + ACPI_ERST_GET_RECORD_COUNT = 10, + ACPI_ERST_BEGIN_DUMMY_WRIITE = 11, + ACPI_ERST_NOT_USED = 12, + ACPI_ERST_GET_ERROR_RANGE = 13, + ACPI_ERST_GET_ERROR_LENGTH = 14, + ACPI_ERST_GET_ERROR_ATTRIBUTES = 15, + ACPI_ERST_ACTION_RESERVED = 16 /* 16 and greater are reserved */ +}; + +/* Values for Instruction field above */ + +enum acpi_erst_instructions { + ACPI_ERST_READ_REGISTER = 0, + ACPI_ERST_READ_REGISTER_VALUE = 1, + ACPI_ERST_WRITE_REGISTER = 2, + ACPI_ERST_WRITE_REGISTER_VALUE = 3, + ACPI_ERST_NOOP = 4, + ACPI_ERST_LOAD_VAR1 = 5, + ACPI_ERST_LOAD_VAR2 = 6, + ACPI_ERST_STORE_VAR1 = 7, + ACPI_ERST_ADD = 8, + ACPI_ERST_SUBTRACT = 9, + ACPI_ERST_ADD_VALUE = 10, + ACPI_ERST_SUBTRACT_VALUE = 11, + ACPI_ERST_STALL = 12, + ACPI_ERST_STALL_WHILE_TRUE = 13, + ACPI_ERST_SKIP_NEXT_IF_TRUE = 14, + ACPI_ERST_GOTO = 15, + ACPI_ERST_SET_SRC_ADDRESS_BASE = 16, + ACPI_ERST_SET_DST_ADDRESS_BASE = 17, + ACPI_ERST_MOVE_DATA = 18, + ACPI_ERST_INSTRUCTION_RESERVED = 19 /* 19 and greater are reserved */ +}; + +/******************************************************************************* + * + * HEST - Hardware Error Source Table + * + ******************************************************************************/ + +struct acpi_table_hest { + struct acpi_table_header header; /* Common ACPI table header */ + u32 error_source_count; +}; + +/* TBD: Need Error Source Descriptor layout */ + /******************************************************************************* * * HPET - High Precision Event Timer table @@ -372,6 +543,96 @@ struct acpi_table_hpet { /*! [End] no source code translation !*/ +/******************************************************************************* + * + * IBFT - i_sCSI Boot Firmware Table + * + ******************************************************************************/ + +struct acpi_table_ibft { + struct acpi_table_header header; /* Common ACPI table header */ + u8 reserved[12]; +}; + +/* IBFT common subtable header */ + +struct acpi_ibft_header { + u8 type; + u8 version; + u16 length; + u8 index; + u8 flags; +}; + +/* Values for Type field above */ + +enum acpi_ibft_type { + ACPI_IBFT_TYPE_NOT_USED = 0, + ACPI_IBFT_TYPE_CONTROL = 1, + ACPI_IBFT_TYPE_INITIATOR = 2, + ACPI_IBFT_TYPE_NIC = 3, + ACPI_IBFT_TYPE_TARGET = 4, + ACPI_IBFT_TYPE_EXTENSIONS = 5, + ACPI_IBFT_TYPE_RESERVED = 6 /* 6 and greater are reserved */ +}; + +/* IBFT subtables */ + +struct acpi_ibft_control { + struct acpi_ibft_header header; + u16 extensions; + u16 initiator_offset; + u16 nic0_offset; + u16 target0_offset; + u16 nic1_offset; + u16 target1_offset; +}; + +struct acpi_ibft_initiator { + struct acpi_ibft_header header; + u8 sns_server[16]; + u8 slp_server[16]; + u8 primary_server[16]; + u8 secondary_server[16]; + u16 name_length; + u16 name_offset; +}; + +struct acpi_ibft_nic { + struct acpi_ibft_header header; + u8 ip_address[16]; + u8 subnet_mask_prefix; + u8 origin; + u8 gateway[16]; + u8 primary_dns[16]; + u8 secondary_dns[16]; + u8 dhcp[16]; + u16 vlan; + u8 mac_address[6]; + u16 pci_address; + u16 name_length; + u16 name_offset; +}; + +struct acpi_ibft_target { + struct acpi_ibft_header header; + u8 target_ip_address[16]; + u16 target_ip_socket; + u8 target_boot_lun[8]; + u8 chap_type; + u8 nic_association; + u16 target_name_length; + u16 target_name_offset; + u16 chap_name_length; + u16 chap_name_offset; + u16 chap_secret_length; + u16 chap_secret_offset; + u16 reverse_chap_name_length; + u16 reverse_chap_name_offset; + u16 reverse_chap_secret_length; + u16 reverse_chap_secret_offset; +}; + /******************************************************************************* * * MADT - Multiple APIC Description Table @@ -696,6 +957,78 @@ struct acpi_table_tcpa { u64 log_address; /* Address of the event log area */ }; +/******************************************************************************* + * + * UEFI - UEFI Boot optimization Table + * + ******************************************************************************/ + +struct acpi_table_uefi { + struct acpi_table_header header; /* Common ACPI table header */ + u8 identifier[16]; /* UUID identifier */ + u16 data_offset; /* Offset of remaining data in table */ + u8 data; +}; + +/******************************************************************************* + * + * WDAT - Watchdog Action Table + * + ******************************************************************************/ + +struct acpi_table_wdat { + struct acpi_table_header header; /* Common ACPI table header */ + u32 header_length; /* Watchdog Header Length */ + u16 pci_segment; /* PCI Segment number */ + u8 pci_bus; /* PCI Bus number */ + u8 pci_device; /* PCI Device number */ + u8 pci_function; /* PCI Function number */ + u8 reserved[3]; + u32 timer_period; /* Period of one timer count (msec) */ + u32 max_count; /* Maximum counter value supported */ + u32 min_count; /* Minimum counter value */ + u8 flags; + u8 reserved2[3]; + u32 entries; /* Number of watchdog entries that follow */ +}; + +/* WDAT Instruction Entries (actions) */ + +struct acpi_wdat_entry { + struct acpi_whea_header whea_header; /* Common header for WHEA tables */ +}; + +/* Values for Action field above */ + +enum acpi_wdat_actions { + ACPI_WDAT_RESET = 1, + ACPI_WDAT_GET_CURRENT_COUNTDOWN = 4, + ACPI_WDAT_GET_COUNTDOWN = 5, + ACPI_WDAT_SET_COUNTDOWN = 6, + ACPI_WDAT_GET_RUNNING_STATE = 8, + ACPI_WDAT_SET_RUNNING_STATE = 9, + ACPI_WDAT_GET_STOPPED_STATE = 10, + ACPI_WDAT_SET_STOPPED_STATE = 11, + ACPI_WDAT_GET_REBOOT = 16, + ACPI_WDAT_SET_REBOOT = 17, + ACPI_WDAT_GET_SHUTDOWN = 18, + ACPI_WDAT_SET_SHUTDOWN = 19, + ACPI_WDAT_GET_STATUS = 32, + ACPI_WDAT_SET_STATUS = 33, + ACPI_WDAT_ACTION_RESERVED = 34 /* 34 and greater are reserved */ +}; + +/* Values for Instruction field above */ + +enum acpi_wdat_instructions { + ACPI_WDAT_READ_VALUE = 0, + ACPI_WDAT_READ_COUNTDOWN = 1, + ACPI_WDAT_WRITE_VALUE = 2, + ACPI_WDAT_WRITE_COUNTDOWN = 3, + ACPI_WDAT_INSTRUCTION_RESERVED = 4, /* 4 and greater are reserved */ + ACPI_WDAT_PRESERVE_REGISTER = 0x80 /* Except for this value */ +}; + /******************************************************************************* * * WDRT - Watchdog Resource Table -- cgit v1.2.2 From a6f4a4511e65942b93ded60d746094ec0e58ed8e Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:42 +0400 Subject: ACPICA: Bulletproof disassembler for bad ACPI tables Fixed a problem with the disassembler where invalid ACPI tables could cause faults or infinite loops. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- include/acpi/acdisasm.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/include/acpi/acdisasm.h b/include/acpi/acdisasm.h index 67d152e7fa44..07d5241ea7a2 100644 --- a/include/acpi/acdisasm.h +++ b/include/acpi/acdisasm.h @@ -97,11 +97,12 @@ typedef const struct acpi_dmtable_info { #define ACPI_DMT_CHKSUM 20 #define ACPI_DMT_SPACEID 21 #define ACPI_DMT_GAS 22 -#define ACPI_DMT_DMAR 23 -#define ACPI_DMT_MADT 24 -#define ACPI_DMT_SRAT 25 -#define ACPI_DMT_EXIT 26 -#define ACPI_DMT_SIG 27 +#define ACPI_DMT_ASF 23 +#define ACPI_DMT_DMAR 24 +#define ACPI_DMT_MADT 25 +#define ACPI_DMT_SRAT 26 +#define ACPI_DMT_EXIT 27 +#define ACPI_DMT_SIG 28 typedef void (*acpi_dmtable_handler) (struct acpi_table_header * table); @@ -195,7 +196,7 @@ extern struct acpi_dmtable_info acpi_dm_table_info_wdrt[]; */ void acpi_dm_dump_data_table(struct acpi_table_header *table); -void +acpi_status acpi_dm_dump_table(u32 table_length, u32 table_offset, void *table, -- cgit v1.2.2 From bc7a36ab74e09da7bb63e2477b0740ac992b290e Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Thu, 10 Apr 2008 19:06:42 +0400 Subject: ACPICA: Fixes for Unload and DDBHandles Implemented support for the use of DDBHandles as an Indexed Reference, as per the ACPI spec. http://www.acpica.org/bugzilla/show_bug.cgi?id=486. Implemented support for UserTerm (Method invocation) for the Unload operator as per the ACPI spec. http://www.acpica.org/bugzilla/show_bug.cgi?id=580 Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/executer/exdump.c | 27 +++++++++++++++++++-------- drivers/acpi/executer/exresolv.c | 13 +++++++++---- drivers/acpi/executer/exstore.c | 23 ++++++++++++++++++----- drivers/acpi/parser/psargs.c | 37 ++++++++++++++++++++++++++++++++++--- drivers/acpi/utilities/utcopy.c | 8 ++++++++ 5 files changed, 88 insertions(+), 20 deletions(-) diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c index 251d84ba79b3..ed560e656f9a 100644 --- a/drivers/acpi/executer/exdump.c +++ b/drivers/acpi/executer/exdump.c @@ -895,14 +895,25 @@ static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc) } else if (obj_desc->reference.object) { if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_OPERAND) { - acpi_os_printf(" Target: %p [%s]\n", - obj_desc->reference.object, - acpi_ut_get_type_name(((union - acpi_operand_object - *)obj_desc-> - reference. - object)->common. - type)); + acpi_os_printf(" Target: %p", + obj_desc->reference.object); + if (obj_desc->reference.opcode == AML_LOAD_OP) { + /* + * For DDBHandle reference, + * obj_desc->Reference.Object is the table index + */ + acpi_os_printf(" [DDBHandle]\n"); + } else { + acpi_os_printf(" [%s]\n", + acpi_ut_get_type_name(((union + acpi_operand_object + *) + obj_desc-> + reference. + object)-> + common. + type)); + } } else { acpi_os_printf(" Target: %p\n", obj_desc->reference.object); diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c index 9c3cdf61dc34..5b5b2ff45ea2 100644 --- a/drivers/acpi/executer/exresolv.c +++ b/drivers/acpi/executer/exresolv.c @@ -382,10 +382,10 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, } /* - * For reference objects created via the ref_of or Index operators, - * we need to get to the base object (as per the ACPI specification - * of the object_type and size_of operators). This means traversing - * the list of possibly many nested references. + * For reference objects created via the ref_of, Index, or Load/load_table + * operators, we need to get to the base object (as per the ACPI + * specification of the object_type and size_of operators). This means + * traversing the list of possibly many nested references. */ while (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) { switch (obj_desc->reference.opcode) { @@ -455,6 +455,11 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, } break; + case AML_LOAD_OP: + + type = ACPI_TYPE_DDB_HANDLE; + goto exit; + case AML_LOCAL_OP: case AML_ARG_OP: diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c index 2408122cb3b2..725614e277f8 100644 --- a/drivers/acpi/executer/exstore.c +++ b/drivers/acpi/executer/exstore.c @@ -434,11 +434,24 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, */ obj_desc = *(index_desc->reference.where); - status = - acpi_ut_copy_iobject_to_iobject(source_desc, &new_desc, - walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + if (ACPI_GET_OBJECT_TYPE(source_desc) == + ACPI_TYPE_LOCAL_REFERENCE + && source_desc->reference.opcode == AML_LOAD_OP) { + + /* This is a DDBHandle, just add a reference to it */ + + acpi_ut_add_reference(source_desc); + new_desc = source_desc; + } else { + /* Normal object, copy it */ + + status = + acpi_ut_copy_iobject_to_iobject(source_desc, + &new_desc, + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } } if (obj_desc) { diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c index 442880f5600e..2a3a948dd114 100644 --- a/drivers/acpi/parser/psargs.c +++ b/drivers/acpi/parser/psargs.c @@ -235,6 +235,7 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, union acpi_parse_object *name_op; union acpi_operand_object *method_desc; struct acpi_namespace_node *node; + u8 *start = parser_state->aml; ACPI_FUNCTION_TRACE(ps_get_next_namepath); @@ -267,6 +268,16 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, */ if (ACPI_SUCCESS(status) && possible_method_call && (node->type == ACPI_TYPE_METHOD)) { + if (walk_state->op->common.aml_opcode == AML_UNLOAD_OP) { + /* + * acpi_ps_get_next_namestring has increased the AML pointer, + * so we need to restore the saved AML pointer for method call. + */ + walk_state->parser_state.aml = start; + walk_state->arg_count = 1; + acpi_ps_init_op(arg, AML_INT_METHODCALL_OP); + return_ACPI_STATUS(AE_OK); + } /* This name is actually a control method invocation */ @@ -678,9 +689,29 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, return_ACPI_STATUS(AE_NO_MEMORY); } - status = - acpi_ps_get_next_namepath(walk_state, parser_state, - arg, 0); + /* To support super_name arg of Unload */ + + if (walk_state->op->common.aml_opcode == AML_UNLOAD_OP) { + status = + acpi_ps_get_next_namepath(walk_state, + parser_state, arg, + 1); + + /* + * If the super_name arg of Unload is a method call, + * we have restored the AML pointer, just free this Arg + */ + if (arg->common.aml_opcode == + AML_INT_METHODCALL_OP) { + acpi_ps_free_op(arg); + arg = NULL; + } + } else { + status = + acpi_ps_get_next_namepath(walk_state, + parser_state, arg, + 0); + } } else { /* Single complex argument, nothing returned */ diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c index b56953d2b59e..ba899714733b 100644 --- a/drivers/acpi/utilities/utcopy.c +++ b/drivers/acpi/utilities/utcopy.c @@ -709,7 +709,15 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc, /* * We copied the reference object, so we now must add a reference * to the object pointed to by the reference + * + * DDBHandle reference (from Load/load_table is a special reference, + * it's Reference.Object is the table index, so does not need to + * increase the reference count */ + if (source_desc->reference.opcode == AML_LOAD_OP) { + break; + } + acpi_ut_add_reference(source_desc->reference.object); break; -- cgit v1.2.2 From 8c49c235774002708bd0da1c28c570073ebd963b Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:42 +0400 Subject: ACPICA: Update version to 20080123 Update version to 20080123. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- include/acpi/acconfig.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index 010703e23866..c7d5c91bedee 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -63,7 +63,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20071219 +#define ACPI_CA_VERSION 0x20080123 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, -- cgit v1.2.2 From 507f046c4dd17e9c94b5130ba184f8da90504685 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:42 +0400 Subject: ACPICA: Add va_end statements as appropriate Added missing va_end statements that should correspond with each va_start statement. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/utilities/utdebug.c | 2 ++ drivers/acpi/utilities/utmisc.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c index 2d6a78fb01cf..80144427bb41 100644 --- a/drivers/acpi/utilities/utdebug.c +++ b/drivers/acpi/utilities/utdebug.c @@ -201,6 +201,7 @@ acpi_ut_debug_print(u32 requested_debug_level, va_start(args, format); acpi_os_vprintf(format, args); + va_end(args); } ACPI_EXPORT_SYMBOL(acpi_ut_debug_print) @@ -238,6 +239,7 @@ acpi_ut_debug_print_raw(u32 requested_debug_level, va_start(args, format); acpi_os_vprintf(format, args); + va_end(args); } ACPI_EXPORT_SYMBOL(acpi_ut_debug_print_raw) diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c index 2d19f71e9cfa..2f48fd663f5c 100644 --- a/drivers/acpi/utilities/utmisc.c +++ b/drivers/acpi/utilities/utmisc.c @@ -1033,6 +1033,7 @@ acpi_ut_error(char *module_name, u32 line_number, char *format, ...) va_start(args, format); acpi_os_vprintf(format, args); acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); + va_end(args); } void ACPI_INTERNAL_VAR_XFACE @@ -1061,6 +1062,8 @@ acpi_ut_warning(char *module_name, u32 line_number, char *format, ...) va_start(args, format); acpi_os_vprintf(format, args); acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); + va_end(args); + va_end(args); } void ACPI_INTERNAL_VAR_XFACE @@ -1077,4 +1080,5 @@ acpi_ut_info(char *module_name, u32 line_number, char *format, ...) va_start(args, format); acpi_os_vprintf(format, args); acpi_os_printf("\n"); + va_end(args); } -- cgit v1.2.2 From b1dd9096fef08642eb509fbf2a40b3c7734dce1c Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:42 +0400 Subject: ACPICA: Added new error messages New messages for the 2 AE_SUPPORT cases. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/utilities/utcopy.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c index ba899714733b..4c4021d82f99 100644 --- a/drivers/acpi/utilities/utcopy.c +++ b/drivers/acpi/utilities/utcopy.c @@ -215,6 +215,11 @@ acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object, /* * There is no corresponding external object type */ + ACPI_ERROR((AE_INFO, + "Unsupported object type, cannot convert to external object: %s", + acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE + (internal_object)))); + return_ACPI_STATUS(AE_SUPPORT); } @@ -467,6 +472,10 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, default: /* All other types are not supported */ + ACPI_ERROR((AE_INFO, + "Unsupported object type, cannot convert to internal object: %s", + acpi_ut_get_type_name(external_object->type))); + return_ACPI_STATUS(AE_SUPPORT); } -- cgit v1.2.2 From 7823665eccdc7e230d0a904c6ec01d5c70ee099b Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:42 +0400 Subject: ACPICA: Fix for ACPI_HIDWORD macro Fixed a regression introduced in version 20071114. The ACPI_HIDWORD macro was inadvertently changed to return a 16-bit value instead of a 32-bit value, truncating the upper Dword of a 64-bit value. This macro is only used to display debug output, so no incorrect calculations were made. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- include/acpi/acmacros.h | 69 +++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/include/acpi/acmacros.h b/include/acpi/acmacros.h index dc6a037311db..1f0fdbf6e09f 100644 --- a/include/acpi/acmacros.h +++ b/include/acpi/acmacros.h @@ -61,30 +61,6 @@ #define ACPI_ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0])) -/* - * Full 64-bit integer must be available on both 32-bit and 64-bit platforms - */ -#define ACPI_LODWORD(l) ((u32)(u64)(l)) -#define ACPI_HIDWORD(l) ((u16)((((u64)(l)) >> 32) & 0xFFFFFFFF)) - -#if 0 -#define ACPI_HIDWORD(l) ((u32)(((*(struct uint64_struct *)(void *)(&l))).hi)) -#endif - -/* - * printf() format helpers - */ - -/* Split 64-bit integer into two 32-bit values. Use with %8.8_x%8.8_x */ - -#define ACPI_FORMAT_UINT64(i) ACPI_HIDWORD(i),ACPI_LODWORD(i) - -#if ACPI_MACHINE_WIDTH == 64 -#define ACPI_FORMAT_NATIVE_UINT(i) ACPI_FORMAT_UINT64(i) -#else -#define ACPI_FORMAT_NATIVE_UINT(i) 0, (i) -#endif - /* * Extract data using a pointer. Any more than a byte and we * get into potential aligment issues -- see the STORE macros below. @@ -121,6 +97,31 @@ #define ACPI_COMPARE_NAME(a,b) (!ACPI_STRNCMP (ACPI_CAST_PTR (char,(a)), ACPI_CAST_PTR (char,(b)), ACPI_NAME_SIZE)) #endif +/* + * Full 64-bit integer must be available on both 32-bit and 64-bit platforms + */ +struct acpi_integer_overlay { + u32 lo_dword; + u32 hi_dword; +}; + +#define ACPI_LODWORD(integer) (ACPI_CAST_PTR (struct acpi_integer_overlay, &integer)->lo_dword) +#define ACPI_HIDWORD(integer) (ACPI_CAST_PTR (struct acpi_integer_overlay, &integer)->hi_dword) + +/* + * printf() format helpers + */ + +/* Split 64-bit integer into two 32-bit values. Use with %8.8_x%8.8_x */ + +#define ACPI_FORMAT_UINT64(i) ACPI_HIDWORD(i),ACPI_LODWORD(i) + +#if ACPI_MACHINE_WIDTH == 64 +#define ACPI_FORMAT_NATIVE_UINT(i) ACPI_FORMAT_UINT64(i) +#else +#define ACPI_FORMAT_NATIVE_UINT(i) 0, (i) +#endif + /* * Macros for moving data around to/from buffers that are possibly unaligned. * If the hardware supports the transfer of unaligned data, just do the store. @@ -137,29 +138,29 @@ /* These macros reverse the bytes during the move, converting little-endian to big endian */ - /* Big Endian <== Little Endian */ - /* Hi...Lo Lo...Hi */ + /* Big Endian <== Little Endian */ + /* Hi...Lo Lo...Hi */ /* 16-bit source, 16/32/64 destination */ #define ACPI_MOVE_16_TO_16(d,s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[1];\ - (( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[0];} + (( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[0];} #define ACPI_MOVE_16_TO_32(d,s) {(*(u32 *)(void *)(d))=0;\ - ((u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\ - ((u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];} + ((u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\ + ((u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];} #define ACPI_MOVE_16_TO_64(d,s) {(*(u64 *)(void *)(d))=0;\ - ((u8 *)(void *)(d))[6] = ((u8 *)(void *)(s))[1];\ - ((u8 *)(void *)(d))[7] = ((u8 *)(void *)(s))[0];} + ((u8 *)(void *)(d))[6] = ((u8 *)(void *)(s))[1];\ + ((u8 *)(void *)(d))[7] = ((u8 *)(void *)(s))[0];} /* 32-bit source, 16/32/64 destination */ #define ACPI_MOVE_32_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */ #define ACPI_MOVE_32_TO_32(d,s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[3];\ - (( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[2];\ - (( u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\ - (( u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];} + (( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[2];\ + (( u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\ + (( u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];} #define ACPI_MOVE_32_TO_64(d,s) {(*(u64 *)(void *)(d))=0;\ ((u8 *)(void *)(d))[4] = ((u8 *)(void *)(s))[3];\ -- cgit v1.2.2 From 3fa347770a8a9cb3568600380ce4b5c041b3ac0b Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:43 +0400 Subject: ACPICA: Disassembler support for new ACPI tables Implemented full disassembler support for the following new ACPI tables: BERT, EINJ, and ERST. Partial disassembler support for the complicated HEST table. These tables support the Windows Hardware Error Architecture (WHEA). Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- include/acpi/acdisasm.h | 26 ++++-- include/acpi/actbl1.h | 233 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 249 insertions(+), 10 deletions(-) diff --git a/include/acpi/acdisasm.h b/include/acpi/acdisasm.h index 07d5241ea7a2..73d86ebaeed6 100644 --- a/include/acpi/acdisasm.h +++ b/include/acpi/acdisasm.h @@ -99,10 +99,13 @@ typedef const struct acpi_dmtable_info { #define ACPI_DMT_GAS 22 #define ACPI_DMT_ASF 23 #define ACPI_DMT_DMAR 24 -#define ACPI_DMT_MADT 25 -#define ACPI_DMT_SRAT 26 -#define ACPI_DMT_EXIT 27 -#define ACPI_DMT_SIG 28 +#define ACPI_DMT_HEST 25 +#define ACPI_DMT_HESTNTFY 26 +#define ACPI_DMT_HESTNTYP 27 +#define ACPI_DMT_MADT 28 +#define ACPI_DMT_SRAT 29 +#define ACPI_DMT_EXIT 30 +#define ACPI_DMT_SIG 31 typedef void (*acpi_dmtable_handler) (struct acpi_table_header * table); @@ -150,6 +153,7 @@ extern struct acpi_dmtable_info acpi_dm_table_info_asf3[]; extern struct acpi_dmtable_info acpi_dm_table_info_asf4[]; extern struct acpi_dmtable_info acpi_dm_table_info_asf_hdr[]; extern struct acpi_dmtable_info acpi_dm_table_info_boot[]; +extern struct acpi_dmtable_info acpi_dm_table_info_bert[]; extern struct acpi_dmtable_info acpi_dm_table_info_cpep[]; extern struct acpi_dmtable_info acpi_dm_table_info_cpep0[]; extern struct acpi_dmtable_info acpi_dm_table_info_dbgp[]; @@ -159,11 +163,17 @@ extern struct acpi_dmtable_info acpi_dm_table_info_dmar_scope[]; extern struct acpi_dmtable_info acpi_dm_table_info_dmar0[]; extern struct acpi_dmtable_info acpi_dm_table_info_dmar1[]; extern struct acpi_dmtable_info acpi_dm_table_info_ecdt[]; +extern struct acpi_dmtable_info acpi_dm_table_info_einj[]; +extern struct acpi_dmtable_info acpi_dm_table_info_einj0[]; +extern struct acpi_dmtable_info acpi_dm_table_info_erst[]; extern struct acpi_dmtable_info acpi_dm_table_info_facs[]; extern struct acpi_dmtable_info acpi_dm_table_info_fadt1[]; extern struct acpi_dmtable_info acpi_dm_table_info_fadt2[]; extern struct acpi_dmtable_info acpi_dm_table_info_gas[]; extern struct acpi_dmtable_info acpi_dm_table_info_header[]; +extern struct acpi_dmtable_info acpi_dm_table_info_hest[]; +extern struct acpi_dmtable_info acpi_dm_table_info_hest9[]; +extern struct acpi_dmtable_info acpi_dm_table_info_hest_notify[]; extern struct acpi_dmtable_info acpi_dm_table_info_hpet[]; extern struct acpi_dmtable_info acpi_dm_table_info_madt[]; extern struct acpi_dmtable_info acpi_dm_table_info_madt0[]; @@ -215,9 +225,13 @@ void acpi_dm_dump_cpep(struct acpi_table_header *table); void acpi_dm_dump_dmar(struct acpi_table_header *table); +void acpi_dm_dump_einj(struct acpi_table_header *table); + +void acpi_dm_dump_erst(struct acpi_table_header *table); + void acpi_dm_dump_fadt(struct acpi_table_header *table); -void acpi_dm_dump_srat(struct acpi_table_header *table); +void acpi_dm_dump_hest(struct acpi_table_header *table); void acpi_dm_dump_mcfg(struct acpi_table_header *table); @@ -229,6 +243,8 @@ void acpi_dm_dump_rsdt(struct acpi_table_header *table); void acpi_dm_dump_slit(struct acpi_table_header *table); +void acpi_dm_dump_srat(struct acpi_table_header *table); + void acpi_dm_dump_xsdt(struct acpi_table_header *table); /* diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h index 5d39992314a9..604dfb311660 100644 --- a/include/acpi/actbl1.h +++ b/include/acpi/actbl1.h @@ -109,8 +109,8 @@ struct acpi_whea_header { u8 flags; u8 reserved; struct acpi_generic_address register_region; - u32 value; /* Value used with Read/Write register */ - u32 mask; /* Bitmask required for this register instruction */ + u64 value; /* Value used with Read/Write register */ + u64 mask; /* Bitmask required for this register instruction */ }; /******************************************************************************* @@ -234,13 +234,14 @@ struct acpi_table_bert { u64 address; /* Physical addresss of the error region */ }; +/* Boot Error Region */ + struct acpi_bert_region { u32 block_status; u32 raw_data_offset; u32 raw_data_length; u32 data_length; u32 error_severity; - u8 error_data[1]; }; /* block_status Flags */ @@ -441,6 +442,15 @@ enum acpi_einj_instructions { ACPI_EINJ_INSTRUCTION_RESERVED = 5 /* 5 and greater are reserved */ }; +/* EINJ Trigger Error Action Table */ + +struct acpi_einj_trigger { + u32 header_size; + u32 revision; + u32 table_size; + u32 entry_count; +}; + /******************************************************************************* * * ERST - Error Record Serialization Table @@ -518,7 +528,220 @@ struct acpi_table_hest { u32 error_source_count; }; -/* TBD: Need Error Source Descriptor layout */ +/* HEST subtable header */ + +struct acpi_hest_header { + u16 type; +}; + +/* Values for Type field above for subtables */ + +enum acpi_hest_types { + ACPI_HEST_TYPE_XPF_MACHINE_CHECK = 0, + ACPI_HEST_TYPE_XPF_CORRECTED_MACHINE_CHECK = 1, + ACPI_HEST_TYPE_XPF_UNUSED = 2, + ACPI_HEST_TYPE_XPF_NON_MASKABLE_INTERRUPT = 3, + ACPI_HEST_TYPE_IPF_CORRECTED_MACHINE_CHECK = 4, + ACPI_HEST_TYPE_IPF_CORRECTED_PLATFORM_ERROR = 5, + ACPI_HEST_TYPE_AER_ROOT_PORT = 6, + ACPI_HEST_TYPE_AER_ENDPOINT = 7, + ACPI_HEST_TYPE_AER_BRIDGE = 8, + ACPI_HEST_TYPE_GENERIC_HARDWARE_ERROR_SOURCE = 9, + ACPI_HEST_TYPE_RESERVED = 10 /* 10 and greater are reserved */ +}; + +/* + * HEST Sub-subtables + */ + +/* XPF Machine Check Error Bank */ + +struct acpi_hest_xpf_error_bank { + u8 bank_number; + u8 clear_status_on_init; + u8 status_format; + u8 config_write_enable; + u32 control_register; + u64 control_init_data; + u32 status_register; + u32 address_register; + u32 misc_register; +}; + +/* Generic Error Status */ + +struct acpi_hest_generic_status { + u32 block_status; + u32 raw_data_offset; + u32 raw_data_length; + u32 data_length; + u32 error_severity; +}; + +/* Generic Error Data */ + +struct acpi_hest_generic_data { + u8 section_type[16]; + u32 error_severity; + u16 revision; + u8 validation_bits; + u8 flags; + u32 error_data_length; + u8 fru_id[16]; + u8 fru_text[20]; +}; + +/* Common HEST structure for PCI/AER types below (6,7,8) */ + +struct acpi_hest_aer_common { + u16 source_id; + u16 config_write_enable; + u8 flags; + u8 enabled; + u32 records_to_pre_allocate; + u32 max_sections_per_record; + u32 bus; + u16 device; + u16 function; + u16 device_control; + u16 reserved; + u32 uncorrectable_error_mask; + u32 uncorrectable_error_severity; + u32 correctable_error_mask; + u32 advanced_error_cababilities; +}; + +/* Hardware Error Notification */ + +struct acpi_hest_notify { + u8 type; + u8 length; + u16 config_write_enable; + u32 poll_interval; + u32 vector; + u32 polling_threshold_value; + u32 polling_threshold_window; + u32 error_threshold_value; + u32 error_threshold_window; +}; + +/* Values for Notify Type field above */ + +enum acpi_hest_notify_types { + ACPI_HEST_NOTIFY_POLLED = 0, + ACPI_HEST_NOTIFY_EXTERNAL = 1, + ACPI_HEST_NOTIFY_LOCAL = 2, + ACPI_HEST_NOTIFY_SCI = 3, + ACPI_HEST_NOTIFY_NMI = 4, + ACPI_HEST_NOTIFY_RESERVED = 5 /* 5 and greater are reserved */ +}; + +/* + * HEST subtables + * + * From WHEA Design Document, 16 May 2007. + * Note: There is no subtable type 2 in this version of the document, + * and there are two different subtable type 3s. + */ + + /* 0: XPF Machine Check Exception */ + +struct acpi_hest_xpf_machine_check { + struct acpi_hest_header header; + u16 source_id; + u16 config_write_enable; + u8 flags; + u8 reserved1; + u32 records_to_pre_allocate; + u32 max_sections_per_record; + u64 global_capability_data; + u64 global_control_data; + u8 num_hardware_banks; + u8 reserved2[7]; +}; + +/* 1: XPF Corrected Machine Check */ + +struct acpi_table_hest_xpf_corrected { + struct acpi_hest_header header; + u16 source_id; + u16 config_write_enable; + u8 flags; + u8 enabled; + u32 records_to_pre_allocate; + u32 max_sections_per_record; + struct acpi_hest_notify notify; + u8 num_hardware_banks; + u8 reserved[3]; +}; + +/* 3: XPF Non-Maskable Interrupt */ + +struct acpi_hest_xpf_nmi { + struct acpi_hest_header header; + u16 source_id; + u32 reserved; + u32 records_to_pre_allocate; + u32 max_sections_per_record; + u32 max_raw_data_length; +}; + +/* 4: IPF Corrected Machine Check */ + +struct acpi_hest_ipf_corrected { + struct acpi_hest_header header; + u8 enabled; + u8 reserved; +}; + +/* 5: IPF Corrected Platform Error */ + +struct acpi_hest_ipf_corrected_platform { + struct acpi_hest_header header; + u8 enabled; + u8 reserved; +}; + +/* 6: PCI Express Root Port AER */ + +struct acpi_hest_aer_root { + struct acpi_hest_header header; + struct acpi_hest_aer_common aer; + u32 root_error_command; +}; + +/* 7: PCI Express AER (AER Endpoint) */ + +struct acpi_hest_aer { + struct acpi_hest_header header; + struct acpi_hest_aer_common aer; +}; + +/* 8: PCI Express/PCI-X Bridge AER */ + +struct acpi_hest_aer_bridge { + struct acpi_hest_header header; + struct acpi_hest_aer_common aer; + u32 secondary_uncorrectable_error_mask; + u32 secondary_uncorrectable_error_severity; + u32 secondary_advanced_capabilities; +}; + +/* 9: Generic Hardware Error Source */ + +struct acpi_hest_generic { + struct acpi_hest_header header; + u16 source_id; + u16 related_source_id; + u8 config_write_enable; + u8 enabled; + u32 records_to_pre_allocate; + u32 max_sections_per_record; + u32 max_raw_data_length; + struct acpi_generic_address error_status_address; + struct acpi_hest_notify notify; + u32 error_status_block_length; +}; /******************************************************************************* * @@ -545,7 +768,7 @@ struct acpi_table_hpet { /******************************************************************************* * - * IBFT - i_sCSI Boot Firmware Table + * IBFT - Boot Firmware Table * ******************************************************************************/ -- cgit v1.2.2 From 1d5b285da1893b90507b081664ac27f1a8a3dc5b Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:43 +0400 Subject: ACPICA: Fix for resource descriptor optimization issues for _CRS/_SRC Fixed a problem where resource descriptor size optimization could cause a problem when a _CRS resource template is passed to a _SRS method. The _SRS resource template must use the same descriptors (with the same size) as returned from _CRS. This change affects the following resource descriptors: IRQ/IRQNoFlags and StartDependendentFn/StartDependentFnNoPri. http://bugzilla.kernel.org/show_bug.cgi?id=9487 Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/resources/rscalc.c | 7 +++++++ drivers/acpi/resources/rsdump.c | 8 ++++++-- drivers/acpi/resources/rsio.c | 39 +++++++++++++++++++++++++++++++++++-- drivers/acpi/resources/rsirq.c | 43 +++++++++++++++++++++++++++++++++++++---- drivers/acpi/resources/rsmisc.c | 11 +++++++++++ include/acpi/acresrc.h | 1 + include/acpi/actypes.h | 2 ++ 7 files changed, 103 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c index dcc51e92ac92..db0a835e3317 100644 --- a/drivers/acpi/resources/rscalc.c +++ b/drivers/acpi/resources/rscalc.c @@ -211,6 +211,13 @@ acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed) * variable-length fields */ switch (resource->type) { + case ACPI_RESOURCE_TYPE_IRQ: + + if (resource->data.irq.descriptor_length == 2) { + total_size--; + } + break; + case ACPI_RESOURCE_TYPE_VENDOR: /* * Vendor Defined Resource: diff --git a/drivers/acpi/resources/rsdump.c b/drivers/acpi/resources/rsdump.c index 46da116a4030..ed6447dcea78 100644 --- a/drivers/acpi/resources/rsdump.c +++ b/drivers/acpi/resources/rsdump.c @@ -87,8 +87,10 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table); * ******************************************************************************/ -struct acpi_rsdump_info acpi_rs_dump_irq[6] = { +struct acpi_rsdump_info acpi_rs_dump_irq[7] = { {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_irq), "IRQ", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.descriptor_length), + "Descriptor Length", NULL}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.triggering), "Triggering", acpi_gbl_he_decode}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.polarity), "Polarity", @@ -115,9 +117,11 @@ struct acpi_rsdump_info acpi_rs_dump_dma[6] = { NULL} }; -struct acpi_rsdump_info acpi_rs_dump_start_dpf[3] = { +struct acpi_rsdump_info acpi_rs_dump_start_dpf[4] = { {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_start_dpf), "Start-Dependent-Functions", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(start_dpf.descriptor_length), + "Descriptor Length", NULL}, {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.compatibility_priority), "Compatibility Priority", acpi_gbl_config_decode}, {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.performance_robustness), diff --git a/drivers/acpi/resources/rsio.c b/drivers/acpi/resources/rsio.c index b297bc3e4419..50f3acdd9c8e 100644 --- a/drivers/acpi/resources/rsio.c +++ b/drivers/acpi/resources/rsio.c @@ -185,7 +185,7 @@ struct acpi_rsconvert_info acpi_rs_convert_end_tag[2] = { * ******************************************************************************/ -struct acpi_rsconvert_info acpi_rs_get_start_dpf[5] = { +struct acpi_rsconvert_info acpi_rs_get_start_dpf[6] = { {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_START_DEPENDENT, ACPI_RS_SIZE(struct acpi_resource_start_dependent), ACPI_RSC_TABLE_SIZE(acpi_rs_get_start_dpf)}, @@ -196,6 +196,12 @@ struct acpi_rsconvert_info acpi_rs_get_start_dpf[5] = { ACPI_ACCEPTABLE_CONFIGURATION, 2}, + /* Get the descriptor length (0 or 1 for Start Dpf descriptor) */ + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.start_dpf.descriptor_length), + AML_OFFSET(start_dpf.descriptor_type), + 0}, + /* All done if there is no flag byte present in the descriptor */ {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 1}, @@ -219,7 +225,9 @@ struct acpi_rsconvert_info acpi_rs_get_start_dpf[5] = { * ******************************************************************************/ -struct acpi_rsconvert_info acpi_rs_set_start_dpf[6] = { +struct acpi_rsconvert_info acpi_rs_set_start_dpf[10] = { + /* Start with a default descriptor of length 1 */ + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_START_DEPENDENT, sizeof(struct aml_resource_start_dependent), ACPI_RSC_TABLE_SIZE(acpi_rs_set_start_dpf)}, @@ -235,6 +243,33 @@ struct acpi_rsconvert_info acpi_rs_set_start_dpf[6] = { ACPI_RS_OFFSET(data.start_dpf.performance_robustness), AML_OFFSET(start_dpf.flags), 2}, + /* + * All done if the output descriptor length is required to be 1 + * (i.e., optimization to 0 bytes cannot be attempted) + */ + {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET(data.start_dpf.descriptor_length), + 1}, + + /* Set length to 0 bytes (no flags byte) */ + + {ACPI_RSC_LENGTH, 0, 0, + sizeof(struct aml_resource_start_dependent_noprio)}, + + /* + * All done if the output descriptor length is required to be 0. + * + * TBD: Perhaps we should check for error if input flags are not + * compatible with a 0-byte descriptor. + */ + {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET(data.start_dpf.descriptor_length), + 0}, + + /* Reset length to 1 byte (descriptor with flags byte) */ + + {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_irq)}, + /* * All done if flags byte is necessary -- if either priority value * is not ACPI_ACCEPTABLE_CONFIGURATION diff --git a/drivers/acpi/resources/rsirq.c b/drivers/acpi/resources/rsirq.c index 5657f7b95039..382a77b8400d 100644 --- a/drivers/acpi/resources/rsirq.c +++ b/drivers/acpi/resources/rsirq.c @@ -52,7 +52,7 @@ ACPI_MODULE_NAME("rsirq") * acpi_rs_get_irq * ******************************************************************************/ -struct acpi_rsconvert_info acpi_rs_get_irq[7] = { +struct acpi_rsconvert_info acpi_rs_get_irq[8] = { {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_IRQ, ACPI_RS_SIZE(struct acpi_resource_irq), ACPI_RSC_TABLE_SIZE(acpi_rs_get_irq)}, @@ -69,6 +69,12 @@ struct acpi_rsconvert_info acpi_rs_get_irq[7] = { ACPI_EDGE_SENSITIVE, 1}, + /* Get the descriptor length (2 or 3 for IRQ descriptor) */ + + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.irq.descriptor_length), + AML_OFFSET(irq.descriptor_type), + 0}, + /* All done if no flag byte present in descriptor */ {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 3}, @@ -94,7 +100,9 @@ struct acpi_rsconvert_info acpi_rs_get_irq[7] = { * ******************************************************************************/ -struct acpi_rsconvert_info acpi_rs_set_irq[9] = { +struct acpi_rsconvert_info acpi_rs_set_irq[13] = { + /* Start with a default descriptor of length 3 */ + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_IRQ, sizeof(struct aml_resource_irq), ACPI_RSC_TABLE_SIZE(acpi_rs_set_irq)}, @@ -105,7 +113,7 @@ struct acpi_rsconvert_info acpi_rs_set_irq[9] = { AML_OFFSET(irq.irq_mask), ACPI_RS_OFFSET(data.irq.interrupt_count)}, - /* Set the flags byte by default */ + /* Set the flags byte */ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.triggering), AML_OFFSET(irq.flags), @@ -118,6 +126,33 @@ struct acpi_rsconvert_info acpi_rs_set_irq[9] = { {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.sharable), AML_OFFSET(irq.flags), 4}, + + /* + * All done if the output descriptor length is required to be 3 + * (i.e., optimization to 2 bytes cannot be attempted) + */ + {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET(data.irq.descriptor_length), + 3}, + + /* Set length to 2 bytes (no flags byte) */ + + {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_irq_noflags)}, + + /* + * All done if the output descriptor length is required to be 2. + * + * TBD: Perhaps we should check for error if input flags are not + * compatible with a 2-byte descriptor. + */ + {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET(data.irq.descriptor_length), + 2}, + + /* Reset length to 3 bytes (descriptor with flags byte) */ + + {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_irq)}, + /* * Check if the flags byte is necessary. Not needed if the flags are: * ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_HIGH, ACPI_EXCLUSIVE @@ -134,7 +169,7 @@ struct acpi_rsconvert_info acpi_rs_set_irq[9] = { ACPI_RS_OFFSET(data.irq.sharable), ACPI_EXCLUSIVE}, - /* irq_no_flags() descriptor can be used */ + /* We can optimize to a 2-byte irq_no_flags() descriptor */ {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_irq_noflags)} }; diff --git a/drivers/acpi/resources/rsmisc.c b/drivers/acpi/resources/rsmisc.c index c7081afa893a..3e69eff303fb 100644 --- a/drivers/acpi/resources/rsmisc.c +++ b/drivers/acpi/resources/rsmisc.c @@ -497,6 +497,17 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, } break; + case ACPI_RSC_EXIT_EQ: + /* + * Control - Exit conversion if equal + */ + if (*ACPI_ADD_PTR(u8, resource, + COMPARE_TARGET(info)) == + COMPARE_VALUE(info)) { + goto exit; + } + break; + default: ACPI_ERROR((AE_INFO, "Invalid conversion opcode")); diff --git a/include/acpi/acresrc.h b/include/acpi/acresrc.h index 9486ab266a5e..33e9f3813220 100644 --- a/include/acpi/acresrc.h +++ b/include/acpi/acresrc.h @@ -94,6 +94,7 @@ typedef const struct acpi_rsconvert_info { #define ACPI_RSC_BITMASK16 18 #define ACPI_RSC_EXIT_NE 19 #define ACPI_RSC_EXIT_LE 20 +#define ACPI_RSC_EXIT_EQ 21 /* Resource Conversion sub-opcodes */ diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index bb44700680a3..599657eac2d4 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -986,6 +986,7 @@ struct acpi_vendor_uuid { * Structures used to describe device resources */ struct acpi_resource_irq { + u8 descriptor_length; u8 triggering; u8 polarity; u8 sharable; @@ -1002,6 +1003,7 @@ struct acpi_resource_dma { }; struct acpi_resource_start_dependent { + u8 descriptor_length; u8 compatibility_priority; u8 performance_robustness; }; -- cgit v1.2.2 From a3df4dadd446c0d7195f2bbe86dd5174426d8090 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Thu, 10 Apr 2008 19:06:43 +0400 Subject: ACPICA: Update behavior of CopyObject to match ACPI spec Fixed a problem where a CopyObject to RegionField, BankField, and IndexField objects did not perform an implicit conversion as it should. These types must retain their initial type permanently as per the ACPI specification. However, a CopyObject to all other object types should not perform an implicit conversion, as per the ACPI specification. http://www.acpica.org/bugzilla/show_bug.cgi?id=388 Signed-off-by: Lin Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/executer/exstore.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c index 725614e277f8..36c0fccb137a 100644 --- a/drivers/acpi/executer/exstore.c +++ b/drivers/acpi/executer/exstore.c @@ -603,10 +603,17 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, /* If no implicit conversion, drop into the default case below */ - if ((!implicit_conversion) || (walk_state->opcode == AML_COPY_OP)) { - - /* Force execution of default (no implicit conversion) */ - + if ((!implicit_conversion) || + ((walk_state->opcode == AML_COPY_OP) && + (target_type != ACPI_TYPE_LOCAL_REGION_FIELD) && + (target_type != ACPI_TYPE_LOCAL_BANK_FIELD) && + (target_type != ACPI_TYPE_LOCAL_INDEX_FIELD))) { + /* + * Force execution of default (no implicit conversion). Note: + * copy_object does not perform an implicit conversion, as per the ACPI + * spec -- except in case of region/bank/index fields -- because these + * objects must retain their original type permanently. + */ target_type = ACPI_TYPE_ANY; } -- cgit v1.2.2 From 24a3157a90ddf851a0880c0b8963bc43481cd85b Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:43 +0400 Subject: ACPICA: Fix for possible error when packages/buffers are passed to methods externally Fixed a problem where buffer and package objects passed as arguments to a control method via the external AcpiEvaluateObject interface could cause an AE_AML_INTERNAL exception depending on the order and type of operators executed by the target control method. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/utilities/utcopy.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c index 4c4021d82f99..4e9a62b34aef 100644 --- a/drivers/acpi/utilities/utcopy.c +++ b/drivers/acpi/utilities/utcopy.c @@ -511,6 +511,10 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, external_object->buffer.length); internal_object->buffer.length = external_object->buffer.length; + + /* Mark buffer data valid */ + + internal_object->buffer.flags |= AOPOBJ_DATA_VALID; break; case ACPI_TYPE_INTEGER: @@ -586,6 +590,10 @@ acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object, } } + /* Mark package data valid */ + + package_object->package.flags |= AOPOBJ_DATA_VALID; + *internal_object = package_object; return_ACPI_STATUS(status); } -- cgit v1.2.2 From a0144a2929620d9682bc4b0c6274ef03e417f49a Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:43 +0400 Subject: ACPICA: Update ACPICA version to 20080213 Update ACPICA version to 20080213. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- include/acpi/acconfig.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index c7d5c91bedee..2c85fd3c8182 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -63,7 +63,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20080123 +#define ACPI_CA_VERSION 0x20080213 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, -- cgit v1.2.2 From 0ba7d25c70699cdd3e06fc049d8884ee54b9d5db Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:43 +0400 Subject: ACPICA: Fix for extraneous debug message for packages Fixed a problem where an extraneous debug message was produced for package objects (when debugging enabled). The message "Package List length larger than NumElements count" is now produced in the correct case, and is also an error message rather than a debug message. Added a debug message for the opposite case, where NumElements is larger than the Package List, and the package has been padded out with NULL elements. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/dispatcher/dsobject.c | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c index 58d4d91c8e97..7562823b3b76 100644 --- a/drivers/acpi/dispatcher/dsobject.c +++ b/drivers/acpi/dispatcher/dsobject.c @@ -373,7 +373,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, union acpi_parse_object *parent; union acpi_operand_object *obj_desc = NULL; acpi_status status = AE_OK; - acpi_native_uint i; + unsigned i; u16 index; u16 reference_count; @@ -476,10 +476,37 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, arg = arg->common.next; } - if (!arg) { + /* Check for match between num_elements and actual length of package_list */ + + if (arg) { + /* + * num_elements was exhausted, but there are remaining elements in the + * package_list. + * + * Note: technically, this is an error, from ACPI spec: "It is an error + * for NumElements to be less than the number of elements in the + * PackageList". However, for now, we just print an error message and + * no exception is returned. + */ + while (arg) { + + /* Find out how many elements there really are */ + + i++; + arg = arg->common.next; + } + + ACPI_ERROR((AE_INFO, + "Package List length (%X) larger than NumElements count (%X), truncated\n", + i, element_count)); + } else if (i < element_count) { + /* + * Arg list (elements) was exhausted, but we did not reach num_elements count. + * Note: this is not an error, the package is padded out with NULLs. + */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Package List length larger than NumElements count (%X), truncated\n", - element_count)); + "Package List length (%X) smaller than NumElements count (%X), padded with null elements\n", + i, element_count)); } obj_desc->package.flags |= AOPOBJ_DATA_VALID; -- cgit v1.2.2 From 7a5bb9964512c5313af19310c6a3002ec54f7336 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Thu, 10 Apr 2008 19:06:43 +0400 Subject: ACPICA: Fix to handle NULL package elements correctly Fixed problem where NULL package elements were not returned to the AcpiEvaluateObject interface correctly. Instead of returning a NULL ACPI_OBJECT package element, the element was simply ignored, potentially causing a buffer overflow and/or confusing the caller who expected a fixed number of elements. http://bugzilla.kernel.org/show_bug.cgi?id=10132 Signed-off-by: Lin Ming Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/utilities/utobject.c | 5 ++--- include/acpi/actypes.h | 29 +++++++++++++++++------------ 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c index 1eccd3db876f..cdb8ff5b92d1 100644 --- a/drivers/acpi/utilities/utobject.c +++ b/drivers/acpi/utilities/utobject.c @@ -470,9 +470,8 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_POWER: - /* - * No extra data for these types - */ + /* No extra data for these types */ + break; case ACPI_TYPE_LOCAL_REFERENCE: diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 599657eac2d4..75ec153338e7 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -639,46 +639,51 @@ typedef u8 acpi_adr_space_type; /* * External ACPI object definition */ + +/* + * Note: Type == ACPI_TYPE_ANY (0) is used to indicate a NULL package element + * or an unresolved named reference. + */ union acpi_object { acpi_object_type type; /* See definition of acpi_ns_type for values */ struct { - acpi_object_type type; + acpi_object_type type; /* ACPI_TYPE_INTEGER */ acpi_integer value; /* The actual number */ } integer; struct { - acpi_object_type type; + acpi_object_type type; /* ACPI_TYPE_STRING */ u32 length; /* # of bytes in string, excluding trailing null */ char *pointer; /* points to the string value */ } string; struct { - acpi_object_type type; + acpi_object_type type; /* ACPI_TYPE_BUFFER */ u32 length; /* # of bytes in buffer */ u8 *pointer; /* points to the buffer */ } buffer; struct { - acpi_object_type type; - u32 fill1; - acpi_handle handle; /* object reference */ - } reference; - - struct { - acpi_object_type type; + acpi_object_type type; /* ACPI_TYPE_PACKAGE */ u32 count; /* # of elements in package */ union acpi_object *elements; /* Pointer to an array of ACPI_OBJECTs */ } package; struct { - acpi_object_type type; + acpi_object_type type; /* ACPI_TYPE_LOCAL_REFERENCE */ + acpi_object_type actual_type; /* Type associated with the Handle */ + acpi_handle handle; /* object reference */ + } reference; + + struct { + acpi_object_type type; /* ACPI_TYPE_PROCESSOR */ u32 proc_id; acpi_io_address pblk_address; u32 pblk_length; } processor; struct { - acpi_object_type type; + acpi_object_type type; /* ACPI_TYPE_POWER */ u32 system_level; u32 resource_order; } power_resource; -- cgit v1.2.2 From cd0b2248241f4146152fb04a6bf4bccb6ce0478a Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:43 +0400 Subject: ACPICA: Fixes for external Reference Objects All Reference Objects returned via the AcpiEvaluteObject interface are now marked as type "REFERENCE" instead of "ANY". The type ANY is now reservered for NULL objects - either NULL package elements or unresolved named references. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/scan.c | 3 +-- drivers/acpi/utilities/utcopy.c | 32 ++++++++++++++++++++++++-------- drivers/acpi/utils.c | 2 +- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index e6ce262b5d44..464ee6ea8c61 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -677,9 +677,8 @@ acpi_bus_extract_wakeup_device_power_package(struct acpi_device *device, device->wakeup.resources.count = package->package.count - 2; for (i = 0; i < device->wakeup.resources.count; i++) { element = &(package->package.elements[i + 2]); - if (element->type != ACPI_TYPE_ANY) { + if (element->type != ACPI_TYPE_LOCAL_REFERENCE) return AE_BAD_DATA; - } device->wakeup.resources.handles[i] = element->reference.handle; } diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c index 4e9a62b34aef..2a57c2c2c782 100644 --- a/drivers/acpi/utilities/utcopy.c +++ b/drivers/acpi/utilities/utcopy.c @@ -43,6 +43,8 @@ #include #include +#include + #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utcopy") @@ -172,22 +174,21 @@ acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object, case ACPI_TYPE_LOCAL_REFERENCE: - /* - * This is an object reference. Attempt to dereference it. - */ + /* This is an object reference. */ + switch (internal_object->reference.opcode) { case AML_INT_NAMEPATH_OP: /* For namepath, return the object handle ("reference") */ default: - /* - * Use the object type of "Any" to indicate a reference - * to object containing a handle to an ACPI named object. - */ - external_object->type = ACPI_TYPE_ANY; + + /* We are referring to the namespace node */ + external_object->reference.handle = internal_object->reference.node; + external_object->reference.actual_type = + acpi_ns_get_type(internal_object->reference.node); break; } break; @@ -460,6 +461,7 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: case ACPI_TYPE_INTEGER: + case ACPI_TYPE_LOCAL_REFERENCE: internal_object = acpi_ut_create_internal_object((u8) external_object-> @@ -469,6 +471,11 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, } break; + case ACPI_TYPE_ANY: /* This is the case for a NULL object */ + + *ret_internal_object = NULL; + return_ACPI_STATUS(AE_OK); + default: /* All other types are not supported */ @@ -522,6 +529,15 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, internal_object->integer.value = external_object->integer.value; break; + case ACPI_TYPE_LOCAL_REFERENCE: + + /* TBD: should validate incoming handle */ + + internal_object->reference.opcode = AML_INT_NAMEPATH_OP; + internal_object->reference.node = + external_object->reference.handle; + break; + default: /* Other types can't get here */ break; diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 44ea60cf21c0..100926143818 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -398,7 +398,7 @@ acpi_evaluate_reference(acpi_handle handle, element = &(package->package.elements[i]); - if (element->type != ACPI_TYPE_ANY) { + if (element->type != ACPI_TYPE_LOCAL_REFERENCE) { status = AE_BAD_DATA; printk(KERN_ERR PREFIX "Expecting a [Reference] package element, found type %X\n", -- cgit v1.2.2 From d8846574ed4a81be319bf68728f9cca9af595afd Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:43 +0400 Subject: ACPICA: Updates for Debug object output Implemented several improvements for the output of the ASL "Debug" object to clarify and keep all data for a given object on one output line. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/executer/exstore.c | 76 ++++++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 24 deletions(-) diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c index 36c0fccb137a..dbc5e18ee150 100644 --- a/drivers/acpi/executer/exstore.c +++ b/drivers/acpi/executer/exstore.c @@ -84,8 +84,12 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, ACPI_FUNCTION_TRACE_PTR(ex_do_debug_object, source_desc); - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %*s", - level, " ")); + /* Print line header as long as we are not in the middle of an object display */ + + if (!((level > 0) && index == 0)) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %*s", + level, " ")); + } /* Display index for package output only */ @@ -95,12 +99,12 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, } if (!source_desc) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "\n")); + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[Null Object]\n")); return_VOID; } if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s: ", + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s ", acpi_ut_get_object_type_name (source_desc))); @@ -162,7 +166,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, case ACPI_TYPE_PACKAGE: ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, - "[0x%.2X Elements]\n", + "[Contains 0x%.2X Elements]\n", source_desc->package.count)); /* Output the entire contents of the package */ @@ -194,8 +198,47 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, break; } - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "\n")); - if (source_desc->reference.object) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, " ")); + + /* Check for valid node first, then valid object */ + + if (source_desc->reference.node) { + if (ACPI_GET_DESCRIPTOR_TYPE + (source_desc->reference.node) != + ACPI_DESC_TYPE_NAMED) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, + " %p - Not a valid namespace node\n", + source_desc->reference. + node)); + } else { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, + "Node %p [%4.4s] ", + source_desc->reference. + node, + (source_desc->reference. + node)->name.ascii)); + + switch ((source_desc->reference.node)->type) { + + /* These types have no attached object */ + + case ACPI_TYPE_DEVICE: + acpi_os_printf("Device\n"); + break; + + case ACPI_TYPE_THERMAL: + acpi_os_printf("Thermal Zone\n"); + break; + + default: + acpi_ex_do_debug_object((source_desc-> + reference. + node)->object, + level + 4, 0); + break; + } + } + } else if (source_desc->reference.object) { if (ACPI_GET_DESCRIPTOR_TYPE (source_desc->reference.object) == ACPI_DESC_TYPE_NAMED) { @@ -208,28 +251,13 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, acpi_ex_do_debug_object(source_desc->reference. object, level + 4, 0); } - } else if (source_desc->reference.node) { - if (ACPI_GET_DESCRIPTOR_TYPE - (source_desc->reference.node) != - ACPI_DESC_TYPE_NAMED) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, - " %p - Not a valid namespace node\n", - source_desc->reference. - node)); - } else { - acpi_ex_do_debug_object((source_desc->reference. - node)->object, - level + 4, 0); - } } break; default: - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%p %s\n", - source_desc, - acpi_ut_get_object_type_name - (source_desc))); + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%p\n", + source_desc)); break; } -- cgit v1.2.2 From 66d3ca9ea28e1b3d591083772fd797b9b46410b8 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:44 +0400 Subject: ACPICA: Fixes for size of StartDependent resource descriptor Fixed a couple of size calculation issues with the variable-length Start Dependent resource descriptor. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/resources/rscalc.c | 11 +++++++++++ drivers/acpi/resources/rsio.c | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c index db0a835e3317..d801823de016 100644 --- a/drivers/acpi/resources/rscalc.c +++ b/drivers/acpi/resources/rscalc.c @@ -213,11 +213,22 @@ acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed) switch (resource->type) { case ACPI_RESOURCE_TYPE_IRQ: + /* Length can be 3 or 2 */ + if (resource->data.irq.descriptor_length == 2) { total_size--; } break; + case ACPI_RESOURCE_TYPE_START_DEPENDENT: + + /* Length can be 1 or 0 */ + + if (resource->data.irq.descriptor_length == 0) { + total_size--; + } + break; + case ACPI_RESOURCE_TYPE_VENDOR: /* * Vendor Defined Resource: diff --git a/drivers/acpi/resources/rsio.c b/drivers/acpi/resources/rsio.c index 50f3acdd9c8e..610d7c2101f2 100644 --- a/drivers/acpi/resources/rsio.c +++ b/drivers/acpi/resources/rsio.c @@ -268,7 +268,7 @@ struct acpi_rsconvert_info acpi_rs_set_start_dpf[10] = { /* Reset length to 1 byte (descriptor with flags byte) */ - {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_irq)}, + {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_start_dependent)}, /* * All done if flags byte is necessary -- if either priority value -- cgit v1.2.2 From 514d18d79b1da052ed4553ceec1f7e1197a5bb51 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 10 Apr 2008 19:06:44 +0400 Subject: ACPICA: Update for new Notify values Implemented several changes for Notify handling: Added support for new Notify values (ACPI 2.0+) and improved the Notify debug output. Notify on PowerResource objects is no longer allowed, as per the ACPI specification. Signed-off-by: Zhang Rui Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/events/evmisc.c | 59 +++++++++++++++------------------------ drivers/acpi/utilities/utglobal.c | 42 ++++++++++++++++++++++++++++ include/acpi/actypes.h | 24 ++++++++++------ include/acpi/acutils.h | 2 ++ 4 files changed, 82 insertions(+), 45 deletions(-) diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c index 4e7a13afe80c..16cf2700c16f 100644 --- a/drivers/acpi/events/evmisc.c +++ b/drivers/acpi/events/evmisc.c @@ -49,22 +49,7 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME("evmisc") -/* Names for Notify() values, used for debug output */ -#ifdef ACPI_DEBUG_OUTPUT -static const char *acpi_notify_value_names[] = { - "Bus Check", - "Device Check", - "Device Wake", - "Eject Request", - "Device Check Light", - "Frequency Mismatch", - "Bus Mode Mismatch", - "Power Fault" -}; -#endif - /* Pointer to FACS needed for the Global Lock */ - static struct acpi_table_facs *facs = NULL; /* Local prototypes */ @@ -94,7 +79,6 @@ u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node) switch (node->type) { case ACPI_TYPE_DEVICE: case ACPI_TYPE_PROCESSOR: - case ACPI_TYPE_POWER: case ACPI_TYPE_THERMAL: /* * These are the ONLY objects that can receive ACPI notifications @@ -139,17 +123,9 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, * initiate soft-off or sleep operation? */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Dispatching Notify(%X) on node %p\n", notify_value, - node)); - - if (notify_value <= 7) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notify value: %s\n", - acpi_notify_value_names[notify_value])); - } else { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Notify value: 0x%2.2X **Device Specific**\n", - notify_value)); - } + "Dispatching Notify on [%4.4s] Node %p Value 0x%2.2X (%s)\n", + acpi_ut_get_node_name(node), node, notify_value, + acpi_ut_get_notify_name(notify_value))); /* Get the notify object attached to the NS Node */ @@ -159,10 +135,12 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, /* We have the notify object, Get the right handler */ switch (node->type) { + + /* Notify allowed only on these types */ + case ACPI_TYPE_DEVICE: case ACPI_TYPE_THERMAL: case ACPI_TYPE_PROCESSOR: - case ACPI_TYPE_POWER: if (notify_value <= ACPI_MAX_SYS_NOTIFY) { handler_obj = @@ -179,8 +157,13 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, } } - /* If there is any handler to run, schedule the dispatcher */ - + /* + * If there is any handler to run, schedule the dispatcher. + * Check for: + * 1) Global system notify handler + * 2) Global device notify handler + * 3) Per-device notify handler + */ if ((acpi_gbl_system_notify.handler && (notify_value <= ACPI_MAX_SYS_NOTIFY)) || (acpi_gbl_device_notify.handler @@ -190,6 +173,13 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, return (AE_NO_MEMORY); } + if (!handler_obj) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Executing system notify handler for Notify (%4.4s, %X) node %p\n", + acpi_ut_get_node_name(node), + notify_value, node)); + } + notify_info->common.descriptor_type = ACPI_DESC_TYPE_STATE_NOTIFY; notify_info->notify.node = node; @@ -202,15 +192,12 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, if (ACPI_FAILURE(status)) { acpi_ut_delete_generic_state(notify_info); } - } - - if (!handler_obj) { + } else { /* - * There is no per-device notify handler for this device. - * This may or may not be a problem. + * There is no notify handler (per-device or system) for this device. */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "No notify handler for Notify(%4.4s, %X) node %p\n", + "No notify handler for Notify (%4.4s, %X) node %p\n", acpi_ut_get_node_name(node), notify_value, node)); } diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index d2097ded262d..d0226fedb004 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c @@ -602,6 +602,48 @@ char *acpi_ut_get_mutex_name(u32 mutex_id) return (acpi_gbl_mutex_names[mutex_id]); } + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_notify_name + * + * PARAMETERS: notify_value - Value from the Notify() request + * + * RETURN: String corresponding to the Notify Value. + * + * DESCRIPTION: Translate a Notify Value to a notify namestring. + * + ******************************************************************************/ + +/* Names for Notify() values, used for debug output */ + +static const char *acpi_gbl_notify_value_names[] = { + "Bus Check", + "Device Check", + "Device Wake", + "Eject Request", + "Device Check Light", + "Frequency Mismatch", + "Bus Mode Mismatch", + "Power Fault", + "Capabilities Check", + "Device PLD Check", + "Reserved", + "System Locality Update" +}; + +const char *acpi_ut_get_notify_name(u32 notify_value) +{ + + if (notify_value <= ACPI_NOTIFY_MAX) { + return (acpi_gbl_notify_value_names[notify_value]); + } else if (notify_value <= ACPI_MAX_SYS_NOTIFY) { + return ("Reserved"); + } else { /* Greater or equal to 0x80 */ + + return ("**Device Specific**"); + } +} #endif /******************************************************************************* diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 75ec153338e7..cc24cef6ce93 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -402,14 +402,20 @@ typedef unsigned long long acpi_integer; /* * Standard notify values */ -#define ACPI_NOTIFY_BUS_CHECK (u8) 0 -#define ACPI_NOTIFY_DEVICE_CHECK (u8) 1 -#define ACPI_NOTIFY_DEVICE_WAKE (u8) 2 -#define ACPI_NOTIFY_EJECT_REQUEST (u8) 3 -#define ACPI_NOTIFY_DEVICE_CHECK_LIGHT (u8) 4 -#define ACPI_NOTIFY_FREQUENCY_MISMATCH (u8) 5 -#define ACPI_NOTIFY_BUS_MODE_MISMATCH (u8) 6 -#define ACPI_NOTIFY_POWER_FAULT (u8) 7 +#define ACPI_NOTIFY_BUS_CHECK (u8) 0x00 +#define ACPI_NOTIFY_DEVICE_CHECK (u8) 0x01 +#define ACPI_NOTIFY_DEVICE_WAKE (u8) 0x02 +#define ACPI_NOTIFY_EJECT_REQUEST (u8) 0x03 +#define ACPI_NOTIFY_DEVICE_CHECK_LIGHT (u8) 0x04 +#define ACPI_NOTIFY_FREQUENCY_MISMATCH (u8) 0x05 +#define ACPI_NOTIFY_BUS_MODE_MISMATCH (u8) 0x06 +#define ACPI_NOTIFY_POWER_FAULT (u8) 0x07 +#define ACPI_NOTIFY_CAPABILITIES_CHECK (u8) 0x08 +#define ACPI_NOTIFY_DEVICE_PLD_CHECK (u8) 0x09 +#define ACPI_NOTIFY_RESERVED (u8) 0x0A +#define ACPI_NOTIFY_LOCALITY_UPDATE (u8) 0x0B + +#define ACPI_NOTIFY_MAX 0x0B /* * Types associated with ACPI names and objects. The first group of @@ -584,7 +590,7 @@ typedef u32 acpi_event_status; #define ACPI_SYSTEM_NOTIFY 0x1 #define ACPI_DEVICE_NOTIFY 0x2 -#define ACPI_ALL_NOTIFY 0x3 +#define ACPI_ALL_NOTIFY (ACPI_SYSTEM_NOTIFY | ACPI_DEVICE_NOTIFY) #define ACPI_MAX_NOTIFY_HANDLER_TYPE 0x3 #define ACPI_MAX_SYS_NOTIFY 0x7f diff --git a/include/acpi/acutils.h b/include/acpi/acutils.h index a2918547c73f..26115da8c099 100644 --- a/include/acpi/acutils.h +++ b/include/acpi/acutils.h @@ -116,6 +116,8 @@ void acpi_ut_init_globals(void); char *acpi_ut_get_mutex_name(u32 mutex_id); +const char *acpi_ut_get_notify_name(u32 notify_value); + #endif char *acpi_ut_get_type_name(acpi_object_type type); -- cgit v1.2.2 From 66e2c0bcc5f6b8454d9091f6ba9ef4090abca4fd Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:44 +0400 Subject: ACPICA: Update version to 20080321 Update version to 20080321. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- include/acpi/acconfig.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index 2c85fd3c8182..b4668b13d38c 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -63,7 +63,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20080213 +#define ACPI_CA_VERSION 0x20080321 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, -- cgit v1.2.2 From cca97b81564c5edbc8700ebb64fc2b4e13dfa51f Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 10 Apr 2008 19:06:44 +0400 Subject: ACPICA: Fix for some local named nodes not marked temporary and to disallow duplicates Fixed a problem with the CreateField, CreateXXXField (Bit, Byte, Word, Dword, Qword), Field, BankField, and IndexField operators when invoked from inside an executing control method. In this case, these operators created namespace nodes that were incorrectly left marked as permanent nodes instead of temporary nodes. This could cause a problem if there is race condition between an exiting control method and a running namespace walk. (Reported by Linn Crosetto). Fixed a problem where the CreateField and CreateXXXField operators would incorrectly allow duplicate names (the name of the field) with no exception generated. Signed-off-by: Bob Moore Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/dispatcher/dsfield.c | 121 +++++++++++++++++++++++--------------- drivers/acpi/dispatcher/dswload.c | 6 ++ 2 files changed, 79 insertions(+), 48 deletions(-) diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c index e87f6bfbfa5c..0befcff19f5a 100644 --- a/drivers/acpi/dispatcher/dsfield.c +++ b/drivers/acpi/dispatcher/dsfield.c @@ -89,12 +89,16 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, ACPI_FUNCTION_TRACE(ds_create_buffer_field); - /* Get the name_string argument */ - + /* + * Get the name_string argument (name of the new buffer_field) + */ if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { + + /* For create_field, name is the 4th argument */ + arg = acpi_ps_get_arg(op, 3); } else { - /* Create Bit/Byte/Word/Dword field */ + /* For all other create_xXXField operators, name is the 3rd argument */ arg = acpi_ps_get_arg(op, 2); } @@ -107,26 +111,30 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, node = walk_state->deferred_node; status = AE_OK; } else { - /* - * During the load phase, we want to enter the name of the field into - * the namespace. During the execute phase (when we evaluate the size - * operand), we want to lookup the name - */ - if (walk_state->parse_flags & ACPI_PARSE_EXECUTE) { - flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE; - } else { - flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | - ACPI_NS_ERROR_IF_FOUND; + /* Execute flag should always be set when this function is entered */ + + if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) { + return_ACPI_STATUS(AE_AML_INTERNAL); } - /* - * Enter the name_string into the namespace - */ + /* Creating new namespace node, should not already exist */ + + flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | + ACPI_NS_ERROR_IF_FOUND; + + /* Mark node temporary if we are executing a method */ + + if (walk_state->method_node) { + flags |= ACPI_NS_TEMPORARY; + } + + /* Enter the name_string into the namespace */ + status = acpi_ns_lookup(walk_state->scope_info, arg->common.value.string, ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS1, flags, walk_state, - &(node)); + &node); if (ACPI_FAILURE(status)) { ACPI_ERROR_NAMESPACE(arg->common.value.string, status); return_ACPI_STATUS(status); @@ -136,13 +144,13 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, /* * We could put the returned object (Node) on the object stack for later, * but for now, we will put it in the "op" object that the parser uses, - * so we can get it again at the end of this scope + * so we can get it again at the end of this scope. */ op->common.node = node; /* * If there is no object attached to the node, this node was just created - * and we need to create the field object. Otherwise, this was a lookup + * and we need to create the field object. Otherwise, this was a lookup * of an existing node and we don't want to create the field object again. */ obj_desc = acpi_ns_get_attached_object(node); @@ -164,9 +172,8 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, } /* - * Remember location in AML stream of the field unit - * opcode and operands -- since the buffer and index - * operands must be evaluated. + * Remember location in AML stream of the field unit opcode and operands -- + * since the buffer and index operands must be evaluated. */ second_desc = obj_desc->common.next_object; second_desc->extra.aml_start = op->named.data; @@ -261,7 +268,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, case AML_INT_NAMEDFIELD_OP: - /* Lookup the name */ + /* Lookup the name, it should already exist */ status = acpi_ns_lookup(walk_state->scope_info, (char *)&arg->named.name, @@ -272,19 +279,16 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, if (ACPI_FAILURE(status)) { ACPI_ERROR_NAMESPACE((char *)&arg->named.name, status); - if (status != AE_ALREADY_EXISTS) { - return_ACPI_STATUS(status); - } - - /* Already exists, ignore error */ + return_ACPI_STATUS(status); } else { arg->common.node = info->field_node; info->field_bit_length = arg->common.value.size; /* - * If there is no object attached to the node, this node was just created - * and we need to create the field object. Otherwise, this was a lookup - * of an existing node and we don't want to create the field object again. + * If there is no object attached to the node, this node was + * just created and we need to create the field object. + * Otherwise, this was a lookup of an existing node and we + * don't want to create the field object again. */ if (!acpi_ns_get_attached_object (info->field_node)) { @@ -409,18 +413,23 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op); - /* - * During the load phase, we want to enter the name of the field into - * the namespace. During the execute phase (when we evaluate the bank_value - * operand), we want to lookup the name. - */ - if (walk_state->deferred_node) { - flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE; - } else { - flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | - ACPI_NS_ERROR_IF_FOUND; + /* Execute flag should always be set when this function is entered */ + + if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) { + if (walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP) { + + /* bank_field Op is deferred, just return OK */ + + return_ACPI_STATUS(AE_OK); + } + + return_ACPI_STATUS(AE_AML_INTERNAL); } + /* + * Get the field_list argument for this opcode. This is the start of the + * list of field elements. + */ switch (walk_state->opcode) { case AML_FIELD_OP: arg = acpi_ps_get_arg(op, 2); @@ -441,18 +450,34 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, return_ACPI_STATUS(AE_BAD_PARAMETER); } + if (!arg) { + return_ACPI_STATUS(AE_AML_NO_OPERAND); + } + + /* Creating new namespace node(s), should not already exist */ + + flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | + ACPI_NS_ERROR_IF_FOUND; + + /* Mark node(s) temporary if we are executing a method */ + + if (walk_state->method_node) { + flags |= ACPI_NS_TEMPORARY; + } + /* * Walk the list of entries in the field_list */ while (arg) { - - /* Ignore OFFSET and ACCESSAS terms here */ - + /* + * Ignore OFFSET and ACCESSAS terms here; we are only interested in the + * field names in order to enter them into the namespace. + */ if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { status = acpi_ns_lookup(walk_state->scope_info, - (char *)&arg->named.name, - type, ACPI_IMODE_LOAD_PASS1, - flags, walk_state, &node); + (char *)&arg->named.name, type, + ACPI_IMODE_LOAD_PASS1, flags, + walk_state, &node); if (ACPI_FAILURE(status)) { ACPI_ERROR_NAMESPACE((char *)&arg->named.name, status); @@ -468,7 +493,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, arg->common.node = node; } - /* Move to next field in the list */ + /* Get the next field element in the list */ arg = arg->common.next; } diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c index ec68c1df3932..775b18390c36 100644 --- a/drivers/acpi/dispatcher/dswload.c +++ b/drivers/acpi/dispatcher/dswload.c @@ -776,6 +776,12 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, acpi_ns_lookup(walk_state->scope_info, buffer_ptr, object_type, ACPI_IMODE_LOAD_PASS2, flags, walk_state, &node); + + if (ACPI_SUCCESS(status) && (flags & ACPI_NS_TEMPORARY)) { + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "***New Node [%4.4s] %p is temporary\n", + acpi_ut_get_node_name(node), node)); + } break; } -- cgit v1.2.2 From 75a44ce00b312f57264f42a0a985d17cd9994b98 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 23 Apr 2008 23:00:13 -0400 Subject: ACPICA: update Intel copyright Signed-off-by: Len Brown --- drivers/acpi/dispatcher/dsfield.c | 2 +- drivers/acpi/dispatcher/dsinit.c | 2 +- drivers/acpi/dispatcher/dsmethod.c | 2 +- drivers/acpi/dispatcher/dsmthdat.c | 2 +- drivers/acpi/dispatcher/dsobject.c | 2 +- drivers/acpi/dispatcher/dsopcode.c | 2 +- drivers/acpi/dispatcher/dsutils.c | 2 +- drivers/acpi/dispatcher/dswexec.c | 2 +- drivers/acpi/dispatcher/dswload.c | 2 +- drivers/acpi/dispatcher/dswscope.c | 2 +- drivers/acpi/dispatcher/dswstate.c | 2 +- drivers/acpi/events/evevent.c | 2 +- drivers/acpi/events/evgpe.c | 2 +- drivers/acpi/events/evgpeblk.c | 2 +- drivers/acpi/events/evmisc.c | 2 +- drivers/acpi/events/evregion.c | 2 +- drivers/acpi/events/evrgnini.c | 2 +- drivers/acpi/events/evsci.c | 2 +- drivers/acpi/events/evxface.c | 2 +- drivers/acpi/events/evxfevnt.c | 2 +- drivers/acpi/events/evxfregn.c | 2 +- drivers/acpi/executer/exconfig.c | 2 +- drivers/acpi/executer/exconvrt.c | 2 +- drivers/acpi/executer/excreate.c | 2 +- drivers/acpi/executer/exdump.c | 2 +- drivers/acpi/executer/exfield.c | 2 +- drivers/acpi/executer/exfldio.c | 2 +- drivers/acpi/executer/exmisc.c | 2 +- drivers/acpi/executer/exmutex.c | 2 +- drivers/acpi/executer/exnames.c | 2 +- drivers/acpi/executer/exoparg1.c | 2 +- drivers/acpi/executer/exoparg2.c | 2 +- drivers/acpi/executer/exoparg3.c | 2 +- drivers/acpi/executer/exoparg6.c | 2 +- drivers/acpi/executer/exprep.c | 2 +- drivers/acpi/executer/exregion.c | 2 +- drivers/acpi/executer/exresnte.c | 2 +- drivers/acpi/executer/exresolv.c | 2 +- drivers/acpi/executer/exresop.c | 2 +- drivers/acpi/executer/exstore.c | 2 +- drivers/acpi/executer/exstoren.c | 2 +- drivers/acpi/executer/exstorob.c | 2 +- drivers/acpi/executer/exsystem.c | 2 +- drivers/acpi/executer/exutils.c | 2 +- drivers/acpi/hardware/hwacpi.c | 2 +- drivers/acpi/hardware/hwgpe.c | 2 +- drivers/acpi/hardware/hwregs.c | 2 +- drivers/acpi/hardware/hwsleep.c | 2 +- drivers/acpi/hardware/hwtimer.c | 2 +- drivers/acpi/namespace/nsaccess.c | 2 +- drivers/acpi/namespace/nsalloc.c | 2 +- drivers/acpi/namespace/nsdump.c | 2 +- drivers/acpi/namespace/nsdumpdv.c | 2 +- drivers/acpi/namespace/nseval.c | 2 +- drivers/acpi/namespace/nsinit.c | 2 +- drivers/acpi/namespace/nsload.c | 2 +- drivers/acpi/namespace/nsnames.c | 2 +- drivers/acpi/namespace/nsobject.c | 2 +- drivers/acpi/namespace/nsparse.c | 2 +- drivers/acpi/namespace/nssearch.c | 2 +- drivers/acpi/namespace/nsutils.c | 2 +- drivers/acpi/namespace/nswalk.c | 2 +- drivers/acpi/namespace/nsxfeval.c | 2 +- drivers/acpi/namespace/nsxfname.c | 2 +- drivers/acpi/namespace/nsxfobj.c | 2 +- drivers/acpi/parser/psargs.c | 2 +- drivers/acpi/parser/psloop.c | 2 +- drivers/acpi/parser/psopcode.c | 2 +- drivers/acpi/parser/psparse.c | 2 +- drivers/acpi/parser/psscope.c | 2 +- drivers/acpi/parser/pstree.c | 2 +- drivers/acpi/parser/psutils.c | 2 +- drivers/acpi/parser/pswalk.c | 2 +- drivers/acpi/parser/psxface.c | 2 +- drivers/acpi/resources/rsaddr.c | 2 +- drivers/acpi/resources/rscalc.c | 2 +- drivers/acpi/resources/rscreate.c | 2 +- drivers/acpi/resources/rsdump.c | 2 +- drivers/acpi/resources/rsinfo.c | 2 +- drivers/acpi/resources/rsio.c | 2 +- drivers/acpi/resources/rsirq.c | 2 +- drivers/acpi/resources/rslist.c | 2 +- drivers/acpi/resources/rsmemory.c | 2 +- drivers/acpi/resources/rsmisc.c | 2 +- drivers/acpi/resources/rsutils.c | 2 +- drivers/acpi/resources/rsxface.c | 2 +- drivers/acpi/tables/tbfadt.c | 2 +- drivers/acpi/tables/tbfind.c | 2 +- drivers/acpi/tables/tbinstal.c | 2 +- drivers/acpi/tables/tbutils.c | 2 +- drivers/acpi/tables/tbxface.c | 2 +- drivers/acpi/tables/tbxfroot.c | 2 +- drivers/acpi/utilities/utalloc.c | 2 +- drivers/acpi/utilities/utcache.c | 2 +- drivers/acpi/utilities/utcopy.c | 2 +- drivers/acpi/utilities/utdebug.c | 2 +- drivers/acpi/utilities/utdelete.c | 2 +- drivers/acpi/utilities/uteval.c | 2 +- drivers/acpi/utilities/utglobal.c | 2 +- drivers/acpi/utilities/utinit.c | 2 +- drivers/acpi/utilities/utmath.c | 2 +- drivers/acpi/utilities/utmisc.c | 2 +- drivers/acpi/utilities/utmutex.c | 2 +- drivers/acpi/utilities/utobject.c | 2 +- drivers/acpi/utilities/utresrc.c | 2 +- drivers/acpi/utilities/utstate.c | 2 +- drivers/acpi/utilities/utxface.c | 2 +- include/acpi/acconfig.h | 2 +- include/acpi/acdebug.h | 2 +- include/acpi/acdisasm.h | 2 +- include/acpi/acdispat.h | 2 +- include/acpi/acevents.h | 2 +- include/acpi/acexcep.h | 2 +- include/acpi/acglobal.h | 2 +- include/acpi/achware.h | 2 +- include/acpi/acinterp.h | 2 +- include/acpi/aclocal.h | 2 +- include/acpi/acmacros.h | 2 +- include/acpi/acnames.h | 2 +- include/acpi/acnamesp.h | 2 +- include/acpi/acobject.h | 2 +- include/acpi/acopcode.h | 2 +- include/acpi/acoutput.h | 2 +- include/acpi/acparser.h | 2 +- include/acpi/acpi.h | 2 +- include/acpi/acpiosxf.h | 2 +- include/acpi/acpixf.h | 2 +- include/acpi/acresrc.h | 2 +- include/acpi/acstruct.h | 2 +- include/acpi/actables.h | 2 +- include/acpi/actbl.h | 2 +- include/acpi/actbl1.h | 2 +- include/acpi/actypes.h | 2 +- include/acpi/acutils.h | 2 +- include/acpi/amlcode.h | 2 +- include/acpi/amlresrc.h | 2 +- include/acpi/platform/acenv.h | 2 +- include/acpi/platform/acgcc.h | 2 +- include/acpi/platform/aclinux.h | 2 +- 139 files changed, 139 insertions(+), 139 deletions(-) diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c index 0befcff19f5a..c78078315be9 100644 --- a/drivers/acpi/dispatcher/dsfield.c +++ b/drivers/acpi/dispatcher/dsfield.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/dispatcher/dsinit.c b/drivers/acpi/dispatcher/dsinit.c index af923c388520..610b1ee102b0 100644 --- a/drivers/acpi/dispatcher/dsinit.c +++ b/drivers/acpi/dispatcher/dsinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index 7a99740248c7..e48a3ea03117 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c index ba4626e06a5e..13c43eac35db 100644 --- a/drivers/acpi/dispatcher/dsmthdat.c +++ b/drivers/acpi/dispatcher/dsmthdat.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c index 7562823b3b76..1022e38994c2 100644 --- a/drivers/acpi/dispatcher/dsobject.c +++ b/drivers/acpi/dispatcher/dsobject.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c index 35a7efdb5ad9..a818e0ddb996 100644 --- a/drivers/acpi/dispatcher/dsopcode.c +++ b/drivers/acpi/dispatcher/dsopcode.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c index f6c28d7b46c5..b398982f0d8b 100644 --- a/drivers/acpi/dispatcher/dsutils.c +++ b/drivers/acpi/dispatcher/dsutils.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c index bfe4450fa588..b246b9657ead 100644 --- a/drivers/acpi/dispatcher/dswexec.c +++ b/drivers/acpi/dispatcher/dswexec.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c index 775b18390c36..dff7a3e445a8 100644 --- a/drivers/acpi/dispatcher/dswload.c +++ b/drivers/acpi/dispatcher/dswload.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/dispatcher/dswscope.c b/drivers/acpi/dispatcher/dswscope.c index 3927c495e4bf..9e6073265873 100644 --- a/drivers/acpi/dispatcher/dswscope.c +++ b/drivers/acpi/dispatcher/dswscope.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c index 4c402be3c74a..1386ced332ec 100644 --- a/drivers/acpi/dispatcher/dswstate.c +++ b/drivers/acpi/dispatcher/dswstate.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c index 3048801a37b5..5d30e5be1b1c 100644 --- a/drivers/acpi/events/evevent.c +++ b/drivers/acpi/events/evevent.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c index 0dadd2adc800..f55e1fd9e0b8 100644 --- a/drivers/acpi/events/evgpe.c +++ b/drivers/acpi/events/evgpe.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c index 361ebe6c4a6f..e6c4d4c49e79 100644 --- a/drivers/acpi/events/evgpeblk.c +++ b/drivers/acpi/events/evgpeblk.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c index 16cf2700c16f..2113e58e2221 100644 --- a/drivers/acpi/events/evmisc.c +++ b/drivers/acpi/events/evmisc.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c index 03624e94778e..1628f5934752 100644 --- a/drivers/acpi/events/evregion.c +++ b/drivers/acpi/events/evregion.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c index b1aaa0e84588..2e3d2c5e4f4d 100644 --- a/drivers/acpi/events/evrgnini.c +++ b/drivers/acpi/events/evrgnini.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/events/evsci.c b/drivers/acpi/events/evsci.c index 7e5d15ce2395..2a8b77877610 100644 --- a/drivers/acpi/events/evsci.c +++ b/drivers/acpi/events/evsci.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c index 412cae698311..94a6efe020be 100644 --- a/drivers/acpi/events/evxface.c +++ b/drivers/acpi/events/evxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c index 9cbd3414a574..99a7502e6a87 100644 --- a/drivers/acpi/events/evxfevnt.c +++ b/drivers/acpi/events/evxfevnt.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/events/evxfregn.c b/drivers/acpi/events/evxfregn.c index 7bf09c5fb242..e8750807e57d 100644 --- a/drivers/acpi/events/evxfregn.c +++ b/drivers/acpi/events/evxfregn.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index ed92fb5a1d2b..24da921d13e3 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c index 79f2c0d42c06..fd954b4ed83d 100644 --- a/drivers/acpi/executer/exconvrt.c +++ b/drivers/acpi/executer/exconvrt.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c index 0396bd4819f1..60e62c4f0577 100644 --- a/drivers/acpi/executer/excreate.c +++ b/drivers/acpi/executer/excreate.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c index ed560e656f9a..74f1b22601b3 100644 --- a/drivers/acpi/executer/exdump.c +++ b/drivers/acpi/executer/exdump.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c index aef8db82570a..3e440d84226a 100644 --- a/drivers/acpi/executer/exfield.c +++ b/drivers/acpi/executer/exfield.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c index ae402949c357..e336b5dc7a50 100644 --- a/drivers/acpi/executer/exfldio.c +++ b/drivers/acpi/executer/exfldio.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c index f13d1cec2d6d..cc956a5b5267 100644 --- a/drivers/acpi/executer/exmisc.c +++ b/drivers/acpi/executer/exmisc.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c index b8d035c00b61..c873ab40cd0e 100644 --- a/drivers/acpi/executer/exmutex.c +++ b/drivers/acpi/executer/exmutex.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/exnames.c b/drivers/acpi/executer/exnames.c index 308eae52dc05..817e67be3697 100644 --- a/drivers/acpi/executer/exnames.c +++ b/drivers/acpi/executer/exnames.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c index 313803b53125..7c3bea575e02 100644 --- a/drivers/acpi/executer/exoparg1.c +++ b/drivers/acpi/executer/exoparg1.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c index 81c02b12d3f2..8e8bbb6ccebd 100644 --- a/drivers/acpi/executer/exoparg2.c +++ b/drivers/acpi/executer/exoparg2.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/exoparg3.c b/drivers/acpi/executer/exoparg3.c index a573f5d260f7..9cb4197681af 100644 --- a/drivers/acpi/executer/exoparg3.c +++ b/drivers/acpi/executer/exoparg3.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/exoparg6.c b/drivers/acpi/executer/exoparg6.c index 163b2b3d9ce2..67d48737af53 100644 --- a/drivers/acpi/executer/exoparg6.c +++ b/drivers/acpi/executer/exoparg6.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c index 6eb45bf355f1..3a2f8cd4c62a 100644 --- a/drivers/acpi/executer/exprep.c +++ b/drivers/acpi/executer/exprep.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/exregion.c b/drivers/acpi/executer/exregion.c index cbc67884454f..7cd8bb54fa01 100644 --- a/drivers/acpi/executer/exregion.c +++ b/drivers/acpi/executer/exregion.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c index 42c8a0f8894c..5596f42c9676 100644 --- a/drivers/acpi/executer/exresnte.c +++ b/drivers/acpi/executer/exresnte.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c index 5b5b2ff45ea2..b35f7c817acf 100644 --- a/drivers/acpi/executer/exresolv.c +++ b/drivers/acpi/executer/exresolv.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c index 259047a383c2..73e29e566a70 100644 --- a/drivers/acpi/executer/exresop.c +++ b/drivers/acpi/executer/exresop.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c index dbc5e18ee150..76c875bc3154 100644 --- a/drivers/acpi/executer/exstore.c +++ b/drivers/acpi/executer/exstore.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c index 1d622c625c64..a6d2168b81f9 100644 --- a/drivers/acpi/executer/exstoren.c +++ b/drivers/acpi/executer/exstoren.c @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/exstorob.c b/drivers/acpi/executer/exstorob.c index 8233d40178ee..9a75ff09fb0c 100644 --- a/drivers/acpi/executer/exstorob.c +++ b/drivers/acpi/executer/exstorob.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c index a20a974f7fac..68990f1df371 100644 --- a/drivers/acpi/executer/exsystem.c +++ b/drivers/acpi/executer/exsystem.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c index 1b93f4dded4c..86c03880b523 100644 --- a/drivers/acpi/executer/exutils.c +++ b/drivers/acpi/executer/exutils.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/hardware/hwacpi.c b/drivers/acpi/hardware/hwacpi.c index 6031ca13dd2f..816894ea839e 100644 --- a/drivers/acpi/hardware/hwacpi.c +++ b/drivers/acpi/hardware/hwacpi.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/hardware/hwgpe.c index 117a05cadaaa..14bc4f456ae8 100644 --- a/drivers/acpi/hardware/hwgpe.c +++ b/drivers/acpi/hardware/hwgpe.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c index 73f9c5fb1ba7..ddf792adcf96 100644 --- a/drivers/acpi/hardware/hwregs.c +++ b/drivers/acpi/hardware/hwregs.c @@ -7,7 +7,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c index 202f11af3689..d9937e05ec6a 100644 --- a/drivers/acpi/hardware/hwsleep.c +++ b/drivers/acpi/hardware/hwsleep.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/hardware/hwtimer.c b/drivers/acpi/hardware/hwtimer.c index c32eab696acd..b53d575491b9 100644 --- a/drivers/acpi/hardware/hwtimer.c +++ b/drivers/acpi/hardware/hwtimer.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c index 54852fbfc878..c39a7f68b889 100644 --- a/drivers/acpi/namespace/nsaccess.c +++ b/drivers/acpi/namespace/nsaccess.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c index 1d693d8ad2d8..3a1740ac2edc 100644 --- a/drivers/acpi/namespace/nsalloc.c +++ b/drivers/acpi/namespace/nsalloc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c index 3068e20911f4..5445751b8a3e 100644 --- a/drivers/acpi/namespace/nsdump.c +++ b/drivers/acpi/namespace/nsdump.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/namespace/nsdumpdv.c b/drivers/acpi/namespace/nsdumpdv.c index 5097e167939e..428f50fde11a 100644 --- a/drivers/acpi/namespace/nsdumpdv.c +++ b/drivers/acpi/namespace/nsdumpdv.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c index 97b2ac57c16b..14bdfa92bea0 100644 --- a/drivers/acpi/namespace/nseval.c +++ b/drivers/acpi/namespace/nseval.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c index 72b32454ce3c..6d6d930c8e18 100644 --- a/drivers/acpi/namespace/nsinit.c +++ b/drivers/acpi/namespace/nsinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c index 1bfcb6f3f44f..2c92f6cf5ce1 100644 --- a/drivers/acpi/namespace/nsload.c +++ b/drivers/acpi/namespace/nsload.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c index ba1a4f00ba12..cffef1bcbdbc 100644 --- a/drivers/acpi/namespace/nsnames.c +++ b/drivers/acpi/namespace/nsnames.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/namespace/nsobject.c b/drivers/acpi/namespace/nsobject.c index d9d7377bc6e6..15fe09e24f71 100644 --- a/drivers/acpi/namespace/nsobject.c +++ b/drivers/acpi/namespace/nsobject.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/namespace/nsparse.c b/drivers/acpi/namespace/nsparse.c index f260b6941c13..46a79b0103b6 100644 --- a/drivers/acpi/namespace/nsparse.c +++ b/drivers/acpi/namespace/nsparse.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c index e863be665ce8..8399276cba1e 100644 --- a/drivers/acpi/namespace/nssearch.c +++ b/drivers/acpi/namespace/nssearch.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c index 90fd059615ff..64c039843ed2 100644 --- a/drivers/acpi/namespace/nsutils.c +++ b/drivers/acpi/namespace/nsutils.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/namespace/nswalk.c b/drivers/acpi/namespace/nswalk.c index c7b5409e2cf8..3c905ce26d7d 100644 --- a/drivers/acpi/namespace/nswalk.c +++ b/drivers/acpi/namespace/nswalk.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c index cd97c80eb8ee..a8d549187c84 100644 --- a/drivers/acpi/namespace/nsxfeval.c +++ b/drivers/acpi/namespace/nsxfeval.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c index b489781b22a8..a287ed550f54 100644 --- a/drivers/acpi/namespace/nsxfname.c +++ b/drivers/acpi/namespace/nsxfname.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/namespace/nsxfobj.c b/drivers/acpi/namespace/nsxfobj.c index faa375887201..2b375ee80cef 100644 --- a/drivers/acpi/namespace/nsxfobj.c +++ b/drivers/acpi/namespace/nsxfobj.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c index 2a3a948dd114..f1e8bf65e24e 100644 --- a/drivers/acpi/parser/psargs.c +++ b/drivers/acpi/parser/psargs.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c index a7c768860648..c06238e55d98 100644 --- a/drivers/acpi/parser/psloop.c +++ b/drivers/acpi/parser/psloop.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c index 18ed59dd2a6e..f425ab30eae8 100644 --- a/drivers/acpi/parser/psopcode.c +++ b/drivers/acpi/parser/psopcode.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c index a4c4020c40e9..15e1702e48d6 100644 --- a/drivers/acpi/parser/psparse.c +++ b/drivers/acpi/parser/psparse.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/parser/psscope.c b/drivers/acpi/parser/psscope.c index 77cfa4ed0cfe..ee50e67c9443 100644 --- a/drivers/acpi/parser/psscope.c +++ b/drivers/acpi/parser/psscope.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/parser/pstree.c b/drivers/acpi/parser/pstree.c index 0e1a3226665d..1dd355ddd182 100644 --- a/drivers/acpi/parser/pstree.c +++ b/drivers/acpi/parser/pstree.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/parser/psutils.c b/drivers/acpi/parser/psutils.c index 8ca52002db55..7cf1f65cd5bb 100644 --- a/drivers/acpi/parser/psutils.c +++ b/drivers/acpi/parser/psutils.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/parser/pswalk.c b/drivers/acpi/parser/pswalk.c index 49f9757434e4..8b86ad5a3201 100644 --- a/drivers/acpi/parser/pswalk.c +++ b/drivers/acpi/parser/pswalk.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c index 94103bced75e..52581454c47c 100644 --- a/drivers/acpi/parser/psxface.c +++ b/drivers/acpi/parser/psxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/resources/rsaddr.c b/drivers/acpi/resources/rsaddr.c index 271e61509eeb..7f96332822bf 100644 --- a/drivers/acpi/resources/rsaddr.c +++ b/drivers/acpi/resources/rsaddr.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c index d801823de016..8a112d11d491 100644 --- a/drivers/acpi/resources/rscalc.c +++ b/drivers/acpi/resources/rscalc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c index 50da494c3ee2..faddaee1bc07 100644 --- a/drivers/acpi/resources/rscreate.c +++ b/drivers/acpi/resources/rscreate.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/resources/rsdump.c b/drivers/acpi/resources/rsdump.c index ed6447dcea78..6bbbb7b8941a 100644 --- a/drivers/acpi/resources/rsdump.c +++ b/drivers/acpi/resources/rsdump.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/resources/rsinfo.c b/drivers/acpi/resources/rsinfo.c index 2c2adb6292c1..3f0a1fedbe0e 100644 --- a/drivers/acpi/resources/rsinfo.c +++ b/drivers/acpi/resources/rsinfo.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/resources/rsio.c b/drivers/acpi/resources/rsio.c index 610d7c2101f2..b66d42e7402e 100644 --- a/drivers/acpi/resources/rsio.c +++ b/drivers/acpi/resources/rsio.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/resources/rsirq.c b/drivers/acpi/resources/rsirq.c index 382a77b8400d..a8805efc0366 100644 --- a/drivers/acpi/resources/rsirq.c +++ b/drivers/acpi/resources/rsirq.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/resources/rslist.c b/drivers/acpi/resources/rslist.c index ca21e4660c79..b78c7e797a19 100644 --- a/drivers/acpi/resources/rslist.c +++ b/drivers/acpi/resources/rslist.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/resources/rsmemory.c b/drivers/acpi/resources/rsmemory.c index 521eab7dd8df..63b21abd90bb 100644 --- a/drivers/acpi/resources/rsmemory.c +++ b/drivers/acpi/resources/rsmemory.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/resources/rsmisc.c b/drivers/acpi/resources/rsmisc.c index 3e69eff303fb..de1ac3881b22 100644 --- a/drivers/acpi/resources/rsmisc.c +++ b/drivers/acpi/resources/rsmisc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c index 935a4827e7ab..befe2302f41b 100644 --- a/drivers/acpi/resources/rsutils.c +++ b/drivers/acpi/resources/rsutils.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c index 4c3fd4cdaf73..f59f4c4e034c 100644 --- a/drivers/acpi/resources/rsxface.c +++ b/drivers/acpi/resources/rsxface.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/tables/tbfadt.c b/drivers/acpi/tables/tbfadt.c index 002bb33003af..949d4114eb9f 100644 --- a/drivers/acpi/tables/tbfadt.c +++ b/drivers/acpi/tables/tbfadt.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/tables/tbfind.c b/drivers/acpi/tables/tbfind.c index 772ca41d840b..9ca3afc98c80 100644 --- a/drivers/acpi/tables/tbfind.c +++ b/drivers/acpi/tables/tbfind.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c index c4a9abb072c0..402f93e1ff20 100644 --- a/drivers/acpi/tables/tbinstal.c +++ b/drivers/acpi/tables/tbinstal.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c index d04442fc4955..bc019b9b6a68 100644 --- a/drivers/acpi/tables/tbutils.c +++ b/drivers/acpi/tables/tbutils.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c index 5f2271542a96..fb57b93c2495 100644 --- a/drivers/acpi/tables/tbxface.c +++ b/drivers/acpi/tables/tbxface.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c index 9ecb4b6c1e7d..b8c0dfa084f6 100644 --- a/drivers/acpi/tables/tbxfroot.c +++ b/drivers/acpi/tables/tbxfroot.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c index 181e66986fa9..ede084829a70 100644 --- a/drivers/acpi/utilities/utalloc.c +++ b/drivers/acpi/utilities/utalloc.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/utilities/utcache.c b/drivers/acpi/utilities/utcache.c index 285a0f531760..245fa80cf600 100644 --- a/drivers/acpi/utilities/utcache.c +++ b/drivers/acpi/utilities/utcache.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c index 2a57c2c2c782..655c290aca7b 100644 --- a/drivers/acpi/utilities/utcopy.c +++ b/drivers/acpi/utilities/utcopy.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c index 80144427bb41..f938f465efa4 100644 --- a/drivers/acpi/utilities/utdebug.c +++ b/drivers/acpi/utilities/utdebug.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c index f5b2f6a358b5..1fbc35139e84 100644 --- a/drivers/acpi/utilities/utdelete.c +++ b/drivers/acpi/utilities/utdelete.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c index 0042b7e78b26..05e61be267d5 100644 --- a/drivers/acpi/utilities/uteval.c +++ b/drivers/acpi/utilities/uteval.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index d0226fedb004..a6e71b801d2d 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/utilities/utinit.c b/drivers/acpi/utilities/utinit.c index de44477be79f..cae515fc02d3 100644 --- a/drivers/acpi/utilities/utinit.c +++ b/drivers/acpi/utilities/utinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/utilities/utmath.c b/drivers/acpi/utilities/utmath.c index 16dbf665927b..c927324fdd26 100644 --- a/drivers/acpi/utilities/utmath.c +++ b/drivers/acpi/utilities/utmath.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c index 2f48fd663f5c..e4ba7192cd15 100644 --- a/drivers/acpi/utilities/utmisc.c +++ b/drivers/acpi/utilities/utmisc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/utilities/utmutex.c b/drivers/acpi/utilities/utmutex.c index 4820bc86d1f5..f7d602b1a894 100644 --- a/drivers/acpi/utilities/utmutex.c +++ b/drivers/acpi/utilities/utmutex.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c index cdb8ff5b92d1..e68466de8044 100644 --- a/drivers/acpi/utilities/utobject.c +++ b/drivers/acpi/utilities/utobject.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/utilities/utresrc.c b/drivers/acpi/utilities/utresrc.c index b630ee137ee1..c3e3e1308edc 100644 --- a/drivers/acpi/utilities/utresrc.c +++ b/drivers/acpi/utilities/utresrc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/utilities/utstate.c b/drivers/acpi/utilities/utstate.c index edcaafad0a31..63a6d3d77d88 100644 --- a/drivers/acpi/utilities/utstate.c +++ b/drivers/acpi/utilities/utstate.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c index 15bd6ff547e7..a92d91277ef9 100644 --- a/drivers/acpi/utilities/utxface.c +++ b/drivers/acpi/utilities/utxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index b4668b13d38c..28fe8bae1037 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acdebug.h b/include/acpi/acdebug.h index d626bb1d2973..c5a1b50d8d94 100644 --- a/include/acpi/acdebug.h +++ b/include/acpi/acdebug.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acdisasm.h b/include/acpi/acdisasm.h index 73d86ebaeed6..788f88782012 100644 --- a/include/acpi/acdisasm.h +++ b/include/acpi/acdisasm.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acdispat.h b/include/acpi/acdispat.h index a5b97f0f0133..910f018d92c7 100644 --- a/include/acpi/acdispat.h +++ b/include/acpi/acdispat.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acevents.h b/include/acpi/acevents.h index d23cdf326808..d5d099bf349c 100644 --- a/include/acpi/acevents.h +++ b/include/acpi/acevents.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h index b73f18a48785..1f591171bf31 100644 --- a/include/acpi/acexcep.h +++ b/include/acpi/acexcep.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acglobal.h b/include/acpi/acglobal.h index 86cff21d9568..74ad971241db 100644 --- a/include/acpi/acglobal.h +++ b/include/acpi/acglobal.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/achware.h b/include/acpi/achware.h index 4053df943453..d4fb9bbc903c 100644 --- a/include/acpi/achware.h +++ b/include/acpi/achware.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acinterp.h b/include/acpi/acinterp.h index f4dd98fc96a3..e249ce5d3300 100644 --- a/include/acpi/acinterp.h +++ b/include/acpi/acinterp.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/aclocal.h b/include/acpi/aclocal.h index 946da60e36e7..c5cdc32ac2f8 100644 --- a/include/acpi/aclocal.h +++ b/include/acpi/aclocal.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acmacros.h b/include/acpi/acmacros.h index 1f0fdbf6e09f..fb41a3b802fc 100644 --- a/include/acpi/acmacros.h +++ b/include/acpi/acmacros.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acnames.h b/include/acpi/acnames.h index 34bfae8a05f3..c1343a9265fa 100644 --- a/include/acpi/acnames.h +++ b/include/acpi/acnames.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acnamesp.h b/include/acpi/acnamesp.h index 1cad10bd6df0..713b30903fe5 100644 --- a/include/acpi/acnamesp.h +++ b/include/acpi/acnamesp.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acobject.h b/include/acpi/acobject.h index 2461bb9ab3e9..e9657dac69b7 100644 --- a/include/acpi/acobject.h +++ b/include/acpi/acobject.h @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acopcode.h b/include/acpi/acopcode.h index ab5434945807..dfdf63327885 100644 --- a/include/acpi/acopcode.h +++ b/include/acpi/acopcode.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acoutput.h b/include/acpi/acoutput.h index c090a8b0bc99..e17873defcec 100644 --- a/include/acpi/acoutput.h +++ b/include/acpi/acoutput.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acparser.h b/include/acpi/acparser.h index a3ae76b270af..23ee0fbf5619 100644 --- a/include/acpi/acparser.h +++ b/include/acpi/acparser.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acpi.h b/include/acpi/acpi.h index 2e5f00d3ea0d..c515ef6cc89e 100644 --- a/include/acpi/acpi.h +++ b/include/acpi/acpi.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index 4839f2af94c3..d4a560d2deb6 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h @@ -8,7 +8,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index c92acda1a77f..2c3806e6546f 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acresrc.h b/include/acpi/acresrc.h index 33e9f3813220..eef5bd7a59fa 100644 --- a/include/acpi/acresrc.h +++ b/include/acpi/acresrc.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acstruct.h b/include/acpi/acstruct.h index 19b838dc1a16..a907c67d651e 100644 --- a/include/acpi/acstruct.h +++ b/include/acpi/acstruct.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/actables.h b/include/acpi/actables.h index 2b9f46f9da4d..4b36a55b0b3b 100644 --- a/include/acpi/actables.h +++ b/include/acpi/actables.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h index 955adfb8d64c..1ebbe883f786 100644 --- a/include/acpi/actbl.h +++ b/include/acpi/actbl.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h index 604dfb311660..9af239bd1153 100644 --- a/include/acpi/actbl1.h +++ b/include/acpi/actbl1.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index cc24cef6ce93..dfea2d440488 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acutils.h b/include/acpi/acutils.h index 26115da8c099..b42cadf07302 100644 --- a/include/acpi/acutils.h +++ b/include/acpi/acutils.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/amlcode.h b/include/acpi/amlcode.h index da53a4ef287a..ff851c5df698 100644 --- a/include/acpi/amlcode.h +++ b/include/acpi/amlcode.h @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/amlresrc.h b/include/acpi/amlresrc.h index f7d541239da4..7b070e42b7c5 100644 --- a/include/acpi/amlresrc.h +++ b/include/acpi/amlresrc.h @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h index c785485e62a6..fcd2572e428c 100644 --- a/include/acpi/platform/acenv.h +++ b/include/acpi/platform/acenv.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/platform/acgcc.h b/include/acpi/platform/acgcc.h index 3bb50494a38a..8996dba90cd9 100644 --- a/include/acpi/platform/acgcc.h +++ b/include/acpi/platform/acgcc.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index 6ed15a0978eb..9af464598682 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without -- cgit v1.2.2 From 204470272c3b055b352d5f127d5d5c7dce5fa597 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Tue, 11 Mar 2008 17:17:08 -0400 Subject: ACPI: GPE enabling should happen after EC installation GPE could try to access EC region, so should not be enabled before EC is installed http://bugzilla.kernel.org/show_bug.cgi?id=9916 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/utilities/utxface.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c index 2d496918b3cd..df41312733c2 100644 --- a/drivers/acpi/utilities/utxface.c +++ b/drivers/acpi/utilities/utxface.c @@ -192,24 +192,6 @@ acpi_status acpi_enable_subsystem(u32 flags) } } - /* - * Complete the GPE initialization for the GPE blocks defined in the FADT - * (GPE block 0 and 1). - * - * Note1: This is where the _PRW methods are executed for the GPEs. These - * methods can only be executed after the SCI and Global Lock handlers are - * installed and initialized. - * - * Note2: Currently, there seems to be no need to run the _REG methods - * before execution of the _PRW methods and enabling of the GPEs. - */ - if (!(flags & ACPI_NO_EVENT_INIT)) { - status = acpi_ev_install_fadt_gpes(); - if (ACPI_FAILURE(status)) { - return (status); - } - } - return_ACPI_STATUS(status); } @@ -279,6 +261,23 @@ acpi_status acpi_initialize_objects(u32 flags) } } + /* + * Complete the GPE initialization for the GPE blocks defined in the FADT + * (GPE block 0 and 1). + * + * Note1: This is where the _PRW methods are executed for the GPEs. These + * methods can only be executed after the SCI and Global Lock handlers are + * installed and initialized. + * + * Note2: Currently, there seems to be no need to run the _REG methods + * before execution of the _PRW methods and enabling of the GPEs. + */ + if (!(flags & ACPI_NO_EVENT_INIT)) { + status = acpi_ev_install_fadt_gpes(); + if (ACPI_FAILURE(status)) + return (status); + } + /* * Empty the caches (delete the cached objects) on the assumption that * the table load filled them up more than they will be at runtime -- -- cgit v1.2.2 From 0fda6b403f0eca66ad8a7c946b3996e359100443 Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Wed, 9 Apr 2008 21:31:46 -0400 Subject: 2.6.25 regression: powertop says 120K wakeups/sec Patch to fix huge number of wakeups reported due to recent changes in processor_idle.c. The problem was that the entry_method determination was broken due to one of the recent commits (bc71bec91f987) causing C1 entry to not to go to halt. http://lkml.org/lkml/2008/3/22/124 Signed-off-by: Venkatesh Pallipadi Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 788da9781f80..836362b50faa 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -848,6 +848,7 @@ static int acpi_processor_get_power_info_default(struct acpi_processor *pr) /* all processors need to support C1 */ pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; pr->power.states[ACPI_STATE_C1].valid = 1; + pr->power.states[ACPI_STATE_C1].entry_method = ACPI_CSTATE_HALT; } /* the C0 state only exists as a filler in our array */ pr->power.states[ACPI_STATE_C0].valid = 1; @@ -960,6 +961,9 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) cx.address); } + if (cx.type == ACPI_STATE_C1) { + cx.valid = 1; + } obj = &(element->package.elements[2]); if (obj->type != ACPI_TYPE_INTEGER) -- cgit v1.2.2 From 2f67a0695dc389247c05041b05d2a2b06fc102a3 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 29 Apr 2008 02:34:42 -0400 Subject: flush kacpi_notify_wq before removing notify handler Flush kacpi_notify_wq before notify handler is removed, this can fix a bug which the deferred notify handler is executed after the notify_handler has already been removed. http://bugzilla.kernel.org/show_bug.cgi?id=9772 Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/osl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index a498a6cc68fe..235a1386888a 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -742,6 +742,7 @@ EXPORT_SYMBOL(acpi_os_execute); void acpi_os_wait_events_complete(void *context) { flush_workqueue(kacpid_wq); + flush_workqueue(kacpi_notify_wq); } EXPORT_SYMBOL(acpi_os_wait_events_complete); -- cgit v1.2.2 From 63c4ec905d63834a97ec7dbbf0a2ec89ef5872be Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Mon, 21 Apr 2008 16:07:13 +0800 Subject: thermal: add the support for building the generic thermal as a module Build the generic thermal driver as module "thermal_sys". Make ACPI thermal, video, processor and fan SELECT the generic thermal driver, as these drivers rely on it to build the sysfs I/F. Signed-off-by: Zhang Rui Acked-by: Jean Delvare Signed-off-by: Len Brown --- drivers/acpi/Kconfig | 3 +++ drivers/misc/Kconfig | 1 + drivers/thermal/Kconfig | 4 ++-- drivers/thermal/Makefile | 3 ++- drivers/thermal/thermal.c | 2 +- include/linux/thermal.h | 14 -------------- 6 files changed, 9 insertions(+), 18 deletions(-) diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index b4f5e8542829..c52fca833268 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -140,6 +140,7 @@ config ACPI_VIDEO tristate "Video" depends on X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL depends on INPUT + select THERMAL help This driver implement the ACPI Extensions For Display Adapters for integrated graphics devices on motherboard, as specified in @@ -151,6 +152,7 @@ config ACPI_VIDEO config ACPI_FAN tristate "Fan" + select THERMAL default y help This driver adds support for ACPI fan devices, allowing user-mode @@ -172,6 +174,7 @@ config ACPI_BAY config ACPI_PROCESSOR tristate "Processor" + select THERMAL default y help This driver installs ACPI as the idle handler for Linux, and uses diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 297a48f85446..08f35d76dcd9 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -344,6 +344,7 @@ config ATMEL_SSC config INTEL_MENLOW tristate "Thermal Management driver for Intel menlow platform" depends on ACPI_THERMAL + select THERMAL depends on X86 ---help--- ACPI thermal management enhancement driver on diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 17e71d56f31e..4b628526df09 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -3,7 +3,7 @@ # menuconfig THERMAL - bool "Generic Thermal sysfs driver" + tristate "Generic Thermal sysfs driver" help Generic Thermal Sysfs driver offers a generic mechanism for thermal management. Usually it's made up of one or more thermal @@ -11,4 +11,4 @@ menuconfig THERMAL Each thermal zone contains its own temperature, trip points, cooling devices. All platforms with ACPI thermal support can use this driver. - If you want this support, you should say Y here. + If you want this support, you should say Y or M here. diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 8ef1232de376..02b64517be8f 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -2,4 +2,5 @@ # Makefile for sensor chip drivers. # -obj-$(CONFIG_THERMAL) += thermal.o +thermal_sys-objs += thermal.o +obj-$(CONFIG_THERMAL) += thermal_sys.o diff --git a/drivers/thermal/thermal.c b/drivers/thermal/thermal.c index 7f79bbf652d7..cf56af4b7e02 100644 --- a/drivers/thermal/thermal.c +++ b/drivers/thermal/thermal.c @@ -31,7 +31,7 @@ #include #include -MODULE_AUTHOR("Zhang Rui") +MODULE_AUTHOR("Zhang Rui"); MODULE_DESCRIPTION("Generic thermal management sysfs support"); MODULE_LICENSE("GPL"); diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 90c1c191ea69..3ff680b44e81 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -88,24 +88,10 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int, struct thermal_cooling_device *); int thermal_zone_unbind_cooling_device(struct thermal_zone_device *, int, struct thermal_cooling_device *); - -#ifdef CONFIG_THERMAL struct thermal_cooling_device *thermal_cooling_device_register(char *, void *, struct thermal_cooling_device_ops *); void thermal_cooling_device_unregister(struct thermal_cooling_device *); -#else -static inline struct thermal_cooling_device -*thermal_cooling_device_register(char *c, void *v, - struct thermal_cooling_device_ops *t) -{ - return NULL; -} -static inline - void thermal_cooling_device_unregister(struct thermal_cooling_device *t) -{ -}; -#endif #endif /* __THERMAL_H__ */ -- cgit v1.2.2 From 9ec732ff80b7e8a9096666f78ae584d3b393bc84 Mon Sep 17 00:00:00 2001 From: "Zhang, Rui" Date: Thu, 10 Apr 2008 16:13:10 +0800 Subject: thermal: add new get_crit_temp callback Add a new callback so that the generic thermal can get the critical trip point info of a thermal zone, which is needed for building the tempX_crit hwmon sysfs attribute. Signed-off-by: Zhang Rui Acked-by: Jean Delvare Signed-off-by: Len Brown --- drivers/acpi/thermal.c | 13 +++++++++++++ include/linux/thermal.h | 1 + 2 files changed, 14 insertions(+) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 766bd25d3376..ec707ed1a70f 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -1012,6 +1012,18 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal, return -EINVAL; } +static int thermal_get_crit_temp(struct thermal_zone_device *thermal, + unsigned long *temperature) { + struct acpi_thermal *tz = thermal->devdata; + + if (tz->trips.critical.flags.valid) { + *temperature = KELVIN_TO_MILLICELSIUS( + tz->trips.critical.temperature); + return 0; + } else + return -EINVAL; +} + typedef int (*cb)(struct thermal_zone_device *, int, struct thermal_cooling_device *); static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, @@ -1103,6 +1115,7 @@ static struct thermal_zone_device_ops acpi_thermal_zone_ops = { .set_mode = thermal_set_mode, .get_trip_type = thermal_get_trip_type, .get_trip_temp = thermal_get_trip_temp, + .get_crit_temp = thermal_get_crit_temp, }; static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 3ff680b44e81..16e6a8bdeb3c 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -41,6 +41,7 @@ struct thermal_zone_device_ops { int (*set_mode) (struct thermal_zone_device *, const char *); int (*get_trip_type) (struct thermal_zone_device *, int, char *); int (*get_trip_temp) (struct thermal_zone_device *, int, char *); + int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *); }; struct thermal_cooling_device_ops { -- cgit v1.2.2 From e68b16abd91dca91e35ea47537ef8a1b7ad72841 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Mon, 21 Apr 2008 16:07:52 +0800 Subject: thermal: add hwmon sysfs I/F Add hwmon sys I/F for generic thermal driver. Note: we have one hwmon class device for EACH TYPE of the thermal zone device. Signed-off-by: Zhang Rui Acked-by: Jean Delvare Signed-off-by: Len Brown --- drivers/thermal/thermal.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/thermal.h | 24 +++++++ 2 files changed, 187 insertions(+) diff --git a/drivers/thermal/thermal.c b/drivers/thermal/thermal.c index cf56af4b7e02..6098787341f3 100644 --- a/drivers/thermal/thermal.c +++ b/drivers/thermal/thermal.c @@ -295,6 +295,164 @@ thermal_cooling_device_trip_point_show(struct device *dev, /* Device management */ +#if defined(CONFIG_HWMON) || \ + (defined(CONFIG_HWMON_MODULE) && defined(CONFIG_THERMAL_MODULE)) +/* hwmon sys I/F */ +#include +static LIST_HEAD(thermal_hwmon_list); + +static ssize_t +name_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct thermal_hwmon_device *hwmon = dev->driver_data; + return sprintf(buf, "%s\n", hwmon->type); +} +static DEVICE_ATTR(name, 0444, name_show, NULL); + +static ssize_t +temp_input_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct thermal_hwmon_attr *hwmon_attr + = container_of(attr, struct thermal_hwmon_attr, attr); + struct thermal_zone_device *tz + = container_of(hwmon_attr, struct thermal_zone_device, + temp_input); + + return tz->ops->get_temp(tz, buf); +} + +static ssize_t +temp_crit_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct thermal_hwmon_attr *hwmon_attr + = container_of(attr, struct thermal_hwmon_attr, attr); + struct thermal_zone_device *tz + = container_of(hwmon_attr, struct thermal_zone_device, + temp_crit); + + return tz->ops->get_trip_temp(tz, 0, buf); +} + + +static int +thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) +{ + struct thermal_hwmon_device *hwmon; + int new_hwmon_device = 1; + int result; + + mutex_lock(&thermal_list_lock); + list_for_each_entry(hwmon, &thermal_hwmon_list, node) + if (!strcmp(hwmon->type, tz->type)) { + new_hwmon_device = 0; + mutex_unlock(&thermal_list_lock); + goto register_sys_interface; + } + mutex_unlock(&thermal_list_lock); + + hwmon = kzalloc(sizeof(struct thermal_hwmon_device), GFP_KERNEL); + if (!hwmon) + return -ENOMEM; + + INIT_LIST_HEAD(&hwmon->tz_list); + strlcpy(hwmon->type, tz->type, THERMAL_NAME_LENGTH); + hwmon->device = hwmon_device_register(NULL); + if (IS_ERR(hwmon->device)) { + result = PTR_ERR(hwmon->device); + goto free_mem; + } + hwmon->device->driver_data = hwmon; + result = device_create_file(hwmon->device, &dev_attr_name); + if (result) + goto unregister_hwmon_device; + + register_sys_interface: + tz->hwmon = hwmon; + hwmon->count++; + + snprintf(tz->temp_input.name, THERMAL_NAME_LENGTH, + "temp%d_input", hwmon->count); + tz->temp_input.attr.attr.name = tz->temp_input.name; + tz->temp_input.attr.attr.mode = 0444; + tz->temp_input.attr.show = temp_input_show; + result = device_create_file(hwmon->device, &tz->temp_input.attr); + if (result) + goto unregister_hwmon_device; + + if (tz->ops->get_crit_temp) { + unsigned long temperature; + if (!tz->ops->get_crit_temp(tz, &temperature)) { + snprintf(tz->temp_crit.name, THERMAL_NAME_LENGTH, + "temp%d_crit", hwmon->count); + tz->temp_crit.attr.attr.name = tz->temp_crit.name; + tz->temp_crit.attr.attr.mode = 0444; + tz->temp_crit.attr.show = temp_crit_show; + result = device_create_file(hwmon->device, + &tz->temp_crit.attr); + if (result) + goto unregister_hwmon_device; + } + } + + mutex_lock(&thermal_list_lock); + if (new_hwmon_device) + list_add_tail(&hwmon->node, &thermal_hwmon_list); + list_add_tail(&tz->hwmon_node, &hwmon->tz_list); + mutex_unlock(&thermal_list_lock); + + return 0; + + unregister_hwmon_device: + device_remove_file(hwmon->device, &tz->temp_crit.attr); + device_remove_file(hwmon->device, &tz->temp_input.attr); + if (new_hwmon_device) { + device_remove_file(hwmon->device, &dev_attr_name); + hwmon_device_unregister(hwmon->device); + } + free_mem: + if (new_hwmon_device) + kfree(hwmon); + + return result; +} + +static void +thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz) +{ + struct thermal_hwmon_device *hwmon = tz->hwmon; + + tz->hwmon = NULL; + device_remove_file(hwmon->device, &tz->temp_input.attr); + device_remove_file(hwmon->device, &tz->temp_crit.attr); + + mutex_lock(&thermal_list_lock); + list_del(&tz->hwmon_node); + if (!list_empty(&hwmon->tz_list)) { + mutex_unlock(&thermal_list_lock); + return; + } + list_del(&hwmon->node); + mutex_unlock(&thermal_list_lock); + + device_remove_file(hwmon->device, &dev_attr_name); + hwmon_device_unregister(hwmon->device); + kfree(hwmon); +} +#else +static int +thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) +{ + return 0; +} + +static void +thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz) +{ +} +#endif + + /** * thermal_zone_bind_cooling_device - bind a cooling device to a thermal zone * @tz: thermal zone device @@ -642,6 +800,10 @@ struct thermal_zone_device *thermal_zone_device_register(char *type, goto unregister; } + result = thermal_add_hwmon_sysfs(tz); + if (result) + goto unregister; + mutex_lock(&thermal_list_lock); list_add_tail(&tz->node, &thermal_tz_list); if (ops->bind) @@ -700,6 +862,7 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) for (count = 0; count < tz->trips; count++) TRIP_POINT_ATTR_REMOVE(&tz->device, count); + thermal_remove_hwmon_sysfs(tz); release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); idr_destroy(&tz->idr); mutex_destroy(&tz->lock); diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 16e6a8bdeb3c..06d3e6eb9ca8 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -66,6 +66,23 @@ struct thermal_cooling_device { ((long)t-2732+5)/10 : ((long)t-2732-5)/10) #define CELSIUS_TO_KELVIN(t) ((t)*10+2732) +#if defined(CONFIG_HWMON) || \ + (defined(CONFIG_HWMON_MODULE) && defined(CONFIG_THERMAL_MODULE)) +/* thermal zone devices with the same type share one hwmon device */ +struct thermal_hwmon_device { + char type[THERMAL_NAME_LENGTH]; + struct device *device; + int count; + struct list_head tz_list; + struct list_head node; +}; + +struct thermal_hwmon_attr { + struct device_attribute attr; + char name[16]; +}; +#endif + struct thermal_zone_device { int id; char type[THERMAL_NAME_LENGTH]; @@ -77,6 +94,13 @@ struct thermal_zone_device { struct idr idr; struct mutex lock; /* protect cooling devices list */ struct list_head node; +#if defined(CONFIG_HWMON) || \ + (defined(CONFIG_HWMON_MODULE) && defined(CONFIG_THERMAL_MODULE)) + struct list_head hwmon_node; + struct thermal_hwmon_device *hwmon; + struct thermal_hwmon_attr temp_input; /* hwmon sys attr */ + struct thermal_hwmon_attr temp_crit; /* hwmon sys attr */ +#endif }; struct thermal_zone_device *thermal_zone_device_register(char *, int, void *, -- cgit v1.2.2 From e9ae71078b2c8657c0e8de808b76b76049806906 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 22 Apr 2008 08:50:09 +0800 Subject: thermal: update the documentation Update the documentation for the thermal driver hwmon sys I/F. Change the ACPI thermal zone type to be consistent with hwmon. Signed-off-by: Zhang Rui Acked-by: Jean Delvare Signed-off-by: Len Brown --- Documentation/thermal/sysfs-api.txt | 33 +++++++++++++++++++++++++++------ drivers/acpi/thermal.c | 2 +- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt index d9f28be75403..70d68ce8640a 100644 --- a/Documentation/thermal/sysfs-api.txt +++ b/Documentation/thermal/sysfs-api.txt @@ -108,10 +108,12 @@ and throttle appropriate devices. RO read only value RW read/write value -All thermal sysfs attributes will be represented under /sys/class/thermal +Thermal sysfs attributes will be represented under /sys/class/thermal. +Hwmon sysfs I/F extension is also available under /sys/class/hwmon +if hwmon is compiled in or built as a module. Thermal zone device sys I/F, created once it's registered: -|thermal_zone[0-*]: +/sys/class/thermal/thermal_zone[0-*]: |-----type: Type of the thermal zone |-----temp: Current temperature |-----mode: Working mode of the thermal zone @@ -119,7 +121,7 @@ Thermal zone device sys I/F, created once it's registered: |-----trip_point_[0-*]_type: Trip point type Thermal cooling device sys I/F, created once it's registered: -|cooling_device[0-*]: +/sys/class/thermal/cooling_device[0-*]: |-----type : Type of the cooling device(processor/fan/...) |-----max_state: Maximum cooling state of the cooling device |-----cur_state: Current cooling state of the cooling device @@ -130,10 +132,19 @@ They represent the relationship between a thermal zone and its associated coolin They are created/removed for each thermal_zone_bind_cooling_device/thermal_zone_unbind_cooling_device successful execution. -|thermal_zone[0-*] +/sys/class/thermal/thermal_zone[0-*] |-----cdev[0-*]: The [0-*]th cooling device in the current thermal zone |-----cdev[0-*]_trip_point: Trip point that cdev[0-*] is associated with +Besides the thermal zone device sysfs I/F and cooling device sysfs I/F, +the generic thermal driver also creates a hwmon sysfs I/F for each _type_ of +thermal zone device. E.g. the generic thermal driver registers one hwmon class device +and build the associated hwmon sysfs I/F for all the registered ACPI thermal zones. +/sys/class/hwmon/hwmon[0-*]: + |-----name: The type of the thermal zone devices. + |-----temp[1-*]_input: The current temperature of thermal zone [1-*]. + |-----temp[1-*]_critical: The critical trip point of thermal zone [1-*]. +Please read Documentation/hwmon/sysfs-interface for additional information. *************************** * Thermal zone attributes * @@ -141,7 +152,10 @@ thermal_zone_bind_cooling_device/thermal_zone_unbind_cooling_device successful e type Strings which represent the thermal zone type. This is given by thermal zone driver as part of registration. - Eg: "ACPI thermal zone" indicates it's a ACPI thermal device + Eg: "acpitz" indicates it's an ACPI thermal device. + In order to keep it consistent with hwmon sys attribute, + this should be a short, lowercase string, + not containing spaces nor dashes. RO Required @@ -218,7 +232,7 @@ the sys I/F structure will be built like this: /sys/class/thermal: |thermal_zone1: - |-----type: ACPI thermal zone + |-----type: acpitz |-----temp: 37000 |-----mode: kernel |-----trip_point_0_temp: 100000 @@ -243,3 +257,10 @@ the sys I/F structure will be built like this: |-----type: Fan |-----max_state: 2 |-----cur_state: 0 + +/sys/class/hwmon: + +|hwmon0: + |-----name: acpitz + |-----temp1_input: 37000 + |-----temp1_crit: 100000 diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index ec707ed1a70f..5e9641c93fcd 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -1136,7 +1136,7 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].flags.valid; i++, trips++); - tz->thermal_zone = thermal_zone_device_register("ACPI thermal zone", + tz->thermal_zone = thermal_zone_device_register("acpitz", trips, tz, &acpi_thermal_zone_ops); if (IS_ERR(tz->thermal_zone)) return -ENODEV; -- cgit v1.2.2 From 9030062f3d61f87c1e787b3aa134fa3a8e4b2d25 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 11 Apr 2008 10:09:24 +0800 Subject: ACPI: elide a non-zero test on a result that is never 0 thermal_cooling_device_register used to return NULL if THERMAL is "n". As the ACPI fan, processor and video drivers SELECT the generic thermal in PATCH 01, this is not a problem any more. Signed-off-by: Julia Lawall Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/fan.c | 35 +++++++++++++++++------------------ drivers/acpi/processor_core.c | 31 +++++++++++++++---------------- drivers/acpi/video.c | 28 +++++++++++++--------------- drivers/misc/intel_menlow.c | 23 +++++++++-------------- 4 files changed, 54 insertions(+), 63 deletions(-) diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index c8e3cba423ef..cf635cde836b 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -260,24 +260,23 @@ static int acpi_fan_add(struct acpi_device *device) result = PTR_ERR(cdev); goto end; } - if (cdev) { - printk(KERN_INFO PREFIX - "%s is registered as cooling_device%d\n", - device->dev.bus_id, cdev->id); - - acpi_driver_data(device) = cdev; - result = sysfs_create_link(&device->dev.kobj, - &cdev->device.kobj, - "thermal_cooling"); - if (result) - return result; - - result = sysfs_create_link(&cdev->device.kobj, - &device->dev.kobj, - "device"); - if (result) - return result; - } + + printk(KERN_INFO PREFIX + "%s is registered as cooling_device%d\n", + device->dev.bus_id, cdev->id); + + acpi_driver_data(device) = cdev; + result = sysfs_create_link(&device->dev.kobj, + &cdev->device.kobj, + "thermal_cooling"); + if (result) + printk(KERN_ERR PREFIX "Create sysfs link\n"); + + result = sysfs_create_link(&cdev->device.kobj, + &device->dev.kobj, + "device"); + if (result) + printk(KERN_ERR PREFIX "Create sysfs link\n"); result = acpi_fan_add_fs(device); if (result) diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index a825b431b64f..ea5f628dcc15 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -674,22 +674,21 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device) result = PTR_ERR(pr->cdev); goto end; } - if (pr->cdev) { - printk(KERN_INFO PREFIX - "%s is registered as cooling_device%d\n", - device->dev.bus_id, pr->cdev->id); - - result = sysfs_create_link(&device->dev.kobj, - &pr->cdev->device.kobj, - "thermal_cooling"); - if (result) - return result; - result = sysfs_create_link(&pr->cdev->device.kobj, - &device->dev.kobj, - "device"); - if (result) - return result; - } + + printk(KERN_INFO PREFIX + "%s is registered as cooling_device%d\n", + device->dev.bus_id, pr->cdev->id); + + result = sysfs_create_link(&device->dev.kobj, + &pr->cdev->device.kobj, + "thermal_cooling"); + if (result) + printk(KERN_ERR PREFIX "Create sysfs link\n"); + result = sysfs_create_link(&pr->cdev->device.kobj, + &device->dev.kobj, + "device"); + if (result) + printk(KERN_ERR PREFIX "Create sysfs link\n"); if (pr->flags.throttling) { printk(KERN_INFO PREFIX "%s [%s] (supports", diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 980a74188781..55c095619379 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -734,21 +734,19 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) if (IS_ERR(device->cdev)) return; - if (device->cdev) { - printk(KERN_INFO PREFIX - "%s is registered as cooling_device%d\n", - device->dev->dev.bus_id, device->cdev->id); - result = sysfs_create_link(&device->dev->dev.kobj, - &device->cdev->device.kobj, - "thermal_cooling"); - if (result) - printk(KERN_ERR PREFIX "Create sysfs link\n"); - result = sysfs_create_link(&device->cdev->device.kobj, - &device->dev->dev.kobj, - "device"); - if (result) - printk(KERN_ERR PREFIX "Create sysfs link\n"); - } + printk(KERN_INFO PREFIX + "%s is registered as cooling_device%d\n", + device->dev->dev.bus_id, device->cdev->id); + result = sysfs_create_link(&device->dev->dev.kobj, + &device->cdev->device.kobj, + "thermal_cooling"); + if (result) + printk(KERN_ERR PREFIX "Create sysfs link\n"); + result = sysfs_create_link(&device->cdev->device.kobj, + &device->dev->dev.kobj, "device"); + if (result) + printk(KERN_ERR PREFIX "Create sysfs link\n"); + } if (device->cap._DCS && device->cap._DSS){ static int count = 0; diff --git a/drivers/misc/intel_menlow.c b/drivers/misc/intel_menlow.c index 0c0bb3093e07..3db83a2dc3a1 100644 --- a/drivers/misc/intel_menlow.c +++ b/drivers/misc/intel_menlow.c @@ -175,20 +175,15 @@ static int intel_menlow_memory_add(struct acpi_device *device) goto end; } - if (cdev) { - acpi_driver_data(device) = cdev; - result = sysfs_create_link(&device->dev.kobj, - &cdev->device.kobj, "thermal_cooling"); - if (result) - goto unregister; - - result = sysfs_create_link(&cdev->device.kobj, - &device->dev.kobj, "device"); - if (result) { - sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); - goto unregister; - } - } + acpi_driver_data(device) = cdev; + result = sysfs_create_link(&device->dev.kobj, + &cdev->device.kobj, "thermal_cooling"); + if (result) + printk(KERN_ERR PREFIX "Create sysfs link\n"); + result = sysfs_create_link(&cdev->device.kobj, + &device->dev.kobj, "device"); + if (result) + printk(KERN_ERR PREFIX "Create sysfs link\n"); end: return result; -- cgit v1.2.2 From 76ecb4f2d7ea5c3aac8970b9529775316507c6d2 Mon Sep 17 00:00:00 2001 From: "Zhang, Rui" Date: Thu, 10 Apr 2008 16:20:23 +0800 Subject: ACPI: update thermal temperature Fix the problem that thermal_get_temp returns the cached value, which causes the temperature in generic thermal never updates. Signed-off-by: Zhang Rui Acked-by: Jean Delvare Signed-off-by: Len Brown --- drivers/acpi/thermal.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 5e9641c93fcd..782c2250443e 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -884,10 +884,15 @@ static void acpi_thermal_check(void *data) static int thermal_get_temp(struct thermal_zone_device *thermal, char *buf) { struct acpi_thermal *tz = thermal->devdata; + int result; if (!tz) return -EINVAL; + result = acpi_thermal_get_temperature(tz); + if (result) + return result; + return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(tz->temperature)); } -- cgit v1.2.2 From ff16cab69b6ed621686cf342306785175775152d Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 29 Apr 2008 03:12:17 -0400 Subject: thermal: re-name thermal.c to thermal_sys.c thermal_sys was already the name of the resulting module, and it is built from this one source file. Signed-off-by: Len Brown --- drivers/thermal/Makefile | 1 - drivers/thermal/thermal.c | 899 ------------------------------------------ drivers/thermal/thermal_sys.c | 899 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 899 insertions(+), 900 deletions(-) delete mode 100644 drivers/thermal/thermal.c create mode 100644 drivers/thermal/thermal_sys.c diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 02b64517be8f..31108a01c22e 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -2,5 +2,4 @@ # Makefile for sensor chip drivers. # -thermal_sys-objs += thermal.o obj-$(CONFIG_THERMAL) += thermal_sys.o diff --git a/drivers/thermal/thermal.c b/drivers/thermal/thermal.c deleted file mode 100644 index 6098787341f3..000000000000 --- a/drivers/thermal/thermal.c +++ /dev/null @@ -1,899 +0,0 @@ -/* - * thermal.c - Generic Thermal Management Sysfs support. - * - * Copyright (C) 2008 Intel Corp - * Copyright (C) 2008 Zhang Rui - * Copyright (C) 2008 Sujith Thomas - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Zhang Rui"); -MODULE_DESCRIPTION("Generic thermal management sysfs support"); -MODULE_LICENSE("GPL"); - -#define PREFIX "Thermal: " - -struct thermal_cooling_device_instance { - int id; - char name[THERMAL_NAME_LENGTH]; - struct thermal_zone_device *tz; - struct thermal_cooling_device *cdev; - int trip; - char attr_name[THERMAL_NAME_LENGTH]; - struct device_attribute attr; - struct list_head node; -}; - -static DEFINE_IDR(thermal_tz_idr); -static DEFINE_IDR(thermal_cdev_idr); -static DEFINE_MUTEX(thermal_idr_lock); - -static LIST_HEAD(thermal_tz_list); -static LIST_HEAD(thermal_cdev_list); -static DEFINE_MUTEX(thermal_list_lock); - -static int get_idr(struct idr *idr, struct mutex *lock, int *id) -{ - int err; - - again: - if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0)) - return -ENOMEM; - - if (lock) - mutex_lock(lock); - err = idr_get_new(idr, NULL, id); - if (lock) - mutex_unlock(lock); - if (unlikely(err == -EAGAIN)) - goto again; - else if (unlikely(err)) - return err; - - *id = *id & MAX_ID_MASK; - return 0; -} - -static void release_idr(struct idr *idr, struct mutex *lock, int id) -{ - if (lock) - mutex_lock(lock); - idr_remove(idr, id); - if (lock) - mutex_unlock(lock); -} - -/* sys I/F for thermal zone */ - -#define to_thermal_zone(_dev) \ - container_of(_dev, struct thermal_zone_device, device) - -static ssize_t -type_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct thermal_zone_device *tz = to_thermal_zone(dev); - - return sprintf(buf, "%s\n", tz->type); -} - -static ssize_t -temp_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct thermal_zone_device *tz = to_thermal_zone(dev); - - if (!tz->ops->get_temp) - return -EPERM; - - return tz->ops->get_temp(tz, buf); -} - -static ssize_t -mode_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct thermal_zone_device *tz = to_thermal_zone(dev); - - if (!tz->ops->get_mode) - return -EPERM; - - return tz->ops->get_mode(tz, buf); -} - -static ssize_t -mode_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct thermal_zone_device *tz = to_thermal_zone(dev); - int result; - - if (!tz->ops->set_mode) - return -EPERM; - - result = tz->ops->set_mode(tz, buf); - if (result) - return result; - - return count; -} - -static ssize_t -trip_point_type_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct thermal_zone_device *tz = to_thermal_zone(dev); - int trip; - - if (!tz->ops->get_trip_type) - return -EPERM; - - if (!sscanf(attr->attr.name, "trip_point_%d_type", &trip)) - return -EINVAL; - - return tz->ops->get_trip_type(tz, trip, buf); -} - -static ssize_t -trip_point_temp_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct thermal_zone_device *tz = to_thermal_zone(dev); - int trip; - - if (!tz->ops->get_trip_temp) - return -EPERM; - - if (!sscanf(attr->attr.name, "trip_point_%d_temp", &trip)) - return -EINVAL; - - return tz->ops->get_trip_temp(tz, trip, buf); -} - -static DEVICE_ATTR(type, 0444, type_show, NULL); -static DEVICE_ATTR(temp, 0444, temp_show, NULL); -static DEVICE_ATTR(mode, 0644, mode_show, mode_store); - -static struct device_attribute trip_point_attrs[] = { - __ATTR(trip_point_0_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_0_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_1_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_1_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_2_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_2_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_3_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_3_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_4_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_4_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_5_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_5_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_6_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_6_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_7_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_7_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_8_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_8_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_9_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_9_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_10_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_10_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_11_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_11_temp, 0444, trip_point_temp_show, NULL), -}; - -#define TRIP_POINT_ATTR_ADD(_dev, _index, result) \ -do { \ - result = device_create_file(_dev, \ - &trip_point_attrs[_index * 2]); \ - if (result) \ - break; \ - result = device_create_file(_dev, \ - &trip_point_attrs[_index * 2 + 1]); \ -} while (0) - -#define TRIP_POINT_ATTR_REMOVE(_dev, _index) \ -do { \ - device_remove_file(_dev, &trip_point_attrs[_index * 2]); \ - device_remove_file(_dev, &trip_point_attrs[_index * 2 + 1]); \ -} while (0) - -/* sys I/F for cooling device */ -#define to_cooling_device(_dev) \ - container_of(_dev, struct thermal_cooling_device, device) - -static ssize_t -thermal_cooling_device_type_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct thermal_cooling_device *cdev = to_cooling_device(dev); - - return sprintf(buf, "%s\n", cdev->type); -} - -static ssize_t -thermal_cooling_device_max_state_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct thermal_cooling_device *cdev = to_cooling_device(dev); - - return cdev->ops->get_max_state(cdev, buf); -} - -static ssize_t -thermal_cooling_device_cur_state_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct thermal_cooling_device *cdev = to_cooling_device(dev); - - return cdev->ops->get_cur_state(cdev, buf); -} - -static ssize_t -thermal_cooling_device_cur_state_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct thermal_cooling_device *cdev = to_cooling_device(dev); - int state; - int result; - - if (!sscanf(buf, "%d\n", &state)) - return -EINVAL; - - if (state < 0) - return -EINVAL; - - result = cdev->ops->set_cur_state(cdev, state); - if (result) - return result; - return count; -} - -static struct device_attribute dev_attr_cdev_type = -__ATTR(type, 0444, thermal_cooling_device_type_show, NULL); -static DEVICE_ATTR(max_state, 0444, - thermal_cooling_device_max_state_show, NULL); -static DEVICE_ATTR(cur_state, 0644, - thermal_cooling_device_cur_state_show, - thermal_cooling_device_cur_state_store); - -static ssize_t -thermal_cooling_device_trip_point_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct thermal_cooling_device_instance *instance; - - instance = - container_of(attr, struct thermal_cooling_device_instance, attr); - - if (instance->trip == THERMAL_TRIPS_NONE) - return sprintf(buf, "-1\n"); - else - return sprintf(buf, "%d\n", instance->trip); -} - -/* Device management */ - -#if defined(CONFIG_HWMON) || \ - (defined(CONFIG_HWMON_MODULE) && defined(CONFIG_THERMAL_MODULE)) -/* hwmon sys I/F */ -#include -static LIST_HEAD(thermal_hwmon_list); - -static ssize_t -name_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct thermal_hwmon_device *hwmon = dev->driver_data; - return sprintf(buf, "%s\n", hwmon->type); -} -static DEVICE_ATTR(name, 0444, name_show, NULL); - -static ssize_t -temp_input_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct thermal_hwmon_attr *hwmon_attr - = container_of(attr, struct thermal_hwmon_attr, attr); - struct thermal_zone_device *tz - = container_of(hwmon_attr, struct thermal_zone_device, - temp_input); - - return tz->ops->get_temp(tz, buf); -} - -static ssize_t -temp_crit_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct thermal_hwmon_attr *hwmon_attr - = container_of(attr, struct thermal_hwmon_attr, attr); - struct thermal_zone_device *tz - = container_of(hwmon_attr, struct thermal_zone_device, - temp_crit); - - return tz->ops->get_trip_temp(tz, 0, buf); -} - - -static int -thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) -{ - struct thermal_hwmon_device *hwmon; - int new_hwmon_device = 1; - int result; - - mutex_lock(&thermal_list_lock); - list_for_each_entry(hwmon, &thermal_hwmon_list, node) - if (!strcmp(hwmon->type, tz->type)) { - new_hwmon_device = 0; - mutex_unlock(&thermal_list_lock); - goto register_sys_interface; - } - mutex_unlock(&thermal_list_lock); - - hwmon = kzalloc(sizeof(struct thermal_hwmon_device), GFP_KERNEL); - if (!hwmon) - return -ENOMEM; - - INIT_LIST_HEAD(&hwmon->tz_list); - strlcpy(hwmon->type, tz->type, THERMAL_NAME_LENGTH); - hwmon->device = hwmon_device_register(NULL); - if (IS_ERR(hwmon->device)) { - result = PTR_ERR(hwmon->device); - goto free_mem; - } - hwmon->device->driver_data = hwmon; - result = device_create_file(hwmon->device, &dev_attr_name); - if (result) - goto unregister_hwmon_device; - - register_sys_interface: - tz->hwmon = hwmon; - hwmon->count++; - - snprintf(tz->temp_input.name, THERMAL_NAME_LENGTH, - "temp%d_input", hwmon->count); - tz->temp_input.attr.attr.name = tz->temp_input.name; - tz->temp_input.attr.attr.mode = 0444; - tz->temp_input.attr.show = temp_input_show; - result = device_create_file(hwmon->device, &tz->temp_input.attr); - if (result) - goto unregister_hwmon_device; - - if (tz->ops->get_crit_temp) { - unsigned long temperature; - if (!tz->ops->get_crit_temp(tz, &temperature)) { - snprintf(tz->temp_crit.name, THERMAL_NAME_LENGTH, - "temp%d_crit", hwmon->count); - tz->temp_crit.attr.attr.name = tz->temp_crit.name; - tz->temp_crit.attr.attr.mode = 0444; - tz->temp_crit.attr.show = temp_crit_show; - result = device_create_file(hwmon->device, - &tz->temp_crit.attr); - if (result) - goto unregister_hwmon_device; - } - } - - mutex_lock(&thermal_list_lock); - if (new_hwmon_device) - list_add_tail(&hwmon->node, &thermal_hwmon_list); - list_add_tail(&tz->hwmon_node, &hwmon->tz_list); - mutex_unlock(&thermal_list_lock); - - return 0; - - unregister_hwmon_device: - device_remove_file(hwmon->device, &tz->temp_crit.attr); - device_remove_file(hwmon->device, &tz->temp_input.attr); - if (new_hwmon_device) { - device_remove_file(hwmon->device, &dev_attr_name); - hwmon_device_unregister(hwmon->device); - } - free_mem: - if (new_hwmon_device) - kfree(hwmon); - - return result; -} - -static void -thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz) -{ - struct thermal_hwmon_device *hwmon = tz->hwmon; - - tz->hwmon = NULL; - device_remove_file(hwmon->device, &tz->temp_input.attr); - device_remove_file(hwmon->device, &tz->temp_crit.attr); - - mutex_lock(&thermal_list_lock); - list_del(&tz->hwmon_node); - if (!list_empty(&hwmon->tz_list)) { - mutex_unlock(&thermal_list_lock); - return; - } - list_del(&hwmon->node); - mutex_unlock(&thermal_list_lock); - - device_remove_file(hwmon->device, &dev_attr_name); - hwmon_device_unregister(hwmon->device); - kfree(hwmon); -} -#else -static int -thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) -{ - return 0; -} - -static void -thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz) -{ -} -#endif - - -/** - * thermal_zone_bind_cooling_device - bind a cooling device to a thermal zone - * @tz: thermal zone device - * @trip: indicates which trip point the cooling devices is - * associated with in this thermal zone. - * @cdev: thermal cooling device - * - * This function is usually called in the thermal zone device .bind callback. - */ -int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, - int trip, - struct thermal_cooling_device *cdev) -{ - struct thermal_cooling_device_instance *dev; - struct thermal_cooling_device_instance *pos; - struct thermal_zone_device *pos1; - struct thermal_cooling_device *pos2; - int result; - - if (trip >= tz->trips || (trip < 0 && trip != THERMAL_TRIPS_NONE)) - return -EINVAL; - - list_for_each_entry(pos1, &thermal_tz_list, node) { - if (pos1 == tz) - break; - } - list_for_each_entry(pos2, &thermal_cdev_list, node) { - if (pos2 == cdev) - break; - } - - if (tz != pos1 || cdev != pos2) - return -EINVAL; - - dev = - kzalloc(sizeof(struct thermal_cooling_device_instance), GFP_KERNEL); - if (!dev) - return -ENOMEM; - dev->tz = tz; - dev->cdev = cdev; - dev->trip = trip; - result = get_idr(&tz->idr, &tz->lock, &dev->id); - if (result) - goto free_mem; - - sprintf(dev->name, "cdev%d", dev->id); - result = - sysfs_create_link(&tz->device.kobj, &cdev->device.kobj, dev->name); - if (result) - goto release_idr; - - sprintf(dev->attr_name, "cdev%d_trip_point", dev->id); - dev->attr.attr.name = dev->attr_name; - dev->attr.attr.mode = 0444; - dev->attr.show = thermal_cooling_device_trip_point_show; - result = device_create_file(&tz->device, &dev->attr); - if (result) - goto remove_symbol_link; - - mutex_lock(&tz->lock); - list_for_each_entry(pos, &tz->cooling_devices, node) - if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) { - result = -EEXIST; - break; - } - if (!result) - list_add_tail(&dev->node, &tz->cooling_devices); - mutex_unlock(&tz->lock); - - if (!result) - return 0; - - device_remove_file(&tz->device, &dev->attr); - remove_symbol_link: - sysfs_remove_link(&tz->device.kobj, dev->name); - release_idr: - release_idr(&tz->idr, &tz->lock, dev->id); - free_mem: - kfree(dev); - return result; -} - -EXPORT_SYMBOL(thermal_zone_bind_cooling_device); - -/** - * thermal_zone_unbind_cooling_device - unbind a cooling device from a thermal zone - * @tz: thermal zone device - * @trip: indicates which trip point the cooling devices is - * associated with in this thermal zone. - * @cdev: thermal cooling device - * - * This function is usually called in the thermal zone device .unbind callback. - */ -int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz, - int trip, - struct thermal_cooling_device *cdev) -{ - struct thermal_cooling_device_instance *pos, *next; - - mutex_lock(&tz->lock); - list_for_each_entry_safe(pos, next, &tz->cooling_devices, node) { - if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) { - list_del(&pos->node); - mutex_unlock(&tz->lock); - goto unbind; - } - } - mutex_unlock(&tz->lock); - - return -ENODEV; - - unbind: - device_remove_file(&tz->device, &pos->attr); - sysfs_remove_link(&tz->device.kobj, pos->name); - release_idr(&tz->idr, &tz->lock, pos->id); - kfree(pos); - return 0; -} - -EXPORT_SYMBOL(thermal_zone_unbind_cooling_device); - -static void thermal_release(struct device *dev) -{ - struct thermal_zone_device *tz; - struct thermal_cooling_device *cdev; - - if (!strncmp(dev->bus_id, "thermal_zone", sizeof "thermal_zone" - 1)) { - tz = to_thermal_zone(dev); - kfree(tz); - } else { - cdev = to_cooling_device(dev); - kfree(cdev); - } -} - -static struct class thermal_class = { - .name = "thermal", - .dev_release = thermal_release, -}; - -/** - * thermal_cooling_device_register - register a new thermal cooling device - * @type: the thermal cooling device type. - * @devdata: device private data. - * @ops: standard thermal cooling devices callbacks. - */ -struct thermal_cooling_device *thermal_cooling_device_register(char *type, - void *devdata, - struct - thermal_cooling_device_ops - *ops) -{ - struct thermal_cooling_device *cdev; - struct thermal_zone_device *pos; - int result; - - if (strlen(type) >= THERMAL_NAME_LENGTH) - return ERR_PTR(-EINVAL); - - if (!ops || !ops->get_max_state || !ops->get_cur_state || - !ops->set_cur_state) - return ERR_PTR(-EINVAL); - - cdev = kzalloc(sizeof(struct thermal_cooling_device), GFP_KERNEL); - if (!cdev) - return ERR_PTR(-ENOMEM); - - result = get_idr(&thermal_cdev_idr, &thermal_idr_lock, &cdev->id); - if (result) { - kfree(cdev); - return ERR_PTR(result); - } - - strcpy(cdev->type, type); - cdev->ops = ops; - cdev->device.class = &thermal_class; - cdev->devdata = devdata; - sprintf(cdev->device.bus_id, "cooling_device%d", cdev->id); - result = device_register(&cdev->device); - if (result) { - release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id); - kfree(cdev); - return ERR_PTR(result); - } - - /* sys I/F */ - if (type) { - result = device_create_file(&cdev->device, &dev_attr_cdev_type); - if (result) - goto unregister; - } - - result = device_create_file(&cdev->device, &dev_attr_max_state); - if (result) - goto unregister; - - result = device_create_file(&cdev->device, &dev_attr_cur_state); - if (result) - goto unregister; - - mutex_lock(&thermal_list_lock); - list_add(&cdev->node, &thermal_cdev_list); - list_for_each_entry(pos, &thermal_tz_list, node) { - if (!pos->ops->bind) - continue; - result = pos->ops->bind(pos, cdev); - if (result) - break; - - } - mutex_unlock(&thermal_list_lock); - - if (!result) - return cdev; - - unregister: - release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id); - device_unregister(&cdev->device); - return ERR_PTR(result); -} - -EXPORT_SYMBOL(thermal_cooling_device_register); - -/** - * thermal_cooling_device_unregister - removes the registered thermal cooling device - * @cdev: the thermal cooling device to remove. - * - * thermal_cooling_device_unregister() must be called when the device is no - * longer needed. - */ -void thermal_cooling_device_unregister(struct - thermal_cooling_device - *cdev) -{ - struct thermal_zone_device *tz; - struct thermal_cooling_device *pos = NULL; - - if (!cdev) - return; - - mutex_lock(&thermal_list_lock); - list_for_each_entry(pos, &thermal_cdev_list, node) - if (pos == cdev) - break; - if (pos != cdev) { - /* thermal cooling device not found */ - mutex_unlock(&thermal_list_lock); - return; - } - list_del(&cdev->node); - list_for_each_entry(tz, &thermal_tz_list, node) { - if (!tz->ops->unbind) - continue; - tz->ops->unbind(tz, cdev); - } - mutex_unlock(&thermal_list_lock); - if (cdev->type[0]) - device_remove_file(&cdev->device, &dev_attr_cdev_type); - device_remove_file(&cdev->device, &dev_attr_max_state); - device_remove_file(&cdev->device, &dev_attr_cur_state); - - release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id); - device_unregister(&cdev->device); - return; -} - -EXPORT_SYMBOL(thermal_cooling_device_unregister); - -/** - * thermal_zone_device_register - register a new thermal zone device - * @type: the thermal zone device type - * @trips: the number of trip points the thermal zone support - * @devdata: private device data - * @ops: standard thermal zone device callbacks - * - * thermal_zone_device_unregister() must be called when the device is no - * longer needed. - */ -struct thermal_zone_device *thermal_zone_device_register(char *type, - int trips, - void *devdata, struct - thermal_zone_device_ops - *ops) -{ - struct thermal_zone_device *tz; - struct thermal_cooling_device *pos; - int result; - int count; - - if (strlen(type) >= THERMAL_NAME_LENGTH) - return ERR_PTR(-EINVAL); - - if (trips > THERMAL_MAX_TRIPS || trips < 0) - return ERR_PTR(-EINVAL); - - if (!ops || !ops->get_temp) - return ERR_PTR(-EINVAL); - - tz = kzalloc(sizeof(struct thermal_zone_device), GFP_KERNEL); - if (!tz) - return ERR_PTR(-ENOMEM); - - INIT_LIST_HEAD(&tz->cooling_devices); - idr_init(&tz->idr); - mutex_init(&tz->lock); - result = get_idr(&thermal_tz_idr, &thermal_idr_lock, &tz->id); - if (result) { - kfree(tz); - return ERR_PTR(result); - } - - strcpy(tz->type, type); - tz->ops = ops; - tz->device.class = &thermal_class; - tz->devdata = devdata; - tz->trips = trips; - sprintf(tz->device.bus_id, "thermal_zone%d", tz->id); - result = device_register(&tz->device); - if (result) { - release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); - kfree(tz); - return ERR_PTR(result); - } - - /* sys I/F */ - if (type) { - result = device_create_file(&tz->device, &dev_attr_type); - if (result) - goto unregister; - } - - result = device_create_file(&tz->device, &dev_attr_temp); - if (result) - goto unregister; - - if (ops->get_mode) { - result = device_create_file(&tz->device, &dev_attr_mode); - if (result) - goto unregister; - } - - for (count = 0; count < trips; count++) { - TRIP_POINT_ATTR_ADD(&tz->device, count, result); - if (result) - goto unregister; - } - - result = thermal_add_hwmon_sysfs(tz); - if (result) - goto unregister; - - mutex_lock(&thermal_list_lock); - list_add_tail(&tz->node, &thermal_tz_list); - if (ops->bind) - list_for_each_entry(pos, &thermal_cdev_list, node) { - result = ops->bind(tz, pos); - if (result) - break; - } - mutex_unlock(&thermal_list_lock); - - if (!result) - return tz; - - unregister: - release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); - device_unregister(&tz->device); - return ERR_PTR(result); -} - -EXPORT_SYMBOL(thermal_zone_device_register); - -/** - * thermal_device_unregister - removes the registered thermal zone device - * @tz: the thermal zone device to remove - */ -void thermal_zone_device_unregister(struct thermal_zone_device *tz) -{ - struct thermal_cooling_device *cdev; - struct thermal_zone_device *pos = NULL; - int count; - - if (!tz) - return; - - mutex_lock(&thermal_list_lock); - list_for_each_entry(pos, &thermal_tz_list, node) - if (pos == tz) - break; - if (pos != tz) { - /* thermal zone device not found */ - mutex_unlock(&thermal_list_lock); - return; - } - list_del(&tz->node); - if (tz->ops->unbind) - list_for_each_entry(cdev, &thermal_cdev_list, node) - tz->ops->unbind(tz, cdev); - mutex_unlock(&thermal_list_lock); - - if (tz->type[0]) - device_remove_file(&tz->device, &dev_attr_type); - device_remove_file(&tz->device, &dev_attr_temp); - if (tz->ops->get_mode) - device_remove_file(&tz->device, &dev_attr_mode); - - for (count = 0; count < tz->trips; count++) - TRIP_POINT_ATTR_REMOVE(&tz->device, count); - - thermal_remove_hwmon_sysfs(tz); - release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); - idr_destroy(&tz->idr); - mutex_destroy(&tz->lock); - device_unregister(&tz->device); - return; -} - -EXPORT_SYMBOL(thermal_zone_device_unregister); - -static int __init thermal_init(void) -{ - int result = 0; - - result = class_register(&thermal_class); - if (result) { - idr_destroy(&thermal_tz_idr); - idr_destroy(&thermal_cdev_idr); - mutex_destroy(&thermal_idr_lock); - mutex_destroy(&thermal_list_lock); - } - return result; -} - -static void __exit thermal_exit(void) -{ - class_unregister(&thermal_class); - idr_destroy(&thermal_tz_idr); - idr_destroy(&thermal_cdev_idr); - mutex_destroy(&thermal_idr_lock); - mutex_destroy(&thermal_list_lock); -} - -subsys_initcall(thermal_init); -module_exit(thermal_exit); diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c new file mode 100644 index 000000000000..6098787341f3 --- /dev/null +++ b/drivers/thermal/thermal_sys.c @@ -0,0 +1,899 @@ +/* + * thermal.c - Generic Thermal Management Sysfs support. + * + * Copyright (C) 2008 Intel Corp + * Copyright (C) 2008 Zhang Rui + * Copyright (C) 2008 Sujith Thomas + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#include +#include +#include +#include +#include +#include +#include + +MODULE_AUTHOR("Zhang Rui"); +MODULE_DESCRIPTION("Generic thermal management sysfs support"); +MODULE_LICENSE("GPL"); + +#define PREFIX "Thermal: " + +struct thermal_cooling_device_instance { + int id; + char name[THERMAL_NAME_LENGTH]; + struct thermal_zone_device *tz; + struct thermal_cooling_device *cdev; + int trip; + char attr_name[THERMAL_NAME_LENGTH]; + struct device_attribute attr; + struct list_head node; +}; + +static DEFINE_IDR(thermal_tz_idr); +static DEFINE_IDR(thermal_cdev_idr); +static DEFINE_MUTEX(thermal_idr_lock); + +static LIST_HEAD(thermal_tz_list); +static LIST_HEAD(thermal_cdev_list); +static DEFINE_MUTEX(thermal_list_lock); + +static int get_idr(struct idr *idr, struct mutex *lock, int *id) +{ + int err; + + again: + if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0)) + return -ENOMEM; + + if (lock) + mutex_lock(lock); + err = idr_get_new(idr, NULL, id); + if (lock) + mutex_unlock(lock); + if (unlikely(err == -EAGAIN)) + goto again; + else if (unlikely(err)) + return err; + + *id = *id & MAX_ID_MASK; + return 0; +} + +static void release_idr(struct idr *idr, struct mutex *lock, int id) +{ + if (lock) + mutex_lock(lock); + idr_remove(idr, id); + if (lock) + mutex_unlock(lock); +} + +/* sys I/F for thermal zone */ + +#define to_thermal_zone(_dev) \ + container_of(_dev, struct thermal_zone_device, device) + +static ssize_t +type_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct thermal_zone_device *tz = to_thermal_zone(dev); + + return sprintf(buf, "%s\n", tz->type); +} + +static ssize_t +temp_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct thermal_zone_device *tz = to_thermal_zone(dev); + + if (!tz->ops->get_temp) + return -EPERM; + + return tz->ops->get_temp(tz, buf); +} + +static ssize_t +mode_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct thermal_zone_device *tz = to_thermal_zone(dev); + + if (!tz->ops->get_mode) + return -EPERM; + + return tz->ops->get_mode(tz, buf); +} + +static ssize_t +mode_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct thermal_zone_device *tz = to_thermal_zone(dev); + int result; + + if (!tz->ops->set_mode) + return -EPERM; + + result = tz->ops->set_mode(tz, buf); + if (result) + return result; + + return count; +} + +static ssize_t +trip_point_type_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct thermal_zone_device *tz = to_thermal_zone(dev); + int trip; + + if (!tz->ops->get_trip_type) + return -EPERM; + + if (!sscanf(attr->attr.name, "trip_point_%d_type", &trip)) + return -EINVAL; + + return tz->ops->get_trip_type(tz, trip, buf); +} + +static ssize_t +trip_point_temp_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct thermal_zone_device *tz = to_thermal_zone(dev); + int trip; + + if (!tz->ops->get_trip_temp) + return -EPERM; + + if (!sscanf(attr->attr.name, "trip_point_%d_temp", &trip)) + return -EINVAL; + + return tz->ops->get_trip_temp(tz, trip, buf); +} + +static DEVICE_ATTR(type, 0444, type_show, NULL); +static DEVICE_ATTR(temp, 0444, temp_show, NULL); +static DEVICE_ATTR(mode, 0644, mode_show, mode_store); + +static struct device_attribute trip_point_attrs[] = { + __ATTR(trip_point_0_type, 0444, trip_point_type_show, NULL), + __ATTR(trip_point_0_temp, 0444, trip_point_temp_show, NULL), + __ATTR(trip_point_1_type, 0444, trip_point_type_show, NULL), + __ATTR(trip_point_1_temp, 0444, trip_point_temp_show, NULL), + __ATTR(trip_point_2_type, 0444, trip_point_type_show, NULL), + __ATTR(trip_point_2_temp, 0444, trip_point_temp_show, NULL), + __ATTR(trip_point_3_type, 0444, trip_point_type_show, NULL), + __ATTR(trip_point_3_temp, 0444, trip_point_temp_show, NULL), + __ATTR(trip_point_4_type, 0444, trip_point_type_show, NULL), + __ATTR(trip_point_4_temp, 0444, trip_point_temp_show, NULL), + __ATTR(trip_point_5_type, 0444, trip_point_type_show, NULL), + __ATTR(trip_point_5_temp, 0444, trip_point_temp_show, NULL), + __ATTR(trip_point_6_type, 0444, trip_point_type_show, NULL), + __ATTR(trip_point_6_temp, 0444, trip_point_temp_show, NULL), + __ATTR(trip_point_7_type, 0444, trip_point_type_show, NULL), + __ATTR(trip_point_7_temp, 0444, trip_point_temp_show, NULL), + __ATTR(trip_point_8_type, 0444, trip_point_type_show, NULL), + __ATTR(trip_point_8_temp, 0444, trip_point_temp_show, NULL), + __ATTR(trip_point_9_type, 0444, trip_point_type_show, NULL), + __ATTR(trip_point_9_temp, 0444, trip_point_temp_show, NULL), + __ATTR(trip_point_10_type, 0444, trip_point_type_show, NULL), + __ATTR(trip_point_10_temp, 0444, trip_point_temp_show, NULL), + __ATTR(trip_point_11_type, 0444, trip_point_type_show, NULL), + __ATTR(trip_point_11_temp, 0444, trip_point_temp_show, NULL), +}; + +#define TRIP_POINT_ATTR_ADD(_dev, _index, result) \ +do { \ + result = device_create_file(_dev, \ + &trip_point_attrs[_index * 2]); \ + if (result) \ + break; \ + result = device_create_file(_dev, \ + &trip_point_attrs[_index * 2 + 1]); \ +} while (0) + +#define TRIP_POINT_ATTR_REMOVE(_dev, _index) \ +do { \ + device_remove_file(_dev, &trip_point_attrs[_index * 2]); \ + device_remove_file(_dev, &trip_point_attrs[_index * 2 + 1]); \ +} while (0) + +/* sys I/F for cooling device */ +#define to_cooling_device(_dev) \ + container_of(_dev, struct thermal_cooling_device, device) + +static ssize_t +thermal_cooling_device_type_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct thermal_cooling_device *cdev = to_cooling_device(dev); + + return sprintf(buf, "%s\n", cdev->type); +} + +static ssize_t +thermal_cooling_device_max_state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct thermal_cooling_device *cdev = to_cooling_device(dev); + + return cdev->ops->get_max_state(cdev, buf); +} + +static ssize_t +thermal_cooling_device_cur_state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct thermal_cooling_device *cdev = to_cooling_device(dev); + + return cdev->ops->get_cur_state(cdev, buf); +} + +static ssize_t +thermal_cooling_device_cur_state_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct thermal_cooling_device *cdev = to_cooling_device(dev); + int state; + int result; + + if (!sscanf(buf, "%d\n", &state)) + return -EINVAL; + + if (state < 0) + return -EINVAL; + + result = cdev->ops->set_cur_state(cdev, state); + if (result) + return result; + return count; +} + +static struct device_attribute dev_attr_cdev_type = +__ATTR(type, 0444, thermal_cooling_device_type_show, NULL); +static DEVICE_ATTR(max_state, 0444, + thermal_cooling_device_max_state_show, NULL); +static DEVICE_ATTR(cur_state, 0644, + thermal_cooling_device_cur_state_show, + thermal_cooling_device_cur_state_store); + +static ssize_t +thermal_cooling_device_trip_point_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct thermal_cooling_device_instance *instance; + + instance = + container_of(attr, struct thermal_cooling_device_instance, attr); + + if (instance->trip == THERMAL_TRIPS_NONE) + return sprintf(buf, "-1\n"); + else + return sprintf(buf, "%d\n", instance->trip); +} + +/* Device management */ + +#if defined(CONFIG_HWMON) || \ + (defined(CONFIG_HWMON_MODULE) && defined(CONFIG_THERMAL_MODULE)) +/* hwmon sys I/F */ +#include +static LIST_HEAD(thermal_hwmon_list); + +static ssize_t +name_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct thermal_hwmon_device *hwmon = dev->driver_data; + return sprintf(buf, "%s\n", hwmon->type); +} +static DEVICE_ATTR(name, 0444, name_show, NULL); + +static ssize_t +temp_input_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct thermal_hwmon_attr *hwmon_attr + = container_of(attr, struct thermal_hwmon_attr, attr); + struct thermal_zone_device *tz + = container_of(hwmon_attr, struct thermal_zone_device, + temp_input); + + return tz->ops->get_temp(tz, buf); +} + +static ssize_t +temp_crit_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct thermal_hwmon_attr *hwmon_attr + = container_of(attr, struct thermal_hwmon_attr, attr); + struct thermal_zone_device *tz + = container_of(hwmon_attr, struct thermal_zone_device, + temp_crit); + + return tz->ops->get_trip_temp(tz, 0, buf); +} + + +static int +thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) +{ + struct thermal_hwmon_device *hwmon; + int new_hwmon_device = 1; + int result; + + mutex_lock(&thermal_list_lock); + list_for_each_entry(hwmon, &thermal_hwmon_list, node) + if (!strcmp(hwmon->type, tz->type)) { + new_hwmon_device = 0; + mutex_unlock(&thermal_list_lock); + goto register_sys_interface; + } + mutex_unlock(&thermal_list_lock); + + hwmon = kzalloc(sizeof(struct thermal_hwmon_device), GFP_KERNEL); + if (!hwmon) + return -ENOMEM; + + INIT_LIST_HEAD(&hwmon->tz_list); + strlcpy(hwmon->type, tz->type, THERMAL_NAME_LENGTH); + hwmon->device = hwmon_device_register(NULL); + if (IS_ERR(hwmon->device)) { + result = PTR_ERR(hwmon->device); + goto free_mem; + } + hwmon->device->driver_data = hwmon; + result = device_create_file(hwmon->device, &dev_attr_name); + if (result) + goto unregister_hwmon_device; + + register_sys_interface: + tz->hwmon = hwmon; + hwmon->count++; + + snprintf(tz->temp_input.name, THERMAL_NAME_LENGTH, + "temp%d_input", hwmon->count); + tz->temp_input.attr.attr.name = tz->temp_input.name; + tz->temp_input.attr.attr.mode = 0444; + tz->temp_input.attr.show = temp_input_show; + result = device_create_file(hwmon->device, &tz->temp_input.attr); + if (result) + goto unregister_hwmon_device; + + if (tz->ops->get_crit_temp) { + unsigned long temperature; + if (!tz->ops->get_crit_temp(tz, &temperature)) { + snprintf(tz->temp_crit.name, THERMAL_NAME_LENGTH, + "temp%d_crit", hwmon->count); + tz->temp_crit.attr.attr.name = tz->temp_crit.name; + tz->temp_crit.attr.attr.mode = 0444; + tz->temp_crit.attr.show = temp_crit_show; + result = device_create_file(hwmon->device, + &tz->temp_crit.attr); + if (result) + goto unregister_hwmon_device; + } + } + + mutex_lock(&thermal_list_lock); + if (new_hwmon_device) + list_add_tail(&hwmon->node, &thermal_hwmon_list); + list_add_tail(&tz->hwmon_node, &hwmon->tz_list); + mutex_unlock(&thermal_list_lock); + + return 0; + + unregister_hwmon_device: + device_remove_file(hwmon->device, &tz->temp_crit.attr); + device_remove_file(hwmon->device, &tz->temp_input.attr); + if (new_hwmon_device) { + device_remove_file(hwmon->device, &dev_attr_name); + hwmon_device_unregister(hwmon->device); + } + free_mem: + if (new_hwmon_device) + kfree(hwmon); + + return result; +} + +static void +thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz) +{ + struct thermal_hwmon_device *hwmon = tz->hwmon; + + tz->hwmon = NULL; + device_remove_file(hwmon->device, &tz->temp_input.attr); + device_remove_file(hwmon->device, &tz->temp_crit.attr); + + mutex_lock(&thermal_list_lock); + list_del(&tz->hwmon_node); + if (!list_empty(&hwmon->tz_list)) { + mutex_unlock(&thermal_list_lock); + return; + } + list_del(&hwmon->node); + mutex_unlock(&thermal_list_lock); + + device_remove_file(hwmon->device, &dev_attr_name); + hwmon_device_unregister(hwmon->device); + kfree(hwmon); +} +#else +static int +thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) +{ + return 0; +} + +static void +thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz) +{ +} +#endif + + +/** + * thermal_zone_bind_cooling_device - bind a cooling device to a thermal zone + * @tz: thermal zone device + * @trip: indicates which trip point the cooling devices is + * associated with in this thermal zone. + * @cdev: thermal cooling device + * + * This function is usually called in the thermal zone device .bind callback. + */ +int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, + int trip, + struct thermal_cooling_device *cdev) +{ + struct thermal_cooling_device_instance *dev; + struct thermal_cooling_device_instance *pos; + struct thermal_zone_device *pos1; + struct thermal_cooling_device *pos2; + int result; + + if (trip >= tz->trips || (trip < 0 && trip != THERMAL_TRIPS_NONE)) + return -EINVAL; + + list_for_each_entry(pos1, &thermal_tz_list, node) { + if (pos1 == tz) + break; + } + list_for_each_entry(pos2, &thermal_cdev_list, node) { + if (pos2 == cdev) + break; + } + + if (tz != pos1 || cdev != pos2) + return -EINVAL; + + dev = + kzalloc(sizeof(struct thermal_cooling_device_instance), GFP_KERNEL); + if (!dev) + return -ENOMEM; + dev->tz = tz; + dev->cdev = cdev; + dev->trip = trip; + result = get_idr(&tz->idr, &tz->lock, &dev->id); + if (result) + goto free_mem; + + sprintf(dev->name, "cdev%d", dev->id); + result = + sysfs_create_link(&tz->device.kobj, &cdev->device.kobj, dev->name); + if (result) + goto release_idr; + + sprintf(dev->attr_name, "cdev%d_trip_point", dev->id); + dev->attr.attr.name = dev->attr_name; + dev->attr.attr.mode = 0444; + dev->attr.show = thermal_cooling_device_trip_point_show; + result = device_create_file(&tz->device, &dev->attr); + if (result) + goto remove_symbol_link; + + mutex_lock(&tz->lock); + list_for_each_entry(pos, &tz->cooling_devices, node) + if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) { + result = -EEXIST; + break; + } + if (!result) + list_add_tail(&dev->node, &tz->cooling_devices); + mutex_unlock(&tz->lock); + + if (!result) + return 0; + + device_remove_file(&tz->device, &dev->attr); + remove_symbol_link: + sysfs_remove_link(&tz->device.kobj, dev->name); + release_idr: + release_idr(&tz->idr, &tz->lock, dev->id); + free_mem: + kfree(dev); + return result; +} + +EXPORT_SYMBOL(thermal_zone_bind_cooling_device); + +/** + * thermal_zone_unbind_cooling_device - unbind a cooling device from a thermal zone + * @tz: thermal zone device + * @trip: indicates which trip point the cooling devices is + * associated with in this thermal zone. + * @cdev: thermal cooling device + * + * This function is usually called in the thermal zone device .unbind callback. + */ +int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz, + int trip, + struct thermal_cooling_device *cdev) +{ + struct thermal_cooling_device_instance *pos, *next; + + mutex_lock(&tz->lock); + list_for_each_entry_safe(pos, next, &tz->cooling_devices, node) { + if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) { + list_del(&pos->node); + mutex_unlock(&tz->lock); + goto unbind; + } + } + mutex_unlock(&tz->lock); + + return -ENODEV; + + unbind: + device_remove_file(&tz->device, &pos->attr); + sysfs_remove_link(&tz->device.kobj, pos->name); + release_idr(&tz->idr, &tz->lock, pos->id); + kfree(pos); + return 0; +} + +EXPORT_SYMBOL(thermal_zone_unbind_cooling_device); + +static void thermal_release(struct device *dev) +{ + struct thermal_zone_device *tz; + struct thermal_cooling_device *cdev; + + if (!strncmp(dev->bus_id, "thermal_zone", sizeof "thermal_zone" - 1)) { + tz = to_thermal_zone(dev); + kfree(tz); + } else { + cdev = to_cooling_device(dev); + kfree(cdev); + } +} + +static struct class thermal_class = { + .name = "thermal", + .dev_release = thermal_release, +}; + +/** + * thermal_cooling_device_register - register a new thermal cooling device + * @type: the thermal cooling device type. + * @devdata: device private data. + * @ops: standard thermal cooling devices callbacks. + */ +struct thermal_cooling_device *thermal_cooling_device_register(char *type, + void *devdata, + struct + thermal_cooling_device_ops + *ops) +{ + struct thermal_cooling_device *cdev; + struct thermal_zone_device *pos; + int result; + + if (strlen(type) >= THERMAL_NAME_LENGTH) + return ERR_PTR(-EINVAL); + + if (!ops || !ops->get_max_state || !ops->get_cur_state || + !ops->set_cur_state) + return ERR_PTR(-EINVAL); + + cdev = kzalloc(sizeof(struct thermal_cooling_device), GFP_KERNEL); + if (!cdev) + return ERR_PTR(-ENOMEM); + + result = get_idr(&thermal_cdev_idr, &thermal_idr_lock, &cdev->id); + if (result) { + kfree(cdev); + return ERR_PTR(result); + } + + strcpy(cdev->type, type); + cdev->ops = ops; + cdev->device.class = &thermal_class; + cdev->devdata = devdata; + sprintf(cdev->device.bus_id, "cooling_device%d", cdev->id); + result = device_register(&cdev->device); + if (result) { + release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id); + kfree(cdev); + return ERR_PTR(result); + } + + /* sys I/F */ + if (type) { + result = device_create_file(&cdev->device, &dev_attr_cdev_type); + if (result) + goto unregister; + } + + result = device_create_file(&cdev->device, &dev_attr_max_state); + if (result) + goto unregister; + + result = device_create_file(&cdev->device, &dev_attr_cur_state); + if (result) + goto unregister; + + mutex_lock(&thermal_list_lock); + list_add(&cdev->node, &thermal_cdev_list); + list_for_each_entry(pos, &thermal_tz_list, node) { + if (!pos->ops->bind) + continue; + result = pos->ops->bind(pos, cdev); + if (result) + break; + + } + mutex_unlock(&thermal_list_lock); + + if (!result) + return cdev; + + unregister: + release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id); + device_unregister(&cdev->device); + return ERR_PTR(result); +} + +EXPORT_SYMBOL(thermal_cooling_device_register); + +/** + * thermal_cooling_device_unregister - removes the registered thermal cooling device + * @cdev: the thermal cooling device to remove. + * + * thermal_cooling_device_unregister() must be called when the device is no + * longer needed. + */ +void thermal_cooling_device_unregister(struct + thermal_cooling_device + *cdev) +{ + struct thermal_zone_device *tz; + struct thermal_cooling_device *pos = NULL; + + if (!cdev) + return; + + mutex_lock(&thermal_list_lock); + list_for_each_entry(pos, &thermal_cdev_list, node) + if (pos == cdev) + break; + if (pos != cdev) { + /* thermal cooling device not found */ + mutex_unlock(&thermal_list_lock); + return; + } + list_del(&cdev->node); + list_for_each_entry(tz, &thermal_tz_list, node) { + if (!tz->ops->unbind) + continue; + tz->ops->unbind(tz, cdev); + } + mutex_unlock(&thermal_list_lock); + if (cdev->type[0]) + device_remove_file(&cdev->device, &dev_attr_cdev_type); + device_remove_file(&cdev->device, &dev_attr_max_state); + device_remove_file(&cdev->device, &dev_attr_cur_state); + + release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id); + device_unregister(&cdev->device); + return; +} + +EXPORT_SYMBOL(thermal_cooling_device_unregister); + +/** + * thermal_zone_device_register - register a new thermal zone device + * @type: the thermal zone device type + * @trips: the number of trip points the thermal zone support + * @devdata: private device data + * @ops: standard thermal zone device callbacks + * + * thermal_zone_device_unregister() must be called when the device is no + * longer needed. + */ +struct thermal_zone_device *thermal_zone_device_register(char *type, + int trips, + void *devdata, struct + thermal_zone_device_ops + *ops) +{ + struct thermal_zone_device *tz; + struct thermal_cooling_device *pos; + int result; + int count; + + if (strlen(type) >= THERMAL_NAME_LENGTH) + return ERR_PTR(-EINVAL); + + if (trips > THERMAL_MAX_TRIPS || trips < 0) + return ERR_PTR(-EINVAL); + + if (!ops || !ops->get_temp) + return ERR_PTR(-EINVAL); + + tz = kzalloc(sizeof(struct thermal_zone_device), GFP_KERNEL); + if (!tz) + return ERR_PTR(-ENOMEM); + + INIT_LIST_HEAD(&tz->cooling_devices); + idr_init(&tz->idr); + mutex_init(&tz->lock); + result = get_idr(&thermal_tz_idr, &thermal_idr_lock, &tz->id); + if (result) { + kfree(tz); + return ERR_PTR(result); + } + + strcpy(tz->type, type); + tz->ops = ops; + tz->device.class = &thermal_class; + tz->devdata = devdata; + tz->trips = trips; + sprintf(tz->device.bus_id, "thermal_zone%d", tz->id); + result = device_register(&tz->device); + if (result) { + release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); + kfree(tz); + return ERR_PTR(result); + } + + /* sys I/F */ + if (type) { + result = device_create_file(&tz->device, &dev_attr_type); + if (result) + goto unregister; + } + + result = device_create_file(&tz->device, &dev_attr_temp); + if (result) + goto unregister; + + if (ops->get_mode) { + result = device_create_file(&tz->device, &dev_attr_mode); + if (result) + goto unregister; + } + + for (count = 0; count < trips; count++) { + TRIP_POINT_ATTR_ADD(&tz->device, count, result); + if (result) + goto unregister; + } + + result = thermal_add_hwmon_sysfs(tz); + if (result) + goto unregister; + + mutex_lock(&thermal_list_lock); + list_add_tail(&tz->node, &thermal_tz_list); + if (ops->bind) + list_for_each_entry(pos, &thermal_cdev_list, node) { + result = ops->bind(tz, pos); + if (result) + break; + } + mutex_unlock(&thermal_list_lock); + + if (!result) + return tz; + + unregister: + release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); + device_unregister(&tz->device); + return ERR_PTR(result); +} + +EXPORT_SYMBOL(thermal_zone_device_register); + +/** + * thermal_device_unregister - removes the registered thermal zone device + * @tz: the thermal zone device to remove + */ +void thermal_zone_device_unregister(struct thermal_zone_device *tz) +{ + struct thermal_cooling_device *cdev; + struct thermal_zone_device *pos = NULL; + int count; + + if (!tz) + return; + + mutex_lock(&thermal_list_lock); + list_for_each_entry(pos, &thermal_tz_list, node) + if (pos == tz) + break; + if (pos != tz) { + /* thermal zone device not found */ + mutex_unlock(&thermal_list_lock); + return; + } + list_del(&tz->node); + if (tz->ops->unbind) + list_for_each_entry(cdev, &thermal_cdev_list, node) + tz->ops->unbind(tz, cdev); + mutex_unlock(&thermal_list_lock); + + if (tz->type[0]) + device_remove_file(&tz->device, &dev_attr_type); + device_remove_file(&tz->device, &dev_attr_temp); + if (tz->ops->get_mode) + device_remove_file(&tz->device, &dev_attr_mode); + + for (count = 0; count < tz->trips; count++) + TRIP_POINT_ATTR_REMOVE(&tz->device, count); + + thermal_remove_hwmon_sysfs(tz); + release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); + idr_destroy(&tz->idr); + mutex_destroy(&tz->lock); + device_unregister(&tz->device); + return; +} + +EXPORT_SYMBOL(thermal_zone_device_unregister); + +static int __init thermal_init(void) +{ + int result = 0; + + result = class_register(&thermal_class); + if (result) { + idr_destroy(&thermal_tz_idr); + idr_destroy(&thermal_cdev_idr); + mutex_destroy(&thermal_idr_lock); + mutex_destroy(&thermal_list_lock); + } + return result; +} + +static void __exit thermal_exit(void) +{ + class_unregister(&thermal_class); + idr_destroy(&thermal_tz_idr); + idr_destroy(&thermal_cdev_idr); + mutex_destroy(&thermal_idr_lock); + mutex_destroy(&thermal_list_lock); +} + +subsys_initcall(thermal_init); +module_exit(thermal_exit); -- cgit v1.2.2 From 1bd17e63a068db6f464925a79b1cc4b27a8b1af9 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:33:48 -0600 Subject: PNP: turn on -DDEBUG when CONFIG_PNP_DEBUG is set Turn on -DDEBUG in CFLAGS when CONFIG_PNP_DEBUG=y. This makes dev_dbg() do what you expect. Signed-off-by: Bjorn Helgaas Acked-by: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/isapnp/Makefile | 4 ++++ drivers/pnp/pnpacpi/Makefile | 4 ++++ drivers/pnp/pnpbios/Makefile | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/drivers/pnp/isapnp/Makefile b/drivers/pnp/isapnp/Makefile index cac18bbfb817..3e38f06f8d78 100644 --- a/drivers/pnp/isapnp/Makefile +++ b/drivers/pnp/isapnp/Makefile @@ -5,3 +5,7 @@ isapnp-proc-$(CONFIG_PROC_FS) = proc.o obj-y := core.o compat.o $(isapnp-proc-y) + +ifeq ($(CONFIG_PNP_DEBUG),y) +EXTRA_CFLAGS += -DDEBUG +endif diff --git a/drivers/pnp/pnpacpi/Makefile b/drivers/pnp/pnpacpi/Makefile index 905326fcca85..2d7a1e6908be 100644 --- a/drivers/pnp/pnpacpi/Makefile +++ b/drivers/pnp/pnpacpi/Makefile @@ -3,3 +3,7 @@ # obj-y := core.o rsparser.o + +ifeq ($(CONFIG_PNP_DEBUG),y) +EXTRA_CFLAGS += -DDEBUG +endif diff --git a/drivers/pnp/pnpbios/Makefile b/drivers/pnp/pnpbios/Makefile index 3cd3ed760605..310e2b3a7710 100644 --- a/drivers/pnp/pnpbios/Makefile +++ b/drivers/pnp/pnpbios/Makefile @@ -5,3 +5,7 @@ pnpbios-proc-$(CONFIG_PNPBIOS_PROC_FS) = proc.o obj-y := core.o bioscalls.o rsparser.o $(pnpbios-proc-y) + +ifeq ($(CONFIG_PNP_DEBUG),y) +EXTRA_CFLAGS += -DDEBUG +endif -- cgit v1.2.2 From ca0e8b6fd29819891c874b86ff286987c5bfdc21 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:33:49 -0600 Subject: ISAPNP: move config register addresses out of isapnp.h These are used only in drivers/pnp/isapnp/core.c, so no need to expose them to the world. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/isapnp/core.c | 8 ++++++++ include/linux/isapnp.h | 10 ---------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index 257f5d827d83..dd67752a5828 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -88,6 +88,14 @@ MODULE_LICENSE("GPL"); #define _LTAG_MEM32RANGE 0x85 #define _LTAG_FIXEDMEM32RANGE 0x86 +/* Logical device control and configuration registers */ + +#define ISAPNP_CFG_ACTIVATE 0x30 /* byte */ +#define ISAPNP_CFG_MEM 0x40 /* 4 * dword */ +#define ISAPNP_CFG_PORT 0x60 /* 8 * word */ +#define ISAPNP_CFG_IRQ 0x70 /* 2 * word */ +#define ISAPNP_CFG_DMA 0x74 /* 2 * byte */ + /* * Sizes of ISAPNP logical device configuration register sets. * See PNP-ISA-v1.0a.pdf, Appendix A. diff --git a/include/linux/isapnp.h b/include/linux/isapnp.h index 1e8728a9ee8a..cd5a269fdb5e 100644 --- a/include/linux/isapnp.h +++ b/include/linux/isapnp.h @@ -25,16 +25,6 @@ #include #include -/* - * Configuration registers (TODO: change by specification) - */ - -#define ISAPNP_CFG_ACTIVATE 0x30 /* byte */ -#define ISAPNP_CFG_MEM 0x40 /* 4 * dword */ -#define ISAPNP_CFG_PORT 0x60 /* 8 * word */ -#define ISAPNP_CFG_IRQ 0x70 /* 2 * word */ -#define ISAPNP_CFG_DMA 0x74 /* 2 * byte */ - /* * */ -- cgit v1.2.2 From 4a490498643ea37520c315769b293085b6018ddd Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:33:50 -0600 Subject: PNPACPI: continue after _CRS and _PRS errors Keep going and register the device even if we have trouble parsing _CRS or _PRS. A parsing problem might mean we ignore some resources the device is using, or we might not be able to change its resources. But we should still take note of anything we *could* parse correctly. Also remove reference to dev_id because I plan to remove it soon. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/pnp/pnpacpi/core.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index c283a9a70d83..53f91068d0b0 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -213,8 +213,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device) &dev->res); if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { pnp_err("PnPACPI: METHOD_NAME__CRS failure for %s", - dev_id->id); - goto err1; + acpi_device_hid(device)); } } @@ -223,8 +222,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device) dev); if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { pnp_err("PnPACPI: METHOD_NAME__PRS failure for %s", - dev_id->id); - goto err1; + acpi_device_hid(device)); } } @@ -252,8 +250,6 @@ static int __init pnpacpi_add_device(struct acpi_device *device) num++; return AE_OK; -err1: - kfree(dev_id); err: kfree(dev); return -EINVAL; -- cgit v1.2.2 From 1692b27bf37826f85f9c12f8468848885643532a Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:33:51 -0600 Subject: PNP: make pnp_add_id() internal to PNP core pnp_add_id() doesn't need to be exposed outside the PNP core, so move the declaration to an internal header file. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/base.h | 1 + drivers/pnp/pnpacpi/core.c | 1 + drivers/pnp/pnpbios/core.c | 1 + include/linux/pnp.h | 2 -- 4 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index 31a633f65547..abefcc351521 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h @@ -1,5 +1,6 @@ extern spinlock_t pnp_lock; void *pnp_alloc(long size); +int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev); int pnp_interface_attach_device(struct pnp_dev *dev); void pnp_fixup_device(struct pnp_dev *dev); void pnp_free_option(struct pnp_option *option); diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 53f91068d0b0..4807d76f8a04 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -25,6 +25,7 @@ #include #include +#include "../base.h" #include "pnpacpi.h" static int num = 0; diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c index a8a51500e1e9..2a5353bceb24 100644 --- a/drivers/pnp/pnpbios/core.c +++ b/drivers/pnp/pnpbios/core.c @@ -69,6 +69,7 @@ #include #include +#include "../base.h" #include "pnpbios.h" /* diff --git a/include/linux/pnp.h b/include/linux/pnp.h index b2f05c230f4b..9a05ab5515b6 100644 --- a/include/linux/pnp.h +++ b/include/linux/pnp.h @@ -403,7 +403,6 @@ void pnp_resource_change(struct resource *resource, resource_size_t start, /* protocol helpers */ int pnp_is_active(struct pnp_dev *dev); int compare_pnp_id(struct pnp_id *pos, const char *id); -int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev); int pnp_register_driver(struct pnp_driver *drv); void pnp_unregister_driver(struct pnp_driver *drv); @@ -450,7 +449,6 @@ static inline void pnp_resource_change(struct resource *resource, resource_size_ /* protocol helpers */ static inline int pnp_is_active(struct pnp_dev *dev) { return 0; } static inline int compare_pnp_id(struct pnp_id *pos, const char *id) { return -ENODEV; } -static inline int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev) { return -ENODEV; } static inline int pnp_register_driver(struct pnp_driver *drv) { return -ENODEV; } static inline void pnp_unregister_driver(struct pnp_driver *drv) { } -- cgit v1.2.2 From 772defc6292bae8b6db298476d1dabd22a99492b Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:33:52 -0600 Subject: PNP: change pnp_add_id() to allocate its own pnp_id structures This moves some of the pnp_id knowledge out of the backends and into the PNP core. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/base.h | 2 +- drivers/pnp/driver.c | 28 +++++++++++++++++++++------- drivers/pnp/isapnp/core.c | 14 ++++++-------- drivers/pnp/pnpacpi/core.c | 25 ++----------------------- drivers/pnp/pnpbios/core.c | 6 ++---- drivers/pnp/pnpbios/rsparser.c | 9 ++++----- 6 files changed, 36 insertions(+), 48 deletions(-) diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index abefcc351521..ba55b0623f7e 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h @@ -1,6 +1,6 @@ extern spinlock_t pnp_lock; void *pnp_alloc(long size); -int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev); +struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id); int pnp_interface_attach_device(struct pnp_dev *dev); void pnp_fixup_device(struct pnp_dev *dev); void pnp_free_option(struct pnp_option *option); diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c index e85cbf116db1..d3f869ee1d92 100644 --- a/drivers/pnp/driver.c +++ b/drivers/pnp/driver.c @@ -226,22 +226,36 @@ void pnp_unregister_driver(struct pnp_driver *drv) /** * pnp_add_id - adds an EISA id to the specified device - * @id: pointer to a pnp_id structure * @dev: pointer to the desired device + * @id: pointer to an EISA id string */ -int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev) +struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id) { - struct pnp_id *ptr; + struct pnp_id *dev_id, *ptr; - id->next = NULL; + dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); + if (!dev_id) + return NULL; + + dev_id->id[0] = id[0]; + dev_id->id[1] = id[1]; + dev_id->id[2] = id[2]; + dev_id->id[3] = tolower(id[3]); + dev_id->id[4] = tolower(id[4]); + dev_id->id[5] = tolower(id[5]); + dev_id->id[6] = tolower(id[6]); + dev_id->id[7] = '\0'; + + dev_id->next = NULL; ptr = dev->id; while (ptr && ptr->next) ptr = ptr->next; if (ptr) - ptr->next = id; + ptr->next = dev_id; else - dev->id = id; - return 0; + dev->id = dev_id; + + return dev_id; } EXPORT_SYMBOL(pnp_register_driver); diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index dd67752a5828..10cade831433 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -44,6 +44,8 @@ #include #include +#include "../base.h" + #if 0 #define ISAPNP_REGION_OK #endif @@ -401,20 +403,16 @@ static void __init isapnp_skip_bytes(int count) static void isapnp_parse_id(struct pnp_dev *dev, unsigned short vendor, unsigned short device) { - struct pnp_id *id; + char id[8]; - if (!dev) - return; - id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); - if (!id) - return; - sprintf(id->id, "%c%c%c%x%x%x%x", + sprintf(id, "%c%c%c%x%x%x%x", 'A' + ((vendor >> 2) & 0x3f) - 1, 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1, 'A' + ((vendor >> 8) & 0x1f) - 1, (device >> 4) & 0x0f, device & 0x0f, (device >> 12) & 0x0f, (device >> 8) & 0x0f); - pnp_add_id(id, dev); + + pnp_add_id(dev, id); } /* diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 4807d76f8a04..86aea1ebfee7 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -73,18 +73,6 @@ static int __init ispnpidacpi(char *id) return 1; } -static void __init pnpidacpi_to_pnpid(char *id, char *str) -{ - str[0] = id[0]; - str[1] = id[1]; - str[2] = id[2]; - str[3] = tolower(id[3]); - str[4] = tolower(id[4]); - str[5] = tolower(id[5]); - str[6] = tolower(id[6]); - str[7] = '\0'; -} - static int pnpacpi_get_resources(struct pnp_dev *dev, struct pnp_resource_table *res) { @@ -201,12 +189,9 @@ static int __init pnpacpi_add_device(struct acpi_device *device) dev->number = num; - /* set the initial values for the PnP device */ - dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); + dev_id = pnp_add_id(dev, acpi_device_hid(device)); if (!dev_id) goto err; - pnpidacpi_to_pnpid(acpi_device_hid(device), dev_id->id); - pnp_add_id(dev_id, dev); if (dev->active) { /* parse allocated resource */ @@ -227,7 +212,6 @@ static int __init pnpacpi_add_device(struct acpi_device *device) } } - /* parse compatible ids */ if (device->flags.compatible_ids) { struct acpi_compatible_id_list *cid_list = device->pnp.cid_list; int i; @@ -235,12 +219,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device) for (i = 0; i < cid_list->count; i++) { if (!ispnpidacpi(cid_list->id[i].value)) continue; - dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); - if (!dev_id) - continue; - - pnpidacpi_to_pnpid(cid_list->id[i].value, dev_id->id); - pnp_add_id(dev_id, dev); + pnp_add_id(dev, cid_list->id[i].value); } } diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c index 2a5353bceb24..2d592aea0aa7 100644 --- a/drivers/pnp/pnpbios/core.c +++ b/drivers/pnp/pnpbios/core.c @@ -332,16 +332,14 @@ static int __init insert_device(struct pnp_bios_node *node) if (!dev) return -1; - dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); + pnpid32_to_pnpid(node->eisa_id, id); + dev_id = pnp_add_id(dev, id); if (!dev_id) { kfree(dev); return -1; } dev->number = node->handle; - pnpid32_to_pnpid(node->eisa_id, id); - memcpy(dev_id->id, id, 7); - pnp_add_id(dev_id, dev); pnpbios_parse_data_stream(dev, node); dev->active = pnp_is_active(dev); dev->flags = node->flags; diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c index caade3531416..dbc88412c12e 100644 --- a/drivers/pnp/pnpbios/rsparser.c +++ b/drivers/pnp/pnpbios/rsparser.c @@ -16,6 +16,7 @@ inline void pcibios_penalize_isa_irq(int irq, int active) } #endif /* CONFIG_PCI */ +#include "../base.h" #include "pnpbios.h" /* standard resource tags */ @@ -548,13 +549,11 @@ static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p, case SMALL_TAG_COMPATDEVID: /* compatible ID */ if (len != 4) goto len_err; - dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); - if (!dev_id) - return NULL; pnpid32_to_pnpid(p[1] | p[2] << 8 | p[3] << 16 | p[4] << 24, id); - memcpy(&dev_id->id, id, 7); - pnp_add_id(dev_id, dev); + dev_id = pnp_add_id(dev, id); + if (!dev_id) + return NULL; break; case SMALL_TAG_END: -- cgit v1.2.2 From 25eb846189d20db4114cebf14fee96d69bef4667 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:33:53 -0600 Subject: PNP: add pnp_eisa_id_to_string() Converting the EISA ID to a string is messy and error-prone, and we might as well use the same code for ISAPNP and PNPBIOS. PNPACPI uses the conversion done by the ACPI core with acpi_ex_eisa_id_to_string(). Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/base.h | 2 ++ drivers/pnp/isapnp/core.c | 32 +++++++++++--------------------- drivers/pnp/pnpbios/core.c | 2 +- drivers/pnp/pnpbios/rsparser.c | 26 +++----------------------- drivers/pnp/support.c | 26 ++++++++++++++++++++++++++ 5 files changed, 43 insertions(+), 45 deletions(-) diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index ba55b0623f7e..9af0a6c7dd41 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h @@ -1,5 +1,7 @@ extern spinlock_t pnp_lock; void *pnp_alloc(long size); +#define PNP_EISA_ID_MASK 0x7fffffff +void pnp_eisa_id_to_string(u32 id, char *str); struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id); int pnp_interface_attach_device(struct pnp_dev *dev); void pnp_fixup_device(struct pnp_dev *dev); diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index 10cade831433..ccb04190044b 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -397,24 +397,6 @@ static void __init isapnp_skip_bytes(int count) isapnp_peek(NULL, count); } -/* - * Parse EISA id. - */ -static void isapnp_parse_id(struct pnp_dev *dev, unsigned short vendor, - unsigned short device) -{ - char id[8]; - - sprintf(id, "%c%c%c%x%x%x%x", - 'A' + ((vendor >> 2) & 0x3f) - 1, - 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1, - 'A' + ((vendor >> 8) & 0x1f) - 1, - (device >> 4) & 0x0f, - device & 0x0f, (device >> 12) & 0x0f, (device >> 8) & 0x0f); - - pnp_add_id(dev, id); -} - /* * Parse logical device tag. */ @@ -423,13 +405,17 @@ static struct pnp_dev *__init isapnp_parse_device(struct pnp_card *card, { unsigned char tmp[6]; struct pnp_dev *dev; + u32 eisa_id; + char id[8]; isapnp_peek(tmp, size); dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL); if (!dev) return NULL; dev->number = number; - isapnp_parse_id(dev, (tmp[1] << 8) | tmp[0], (tmp[3] << 8) | tmp[2]); + eisa_id = tmp[0] | tmp[1] << 8 | tmp[2] << 16 | tmp[3] << 24; + pnp_eisa_id_to_string(eisa_id, id); + pnp_add_id(dev, id); dev->regs = tmp[4]; dev->card = card; if (size > 5) @@ -619,6 +605,8 @@ static int __init isapnp_create_device(struct pnp_card *card, unsigned char type, tmp[17]; struct pnp_option *option; struct pnp_dev *dev; + u32 eisa_id; + char id[8]; if ((dev = isapnp_parse_device(card, size, number++)) == NULL) return 1; @@ -658,8 +646,10 @@ static int __init isapnp_create_device(struct pnp_card *card, case _STAG_COMPATDEVID: if (size == 4 && compat < DEVICE_COUNT_COMPATIBLE) { isapnp_peek(tmp, 4); - isapnp_parse_id(dev, (tmp[1] << 8) | tmp[0], - (tmp[3] << 8) | tmp[2]); + eisa_id = tmp[0] | tmp[1] << 8 | + tmp[2] << 16 | tmp[3] << 24; + pnp_eisa_id_to_string(eisa_id, id); + pnp_add_id(dev, id); compat++; size = 0; } diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c index 2d592aea0aa7..3ee5ed437385 100644 --- a/drivers/pnp/pnpbios/core.c +++ b/drivers/pnp/pnpbios/core.c @@ -332,7 +332,7 @@ static int __init insert_device(struct pnp_bios_node *node) if (!dev) return -1; - pnpid32_to_pnpid(node->eisa_id, id); + pnp_eisa_id_to_string(node->eisa_id & PNP_EISA_ID_MASK, id); dev_id = pnp_add_id(dev, id); if (!dev_id) { kfree(dev); diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c index dbc88412c12e..948a661280d7 100644 --- a/drivers/pnp/pnpbios/rsparser.c +++ b/drivers/pnp/pnpbios/rsparser.c @@ -494,32 +494,12 @@ len_err: * Compatible Device IDs */ -#define HEX(id,a) hex[((id)>>a) & 15] -#define CHAR(id,a) (0x40 + (((id)>>a) & 31)) - -void pnpid32_to_pnpid(u32 id, char *str) -{ - const char *hex = "0123456789abcdef"; - - id = be32_to_cpu(id); - str[0] = CHAR(id, 26); - str[1] = CHAR(id, 21); - str[2] = CHAR(id, 16); - str[3] = HEX(id, 12); - str[4] = HEX(id, 8); - str[5] = HEX(id, 4); - str[6] = HEX(id, 0); - str[7] = '\0'; -} - -#undef CHAR -#undef HEX - static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p, unsigned char *end, struct pnp_dev *dev) { int len, tag; + u32 eisa_id; char id[8]; struct pnp_id *dev_id; @@ -549,8 +529,8 @@ static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p, case SMALL_TAG_COMPATDEVID: /* compatible ID */ if (len != 4) goto len_err; - pnpid32_to_pnpid(p[1] | p[2] << 8 | p[3] << 16 | p[4] << - 24, id); + eisa_id = p[1] | p[2] << 8 | p[3] << 16 | p[4] << 24; + pnp_eisa_id_to_string(eisa_id & PNP_EISA_ID_MASK, id); dev_id = pnp_add_id(dev, id); if (!dev_id) return NULL; diff --git a/drivers/pnp/support.c b/drivers/pnp/support.c index 13c608f5fb30..e848b794e312 100644 --- a/drivers/pnp/support.c +++ b/drivers/pnp/support.c @@ -25,3 +25,29 @@ int pnp_is_active(struct pnp_dev *dev) } EXPORT_SYMBOL(pnp_is_active); + +/* + * Functionally similar to acpi_ex_eisa_id_to_string(), but that's + * buried in the ACPI CA, and we can't depend on it being present. + */ +void pnp_eisa_id_to_string(u32 id, char *str) +{ + id = be32_to_cpu(id); + + /* + * According to the specs, the first three characters are five-bit + * compressed ASCII, and the left-over high order bit should be zero. + * However, the Linux ISAPNP code historically used six bits for the + * first character, and there seem to be IDs that depend on that, + * e.g., "nEC8241" in the Linux 8250_pnp serial driver and the + * FreeBSD sys/pc98/cbus/sio_cbus.c driver. + */ + str[0] = 'A' + ((id >> 26) & 0x3f) - 1; + str[1] = 'A' + ((id >> 21) & 0x1f) - 1; + str[2] = 'A' + ((id >> 16) & 0x1f) - 1; + str[3] = hex_asc((id >> 12) & 0xf); + str[4] = hex_asc((id >> 8) & 0xf); + str[5] = hex_asc((id >> 4) & 0xf); + str[6] = hex_asc((id >> 0) & 0xf); + str[7] = '\0'; +} -- cgit v1.2.2 From bda1e4e5a3d976046378cd495a63e1ee0847deec Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:33:54 -0600 Subject: PNP: add pnp_alloc_dev() Add pnp_alloc_dev() to allocate a struct pnp_dev and fill in the protocol, instance number, and initial PNP ID. Now it is always valid to use dev_printk() on any pnp_dev pointer. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/base.h | 1 + drivers/pnp/core.c | 38 +++++++++++++++++++++++++++++++------- drivers/pnp/isapnp/core.c | 11 +++++------ drivers/pnp/pnpacpi/core.c | 19 +++---------------- drivers/pnp/pnpbios/core.c | 13 ++----------- 5 files changed, 42 insertions(+), 40 deletions(-) diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index 9af0a6c7dd41..ff435bd1ca18 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h @@ -2,6 +2,7 @@ extern spinlock_t pnp_lock; void *pnp_alloc(long size); #define PNP_EISA_ID_MASK 0x7fffffff void pnp_eisa_id_to_string(u32 id, char *str); +struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *, int id, char *pnpid); struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id); int pnp_interface_attach_device(struct pnp_dev *dev); void pnp_fixup_device(struct pnp_dev *dev); diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c index 7d366ca672d3..cf37701a4f9e 100644 --- a/drivers/pnp/core.c +++ b/drivers/pnp/core.c @@ -109,15 +109,42 @@ static void pnp_release_device(struct device *dmdev) kfree(dev); } -int __pnp_add_device(struct pnp_dev *dev) +struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, char *pnpid) { - int ret; + struct pnp_dev *dev; + struct pnp_id *dev_id; - pnp_fixup_device(dev); + dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL); + if (!dev) + return NULL; + + dev->protocol = protocol; + dev->number = id; + dev->dma_mask = DMA_24BIT_MASK; + + dev->dev.parent = &dev->protocol->dev; dev->dev.bus = &pnp_bus_type; dev->dev.dma_mask = &dev->dma_mask; - dev->dma_mask = dev->dev.coherent_dma_mask = DMA_24BIT_MASK; + dev->dev.coherent_dma_mask = dev->dma_mask; dev->dev.release = &pnp_release_device; + + sprintf(dev->dev.bus_id, "%02x:%02x", dev->protocol->number, + dev->number); + + dev_id = pnp_add_id(dev, pnpid); + if (!dev_id) { + kfree(dev); + return NULL; + } + + return dev; +} + +int __pnp_add_device(struct pnp_dev *dev) +{ + int ret; + + pnp_fixup_device(dev); dev->status = PNP_READY; spin_lock(&pnp_lock); list_add_tail(&dev->global_list, &pnp_global); @@ -145,9 +172,6 @@ int pnp_add_device(struct pnp_dev *dev) if (dev->card) return -EINVAL; - dev->dev.parent = &dev->protocol->dev; - sprintf(dev->dev.bus_id, "%02x:%02x", dev->protocol->number, - dev->number); ret = __pnp_add_device(dev); if (ret) return ret; diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index ccb04190044b..727936a6befb 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -409,18 +409,17 @@ static struct pnp_dev *__init isapnp_parse_device(struct pnp_card *card, char id[8]; isapnp_peek(tmp, size); - dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL); - if (!dev) - return NULL; - dev->number = number; eisa_id = tmp[0] | tmp[1] << 8 | tmp[2] << 16 | tmp[3] << 24; pnp_eisa_id_to_string(eisa_id, id); - pnp_add_id(dev, id); + + dev = pnp_alloc_dev(&isapnp_protocol, number, id); + if (!dev) + return NULL; + dev->regs = tmp[4]; dev->card = card; if (size > 5) dev->regs |= tmp[5] << 8; - dev->protocol = &isapnp_protocol; dev->capabilities |= PNP_CONFIGURABLE; dev->capabilities |= PNP_READ; dev->capabilities |= PNP_WRITE; diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 86aea1ebfee7..fd3fca6dddd3 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -152,7 +152,6 @@ static int __init pnpacpi_add_device(struct acpi_device *device) { acpi_handle temp = NULL; acpi_status status; - struct pnp_id *dev_id; struct pnp_dev *dev; status = acpi_get_handle(device->handle, "_CRS", &temp); @@ -160,11 +159,10 @@ static int __init pnpacpi_add_device(struct acpi_device *device) is_exclusive_device(device)) return 0; - dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL); - if (!dev) { - pnp_err("Out of memory"); + dev = pnp_alloc_dev(&pnpacpi_protocol, num, acpi_device_hid(device)); + if (!dev) return -ENOMEM; - } + dev->data = device->handle; /* .enabled means the device can decode the resources */ dev->active = device->status.enabled; @@ -180,19 +178,11 @@ static int __init pnpacpi_add_device(struct acpi_device *device) if (ACPI_SUCCESS(status)) dev->capabilities |= PNP_DISABLE; - dev->protocol = &pnpacpi_protocol; - if (strlen(acpi_device_name(device))) strncpy(dev->name, acpi_device_name(device), sizeof(dev->name)); else strncpy(dev->name, acpi_device_bid(device), sizeof(dev->name)); - dev->number = num; - - dev_id = pnp_add_id(dev, acpi_device_hid(device)); - if (!dev_id) - goto err; - if (dev->active) { /* parse allocated resource */ status = pnpacpi_parse_allocated_resource(device->handle, @@ -230,9 +220,6 @@ static int __init pnpacpi_add_device(struct acpi_device *device) num++; return AE_OK; -err: - kfree(dev); - return -EINVAL; } static acpi_status __init pnpacpi_add_device_handler(acpi_handle handle, diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c index 3ee5ed437385..6af2be2c1d67 100644 --- a/drivers/pnp/pnpbios/core.c +++ b/drivers/pnp/pnpbios/core.c @@ -318,7 +318,6 @@ static int __init insert_device(struct pnp_bios_node *node) { struct list_head *pos; struct pnp_dev *dev; - struct pnp_id *dev_id; char id[8]; /* check if the device is already added */ @@ -328,18 +327,11 @@ static int __init insert_device(struct pnp_bios_node *node) return -1; } - dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL); - if (!dev) - return -1; - pnp_eisa_id_to_string(node->eisa_id & PNP_EISA_ID_MASK, id); - dev_id = pnp_add_id(dev, id); - if (!dev_id) { - kfree(dev); + dev = pnp_alloc_dev(&pnpbios_protocol, node->handle, id); + if (!dev) return -1; - } - dev->number = node->handle; pnpbios_parse_data_stream(dev, node); dev->active = pnp_is_active(dev); dev->flags = node->flags; @@ -352,7 +344,6 @@ static int __init insert_device(struct pnp_bios_node *node) dev->capabilities |= PNP_WRITE; if (dev->flags & PNPBIOS_REMOVABLE) dev->capabilities |= PNP_REMOVABLE; - dev->protocol = &pnpbios_protocol; /* clear out the damaged flags */ if (!dev->active) -- cgit v1.2.2 From 048825deea5f261335b5202cd1114c53a3a21ae7 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:33:55 -0600 Subject: PNP: make pnp_add_card_id() internal to PNP core pnp_add_card_id() doesn't need to be exposed outside the PNP core, so move the declaration to an internal header file. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/base.h | 1 + include/linux/pnp.h | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index ff435bd1ca18..b492569bcdf4 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h @@ -4,6 +4,7 @@ void *pnp_alloc(long size); void pnp_eisa_id_to_string(u32 id, char *str); struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *, int id, char *pnpid); struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id); +int pnp_add_card_id(struct pnp_id *id, struct pnp_card *card); int pnp_interface_attach_device(struct pnp_dev *dev); void pnp_fixup_device(struct pnp_dev *dev); void pnp_free_option(struct pnp_option *option); diff --git a/include/linux/pnp.h b/include/linux/pnp.h index 9a05ab5515b6..7639db83ce3f 100644 --- a/include/linux/pnp.h +++ b/include/linux/pnp.h @@ -371,7 +371,6 @@ int pnp_add_card(struct pnp_card *card); void pnp_remove_card(struct pnp_card *card); int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev); void pnp_remove_card_device(struct pnp_dev *dev); -int pnp_add_card_id(struct pnp_id *id, struct pnp_card *card); struct pnp_dev *pnp_request_card_device(struct pnp_card_link *clink, const char *id, struct pnp_dev *from); void pnp_release_card_device(struct pnp_dev *dev); @@ -423,7 +422,6 @@ static inline int pnp_add_card(struct pnp_card *card) { return -ENODEV; } static inline void pnp_remove_card(struct pnp_card *card) { } static inline int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev) { return -ENODEV; } static inline void pnp_remove_card_device(struct pnp_dev *dev) { } -static inline int pnp_add_card_id(struct pnp_id *id, struct pnp_card *card) { return -ENODEV; } static inline struct pnp_dev *pnp_request_card_device(struct pnp_card_link *clink, const char *id, struct pnp_dev *from) { return NULL; } static inline void pnp_release_card_device(struct pnp_dev *dev) { } static inline int pnp_register_card_driver(struct pnp_card_driver *drv) { return -ENODEV; } -- cgit v1.2.2 From e436675f2a09ea389c1844507658f304924a2eca Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:33:56 -0600 Subject: PNP: change pnp_add_card_id() to allocate its own pnp_id structures This moves some of the pnp_id knowledge out of the backends and into the PNP core. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/base.h | 2 +- drivers/pnp/card.c | 27 +++++++++++++++++++++------ drivers/pnp/isapnp/core.c | 21 +++++++++++---------- 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index b492569bcdf4..37f7d85fc4bc 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h @@ -4,7 +4,7 @@ void *pnp_alloc(long size); void pnp_eisa_id_to_string(u32 id, char *str); struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *, int id, char *pnpid); struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id); -int pnp_add_card_id(struct pnp_id *id, struct pnp_card *card); +struct pnp_id *pnp_add_card_id(struct pnp_card *card, char *id); int pnp_interface_attach_device(struct pnp_dev *dev); void pnp_fixup_device(struct pnp_dev *dev); void pnp_free_option(struct pnp_option *option); diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c index da1c9909eb44..d606a163b1d7 100644 --- a/drivers/pnp/card.c +++ b/drivers/pnp/card.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include "base.h" @@ -100,19 +101,33 @@ static int card_probe(struct pnp_card *card, struct pnp_card_driver *drv) * @id: pointer to a pnp_id structure * @card: pointer to the desired card */ -int pnp_add_card_id(struct pnp_id *id, struct pnp_card *card) +struct pnp_id *pnp_add_card_id(struct pnp_card *card, char *id) { - struct pnp_id *ptr; + struct pnp_id *dev_id, *ptr; - id->next = NULL; + dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); + if (!dev_id) + return NULL; + + dev_id->id[0] = id[0]; + dev_id->id[1] = id[1]; + dev_id->id[2] = id[2]; + dev_id->id[3] = tolower(id[3]); + dev_id->id[4] = tolower(id[4]); + dev_id->id[5] = tolower(id[5]); + dev_id->id[6] = tolower(id[6]); + dev_id->id[7] = '\0'; + + dev_id->next = NULL; ptr = card->id; while (ptr && ptr->next) ptr = ptr->next; if (ptr) - ptr->next = id; + ptr->next = dev_id; else - card->id = id; - return 0; + card->id = dev_id; + + return dev_id; } static void pnp_free_card_ids(struct pnp_card *card) diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index 727936a6befb..1949c18a7365 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -822,17 +822,18 @@ static unsigned char __init isapnp_checksum(unsigned char *data) static void isapnp_parse_card_id(struct pnp_card *card, unsigned short vendor, unsigned short device) { - struct pnp_id *id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); + char id[8]; - if (!id) - return; - sprintf(id->id, "%c%c%c%x%x%x%x", - 'A' + ((vendor >> 2) & 0x3f) - 1, - 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1, - 'A' + ((vendor >> 8) & 0x1f) - 1, - (device >> 4) & 0x0f, - device & 0x0f, (device >> 12) & 0x0f, (device >> 8) & 0x0f); - pnp_add_card_id(id, card); + id[0] = 'A' + ((vendor >> 2) & 0x3f) - 1; + id[1] = 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1; + id[2] = 'A' + ((vendor >> 8) & 0x1f) - 1; + id[3] = hex_asc((device >> 4) & 0x0f); + id[4] = hex_asc(device & 0x0f); + id[5] = hex_asc((device >> 12) & 0x0f); + id[6] = hex_asc((device >> 8) & 0x0f); + id[7] = '\0'; + + pnp_add_card_id(card, id); } /* -- cgit v1.2.2 From 068076d5517009654376ceda75ff44af0feb9b1d Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:33:57 -0600 Subject: ISAPNP: pull pnp_add_card_id() out of isapnp_parse_card_id() Split the pnp_add_card_id() part from the PNPID conversion part so we can move the initial add_id() into the pnp_card allocation. This makes the PNPID conversion generic so we can use the same one for both devices and cards. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/isapnp/core.c | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index 1949c18a7365..3a326f9305f6 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -816,26 +816,6 @@ static unsigned char __init isapnp_checksum(unsigned char *data) return checksum; } -/* - * Parse EISA id for ISA PnP card. - */ -static void isapnp_parse_card_id(struct pnp_card *card, unsigned short vendor, - unsigned short device) -{ - char id[8]; - - id[0] = 'A' + ((vendor >> 2) & 0x3f) - 1; - id[1] = 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1; - id[2] = 'A' + ((vendor >> 8) & 0x1f) - 1; - id[3] = hex_asc((device >> 4) & 0x0f); - id[4] = hex_asc(device & 0x0f); - id[5] = hex_asc((device >> 12) & 0x0f); - id[6] = hex_asc((device >> 8) & 0x0f); - id[7] = '\0'; - - pnp_add_card_id(card, id); -} - /* * Build device list for all present ISA PnP devices. */ @@ -844,6 +824,8 @@ static int __init isapnp_build_device_list(void) int csn; unsigned char header[9], checksum; struct pnp_card *card; + u32 eisa_id; + char id[8]; isapnp_wait(); isapnp_key(); @@ -864,8 +846,10 @@ static int __init isapnp_build_device_list(void) card->number = csn; INIT_LIST_HEAD(&card->devices); - isapnp_parse_card_id(card, (header[1] << 8) | header[0], - (header[3] << 8) | header[2]); + eisa_id = header[0] | header[1] << 8 | + header[2] << 16 | header[3] << 24; + pnp_eisa_id_to_string(eisa_id, id); + pnp_add_card_id(card, id); card->serial = (header[7] << 24) | (header[6] << 16) | (header[5] << 8) | header[4]; -- cgit v1.2.2 From 6bf2aab24a5dc26bf8274c4b9dbbed8ca99ae82c Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:33:58 -0600 Subject: PNP: add pnp_alloc_card() Add pnp_alloc_card() to allocate a struct pnp_card and fill in the protocol, instance number, and initial PNP ID. Now it is always valid to use dev_printk() on any pnp_card pointer. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/base.h | 1 + drivers/pnp/card.c | 28 +++++++++++++++++++++++++--- drivers/pnp/isapnp/core.c | 13 +++++-------- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index 37f7d85fc4bc..a83cdcfee165 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h @@ -3,6 +3,7 @@ void *pnp_alloc(long size); #define PNP_EISA_ID_MASK 0x7fffffff void pnp_eisa_id_to_string(u32 id, char *str); struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *, int id, char *pnpid); +struct pnp_card *pnp_alloc_card(struct pnp_protocol *, int id, char *pnpid); struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id); struct pnp_id *pnp_add_card_id(struct pnp_card *card, char *id); int pnp_interface_attach_device(struct pnp_dev *dev); diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c index d606a163b1d7..a762a4176736 100644 --- a/drivers/pnp/card.c +++ b/drivers/pnp/card.c @@ -151,6 +151,31 @@ static void pnp_release_card(struct device *dmdev) kfree(card); } +struct pnp_card *pnp_alloc_card(struct pnp_protocol *protocol, int id, char *pnpid) +{ + struct pnp_card *card; + struct pnp_id *dev_id; + + card = kzalloc(sizeof(struct pnp_card), GFP_KERNEL); + if (!card) + return NULL; + + card->protocol = protocol; + card->number = id; + + card->dev.parent = &card->protocol->dev; + sprintf(card->dev.bus_id, "%02x:%02x", card->protocol->number, + card->number); + + dev_id = pnp_add_card_id(card, pnpid); + if (!dev_id) { + kfree(card); + return NULL; + } + + return card; +} + static ssize_t pnp_show_card_name(struct device *dmdev, struct device_attribute *attr, char *buf) { @@ -206,9 +231,6 @@ int pnp_add_card(struct pnp_card *card) int error; struct list_head *pos, *temp; - sprintf(card->dev.bus_id, "%02x:%02x", card->protocol->number, - card->number); - card->dev.parent = &card->protocol->dev; card->dev.bus = NULL; card->dev.release = &pnp_release_card; error = device_register(&card->dev); diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index 3a326f9305f6..883577a93d6a 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -840,16 +840,14 @@ static int __init isapnp_build_device_list(void) header[5], header[6], header[7], header[8]); printk(KERN_DEBUG "checksum = 0x%x\n", checksum); #endif - if ((card = - kzalloc(sizeof(struct pnp_card), GFP_KERNEL)) == NULL) - continue; - - card->number = csn; - INIT_LIST_HEAD(&card->devices); eisa_id = header[0] | header[1] << 8 | header[2] << 16 | header[3] << 24; pnp_eisa_id_to_string(eisa_id, id); - pnp_add_card_id(card, id); + card = pnp_alloc_card(&isapnp_protocol, csn, id); + if (!card) + continue; + + INIT_LIST_HEAD(&card->devices); card->serial = (header[7] << 24) | (header[6] << 16) | (header[5] << 8) | header[4]; @@ -860,7 +858,6 @@ static int __init isapnp_build_device_list(void) "isapnp: checksum for device %i is not valid (0x%x)\n", csn, isapnp_checksum_value); card->checksum = isapnp_checksum_value; - card->protocol = &isapnp_protocol; pnp_add_card(card); } -- cgit v1.2.2 From f7e8466a045c690002c1926e695ae312dd73bb4a Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:33:59 -0600 Subject: PNPACPI: pnpacpi_encode_ext_irq() wrongly set "irq" instead of "extended_irq" pnpacpi_encode_ext_irq() should set resource->data.extended_irq, not resource->data.irq. This has been wrong since at least 2.6.12. I haven't seen any bug reports, but it's clearly incorrect. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/pnp/pnpacpi/rsparser.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 98cbc9f18eed..4ce754ab14fd 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -820,9 +820,9 @@ static void pnpacpi_encode_ext_irq(struct acpi_resource *resource, resource->data.extended_irq.triggering = triggering; resource->data.extended_irq.polarity = polarity; if (triggering == ACPI_EDGE_SENSITIVE) - resource->data.irq.sharable = ACPI_EXCLUSIVE; + resource->data.extended_irq.sharable = ACPI_EXCLUSIVE; else - resource->data.irq.sharable = ACPI_SHARED; + resource->data.extended_irq.sharable = ACPI_SHARED; resource->data.extended_irq.interrupt_count = 1; resource->data.extended_irq.interrupts[0] = p->start; } -- cgit v1.2.2 From 9570a20e9da282721afc6885dbeaa1b9c1e7ff4d Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:00 -0600 Subject: PNPACPI: use temporaries to reduce repetition No functional change, just fewer words and fewer chances for transcription errors. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/pnpacpi/rsparser.c | 176 ++++++++++++++++++++++++----------------- 1 file changed, 103 insertions(+), 73 deletions(-) diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 4ce754ab14fd..37708fdefe09 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -280,6 +280,14 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, void *data) { struct pnp_resource_table *res_table = data; + struct acpi_resource_irq *irq; + struct acpi_resource_dma *dma; + struct acpi_resource_io *io; + struct acpi_resource_fixed_io *fixed_io; + struct acpi_resource_memory24 *memory24; + struct acpi_resource_memory32 *memory32; + struct acpi_resource_fixed_memory32 *fixed_memory32; + struct acpi_resource_extended_irq *extended_irq; int i; switch (res->type) { @@ -288,29 +296,32 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, * Per spec, only one interrupt per descriptor is allowed in * _CRS, but some firmware violates this, so parse them all. */ - for (i = 0; i < res->data.irq.interrupt_count; i++) { + irq = &res->data.irq; + for (i = 0; i < irq->interrupt_count; i++) { pnpacpi_parse_allocated_irqresource(res_table, - res->data.irq.interrupts[i], - res->data.irq.triggering, - res->data.irq.polarity, - res->data.irq.sharable); + irq->interrupts[i], + irq->triggering, + irq->polarity, + irq->sharable); } break; case ACPI_RESOURCE_TYPE_DMA: - if (res->data.dma.channel_count > 0) + dma = &res->data.dma; + if (dma->channel_count > 0) pnpacpi_parse_allocated_dmaresource(res_table, - res->data.dma.channels[0], - res->data.dma.type, - res->data.dma.bus_master, - res->data.dma.transfer); + dma->channels[0], + dma->type, + dma->bus_master, + dma->transfer); break; case ACPI_RESOURCE_TYPE_IO: + io = &res->data.io; pnpacpi_parse_allocated_ioresource(res_table, - res->data.io.minimum, - res->data.io.address_length, - res->data.io.io_decode); + io->minimum, + io->address_length, + io->io_decode); break; case ACPI_RESOURCE_TYPE_START_DEPENDENT: @@ -318,9 +329,10 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, break; case ACPI_RESOURCE_TYPE_FIXED_IO: + fixed_io = &res->data.fixed_io; pnpacpi_parse_allocated_ioresource(res_table, - res->data.fixed_io.address, - res->data.fixed_io.address_length, + fixed_io->address, + fixed_io->address_length, ACPI_DECODE_10); break; @@ -331,22 +343,25 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, break; case ACPI_RESOURCE_TYPE_MEMORY24: + memory24 = &res->data.memory24; pnpacpi_parse_allocated_memresource(res_table, - res->data.memory24.minimum, - res->data.memory24.address_length, - res->data.memory24.write_protect); + memory24->minimum, + memory24->address_length, + memory24->write_protect); break; case ACPI_RESOURCE_TYPE_MEMORY32: + memory32 = &res->data.memory32; pnpacpi_parse_allocated_memresource(res_table, - res->data.memory32.minimum, - res->data.memory32.address_length, - res->data.memory32.write_protect); + memory32->minimum, + memory32->address_length, + memory32->write_protect); break; case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: + fixed_memory32 = &res->data.fixed_memory32; pnpacpi_parse_allocated_memresource(res_table, - res->data.fixed_memory32.address, - res->data.fixed_memory32.address_length, - res->data.fixed_memory32.write_protect); + fixed_memory32->address, + fixed_memory32->address_length, + fixed_memory32->write_protect); break; case ACPI_RESOURCE_TYPE_ADDRESS16: case ACPI_RESOURCE_TYPE_ADDRESS32: @@ -360,15 +375,16 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, break; case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: - if (res->data.extended_irq.producer_consumer == ACPI_PRODUCER) + extended_irq = &res->data.extended_irq; + if (extended_irq->producer_consumer == ACPI_PRODUCER) return AE_OK; - for (i = 0; i < res->data.extended_irq.interrupt_count; i++) { + for (i = 0; i < extended_irq->interrupt_count; i++) { pnpacpi_parse_allocated_irqresource(res_table, - res->data.extended_irq.interrupts[i], - res->data.extended_irq.triggering, - res->data.extended_irq.polarity, - res->data.extended_irq.sharable); + extended_irq->interrupts[i], + extended_irq->triggering, + extended_irq->polarity, + extended_irq->sharable); } break; @@ -797,122 +813,136 @@ int pnpacpi_build_resource_template(acpi_handle handle, static void pnpacpi_encode_irq(struct acpi_resource *resource, struct resource *p) { + struct acpi_resource_irq *irq = &resource->data.irq; int triggering, polarity; decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity); - resource->data.irq.triggering = triggering; - resource->data.irq.polarity = polarity; + irq->triggering = triggering; + irq->polarity = polarity; if (triggering == ACPI_EDGE_SENSITIVE) - resource->data.irq.sharable = ACPI_EXCLUSIVE; + irq->sharable = ACPI_EXCLUSIVE; else - resource->data.irq.sharable = ACPI_SHARED; - resource->data.irq.interrupt_count = 1; - resource->data.irq.interrupts[0] = p->start; + irq->sharable = ACPI_SHARED; + irq->interrupt_count = 1; + irq->interrupts[0] = p->start; } static void pnpacpi_encode_ext_irq(struct acpi_resource *resource, struct resource *p) { + struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq; int triggering, polarity; decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity); - resource->data.extended_irq.producer_consumer = ACPI_CONSUMER; - resource->data.extended_irq.triggering = triggering; - resource->data.extended_irq.polarity = polarity; + extended_irq->producer_consumer = ACPI_CONSUMER; + extended_irq->triggering = triggering; + extended_irq->polarity = polarity; if (triggering == ACPI_EDGE_SENSITIVE) - resource->data.extended_irq.sharable = ACPI_EXCLUSIVE; + extended_irq->sharable = ACPI_EXCLUSIVE; else - resource->data.extended_irq.sharable = ACPI_SHARED; - resource->data.extended_irq.interrupt_count = 1; - resource->data.extended_irq.interrupts[0] = p->start; + extended_irq->sharable = ACPI_SHARED; + extended_irq->interrupt_count = 1; + extended_irq->interrupts[0] = p->start; } static void pnpacpi_encode_dma(struct acpi_resource *resource, struct resource *p) { + struct acpi_resource_dma *dma = &resource->data.dma; + /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */ switch (p->flags & IORESOURCE_DMA_SPEED_MASK) { case IORESOURCE_DMA_TYPEA: - resource->data.dma.type = ACPI_TYPE_A; + dma->type = ACPI_TYPE_A; break; case IORESOURCE_DMA_TYPEB: - resource->data.dma.type = ACPI_TYPE_B; + dma->type = ACPI_TYPE_B; break; case IORESOURCE_DMA_TYPEF: - resource->data.dma.type = ACPI_TYPE_F; + dma->type = ACPI_TYPE_F; break; default: - resource->data.dma.type = ACPI_COMPATIBILITY; + dma->type = ACPI_COMPATIBILITY; } switch (p->flags & IORESOURCE_DMA_TYPE_MASK) { case IORESOURCE_DMA_8BIT: - resource->data.dma.transfer = ACPI_TRANSFER_8; + dma->transfer = ACPI_TRANSFER_8; break; case IORESOURCE_DMA_8AND16BIT: - resource->data.dma.transfer = ACPI_TRANSFER_8_16; + dma->transfer = ACPI_TRANSFER_8_16; break; default: - resource->data.dma.transfer = ACPI_TRANSFER_16; + dma->transfer = ACPI_TRANSFER_16; } - resource->data.dma.bus_master = !!(p->flags & IORESOURCE_DMA_MASTER); - resource->data.dma.channel_count = 1; - resource->data.dma.channels[0] = p->start; + dma->bus_master = !!(p->flags & IORESOURCE_DMA_MASTER); + dma->channel_count = 1; + dma->channels[0] = p->start; } static void pnpacpi_encode_io(struct acpi_resource *resource, struct resource *p) { + struct acpi_resource_io *io = &resource->data.io; + /* Note: pnp_assign_port will copy pnp_port->flags into p->flags */ - resource->data.io.io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ? + io->io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ? ACPI_DECODE_16 : ACPI_DECODE_10; - resource->data.io.minimum = p->start; - resource->data.io.maximum = p->end; - resource->data.io.alignment = 0; /* Correct? */ - resource->data.io.address_length = p->end - p->start + 1; + io->minimum = p->start; + io->maximum = p->end; + io->alignment = 0; /* Correct? */ + io->address_length = p->end - p->start + 1; } static void pnpacpi_encode_fixed_io(struct acpi_resource *resource, struct resource *p) { - resource->data.fixed_io.address = p->start; - resource->data.fixed_io.address_length = p->end - p->start + 1; + struct acpi_resource_fixed_io *fixed_io = &resource->data.fixed_io; + + fixed_io->address = p->start; + fixed_io->address_length = p->end - p->start + 1; } static void pnpacpi_encode_mem24(struct acpi_resource *resource, struct resource *p) { + struct acpi_resource_memory24 *memory24 = &resource->data.memory24; + /* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */ - resource->data.memory24.write_protect = + memory24->write_protect = (p->flags & IORESOURCE_MEM_WRITEABLE) ? ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; - resource->data.memory24.minimum = p->start; - resource->data.memory24.maximum = p->end; - resource->data.memory24.alignment = 0; - resource->data.memory24.address_length = p->end - p->start + 1; + memory24->minimum = p->start; + memory24->maximum = p->end; + memory24->alignment = 0; + memory24->address_length = p->end - p->start + 1; } static void pnpacpi_encode_mem32(struct acpi_resource *resource, struct resource *p) { - resource->data.memory32.write_protect = + struct acpi_resource_memory32 *memory32 = &resource->data.memory32; + + memory32->write_protect = (p->flags & IORESOURCE_MEM_WRITEABLE) ? ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; - resource->data.memory32.minimum = p->start; - resource->data.memory32.maximum = p->end; - resource->data.memory32.alignment = 0; - resource->data.memory32.address_length = p->end - p->start + 1; + memory32->minimum = p->start; + memory32->maximum = p->end; + memory32->alignment = 0; + memory32->address_length = p->end - p->start + 1; } static void pnpacpi_encode_fixed_mem32(struct acpi_resource *resource, struct resource *p) { - resource->data.fixed_memory32.write_protect = + struct acpi_resource_fixed_memory32 *fixed_memory32 = &resource->data.fixed_memory32; + + fixed_memory32->write_protect = (p->flags & IORESOURCE_MEM_WRITEABLE) ? ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; - resource->data.fixed_memory32.address = p->start; - resource->data.fixed_memory32.address_length = p->end - p->start + 1; + fixed_memory32->address = p->start; + fixed_memory32->address_length = p->end - p->start + 1; } int pnpacpi_encode_resources(struct pnp_resource_table *res_table, -- cgit v1.2.2 From bb84b41d1a1e3ad1ebe7f91a7c97d3b6ca242e9d Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:01 -0600 Subject: PNPACPI: hoist dma_flags() out of pnpacpi_parse_allocated_dmaresource() Hoist dma_flags() out of pnpacpi_parse_allocated_dmaresource() into its caller. This makes pnpacpi_parse_allocated_dmaresource() more similar to pnpbios_parse_allocated_dmaresource(). Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/pnpacpi/rsparser.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 37708fdefe09..2a47e977d8a8 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -169,8 +169,7 @@ static int dma_flags(int type, int bus_master, int transfer) } static void pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, - u32 dma, int type, - int bus_master, int transfer) + u32 dma, int flags) { int i = 0; static unsigned char warned; @@ -180,8 +179,7 @@ static void pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, i++; if (i < PNP_MAX_DMA) { res->dma_resource[i].flags = IORESOURCE_DMA; // Also clears _UNSET flag - res->dma_resource[i].flags |= - dma_flags(type, bus_master, transfer); + res->dma_resource[i].flags |= flags; if (dma == -1) { res->dma_resource[i].flags |= IORESOURCE_DISABLED; return; @@ -311,9 +309,8 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, if (dma->channel_count > 0) pnpacpi_parse_allocated_dmaresource(res_table, dma->channels[0], - dma->type, - dma->bus_master, - dma->transfer); + dma_flags(dma->type, dma->bus_master, + dma->transfer)); break; case ACPI_RESOURCE_TYPE_IO: -- cgit v1.2.2 From cd7ec927d9cd3d2001cbbdce872bd73f6e49c986 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:02 -0600 Subject: PNPACPI: extend irq_flags() to set IORESOURCE_IRQ_SHAREABLE when appropriate This simplifies IRQ resource parsing slightly by computing all the IORESOURCE_IRQ_* flags at the same time. This also keeps track of shareability information when parsing options from _PRS. Previously we ignored shareability in _PRS. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/pnpacpi/rsparser.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 2a47e977d8a8..a5f5e2130e75 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -32,19 +32,26 @@ /* * Allocated Resources */ -static int irq_flags(int triggering, int polarity) +static int irq_flags(int triggering, int polarity, int shareable) { + int flags; + if (triggering == ACPI_LEVEL_SENSITIVE) { if (polarity == ACPI_ACTIVE_LOW) - return IORESOURCE_IRQ_LOWLEVEL; + flags = IORESOURCE_IRQ_LOWLEVEL; else - return IORESOURCE_IRQ_HIGHLEVEL; + flags = IORESOURCE_IRQ_HIGHLEVEL; } else { if (polarity == ACPI_ACTIVE_LOW) - return IORESOURCE_IRQ_LOWEDGE; + flags = IORESOURCE_IRQ_LOWEDGE; else - return IORESOURCE_IRQ_HIGHEDGE; + flags = IORESOURCE_IRQ_HIGHEDGE; } + + if (shareable) + flags |= IORESOURCE_IRQ_SHAREABLE; + + return flags; } static void decode_irq_flags(int flag, int *triggering, int *polarity) @@ -110,16 +117,13 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, } res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag - res->irq_resource[i].flags |= irq_flags(triggering, polarity); + res->irq_resource[i].flags |= irq_flags(triggering, polarity, shareable); irq = acpi_register_gsi(gsi, triggering, polarity); if (irq < 0) { res->irq_resource[i].flags |= IORESOURCE_DISABLED; return; } - if (shareable) - res->irq_resource[i].flags |= IORESOURCE_IRQ_SHAREABLE; - res->irq_resource[i].start = irq; res->irq_resource[i].end = irq; pcibios_penalize_isa_irq(irq, 1); @@ -441,7 +445,7 @@ static __init void pnpacpi_parse_irq_option(struct pnp_option *option, for (i = 0; i < p->interrupt_count; i++) if (p->interrupts[i]) __set_bit(p->interrupts[i], irq->map); - irq->flags = irq_flags(p->triggering, p->polarity); + irq->flags = irq_flags(p->triggering, p->polarity, p->sharable); pnp_register_irq_resource(option, irq); } @@ -461,7 +465,7 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_option *option, for (i = 0; i < p->interrupt_count; i++) if (p->interrupts[i]) __set_bit(p->interrupts[i], irq->map); - irq->flags = irq_flags(p->triggering, p->polarity); + irq->flags = irq_flags(p->triggering, p->polarity, p->sharable); pnp_register_irq_resource(option, irq); } -- cgit v1.2.2 From cdef6254e17e98f1071ce1bfc8f2a87997c855d0 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:03 -0600 Subject: PNPACPI: pass pnp_dev instead of acpi_handle Pass the pnp_dev pointer when possible instead of the acpi_handle. This allows better error messages and reduces the chance of error in the caller. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/pnpacpi/core.c | 4 ++-- drivers/pnp/pnpacpi/pnpacpi.h | 2 +- drivers/pnp/pnpacpi/rsparser.c | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index fd3fca6dddd3..27546873880c 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -88,10 +88,10 @@ static int pnpacpi_set_resources(struct pnp_dev *dev, { acpi_handle handle = dev->data; struct acpi_buffer buffer; - int ret = 0; + int ret; acpi_status status; - ret = pnpacpi_build_resource_template(handle, &buffer); + ret = pnpacpi_build_resource_template(dev, &buffer); if (ret) return ret; ret = pnpacpi_encode_resources(res, &buffer); diff --git a/drivers/pnp/pnpacpi/pnpacpi.h b/drivers/pnp/pnpacpi/pnpacpi.h index f28e2ed66fa3..116c591d8634 100644 --- a/drivers/pnp/pnpacpi/pnpacpi.h +++ b/drivers/pnp/pnpacpi/pnpacpi.h @@ -8,5 +8,5 @@ acpi_status pnpacpi_parse_allocated_resource(acpi_handle, struct pnp_resource_table*); acpi_status pnpacpi_parse_resource_option_data(acpi_handle, struct pnp_dev*); int pnpacpi_encode_resources(struct pnp_resource_table *, struct acpi_buffer *); -int pnpacpi_build_resource_template(acpi_handle, struct acpi_buffer*); +int pnpacpi_build_resource_template(struct pnp_dev *, struct acpi_buffer *); #endif diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index a5f5e2130e75..baaf60212779 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -777,9 +777,10 @@ static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data) return AE_OK; } -int pnpacpi_build_resource_template(acpi_handle handle, +int pnpacpi_build_resource_template(struct pnp_dev *dev, struct acpi_buffer *buffer) { + acpi_handle handle = dev->data; struct acpi_resource *resource; int res_cnt = 0; acpi_status status; -- cgit v1.2.2 From c1caf06ccfd3a4efd4b489f89bcdabd2362f31d0 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:04 -0600 Subject: PNP: add debug output to option registration Add debug output to resource option registration functions (enabled by CONFIG_PNP_DEBUG). This uses dev_printk, so I had to add pnp_dev arguments at the same time. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/isapnp/core.c | 50 ++++++++++++++++++------------- drivers/pnp/pnpacpi/rsparser.c | 68 +++++++++++++++++++++++++----------------- drivers/pnp/pnpbios/rsparser.c | 54 +++++++++++++++++++-------------- drivers/pnp/resource.c | 34 ++++++++++++++++++--- include/linux/pnp.h | 19 +++++++----- 5 files changed, 141 insertions(+), 84 deletions(-) diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index 883577a93d6a..38ff64dce9c0 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -431,7 +431,8 @@ static struct pnp_dev *__init isapnp_parse_device(struct pnp_card *card, /* * Add IRQ resource to resources list. */ -static void __init isapnp_parse_irq_resource(struct pnp_option *option, +static void __init isapnp_parse_irq_resource(struct pnp_dev *dev, + struct pnp_option *option, int size) { unsigned char tmp[3]; @@ -448,13 +449,14 @@ static void __init isapnp_parse_irq_resource(struct pnp_option *option, irq->flags = tmp[2]; else irq->flags = IORESOURCE_IRQ_HIGHEDGE; - pnp_register_irq_resource(option, irq); + pnp_register_irq_resource(dev, option, irq); } /* * Add DMA resource to resources list. */ -static void __init isapnp_parse_dma_resource(struct pnp_option *option, +static void __init isapnp_parse_dma_resource(struct pnp_dev *dev, + struct pnp_option *option, int size) { unsigned char tmp[2]; @@ -466,13 +468,14 @@ static void __init isapnp_parse_dma_resource(struct pnp_option *option, return; dma->map = tmp[0]; dma->flags = tmp[1]; - pnp_register_dma_resource(option, dma); + pnp_register_dma_resource(dev, option, dma); } /* * Add port resource to resources list. */ -static void __init isapnp_parse_port_resource(struct pnp_option *option, +static void __init isapnp_parse_port_resource(struct pnp_dev *dev, + struct pnp_option *option, int size) { unsigned char tmp[7]; @@ -487,13 +490,14 @@ static void __init isapnp_parse_port_resource(struct pnp_option *option, port->align = tmp[5]; port->size = tmp[6]; port->flags = tmp[0] ? PNP_PORT_FLAG_16BITADDR : 0; - pnp_register_port_resource(option, port); + pnp_register_port_resource(dev, option, port); } /* * Add fixed port resource to resources list. */ -static void __init isapnp_parse_fixed_port_resource(struct pnp_option *option, +static void __init isapnp_parse_fixed_port_resource(struct pnp_dev *dev, + struct pnp_option *option, int size) { unsigned char tmp[3]; @@ -507,13 +511,14 @@ static void __init isapnp_parse_fixed_port_resource(struct pnp_option *option, port->size = tmp[2]; port->align = 0; port->flags = PNP_PORT_FLAG_FIXED; - pnp_register_port_resource(option, port); + pnp_register_port_resource(dev, option, port); } /* * Add memory resource to resources list. */ -static void __init isapnp_parse_mem_resource(struct pnp_option *option, +static void __init isapnp_parse_mem_resource(struct pnp_dev *dev, + struct pnp_option *option, int size) { unsigned char tmp[9]; @@ -528,13 +533,14 @@ static void __init isapnp_parse_mem_resource(struct pnp_option *option, mem->align = (tmp[6] << 8) | tmp[5]; mem->size = ((tmp[8] << 8) | tmp[7]) << 8; mem->flags = tmp[0]; - pnp_register_mem_resource(option, mem); + pnp_register_mem_resource(dev, option, mem); } /* * Add 32-bit memory resource to resources list. */ -static void __init isapnp_parse_mem32_resource(struct pnp_option *option, +static void __init isapnp_parse_mem32_resource(struct pnp_dev *dev, + struct pnp_option *option, int size) { unsigned char tmp[17]; @@ -551,13 +557,14 @@ static void __init isapnp_parse_mem32_resource(struct pnp_option *option, mem->size = (tmp[16] << 24) | (tmp[15] << 16) | (tmp[14] << 8) | tmp[13]; mem->flags = tmp[0]; - pnp_register_mem_resource(option, mem); + pnp_register_mem_resource(dev, option, mem); } /* * Add 32-bit fixed memory resource to resources list. */ -static void __init isapnp_parse_fixed_mem32_resource(struct pnp_option *option, +static void __init isapnp_parse_fixed_mem32_resource(struct pnp_dev *dev, + struct pnp_option *option, int size) { unsigned char tmp[9]; @@ -572,7 +579,7 @@ static void __init isapnp_parse_fixed_mem32_resource(struct pnp_option *option, mem->size = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5]; mem->align = 0; mem->flags = tmp[0]; - pnp_register_mem_resource(option, mem); + pnp_register_mem_resource(dev, option, mem); } /* @@ -656,13 +663,13 @@ static int __init isapnp_create_device(struct pnp_card *card, case _STAG_IRQ: if (size < 2 || size > 3) goto __skip; - isapnp_parse_irq_resource(option, size); + isapnp_parse_irq_resource(dev, option, size); size = 0; break; case _STAG_DMA: if (size != 2) goto __skip; - isapnp_parse_dma_resource(option, size); + isapnp_parse_dma_resource(dev, option, size); size = 0; break; case _STAG_STARTDEP: @@ -682,17 +689,18 @@ static int __init isapnp_create_device(struct pnp_card *card, if (size != 0) goto __skip; priority = 0; + dev_dbg(&dev->dev, "end dependent options\n"); break; case _STAG_IOPORT: if (size != 7) goto __skip; - isapnp_parse_port_resource(option, size); + isapnp_parse_port_resource(dev, option, size); size = 0; break; case _STAG_FIXEDIO: if (size != 3) goto __skip; - isapnp_parse_fixed_port_resource(option, size); + isapnp_parse_fixed_port_resource(dev, option, size); size = 0; break; case _STAG_VENDOR: @@ -700,7 +708,7 @@ static int __init isapnp_create_device(struct pnp_card *card, case _LTAG_MEMRANGE: if (size != 9) goto __skip; - isapnp_parse_mem_resource(option, size); + isapnp_parse_mem_resource(dev, option, size); size = 0; break; case _LTAG_ANSISTR: @@ -715,13 +723,13 @@ static int __init isapnp_create_device(struct pnp_card *card, case _LTAG_MEM32RANGE: if (size != 17) goto __skip; - isapnp_parse_mem32_resource(option, size); + isapnp_parse_mem32_resource(dev, option, size); size = 0; break; case _LTAG_FIXEDMEM32RANGE: if (size != 9) goto __skip; - isapnp_parse_fixed_mem32_resource(option, size); + isapnp_parse_fixed_mem32_resource(dev, option, size); size = 0; break; case _STAG_END: diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index baaf60212779..32454aa07ebc 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -410,7 +410,8 @@ acpi_status pnpacpi_parse_allocated_resource(acpi_handle handle, pnpacpi_allocated_resource, res); } -static __init void pnpacpi_parse_dma_option(struct pnp_option *option, +static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev, + struct pnp_option *option, struct acpi_resource_dma *p) { int i; @@ -427,10 +428,11 @@ static __init void pnpacpi_parse_dma_option(struct pnp_option *option, dma->flags = dma_flags(p->type, p->bus_master, p->transfer); - pnp_register_dma_resource(option, dma); + pnp_register_dma_resource(dev, option, dma); } -static __init void pnpacpi_parse_irq_option(struct pnp_option *option, +static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev, + struct pnp_option *option, struct acpi_resource_irq *p) { int i; @@ -447,10 +449,11 @@ static __init void pnpacpi_parse_irq_option(struct pnp_option *option, __set_bit(p->interrupts[i], irq->map); irq->flags = irq_flags(p->triggering, p->polarity, p->sharable); - pnp_register_irq_resource(option, irq); + pnp_register_irq_resource(dev, option, irq); } -static __init void pnpacpi_parse_ext_irq_option(struct pnp_option *option, +static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev, + struct pnp_option *option, struct acpi_resource_extended_irq *p) { int i; @@ -467,10 +470,11 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_option *option, __set_bit(p->interrupts[i], irq->map); irq->flags = irq_flags(p->triggering, p->polarity, p->sharable); - pnp_register_irq_resource(option, irq); + pnp_register_irq_resource(dev, option, irq); } -static __init void pnpacpi_parse_port_option(struct pnp_option *option, +static __init void pnpacpi_parse_port_option(struct pnp_dev *dev, + struct pnp_option *option, struct acpi_resource_io *io) { struct pnp_port *port; @@ -486,10 +490,11 @@ static __init void pnpacpi_parse_port_option(struct pnp_option *option, port->size = io->address_length; port->flags = ACPI_DECODE_16 == io->io_decode ? PNP_PORT_FLAG_16BITADDR : 0; - pnp_register_port_resource(option, port); + pnp_register_port_resource(dev, option, port); } -static __init void pnpacpi_parse_fixed_port_option(struct pnp_option *option, +static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev, + struct pnp_option *option, struct acpi_resource_fixed_io *io) { struct pnp_port *port; @@ -503,10 +508,11 @@ static __init void pnpacpi_parse_fixed_port_option(struct pnp_option *option, port->size = io->address_length; port->align = 0; port->flags = PNP_PORT_FLAG_FIXED; - pnp_register_port_resource(option, port); + pnp_register_port_resource(dev, option, port); } -static __init void pnpacpi_parse_mem24_option(struct pnp_option *option, +static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev, + struct pnp_option *option, struct acpi_resource_memory24 *p) { struct pnp_mem *mem; @@ -524,10 +530,11 @@ static __init void pnpacpi_parse_mem24_option(struct pnp_option *option, mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? IORESOURCE_MEM_WRITEABLE : 0; - pnp_register_mem_resource(option, mem); + pnp_register_mem_resource(dev, option, mem); } -static __init void pnpacpi_parse_mem32_option(struct pnp_option *option, +static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev, + struct pnp_option *option, struct acpi_resource_memory32 *p) { struct pnp_mem *mem; @@ -545,10 +552,11 @@ static __init void pnpacpi_parse_mem32_option(struct pnp_option *option, mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? IORESOURCE_MEM_WRITEABLE : 0; - pnp_register_mem_resource(option, mem); + pnp_register_mem_resource(dev, option, mem); } -static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_option *option, +static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev, + struct pnp_option *option, struct acpi_resource_fixed_memory32 *p) { struct pnp_mem *mem; @@ -565,10 +573,11 @@ static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_option *option, mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? IORESOURCE_MEM_WRITEABLE : 0; - pnp_register_mem_resource(option, mem); + pnp_register_mem_resource(dev, option, mem); } -static __init void pnpacpi_parse_address_option(struct pnp_option *option, +static __init void pnpacpi_parse_address_option(struct pnp_dev *dev, + struct pnp_option *option, struct acpi_resource *r) { struct acpi_resource_address64 addr, *p = &addr; @@ -596,7 +605,7 @@ static __init void pnpacpi_parse_address_option(struct pnp_option *option, mem->flags = (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE : 0; - pnp_register_mem_resource(option, mem); + pnp_register_mem_resource(dev, option, mem); } else if (p->resource_type == ACPI_IO_RANGE) { port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL); if (!port) @@ -605,7 +614,7 @@ static __init void pnpacpi_parse_address_option(struct pnp_option *option, port->size = p->address_length; port->align = 0; port->flags = PNP_PORT_FLAG_FIXED; - pnp_register_port_resource(option, port); + pnp_register_port_resource(dev, option, port); } } @@ -625,11 +634,11 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, switch (res->type) { case ACPI_RESOURCE_TYPE_IRQ: - pnpacpi_parse_irq_option(option, &res->data.irq); + pnpacpi_parse_irq_option(dev, option, &res->data.irq); break; case ACPI_RESOURCE_TYPE_DMA: - pnpacpi_parse_dma_option(option, &res->data.dma); + pnpacpi_parse_dma_option(dev, option, &res->data.dma); break; case ACPI_RESOURCE_TYPE_START_DEPENDENT: @@ -664,14 +673,16 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, } parse_data->option = parse_data->option_independent; parse_data->option_independent = NULL; + dev_dbg(&dev->dev, "end dependent options\n"); break; case ACPI_RESOURCE_TYPE_IO: - pnpacpi_parse_port_option(option, &res->data.io); + pnpacpi_parse_port_option(dev, option, &res->data.io); break; case ACPI_RESOURCE_TYPE_FIXED_IO: - pnpacpi_parse_fixed_port_option(option, &res->data.fixed_io); + pnpacpi_parse_fixed_port_option(dev, option, + &res->data.fixed_io); break; case ACPI_RESOURCE_TYPE_VENDOR: @@ -679,29 +690,30 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, break; case ACPI_RESOURCE_TYPE_MEMORY24: - pnpacpi_parse_mem24_option(option, &res->data.memory24); + pnpacpi_parse_mem24_option(dev, option, &res->data.memory24); break; case ACPI_RESOURCE_TYPE_MEMORY32: - pnpacpi_parse_mem32_option(option, &res->data.memory32); + pnpacpi_parse_mem32_option(dev, option, &res->data.memory32); break; case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: - pnpacpi_parse_fixed_mem32_option(option, + pnpacpi_parse_fixed_mem32_option(dev, option, &res->data.fixed_memory32); break; case ACPI_RESOURCE_TYPE_ADDRESS16: case ACPI_RESOURCE_TYPE_ADDRESS32: case ACPI_RESOURCE_TYPE_ADDRESS64: - pnpacpi_parse_address_option(option, res); + pnpacpi_parse_address_option(dev, option, res); break; case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: break; case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: - pnpacpi_parse_ext_irq_option(option, &res->data.extended_irq); + pnpacpi_parse_ext_irq_option(dev, option, + &res->data.extended_irq); break; case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c index 948a661280d7..70aa559b3f8c 100644 --- a/drivers/pnp/pnpbios/rsparser.c +++ b/drivers/pnp/pnpbios/rsparser.c @@ -263,7 +263,8 @@ len_err: * Resource Configuration Options */ -static __init void pnpbios_parse_mem_option(unsigned char *p, int size, +static __init void pnpbios_parse_mem_option(struct pnp_dev *dev, + unsigned char *p, int size, struct pnp_option *option) { struct pnp_mem *mem; @@ -276,10 +277,11 @@ static __init void pnpbios_parse_mem_option(unsigned char *p, int size, mem->align = (p[9] << 8) | p[8]; mem->size = ((p[11] << 8) | p[10]) << 8; mem->flags = p[3]; - pnp_register_mem_resource(option, mem); + pnp_register_mem_resource(dev, option, mem); } -static __init void pnpbios_parse_mem32_option(unsigned char *p, int size, +static __init void pnpbios_parse_mem32_option(struct pnp_dev *dev, + unsigned char *p, int size, struct pnp_option *option) { struct pnp_mem *mem; @@ -292,10 +294,11 @@ static __init void pnpbios_parse_mem32_option(unsigned char *p, int size, mem->align = (p[15] << 24) | (p[14] << 16) | (p[13] << 8) | p[12]; mem->size = (p[19] << 24) | (p[18] << 16) | (p[17] << 8) | p[16]; mem->flags = p[3]; - pnp_register_mem_resource(option, mem); + pnp_register_mem_resource(dev, option, mem); } -static __init void pnpbios_parse_fixed_mem32_option(unsigned char *p, int size, +static __init void pnpbios_parse_fixed_mem32_option(struct pnp_dev *dev, + unsigned char *p, int size, struct pnp_option *option) { struct pnp_mem *mem; @@ -307,11 +310,12 @@ static __init void pnpbios_parse_fixed_mem32_option(unsigned char *p, int size, mem->size = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8]; mem->align = 0; mem->flags = p[3]; - pnp_register_mem_resource(option, mem); + pnp_register_mem_resource(dev, option, mem); } -static __init void pnpbios_parse_irq_option(unsigned char *p, int size, - struct pnp_option *option) +static __init void pnpbios_parse_irq_option(struct pnp_dev *dev, + unsigned char *p, int size, + struct pnp_option *option) { struct pnp_irq *irq; unsigned long bits; @@ -325,11 +329,12 @@ static __init void pnpbios_parse_irq_option(unsigned char *p, int size, irq->flags = p[3]; else irq->flags = IORESOURCE_IRQ_HIGHEDGE; - pnp_register_irq_resource(option, irq); + pnp_register_irq_resource(dev, option, irq); } -static __init void pnpbios_parse_dma_option(unsigned char *p, int size, - struct pnp_option *option) +static __init void pnpbios_parse_dma_option(struct pnp_dev *dev, + unsigned char *p, int size, + struct pnp_option *option) { struct pnp_dma *dma; @@ -338,10 +343,11 @@ static __init void pnpbios_parse_dma_option(unsigned char *p, int size, return; dma->map = p[1]; dma->flags = p[2]; - pnp_register_dma_resource(option, dma); + pnp_register_dma_resource(dev, option, dma); } -static __init void pnpbios_parse_port_option(unsigned char *p, int size, +static __init void pnpbios_parse_port_option(struct pnp_dev *dev, + unsigned char *p, int size, struct pnp_option *option) { struct pnp_port *port; @@ -354,10 +360,11 @@ static __init void pnpbios_parse_port_option(unsigned char *p, int size, port->align = p[6]; port->size = p[7]; port->flags = p[1] ? PNP_PORT_FLAG_16BITADDR : 0; - pnp_register_port_resource(option, port); + pnp_register_port_resource(dev, option, port); } -static __init void pnpbios_parse_fixed_port_option(unsigned char *p, int size, +static __init void pnpbios_parse_fixed_port_option(struct pnp_dev *dev, + unsigned char *p, int size, struct pnp_option *option) { struct pnp_port *port; @@ -369,7 +376,7 @@ static __init void pnpbios_parse_fixed_port_option(unsigned char *p, int size, port->size = p[3]; port->align = 0; port->flags = PNP_PORT_FLAG_FIXED; - pnp_register_port_resource(option, port); + pnp_register_port_resource(dev, option, port); } static __init unsigned char * @@ -403,37 +410,37 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, case LARGE_TAG_MEM: if (len != 9) goto len_err; - pnpbios_parse_mem_option(p, len, option); + pnpbios_parse_mem_option(dev, p, len, option); break; case LARGE_TAG_MEM32: if (len != 17) goto len_err; - pnpbios_parse_mem32_option(p, len, option); + pnpbios_parse_mem32_option(dev, p, len, option); break; case LARGE_TAG_FIXEDMEM32: if (len != 9) goto len_err; - pnpbios_parse_fixed_mem32_option(p, len, option); + pnpbios_parse_fixed_mem32_option(dev, p, len, option); break; case SMALL_TAG_IRQ: if (len < 2 || len > 3) goto len_err; - pnpbios_parse_irq_option(p, len, option); + pnpbios_parse_irq_option(dev, p, len, option); break; case SMALL_TAG_DMA: if (len != 2) goto len_err; - pnpbios_parse_dma_option(p, len, option); + pnpbios_parse_dma_option(dev, p, len, option); break; case SMALL_TAG_PORT: if (len != 7) goto len_err; - pnpbios_parse_port_option(p, len, option); + pnpbios_parse_port_option(dev, p, len, option); break; case SMALL_TAG_VENDOR: @@ -443,7 +450,7 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, case SMALL_TAG_FIXEDPORT: if (len != 3) goto len_err; - pnpbios_parse_fixed_port_option(p, len, option); + pnpbios_parse_fixed_port_option(dev, p, len, option); break; case SMALL_TAG_STARTDEP: @@ -464,6 +471,7 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, printk(KERN_WARNING "PnPBIOS: Missing SMALL_TAG_STARTDEP tag\n"); option = option_independent; + dev_dbg(&dev->dev, "end dependent options\n"); break; case SMALL_TAG_END: diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index e50ebcffb962..eee6d8eddcb4 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -53,6 +53,8 @@ struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev) if (dev->independent) dev_err(&dev->dev, "independent resource already registered\n"); dev->independent = option; + + dev_dbg(&dev->dev, "new independent option\n"); return option; } @@ -70,12 +72,18 @@ struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev, parent->next = option; } else dev->dependent = option; + + dev_dbg(&dev->dev, "new dependent option (priority %#x)\n", priority); return option; } -int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data) +int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option, + struct pnp_irq *data) { struct pnp_irq *ptr; +#ifdef DEBUG + char buf[PNP_IRQ_NR]; /* hex-encoded, so this is overkill but safe */ +#endif ptr = option->irq; while (ptr && ptr->next) @@ -94,10 +102,17 @@ int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data) pcibios_penalize_isa_irq(i, 0); } #endif + +#ifdef DEBUG + bitmap_scnprintf(buf, sizeof(buf), data->map, PNP_IRQ_NR); + dev_dbg(&dev->dev, " irq bitmask %s flags %#x\n", buf, + data->flags); +#endif return 0; } -int pnp_register_dma_resource(struct pnp_option *option, struct pnp_dma *data) +int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option, + struct pnp_dma *data) { struct pnp_dma *ptr; @@ -109,10 +124,13 @@ int pnp_register_dma_resource(struct pnp_option *option, struct pnp_dma *data) else option->dma = data; + dev_dbg(&dev->dev, " dma bitmask %#x flags %#x\n", data->map, + data->flags); return 0; } -int pnp_register_port_resource(struct pnp_option *option, struct pnp_port *data) +int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option, + struct pnp_port *data) { struct pnp_port *ptr; @@ -124,10 +142,14 @@ int pnp_register_port_resource(struct pnp_option *option, struct pnp_port *data) else option->port = data; + dev_dbg(&dev->dev, " io " + "min %#x max %#x align %d size %d flags %#x\n", + data->min, data->max, data->align, data->size, data->flags); return 0; } -int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data) +int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option, + struct pnp_mem *data) { struct pnp_mem *ptr; @@ -138,6 +160,10 @@ int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data) ptr->next = data; else option->mem = data; + + dev_dbg(&dev->dev, " mem " + "min %#x max %#x align %d size %d flags %#x\n", + data->min, data->max, data->align, data->size, data->flags); return 0; } diff --git a/include/linux/pnp.h b/include/linux/pnp.h index 7639db83ce3f..a4c2bf361596 100644 --- a/include/linux/pnp.h +++ b/include/linux/pnp.h @@ -382,11 +382,14 @@ extern struct list_head pnp_cards; struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev); struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev, int priority); -int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data); -int pnp_register_dma_resource(struct pnp_option *option, struct pnp_dma *data); -int pnp_register_port_resource(struct pnp_option *option, +int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option, + struct pnp_irq *data); +int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option, + struct pnp_dma *data); +int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option, struct pnp_port *data); -int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data); +int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option, + struct pnp_mem *data); void pnp_init_resource_table(struct pnp_resource_table *table); int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, int mode); @@ -430,10 +433,10 @@ static inline void pnp_unregister_card_driver(struct pnp_card_driver *drv) { } /* resource management */ static inline struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev) { return NULL; } static inline struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev, int priority) { return NULL; } -static inline int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data) { return -ENODEV; } -static inline int pnp_register_dma_resource(struct pnp_option *option, struct pnp_dma *data) { return -ENODEV; } -static inline int pnp_register_port_resource(struct pnp_option *option, struct pnp_port *data) { return -ENODEV; } -static inline int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data) { return -ENODEV; } +static inline int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option, struct pnp_irq *data) { return -ENODEV; } +static inline int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option, struct pnp_dma *data) { return -ENODEV; } +static inline int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option, struct pnp_port *data) { return -ENODEV; } +static inline int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option, struct pnp_mem *data) { return -ENODEV; } static inline void pnp_init_resource_table(struct pnp_resource_table *table) { } static inline int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, int mode) { return -ENODEV; } static inline int pnp_auto_config_dev(struct pnp_dev *dev) { return -ENODEV; } -- cgit v1.2.2 From 59284cb4099411bc6f4915a5a4cb76414440c447 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:05 -0600 Subject: PNP: remove pnp_resource_table from internal get/set interfaces When we call protocol->get() and protocol->set() methods, we currently supply pointers to both the pnp_dev and the pnp_resource_table even though the pnp_resource_table should always be the one associated with the pnp_dev. This removes the pnp_resource_table arguments to make it clear that these methods only operate on the specified pnp_dev. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/interface.c | 2 +- drivers/pnp/isapnp/core.c | 11 +++++------ drivers/pnp/manager.c | 2 +- drivers/pnp/pnpacpi/core.c | 8 +++----- drivers/pnp/pnpbios/core.c | 10 ++++------ include/linux/pnp.h | 4 ++-- 6 files changed, 16 insertions(+), 21 deletions(-) diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c index 982658477a58..e882896bdbd7 100644 --- a/drivers/pnp/interface.c +++ b/drivers/pnp/interface.c @@ -364,7 +364,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, if (!strnicmp(buf, "get", 3)) { mutex_lock(&pnp_res_mutex); if (pnp_can_read(dev)) - dev->protocol->get(dev, &dev->res); + dev->protocol->get(dev); mutex_unlock(&pnp_res_mutex); goto done; } diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index 38ff64dce9c0..1ae3d8996156 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -976,21 +976,20 @@ static int isapnp_read_resources(struct pnp_dev *dev, return 0; } -static int isapnp_get_resources(struct pnp_dev *dev, - struct pnp_resource_table *res) +static int isapnp_get_resources(struct pnp_dev *dev) { int ret; - pnp_init_resource_table(res); + pnp_init_resource_table(&dev->res); isapnp_cfg_begin(dev->card->number, dev->number); - ret = isapnp_read_resources(dev, res); + ret = isapnp_read_resources(dev, &dev->res); isapnp_cfg_end(); return ret; } -static int isapnp_set_resources(struct pnp_dev *dev, - struct pnp_resource_table *res) +static int isapnp_set_resources(struct pnp_dev *dev) { + struct pnp_resource_table *res = &dev->res; int tmp; isapnp_cfg_begin(dev->card->number, dev->number); diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index c28caf272c11..6a1f0b0b24b3 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c @@ -473,7 +473,7 @@ int pnp_start_dev(struct pnp_dev *dev) return -EINVAL; } - if (dev->protocol->set(dev, &dev->res) < 0) { + if (dev->protocol->set(dev) < 0) { dev_err(&dev->dev, "activation failed\n"); return -EIO; } diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 27546873880c..590fbcb0ee89 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -73,8 +73,7 @@ static int __init ispnpidacpi(char *id) return 1; } -static int pnpacpi_get_resources(struct pnp_dev *dev, - struct pnp_resource_table *res) +static int pnpacpi_get_resources(struct pnp_dev *dev) { acpi_status status; @@ -83,8 +82,7 @@ static int pnpacpi_get_resources(struct pnp_dev *dev, return ACPI_FAILURE(status) ? -ENODEV : 0; } -static int pnpacpi_set_resources(struct pnp_dev *dev, - struct pnp_resource_table *res) +static int pnpacpi_set_resources(struct pnp_dev *dev) { acpi_handle handle = dev->data; struct acpi_buffer buffer; @@ -94,7 +92,7 @@ static int pnpacpi_set_resources(struct pnp_dev *dev, ret = pnpacpi_build_resource_template(dev, &buffer); if (ret) return ret; - ret = pnpacpi_encode_resources(res, &buffer); + ret = pnpacpi_encode_resources(&dev->res, &buffer); if (ret) { kfree(buffer.pointer); return ret; diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c index 6af2be2c1d67..9852755b5590 100644 --- a/drivers/pnp/pnpbios/core.c +++ b/drivers/pnp/pnpbios/core.c @@ -204,8 +204,7 @@ static int pnp_dock_thread(void *unused) #endif /* CONFIG_HOTPLUG */ -static int pnpbios_get_resources(struct pnp_dev *dev, - struct pnp_resource_table *res) +static int pnpbios_get_resources(struct pnp_dev *dev) { u8 nodenum = dev->number; struct pnp_bios_node *node; @@ -220,14 +219,13 @@ static int pnpbios_get_resources(struct pnp_dev *dev, kfree(node); return -ENODEV; } - pnpbios_read_resources_from_node(res, node); + pnpbios_read_resources_from_node(&dev->res, node); dev->active = pnp_is_active(dev); kfree(node); return 0; } -static int pnpbios_set_resources(struct pnp_dev *dev, - struct pnp_resource_table *res) +static int pnpbios_set_resources(struct pnp_dev *dev) { u8 nodenum = dev->number; struct pnp_bios_node *node; @@ -243,7 +241,7 @@ static int pnpbios_set_resources(struct pnp_dev *dev, kfree(node); return -ENODEV; } - if (pnpbios_write_resources_to_node(res, node) < 0) { + if (pnpbios_write_resources_to_node(&dev->res, node) < 0) { kfree(node); return -1; } diff --git a/include/linux/pnp.h b/include/linux/pnp.h index a4c2bf361596..8d7c9bc2fdbb 100644 --- a/include/linux/pnp.h +++ b/include/linux/pnp.h @@ -328,8 +328,8 @@ struct pnp_protocol { char *name; /* resource control functions */ - int (*get) (struct pnp_dev *dev, struct pnp_resource_table *res); - int (*set) (struct pnp_dev *dev, struct pnp_resource_table *res); + int (*get) (struct pnp_dev *dev); + int (*set) (struct pnp_dev *dev); int (*disable) (struct pnp_dev *dev); /* protocol specific suspend/resume */ -- cgit v1.2.2 From 4ab55d8d4f7b910c4c60e0f8ff70d0dfdd484f02 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:06 -0600 Subject: PNP: remove more pnp_resource_table arguments Stop passing around struct pnp_resource_table pointers. In most cases, the caller doesn't need to know how the resources are stored inside the struct pnp_dev. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/isapnp/core.c | 6 ++--- drivers/pnp/pnpacpi/core.c | 11 +++----- drivers/pnp/pnpacpi/pnpacpi.h | 6 ++--- drivers/pnp/pnpacpi/rsparser.c | 55 +++++++++++++++++++++------------------ drivers/pnp/pnpbios/core.c | 4 +-- drivers/pnp/pnpbios/pnpbios.h | 4 +-- drivers/pnp/pnpbios/rsparser.c | 58 +++++++++++++++++++++--------------------- 7 files changed, 73 insertions(+), 71 deletions(-) diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index 1ae3d8996156..b8e639f4f227 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -932,9 +932,9 @@ EXPORT_SYMBOL(isapnp_cfg_begin); EXPORT_SYMBOL(isapnp_cfg_end); EXPORT_SYMBOL(isapnp_write_byte); -static int isapnp_read_resources(struct pnp_dev *dev, - struct pnp_resource_table *res) +static int isapnp_read_resources(struct pnp_dev *dev) { + struct pnp_resource_table *res = &dev->res; int tmp, ret; dev->active = isapnp_read_byte(ISAPNP_CFG_ACTIVATE); @@ -982,7 +982,7 @@ static int isapnp_get_resources(struct pnp_dev *dev) pnp_init_resource_table(&dev->res); isapnp_cfg_begin(dev->card->number, dev->number); - ret = isapnp_read_resources(dev, &dev->res); + ret = isapnp_read_resources(dev); isapnp_cfg_end(); return ret; } diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 590fbcb0ee89..3fd2416d6795 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -77,8 +77,7 @@ static int pnpacpi_get_resources(struct pnp_dev *dev) { acpi_status status; - status = pnpacpi_parse_allocated_resource((acpi_handle) dev->data, - &dev->res); + status = pnpacpi_parse_allocated_resource(dev); return ACPI_FAILURE(status) ? -ENODEV : 0; } @@ -92,7 +91,7 @@ static int pnpacpi_set_resources(struct pnp_dev *dev) ret = pnpacpi_build_resource_template(dev, &buffer); if (ret) return ret; - ret = pnpacpi_encode_resources(&dev->res, &buffer); + ret = pnpacpi_encode_resources(dev, &buffer); if (ret) { kfree(buffer.pointer); return ret; @@ -183,8 +182,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device) if (dev->active) { /* parse allocated resource */ - status = pnpacpi_parse_allocated_resource(device->handle, - &dev->res); + status = pnpacpi_parse_allocated_resource(dev); if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { pnp_err("PnPACPI: METHOD_NAME__CRS failure for %s", acpi_device_hid(device)); @@ -192,8 +190,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device) } if (dev->capabilities & PNP_CONFIGURABLE) { - status = pnpacpi_parse_resource_option_data(device->handle, - dev); + status = pnpacpi_parse_resource_option_data(dev); if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { pnp_err("PnPACPI: METHOD_NAME__PRS failure for %s", acpi_device_hid(device)); diff --git a/drivers/pnp/pnpacpi/pnpacpi.h b/drivers/pnp/pnpacpi/pnpacpi.h index 116c591d8634..db0c4f25c2a3 100644 --- a/drivers/pnp/pnpacpi/pnpacpi.h +++ b/drivers/pnp/pnpacpi/pnpacpi.h @@ -5,8 +5,8 @@ #include #include -acpi_status pnpacpi_parse_allocated_resource(acpi_handle, struct pnp_resource_table*); -acpi_status pnpacpi_parse_resource_option_data(acpi_handle, struct pnp_dev*); -int pnpacpi_encode_resources(struct pnp_resource_table *, struct acpi_buffer *); +acpi_status pnpacpi_parse_allocated_resource(struct pnp_dev *); +acpi_status pnpacpi_parse_resource_option_data(struct pnp_dev *); +int pnpacpi_encode_resources(struct pnp_dev *, struct acpi_buffer *); int pnpacpi_build_resource_template(struct pnp_dev *, struct acpi_buffer *); #endif diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 32454aa07ebc..8a0617687723 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -76,10 +76,11 @@ static void decode_irq_flags(int flag, int *triggering, int *polarity) } } -static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, +static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev, u32 gsi, int triggering, int polarity, int shareable) { + struct pnp_resource_table *res = &dev->res; int i = 0; int irq; int p, t; @@ -172,9 +173,10 @@ static int dma_flags(int type, int bus_master, int transfer) return flags; } -static void pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, +static void pnpacpi_parse_allocated_dmaresource(struct pnp_dev *dev, u32 dma, int flags) { + struct pnp_resource_table *res = &dev->res; int i = 0; static unsigned char warned; @@ -197,9 +199,10 @@ static void pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, } } -static void pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res, +static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 io, u64 len, int io_decode) { + struct pnp_resource_table *res = &dev->res; int i = 0; static unsigned char warned; @@ -223,10 +226,11 @@ static void pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res, } } -static void pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res, +static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev, u64 mem, u64 len, int write_protect) { + struct pnp_resource_table *res = &dev->res; int i = 0; static unsigned char warned; @@ -251,7 +255,7 @@ static void pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res, } } -static void pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res_table, +static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev, struct acpi_resource *res) { struct acpi_resource_address64 addr, *p = &addr; @@ -268,11 +272,11 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res return; if (p->resource_type == ACPI_MEMORY_RANGE) - pnpacpi_parse_allocated_memresource(res_table, + pnpacpi_parse_allocated_memresource(dev, p->minimum, p->address_length, p->info.mem.write_protect); else if (p->resource_type == ACPI_IO_RANGE) - pnpacpi_parse_allocated_ioresource(res_table, + pnpacpi_parse_allocated_ioresource(dev, p->minimum, p->address_length, p->granularity == 0xfff ? ACPI_DECODE_10 : ACPI_DECODE_16); @@ -281,7 +285,7 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, void *data) { - struct pnp_resource_table *res_table = data; + struct pnp_dev *dev = data; struct acpi_resource_irq *irq; struct acpi_resource_dma *dma; struct acpi_resource_io *io; @@ -300,7 +304,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, */ irq = &res->data.irq; for (i = 0; i < irq->interrupt_count; i++) { - pnpacpi_parse_allocated_irqresource(res_table, + pnpacpi_parse_allocated_irqresource(dev, irq->interrupts[i], irq->triggering, irq->polarity, @@ -311,7 +315,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, case ACPI_RESOURCE_TYPE_DMA: dma = &res->data.dma; if (dma->channel_count > 0) - pnpacpi_parse_allocated_dmaresource(res_table, + pnpacpi_parse_allocated_dmaresource(dev, dma->channels[0], dma_flags(dma->type, dma->bus_master, dma->transfer)); @@ -319,7 +323,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, case ACPI_RESOURCE_TYPE_IO: io = &res->data.io; - pnpacpi_parse_allocated_ioresource(res_table, + pnpacpi_parse_allocated_ioresource(dev, io->minimum, io->address_length, io->io_decode); @@ -331,7 +335,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, case ACPI_RESOURCE_TYPE_FIXED_IO: fixed_io = &res->data.fixed_io; - pnpacpi_parse_allocated_ioresource(res_table, + pnpacpi_parse_allocated_ioresource(dev, fixed_io->address, fixed_io->address_length, ACPI_DECODE_10); @@ -345,21 +349,21 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, case ACPI_RESOURCE_TYPE_MEMORY24: memory24 = &res->data.memory24; - pnpacpi_parse_allocated_memresource(res_table, + pnpacpi_parse_allocated_memresource(dev, memory24->minimum, memory24->address_length, memory24->write_protect); break; case ACPI_RESOURCE_TYPE_MEMORY32: memory32 = &res->data.memory32; - pnpacpi_parse_allocated_memresource(res_table, + pnpacpi_parse_allocated_memresource(dev, memory32->minimum, memory32->address_length, memory32->write_protect); break; case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: fixed_memory32 = &res->data.fixed_memory32; - pnpacpi_parse_allocated_memresource(res_table, + pnpacpi_parse_allocated_memresource(dev, fixed_memory32->address, fixed_memory32->address_length, fixed_memory32->write_protect); @@ -367,7 +371,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, case ACPI_RESOURCE_TYPE_ADDRESS16: case ACPI_RESOURCE_TYPE_ADDRESS32: case ACPI_RESOURCE_TYPE_ADDRESS64: - pnpacpi_parse_allocated_address_space(res_table, res); + pnpacpi_parse_allocated_address_space(dev, res); break; case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: @@ -381,7 +385,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, return AE_OK; for (i = 0; i < extended_irq->interrupt_count; i++) { - pnpacpi_parse_allocated_irqresource(res_table, + pnpacpi_parse_allocated_irqresource(dev, extended_irq->interrupts[i], extended_irq->triggering, extended_irq->polarity, @@ -400,14 +404,15 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, return AE_OK; } -acpi_status pnpacpi_parse_allocated_resource(acpi_handle handle, - struct pnp_resource_table * res) +acpi_status pnpacpi_parse_allocated_resource(struct pnp_dev *dev) { + acpi_handle handle = dev->data; + /* Blank the resource table values */ - pnp_init_resource_table(res); + pnp_init_resource_table(&dev->res); return acpi_walk_resources(handle, METHOD_NAME__CRS, - pnpacpi_allocated_resource, res); + pnpacpi_allocated_resource, dev); } static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev, @@ -727,9 +732,9 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, return AE_OK; } -acpi_status __init pnpacpi_parse_resource_option_data(acpi_handle handle, - struct pnp_dev *dev) +acpi_status __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev) { + acpi_handle handle = dev->data; acpi_status status; struct acpipnp_parse_option_s parse_data; @@ -959,9 +964,9 @@ static void pnpacpi_encode_fixed_mem32(struct acpi_resource *resource, fixed_memory32->address_length = p->end - p->start + 1; } -int pnpacpi_encode_resources(struct pnp_resource_table *res_table, - struct acpi_buffer *buffer) +int pnpacpi_encode_resources(struct pnp_dev *dev, struct acpi_buffer *buffer) { + struct pnp_resource_table *res_table = &dev->res; int i = 0; /* pnpacpi_build_resource_template allocates extra mem */ int res_cnt = (buffer->length - 1) / sizeof(struct acpi_resource) - 1; diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c index 9852755b5590..1711e7f29613 100644 --- a/drivers/pnp/pnpbios/core.c +++ b/drivers/pnp/pnpbios/core.c @@ -219,7 +219,7 @@ static int pnpbios_get_resources(struct pnp_dev *dev) kfree(node); return -ENODEV; } - pnpbios_read_resources_from_node(&dev->res, node); + pnpbios_read_resources_from_node(dev, node); dev->active = pnp_is_active(dev); kfree(node); return 0; @@ -241,7 +241,7 @@ static int pnpbios_set_resources(struct pnp_dev *dev) kfree(node); return -ENODEV; } - if (pnpbios_write_resources_to_node(&dev->res, node) < 0) { + if (pnpbios_write_resources_to_node(dev, node) < 0) { kfree(node); return -1; } diff --git a/drivers/pnp/pnpbios/pnpbios.h b/drivers/pnp/pnpbios/pnpbios.h index d8cb2fd1f127..42343fc753ba 100644 --- a/drivers/pnp/pnpbios/pnpbios.h +++ b/drivers/pnp/pnpbios/pnpbios.h @@ -28,8 +28,8 @@ extern int pnp_bios_present(void); extern int pnpbios_dont_use_current_config; extern int pnpbios_parse_data_stream(struct pnp_dev *dev, struct pnp_bios_node * node); -extern int pnpbios_read_resources_from_node(struct pnp_resource_table *res, struct pnp_bios_node * node); -extern int pnpbios_write_resources_to_node(struct pnp_resource_table *res, struct pnp_bios_node * node); +extern int pnpbios_read_resources_from_node(struct pnp_dev *dev, struct pnp_bios_node *node); +extern int pnpbios_write_resources_to_node(struct pnp_dev *dev, struct pnp_bios_node *node); extern void pnpid32_to_pnpid(u32 id, char *str); extern void pnpbios_print_status(const char * module, u16 status); diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c index 70aa559b3f8c..1b8f30ff192a 100644 --- a/drivers/pnp/pnpbios/rsparser.c +++ b/drivers/pnp/pnpbios/rsparser.c @@ -54,9 +54,9 @@ inline void pcibios_penalize_isa_irq(int irq, int active) * Allocated Resources */ -static void pnpbios_parse_allocated_irqresource(struct pnp_resource_table *res, - int irq) +static void pnpbios_parse_allocated_irqresource(struct pnp_dev *dev, int irq) { + struct pnp_resource_table *res = &dev->res; int i = 0; while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) @@ -74,9 +74,9 @@ static void pnpbios_parse_allocated_irqresource(struct pnp_resource_table *res, } } -static void pnpbios_parse_allocated_dmaresource(struct pnp_resource_table *res, - int dma) +static void pnpbios_parse_allocated_dmaresource(struct pnp_dev *dev, int dma) { + struct pnp_resource_table *res = &dev->res; int i = 0; while (i < PNP_MAX_DMA && @@ -93,9 +93,10 @@ static void pnpbios_parse_allocated_dmaresource(struct pnp_resource_table *res, } } -static void pnpbios_parse_allocated_ioresource(struct pnp_resource_table *res, +static void pnpbios_parse_allocated_ioresource(struct pnp_dev *dev, int io, int len) { + struct pnp_resource_table *res = &dev->res; int i = 0; while (!(res->port_resource[i].flags & IORESOURCE_UNSET) @@ -112,9 +113,10 @@ static void pnpbios_parse_allocated_ioresource(struct pnp_resource_table *res, } } -static void pnpbios_parse_allocated_memresource(struct pnp_resource_table *res, +static void pnpbios_parse_allocated_memresource(struct pnp_dev *dev, int mem, int len) { + struct pnp_resource_table *res = &dev->res; int i = 0; while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) @@ -131,11 +133,9 @@ static void pnpbios_parse_allocated_memresource(struct pnp_resource_table *res, } } -static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p, - unsigned char *end, - struct - pnp_resource_table - *res) +static unsigned char *pnpbios_parse_allocated_resource_data(struct pnp_dev *dev, + unsigned char *p, + unsigned char *end) { unsigned int len, tag; int io, size, mask, i; @@ -144,7 +144,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p, return NULL; /* Blank the resource table values */ - pnp_init_resource_table(res); + pnp_init_resource_table(&dev->res); while ((char *)p < (char *)end) { @@ -164,7 +164,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p, goto len_err; io = *(short *)&p[4]; size = *(short *)&p[10]; - pnpbios_parse_allocated_memresource(res, io, size); + pnpbios_parse_allocated_memresource(dev, io, size); break; case LARGE_TAG_ANSISTR: @@ -180,7 +180,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p, goto len_err; io = *(int *)&p[4]; size = *(int *)&p[16]; - pnpbios_parse_allocated_memresource(res, io, size); + pnpbios_parse_allocated_memresource(dev, io, size); break; case LARGE_TAG_FIXEDMEM32: @@ -188,7 +188,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p, goto len_err; io = *(int *)&p[4]; size = *(int *)&p[8]; - pnpbios_parse_allocated_memresource(res, io, size); + pnpbios_parse_allocated_memresource(dev, io, size); break; case SMALL_TAG_IRQ: @@ -199,7 +199,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p, for (i = 0; i < 16; i++, mask = mask >> 1) if (mask & 0x01) io = i; - pnpbios_parse_allocated_irqresource(res, io); + pnpbios_parse_allocated_irqresource(dev, io); break; case SMALL_TAG_DMA: @@ -210,7 +210,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p, for (i = 0; i < 8; i++, mask = mask >> 1) if (mask & 0x01) io = i; - pnpbios_parse_allocated_dmaresource(res, io); + pnpbios_parse_allocated_dmaresource(dev, io); break; case SMALL_TAG_PORT: @@ -218,7 +218,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p, goto len_err; io = p[2] + p[3] * 256; size = p[7]; - pnpbios_parse_allocated_ioresource(res, io, size); + pnpbios_parse_allocated_ioresource(dev, io, size); break; case SMALL_TAG_VENDOR: @@ -230,7 +230,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p, goto len_err; io = p[1] + p[2] * 256; size = p[3]; - pnpbios_parse_allocated_ioresource(res, io, size); + pnpbios_parse_allocated_ioresource(dev, io, size); break; case SMALL_TAG_END: @@ -660,12 +660,12 @@ static void pnpbios_encode_fixed_port(unsigned char *p, struct resource *res) p[3] = len & 0xff; } -static unsigned char *pnpbios_encode_allocated_resource_data(unsigned char *p, - unsigned char *end, - struct - pnp_resource_table - *res) +static unsigned char *pnpbios_encode_allocated_resource_data(struct pnp_dev + *dev, + unsigned char *p, + unsigned char *end) { + struct pnp_resource_table *res = &dev->res; unsigned int len, tag; int port = 0, irq = 0, dma = 0, mem = 0; @@ -774,7 +774,7 @@ int __init pnpbios_parse_data_stream(struct pnp_dev *dev, unsigned char *p = (char *)node->data; unsigned char *end = (char *)(node->data + node->size); - p = pnpbios_parse_allocated_resource_data(p, end, &dev->res); + p = pnpbios_parse_allocated_resource_data(dev, p, end); if (!p) return -EIO; p = pnpbios_parse_resource_option_data(p, end, dev); @@ -786,25 +786,25 @@ int __init pnpbios_parse_data_stream(struct pnp_dev *dev, return 0; } -int pnpbios_read_resources_from_node(struct pnp_resource_table *res, +int pnpbios_read_resources_from_node(struct pnp_dev *dev, struct pnp_bios_node *node) { unsigned char *p = (char *)node->data; unsigned char *end = (char *)(node->data + node->size); - p = pnpbios_parse_allocated_resource_data(p, end, res); + p = pnpbios_parse_allocated_resource_data(dev, p, end); if (!p) return -EIO; return 0; } -int pnpbios_write_resources_to_node(struct pnp_resource_table *res, +int pnpbios_write_resources_to_node(struct pnp_dev *dev, struct pnp_bios_node *node) { unsigned char *p = (char *)node->data; unsigned char *end = (char *)(node->data + node->size); - p = pnpbios_encode_allocated_resource_data(p, end, res); + p = pnpbios_encode_allocated_resource_data(dev, p, end); if (!p) return -EIO; return 0; -- cgit v1.2.2 From 72dcc883d8e5b59105e75ee5265442e458740575 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:07 -0600 Subject: PNP: add debug output to encoders Add debug output to encoders (enabled by CONFIG_PNP_DEBUG). This uses dev_printk, so I had to add pnp_dev arguments at the same time. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/isapnp/core.c | 18 +++++++-- drivers/pnp/pnpacpi/core.c | 2 + drivers/pnp/pnpacpi/rsparser.c | 90 ++++++++++++++++++++++++++++++------------ drivers/pnp/pnpbios/core.c | 2 + drivers/pnp/pnpbios/rsparser.c | 58 ++++++++++++++++++++------- 5 files changed, 127 insertions(+), 43 deletions(-) diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index b8e639f4f227..6740016437d9 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -980,6 +980,7 @@ static int isapnp_get_resources(struct pnp_dev *dev) { int ret; + dev_dbg(&dev->dev, "get resources\n"); pnp_init_resource_table(&dev->res); isapnp_cfg_begin(dev->card->number, dev->number); ret = isapnp_read_resources(dev); @@ -992,15 +993,19 @@ static int isapnp_set_resources(struct pnp_dev *dev) struct pnp_resource_table *res = &dev->res; int tmp; + dev_dbg(&dev->dev, "set resources\n"); isapnp_cfg_begin(dev->card->number, dev->number); dev->active = 1; for (tmp = 0; tmp < ISAPNP_MAX_PORT && (res->port_resource[tmp]. flags & (IORESOURCE_IO | IORESOURCE_UNSET)) == IORESOURCE_IO; - tmp++) + tmp++) { + dev_dbg(&dev->dev, " set io %d to %#llx\n", + tmp, (unsigned long long) res->port_resource[tmp].start); isapnp_write_word(ISAPNP_CFG_PORT + (tmp << 1), res->port_resource[tmp].start); + } for (tmp = 0; tmp < ISAPNP_MAX_IRQ && (res->irq_resource[tmp]. @@ -1009,22 +1014,29 @@ static int isapnp_set_resources(struct pnp_dev *dev) int irq = res->irq_resource[tmp].start; if (irq == 2) irq = 9; + dev_dbg(&dev->dev, " set irq %d to %d\n", tmp, irq); isapnp_write_byte(ISAPNP_CFG_IRQ + (tmp << 1), irq); } for (tmp = 0; tmp < ISAPNP_MAX_DMA && (res->dma_resource[tmp]. flags & (IORESOURCE_DMA | IORESOURCE_UNSET)) == IORESOURCE_DMA; - tmp++) + tmp++) { + dev_dbg(&dev->dev, " set dma %d to %lld\n", + tmp, (unsigned long long) res->dma_resource[tmp].start); isapnp_write_byte(ISAPNP_CFG_DMA + tmp, res->dma_resource[tmp].start); + } for (tmp = 0; tmp < ISAPNP_MAX_MEM && (res->mem_resource[tmp]. flags & (IORESOURCE_MEM | IORESOURCE_UNSET)) == IORESOURCE_MEM; - tmp++) + tmp++) { + dev_dbg(&dev->dev, " set mem %d to %#llx\n", + tmp, (unsigned long long) res->mem_resource[tmp].start); isapnp_write_word(ISAPNP_CFG_MEM + (tmp << 3), (res->mem_resource[tmp].start >> 8) & 0xffff); + } /* FIXME: We aren't handling 32bit mems properly here */ isapnp_activate(dev->number); isapnp_cfg_end(); diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 3fd2416d6795..1ac894d2df5a 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -77,6 +77,7 @@ static int pnpacpi_get_resources(struct pnp_dev *dev) { acpi_status status; + dev_dbg(&dev->dev, "get resources\n"); status = pnpacpi_parse_allocated_resource(dev); return ACPI_FAILURE(status) ? -ENODEV : 0; } @@ -88,6 +89,7 @@ static int pnpacpi_set_resources(struct pnp_dev *dev) int ret; acpi_status status; + dev_dbg(&dev->dev, "set resources\n"); ret = pnpacpi_build_resource_template(dev, &buffer); if (ret) return ret; diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 8a0617687723..c5adf7631ac2 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -408,6 +408,8 @@ acpi_status pnpacpi_parse_allocated_resource(struct pnp_dev *dev) { acpi_handle handle = dev->data; + dev_dbg(&dev->dev, "parse allocated resources\n"); + /* Blank the resource table values */ pnp_init_resource_table(&dev->res); @@ -738,6 +740,8 @@ acpi_status __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev) acpi_status status; struct acpipnp_parse_option_s parse_data; + dev_dbg(&dev->dev, "parse resource options\n"); + parse_data.option = pnp_register_independent_option(dev); if (!parse_data.option) return AE_ERROR; @@ -814,7 +818,7 @@ int pnpacpi_build_resource_template(struct pnp_dev *dev, buffer->pointer = kzalloc(buffer->length - 1, GFP_KERNEL); if (!buffer->pointer) return -ENOMEM; - pnp_dbg("Res cnt %d", res_cnt); + resource = (struct acpi_resource *)buffer->pointer; status = acpi_walk_resources(handle, METHOD_NAME__CRS, pnpacpi_type_resources, &resource); @@ -829,7 +833,8 @@ int pnpacpi_build_resource_template(struct pnp_dev *dev, return 0; } -static void pnpacpi_encode_irq(struct acpi_resource *resource, +static void pnpacpi_encode_irq(struct pnp_dev *dev, + struct acpi_resource *resource, struct resource *p) { struct acpi_resource_irq *irq = &resource->data.irq; @@ -844,9 +849,15 @@ static void pnpacpi_encode_irq(struct acpi_resource *resource, irq->sharable = ACPI_SHARED; irq->interrupt_count = 1; irq->interrupts[0] = p->start; + + dev_dbg(&dev->dev, " encode irq %d %s %s %s\n", (int) p->start, + triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge", + polarity == ACPI_ACTIVE_LOW ? "low" : "high", + irq->sharable == ACPI_SHARED ? "shared" : "exclusive"); } -static void pnpacpi_encode_ext_irq(struct acpi_resource *resource, +static void pnpacpi_encode_ext_irq(struct pnp_dev *dev, + struct acpi_resource *resource, struct resource *p) { struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq; @@ -862,9 +873,15 @@ static void pnpacpi_encode_ext_irq(struct acpi_resource *resource, extended_irq->sharable = ACPI_SHARED; extended_irq->interrupt_count = 1; extended_irq->interrupts[0] = p->start; + + dev_dbg(&dev->dev, " encode irq %d %s %s %s\n", (int) p->start, + triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge", + polarity == ACPI_ACTIVE_LOW ? "low" : "high", + extended_irq->sharable == ACPI_SHARED ? "shared" : "exclusive"); } -static void pnpacpi_encode_dma(struct acpi_resource *resource, +static void pnpacpi_encode_dma(struct pnp_dev *dev, + struct acpi_resource *resource, struct resource *p) { struct acpi_resource_dma *dma = &resource->data.dma; @@ -898,9 +915,14 @@ static void pnpacpi_encode_dma(struct acpi_resource *resource, dma->bus_master = !!(p->flags & IORESOURCE_DMA_MASTER); dma->channel_count = 1; dma->channels[0] = p->start; + + dev_dbg(&dev->dev, " encode dma %d " + "type %#x transfer %#x master %d\n", + (int) p->start, dma->type, dma->transfer, dma->bus_master); } -static void pnpacpi_encode_io(struct acpi_resource *resource, +static void pnpacpi_encode_io(struct pnp_dev *dev, + struct acpi_resource *resource, struct resource *p) { struct acpi_resource_io *io = &resource->data.io; @@ -912,18 +934,27 @@ static void pnpacpi_encode_io(struct acpi_resource *resource, io->maximum = p->end; io->alignment = 0; /* Correct? */ io->address_length = p->end - p->start + 1; + + dev_dbg(&dev->dev, " encode io %#llx-%#llx decode %#x\n", + (unsigned long long) p->start, (unsigned long long) p->end, + io->io_decode); } -static void pnpacpi_encode_fixed_io(struct acpi_resource *resource, +static void pnpacpi_encode_fixed_io(struct pnp_dev *dev, + struct acpi_resource *resource, struct resource *p) { struct acpi_resource_fixed_io *fixed_io = &resource->data.fixed_io; fixed_io->address = p->start; fixed_io->address_length = p->end - p->start + 1; + + dev_dbg(&dev->dev, " encode fixed_io %#llx-%#llx\n", + (unsigned long long) p->start, (unsigned long long) p->end); } -static void pnpacpi_encode_mem24(struct acpi_resource *resource, +static void pnpacpi_encode_mem24(struct pnp_dev *dev, + struct acpi_resource *resource, struct resource *p) { struct acpi_resource_memory24 *memory24 = &resource->data.memory24; @@ -936,9 +967,14 @@ static void pnpacpi_encode_mem24(struct acpi_resource *resource, memory24->maximum = p->end; memory24->alignment = 0; memory24->address_length = p->end - p->start + 1; + + dev_dbg(&dev->dev, " encode mem24 %#llx-%#llx write_protect %#x\n", + (unsigned long long) p->start, (unsigned long long) p->end, + memory24->write_protect); } -static void pnpacpi_encode_mem32(struct acpi_resource *resource, +static void pnpacpi_encode_mem32(struct pnp_dev *dev, + struct acpi_resource *resource, struct resource *p) { struct acpi_resource_memory32 *memory32 = &resource->data.memory32; @@ -950,9 +986,14 @@ static void pnpacpi_encode_mem32(struct acpi_resource *resource, memory32->maximum = p->end; memory32->alignment = 0; memory32->address_length = p->end - p->start + 1; + + dev_dbg(&dev->dev, " encode mem32 %#llx-%#llx write_protect %#x\n", + (unsigned long long) p->start, (unsigned long long) p->end, + memory32->write_protect); } -static void pnpacpi_encode_fixed_mem32(struct acpi_resource *resource, +static void pnpacpi_encode_fixed_mem32(struct pnp_dev *dev, + struct acpi_resource *resource, struct resource *p) { struct acpi_resource_fixed_memory32 *fixed_memory32 = &resource->data.fixed_memory32; @@ -962,6 +1003,11 @@ static void pnpacpi_encode_fixed_mem32(struct acpi_resource *resource, ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; fixed_memory32->address = p->start; fixed_memory32->address_length = p->end - p->start + 1; + + dev_dbg(&dev->dev, " encode fixed_mem32 %#llx-%#llx " + "write_protect %#x\n", + (unsigned long long) p->start, (unsigned long long) p->end, + fixed_memory32->write_protect); } int pnpacpi_encode_resources(struct pnp_dev *dev, struct acpi_buffer *buffer) @@ -973,57 +1019,49 @@ int pnpacpi_encode_resources(struct pnp_dev *dev, struct acpi_buffer *buffer) struct acpi_resource *resource = buffer->pointer; int port = 0, irq = 0, dma = 0, mem = 0; - pnp_dbg("res cnt %d", res_cnt); + dev_dbg(&dev->dev, "encode %d resources\n", res_cnt); while (i < res_cnt) { switch (resource->type) { case ACPI_RESOURCE_TYPE_IRQ: - pnp_dbg("Encode irq"); - pnpacpi_encode_irq(resource, + pnpacpi_encode_irq(dev, resource, &res_table->irq_resource[irq]); irq++; break; case ACPI_RESOURCE_TYPE_DMA: - pnp_dbg("Encode dma"); - pnpacpi_encode_dma(resource, + pnpacpi_encode_dma(dev, resource, &res_table->dma_resource[dma]); dma++; break; case ACPI_RESOURCE_TYPE_IO: - pnp_dbg("Encode io"); - pnpacpi_encode_io(resource, + pnpacpi_encode_io(dev, resource, &res_table->port_resource[port]); port++; break; case ACPI_RESOURCE_TYPE_FIXED_IO: - pnp_dbg("Encode fixed io"); - pnpacpi_encode_fixed_io(resource, + pnpacpi_encode_fixed_io(dev, resource, &res_table-> port_resource[port]); port++; break; case ACPI_RESOURCE_TYPE_MEMORY24: - pnp_dbg("Encode mem24"); - pnpacpi_encode_mem24(resource, + pnpacpi_encode_mem24(dev, resource, &res_table->mem_resource[mem]); mem++; break; case ACPI_RESOURCE_TYPE_MEMORY32: - pnp_dbg("Encode mem32"); - pnpacpi_encode_mem32(resource, + pnpacpi_encode_mem32(dev, resource, &res_table->mem_resource[mem]); mem++; break; case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: - pnp_dbg("Encode fixed mem32"); - pnpacpi_encode_fixed_mem32(resource, + pnpacpi_encode_fixed_mem32(dev, resource, &res_table-> mem_resource[mem]); mem++; break; case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: - pnp_dbg("Encode ext irq"); - pnpacpi_encode_ext_irq(resource, + pnpacpi_encode_ext_irq(dev, resource, &res_table->irq_resource[irq]); irq++; break; diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c index 1711e7f29613..76d398531da6 100644 --- a/drivers/pnp/pnpbios/core.c +++ b/drivers/pnp/pnpbios/core.c @@ -212,6 +212,7 @@ static int pnpbios_get_resources(struct pnp_dev *dev) if (!pnpbios_is_dynamic(dev)) return -EPERM; + dev_dbg(&dev->dev, "get resources\n"); node = kzalloc(node_info.max_node_size, GFP_KERNEL); if (!node) return -1; @@ -234,6 +235,7 @@ static int pnpbios_set_resources(struct pnp_dev *dev) if (!pnpbios_is_dynamic(dev)) return -EPERM; + dev_dbg(&dev->dev, "set resources\n"); node = kzalloc(node_info.max_node_size, GFP_KERNEL); if (!node) return -1; diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c index 1b8f30ff192a..7428f62db4d2 100644 --- a/drivers/pnp/pnpbios/rsparser.c +++ b/drivers/pnp/pnpbios/rsparser.c @@ -143,6 +143,8 @@ static unsigned char *pnpbios_parse_allocated_resource_data(struct pnp_dev *dev, if (!p) return NULL; + dev_dbg(&dev->dev, "parse allocated resources\n"); + /* Blank the resource table values */ pnp_init_resource_table(&dev->res); @@ -390,6 +392,8 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, if (!p) return NULL; + dev_dbg(&dev->dev, "parse resource options\n"); + option_independent = option = pnp_register_independent_option(dev); if (!option) return NULL; @@ -574,7 +578,8 @@ len_err: * Allocated Resource Encoding */ -static void pnpbios_encode_mem(unsigned char *p, struct resource *res) +static void pnpbios_encode_mem(struct pnp_dev *dev, unsigned char *p, + struct resource *res) { unsigned long base = res->start; unsigned long len = res->end - res->start + 1; @@ -585,9 +590,13 @@ static void pnpbios_encode_mem(unsigned char *p, struct resource *res) p[7] = ((base >> 8) >> 8) & 0xff; p[10] = (len >> 8) & 0xff; p[11] = ((len >> 8) >> 8) & 0xff; + + dev_dbg(&dev->dev, " encode mem %#llx-%#llx\n", + (unsigned long long) res->start, (unsigned long long) res->end); } -static void pnpbios_encode_mem32(unsigned char *p, struct resource *res) +static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p, + struct resource *res) { unsigned long base = res->start; unsigned long len = res->end - res->start + 1; @@ -604,9 +613,13 @@ static void pnpbios_encode_mem32(unsigned char *p, struct resource *res) p[17] = (len >> 8) & 0xff; p[18] = (len >> 16) & 0xff; p[19] = (len >> 24) & 0xff; + + dev_dbg(&dev->dev, " encode mem32 %#llx-%#llx\n", + (unsigned long long) res->start, (unsigned long long) res->end); } -static void pnpbios_encode_fixed_mem32(unsigned char *p, struct resource *res) +static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p, + struct resource *res) { unsigned long base = res->start; unsigned long len = res->end - res->start + 1; @@ -619,26 +632,36 @@ static void pnpbios_encode_fixed_mem32(unsigned char *p, struct resource *res) p[9] = (len >> 8) & 0xff; p[10] = (len >> 16) & 0xff; p[11] = (len >> 24) & 0xff; + + dev_dbg(&dev->dev, " encode fixed_mem32 %#llx-%#llx\n", + (unsigned long long) res->start, (unsigned long long) res->end); } -static void pnpbios_encode_irq(unsigned char *p, struct resource *res) +static void pnpbios_encode_irq(struct pnp_dev *dev, unsigned char *p, + struct resource *res) { unsigned long map = 0; map = 1 << res->start; p[1] = map & 0xff; p[2] = (map >> 8) & 0xff; + + dev_dbg(&dev->dev, " encode irq %d\n", res->start); } -static void pnpbios_encode_dma(unsigned char *p, struct resource *res) +static void pnpbios_encode_dma(struct pnp_dev *dev, unsigned char *p, + struct resource *res) { unsigned long map = 0; map = 1 << res->start; p[1] = map & 0xff; + + dev_dbg(&dev->dev, " encode dma %d\n", res->start); } -static void pnpbios_encode_port(unsigned char *p, struct resource *res) +static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p, + struct resource *res) { unsigned long base = res->start; unsigned long len = res->end - res->start + 1; @@ -648,9 +671,13 @@ static void pnpbios_encode_port(unsigned char *p, struct resource *res) p[4] = base & 0xff; p[5] = (base >> 8) & 0xff; p[7] = len & 0xff; + + dev_dbg(&dev->dev, " encode io %#llx-%#llx\n", + (unsigned long long) res->start, (unsigned long long) res->end); } -static void pnpbios_encode_fixed_port(unsigned char *p, struct resource *res) +static void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p, + struct resource *res) { unsigned long base = res->start; unsigned long len = res->end - res->start + 1; @@ -658,6 +685,9 @@ static void pnpbios_encode_fixed_port(unsigned char *p, struct resource *res) p[1] = base & 0xff; p[2] = (base >> 8) & 0xff; p[3] = len & 0xff; + + dev_dbg(&dev->dev, " encode fixed_io %#llx-%#llx\n", + (unsigned long long) res->start, (unsigned long long) res->end); } static unsigned char *pnpbios_encode_allocated_resource_data(struct pnp_dev @@ -688,42 +718,42 @@ static unsigned char *pnpbios_encode_allocated_resource_data(struct pnp_dev case LARGE_TAG_MEM: if (len != 9) goto len_err; - pnpbios_encode_mem(p, &res->mem_resource[mem]); + pnpbios_encode_mem(dev, p, &res->mem_resource[mem]); mem++; break; case LARGE_TAG_MEM32: if (len != 17) goto len_err; - pnpbios_encode_mem32(p, &res->mem_resource[mem]); + pnpbios_encode_mem32(dev, p, &res->mem_resource[mem]); mem++; break; case LARGE_TAG_FIXEDMEM32: if (len != 9) goto len_err; - pnpbios_encode_fixed_mem32(p, &res->mem_resource[mem]); + pnpbios_encode_fixed_mem32(dev, p, &res->mem_resource[mem]); mem++; break; case SMALL_TAG_IRQ: if (len < 2 || len > 3) goto len_err; - pnpbios_encode_irq(p, &res->irq_resource[irq]); + pnpbios_encode_irq(dev, p, &res->irq_resource[irq]); irq++; break; case SMALL_TAG_DMA: if (len != 2) goto len_err; - pnpbios_encode_dma(p, &res->dma_resource[dma]); + pnpbios_encode_dma(dev, p, &res->dma_resource[dma]); dma++; break; case SMALL_TAG_PORT: if (len != 7) goto len_err; - pnpbios_encode_port(p, &res->port_resource[port]); + pnpbios_encode_port(dev, p, &res->port_resource[port]); port++; break; @@ -734,7 +764,7 @@ static unsigned char *pnpbios_encode_allocated_resource_data(struct pnp_dev case SMALL_TAG_FIXEDPORT: if (len != 3) goto len_err; - pnpbios_encode_fixed_port(p, &res->port_resource[port]); + pnpbios_encode_fixed_port(dev, p, &res->port_resource[port]); port++; break; -- cgit v1.2.2 From 81b5c75f0ed22a93c3da00650d0898eec56e1d62 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:08 -0600 Subject: PNP: add debug when assigning PNP resources This patch adds code to dump PNP resources before and after assigning resources and before writing them to the device. This is enabled by CONFIG_PNP_DEBUG=y. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/pnp/base.h | 2 ++ drivers/pnp/manager.c | 81 ++++++++++++++++++++++++++++++++++++++------------- drivers/pnp/support.c | 37 +++++++++++++++++++++++ 3 files changed, 100 insertions(+), 20 deletions(-) diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index a83cdcfee165..0c5cb1d58c6c 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h @@ -16,3 +16,5 @@ int pnp_check_port(struct pnp_dev * dev, int idx); int pnp_check_mem(struct pnp_dev * dev, int idx); int pnp_check_irq(struct pnp_dev * dev, int idx); int pnp_check_dma(struct pnp_dev * dev, int idx); + +void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc); diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index 6a1f0b0b24b3..945c6201719d 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c @@ -28,20 +28,25 @@ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) return 1; } - /* check if this resource has been manually set, if so skip */ - if (!(dev->res.port_resource[idx].flags & IORESOURCE_AUTO)) - return 1; - start = &dev->res.port_resource[idx].start; end = &dev->res.port_resource[idx].end; flags = &dev->res.port_resource[idx].flags; + /* check if this resource has been manually set, if so skip */ + if (!(dev->res.port_resource[idx].flags & IORESOURCE_AUTO)) { + dev_dbg(&dev->dev, " io %d already set to %#llx-%#llx " + "flags %#lx\n", idx, (unsigned long long) *start, + (unsigned long long) *end, *flags); + return 1; + } + /* set the initial values */ *flags |= rule->flags | IORESOURCE_IO; *flags &= ~IORESOURCE_UNSET; if (!rule->size) { *flags |= IORESOURCE_DISABLED; + dev_dbg(&dev->dev, " io %d disabled\n", idx); return 1; /* skip disabled resource requests */ } @@ -52,9 +57,13 @@ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) while (!pnp_check_port(dev, idx)) { *start += rule->align; *end = *start + rule->size - 1; - if (*start > rule->max || !rule->align) + if (*start > rule->max || !rule->align) { + dev_dbg(&dev->dev, " couldn't assign io %d\n", idx); return 0; + } } + dev_dbg(&dev->dev, " assign io %d %#llx-%#llx\n", idx, + (unsigned long long) *start, (unsigned long long) *end); return 1; } @@ -69,14 +78,18 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) return 1; } - /* check if this resource has been manually set, if so skip */ - if (!(dev->res.mem_resource[idx].flags & IORESOURCE_AUTO)) - return 1; - start = &dev->res.mem_resource[idx].start; end = &dev->res.mem_resource[idx].end; flags = &dev->res.mem_resource[idx].flags; + /* check if this resource has been manually set, if so skip */ + if (!(dev->res.mem_resource[idx].flags & IORESOURCE_AUTO)) { + dev_dbg(&dev->dev, " mem %d already set to %#llx-%#llx " + "flags %#lx\n", idx, (unsigned long long) *start, + (unsigned long long) *end, *flags); + return 1; + } + /* set the initial values */ *flags |= rule->flags | IORESOURCE_MEM; *flags &= ~IORESOURCE_UNSET; @@ -93,6 +106,7 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) if (!rule->size) { *flags |= IORESOURCE_DISABLED; + dev_dbg(&dev->dev, " mem %d disabled\n", idx); return 1; /* skip disabled resource requests */ } @@ -103,9 +117,13 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) while (!pnp_check_mem(dev, idx)) { *start += rule->align; *end = *start + rule->size - 1; - if (*start > rule->max || !rule->align) + if (*start > rule->max || !rule->align) { + dev_dbg(&dev->dev, " couldn't assign mem %d\n", idx); return 0; + } } + dev_dbg(&dev->dev, " assign mem %d %#llx-%#llx\n", idx, + (unsigned long long) *start, (unsigned long long) *end); return 1; } @@ -126,20 +144,24 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) return 1; } - /* check if this resource has been manually set, if so skip */ - if (!(dev->res.irq_resource[idx].flags & IORESOURCE_AUTO)) - return 1; - start = &dev->res.irq_resource[idx].start; end = &dev->res.irq_resource[idx].end; flags = &dev->res.irq_resource[idx].flags; + /* check if this resource has been manually set, if so skip */ + if (!(dev->res.irq_resource[idx].flags & IORESOURCE_AUTO)) { + dev_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n", + idx, (int) *start, *flags); + return 1; + } + /* set the initial values */ *flags |= rule->flags | IORESOURCE_IRQ; *flags &= ~IORESOURCE_UNSET; if (bitmap_empty(rule->map, PNP_IRQ_NR)) { *flags |= IORESOURCE_DISABLED; + dev_dbg(&dev->dev, " irq %d disabled\n", idx); return 1; /* skip disabled resource requests */ } @@ -147,15 +169,20 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) *start = find_next_bit(rule->map, PNP_IRQ_NR, 16); if (*start < PNP_IRQ_NR) { *end = *start; + dev_dbg(&dev->dev, " assign irq %d %d\n", idx, (int) *start); return 1; } for (i = 0; i < 16; i++) { if (test_bit(xtab[i], rule->map)) { *start = *end = xtab[i]; - if (pnp_check_irq(dev, idx)) + if (pnp_check_irq(dev, idx)) { + dev_dbg(&dev->dev, " assign irq %d %d\n", idx, + (int) *start); return 1; + } } } + dev_dbg(&dev->dev, " couldn't assign irq %d\n", idx); return 0; } @@ -175,14 +202,17 @@ static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) return; } - /* check if this resource has been manually set, if so skip */ - if (!(dev->res.dma_resource[idx].flags & IORESOURCE_AUTO)) - return; - start = &dev->res.dma_resource[idx].start; end = &dev->res.dma_resource[idx].end; flags = &dev->res.dma_resource[idx].flags; + /* check if this resource has been manually set, if so skip */ + if (!(dev->res.dma_resource[idx].flags & IORESOURCE_AUTO)) { + dev_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n", + idx, (int) *start, *flags); + return; + } + /* set the initial values */ *flags |= rule->flags | IORESOURCE_DMA; *flags &= ~IORESOURCE_UNSET; @@ -190,14 +220,18 @@ static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) for (i = 0; i < 8; i++) { if (rule->map & (1 << xtab[i])) { *start = *end = xtab[i]; - if (pnp_check_dma(dev, idx)) + if (pnp_check_dma(dev, idx)) { + dev_dbg(&dev->dev, " assign dma %d %d\n", idx, + (int) *start); return; + } } } #ifdef MAX_DMA_CHANNELS *start = *end = MAX_DMA_CHANNELS; #endif *flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; + dev_dbg(&dev->dev, " disable dma %d\n", idx); } /** @@ -298,9 +332,11 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum) if (!pnp_can_configure(dev)) return -ENODEV; + dbg_pnp_show_resources(dev, "before pnp_assign_resources"); mutex_lock(&pnp_res_mutex); pnp_clean_resource_table(&dev->res); /* start with a fresh slate */ if (dev->independent) { + dev_dbg(&dev->dev, "assigning independent options\n"); port = dev->independent->port; mem = dev->independent->mem; irq = dev->independent->irq; @@ -333,6 +369,8 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum) if (depnum) { struct pnp_option *dep; int i; + + dev_dbg(&dev->dev, "assigning dependent option %d\n", depnum); for (i = 1, dep = dev->dependent; i < depnum; i++, dep = dep->next) if (!dep) @@ -368,11 +406,13 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum) goto fail; mutex_unlock(&pnp_res_mutex); + dbg_pnp_show_resources(dev, "after pnp_assign_resources"); return 1; fail: pnp_clean_resource_table(&dev->res); mutex_unlock(&pnp_res_mutex); + dbg_pnp_show_resources(dev, "after pnp_assign_resources (failed)"); return 0; } @@ -473,6 +513,7 @@ int pnp_start_dev(struct pnp_dev *dev) return -EINVAL; } + dbg_pnp_show_resources(dev, "pnp_start_dev"); if (dev->protocol->set(dev) < 0) { dev_err(&dev->dev, "activation failed\n"); return -EIO; diff --git a/drivers/pnp/support.c b/drivers/pnp/support.c index e848b794e312..3aeb154e27d6 100644 --- a/drivers/pnp/support.c +++ b/drivers/pnp/support.c @@ -51,3 +51,40 @@ void pnp_eisa_id_to_string(u32 id, char *str) str[6] = hex_asc((id >> 0) & 0xf); str[7] = '\0'; } + +void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc) +{ +#ifdef DEBUG + struct resource *res; + int i; + + dev_dbg(&dev->dev, "current resources: %s\n", desc); + + for (i = 0; i < PNP_MAX_IRQ; i++) { + res = &dev->res.irq_resource[i]; + if (!(res->flags & IORESOURCE_UNSET)) + dev_dbg(&dev->dev, " irq %lld flags %#lx\n", + (unsigned long long) res->start, res->flags); + } + for (i = 0; i < PNP_MAX_DMA; i++) { + res = &dev->res.dma_resource[i]; + if (!(res->flags & IORESOURCE_UNSET)) + dev_dbg(&dev->dev, " dma %lld flags %#lx\n", + (unsigned long long) res->start, res->flags); + } + for (i = 0; i < PNP_MAX_PORT; i++) { + res = &dev->res.port_resource[i]; + if (!(res->flags & IORESOURCE_UNSET)) + dev_dbg(&dev->dev, " io %#llx-%#llx flags %#lx\n", + (unsigned long long) res->start, + (unsigned long long) res->end, res->flags); + } + for (i = 0; i < PNP_MAX_MEM; i++) { + res = &dev->res.mem_resource[i]; + if (!(res->flags & IORESOURCE_UNSET)) + dev_dbg(&dev->dev, " mem %#llx-%#llx flags %#lx\n", + (unsigned long long) res->start, + (unsigned long long) res->end, res->flags); + } +#endif +} -- cgit v1.2.2 From f44900020926b2cb06b87f0f52643d6285514fc3 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:09 -0600 Subject: PNP: add pnp_init_resources(struct pnp_dev *) interface Add pnp_init_resources(struct pnp_dev *) to replace pnp_init_resource_table(), which takes a pointer to the pnp_resource_table itself. Passing only the pnp_dev * reduces the possibility for error in the caller and removes the pnp_resource_table implementation detail from the interface. Even though pnp_init_resource_table() is exported, I did not export pnp_init_resources() because it is used only by the PNP core. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/interface.c | 6 +++--- drivers/pnp/isapnp/core.c | 4 ++-- drivers/pnp/manager.c | 5 +++++ drivers/pnp/pnpacpi/core.c | 2 +- drivers/pnp/pnpacpi/rsparser.c | 3 +-- drivers/pnp/pnpbios/core.c | 2 +- drivers/pnp/pnpbios/rsparser.c | 3 +-- include/linux/pnp.h | 2 ++ 8 files changed, 16 insertions(+), 11 deletions(-) diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c index e882896bdbd7..cdc3ecfde6ef 100644 --- a/drivers/pnp/interface.c +++ b/drivers/pnp/interface.c @@ -351,14 +351,14 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, if (!strnicmp(buf, "auto", 4)) { if (dev->active) goto done; - pnp_init_resource_table(&dev->res); + pnp_init_resources(dev); retval = pnp_auto_config_dev(dev); goto done; } if (!strnicmp(buf, "clear", 5)) { if (dev->active) goto done; - pnp_init_resource_table(&dev->res); + pnp_init_resources(dev); goto done; } if (!strnicmp(buf, "get", 3)) { @@ -373,7 +373,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, if (dev->active) goto done; buf += 3; - pnp_init_resource_table(&dev->res); + pnp_init_resources(dev); mutex_lock(&pnp_res_mutex); while (1) { while (isspace(*buf)) diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index 6740016437d9..6f1007548c93 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -424,7 +424,7 @@ static struct pnp_dev *__init isapnp_parse_device(struct pnp_card *card, dev->capabilities |= PNP_READ; dev->capabilities |= PNP_WRITE; dev->capabilities |= PNP_DISABLE; - pnp_init_resource_table(&dev->res); + pnp_init_resources(dev); return dev; } @@ -981,7 +981,7 @@ static int isapnp_get_resources(struct pnp_dev *dev) int ret; dev_dbg(&dev->dev, "get resources\n"); - pnp_init_resource_table(&dev->res); + pnp_init_resources(dev); isapnp_cfg_begin(dev->card->number, dev->number); ret = isapnp_read_resources(dev); isapnp_cfg_end(); diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index 945c6201719d..c9af87a8fb16 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c @@ -272,6 +272,11 @@ void pnp_init_resource_table(struct pnp_resource_table *table) } } +void pnp_init_resources(struct pnp_dev *dev) +{ + pnp_init_resource_table(&dev->res); +} + /** * pnp_clean_resources - clears resources that were not manually set * @res: the resources to clean diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 1ac894d2df5a..7e4512a60f58 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -212,7 +212,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device) /* clear out the damaged flags */ if (!dev->active) - pnp_init_resource_table(&dev->res); + pnp_init_resources(dev); pnp_add_device(dev); num++; diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index c5adf7631ac2..33dbf3644f2b 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -410,8 +410,7 @@ acpi_status pnpacpi_parse_allocated_resource(struct pnp_dev *dev) dev_dbg(&dev->dev, "parse allocated resources\n"); - /* Blank the resource table values */ - pnp_init_resource_table(&dev->res); + pnp_init_resources(dev); return acpi_walk_resources(handle, METHOD_NAME__CRS, pnpacpi_allocated_resource, dev); diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c index 76d398531da6..f5477ca85956 100644 --- a/drivers/pnp/pnpbios/core.c +++ b/drivers/pnp/pnpbios/core.c @@ -347,7 +347,7 @@ static int __init insert_device(struct pnp_bios_node *node) /* clear out the damaged flags */ if (!dev->active) - pnp_init_resource_table(&dev->res); + pnp_init_resources(dev); pnp_add_device(dev); pnpbios_interface_attach_device(node); diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c index 7428f62db4d2..e90a3d4360b2 100644 --- a/drivers/pnp/pnpbios/rsparser.c +++ b/drivers/pnp/pnpbios/rsparser.c @@ -145,8 +145,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(struct pnp_dev *dev, dev_dbg(&dev->dev, "parse allocated resources\n"); - /* Blank the resource table values */ - pnp_init_resource_table(&dev->res); + pnp_init_resources(dev); while ((char *)p < (char *)end) { diff --git a/include/linux/pnp.h b/include/linux/pnp.h index 8d7c9bc2fdbb..1737f071787a 100644 --- a/include/linux/pnp.h +++ b/include/linux/pnp.h @@ -391,6 +391,7 @@ int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option, int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option, struct pnp_mem *data); void pnp_init_resource_table(struct pnp_resource_table *table); +void pnp_init_resources(struct pnp_dev *dev); int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, int mode); int pnp_auto_config_dev(struct pnp_dev *dev); @@ -438,6 +439,7 @@ static inline int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_opti static inline int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option, struct pnp_port *data) { return -ENODEV; } static inline int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option, struct pnp_mem *data) { return -ENODEV; } static inline void pnp_init_resource_table(struct pnp_resource_table *table) { } +static inline void pnp_init_resources(struct pnp_dev *dev) { } static inline int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, int mode) { return -ENODEV; } static inline int pnp_auto_config_dev(struct pnp_dev *dev) { return -ENODEV; } static inline int pnp_validate_config(struct pnp_dev *dev) { return -ENODEV; } -- cgit v1.2.2 From 6969c7ed558cf5e9eff01734be0174a296938092 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:10 -0600 Subject: PNP: remove pnp_resource_table from internal pnp_clean_resource_table interface This changes pnp_clean_resource_table() to take a pnp_dev pointer rather than a pnp_resource_table pointer. This reduces the visibility of pnp_resource_table and removes an opportunity for error in the caller. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/manager.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index c9af87a8fb16..2251dd7da062 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c @@ -281,8 +281,9 @@ void pnp_init_resources(struct pnp_dev *dev) * pnp_clean_resources - clears resources that were not manually set * @res: the resources to clean */ -static void pnp_clean_resource_table(struct pnp_resource_table *res) +static void pnp_clean_resource_table(struct pnp_dev *dev) { + struct pnp_resource_table *res = &dev->res; int idx; for (idx = 0; idx < PNP_MAX_IRQ; idx++) { @@ -339,7 +340,7 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum) dbg_pnp_show_resources(dev, "before pnp_assign_resources"); mutex_lock(&pnp_res_mutex); - pnp_clean_resource_table(&dev->res); /* start with a fresh slate */ + pnp_clean_resource_table(dev); if (dev->independent) { dev_dbg(&dev->dev, "assigning independent options\n"); port = dev->independent->port; @@ -415,7 +416,7 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum) return 1; fail: - pnp_clean_resource_table(&dev->res); + pnp_clean_resource_table(dev); mutex_unlock(&pnp_res_mutex); dbg_pnp_show_resources(dev, "after pnp_assign_resources (failed)"); return 0; @@ -595,7 +596,7 @@ int pnp_disable_dev(struct pnp_dev *dev) /* release the resources so that other devices can use them */ mutex_lock(&pnp_res_mutex); - pnp_clean_resource_table(&dev->res); + pnp_clean_resource_table(dev); mutex_unlock(&pnp_res_mutex); return 0; -- cgit v1.2.2 From 2cd1393098073426256cb4543c897f8c340d0b93 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:11 -0600 Subject: PNP: remove unused interfaces using pnp_resource_table Rene Herman recently removed the only in-tree driver uses of: pnp_init_resource_table() pnp_manual_config_dev() pnp_resource_change() in this change: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=109c53f840e551d6e99ecfd8b0131a968332c89f These are no longer used in the PNP core either, so we can just remove them completely. It's possible that there are out-of-tree drivers that use these interfaces. They should be changed to either (1) use PNP quirks to work around broken hardware or firmware, or (2) use the sysfs interfaces to control resource usage from userspace. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/manager.c | 78 ++------------------------------------------------- include/linux/pnp.h | 8 ------ 2 files changed, 2 insertions(+), 84 deletions(-) diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index 2251dd7da062..d407c07b5b9d 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c @@ -238,8 +238,9 @@ static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) * pnp_init_resources - Resets a resource table to default values. * @table: pointer to the desired resource table */ -void pnp_init_resource_table(struct pnp_resource_table *table) +void pnp_init_resources(struct pnp_dev *dev) { + struct pnp_resource_table *table = &dev->res; int idx; for (idx = 0; idx < PNP_MAX_IRQ; idx++) { @@ -272,11 +273,6 @@ void pnp_init_resource_table(struct pnp_resource_table *table) } } -void pnp_init_resources(struct pnp_dev *dev) -{ - pnp_init_resource_table(&dev->res); -} - /** * pnp_clean_resources - clears resources that were not manually set * @res: the resources to clean @@ -422,59 +418,6 @@ fail: return 0; } -/** - * pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table - * @dev: pointer to the desired device - * @res: pointer to the new resource config - * @mode: 0 or PNP_CONFIG_FORCE - * - * This function can be used by drivers that want to manually set thier resources. - */ -int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, - int mode) -{ - int i; - struct pnp_resource_table *bak; - - if (!pnp_can_configure(dev)) - return -ENODEV; - bak = pnp_alloc(sizeof(struct pnp_resource_table)); - if (!bak) - return -ENOMEM; - *bak = dev->res; - - mutex_lock(&pnp_res_mutex); - dev->res = *res; - if (!(mode & PNP_CONFIG_FORCE)) { - for (i = 0; i < PNP_MAX_PORT; i++) { - if (!pnp_check_port(dev, i)) - goto fail; - } - for (i = 0; i < PNP_MAX_MEM; i++) { - if (!pnp_check_mem(dev, i)) - goto fail; - } - for (i = 0; i < PNP_MAX_IRQ; i++) { - if (!pnp_check_irq(dev, i)) - goto fail; - } - for (i = 0; i < PNP_MAX_DMA; i++) { - if (!pnp_check_dma(dev, i)) - goto fail; - } - } - mutex_unlock(&pnp_res_mutex); - - kfree(bak); - return 0; - -fail: - dev->res = *bak; - mutex_unlock(&pnp_res_mutex); - kfree(bak); - return -EINVAL; -} - /** * pnp_auto_config_dev - automatically assigns resources to a device * @dev: pointer to the desired device @@ -602,24 +545,7 @@ int pnp_disable_dev(struct pnp_dev *dev) return 0; } -/** - * pnp_resource_change - change one resource - * @resource: pointer to resource to be changed - * @start: start of region - * @size: size of region - */ -void pnp_resource_change(struct resource *resource, resource_size_t start, - resource_size_t size) -{ - resource->flags &= ~(IORESOURCE_AUTO | IORESOURCE_UNSET); - resource->start = start; - resource->end = start + size - 1; -} - -EXPORT_SYMBOL(pnp_manual_config_dev); EXPORT_SYMBOL(pnp_start_dev); EXPORT_SYMBOL(pnp_stop_dev); EXPORT_SYMBOL(pnp_activate_dev); EXPORT_SYMBOL(pnp_disable_dev); -EXPORT_SYMBOL(pnp_resource_change); -EXPORT_SYMBOL(pnp_init_resource_table); diff --git a/include/linux/pnp.h b/include/linux/pnp.h index 1737f071787a..e8187d9faf01 100644 --- a/include/linux/pnp.h +++ b/include/linux/pnp.h @@ -390,18 +390,13 @@ int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option, struct pnp_port *data); int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option, struct pnp_mem *data); -void pnp_init_resource_table(struct pnp_resource_table *table); void pnp_init_resources(struct pnp_dev *dev); -int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, - int mode); int pnp_auto_config_dev(struct pnp_dev *dev); int pnp_validate_config(struct pnp_dev *dev); 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); -void pnp_resource_change(struct resource *resource, resource_size_t start, - resource_size_t size); /* protocol helpers */ int pnp_is_active(struct pnp_dev *dev); @@ -438,16 +433,13 @@ static inline int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_opti static inline int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option, struct pnp_dma *data) { return -ENODEV; } static inline int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option, struct pnp_port *data) { return -ENODEV; } static inline int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option, struct pnp_mem *data) { return -ENODEV; } -static inline void pnp_init_resource_table(struct pnp_resource_table *table) { } static inline void pnp_init_resources(struct pnp_dev *dev) { } -static inline int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, int mode) { return -ENODEV; } static inline int pnp_auto_config_dev(struct pnp_dev *dev) { return -ENODEV; } static inline int pnp_validate_config(struct pnp_dev *dev) { return -ENODEV; } 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 void pnp_resource_change(struct resource *resource, resource_size_t start, resource_size_t size) { } /* protocol helpers */ static inline int pnp_is_active(struct pnp_dev *dev) { return 0; } -- cgit v1.2.2 From af11cb2d521f9d7e10c565bafe8f2358772baa65 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:12 -0600 Subject: PNP: use dev_printk when possible Use dev_printk() when possible for more informative error messages. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/isapnp/core.c | 37 +++++++++++++++++-------------------- drivers/pnp/pnpacpi/rsparser.c | 20 ++++++++++++-------- drivers/pnp/pnpbios/rsparser.c | 36 ++++++++++++++---------------------- 3 files changed, 43 insertions(+), 50 deletions(-) diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index 6f1007548c93..990d8cd6295c 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -737,9 +737,8 @@ static int __init isapnp_create_device(struct pnp_card *card, isapnp_skip_bytes(size); return 1; default: - printk(KERN_ERR - "isapnp: unexpected or unknown tag type 0x%x for logical device %i (device %i), ignored\n", - type, dev->number, card->number); + dev_err(&dev->dev, "unknown tag %#x (card %i), " + "ignored\n", type, card->number); } __skip: if (size > 0) @@ -792,9 +791,8 @@ static void __init isapnp_parse_resource_map(struct pnp_card *card) isapnp_skip_bytes(size); return; default: - printk(KERN_ERR - "isapnp: unexpected or unknown tag type 0x%x for device %i, ignored\n", - type, card->number); + dev_err(&card->dev, "unknown tag %#x, ignored\n", + type); } __skip: if (size > 0) @@ -841,13 +839,6 @@ static int __init isapnp_build_device_list(void) isapnp_wake(csn); isapnp_peek(header, 9); checksum = isapnp_checksum(header); -#if 0 - printk(KERN_DEBUG - "vendor: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", - header[0], header[1], header[2], header[3], header[4], - header[5], header[6], header[7], header[8]); - printk(KERN_DEBUG "checksum = 0x%x\n", checksum); -#endif eisa_id = header[0] | header[1] << 8 | header[2] << 16 | header[3] << 24; pnp_eisa_id_to_string(eisa_id, id); @@ -855,6 +846,13 @@ static int __init isapnp_build_device_list(void) if (!card) continue; +#if 0 + dev_info(&card->dev, + "vendor: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + header[0], header[1], header[2], header[3], header[4], + header[5], header[6], header[7], header[8]); + dev_info(&card->dev, "checksum = %#x\n", checksum); +#endif INIT_LIST_HEAD(&card->devices); card->serial = (header[7] << 24) | (header[6] << 16) | (header[5] << 8) | @@ -862,9 +860,8 @@ static int __init isapnp_build_device_list(void) isapnp_checksum_value = 0x00; isapnp_parse_resource_map(card); if (isapnp_checksum_value != 0x00) - printk(KERN_ERR - "isapnp: checksum for device %i is not valid (0x%x)\n", - csn, isapnp_checksum_value); + dev_err(&card->dev, "invalid checksum %#x\n", + isapnp_checksum_value); card->checksum = isapnp_checksum_value; pnp_add_card(card); @@ -1134,13 +1131,13 @@ static int __init isapnp_init(void) protocol_for_each_card(&isapnp_protocol, card) { cards++; if (isapnp_verbose) { - printk(KERN_INFO "isapnp: Card '%s'\n", - card->name[0] ? card->name : "Unknown"); + dev_info(&card->dev, "card '%s'\n", + card->name[0] ? card->name : "unknown"); if (isapnp_verbose < 2) continue; card_for_each_dev(card, dev) { - printk(KERN_INFO "isapnp: Device '%s'\n", - dev->name[0] ? dev->name : "Unknown"); + dev_info(&card->dev, "device '%s'\n", + dev->name[0] ? dev->name : "unknown"); } } } diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 33dbf3644f2b..bd41e4d4270c 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -110,7 +110,7 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev, p = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; if (triggering != t || polarity != p) { - pnp_warn("IRQ %d override to %s, %s", + dev_warn(&dev->dev, "IRQ %d override to %s, %s\n", gsi, t ? "edge":"level", p ? "low":"high"); triggering = t; polarity = p; @@ -263,7 +263,7 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev, status = acpi_resource_to_address64(res, p); if (!ACPI_SUCCESS(status)) { - pnp_warn("PnPACPI: failed to convert resource type %d", + dev_warn(&dev->dev, "failed to convert resource type %d\n", res->type); return; } @@ -397,7 +397,8 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, break; default: - pnp_warn("PnPACPI: unknown resource type %d", res->type); + dev_warn(&dev->dev, "unknown resource type %d in _CRS\n", + res->type); return AE_ERROR; } @@ -674,7 +675,8 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, case ACPI_RESOURCE_TYPE_END_DEPENDENT: /*only one EndDependentFn is allowed */ if (!parse_data->option_independent) { - pnp_warn("PnPACPI: more than one EndDependentFn"); + dev_warn(&dev->dev, "more than one EndDependentFn " + "in _PRS\n"); return AE_ERROR; } parse_data->option = parse_data->option_independent; @@ -726,7 +728,8 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, break; default: - pnp_warn("PnPACPI: unknown resource type %d", res->type); + dev_warn(&dev->dev, "unknown resource type %d in _PRS\n", + res->type); return AE_ERROR; } @@ -808,7 +811,7 @@ int pnpacpi_build_resource_template(struct pnp_dev *dev, status = acpi_walk_resources(handle, METHOD_NAME__CRS, pnpacpi_count_resources, &res_cnt); if (ACPI_FAILURE(status)) { - pnp_err("Evaluate _CRS failed"); + dev_err(&dev->dev, "can't evaluate _CRS\n"); return -EINVAL; } if (!res_cnt) @@ -823,7 +826,7 @@ int pnpacpi_build_resource_template(struct pnp_dev *dev, pnpacpi_type_resources, &resource); if (ACPI_FAILURE(status)) { kfree(buffer->pointer); - pnp_err("Evaluate _CRS failed"); + dev_err(&dev->dev, "can't evaluate _CRS\n"); return -EINVAL; } /* resource will pointer the end resource now */ @@ -1074,7 +1077,8 @@ int pnpacpi_encode_resources(struct pnp_dev *dev, struct acpi_buffer *buffer) case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: default: /* other type */ - pnp_warn("unknown resource type %d", resource->type); + dev_warn(&dev->dev, "can't encode unknown resource " + "type %d\n", resource->type); return -EINVAL; } resource++; diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c index e90a3d4360b2..4390e3b41df0 100644 --- a/drivers/pnp/pnpbios/rsparser.c +++ b/drivers/pnp/pnpbios/rsparser.c @@ -241,9 +241,8 @@ static unsigned char *pnpbios_parse_allocated_resource_data(struct pnp_dev *dev, default: /* an unkown tag */ len_err: - printk(KERN_ERR - "PnPBIOS: Unknown tag '0x%x', length '%d'.\n", - tag, len); + dev_err(&dev->dev, "unknown tag %#x length %d\n", + tag, len); break; } @@ -254,8 +253,7 @@ len_err: p += len + 1; } - printk(KERN_ERR - "PnPBIOS: Resource structure does not contain an end tag.\n"); + dev_err(&dev->dev, "no end tag in resource structure\n"); return NULL; } @@ -471,8 +469,8 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, if (len != 0) goto len_err; if (option_independent == option) - printk(KERN_WARNING - "PnPBIOS: Missing SMALL_TAG_STARTDEP tag\n"); + dev_warn(&dev->dev, "missing " + "SMALL_TAG_STARTDEP tag\n"); option = option_independent; dev_dbg(&dev->dev, "end dependent options\n"); break; @@ -482,9 +480,8 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, default: /* an unkown tag */ len_err: - printk(KERN_ERR - "PnPBIOS: Unknown tag '0x%x', length '%d'.\n", - tag, len); + dev_err(&dev->dev, "unknown tag %#x length %d\n", + tag, len); break; } @@ -495,8 +492,7 @@ len_err: p += len + 1; } - printk(KERN_ERR - "PnPBIOS: Resource structure does not contain an end tag.\n"); + dev_err(&dev->dev, "no end tag in resource structure\n"); return NULL; } @@ -554,9 +550,8 @@ static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p, default: /* an unkown tag */ len_err: - printk(KERN_ERR - "PnPBIOS: Unknown tag '0x%x', length '%d'.\n", - tag, len); + dev_err(&dev->dev, "unknown tag %#x length %d\n", + tag, len); break; } @@ -567,8 +562,7 @@ len_err: p += len + 1; } - printk(KERN_ERR - "PnPBIOS: Resource structure does not contain an end tag.\n"); + dev_err(&dev->dev, "no end tag in resource structure\n"); return NULL; } @@ -774,9 +768,8 @@ static unsigned char *pnpbios_encode_allocated_resource_data(struct pnp_dev default: /* an unkown tag */ len_err: - printk(KERN_ERR - "PnPBIOS: Unknown tag '0x%x', length '%d'.\n", - tag, len); + dev_err(&dev->dev, "unknown tag %#x length %d\n", + tag, len); break; } @@ -787,8 +780,7 @@ len_err: p += len + 1; } - printk(KERN_ERR - "PnPBIOS: Resource structure does not contain an end tag.\n"); + dev_err(&dev->dev, "no end tag in resource structure\n"); return NULL; } -- cgit v1.2.2 From d948a8daa059cf5b3e7f002e7b92acf00fc70c49 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:13 -0600 Subject: PNP: factor pnp_init_resource_table() and pnp_clean_resource_table() Move the common part of pnp_init_resource_table() and pnp_clean_resource_table() into a new pnp_init_resource(). This reduces a little code duplication and will be useful later to initialize an individual resource. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/pnp/base.h | 2 ++ drivers/pnp/manager.c | 98 +++++++++++++++++++++++++++------------------------ 2 files changed, 54 insertions(+), 46 deletions(-) diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index 0c5cb1d58c6c..eb43fc6bff11 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h @@ -18,3 +18,5 @@ int pnp_check_irq(struct pnp_dev * dev, int idx); int pnp_check_dma(struct pnp_dev * dev, int idx); void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc); + +void pnp_init_resource(struct resource *res); diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index d407c07b5b9d..8267efd679a1 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c @@ -234,42 +234,52 @@ static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) dev_dbg(&dev->dev, " disable dma %d\n", idx); } +void pnp_init_resource(struct resource *res) +{ + unsigned long type; + + type = res->flags & (IORESOURCE_IO | IORESOURCE_MEM | + IORESOURCE_IRQ | IORESOURCE_DMA); + + res->name = NULL; + res->flags = type | IORESOURCE_AUTO | IORESOURCE_UNSET; + if (type == IORESOURCE_IRQ || type == IORESOURCE_DMA) { + res->start = -1; + res->end = -1; + } else { + res->start = 0; + res->end = 0; + } +} + /** * pnp_init_resources - Resets a resource table to default values. * @table: pointer to the desired resource table */ void pnp_init_resources(struct pnp_dev *dev) { - struct pnp_resource_table *table = &dev->res; + struct resource *res; int idx; for (idx = 0; idx < PNP_MAX_IRQ; idx++) { - table->irq_resource[idx].name = NULL; - table->irq_resource[idx].start = -1; - table->irq_resource[idx].end = -1; - table->irq_resource[idx].flags = - IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET; + res = &dev->res.irq_resource[idx]; + res->flags = IORESOURCE_IRQ; + pnp_init_resource(res); } for (idx = 0; idx < PNP_MAX_DMA; idx++) { - table->dma_resource[idx].name = NULL; - table->dma_resource[idx].start = -1; - table->dma_resource[idx].end = -1; - table->dma_resource[idx].flags = - IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET; + res = &dev->res.dma_resource[idx]; + res->flags = IORESOURCE_DMA; + pnp_init_resource(res); } for (idx = 0; idx < PNP_MAX_PORT; idx++) { - table->port_resource[idx].name = NULL; - table->port_resource[idx].start = 0; - table->port_resource[idx].end = 0; - table->port_resource[idx].flags = - IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET; + res = &dev->res.port_resource[idx]; + res->flags = IORESOURCE_IO; + pnp_init_resource(res); } for (idx = 0; idx < PNP_MAX_MEM; idx++) { - table->mem_resource[idx].name = NULL; - table->mem_resource[idx].start = 0; - table->mem_resource[idx].end = 0; - table->mem_resource[idx].flags = - IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET; + res = &dev->res.mem_resource[idx]; + res->flags = IORESOURCE_MEM; + pnp_init_resource(res); } } @@ -279,40 +289,36 @@ void pnp_init_resources(struct pnp_dev *dev) */ static void pnp_clean_resource_table(struct pnp_dev *dev) { - struct pnp_resource_table *res = &dev->res; + struct resource *res; int idx; for (idx = 0; idx < PNP_MAX_IRQ; idx++) { - if (!(res->irq_resource[idx].flags & IORESOURCE_AUTO)) - continue; - res->irq_resource[idx].start = -1; - res->irq_resource[idx].end = -1; - res->irq_resource[idx].flags = - IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET; + res = &dev->res.irq_resource[idx]; + if (res->flags & IORESOURCE_AUTO) { + res->flags = IORESOURCE_IRQ; + pnp_init_resource(res); + } } for (idx = 0; idx < PNP_MAX_DMA; idx++) { - if (!(res->dma_resource[idx].flags & IORESOURCE_AUTO)) - continue; - res->dma_resource[idx].start = -1; - res->dma_resource[idx].end = -1; - res->dma_resource[idx].flags = - IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET; + res = &dev->res.dma_resource[idx]; + if (res->flags & IORESOURCE_AUTO) { + res->flags = IORESOURCE_DMA; + pnp_init_resource(res); + } } for (idx = 0; idx < PNP_MAX_PORT; idx++) { - if (!(res->port_resource[idx].flags & IORESOURCE_AUTO)) - continue; - res->port_resource[idx].start = 0; - res->port_resource[idx].end = 0; - res->port_resource[idx].flags = - IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET; + res = &dev->res.port_resource[idx]; + if (res->flags & IORESOURCE_AUTO) { + res->flags = IORESOURCE_IO; + pnp_init_resource(res); + } } for (idx = 0; idx < PNP_MAX_MEM; idx++) { - if (!(res->mem_resource[idx].flags & IORESOURCE_AUTO)) - continue; - res->mem_resource[idx].start = 0; - res->mem_resource[idx].end = 0; - res->mem_resource[idx].flags = - IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET; + res = &dev->res.mem_resource[idx]; + if (res->flags & IORESOURCE_AUTO) { + res->flags = IORESOURCE_MEM; + pnp_init_resource(res); + } } } -- cgit v1.2.2 From b90eca0a61ebd010036242e29610bc6a909e3f19 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:14 -0600 Subject: PNP: add pnp_get_resource() interface This adds a pnp_get_resource() that works the same way as platform_get_resource(). This will enable us to consolidate many pnp_resource_table references in one place, which will make it easier to make the table dynamic. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/resource.c | 27 +++++++++++++++++++++++++++ include/linux/pnp.h | 1 + 2 files changed, 28 insertions(+) diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index eee6d8eddcb4..ef8835ec5778 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -487,6 +487,33 @@ int pnp_check_dma(struct pnp_dev *dev, int idx) #endif } +struct resource *pnp_get_resource(struct pnp_dev *dev, + unsigned int type, unsigned int num) +{ + struct pnp_resource_table *res = &dev->res; + + switch (type) { + case IORESOURCE_IO: + if (num >= PNP_MAX_PORT) + return NULL; + return &res->port_resource[num]; + case IORESOURCE_MEM: + if (num >= PNP_MAX_MEM) + return NULL; + return &res->mem_resource[num]; + case IORESOURCE_IRQ: + if (num >= PNP_MAX_IRQ) + return NULL; + return &res->irq_resource[num]; + case IORESOURCE_DMA: + if (num >= PNP_MAX_DMA) + return NULL; + return &res->dma_resource[num]; + } + return NULL; +} +EXPORT_SYMBOL(pnp_get_resource); + /* format is: pnp_reserve_irq=irq1[,irq2] .... */ static int __init pnp_setup_reserve_irq(char *str) { diff --git a/include/linux/pnp.h b/include/linux/pnp.h index e8187d9faf01..b5fd03854fa4 100644 --- a/include/linux/pnp.h +++ b/include/linux/pnp.h @@ -25,6 +25,7 @@ struct pnp_dev; /* * Resource Management */ +struct resource *pnp_get_resource(struct pnp_dev *, unsigned int, unsigned int); /* Use these instead of directly reading pnp_dev to get resource information */ #define pnp_port_start(dev,bar) ((dev)->res.port_resource[(bar)].start) -- cgit v1.2.2 From 53052feb6ddd05cb2b5c6e89fb489bf83bbb6803 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:15 -0600 Subject: PNP: remove pnp_mem_flags() as an lvalue A future change will change pnp_mem_flags() from a "#define that simplifies to an lvalue" to "an inline function that returns the flags value." Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/quirks.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c index e4daf4635c48..c47dd252f449 100644 --- a/drivers/pnp/quirks.c +++ b/drivers/pnp/quirks.c @@ -117,6 +117,7 @@ static void quirk_sb16audio_resources(struct pnp_dev *dev) static void quirk_system_pci_resources(struct pnp_dev *dev) { struct pci_dev *pdev = NULL; + struct resource *res; resource_size_t pnp_start, pnp_end, pci_start, pci_end; int i, j; @@ -176,7 +177,8 @@ static void quirk_system_pci_resources(struct pnp_dev *dev) pci_name(pdev), i, (unsigned long long) pci_start, (unsigned long long) pci_end); - pnp_mem_flags(dev, j) = 0; + res = pnp_get_resource(dev, IORESOURCE_MEM, j); + res->flags = 0; } } } -- cgit v1.2.2 From 13575e81bb38fc797a5513ad1bd8e6fda17439b8 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:16 -0600 Subject: PNP: convert resource accessors to use pnp_get_resource(), not pnp_resource_table This removes more direct references to pnp_resource_table. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- include/linux/pnp.h | 145 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 105 insertions(+), 40 deletions(-) diff --git a/include/linux/pnp.h b/include/linux/pnp.h index b5fd03854fa4..1640562f3ebc 100644 --- a/include/linux/pnp.h +++ b/include/linux/pnp.h @@ -27,46 +27,111 @@ struct pnp_dev; */ struct resource *pnp_get_resource(struct pnp_dev *, unsigned int, unsigned int); -/* Use these instead of directly reading pnp_dev to get resource information */ -#define pnp_port_start(dev,bar) ((dev)->res.port_resource[(bar)].start) -#define pnp_port_end(dev,bar) ((dev)->res.port_resource[(bar)].end) -#define pnp_port_flags(dev,bar) ((dev)->res.port_resource[(bar)].flags) -#define pnp_port_valid(dev,bar) \ - ((pnp_port_flags((dev),(bar)) & (IORESOURCE_IO | IORESOURCE_UNSET)) \ - == IORESOURCE_IO) -#define pnp_port_len(dev,bar) \ - ((pnp_port_start((dev),(bar)) == 0 && \ - pnp_port_end((dev),(bar)) == \ - pnp_port_start((dev),(bar))) ? 0 : \ - \ - (pnp_port_end((dev),(bar)) - \ - pnp_port_start((dev),(bar)) + 1)) - -#define pnp_mem_start(dev,bar) ((dev)->res.mem_resource[(bar)].start) -#define pnp_mem_end(dev,bar) ((dev)->res.mem_resource[(bar)].end) -#define pnp_mem_flags(dev,bar) ((dev)->res.mem_resource[(bar)].flags) -#define pnp_mem_valid(dev,bar) \ - ((pnp_mem_flags((dev),(bar)) & (IORESOURCE_MEM | IORESOURCE_UNSET)) \ - == IORESOURCE_MEM) -#define pnp_mem_len(dev,bar) \ - ((pnp_mem_start((dev),(bar)) == 0 && \ - pnp_mem_end((dev),(bar)) == \ - pnp_mem_start((dev),(bar))) ? 0 : \ - \ - (pnp_mem_end((dev),(bar)) - \ - pnp_mem_start((dev),(bar)) + 1)) - -#define pnp_irq(dev,bar) ((dev)->res.irq_resource[(bar)].start) -#define pnp_irq_flags(dev,bar) ((dev)->res.irq_resource[(bar)].flags) -#define pnp_irq_valid(dev,bar) \ - ((pnp_irq_flags((dev),(bar)) & (IORESOURCE_IRQ | IORESOURCE_UNSET)) \ - == IORESOURCE_IRQ) - -#define pnp_dma(dev,bar) ((dev)->res.dma_resource[(bar)].start) -#define pnp_dma_flags(dev,bar) ((dev)->res.dma_resource[(bar)].flags) -#define pnp_dma_valid(dev,bar) \ - ((pnp_dma_flags((dev),(bar)) & (IORESOURCE_DMA | IORESOURCE_UNSET)) \ - == IORESOURCE_DMA) +static inline int pnp_resource_valid(struct resource *res) +{ + if (res && !(res->flags & IORESOURCE_UNSET)) + return 1; + return 0; +} + +static inline resource_size_t pnp_resource_len(struct resource *res) +{ + if (res->start == 0 && res->end == 0) + return 0; + return res->end - res->start + 1; +} + + +static inline resource_size_t pnp_port_start(struct pnp_dev *dev, + unsigned int bar) +{ + return pnp_get_resource(dev, IORESOURCE_IO, bar)->start; +} + +static inline resource_size_t pnp_port_end(struct pnp_dev *dev, + unsigned int bar) +{ + return pnp_get_resource(dev, IORESOURCE_IO, bar)->end; +} + +static inline unsigned long pnp_port_flags(struct pnp_dev *dev, + unsigned int bar) +{ + return pnp_get_resource(dev, IORESOURCE_IO, bar)->flags; +} + +static inline int pnp_port_valid(struct pnp_dev *dev, unsigned int bar) +{ + return pnp_resource_valid(pnp_get_resource(dev, IORESOURCE_IO, bar)); +} + +static inline resource_size_t pnp_port_len(struct pnp_dev *dev, + unsigned int bar) +{ + return pnp_resource_len(pnp_get_resource(dev, IORESOURCE_IO, bar)); +} + + +static inline resource_size_t pnp_mem_start(struct pnp_dev *dev, + unsigned int bar) +{ + return pnp_get_resource(dev, IORESOURCE_MEM, bar)->start; +} + +static inline resource_size_t pnp_mem_end(struct pnp_dev *dev, + unsigned int bar) +{ + return pnp_get_resource(dev, IORESOURCE_MEM, bar)->end; +} + +static inline unsigned long pnp_mem_flags(struct pnp_dev *dev, unsigned int bar) +{ + return pnp_get_resource(dev, IORESOURCE_MEM, bar)->flags; +} + +static inline int pnp_mem_valid(struct pnp_dev *dev, unsigned int bar) +{ + return pnp_resource_valid(pnp_get_resource(dev, IORESOURCE_MEM, bar)); +} + +static inline resource_size_t pnp_mem_len(struct pnp_dev *dev, + unsigned int bar) +{ + return pnp_resource_len(pnp_get_resource(dev, IORESOURCE_MEM, bar)); +} + + +static inline resource_size_t pnp_irq(struct pnp_dev *dev, unsigned int bar) +{ + return pnp_get_resource(dev, IORESOURCE_IRQ, bar)->start; +} + +static inline unsigned long pnp_irq_flags(struct pnp_dev *dev, unsigned int bar) +{ + return pnp_get_resource(dev, IORESOURCE_IRQ, bar)->flags; +} + +static inline int pnp_irq_valid(struct pnp_dev *dev, unsigned int bar) +{ + return pnp_resource_valid(pnp_get_resource(dev, IORESOURCE_IRQ, bar)); +} + + +static inline resource_size_t pnp_dma(struct pnp_dev *dev, unsigned int bar) +{ + return pnp_get_resource(dev, IORESOURCE_DMA, bar)->start; +} + +static inline unsigned long pnp_dma_flags(struct pnp_dev *dev, unsigned int bar) +{ + return pnp_get_resource(dev, IORESOURCE_DMA, bar)->flags; +} + +static inline int pnp_dma_valid(struct pnp_dev *dev, unsigned int bar) +{ + return pnp_resource_valid(pnp_get_resource(dev, IORESOURCE_DMA, bar)); +} + #define PNP_PORT_FLAG_16BITADDR (1<<0) #define PNP_PORT_FLAG_FIXED (1<<1) -- cgit v1.2.2 From ecfa935a2f7ef89543608f3ca05340c158c9a236 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:17 -0600 Subject: PNP: use conventional "i" for loop indices Cosmetic only: just use "i" instead of "tmp". Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/resource.c | 92 +++++++++++++++++++++++++------------------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index ef8835ec5778..15995f9f8b7c 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -241,7 +241,7 @@ void pnp_free_option(struct pnp_option *option) int pnp_check_port(struct pnp_dev *dev, int idx) { - int tmp; + int i; struct pnp_dev *tdev; resource_size_t *port, *end, *tport, *tend; @@ -260,18 +260,18 @@ int pnp_check_port(struct pnp_dev *dev, int idx) } /* check if the resource is reserved */ - for (tmp = 0; tmp < 8; tmp++) { - int rport = pnp_reserve_io[tmp << 1]; - int rend = pnp_reserve_io[(tmp << 1) + 1] + rport - 1; + for (i = 0; i < 8; i++) { + int rport = pnp_reserve_io[i << 1]; + int rend = pnp_reserve_io[(i << 1) + 1] + rport - 1; if (ranged_conflict(port, end, &rport, &rend)) return 0; } /* check for internal conflicts */ - for (tmp = 0; tmp < PNP_MAX_PORT && tmp != idx; tmp++) { - if (dev->res.port_resource[tmp].flags & IORESOURCE_IO) { - tport = &dev->res.port_resource[tmp].start; - tend = &dev->res.port_resource[tmp].end; + for (i = 0; i < PNP_MAX_PORT && i != idx; i++) { + if (dev->res.port_resource[i].flags & IORESOURCE_IO) { + tport = &dev->res.port_resource[i].start; + tend = &dev->res.port_resource[i].end; if (ranged_conflict(port, end, tport, tend)) return 0; } @@ -281,13 +281,13 @@ int pnp_check_port(struct pnp_dev *dev, int idx) pnp_for_each_dev(tdev) { if (tdev == dev) continue; - for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) { - if (tdev->res.port_resource[tmp].flags & IORESOURCE_IO) { + for (i = 0; i < PNP_MAX_PORT; i++) { + if (tdev->res.port_resource[i].flags & IORESOURCE_IO) { if (cannot_compare - (tdev->res.port_resource[tmp].flags)) + (tdev->res.port_resource[i].flags)) continue; - tport = &tdev->res.port_resource[tmp].start; - tend = &tdev->res.port_resource[tmp].end; + tport = &tdev->res.port_resource[i].start; + tend = &tdev->res.port_resource[i].end; if (ranged_conflict(port, end, tport, tend)) return 0; } @@ -299,7 +299,7 @@ int pnp_check_port(struct pnp_dev *dev, int idx) int pnp_check_mem(struct pnp_dev *dev, int idx) { - int tmp; + int i; struct pnp_dev *tdev; resource_size_t *addr, *end, *taddr, *tend; @@ -318,18 +318,18 @@ int pnp_check_mem(struct pnp_dev *dev, int idx) } /* check if the resource is reserved */ - for (tmp = 0; tmp < 8; tmp++) { - int raddr = pnp_reserve_mem[tmp << 1]; - int rend = pnp_reserve_mem[(tmp << 1) + 1] + raddr - 1; + for (i = 0; i < 8; i++) { + int raddr = pnp_reserve_mem[i << 1]; + int rend = pnp_reserve_mem[(i << 1) + 1] + raddr - 1; if (ranged_conflict(addr, end, &raddr, &rend)) return 0; } /* check for internal conflicts */ - for (tmp = 0; tmp < PNP_MAX_MEM && tmp != idx; tmp++) { - if (dev->res.mem_resource[tmp].flags & IORESOURCE_MEM) { - taddr = &dev->res.mem_resource[tmp].start; - tend = &dev->res.mem_resource[tmp].end; + for (i = 0; i < PNP_MAX_MEM && i != idx; i++) { + if (dev->res.mem_resource[i].flags & IORESOURCE_MEM) { + taddr = &dev->res.mem_resource[i].start; + tend = &dev->res.mem_resource[i].end; if (ranged_conflict(addr, end, taddr, tend)) return 0; } @@ -339,13 +339,13 @@ int pnp_check_mem(struct pnp_dev *dev, int idx) pnp_for_each_dev(tdev) { if (tdev == dev) continue; - for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) { - if (tdev->res.mem_resource[tmp].flags & IORESOURCE_MEM) { + for (i = 0; i < PNP_MAX_MEM; i++) { + if (tdev->res.mem_resource[i].flags & IORESOURCE_MEM) { if (cannot_compare - (tdev->res.mem_resource[tmp].flags)) + (tdev->res.mem_resource[i].flags)) continue; - taddr = &tdev->res.mem_resource[tmp].start; - tend = &tdev->res.mem_resource[tmp].end; + taddr = &tdev->res.mem_resource[i].start; + tend = &tdev->res.mem_resource[i].end; if (ranged_conflict(addr, end, taddr, tend)) return 0; } @@ -362,7 +362,7 @@ static irqreturn_t pnp_test_handler(int irq, void *dev_id) int pnp_check_irq(struct pnp_dev *dev, int idx) { - int tmp; + int i; struct pnp_dev *tdev; resource_size_t *irq = &dev->res.irq_resource[idx].start; @@ -375,15 +375,15 @@ int pnp_check_irq(struct pnp_dev *dev, int idx) return 0; /* check if the resource is reserved */ - for (tmp = 0; tmp < 16; tmp++) { - if (pnp_reserve_irq[tmp] == *irq) + for (i = 0; i < 16; i++) { + if (pnp_reserve_irq[i] == *irq) return 0; } /* check for internal conflicts */ - for (tmp = 0; tmp < PNP_MAX_IRQ && tmp != idx; tmp++) { - if (dev->res.irq_resource[tmp].flags & IORESOURCE_IRQ) { - if (dev->res.irq_resource[tmp].start == *irq) + for (i = 0; i < PNP_MAX_IRQ && i != idx; i++) { + if (dev->res.irq_resource[i].flags & IORESOURCE_IRQ) { + if (dev->res.irq_resource[i].start == *irq) return 0; } } @@ -414,12 +414,12 @@ int pnp_check_irq(struct pnp_dev *dev, int idx) pnp_for_each_dev(tdev) { if (tdev == dev) continue; - for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) { - if (tdev->res.irq_resource[tmp].flags & IORESOURCE_IRQ) { + for (i = 0; i < PNP_MAX_IRQ; i++) { + if (tdev->res.irq_resource[i].flags & IORESOURCE_IRQ) { if (cannot_compare - (tdev->res.irq_resource[tmp].flags)) + (tdev->res.irq_resource[i].flags)) continue; - if ((tdev->res.irq_resource[tmp].start == *irq)) + if ((tdev->res.irq_resource[i].start == *irq)) return 0; } } @@ -431,7 +431,7 @@ int pnp_check_irq(struct pnp_dev *dev, int idx) int pnp_check_dma(struct pnp_dev *dev, int idx) { #ifndef CONFIG_IA64 - int tmp; + int i; struct pnp_dev *tdev; resource_size_t *dma = &dev->res.dma_resource[idx].start; @@ -444,15 +444,15 @@ int pnp_check_dma(struct pnp_dev *dev, int idx) return 0; /* check if the resource is reserved */ - for (tmp = 0; tmp < 8; tmp++) { - if (pnp_reserve_dma[tmp] == *dma) + for (i = 0; i < 8; i++) { + if (pnp_reserve_dma[i] == *dma) return 0; } /* check for internal conflicts */ - for (tmp = 0; tmp < PNP_MAX_DMA && tmp != idx; tmp++) { - if (dev->res.dma_resource[tmp].flags & IORESOURCE_DMA) { - if (dev->res.dma_resource[tmp].start == *dma) + for (i = 0; i < PNP_MAX_DMA && i != idx; i++) { + if (dev->res.dma_resource[i].flags & IORESOURCE_DMA) { + if (dev->res.dma_resource[i].start == *dma) return 0; } } @@ -469,12 +469,12 @@ int pnp_check_dma(struct pnp_dev *dev, int idx) pnp_for_each_dev(tdev) { if (tdev == dev) continue; - for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) { - if (tdev->res.dma_resource[tmp].flags & IORESOURCE_DMA) { + for (i = 0; i < PNP_MAX_DMA; i++) { + if (tdev->res.dma_resource[i].flags & IORESOURCE_DMA) { if (cannot_compare - (tdev->res.dma_resource[tmp].flags)) + (tdev->res.dma_resource[i].flags)) continue; - if ((tdev->res.dma_resource[tmp].start == *dma)) + if ((tdev->res.dma_resource[i].start == *dma)) return 0; } } -- cgit v1.2.2 From 28ccffcf028777e830cbdc30bc54ba8a37e2fc23 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:18 -0600 Subject: PNP: reduce redundancy in pnp_assign_port() and others Use a temporary "res" pointer to replace repeated lookups in the pnp resource tables. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/manager.c | 123 +++++++++++++++++++++++--------------------------- 1 file changed, 56 insertions(+), 67 deletions(-) diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index 8267efd679a1..be21dec539d9 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c @@ -19,8 +19,7 @@ DEFINE_MUTEX(pnp_res_mutex); static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) { - resource_size_t *start, *end; - unsigned long *flags; + struct resource *res; if (idx >= PNP_MAX_PORT) { dev_err(&dev->dev, "too many I/O port resources\n"); @@ -28,49 +27,46 @@ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) return 1; } - start = &dev->res.port_resource[idx].start; - end = &dev->res.port_resource[idx].end; - flags = &dev->res.port_resource[idx].flags; + res = &dev->res.port_resource[idx]; /* check if this resource has been manually set, if so skip */ - if (!(dev->res.port_resource[idx].flags & IORESOURCE_AUTO)) { + if (!(res->flags & IORESOURCE_AUTO)) { dev_dbg(&dev->dev, " io %d already set to %#llx-%#llx " - "flags %#lx\n", idx, (unsigned long long) *start, - (unsigned long long) *end, *flags); + "flags %#lx\n", idx, (unsigned long long) res->start, + (unsigned long long) res->end, res->flags); return 1; } /* set the initial values */ - *flags |= rule->flags | IORESOURCE_IO; - *flags &= ~IORESOURCE_UNSET; + res->flags |= rule->flags | IORESOURCE_IO; + res->flags &= ~IORESOURCE_UNSET; if (!rule->size) { - *flags |= IORESOURCE_DISABLED; + res->flags |= IORESOURCE_DISABLED; dev_dbg(&dev->dev, " io %d disabled\n", idx); return 1; /* skip disabled resource requests */ } - *start = rule->min; - *end = *start + rule->size - 1; + res->start = rule->min; + res->end = res->start + rule->size - 1; /* run through until pnp_check_port is happy */ while (!pnp_check_port(dev, idx)) { - *start += rule->align; - *end = *start + rule->size - 1; - if (*start > rule->max || !rule->align) { + res->start += rule->align; + res->end = res->start + rule->size - 1; + if (res->start > rule->max || !rule->align) { dev_dbg(&dev->dev, " couldn't assign io %d\n", idx); return 0; } } dev_dbg(&dev->dev, " assign io %d %#llx-%#llx\n", idx, - (unsigned long long) *start, (unsigned long long) *end); + (unsigned long long) res->start, (unsigned long long) res->end); return 1; } static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) { - resource_size_t *start, *end; - unsigned long *flags; + struct resource *res; if (idx >= PNP_MAX_MEM) { dev_err(&dev->dev, "too many memory resources\n"); @@ -78,59 +74,56 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) return 1; } - start = &dev->res.mem_resource[idx].start; - end = &dev->res.mem_resource[idx].end; - flags = &dev->res.mem_resource[idx].flags; + res = &dev->res.mem_resource[idx]; /* check if this resource has been manually set, if so skip */ - if (!(dev->res.mem_resource[idx].flags & IORESOURCE_AUTO)) { + if (!(res->flags & IORESOURCE_AUTO)) { dev_dbg(&dev->dev, " mem %d already set to %#llx-%#llx " - "flags %#lx\n", idx, (unsigned long long) *start, - (unsigned long long) *end, *flags); + "flags %#lx\n", idx, (unsigned long long) res->start, + (unsigned long long) res->end, res->flags); return 1; } /* set the initial values */ - *flags |= rule->flags | IORESOURCE_MEM; - *flags &= ~IORESOURCE_UNSET; + res->flags |= rule->flags | IORESOURCE_MEM; + res->flags &= ~IORESOURCE_UNSET; /* convert pnp flags to standard Linux flags */ if (!(rule->flags & IORESOURCE_MEM_WRITEABLE)) - *flags |= IORESOURCE_READONLY; + res->flags |= IORESOURCE_READONLY; if (rule->flags & IORESOURCE_MEM_CACHEABLE) - *flags |= IORESOURCE_CACHEABLE; + res->flags |= IORESOURCE_CACHEABLE; if (rule->flags & IORESOURCE_MEM_RANGELENGTH) - *flags |= IORESOURCE_RANGELENGTH; + res->flags |= IORESOURCE_RANGELENGTH; if (rule->flags & IORESOURCE_MEM_SHADOWABLE) - *flags |= IORESOURCE_SHADOWABLE; + res->flags |= IORESOURCE_SHADOWABLE; if (!rule->size) { - *flags |= IORESOURCE_DISABLED; + res->flags |= IORESOURCE_DISABLED; dev_dbg(&dev->dev, " mem %d disabled\n", idx); return 1; /* skip disabled resource requests */ } - *start = rule->min; - *end = *start + rule->size - 1; + res->start = rule->min; + res->end = res->start + rule->size - 1; /* run through until pnp_check_mem is happy */ while (!pnp_check_mem(dev, idx)) { - *start += rule->align; - *end = *start + rule->size - 1; - if (*start > rule->max || !rule->align) { + res->start += rule->align; + res->end = res->start + rule->size - 1; + if (res->start > rule->max || !rule->align) { dev_dbg(&dev->dev, " couldn't assign mem %d\n", idx); return 0; } } dev_dbg(&dev->dev, " assign mem %d %#llx-%#llx\n", idx, - (unsigned long long) *start, (unsigned long long) *end); + (unsigned long long) res->start, (unsigned long long) res->end); return 1; } static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) { - resource_size_t *start, *end; - unsigned long *flags; + struct resource *res; int i; /* IRQ priority: this table is good for i386 */ @@ -144,40 +137,39 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) return 1; } - start = &dev->res.irq_resource[idx].start; - end = &dev->res.irq_resource[idx].end; - flags = &dev->res.irq_resource[idx].flags; + res = &dev->res.irq_resource[idx]; /* check if this resource has been manually set, if so skip */ - if (!(dev->res.irq_resource[idx].flags & IORESOURCE_AUTO)) { + if (!(res->flags & IORESOURCE_AUTO)) { dev_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n", - idx, (int) *start, *flags); + idx, (int) res->start, res->flags); return 1; } /* set the initial values */ - *flags |= rule->flags | IORESOURCE_IRQ; - *flags &= ~IORESOURCE_UNSET; + res->flags |= rule->flags | IORESOURCE_IRQ; + res->flags &= ~IORESOURCE_UNSET; if (bitmap_empty(rule->map, PNP_IRQ_NR)) { - *flags |= IORESOURCE_DISABLED; + res->flags |= IORESOURCE_DISABLED; dev_dbg(&dev->dev, " irq %d disabled\n", idx); return 1; /* skip disabled resource requests */ } /* TBD: need check for >16 IRQ */ - *start = find_next_bit(rule->map, PNP_IRQ_NR, 16); - if (*start < PNP_IRQ_NR) { - *end = *start; - dev_dbg(&dev->dev, " assign irq %d %d\n", idx, (int) *start); + res->start = find_next_bit(rule->map, PNP_IRQ_NR, 16); + if (res->start < PNP_IRQ_NR) { + res->end = res->start; + dev_dbg(&dev->dev, " assign irq %d %d\n", idx, + (int) res->start); return 1; } for (i = 0; i < 16; i++) { if (test_bit(xtab[i], rule->map)) { - *start = *end = xtab[i]; + res->start = res->end = xtab[i]; if (pnp_check_irq(dev, idx)) { dev_dbg(&dev->dev, " assign irq %d %d\n", idx, - (int) *start); + (int) res->start); return 1; } } @@ -188,8 +180,7 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) { - resource_size_t *start, *end; - unsigned long *flags; + struct resource *res; int i; /* DMA priority: this table is good for i386 */ @@ -202,35 +193,33 @@ static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) return; } - start = &dev->res.dma_resource[idx].start; - end = &dev->res.dma_resource[idx].end; - flags = &dev->res.dma_resource[idx].flags; + res = &dev->res.dma_resource[idx]; /* check if this resource has been manually set, if so skip */ - if (!(dev->res.dma_resource[idx].flags & IORESOURCE_AUTO)) { + if (!(res->flags & IORESOURCE_AUTO)) { dev_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n", - idx, (int) *start, *flags); + idx, (int) res->start, res->flags); return; } /* set the initial values */ - *flags |= rule->flags | IORESOURCE_DMA; - *flags &= ~IORESOURCE_UNSET; + res->flags |= rule->flags | IORESOURCE_DMA; + res->flags &= ~IORESOURCE_UNSET; for (i = 0; i < 8; i++) { if (rule->map & (1 << xtab[i])) { - *start = *end = xtab[i]; + res->start = res->end = xtab[i]; if (pnp_check_dma(dev, idx)) { dev_dbg(&dev->dev, " assign dma %d %d\n", idx, - (int) *start); + (int) res->start); return; } } } #ifdef MAX_DMA_CHANNELS - *start = *end = MAX_DMA_CHANNELS; + res->start = res->end = MAX_DMA_CHANNELS; #endif - *flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; + res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; dev_dbg(&dev->dev, " disable dma %d\n", idx); } -- cgit v1.2.2 From 30c016a0c8d2aae10be6a87bb98f0e85db8b09d5 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:19 -0600 Subject: PNP: reduce redundancy in pnp_check_port() and others Use a temporary "res" pointer to replace repeated lookups in the pnp resource tables. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/resource.c | 92 +++++++++++++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 38 deletions(-) diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index 15995f9f8b7c..f89945ebd8b6 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -243,13 +243,15 @@ int pnp_check_port(struct pnp_dev *dev, int idx) { int i; struct pnp_dev *tdev; + struct resource *res, *tres; resource_size_t *port, *end, *tport, *tend; - port = &dev->res.port_resource[idx].start; - end = &dev->res.port_resource[idx].end; + res = &dev->res.port_resource[idx]; + port = &res->start; + end = &res->end; /* if the resource doesn't exist, don't complain about it */ - if (cannot_compare(dev->res.port_resource[idx].flags)) + if (cannot_compare(res->flags)) return 1; /* check if the resource is already in use, skip if the @@ -269,9 +271,10 @@ int pnp_check_port(struct pnp_dev *dev, int idx) /* check for internal conflicts */ for (i = 0; i < PNP_MAX_PORT && i != idx; i++) { - if (dev->res.port_resource[i].flags & IORESOURCE_IO) { - tport = &dev->res.port_resource[i].start; - tend = &dev->res.port_resource[i].end; + tres = &dev->res.port_resource[i]; + if (tres->flags & IORESOURCE_IO) { + tport = &tres->start; + tend = &tres->end; if (ranged_conflict(port, end, tport, tend)) return 0; } @@ -282,12 +285,12 @@ int pnp_check_port(struct pnp_dev *dev, int idx) if (tdev == dev) continue; for (i = 0; i < PNP_MAX_PORT; i++) { - if (tdev->res.port_resource[i].flags & IORESOURCE_IO) { - if (cannot_compare - (tdev->res.port_resource[i].flags)) + tres = &tdev->res.port_resource[i]; + if (tres->flags & IORESOURCE_IO) { + if (cannot_compare(tres->flags)) continue; - tport = &tdev->res.port_resource[i].start; - tend = &tdev->res.port_resource[i].end; + tport = &tres->start; + tend = &tres->end; if (ranged_conflict(port, end, tport, tend)) return 0; } @@ -301,13 +304,15 @@ int pnp_check_mem(struct pnp_dev *dev, int idx) { int i; struct pnp_dev *tdev; + struct resource *res, *tres; resource_size_t *addr, *end, *taddr, *tend; - addr = &dev->res.mem_resource[idx].start; - end = &dev->res.mem_resource[idx].end; + res = &dev->res.mem_resource[idx]; + addr = &res->start; + end = &res->end; /* if the resource doesn't exist, don't complain about it */ - if (cannot_compare(dev->res.mem_resource[idx].flags)) + if (cannot_compare(res->flags)) return 1; /* check if the resource is already in use, skip if the @@ -327,9 +332,10 @@ int pnp_check_mem(struct pnp_dev *dev, int idx) /* check for internal conflicts */ for (i = 0; i < PNP_MAX_MEM && i != idx; i++) { - if (dev->res.mem_resource[i].flags & IORESOURCE_MEM) { - taddr = &dev->res.mem_resource[i].start; - tend = &dev->res.mem_resource[i].end; + tres = &dev->res.mem_resource[i]; + if (tres->flags & IORESOURCE_MEM) { + taddr = &tres->start; + tend = &tres->end; if (ranged_conflict(addr, end, taddr, tend)) return 0; } @@ -340,12 +346,12 @@ int pnp_check_mem(struct pnp_dev *dev, int idx) if (tdev == dev) continue; for (i = 0; i < PNP_MAX_MEM; i++) { - if (tdev->res.mem_resource[i].flags & IORESOURCE_MEM) { - if (cannot_compare - (tdev->res.mem_resource[i].flags)) + tres = &tdev->res.mem_resource[i]; + if (tres->flags & IORESOURCE_MEM) { + if (cannot_compare(tres->flags)) continue; - taddr = &tdev->res.mem_resource[i].start; - tend = &tdev->res.mem_resource[i].end; + taddr = &tres->start; + tend = &tres->end; if (ranged_conflict(addr, end, taddr, tend)) return 0; } @@ -364,10 +370,14 @@ int pnp_check_irq(struct pnp_dev *dev, int idx) { int i; struct pnp_dev *tdev; - resource_size_t *irq = &dev->res.irq_resource[idx].start; + struct resource *res, *tres; + resource_size_t *irq; + + res = &dev->res.irq_resource[idx]; + irq = &res->start; /* if the resource doesn't exist, don't complain about it */ - if (cannot_compare(dev->res.irq_resource[idx].flags)) + if (cannot_compare(res->flags)) return 1; /* check if the resource is valid */ @@ -382,8 +392,9 @@ int pnp_check_irq(struct pnp_dev *dev, int idx) /* check for internal conflicts */ for (i = 0; i < PNP_MAX_IRQ && i != idx; i++) { - if (dev->res.irq_resource[i].flags & IORESOURCE_IRQ) { - if (dev->res.irq_resource[i].start == *irq) + tres = &dev->res.irq_resource[i]; + if (tres->flags & IORESOURCE_IRQ) { + if (tres->start == *irq) return 0; } } @@ -415,11 +426,11 @@ int pnp_check_irq(struct pnp_dev *dev, int idx) if (tdev == dev) continue; for (i = 0; i < PNP_MAX_IRQ; i++) { - if (tdev->res.irq_resource[i].flags & IORESOURCE_IRQ) { - if (cannot_compare - (tdev->res.irq_resource[i].flags)) + tres = &tdev->res.irq_resource[i]; + if (tres->flags & IORESOURCE_IRQ) { + if (cannot_compare(tres->flags)) continue; - if ((tdev->res.irq_resource[i].start == *irq)) + if (tres->start == *irq) return 0; } } @@ -433,10 +444,14 @@ int pnp_check_dma(struct pnp_dev *dev, int idx) #ifndef CONFIG_IA64 int i; struct pnp_dev *tdev; - resource_size_t *dma = &dev->res.dma_resource[idx].start; + struct resource *res, *tres; + resource_size_t *dma; + + res = &dev->res.dma_resource[idx]; + dma = &res->start; /* if the resource doesn't exist, don't complain about it */ - if (cannot_compare(dev->res.dma_resource[idx].flags)) + if (cannot_compare(res->flags)) return 1; /* check if the resource is valid */ @@ -451,8 +466,9 @@ int pnp_check_dma(struct pnp_dev *dev, int idx) /* check for internal conflicts */ for (i = 0; i < PNP_MAX_DMA && i != idx; i++) { - if (dev->res.dma_resource[i].flags & IORESOURCE_DMA) { - if (dev->res.dma_resource[i].start == *dma) + tres = &dev->res.dma_resource[i]; + if (tres->flags & IORESOURCE_DMA) { + if (tres->start == *dma) return 0; } } @@ -470,11 +486,11 @@ int pnp_check_dma(struct pnp_dev *dev, int idx) if (tdev == dev) continue; for (i = 0; i < PNP_MAX_DMA; i++) { - if (tdev->res.dma_resource[i].flags & IORESOURCE_DMA) { - if (cannot_compare - (tdev->res.dma_resource[i].flags)) + tres = &tdev->res.dma_resource[i]; + if (tres->flags & IORESOURCE_DMA) { + if (cannot_compare(tres->flags)) continue; - if ((tdev->res.dma_resource[i].start == *dma)) + if (tres->start == *dma) return 0; } } -- cgit v1.2.2 From 470feb113a23de365b6051efde0d69de86d9d2f8 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:20 -0600 Subject: PNP: reduce redundancy in pnp_set_current_resources() Use a temporary "res" pointer to replace repeated lookups in the pnp resource tables. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/interface.c | 41 +++++++++++++++++------------------------ 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c index cdc3ecfde6ef..1801df3db1e8 100644 --- a/drivers/pnp/interface.c +++ b/drivers/pnp/interface.c @@ -323,6 +323,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, const char *ubuf, size_t count) { struct pnp_dev *dev = to_pnp_dev(dmdev); + struct resource *res; char *buf = (void *)ubuf; int retval = 0; @@ -382,21 +383,18 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, buf += 2; while (isspace(*buf)) ++buf; - dev->res.port_resource[nport].start = - simple_strtoul(buf, &buf, 0); + res = &dev->res.port_resource[nport]; + res->start = simple_strtoul(buf, &buf, 0); while (isspace(*buf)) ++buf; if (*buf == '-') { buf += 1; while (isspace(*buf)) ++buf; - dev->res.port_resource[nport].end = - simple_strtoul(buf, &buf, 0); + res->end = simple_strtoul(buf, &buf, 0); } else - dev->res.port_resource[nport].end = - dev->res.port_resource[nport].start; - dev->res.port_resource[nport].flags = - IORESOURCE_IO; + res->end = res->start; + res->flags = IORESOURCE_IO; nport++; if (nport >= PNP_MAX_PORT) break; @@ -406,21 +404,18 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, buf += 3; while (isspace(*buf)) ++buf; - dev->res.mem_resource[nmem].start = - simple_strtoul(buf, &buf, 0); + res = &dev->res.mem_resource[nmem]; + res->start = simple_strtoul(buf, &buf, 0); while (isspace(*buf)) ++buf; if (*buf == '-') { buf += 1; while (isspace(*buf)) ++buf; - dev->res.mem_resource[nmem].end = - simple_strtoul(buf, &buf, 0); + res->end = simple_strtoul(buf, &buf, 0); } else - dev->res.mem_resource[nmem].end = - dev->res.mem_resource[nmem].start; - dev->res.mem_resource[nmem].flags = - IORESOURCE_MEM; + res->end = res->start; + res->flags = IORESOURCE_MEM; nmem++; if (nmem >= PNP_MAX_MEM) break; @@ -430,11 +425,10 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, buf += 3; while (isspace(*buf)) ++buf; - dev->res.irq_resource[nirq].start = - dev->res.irq_resource[nirq].end = + res = &dev->res.irq_resource[nirq]; + res->start = res->end = simple_strtoul(buf, &buf, 0); - dev->res.irq_resource[nirq].flags = - IORESOURCE_IRQ; + res->flags = IORESOURCE_IRQ; nirq++; if (nirq >= PNP_MAX_IRQ) break; @@ -444,11 +438,10 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, buf += 3; while (isspace(*buf)) ++buf; - dev->res.dma_resource[ndma].start = - dev->res.dma_resource[ndma].end = + res = &dev->res.dma_resource[ndma]; + res->start = res->end = simple_strtoul(buf, &buf, 0); - dev->res.dma_resource[ndma].flags = - IORESOURCE_DMA; + res->flags = IORESOURCE_DMA; ndma++; if (ndma >= PNP_MAX_DMA) break; -- cgit v1.2.2 From db9eaeab3e7ab72d773820820f1ba33960ad24c4 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:21 -0600 Subject: PNP: check for conflicts with all resources, not just earlier ones This patch removes a use of "idx" in pnp_check_port() and similar functions, in preparation for replacing idx with a pointer to the resource itself. I split this out because it changes the behavior slightly: we used to check for conflicts only with earlier resources, e.g., we checked resource 2 against resources 0 and 1 but not against 3, 4, etc. Now we will check against all resources except 2. Since resources are assigned in ascending order, the old behavior was probably safe, but I don't like to depend on that ordering. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/resource.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index f89945ebd8b6..eab16e5520ae 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -270,9 +270,9 @@ int pnp_check_port(struct pnp_dev *dev, int idx) } /* check for internal conflicts */ - for (i = 0; i < PNP_MAX_PORT && i != idx; i++) { + for (i = 0; i < PNP_MAX_PORT; i++) { tres = &dev->res.port_resource[i]; - if (tres->flags & IORESOURCE_IO) { + if (tres != res && tres->flags & IORESOURCE_IO) { tport = &tres->start; tend = &tres->end; if (ranged_conflict(port, end, tport, tend)) @@ -331,9 +331,9 @@ int pnp_check_mem(struct pnp_dev *dev, int idx) } /* check for internal conflicts */ - for (i = 0; i < PNP_MAX_MEM && i != idx; i++) { + for (i = 0; i < PNP_MAX_MEM; i++) { tres = &dev->res.mem_resource[i]; - if (tres->flags & IORESOURCE_MEM) { + if (tres != res && tres->flags & IORESOURCE_MEM) { taddr = &tres->start; tend = &tres->end; if (ranged_conflict(addr, end, taddr, tend)) @@ -391,9 +391,9 @@ int pnp_check_irq(struct pnp_dev *dev, int idx) } /* check for internal conflicts */ - for (i = 0; i < PNP_MAX_IRQ && i != idx; i++) { + for (i = 0; i < PNP_MAX_IRQ; i++) { tres = &dev->res.irq_resource[i]; - if (tres->flags & IORESOURCE_IRQ) { + if (tres != res && tres->flags & IORESOURCE_IRQ) { if (tres->start == *irq) return 0; } @@ -465,9 +465,9 @@ int pnp_check_dma(struct pnp_dev *dev, int idx) } /* check for internal conflicts */ - for (i = 0; i < PNP_MAX_DMA && i != idx; i++) { + for (i = 0; i < PNP_MAX_DMA; i++) { tres = &dev->res.dma_resource[i]; - if (tres->flags & IORESOURCE_DMA) { + if (tres != res && tres->flags & IORESOURCE_DMA) { if (tres->start == *dma) return 0; } -- cgit v1.2.2 From f5d94ff014cb7e6212f40fc6644f3fd68507df33 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:22 -0600 Subject: PNP: pass resources, not indexes, to pnp_check_port(), et al The caller already has the struct resource pointer, so no need for pnp_check_port(), pnp_check_mem(), etc., to look it up again. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/base.h | 8 ++++---- drivers/pnp/manager.c | 8 ++++---- drivers/pnp/resource.c | 20 ++++++++------------ 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index eb43fc6bff11..e739d4bba423 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h @@ -12,10 +12,10 @@ void pnp_free_option(struct pnp_option *option); int __pnp_add_device(struct pnp_dev *dev); void __pnp_remove_device(struct pnp_dev *dev); -int pnp_check_port(struct pnp_dev * dev, int idx); -int pnp_check_mem(struct pnp_dev * dev, int idx); -int pnp_check_irq(struct pnp_dev * dev, int idx); -int pnp_check_dma(struct pnp_dev * dev, int idx); +int pnp_check_port(struct pnp_dev *dev, struct resource *res); +int pnp_check_mem(struct pnp_dev *dev, struct resource *res); +int pnp_check_irq(struct pnp_dev *dev, struct resource *res); +int pnp_check_dma(struct pnp_dev *dev, struct resource *res); void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc); diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index be21dec539d9..08865292fc95 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c @@ -51,7 +51,7 @@ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) res->end = res->start + rule->size - 1; /* run through until pnp_check_port is happy */ - while (!pnp_check_port(dev, idx)) { + while (!pnp_check_port(dev, res)) { res->start += rule->align; res->end = res->start + rule->size - 1; if (res->start > rule->max || !rule->align) { @@ -108,7 +108,7 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) res->end = res->start + rule->size - 1; /* run through until pnp_check_mem is happy */ - while (!pnp_check_mem(dev, idx)) { + while (!pnp_check_mem(dev, res)) { res->start += rule->align; res->end = res->start + rule->size - 1; if (res->start > rule->max || !rule->align) { @@ -167,7 +167,7 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) for (i = 0; i < 16; i++) { if (test_bit(xtab[i], rule->map)) { res->start = res->end = xtab[i]; - if (pnp_check_irq(dev, idx)) { + if (pnp_check_irq(dev, res)) { dev_dbg(&dev->dev, " assign irq %d %d\n", idx, (int) res->start); return 1; @@ -209,7 +209,7 @@ static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) for (i = 0; i < 8; i++) { if (rule->map & (1 << xtab[i])) { res->start = res->end = xtab[i]; - if (pnp_check_dma(dev, idx)) { + if (pnp_check_dma(dev, res)) { dev_dbg(&dev->dev, " assign dma %d %d\n", idx, (int) res->start); return; diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index eab16e5520ae..93bf45e01f2c 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -239,14 +239,13 @@ void pnp_free_option(struct pnp_option *option) #define cannot_compare(flags) \ ((flags) & (IORESOURCE_UNSET | IORESOURCE_DISABLED)) -int pnp_check_port(struct pnp_dev *dev, int idx) +int pnp_check_port(struct pnp_dev *dev, struct resource *res) { int i; struct pnp_dev *tdev; - struct resource *res, *tres; + struct resource *tres; resource_size_t *port, *end, *tport, *tend; - res = &dev->res.port_resource[idx]; port = &res->start; end = &res->end; @@ -300,14 +299,13 @@ int pnp_check_port(struct pnp_dev *dev, int idx) return 1; } -int pnp_check_mem(struct pnp_dev *dev, int idx) +int pnp_check_mem(struct pnp_dev *dev, struct resource *res) { int i; struct pnp_dev *tdev; - struct resource *res, *tres; + struct resource *tres; resource_size_t *addr, *end, *taddr, *tend; - res = &dev->res.mem_resource[idx]; addr = &res->start; end = &res->end; @@ -366,14 +364,13 @@ static irqreturn_t pnp_test_handler(int irq, void *dev_id) return IRQ_HANDLED; } -int pnp_check_irq(struct pnp_dev *dev, int idx) +int pnp_check_irq(struct pnp_dev *dev, struct resource *res) { int i; struct pnp_dev *tdev; - struct resource *res, *tres; + struct resource *tres; resource_size_t *irq; - res = &dev->res.irq_resource[idx]; irq = &res->start; /* if the resource doesn't exist, don't complain about it */ @@ -439,15 +436,14 @@ int pnp_check_irq(struct pnp_dev *dev, int idx) return 1; } -int pnp_check_dma(struct pnp_dev *dev, int idx) +int pnp_check_dma(struct pnp_dev *dev, struct resource *res) { #ifndef CONFIG_IA64 int i; struct pnp_dev *tdev; - struct resource *res, *tres; + struct resource *tres; resource_size_t *dma; - res = &dev->res.dma_resource[idx]; dma = &res->start; /* if the resource doesn't exist, don't complain about it */ -- cgit v1.2.2 From be81b4a4838ce329b9f3978c7fc007b047c23722 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:23 -0600 Subject: PNP: convert resource checks to use pnp_get_resource(), not pnp_resource_table This removes more direct references to pnp_resource_table. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/resource.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index 93bf45e01f2c..b2516d62fcf6 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -270,8 +270,8 @@ int pnp_check_port(struct pnp_dev *dev, struct resource *res) /* check for internal conflicts */ for (i = 0; i < PNP_MAX_PORT; i++) { - tres = &dev->res.port_resource[i]; - if (tres != res && tres->flags & IORESOURCE_IO) { + tres = pnp_get_resource(dev, IORESOURCE_IO, i); + if (tres && tres != res && tres->flags & IORESOURCE_IO) { tport = &tres->start; tend = &tres->end; if (ranged_conflict(port, end, tport, tend)) @@ -284,8 +284,8 @@ int pnp_check_port(struct pnp_dev *dev, struct resource *res) if (tdev == dev) continue; for (i = 0; i < PNP_MAX_PORT; i++) { - tres = &tdev->res.port_resource[i]; - if (tres->flags & IORESOURCE_IO) { + tres = pnp_get_resource(tdev, IORESOURCE_IO, i); + if (tres && tres->flags & IORESOURCE_IO) { if (cannot_compare(tres->flags)) continue; tport = &tres->start; @@ -330,8 +330,8 @@ int pnp_check_mem(struct pnp_dev *dev, struct resource *res) /* check for internal conflicts */ for (i = 0; i < PNP_MAX_MEM; i++) { - tres = &dev->res.mem_resource[i]; - if (tres != res && tres->flags & IORESOURCE_MEM) { + tres = pnp_get_resource(dev, IORESOURCE_MEM, i); + if (tres && tres != res && tres->flags & IORESOURCE_MEM) { taddr = &tres->start; tend = &tres->end; if (ranged_conflict(addr, end, taddr, tend)) @@ -344,8 +344,8 @@ int pnp_check_mem(struct pnp_dev *dev, struct resource *res) if (tdev == dev) continue; for (i = 0; i < PNP_MAX_MEM; i++) { - tres = &tdev->res.mem_resource[i]; - if (tres->flags & IORESOURCE_MEM) { + tres = pnp_get_resource(tdev, IORESOURCE_MEM, i); + if (tres && tres->flags & IORESOURCE_MEM) { if (cannot_compare(tres->flags)) continue; taddr = &tres->start; @@ -389,8 +389,8 @@ int pnp_check_irq(struct pnp_dev *dev, struct resource *res) /* check for internal conflicts */ for (i = 0; i < PNP_MAX_IRQ; i++) { - tres = &dev->res.irq_resource[i]; - if (tres != res && tres->flags & IORESOURCE_IRQ) { + tres = pnp_get_resource(dev, IORESOURCE_IRQ, i); + if (tres && tres != res && tres->flags & IORESOURCE_IRQ) { if (tres->start == *irq) return 0; } @@ -423,8 +423,8 @@ int pnp_check_irq(struct pnp_dev *dev, struct resource *res) if (tdev == dev) continue; for (i = 0; i < PNP_MAX_IRQ; i++) { - tres = &tdev->res.irq_resource[i]; - if (tres->flags & IORESOURCE_IRQ) { + tres = pnp_get_resource(tdev, IORESOURCE_IRQ, i); + if (tres && tres->flags & IORESOURCE_IRQ) { if (cannot_compare(tres->flags)) continue; if (tres->start == *irq) @@ -462,8 +462,8 @@ int pnp_check_dma(struct pnp_dev *dev, struct resource *res) /* check for internal conflicts */ for (i = 0; i < PNP_MAX_DMA; i++) { - tres = &dev->res.dma_resource[i]; - if (tres != res && tres->flags & IORESOURCE_DMA) { + tres = pnp_get_resource(dev, IORESOURCE_DMA, i); + if (tres && tres != res && tres->flags & IORESOURCE_DMA) { if (tres->start == *dma) return 0; } @@ -482,8 +482,8 @@ int pnp_check_dma(struct pnp_dev *dev, struct resource *res) if (tdev == dev) continue; for (i = 0; i < PNP_MAX_DMA; i++) { - tres = &tdev->res.dma_resource[i]; - if (tres->flags & IORESOURCE_DMA) { + tres = pnp_get_resource(tdev, IORESOURCE_DMA, i); + if (tres && tres->flags & IORESOURCE_DMA) { if (cannot_compare(tres->flags)) continue; if (tres->start == *dma) -- cgit v1.2.2 From 7e2cf31f1c97ac14b6d9dc5f1ce9e1e01aef9c18 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:24 -0600 Subject: PNP: convert encoders to use pnp_get_resource(), not pnp_resource_table This removes more direct references to pnp_resource_table. This path is used when telling a device what resources it should use. This doesn't convert ISAPNP because ISA needs to know the config register index in addition to the resource itself. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/pnpacpi/rsparser.c | 19 ++++++++----------- drivers/pnp/pnpbios/rsparser.c | 22 ++++++++++++++-------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index bd41e4d4270c..000a1b39f0b6 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -1014,7 +1014,6 @@ static void pnpacpi_encode_fixed_mem32(struct pnp_dev *dev, int pnpacpi_encode_resources(struct pnp_dev *dev, struct acpi_buffer *buffer) { - struct pnp_resource_table *res_table = &dev->res; int i = 0; /* pnpacpi_build_resource_template allocates extra mem */ int res_cnt = (buffer->length - 1) / sizeof(struct acpi_resource) - 1; @@ -1026,45 +1025,43 @@ int pnpacpi_encode_resources(struct pnp_dev *dev, struct acpi_buffer *buffer) switch (resource->type) { case ACPI_RESOURCE_TYPE_IRQ: pnpacpi_encode_irq(dev, resource, - &res_table->irq_resource[irq]); + pnp_get_resource(dev, IORESOURCE_IRQ, irq)); irq++; break; case ACPI_RESOURCE_TYPE_DMA: pnpacpi_encode_dma(dev, resource, - &res_table->dma_resource[dma]); + pnp_get_resource(dev, IORESOURCE_DMA, dma)); dma++; break; case ACPI_RESOURCE_TYPE_IO: pnpacpi_encode_io(dev, resource, - &res_table->port_resource[port]); + pnp_get_resource(dev, IORESOURCE_IO, port)); port++; break; case ACPI_RESOURCE_TYPE_FIXED_IO: pnpacpi_encode_fixed_io(dev, resource, - &res_table-> - port_resource[port]); + pnp_get_resource(dev, IORESOURCE_IO, port)); port++; break; case ACPI_RESOURCE_TYPE_MEMORY24: pnpacpi_encode_mem24(dev, resource, - &res_table->mem_resource[mem]); + pnp_get_resource(dev, IORESOURCE_MEM, mem)); mem++; break; case ACPI_RESOURCE_TYPE_MEMORY32: pnpacpi_encode_mem32(dev, resource, - &res_table->mem_resource[mem]); + pnp_get_resource(dev, IORESOURCE_MEM, mem)); mem++; break; case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: pnpacpi_encode_fixed_mem32(dev, resource, - &res_table-> - mem_resource[mem]); + pnp_get_resource(dev, IORESOURCE_MEM, mem)); mem++; break; case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: pnpacpi_encode_ext_irq(dev, resource, - &res_table->irq_resource[irq]); + pnp_get_resource(dev, IORESOURCE_IRQ, irq)); irq++; break; case ACPI_RESOURCE_TYPE_START_DEPENDENT: diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c index 4390e3b41df0..c1f9e162d2c5 100644 --- a/drivers/pnp/pnpbios/rsparser.c +++ b/drivers/pnp/pnpbios/rsparser.c @@ -688,7 +688,6 @@ static unsigned char *pnpbios_encode_allocated_resource_data(struct pnp_dev unsigned char *p, unsigned char *end) { - struct pnp_resource_table *res = &dev->res; unsigned int len, tag; int port = 0, irq = 0, dma = 0, mem = 0; @@ -711,42 +710,48 @@ static unsigned char *pnpbios_encode_allocated_resource_data(struct pnp_dev case LARGE_TAG_MEM: if (len != 9) goto len_err; - pnpbios_encode_mem(dev, p, &res->mem_resource[mem]); + pnpbios_encode_mem(dev, p, + pnp_get_resource(dev, IORESOURCE_MEM, mem)); mem++; break; case LARGE_TAG_MEM32: if (len != 17) goto len_err; - pnpbios_encode_mem32(dev, p, &res->mem_resource[mem]); + pnpbios_encode_mem32(dev, p, + pnp_get_resource(dev, IORESOURCE_MEM, mem)); mem++; break; case LARGE_TAG_FIXEDMEM32: if (len != 9) goto len_err; - pnpbios_encode_fixed_mem32(dev, p, &res->mem_resource[mem]); + pnpbios_encode_fixed_mem32(dev, p, + pnp_get_resource(dev, IORESOURCE_MEM, mem)); mem++; break; case SMALL_TAG_IRQ: if (len < 2 || len > 3) goto len_err; - pnpbios_encode_irq(dev, p, &res->irq_resource[irq]); + pnpbios_encode_irq(dev, p, + pnp_get_resource(dev, IORESOURCE_IRQ, irq)); irq++; break; case SMALL_TAG_DMA: if (len != 2) goto len_err; - pnpbios_encode_dma(dev, p, &res->dma_resource[dma]); + pnpbios_encode_dma(dev, p, + pnp_get_resource(dev, IORESOURCE_DMA, dma)); dma++; break; case SMALL_TAG_PORT: if (len != 7) goto len_err; - pnpbios_encode_port(dev, p, &res->port_resource[port]); + pnpbios_encode_port(dev, p, + pnp_get_resource(dev, IORESOURCE_IO, port)); port++; break; @@ -757,7 +762,8 @@ static unsigned char *pnpbios_encode_allocated_resource_data(struct pnp_dev case SMALL_TAG_FIXEDPORT: if (len != 3) goto len_err; - pnpbios_encode_fixed_port(dev, p, &res->port_resource[port]); + pnpbios_encode_fixed_port(dev, p, + pnp_get_resource(dev, IORESOURCE_IO, port)); port++; break; -- cgit v1.2.2 From f6505fef18644557f732468c1f22f84560d8a819 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:25 -0600 Subject: PNP: convert assign, interface to use pnp_get_resource(), not pnp_resource_table This removes more direct references to pnp_resource_table from the pnp_assign_resources() path and the /sys user interface path. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/pnp/interface.c | 28 ++++++++++++++++------------ drivers/pnp/manager.c | 20 ++++++++------------ drivers/pnp/support.c | 16 ++++++++-------- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c index 1801df3db1e8..a608054a3e53 100644 --- a/drivers/pnp/interface.c +++ b/drivers/pnp/interface.c @@ -383,7 +383,10 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, buf += 2; while (isspace(*buf)) ++buf; - res = &dev->res.port_resource[nport]; + res = pnp_get_resource(dev, IORESOURCE_IO, + nport); + if (!res) + break; res->start = simple_strtoul(buf, &buf, 0); while (isspace(*buf)) ++buf; @@ -396,15 +399,16 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, res->end = res->start; res->flags = IORESOURCE_IO; nport++; - if (nport >= PNP_MAX_PORT) - break; continue; } if (!strnicmp(buf, "mem", 3)) { buf += 3; while (isspace(*buf)) ++buf; - res = &dev->res.mem_resource[nmem]; + res = pnp_get_resource(dev, IORESOURCE_MEM, + nmem); + if (!res) + break; res->start = simple_strtoul(buf, &buf, 0); while (isspace(*buf)) ++buf; @@ -417,34 +421,34 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, res->end = res->start; res->flags = IORESOURCE_MEM; nmem++; - if (nmem >= PNP_MAX_MEM) - break; continue; } if (!strnicmp(buf, "irq", 3)) { buf += 3; while (isspace(*buf)) ++buf; - res = &dev->res.irq_resource[nirq]; + res = pnp_get_resource(dev, IORESOURCE_IRQ, + nirq); + if (!res) + break; res->start = res->end = simple_strtoul(buf, &buf, 0); res->flags = IORESOURCE_IRQ; nirq++; - if (nirq >= PNP_MAX_IRQ) - break; continue; } if (!strnicmp(buf, "dma", 3)) { buf += 3; while (isspace(*buf)) ++buf; - res = &dev->res.dma_resource[ndma]; + res = pnp_get_resource(dev, IORESOURCE_DMA, + ndma); + if (!res) + break; res->start = res->end = simple_strtoul(buf, &buf, 0); res->flags = IORESOURCE_DMA; ndma++; - if (ndma >= PNP_MAX_DMA) - break; continue; } break; diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index 08865292fc95..7c5ebddfc6af 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c @@ -21,14 +21,13 @@ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) { struct resource *res; - if (idx >= PNP_MAX_PORT) { + res = pnp_get_resource(dev, IORESOURCE_IO, idx); + if (!res) { dev_err(&dev->dev, "too many I/O port resources\n"); /* pretend we were successful so at least the manager won't try again */ return 1; } - res = &dev->res.port_resource[idx]; - /* check if this resource has been manually set, if so skip */ if (!(res->flags & IORESOURCE_AUTO)) { dev_dbg(&dev->dev, " io %d already set to %#llx-%#llx " @@ -68,14 +67,13 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) { struct resource *res; - if (idx >= PNP_MAX_MEM) { + res = pnp_get_resource(dev, IORESOURCE_MEM, idx); + if (!res) { dev_err(&dev->dev, "too many memory resources\n"); /* pretend we were successful so at least the manager won't try again */ return 1; } - res = &dev->res.mem_resource[idx]; - /* check if this resource has been manually set, if so skip */ if (!(res->flags & IORESOURCE_AUTO)) { dev_dbg(&dev->dev, " mem %d already set to %#llx-%#llx " @@ -131,14 +129,13 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2 }; - if (idx >= PNP_MAX_IRQ) { + res = pnp_get_resource(dev, IORESOURCE_IRQ, idx); + if (!res) { dev_err(&dev->dev, "too many IRQ resources\n"); /* pretend we were successful so at least the manager won't try again */ return 1; } - res = &dev->res.irq_resource[idx]; - /* check if this resource has been manually set, if so skip */ if (!(res->flags & IORESOURCE_AUTO)) { dev_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n", @@ -188,13 +185,12 @@ static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) 1, 3, 5, 6, 7, 0, 2, 4 }; - if (idx >= PNP_MAX_DMA) { + res = pnp_get_resource(dev, IORESOURCE_DMA, idx); + if (!res) { dev_err(&dev->dev, "too many DMA resources\n"); return; } - res = &dev->res.dma_resource[idx]; - /* check if this resource has been manually set, if so skip */ if (!(res->flags & IORESOURCE_AUTO)) { dev_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n", diff --git a/drivers/pnp/support.c b/drivers/pnp/support.c index 3aeb154e27d6..3eba85ed729c 100644 --- a/drivers/pnp/support.c +++ b/drivers/pnp/support.c @@ -61,27 +61,27 @@ void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc) dev_dbg(&dev->dev, "current resources: %s\n", desc); for (i = 0; i < PNP_MAX_IRQ; i++) { - res = &dev->res.irq_resource[i]; - if (!(res->flags & IORESOURCE_UNSET)) + res = pnp_get_resource(dev, IORESOURCE_IRQ, i); + if (res && !(res->flags & IORESOURCE_UNSET)) dev_dbg(&dev->dev, " irq %lld flags %#lx\n", (unsigned long long) res->start, res->flags); } for (i = 0; i < PNP_MAX_DMA; i++) { - res = &dev->res.dma_resource[i]; - if (!(res->flags & IORESOURCE_UNSET)) + res = pnp_get_resource(dev, IORESOURCE_DMA, i); + if (res && !(res->flags & IORESOURCE_UNSET)) dev_dbg(&dev->dev, " dma %lld flags %#lx\n", (unsigned long long) res->start, res->flags); } for (i = 0; i < PNP_MAX_PORT; i++) { - res = &dev->res.port_resource[i]; - if (!(res->flags & IORESOURCE_UNSET)) + res = pnp_get_resource(dev, IORESOURCE_IO, i); + if (res && !(res->flags & IORESOURCE_UNSET)) dev_dbg(&dev->dev, " io %#llx-%#llx flags %#lx\n", (unsigned long long) res->start, (unsigned long long) res->end, res->flags); } for (i = 0; i < PNP_MAX_MEM; i++) { - res = &dev->res.mem_resource[i]; - if (!(res->flags & IORESOURCE_UNSET)) + res = pnp_get_resource(dev, IORESOURCE_MEM, i); + if (res && !(res->flags & IORESOURCE_UNSET)) dev_dbg(&dev->dev, " mem %#llx-%#llx flags %#lx\n", (unsigned long long) res->start, (unsigned long long) res->end, res->flags); -- cgit v1.2.2 From 95ab3669f7830682c7762e9c305a0c1dd44454cc Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:26 -0600 Subject: PNP: remove PNP_MAX_* uses Remove some PNP_MAX_* uses. The pnp_resource_table isn't dynamic yet, but with pnp_get_resource(), we can start moving away from the table size constants. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/pnp/interface.c | 41 +++++++++++++++++++---------------------- drivers/pnp/quirks.c | 13 +++++++------ drivers/pnp/resource.c | 48 ++++++++++++++++++++++++------------------------ drivers/pnp/system.c | 21 ++++++++++----------- 4 files changed, 60 insertions(+), 63 deletions(-) diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c index a608054a3e53..e9e66ed4fa31 100644 --- a/drivers/pnp/interface.c +++ b/drivers/pnp/interface.c @@ -248,6 +248,7 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf) { struct pnp_dev *dev = to_pnp_dev(dmdev); + struct resource *res; int i, ret; pnp_info_buffer_t *buffer; @@ -267,50 +268,46 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, else pnp_printf(buffer, "disabled\n"); - for (i = 0; i < PNP_MAX_PORT; i++) { - if (pnp_port_valid(dev, i)) { + for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) { + if (pnp_resource_valid(res)) { pnp_printf(buffer, "io"); - if (pnp_port_flags(dev, i) & IORESOURCE_DISABLED) + if (res->flags & IORESOURCE_DISABLED) pnp_printf(buffer, " disabled\n"); else pnp_printf(buffer, " 0x%llx-0x%llx\n", - (unsigned long long) - pnp_port_start(dev, i), - (unsigned long long)pnp_port_end(dev, - i)); + (unsigned long long) res->start, + (unsigned long long) res->end); } } - for (i = 0; i < PNP_MAX_MEM; i++) { - if (pnp_mem_valid(dev, i)) { + for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) { + if (pnp_resource_valid(res)) { pnp_printf(buffer, "mem"); - if (pnp_mem_flags(dev, i) & IORESOURCE_DISABLED) + if (res->flags & IORESOURCE_DISABLED) pnp_printf(buffer, " disabled\n"); else pnp_printf(buffer, " 0x%llx-0x%llx\n", - (unsigned long long) - pnp_mem_start(dev, i), - (unsigned long long)pnp_mem_end(dev, - i)); + (unsigned long long) res->start, + (unsigned long long) res->end); } } - for (i = 0; i < PNP_MAX_IRQ; i++) { - if (pnp_irq_valid(dev, i)) { + for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IRQ, i)); i++) { + if (pnp_resource_valid(res)) { pnp_printf(buffer, "irq"); - if (pnp_irq_flags(dev, i) & IORESOURCE_DISABLED) + if (res->flags & IORESOURCE_DISABLED) pnp_printf(buffer, " disabled\n"); else pnp_printf(buffer, " %lld\n", - (unsigned long long)pnp_irq(dev, i)); + (unsigned long long) res->start); } } - for (i = 0; i < PNP_MAX_DMA; i++) { - if (pnp_dma_valid(dev, i)) { + for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_DMA, i)); i++) { + if (pnp_resource_valid(res)) { pnp_printf(buffer, "dma"); - if (pnp_dma_flags(dev, i) & IORESOURCE_DISABLED) + if (res->flags & IORESOURCE_DISABLED) pnp_printf(buffer, " disabled\n"); else pnp_printf(buffer, " %lld\n", - (unsigned long long)pnp_dma(dev, i)); + (unsigned long long) res->start); } } ret = (buffer->curr - buf); diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c index c47dd252f449..d049a2279fea 100644 --- a/drivers/pnp/quirks.c +++ b/drivers/pnp/quirks.c @@ -138,13 +138,15 @@ static void quirk_system_pci_resources(struct pnp_dev *dev) pci_start = pci_resource_start(pdev, i); pci_end = pci_resource_end(pdev, i); - for (j = 0; j < PNP_MAX_MEM; j++) { - if (!pnp_mem_valid(dev, j) || - pnp_mem_len(dev, j) == 0) + for (j = 0; + (res = pnp_get_resource(dev, IORESOURCE_MEM, j)); + j++) { + if (res->flags & IORESOURCE_UNSET || + (res->start == 0 && res->end == 0)) continue; - pnp_start = pnp_mem_start(dev, j); - pnp_end = pnp_mem_end(dev, j); + pnp_start = res->start; + pnp_end = res->end; /* * If the PNP region doesn't overlap the PCI @@ -177,7 +179,6 @@ static void quirk_system_pci_resources(struct pnp_dev *dev) pci_name(pdev), i, (unsigned long long) pci_start, (unsigned long long) pci_end); - res = pnp_get_resource(dev, IORESOURCE_MEM, j); res->flags = 0; } } diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index b2516d62fcf6..84362818fa8b 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -269,9 +269,8 @@ int pnp_check_port(struct pnp_dev *dev, struct resource *res) } /* check for internal conflicts */ - for (i = 0; i < PNP_MAX_PORT; i++) { - tres = pnp_get_resource(dev, IORESOURCE_IO, i); - if (tres && tres != res && tres->flags & IORESOURCE_IO) { + for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) { + if (tres != res && tres->flags & IORESOURCE_IO) { tport = &tres->start; tend = &tres->end; if (ranged_conflict(port, end, tport, tend)) @@ -283,9 +282,10 @@ int pnp_check_port(struct pnp_dev *dev, struct resource *res) pnp_for_each_dev(tdev) { if (tdev == dev) continue; - for (i = 0; i < PNP_MAX_PORT; i++) { - tres = pnp_get_resource(tdev, IORESOURCE_IO, i); - if (tres && tres->flags & IORESOURCE_IO) { + for (i = 0; + (tres = pnp_get_resource(tdev, IORESOURCE_IO, i)); + i++) { + if (tres->flags & IORESOURCE_IO) { if (cannot_compare(tres->flags)) continue; tport = &tres->start; @@ -329,9 +329,8 @@ int pnp_check_mem(struct pnp_dev *dev, struct resource *res) } /* check for internal conflicts */ - for (i = 0; i < PNP_MAX_MEM; i++) { - tres = pnp_get_resource(dev, IORESOURCE_MEM, i); - if (tres && tres != res && tres->flags & IORESOURCE_MEM) { + for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) { + if (tres != res && tres->flags & IORESOURCE_MEM) { taddr = &tres->start; tend = &tres->end; if (ranged_conflict(addr, end, taddr, tend)) @@ -343,9 +342,10 @@ int pnp_check_mem(struct pnp_dev *dev, struct resource *res) pnp_for_each_dev(tdev) { if (tdev == dev) continue; - for (i = 0; i < PNP_MAX_MEM; i++) { - tres = pnp_get_resource(tdev, IORESOURCE_MEM, i); - if (tres && tres->flags & IORESOURCE_MEM) { + for (i = 0; + (tres = pnp_get_resource(tdev, IORESOURCE_MEM, i)); + i++) { + if (tres->flags & IORESOURCE_MEM) { if (cannot_compare(tres->flags)) continue; taddr = &tres->start; @@ -388,9 +388,8 @@ int pnp_check_irq(struct pnp_dev *dev, struct resource *res) } /* check for internal conflicts */ - for (i = 0; i < PNP_MAX_IRQ; i++) { - tres = pnp_get_resource(dev, IORESOURCE_IRQ, i); - if (tres && tres != res && tres->flags & IORESOURCE_IRQ) { + for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_IRQ, i)); i++) { + if (tres != res && tres->flags & IORESOURCE_IRQ) { if (tres->start == *irq) return 0; } @@ -422,9 +421,10 @@ int pnp_check_irq(struct pnp_dev *dev, struct resource *res) pnp_for_each_dev(tdev) { if (tdev == dev) continue; - for (i = 0; i < PNP_MAX_IRQ; i++) { - tres = pnp_get_resource(tdev, IORESOURCE_IRQ, i); - if (tres && tres->flags & IORESOURCE_IRQ) { + for (i = 0; + (tres = pnp_get_resource(tdev, IORESOURCE_IRQ, i)); + i++) { + if (tres->flags & IORESOURCE_IRQ) { if (cannot_compare(tres->flags)) continue; if (tres->start == *irq) @@ -461,9 +461,8 @@ int pnp_check_dma(struct pnp_dev *dev, struct resource *res) } /* check for internal conflicts */ - for (i = 0; i < PNP_MAX_DMA; i++) { - tres = pnp_get_resource(dev, IORESOURCE_DMA, i); - if (tres && tres != res && tres->flags & IORESOURCE_DMA) { + for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_DMA, i)); i++) { + if (tres != res && tres->flags & IORESOURCE_DMA) { if (tres->start == *dma) return 0; } @@ -481,9 +480,10 @@ int pnp_check_dma(struct pnp_dev *dev, struct resource *res) pnp_for_each_dev(tdev) { if (tdev == dev) continue; - for (i = 0; i < PNP_MAX_DMA; i++) { - tres = pnp_get_resource(tdev, IORESOURCE_DMA, i); - if (tres && tres->flags & IORESOURCE_DMA) { + for (i = 0; + (tres = pnp_get_resource(tdev, IORESOURCE_DMA, i)); + i++) { + if (tres->flags & IORESOURCE_DMA) { if (cannot_compare(tres->flags)) continue; if (tres->start == *dma) diff --git a/drivers/pnp/system.c b/drivers/pnp/system.c index 55c4563986b3..9c2496dbeee4 100644 --- a/drivers/pnp/system.c +++ b/drivers/pnp/system.c @@ -56,14 +56,15 @@ static void reserve_range(struct pnp_dev *dev, resource_size_t start, static void reserve_resources_of_dev(struct pnp_dev *dev) { + struct resource *res; int i; - for (i = 0; i < PNP_MAX_PORT; i++) { - if (!pnp_port_valid(dev, i)) + for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) { + if (res->flags & IORESOURCE_UNSET) continue; - if (pnp_port_start(dev, i) == 0) + if (res->start == 0) continue; /* disabled */ - if (pnp_port_start(dev, i) < 0x100) + if (res->start < 0x100) /* * Below 0x100 is only standard PC hardware * (pics, kbd, timer, dma, ...) @@ -73,19 +74,17 @@ static void reserve_resources_of_dev(struct pnp_dev *dev) * So, do nothing */ continue; - if (pnp_port_end(dev, i) < pnp_port_start(dev, i)) + if (res->end < res->start) continue; /* invalid */ - reserve_range(dev, pnp_port_start(dev, i), - pnp_port_end(dev, i), 1); + reserve_range(dev, res->start, res->end, 1); } - for (i = 0; i < PNP_MAX_MEM; i++) { - if (!pnp_mem_valid(dev, i)) + for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) { + if (res->flags & IORESOURCE_UNSET) continue; - reserve_range(dev, pnp_mem_start(dev, i), - pnp_mem_end(dev, i), 0); + reserve_range(dev, res->start, res->end, 0); } } -- cgit v1.2.2 From 8766ad0ce8621aa6f0e4a91ef355509cc3364d5b Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:27 -0600 Subject: rtc: dont reference pnp_resource_table directly pnp_resource_table is going away soon, so use the more generic public interfaces instead. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/rtc/rtc-cmos.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index dcdc142a3441..d060a06ce05b 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -854,11 +854,12 @@ cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) * don't define the IRQ. It should always be safe to * hardcode it in these cases */ - return cmos_do_probe(&pnp->dev, &pnp->res.port_resource[0], 8); + return cmos_do_probe(&pnp->dev, + pnp_get_resource(pnp, IORESOURCE_IO, 0), 8); else return cmos_do_probe(&pnp->dev, - &pnp->res.port_resource[0], - pnp->res.irq_resource[0].start); + pnp_get_resource(pnp, IORESOURCE_IO, 0), + pnp_irq(pnp, 0)); } static void __exit cmos_pnp_remove(struct pnp_dev *pnp) -- cgit v1.2.2 From 02d83b5da3efa3c278ce87db2637f3dd6837166d Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:28 -0600 Subject: PNP: make pnp_resource_table private to PNP core There are no remaining references to the PNP_MAX_* constants or the pnp_resource_table structure outside of the PNP core. Make them private to the PNP core. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/pnp/base.h | 12 ++++++++++++ drivers/pnp/core.c | 8 ++++++++ drivers/pnp/isapnp/core.c | 4 ++-- drivers/pnp/manager.c | 16 ++++++++-------- drivers/pnp/pnpacpi/rsparser.c | 10 ++++++---- drivers/pnp/pnpbios/rsparser.c | 8 ++++---- drivers/pnp/resource.c | 2 +- include/linux/pnp.h | 14 ++------------ 8 files changed, 43 insertions(+), 31 deletions(-) diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index e739d4bba423..b888a5fb6b7f 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h @@ -20,3 +20,15 @@ int pnp_check_dma(struct pnp_dev *dev, struct resource *res); void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc); void pnp_init_resource(struct resource *res); + +#define PNP_MAX_PORT 40 +#define PNP_MAX_MEM 24 +#define PNP_MAX_IRQ 2 +#define PNP_MAX_DMA 2 + +struct pnp_resource_table { + struct resource port_resource[PNP_MAX_PORT]; + struct resource mem_resource[PNP_MAX_MEM]; + struct resource dma_resource[PNP_MAX_DMA]; + struct resource irq_resource[PNP_MAX_IRQ]; +}; diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c index cf37701a4f9e..20771b7d4482 100644 --- a/drivers/pnp/core.c +++ b/drivers/pnp/core.c @@ -106,6 +106,7 @@ static void pnp_release_device(struct device *dmdev) pnp_free_option(dev->independent); pnp_free_option(dev->dependent); pnp_free_ids(dev); + kfree(dev->res); kfree(dev); } @@ -118,6 +119,12 @@ struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, char *pnpid if (!dev) return NULL; + dev->res = kzalloc(sizeof(struct pnp_resource_table), GFP_KERNEL); + if (!dev->res) { + kfree(dev); + return NULL; + } + dev->protocol = protocol; dev->number = id; dev->dma_mask = DMA_24BIT_MASK; @@ -133,6 +140,7 @@ struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, char *pnpid dev_id = pnp_add_id(dev, pnpid); if (!dev_id) { + kfree(dev->res); kfree(dev); return NULL; } diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index 990d8cd6295c..4407e844b5ea 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -931,7 +931,7 @@ EXPORT_SYMBOL(isapnp_write_byte); static int isapnp_read_resources(struct pnp_dev *dev) { - struct pnp_resource_table *res = &dev->res; + struct pnp_resource_table *res = dev->res; int tmp, ret; dev->active = isapnp_read_byte(ISAPNP_CFG_ACTIVATE); @@ -987,7 +987,7 @@ static int isapnp_get_resources(struct pnp_dev *dev) static int isapnp_set_resources(struct pnp_dev *dev) { - struct pnp_resource_table *res = &dev->res; + struct pnp_resource_table *res = dev->res; int tmp; dev_dbg(&dev->dev, "set resources\n"); diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index 7c5ebddfc6af..46a5e0e90d9a 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c @@ -247,22 +247,22 @@ void pnp_init_resources(struct pnp_dev *dev) int idx; for (idx = 0; idx < PNP_MAX_IRQ; idx++) { - res = &dev->res.irq_resource[idx]; + res = &dev->res->irq_resource[idx]; res->flags = IORESOURCE_IRQ; pnp_init_resource(res); } for (idx = 0; idx < PNP_MAX_DMA; idx++) { - res = &dev->res.dma_resource[idx]; + res = &dev->res->dma_resource[idx]; res->flags = IORESOURCE_DMA; pnp_init_resource(res); } for (idx = 0; idx < PNP_MAX_PORT; idx++) { - res = &dev->res.port_resource[idx]; + res = &dev->res->port_resource[idx]; res->flags = IORESOURCE_IO; pnp_init_resource(res); } for (idx = 0; idx < PNP_MAX_MEM; idx++) { - res = &dev->res.mem_resource[idx]; + res = &dev->res->mem_resource[idx]; res->flags = IORESOURCE_MEM; pnp_init_resource(res); } @@ -278,28 +278,28 @@ static void pnp_clean_resource_table(struct pnp_dev *dev) int idx; for (idx = 0; idx < PNP_MAX_IRQ; idx++) { - res = &dev->res.irq_resource[idx]; + res = &dev->res->irq_resource[idx]; if (res->flags & IORESOURCE_AUTO) { res->flags = IORESOURCE_IRQ; pnp_init_resource(res); } } for (idx = 0; idx < PNP_MAX_DMA; idx++) { - res = &dev->res.dma_resource[idx]; + res = &dev->res->dma_resource[idx]; if (res->flags & IORESOURCE_AUTO) { res->flags = IORESOURCE_DMA; pnp_init_resource(res); } } for (idx = 0; idx < PNP_MAX_PORT; idx++) { - res = &dev->res.port_resource[idx]; + res = &dev->res->port_resource[idx]; if (res->flags & IORESOURCE_AUTO) { res->flags = IORESOURCE_IO; pnp_init_resource(res); } } for (idx = 0; idx < PNP_MAX_MEM; idx++) { - res = &dev->res.mem_resource[idx]; + res = &dev->res->mem_resource[idx]; if (res->flags & IORESOURCE_AUTO) { res->flags = IORESOURCE_MEM; pnp_init_resource(res); diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 000a1b39f0b6..2669518b4795 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include "../base.h" #include "pnpacpi.h" #ifdef CONFIG_IA64 @@ -80,7 +82,7 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev, u32 gsi, int triggering, int polarity, int shareable) { - struct pnp_resource_table *res = &dev->res; + struct pnp_resource_table *res = dev->res; int i = 0; int irq; int p, t; @@ -176,7 +178,7 @@ static int dma_flags(int type, int bus_master, int transfer) static void pnpacpi_parse_allocated_dmaresource(struct pnp_dev *dev, u32 dma, int flags) { - struct pnp_resource_table *res = &dev->res; + struct pnp_resource_table *res = dev->res; int i = 0; static unsigned char warned; @@ -202,7 +204,7 @@ static void pnpacpi_parse_allocated_dmaresource(struct pnp_dev *dev, static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 io, u64 len, int io_decode) { - struct pnp_resource_table *res = &dev->res; + struct pnp_resource_table *res = dev->res; int i = 0; static unsigned char warned; @@ -230,7 +232,7 @@ static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev, u64 mem, u64 len, int write_protect) { - struct pnp_resource_table *res = &dev->res; + struct pnp_resource_table *res = dev->res; int i = 0; static unsigned char warned; diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c index c1f9e162d2c5..9f0538af0321 100644 --- a/drivers/pnp/pnpbios/rsparser.c +++ b/drivers/pnp/pnpbios/rsparser.c @@ -56,7 +56,7 @@ inline void pcibios_penalize_isa_irq(int irq, int active) static void pnpbios_parse_allocated_irqresource(struct pnp_dev *dev, int irq) { - struct pnp_resource_table *res = &dev->res; + struct pnp_resource_table *res = dev->res; int i = 0; while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) @@ -76,7 +76,7 @@ static void pnpbios_parse_allocated_irqresource(struct pnp_dev *dev, int irq) static void pnpbios_parse_allocated_dmaresource(struct pnp_dev *dev, int dma) { - struct pnp_resource_table *res = &dev->res; + struct pnp_resource_table *res = dev->res; int i = 0; while (i < PNP_MAX_DMA && @@ -96,7 +96,7 @@ static void pnpbios_parse_allocated_dmaresource(struct pnp_dev *dev, int dma) static void pnpbios_parse_allocated_ioresource(struct pnp_dev *dev, int io, int len) { - struct pnp_resource_table *res = &dev->res; + struct pnp_resource_table *res = dev->res; int i = 0; while (!(res->port_resource[i].flags & IORESOURCE_UNSET) @@ -116,7 +116,7 @@ static void pnpbios_parse_allocated_ioresource(struct pnp_dev *dev, static void pnpbios_parse_allocated_memresource(struct pnp_dev *dev, int mem, int len) { - struct pnp_resource_table *res = &dev->res; + struct pnp_resource_table *res = dev->res; int i = 0; while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index 84362818fa8b..f7adc7eefbf8 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -502,7 +502,7 @@ int pnp_check_dma(struct pnp_dev *dev, struct resource *res) struct resource *pnp_get_resource(struct pnp_dev *dev, unsigned int type, unsigned int num) { - struct pnp_resource_table *res = &dev->res; + struct pnp_resource_table *res = dev->res; switch (type) { case IORESOURCE_IO: diff --git a/include/linux/pnp.h b/include/linux/pnp.h index 1640562f3ebc..a5487b6a4e57 100644 --- a/include/linux/pnp.h +++ b/include/linux/pnp.h @@ -13,14 +13,11 @@ #include #include -#define PNP_MAX_PORT 40 -#define PNP_MAX_MEM 24 -#define PNP_MAX_IRQ 2 -#define PNP_MAX_DMA 2 #define PNP_NAME_LEN 50 struct pnp_protocol; struct pnp_dev; +struct pnp_resource_table; /* * Resource Management @@ -184,13 +181,6 @@ struct pnp_option { struct pnp_option *next; /* used to chain dependent resources */ }; -struct pnp_resource_table { - struct resource port_resource[PNP_MAX_PORT]; - struct resource mem_resource[PNP_MAX_MEM]; - struct resource dma_resource[PNP_MAX_DMA]; - struct resource irq_resource[PNP_MAX_IRQ]; -}; - /* * Device Management */ @@ -260,7 +250,7 @@ struct pnp_dev { int capabilities; struct pnp_option *independent; struct pnp_option *dependent; - struct pnp_resource_table res; + struct pnp_resource_table *res; char name[PNP_NAME_LEN]; /* contains a human-readable name */ unsigned short regs; /* ISAPnP: supported registers */ -- cgit v1.2.2 From 06cb58a6eb0b689f95a6c055cfc400fd30c500c6 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:29 -0600 Subject: PNP: remove pnp_resource_table references from resource decoders This removes a few more references to the pnp_resource_table. No functional change. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/pnp/isapnp/core.c | 95 ++++++++++++++++++++---------------------- drivers/pnp/pnpacpi/rsparser.c | 88 ++++++++++++++++++++------------------ drivers/pnp/pnpbios/rsparser.c | 82 ++++++++++++++++++++---------------- 3 files changed, 140 insertions(+), 125 deletions(-) diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index 4407e844b5ea..a62ecc6f13bd 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -931,7 +931,7 @@ EXPORT_SYMBOL(isapnp_write_byte); static int isapnp_read_resources(struct pnp_dev *dev) { - struct pnp_resource_table *res = dev->res; + struct resource *res; int tmp, ret; dev->active = isapnp_read_byte(ISAPNP_CFG_ACTIVATE); @@ -940,16 +940,18 @@ static int isapnp_read_resources(struct pnp_dev *dev) ret = isapnp_read_word(ISAPNP_CFG_PORT + (tmp << 1)); if (!ret) continue; - res->port_resource[tmp].start = ret; - res->port_resource[tmp].flags = IORESOURCE_IO; + res = pnp_get_resource(dev, IORESOURCE_IO, tmp); + res->start = ret; + res->flags = IORESOURCE_IO; } for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) { ret = isapnp_read_word(ISAPNP_CFG_MEM + (tmp << 3)) << 8; if (!ret) continue; - res->mem_resource[tmp].start = ret; - res->mem_resource[tmp].flags = IORESOURCE_MEM; + res = pnp_get_resource(dev, IORESOURCE_MEM, tmp); + res->start = ret; + res->flags = IORESOURCE_MEM; } for (tmp = 0; tmp < ISAPNP_MAX_IRQ; tmp++) { ret = @@ -957,17 +959,17 @@ static int isapnp_read_resources(struct pnp_dev *dev) 8); if (!ret) continue; - res->irq_resource[tmp].start = - res->irq_resource[tmp].end = ret; - res->irq_resource[tmp].flags = IORESOURCE_IRQ; + res = pnp_get_resource(dev, IORESOURCE_IRQ, tmp); + res->start = res->end = ret; + res->flags = IORESOURCE_IRQ; } for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) { ret = isapnp_read_byte(ISAPNP_CFG_DMA + tmp); if (ret == 4) continue; - res->dma_resource[tmp].start = - res->dma_resource[tmp].end = ret; - res->dma_resource[tmp].flags = IORESOURCE_DMA; + res = pnp_get_resource(dev, IORESOURCE_DMA, tmp); + res->start = res->end = ret; + res->flags = IORESOURCE_DMA; } } return 0; @@ -987,52 +989,47 @@ static int isapnp_get_resources(struct pnp_dev *dev) static int isapnp_set_resources(struct pnp_dev *dev) { - struct pnp_resource_table *res = dev->res; + struct resource *res; int tmp; dev_dbg(&dev->dev, "set resources\n"); isapnp_cfg_begin(dev->card->number, dev->number); dev->active = 1; - for (tmp = 0; - tmp < ISAPNP_MAX_PORT - && (res->port_resource[tmp]. - flags & (IORESOURCE_IO | IORESOURCE_UNSET)) == IORESOURCE_IO; - tmp++) { - dev_dbg(&dev->dev, " set io %d to %#llx\n", - tmp, (unsigned long long) res->port_resource[tmp].start); - isapnp_write_word(ISAPNP_CFG_PORT + (tmp << 1), - res->port_resource[tmp].start); + for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) { + res = pnp_get_resource(dev, IORESOURCE_IO, tmp); + if (pnp_resource_valid(res)) { + dev_dbg(&dev->dev, " set io %d to %#llx\n", + tmp, (unsigned long long) res->start); + isapnp_write_word(ISAPNP_CFG_PORT + (tmp << 1), + res->start); + } } - for (tmp = 0; - tmp < ISAPNP_MAX_IRQ - && (res->irq_resource[tmp]. - flags & (IORESOURCE_IRQ | IORESOURCE_UNSET)) == IORESOURCE_IRQ; - tmp++) { - int irq = res->irq_resource[tmp].start; - if (irq == 2) - irq = 9; - dev_dbg(&dev->dev, " set irq %d to %d\n", tmp, irq); - isapnp_write_byte(ISAPNP_CFG_IRQ + (tmp << 1), irq); + for (tmp = 0; tmp < ISAPNP_MAX_IRQ; tmp++) { + res = pnp_get_resource(dev, IORESOURCE_IRQ, tmp); + if (pnp_resource_valid(res)) { + int irq = res->start; + if (irq == 2) + irq = 9; + dev_dbg(&dev->dev, " set irq %d to %d\n", tmp, irq); + isapnp_write_byte(ISAPNP_CFG_IRQ + (tmp << 1), irq); + } } - for (tmp = 0; - tmp < ISAPNP_MAX_DMA - && (res->dma_resource[tmp]. - flags & (IORESOURCE_DMA | IORESOURCE_UNSET)) == IORESOURCE_DMA; - tmp++) { - dev_dbg(&dev->dev, " set dma %d to %lld\n", - tmp, (unsigned long long) res->dma_resource[tmp].start); - isapnp_write_byte(ISAPNP_CFG_DMA + tmp, - res->dma_resource[tmp].start); + for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) { + res = pnp_get_resource(dev, IORESOURCE_DMA, tmp); + if (pnp_resource_valid(res)) { + dev_dbg(&dev->dev, " set dma %d to %lld\n", + tmp, (unsigned long long) res->start); + isapnp_write_byte(ISAPNP_CFG_DMA + tmp, res->start); + } } - for (tmp = 0; - tmp < ISAPNP_MAX_MEM - && (res->mem_resource[tmp]. - flags & (IORESOURCE_MEM | IORESOURCE_UNSET)) == IORESOURCE_MEM; - tmp++) { - dev_dbg(&dev->dev, " set mem %d to %#llx\n", - tmp, (unsigned long long) res->mem_resource[tmp].start); - isapnp_write_word(ISAPNP_CFG_MEM + (tmp << 3), - (res->mem_resource[tmp].start >> 8) & 0xffff); + for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) { + res = pnp_get_resource(dev, IORESOURCE_MEM, tmp); + if (pnp_resource_valid(res)) { + dev_dbg(&dev->dev, " set mem %d to %#llx\n", + tmp, (unsigned long long) res->start); + isapnp_write_word(ISAPNP_CFG_MEM + (tmp << 3), + (res->start >> 8) & 0xffff); + } } /* FIXME: We aren't handling 32bit mems properly here */ isapnp_activate(dev->number); diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 2669518b4795..3634f2f3f745 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -82,8 +82,8 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev, u32 gsi, int triggering, int polarity, int shareable) { - struct pnp_resource_table *res = dev->res; - int i = 0; + struct resource *res; + int i; int irq; int p, t; static unsigned char warned; @@ -91,9 +91,11 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev, if (!valid_IRQ(gsi)) return; - while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) && - i < PNP_MAX_IRQ) - i++; + for (i = 0; i < PNP_MAX_IRQ; i++) { + res = pnp_get_resource(dev, IORESOURCE_IRQ, i); + if (!pnp_resource_valid(res)) + break; + } if (i >= PNP_MAX_IRQ) { if (!warned) { printk(KERN_WARNING "pnpacpi: exceeded the max number" @@ -119,16 +121,16 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev, } } - res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag - res->irq_resource[i].flags |= irq_flags(triggering, polarity, shareable); + res->flags = IORESOURCE_IRQ; // Also clears _UNSET flag + res->flags |= irq_flags(triggering, polarity, shareable); irq = acpi_register_gsi(gsi, triggering, polarity); if (irq < 0) { - res->irq_resource[i].flags |= IORESOURCE_DISABLED; + res->flags |= IORESOURCE_DISABLED; return; } - res->irq_resource[i].start = irq; - res->irq_resource[i].end = irq; + res->start = irq; + res->end = irq; pcibios_penalize_isa_irq(irq, 1); } @@ -178,22 +180,24 @@ static int dma_flags(int type, int bus_master, int transfer) static void pnpacpi_parse_allocated_dmaresource(struct pnp_dev *dev, u32 dma, int flags) { - struct pnp_resource_table *res = dev->res; - int i = 0; + struct resource *res; + int i; static unsigned char warned; - while (i < PNP_MAX_DMA && - !(res->dma_resource[i].flags & IORESOURCE_UNSET)) - i++; + for (i = 0; i < PNP_MAX_DMA; i++) { + res = pnp_get_resource(dev, IORESOURCE_DMA, i); + if (!pnp_resource_valid(res)) + break; + } if (i < PNP_MAX_DMA) { - res->dma_resource[i].flags = IORESOURCE_DMA; // Also clears _UNSET flag - res->dma_resource[i].flags |= flags; + res->flags = IORESOURCE_DMA; // Also clears _UNSET flag + res->flags |= flags; if (dma == -1) { - res->dma_resource[i].flags |= IORESOURCE_DISABLED; + res->flags |= IORESOURCE_DISABLED; return; } - res->dma_resource[i].start = dma; - res->dma_resource[i].end = dma; + res->start = dma; + res->end = dma; } else if (!warned) { printk(KERN_WARNING "pnpacpi: exceeded the max number of DMA " "resources: %d \n", PNP_MAX_DMA); @@ -204,23 +208,25 @@ static void pnpacpi_parse_allocated_dmaresource(struct pnp_dev *dev, static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 io, u64 len, int io_decode) { - struct pnp_resource_table *res = dev->res; - int i = 0; + struct resource *res; + int i; static unsigned char warned; - while (!(res->port_resource[i].flags & IORESOURCE_UNSET) && - i < PNP_MAX_PORT) - i++; + for (i = 0; i < PNP_MAX_PORT; i++) { + res = pnp_get_resource(dev, IORESOURCE_IO, i); + if (!pnp_resource_valid(res)) + break; + } if (i < PNP_MAX_PORT) { - res->port_resource[i].flags = IORESOURCE_IO; // Also clears _UNSET flag + res->flags = IORESOURCE_IO; // Also clears _UNSET flag if (io_decode == ACPI_DECODE_16) - res->port_resource[i].flags |= PNP_PORT_FLAG_16BITADDR; + res->flags |= PNP_PORT_FLAG_16BITADDR; if (len <= 0 || (io + len - 1) >= 0x10003) { - res->port_resource[i].flags |= IORESOURCE_DISABLED; + res->flags |= IORESOURCE_DISABLED; return; } - res->port_resource[i].start = io; - res->port_resource[i].end = io + len - 1; + res->start = io; + res->end = io + len - 1; } else if (!warned) { printk(KERN_WARNING "pnpacpi: exceeded the max number of IO " "resources: %d \n", PNP_MAX_PORT); @@ -232,24 +238,26 @@ static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev, u64 mem, u64 len, int write_protect) { - struct pnp_resource_table *res = dev->res; - int i = 0; + struct resource *res; + int i; static unsigned char warned; - while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) && - (i < PNP_MAX_MEM)) - i++; + for (i = 0; i < PNP_MAX_MEM; i++) { + res = pnp_get_resource(dev, IORESOURCE_MEM, i); + if (!pnp_resource_valid(res)) + break; + } if (i < PNP_MAX_MEM) { - res->mem_resource[i].flags = IORESOURCE_MEM; // Also clears _UNSET flag + res->flags = IORESOURCE_MEM; // Also clears _UNSET flag if (len <= 0) { - res->mem_resource[i].flags |= IORESOURCE_DISABLED; + res->flags |= IORESOURCE_DISABLED; return; } if (write_protect == ACPI_READ_WRITE_MEMORY) - res->mem_resource[i].flags |= IORESOURCE_MEM_WRITEABLE; + res->flags |= IORESOURCE_MEM_WRITEABLE; - res->mem_resource[i].start = mem; - res->mem_resource[i].end = mem + len - 1; + res->start = mem; + res->end = mem + len - 1; } else if (!warned) { printk(KERN_WARNING "pnpacpi: exceeded the max number of mem " "resources: %d\n", PNP_MAX_MEM); diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c index 9f0538af0321..d3b0a4e53692 100644 --- a/drivers/pnp/pnpbios/rsparser.c +++ b/drivers/pnp/pnpbios/rsparser.c @@ -56,80 +56,90 @@ inline void pcibios_penalize_isa_irq(int irq, int active) static void pnpbios_parse_allocated_irqresource(struct pnp_dev *dev, int irq) { - struct pnp_resource_table *res = dev->res; - int i = 0; + struct resource *res; + int i; + + for (i = 0; i < PNP_MAX_IRQ; i++) { + res = pnp_get_resource(dev, IORESOURCE_IRQ, i); + if (!pnp_resource_valid(res)) + break; + } - while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) - && i < PNP_MAX_IRQ) - i++; if (i < PNP_MAX_IRQ) { - res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag + res->flags = IORESOURCE_IRQ; // Also clears _UNSET flag if (irq == -1) { - res->irq_resource[i].flags |= IORESOURCE_DISABLED; + res->flags |= IORESOURCE_DISABLED; return; } - res->irq_resource[i].start = - res->irq_resource[i].end = (unsigned long)irq; + res->start = res->end = (unsigned long)irq; pcibios_penalize_isa_irq(irq, 1); } } static void pnpbios_parse_allocated_dmaresource(struct pnp_dev *dev, int dma) { - struct pnp_resource_table *res = dev->res; - int i = 0; + struct resource *res; + int i; + + for (i = 0; i < PNP_MAX_DMA; i++) { + res = pnp_get_resource(dev, IORESOURCE_DMA, i); + if (!pnp_resource_valid(res)) + break; + } - while (i < PNP_MAX_DMA && - !(res->dma_resource[i].flags & IORESOURCE_UNSET)) - i++; if (i < PNP_MAX_DMA) { - res->dma_resource[i].flags = IORESOURCE_DMA; // Also clears _UNSET flag + res->flags = IORESOURCE_DMA; // Also clears _UNSET flag if (dma == -1) { - res->dma_resource[i].flags |= IORESOURCE_DISABLED; + res->flags |= IORESOURCE_DISABLED; return; } - res->dma_resource[i].start = - res->dma_resource[i].end = (unsigned long)dma; + res->start = res->end = (unsigned long)dma; } } static void pnpbios_parse_allocated_ioresource(struct pnp_dev *dev, int io, int len) { - struct pnp_resource_table *res = dev->res; - int i = 0; + struct resource *res; + int i; + + for (i = 0; i < PNP_MAX_PORT; i++) { + res = pnp_get_resource(dev, IORESOURCE_IO, i); + if (!pnp_resource_valid(res)) + break; + } - while (!(res->port_resource[i].flags & IORESOURCE_UNSET) - && i < PNP_MAX_PORT) - i++; if (i < PNP_MAX_PORT) { - res->port_resource[i].flags = IORESOURCE_IO; // Also clears _UNSET flag + res->flags = IORESOURCE_IO; // Also clears _UNSET flag if (len <= 0 || (io + len - 1) >= 0x10003) { - res->port_resource[i].flags |= IORESOURCE_DISABLED; + res->flags |= IORESOURCE_DISABLED; return; } - res->port_resource[i].start = (unsigned long)io; - res->port_resource[i].end = (unsigned long)(io + len - 1); + res->start = (unsigned long)io; + res->end = (unsigned long)(io + len - 1); } } static void pnpbios_parse_allocated_memresource(struct pnp_dev *dev, int mem, int len) { - struct pnp_resource_table *res = dev->res; - int i = 0; + struct resource *res; + int i; + + for (i = 0; i < PNP_MAX_MEM; i++) { + res = pnp_get_resource(dev, IORESOURCE_MEM, i); + if (!pnp_resource_valid(res)) + break; + } - while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) - && i < PNP_MAX_MEM) - i++; if (i < PNP_MAX_MEM) { - res->mem_resource[i].flags = IORESOURCE_MEM; // Also clears _UNSET flag + res->flags = IORESOURCE_MEM; // Also clears _UNSET flag if (len <= 0) { - res->mem_resource[i].flags |= IORESOURCE_DISABLED; + res->flags |= IORESOURCE_DISABLED; return; } - res->mem_resource[i].start = (unsigned long)mem; - res->mem_resource[i].end = (unsigned long)(mem + len - 1); + res->start = (unsigned long)mem; + res->end = (unsigned long)(mem + len - 1); } } -- cgit v1.2.2 From 784f01d5bdeae7d7005ede17305306b042ba2617 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:30 -0600 Subject: PNP: add struct pnp_resource This patch adds a "struct pnp_resource". This currently contains only a struct resource, but we will soon need additional PNP-specific information. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/pnp/base.h | 12 ++++++++---- drivers/pnp/manager.c | 16 ++++++++-------- drivers/pnp/resource.c | 8 ++++---- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index b888a5fb6b7f..1d6bb351d323 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h @@ -26,9 +26,13 @@ void pnp_init_resource(struct resource *res); #define PNP_MAX_IRQ 2 #define PNP_MAX_DMA 2 +struct pnp_resource { + struct resource res; +}; + struct pnp_resource_table { - struct resource port_resource[PNP_MAX_PORT]; - struct resource mem_resource[PNP_MAX_MEM]; - struct resource dma_resource[PNP_MAX_DMA]; - struct resource irq_resource[PNP_MAX_IRQ]; + struct pnp_resource port[PNP_MAX_PORT]; + struct pnp_resource mem[PNP_MAX_MEM]; + struct pnp_resource dma[PNP_MAX_DMA]; + struct pnp_resource irq[PNP_MAX_IRQ]; }; diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index 46a5e0e90d9a..4823da27e640 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c @@ -247,22 +247,22 @@ void pnp_init_resources(struct pnp_dev *dev) int idx; for (idx = 0; idx < PNP_MAX_IRQ; idx++) { - res = &dev->res->irq_resource[idx]; + res = &dev->res->irq[idx].res; res->flags = IORESOURCE_IRQ; pnp_init_resource(res); } for (idx = 0; idx < PNP_MAX_DMA; idx++) { - res = &dev->res->dma_resource[idx]; + res = &dev->res->dma[idx].res; res->flags = IORESOURCE_DMA; pnp_init_resource(res); } for (idx = 0; idx < PNP_MAX_PORT; idx++) { - res = &dev->res->port_resource[idx]; + res = &dev->res->port[idx].res; res->flags = IORESOURCE_IO; pnp_init_resource(res); } for (idx = 0; idx < PNP_MAX_MEM; idx++) { - res = &dev->res->mem_resource[idx]; + res = &dev->res->mem[idx].res; res->flags = IORESOURCE_MEM; pnp_init_resource(res); } @@ -278,28 +278,28 @@ static void pnp_clean_resource_table(struct pnp_dev *dev) int idx; for (idx = 0; idx < PNP_MAX_IRQ; idx++) { - res = &dev->res->irq_resource[idx]; + res = &dev->res->irq[idx].res; if (res->flags & IORESOURCE_AUTO) { res->flags = IORESOURCE_IRQ; pnp_init_resource(res); } } for (idx = 0; idx < PNP_MAX_DMA; idx++) { - res = &dev->res->dma_resource[idx]; + res = &dev->res->dma[idx].res; if (res->flags & IORESOURCE_AUTO) { res->flags = IORESOURCE_DMA; pnp_init_resource(res); } } for (idx = 0; idx < PNP_MAX_PORT; idx++) { - res = &dev->res->port_resource[idx]; + res = &dev->res->port[idx].res; if (res->flags & IORESOURCE_AUTO) { res->flags = IORESOURCE_IO; pnp_init_resource(res); } } for (idx = 0; idx < PNP_MAX_MEM; idx++) { - res = &dev->res->mem_resource[idx]; + res = &dev->res->mem[idx].res; if (res->flags & IORESOURCE_AUTO) { res->flags = IORESOURCE_MEM; pnp_init_resource(res); diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index f7adc7eefbf8..7e9f4300e5f6 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -508,19 +508,19 @@ struct resource *pnp_get_resource(struct pnp_dev *dev, case IORESOURCE_IO: if (num >= PNP_MAX_PORT) return NULL; - return &res->port_resource[num]; + return &res->port[num].res; case IORESOURCE_MEM: if (num >= PNP_MAX_MEM) return NULL; - return &res->mem_resource[num]; + return &res->mem[num].res; case IORESOURCE_IRQ: if (num >= PNP_MAX_IRQ) return NULL; - return &res->irq_resource[num]; + return &res->irq[num].res; case IORESOURCE_DMA: if (num >= PNP_MAX_DMA) return NULL; - return &res->dma_resource[num]; + return &res->dma[num].res; } return NULL; } -- cgit v1.2.2 From 0a977f15469457d9a19eed992caf71995c674064 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:31 -0600 Subject: PNP: add pnp_get_pnp_resource() In some places, we need to get the struct pnp_resource, not just the struct resource, because ISAPNP needs to store the register index in the pnp_resource. I don't like pnp_get_pnp_resource() and hope that it is temporary, but we need it for a little while. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/pnp/base.h | 3 +++ drivers/pnp/resource.c | 24 ++++++++++++++++++------ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index 1d6bb351d323..49b4138f3476 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h @@ -21,6 +21,9 @@ void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc); void pnp_init_resource(struct resource *res); +struct pnp_resource *pnp_get_pnp_resource(struct pnp_dev *dev, + unsigned int type, unsigned int num); + #define PNP_MAX_PORT 40 #define PNP_MAX_MEM 24 #define PNP_MAX_IRQ 2 diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index 7e9f4300e5f6..c57cfe51d52a 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -499,8 +499,8 @@ int pnp_check_dma(struct pnp_dev *dev, struct resource *res) #endif } -struct resource *pnp_get_resource(struct pnp_dev *dev, - unsigned int type, unsigned int num) +struct pnp_resource *pnp_get_pnp_resource(struct pnp_dev *dev, + unsigned int type, unsigned int num) { struct pnp_resource_table *res = dev->res; @@ -508,22 +508,34 @@ struct resource *pnp_get_resource(struct pnp_dev *dev, case IORESOURCE_IO: if (num >= PNP_MAX_PORT) return NULL; - return &res->port[num].res; + return &res->port[num]; case IORESOURCE_MEM: if (num >= PNP_MAX_MEM) return NULL; - return &res->mem[num].res; + return &res->mem[num]; case IORESOURCE_IRQ: if (num >= PNP_MAX_IRQ) return NULL; - return &res->irq[num].res; + return &res->irq[num]; case IORESOURCE_DMA: if (num >= PNP_MAX_DMA) return NULL; - return &res->dma[num].res; + return &res->dma[num]; } return NULL; } + +struct resource *pnp_get_resource(struct pnp_dev *dev, + unsigned int type, unsigned int num) +{ + struct pnp_resource *pnp_res; + + pnp_res = pnp_get_pnp_resource(dev, type, num); + if (pnp_res) + return &pnp_res->res; + + return NULL; +} EXPORT_SYMBOL(pnp_get_resource); /* format is: pnp_reserve_irq=irq1[,irq2] .... */ -- cgit v1.2.2 From 21855d69d1e3ace3efdb8159a4a7ab1ab98a6f19 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:32 -0600 Subject: PNP: add pnp_resource index for ISAPNP Save the ISAPNP config register index in the struct pnp_resource. We need this because it is important to write ISAPNP configuration back to the same registers we read it from. For example, if we read valid regions from memory descriptors 0, 1, and 3, we'd better write them back to the same registers, without compressing them to descriptors 0, 1, and 2. This was previously guaranteed by using the index into the pnp_resource_table array as the ISAPNP config register index. However, I am removing those fixed-size arrays, so we need to save the ISAPNP register index elsewhere. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/pnp/base.h | 1 + drivers/pnp/interface.c | 33 ++++++++++++++++--------- drivers/pnp/isapnp/core.c | 63 ++++++++++++++++++++++++++++++++++------------- drivers/pnp/manager.c | 32 ++++++++++++++++++------ 4 files changed, 92 insertions(+), 37 deletions(-) diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index 49b4138f3476..786735770684 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h @@ -31,6 +31,7 @@ struct pnp_resource *pnp_get_pnp_resource(struct pnp_dev *dev, struct pnp_resource { struct resource res; + unsigned int index; /* ISAPNP config register index */ }; struct pnp_resource_table { diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c index e9e66ed4fa31..ead151242a64 100644 --- a/drivers/pnp/interface.c +++ b/drivers/pnp/interface.c @@ -320,6 +320,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, const char *ubuf, size_t count) { struct pnp_dev *dev = to_pnp_dev(dmdev); + struct pnp_resource *pnp_res; struct resource *res; char *buf = (void *)ubuf; int retval = 0; @@ -380,10 +381,12 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, buf += 2; while (isspace(*buf)) ++buf; - res = pnp_get_resource(dev, IORESOURCE_IO, - nport); - if (!res) + pnp_res = pnp_get_pnp_resource(dev, + IORESOURCE_IO, nport); + if (!pnp_res) break; + pnp_res->index = nport; + res = &pnp_res->res; res->start = simple_strtoul(buf, &buf, 0); while (isspace(*buf)) ++buf; @@ -402,10 +405,12 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, buf += 3; while (isspace(*buf)) ++buf; - res = pnp_get_resource(dev, IORESOURCE_MEM, - nmem); - if (!res) + pnp_res = pnp_get_pnp_resource(dev, + IORESOURCE_MEM, nmem); + if (!pnp_res) break; + pnp_res->index = nmem; + res = &pnp_res->res; res->start = simple_strtoul(buf, &buf, 0); while (isspace(*buf)) ++buf; @@ -424,10 +429,12 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, buf += 3; while (isspace(*buf)) ++buf; - res = pnp_get_resource(dev, IORESOURCE_IRQ, - nirq); - if (!res) + pnp_res = pnp_get_pnp_resource(dev, + IORESOURCE_IRQ, nirq); + if (!pnp_res) break; + pnp_res->index = nirq; + res = &pnp_res->res; res->start = res->end = simple_strtoul(buf, &buf, 0); res->flags = IORESOURCE_IRQ; @@ -438,10 +445,12 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, buf += 3; while (isspace(*buf)) ++buf; - res = pnp_get_resource(dev, IORESOURCE_DMA, - ndma); - if (!res) + pnp_res = pnp_get_pnp_resource(dev, + IORESOURCE_DMA, ndma); + if (!pnp_res) break; + pnp_res->index = ndma; + res = &pnp_res->res; res->start = res->end = simple_strtoul(buf, &buf, 0); res->flags = IORESOURCE_DMA; diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index a62ecc6f13bd..f949a538ccde 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -931,6 +931,7 @@ EXPORT_SYMBOL(isapnp_write_byte); static int isapnp_read_resources(struct pnp_dev *dev) { + struct pnp_resource *pnp_res; struct resource *res; int tmp, ret; @@ -940,7 +941,9 @@ static int isapnp_read_resources(struct pnp_dev *dev) ret = isapnp_read_word(ISAPNP_CFG_PORT + (tmp << 1)); if (!ret) continue; - res = pnp_get_resource(dev, IORESOURCE_IO, tmp); + pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, tmp); + pnp_res->index = tmp; + res = &pnp_res->res; res->start = ret; res->flags = IORESOURCE_IO; } @@ -949,7 +952,10 @@ static int isapnp_read_resources(struct pnp_dev *dev) isapnp_read_word(ISAPNP_CFG_MEM + (tmp << 3)) << 8; if (!ret) continue; - res = pnp_get_resource(dev, IORESOURCE_MEM, tmp); + pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, + tmp); + pnp_res->index = tmp; + res = &pnp_res->res; res->start = ret; res->flags = IORESOURCE_MEM; } @@ -959,7 +965,10 @@ static int isapnp_read_resources(struct pnp_dev *dev) 8); if (!ret) continue; - res = pnp_get_resource(dev, IORESOURCE_IRQ, tmp); + pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, + tmp); + pnp_res->index = tmp; + res = &pnp_res->res; res->start = res->end = ret; res->flags = IORESOURCE_IRQ; } @@ -967,7 +976,10 @@ static int isapnp_read_resources(struct pnp_dev *dev) ret = isapnp_read_byte(ISAPNP_CFG_DMA + tmp); if (ret == 4) continue; - res = pnp_get_resource(dev, IORESOURCE_DMA, tmp); + pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, + tmp); + pnp_res->index = tmp; + res = &pnp_res->res; res->start = res->end = ret; res->flags = IORESOURCE_DMA; } @@ -989,45 +1001,62 @@ static int isapnp_get_resources(struct pnp_dev *dev) static int isapnp_set_resources(struct pnp_dev *dev) { + struct pnp_resource *pnp_res; struct resource *res; - int tmp; + int tmp, index; dev_dbg(&dev->dev, "set resources\n"); isapnp_cfg_begin(dev->card->number, dev->number); dev->active = 1; for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) { - res = pnp_get_resource(dev, IORESOURCE_IO, tmp); + pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, tmp); + if (!pnp_res) + continue; + res = &pnp_res->res; if (pnp_resource_valid(res)) { + index = pnp_res->index; dev_dbg(&dev->dev, " set io %d to %#llx\n", - tmp, (unsigned long long) res->start); - isapnp_write_word(ISAPNP_CFG_PORT + (tmp << 1), + index, (unsigned long long) res->start); + isapnp_write_word(ISAPNP_CFG_PORT + (index << 1), res->start); } } for (tmp = 0; tmp < ISAPNP_MAX_IRQ; tmp++) { - res = pnp_get_resource(dev, IORESOURCE_IRQ, tmp); + pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, tmp); + if (!pnp_res) + continue; + res = &pnp_res->res; if (pnp_resource_valid(res)) { int irq = res->start; if (irq == 2) irq = 9; - dev_dbg(&dev->dev, " set irq %d to %d\n", tmp, irq); - isapnp_write_byte(ISAPNP_CFG_IRQ + (tmp << 1), irq); + index = pnp_res->index; + dev_dbg(&dev->dev, " set irq %d to %d\n", index, irq); + isapnp_write_byte(ISAPNP_CFG_IRQ + (index << 1), irq); } } for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) { - res = pnp_get_resource(dev, IORESOURCE_DMA, tmp); + pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, tmp); + if (!pnp_res) + continue; + res = &pnp_res->res; if (pnp_resource_valid(res)) { + index = pnp_res->index; dev_dbg(&dev->dev, " set dma %d to %lld\n", - tmp, (unsigned long long) res->start); - isapnp_write_byte(ISAPNP_CFG_DMA + tmp, res->start); + index, (unsigned long long) res->start); + isapnp_write_byte(ISAPNP_CFG_DMA + index, res->start); } } for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) { - res = pnp_get_resource(dev, IORESOURCE_MEM, tmp); + pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, tmp); + if (!pnp_res) + continue; + res = &pnp_res->res; if (pnp_resource_valid(res)) { + index = pnp_res->index; dev_dbg(&dev->dev, " set mem %d to %#llx\n", - tmp, (unsigned long long) res->start); - isapnp_write_word(ISAPNP_CFG_MEM + (tmp << 3), + index, (unsigned long long) res->start); + isapnp_write_word(ISAPNP_CFG_MEM + (index << 3), (res->start >> 8) & 0xffff); } } diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index 4823da27e640..bea0914ff947 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c @@ -19,15 +19,18 @@ DEFINE_MUTEX(pnp_res_mutex); static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) { + struct pnp_resource *pnp_res; struct resource *res; - res = pnp_get_resource(dev, IORESOURCE_IO, idx); - if (!res) { + pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, idx); + if (!pnp_res) { dev_err(&dev->dev, "too many I/O port resources\n"); /* pretend we were successful so at least the manager won't try again */ return 1; } + res = &pnp_res->res; + /* check if this resource has been manually set, if so skip */ if (!(res->flags & IORESOURCE_AUTO)) { dev_dbg(&dev->dev, " io %d already set to %#llx-%#llx " @@ -37,6 +40,7 @@ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) } /* set the initial values */ + pnp_res->index = idx; res->flags |= rule->flags | IORESOURCE_IO; res->flags &= ~IORESOURCE_UNSET; @@ -65,15 +69,18 @@ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) { + struct pnp_resource *pnp_res; struct resource *res; - res = pnp_get_resource(dev, IORESOURCE_MEM, idx); - if (!res) { + pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, idx); + if (!pnp_res) { dev_err(&dev->dev, "too many memory resources\n"); /* pretend we were successful so at least the manager won't try again */ return 1; } + res = &pnp_res->res; + /* check if this resource has been manually set, if so skip */ if (!(res->flags & IORESOURCE_AUTO)) { dev_dbg(&dev->dev, " mem %d already set to %#llx-%#llx " @@ -83,6 +90,7 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) } /* set the initial values */ + pnp_res->index = idx; res->flags |= rule->flags | IORESOURCE_MEM; res->flags &= ~IORESOURCE_UNSET; @@ -121,6 +129,7 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) { + struct pnp_resource *pnp_res; struct resource *res; int i; @@ -129,13 +138,15 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2 }; - res = pnp_get_resource(dev, IORESOURCE_IRQ, idx); - if (!res) { + pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, idx); + if (!pnp_res) { dev_err(&dev->dev, "too many IRQ resources\n"); /* pretend we were successful so at least the manager won't try again */ return 1; } + res = &pnp_res->res; + /* check if this resource has been manually set, if so skip */ if (!(res->flags & IORESOURCE_AUTO)) { dev_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n", @@ -144,6 +155,7 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) } /* set the initial values */ + pnp_res->index = idx; res->flags |= rule->flags | IORESOURCE_IRQ; res->flags &= ~IORESOURCE_UNSET; @@ -177,6 +189,7 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) { + struct pnp_resource *pnp_res; struct resource *res; int i; @@ -185,12 +198,14 @@ static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) 1, 3, 5, 6, 7, 0, 2, 4 }; - res = pnp_get_resource(dev, IORESOURCE_DMA, idx); - if (!res) { + pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, idx); + if (!pnp_res) { dev_err(&dev->dev, "too many DMA resources\n"); return; } + res = &pnp_res->res; + /* check if this resource has been manually set, if so skip */ if (!(res->flags & IORESOURCE_AUTO)) { dev_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n", @@ -199,6 +214,7 @@ static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) } /* set the initial values */ + pnp_res->index = idx; res->flags |= rule->flags | IORESOURCE_DMA; res->flags &= ~IORESOURCE_UNSET; -- cgit v1.2.2 From a50b6d7b8d7e1a8b13bd1be65a865b115e1190d9 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:33 -0600 Subject: PNP: add pnp_new_resource() to find a new unset pnp_resource This encapsulates the code to locate a new pnp_resource of the desired type. Currently this uses the pnp_resource_table, but it will soon change to find a resource in a linked list. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/pnp/resource.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index c57cfe51d52a..1f4134eea7b7 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -538,6 +538,44 @@ struct resource *pnp_get_resource(struct pnp_dev *dev, } EXPORT_SYMBOL(pnp_get_resource); +static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev, int type) +{ + struct pnp_resource *pnp_res; + int i; + + switch (type) { + case IORESOURCE_IO: + for (i = 0; i < PNP_MAX_PORT; i++) { + pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, i); + if (pnp_res && !pnp_resource_valid(&pnp_res->res)) + return pnp_res; + } + break; + case IORESOURCE_MEM: + for (i = 0; i < PNP_MAX_MEM; i++) { + pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, i); + if (pnp_res && !pnp_resource_valid(&pnp_res->res)) + return pnp_res; + } + break; + case IORESOURCE_IRQ: + for (i = 0; i < PNP_MAX_IRQ; i++) { + pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, i); + if (pnp_res && !pnp_resource_valid(&pnp_res->res)) + return pnp_res; + } + break; + case IORESOURCE_DMA: + for (i = 0; i < PNP_MAX_DMA; i++) { + pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, i); + if (pnp_res && !pnp_resource_valid(&pnp_res->res)) + return pnp_res; + } + break; + } + return NULL; +} + /* format is: pnp_reserve_irq=irq1[,irq2] .... */ static int __init pnp_setup_reserve_irq(char *str) { -- cgit v1.2.2 From dbddd0383c59d588f8db5e773b062756e39117ec Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:34 -0600 Subject: PNP: make generic pnp_add_irq_resource() Add a pnp_add_irq_resource() that can be used by all the PNP backends. This consolidates a little more pnp_resource_table knowledge into one place. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/pnp/base.h | 3 +++ drivers/pnp/interface.c | 15 +++++---------- drivers/pnp/isapnp/core.c | 9 +++------ drivers/pnp/pnpacpi/rsparser.c | 33 +++++++-------------------------- drivers/pnp/pnpbios/rsparser.c | 31 +++++++------------------------ drivers/pnp/resource.c | 26 ++++++++++++++++++++++++++ 6 files changed, 51 insertions(+), 66 deletions(-) diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index 786735770684..3dd5d849c30f 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h @@ -40,3 +40,6 @@ struct pnp_resource_table { struct pnp_resource dma[PNP_MAX_DMA]; struct pnp_resource irq[PNP_MAX_IRQ]; }; + +struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, + int flags); diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c index ead151242a64..e8134c286207 100644 --- a/drivers/pnp/interface.c +++ b/drivers/pnp/interface.c @@ -324,6 +324,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, struct resource *res; char *buf = (void *)ubuf; int retval = 0; + resource_size_t start; if (dev->status & PNP_ATTACHED) { retval = -EBUSY; @@ -429,16 +430,10 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, buf += 3; while (isspace(*buf)) ++buf; - pnp_res = pnp_get_pnp_resource(dev, - IORESOURCE_IRQ, nirq); - if (!pnp_res) - break; - pnp_res->index = nirq; - res = &pnp_res->res; - res->start = res->end = - simple_strtoul(buf, &buf, 0); - res->flags = IORESOURCE_IRQ; - nirq++; + start = simple_strtoul(buf, &buf, 0); + pnp_res = pnp_add_irq_resource(dev, start, 0); + if (pnp_res) + nirq++; continue; } if (!strnicmp(buf, "dma", 3)) { diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index f949a538ccde..2cf750f077a4 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -965,12 +965,9 @@ static int isapnp_read_resources(struct pnp_dev *dev) 8); if (!ret) continue; - pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, - tmp); - pnp_res->index = tmp; - res = &pnp_res->res; - res->start = res->end = ret; - res->flags = IORESOURCE_IRQ; + pnp_res = pnp_add_irq_resource(dev, ret, 0); + if (pnp_res) + pnp_res->index = tmp; } for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) { ret = isapnp_read_byte(ISAPNP_CFG_DMA + tmp); diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 3634f2f3f745..0b67dff1e7c3 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -82,28 +82,12 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev, u32 gsi, int triggering, int polarity, int shareable) { - struct resource *res; - int i; - int irq; + int irq, flags; int p, t; - static unsigned char warned; if (!valid_IRQ(gsi)) return; - for (i = 0; i < PNP_MAX_IRQ; i++) { - res = pnp_get_resource(dev, IORESOURCE_IRQ, i); - if (!pnp_resource_valid(res)) - break; - } - if (i >= PNP_MAX_IRQ) { - if (!warned) { - printk(KERN_WARNING "pnpacpi: exceeded the max number" - " of IRQ resources: %d\n", PNP_MAX_IRQ); - warned = 1; - } - return; - } /* * in IO-APIC mode, use overrided attribute. Two reasons: * 1. BIOS bug in DSDT @@ -121,17 +105,14 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev, } } - res->flags = IORESOURCE_IRQ; // Also clears _UNSET flag - res->flags |= irq_flags(triggering, polarity, shareable); + flags = irq_flags(triggering, polarity, shareable); irq = acpi_register_gsi(gsi, triggering, polarity); - if (irq < 0) { - res->flags |= IORESOURCE_DISABLED; - return; - } + if (irq >= 0) + pcibios_penalize_isa_irq(irq, 1); + else + flags |= IORESOURCE_DISABLED; - res->start = irq; - res->end = irq; - pcibios_penalize_isa_irq(irq, 1); + pnp_add_irq_resource(dev, irq, flags); } static int dma_flags(int type, int bus_master, int transfer) diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c index d3b0a4e53692..845730c57edc 100644 --- a/drivers/pnp/pnpbios/rsparser.c +++ b/drivers/pnp/pnpbios/rsparser.c @@ -54,28 +54,6 @@ inline void pcibios_penalize_isa_irq(int irq, int active) * Allocated Resources */ -static void pnpbios_parse_allocated_irqresource(struct pnp_dev *dev, int irq) -{ - struct resource *res; - int i; - - for (i = 0; i < PNP_MAX_IRQ; i++) { - res = pnp_get_resource(dev, IORESOURCE_IRQ, i); - if (!pnp_resource_valid(res)) - break; - } - - if (i < PNP_MAX_IRQ) { - res->flags = IORESOURCE_IRQ; // Also clears _UNSET flag - if (irq == -1) { - res->flags |= IORESOURCE_DISABLED; - return; - } - res->start = res->end = (unsigned long)irq; - pcibios_penalize_isa_irq(irq, 1); - } -} - static void pnpbios_parse_allocated_dmaresource(struct pnp_dev *dev, int dma) { struct resource *res; @@ -148,7 +126,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(struct pnp_dev *dev, unsigned char *end) { unsigned int len, tag; - int io, size, mask, i; + int io, size, mask, i, flags; if (!p) return NULL; @@ -205,12 +183,17 @@ static unsigned char *pnpbios_parse_allocated_resource_data(struct pnp_dev *dev, case SMALL_TAG_IRQ: if (len < 2 || len > 3) goto len_err; + flags = 0; io = -1; mask = p[1] + p[2] * 256; for (i = 0; i < 16; i++, mask = mask >> 1) if (mask & 0x01) io = i; - pnpbios_parse_allocated_irqresource(dev, io); + if (io != -1) + pcibios_penalize_isa_irq(io, 1); + else + flags = IORESOURCE_DISABLED; + pnp_add_irq_resource(dev, io, flags); break; case SMALL_TAG_DMA: diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index 1f4134eea7b7..082a556b9dcc 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -576,6 +576,32 @@ static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev, int type) return NULL; } +struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, + int flags) +{ + struct pnp_resource *pnp_res; + struct resource *res; + static unsigned char warned; + + pnp_res = pnp_new_resource(dev, IORESOURCE_IRQ); + if (!pnp_res) { + if (!warned) { + dev_err(&dev->dev, "can't add resource for IRQ %d\n", + irq); + warned = 1; + } + return NULL; + } + + res = &pnp_res->res; + res->flags = IORESOURCE_IRQ | flags; + res->start = irq; + res->end = irq; + + dev_dbg(&dev->dev, " add irq %d flags %#x\n", irq, flags); + return pnp_res; +} + /* format is: pnp_reserve_irq=irq1[,irq2] .... */ static int __init pnp_setup_reserve_irq(char *str) { -- cgit v1.2.2 From dc16f5f2ede8cc2acf8ac22857a7fecf3a4296c2 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:35 -0600 Subject: PNP: make generic pnp_add_dma_resource() Add a pnp_add_dma_resource() that can be used by all the PNP backends. This consolidates a little more pnp_resource_table knowledge into one place. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/pnp/base.h | 2 ++ drivers/pnp/interface.c | 14 ++++---------- drivers/pnp/isapnp/core.c | 9 +++------ drivers/pnp/pnpacpi/rsparser.c | 42 ++++++++---------------------------------- drivers/pnp/pnpbios/rsparser.c | 26 ++++---------------------- drivers/pnp/resource.c | 26 ++++++++++++++++++++++++++ 6 files changed, 47 insertions(+), 72 deletions(-) diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index 3dd5d849c30f..b6719b384347 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h @@ -43,3 +43,5 @@ struct pnp_resource_table { struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, int flags); +struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma, + int flags); diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c index e8134c286207..00c8a970a97e 100644 --- a/drivers/pnp/interface.c +++ b/drivers/pnp/interface.c @@ -440,16 +440,10 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, buf += 3; while (isspace(*buf)) ++buf; - pnp_res = pnp_get_pnp_resource(dev, - IORESOURCE_DMA, ndma); - if (!pnp_res) - break; - pnp_res->index = ndma; - res = &pnp_res->res; - res->start = res->end = - simple_strtoul(buf, &buf, 0); - res->flags = IORESOURCE_DMA; - ndma++; + start = simple_strtoul(buf, &buf, 0); + pnp_res = pnp_add_dma_resource(dev, start, 0); + if (pnp_res) + pnp_res->index = ndma++; continue; } break; diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index 2cf750f077a4..2e5e58c777dd 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -973,12 +973,9 @@ static int isapnp_read_resources(struct pnp_dev *dev) ret = isapnp_read_byte(ISAPNP_CFG_DMA + tmp); if (ret == 4) continue; - pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, - tmp); - pnp_res->index = tmp; - res = &pnp_res->res; - res->start = res->end = ret; - res->flags = IORESOURCE_DMA; + pnp_res = pnp_add_dma_resource(dev, ret, 0); + if (pnp_res) + pnp_res->index = tmp; } } return 0; diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 0b67dff1e7c3..fc7cf73b7a7e 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -158,34 +158,6 @@ static int dma_flags(int type, int bus_master, int transfer) return flags; } -static void pnpacpi_parse_allocated_dmaresource(struct pnp_dev *dev, - u32 dma, int flags) -{ - struct resource *res; - int i; - static unsigned char warned; - - for (i = 0; i < PNP_MAX_DMA; i++) { - res = pnp_get_resource(dev, IORESOURCE_DMA, i); - if (!pnp_resource_valid(res)) - break; - } - if (i < PNP_MAX_DMA) { - res->flags = IORESOURCE_DMA; // Also clears _UNSET flag - res->flags |= flags; - if (dma == -1) { - res->flags |= IORESOURCE_DISABLED; - return; - } - res->start = dma; - res->end = dma; - } else if (!warned) { - printk(KERN_WARNING "pnpacpi: exceeded the max number of DMA " - "resources: %d \n", PNP_MAX_DMA); - warned = 1; - } -} - static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 io, u64 len, int io_decode) { @@ -285,7 +257,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, struct acpi_resource_memory32 *memory32; struct acpi_resource_fixed_memory32 *fixed_memory32; struct acpi_resource_extended_irq *extended_irq; - int i; + int i, flags; switch (res->type) { case ACPI_RESOURCE_TYPE_IRQ: @@ -305,11 +277,13 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, case ACPI_RESOURCE_TYPE_DMA: dma = &res->data.dma; - if (dma->channel_count > 0) - pnpacpi_parse_allocated_dmaresource(dev, - dma->channels[0], - dma_flags(dma->type, dma->bus_master, - dma->transfer)); + if (dma->channel_count > 0) { + flags = dma_flags(dma->type, dma->bus_master, + dma->transfer); + if (dma->channels[0] == (u8) -1) + flags |= IORESOURCE_DISABLED; + pnp_add_dma_resource(dev, dma->channels[0], flags); + } break; case ACPI_RESOURCE_TYPE_IO: diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c index 845730c57edc..7f8d65728599 100644 --- a/drivers/pnp/pnpbios/rsparser.c +++ b/drivers/pnp/pnpbios/rsparser.c @@ -54,27 +54,6 @@ inline void pcibios_penalize_isa_irq(int irq, int active) * Allocated Resources */ -static void pnpbios_parse_allocated_dmaresource(struct pnp_dev *dev, int dma) -{ - struct resource *res; - int i; - - for (i = 0; i < PNP_MAX_DMA; i++) { - res = pnp_get_resource(dev, IORESOURCE_DMA, i); - if (!pnp_resource_valid(res)) - break; - } - - if (i < PNP_MAX_DMA) { - res->flags = IORESOURCE_DMA; // Also clears _UNSET flag - if (dma == -1) { - res->flags |= IORESOURCE_DISABLED; - return; - } - res->start = res->end = (unsigned long)dma; - } -} - static void pnpbios_parse_allocated_ioresource(struct pnp_dev *dev, int io, int len) { @@ -199,12 +178,15 @@ static unsigned char *pnpbios_parse_allocated_resource_data(struct pnp_dev *dev, case SMALL_TAG_DMA: if (len != 2) goto len_err; + flags = 0; io = -1; mask = p[1]; for (i = 0; i < 8; i++, mask = mask >> 1) if (mask & 0x01) io = i; - pnpbios_parse_allocated_dmaresource(dev, io); + if (io == -1) + flags = IORESOURCE_DISABLED; + pnp_add_dma_resource(dev, io, flags); break; case SMALL_TAG_PORT: diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index 082a556b9dcc..2a8612e31ab7 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -602,6 +602,32 @@ struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, return pnp_res; } +struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma, + int flags) +{ + struct pnp_resource *pnp_res; + struct resource *res; + static unsigned char warned; + + pnp_res = pnp_new_resource(dev, IORESOURCE_DMA); + if (!pnp_res) { + if (!warned) { + dev_err(&dev->dev, "can't add resource for DMA %d\n", + dma); + warned = 1; + } + return NULL; + } + + res = &pnp_res->res; + res->flags = IORESOURCE_DMA | flags; + res->start = dma; + res->end = dma; + + dev_dbg(&dev->dev, " add dma %d flags %#x\n", dma, flags); + return pnp_res; +} + /* format is: pnp_reserve_irq=irq1[,irq2] .... */ static int __init pnp_setup_reserve_irq(char *str) { -- cgit v1.2.2 From cc8c2e308194f0997c718c7c735550ff06754d20 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:36 -0600 Subject: PNP: make generic pnp_add_io_resource() Add a pnp_add_io_resource() that can be used by all the PNP backends. This consolidates a little more pnp_resource_table knowledge into one place. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/pnp/base.h | 3 +++ drivers/pnp/interface.c | 20 ++++++++------------ drivers/pnp/isapnp/core.c | 8 +++----- drivers/pnp/pnpacpi/rsparser.c | 35 ++++++++++------------------------- drivers/pnp/pnpbios/rsparser.c | 23 ++++++----------------- drivers/pnp/resource.c | 29 +++++++++++++++++++++++++++++ 6 files changed, 59 insertions(+), 59 deletions(-) diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index b6719b384347..bfb08abc311b 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h @@ -45,3 +45,6 @@ struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, int flags); struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma, int flags); +struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev, + resource_size_t start, + resource_size_t end, int flags); diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c index 00c8a970a97e..77d8bf01b485 100644 --- a/drivers/pnp/interface.c +++ b/drivers/pnp/interface.c @@ -324,7 +324,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, struct resource *res; char *buf = (void *)ubuf; int retval = 0; - resource_size_t start; + resource_size_t start, end; if (dev->status & PNP_ATTACHED) { retval = -EBUSY; @@ -382,24 +382,20 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, buf += 2; while (isspace(*buf)) ++buf; - pnp_res = pnp_get_pnp_resource(dev, - IORESOURCE_IO, nport); - if (!pnp_res) - break; - pnp_res->index = nport; - res = &pnp_res->res; - res->start = simple_strtoul(buf, &buf, 0); + start = simple_strtoul(buf, &buf, 0); while (isspace(*buf)) ++buf; if (*buf == '-') { buf += 1; while (isspace(*buf)) ++buf; - res->end = simple_strtoul(buf, &buf, 0); + end = simple_strtoul(buf, &buf, 0); } else - res->end = res->start; - res->flags = IORESOURCE_IO; - nport++; + end = start; + pnp_res = pnp_add_io_resource(dev, start, end, + 0); + if (pnp_res) + pnp_res->index = nport++; continue; } if (!strnicmp(buf, "mem", 3)) { diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index 2e5e58c777dd..bdd8508090da 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -941,11 +941,9 @@ static int isapnp_read_resources(struct pnp_dev *dev) ret = isapnp_read_word(ISAPNP_CFG_PORT + (tmp << 1)); if (!ret) continue; - pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, tmp); - pnp_res->index = tmp; - res = &pnp_res->res; - res->start = ret; - res->flags = IORESOURCE_IO; + pnp_res = pnp_add_io_resource(dev, ret, ret, 0); + if (pnp_res) + pnp_res->index = tmp; } for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) { ret = diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index fc7cf73b7a7e..d3ca8e035c19 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -158,33 +158,18 @@ static int dma_flags(int type, int bus_master, int transfer) return flags; } -static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, - u64 io, u64 len, int io_decode) +static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start, + u64 len, int io_decode) { - struct resource *res; - int i; - static unsigned char warned; + int flags = 0; + u64 end = start + len - 1; - for (i = 0; i < PNP_MAX_PORT; i++) { - res = pnp_get_resource(dev, IORESOURCE_IO, i); - if (!pnp_resource_valid(res)) - break; - } - if (i < PNP_MAX_PORT) { - res->flags = IORESOURCE_IO; // Also clears _UNSET flag - if (io_decode == ACPI_DECODE_16) - res->flags |= PNP_PORT_FLAG_16BITADDR; - if (len <= 0 || (io + len - 1) >= 0x10003) { - res->flags |= IORESOURCE_DISABLED; - return; - } - res->start = io; - res->end = io + len - 1; - } else if (!warned) { - printk(KERN_WARNING "pnpacpi: exceeded the max number of IO " - "resources: %d \n", PNP_MAX_PORT); - warned = 1; - } + if (io_decode == ACPI_DECODE_16) + flags |= PNP_PORT_FLAG_16BITADDR; + if (len == 0 || end >= 0x10003) + flags |= IORESOURCE_DISABLED; + + pnp_add_io_resource(dev, start, end, flags); } static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev, diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c index 7f8d65728599..8c83bc16a9be 100644 --- a/drivers/pnp/pnpbios/rsparser.c +++ b/drivers/pnp/pnpbios/rsparser.c @@ -55,26 +55,15 @@ inline void pcibios_penalize_isa_irq(int irq, int active) */ static void pnpbios_parse_allocated_ioresource(struct pnp_dev *dev, - int io, int len) + int start, int len) { - struct resource *res; - int i; + int flags = 0; + int end = start + len - 1; - for (i = 0; i < PNP_MAX_PORT; i++) { - res = pnp_get_resource(dev, IORESOURCE_IO, i); - if (!pnp_resource_valid(res)) - break; - } + if (len <= 0 || end >= 0x10003) + flags |= IORESOURCE_DISABLED; - if (i < PNP_MAX_PORT) { - res->flags = IORESOURCE_IO; // Also clears _UNSET flag - if (len <= 0 || (io + len - 1) >= 0x10003) { - res->flags |= IORESOURCE_DISABLED; - return; - } - res->start = (unsigned long)io; - res->end = (unsigned long)(io + len - 1); - } + pnp_add_io_resource(dev, start, end, flags); } static void pnpbios_parse_allocated_memresource(struct pnp_dev *dev, diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index 2a8612e31ab7..64387b70026a 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -628,6 +628,35 @@ struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma, return pnp_res; } +struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev, + resource_size_t start, + resource_size_t end, int flags) +{ + struct pnp_resource *pnp_res; + struct resource *res; + static unsigned char warned; + + pnp_res = pnp_new_resource(dev, IORESOURCE_IO); + if (!pnp_res) { + if (!warned) { + dev_err(&dev->dev, "can't add resource for IO " + "%#llx-%#llx\n",(unsigned long long) start, + (unsigned long long) end); + warned = 1; + } + return NULL; + } + + res = &pnp_res->res; + res->flags = IORESOURCE_IO | flags; + res->start = start; + res->end = end; + + dev_dbg(&dev->dev, " add io %#llx-%#llx flags %#x\n", + (unsigned long long) start, (unsigned long long) end, flags); + return pnp_res; +} + /* format is: pnp_reserve_irq=irq1[,irq2] .... */ static int __init pnp_setup_reserve_irq(char *str) { -- cgit v1.2.2 From d6180f36617953990bf90d4c1ff85b77e9995cd1 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:37 -0600 Subject: PNP: make generic pnp_add_mem_resource() Add a pnp_add_mem_resource() that can be used by all the PNP backends. This consolidates a little more pnp_resource_table knowledge into one place. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/pnp/base.h | 3 +++ drivers/pnp/interface.c | 19 +++++++------------ drivers/pnp/isapnp/core.c | 10 +++------- drivers/pnp/pnpacpi/rsparser.c | 34 +++++++++------------------------- drivers/pnp/pnpbios/rsparser.c | 23 ++++++----------------- drivers/pnp/resource.c | 29 +++++++++++++++++++++++++++++ 6 files changed, 57 insertions(+), 61 deletions(-) diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index bfb08abc311b..9b7bb62c98b1 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h @@ -48,3 +48,6 @@ struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma, struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev, resource_size_t start, resource_size_t end, int flags); +struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev, + resource_size_t start, + resource_size_t end, int flags); diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c index 77d8bf01b485..5d9301de1778 100644 --- a/drivers/pnp/interface.c +++ b/drivers/pnp/interface.c @@ -321,7 +321,6 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, { struct pnp_dev *dev = to_pnp_dev(dmdev); struct pnp_resource *pnp_res; - struct resource *res; char *buf = (void *)ubuf; int retval = 0; resource_size_t start, end; @@ -402,24 +401,20 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, buf += 3; while (isspace(*buf)) ++buf; - pnp_res = pnp_get_pnp_resource(dev, - IORESOURCE_MEM, nmem); - if (!pnp_res) - break; - pnp_res->index = nmem; - res = &pnp_res->res; - res->start = simple_strtoul(buf, &buf, 0); + start = simple_strtoul(buf, &buf, 0); while (isspace(*buf)) ++buf; if (*buf == '-') { buf += 1; while (isspace(*buf)) ++buf; - res->end = simple_strtoul(buf, &buf, 0); + end = simple_strtoul(buf, &buf, 0); } else - res->end = res->start; - res->flags = IORESOURCE_MEM; - nmem++; + end = start; + pnp_res = pnp_add_mem_resource(dev, start, end, + 0); + if (pnp_res) + pnp_res->index = nmem++; continue; } if (!strnicmp(buf, "irq", 3)) { diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index bdd8508090da..f08399497e4c 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -932,7 +932,6 @@ EXPORT_SYMBOL(isapnp_write_byte); static int isapnp_read_resources(struct pnp_dev *dev) { struct pnp_resource *pnp_res; - struct resource *res; int tmp, ret; dev->active = isapnp_read_byte(ISAPNP_CFG_ACTIVATE); @@ -950,12 +949,9 @@ static int isapnp_read_resources(struct pnp_dev *dev) isapnp_read_word(ISAPNP_CFG_MEM + (tmp << 3)) << 8; if (!ret) continue; - pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, - tmp); - pnp_res->index = tmp; - res = &pnp_res->res; - res->start = ret; - res->flags = IORESOURCE_MEM; + pnp_res = pnp_add_mem_resource(dev, ret, ret, 0); + if (pnp_res) + pnp_res->index = tmp; } for (tmp = 0; tmp < ISAPNP_MAX_IRQ; tmp++) { ret = diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index d3ca8e035c19..a512908bf4e3 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -173,34 +173,18 @@ static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start, } static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev, - u64 mem, u64 len, + u64 start, u64 len, int write_protect) { - struct resource *res; - int i; - static unsigned char warned; + int flags = 0; + u64 end = start + len - 1; - for (i = 0; i < PNP_MAX_MEM; i++) { - res = pnp_get_resource(dev, IORESOURCE_MEM, i); - if (!pnp_resource_valid(res)) - break; - } - if (i < PNP_MAX_MEM) { - res->flags = IORESOURCE_MEM; // Also clears _UNSET flag - if (len <= 0) { - res->flags |= IORESOURCE_DISABLED; - return; - } - if (write_protect == ACPI_READ_WRITE_MEMORY) - res->flags |= IORESOURCE_MEM_WRITEABLE; - - res->start = mem; - res->end = mem + len - 1; - } else if (!warned) { - printk(KERN_WARNING "pnpacpi: exceeded the max number of mem " - "resources: %d\n", PNP_MAX_MEM); - warned = 1; - } + if (len == 0) + flags |= IORESOURCE_DISABLED; + if (write_protect == ACPI_READ_WRITE_MEMORY) + flags |= IORESOURCE_MEM_WRITEABLE; + + pnp_add_mem_resource(dev, start, end, flags); } static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev, diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c index 8c83bc16a9be..ed63ecd9bf40 100644 --- a/drivers/pnp/pnpbios/rsparser.c +++ b/drivers/pnp/pnpbios/rsparser.c @@ -67,26 +67,15 @@ static void pnpbios_parse_allocated_ioresource(struct pnp_dev *dev, } static void pnpbios_parse_allocated_memresource(struct pnp_dev *dev, - int mem, int len) + int start, int len) { - struct resource *res; - int i; + int flags = 0; + int end = start + len - 1; - for (i = 0; i < PNP_MAX_MEM; i++) { - res = pnp_get_resource(dev, IORESOURCE_MEM, i); - if (!pnp_resource_valid(res)) - break; - } + if (len <= 0) + flags |= IORESOURCE_DISABLED; - if (i < PNP_MAX_MEM) { - res->flags = IORESOURCE_MEM; // Also clears _UNSET flag - if (len <= 0) { - res->flags |= IORESOURCE_DISABLED; - return; - } - res->start = (unsigned long)mem; - res->end = (unsigned long)(mem + len - 1); - } + pnp_add_mem_resource(dev, start, end, flags); } static unsigned char *pnpbios_parse_allocated_resource_data(struct pnp_dev *dev, diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index 64387b70026a..2041620d5682 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -657,6 +657,35 @@ struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev, return pnp_res; } +struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev, + resource_size_t start, + resource_size_t end, int flags) +{ + struct pnp_resource *pnp_res; + struct resource *res; + static unsigned char warned; + + pnp_res = pnp_new_resource(dev, IORESOURCE_MEM); + if (!pnp_res) { + if (!warned) { + dev_err(&dev->dev, "can't add resource for MEM " + "%#llx-%#llx\n",(unsigned long long) start, + (unsigned long long) end); + warned = 1; + } + return NULL; + } + + res = &pnp_res->res; + res->flags = IORESOURCE_MEM | flags; + res->start = start; + res->end = end; + + dev_dbg(&dev->dev, " add mem %#llx-%#llx flags %#x\n", + (unsigned long long) start, (unsigned long long) end, flags); + return pnp_res; +} + /* format is: pnp_reserve_irq=irq1[,irq2] .... */ static int __init pnp_setup_reserve_irq(char *str) { -- cgit v1.2.2 From 01115e7d41c4eaeffa064d818b4abbd3efa94f80 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:38 -0600 Subject: ISAPNP: fold isapnp_read_resources() back into isapnp_get_resources() isapnp_get_resources() does very little besides call isapnp_read_resources(), so just fold them back together. Based on a patch by Rene Herman Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/pnp/isapnp/core.c | 66 +++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 37 deletions(-) diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index f08399497e4c..a3f1566ccea5 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -929,62 +929,54 @@ EXPORT_SYMBOL(isapnp_cfg_begin); EXPORT_SYMBOL(isapnp_cfg_end); EXPORT_SYMBOL(isapnp_write_byte); -static int isapnp_read_resources(struct pnp_dev *dev) +static int isapnp_get_resources(struct pnp_dev *dev) { struct pnp_resource *pnp_res; - int tmp, ret; + int i, ret; + dev_dbg(&dev->dev, "get resources\n"); + pnp_init_resources(dev); + isapnp_cfg_begin(dev->card->number, dev->number); dev->active = isapnp_read_byte(ISAPNP_CFG_ACTIVATE); - if (dev->active) { - for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) { - ret = isapnp_read_word(ISAPNP_CFG_PORT + (tmp << 1)); - if (!ret) - continue; + if (!dev->active) + goto __end; + + for (i = 0; i < ISAPNP_MAX_PORT; i++) { + ret = isapnp_read_word(ISAPNP_CFG_PORT + (i << 1)); + if (ret) { pnp_res = pnp_add_io_resource(dev, ret, ret, 0); if (pnp_res) - pnp_res->index = tmp; + pnp_res->index = i; } - for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) { - ret = - isapnp_read_word(ISAPNP_CFG_MEM + (tmp << 3)) << 8; - if (!ret) - continue; + } + for (i = 0; i < ISAPNP_MAX_MEM; i++) { + ret = isapnp_read_word(ISAPNP_CFG_MEM + (i << 3)) << 8; + if (ret) { pnp_res = pnp_add_mem_resource(dev, ret, ret, 0); if (pnp_res) - pnp_res->index = tmp; + pnp_res->index = i; } - for (tmp = 0; tmp < ISAPNP_MAX_IRQ; tmp++) { - ret = - (isapnp_read_word(ISAPNP_CFG_IRQ + (tmp << 1)) >> - 8); - if (!ret) - continue; + } + for (i = 0; i < ISAPNP_MAX_IRQ; i++) { + ret = isapnp_read_word(ISAPNP_CFG_IRQ + (i << 1)) >> 8; + if (ret) { pnp_res = pnp_add_irq_resource(dev, ret, 0); if (pnp_res) - pnp_res->index = tmp; + pnp_res->index = i; } - for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) { - ret = isapnp_read_byte(ISAPNP_CFG_DMA + tmp); - if (ret == 4) - continue; + } + for (i = 0; i < ISAPNP_MAX_DMA; i++) { + ret = isapnp_read_byte(ISAPNP_CFG_DMA + i); + if (ret != 4) { pnp_res = pnp_add_dma_resource(dev, ret, 0); if (pnp_res) - pnp_res->index = tmp; + pnp_res->index = i; } } - return 0; -} -static int isapnp_get_resources(struct pnp_dev *dev) -{ - int ret; - - dev_dbg(&dev->dev, "get resources\n"); - pnp_init_resources(dev); - isapnp_cfg_begin(dev->card->number, dev->number); - ret = isapnp_read_resources(dev); +__end: isapnp_cfg_end(); - return ret; + return 0; } static int isapnp_set_resources(struct pnp_dev *dev) -- cgit v1.2.2 From d152cf5d0c3325979e71ee53b425fdd51a1a285a Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:39 -0600 Subject: PNPACPI: move _CRS/_PRS warnings closer to the action Move warnings about _CRS and _PRS problems to the place where we actually make the ACPI calls. Then we don't have to pass around acpi_status values any more than necessary. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/pnpacpi/core.c | 24 +++++------------------- drivers/pnp/pnpacpi/pnpacpi.h | 4 ++-- drivers/pnp/pnpacpi/rsparser.c | 30 ++++++++++++++++++++++-------- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 7e4512a60f58..0950b711f19e 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -75,11 +75,8 @@ static int __init ispnpidacpi(char *id) static int pnpacpi_get_resources(struct pnp_dev *dev) { - acpi_status status; - dev_dbg(&dev->dev, "get resources\n"); - status = pnpacpi_parse_allocated_resource(dev); - return ACPI_FAILURE(status) ? -ENODEV : 0; + return pnpacpi_parse_allocated_resource(dev); } static int pnpacpi_set_resources(struct pnp_dev *dev) @@ -182,22 +179,11 @@ static int __init pnpacpi_add_device(struct acpi_device *device) else strncpy(dev->name, acpi_device_bid(device), sizeof(dev->name)); - if (dev->active) { - /* parse allocated resource */ - status = pnpacpi_parse_allocated_resource(dev); - if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { - pnp_err("PnPACPI: METHOD_NAME__CRS failure for %s", - acpi_device_hid(device)); - } - } + if (dev->active) + pnpacpi_parse_allocated_resource(dev); - if (dev->capabilities & PNP_CONFIGURABLE) { - status = pnpacpi_parse_resource_option_data(dev); - if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { - pnp_err("PnPACPI: METHOD_NAME__PRS failure for %s", - acpi_device_hid(device)); - } - } + if (dev->capabilities & PNP_CONFIGURABLE) + pnpacpi_parse_resource_option_data(dev); if (device->flags.compatible_ids) { struct acpi_compatible_id_list *cid_list = device->pnp.cid_list; diff --git a/drivers/pnp/pnpacpi/pnpacpi.h b/drivers/pnp/pnpacpi/pnpacpi.h index db0c4f25c2a3..3e60225b0227 100644 --- a/drivers/pnp/pnpacpi/pnpacpi.h +++ b/drivers/pnp/pnpacpi/pnpacpi.h @@ -5,8 +5,8 @@ #include #include -acpi_status pnpacpi_parse_allocated_resource(struct pnp_dev *); -acpi_status pnpacpi_parse_resource_option_data(struct pnp_dev *); +int pnpacpi_parse_allocated_resource(struct pnp_dev *); +int pnpacpi_parse_resource_option_data(struct pnp_dev *); int pnpacpi_encode_resources(struct pnp_dev *, struct acpi_buffer *); int pnpacpi_build_resource_template(struct pnp_dev *, struct acpi_buffer *); #endif diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index a512908bf4e3..0201c8adfda7 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -339,16 +339,24 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, return AE_OK; } -acpi_status pnpacpi_parse_allocated_resource(struct pnp_dev *dev) +int pnpacpi_parse_allocated_resource(struct pnp_dev *dev) { acpi_handle handle = dev->data; + acpi_status status; dev_dbg(&dev->dev, "parse allocated resources\n"); pnp_init_resources(dev); - return acpi_walk_resources(handle, METHOD_NAME__CRS, - pnpacpi_allocated_resource, dev); + status = acpi_walk_resources(handle, METHOD_NAME__CRS, + pnpacpi_allocated_resource, dev); + + if (ACPI_FAILURE(status)) { + if (status != AE_NOT_FOUND) + dev_err(&dev->dev, "can't evaluate _CRS: %d", status); + return -EPERM; + } + return 0; } static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev, @@ -670,7 +678,7 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, return AE_OK; } -acpi_status __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev) +int __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev) { acpi_handle handle = dev->data; acpi_status status; @@ -680,13 +688,19 @@ acpi_status __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev) parse_data.option = pnp_register_independent_option(dev); if (!parse_data.option) - return AE_ERROR; + return -ENOMEM; + parse_data.option_independent = parse_data.option; parse_data.dev = dev; status = acpi_walk_resources(handle, METHOD_NAME__PRS, pnpacpi_option_resource, &parse_data); - return status; + if (ACPI_FAILURE(status)) { + if (status != AE_NOT_FOUND) + dev_err(&dev->dev, "can't evaluate _PRS: %d", status); + return -EPERM; + } + return 0; } static int pnpacpi_supported_resource(struct acpi_resource *res) @@ -745,7 +759,7 @@ int pnpacpi_build_resource_template(struct pnp_dev *dev, status = acpi_walk_resources(handle, METHOD_NAME__CRS, pnpacpi_count_resources, &res_cnt); if (ACPI_FAILURE(status)) { - dev_err(&dev->dev, "can't evaluate _CRS\n"); + dev_err(&dev->dev, "can't evaluate _CRS: %d\n", status); return -EINVAL; } if (!res_cnt) @@ -760,7 +774,7 @@ int pnpacpi_build_resource_template(struct pnp_dev *dev, pnpacpi_type_resources, &resource); if (ACPI_FAILURE(status)) { kfree(buffer->pointer); - dev_err(&dev->dev, "can't evaluate _CRS\n"); + dev_err(&dev->dev, "can't evaluate _CRS: %d\n", status); return -EINVAL; } /* resource will pointer the end resource now */ -- cgit v1.2.2 From 62cfb298b95d713825deb8faf2044c45a1e17a0a Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:40 -0600 Subject: PNP: make interfaces private to the PNP core The interfaces for registering protocols, devices, cards, and resource options should only be used inside the PNP core. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/base.h | 27 ++++++++++++++++++++++++++- include/linux/pnp.h | 36 ------------------------------------ 2 files changed, 26 insertions(+), 37 deletions(-) diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index 9b7bb62c98b1..4fe7c58f57e9 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h @@ -1,12 +1,37 @@ extern spinlock_t pnp_lock; void *pnp_alloc(long size); + +int pnp_register_protocol(struct pnp_protocol *protocol); +void pnp_unregister_protocol(struct pnp_protocol *protocol); + #define PNP_EISA_ID_MASK 0x7fffffff void pnp_eisa_id_to_string(u32 id, char *str); struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *, int id, char *pnpid); struct pnp_card *pnp_alloc_card(struct pnp_protocol *, int id, char *pnpid); + +int pnp_add_device(struct pnp_dev *dev); struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id); -struct pnp_id *pnp_add_card_id(struct pnp_card *card, char *id); int pnp_interface_attach_device(struct pnp_dev *dev); + +int pnp_add_card(struct pnp_card *card); +struct pnp_id *pnp_add_card_id(struct pnp_card *card, char *id); +void pnp_remove_card(struct pnp_card *card); +int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev); +void pnp_remove_card_device(struct pnp_dev *dev); + +struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev); +struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev, + int priority); +int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option, + struct pnp_irq *data); +int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option, + struct pnp_dma *data); +int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option, + struct pnp_port *data); +int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option, + struct pnp_mem *data); +void pnp_init_resources(struct pnp_dev *dev); + void pnp_fixup_device(struct pnp_dev *dev); void pnp_free_option(struct pnp_option *option); int __pnp_add_device(struct pnp_dev *dev); diff --git a/include/linux/pnp.h b/include/linux/pnp.h index a5487b6a4e57..f5b985e912ae 100644 --- a/include/linux/pnp.h +++ b/include/linux/pnp.h @@ -414,19 +414,12 @@ extern struct bus_type pnp_bus_type; #if defined(CONFIG_PNP) /* device management */ -int pnp_register_protocol(struct pnp_protocol *protocol); -void pnp_unregister_protocol(struct pnp_protocol *protocol); -int pnp_add_device(struct pnp_dev *dev); int pnp_device_attach(struct pnp_dev *pnp_dev); void pnp_device_detach(struct pnp_dev *pnp_dev); extern struct list_head pnp_global; extern int pnp_platform_devices; /* multidevice card support */ -int pnp_add_card(struct pnp_card *card); -void pnp_remove_card(struct pnp_card *card); -int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev); -void pnp_remove_card_device(struct pnp_dev *dev); struct pnp_dev *pnp_request_card_device(struct pnp_card_link *clink, const char *id, struct pnp_dev *from); void pnp_release_card_device(struct pnp_dev *dev); @@ -435,20 +428,7 @@ void pnp_unregister_card_driver(struct pnp_card_driver *drv); extern struct list_head pnp_cards; /* resource management */ -struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev); -struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev, - int priority); -int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option, - struct pnp_irq *data); -int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option, - struct pnp_dma *data); -int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option, - struct pnp_port *data); -int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option, - struct pnp_mem *data); -void pnp_init_resources(struct pnp_dev *dev); int pnp_auto_config_dev(struct pnp_dev *dev); -int pnp_validate_config(struct pnp_dev *dev); int pnp_start_dev(struct pnp_dev *dev); int pnp_stop_dev(struct pnp_dev *dev); int pnp_activate_dev(struct pnp_dev *dev); @@ -463,35 +443,19 @@ void pnp_unregister_driver(struct pnp_driver *drv); #else /* device management */ -static inline int pnp_register_protocol(struct pnp_protocol *protocol) { return -ENODEV; } -static inline void pnp_unregister_protocol(struct pnp_protocol *protocol) { } -static inline int pnp_init_device(struct pnp_dev *dev) { return -ENODEV; } -static inline int pnp_add_device(struct pnp_dev *dev) { return -ENODEV; } static inline int pnp_device_attach(struct pnp_dev *pnp_dev) { return -ENODEV; } static inline void pnp_device_detach(struct pnp_dev *pnp_dev) { } #define pnp_platform_devices 0 /* multidevice card support */ -static inline int pnp_add_card(struct pnp_card *card) { return -ENODEV; } -static inline void pnp_remove_card(struct pnp_card *card) { } -static inline int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev) { return -ENODEV; } -static inline void pnp_remove_card_device(struct pnp_dev *dev) { } static inline struct pnp_dev *pnp_request_card_device(struct pnp_card_link *clink, const char *id, struct pnp_dev *from) { return NULL; } static inline void pnp_release_card_device(struct pnp_dev *dev) { } static inline int pnp_register_card_driver(struct pnp_card_driver *drv) { return -ENODEV; } static inline void pnp_unregister_card_driver(struct pnp_card_driver *drv) { } /* resource management */ -static inline struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev) { return NULL; } -static inline struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev, int priority) { return NULL; } -static inline int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option, struct pnp_irq *data) { return -ENODEV; } -static inline int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option, struct pnp_dma *data) { return -ENODEV; } -static inline int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option, struct pnp_port *data) { return -ENODEV; } -static inline int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option, struct pnp_mem *data) { return -ENODEV; } -static inline void pnp_init_resources(struct pnp_dev *dev) { } static inline int pnp_auto_config_dev(struct pnp_dev *dev) { return -ENODEV; } -static inline int pnp_validate_config(struct pnp_dev *dev) { return -ENODEV; } 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; } -- cgit v1.2.2 From 261b20da4bd349f1b26e206f440809f1351be34b Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:41 -0600 Subject: ISAPNP: remove unused pnp_dev->regs field The "regs" field in struct pnp_dev is set but never read, so remove it. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/isapnp/core.c | 3 --- include/linux/pnp.h | 1 - 2 files changed, 4 deletions(-) diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index a3f1566ccea5..f1bccdbdeb08 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -416,10 +416,7 @@ static struct pnp_dev *__init isapnp_parse_device(struct pnp_card *card, if (!dev) return NULL; - dev->regs = tmp[4]; dev->card = card; - if (size > 5) - dev->regs |= tmp[5] << 8; dev->capabilities |= PNP_CONFIGURABLE; dev->capabilities |= PNP_READ; dev->capabilities |= PNP_WRITE; diff --git a/include/linux/pnp.h b/include/linux/pnp.h index f5b985e912ae..e3b2c0068de7 100644 --- a/include/linux/pnp.h +++ b/include/linux/pnp.h @@ -253,7 +253,6 @@ struct pnp_dev { struct pnp_resource_table *res; char name[PNP_NAME_LEN]; /* contains a human-readable name */ - unsigned short regs; /* ISAPnP: supported registers */ int flags; /* used by protocols */ struct proc_dir_entry *procent; /* device entry in /proc/bus/isapnp */ void *data; -- cgit v1.2.2 From dfd2e1b4e6eb46ff59c7e1c1111c967b8b5981c1 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2008 16:34:42 -0600 Subject: PNPBIOS: remove include/linux/pnpbios.h The contents of include/linux/pnpbios.h are used only inside the PNPBIOS backend, so this file doesn't need to be visible outside PNP. This patch moves the contents into an existing PNPBIOS-specific file, drivers/pnp/pnpbios/pnpbios.h. Signed-off-by: Bjorn Helgaas Acked-By: Rene Herman Signed-off-by: Len Brown --- drivers/pnp/pnpbios/bioscalls.c | 1 - drivers/pnp/pnpbios/core.c | 1 - drivers/pnp/pnpbios/pnpbios.h | 136 ++++++++++++++++++++++++++++++++++++ drivers/pnp/pnpbios/proc.c | 2 +- drivers/pnp/pnpbios/rsparser.c | 1 - include/linux/pnpbios.h | 151 ---------------------------------------- 6 files changed, 137 insertions(+), 155 deletions(-) delete mode 100644 include/linux/pnpbios.h diff --git a/drivers/pnp/pnpbios/bioscalls.c b/drivers/pnp/pnpbios/bioscalls.c index a8364d815222..7ff824496b39 100644 --- a/drivers/pnp/pnpbios/bioscalls.c +++ b/drivers/pnp/pnpbios/bioscalls.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c index f5477ca85956..19a4be1a9a31 100644 --- a/drivers/pnp/pnpbios/core.c +++ b/drivers/pnp/pnpbios/core.c @@ -50,7 +50,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/pnp/pnpbios/pnpbios.h b/drivers/pnp/pnpbios/pnpbios.h index 42343fc753ba..b09cf6dc2075 100644 --- a/drivers/pnp/pnpbios/pnpbios.h +++ b/drivers/pnp/pnpbios/pnpbios.h @@ -2,6 +2,142 @@ * pnpbios.h - contains local definitions */ +/* + * Include file for the interface to a PnP BIOS + * + * Original BIOS code (C) 1998 Christian Schmidt (chr.schmidt@tu-bs.de) + * PnP handler parts (c) 1998 Tom Lees + * Minor reorganizations by David Hinds + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Return codes + */ +#define PNP_SUCCESS 0x00 +#define PNP_NOT_SET_STATICALLY 0x7f +#define PNP_UNKNOWN_FUNCTION 0x81 +#define PNP_FUNCTION_NOT_SUPPORTED 0x82 +#define PNP_INVALID_HANDLE 0x83 +#define PNP_BAD_PARAMETER 0x84 +#define PNP_SET_FAILED 0x85 +#define PNP_EVENTS_NOT_PENDING 0x86 +#define PNP_SYSTEM_NOT_DOCKED 0x87 +#define PNP_NO_ISA_PNP_CARDS 0x88 +#define PNP_UNABLE_TO_DETERMINE_DOCK_CAPABILITIES 0x89 +#define PNP_CONFIG_CHANGE_FAILED_NO_BATTERY 0x8a +#define PNP_CONFIG_CHANGE_FAILED_RESOURCE_CONFLICT 0x8b +#define PNP_BUFFER_TOO_SMALL 0x8c +#define PNP_USE_ESCD_SUPPORT 0x8d +#define PNP_MESSAGE_NOT_SUPPORTED 0x8e +#define PNP_HARDWARE_ERROR 0x8f + +#define ESCD_SUCCESS 0x00 +#define ESCD_IO_ERROR_READING 0x55 +#define ESCD_INVALID 0x56 +#define ESCD_BUFFER_TOO_SMALL 0x59 +#define ESCD_NVRAM_TOO_SMALL 0x5a +#define ESCD_FUNCTION_NOT_SUPPORTED 0x81 + +/* + * Events that can be received by "get event" + */ +#define PNPEV_ABOUT_TO_CHANGE_CONFIG 0x0001 +#define PNPEV_DOCK_CHANGED 0x0002 +#define PNPEV_SYSTEM_DEVICE_CHANGED 0x0003 +#define PNPEV_CONFIG_CHANGED_FAILED 0x0004 +#define PNPEV_UNKNOWN_SYSTEM_EVENT 0xffff +/* 0x8000 through 0xfffe are OEM defined */ + +/* + * Messages that should be sent through "send message" + */ +#define PNPMSG_OK 0x00 +#define PNPMSG_ABORT 0x01 +#define PNPMSG_UNDOCK_DEFAULT_ACTION 0x40 +#define PNPMSG_POWER_OFF 0x41 +#define PNPMSG_PNP_OS_ACTIVE 0x42 +#define PNPMSG_PNP_OS_INACTIVE 0x43 + +/* + * Plug and Play BIOS flags + */ +#define PNPBIOS_NO_DISABLE 0x0001 +#define PNPBIOS_NO_CONFIG 0x0002 +#define PNPBIOS_OUTPUT 0x0004 +#define PNPBIOS_INPUT 0x0008 +#define PNPBIOS_BOOTABLE 0x0010 +#define PNPBIOS_DOCK 0x0020 +#define PNPBIOS_REMOVABLE 0x0040 +#define pnpbios_is_static(x) (((x)->flags & 0x0100) == 0x0000) +#define pnpbios_is_dynamic(x) ((x)->flags & 0x0080) + +/* + * Function Parameters + */ +#define PNPMODE_STATIC 1 +#define PNPMODE_DYNAMIC 0 + +/* 0x8000 through 0xffff are OEM defined */ + +#pragma pack(1) +struct pnp_dev_node_info { + __u16 no_nodes; + __u16 max_node_size; +}; +struct pnp_docking_station_info { + __u32 location_id; + __u32 serial; + __u16 capabilities; +}; +struct pnp_isa_config_struc { + __u8 revision; + __u8 no_csns; + __u16 isa_rd_data_port; + __u16 reserved; +}; +struct escd_info_struc { + __u16 min_escd_write_size; + __u16 escd_size; + __u32 nv_storage_base; +}; +struct pnp_bios_node { + __u16 size; + __u8 handle; + __u32 eisa_id; + __u8 type_code[3]; + __u16 flags; + __u8 data[0]; +}; +#pragma pack() + +/* non-exported */ +extern struct pnp_dev_node_info node_info; + +extern int pnp_bios_dev_node_info(struct pnp_dev_node_info *data); +extern int pnp_bios_get_dev_node(u8 *nodenum, char config, + struct pnp_bios_node *data); +extern int pnp_bios_set_dev_node(u8 nodenum, char config, + struct pnp_bios_node *data); +extern int pnp_bios_get_stat_res(char *info); +extern int pnp_bios_isapnp_config(struct pnp_isa_config_struc *data); +extern int pnp_bios_escd_info(struct escd_info_struc *data); +extern int pnp_bios_read_escd(char *data, u32 nvram_base); +extern int pnp_bios_dock_station_info(struct pnp_docking_station_info *data); + #pragma pack(1) union pnp_bios_install_struct { struct { diff --git a/drivers/pnp/pnpbios/proc.c b/drivers/pnp/pnpbios/proc.c index bb19bc957bad..4f89f1677e69 100644 --- a/drivers/pnp/pnpbios/proc.c +++ b/drivers/pnp/pnpbios/proc.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c index ed63ecd9bf40..2e2c457a0fea 100644 --- a/drivers/pnp/pnpbios/rsparser.c +++ b/drivers/pnp/pnpbios/rsparser.c @@ -4,7 +4,6 @@ #include #include -#include #include #include diff --git a/include/linux/pnpbios.h b/include/linux/pnpbios.h deleted file mode 100644 index 329192adc9dd..000000000000 --- a/include/linux/pnpbios.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Include file for the interface to a PnP BIOS - * - * Original BIOS code (C) 1998 Christian Schmidt (chr.schmidt@tu-bs.de) - * PnP handler parts (c) 1998 Tom Lees - * Minor reorganizations by David Hinds - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _LINUX_PNPBIOS_H -#define _LINUX_PNPBIOS_H - -#ifdef __KERNEL__ - -#include -#include - -/* - * Return codes - */ -#define PNP_SUCCESS 0x00 -#define PNP_NOT_SET_STATICALLY 0x7f -#define PNP_UNKNOWN_FUNCTION 0x81 -#define PNP_FUNCTION_NOT_SUPPORTED 0x82 -#define PNP_INVALID_HANDLE 0x83 -#define PNP_BAD_PARAMETER 0x84 -#define PNP_SET_FAILED 0x85 -#define PNP_EVENTS_NOT_PENDING 0x86 -#define PNP_SYSTEM_NOT_DOCKED 0x87 -#define PNP_NO_ISA_PNP_CARDS 0x88 -#define PNP_UNABLE_TO_DETERMINE_DOCK_CAPABILITIES 0x89 -#define PNP_CONFIG_CHANGE_FAILED_NO_BATTERY 0x8a -#define PNP_CONFIG_CHANGE_FAILED_RESOURCE_CONFLICT 0x8b -#define PNP_BUFFER_TOO_SMALL 0x8c -#define PNP_USE_ESCD_SUPPORT 0x8d -#define PNP_MESSAGE_NOT_SUPPORTED 0x8e -#define PNP_HARDWARE_ERROR 0x8f - -#define ESCD_SUCCESS 0x00 -#define ESCD_IO_ERROR_READING 0x55 -#define ESCD_INVALID 0x56 -#define ESCD_BUFFER_TOO_SMALL 0x59 -#define ESCD_NVRAM_TOO_SMALL 0x5a -#define ESCD_FUNCTION_NOT_SUPPORTED 0x81 - -/* - * Events that can be received by "get event" - */ -#define PNPEV_ABOUT_TO_CHANGE_CONFIG 0x0001 -#define PNPEV_DOCK_CHANGED 0x0002 -#define PNPEV_SYSTEM_DEVICE_CHANGED 0x0003 -#define PNPEV_CONFIG_CHANGED_FAILED 0x0004 -#define PNPEV_UNKNOWN_SYSTEM_EVENT 0xffff -/* 0x8000 through 0xfffe are OEM defined */ - -/* - * Messages that should be sent through "send message" - */ -#define PNPMSG_OK 0x00 -#define PNPMSG_ABORT 0x01 -#define PNPMSG_UNDOCK_DEFAULT_ACTION 0x40 -#define PNPMSG_POWER_OFF 0x41 -#define PNPMSG_PNP_OS_ACTIVE 0x42 -#define PNPMSG_PNP_OS_INACTIVE 0x43 - -/* - * Plug and Play BIOS flags - */ -#define PNPBIOS_NO_DISABLE 0x0001 -#define PNPBIOS_NO_CONFIG 0x0002 -#define PNPBIOS_OUTPUT 0x0004 -#define PNPBIOS_INPUT 0x0008 -#define PNPBIOS_BOOTABLE 0x0010 -#define PNPBIOS_DOCK 0x0020 -#define PNPBIOS_REMOVABLE 0x0040 -#define pnpbios_is_static(x) (((x)->flags & 0x0100) == 0x0000) -#define pnpbios_is_dynamic(x) ((x)->flags & 0x0080) - -/* - * Function Parameters - */ -#define PNPMODE_STATIC 1 -#define PNPMODE_DYNAMIC 0 - -/* 0x8000 through 0xffff are OEM defined */ - -#pragma pack(1) -struct pnp_dev_node_info { - __u16 no_nodes; - __u16 max_node_size; -}; -struct pnp_docking_station_info { - __u32 location_id; - __u32 serial; - __u16 capabilities; -}; -struct pnp_isa_config_struc { - __u8 revision; - __u8 no_csns; - __u16 isa_rd_data_port; - __u16 reserved; -}; -struct escd_info_struc { - __u16 min_escd_write_size; - __u16 escd_size; - __u32 nv_storage_base; -}; -struct pnp_bios_node { - __u16 size; - __u8 handle; - __u32 eisa_id; - __u8 type_code[3]; - __u16 flags; - __u8 data[0]; -}; -#pragma pack() - -#ifdef CONFIG_PNPBIOS - -/* non-exported */ -extern struct pnp_dev_node_info node_info; - -extern int pnp_bios_dev_node_info(struct pnp_dev_node_info *data); -extern int pnp_bios_get_dev_node(u8 *nodenum, char config, - struct pnp_bios_node *data); -extern int pnp_bios_set_dev_node(u8 nodenum, char config, - struct pnp_bios_node *data); -extern int pnp_bios_get_stat_res(char *info); -extern int pnp_bios_isapnp_config(struct pnp_isa_config_struc *data); -extern int pnp_bios_escd_info(struct escd_info_struc *data); -extern int pnp_bios_read_escd(char *data, u32 nvram_base); -extern int pnp_bios_dock_station_info(struct pnp_docking_station_info *data); - -#endif /* CONFIG_PNPBIOS */ - -#endif /* __KERNEL__ */ - -#endif /* _LINUX_PNPBIOS_H */ -- cgit v1.2.2 From 51ae796f7fa1d8034252628572053f477bc29913 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dami=C3=A1n=20Viano?= Date: Tue, 29 Apr 2008 03:32:25 -0400 Subject: ACPICA: always disable GPE when requested MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit acpi_ev_disable_gpe() has an optimization where it doesn't disable a GPE that it "doesn't have to". Unfortunately, it can get tricked by AML that scribbles on register state behind its back. So when asked to disable a GPE, simply do it -- a redundant register write in the common case is a fair price to pay to be bomb-proof for the rare cases. http://bugzilla.kernel.org/show_bug.cgi?id=6217 Signed-off-by: Damián Viano Acked-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/events/evgpe.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c index 0dadd2adc800..cd06170e7871 100644 --- a/drivers/acpi/events/evgpe.c +++ b/drivers/acpi/events/evgpe.c @@ -248,10 +248,6 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) ACPI_FUNCTION_TRACE(ev_disable_gpe); - if (!(gpe_event_info->flags & ACPI_GPE_ENABLE_MASK)) { - return_ACPI_STATUS(AE_OK); - } - /* Make sure HW enable masks are updated */ status = -- cgit v1.2.2 From b59727965d7f286489206c292e2788d4835a8a23 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 26 Apr 2008 01:02:17 -0300 Subject: ACPI: thinkpad-acpi: BIOS backlight mode helper (v2.1) Lenovo ThinkPads with generic ACPI backlight level control can be easily set to react to keyboard brightness key presses in a more predictable way than what they do when in "DOS / bootloader" mode after Linux brings up the ACPI interface. The switch to the ACPI backlight mode in the firmware is designed to be safe to use only as an one way trapdoor. One is not to force the firmware to switch back to "DOS/bootloader" mode except by rebooting. The mode switch itself is performed by calling any of the ACPI _BCL methods at least once. When in ACPI mode, the backlight firmware just issues (standard) events for the brightness up/down hot key presses along with the non-standard HKEY events which thinkpad-acpi traps, and doesn't touch the hardware. thinkpad-acpi will: 1. Place the ThinkPad firmware in ACPI backlight control mode if one is available 2. Suppress HKEY backlight change notifications by default to avoid double-reporting when ACPI video is loaded when the ThinkPad is in ACPI backlight control mode 3. Urge the user to load the ACPI video driver The user is free to use either the ACPI video driver to get the brightness key events, or to override the thinkpad-acpi default hotkey mask to get them from thinkpad-acpi as well (this will result in duplicate events if ACPI video is loaded, so let's hope distros won't screw this up). Provided userspace is sane, all should work (and *keep* working), which is more that can be said about the non-ACPI mode of the new Lenovo ThinkPad BIOSes when coupled to current userspace and X.org drivers. Full guidelines for backlight hot key reporting and use of the thinkpad-acpi backlight interface have been added to the documentation. Signed-off-by: Henrique de Moraes Holschuh Cc: Matthew Garrett Cc: Thomas Renninger Signed-off-by: Len Brown --- Documentation/laptops/thinkpad-acpi.txt | 50 +++++++ drivers/misc/thinkpad_acpi.c | 238 ++++++++++++++++++-------------- 2 files changed, 183 insertions(+), 105 deletions(-) diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index 76cb428435da..a77da28a6f8e 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt @@ -571,6 +571,47 @@ netlink interface and the input layer interface, and don't bother at all with hotkey_report_mode. +Brightness hotkey notes: + +These are the current sane choices for brightness key mapping in +thinkpad-acpi: + +For IBM and Lenovo models *without* ACPI backlight control (the ones on +which thinkpad-acpi will autoload its backlight interface by default, +and on which ACPI video does not export a backlight interface): + +1. Don't enable or map the brightness hotkeys in thinkpad-acpi, as + these older firmware versions unfortunately won't respect the hotkey + mask for brightness keys anyway, and always reacts to them. This + usually work fine, unless X.org drivers are doing something to block + the BIOS. In that case, use (3) below. This is the default mode of + operation. + +2. Enable the hotkeys, but map them to something else that is NOT + KEY_BRIGHTNESS_UP/DOWN or any other keycode that would cause + userspace to try to change the backlight level, and use that as an + on-screen-display hint. + +3. IF AND ONLY IF X.org drivers find a way to block the firmware from + automatically changing the brightness, enable the hotkeys and map + them to KEY_BRIGHTNESS_UP and KEY_BRIGHTNESS_DOWN, and feed that to + something that calls xbacklight. thinkpad-acpi will not be able to + change brightness in that case either, so you should disable its + backlight interface. + +For Lenovo models *with* ACPI backlight control: + +1. Load up ACPI video and use that. ACPI video will report ACPI + events for brightness change keys. Do not mess with thinkpad-acpi + defaults in this case. thinkpad-acpi should not have anything to do + with backlight events in a scenario where ACPI video is loaded: + brightness hotkeys must be disabled, and the backlight interface is + to be kept disabled as well. This is the default mode of operation. + +2. Do *NOT* load up ACPI video, enable the hotkeys in thinkpad-acpi, + and map them to KEY_BRIGHTNESS_UP and KEY_BRIGHTNESS_DOWN. Process + these keys on userspace somehow (e.g. by calling xbacklight). + Bluetooth --------- @@ -1090,6 +1131,15 @@ it there will be the following attributes: dim the display. +WARNING: + + Whatever you do, do NOT ever call thinkpad-acpi backlight-level change + interface and the ACPI-based backlight level change interface + (available on newer BIOSes, and driven by the Linux ACPI video driver) + at the same time. The two will interact in bad ways, do funny things, + and maybe reduce the life of the backlight lamps by needlessly kicking + its level up and down at every change. + Volume control -- /proc/acpi/ibm/volume --------------------------------------- diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 6cb781262f94..2c85a2e10a25 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -225,6 +225,7 @@ static struct { u32 light:1; u32 light_status:1; u32 bright_16levels:1; + u32 bright_acpimode:1; u32 wan:1; u32 fan_ctrl_status_undef:1; u32 input_device_registered:1; @@ -807,6 +808,80 @@ static int parse_strtoul(const char *buf, return 0; } +static int __init tpacpi_query_bcl_levels(acpi_handle handle) +{ + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *obj; + int rc; + + if (ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buffer))) { + obj = (union acpi_object *)buffer.pointer; + if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) { + printk(TPACPI_ERR "Unknown _BCL data, " + "please report this to %s\n", TPACPI_MAIL); + rc = 0; + } else { + rc = obj->package.count; + } + } else { + return 0; + } + + kfree(buffer.pointer); + return rc; +} + +static acpi_status __init tpacpi_acpi_walk_find_bcl(acpi_handle handle, + u32 lvl, void *context, void **rv) +{ + char name[ACPI_PATH_SEGMENT_LENGTH]; + struct acpi_buffer buffer = { sizeof(name), &name }; + + if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) && + !strncmp("_BCL", name, sizeof(name) - 1)) { + BUG_ON(!rv || !*rv); + **(int **)rv = tpacpi_query_bcl_levels(handle); + return AE_CTRL_TERMINATE; + } else { + return AE_OK; + } +} + +/* + * Returns 0 (no ACPI _BCL or _BCL invalid), or size of brightness map + */ +static int __init tpacpi_check_std_acpi_brightness_support(void) +{ + int status; + int bcl_levels = 0; + void *bcl_ptr = &bcl_levels; + + if (!vid_handle) { + TPACPI_ACPIHANDLE_INIT(vid); + } + if (!vid_handle) + return 0; + + /* + * Search for a _BCL method, and execute it. This is safe on all + * ThinkPads, and as a side-effect, _BCL will place a Lenovo Vista + * BIOS in ACPI backlight control mode. We do NOT have to care + * about calling the _BCL method in an enabled video device, any + * will do for our purposes. + */ + + status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3, + tpacpi_acpi_walk_find_bcl, NULL, + &bcl_ptr); + + if (ACPI_SUCCESS(status) && bcl_levels > 2) { + tp_features.bright_acpimode = 1; + return (bcl_levels - 2); + } + + return 0; +} + /************************************************************************* * thinkpad-acpi driver attributes */ @@ -1887,6 +1962,9 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) KEY_UNKNOWN, /* 0x0D: FN+INSERT */ KEY_UNKNOWN, /* 0x0E: FN+DELETE */ + /* These either have to go through ACPI video, or + * act like in the IBM ThinkPads, so don't ever + * enable them by default */ KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */ KEY_RESERVED, /* 0x10: FN+END (brightness down) */ @@ -2091,6 +2169,32 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit); } + /* Do not issue duplicate brightness change events to + * userspace */ + if (!tp_features.bright_acpimode) + /* update bright_acpimode... */ + tpacpi_check_std_acpi_brightness_support(); + + if (tp_features.bright_acpimode) { + printk(TPACPI_INFO + "This ThinkPad has standard ACPI backlight " + "brightness control, supported by the ACPI " + "video driver\n"); + printk(TPACPI_NOTICE + "Disabling thinkpad-acpi brightness events " + "by default...\n"); + + /* The hotkey_reserved_mask change below is not + * necessary while the keys are at KEY_RESERVED in the + * default map, but better safe than sorry, leave it + * here as a marker of what we have to do, especially + * when we finally become able to set this at runtime + * on response to X.org requests */ + hotkey_reserved_mask |= + (1 << TP_ACPI_HOTKEYSCAN_FNHOME) + | (1 << TP_ACPI_HOTKEYSCAN_FNEND); + } + dbg_printk(TPACPI_DBG_INIT, "enabling hot key handling\n"); res = hotkey_status_set(1); @@ -4273,100 +4377,6 @@ static struct backlight_ops ibm_backlight_data = { /* --------------------------------------------------------------------- */ -static int __init tpacpi_query_bcll_levels(acpi_handle handle) -{ - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *obj; - int rc; - - if (ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buffer))) { - obj = (union acpi_object *)buffer.pointer; - if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) { - printk(TPACPI_ERR "Unknown BCLL data, " - "please report this to %s\n", TPACPI_MAIL); - rc = 0; - } else { - rc = obj->package.count; - } - } else { - return 0; - } - - kfree(buffer.pointer); - return rc; -} - -static acpi_status __init brightness_find_bcll(acpi_handle handle, u32 lvl, - void *context, void **rv) -{ - char name[ACPI_PATH_SEGMENT_LENGTH]; - struct acpi_buffer buffer = { sizeof(name), &name }; - - if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) && - !strncmp("BCLL", name, sizeof(name) - 1)) { - if (tpacpi_query_bcll_levels(handle) == 16) { - *rv = handle; - return AE_CTRL_TERMINATE; - } else { - return AE_OK; - } - } else { - return AE_OK; - } -} - -static int __init brightness_check_levels(void) -{ - int status; - void *found_node = NULL; - - if (!vid_handle) { - TPACPI_ACPIHANDLE_INIT(vid); - } - if (!vid_handle) - return 0; - - /* Search for a BCLL package with 16 levels */ - status = acpi_walk_namespace(ACPI_TYPE_PACKAGE, vid_handle, 3, - brightness_find_bcll, NULL, - &found_node); - - return (ACPI_SUCCESS(status) && found_node != NULL); -} - -static acpi_status __init brightness_find_bcl(acpi_handle handle, u32 lvl, - void *context, void **rv) -{ - char name[ACPI_PATH_SEGMENT_LENGTH]; - struct acpi_buffer buffer = { sizeof(name), &name }; - - if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) && - !strncmp("_BCL", name, sizeof(name) - 1)) { - *rv = handle; - return AE_CTRL_TERMINATE; - } else { - return AE_OK; - } -} - -static int __init brightness_check_std_acpi_support(void) -{ - int status; - void *found_node = NULL; - - if (!vid_handle) { - TPACPI_ACPIHANDLE_INIT(vid); - } - if (!vid_handle) - return 0; - - /* Search for a _BCL method, but don't execute it */ - status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3, - brightness_find_bcl, NULL, &found_node); - - return (ACPI_SUCCESS(status) && found_node != NULL); -} - static int __init brightness_init(struct ibm_init_struct *iibm) { int b; @@ -4375,13 +4385,19 @@ static int __init brightness_init(struct ibm_init_struct *iibm) mutex_init(&brightness_mutex); - if (!brightness_enable) { - dbg_printk(TPACPI_DBG_INIT, - "brightness support disabled by " - "module parameter\n"); - return 1; - } else if (brightness_enable > 1) { - if (brightness_check_std_acpi_support()) { + /* + * We always attempt to detect acpi support, so as to switch + * Lenovo Vista BIOS to ACPI brightness mode even if we are not + * going to publish a backlight interface + */ + b = tpacpi_check_std_acpi_brightness_support(); + if (b > 0) { + if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) { + printk(TPACPI_NOTICE + "Lenovo BIOS switched to ACPI backlight " + "control mode\n"); + } + if (brightness_enable > 1) { printk(TPACPI_NOTICE "standard ACPI backlight interface " "available, not loading native one...\n"); @@ -4389,6 +4405,22 @@ static int __init brightness_init(struct ibm_init_struct *iibm) } } + if (!brightness_enable) { + dbg_printk(TPACPI_DBG_INIT, + "brightness support disabled by " + "module parameter\n"); + return 1; + } + + if (b > 16) { + printk(TPACPI_ERR + "Unsupported brightness interface, " + "please contact %s\n", TPACPI_MAIL); + return 1; + } + if (b == 16) + tp_features.bright_16levels = 1; + if (!brightness_mode) { if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) brightness_mode = 2; @@ -4402,10 +4434,6 @@ static int __init brightness_init(struct ibm_init_struct *iibm) if (brightness_mode > 3) return -EINVAL; - tp_features.bright_16levels = - thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO && - brightness_check_levels(); - b = brightness_get(NULL); if (b < 0) return 1; -- cgit v1.2.2 From 92889022250d736e135ca92fbffd1ab0ea4780d1 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 26 Apr 2008 01:02:18 -0300 Subject: ACPI: thinkpad-acpi: warn once about weird hotkey masks thinkpad-acpi knows for a while now how to best program the hotkeys by default, and always enable them by default. Unfortunately, this information has not filtered down everywhere it needs to, yet. Notably, old ibm-acpi documentation and most "thinkpad setup guides" will have wrong information on this area. Warn the local admin once whenever any of the following patterns are met: 1. Attempts to set hotkey mask to 0xffff (artifact from docs and config for the old ibm-acpi driver and behaviour). This mask makes no real-world sense; 2. Attempts to set hotkey mask to 0xffffffff, which means the user is trying to just have "everything work" without even reading the documentation, or that we need to get a bug report, because there is a new thinkpad out there with new exciting hot keys :-) 3. Attempts to set hotkey mask to 0xffffff, which is almost never the correct way to set up volume and brightness event reporting (and with the current state-of-the-art, it is known to never be right way to do it). The driver will perform any and all requested operations, though, regardless of any warnings. I hope these warnings can be removed one or two years from now. Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- drivers/misc/thinkpad_acpi.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 2c85a2e10a25..cd263c518e06 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -237,6 +237,10 @@ static struct { u32 hotkey_poll_active:1; } tp_features; +static struct { + u16 hotkey_mask_ff:1; +} tp_warned; + struct thinkpad_id_data { unsigned int vendor; /* ThinkPad vendor: * PCI_VENDOR_ID_IBM/PCI_VENDOR_ID_LENOVO */ @@ -1182,6 +1186,19 @@ static int hotkey_mask_set(u32 mask) int rc = 0; if (tp_features.hotkey_mask) { + if (!tp_warned.hotkey_mask_ff && + (mask == 0xffff || mask == 0xffffff || + mask == 0xffffffff)) { + tp_warned.hotkey_mask_ff = 1; + printk(TPACPI_NOTICE + "setting the hotkey mask to 0x%08x is likely " + "not the best way to go about it\n", mask); + printk(TPACPI_NOTICE + "please consider using the driver defaults, " + "and refer to up-to-date thinkpad-acpi " + "documentation\n"); + } + HOTKEY_CONFIG_CRITICAL_START for (i = 0; i < 32; i++) { u32 m = 1 << i; -- cgit v1.2.2 From 8c74adbc692a3cb040cc69d7ca3dfd86d75860a8 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 26 Apr 2008 01:02:19 -0300 Subject: ACPI: thinkpad-acpi: enhance box identification output (v2) During initialization, thinkpad-acpi outputs some messages to make sure releavant box identification information is easily available in-line with the rest of the driver messages. Enhance those messages to output the alfanumeric model number as well. Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- drivers/misc/thinkpad_acpi.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index cd263c518e06..601dbe8b407a 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -251,7 +251,8 @@ struct thinkpad_id_data { u16 bios_model; /* Big Endian, TP-1Y = 0x5931, 0 = unknown */ u16 ec_model; - char *model_str; + char *model_str; /* ThinkPad T43 */ + char *nummodel_str; /* 9384A9C for a 9384-A9C model */ }; static struct thinkpad_id_data thinkpad_id; @@ -988,12 +989,14 @@ static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm) thinkpad_id.ec_version_str : "unknown"); if (thinkpad_id.vendor && thinkpad_id.model_str) - printk(TPACPI_INFO "%s %s\n", + printk(TPACPI_INFO "%s %s, model %s\n", (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) ? "IBM" : ((thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) ? "Lenovo" : "Unknown vendor"), - thinkpad_id.model_str); + thinkpad_id.model_str, + (thinkpad_id.nummodel_str) ? + thinkpad_id.nummodel_str : "unknown"); return 0; } @@ -5875,6 +5878,9 @@ static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp) kfree(tp->model_str); tp->model_str = NULL; } + + tp->nummodel_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_NAME), + GFP_KERNEL); } static int __init probe_for_thinkpad(void) -- cgit v1.2.2 From 2d5e94d7ca315f859a0eee1366838e8ad34dd7b2 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 26 Apr 2008 01:02:20 -0300 Subject: ACPI: thinkpad-acpi: rate-limit CMOS/EC unsynced error messages If userspace applications mess with the CMOS NVRAM, or something causes both the ACPI firmware and thinkpad-acpi to try to change the brightness at the same time, it is possible to have the CMOS and EC registers for the current brightness go out of sync. Should that happen, thinkpad-acpi could be really obnoxious when using a brightness_mode of 3 (both EC and CMOS). Instead of complaining a massive number of times, make sure to complain only once until EC and CMOS are back in sync. Signed-off-by: Henrique de Moraes Holschuh Cc: Joerg Platte Signed-off-by: Len Brown --- drivers/misc/thinkpad_acpi.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 601dbe8b407a..7dc6b73e8f5b 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -239,6 +239,7 @@ static struct { static struct { u16 hotkey_mask_ff:1; + u16 bright_cmos_ec_unsync:1; } tp_warned; struct thinkpad_id_data { @@ -4323,13 +4324,20 @@ static int brightness_get(struct backlight_device *bd) level = lcmos; } - if (brightness_mode == 3 && lec != lcmos) { - printk(TPACPI_ERR - "CMOS NVRAM (%u) and EC (%u) do not agree " - "on display brightness level\n", - (unsigned int) lcmos, - (unsigned int) lec); - return -EIO; + if (brightness_mode == 3) { + if (lec == lcmos) + tp_warned.bright_cmos_ec_unsync = 0; + else { + if (!tp_warned.bright_cmos_ec_unsync) { + printk(TPACPI_ERR + "CMOS NVRAM (%u) and EC (%u) do not " + "agree on display brightness level\n", + (unsigned int) lcmos, + (unsigned int) lec); + tp_warned.bright_cmos_ec_unsync = 1; + } + return -EIO; + } } return level; -- cgit v1.2.2 From e11aecf1379e7c4a0293182096e38e5a336696b2 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 26 Apr 2008 01:02:21 -0300 Subject: ACPI: thinkpad-acpi: fix brightness dimming control bug ibm-acpi and thinkpad-acpi did not know about bit 5 of the EC backlight level control register (EC 0x31), so it was always forced to zero on any writes. This would disable the BIOS option to *not* use a dimmer backlight level scale while on battery, and who knows what else (there are two other control bits of unknown function). Bit 5 controls the "reduce backlight levels when on battery" optional functionality (active low). Bits 6 and 7 are better left alone as well, instead of being forced to zero. Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- drivers/misc/thinkpad_acpi.c | 64 +++++++++++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 15 deletions(-) diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 7dc6b73e8f5b..5e25abc54008 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -4295,8 +4295,16 @@ static struct ibm_struct ecdump_driver_data = { #define TPACPI_BACKLIGHT_DEV_NAME "thinkpad_screen" +enum { + TP_EC_BACKLIGHT = 0x31, + + /* TP_EC_BACKLIGHT bitmasks */ + TP_EC_BACKLIGHT_LVLMSK = 0x1F, + TP_EC_BACKLIGHT_CMDMSK = 0xE0, + TP_EC_BACKLIGHT_MAPSW = 0x20, +}; + static struct backlight_device *ibm_backlight_device; -static int brightness_offset = 0x31; static int brightness_mode; static unsigned int brightness_enable = 2; /* 2 = auto, 0 = no, 1 = yes */ @@ -4305,16 +4313,24 @@ static struct mutex brightness_mutex; /* * ThinkPads can read brightness from two places: EC 0x31, or * CMOS NVRAM byte 0x5E, bits 0-3. + * + * EC 0x31 has the following layout + * Bit 7: unknown function + * Bit 6: unknown function + * Bit 5: Z: honour scale changes, NZ: ignore scale changes + * Bit 4: must be set to zero to avoid problems + * Bit 3-0: backlight brightness level + * + * brightness_get_raw returns status data in the EC 0x31 layout */ -static int brightness_get(struct backlight_device *bd) +static int brightness_get_raw(int *status) { u8 lec = 0, lcmos = 0, level = 0; if (brightness_mode & 1) { - if (!acpi_ec_read(brightness_offset, &lec)) + if (!acpi_ec_read(TP_EC_BACKLIGHT, &lec)) return -EIO; - lec &= (tp_features.bright_16levels)? 0x0f : 0x07; - level = lec; + level = lec & TP_EC_BACKLIGHT_LVLMSK; }; if (brightness_mode & 2) { lcmos = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS) @@ -4325,6 +4341,8 @@ static int brightness_get(struct backlight_device *bd) } if (brightness_mode == 3) { + *status = lec; /* Prefer EC, CMOS is just a backing store */ + lec &= TP_EC_BACKLIGHT_LVLMSK; if (lec == lcmos) tp_warned.bright_cmos_ec_unsync = 0; else { @@ -4338,9 +4356,11 @@ static int brightness_get(struct backlight_device *bd) } return -EIO; } + } else { + *status = level; } - return level; + return 0; } /* May return EINTR which can always be mapped to ERESTARTSYS */ @@ -4348,19 +4368,22 @@ static int brightness_set(int value) { int cmos_cmd, inc, i, res; int current_value; + int command_bits; - if (value > ((tp_features.bright_16levels)? 15 : 7)) + if (value > ((tp_features.bright_16levels)? 15 : 7) || + value < 0) return -EINVAL; res = mutex_lock_interruptible(&brightness_mutex); if (res < 0) return res; - current_value = brightness_get(NULL); - if (current_value < 0) { - res = current_value; + res = brightness_get_raw(¤t_value); + if (res < 0) goto errout; - } + + command_bits = current_value & TP_EC_BACKLIGHT_CMDMSK; + current_value &= TP_EC_BACKLIGHT_LVLMSK; cmos_cmd = value > current_value ? TP_CMOS_BRIGHTNESS_UP : @@ -4375,7 +4398,8 @@ static int brightness_set(int value) goto errout; } if ((brightness_mode & 1) && - !acpi_ec_write(brightness_offset, i + inc)) { + !acpi_ec_write(TP_EC_BACKLIGHT, + (i + inc) | command_bits)) { res = -EIO; goto errout;; } @@ -4398,6 +4422,17 @@ static int brightness_update_status(struct backlight_device *bd) bd->props.brightness : 0); } +static int brightness_get(struct backlight_device *bd) +{ + int status, res; + + res = brightness_get_raw(&status); + if (res < 0) + return 0; /* FIXME: teach backlight about error handling */ + + return status & TP_EC_BACKLIGHT_LVLMSK; +} + static struct backlight_ops ibm_backlight_data = { .get_brightness = brightness_get, .update_status = brightness_update_status, @@ -4462,8 +4497,7 @@ static int __init brightness_init(struct ibm_init_struct *iibm) if (brightness_mode > 3) return -EINVAL; - b = brightness_get(NULL); - if (b < 0) + if (brightness_get_raw(&b) < 0) return 1; if (tp_features.bright_16levels) @@ -4481,7 +4515,7 @@ static int __init brightness_init(struct ibm_init_struct *iibm) ibm_backlight_device->props.max_brightness = (tp_features.bright_16levels)? 15 : 7; - ibm_backlight_device->props.brightness = b; + ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK; backlight_update_status(ibm_backlight_device); return 0; -- cgit v1.2.2 From 95e57ab2cbd8b016327b23d76da8a96cbd26ac0c Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 26 Apr 2008 01:02:22 -0300 Subject: ACPI: thinkpad-acpi: claim tpacpi as an official short handle (v1.1) Unfortunately, a lot of stuff in the kernel has size limitations, so "thinkpad-acpi" ends up eating up too much real estate. We were using "tpacpi" in symbols already, but this shorthand was not visible to userland. Document that the driver will use tpacpi as a short hand where necessary, and use it to name the kernel thread for NVRAM polling (now named "ktpacpi_nvramd"). Also, register a module alias with the shorthand. One can refer to the module using the shorthand name. Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- Documentation/laptops/thinkpad-acpi.txt | 5 +++++ drivers/misc/thinkpad_acpi.c | 8 ++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index a77da28a6f8e..a41bc893f8d6 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt @@ -18,6 +18,11 @@ This driver used to be named ibm-acpi until kernel 2.6.21 and release moved to the drivers/misc tree and renamed to thinkpad-acpi for kernel 2.6.22, and release 0.14. +The driver is named "thinkpad-acpi". In some places, like module +names, "thinkpad_acpi" is used because of userspace issues. + +"tpacpi" is used as a shorthand where "thinkpad-acpi" would be too +long due to length limitations on some Linux kernel versions. Status ------ diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 5e25abc54008..2b73dfafac9d 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -133,8 +133,11 @@ enum { #define TPACPI_PROC_DIR "ibm" #define TPACPI_ACPI_EVENT_PREFIX "ibm" #define TPACPI_DRVR_NAME TPACPI_FILE +#define TPACPI_DRVR_SHORTNAME "tpacpi" #define TPACPI_HWMON_DRVR_NAME TPACPI_NAME "_hwmon" +#define TPACPI_NVRAM_KTHREAD_NAME "ktpacpi_nvramd" + #define TPACPI_MAX_ACPI_ARGS 3 /* Debugging */ @@ -1523,8 +1526,7 @@ static void hotkey_poll_setup(int may_warn) (tpacpi_inputdev->users > 0 || hotkey_report_mode < 2)) { if (!tpacpi_hotkey_task) { tpacpi_hotkey_task = kthread_run(hotkey_kthread, - NULL, - TPACPI_FILE "d"); + NULL, TPACPI_NVRAM_KTHREAD_NAME); if (IS_ERR(tpacpi_hotkey_task)) { tpacpi_hotkey_task = NULL; printk(TPACPI_ERR @@ -6316,6 +6318,8 @@ static int __init thinkpad_acpi_module_init(void) /* Please remove this in year 2009 */ MODULE_ALIAS("ibm_acpi"); +MODULE_ALIAS(TPACPI_DRVR_SHORTNAME); + /* * DMI matching for module autoloading * -- cgit v1.2.2 From 4fa6811b8ade1b7839342824939817a8fc751539 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 26 Apr 2008 01:02:23 -0300 Subject: ACPI: thinkpad-acpi: prepare light and LED for sysfs support Do some preparatory work to add sysfs support to the thinklight and thinkpad leds driver. Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- drivers/misc/Kconfig | 2 + drivers/misc/thinkpad_acpi.c | 191 ++++++++++++++++++++++++++++++------------- 2 files changed, 138 insertions(+), 55 deletions(-) diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 297a48f85446..3a5d7694b878 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -245,6 +245,8 @@ config THINKPAD_ACPI select HWMON select NVRAM depends on INPUT + select NEW_LEDS + select LEDS_CLASS ---help--- This is a driver for the IBM and Lenovo ThinkPad laptops. It adds support for Fn-Fx key combinations, Bluetooth control, video diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 2b73dfafac9d..5a3fb09f10d3 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -67,6 +67,7 @@ #include #include #include +#include #include #include @@ -85,6 +86,8 @@ #define TP_CMOS_VOLUME_MUTE 2 #define TP_CMOS_BRIGHTNESS_UP 4 #define TP_CMOS_BRIGHTNESS_DOWN 5 +#define TP_CMOS_THINKLIGHT_ON 12 +#define TP_CMOS_THINKLIGHT_OFF 13 /* NVRAM Addresses */ enum tp_nvram_addr { @@ -269,6 +272,13 @@ static enum { static int experimental; static u32 dbg_level; +/* Special LED class that can defer work */ +struct tpacpi_led_classdev { + struct led_classdev led_classdev; + struct work_struct work; + enum led_brightness new_brightness; +}; + /**************************************************************************** **************************************************************************** * @@ -3237,6 +3247,39 @@ static struct ibm_struct video_driver_data = { TPACPI_HANDLE(lght, root, "\\LGHT"); /* A21e, A2xm/p, T20-22, X20-21 */ TPACPI_HANDLE(ledb, ec, "LEDB"); /* G4x */ +static int light_get_status(void) +{ + int status = 0; + + if (tp_features.light_status) { + if (!acpi_evalf(ec_handle, &status, "KBLT", "d")) + return -EIO; + return (!!status); + } + + return -ENXIO; +} + +static int light_set_status(int status) +{ + int rc; + + if (tp_features.light) { + if (cmos_handle) { + rc = acpi_evalf(cmos_handle, NULL, NULL, "vd", + (status)? + TP_CMOS_THINKLIGHT_ON : + TP_CMOS_THINKLIGHT_OFF); + } else { + rc = acpi_evalf(lght_handle, NULL, NULL, "vd", + (status)? 1 : 0); + } + return (rc)? 0 : -EIO; + } + + return -ENXIO; +} + static int __init light_init(struct ibm_init_struct *iibm) { vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n"); @@ -3263,7 +3306,7 @@ static int __init light_init(struct ibm_init_struct *iibm) static int light_read(char *p) { int len = 0; - int status = 0; + int status; if (!tp_features.light) { len += sprintf(p + len, "status:\t\tnot supported\n"); @@ -3271,8 +3314,9 @@ static int light_read(char *p) len += sprintf(p + len, "status:\t\tunknown\n"); len += sprintf(p + len, "commands:\ton, off\n"); } else { - if (!acpi_evalf(ec_handle, &status, "KBLT", "d")) - return -EIO; + status = light_get_status(); + if (status < 0) + return status; len += sprintf(p + len, "status:\t\t%s\n", onoff(status, 0)); len += sprintf(p + len, "commands:\ton, off\n"); } @@ -3282,31 +3326,22 @@ static int light_read(char *p) static int light_write(char *buf) { - int cmos_cmd, lght_cmd; char *cmd; - int success; + int newstatus = 0; if (!tp_features.light) return -ENODEV; while ((cmd = next_cmd(&buf))) { if (strlencmp(cmd, "on") == 0) { - cmos_cmd = 0x0c; - lght_cmd = 1; + newstatus = 1; } else if (strlencmp(cmd, "off") == 0) { - cmos_cmd = 0x0d; - lght_cmd = 0; + newstatus = 0; } else return -EINVAL; - - success = cmos_handle ? - acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd) : - acpi_evalf(lght_handle, NULL, NULL, "vd", lght_cmd); - if (!success) - return -EIO; } - return 0; + return light_set_status(newstatus); } static struct ibm_struct light_driver_data = { @@ -3710,6 +3745,12 @@ enum { /* For TPACPI_LED_OLD */ TPACPI_LED_EC_HLMS = 0x0e, /* EC reg to select led to command */ }; +enum led_status_t { + TPACPI_LED_OFF = 0, + TPACPI_LED_ON, + TPACPI_LED_BLINK, +}; + static enum led_access_mode led_supported; TPACPI_HANDLE(led, ec, "SLED", /* 570 */ @@ -3718,6 +3759,69 @@ TPACPI_HANDLE(led, ec, "SLED", /* 570 */ "LED", /* all others */ ); /* R30, R31 */ +static int led_get_status(unsigned int led) +{ + int status; + + switch (led_supported) { + case TPACPI_LED_570: + if (!acpi_evalf(ec_handle, + &status, "GLED", "dd", 1 << led)) + return -EIO; + return (status == 0)? + TPACPI_LED_OFF : + ((status == 1)? + TPACPI_LED_ON : + TPACPI_LED_BLINK); + default: + return -ENXIO; + } + + /* not reached */ +} + +static int led_set_status(unsigned int led, enum led_status_t ledstatus) +{ + /* off, on, blink. Index is led_status_t */ + static const int const led_sled_arg1[] = { 0, 1, 3 }; + static const int const led_exp_hlbl[] = { 0, 0, 1 }; /* led# * */ + static const int const led_exp_hlcl[] = { 0, 1, 1 }; /* led# * */ + static const int const led_led_arg1[] = { 0, 0x80, 0xc0 }; + + int rc = 0; + + switch (led_supported) { + case TPACPI_LED_570: + /* 570 */ + led = 1 << led; + if (!acpi_evalf(led_handle, NULL, NULL, "vdd", + led, led_sled_arg1[ledstatus])) + rc = -EIO; + break; + case TPACPI_LED_OLD: + /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */ + led = 1 << led; + rc = ec_write(TPACPI_LED_EC_HLMS, led); + if (rc >= 0) + rc = ec_write(TPACPI_LED_EC_HLBL, + led * led_exp_hlbl[ledstatus]); + if (rc >= 0) + rc = ec_write(TPACPI_LED_EC_HLCL, + led * led_exp_hlcl[ledstatus]); + break; + case TPACPI_LED_NEW: + /* all others */ + if (!acpi_evalf(led_handle, NULL, NULL, "vdd", + led, led_led_arg1[ledstatus])) + rc = -EIO; + break; + default: + rc = -ENXIO; + } + + return rc; +} + static int __init led_init(struct ibm_init_struct *iibm) { vdbg_printk(TPACPI_DBG_INIT, "initializing LED subdriver\n"); @@ -3743,7 +3847,9 @@ static int __init led_init(struct ibm_init_struct *iibm) return (led_supported != TPACPI_LED_NONE)? 0 : 1; } -#define led_status(s) ((s) == 0 ? "off" : ((s) == 1 ? "on" : "blinking")) +#define str_led_status(s) \ + ((s) == TPACPI_LED_OFF ? "off" : \ + ((s) == TPACPI_LED_ON ? "on" : "blinking")) static int led_read(char *p) { @@ -3759,11 +3865,11 @@ static int led_read(char *p) /* 570 */ int i, status; for (i = 0; i < 8; i++) { - if (!acpi_evalf(ec_handle, - &status, "GLED", "dd", 1 << i)) + status = led_get_status(i); + if (status < 0) return -EIO; len += sprintf(p + len, "%d:\t\t%s\n", - i, led_status(status)); + i, str_led_status(status)); } } @@ -3773,16 +3879,11 @@ static int led_read(char *p) return len; } -/* off, on, blink */ -static const int led_sled_arg1[] = { 0, 1, 3 }; -static const int led_exp_hlbl[] = { 0, 0, 1 }; /* led# * */ -static const int led_exp_hlcl[] = { 0, 1, 1 }; /* led# * */ -static const int led_led_arg1[] = { 0, 0x80, 0xc0 }; - static int led_write(char *buf) { char *cmd; - int led, ind, ret; + int led, rc; + enum led_status_t s; if (!led_supported) return -ENODEV; @@ -3792,38 +3893,18 @@ static int led_write(char *buf) return -EINVAL; if (strstr(cmd, "off")) { - ind = 0; + s = TPACPI_LED_OFF; } else if (strstr(cmd, "on")) { - ind = 1; + s = TPACPI_LED_ON; } else if (strstr(cmd, "blink")) { - ind = 2; - } else - return -EINVAL; - - if (led_supported == TPACPI_LED_570) { - /* 570 */ - led = 1 << led; - if (!acpi_evalf(led_handle, NULL, NULL, "vdd", - led, led_sled_arg1[ind])) - return -EIO; - } else if (led_supported == TPACPI_LED_OLD) { - /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */ - led = 1 << led; - ret = ec_write(TPACPI_LED_EC_HLMS, led); - if (ret >= 0) - ret = ec_write(TPACPI_LED_EC_HLBL, - led * led_exp_hlbl[ind]); - if (ret >= 0) - ret = ec_write(TPACPI_LED_EC_HLCL, - led * led_exp_hlcl[ind]); - if (ret < 0) - return ret; + s = TPACPI_LED_BLINK; } else { - /* all others */ - if (!acpi_evalf(led_handle, NULL, NULL, "vdd", - led, led_led_arg1[ind])) - return -EIO; + return -EINVAL; } + + rc = led_set_status(led, s); + if (rc < 0) + return rc; } return 0; -- cgit v1.2.2 From e306501d1c4ff610feaba74ac35dd13e470480e6 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 26 Apr 2008 01:02:24 -0300 Subject: ACPI: thinkpad-acpi: add sysfs led class support for thinklight (v3.1) Add a sysfs led class interface to the thinklight (light subdriver). Signed-off-by: Henrique de Moraes Holschuh Cc: Richard Purdie Signed-off-by: Len Brown --- Documentation/laptops/thinkpad-acpi.txt | 25 ++++++++++++--- drivers/misc/thinkpad_acpi.c | 57 ++++++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 6 deletions(-) diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index a41bc893f8d6..af1f2bcb6f66 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt @@ -693,16 +693,31 @@ while others are still having problems. For more information: https://bugs.freedesktop.org/show_bug.cgi?id=2000 -ThinkLight control -- /proc/acpi/ibm/light ------------------------------------------- +ThinkLight control +------------------ + +procfs: /proc/acpi/ibm/light +sysfs attributes: as per led class, for the "tpacpi::thinklight" led + +procfs notes: -The current status of the ThinkLight can be found in this file. A few -models which do not make the status available will show it as -"unknown". The available commands are: +The ThinkLight status can be read and set through the procfs interface. A +few models which do not make the status available will show the ThinkLight +status as "unknown". The available commands are: echo on > /proc/acpi/ibm/light echo off > /proc/acpi/ibm/light +sysfs notes: + +The ThinkLight sysfs interface is documented by the led class +documentation, in Documentation/leds-class.txt. The ThinkLight led name +is "tpacpi::thinklight". + +Due to limitations in the sysfs led class, if the status of the thinklight +cannot be read or if it is unknown, thinkpad-acpi will report it as "off". +It is impossible to know if the status returned through sysfs is valid. + Docking / undocking -- /proc/acpi/ibm/dock ------------------------------------------ diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 5a3fb09f10d3..38a119bd931e 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -3280,13 +3280,49 @@ static int light_set_status(int status) return -ENXIO; } +static void light_set_status_worker(struct work_struct *work) +{ + struct tpacpi_led_classdev *data = + container_of(work, struct tpacpi_led_classdev, work); + + if (likely(tpacpi_lifecycle == TPACPI_LIFE_RUNNING)) + light_set_status((data->new_brightness != LED_OFF)); +} + +static void light_sysfs_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct tpacpi_led_classdev *data = + container_of(led_cdev, + struct tpacpi_led_classdev, + led_classdev); + data->new_brightness = brightness; + schedule_work(&data->work); +} + +static enum led_brightness light_sysfs_get(struct led_classdev *led_cdev) +{ + return (light_get_status() == 1)? LED_FULL : LED_OFF; +} + +static struct tpacpi_led_classdev tpacpi_led_thinklight = { + .led_classdev = { + .name = "tpacpi::thinklight", + .brightness_set = &light_sysfs_set, + .brightness_get = &light_sysfs_get, + } +}; + static int __init light_init(struct ibm_init_struct *iibm) { + int rc = 0; + vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n"); TPACPI_ACPIHANDLE_INIT(ledb); TPACPI_ACPIHANDLE_INIT(lght); TPACPI_ACPIHANDLE_INIT(cmos); + INIT_WORK(&tpacpi_led_thinklight.work, light_set_status_worker); /* light not supported on 570, 600e/x, 770e, 770x, G4x, R30, R31 */ tp_features.light = (cmos_handle || lght_handle) && !ledb_handle; @@ -3300,7 +3336,25 @@ static int __init light_init(struct ibm_init_struct *iibm) vdbg_printk(TPACPI_DBG_INIT, "light is %s\n", str_supported(tp_features.light)); - return (tp_features.light)? 0 : 1; + if (tp_features.light) { + rc = led_classdev_register(&tpacpi_pdev->dev, + &tpacpi_led_thinklight.led_classdev); + } + + if (rc < 0) { + tp_features.light = 0; + tp_features.light_status = 0; + } else { + rc = (tp_features.light)? 0 : 1; + } + return rc; +} + +static void light_exit(void) +{ + led_classdev_unregister(&tpacpi_led_thinklight.led_classdev); + if (work_pending(&tpacpi_led_thinklight.work)) + flush_scheduled_work(); } static int light_read(char *p) @@ -3348,6 +3402,7 @@ static struct ibm_struct light_driver_data = { .name = "light", .read = light_read, .write = light_write, + .exit = light_exit, }; /************************************************************************* -- cgit v1.2.2 From af116101924914a9655dfad108548d0db58c40f9 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 26 Apr 2008 01:02:25 -0300 Subject: ACPI: thinkpad-acpi: add sysfs led class support to thinkpad leds (v3.2) Add a sysfs led class interface to the led subdriver. Signed-off-by: Henrique de Moraes Holschuh Cc: Richard Purdie Signed-off-by: Len Brown --- Documentation/laptops/thinkpad-acpi.txt | 47 +++++++++-- drivers/misc/thinkpad_acpi.c | 136 +++++++++++++++++++++++++++++++- 2 files changed, 176 insertions(+), 7 deletions(-) diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index af1f2bcb6f66..73b80a7e9b03 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt @@ -876,28 +876,63 @@ The cmos command interface is prone to firmware split-brain problems, as in newer ThinkPads it is just a compatibility layer. Do not use it, it is exported just as a debug tool. -LED control -- /proc/acpi/ibm/led ---------------------------------- +LED control +----------- -Some of the LED indicators can be controlled through this feature. The -available commands are: +procfs: /proc/acpi/ibm/led +sysfs attributes: as per led class, see below for names + +Some of the LED indicators can be controlled through this feature. On +some older ThinkPad models, it is possible to query the status of the +LED indicators as well. Newer ThinkPads cannot query the real status +of the LED indicators. + +procfs notes: + +The available commands are: echo ' on' >/proc/acpi/ibm/led echo ' off' >/proc/acpi/ibm/led echo ' blink' >/proc/acpi/ibm/led The range is 0 to 7. The set of LEDs that can be -controlled varies from model to model. Here is the mapping on the X40: +controlled varies from model to model. Here is the common ThinkPad +mapping: 0 - power 1 - battery (orange) 2 - battery (green) - 3 - UltraBase + 3 - UltraBase/dock 4 - UltraBay + 5 - UltraBase battery slot + 6 - (unknown) 7 - standby All of the above can be turned on and off and can be made to blink. +sysfs notes: + +The ThinkPad LED sysfs interface is described in detail by the led class +documentation, in Documentation/leds-class.txt. + +The leds are named (in LED ID order, from 0 to 7): +"tpacpi::power", "tpacpi:orange:batt", "tpacpi:green:batt", +"tpacpi::dock_active", "tpacpi::bay_active", "tpacpi::dock_batt", +"tpacpi::unknown_led", "tpacpi::standby". + +Due to limitations in the sysfs led class, if the status of the LED +indicators cannot be read due to an error, thinkpad-acpi will report it as +a brightness of zero (same as LED off). + +If the thinkpad firmware doesn't support reading the current status, +trying to read the current LED brightness will just return whatever +brightness was last written to that attribute. + +These LEDs can blink using hardware acceleration. To request that a +ThinkPad indicator LED should blink in hardware accelerated mode, use the +"timer" trigger, and leave the delay_on and delay_off parameters set to +zero (to request hardware acceleration autodetection). + ACPI sounds -- /proc/acpi/ibm/beep ---------------------------------- diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 38a119bd931e..2ab3633f4e56 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -277,6 +277,7 @@ struct tpacpi_led_classdev { struct led_classdev led_classdev; struct work_struct work; enum led_brightness new_brightness; + unsigned int led; }; /**************************************************************************** @@ -3814,20 +3815,38 @@ TPACPI_HANDLE(led, ec, "SLED", /* 570 */ "LED", /* all others */ ); /* R30, R31 */ +#define TPACPI_LED_NUMLEDS 8 +static struct tpacpi_led_classdev *tpacpi_leds; +static enum led_status_t tpacpi_led_state_cache[TPACPI_LED_NUMLEDS]; +static const char const *tpacpi_led_names[TPACPI_LED_NUMLEDS] = { + /* there's a limit of 19 chars + NULL before 2.6.26 */ + "tpacpi::power", + "tpacpi:orange:batt", + "tpacpi:green:batt", + "tpacpi::dock_active", + "tpacpi::bay_active", + "tpacpi::dock_batt", + "tpacpi::unknown_led", + "tpacpi::standby", +}; + static int led_get_status(unsigned int led) { int status; + enum led_status_t led_s; switch (led_supported) { case TPACPI_LED_570: if (!acpi_evalf(ec_handle, &status, "GLED", "dd", 1 << led)) return -EIO; - return (status == 0)? + led_s = (status == 0)? TPACPI_LED_OFF : ((status == 1)? TPACPI_LED_ON : TPACPI_LED_BLINK); + tpacpi_led_state_cache[led] = led_s; + return led_s; default: return -ENXIO; } @@ -3874,11 +3893,96 @@ static int led_set_status(unsigned int led, enum led_status_t ledstatus) rc = -ENXIO; } + if (!rc) + tpacpi_led_state_cache[led] = ledstatus; + return rc; } +static void led_sysfs_set_status(unsigned int led, + enum led_brightness brightness) +{ + led_set_status(led, + (brightness == LED_OFF) ? + TPACPI_LED_OFF : + (tpacpi_led_state_cache[led] == TPACPI_LED_BLINK) ? + TPACPI_LED_BLINK : TPACPI_LED_ON); +} + +static void led_set_status_worker(struct work_struct *work) +{ + struct tpacpi_led_classdev *data = + container_of(work, struct tpacpi_led_classdev, work); + + if (likely(tpacpi_lifecycle == TPACPI_LIFE_RUNNING)) + led_sysfs_set_status(data->led, data->new_brightness); +} + +static void led_sysfs_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct tpacpi_led_classdev *data = container_of(led_cdev, + struct tpacpi_led_classdev, led_classdev); + + data->new_brightness = brightness; + schedule_work(&data->work); +} + +static int led_sysfs_blink_set(struct led_classdev *led_cdev, + unsigned long *delay_on, unsigned long *delay_off) +{ + struct tpacpi_led_classdev *data = container_of(led_cdev, + struct tpacpi_led_classdev, led_classdev); + + /* Can we choose the flash rate? */ + if (*delay_on == 0 && *delay_off == 0) { + /* yes. set them to the hardware blink rate (1 Hz) */ + *delay_on = 500; /* ms */ + *delay_off = 500; /* ms */ + } else if ((*delay_on != 500) || (*delay_off != 500)) + return -EINVAL; + + data->new_brightness = TPACPI_LED_BLINK; + schedule_work(&data->work); + + return 0; +} + +static enum led_brightness led_sysfs_get(struct led_classdev *led_cdev) +{ + int rc; + + struct tpacpi_led_classdev *data = container_of(led_cdev, + struct tpacpi_led_classdev, led_classdev); + + rc = led_get_status(data->led); + + if (rc == TPACPI_LED_OFF || rc < 0) + rc = LED_OFF; /* no error handling in led class :( */ + else + rc = LED_FULL; + + return rc; +} + +static void led_exit(void) +{ + unsigned int i; + + for (i = 0; i < TPACPI_LED_NUMLEDS; i++) { + if (tpacpi_leds[i].led_classdev.name) + led_classdev_unregister(&tpacpi_leds[i].led_classdev); + } + + kfree(tpacpi_leds); + tpacpi_leds = NULL; +} + static int __init led_init(struct ibm_init_struct *iibm) { + unsigned int i; + int rc; + vdbg_printk(TPACPI_DBG_INIT, "initializing LED subdriver\n"); TPACPI_ACPIHANDLE_INIT(led); @@ -3899,6 +4003,35 @@ static int __init led_init(struct ibm_init_struct *iibm) vdbg_printk(TPACPI_DBG_INIT, "LED commands are %s, mode %d\n", str_supported(led_supported), led_supported); + tpacpi_leds = kzalloc(sizeof(*tpacpi_leds) * TPACPI_LED_NUMLEDS, + GFP_KERNEL); + if (!tpacpi_leds) { + printk(TPACPI_ERR "Out of memory for LED data\n"); + return -ENOMEM; + } + + for (i = 0; i < TPACPI_LED_NUMLEDS; i++) { + tpacpi_leds[i].led = i; + + tpacpi_leds[i].led_classdev.brightness_set = &led_sysfs_set; + tpacpi_leds[i].led_classdev.blink_set = &led_sysfs_blink_set; + if (led_supported == TPACPI_LED_570) + tpacpi_leds[i].led_classdev.brightness_get = + &led_sysfs_get; + + tpacpi_leds[i].led_classdev.name = tpacpi_led_names[i]; + + INIT_WORK(&tpacpi_leds[i].work, led_set_status_worker); + + rc = led_classdev_register(&tpacpi_pdev->dev, + &tpacpi_leds[i].led_classdev); + if (rc < 0) { + tpacpi_leds[i].led_classdev.name = NULL; + led_exit(); + return rc; + } + } + return (led_supported != TPACPI_LED_NONE)? 0 : 1; } @@ -3969,6 +4102,7 @@ static struct ibm_struct led_driver_data = { .name = "led", .read = led_read, .write = led_write, + .exit = led_exit, }; /************************************************************************* -- cgit v1.2.2 From 65807cc284dd291b024dd6e55de88feb16b4230a Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 26 Apr 2008 01:02:26 -0300 Subject: ACPI: thinkpad-acpi: use uppercase for "LED" on user documentation Change all occourences of the "led" word to full uppercase in user documentation. Signed-off-by: Henrique de Moraes Holschuh Acked-by: Randy Dunlap Signed-off-by: Len Brown --- Documentation/laptops/thinkpad-acpi.txt | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index 73b80a7e9b03..947b72654e36 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt @@ -697,7 +697,7 @@ ThinkLight control ------------------ procfs: /proc/acpi/ibm/light -sysfs attributes: as per led class, for the "tpacpi::thinklight" led +sysfs attributes: as per LED class, for the "tpacpi::thinklight" LED procfs notes: @@ -710,11 +710,11 @@ status as "unknown". The available commands are: sysfs notes: -The ThinkLight sysfs interface is documented by the led class -documentation, in Documentation/leds-class.txt. The ThinkLight led name +The ThinkLight sysfs interface is documented by the LED class +documentation, in Documentation/leds-class.txt. The ThinkLight LED name is "tpacpi::thinklight". -Due to limitations in the sysfs led class, if the status of the thinklight +Due to limitations in the sysfs LED class, if the status of the thinklight cannot be read or if it is unknown, thinkpad-acpi will report it as "off". It is impossible to know if the status returned through sysfs is valid. @@ -880,7 +880,7 @@ LED control ----------- procfs: /proc/acpi/ibm/led -sysfs attributes: as per led class, see below for names +sysfs attributes: as per LED class, see below for names Some of the LED indicators can be controlled through this feature. On some older ThinkPad models, it is possible to query the status of the @@ -891,11 +891,11 @@ procfs notes: The available commands are: - echo ' on' >/proc/acpi/ibm/led - echo ' off' >/proc/acpi/ibm/led - echo ' blink' >/proc/acpi/ibm/led + echo ' on' >/proc/acpi/ibm/led + echo ' off' >/proc/acpi/ibm/led + echo ' blink' >/proc/acpi/ibm/led -The range is 0 to 7. The set of LEDs that can be +The range is 0 to 7. The set of LEDs that can be controlled varies from model to model. Here is the common ThinkPad mapping: @@ -912,7 +912,7 @@ All of the above can be turned on and off and can be made to blink. sysfs notes: -The ThinkPad LED sysfs interface is described in detail by the led class +The ThinkPad LED sysfs interface is described in detail by the LED class documentation, in Documentation/leds-class.txt. The leds are named (in LED ID order, from 0 to 7): @@ -920,7 +920,7 @@ The leds are named (in LED ID order, from 0 to 7): "tpacpi::dock_active", "tpacpi::bay_active", "tpacpi::dock_batt", "tpacpi::unknown_led", "tpacpi::standby". -Due to limitations in the sysfs led class, if the status of the LED +Due to limitations in the sysfs LED class, if the status of the LED indicators cannot be read due to an error, thinkpad-acpi will report it as a brightness of zero (same as LED off). -- cgit v1.2.2 From 10cc92759bb5d6031d308bdde96775f74082bb44 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 26 Apr 2008 01:02:27 -0300 Subject: ACPI: thinkpad-acpi: fluff really minor fix Fix a minor (nano?) thing that bothered me at exactly at the wrong time. Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- drivers/misc/thinkpad_acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 2ab3633f4e56..f471b46dcf5c 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -3881,7 +3881,7 @@ static int led_set_status(unsigned int led, enum led_status_t ledstatus) led * led_exp_hlbl[ledstatus]); if (rc >= 0) rc = ec_write(TPACPI_LED_EC_HLCL, - led * led_exp_hlcl[ledstatus]); + led * led_exp_hlcl[ledstatus]); break; case TPACPI_LED_NEW: /* all others */ -- cgit v1.2.2 From e0e3c0615abdb1c3e28356595f7be87627288d5b Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 26 Apr 2008 01:02:28 -0300 Subject: ACPI: thinkpad-acpi: use a private workqueue Switch all task workers to a private thinkpad-acpi workqueue. This way, we don't risk causing trouble for other tasks scheduled to the default work queue, as our workers end up needing to access the ACPI EC, run ACPI AML code, trigger SMI traps... and none of those are exactly known to be fast, simple operations. Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- drivers/misc/thinkpad_acpi.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index f471b46dcf5c..d5c08c01fd11 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -140,6 +140,7 @@ enum { #define TPACPI_HWMON_DRVR_NAME TPACPI_NAME "_hwmon" #define TPACPI_NVRAM_KTHREAD_NAME "ktpacpi_nvramd" +#define TPACPI_WORKQUEUE_NAME "ktpacpid" #define TPACPI_MAX_ACPI_ARGS 3 @@ -272,6 +273,8 @@ static enum { static int experimental; static u32 dbg_level; +static struct workqueue_struct *tpacpi_wq; + /* Special LED class that can defer work */ struct tpacpi_led_classdev { struct led_classdev led_classdev; @@ -3298,7 +3301,7 @@ static void light_sysfs_set(struct led_classdev *led_cdev, struct tpacpi_led_classdev, led_classdev); data->new_brightness = brightness; - schedule_work(&data->work); + queue_work(tpacpi_wq, &data->work); } static enum led_brightness light_sysfs_get(struct led_classdev *led_cdev) @@ -3355,7 +3358,7 @@ static void light_exit(void) { led_classdev_unregister(&tpacpi_led_thinklight.led_classdev); if (work_pending(&tpacpi_led_thinklight.work)) - flush_scheduled_work(); + flush_workqueue(tpacpi_wq); } static int light_read(char *p) @@ -3925,7 +3928,7 @@ static void led_sysfs_set(struct led_classdev *led_cdev, struct tpacpi_led_classdev, led_classdev); data->new_brightness = brightness; - schedule_work(&data->work); + queue_work(tpacpi_wq, &data->work); } static int led_sysfs_blink_set(struct led_classdev *led_cdev, @@ -3943,7 +3946,7 @@ static int led_sysfs_blink_set(struct led_classdev *led_cdev, return -EINVAL; data->new_brightness = TPACPI_LED_BLINK; - schedule_work(&data->work); + queue_work(tpacpi_wq, &data->work); return 0; } @@ -5408,11 +5411,11 @@ static void fan_watchdog_reset(void) if (fan_watchdog_maxinterval > 0 && tpacpi_lifecycle != TPACPI_LIFE_EXITING) { fan_watchdog_active = 1; - if (!schedule_delayed_work(&fan_watchdog_task, + if (!queue_delayed_work(tpacpi_wq, &fan_watchdog_task, msecs_to_jiffies(fan_watchdog_maxinterval * 1000))) { printk(TPACPI_ERR - "failed to schedule the fan watchdog, " + "failed to queue the fan watchdog, " "watchdog will not trigger\n"); } } else @@ -5782,7 +5785,7 @@ static void fan_exit(void) &driver_attr_fan_watchdog); cancel_delayed_work(&fan_watchdog_task); - flush_scheduled_work(); + flush_workqueue(tpacpi_wq); } static int fan_read(char *p) @@ -6436,6 +6439,9 @@ static void thinkpad_acpi_module_exit(void) if (proc_dir) remove_proc_entry(TPACPI_PROC_DIR, acpi_root_dir); + if (tpacpi_wq) + destroy_workqueue(tpacpi_wq); + kfree(thinkpad_id.bios_version_str); kfree(thinkpad_id.ec_version_str); kfree(thinkpad_id.model_str); @@ -6466,6 +6472,12 @@ static int __init thinkpad_acpi_module_init(void) TPACPI_ACPIHANDLE_INIT(ecrd); TPACPI_ACPIHANDLE_INIT(ecwr); + tpacpi_wq = create_singlethread_workqueue(TPACPI_WORKQUEUE_NAME); + if (!tpacpi_wq) { + thinkpad_acpi_module_exit(); + return -ENOMEM; + } + proc_dir = proc_mkdir(TPACPI_PROC_DIR, acpi_root_dir); if (!proc_dir) { printk(TPACPI_ERR -- cgit v1.2.2 From 3f6cb5630a5994f58c3cf620d0f6d71ff626229d Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 26 Apr 2008 01:02:29 -0300 Subject: ACPI: thinkpad-acpi: fix selects in Kconfig Add missing select for BACKLIGHT_LCD_SUPPORT, as select doesn't select the dependencies of a symbol for us. Also, "select INPUT" in Kconfig. We are not an Input device, nor are we anywhere close to the input subsystem in the Kconfig tree, so using "depends on INPUT" is not user-friendly at all. Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- drivers/misc/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 3a5d7694b878..2e217947d971 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -241,10 +241,11 @@ config SONYPI_COMPAT config THINKPAD_ACPI tristate "ThinkPad ACPI Laptop Extras" depends on X86 && ACPI + select BACKLIGHT_LCD_SUPPORT select BACKLIGHT_CLASS_DEVICE select HWMON select NVRAM - depends on INPUT + select INPUT select NEW_LEDS select LEDS_CLASS ---help--- -- cgit v1.2.2 From 68f12ae5d778279e13e406d3913c74c592307770 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 26 Apr 2008 01:02:30 -0300 Subject: ACPI: thinkpad-acpi: bump up version to 0.20 Full LED sysfs support, and the rest of the assorted minor fixes and enhancements are a good reason to checkpoint a new version... Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- Documentation/laptops/thinkpad-acpi.txt | 4 ++-- drivers/misc/thinkpad_acpi.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index 947b72654e36..01c6c3d8a7e3 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt @@ -1,7 +1,7 @@ ThinkPad ACPI Extras Driver - Version 0.19 - January 06th, 2008 + Version 0.20 + April 09th, 2008 Borislav Deianov Henrique de Moraes Holschuh diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index d5c08c01fd11..d29ad2e4afc2 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -21,7 +21,7 @@ * 02110-1301, USA. */ -#define TPACPI_VERSION "0.19" +#define TPACPI_VERSION "0.20" #define TPACPI_SYSFS_VERSION 0x020200 /* -- cgit v1.2.2 From e59f87966adef2cb03d419530e3ade5159487d6d Mon Sep 17 00:00:00 2001 From: Eric Cooper Date: Thu, 13 Mar 2008 12:55:46 +0100 Subject: eeepc-laptop: add base driver This patch is based on Eric Cooper's work to clean the original asus_acpi given by Asus. It's a platform driver (/sys/devices/platform/eeepc/) wich support: - hotkeys - wlan on/off - camera on/off - cardr on/off Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- MAINTAINERS | 7 + drivers/misc/Kconfig | 11 ++ drivers/misc/Makefile | 3 +- drivers/misc/eeepc-laptop.c | 442 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 462 insertions(+), 1 deletion(-) create mode 100644 drivers/misc/eeepc-laptop.c diff --git a/MAINTAINERS b/MAINTAINERS index c1dd1ae7b133..37debda36661 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1531,6 +1531,13 @@ L: bluesmoke-devel@lists.sourceforge.net W: bluesmoke.sourceforge.net S: Maintained +EEEPC LAPTOP EXTRAS DRIVER +P: Corentin Chary +M: corentincj@iksaif.net +L: acpi4asus-user@lists.sourceforge.net +W: http://sourceforge.net/projects/acpi4asus +S: Maintained + EEPRO100 NETWORK DRIVER P: Andrey V. Savochkin M: saw@saw.sw.com.sg diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 297a48f85446..2264127afac7 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -351,6 +351,17 @@ config INTEL_MENLOW If unsure, say N. +config EEEPC_LAPTOP + tristate "Eee PC Hotkey Driver (EXPERIMENTAL)" + depends on X86 + depends on ACPI + depends on EXPERIMENTAL + ---help--- + This driver supports the Fn-Fx keys on Eee PC laptops. + It also adds the ability to switch camera/wlan on/off. + + If you have an Eee PC laptop, say Y or M here. + config ENCLOSURE_SERVICES tristate "Enclosure Services" default n diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 5914da434854..1952875a272e 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -7,7 +7,8 @@ obj-$(CONFIG_IBM_ASM) += ibmasm/ obj-$(CONFIG_HDPU_FEATURES) += hdpuftrs/ obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o obj-$(CONFIG_ACER_WMI) += acer-wmi.o -obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o +obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o +obj-$(CONFIG_EEEPC_LAPTOP) += eeepc-laptop.o obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o diff --git a/drivers/misc/eeepc-laptop.c b/drivers/misc/eeepc-laptop.c new file mode 100644 index 000000000000..e34ff97530cd --- /dev/null +++ b/drivers/misc/eeepc-laptop.c @@ -0,0 +1,442 @@ +/* + * eepc-laptop.c - Asus Eee PC extras + * + * Based on asus_acpi.c as patched for the Eee PC by Asus: + * ftp://ftp.asus.com/pub/ASUS/EeePC/701/ASUS_ACPI_071126.rar + * Based on eee.c from eeepc-linux + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define EEEPC_LAPTOP_VERSION "0.1" + +#define EEEPC_HOTK_NAME "Eee PC Hotkey Driver" +#define EEEPC_HOTK_FILE "eeepc" +#define EEEPC_HOTK_CLASS "hotkey" +#define EEEPC_HOTK_DEVICE_NAME "Hotkey" +#define EEEPC_HOTK_HID "ASUS010" + +#define EEEPC_LOG EEEPC_HOTK_FILE ": " +#define EEEPC_ERR KERN_ERR EEEPC_LOG +#define EEEPC_WARNING KERN_WARNING EEEPC_LOG +#define EEEPC_NOTICE KERN_NOTICE EEEPC_LOG +#define EEEPC_INFO KERN_INFO EEEPC_LOG + +/* + * Definitions for Asus EeePC + */ +#define NOTIFY_WLAN_ON 0x10 + +enum { + DISABLE_ASL_WLAN = 0x0001, + DISABLE_ASL_BLUETOOTH = 0x0002, + DISABLE_ASL_IRDA = 0x0004, + DISABLE_ASL_CAMERA = 0x0008, + DISABLE_ASL_TV = 0x0010, + DISABLE_ASL_GPS = 0x0020, + DISABLE_ASL_DISPLAYSWITCH = 0x0040, + DISABLE_ASL_MODEM = 0x0080, + DISABLE_ASL_CARDREADER = 0x0100 +}; + +enum { + CM_ASL_WLAN = 0, + CM_ASL_BLUETOOTH, + CM_ASL_IRDA, + CM_ASL_1394, + CM_ASL_CAMERA, + CM_ASL_TV, + CM_ASL_GPS, + CM_ASL_DVDROM, + CM_ASL_DISPLAYSWITCH, + CM_ASL_PANELBRIGHT, + CM_ASL_BIOSFLASH, + CM_ASL_ACPIFLASH, + CM_ASL_CPUFV, + CM_ASL_CPUTEMPERATURE, + CM_ASL_FANCPU, + CM_ASL_FANCHASSIS, + CM_ASL_USBPORT1, + CM_ASL_USBPORT2, + CM_ASL_USBPORT3, + CM_ASL_MODEM, + CM_ASL_CARDREADER, + CM_ASL_LID +}; + +const char *cm_getv[] = { + "WLDG", NULL, NULL, NULL, + "CAMG", NULL, NULL, NULL, + NULL, "PBLG", NULL, NULL, + "CFVG", NULL, NULL, NULL, + "USBG", NULL, NULL, "MODG", + "CRDG", "LIDG" +}; + +const char *cm_setv[] = { + "WLDS", NULL, NULL, NULL, + "CAMS", NULL, NULL, NULL, + "SDSP", "PBLS", "HDPS", NULL, + "CFVS", NULL, NULL, NULL, + "USBG", NULL, NULL, "MODS", + "CRDS", NULL +}; + +/* + * This is the main structure, we can use it to store useful information + * about the hotk device + */ +struct eeepc_hotk { + struct acpi_device *device; /* the device we are in */ + acpi_handle handle; /* the handle of the hotk device */ + u32 cm_supported; /* the control methods supported + by this BIOS */ + uint init_flag; /* Init flags */ + u16 event_count[128]; /* count for each event */ +}; + +/* The actual device the driver binds to */ +static struct eeepc_hotk *ehotk; + +/* Platform device/driver */ +static struct platform_driver platform_driver = { + .driver = { + .name = EEEPC_HOTK_FILE, + .owner = THIS_MODULE, + } +}; + +static struct platform_device *platform_device; + +/* + * The hotkey driver declaration + */ +static int eeepc_hotk_add(struct acpi_device *device); +static int eeepc_hotk_remove(struct acpi_device *device, int type); + +static const struct acpi_device_id eeepc_device_ids[] = { + {EEEPC_HOTK_HID, 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, eeepc_device_ids); + +static struct acpi_driver eeepc_hotk_driver = { + .name = EEEPC_HOTK_NAME, + .class = EEEPC_HOTK_CLASS, + .ids = eeepc_device_ids, + .ops = { + .add = eeepc_hotk_add, + .remove = eeepc_hotk_remove, + }, +}; + +MODULE_AUTHOR("Corentin Chary, Eric Cooper"); +MODULE_DESCRIPTION(EEEPC_HOTK_NAME); +MODULE_LICENSE("GPL"); + +/* + * ACPI Helpers + */ +static int write_acpi_int(acpi_handle handle, const char *method, int val, + struct acpi_buffer *output) +{ + struct acpi_object_list params; + union acpi_object in_obj; + acpi_status status; + + params.count = 1; + params.pointer = &in_obj; + in_obj.type = ACPI_TYPE_INTEGER; + in_obj.integer.value = val; + + status = acpi_evaluate_object(handle, (char *)method, ¶ms, output); + return (status == AE_OK ? 0 : -1); +} + +static int read_acpi_int(acpi_handle handle, const char *method, int *val) +{ + acpi_status status; + ulong result; + + status = acpi_evaluate_integer(handle, (char *)method, NULL, &result); + if (ACPI_FAILURE(status)) { + *val = -1; + return -1; + } else { + *val = result; + return 0; + } +} + +static int set_acpi(int cm, int value) +{ + if (ehotk->cm_supported & (0x1 << cm)) { + const char *method = cm_setv[cm]; + if (method == NULL) + return -ENODEV; + if (write_acpi_int(ehotk->handle, method, value, NULL)) + printk(EEEPC_WARNING "Error writing %s\n", method); + } + return 0; +} + +static int get_acpi(int cm) +{ + int value = -1; + if ((ehotk->cm_supported & (0x1 << cm))) { + const char *method = cm_getv[cm]; + if (method == NULL) + return -ENODEV; + if (read_acpi_int(ehotk->handle, method, &value)) + printk(EEEPC_WARNING "Error reading %s\n", method); + } + return value; +} + +/* + * Sys helpers + */ +static int parse_arg(const char *buf, unsigned long count, int *val) +{ + if (!count) + return 0; + if (sscanf(buf, "%i", val) != 1) + return -EINVAL; + return count; +} + +static ssize_t store_sys_acpi(int cm, const char *buf, size_t count) +{ + int rv, value; + + rv = parse_arg(buf, count, &value); + if (rv > 0) + set_acpi(cm, value); + return rv; +} + +static ssize_t show_sys_acpi(int cm, char *buf) +{ + return sprintf(buf, "%d\n", get_acpi(cm)); +} + +#define EEEPC_CREATE_DEVICE_ATTR(_name, _cm) \ + static ssize_t show_##_name(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ + { \ + return show_sys_acpi(_cm, buf); \ + } \ + static ssize_t store_##_name(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t count) \ + { \ + return store_sys_acpi(_cm, buf, count); \ + } \ + static struct device_attribute dev_attr_##_name = { \ + .attr = { \ + .name = __stringify(_name), \ + .mode = 0644 }, \ + .show = show_##_name, \ + .store = store_##_name, \ + } + +EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA); +EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER); +EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH); +EEEPC_CREATE_DEVICE_ATTR(wlan, CM_ASL_WLAN); + +static struct attribute *platform_attributes[] = { + &dev_attr_camera.attr, + &dev_attr_cardr.attr, + &dev_attr_disp.attr, + &dev_attr_wlan.attr, + NULL +}; + +static struct attribute_group platform_attribute_group = { + .attrs = platform_attributes +}; + +/* + * Hotkey functions + */ +static int eeepc_hotk_check(void) +{ + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + int result; + + result = acpi_bus_get_status(ehotk->device); + if (result) + return result; + if (ehotk->device->status.present) { + if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag, + &buffer)) { + printk(EEEPC_ERR "Hotkey initialization failed\n"); + return -ENODEV; + } else { + printk(EEEPC_NOTICE "Hotkey init flags 0x%x\n", + ehotk->init_flag); + } + /* get control methods supported */ + if (read_acpi_int(ehotk->handle, "CMSG" + , &ehotk->cm_supported)) { + printk(EEEPC_ERR + "Get control methods supported failed\n"); + return -ENODEV; + } else { + printk(EEEPC_INFO + "Get control methods supported: 0x%x\n", + ehotk->cm_supported); + } + } else { + printk(EEEPC_ERR "Hotkey device not present, aborting\n"); + return -EINVAL; + } + return 0; +} + +static void notify_wlan(u32 *event) +{ + /* if DISABLE_ASL_WLAN is set, the notify code for fn+f2 + will always be 0x10 */ + if (ehotk->cm_supported & (0x1 << CM_ASL_WLAN)) { + const char *method = cm_getv[CM_ASL_WLAN]; + int value; + if (read_acpi_int(ehotk->handle, method, &value)) + printk(EEEPC_WARNING "Error reading %s\n", + method); + else if (value == 1) + *event = 0x11; + } +} + +static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) +{ + if (!ehotk) + return; + if (event == NOTIFY_WLAN_ON && (DISABLE_ASL_WLAN & ehotk->init_flag)) + notify_wlan(&event); + acpi_bus_generate_proc_event(ehotk->device, event, + ehotk->event_count[event % 128]++); +} + +static int eeepc_hotk_add(struct acpi_device *device) +{ + acpi_status status = AE_OK; + int result; + + if (!device) + return -EINVAL; + printk(EEEPC_NOTICE EEEPC_HOTK_NAME "\n"); + ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL); + if (!ehotk) + return -ENOMEM; + ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH; + ehotk->handle = device->handle; + strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME); + strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS); + acpi_driver_data(device) = ehotk; + ehotk->device = device; + result = eeepc_hotk_check(); + if (result) + goto end; + status = acpi_install_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY, + eeepc_hotk_notify, ehotk); + if (ACPI_FAILURE(status)) + printk(EEEPC_ERR "Error installing notify handler\n"); + end: + if (result) { + kfree(ehotk); + ehotk = NULL; + } + return result; +} + +static int eeepc_hotk_remove(struct acpi_device *device, int type) +{ + acpi_status status = 0; + + if (!device || !acpi_driver_data(device)) + return -EINVAL; + status = acpi_remove_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY, + eeepc_hotk_notify); + if (ACPI_FAILURE(status)) + printk(EEEPC_ERR "Error removing notify handler\n"); + kfree(ehotk); + return 0; +} + +/* + * exit/init + */ +static void __exit eeepc_laptop_exit(void) +{ + acpi_bus_unregister_driver(&eeepc_hotk_driver); + sysfs_remove_group(&platform_device->dev.kobj, + &platform_attribute_group); + platform_device_unregister(platform_device); + platform_driver_unregister(&platform_driver); +} + +static int __init eeepc_laptop_init(void) +{ + struct device *dev; + int result; + + if (acpi_disabled) + return -ENODEV; + result = acpi_bus_register_driver(&eeepc_hotk_driver); + if (result < 0) + return result; + if (!ehotk) { + acpi_bus_unregister_driver(&eeepc_hotk_driver); + return -ENODEV; + } + dev = acpi_get_physical_device(ehotk->device->handle); + /* Register platform stuff */ + result = platform_driver_register(&platform_driver); + if (result) + goto fail_platform_driver; + platform_device = platform_device_alloc(EEEPC_HOTK_FILE, -1); + if (!platform_device) { + result = -ENOMEM; + goto fail_platform_device1; + } + result = platform_device_add(platform_device); + if (result) + goto fail_platform_device2; + result = sysfs_create_group(&platform_device->dev.kobj, + &platform_attribute_group); + if (result) + goto fail_sysfs; + return 0; +fail_sysfs: + platform_device_del(platform_device); +fail_platform_device2: + platform_device_put(platform_device); +fail_platform_device1: + platform_driver_unregister(&platform_driver); +fail_platform_driver: + return result; +} + +module_init(eeepc_laptop_init); +module_exit(eeepc_laptop_exit); -- cgit v1.2.2 From a5fa429b4b19cccd3f91a98af891c7ba2706cc1d Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Thu, 13 Mar 2008 12:56:37 +0100 Subject: eeepc-laptop: add backlight Add backlight class support to the eeepc-laptop driver. Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/misc/Kconfig | 1 + drivers/misc/eeepc-laptop.c | 77 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 2264127afac7..01b7deba91e8 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -355,6 +355,7 @@ config EEEPC_LAPTOP tristate "Eee PC Hotkey Driver (EXPERIMENTAL)" depends on X86 depends on ACPI + depends on BACKLIGHT_CLASS_DEVICE depends on EXPERIMENTAL ---help--- This driver supports the Fn-Fx keys on Eee PC laptops. diff --git a/drivers/misc/eeepc-laptop.c b/drivers/misc/eeepc-laptop.c index e34ff97530cd..2b59b7ed4b14 100644 --- a/drivers/misc/eeepc-laptop.c +++ b/drivers/misc/eeepc-laptop.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include #include #include @@ -43,6 +45,8 @@ * Definitions for Asus EeePC */ #define NOTIFY_WLAN_ON 0x10 +#define NOTIFY_BRN_MIN 0x20 +#define NOTIFY_BRN_MAX 0x2f enum { DISABLE_ASL_WLAN = 0x0001, @@ -147,6 +151,19 @@ static struct acpi_driver eeepc_hotk_driver = { }, }; +/* The backlight device /sys/class/backlight */ +static struct backlight_device *eeepc_backlight_device; + +/* + * The backlight class declaration + */ +static int read_brightness(struct backlight_device *bd); +static int update_bl_status(struct backlight_device *bd); +static struct backlight_ops eeepcbl_ops = { + .get_brightness = read_brightness, + .update_status = update_bl_status, +}; + MODULE_AUTHOR("Corentin Chary, Eric Cooper"); MODULE_DESCRIPTION(EEEPC_HOTK_NAME); MODULE_LICENSE("GPL"); @@ -210,6 +227,25 @@ static int get_acpi(int cm) return value; } +/* + * Backlight + */ +static int read_brightness(struct backlight_device *bd) +{ + return get_acpi(CM_ASL_PANELBRIGHT); +} + +static int set_brightness(struct backlight_device *bd, int value) +{ + value = max(0, min(15, value)); + return set_acpi(CM_ASL_PANELBRIGHT, value); +} + +static int update_bl_status(struct backlight_device *bd) +{ + return set_brightness(bd, bd->props.brightness); +} + /* * Sys helpers */ @@ -328,12 +364,20 @@ static void notify_wlan(u32 *event) } } +static void notify_brn(void) +{ + struct backlight_device *bd = eeepc_backlight_device; + bd->props.brightness = read_brightness(bd); +} + static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) { if (!ehotk) return; if (event == NOTIFY_WLAN_ON && (DISABLE_ASL_WLAN & ehotk->init_flag)) notify_wlan(&event); + if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) + notify_brn(); acpi_bus_generate_proc_event(ehotk->device, event, ehotk->event_count[event % 128]++); } @@ -387,8 +431,16 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type) /* * exit/init */ +static void eeepc_backlight_exit(void) +{ + if (eeepc_backlight_device) + backlight_device_unregister(eeepc_backlight_device); + eeepc_backlight_device = NULL; +} + static void __exit eeepc_laptop_exit(void) { + eeepc_backlight_exit(); acpi_bus_unregister_driver(&eeepc_hotk_driver); sysfs_remove_group(&platform_device->dev.kobj, &platform_attribute_group); @@ -396,6 +448,26 @@ static void __exit eeepc_laptop_exit(void) platform_driver_unregister(&platform_driver); } +static int eeepc_backlight_init(struct device *dev) +{ + struct backlight_device *bd; + + bd = backlight_device_register(EEEPC_HOTK_FILE, dev, + NULL, &eeepcbl_ops); + if (IS_ERR(bd)) { + printk(EEEPC_ERR + "Could not register eeepc backlight device\n"); + eeepc_backlight_device = NULL; + return PTR_ERR(bd); + } + eeepc_backlight_device = bd; + bd->props.max_brightness = 15; + bd->props.brightness = read_brightness(NULL); + bd->props.power = FB_BLANK_UNBLANK; + backlight_update_status(bd); + return 0; +} + static int __init eeepc_laptop_init(void) { struct device *dev; @@ -411,6 +483,9 @@ static int __init eeepc_laptop_init(void) return -ENODEV; } dev = acpi_get_physical_device(ehotk->device->handle); + result = eeepc_backlight_init(dev); + if (result) + goto fail_backlight; /* Register platform stuff */ result = platform_driver_register(&platform_driver); if (result) @@ -435,6 +510,8 @@ fail_platform_device2: fail_platform_device1: platform_driver_unregister(&platform_driver); fail_platform_driver: + eeepc_backlight_exit(); +fail_backlight: return result; } -- cgit v1.2.2 From e1faa9da284d14487ed4280b4e87cfde8e1539af Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Thu, 13 Mar 2008 12:57:18 +0100 Subject: eeepc-laptop: add hwmon fan control Adds an hwmon interface to control the fan. Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/misc/Kconfig | 1 + drivers/misc/eeepc-laptop.c | 147 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+) diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 01b7deba91e8..7a4869a9db86 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -356,6 +356,7 @@ config EEEPC_LAPTOP depends on X86 depends on ACPI depends on BACKLIGHT_CLASS_DEVICE + depends on HWMON depends on EXPERIMENTAL ---help--- This driver supports the Fn-Fx keys on Eee PC laptops. diff --git a/drivers/misc/eeepc-laptop.c b/drivers/misc/eeepc-laptop.c index 2b59b7ed4b14..6d727609097f 100644 --- a/drivers/misc/eeepc-laptop.c +++ b/drivers/misc/eeepc-laptop.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include #include @@ -103,6 +105,15 @@ const char *cm_setv[] = { "CRDS", NULL }; +#define EEEPC_EC "\\_SB.PCI0.SBRG.EC0." + +#define EEEPC_EC_FAN_PWM EEEPC_EC "SC02" /* Fan PWM duty cycle (%) */ +#define EEEPC_EC_SC02 0x63 +#define EEEPC_EC_FAN_HRPM EEEPC_EC "SC05" /* High byte, fan speed (RPM) */ +#define EEEPC_EC_FAN_LRPM EEEPC_EC "SC06" /* Low byte, fan speed (RPM) */ +#define EEEPC_EC_FAN_CTRL EEEPC_EC "SFB3" /* Byte containing SF25 */ +#define EEEPC_EC_SFB3 0xD3 + /* * This is the main structure, we can use it to store useful information * about the hotk device @@ -154,6 +165,9 @@ static struct acpi_driver eeepc_hotk_driver = { /* The backlight device /sys/class/backlight */ static struct backlight_device *eeepc_backlight_device; +/* The hwmon device */ +static struct device *eeepc_hwmon_device; + /* * The backlight class declaration */ @@ -428,6 +442,100 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type) return 0; } +/* + * Hwmon + */ +static int eeepc_get_fan_pwm(void) +{ + int value = 0; + + read_acpi_int(NULL, EEEPC_EC_FAN_PWM, &value); + return (value); +} + +static void eeepc_set_fan_pwm(int value) +{ + value = SENSORS_LIMIT(value, 0, 100); + ec_write(EEEPC_EC_SC02, value); +} + +static int eeepc_get_fan_rpm(void) +{ + int high = 0; + int low = 0; + + read_acpi_int(NULL, EEEPC_EC_FAN_HRPM, &high); + read_acpi_int(NULL, EEEPC_EC_FAN_LRPM, &low); + return (high << 8 | low); +} + +static int eeepc_get_fan_ctrl(void) +{ + int value = 0; + + read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value); + return ((value & 0x02 ? 1 : 0)); +} + +static void eeepc_set_fan_ctrl(int manual) +{ + int value = 0; + + read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value); + if (manual) + value |= 0x02; + else + value &= ~0x02; + ec_write(EEEPC_EC_SFB3, value); +} + +static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count) +{ + int rv, value; + + rv = parse_arg(buf, count, &value); + if (rv > 0) + set(value); + return rv; +} + +static ssize_t show_sys_hwmon(int (*get)(void), char *buf) +{ + return sprintf(buf, "%d\n", get()); +} + +#define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _set, _get) \ + static ssize_t show_##_name(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ + { \ + return show_sys_hwmon(_set, buf); \ + } \ + static ssize_t store_##_name(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t count) \ + { \ + return store_sys_hwmon(_get, buf, count); \ + } \ + static SENSOR_DEVICE_ATTR(_name, _mode, show_##_name, store_##_name, 0); + +EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL); +EEEPC_CREATE_SENSOR_ATTR(fan1_pwm, S_IRUGO | S_IWUSR, + eeepc_get_fan_pwm, eeepc_set_fan_pwm); +EEEPC_CREATE_SENSOR_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, + eeepc_get_fan_ctrl, eeepc_set_fan_ctrl); + +static struct attribute *hwmon_attributes[] = { + &sensor_dev_attr_fan1_pwm.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_pwm1_enable.dev_attr.attr, + NULL +}; + +static struct attribute_group hwmon_attribute_group = { + .attrs = hwmon_attributes +}; + /* * exit/init */ @@ -438,9 +546,23 @@ static void eeepc_backlight_exit(void) eeepc_backlight_device = NULL; } +static void eeepc_hwmon_exit(void) +{ + struct device *hwmon; + + hwmon = eeepc_hwmon_device; + if (!hwmon) + return ; + hwmon_device_unregister(hwmon); + sysfs_remove_group(&hwmon->kobj, + &hwmon_attribute_group); + eeepc_hwmon_device = NULL; +} + static void __exit eeepc_laptop_exit(void) { eeepc_backlight_exit(); + eeepc_hwmon_exit(); acpi_bus_unregister_driver(&eeepc_hotk_driver); sysfs_remove_group(&platform_device->dev.kobj, &platform_attribute_group); @@ -468,6 +590,26 @@ static int eeepc_backlight_init(struct device *dev) return 0; } +static int eeepc_hwmon_init(struct device *dev) +{ + struct device *hwmon; + int result; + + hwmon = hwmon_device_register(dev); + if (IS_ERR(hwmon)) { + printk(EEEPC_ERR + "Could not register eeepc hwmon device\n"); + eeepc_hwmon_device = NULL; + return PTR_ERR(hwmon); + } + eeepc_hwmon_device = hwmon; + result = sysfs_create_group(&hwmon->kobj, + &hwmon_attribute_group); + if (result) + eeepc_hwmon_exit(); + return result; +} + static int __init eeepc_laptop_init(void) { struct device *dev; @@ -486,6 +628,9 @@ static int __init eeepc_laptop_init(void) result = eeepc_backlight_init(dev); if (result) goto fail_backlight; + result = eeepc_hwmon_init(dev); + if (result) + goto fail_hwmon; /* Register platform stuff */ result = platform_driver_register(&platform_driver); if (result) @@ -510,6 +655,8 @@ fail_platform_device2: fail_platform_device1: platform_driver_unregister(&platform_driver); fail_platform_driver: + eeepc_hwmon_exit(); +fail_hwmon: eeepc_backlight_exit(); fail_backlight: return result; -- cgit v1.2.2 From 2a241d77cfdab08544a78057a4b24c9a98dc79d0 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 31 Mar 2008 02:05:40 +0300 Subject: #if 0 acpi/bay.c:eject_removable_drive() This patch #if 0's the unused eject_removable_drive(). Signed-off-by: Adrian Bunk Signed-off-by: Len Brown --- drivers/acpi/bay.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c index 1fa86811b8ee..d2fc94161848 100644 --- a/drivers/acpi/bay.c +++ b/drivers/acpi/bay.c @@ -201,6 +201,7 @@ static int is_ejectable_bay(acpi_handle handle) return 0; } +#if 0 /** * eject_removable_drive - try to eject this drive * @dev : the device structure of the drive @@ -225,6 +226,7 @@ int eject_removable_drive(struct device *dev) return 0; } EXPORT_SYMBOL_GPL(eject_removable_drive); +#endif /* 0 */ static int acpi_bay_add_fs(struct bay *bay) { -- cgit v1.2.2 From a815ab8b5891f3d2515316655729272f68269e3b Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Fri, 18 Apr 2008 13:27:29 -0700 Subject: ACPI: check a return value correctly in acpi_power_get_context() We should check *resource != NULL rather than resource != NULL, which will be always true. Signed-off-by: Li Zefan Acked-by: Zhao Yakui Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/power.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 76bf6d90c700..f2a76acecfcd 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -121,7 +121,7 @@ acpi_power_get_context(acpi_handle handle, } *resource = acpi_driver_data(device); - if (!resource) + if (!*resource) return -ENODEV; return 0; -- cgit v1.2.2 From 90fe17f4df2f830601ffd422b11d1f7f9a9d0355 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Fri, 18 Apr 2008 13:27:29 -0700 Subject: thinkpad_acpi: fix possible NULL pointer dereference if kstrdup failed Signed-off-by: Cyrill Gorcunov Acked-by: Henrique de Moraes Holschuh Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/misc/thinkpad_acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 6cb781262f94..31115c9cfb34 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -5826,7 +5826,7 @@ static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp) tp->model_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_VERSION), GFP_KERNEL); - if (strnicmp(tp->model_str, "ThinkPad", 8) != 0) { + if (tp->model_str && strnicmp(tp->model_str, "ThinkPad", 8) != 0) { kfree(tp->model_str); tp->model_str = NULL; } -- cgit v1.2.2 From e7ae1e7ef9b4ef50444a49611dab92cb778eb97c Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 29 Apr 2008 10:21:20 +0200 Subject: ACER_WMI/ASUS_LAPTOP: fix build bug randconfig testing in x86.git found the following upstream build bug: drivers/built-in.o: In function `acer_led_exit': acer-wmi.c:(.text+0xdc76e): undefined reference to `led_classdev_unregister' drivers/built-in.o: In function `acer_platform_probe': acer-wmi.c:(.devinit.text+0x63e6): undefined reference to `led_classdev_register' which was due to acer-wmi.o only depending on CONFIG_LEDS_CLASS, while also using a symbol offered by CONFIG_NEW_LEDS. Also fix a similar bug in CONFIG_ASUS_LAPTOP. Signed-off-by: Ingo Molnar Signed-off-by: Len Brown --- drivers/misc/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 297a48f85446..38cce4d1e2fb 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -140,6 +140,7 @@ config ACER_WMI depends on EXPERIMENTAL depends on ACPI depends on LEDS_CLASS + depends on NEW_LEDS depends on BACKLIGHT_CLASS_DEVICE depends on SERIO_I8042 select ACPI_WMI @@ -160,6 +161,7 @@ config ASUS_LAPTOP depends on ACPI depends on EXPERIMENTAL && !ACPI_ASUS depends on LEDS_CLASS + depends on NEW_LEDS depends on BACKLIGHT_CLASS_DEVICE ---help--- This is the new Linux driver for Asus laptops. It may also support some -- cgit v1.2.2 From 2c6e33c366bff2f839df60d9235ff09143e28dd9 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 23 Apr 2008 18:02:52 -0400 Subject: ACPI: re-name acpi_pm_ops to acpi_suspend_ops ... as they are platform_suspend_ops after all. cosmetic re-name only, no functional change. Signed-off-by: Len Brown --- drivers/acpi/sleep/main.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index 71183eea7906..c3b0cd88d09f 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c @@ -51,7 +51,7 @@ static int acpi_sleep_prepare(u32 acpi_state) } #ifdef CONFIG_SUSPEND -static struct platform_suspend_ops acpi_pm_ops; +static struct platform_suspend_ops acpi_suspend_ops; extern void do_suspend_lowlevel(void); @@ -65,11 +65,11 @@ static u32 acpi_suspend_states[] = { static int init_8259A_after_S1; /** - * acpi_pm_begin - Set the target system sleep state to the state + * acpi_suspend_begin - Set the target system sleep state to the state * associated with given @pm_state, if supported. */ -static int acpi_pm_begin(suspend_state_t pm_state) +static int acpi_suspend_begin(suspend_state_t pm_state) { u32 acpi_state = acpi_suspend_states[pm_state]; int error = 0; @@ -85,13 +85,13 @@ static int acpi_pm_begin(suspend_state_t pm_state) } /** - * acpi_pm_prepare - Do preliminary suspend work. + * acpi_suspend_prepare - Do preliminary suspend work. * * If necessary, set the firmware waking vector and do arch-specific * nastiness to get the wakeup code to the waking vector. */ -static int acpi_pm_prepare(void) +static int acpi_suspend_prepare(void) { int error = acpi_sleep_prepare(acpi_target_sleep_state); @@ -104,7 +104,7 @@ static int acpi_pm_prepare(void) } /** - * acpi_pm_enter - Actually enter a sleep state. + * acpi_suspend_enter - Actually enter a sleep state. * @pm_state: ignored * * Flush caches and go to sleep. For STR we have to call arch-specific @@ -112,7 +112,7 @@ static int acpi_pm_prepare(void) * It's unfortunate, but it works. Please fix if you're feeling frisky. */ -static int acpi_pm_enter(suspend_state_t pm_state) +static int acpi_suspend_enter(suspend_state_t pm_state) { acpi_status status = AE_OK; unsigned long flags = 0; @@ -169,13 +169,13 @@ static int acpi_pm_enter(suspend_state_t pm_state) } /** - * acpi_pm_finish - Instruct the platform to leave a sleep state. + * acpi_suspend_finish - Instruct the platform to leave a sleep state. * * This is called after we wake back up (or if entering the sleep state * failed). */ -static void acpi_pm_finish(void) +static void acpi_suspend_finish(void) { u32 acpi_state = acpi_target_sleep_state; @@ -196,19 +196,19 @@ static void acpi_pm_finish(void) } /** - * acpi_pm_end - Finish up suspend sequence. + * acpi_suspend_end - Finish up suspend sequence. */ -static void acpi_pm_end(void) +static void acpi_suspend_end(void) { /* - * This is necessary in case acpi_pm_finish() is not called during a + * This is necessary in case acpi_suspend_finish() is not called during a * failing transition to a sleep state. */ acpi_target_sleep_state = ACPI_STATE_S0; } -static int acpi_pm_state_valid(suspend_state_t pm_state) +static int acpi_suspend_state_valid(suspend_state_t pm_state) { u32 acpi_state; @@ -224,13 +224,13 @@ static int acpi_pm_state_valid(suspend_state_t pm_state) } } -static struct platform_suspend_ops acpi_pm_ops = { - .valid = acpi_pm_state_valid, - .begin = acpi_pm_begin, - .prepare = acpi_pm_prepare, - .enter = acpi_pm_enter, - .finish = acpi_pm_finish, - .end = acpi_pm_end, +static struct platform_suspend_ops acpi_suspend_ops = { + .valid = acpi_suspend_state_valid, + .begin = acpi_suspend_begin, + .prepare = acpi_suspend_prepare, + .enter = acpi_suspend_enter, + .finish = acpi_suspend_finish, + .end = acpi_suspend_end, }; /* @@ -492,7 +492,7 @@ int __init acpi_sleep_init(void) } } - suspend_set_ops(&acpi_pm_ops); + suspend_set_ops(&acpi_suspend_ops); #endif #ifdef CONFIG_HIBERNATION -- cgit v1.2.2 From 78eed028f13b1a0b2612368dff3786e400e6cf8b Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 5 Nov 2007 11:43:33 -0500 Subject: ACPI: video - do not store invalid entries in attached_array list this is a cleanup, not a change to function. Signed-off-by: Dmitry Torokhov Acked-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/video.c | 58 ++++++++++++++++++++++++---------------------------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 980a74188781..3f0e4bccf9db 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -57,8 +57,6 @@ #define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS 0x88 #define ACPI_VIDEO_NOTIFY_DISPLAY_OFF 0x89 -#define ACPI_VIDEO_HEAD_INVALID (~0u - 1) -#define ACPI_VIDEO_HEAD_END (~0u) #define MAX_NAME_LEN 20 #define ACPI_VIDEO_DISPLAY_CRT 1 @@ -1440,11 +1438,15 @@ static int acpi_video_bus_remove_fs(struct acpi_device *device) static struct acpi_video_device_attrib* acpi_video_get_device_attr(struct acpi_video_bus *video, unsigned long device_id) { - int count; + struct acpi_video_enumerated_device *ids; + int i; + + for (i = 0; i < video->attached_count; i++) { + ids = &video->attached_array[i]; + if ((ids->value.int_val & 0xffff) == device_id) + return &ids->value.attrib; + } - for(count = 0; count < video->attached_count; count++) - if((video->attached_array[count].value.int_val & 0xffff) == device_id) - return &(video->attached_array[count].value.attrib); return NULL; } @@ -1571,20 +1573,16 @@ static void acpi_video_device_bind(struct acpi_video_bus *video, struct acpi_video_device *device) { + struct acpi_video_enumerated_device *ids; int i; -#define IDS_VAL(i) video->attached_array[i].value.int_val -#define IDS_BIND(i) video->attached_array[i].bind_info - - for (i = 0; IDS_VAL(i) != ACPI_VIDEO_HEAD_INVALID && - i < video->attached_count; i++) { - if (device->device_id == (IDS_VAL(i) & 0xffff)) { - IDS_BIND(i) = device; + for (i = 0; i < video->attached_count; i++) { + ids = &video->attached_array[i]; + if (device->device_id == (ids->value.int_val & 0xffff)) { + ids->bind_info = device; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "device_bind %d\n", i)); } } -#undef IDS_VAL -#undef IDS_BIND } /* @@ -1603,7 +1601,7 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) int status; int count; int i; - struct acpi_video_enumerated_device *active_device_list; + struct acpi_video_enumerated_device *active_list; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *dod = NULL; union acpi_object *obj; @@ -1624,13 +1622,10 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d video heads in _DOD\n", dod->package.count)); - active_device_list = kmalloc((1 + - dod->package.count) * - sizeof(struct - acpi_video_enumerated_device), - GFP_KERNEL); - - if (!active_device_list) { + active_list = kcalloc(1 + dod->package.count, + sizeof(struct acpi_video_enumerated_device), + GFP_KERNEL); + if (!active_list) { status = -ENOMEM; goto out; } @@ -1640,23 +1635,24 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) obj = &dod->package.elements[i]; if (obj->type != ACPI_TYPE_INTEGER) { - printk(KERN_ERR PREFIX "Invalid _DOD data\n"); - active_device_list[i].value.int_val = - ACPI_VIDEO_HEAD_INVALID; + printk(KERN_ERR PREFIX + "Invalid _DOD data in element %d\n", i); + continue; } - active_device_list[i].value.int_val = obj->integer.value; - active_device_list[i].bind_info = NULL; + + active_list[count].value.int_val = obj->integer.value; + active_list[count].bind_info = NULL; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "dod element[%d] = %d\n", i, (int)obj->integer.value)); count++; } - active_device_list[count].value.int_val = ACPI_VIDEO_HEAD_END; kfree(video->attached_array); - video->attached_array = active_device_list; + video->attached_array = active_list; video->attached_count = count; - out: + + out: kfree(buffer.pointer); return status; } -- cgit v1.2.2 From 251cb0bc795f5c0d8ca27df093319e5b39966174 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 5 Nov 2007 11:43:34 -0500 Subject: ACPI: video - properly handle errors when registering proc elements Have acpi_video_device_add_fs() and acpi_video_bus_add_fs() properly unwind proc creation after error. Signed-off-by: Dmitry Torokhov Acked-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/video.c | 230 +++++++++++++++++++++++++-------------------------- 1 file changed, 115 insertions(+), 115 deletions(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 3f0e4bccf9db..87ae791781ab 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -1048,87 +1048,90 @@ acpi_video_device_EDID_open_fs(struct inode *inode, struct file *file) static int acpi_video_device_add_fs(struct acpi_device *device) { - struct proc_dir_entry *entry = NULL; + struct proc_dir_entry *entry, *device_dir; struct acpi_video_device *vid_dev; - - if (!device) - return -ENODEV; - vid_dev = acpi_driver_data(device); if (!vid_dev) return -ENODEV; - if (!acpi_device_dir(device)) { - acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), - vid_dev->video->dir); - if (!acpi_device_dir(device)) - return -ENODEV; - acpi_device_dir(device)->owner = THIS_MODULE; - } + device_dir = proc_mkdir(acpi_device_bid(device), + vid_dev->video->dir); + if (!device_dir) + return -ENOMEM; + + device_dir->owner = THIS_MODULE; /* 'info' [R] */ - entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device)); + entry = create_proc_entry("info", S_IRUGO, device_dir); if (!entry) - return -ENODEV; - else { - entry->proc_fops = &acpi_video_device_info_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } + goto err_remove_dir; + + entry->proc_fops = &acpi_video_device_info_fops; + entry->data = acpi_driver_data(device); + entry->owner = THIS_MODULE; /* 'state' [R/W] */ - entry = - create_proc_entry("state", S_IFREG | S_IRUGO | S_IWUSR, - acpi_device_dir(device)); + entry = create_proc_entry("state", S_IFREG | S_IRUGO | S_IWUSR, + device_dir); if (!entry) - return -ENODEV; - else { - acpi_video_device_state_fops.write = acpi_video_device_write_state; - entry->proc_fops = &acpi_video_device_state_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } + goto err_remove_info; + + acpi_video_device_state_fops.write = acpi_video_device_write_state; + entry->proc_fops = &acpi_video_device_state_fops; + entry->data = acpi_driver_data(device); + entry->owner = THIS_MODULE; /* 'brightness' [R/W] */ - entry = - create_proc_entry("brightness", S_IFREG | S_IRUGO | S_IWUSR, - acpi_device_dir(device)); + entry = create_proc_entry("brightness", S_IFREG | S_IRUGO | S_IWUSR, + device_dir); if (!entry) - return -ENODEV; - else { - acpi_video_device_brightness_fops.write = acpi_video_device_write_brightness; - entry->proc_fops = &acpi_video_device_brightness_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } + goto err_remove_state; + + acpi_video_device_brightness_fops.write = + acpi_video_device_write_brightness; + entry->proc_fops = &acpi_video_device_brightness_fops; + entry->data = acpi_driver_data(device); + entry->owner = THIS_MODULE; /* 'EDID' [R] */ - entry = create_proc_entry("EDID", S_IRUGO, acpi_device_dir(device)); + entry = create_proc_entry("EDID", S_IRUGO, device_dir); if (!entry) - return -ENODEV; - else { - entry->proc_fops = &acpi_video_device_EDID_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } + goto err_remove_brightness; + entry->proc_fops = &acpi_video_device_EDID_fops; + entry->data = acpi_driver_data(device); + entry->owner = THIS_MODULE; + + acpi_device_dir(device) = device_dir; return 0; + + err_remove_brightness: + remove_proc_entry("brightness", device_dir); + err_remove_state: + remove_proc_entry("state", device_dir); + err_remove_info: + remove_proc_entry("info", device_dir); + err_remove_dir: + remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir); + return -ENOMEM; } static int acpi_video_device_remove_fs(struct acpi_device *device) { struct acpi_video_device *vid_dev; + struct proc_dir_entry *device_dir; vid_dev = acpi_driver_data(device); if (!vid_dev || !vid_dev->video || !vid_dev->video->dir) return -ENODEV; - if (acpi_device_dir(device)) { - remove_proc_entry("info", acpi_device_dir(device)); - remove_proc_entry("state", acpi_device_dir(device)); - remove_proc_entry("brightness", acpi_device_dir(device)); - remove_proc_entry("EDID", acpi_device_dir(device)); + device_dir = acpi_device_dir(device); + if (device_dir) { + remove_proc_entry("info", device_dir); + remove_proc_entry("state", device_dir); + remove_proc_entry("brightness", device_dir); + remove_proc_entry("EDID", device_dir); remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir); acpi_device_dir(device) = NULL; } @@ -1335,94 +1338,91 @@ acpi_video_bus_write_DOS(struct file *file, static int acpi_video_bus_add_fs(struct acpi_device *device) { - struct proc_dir_entry *entry = NULL; - struct acpi_video_bus *video; - + struct acpi_video_bus *video = acpi_driver_data(device); + struct proc_dir_entry *device_dir; + struct proc_dir_entry *entry; - video = acpi_driver_data(device); + device_dir = proc_mkdir(acpi_device_bid(device), acpi_video_dir); + if (!device_dir) + return -ENOMEM; - if (!acpi_device_dir(device)) { - acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), - acpi_video_dir); - if (!acpi_device_dir(device)) - return -ENODEV; - video->dir = acpi_device_dir(device); - acpi_device_dir(device)->owner = THIS_MODULE; - } + device_dir->owner = THIS_MODULE; /* 'info' [R] */ - entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device)); + entry = create_proc_entry("info", S_IRUGO, device_dir); if (!entry) - return -ENODEV; - else { - entry->proc_fops = &acpi_video_bus_info_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } + goto err_remove_dir; + + entry->proc_fops = &acpi_video_bus_info_fops; + entry->data = acpi_driver_data(device); + entry->owner = THIS_MODULE; /* 'ROM' [R] */ - entry = create_proc_entry("ROM", S_IRUGO, acpi_device_dir(device)); + entry = create_proc_entry("ROM", S_IRUGO, device_dir); if (!entry) - return -ENODEV; - else { - entry->proc_fops = &acpi_video_bus_ROM_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } + goto err_remove_info; + + entry->proc_fops = &acpi_video_bus_ROM_fops; + entry->data = acpi_driver_data(device); + entry->owner = THIS_MODULE; /* 'POST_info' [R] */ - entry = - create_proc_entry("POST_info", S_IRUGO, acpi_device_dir(device)); + entry = create_proc_entry("POST_info", S_IRUGO, device_dir); if (!entry) - return -ENODEV; - else { - entry->proc_fops = &acpi_video_bus_POST_info_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } + goto err_remove_rom; + + entry->proc_fops = &acpi_video_bus_POST_info_fops; + entry->data = acpi_driver_data(device); + entry->owner = THIS_MODULE; /* 'POST' [R/W] */ - entry = - create_proc_entry("POST", S_IFREG | S_IRUGO | S_IRUSR, - acpi_device_dir(device)); + entry = create_proc_entry("POST", S_IFREG | S_IRUGO | S_IRUSR, + device_dir); if (!entry) - return -ENODEV; - else { - acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST; - entry->proc_fops = &acpi_video_bus_POST_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } + goto err_remove_post_info; + + acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST; + entry->proc_fops = &acpi_video_bus_POST_fops; + entry->data = acpi_driver_data(device); + entry->owner = THIS_MODULE; /* 'DOS' [R/W] */ - entry = - create_proc_entry("DOS", S_IFREG | S_IRUGO | S_IRUSR, - acpi_device_dir(device)); + entry = create_proc_entry("DOS", S_IFREG | S_IRUGO | S_IRUSR, + device_dir); if (!entry) - return -ENODEV; - else { - acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS; - entry->proc_fops = &acpi_video_bus_DOS_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } + goto err_remove_post; + + acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS; + entry->proc_fops = &acpi_video_bus_DOS_fops; + entry->data = acpi_driver_data(device); + entry->owner = THIS_MODULE; + video->dir = acpi_device_dir(device) = device_dir; return 0; + + err_remove_post: + remove_proc_entry("POST", device_dir); + err_remove_post_info: + remove_proc_entry("POST_info", device_dir); + err_remove_rom: + remove_proc_entry("ROM", device_dir); + err_remove_info: + remove_proc_entry("info", device_dir); + err_remove_dir: + remove_proc_entry(acpi_device_bid(device), acpi_video_dir); + return -ENOMEM; } static int acpi_video_bus_remove_fs(struct acpi_device *device) { - struct acpi_video_bus *video; - - - video = acpi_driver_data(device); + struct proc_dir_entry *device_dir = acpi_device_dir(device); - if (acpi_device_dir(device)) { - remove_proc_entry("info", acpi_device_dir(device)); - remove_proc_entry("ROM", acpi_device_dir(device)); - remove_proc_entry("POST_info", acpi_device_dir(device)); - remove_proc_entry("POST", acpi_device_dir(device)); - remove_proc_entry("DOS", acpi_device_dir(device)); + if (device_dir) { + remove_proc_entry("info", device_dir); + remove_proc_entry("ROM", device_dir); + remove_proc_entry("POST_info", device_dir); + remove_proc_entry("POST", device_dir); + remove_proc_entry("DOS", device_dir); remove_proc_entry(acpi_device_bid(device), acpi_video_dir); acpi_device_dir(device) = NULL; } -- cgit v1.2.2 From c46e5658a0b81891532705bd65592afe091a5967 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 5 Nov 2007 11:43:36 -0500 Subject: ACPI: video - fix permissions on some proc entries POST and DOS are supposed to be writable but permissions did not allow it. Signed-off-by: Dmitry Torokhov Acked-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 87ae791781ab..c24a1d743257 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -1376,7 +1376,7 @@ static int acpi_video_bus_add_fs(struct acpi_device *device) entry->owner = THIS_MODULE; /* 'POST' [R/W] */ - entry = create_proc_entry("POST", S_IFREG | S_IRUGO | S_IRUSR, + entry = create_proc_entry("POST", S_IFREG | S_IRUGO | S_IWUSR, device_dir); if (!entry) goto err_remove_post_info; @@ -1387,7 +1387,7 @@ static int acpi_video_bus_add_fs(struct acpi_device *device) entry->owner = THIS_MODULE; /* 'DOS' [R/W] */ - entry = create_proc_entry("DOS", S_IFREG | S_IRUGO | S_IRUSR, + entry = create_proc_entry("DOS", S_IFREG | S_IRUGO | S_IWUSR, device_dir); if (!entry) goto err_remove_post; -- cgit v1.2.2 From 66fb9d120e91050093b8ce4c1daa2e440660152b Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Wed, 16 Apr 2008 20:52:02 +0200 Subject: ACPI: Cleanup: Remove unneeded, multiple local dummy variables Signed-off-by: Thomas Renninger Signed-off-by: Len Brown --- drivers/acpi/scan.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index e6ce262b5d44..6b1999b1cd34 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -882,10 +882,7 @@ static void acpi_device_get_busid(struct acpi_device *device, static int acpi_video_bus_match(struct acpi_device *device) { - acpi_handle h_dummy1; - acpi_handle h_dummy2; - acpi_handle h_dummy3; - + acpi_handle h_dummy; if (!device) return -EINVAL; @@ -895,18 +892,18 @@ acpi_video_bus_match(struct acpi_device *device) */ /* Does this device able to support video switching ? */ - if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy1)) && - ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy2))) + if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy)) && + ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy))) return 0; /* Does this device able to retrieve a video ROM ? */ - if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy1))) + if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy))) return 0; /* Does this device able to configure which video head to be POSTed ? */ - if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy1)) && - ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy2)) && - ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy3))) + if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy)) && + ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy)) && + ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy))) return 0; return -ENODEV; -- cgit v1.2.2 From 7aa0f1a8b1f7072990c9dc37f238c96dc6d78911 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 29 Apr 2008 12:24:24 -0400 Subject: intel_menlo: fix build warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/misc/intel_menlow.c:191: warning: label ‘unregister’ defined but not used Signed-off-by: Len Brown --- drivers/misc/intel_menlow.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/misc/intel_menlow.c b/drivers/misc/intel_menlow.c index 3db83a2dc3a1..5bb8816c9126 100644 --- a/drivers/misc/intel_menlow.c +++ b/drivers/misc/intel_menlow.c @@ -187,11 +187,6 @@ static int intel_menlow_memory_add(struct acpi_device *device) end: return result; - - unregister: - thermal_cooling_device_unregister(cdev); - return result; - } static int intel_menlow_memory_remove(struct acpi_device *device, int type) -- cgit v1.2.2 From 9448b0d43e5509c6b7baca02510a92ef2de6e328 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Tue, 29 Apr 2008 22:52:01 +0200 Subject: acpi: fix section mismatch warning in pnpacpi Fix following section mismatch warning: WARNING: vmlinux.o(.text+0x153d69): Section mismatch in reference from the function is_exclusive_device() to the variable .init.data:excluded_id_list is_exclusive_device is only used from __init context so document this with the __init annotation and get rid of the warning. Signed-off-by: Sam Ravnborg Signed-off-by: Len Brown --- drivers/pnp/pnpacpi/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index c283a9a70d83..63e64ef39fb7 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -44,7 +44,7 @@ static struct acpi_device_id excluded_id_list[] __initdata = { {"", 0}, }; -static inline int is_exclusive_device(struct acpi_device *dev) +static inline int __init is_exclusive_device(struct acpi_device *dev) { return (!acpi_match_device_ids(dev, excluded_id_list)); } -- cgit v1.2.2 From 36a913586597cab1cd565e9bf348d037f0df955b Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Wed, 30 Apr 2008 13:57:15 -0400 Subject: ACPI: Fix acpi_processor_idle and idle= boot parameters interaction acpi_processor_idle and "idle=" boot parameter interaction is broken. The problem is that, at boot time acpi driver is checking for "idle=" boot option and not registering the acpi idle handler. But, when there is a CST changed callback (typically when switching AC <-> battery or suspend-resume) there are no checks for boot_option_idle_override and acpi idle handler tries to get installed with nasty side effects. With CPU_IDLE configured this issue causes results in a nasty oops on CST change callback and without CPU_IDLE there is no oops, but boot option of "idle=" gets ignored and acpi idle handler gets installed. Change the behavior to not do anything in acpi idle handler when there is a "idle=" boot option. Note that the problem is only there when "idle=" boot option is used. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 836362b50faa..47b167c731a0 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -1299,6 +1299,8 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) { int result = 0; + if (boot_option_idle_override) + return 0; if (!pr) return -EINVAL; @@ -1738,6 +1740,9 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) { int ret; + if (boot_option_idle_override) + return 0; + if (!pr) return -EINVAL; @@ -1768,6 +1773,8 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, struct proc_dir_entry *entry = NULL; unsigned int i; + if (boot_option_idle_override) + return 0; if (!first_run) { dmi_check_system(processor_power_dmi_table); @@ -1803,7 +1810,7 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, * Note that we use previously set idle handler will be used on * platforms that only support C1. */ - if ((pr->flags.power) && (!boot_option_idle_override)) { + if (pr->flags.power) { #ifdef CONFIG_CPU_IDLE acpi_processor_setup_cpuidle(pr); pr->power.dev.cpu = pr->id; @@ -1843,8 +1850,11 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, int acpi_processor_power_exit(struct acpi_processor *pr, struct acpi_device *device) { + if (boot_option_idle_override) + return 0; + #ifdef CONFIG_CPU_IDLE - if ((pr->flags.power) && (!boot_option_idle_override)) + if (pr->flags.power) cpuidle_unregister_device(&pr->power.dev); #endif pr->flags.power_setup_done = 0; -- cgit v1.2.2