* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (179 commits)
ACPI: Fix acpi_processor_idle and idle= boot parameters interaction
acpi: fix section mismatch warning in pnpacpi
intel_menlo: fix build warning
ACPI: Cleanup: Remove unneeded, multiple local dummy variables
ACPI: video - fix permissions on some proc entries
ACPI: video - properly handle errors when registering proc elements
ACPI: video - do not store invalid entries in attached_array list
ACPI: re-name acpi_pm_ops to acpi_suspend_ops
ACER_WMI/ASUS_LAPTOP: fix build bug
thinkpad_acpi: fix possible NULL pointer dereference if kstrdup failed
ACPI: check a return value correctly in acpi_power_get_context()
#if 0 acpi/bay.c:eject_removable_drive()
eeepc-laptop: add hwmon fan control
eeepc-laptop: add backlight
eeepc-laptop: add base driver
ACPI: thinkpad-acpi: bump up version to 0.20
ACPI: thinkpad-acpi: fix selects in Kconfig
ACPI: thinkpad-acpi: use a private workqueue
ACPI: thinkpad-acpi: fluff really minor fix
ACPI: thinkpad-acpi: use uppercase for "LED" on user documentation
...
Fixed conflicts in drivers/acpi/video.c and drivers/misc/intel_menlow.c
manually.
S: Maintained
AUDIT SUBSYSTEM
-P: David Woodhouse
-M: dwmw2@infradead.org
+P: Al Viro
+M: viro@zeniv.linux.org.uk
+P: Eric Paris
+M: eparis@redhat.com
L: linux-audit@redhat.com (subscribers-only)
W: http://people.redhat.com/sgrubb/audit/
-T: git kernel.org:/pub/scm/linux/kernel/git/dwmw2/audit-2.6.git
+T: git git.kernel.org/pub/scm/linux/kernel/git/viro/audit-current.git
S: Maintained
AUXILIARY DISPLAY DRIVERS
M: urs.thuermann@volkswagen.de
P: Oliver Hartkopp
M: oliver.hartkopp@volkswagen.de
-L: socketcan-core@lists.berlios.de
+L: socketcan-core@lists.berlios.de (subscribers-only)
W: http://developer.berlios.de/projects/socketcan/
S: Maintained
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
M: dhowells@redhat.com
P: Koichi Yasutake
M: yasutake.koichi@jp.panasonic.com
-L: linux-am33-list@redhat.com
+L: linux-am33-list@redhat.com (moderated for non-subscribers)
W: ftp://ftp.redhat.com/pub/redhat/gnupro/AM33/
S: Maintained
L: linux-kernel@vger.kernel.org
S: Maintained
-MOXA SMARTIO/INDUSTIO SERIAL CARD (MXSER 2.0)
+MOXA SMARTIO/INDUSTIO/INTELLIO SERIAL CARD
P: Jiri Slaby
M: jirislaby@gmail.com
L: linux-kernel@vger.kernel.org
M: jbarnes@virtuousgeek.org
L: linux-kernel@vger.kernel.org
L: linux-pci@atrey.karlin.mff.cuni.cz
+T: git kernel.org:/pub/scm/linux/kernel/git/jbarnes/pci-2.6.git
S: Supported
PCI HOTPLUG CORE
L: linux-ia64@vger.kernel.org
S: Supported
+SFC NETWORK DRIVER
+P: Steve Hodgson
+P: Ben Hutchings
+P: Robert Stonehouse
+M: linux-net-drivers@solarflare.com
+S: Supported
+
SGI VISUAL WORKSTATION 320 AND 540
P: Andrey Panin
M: pazke@donpac.ru
L: stable@kernel.org
S: Maintained
-TPM DEVICE DRIVER
-P: Kylene Hall
-M: tpmdd-devel@lists.sourceforge.net
-W: http://tpmdd.sourceforge.net
-P: Marcel Selhorst
-M: tpm@selhorst.net
-W: http://www.prosec.rub.de/tpm/
-L: tpmdd-devel@lists.sourceforge.net
-S: Maintained
-
-Telecom Clock Driver for MCPL0010
-P: Mark Gross
-M: mark.gross@intel.com
-S: Supported
-
-TENSILICA XTENSA PORT (xtensa):
-P: Chris Zankel
-M: chris@zankel.net
-S: Maintained
-
-THINKPAD ACPI EXTRAS DRIVER
-P: Henrique de Moraes Holschuh
-M: ibm-acpi@hmh.eng.br
-L: ibm-acpi-devel@lists.sourceforge.net
-W: http://ibm-acpi.sourceforge.net
-W: http://thinkwiki.org/wiki/Ibm-acpi
-T: git repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git
-S: Maintained
-
-UltraSPARC (sparc64):
-P: David S. Miller
-M: davem@davemloft.net
-L: sparclinux@vger.kernel.org
-T: git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6.git
-S: Maintained
-
SHARP LH SUPPORT (LH7952X & LH7A40X)
P: Marc Singer
M: elf@buici.com
M: hch@infradead.org
S: Maintained
+TASKSTATS STATISTICS INTERFACE
+P: Shailabh Nagar
+M: nagar@watson.ibm.com
+L: linux-kernel@vger.kernel.org
+S: Maintained
+
TC CLASSIFIER
P: Jamal Hadi Salim
M: hadi@cyberus.ca
L: netdev@vger.kernel.org
S: Supported
+Telecom Clock Driver for MCPL0010
+P: Mark Gross
+M: mark.gross@intel.com
+S: Supported
+
+TENSILICA XTENSA PORT (xtensa):
+P: Chris Zankel
+M: chris@zankel.net
+S: Maintained
+
+THINKPAD ACPI EXTRAS DRIVER
+P: Henrique de Moraes Holschuh
+M: ibm-acpi@hmh.eng.br
+L: ibm-acpi-devel@lists.sourceforge.net
+W: http://ibm-acpi.sourceforge.net
+W: http://thinkwiki.org/wiki/Ibm-acpi
+T: git repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git
+S: Maintained
+
TI FLASH MEDIA INTERFACE DRIVER
P: Alex Dubov
M: oakad@yahoo.com
M: dsaxena@plexity.net
S: Maintained
-TASKSTATS STATISTICS INTERFACE
-P: Shailabh Nagar
-M: nagar@watson.ibm.com
-L: linux-kernel@vger.kernel.org
-S: Maintained
-
TIPC NETWORK LAYER
P: Per Liden
M: per.liden@ericsson.com
W: http://www.buzzard.org.uk/toshiba/
S: Maintained
+TPM DEVICE DRIVER
+P: Kylene Hall
+M: tpmdd-devel@lists.sourceforge.net
+W: http://tpmdd.sourceforge.net
+P: Marcel Selhorst
+M: tpm@selhorst.net
+W: http://www.prosec.rub.de/tpm/
+L: tpmdd-devel@lists.sourceforge.net
+S: Maintained
+
TRIDENT 4DWAVE/SIS 7018 PCI AUDIO CORE
P: Muli Ben-Yehuda
M: mulix@mulix.org
L: linux-kernel@vger.kernel.org
S: Maintained
+TTY LAYER
+P: Alan Cox
+M: alan@lxorguk.ukuu.org.uk
+L: linux-kernel@vger.kernel.org
+S: Maintained
+
TULIP NETWORK DRIVERS
P: Grant Grundler
M: grundler@parisc-linux.org
W: http://www.chello.nl/~j.vreeken/se401/
S: Maintained
+USB SERIAL BELKIN F5U103 DRIVER
+P: William Greathouse
+M: wgreathouse@smva.com
+L: linux-usb@vger.kernel.org
+S: Maintained
+
+USB SERIAL CYPRESS M8 DRIVER
+P: Lonnie Mendez
+M: dignome@gmail.com
+L: linux-usb@vger.kernel.org
+S: Maintained
+W: http://geocities.com/i0xox0i
+W: http://firstlight.net/cvs
+
USB SERIAL CYBERJACK DRIVER
P: Matthias Bruestle and Harald Welte
M: support@reiner-sct.com
L: linux-usb@vger.kernel.org
S: Supported
-USB SERIAL BELKIN F5U103 DRIVER
-P: William Greathouse
-M: wgreathouse@smva.com
-L: linux-usb@vger.kernel.org
-S: Maintained
-
-USB SERIAL CYPRESS M8 DRIVER
-P: Lonnie Mendez
-M: dignome@gmail.com
-L: linux-usb@vger.kernel.org
-S: Maintained
-W: http://geocities.com/i0xox0i
-W: http://firstlight.net/cvs
-
USB SERIAL EMPEG EMPEG-CAR MARK I/II DRIVER
P: Gary Brubaker
M: xavyer@ix.netcom.com
L: linux-kernel@vger.kernel.org
S: Maintained
-FAT/VFAT/MSDOS FILESYSTEM:
+VFAT/FAT/MSDOS FILESYSTEM:
P: OGAWA Hirofumi
M: hirofumi@mail.parknet.co.jp
L: linux-kernel@vger.kernel.org
L: linux-kernel@vger.kernel.org
S: Maintained
+UltraSPARC (sparc64):
+P: David S. Miller
+M: davem@davemloft.net
+L: sparclinux@vger.kernel.org
+T: git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6.git
+S: Maintained
+
USB DIAMOND RIO500 DRIVER
P: Cesar Miquel
M: miquel@df.uba.ar
#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 */
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 */
- };
-
- 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,
- },
+ EC_FLAGS_NO_GPE, /* Don't use GPE mode */
+ EC_FLAGS_RESCHEDULE_POLL /* Re-schedule poll */
};
/* If we find an EC via the ECDT, we need to keep a ptr to its context */
struct mutex lock;
wait_queue_head_t wait;
struct list_head list;
+ struct delayed_work work;
+ atomic_t irq_count;
u8 handlers_installed;
} *boot_ec, *first_ec;
return 0;
}
- static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
+ static void ec_schedule_ec_poll(struct acpi_ec *ec)
{
- int ret = 0;
+ if (test_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags))
+ schedule_delayed_work(&ec->work,
+ msecs_to_jiffies(ACPI_EC_DELAY));
+ }
- 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;
+ 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);
+ }
+
+ 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),
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");
- clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
- }
- 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 = %d, expect_event = %d\n",
- acpi_ec_read_status(ec), event);
- ret = -ETIME;
- end:
- clear_bit(EC_FLAGS_ADDRESS, &ec->flags);
- return ret;
+ 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\"");
+ return -ETIME;
}
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) {
"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
{
acpi_status status = AE_OK;
struct acpi_ec *ec = 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);
- 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) &&
+ !test_bit(EC_FLAGS_NO_GPE, &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);
}
-
+ end:
+ 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);
+ atomic_set(&ec->irq_count, 0);
+ (void)acpi_ec_gpe_handler(ec);
+ }
+
/* --------------------------------------------------------------------------
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,
return -ENODEV;
}
- entry = create_proc_entry(ACPI_EC_FILE_INFO, S_IRUGO,
- acpi_device_dir(device));
+ entry = proc_create_data(ACPI_EC_FILE_INFO, S_IRUGO,
+ acpi_device_dir(device),
+ &acpi_ec_info_ops, acpi_driver_data(device));
if (!entry)
return -ENODEV;
- else {
- entry->proc_fops = &acpi_ec_info_ops;
- entry->data = acpi_driver_data(device);
- entry->owner = THIS_MODULE;
- }
-
return 0;
}
mutex_init(&ec->lock);
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;
}
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;
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");
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;
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;
/* EC is fully operational, allow queries */
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
+ ec_schedule_ec_poll(ec);
return ret;
}
return -EFAULT;
}
+ static const struct acpi_device_id ec_device_ids[] = {
+ {"PNP0C09", 0},
+ {"", 0},
+ };
+
int __init acpi_ec_ecdt_probe(void)
{
int ret;
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 */
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;
}
/* 'status' [R/W] */
- entry = create_proc_entry(ACPI_FAN_FILE_STATE,
- S_IFREG | S_IRUGO | S_IWUSR,
- acpi_device_dir(device));
+ entry = proc_create_data(ACPI_FAN_FILE_STATE,
+ S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device),
+ &acpi_fan_state_ops,
+ device);
if (!entry)
return -ENODEV;
- else {
- entry->proc_fops = &acpi_fan_state_ops;
- entry->data = device;
- entry->owner = THIS_MODULE;
- }
-
return 0;
}
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)
static struct list_head acpi_power_resource_list;
static const struct file_operations acpi_power_fops = {
+ .owner = THIS_MODULE,
.open = acpi_power_open_fs,
.read = seq_read,
.llseek = seq_lseek,
}
*resource = acpi_driver_data(device);
- if (!resource)
+ if (!*resource)
return -ENODEV;
return 0;
}
/* 'status' [R] */
- entry = create_proc_entry(ACPI_POWER_FILE_STATUS,
- S_IRUGO, acpi_device_dir(device));
+ entry = proc_create_data(ACPI_POWER_FILE_STATUS,
+ S_IRUGO, acpi_device_dir(device),
+ &acpi_power_fops, acpi_driver_data(device));
if (!entry)
return -EIO;
- else {
- entry->proc_fops = &acpi_power_fops;
- entry->data = acpi_driver_data(device);
- }
-
return 0;
}
#define UNINSTALL_NOTIFY_HANDLER 2
static const struct file_operations acpi_processor_info_fops = {
+ .owner = THIS_MODULE,
.open = acpi_processor_info_open_fs,
.read = seq_read,
.llseek = seq_lseek,
acpi_device_dir(device)->owner = THIS_MODULE;
/* 'info' [R] */
- entry = create_proc_entry(ACPI_PROCESSOR_FILE_INFO,
- S_IRUGO, acpi_device_dir(device));
+ entry = proc_create_data(ACPI_PROCESSOR_FILE_INFO,
+ S_IRUGO, acpi_device_dir(device),
+ &acpi_processor_info_fops,
+ acpi_driver_data(device));
if (!entry)
return -EIO;
- else {
- entry->proc_fops = &acpi_processor_info_fops;
- entry->data = acpi_driver_data(device);
- entry->owner = THIS_MODULE;
- }
/* 'throttling' [R/W] */
- entry = create_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING,
- S_IFREG | S_IRUGO | S_IWUSR,
- acpi_device_dir(device));
+ entry = proc_create_data(ACPI_PROCESSOR_FILE_THROTTLING,
+ S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device),
+ &acpi_processor_throttling_fops,
+ acpi_driver_data(device));
if (!entry)
return -EIO;
- else {
- entry->proc_fops = &acpi_processor_throttling_fops;
- entry->data = acpi_driver_data(device);
- entry->owner = THIS_MODULE;
- }
/* 'limit' [R/W] */
- entry = create_proc_entry(ACPI_PROCESSOR_FILE_LIMIT,
- S_IFREG | S_IRUGO | S_IWUSR,
- acpi_device_dir(device));
+ entry = proc_create_data(ACPI_PROCESSOR_FILE_LIMIT,
+ S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device),
+ &acpi_processor_limit_fops,
+ acpi_driver_data(device));
if (!entry)
return -EIO;
- else {
- entry->proc_fops = &acpi_processor_limit_fops;
- entry->data = acpi_driver_data(device);
- entry->owner = THIS_MODULE;
- }
-
return 0;
}
request_region(pr->throttling.address, 6, "ACPI CPU throttle");
}
+ /*
+ * If ACPI describes a slot number for this CPU, we can use it
+ * ensure we get the right value in the "physical id" field
+ * of /proc/cpuinfo
+ */
+ status = acpi_evaluate_object(pr->handle, "_SUN", NULL, &buffer);
+ if (ACPI_SUCCESS(status))
+ arch_fix_phys_package_id(pr->id, object.integer.value);
+
return 0;
}
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",
/* 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;
cx.address);
}
+ if (cx.type == ACPI_STATE_C1) {
+ cx.valid = 1;
+ }
obj = &(element->package.elements[2]);
if (obj->type != ACPI_TYPE_INTEGER)
}
static const struct file_operations acpi_processor_power_fops = {
+ .owner = THIS_MODULE,
.open = acpi_processor_power_open_fs,
.read = seq_read,
.llseek = seq_lseek,
{
int result = 0;
+ if (boot_option_idle_override)
+ return 0;
if (!pr)
return -EINVAL;
{
int ret;
+ if (boot_option_idle_override)
+ return 0;
+
if (!pr)
return -EINVAL;
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);
* 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;
}
/* 'power' [R] */
- entry = create_proc_entry(ACPI_PROCESSOR_FILE_POWER,
- S_IRUGO, acpi_device_dir(device));
+ entry = proc_create_data(ACPI_PROCESSOR_FILE_POWER,
+ S_IRUGO, acpi_device_dir(device),
+ &acpi_processor_power_fops,
+ acpi_driver_data(device));
if (!entry)
return -EIO;
- else {
- entry->proc_fops = &acpi_processor_power_fops;
- entry->data = acpi_driver_data(device);
- entry->owner = THIS_MODULE;
- }
-
return 0;
}
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;
};
static const struct file_operations acpi_thermal_state_fops = {
+ .owner = THIS_MODULE,
.open = acpi_thermal_state_open_fs,
.read = seq_read,
.llseek = seq_lseek,
};
static const struct file_operations acpi_thermal_temp_fops = {
+ .owner = THIS_MODULE,
.open = acpi_thermal_temp_open_fs,
.read = seq_read,
.llseek = seq_lseek,
};
static const struct file_operations acpi_thermal_trip_fops = {
+ .owner = THIS_MODULE,
.open = acpi_thermal_trip_open_fs,
.read = seq_read,
.llseek = seq_lseek,
};
static const struct file_operations acpi_thermal_cooling_fops = {
+ .owner = THIS_MODULE,
.open = acpi_thermal_cooling_open_fs,
.read = seq_read,
.write = acpi_thermal_write_cooling_mode,
};
static const struct file_operations acpi_thermal_polling_fops = {
+ .owner = THIS_MODULE,
.open = acpi_thermal_polling_open_fs,
.read = seq_read,
.write = acpi_thermal_write_polling,
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));
}
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,
.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)
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;
}
/* 'state' [R] */
- entry = create_proc_entry(ACPI_THERMAL_FILE_STATE,
- S_IRUGO, acpi_device_dir(device));
+ entry = proc_create_data(ACPI_THERMAL_FILE_STATE,
+ S_IRUGO, acpi_device_dir(device),
+ &acpi_thermal_state_fops,
+ acpi_driver_data(device));
if (!entry)
return -ENODEV;
- else {
- entry->proc_fops = &acpi_thermal_state_fops;
- entry->data = acpi_driver_data(device);
- entry->owner = THIS_MODULE;
- }
/* 'temperature' [R] */
- entry = create_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE,
- S_IRUGO, acpi_device_dir(device));
+ entry = proc_create_data(ACPI_THERMAL_FILE_TEMPERATURE,
+ S_IRUGO, acpi_device_dir(device),
+ &acpi_thermal_temp_fops,
+ acpi_driver_data(device));
if (!entry)
return -ENODEV;
- else {
- entry->proc_fops = &acpi_thermal_temp_fops;
- entry->data = acpi_driver_data(device);
- entry->owner = THIS_MODULE;
- }
/* 'trip_points' [R] */
- entry = create_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS,
- S_IRUGO,
- acpi_device_dir(device));
+ entry = proc_create_data(ACPI_THERMAL_FILE_TRIP_POINTS,
+ S_IRUGO,
+ acpi_device_dir(device),
+ &acpi_thermal_trip_fops,
+ acpi_driver_data(device));
if (!entry)
return -ENODEV;
- else {
- entry->proc_fops = &acpi_thermal_trip_fops;
- entry->data = acpi_driver_data(device);
- entry->owner = THIS_MODULE;
- }
/* 'cooling_mode' [R/W] */
- entry = create_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE,
- S_IFREG | S_IRUGO | S_IWUSR,
- acpi_device_dir(device));
+ entry = proc_create_data(ACPI_THERMAL_FILE_COOLING_MODE,
+ S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device),
+ &acpi_thermal_cooling_fops,
+ acpi_driver_data(device));
if (!entry)
return -ENODEV;
- else {
- entry->proc_fops = &acpi_thermal_cooling_fops;
- entry->data = acpi_driver_data(device);
- entry->owner = THIS_MODULE;
- }
/* 'polling_frequency' [R/W] */
- entry = create_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ,
- S_IFREG | S_IRUGO | S_IWUSR,
- acpi_device_dir(device));
+ entry = proc_create_data(ACPI_THERMAL_FILE_POLLING_FREQ,
+ S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device),
+ &acpi_thermal_polling_fops,
+ acpi_driver_data(device));
if (!entry)
return -ENODEV;
- else {
- entry->proc_fops = &acpi_thermal_polling_fops;
- entry->data = acpi_driver_data(device);
- entry->owner = THIS_MODULE;
- }
-
return 0;
}
#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
/* bus */
static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file);
static struct file_operations acpi_video_bus_info_fops = {
+ .owner = THIS_MODULE,
.open = acpi_video_bus_info_open_fs,
.read = seq_read,
.llseek = seq_lseek,
static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file);
static struct file_operations acpi_video_bus_ROM_fops = {
+ .owner = THIS_MODULE,
.open = acpi_video_bus_ROM_open_fs,
.read = seq_read,
.llseek = seq_lseek,
static int acpi_video_bus_POST_info_open_fs(struct inode *inode,
struct file *file);
static struct file_operations acpi_video_bus_POST_info_fops = {
+ .owner = THIS_MODULE,
.open = acpi_video_bus_POST_info_open_fs,
.read = seq_read,
.llseek = seq_lseek,
static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file);
static struct file_operations acpi_video_bus_POST_fops = {
+ .owner = THIS_MODULE,
.open = acpi_video_bus_POST_open_fs,
.read = seq_read,
.llseek = seq_lseek,
static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file);
static struct file_operations acpi_video_bus_DOS_fops = {
+ .owner = THIS_MODULE,
.open = acpi_video_bus_DOS_open_fs,
.read = seq_read,
.llseek = seq_lseek,
static int acpi_video_device_info_open_fs(struct inode *inode,
struct file *file);
static struct file_operations acpi_video_device_info_fops = {
+ .owner = THIS_MODULE,
.open = acpi_video_device_info_open_fs,
.read = seq_read,
.llseek = seq_lseek,
static int acpi_video_device_state_open_fs(struct inode *inode,
struct file *file);
static struct file_operations acpi_video_device_state_fops = {
+ .owner = THIS_MODULE,
.open = acpi_video_device_state_open_fs,
.read = seq_read,
.llseek = seq_lseek,
static int acpi_video_device_brightness_open_fs(struct inode *inode,
struct file *file);
static struct file_operations acpi_video_device_brightness_fops = {
+ .owner = THIS_MODULE,
.open = acpi_video_device_brightness_open_fs,
.read = seq_read,
.llseek = seq_lseek,
static int acpi_video_device_EDID_open_fs(struct inode *inode,
struct file *file);
static struct file_operations acpi_video_device_EDID_fops = {
+ .owner = THIS_MODULE,
.open = acpi_video_device_EDID_open_fs,
.read = seq_read,
.llseek = seq_lseek,
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;
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, device_dir);
+ entry = proc_create_data("info", S_IRUGO, acpi_device_dir(device),
+ &acpi_video_device_info_fops, acpi_driver_data(device));
if (!entry)
- return -ENODEV;
+ 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,
- device_dir);
+ acpi_video_device_state_fops.write = acpi_video_device_write_state;
+ entry = proc_create_data("state", S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device),
+ &acpi_video_device_state_fops,
+ acpi_driver_data(device));
if (!entry)
- return -ENODEV;
+ 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,
- device_dir);
+ acpi_video_device_brightness_fops.write =
+ acpi_video_device_write_brightness;
+ entry = proc_create_data("brightness", S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device),
+ &acpi_video_device_brightness_fops,
+ acpi_driver_data(device));
if (!entry)
- return -ENODEV;
+ 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, device_dir);
+ entry = proc_create_data("EDID", S_IRUGO, acpi_device_dir(device),
+ &acpi_video_device_EDID_fops,
+ acpi_driver_data(device));
if (!entry)
- return -ENODEV;
+ 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;
}
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, device_dir);
+ entry = proc_create_data("info", S_IRUGO, acpi_device_dir(device),
+ &acpi_video_bus_info_fops,
+ acpi_driver_data(device));
if (!entry)
- return -ENODEV;
+ 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, device_dir);
+ entry = proc_create_data("ROM", S_IRUGO, acpi_device_dir(device),
+ &acpi_video_bus_ROM_fops,
+ acpi_driver_data(device));
if (!entry)
- return -ENODEV;
+ 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, device_dir);
+ entry = proc_create_data("POST_info", S_IRUGO, acpi_device_dir(device),
+ &acpi_video_bus_POST_info_fops,
+ acpi_driver_data(device));
if (!entry)
- return -ENODEV;
+ 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_IWUSR,
- device_dir);
+ acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST;
- entry = proc_create_data("POST", S_IFREG | S_IRUGO | S_IRUSR,
++ entry = proc_create_data("POST", S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device),
+ &acpi_video_bus_POST_fops,
+ acpi_driver_data(device));
if (!entry)
- return -ENODEV;
+ 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_IWUSR,
- device_dir);
+ acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS;
- entry = proc_create_data("DOS", S_IFREG | S_IRUGO | S_IRUSR,
++ entry = proc_create_data("DOS", S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device),
+ &acpi_video_bus_DOS_fops,
+ acpi_driver_data(device));
if (!entry)
- return -ENODEV;
+ 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);
-
- 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));
+ struct proc_dir_entry *device_dir = 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;
}
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;
}
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
}
/*
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;
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;
}
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;
}
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
- #include <linux/pnpbios.h>
+ #include <linux/pnp.h>
#include <linux/init.h>
#include <asm/uaccess.h>
*/
int __init pnpbios_proc_init(void)
{
- proc_pnp = proc_mkdir("pnp", proc_bus);
+ proc_pnp = proc_mkdir("bus/pnp", NULL);
if (!proc_pnp)
return -EIO;
proc_pnp_boot = proc_mkdir("boot", proc_pnp);
remove_proc_entry("configuration_info", proc_pnp);
remove_proc_entry("devices", proc_pnp);
remove_proc_entry("boot", proc_pnp);
- remove_proc_entry("pnp", proc_bus);
+ remove_proc_entry("bus/pnp", NULL);
}
#ifndef _LINUX_PNP_H
#define _LINUX_PNP_H
-#ifdef __KERNEL__
-
#include <linux/device.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/mod_devicetable.h>
- #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
*/
+ struct resource *pnp_get_resource(struct pnp_dev *, unsigned int, unsigned int);
+
+ 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));
+ }
- /* 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)
#define PNP_PORT_FLAG_16BITADDR (1<<0)
#define PNP_PORT_FLAG_FIXED (1<<1)
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
*/
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 */
int flags; /* used by protocols */
struct proc_dir_entry *procent; /* device entry in /proc/bus/isapnp */
void *data;
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 */
#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);
- 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);
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_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,
- struct pnp_port *data);
- int pnp_register_mem_resource(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);
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);
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);
#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 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; }
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 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; }
- 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; }
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) { }
#define pnp_dbg(format, arg...) do {} while (0)
#endif
-#endif /* __KERNEL__ */
-
#endif /* _LINUX_PNP_H */