diff options
Diffstat (limited to 'drivers')
92 files changed, 1512 insertions, 1614 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 20eacc2c9e0..e942ffe8b57 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -13,6 +13,7 @@ config ACPI depends on IA64 || X86 depends on PCI depends on PM + select PNP default y ---help--- Advanced Configuration and Power Interface (ACPI) support for @@ -132,15 +133,6 @@ config ACPI_VIDEO Note that this is an ref. implementation only. It may or may not work for your integrated video device. -config ACPI_HOTKEY - tristate "Generic Hotkey (EXPERIMENTAL)" - depends on EXPERIMENTAL - depends on X86 - default n - help - Experimental consolidated hotkey driver. - If you are unsure, say N. - config ACPI_FAN tristate "Fan" default y diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 856c32bccac..5956e9f64a8 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -46,7 +46,6 @@ obj-$(CONFIG_ACPI_FAN) += fan.o obj-$(CONFIG_ACPI_DOCK) += dock.o obj-$(CONFIG_ACPI_BAY) += bay.o obj-$(CONFIG_ACPI_VIDEO) += video.o -obj-$(CONFIG_ACPI_HOTKEY) += hotkey.o obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.o obj-$(CONFIG_ACPI_POWER) += power.o obj-$(CONFIG_ACPI_PROCESSOR) += processor.o diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 6daeace796a..37c7dc4f9fe 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -35,7 +35,6 @@ #define ACPI_AC_COMPONENT 0x00020000 #define ACPI_AC_CLASS "ac_adapter" #define ACPI_AC_HID "ACPI0003" -#define ACPI_AC_DRIVER_NAME "ACPI AC Adapter Driver" #define ACPI_AC_DEVICE_NAME "AC Adapter" #define ACPI_AC_FILE_STATE "state" #define ACPI_AC_NOTIFY_STATUS 0x80 @@ -44,10 +43,10 @@ #define ACPI_AC_STATUS_UNKNOWN 0xFF #define _COMPONENT ACPI_AC_COMPONENT -ACPI_MODULE_NAME("acpi_ac") +ACPI_MODULE_NAME("ac"); - MODULE_AUTHOR("Paul Diefenbaugh"); -MODULE_DESCRIPTION(ACPI_AC_DRIVER_NAME); +MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_DESCRIPTION("ACPI AC Adapter Driver"); MODULE_LICENSE("GPL"); extern struct proc_dir_entry *acpi_lock_ac_dir(void); @@ -58,7 +57,7 @@ static int acpi_ac_remove(struct acpi_device *device, int type); static int acpi_ac_open_fs(struct inode *inode, struct file *file); static struct acpi_driver acpi_ac_driver = { - .name = ACPI_AC_DRIVER_NAME, + .name = "ac", .class = ACPI_AC_CLASS, .ids = ACPI_AC_HID, .ops = { diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index cd946ed192d..c26172671fd 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -35,14 +35,13 @@ #define ACPI_MEMORY_DEVICE_COMPONENT 0x08000000UL #define ACPI_MEMORY_DEVICE_CLASS "memory" #define ACPI_MEMORY_DEVICE_HID "PNP0C80" -#define ACPI_MEMORY_DEVICE_DRIVER_NAME "Hotplug Mem Driver" #define ACPI_MEMORY_DEVICE_NAME "Hotplug Mem Device" #define _COMPONENT ACPI_MEMORY_DEVICE_COMPONENT -ACPI_MODULE_NAME("acpi_memory") - MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>"); -MODULE_DESCRIPTION(ACPI_MEMORY_DEVICE_DRIVER_NAME); +ACPI_MODULE_NAME("acpi_memhotplug"); +MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>"); +MODULE_DESCRIPTION("Hotplug Mem Driver"); MODULE_LICENSE("GPL"); /* ACPI _STA method values */ @@ -60,7 +59,7 @@ static int acpi_memory_device_remove(struct acpi_device *device, int type); static int acpi_memory_device_start(struct acpi_device *device); static struct acpi_driver acpi_memory_device_driver = { - .name = ACPI_MEMORY_DEVICE_DRIVER_NAME, + .name = "acpi_memhotplug", .class = ACPI_MEMORY_DEVICE_CLASS, .ids = ACPI_MEMORY_DEVICE_HID, .ops = { diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c index 31ad70a6e22..772299fb5f9 100644 --- a/drivers/acpi/asus_acpi.c +++ b/drivers/acpi/asus_acpi.c @@ -141,6 +141,7 @@ struct asus_hotk { W5A, //W5A W3V, //W3030V xxN, //M2400N, M3700N, M5200N, M6800N, S1300N, S5200N + A4S, //Z81sp //(Centrino) END_MODEL } model; //Models currently supported @@ -397,7 +398,16 @@ static struct model_data model_conf[END_MODEL] = { .brightness_set = "SPLV", .brightness_get = "GPLV", .display_set = "SDSP", - .display_get = "\\ADVG"} + .display_get = "\\ADVG"}, + + { + .name = "A4S", + .brightness_set = "SPLV", + .brightness_get = "GPLV", + .mt_bt_switch = "BLED", + .mt_wled = "WLED" + } + }; /* procdir we use */ @@ -421,7 +431,7 @@ static struct asus_hotk *hotk; static int asus_hotk_add(struct acpi_device *device); static int asus_hotk_remove(struct acpi_device *device, int type); static struct acpi_driver asus_hotk_driver = { - .name = ACPI_HOTK_NAME, + .name = "asus_acpi", .class = ACPI_HOTK_CLASS, .ids = ACPI_HOTK_HID, .ops = { @@ -1117,6 +1127,8 @@ static int asus_model_match(char *model) return W3V; else if (strncmp(model, "W5A", 3) == 0) return W5A; + else if (strncmp(model, "A4S", 3) == 0) + return A4S; else return END_MODEL; } @@ -1365,10 +1377,6 @@ static int __init asus_acpi_init(void) if (acpi_disabled) return -ENODEV; - if (!acpi_specific_hotkey_enabled) { - printk(KERN_ERR "Using generic hotkey driver\n"); - return -ENODEV; - } asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir); if (!asus_proc_dir) { printk(KERN_ERR "Asus ACPI: Unable to create /proc entry\n"); diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 2f4521a48fe..e64c76c8b72 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -42,7 +42,6 @@ #define ACPI_BATTERY_COMPONENT 0x00040000 #define ACPI_BATTERY_CLASS "battery" #define ACPI_BATTERY_HID "PNP0C0A" -#define ACPI_BATTERY_DRIVER_NAME "ACPI Battery Driver" #define ACPI_BATTERY_DEVICE_NAME "Battery" #define ACPI_BATTERY_FILE_INFO "info" #define ACPI_BATTERY_FILE_STATUS "state" @@ -53,10 +52,10 @@ #define ACPI_BATTERY_UNITS_AMPS "mA" #define _COMPONENT ACPI_BATTERY_COMPONENT -ACPI_MODULE_NAME("acpi_battery") +ACPI_MODULE_NAME("battery"); - MODULE_AUTHOR("Paul Diefenbaugh"); -MODULE_DESCRIPTION(ACPI_BATTERY_DRIVER_NAME); +MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_DESCRIPTION("ACPI Battery Driver"); MODULE_LICENSE("GPL"); extern struct proc_dir_entry *acpi_lock_battery_dir(void); @@ -67,7 +66,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type); static int acpi_battery_resume(struct acpi_device *device); static struct acpi_driver acpi_battery_driver = { - .name = ACPI_BATTERY_DRIVER_NAME, + .name = "battery", .class = ACPI_BATTERY_CLASS, .ids = ACPI_BATTERY_HID, .ops = { @@ -324,6 +323,13 @@ static int acpi_battery_check(struct acpi_battery *battery) return result; } +static void acpi_battery_check_present(struct acpi_battery *battery) +{ + if (!battery->flags.present) { + acpi_battery_check(battery); + } +} + /* -------------------------------------------------------------------------- FS Interface (/proc) -------------------------------------------------------------------------- */ @@ -340,6 +346,8 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset) if (!battery) goto end; + acpi_battery_check_present(battery); + if (battery->flags.present) seq_printf(seq, "present: yes\n"); else { @@ -424,6 +432,8 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset) if (!battery) goto end; + acpi_battery_check_present(battery); + if (battery->flags.present) seq_printf(seq, "present: yes\n"); else { @@ -499,6 +509,8 @@ static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) if (!battery) goto end; + acpi_battery_check_present(battery); + if (!battery->flags.present) { seq_printf(seq, "present: no\n"); goto end; @@ -536,6 +548,8 @@ acpi_battery_write_alarm(struct file *file, if (!battery || (count > sizeof(alarm_string) - 1)) return -EINVAL; + acpi_battery_check_present(battery); + if (!battery->flags.present) return -ENODEV; diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c index 91082ce6f5d..fb3f31b5e69 100644 --- a/drivers/acpi/bay.c +++ b/drivers/acpi/bay.c @@ -32,11 +32,9 @@ #include <asm/uaccess.h> #include <linux/platform_device.h> -#define ACPI_BAY_DRIVER_NAME "ACPI Removable Drive Bay Driver" - -ACPI_MODULE_NAME("bay") +ACPI_MODULE_NAME("bay"); MODULE_AUTHOR("Kristen Carlson Accardi"); -MODULE_DESCRIPTION(ACPI_BAY_DRIVER_NAME); +MODULE_DESCRIPTION("ACPI Removable Drive Bay Driver"); MODULE_LICENSE("GPL"); #define ACPI_BAY_CLASS "bay" #define ACPI_BAY_COMPONENT 0x10000000 @@ -47,18 +45,6 @@ MODULE_LICENSE("GPL"); acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer);\ printk(KERN_DEBUG PREFIX "%s: %s\n", prefix, s); } static void bay_notify(acpi_handle handle, u32 event, void *data); -static int acpi_bay_add(struct acpi_device *device); -static int acpi_bay_remove(struct acpi_device *device, int type); - -static struct acpi_driver acpi_bay_driver = { - .name = ACPI_BAY_DRIVER_NAME, - .class = ACPI_BAY_CLASS, - .ids = ACPI_BAY_HID, - .ops = { - .add = acpi_bay_add, - .remove = acpi_bay_remove, - }, -}; struct bay { acpi_handle handle; @@ -234,14 +220,6 @@ int eject_removable_drive(struct device *dev) } EXPORT_SYMBOL_GPL(eject_removable_drive); -static int acpi_bay_add(struct acpi_device *device) -{ - bay_dprintk(device->handle, "adding bay device"); - strcpy(acpi_device_name(device), "Dockable Bay"); - strcpy(acpi_device_class(device), "bay"); - return 0; -} - static int acpi_bay_add_fs(struct bay *bay) { int ret; @@ -303,7 +281,7 @@ static int bay_add(acpi_handle handle, int id) /* initialize platform device stuff */ pdev = platform_device_register_simple(ACPI_BAY_CLASS, id, NULL, 0); - if (pdev == NULL) { + if (IS_ERR(pdev)) { printk(KERN_ERR PREFIX "Error registering bay device\n"); goto bay_add_err; } @@ -339,52 +317,6 @@ bay_add_err: return -ENODEV; } -static int acpi_bay_remove(struct acpi_device *device, int type) -{ - /*** FIXME: do something here */ - return 0; -} - -/** - * bay_create_acpi_device - add new devices to acpi - * @handle - handle of the device to add - * - * This function will create a new acpi_device for the given - * handle if one does not exist already. This should cause - * acpi to scan for drivers for the given devices, and call - * matching driver's add routine. - * - * Returns a pointer to the acpi_device corresponding to the handle. - */ -static struct acpi_device * bay_create_acpi_device(acpi_handle handle) -{ - struct acpi_device *device = NULL; - struct acpi_device *parent_device; - acpi_handle parent; - int ret; - - bay_dprintk(handle, "Trying to get device"); - if (acpi_bus_get_device(handle, &device)) { - /* - * no device created for this object, - * so we should create one. - */ - bay_dprintk(handle, "No device for handle"); - acpi_get_parent(handle, &parent); - if (acpi_bus_get_device(parent, &parent_device)) - parent_device = NULL; - - ret = acpi_bus_add(&device, parent_device, handle, - ACPI_BUS_TYPE_DEVICE); - if (ret) { - pr_debug("error adding bus, %x\n", - -ret); - return NULL; - } - } - return device; -} - /** * bay_notify - act upon an acpi bay notification * @handle: the bay handle @@ -394,38 +326,19 @@ static struct acpi_device * bay_create_acpi_device(acpi_handle handle) */ static void bay_notify(acpi_handle handle, u32 event, void *data) { - struct acpi_device *dev; + struct bay *bay_dev = (struct bay *)data; + struct device *dev = &bay_dev->pdev->dev; bay_dprintk(handle, "Bay event"); switch(event) { case ACPI_NOTIFY_BUS_CHECK: - printk("Bus Check\n"); case ACPI_NOTIFY_DEVICE_CHECK: - printk("Device Check\n"); - dev = bay_create_acpi_device(handle); - if (dev) - acpi_bus_generate_event(dev, event, 0); - else - printk("No device for generating event\n"); - /* wouldn't it be a good idea to just rescan SATA - * right here? - */ - break; case ACPI_NOTIFY_EJECT_REQUEST: - printk("Eject request\n"); - dev = bay_create_acpi_device(handle); - if (dev) - acpi_bus_generate_event(dev, event, 0); - else - printk("No device for generating eventn"); - - /* wouldn't it be a good idea to just call the - * eject_device here if we were a SATA device? - */ + kobject_uevent(&dev->kobj, KOBJ_CHANGE); break; default: - printk("unknown event %d\n", event); + printk(KERN_ERR PREFIX "Bay: unknown event %d\n", event); } } @@ -457,10 +370,6 @@ static int __init bay_init(void) acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, find_bay, &bays, NULL); - if (bays) - if ((acpi_bus_register_driver(&acpi_bay_driver) < 0)) - printk(KERN_ERR "Unable to register bay driver\n"); - if (!bays) return -ENODEV; @@ -481,8 +390,6 @@ static void __exit bay_exit(void) kfree(bay->name); kfree(bay); } - - acpi_bus_unregister_driver(&acpi_bay_driver); } postcore_initcall(bay_init); diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index c26468da429..dd49ea0d0ed 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -39,7 +39,7 @@ #include <acpi/acpi_drivers.h> #define _COMPONENT ACPI_BUS_COMPONENT -ACPI_MODULE_NAME("acpi_bus") +ACPI_MODULE_NAME("bus"); #ifdef CONFIG_X86 extern void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger); #endif @@ -147,7 +147,7 @@ int acpi_bus_get_power(acpi_handle handle, int *state) *state = ACPI_STATE_D0; } else { /* - * Get the device's power state either directly (via _PSC) or + * Get the device's power state either directly (via _PSC) or * indirectly (via power resources). */ if (device->power.flags.explicit_get) { @@ -199,15 +199,14 @@ int acpi_bus_set_power(acpi_handle handle, int state) * Get device's current power state if it's unknown * This means device power state isn't initialized or previous setting failed */ - if (!device->flags.force_power_state) { - if (device->power.state == ACPI_STATE_UNKNOWN) - acpi_bus_get_power(device->handle, &device->power.state); - if (state == device->power.state) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", - state)); - return 0; - } + if ((device->power.state == ACPI_STATE_UNKNOWN) || device->flags.force_power_state) + acpi_bus_get_power(device->handle, &device->power.state); + if ((state == device->power.state) && !device->flags.force_power_state) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", + state)); + return 0; } + if (!device->power.states[state].flags.valid) { printk(KERN_WARNING PREFIX "Device does not support D%d\n", state); return -ENODEV; @@ -462,7 +461,7 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) "Received BUS CHECK notification for device [%s]\n", device->pnp.bus_id)); result = acpi_bus_check_scope(device); - /* + /* * TBD: We'll need to outsource certain events to non-ACPI * drivers via the device manager (device.c). */ @@ -473,7 +472,7 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) "Received DEVICE CHECK notification for device [%s]\n", device->pnp.bus_id)); result = acpi_bus_check_device(device, NULL); - /* + /* * TBD: We'll need to outsource certain events to non-ACPI * drivers via the device manager (device.c). */ @@ -543,7 +542,7 @@ static int __init acpi_bus_init_irq(void) char *message = NULL; - /* + /* * Let the system know what interrupt model we are using by * evaluating the \_PIC object, if exists. */ @@ -684,7 +683,7 @@ static int __init acpi_bus_init(void) * the EC device is found in the namespace (i.e. before acpi_initialize_objects() * is called). * - * This is accomplished by looking for the ECDT table, and getting + * This is accomplished by looking for the ECDT table, and getting * the EC parameters out of that. */ status = acpi_ec_ecdt_probe(); @@ -699,6 +698,9 @@ static int __init acpi_bus_init(void) printk(KERN_INFO PREFIX "Interpreter enabled\n"); + /* Initialize sleep structures */ + acpi_sleep_init(); + /* * Get the system interrupt model and evaluate \_PIC. */ diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index c726612fafb..cb4110b50cd 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -34,7 +34,6 @@ #include <acpi/acpi_drivers.h> #define ACPI_BUTTON_COMPONENT 0x00080000 -#define ACPI_BUTTON_DRIVER_NAME "ACPI Button Driver" #define ACPI_BUTTON_CLASS "button" #define ACPI_BUTTON_FILE_INFO "info" #define ACPI_BUTTON_FILE_STATE "state" @@ -61,10 +60,10 @@ #define ACPI_BUTTON_TYPE_LID 0x05 #define _COMPONENT ACPI_BUTTON_COMPONENT -ACPI_MODULE_NAME("acpi_button") +ACPI_MODULE_NAME("button"); MODULE_AUTHOR("Paul Diefenbaugh"); -MODULE_DESCRIPTION(ACPI_BUTTON_DRIVER_NAME); +MODULE_DESCRIPTION("ACPI Button Driver"); MODULE_LICENSE("GPL"); static int acpi_button_add(struct acpi_device *device); @@ -73,7 +72,7 @@ static int acpi_button_info_open_fs(struct inode *inode, struct file *file); static int acpi_button_state_open_fs(struct inode *inode, struct file *file); static struct acpi_driver acpi_button_driver = { - .name = ACPI_BUTTON_DRIVER_NAME, + .name = "button", .class = ACPI_BUTTON_CLASS, .ids = "button_power,button_sleep,PNP0C0D,PNP0C0C,PNP0C0E", .ops = { diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c index 4a9b7bf6f44..f9db4f444bd 100644 --- a/drivers/acpi/cm_sbs.c +++ b/drivers/acpi/cm_sbs.c @@ -31,7 +31,7 @@ #include <acpi/actypes.h> #include <acpi/acutils.h> -ACPI_MODULE_NAME("cm_sbs") +ACPI_MODULE_NAME("cm_sbs"); #define ACPI_AC_CLASS "ac_adapter" #define ACPI_BATTERY_CLASS "battery" #define ACPI_SBS_COMPONENT 0x00080000 diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 69a68fd394c..0930d9413df 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -35,7 +35,6 @@ #include <acpi/acpi_drivers.h> #include <acpi/container.h> -#define ACPI_CONTAINER_DRIVER_NAME "ACPI container driver" #define ACPI_CONTAINER_DEVICE_NAME "ACPI container device" #define ACPI_CONTAINER_CLASS "container" @@ -44,10 +43,10 @@ #define ACPI_CONTAINER_COMPONENT 0x01000000 #define _COMPONENT ACPI_CONTAINER_COMPONENT -ACPI_MODULE_NAME("acpi_container") +ACPI_MODULE_NAME("container"); - MODULE_AUTHOR("Anil S Keshavamurthy"); -MODULE_DESCRIPTION(ACPI_CONTAINER_DRIVER_NAME); +MODULE_AUTHOR("Anil S Keshavamurthy"); +MODULE_DESCRIPTION("ACPI container driver"); MODULE_LICENSE("GPL"); #define ACPI_STA_PRESENT (0x00000001) @@ -56,7 +55,7 @@ static int acpi_container_add(struct acpi_device *device); static int acpi_container_remove(struct acpi_device *device, int type); static struct acpi_driver acpi_container_driver = { - .name = ACPI_CONTAINER_DRIVER_NAME, + .name = "container", .class = ACPI_CONTAINER_CLASS, .ids = "ACPI0004,PNP0A05,PNP0A06", .ops = { diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c index d48f65a8f65..bf513e07b77 100644 --- a/drivers/acpi/debug.c +++ b/drivers/acpi/debug.c @@ -12,7 +12,7 @@ #include <acpi/acglobal.h> #define _COMPONENT ACPI_SYSTEM_COMPONENT -ACPI_MODULE_NAME("debug") +ACPI_MODULE_NAME("debug"); #ifdef MODULE_PARAM_PREFIX #undef MODULE_PARAM_PREFIX diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index 1cbe6190582..1683e5c5b94 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c @@ -231,10 +231,8 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, * Obtain the method mutex if necessary. Do not acquire mutex for a * recursive call. */ - if (!walk_state || - !obj_desc->method.mutex->mutex.owner_thread || - (walk_state->thread != - obj_desc->method.mutex->mutex.owner_thread)) { + if (acpi_os_get_thread_id() != + obj_desc->method.mutex->mutex.owner_thread_id) { /* * Acquire the method mutex. This releases the interpreter if we * block (and reacquires it before it returns) @@ -248,14 +246,14 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, } /* Update the mutex and walk info and save the original sync_level */ + obj_desc->method.mutex->mutex.owner_thread_id = + acpi_os_get_thread_id(); if (walk_state) { obj_desc->method.mutex->mutex. original_sync_level = walk_state->thread->current_sync_level; - obj_desc->method.mutex->mutex.owner_thread = - walk_state->thread; walk_state->thread->current_sync_level = obj_desc->method.sync_level; } else { @@ -569,7 +567,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.owner_thread_id = ACPI_MUTEX_NOT_ACQUIRED; } } diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 688e83a1690..54a697f9aa1 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -32,11 +32,11 @@ #include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h> -#define ACPI_DOCK_DRIVER_NAME "ACPI Dock Station Driver" +#define ACPI_DOCK_DRIVER_DESCRIPTION "ACPI Dock Station Driver" -ACPI_MODULE_NAME("dock") +ACPI_MODULE_NAME("dock"); MODULE_AUTHOR("Kristen Carlson Accardi"); -MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_NAME); +MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_DESCRIPTION); MODULE_LICENSE("GPL"); static struct atomic_notifier_head dock_notifier_list; @@ -741,7 +741,7 @@ static int dock_add(acpi_handle handle) goto dock_add_err; } - printk(KERN_INFO PREFIX "%s \n", ACPI_DOCK_DRIVER_NAME); + printk(KERN_INFO PREFIX "%s \n", ACPI_DOCK_DRIVER_DESCRIPTION); return 0; diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 743ce27fa0b..ab688837379 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -38,11 +38,10 @@ #include <acpi/actypes.h> #define _COMPONENT ACPI_EC_COMPONENT -ACPI_MODULE_NAME("acpi_ec") +ACPI_MODULE_NAME("ec"); #define ACPI_EC_COMPONENT 0x00100000 #define ACPI_EC_CLASS "embedded_controller" #define ACPI_EC_HID "PNP0C09" -#define ACPI_EC_DRIVER_NAME "ACPI Embedded Controller Driver" #define ACPI_EC_DEVICE_NAME "Embedded Controller" #define ACPI_EC_FILE_INFO "info" #undef PREFIX @@ -80,7 +79,7 @@ static int acpi_ec_stop(struct acpi_device *device, int type); static int acpi_ec_add(struct acpi_device *device); static struct acpi_driver acpi_ec_driver = { - .name = ACPI_EC_DRIVER_NAME, + .name = "ec", .class = ACPI_EC_CLASS, .ids = ACPI_EC_HID, .ops = { @@ -280,8 +279,10 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, mutex_lock(&ec->lock); if (ec->global_lock) { status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); - if (ACPI_FAILURE(status)) + if (ACPI_FAILURE(status)) { + mutex_unlock(&ec->lock); return -ENODEV; + } } /* Make sure GPE is enabled before doing transaction */ diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c index 959a893c8d1..3b23562e6f9 100644 --- a/drivers/acpi/event.c +++ b/drivers/acpi/event.c @@ -13,7 +13,7 @@ #include <acpi/acpi_drivers.h> #define _COMPONENT ACPI_SYSTEM_COMPONENT -ACPI_MODULE_NAME("event") +ACPI_MODULE_NAME("event"); /* Global vars for handling event proc entry */ static DEFINE_SPINLOCK(acpi_system_event_lock); diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c index dfac3ecc596..635ba449ebc 100644 --- a/drivers/acpi/events/evgpe.c +++ b/drivers/acpi/events/evgpe.c @@ -636,17 +636,6 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) } } - if (!acpi_gbl_system_awake_and_running) { - /* - * We just woke up because of a wake GPE. Disable any further GPEs - * until we are fully up and running (Only wake GPEs should be enabled - * at this time, but we just brute-force disable them all.) - * 1) We must disable this particular wake GPE so it won't fire again - * 2) We want to disable all wake GPEs, since we are now awake - */ - (void)acpi_hw_disable_all_gpes(); - } - /* * Dispatch the GPE to either an installed handler, or the control method * associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c index 1b784ffe54c..d572700197f 100644 --- a/drivers/acpi/events/evmisc.c +++ b/drivers/acpi/events/evmisc.c @@ -196,12 +196,11 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, notify_info->notify.value = (u16) notify_value; notify_info->notify.handler_obj = handler_obj; - status = - acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch, - notify_info); - if (ACPI_FAILURE(status)) { - acpi_ut_delete_generic_state(notify_info); - } + acpi_ex_relinquish_interpreter(); + + acpi_ev_notify_dispatch(notify_info); + + acpi_ex_reacquire_interpreter(); } if (!handler_obj) { diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c index 68d283fd60e..1a73c14df2c 100644 --- a/drivers/acpi/executer/exdump.c +++ b/drivers/acpi/executer/exdump.c @@ -134,7 +134,7 @@ static struct acpi_exdump_info acpi_ex_dump_method[8] = { static struct acpi_exdump_info acpi_ex_dump_mutex[5] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_mutex), NULL}, {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(mutex.sync_level), "Sync Level"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.owner_thread), "Owner Thread"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.owner_thread_id), "Owner Thread"}, {ACPI_EXD_UINT16, ACPI_EXD_OFFSET(mutex.acquisition_depth), "Acquire Depth"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.os_mutex), "OsMutex"} diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c index 5101bad5baf..4eb883bda6a 100644 --- a/drivers/acpi/executer/exmutex.c +++ b/drivers/acpi/executer/exmutex.c @@ -66,10 +66,9 @@ acpi_ex_link_mutex(union acpi_operand_object *obj_desc, * ******************************************************************************/ -void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc) +void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc, + struct acpi_thread_state *thread) { - struct acpi_thread_state *thread = obj_desc->mutex.owner_thread; - if (!thread) { return; } @@ -174,16 +173,13 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, /* Support for multiple acquires by the owning thread */ - 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); - } + if (obj_desc->mutex.owner_thread_id == acpi_os_get_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 */ @@ -206,7 +202,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, /* Have the mutex: update mutex and walk info and save the sync_level */ - obj_desc->mutex.owner_thread = walk_state->thread; + obj_desc->mutex.owner_thread_id = acpi_os_get_thread_id(); obj_desc->mutex.acquisition_depth = 1; obj_desc->mutex.original_sync_level = walk_state->thread->current_sync_level; @@ -246,7 +242,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, /* The mutex must have been previously acquired in order to release it */ - if (!obj_desc->mutex.owner_thread) { + if (!obj_desc->mutex.owner_thread_id) { ACPI_ERROR((AE_INFO, "Cannot release Mutex [%4.4s], not acquired", acpi_ut_get_node_name(obj_desc->mutex.node))); @@ -266,14 +262,14 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, * 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 != + if ((obj_desc->mutex.owner_thread_id != walk_state->thread->thread_id) && (obj_desc->mutex.os_mutex != 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, acpi_ut_get_node_name(obj_desc->mutex.node), - (unsigned long)obj_desc->mutex.owner_thread->thread_id)); + (unsigned long)obj_desc->mutex.owner_thread_id)); return_ACPI_STATUS(AE_AML_NOT_OWNER); } @@ -300,7 +296,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, /* Unlink the mutex from the owner's list */ - acpi_ex_unlink_mutex(obj_desc); + acpi_ex_unlink_mutex(obj_desc, walk_state->thread); /* Release the mutex, special case for Global Lock */ @@ -312,7 +308,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, /* Update the mutex and restore sync_level */ - obj_desc->mutex.owner_thread = NULL; + obj_desc->mutex.owner_thread_id = ACPI_MUTEX_NOT_ACQUIRED; walk_state->thread->current_sync_level = obj_desc->mutex.original_sync_level; @@ -367,7 +363,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread) /* Mark mutex unowned */ - obj_desc->mutex.owner_thread = NULL; + obj_desc->mutex.owner_thread_id = ACPI_MUTEX_NOT_ACQUIRED; /* Update Thread sync_level (Last mutex is the important one) */ diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index af22fdf7341..ec655c53949 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -36,14 +36,13 @@ #define ACPI_FAN_COMPONENT 0x00200000 #define ACPI_FAN_CLASS "fan" -#define ACPI_FAN_DRIVER_NAME "ACPI Fan Driver" #define ACPI_FAN_FILE_STATE "state" #define _COMPONENT ACPI_FAN_COMPONENT -ACPI_MODULE_NAME("acpi_fan") +ACPI_MODULE_NAME("fan"); - MODULE_AUTHOR("Paul Diefenbaugh"); -MODULE_DESCRIPTION(ACPI_FAN_DRIVER_NAME); +MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_DESCRIPTION("ACPI Fan Driver"); MODULE_LICENSE("GPL"); static int acpi_fan_add(struct acpi_device *device); @@ -52,7 +51,7 @@ static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state); static int acpi_fan_resume(struct acpi_device *device); static struct acpi_driver acpi_fan_driver = { - .name = ACPI_FAN_DRIVER_NAME, + .name = "fan", .class = ACPI_FAN_CLASS, .ids = "PNP0C0B", .ops = { diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 7b6c9ff9beb..4334c208841 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -241,3 +241,65 @@ static int __init init_acpi_device_notify(void) } arch_initcall(init_acpi_device_notify); + + +#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) + +/* Every ACPI platform has a mc146818 compatible "cmos rtc". Here we find + * its device node and pass extra config data. This helps its driver use + * capabilities that the now-obsolete mc146818 didn't have, and informs it + * that this board's RTC is wakeup-capable (per ACPI spec). + */ +#include <linux/mc146818rtc.h> + +static struct cmos_rtc_board_info rtc_info; + + +/* PNP devices are registered in a subsys_initcall(); + * ACPI specifies the PNP IDs to use. + */ +#include <linux/pnp.h> + +static int __init pnp_match(struct device *dev, void *data) +{ + static const char *ids[] = { "PNP0b00", "PNP0b01", "PNP0b02", }; + struct pnp_dev *pnp = to_pnp_dev(dev); + int i; + + for (i = 0; i < ARRAY_SIZE(ids); i++) { + if (compare_pnp_id(pnp->id, ids[i]) != 0) + return 1; + } + return 0; +} + +static struct device *__init get_rtc_dev(void) +{ + return bus_find_device(&pnp_bus_type, NULL, NULL, pnp_match); +} + +static int __init acpi_rtc_init(void) +{ + struct device *dev = get_rtc_dev(); + + if (dev) { + rtc_info.rtc_day_alarm = acpi_gbl_FADT.day_alarm; + rtc_info.rtc_mon_alarm = acpi_gbl_FADT.month_alarm; + rtc_info.rtc_century = acpi_gbl_FADT.century; + + /* NOTE: acpi_gbl_FADT->rtcs4 is NOT currently useful */ + + dev->platform_data = &rtc_info; + + /* RTC always wakes from S1/S2/S3, and often S4/STD */ + device_init_wakeup(dev, 1); + + put_device(dev); + } else + pr_debug("ACPI: RTC unavailable?\n"); + return 0; +} +/* do this between RTC subsys_initcall() and rtc_cmos driver_initcall() */ +fs_initcall(acpi_rtc_init); + +#endif diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c index 57901ca3ade..8fa93125fd4 100644 --- a/drivers/acpi/hardware/hwsleep.c +++ b/drivers/acpi/hardware/hwsleep.c @@ -235,6 +235,14 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) "While executing method _SST")); } + /* + * 1) Disable/Clear all GPEs + */ + status = acpi_hw_disable_all_gpes(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + return_ACPI_STATUS(AE_OK); } @@ -290,13 +298,8 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) } /* - * 1) Disable/Clear all GPEs * 2) Enable all wakeup GPEs */ - status = acpi_hw_disable_all_gpes(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } acpi_gbl_system_awake_and_running = FALSE; status = acpi_hw_enable_all_wakeup_gpes(); diff --git a/drivers/acpi/hotkey.c b/drivers/acpi/hotkey.c deleted file mode 100644 index 8edfb92f7ed..00000000000 --- a/drivers/acpi/hotkey.c +++ /dev/null @@ -1,1042 +0,0 @@ -/* - * hotkey.c - ACPI Hotkey Driver ($Revision: 0.2 $) - * - * Copyright (C) 2004 Luming Yu <luming.yu@intel.com> - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * 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 <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/types.h> -#include <linux/proc_fs.h> -#include <linux/sched.h> -#include <linux/kmod.h> -#include <linux/seq_file.h> -#include <acpi/acpi_drivers.h> -#include <acpi/acpi_bus.h> -#include <asm/uaccess.h> - -#define HOTKEY_ACPI_VERSION "0.1" - -#define HOTKEY_PROC "hotkey" -#define HOTKEY_EV_CONFIG "event_config" -#define HOTKEY_PL_CONFIG "poll_config" -#define HOTKEY_ACTION "action" -#define HOTKEY_INFO "info" - -#define ACPI_HOTK_NAME "Generic Hotkey Driver" -#define ACPI_HOTK_CLASS "Hotkey" -#define ACPI_HOTK_DEVICE_NAME "Hotkey" -#define ACPI_HOTK_HID "Unknown?" -#define ACPI_HOTKEY_COMPONENT 0x20000000 - -#define ACPI_HOTKEY_EVENT 0x1 -#define ACPI_HOTKEY_POLLING 0x2 -#define ACPI_UNDEFINED_EVENT 0xf - -#define RESULT_STR_LEN 80 - -#define ACTION_METHOD 0 -#define POLL_METHOD 1 - -#define IS_EVENT(e) ((e) <= 10000 && (e) >0) -#define IS_POLL(e) ((e) > 10000) -#define IS_OTHERS(e) ((e)<=0 || (e)>=20000) -#define _COMPONENT ACPI_HOTKEY_COMPONENT -ACPI_MODULE_NAME("acpi_hotkey") - - MODULE_AUTHOR("luming.yu@intel.com"); -MODULE_DESCRIPTION(ACPI_HOTK_NAME); -MODULE_LICENSE("GPL"); - -/* standardized internal hotkey number/event */ -enum { - /* Video Extension event */ - HK_EVENT_CYCLE_OUTPUT_DEVICE = 0x80, - HK_EVENT_OUTPUT_DEVICE_STATUS_CHANGE, - HK_EVENT_CYCLE_DISPLAY_OUTPUT, - HK_EVENT_NEXT_DISPLAY_OUTPUT, - HK_EVENT_PREVIOUS_DISPLAY_OUTPUT, - HK_EVENT_CYCLE_BRIGHTNESS, - HK_EVENT_INCREASE_BRIGHTNESS, - HK_EVENT_DECREASE_BRIGHTNESS, - HK_EVENT_ZERO_BRIGHTNESS, - HK_EVENT_DISPLAY_DEVICE_OFF, - - /* Snd Card event */ - HK_EVENT_VOLUME_MUTE, - HK_EVENT_VOLUME_INCLREASE, - HK_EVENT_VOLUME_DECREASE, - - /* running state control */ - HK_EVENT_ENTERRING_S3, - HK_EVENT_ENTERRING_S4, - HK_EVENT_ENTERRING_S5, -}; - -enum conf_entry_enum { - bus_handle = 0, - bus_method = 1, - action_handle = 2, - method = 3, - LAST_CONF_ENTRY -}; - -/* procdir we use */ -static struct proc_dir_entry *hotkey_proc_dir; -static struct proc_dir_entry *hotkey_config; -static struct proc_dir_entry *hotkey_poll_config; -static struct proc_dir_entry *hotkey_action; -static struct proc_dir_entry *hotkey_info; - -/* linkage for all type of hotkey */ -struct acpi_hotkey_link { - struct list_head entries; - int hotkey_type; /* event or polling based hotkey */ - int hotkey_standard_num; /* standardized hotkey(event) number */ -}; - -/* event based hotkey */ -struct acpi_event_hotkey { - struct acpi_hotkey_link hotkey_link; - int flag; - acpi_handle bus_handle; /* bus to install notify handler */ - int external_hotkey_num; /* external hotkey/event number */ - acpi_handle action_handle; /* acpi handle attached aml action method */ - char *action_method; /* action method */ -}; - -/* - * There are two ways to poll status - * 1. directy call read_xxx method, without any arguments passed in - * 2. call write_xxx method, with arguments passed in, you need - * the result is saved in acpi_polling_hotkey.poll_result. - * anthoer read command through polling interface. - * - */ - -/* polling based hotkey */ -struct acpi_polling_hotkey { - struct acpi_hotkey_link hotkey_link; - int flag; - acpi_handle poll_handle; /* acpi handle attached polling method */ - char *poll_method; /* poll method */ - acpi_handle action_handle; /* acpi handle attached action method */ - char *action_method; /* action method */ - union acpi_object *poll_result; /* polling_result */ - struct proc_dir_entry *proc; -}; - -/* hotkey object union */ -union acpi_hotkey { - struct list_head entries; - struct acpi_hotkey_link link; - struct acpi_event_hotkey event_hotkey; - struct acpi_polling_hotkey poll_hotkey; -}; - -/* hotkey object list */ -struct acpi_hotkey_list { - struct list_head *entries; - int count; -}; - -static int auto_hotkey_add(struct acpi_device *device); -static int auto_hotkey_remove(struct acpi_device *device, int type); - -static struct acpi_driver hotkey_driver = { - .name = ACPI_HOTK_NAME, - .class = ACPI_HOTK_CLASS, - .ids = ACPI_HOTK_HID, - .ops = { - .add = auto_hotkey_add, - .remove = auto_hotkey_remove, - }, -}; - -static void free_hotkey_device(union acpi_hotkey *key); -static void free_hotkey_buffer(union acpi_hotkey *key); -static void free_poll_hotkey_buffer(union acpi_hotkey *key); -static int hotkey_open_config(struct inode *inode, struct file *file); -static int hotkey_poll_open_config(struct inode *inode, struct file *file); -static ssize_t hotkey_write_config(struct file *file, - const char __user * buffer, - size_t count, loff_t * data); -static int hotkey_info_open_fs(struct inode *inode, struct file *file); -static int hotkey_action_open_fs(struct inode *inode, struct file *file); -static ssize_t hotkey_execute_aml_method(struct file *file, - const char __user * buffer, - size_t count, loff_t * data); -static int hotkey_config_seq_show(struct seq_file *seq, void *offset); -static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset); -static int hotkey_polling_open_fs(struct inode *inode, struct file *file); -static union acpi_hotkey *get_hotkey_by_event(struct - acpi_hotkey_list - *hotkey_list, int event); - -/* event based config */ -static const struct file_operations hotkey_config_fops = { - .open = hotkey_open_config, - .read = seq_read, - .write = hotkey_write_config, - .llseek = seq_lseek, - .release = single_release, -}; - -/* polling based config */ -static const struct file_operations hotkey_poll_config_fops = { - .open = hotkey_poll_open_config, - .read = seq_read, - .write = hotkey_write_config, - .llseek = seq_lseek, - .release = single_release, -}; - -/* hotkey driver info */ -static const struct file_operations hotkey_info_fops = { - .open = hotkey_info_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/* action */ -static const struct file_operations hotkey_action_fops = { - .open = hotkey_action_open_fs, - .read = seq_read, - .write = hotkey_execute_aml_method, - .llseek = seq_lseek, - .release = single_release, -}; - -/* polling results */ -static const struct file_operations hotkey_polling_fops = { - .open = hotkey_polling_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -struct acpi_hotkey_list global_hotkey_list; /* link all ev or pl hotkey */ -struct list_head hotkey_entries; /* head of the list of hotkey_list */ - -static int hotkey_info_seq_show(struct seq_file *seq, void *offset) -{ - - seq_printf(seq, "Hotkey generic driver ver: %s\n", HOTKEY_ACPI_VERSION); - - return 0; -} - -static int hotkey_info_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, hotkey_info_seq_show, PDE(inode)->data); -} - -static char *format_result(union acpi_object *object) -{ - char *buf; - - buf = kzalloc(RESULT_STR_LEN, GFP_KERNEL); - if (!buf) - return NULL; - /* Now, just support integer type */ - if (object->type == ACPI_TYPE_INTEGER) - sprintf(buf, "%d\n", (u32) object->integer.value); - return buf; -} - -static int hotkey_polling_seq_show(struct seq_file *seq, void *offset) -{ - struct acpi_polling_hotkey *poll_hotkey = seq->private; - char *buf; - - - if (poll_hotkey->poll_result) { - buf = format_result(poll_hotkey->poll_result); - if (buf) - seq_printf(seq, "%s", buf); - kfree(buf); - } - return 0; -} - -static int hotkey_polling_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, hotkey_polling_seq_show, PDE(inode)->data); -} - -static int hotkey_action_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, hotkey_info_seq_show, PDE(inode)->data); -} - -/* Mapping external hotkey number to standardized hotkey event num */ -static int hotkey_get_internal_event(int event, struct acpi_hotkey_list *list) -{ - struct list_head *entries; - int val = -1; - - - list_for_each(entries, list->entries) { - union acpi_hotkey *key = - container_of(entries, union acpi_hotkey, entries); - if (key->link.hotkey_type == ACPI_HOTKEY_EVENT - && key->event_hotkey.external_hotkey_num == event) { - val = key->link.hotkey_standard_num; - break; - } - } - - return val; -} - -static void -acpi_hotkey_notify_handler(acpi_handle handle, u32 event, void *data) -{ - struct acpi_device *device = NULL; - u32 internal_event; - - - if (acpi_bus_get_device(handle, &device)) - return; - - internal_event = hotkey_get_internal_event(event, &global_hotkey_list); - acpi_bus_generate_event(device, internal_event, 0); - - return; -} - -/* Need to invent automatically hotkey add method */ -static int auto_hotkey_add(struct acpi_device *device) -{ - /* Implement me */ - return 0; -} - -/* Need to invent automatically hotkey remove method */ -static int auto_hotkey_remove(struct acpi_device *device, int type) -{ - /* Implement me */ - return 0; -} - -/* Create a proc file for each polling method */ -static int create_polling_proc(union acpi_hotkey *device) -{ - struct proc_dir_entry *proc; - char proc_name[80]; - mode_t mode; - - mode = S_IFREG | S_IRUGO | S_IWUGO; - - sprintf(proc_name, "%d", device->link.hotkey_standard_num); - /* - strcat(proc_name, device->poll_hotkey.poll_method); - */ - proc = create_proc_entry(proc_name, mode, hotkey_proc_dir); - - if (!proc) { - return -ENODEV; - } else { - proc->proc_fops = &hotkey_polling_fops; - proc->owner = THIS_MODULE; - proc->data = device; - proc->uid = 0; - proc->gid = 0; - device->poll_hotkey.proc = proc; - } - return 0; -} - -static int hotkey_add(union acpi_hotkey *device) -{ - int status = 0; - struct acpi_device *dev = NULL; - - - if (device->link.hotkey_type == ACPI_HOTKEY_EVENT) { - acpi_bus_get_device(device->event_hotkey.bus_handle, &dev); - status = acpi_install_notify_handler(dev->handle, - ACPI_DEVICE_NOTIFY, - acpi_hotkey_notify_handler, - dev); - } else /* Add polling hotkey */ - create_polling_proc(device); - - global_hotkey_list.count++; - - list_add_tail(&device->link.entries, global_hotkey_list.entries); - - return status; -} - -static int hotkey_remove(union acpi_hotkey *device) -{ - struct list_head *entries, *next; - - - list_for_each_safe(entries, next, global_hotkey_list.entries) { - union acpi_hotkey *key = - container_of(entries, union acpi_hotkey, entries); - if (key->link.hotkey_standard_num == - device->link.hotkey_standard_num) { - list_del(&key->link.entries); - free_hotkey_device(key); - global_hotkey_list.count--; - break; - } - } - kfree(device); - return 0; -} - -static int hotkey_update(union acpi_hotkey *key) -{ - struct list_head *entries; - - - list_for_each(entries, global_hotkey_list.entries) { - union acpi_hotkey *tmp = - container_of(entries, union acpi_hotkey, entries); - if (tmp->link.hotkey_standard_num == - key->link.hotkey_standard_num) { - if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) { - free_hotkey_buffer(tmp); - tmp->event_hotkey.bus_handle = - key->event_hotkey.bus_handle; - tmp->event_hotkey.external_hotkey_num = - key->event_hotkey.external_hotkey_num; - tmp->event_hotkey.action_handle = - key->event_hotkey.action_handle; - tmp->event_hotkey.action_method = - key->event_hotkey.action_method; - kfree(key); - } else { - /* - char proc_name[80]; - - sprintf(proc_name, "%d", tmp->link.hotkey_standard_num); - strcat(proc_name, tmp->poll_hotkey.poll_method); - remove_proc_entry(proc_name,hotkey_proc_dir); - */ - free_poll_hotkey_buffer(tmp); - tmp->poll_hotkey.poll_handle = - key->poll_hotkey.poll_handle; - tmp->poll_hotkey.poll_method = - key->poll_hotkey.poll_method; - tmp->poll_hotkey.action_handle = - key->poll_hotkey.action_handle; - tmp->poll_hotkey.action_method = - key->poll_hotkey.action_method; - tmp->poll_hotkey.poll_result = - key->poll_hotkey.poll_result; - /* - create_polling_proc(tmp); - */ - kfree(key); - } - return 0; - break; - } - } - - return -ENODEV; -} - -static void free_hotkey_device(union acpi_hotkey *key) -{ - struct acpi_device *dev; - - - if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) { - acpi_bus_get_device(key->event_hotkey.bus_handle, &dev); - if (dev->handle) - acpi_remove_notify_handler(dev->handle, - ACPI_DEVICE_NOTIFY, - acpi_hotkey_notify_handler); - free_hotkey_buffer(key); - } else { - char proc_name[80]; - - sprintf(proc_name, "%d", key->link.hotkey_standard_num); - /* - strcat(proc_name, key->poll_hotkey.poll_method); - */ - remove_proc_entry(proc_name, hotkey_proc_dir); - free_poll_hotkey_buffer(key); - } - kfree(key); - return; -} - -static void free_hotkey_buffer(union acpi_hotkey *key) -{ - /* key would never be null, action method could be */ - kfree(key->event_hotkey.action_method); -} - -static void free_poll_hotkey_buffer(union acpi_hotkey *key) -{ - /* key would never be null, others could be*/ - kfree(key->poll_hotkey.action_method); - kfree(key->poll_hotkey.poll_method); - kfree(key->poll_hotkey.poll_result); -} -static int -init_hotkey_device(union acpi_hotkey *key, char **config_entry, - int std_num, int external_num) -{ - acpi_handle tmp_handle; - acpi_status status = AE_OK; - - if (std_num < 0 || IS_POLL(std_num) || !key) - goto do_fail; - - if (!config_entry[bus_handle] || !config_entry[action_handle] - || !config_entry[method]) - goto do_fail; - - key->link.hotkey_type = ACPI_HOTKEY_EVENT; - key->link.hotkey_standard_num = std_num; - key->event_hotkey.flag = 0; - key->event_hotkey.action_method = config_entry[method]; - - status = acpi_get_handle(NULL, config_entry[bus_handle], - &(key->event_hotkey.bus_handle)); - if (ACPI_FAILURE(status)) - goto do_fail_zero; - key->event_hotkey.external_hotkey_num = external_num; - status = acpi_get_handle(NULL, config_entry[action_handle], - &(key->event_hotkey.action_handle)); - if (ACPI_FAILURE(status)) - goto do_fail_zero; - status = acpi_get_handle(key->event_hotkey.action_handle, - config_entry[method], &tmp_handle); - if (ACPI_FAILURE(status)) - goto do_fail_zero; - return AE_OK; -do_fail_zero: - key->event_hotkey.action_method = NULL; -do_fail: - return -ENODEV; -} - -static int -init_poll_hotkey_device(union acpi_hotkey *key, char **config_entry, - int std_num) -{ - acpi_status status = AE_OK; - acpi_handle tmp_handle; - - if (std_num < 0 || IS_EVENT(std_num) || !key) - goto do_fail; - if (!config_entry[bus_handle] ||!config_entry[bus_method] || - !config_entry[action_handle] || !config_entry[method]) - goto do_fail; - - key->link.hotkey_type = ACPI_HOTKEY_POLLING; - key->link.hotkey_standard_num = std_num; - key->poll_hotkey.flag = 0; - key->poll_hotkey.poll_method = config_entry[bus_method]; - key->poll_hotkey.action_method = config_entry[method]; - - status = acpi_get_handle(NULL, config_entry[bus_handle], - &(key->poll_hotkey.poll_handle)); - if (ACPI_FAILURE(status)) - goto do_fail_zero; - status = acpi_get_handle(key->poll_hotkey.poll_handle, - config_entry[bus_method], &tmp_handle); - if (ACPI_FAILURE(status)) - goto do_fail_zero; - status = - acpi_get_handle(NULL, config_entry[action_handle], - &(key->poll_hotkey.action_handle)); - if (ACPI_FAILURE(status)) - goto do_fail_zero; - status = acpi_get_handle(key->poll_hotkey.action_handle, - config_entry[method], &tmp_handle); - if (ACPI_FAILURE(status)) - goto do_fail_zero; - key->poll_hotkey.poll_result = - kmalloc(sizeof(union acpi_object), GFP_KERNEL); - if (!key->poll_hotkey.poll_result) - goto do_fail_zero; - return AE_OK; - -do_fail_zero: - key->poll_hotkey.poll_method = NULL; - key->poll_hotkey.action_method = NULL; -do_fail: - return -ENODEV; -} - -static int hotkey_open_config(struct inode *inode, struct file *file) -{ - return (single_open - (file, hotkey_config_seq_show, PDE(inode)->data)); -} - -static int hotkey_poll_open_config(struct inode *inode, struct file *file) -{ - return (single_open - (file, hotkey_poll_config_seq_show, PDE(inode)->data)); -} - -static int hotkey_config_seq_show(struct seq_file *seq, void *offset) -{ - struct acpi_hotkey_list *hotkey_list = &global_hotkey_list; - struct list_head *entries; - char bus_name[ACPI_PATHNAME_MAX] = { 0 }; - char action_name[ACPI_PATHNAME_MAX] = { 0 }; - struct acpi_buffer bus = { ACPI_PATHNAME_MAX, bus_name }; - struct acpi_buffer act = { ACPI_PATHNAME_MAX, action_name }; - - - list_for_each(entries, hotkey_list->entries) { - union acpi_hotkey *key = - container_of(entries, union acpi_hotkey, entries); - if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) { - acpi_get_name(key->event_hotkey.bus_handle, - ACPI_NAME_TYPE_MAX, &bus); - acpi_get_name(key->event_hotkey.action_handle, - ACPI_NAME_TYPE_MAX, &act); - seq_printf(seq, "%s:%s:%s:%d:%d\n", bus_name, - action_name, - key->event_hotkey.action_method, - key->link.hotkey_standard_num, - key->event_hotkey.external_hotkey_num); - } - } - seq_puts(seq, "\n"); - return 0; -} - -static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset) -{ - struct acpi_hotkey_list *hotkey_list = &global_hotkey_list; - struct list_head *entries; - char bus_name[ACPI_PATHNAME_MAX] = { 0 }; - char action_name[ACPI_PATHNAME_MAX] = { 0 }; - struct acpi_buffer bus = { ACPI_PATHNAME_MAX, bus_name }; - struct acpi_buffer act = { ACPI_PATHNAME_MAX, action_name }; - - - list_for_each(entries, hotkey_list->entries) { - union acpi_hotkey *key = - container_of(entries, union acpi_hotkey, entries); - if (key->link.hotkey_type == ACPI_HOTKEY_POLLING) { - acpi_get_name(key->poll_hotkey.poll_handle, - ACPI_NAME_TYPE_MAX, &bus); - acpi_get_name(key->poll_hotkey.action_handle, - ACPI_NAME_TYPE_MAX, &act); - seq_printf(seq, "%s:%s:%s:%s:%d\n", bus_name, - key->poll_hotkey.poll_method, - action_name, - key->poll_hotkey.action_method, - key->link.hotkey_standard_num); - } - } - seq_puts(seq, "\n"); - return 0; -} - -static int -get_parms(char *config_record, int *cmd, char **config_entry, - int *internal_event_num, int *external_event_num) -{ -/* the format of *config_record = - * "1:\d+:*" : "cmd:internal_event_num" - * "\d+:\w+:\w+:\w+:\w+:\d+:\d+" : - * "cmd:bus_handle:bus_method:action_handle:method:internal_event_num:external_event_num" - */ - char *tmp, *tmp1, count; - int i; - - sscanf(config_record, "%d", cmd); - if (*cmd == 1) { - if (sscanf(config_record, "%d:%d", cmd, internal_event_num) != - 2) - goto do_fail; - else - return (6); - } - tmp = strchr(config_record, ':'); - if (!tmp) - goto do_fail; - tmp++; - for (i = 0; i < LAST_CONF_ENTRY; i++) { - tmp1 = strchr(tmp, ':'); - if (!tmp1) { - goto do_fail; - } - count = tmp1 - tmp; - config_entry[i] = kzalloc(count + 1, GFP_KERNEL); - if (!config_entry[i]) - goto handle_failure; - strncpy(config_entry[i], tmp, count); - tmp = tmp1 + 1; - } - if (sscanf(tmp, "%d:%d", internal_event_num, external_event_num) <= 0) - goto handle_failure; - if (!IS_OTHERS(*internal_event_num)) { - return 6; - } -handle_failure: - while (i-- > 0) - kfree(config_entry[i]); -do_fail: - return -1; -} - -/* count is length for one input record */ -static ssize_t hotkey_write_config(struct file *file, - const char __user * buffer, - size_t count, loff_t * data) -{ - char *config_record = NULL; - char *config_entry[LAST_CONF_ENTRY]; - int cmd, internal_event_num, external_event_num; - int ret = 0; - union acpi_hotkey *key = kzalloc(sizeof(union acpi_hotkey), GFP_KERNEL); - - if (!key) - return -ENOMEM; - - config_record = kzalloc(count + 1, GFP_KERNEL); - if (!config_record) { - kfree(key); - return -ENOMEM; - } - - if (copy_from_user(config_record, buffer, count)) { - kfree(config_record); - kfree(key); - printk(KERN_ERR PREFIX "Invalid data\n"); - return -EINVAL; - } - ret = get_parms(config_record, &cmd, config_entry, - &internal_event_num, &external_event_num); - kfree(config_record); - if (ret != 6) { - printk(KERN_ERR PREFIX "Invalid data format ret=%d\n", ret); - return -EINVAL; - } - - if (cmd == 1) { - union acpi_hotkey *tmp = NULL; - tmp = get_hotkey_by_event(&global_hotkey_list, - internal_event_num); - if (!tmp) - printk(KERN_ERR PREFIX "Invalid key\n"); - else - memcpy(key, tmp, sizeof(union acpi_hotkey)); - goto cont_cmd; - } - if (IS_EVENT(internal_event_num)) { - if (init_hotkey_device(key, config_entry, - internal_event_num, external_event_num)) - goto init_hotkey_fail; - } else { - if (init_poll_hotkey_device(key, config_entry, - internal_event_num)) - goto init_poll_hotkey_fail; - } -cont_cmd: - switch (cmd) { - case 0: - if (get_hotkey_by_event(&global_hotkey_list, - key->link.hotkey_standard_num)) - goto fail_out; - else - hotkey_add(key); - break; - case 1: - hotkey_remove(key); - break; - case 2: - /* key is kfree()ed if matched*/ - if (hotkey_update(key)) - goto fail_out; - break; - default: - goto fail_out; - break; - } - return count; - -init_poll_hotkey_fail: /* failed init_poll_hotkey_device */ - kfree(config_entry[bus_method]); - config_entry[bus_method] = NULL; -init_hotkey_fail: /* failed init_hotkey_device */ - kfree(config_entry[method]); -fail_out: - kfree(config_entry[bus_handle]); - kfree(config_entry[action_handle]); - /* No double free since elements =NULL for error cases */ - if (IS_EVENT(internal_event_num)) { - if (config_entry[bus_method]) - kfree(config_entry[bus_method]); - free_hotkey_buffer(key); /* frees [method] */ - } else - free_poll_hotkey_buffer(key); /* frees [bus_method]+[method] */ - kfree(key); - printk(KERN_ERR PREFIX "invalid key\n"); - return -EINVAL; -} - -/* - * This function evaluates an ACPI method, given an int as parameter, the - * method is searched within the scope of the handle, can be NULL. The output - * of the method is written is output, which can also be NULL - * - * returns 1 if write is successful, 0 else. - */ -static int write_acpi_int(acpi_handle handle, const char *method, int val, - struct acpi_buffer *output) -{ - struct acpi_object_list params; /* list of input parameters (an int here) */ - union acpi_object in_obj; /* the only param we use */ - 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); -} - -static int read_acpi_int(acpi_handle handle, const char *method, - union acpi_object *val) -{ - struct acpi_buffer output; - union acpi_object out_obj; - acpi_status status; - - output.length = sizeof(out_obj); - output.pointer = &out_obj; - - status = acpi_evaluate_object(handle, (char *)method, NULL, &output); - if (val) { - val->integer.value = out_obj.integer.value; - val->type = out_obj.type; - } else - printk(KERN_ERR PREFIX "null val pointer\n"); - return ((status == AE_OK) - && (out_obj.type == ACPI_TYPE_INTEGER)); -} - -static union acpi_hotkey *get_hotkey_by_event(struct - acpi_hotkey_list - *hotkey_list, int event) -{ - struct list_head *entries; - - list_for_each(entries, hotkey_list->entries) { - union acpi_hotkey *key = - container_of(entries, union acpi_hotkey, entries); - if (key->link.hotkey_standard_num == event) { - return (key); - } - } - return (NULL); -} - -/* - * user call AML method interface: - * Call convention: - * echo "event_num: arg type : value" - * example: echo "1:1:30" > /proc/acpi/action - * Just support 1 integer arg passing to AML method - */ - -static ssize_t hotkey_execute_aml_method(struct file *file, - const char __user * buffer, - size_t count, loff_t * data) -{ - struct acpi_hotkey_list *hotkey_list = &global_hotkey_list; - char *arg; - int event, method_type, type, value; - union acpi_hotkey *key; - - - arg = kzalloc(count + 1, GFP_KERNEL); - if (!arg) - return -ENOMEM; - - if (copy_from_user(arg, buffer, count)) { - kfree(arg); - printk(KERN_ERR PREFIX "Invalid argument 2\n"); - return -EINVAL; - } - - if (sscanf(arg, "%d:%d:%d:%d", &event, &method_type, &type, &value) != - 4) { - kfree(arg); - printk(KERN_ERR PREFIX "Invalid argument 3\n"); - return -EINVAL; - } - kfree(arg); - if (type == ACPI_TYPE_INTEGER) { - key = get_hotkey_by_event(hotkey_list, event); - if (!key) - goto do_fail; - if (IS_EVENT(event)) - write_acpi_int(key->event_hotkey.action_handle, - key->event_hotkey.action_method, value, - NULL); - else if (IS_POLL(event)) { - if (method_type == POLL_METHOD) - read_acpi_int(key->poll_hotkey.poll_handle, - key->poll_hotkey.poll_method, - key->poll_hotkey.poll_result); - else if (method_type == ACTION_METHOD) - write_acpi_int(key->poll_hotkey.action_handle, - key->poll_hotkey.action_method, - value, NULL); - else - goto do_fail; - - } - } else { - printk(KERN_WARNING "Not supported\n"); - return -EINVAL; - } - return count; - do_fail: - return -EINVAL; - -} - -static int __init hotkey_init(void) -{ - int result; - mode_t mode = S_IFREG | S_IRUGO | S_IWUGO; - - - if (acpi_disabled) - return -ENODEV; - - if (acpi_specific_hotkey_enabled) { - printk("Using specific hotkey driver\n"); - return -ENODEV; - } - - hotkey_proc_dir = proc_mkdir(HOTKEY_PROC, acpi_root_dir); - if (!hotkey_proc_dir) { - return (-ENODEV); - } - hotkey_proc_dir->owner = THIS_MODULE; - - hotkey_config = - create_proc_entry(HOTKEY_EV_CONFIG, mode, hotkey_proc_dir); - if (!hotkey_config) { - goto do_fail1; - } else { - hotkey_config->proc_fops = &hotkey_config_fops; - hotkey_config->data = &global_hotkey_list; - hotkey_config->owner = THIS_MODULE; - hotkey_config->uid = 0; - hotkey_config->gid = 0; - } - - hotkey_poll_config = - create_proc_entry(HOTKEY_PL_CONFIG, mode, hotkey_proc_dir); - if (!hotkey_poll_config) { - goto do_fail2; - } else { - hotkey_poll_config->proc_fops = &hotkey_poll_config_fops; - hotkey_poll_config->data = &global_hotkey_list; - hotkey_poll_config->owner = THIS_MODULE; - hotkey_poll_config->uid = 0; - hotkey_poll_config->gid = 0; - } - - hotkey_action = create_proc_entry(HOTKEY_ACTION, mode, hotkey_proc_dir); - if (!hotkey_action) { - goto do_fail3; - } else { - hotkey_action->proc_fops = &hotkey_action_fops; - hotkey_action->owner = THIS_MODULE; - hotkey_action->uid = 0; - hotkey_action->gid = 0; - } - - hotkey_info = create_proc_entry(HOTKEY_INFO, mode, hotkey_proc_dir); - if (!hotkey_info) { - goto do_fail4; - } else { - hotkey_info->proc_fops = &hotkey_info_fops; - hotkey_info->owner = THIS_MODULE; - hotkey_info->uid = 0; - hotkey_info->gid = 0; - } - - result = acpi_bus_register_driver(&hotkey_driver); - if (result < 0) - goto do_fail5; - global_hotkey_list.count = 0; - global_hotkey_list.entries = &hotkey_entries; - - INIT_LIST_HEAD(&hotkey_entries); - - return (0); - - do_fail5: - remove_proc_entry(HOTKEY_INFO, hotkey_proc_dir); - do_fail4: - remove_proc_entry(HOTKEY_ACTION, hotkey_proc_dir); - do_fail3: - remove_proc_entry(HOTKEY_PL_CONFIG, hotkey_proc_dir); - do_fail2: - remove_proc_entry(HOTKEY_EV_CONFIG, hotkey_proc_dir); - do_fail1: - remove_proc_entry(HOTKEY_PROC, acpi_root_dir); - return (-ENODEV); -} - -static void __exit hotkey_exit(void) -{ - struct list_head *entries, *next; - - - list_for_each_safe(entries, next, global_hotkey_list.entries) { - union acpi_hotkey *key = - container_of(entries, union acpi_hotkey, entries); - - acpi_os_wait_events_complete(NULL); - list_del(&key->link.entries); - global_hotkey_list.count--; - free_hotkey_device(key); - } - acpi_bus_unregister_driver(&hotkey_driver); - remove_proc_entry(HOTKEY_EV_CONFIG, hotkey_proc_dir); - remove_proc_entry(HOTKEY_PL_CONFIG, hotkey_proc_dir); - remove_proc_entry(HOTKEY_ACTION, hotkey_proc_dir); - remove_proc_entry(HOTKEY_INFO, hotkey_proc_dir); - remove_proc_entry(HOTKEY_PROC, acpi_root_dir); - return; -} - -module_init(hotkey_init); -module_exit(hotkey_exit); diff --git a/drivers/acpi/i2c_ec.c b/drivers/acpi/i2c_ec.c index 76ec8b63e69..acab4a48189 100644 --- a/drivers/acpi/i2c_ec.c +++ b/drivers/acpi/i2c_ec.c @@ -27,18 +27,17 @@ #define ACPI_EC_HC_COMPONENT 0x00080000 #define ACPI_EC_HC_CLASS "ec_hc_smbus" #define ACPI_EC_HC_HID "ACPI0001" -#define ACPI_EC_HC_DRIVER_NAME "ACPI EC HC smbus driver" #define ACPI_EC_HC_DEVICE_NAME "EC HC smbus" #define _COMPONENT ACPI_EC_HC_COMPONENT -ACPI_MODULE_NAME("acpi_smbus") +ACPI_MODULE_NAME("i2c_ec"); static int acpi_ec_hc_add(struct acpi_device *device); static int acpi_ec_hc_remove(struct acpi_device *device, int type); static struct acpi_driver acpi_ec_hc_driver = { - .name = ACPI_EC_HC_DRIVER_NAME, + .name = "i2c_ec", .class = ACPI_EC_HC_CLASS, .ids = ACPI_EC_HC_HID, .ops = { diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index c6144ca6663..1a0ed3dc409 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -496,6 +496,10 @@ static int ibm_acpi_driver_init(void) printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION); printk(IBM_INFO "%s\n", IBM_URL); + if (ibm_thinkpad_ec_found) + printk(IBM_INFO "ThinkPad EC firmware %s\n", + ibm_thinkpad_ec_found); + return 0; } @@ -2617,7 +2621,7 @@ static void __init ibm_handle_init(char *name, ibm_handle_init(#object, &object##_handle, *object##_parent, \ object##_paths, ARRAY_SIZE(object##_paths), &object##_path) -static int set_ibm_param(const char *val, struct kernel_param *kp) +static int __init set_ibm_param(const char *val, struct kernel_param *kp) { unsigned int i; @@ -2659,7 +2663,8 @@ static void acpi_ibm_exit(void) for (i = ARRAY_SIZE(ibms) - 1; i >= 0; i--) ibm_exit(&ibms[i]); - remove_proc_entry(IBM_DIR, acpi_root_dir); + if (proc_dir) + remove_proc_entry(IBM_DIR, acpi_root_dir); if (ibm_thinkpad_ec_found) kfree(ibm_thinkpad_ec_found); @@ -2696,11 +2701,6 @@ static int __init acpi_ibm_init(void) if (acpi_disabled) return -ENODEV; - if (!acpi_specific_hotkey_enabled) { - printk(IBM_ERR "using generic hotkey driver\n"); - return -ENODEV; - } - /* ec is required because many other handles are relative to it */ IBM_HANDLE_INIT(ec); if (!ec_handle) { @@ -2710,9 +2710,6 @@ static int __init acpi_ibm_init(void) /* Models with newer firmware report the EC in DMI */ ibm_thinkpad_ec_found = check_dmi_for_ec(); - if (ibm_thinkpad_ec_found) - printk(IBM_INFO "ThinkPad EC firmware %s\n", - ibm_thinkpad_ec_found); /* these handles are not required */ IBM_HANDLE_INIT(vid); @@ -2742,6 +2739,7 @@ static int __init acpi_ibm_init(void) proc_dir = proc_mkdir(IBM_DIR, acpi_root_dir); if (!proc_dir) { printk(IBM_ERR "unable to create proc dir %s", IBM_DIR); + acpi_ibm_exit(); return -ENODEV; } proc_dir->owner = THIS_MODULE; diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 4a9faff4c01..8fcd6a15517 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -33,7 +33,7 @@ #define ACPI_NUMA 0x80000000 #define _COMPONENT ACPI_NUMA -ACPI_MODULE_NAME("numa") +ACPI_MODULE_NAME("numa"); static nodemask_t nodes_found_map = NODE_MASK_NONE; #define PXM_INVAL -1 @@ -45,12 +45,6 @@ int __cpuinitdata pxm_to_node_map[MAX_PXM_DOMAINS] int __cpuinitdata node_to_pxm_map[MAX_NUMNODES] = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL }; -extern int __init acpi_table_parse_madt_family(char *id, - unsigned long madt_size, - int entry_id, - acpi_madt_entry_handler handler, - unsigned int max_entries); - int __cpuinit pxm_to_node(int pxm) { if (pxm < 0) @@ -208,9 +202,9 @@ static int __init acpi_parse_srat(struct acpi_table_header *table) int __init acpi_table_parse_srat(enum acpi_srat_type id, - acpi_madt_entry_handler handler, unsigned int max_entries) + acpi_table_entry_handler handler, unsigned int max_entries) { - return acpi_table_parse_madt_family(ACPI_SIG_SRAT, + return acpi_table_parse_entries(ACPI_SIG_SRAT, sizeof(struct acpi_table_srat), id, handler, max_entries); } @@ -220,9 +214,7 @@ int __init acpi_numa_init(void) int result; /* SRAT: Static Resource Affinity Table */ - result = acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat); - - if (result > 0) { + if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) { result = acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY, acpi_parse_processor_affinity, NR_CPUS); @@ -230,7 +222,7 @@ int __init acpi_numa_init(void) } /* SLIT: System Locality Information Table */ - result = acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit); + acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit); acpi_numa_arch_fixup(); return 0; diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 0f6f3bcbc8e..971eca4864f 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -46,7 +46,7 @@ #include <linux/efi.h> #define _COMPONENT ACPI_OS_SERVICES -ACPI_MODULE_NAME("osl") +ACPI_MODULE_NAME("osl"); #define PREFIX "ACPI: " struct acpi_os_dpc { acpi_osd_exec_callback function; @@ -68,9 +68,6 @@ EXPORT_SYMBOL(acpi_in_debugger); extern char line_buf[80]; #endif /*ENABLE_DEBUGGER */ -int acpi_specific_hotkey_enabled = TRUE; -EXPORT_SYMBOL(acpi_specific_hotkey_enabled); - static unsigned int acpi_irq_irq; static acpi_osd_handler acpi_irq_handler; static void *acpi_irq_context; @@ -205,7 +202,7 @@ void __iomem *acpi_os_map_memory(acpi_physical_address phys, acpi_size size) { if (phys > ULONG_MAX) { printk(KERN_ERR PREFIX "Cannot map memory that high\n"); - return 0; + return NULL; } if (acpi_gbl_permanent_mmap) /* @@ -890,26 +887,6 @@ u32 acpi_os_get_line(char *buffer) } #endif /* ACPI_FUTURE_USAGE */ -/* Assumes no unreadable holes inbetween */ -u8 acpi_os_readable(void *ptr, acpi_size len) -{ -#if defined(__i386__) || defined(__x86_64__) - char tmp; - return !__get_user(tmp, (char __user *)ptr) - && !__get_user(tmp, (char __user *)ptr + len - 1); -#endif - return 1; -} - -#ifdef ACPI_FUTURE_USAGE -u8 acpi_os_writable(void *ptr, acpi_size len) -{ - /* could do dummy write (racy) or a kernel page table lookup. - The later may be difficult at early boot when kmap doesn't work yet. */ - return 1; -} -#endif - acpi_status acpi_os_signal(u32 function, void *info) { switch (function) { @@ -1012,14 +989,6 @@ static int __init acpi_wake_gpes_always_on_setup(char *str) __setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup); -static int __init acpi_hotkey_setup(char *str) -{ - acpi_specific_hotkey_enabled = FALSE; - return 1; -} - -__setup("acpi_generic_hotkey", acpi_hotkey_setup); - /* * max_cstate is defined in the base kernel so modules can * change it w/o depending on the state of the processor module. diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c index 55f57a61c55..028969370bb 100644 --- a/drivers/acpi/pci_bind.c +++ b/drivers/acpi/pci_bind.c @@ -36,7 +36,7 @@ #include <acpi/acpi_drivers.h> #define _COMPONENT ACPI_PCI_COMPONENT -ACPI_MODULE_NAME("pci_bind") +ACPI_MODULE_NAME("pci_bind"); struct acpi_pci_data { struct acpi_pci_id id; diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index fe7d007833a..dd3186abe07 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -38,7 +38,7 @@ #include <acpi/acpi_drivers.h> #define _COMPONENT ACPI_PCI_COMPONENT -ACPI_MODULE_NAME("pci_irq") +ACPI_MODULE_NAME("pci_irq"); static struct acpi_prt_list acpi_prt; static DEFINE_SPINLOCK(acpi_prt_lock); diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 0f683c8c6fb..acc59477137 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -44,10 +44,9 @@ #include <acpi/acpi_drivers.h> #define _COMPONENT ACPI_PCI_COMPONENT -ACPI_MODULE_NAME("pci_link") +ACPI_MODULE_NAME("pci_link"); #define ACPI_PCI_LINK_CLASS "pci_irq_routing" #define ACPI_PCI_LINK_HID "PNP0C0F" -#define ACPI_PCI_LINK_DRIVER_NAME "ACPI PCI Interrupt Link Driver" #define ACPI_PCI_LINK_DEVICE_NAME "PCI Interrupt Link" #define ACPI_PCI_LINK_FILE_INFO "info" #define ACPI_PCI_LINK_FILE_STATUS "state" @@ -56,7 +55,7 @@ static int acpi_pci_link_add(struct acpi_device *device); static int acpi_pci_link_remove(struct acpi_device *device, int type); static struct acpi_driver acpi_pci_link_driver = { - .name = ACPI_PCI_LINK_DRIVER_NAME, + .name = "pci_link", .class = ACPI_PCI_LINK_CLASS, .ids = ACPI_PCI_LINK_HID, .ops = { diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 4ecf701687e..ad4145a3778 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -36,17 +36,16 @@ #include <acpi/acpi_drivers.h> #define _COMPONENT ACPI_PCI_COMPONENT -ACPI_MODULE_NAME("pci_root") +ACPI_MODULE_NAME("pci_root"); #define ACPI_PCI_ROOT_CLASS "pci_bridge" #define ACPI_PCI_ROOT_HID "PNP0A03" -#define ACPI_PCI_ROOT_DRIVER_NAME "ACPI PCI Root Bridge Driver" #define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge" static int acpi_pci_root_add(struct acpi_device *device); static int acpi_pci_root_remove(struct acpi_device *device, int type); static int acpi_pci_root_start(struct acpi_device *device); static struct acpi_driver acpi_pci_root_driver = { - .name = ACPI_PCI_ROOT_DRIVER_NAME, + .name = "pci_root", .class = ACPI_PCI_ROOT_CLASS, .ids = ACPI_PCI_ROOT_HID, .ops = { diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 0ba7dfbbb2e..1ef338545df 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -45,10 +45,9 @@ #include <acpi/acpi_drivers.h> #define _COMPONENT ACPI_POWER_COMPONENT -ACPI_MODULE_NAME("acpi_power") +ACPI_MODULE_NAME("power"); #define ACPI_POWER_COMPONENT 0x00800000 #define ACPI_POWER_CLASS "power_resource" -#define ACPI_POWER_DRIVER_NAME "ACPI Power Resource Driver" #define ACPI_POWER_DEVICE_NAME "Power Resource" #define ACPI_POWER_FILE_INFO "info" #define ACPI_POWER_FILE_STATUS "state" @@ -57,25 +56,33 @@ ACPI_MODULE_NAME("acpi_power") #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF static int acpi_power_add(struct acpi_device *device); static int acpi_power_remove(struct acpi_device *device, int type); +static int acpi_power_resume(struct acpi_device *device); static int acpi_power_open_fs(struct inode *inode, struct file *file); static struct acpi_driver acpi_power_driver = { - .name = ACPI_POWER_DRIVER_NAME, + .name = "power", .class = ACPI_POWER_CLASS, .ids = ACPI_POWER_HID, .ops = { .add = acpi_power_add, .remove = acpi_power_remove, + .resume = acpi_power_resume, }, }; +struct acpi_power_reference { + struct list_head node; + struct acpi_device *device; +}; + struct acpi_power_resource { struct acpi_device * device; acpi_bus_id name; u32 system_level; u32 order; int state; - int references; + struct mutex resource_lock; + struct list_head reference; }; static struct list_head acpi_power_resource_list; @@ -171,22 +178,47 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) return result; } -static int acpi_power_on(acpi_handle handle) +static int acpi_power_on(acpi_handle handle, struct acpi_device *dev) { int result = 0; + int found = 0; acpi_status status = AE_OK; - struct acpi_device *device = NULL; struct acpi_power_resource *resource = NULL; + struct list_head *node, *next; + struct acpi_power_reference *ref; result = acpi_power_get_context(handle, &resource); if (result) return result; - resource->references++; + mutex_lock(&resource->resource_lock); + list_for_each_safe(node, next, &resource->reference) { + ref = container_of(node, struct acpi_power_reference, node); + if (dev->handle == ref->device->handle) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] already referenced by resource [%s]\n", + dev->pnp.bus_id, resource->name)); + found = 1; + break; + } + } + + if (!found) { + ref = kmalloc(sizeof (struct acpi_power_reference), + irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL); + if (!ref) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "kmalloc() failed\n")); + mutex_unlock(&resource->resource_lock); + return -ENOMEM; + } + list_add_tail(&ref->node, &resource->reference); + ref->device = dev; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] added to resource [%s] references\n", + dev->pnp.bus_id, resource->name)); + } + mutex_unlock(&resource->resource_lock); - if ((resource->references > 1) - || (resource->state == ACPI_POWER_RESOURCE_STATE_ON)) { + if (resource->state == ACPI_POWER_RESOURCE_STATE_ON) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already on\n", resource->name)); return 0; @@ -203,38 +235,49 @@ static int acpi_power_on(acpi_handle handle) return -ENOEXEC; /* Update the power resource's _device_ power state */ - device = resource->device; resource->device->power.state = ACPI_STATE_D0; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned on\n", resource->name)); - return 0; } -static int acpi_power_off_device(acpi_handle handle) +static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev) { int result = 0; acpi_status status = AE_OK; struct acpi_power_resource *resource = NULL; + struct list_head *node, *next; + struct acpi_power_reference *ref; + result = acpi_power_get_context(handle, &resource); if (result) return result; - if (resource->references) - resource->references--; + mutex_lock(&resource->resource_lock); + list_for_each_safe(node, next, &resource->reference) { + ref = container_of(node, struct acpi_power_reference, node); + if (dev->handle == ref->device->handle) { + list_del(&ref->node); + kfree(ref); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] removed from resource [%s] references\n", + dev->pnp.bus_id, resource->name)); + break; + } + } - if (resource->references) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Resource [%s] is still in use, dereferencing\n", - resource->device->pnp.bus_id)); + if (!list_empty(&resource->reference)) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cannot turn resource [%s] off - resource is in use\n", + resource->name)); + mutex_unlock(&resource->resource_lock); return 0; } + mutex_unlock(&resource->resource_lock); if (resource->state == ACPI_POWER_RESOURCE_STATE_OFF) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already off\n", - resource->device->pnp.bus_id)); + resource->name)); return 0; } @@ -276,7 +319,7 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev) arg.integer.value = 1; /* Open power resource */ for (i = 0; i < dev->wakeup.resources.count; i++) { - ret = acpi_power_on(dev->wakeup.resources.handles[i]); + ret = acpi_power_on(dev->wakeup.resources.handles[i], dev); if (ret) { printk(KERN_ERR PREFIX "Transition power state\n"); dev->wakeup.flags.valid = 0; @@ -323,7 +366,7 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev) /* Close power resource */ for (i = 0; i < dev->wakeup.resources.count; i++) { - ret = acpi_power_off_device(dev->wakeup.resources.handles[i]); + ret = acpi_power_off_device(dev->wakeup.resources.handles[i], dev); if (ret) { printk(KERN_ERR PREFIX "Transition power state\n"); dev->wakeup.flags.valid = 0; @@ -407,16 +450,20 @@ int acpi_power_transition(struct acpi_device *device, int state) * (e.g. so the device doesn't lose power while transitioning). */ for (i = 0; i < tl->count; i++) { - result = acpi_power_on(tl->handles[i]); + result = acpi_power_on(tl->handles[i], device); if (result) goto end; } + if (device->power.state == state) { + goto end; + } + /* * Then we dereference all power resources used in the current list. */ for (i = 0; i < cl->count; i++) { - result = acpi_power_off_device(cl->handles[i]); + result = acpi_power_off_device(cl->handles[i], device); if (result) goto end; } @@ -439,7 +486,11 @@ static struct proc_dir_entry *acpi_power_dir; static int acpi_power_seq_show(struct seq_file *seq, void *offset) { + int count = 0; + int result = 0; struct acpi_power_resource *resource = NULL; + struct list_head *node, *next; + struct acpi_power_reference *ref; resource = seq->private; @@ -447,6 +498,10 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset) if (!resource) goto end; + result = acpi_power_get_state(resource); + if (result) + goto end; + seq_puts(seq, "state: "); switch (resource->state) { case ACPI_POWER_RESOURCE_STATE_ON: @@ -460,11 +515,18 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset) break; } + mutex_lock(&resource->resource_lock); + list_for_each_safe(node, next, &resource->reference) { + ref = container_of(node, struct acpi_power_reference, node); + count++; + } + mutex_unlock(&resource->resource_lock); + seq_printf(seq, "system level: S%d\n" "order: %d\n" "reference count: %d\n", resource->system_level, - resource->order, resource->references); + resource->order, count); end: return 0; @@ -537,6 +599,8 @@ static int acpi_power_add(struct acpi_device *device) return -ENOMEM; resource->device = device; + mutex_init(&resource->resource_lock); + INIT_LIST_HEAD(&resource->reference); strcpy(resource->name, device->pnp.bus_id); strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_POWER_CLASS); @@ -584,6 +648,7 @@ static int acpi_power_add(struct acpi_device *device) static int acpi_power_remove(struct acpi_device *device, int type) { struct acpi_power_resource *resource = NULL; + struct list_head *node, *next; if (!device || !acpi_driver_data(device)) @@ -593,11 +658,54 @@ static int acpi_power_remove(struct acpi_device *device, int type) acpi_power_remove_fs(device); + mutex_lock(&resource->resource_lock); + list_for_each_safe(node, next, &resource->reference) { + struct acpi_power_reference *ref = container_of(node, struct acpi_power_reference, node); + list_del(&ref->node); + kfree(ref); + } + mutex_unlock(&resource->resource_lock); + kfree(resource); return 0; } +static int acpi_power_resume(struct acpi_device *device) +{ + int result = 0; + struct acpi_power_resource *resource = NULL; + struct acpi_power_reference *ref; + + if (!device || !acpi_driver_data(device)) + return -EINVAL; + + resource = (struct acpi_power_resource *)acpi_driver_data(device); + + result = acpi_power_get_state(resource); + if (result) + return result; + + mutex_lock(&resource->resource_lock); + if ((resource->state == ACPI_POWER_RESOURCE_STATE_ON) && + list_empty(&resource->reference)) { + mutex_unlock(&resource->resource_lock); + result = acpi_power_off_device(device->handle, NULL); + return result; + } + + if ((resource->state == ACPI_POWER_RESOURCE_STATE_OFF) && + !list_empty(&resource->reference)) { + ref = container_of(resource->reference.next, struct acpi_power_reference, node); + mutex_unlock(&resource->resource_lock); + result = acpi_power_on(device->handle, ref->device); + return result; + } + + mutex_unlock(&resource->resource_lock); + return 0; +} + static int __init acpi_power_init(void) { int result = 0; diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 0079bc51082..99d1516d1e7 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -60,7 +60,6 @@ #define ACPI_PROCESSOR_COMPONENT 0x01000000 #define ACPI_PROCESSOR_CLASS "processor" -#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver" #define ACPI_PROCESSOR_DEVICE_NAME "Processor" #define ACPI_PROCESSOR_FILE_INFO "info" #define ACPI_PROCESSOR_FILE_THROTTLING "throttling" @@ -74,10 +73,10 @@ #define ACPI_STA_PRESENT 0x00000001 #define _COMPONENT ACPI_PROCESSOR_COMPONENT -ACPI_MODULE_NAME("acpi_processor") +ACPI_MODULE_NAME("processor_core"); - MODULE_AUTHOR("Paul Diefenbaugh"); -MODULE_DESCRIPTION(ACPI_PROCESSOR_DRIVER_NAME); +MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_DESCRIPTION("ACPI Processor Driver"); MODULE_LICENSE("GPL"); static int acpi_processor_add(struct acpi_device *device); @@ -89,7 +88,7 @@ static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu); static int acpi_processor_handle_eject(struct acpi_processor *pr); static struct acpi_driver acpi_processor_driver = { - .name = ACPI_PROCESSOR_DRIVER_NAME, + .name = "processor", .class = ACPI_PROCESSOR_CLASS, .ids = ACPI_PROCESSOR_HID, .ops = { @@ -404,7 +403,7 @@ static int map_lsapic_id(struct acpi_subtable_header *entry, if (lsapic->lapic_flags & ACPI_MADT_ENABLED) { /* First check against id */ if (lsapic->processor_id == acpi_id) { - *apic_id = lsapic->id; + *apic_id = (lsapic->id << 8) | lsapic->eid; return 1; /* Check against optional uid */ } else if (entry->length >= 16 && @@ -1005,7 +1004,7 @@ static int __init acpi_processor_init(void) #ifdef CONFIG_SMP if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_MADT, 0, (struct acpi_table_header **)&madt))) - madt = 0; + madt = NULL; #endif acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir); diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 8206fc1ecc5..60773005b8a 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -51,6 +51,14 @@ #include <asm/apic.h> #endif +/* + * Include the apic definitions for x86 to have the APIC timer related defines + * available also for UP (on SMP it gets magically included via linux/smp.h). + */ +#ifdef CONFIG_X86 +#include <asm/apic.h> +#endif + #include <asm/io.h> #include <asm/uaccess.h> @@ -59,9 +67,8 @@ #define ACPI_PROCESSOR_COMPONENT 0x01000000 #define ACPI_PROCESSOR_CLASS "processor" -#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver" #define _COMPONENT ACPI_PROCESSOR_COMPONENT -ACPI_MODULE_NAME("acpi_processor") +ACPI_MODULE_NAME("processor_idle"); #define ACPI_PROCESSOR_FILE_POWER "power" #define US_TO_PM_TIMER_TICKS(t) ((t * (PM_TIMER_FREQUENCY/1000)) / 1000) #define C2_OVERHEAD 4 /* 1us (3.579 ticks per us) */ diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 058f13cf3b7..2f2e7964226 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -44,10 +44,9 @@ #define ACPI_PROCESSOR_COMPONENT 0x01000000 #define ACPI_PROCESSOR_CLASS "processor" -#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver" #define ACPI_PROCESSOR_FILE_PERFORMANCE "performance" #define _COMPONENT ACPI_PROCESSOR_COMPONENT -ACPI_MODULE_NAME("acpi_processor") +ACPI_MODULE_NAME("processor_perflib"); static DEFINE_MUTEX(performance_mutex); diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index 40fecd67ad8..06e6f3fb882 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c @@ -41,9 +41,8 @@ #define ACPI_PROCESSOR_COMPONENT 0x01000000 #define ACPI_PROCESSOR_CLASS "processor" -#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver" #define _COMPONENT ACPI_PROCESSOR_COMPONENT -ACPI_MODULE_NAME("acpi_processor") +ACPI_MODULE_NAME("processor_thermal"); /* -------------------------------------------------------------------------- Limit Interface diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 89dff3639ab..b33486009f4 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -41,9 +41,8 @@ #define ACPI_PROCESSOR_COMPONENT 0x01000000 #define ACPI_PROCESSOR_CLASS "processor" -#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver" #define _COMPONENT ACPI_PROCESSOR_COMPONENT -ACPI_MODULE_NAME("acpi_processor") +ACPI_MODULE_NAME("processor_throttling"); /* -------------------------------------------------------------------------- Throttling Control diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index f58fc7447ab..59640d9a0ac 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -59,7 +59,6 @@ extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); #define ACPI_AC_CLASS "ac_adapter" #define ACPI_BATTERY_CLASS "battery" #define ACPI_SBS_HID "ACPI0002" -#define ACPI_SBS_DRIVER_NAME "ACPI Smart Battery System Driver" #define ACPI_SBS_DEVICE_NAME "Smart Battery System" #define ACPI_SBS_FILE_INFO "info" #define ACPI_SBS_FILE_STATE "state" @@ -78,7 +77,7 @@ extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); #define MAX_SBS_BAT 4 #define MAX_SMBUS_ERR 1 -ACPI_MODULE_NAME("acpi_sbs"); +ACPI_MODULE_NAME("sbs"); MODULE_AUTHOR("Rich Townsend"); MODULE_DESCRIPTION("Smart Battery System ACPI interface driver"); @@ -110,7 +109,7 @@ static void acpi_battery_smbus_err_handler(struct acpi_ec_smbus *smbus); static void acpi_sbs_update_queue(void *data); static struct acpi_driver acpi_sbs_driver = { - .name = ACPI_SBS_DRIVER_NAME, + .name = "sbs", .class = ACPI_SBS_CLASS, .ids = ACPI_SBS_HID, .ops = { @@ -1034,21 +1033,19 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset) } else { seq_printf(seq, "capacity state: ok\n"); } + + foo = (s16) battery->state.amperage * battery->info.ipscale; + if (battery->info.capacity_mode) { + foo = foo * battery->info.design_voltage / 1000; + } if (battery->state.amperage < 0) { seq_printf(seq, "charging state: discharging\n"); - foo = battery->state.remaining_capacity * cscale * 60 / - (battery->state.average_time_to_empty == 0 ? 1 : - battery->state.average_time_to_empty); - seq_printf(seq, "present rate: %i%s\n", - foo, battery->info.capacity_mode ? "0 mW" : " mA"); + seq_printf(seq, "present rate: %d %s\n", + -foo, battery->info.capacity_mode ? "mW" : "mA"); } else if (battery->state.amperage > 0) { seq_printf(seq, "charging state: charging\n"); - foo = (battery->info.full_charge_capacity - - battery->state.remaining_capacity) * cscale * 60 / - (battery->state.average_time_to_full == 0 ? 1 : - battery->state.average_time_to_full); - seq_printf(seq, "present rate: %i%s\n", - foo, battery->info.capacity_mode ? "0 mW" : " mA"); + seq_printf(seq, "present rate: %d %s\n", + foo, battery->info.capacity_mode ? "mW" : "mA"); } else { seq_printf(seq, "charging state: charged\n"); seq_printf(seq, "present rate: 0 %s\n", diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 64f26db10c8..bb0e0da39fb 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -11,13 +11,12 @@ #include <acpi/acinterp.h> /* for acpi_ex_eisa_id_to_string() */ #define _COMPONENT ACPI_BUS_COMPONENT -ACPI_MODULE_NAME("scan") +ACPI_MODULE_NAME("scan"); #define STRUCT_TO_INT(s) (*((int*)&s)) extern struct acpi_device *acpi_root; #define ACPI_BUS_CLASS "system_bus" #define ACPI_BUS_HID "ACPI_BUS" -#define ACPI_BUS_DRIVER_NAME "ACPI Bus Driver" #define ACPI_BUS_DEVICE_NAME "System Bus" static LIST_HEAD(acpi_device_list); diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index 62ce87d7165..37a0930fc0a 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c @@ -200,7 +200,7 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { {}, }; -static int __init acpi_sleep_init(void) +int __init acpi_sleep_init(void) { int i = 0; @@ -229,4 +229,3 @@ static int __init acpi_sleep_init(void) return 0; } -late_initcall(acpi_sleep_init); diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 7147b0bdab0..83a8d309790 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -31,14 +31,13 @@ #include <acpi/acpi_drivers.h> #define _COMPONENT ACPI_SYSTEM_COMPONENT -ACPI_MODULE_NAME("acpi_system") +ACPI_MODULE_NAME("system"); #ifdef MODULE_PARAM_PREFIX #undef MODULE_PARAM_PREFIX #endif #define MODULE_PARAM_PREFIX "acpi." #define ACPI_SYSTEM_CLASS "system" -#define ACPI_SYSTEM_DRIVER_NAME "ACPI System Driver" #define ACPI_SYSTEM_DEVICE_NAME "System" #define ACPI_SYSTEM_FILE_INFO "info" #define ACPI_SYSTEM_FILE_EVENT "event" diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 45bd17313c4..849e2c36180 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -169,40 +169,40 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header * header) int __init -acpi_table_parse_madt_family(char *id, - unsigned long madt_size, +acpi_table_parse_entries(char *id, + unsigned long table_size, int entry_id, - acpi_madt_entry_handler handler, + acpi_table_entry_handler handler, unsigned int max_entries) { - struct acpi_table_header *madt = NULL; + struct acpi_table_header *table_header = NULL; struct acpi_subtable_header *entry; unsigned int count = 0; - unsigned long madt_end; + unsigned long table_end; if (!handler) return -EINVAL; - /* Locate the MADT (if exists). There should only be one. */ - acpi_get_table(id, 0, &madt); + /* Locate the table (if exists). There should only be one. */ + acpi_get_table(id, 0, &table_header); - if (!madt) { + if (!table_header) { printk(KERN_WARNING PREFIX "%4.4s not present\n", id); return -ENODEV; } - madt_end = (unsigned long)madt + madt->length; + table_end = (unsigned long)table_header + table_header->length; /* Parse all entries looking for a match. */ entry = (struct acpi_subtable_header *) - ((unsigned long)madt + madt_size); + ((unsigned long)table_header + table_size); while (((unsigned long)entry) + sizeof(struct acpi_subtable_header) < - madt_end) { + table_end) { if (entry->type == entry_id && (!max_entries || count++ < max_entries)) - if (handler(entry, madt_end)) + if (handler(entry, table_end)) return -EINVAL; entry = (struct acpi_subtable_header *) @@ -218,13 +218,22 @@ acpi_table_parse_madt_family(char *id, int __init acpi_table_parse_madt(enum acpi_madt_type id, - acpi_madt_entry_handler handler, unsigned int max_entries) + acpi_table_entry_handler handler, unsigned int max_entries) { - return acpi_table_parse_madt_family(ACPI_SIG_MADT, + return acpi_table_parse_entries(ACPI_SIG_MADT, sizeof(struct acpi_table_madt), id, handler, max_entries); } +/** + * acpi_table_parse - find table with @id, run @handler on it + * + * @id: table id to find + * @handler: handler to run + * + * Scan the ACPI System Descriptor Table (STD) for a table matching @id, + * run @handler on it. Return 0 if table found, return on if not. + */ int __init acpi_table_parse(char *id, acpi_table_handler handler) { struct acpi_table_header *table = NULL; @@ -234,9 +243,9 @@ int __init acpi_table_parse(char *id, acpi_table_handler handler) acpi_get_table(id, 0, &table); if (table) { handler(table); - return 1; - } else return 0; + } else + return 1; } /* diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c index 807978d5381..417ef5fa766 100644 --- a/drivers/acpi/tables/tbxface.c +++ b/drivers/acpi/tables/tbxface.c @@ -338,9 +338,9 @@ acpi_status acpi_unload_table_id(acpi_owner_id id) int i; acpi_status status = AE_NOT_EXIST; - ACPI_FUNCTION_TRACE(acpi_unload_table); + ACPI_FUNCTION_TRACE(acpi_unload_table_id); - /* Find table from the requested type list */ + /* Find table in the global table list */ for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { if (id != acpi_gbl_root_table_list.tables[i].owner_id) { continue; @@ -352,8 +352,9 @@ acpi_status acpi_unload_table_id(acpi_owner_id id) * simply a position within the hierarchy */ acpi_tb_delete_namespace_by_owner(i); - acpi_tb_release_owner_id(i); + status = acpi_tb_release_owner_id(i); acpi_tb_set_table_loaded_flag(i, FALSE); + break; } return_ACPI_STATUS(status); } @@ -408,7 +409,7 @@ acpi_get_table(char *signature, } if (!acpi_gbl_permanent_mmap) { - acpi_gbl_root_table_list.tables[i].pointer = 0; + acpi_gbl_root_table_list.tables[i].pointer = NULL; } return (status); diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 986afd470a1..0ae8b9310cb 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -47,7 +47,6 @@ #define ACPI_THERMAL_COMPONENT 0x04000000 #define ACPI_THERMAL_CLASS "thermal_zone" -#define ACPI_THERMAL_DRIVER_NAME "ACPI Thermal Zone Driver" #define ACPI_THERMAL_DEVICE_NAME "Thermal Zone" #define ACPI_THERMAL_FILE_STATE "state" #define ACPI_THERMAL_FILE_TEMPERATURE "temperature" @@ -71,10 +70,10 @@ #define CELSIUS_TO_KELVIN(t) ((t+273)*10) #define _COMPONENT ACPI_THERMAL_COMPONENT -ACPI_MODULE_NAME("acpi_thermal") +ACPI_MODULE_NAME("thermal"); MODULE_AUTHOR("Paul Diefenbaugh"); -MODULE_DESCRIPTION(ACPI_THERMAL_DRIVER_NAME); +MODULE_DESCRIPTION("ACPI Thermal Zone Driver"); MODULE_LICENSE("GPL"); static int tzp; @@ -99,7 +98,7 @@ static ssize_t acpi_thermal_write_polling(struct file *, const char __user *, size_t, loff_t *); static struct acpi_driver acpi_thermal_driver = { - .name = ACPI_THERMAL_DRIVER_NAME, + .name = "thermal", .class = ACPI_THERMAL_CLASS, .ids = ACPI_THERMAL_HID, .ops = { @@ -270,7 +269,7 @@ static int acpi_thermal_set_polling(struct acpi_thermal *tz, int seconds) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency set to %lu seconds\n", - tz->polling_frequency)); + tz->polling_frequency/10)); return 0; } @@ -1357,28 +1356,32 @@ static int acpi_thermal_remove(struct acpi_device *device, int type) static int acpi_thermal_resume(struct acpi_device *device) { struct acpi_thermal *tz = NULL; - int i; + int i, j, power_state, result; + if (!device || !acpi_driver_data(device)) return -EINVAL; tz = acpi_driver_data(device); - acpi_thermal_get_temperature(tz); - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { - if (tz->trips.active[i].flags.valid) { - tz->temperature = tz->trips.active[i].temperature; - tz->trips.active[i].flags.enabled = 0; - - acpi_thermal_active(tz); - - tz->state.active |= tz->trips.active[i].flags.enabled; - tz->state.active_index = i; + if (!(&tz->trips.active[i])) + break; + if (!tz->trips.active[i].flags.valid) + break; + tz->trips.active[i].flags.enabled = 1; + for (j = 0; j < tz->trips.active[i].devices.count; j++) { + result = acpi_bus_get_power(tz->trips.active[i].devices. + handles[j], &power_state); + if (result || (power_state != ACPI_STATE_D0)) { + tz->trips.active[i].flags.enabled = 0; + break; + } } + tz->state.active |= tz->trips.active[i].flags.enabled; } - acpi_thermal_check(tz); + acpi_thermal_check(tz); return AE_OK; } diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c index d9b651ffcdc..faf8a5232d8 100644 --- a/drivers/acpi/toshiba_acpi.c +++ b/drivers/acpi/toshiba_acpi.c @@ -125,7 +125,7 @@ static int write_acpi_int(const char *methodName, int val) union acpi_object in_objs[1]; acpi_status status; - params.count = sizeof(in_objs) / sizeof(in_objs[0]); + params.count = ARRAY_SIZE(in_objs); params.pointer = in_objs; in_objs[0].type = ACPI_TYPE_INTEGER; in_objs[0].integer.value = val; @@ -561,10 +561,6 @@ static int __init toshiba_acpi_init(void) if (acpi_disabled) return -ENODEV; - if (!acpi_specific_hotkey_enabled) { - printk(MY_INFO "Using generic hotkey driver\n"); - return -ENODEV; - } /* simple device detection: look for HCI method */ if (is_valid_acpi_path(METHOD_HCI_1)) method_hci = METHOD_HCI_1; diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c index f777cebdc46..673a0caa407 100644 --- a/drivers/acpi/utilities/utdelete.c +++ b/drivers/acpi/utilities/utdelete.c @@ -170,7 +170,6 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) acpi_os_delete_mutex(object->mutex.os_mutex); acpi_gbl_global_lock_mutex = NULL; } else { - acpi_ex_unlink_mutex(object); acpi_os_delete_mutex(object->mutex.os_mutex); } break; diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 68a809fa7b1..34f15757108 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -31,7 +31,7 @@ #include <acpi/acpi_drivers.h> #define _COMPONENT ACPI_BUS_COMPONENT -ACPI_MODULE_NAME("acpi_utils") +ACPI_MODULE_NAME("utils"); /* -------------------------------------------------------------------------- Object Evaluation Helpers diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index e0b97add8c6..bf525cca3b6 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -40,7 +40,6 @@ #define ACPI_VIDEO_COMPONENT 0x08000000 #define ACPI_VIDEO_CLASS "video" -#define ACPI_VIDEO_DRIVER_NAME "ACPI Video Driver" #define ACPI_VIDEO_BUS_NAME "Video Bus" #define ACPI_VIDEO_DEVICE_NAME "Video Device" #define ACPI_VIDEO_NOTIFY_SWITCH 0x80 @@ -65,17 +64,17 @@ #define ACPI_VIDEO_DISPLAY_LCD 4 #define _COMPONENT ACPI_VIDEO_COMPONENT -ACPI_MODULE_NAME("acpi_video") +ACPI_MODULE_NAME("video"); - MODULE_AUTHOR("Bruno Ducrot"); -MODULE_DESCRIPTION(ACPI_VIDEO_DRIVER_NAME); +MODULE_AUTHOR("Bruno Ducrot"); +MODULE_DESCRIPTION("ACPI Video Driver"); MODULE_LICENSE("GPL"); static int acpi_video_bus_add(struct acpi_device *device); static int acpi_video_bus_remove(struct acpi_device *device, int type); static struct acpi_driver acpi_video_bus = { - .name = ACPI_VIDEO_DRIVER_NAME, + .name = "video", .class = ACPI_VIDEO_CLASS, .ids = ACPI_VIDEO_HID, .ops = { diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index bedae4ad3f7..80b199fa0aa 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -107,4 +107,19 @@ config MSI_LAPTOP If you have an MSI S270 laptop, say Y or M here. +config SONY_LAPTOP + tristate "Sony Laptop Extras" + depends on X86 && ACPI + select BACKLIGHT_CLASS_DEVICE + ---help--- + This mini-driver drives the SNC device present in the ACPI BIOS of + the Sony Vaio laptops. + + It gives access to some extra laptop functionalities. In its current + form, this driver let the user set or query the screen brightness + through the backlight subsystem and remove/apply power to some + devices. + + Read <file:Documentation/sony-laptop.txt> for more information. + endmenu diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 35da53c409c..7793ccd7904 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_LKDTM) += lkdtm.o obj-$(CONFIG_TIFM_CORE) += tifm_core.o obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o obj-$(CONFIG_SGI_IOC4) += ioc4.o +obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c index 861c39935f9..e4e2b707a35 100644 --- a/drivers/misc/asus-laptop.c +++ b/drivers/misc/asus-laptop.c @@ -1088,11 +1088,6 @@ static int __init asus_laptop_init(void) if (acpi_disabled) return -ENODEV; - if (!acpi_specific_hotkey_enabled) { - printk(ASUS_ERR "Using generic hotkey driver\n"); - return -ENODEV; - } - result = acpi_bus_register_driver(&asus_hotk_driver); if (result < 0) return result; diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c new file mode 100644 index 00000000000..cabbed0015e --- /dev/null +++ b/drivers/misc/sony-laptop.c @@ -0,0 +1,562 @@ +/* + * ACPI Sony Notebook Control Driver (SNC) + * + * Copyright (C) 2004-2005 Stelian Pop <stelian@popies.net> + * Copyright (C) 2007 Mattia Dongili <malattia@linux.it> + * + * Parts of this driver inspired from asus_acpi.c and ibm_acpi.c + * which are copyrighted by their respective authors. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/backlight.h> +#include <linux/platform_device.h> +#include <linux/err.h> +#include <acpi/acpi_drivers.h> +#include <acpi/acpi_bus.h> +#include <asm/uaccess.h> + +#define ACPI_SNC_CLASS "sony" +#define ACPI_SNC_HID "SNY5001" +#define ACPI_SNC_DRIVER_NAME "ACPI Sony Notebook Control Driver v0.4" + +/* the device uses 1-based values, while the backlight subsystem uses + 0-based values */ +#define SONY_MAX_BRIGHTNESS 8 + +#define LOG_PFX KERN_WARNING "sony-laptop: " + +MODULE_AUTHOR("Stelian Pop, Mattia Dongili"); +MODULE_DESCRIPTION(ACPI_SNC_DRIVER_NAME); +MODULE_LICENSE("GPL"); + +static int debug; +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "set this to 1 (and RTFM) if you want to help " + "the development of this driver"); + +static ssize_t sony_acpi_show(struct device *, struct device_attribute *, + char *); +static ssize_t sony_acpi_store(struct device *, struct device_attribute *, + const char *, size_t); +static int boolean_validate(const int, const int); +static int brightness_default_validate(const int, const int); + +#define SNC_VALIDATE_IN 0 +#define SNC_VALIDATE_OUT 1 + +struct sony_acpi_value { + char *name; /* name of the entry */ + char **acpiget; /* names of the ACPI get function */ + char **acpiset; /* names of the ACPI set function */ + int (*validate)(const int, const int); /* input/output validation */ + int value; /* current setting */ + int valid; /* Has ever been set */ + int debug; /* active only in debug mode ? */ + struct device_attribute devattr; /* sysfs atribute */ +}; + +#define HANDLE_NAMES(_name, _values...) \ + static char *snc_##_name[] = { _values, NULL } + +#define SONY_ACPI_VALUE(_name, _getters, _setters, _validate, _debug) \ + { \ + .name = __stringify(_name), \ + .acpiget = _getters, \ + .acpiset = _setters, \ + .validate = _validate, \ + .debug = _debug, \ + .devattr = __ATTR(_name, 0, sony_acpi_show, sony_acpi_store), \ + } + +#define SONY_ACPI_VALUE_NULL { .name = NULL } + +HANDLE_NAMES(fnkey_get, "GHKE"); + +HANDLE_NAMES(brightness_def_get, "GPBR"); +HANDLE_NAMES(brightness_def_set, "SPBR"); + +HANDLE_NAMES(cdpower_get, "GCDP"); +HANDLE_NAMES(cdpower_set, "SCDP", "CDPW"); + +HANDLE_NAMES(audiopower_get, "GAZP"); +HANDLE_NAMES(audiopower_set, "AZPW"); + +HANDLE_NAMES(lanpower_get, "GLNP"); +HANDLE_NAMES(lanpower_set, "LNPW"); + +HANDLE_NAMES(PID_get, "GPID"); + +HANDLE_NAMES(CTR_get, "GCTR"); +HANDLE_NAMES(CTR_set, "SCTR"); + +HANDLE_NAMES(PCR_get, "GPCR"); +HANDLE_NAMES(PCR_set, "SPCR"); + +HANDLE_NAMES(CMI_get, "GCMI"); +HANDLE_NAMES(CMI_set, "SCMI"); + +static struct sony_acpi_value sony_acpi_values[] = { + SONY_ACPI_VALUE(brightness_default, snc_brightness_def_get, + snc_brightness_def_set, brightness_default_validate, 0), + SONY_ACPI_VALUE(fnkey, snc_fnkey_get, NULL, NULL, 0), + SONY_ACPI_VALUE(cdpower, snc_cdpower_get, snc_cdpower_set, boolean_validate, 0), + SONY_ACPI_VALUE(audiopower, snc_audiopower_get, snc_audiopower_set, + boolean_validate, 0), + SONY_ACPI_VALUE(lanpower, snc_lanpower_get, snc_lanpower_set, + boolean_validate, 1), + /* unknown methods */ + SONY_ACPI_VALUE(PID, snc_PID_get, NULL, NULL, 1), + SONY_ACPI_VALUE(CTR, snc_CTR_get, snc_CTR_set, NULL, 1), + SONY_ACPI_VALUE(PCR, snc_PCR_get, snc_PCR_set, NULL, 1), + SONY_ACPI_VALUE(CMI, snc_CMI_get, snc_CMI_set, NULL, 1), + SONY_ACPI_VALUE_NULL +}; + +static acpi_handle sony_acpi_handle; +static struct acpi_device *sony_acpi_acpi_device = NULL; + +/* + * acpi_evaluate_object wrappers + */ +static int acpi_callgetfunc(acpi_handle handle, char *name, int *result) +{ + struct acpi_buffer output; + union acpi_object out_obj; + acpi_status status; + + output.length = sizeof(out_obj); + output.pointer = &out_obj; + + status = acpi_evaluate_object(handle, name, NULL, &output); + if ((status == AE_OK) && (out_obj.type == ACPI_TYPE_INTEGER)) { + *result = out_obj.integer.value; + return 0; + } + + printk(LOG_PFX "acpi_callreadfunc failed\n"); + + return -1; +} + +static int acpi_callsetfunc(acpi_handle handle, char *name, int value, + int *result) +{ + struct acpi_object_list params; + union acpi_object in_obj; + struct acpi_buffer output; + union acpi_object out_obj; + acpi_status status; + + params.count = 1; + params.pointer = &in_obj; + in_obj.type = ACPI_TYPE_INTEGER; + in_obj.integer.value = value; + + output.length = sizeof(out_obj); + output.pointer = &out_obj; + + status = acpi_evaluate_object(handle, name, ¶ms, &output); + if (status == AE_OK) { + if (result != NULL) { + if (out_obj.type != ACPI_TYPE_INTEGER) { + printk(LOG_PFX "acpi_evaluate_object bad " + "return type\n"); + return -1; + } + *result = out_obj.integer.value; + } + return 0; + } + + printk(LOG_PFX "acpi_evaluate_object failed\n"); + + return -1; +} + +/* + * sony_acpi_values input/output validate functions + */ + +/* brightness_default_validate: + * + * manipulate input output values to keep consistency with the + * backlight framework for which brightness values are 0-based. + */ +static int brightness_default_validate(const int direction, const int value) +{ + switch (direction) { + case SNC_VALIDATE_OUT: + return value - 1; + case SNC_VALIDATE_IN: + if (value >= 0 && value < SONY_MAX_BRIGHTNESS) + return value + 1; + } + return -EINVAL; +} + +/* boolean_validate: + * + * on input validate boolean values 0/1, on output just pass the + * received value. + */ +static int boolean_validate(const int direction, const int value) +{ + if (direction == SNC_VALIDATE_IN) { + if (value != 0 && value != 1) + return -EINVAL; + } + return value; +} + +/* + * Sysfs show/store common to all sony_acpi_values + */ +static ssize_t sony_acpi_show(struct device *dev, struct device_attribute *attr, + char *buffer) +{ + int value; + struct sony_acpi_value *item = + container_of(attr, struct sony_acpi_value, devattr); + + if (!*item->acpiget) + return -EIO; + + if (acpi_callgetfunc(sony_acpi_handle, *item->acpiget, &value) < 0) + return -EIO; + + if (item->validate) + value = item->validate(SNC_VALIDATE_OUT, value); + + return snprintf(buffer, PAGE_SIZE, "%d\n", value); +} + +static ssize_t sony_acpi_store(struct device *dev, + struct device_attribute *attr, + const char *buffer, size_t count) +{ + int value; + struct sony_acpi_value *item = + container_of(attr, struct sony_acpi_value, devattr); + + if (!item->acpiset) + return -EIO; + + if (count > 31) + return -EINVAL; + + value = simple_strtoul(buffer, NULL, 10); + + if (item->validate) + value = item->validate(SNC_VALIDATE_IN, value); + + if (value < 0) + return value; + + if (acpi_callsetfunc(sony_acpi_handle, *item->acpiset, value, NULL) < 0) + return -EIO; + item->value = value; + item->valid = 1; + return count; +} + +/* + * Platform device + */ +static struct platform_driver sncpf_driver = { + .driver = { + .name = "sony-laptop", + .owner = THIS_MODULE, + } +}; +static struct platform_device *sncpf_device; + +static int sony_snc_pf_add(void) +{ + acpi_handle handle; + struct sony_acpi_value *item; + int ret = 0; + + ret = platform_driver_register(&sncpf_driver); + if (ret) + goto out; + + sncpf_device = platform_device_alloc("sony-laptop", -1); + if (!sncpf_device) { + ret = -ENOMEM; + goto out_platform_registered; + } + + ret = platform_device_add(sncpf_device); + if (ret) + goto out_platform_alloced; + + for (item = sony_acpi_values; item->name; ++item) { + + if (!debug && item->debug) + continue; + + /* find the available acpiget as described in the DSDT */ + for (; item->acpiget && *item->acpiget; ++item->acpiget) { + if (ACPI_SUCCESS(acpi_get_handle(sony_acpi_handle, + *item->acpiget, + &handle))) { + if (debug) + printk(LOG_PFX "Found %s getter: %s\n", + item->name, *item->acpiget); + item->devattr.attr.mode |= S_IRUGO; + break; + } + } + + /* find the available acpiset as described in the DSDT */ + for (; item->acpiset && *item->acpiset; ++item->acpiset) { + if (ACPI_SUCCESS(acpi_get_handle(sony_acpi_handle, + *item->acpiset, + &handle))) { + if (debug) + printk(LOG_PFX "Found %s setter: %s\n", + item->name, *item->acpiset); + item->devattr.attr.mode |= S_IWUSR; + break; + } + } + + if (item->devattr.attr.mode != 0) { + ret = + device_create_file(&sncpf_device->dev, + &item->devattr); + if (ret) + goto out_sysfs; + } + } + + return 0; + + out_sysfs: + for (item = sony_acpi_values; item->name; ++item) { + device_remove_file(&sncpf_device->dev, &item->devattr); + } + platform_device_del(sncpf_device); + out_platform_alloced: + platform_device_put(sncpf_device); + out_platform_registered: + platform_driver_unregister(&sncpf_driver); + out: + return ret; +} + +static void sony_snc_pf_remove(void) +{ + struct sony_acpi_value *item; + + for (item = sony_acpi_values; item->name; ++item) { + device_remove_file(&sncpf_device->dev, &item->devattr); + } + + platform_device_del(sncpf_device); + platform_device_put(sncpf_device); + platform_driver_unregister(&sncpf_driver); +} + +/* + * Backlight device + */ +static int sony_backlight_update_status(struct backlight_device *bd) +{ + return acpi_callsetfunc(sony_acpi_handle, "SBRT", + bd->props->brightness + 1, NULL); +} + +static int sony_backlight_get_brightness(struct backlight_device *bd) +{ + int value; + + if (acpi_callgetfunc(sony_acpi_handle, "GBRT", &value)) + return 0; + /* brightness levels are 1-based, while backlight ones are 0-based */ + return value - 1; +} + +static struct backlight_device *sony_backlight_device; +static struct backlight_properties sony_backlight_properties = { + .owner = THIS_MODULE, + .update_status = sony_backlight_update_status, + .get_brightness = sony_backlight_get_brightness, + .max_brightness = SONY_MAX_BRIGHTNESS - 1, +}; + +/* + * ACPI callbacks + */ +static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) +{ + if (debug) + printk(LOG_PFX "sony_acpi_notify, event: %d\n", event); + acpi_bus_generate_event(sony_acpi_acpi_device, 1, event); +} + +static acpi_status sony_walk_callback(acpi_handle handle, u32 level, + void *context, void **return_value) +{ + struct acpi_namespace_node *node; + union acpi_operand_object *operand; + + node = (struct acpi_namespace_node *)handle; + operand = (union acpi_operand_object *)node->object; + + printk(LOG_PFX "method: name: %4.4s, args %X\n", node->name.ascii, + (u32) operand->method.param_count); + + return AE_OK; +} + +/* + * ACPI device + */ +static int sony_acpi_resume(struct acpi_device *device) +{ + struct sony_acpi_value *item; + + for (item = sony_acpi_values; item->name; item++) { + int ret; + + if (!item->valid) + continue; + ret = acpi_callsetfunc(sony_acpi_handle, *item->acpiset, + item->value, NULL); + if (ret < 0) { + printk("%s: %d\n", __FUNCTION__, ret); + break; + } + } + return 0; +} + +static int sony_acpi_add(struct acpi_device *device) +{ + acpi_status status; + int result; + acpi_handle handle; + + sony_acpi_acpi_device = device; + + sony_acpi_handle = device->handle; + + if (debug) { + status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_acpi_handle, + 1, sony_walk_callback, NULL, NULL); + if (ACPI_FAILURE(status)) { + printk(LOG_PFX "unable to walk acpi resources\n"); + result = -ENODEV; + goto outwalk; + } + } + + status = acpi_install_notify_handler(sony_acpi_handle, + ACPI_DEVICE_NOTIFY, + sony_acpi_notify, NULL); + if (ACPI_FAILURE(status)) { + printk(LOG_PFX "unable to install notify handler\n"); + result = -ENODEV; + goto outwalk; + } + + if (ACPI_SUCCESS(acpi_get_handle(sony_acpi_handle, "GBRT", &handle))) { + sony_backlight_device = backlight_device_register("sony", NULL, + NULL, + &sony_backlight_properties); + + if (IS_ERR(sony_backlight_device)) { + printk(LOG_PFX "unable to register backlight device\n"); + sony_backlight_device = NULL; + } else + sony_backlight_properties.brightness = + sony_backlight_get_brightness + (sony_backlight_device); + } + + if (sony_snc_pf_add()) + goto outbacklight; + + printk(KERN_INFO ACPI_SNC_DRIVER_NAME " successfully installed\n"); + + return 0; + + outbacklight: + if (sony_backlight_device) + backlight_device_unregister(sony_backlight_device); + + status = acpi_remove_notify_handler(sony_acpi_handle, + ACPI_DEVICE_NOTIFY, + sony_acpi_notify); + if (ACPI_FAILURE(status)) + printk(LOG_PFX "unable to remove notify handler\n"); + outwalk: + return result; +} + +static int sony_acpi_remove(struct acpi_device *device, int type) +{ + acpi_status status; + + if (sony_backlight_device) + backlight_device_unregister(sony_backlight_device); + + sony_acpi_acpi_device = NULL; + + status = acpi_remove_notify_handler(sony_acpi_handle, + ACPI_DEVICE_NOTIFY, + sony_acpi_notify); + if (ACPI_FAILURE(status)) + printk(LOG_PFX "unable to remove notify handler\n"); + + sony_snc_pf_remove(); + + printk(KERN_INFO ACPI_SNC_DRIVER_NAME " successfully removed\n"); + + return 0; +} + +static struct acpi_driver sony_acpi_driver = { + .name = ACPI_SNC_DRIVER_NAME, + .class = ACPI_SNC_CLASS, + .ids = ACPI_SNC_HID, + .ops = { + .add = sony_acpi_add, + .remove = sony_acpi_remove, + .resume = sony_acpi_resume, + }, +}; + +static int __init sony_acpi_init(void) +{ + return acpi_bus_register_driver(&sony_acpi_driver); +} + +static void __exit sony_acpi_exit(void) +{ + acpi_bus_unregister_driver(&sony_acpi_driver); +} + +module_init(sony_acpi_init); +module_exit(sony_acpi_exit); diff --git a/drivers/pnp/pnpacpi/Kconfig b/drivers/pnp/pnpacpi/Kconfig index ad27e5e0101..b04767ce273 100644 --- a/drivers/pnp/pnpacpi/Kconfig +++ b/drivers/pnp/pnpacpi/Kconfig @@ -2,17 +2,5 @@ # Plug and Play ACPI configuration # config PNPACPI - bool "Plug and Play ACPI support" - depends on PNP && ACPI - default y - ---help--- - Linux uses the PNPACPI to autodetect built-in - mainboard resources (e.g. parallel port resources). - - Some features (e.g. real hotplug) are not currently - implemented. - - If you would like the kernel to detect and allocate resources to - your mainboard devices (on some systems they are disabled by the - BIOS) say Y here. Also the PNPACPI can help prevent resource - conflicts between mainboard devices and other bus devices. + bool + default (PNP && ACPI) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 3f048bd6326..5a8f55fea5f 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1269,9 +1269,18 @@ repeat: /* Some devices return the total number of sectors, not the * highest sector number. Make the necessary adjustment. */ - if (sdp->fix_capacity) + if (sdp->fix_capacity) { --sdkp->capacity; + /* Some devices have version which report the correct sizes + * and others which do not. We guess size according to a heuristic + * and err on the side of lowering the capacity. */ + } else { + if (sdp->guess_capacity) + if (sdkp->capacity & 0x01) /* odd sizes are odd */ + --sdkp->capacity; + } + got_data: if (sector_size == 0) { sector_size = 512; diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 825bf884537..8b7ff467d26 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_USB_SERIAL) += serial/ obj-$(CONFIG_USB_ADUTUX) += misc/ obj-$(CONFIG_USB_APPLEDISPLAY) += misc/ obj-$(CONFIG_USB_AUERSWALD) += misc/ +obj-$(CONFIG_USB_BERRY_CHARGE) += misc/ obj-$(CONFIG_USB_CYPRESS_CY7C63)+= misc/ obj-$(CONFIG_USB_CYTHERM) += misc/ obj-$(CONFIG_USB_EMI26) += misc/ diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index dae4ef1e8fe..4973e147bc7 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c @@ -61,6 +61,7 @@ #include <linux/usb.h> #include <linux/firmware.h> #include <linux/ctype.h> +#include <linux/sched.h> #include <linux/kthread.h> #include <linux/version.h> #include <linux/mutex.h> diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 98199628e39..d38a25f36ea 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -326,10 +326,16 @@ static void acm_rx_tasklet(unsigned long _acm) struct tty_struct *tty = acm->tty; struct acm_ru *rcv; unsigned long flags; - int i = 0; + unsigned char throttled; dbg("Entering acm_rx_tasklet"); - if (!ACM_READY(acm) || acm->throttle) + if (!ACM_READY(acm)) + return; + + spin_lock(&acm->throttle_lock); + throttled = acm->throttle; + spin_unlock(&acm->throttle_lock); + if (throttled) return; next_buffer: @@ -346,22 +352,20 @@ next_buffer: dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size); tty_buffer_request_room(tty, buf->size); - if (!acm->throttle) + spin_lock(&acm->throttle_lock); + throttled = acm->throttle; + spin_unlock(&acm->throttle_lock); + if (!throttled) tty_insert_flip_string(tty, buf->base, buf->size); tty_flip_buffer_push(tty); - spin_lock(&acm->throttle_lock); - if (acm->throttle) { - dbg("Throtteling noticed"); - memmove(buf->base, buf->base + i, buf->size - i); - buf->size -= i; - spin_unlock(&acm->throttle_lock); + if (throttled) { + dbg("Throttling noticed"); spin_lock_irqsave(&acm->read_lock, flags); list_add(&buf->list, &acm->filled_read_bufs); spin_unlock_irqrestore(&acm->read_lock, flags); return; } - spin_unlock(&acm->throttle_lock); spin_lock_irqsave(&acm->read_lock, flags); list_add(&buf->list, &acm->spare_read_bufs); @@ -467,7 +471,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) goto bail_out; } - if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS)) + if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS) && + (acm->ctrl_caps & USB_CDC_CAP_LINE)) goto full_bailout; INIT_LIST_HEAD(&acm->spare_read_urbs); @@ -480,6 +485,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) list_add(&(acm->rb[i].list), &acm->spare_read_bufs); } + acm->throttle = 0; + tasklet_schedule(&acm->urb_task); done: @@ -1092,6 +1099,10 @@ static struct usb_device_id acm_ids[] = { { USB_DEVICE(0x0ace, 0x1611), /* ZyDAS 56K USB MODEM - new version */ .driver_info = SINGLE_RX_URB, /* firmware bug */ }, + { USB_DEVICE(0x22b8, 0x7000), /* Motorola Q Phone */ + .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ + }, + /* control interfaces with various AT-command sets */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, USB_CDC_ACM_PROTO_AT_V25TER) }, diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index a47c30b2d76..aefc7987120 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -604,10 +604,6 @@ static unsigned int usb_device_poll(struct file *file, struct poll_table_struct lock_kernel(); if (!st) { st = kmalloc(sizeof(struct usb_device_status), GFP_KERNEL); - if (!st) { - unlock_kernel(); - return POLLIN; - } /* we may have dropped BKL - need to check for having lost the race */ if (file->private_data) { @@ -615,6 +611,11 @@ static unsigned int usb_device_poll(struct file *file, struct poll_table_struct st = file->private_data; goto lost_race; } + /* we haven't lost - check for allocation failure now */ + if (!st) { + unlock_kernel(); + return POLLIN; + } /* * need to prevent the module from being unloaded, since diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 2087766f9e8..274f14f1633 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -857,11 +857,11 @@ static int proc_setintf(struct dev_state *ps, void __user *arg) static int proc_setconfig(struct dev_state *ps, void __user *arg) { - unsigned int u; + int u; int status = 0; struct usb_host_config *actconfig; - if (get_user(u, (unsigned int __user *)arg)) + if (get_user(u, (int __user *)arg)) return -EFAULT; actconfig = ps->dev->actconfig; diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 600d1bc8272..2aded261f42 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -743,6 +743,7 @@ EXPORT_SYMBOL_GPL(usb_deregister_device_driver); * usb_register_driver - register a USB interface driver * @new_driver: USB operations for the interface driver * @owner: module owner of this driver. + * @mod_name: module name string * * Registers a USB interface driver with the USB core. The list of * unattached interfaces will be rescanned whenever a new driver is diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index 5e628ae3aec..e0ec7045e86 100644 --- a/drivers/usb/core/endpoint.c +++ b/drivers/usb/core/endpoint.c @@ -229,7 +229,7 @@ static int init_endpoint_class(void) kref_init(&ep_class->kref); ep_class->class = class_create(THIS_MODULE, "usb_endpoint"); if (IS_ERR(ep_class->class)) { - result = IS_ERR(ep_class->class); + result = PTR_ERR(ep_class->class); goto class_create_error; } diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index b531a4fd30c..9bbcb20e2d9 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c @@ -184,7 +184,7 @@ static void generic_disconnect(struct usb_device *udev) /* if this is only an unbind, not a physical disconnect, then * unconfigure the device */ if (udev->actconfig) - usb_set_configuration(udev, 0); + usb_set_configuration(udev, -1); usb_remove_sysfs_dev_files(udev); } diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 590ec82d051..50c0db15304 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -44,6 +44,7 @@ struct usb_hub { struct usb_hub_status hub; struct usb_port_status port; } *status; /* buffer for status reports */ + struct mutex status_mutex; /* for the status buffer */ int error; /* last reported error */ int nerrors; /* track consecutive errors */ @@ -535,6 +536,7 @@ static int hub_hub_status(struct usb_hub *hub, { int ret; + mutex_lock(&hub->status_mutex); ret = get_hub_status(hub->hdev, &hub->status->hub); if (ret < 0) dev_err (hub->intfdev, @@ -544,6 +546,7 @@ static int hub_hub_status(struct usb_hub *hub, *change = le16_to_cpu(hub->status->hub.wHubChange); ret = 0; } + mutex_unlock(&hub->status_mutex); return ret; } @@ -617,6 +620,7 @@ static int hub_configure(struct usb_hub *hub, ret = -ENOMEM; goto fail; } + mutex_init(&hub->status_mutex); hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL); if (!hub->descriptor) { @@ -1396,6 +1400,7 @@ static int hub_port_status(struct usb_hub *hub, int port1, { int ret; + mutex_lock(&hub->status_mutex); ret = get_port_status(hub->hdev, port1, &hub->status->port); if (ret < 4) { dev_err (hub->intfdev, @@ -1407,6 +1412,7 @@ static int hub_port_status(struct usb_hub *hub, int port1, *change = le16_to_cpu(hub->status->port.wPortChange); ret = 0; } + mutex_unlock(&hub->status_mutex); return ret; } @@ -1904,6 +1910,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) struct usb_hub *hub = usb_get_intfdata (intf); struct usb_device *hdev = hub->hdev; unsigned port1; + int status = 0; /* fail if children aren't already suspended */ for (port1 = 1; port1 <= hdev->maxchild; port1++) { @@ -1927,24 +1934,18 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) dev_dbg(&intf->dev, "%s\n", __FUNCTION__); + /* stop khubd and related activity */ + hub_quiesce(hub); + /* "global suspend" of the downstream HC-to-USB interface */ if (!hdev->parent) { - struct usb_bus *bus = hdev->bus; - if (bus) { - int status = hcd_bus_suspend (bus); - - if (status != 0) { - dev_dbg(&hdev->dev, "'global' suspend %d\n", - status); - return status; - } - } else - return -EOPNOTSUPP; + status = hcd_bus_suspend(hdev->bus); + if (status != 0) { + dev_dbg(&hdev->dev, "'global' suspend %d\n", status); + hub_activate(hub); + } } - - /* stop khubd and related activity */ - hub_quiesce(hub); - return 0; + return status; } static int hub_resume(struct usb_interface *intf) diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 8aca3574c2b..74edaea5665 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1316,6 +1316,14 @@ static void release_interface(struct device *dev) * use this kind of configurability; many devices only have one * configuration. * + * @configuration is the value of the configuration to be installed. + * According to the USB spec (e.g. section 9.1.1.5), configuration values + * must be non-zero; a value of zero indicates that the device in + * unconfigured. However some devices erroneously use 0 as one of their + * configuration values. To help manage such devices, this routine will + * accept @configuration = -1 as indicating the device should be put in + * an unconfigured state. + * * USB device configurations may affect Linux interoperability, * power consumption and the functionality available. For example, * the default configuration is limited to using 100mA of bus power, @@ -1347,10 +1355,15 @@ int usb_set_configuration(struct usb_device *dev, int configuration) struct usb_interface **new_interfaces = NULL; int n, nintf; - for (i = 0; i < dev->descriptor.bNumConfigurations; i++) { - if (dev->config[i].desc.bConfigurationValue == configuration) { - cp = &dev->config[i]; - break; + if (configuration == -1) + configuration = 0; + else { + for (i = 0; i < dev->descriptor.bNumConfigurations; i++) { + if (dev->config[i].desc.bConfigurationValue == + configuration) { + cp = &dev->config[i]; + break; + } } } if ((!cp && configuration != 0)) @@ -1359,6 +1372,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration) /* The USB spec says configuration 0 means unconfigured. * But if a device includes a configuration numbered 0, * we will accept it as a correctly configured state. + * Use -1 if you really want to unconfigure the device. */ if (cp && configuration == 0) dev_warn(&dev->dev, "config 0 descriptor??\n"); diff --git a/drivers/usb/core/otg_whitelist.h b/drivers/usb/core/otg_whitelist.h index 627a5a2fc9c..7f31a495a25 100644 --- a/drivers/usb/core/otg_whitelist.h +++ b/drivers/usb/core/otg_whitelist.h @@ -31,7 +31,7 @@ static struct usb_device_id whitelist_table [] = { { USB_DEVICE_INFO(7, 1, 3) }, #endif -#ifdef CONFIG_USB_CDCETHER +#ifdef CONFIG_USB_NET_CDCETHER /* Linux-USB CDC Ethernet gadget */ { USB_DEVICE(0x0525, 0xa4a1), }, /* Linux-USB CDC Ethernet + RNDIS gadget */ diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 4eaa0ee8e72..0edfbafd702 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -63,7 +63,7 @@ set_bConfigurationValue(struct device *dev, struct device_attribute *attr, struct usb_device *udev = to_usb_device(dev); int config, value; - if (sscanf(buf, "%u", &config) != 1 || config > 255) + if (sscanf(buf, "%d", &config) != 1 || config < -1 || config > 255) return -EINVAL; usb_lock_device(udev); value = usb_set_configuration(udev, config); diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 36b36e0175f..82369c4729b 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -784,7 +784,7 @@ static int at91_ep_set_halt(struct usb_ep *_ep, int value) return status; } -static struct usb_ep_ops at91_ep_ops = { +static const struct usb_ep_ops at91_ep_ops = { .enable = at91_ep_enable, .disable = at91_ep_disable, .alloc_request = at91_ep_alloc_request, @@ -1651,7 +1651,7 @@ static void at91udc_shutdown(struct platform_device *dev) pullup(platform_get_drvdata(dev), 0); } -static int __devinit at91udc_probe(struct platform_device *pdev) +static int __init at91udc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct at91_udc *udc; @@ -1762,7 +1762,7 @@ fail0: return retval; } -static int __devexit at91udc_remove(struct platform_device *pdev) +static int __exit at91udc_remove(struct platform_device *pdev) { struct at91_udc *udc = platform_get_drvdata(pdev); struct resource *res; @@ -1836,8 +1836,7 @@ static int at91udc_resume(struct platform_device *pdev) #endif static struct platform_driver at91_udc = { - .probe = at91udc_probe, - .remove = __devexit_p(at91udc_remove), + .remove = __exit_p(at91udc_remove), .shutdown = at91udc_shutdown, .suspend = at91udc_suspend, .resume = at91udc_resume, @@ -1847,13 +1846,13 @@ static struct platform_driver at91_udc = { }, }; -static int __devinit udc_init_module(void) +static int __init udc_init_module(void) { - return platform_driver_register(&at91_udc); + return platform_driver_probe(&at91_udc, at91udc_probe); } module_init(udc_init_module); -static void __devexit udc_exit_module(void) +static void __exit udc_exit_module(void) { platform_driver_unregister(&at91_udc); } diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index e6c19aa4bef..e552668d36b 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -1699,6 +1699,7 @@ static int gs_setup_class(struct usb_gadget *gadget, memcpy(&port->port_line_coding, req->buf, ret); spin_unlock(&port->port_lock); } + ret = 0; break; case USB_CDC_REQ_GET_LINE_CODING: diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 185721dba42..a7405648823 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -42,6 +42,9 @@ #include <asm/irq.h> #include <asm/system.h> #include <asm/unaligned.h> +#ifdef CONFIG_PPC_PS3 +#include <asm/firmware.h> +#endif /*-------------------------------------------------------------------------*/ @@ -299,6 +302,19 @@ static void ehci_watchdog (unsigned long param) spin_unlock_irqrestore (&ehci->lock, flags); } +/* On some systems, leaving remote wakeup enabled prevents system shutdown. + * The firmware seems to think that powering off is a wakeup event! + * This routine turns off remote wakeup and everything else, on all ports. + */ +static void ehci_turn_off_all_ports(struct ehci_hcd *ehci) +{ + int port = HCS_N_PORTS(ehci->hcs_params); + + while (port--) + ehci_writel(ehci, PORT_RWC_BITS, + &ehci->regs->port_status[port]); +} + /* ehci_shutdown kick in for silicon on any bus (not just pci, etc). * This forcibly disables dma and IRQs, helping kexec and other cases * where the next system software may expect clean state. @@ -310,9 +326,13 @@ ehci_shutdown (struct usb_hcd *hcd) ehci = hcd_to_ehci (hcd); (void) ehci_halt (ehci); + ehci_turn_off_all_ports(ehci); /* make BIOS/etc use companion controller during reboot */ ehci_writel(ehci, 0, &ehci->regs->configured_flag); + + /* unblock posted writes */ + ehci_readl(ehci, &ehci->regs->configured_flag); } static void ehci_port_power (struct ehci_hcd *ehci, int is_on) @@ -951,15 +971,18 @@ static int __init ehci_hcd_init(void) #endif #ifdef PS3_SYSTEM_BUS_DRIVER - retval = ps3_system_bus_driver_register(&PS3_SYSTEM_BUS_DRIVER); - if (retval < 0) { + if (firmware_has_feature(FW_FEATURE_PS3_LV1)) { + retval = ps3_system_bus_driver_register( + &PS3_SYSTEM_BUS_DRIVER); + if (retval < 0) { #ifdef PLATFORM_DRIVER - platform_driver_unregister(&PLATFORM_DRIVER); + platform_driver_unregister(&PLATFORM_DRIVER); #endif #ifdef PCI_DRIVER - pci_unregister_driver(&PCI_DRIVER); + pci_unregister_driver(&PCI_DRIVER); #endif - return retval; + return retval; + } } #endif @@ -976,7 +999,8 @@ static void __exit ehci_hcd_cleanup(void) pci_unregister_driver(&PCI_DRIVER); #endif #ifdef PS3_SYSTEM_BUS_DRIVER - ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); + if (firmware_has_feature(FW_FEATURE_PS3_LV1)) + ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); #endif } module_exit(ehci_hcd_cleanup); diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 0d83c6df1a3..9af529d22b3 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -36,6 +36,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) int port; int mask; + ehci_dbg(ehci, "suspend root hub\n"); + if (time_before (jiffies, ehci->next_statechange)) msleep(5); diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 2718b5dc4ec..46873f2534b 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -1577,7 +1577,7 @@ static int isp116x_remove(struct platform_device *pdev) #define resource_len(r) (((r)->end - (r)->start) + 1) -static int __init isp116x_probe(struct platform_device *pdev) +static int __devinit isp116x_probe(struct platform_device *pdev) { struct usb_hcd *hcd; struct isp116x *isp116x; diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 93034648727..d849c809acb 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -18,19 +18,38 @@ #include <asm/mach-types.h> #include <asm/hardware.h> #include <asm/arch/board.h> +#include <asm/arch/cpu.h> #ifndef CONFIG_ARCH_AT91 #error "CONFIG_ARCH_AT91 must be defined." #endif -/* interface and function clocks */ -static struct clk *iclk, *fclk; +/* interface and function clocks; sometimes also an AHB clock */ +static struct clk *iclk, *fclk, *hclk; static int clocked; extern int usb_disabled(void); /*-------------------------------------------------------------------------*/ +static void at91_start_clock(void) +{ + if (cpu_is_at91sam9261()) + clk_enable(hclk); + clk_enable(iclk); + clk_enable(fclk); + clocked = 1; +} + +static void at91_stop_clock(void) +{ + clk_disable(fclk); + clk_disable(iclk); + if (cpu_is_at91sam9261()) + clk_disable(hclk); + clocked = 0; +} + static void at91_start_hc(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); @@ -41,9 +60,7 @@ static void at91_start_hc(struct platform_device *pdev) /* * Start the USB clocks. */ - clk_enable(iclk); - clk_enable(fclk); - clocked = 1; + at91_start_clock(); /* * The USB host controller must remain in reset. @@ -66,9 +83,7 @@ static void at91_stop_hc(struct platform_device *pdev) /* * Stop the USB clocks. */ - clk_disable(fclk); - clk_disable(iclk); - clocked = 0; + at91_stop_clock(); } @@ -126,6 +141,8 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, iclk = clk_get(&pdev->dev, "ohci_clk"); fclk = clk_get(&pdev->dev, "uhpck"); + if (cpu_is_at91sam9261()) + hclk = clk_get(&pdev->dev, "hck0"); at91_start_hc(pdev); ohci_hcd_init(hcd_to_ohci(hcd)); @@ -137,6 +154,8 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, /* Error handling */ at91_stop_hc(pdev); + if (cpu_is_at91sam9261()) + clk_put(hclk); clk_put(fclk); clk_put(iclk); @@ -171,9 +190,11 @@ static int usb_hcd_at91_remove(struct usb_hcd *hcd, iounmap(hcd->regs); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + if (cpu_is_at91sam9261()) + clk_put(hclk); clk_put(fclk); clk_put(iclk); - fclk = iclk = NULL; + fclk = iclk = hclk = NULL; dev_set_drvdata(&pdev->dev, NULL); return 0; @@ -280,9 +301,7 @@ ohci_hcd_at91_drv_suspend(struct platform_device *pdev, pm_message_t mesg) */ if (at91_suspend_entering_slow_clock()) { ohci_usb_reset (ohci); - clk_disable(fclk); - clk_disable(iclk); - clocked = 0; + at91_stop_clock(); } return 0; @@ -295,11 +314,8 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *pdev) if (device_may_wakeup(&pdev->dev)) disable_irq_wake(hcd->irq); - if (!clocked) { - clk_enable(iclk); - clk_enable(fclk); - clocked = 1; - } + if (!clocked) + at91_start_clock(); return 0; } diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index fa6a7ceaa0d..f0d29eda3c6 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -42,6 +42,9 @@ #include <asm/system.h> #include <asm/unaligned.h> #include <asm/byteorder.h> +#ifdef CONFIG_PPC_PS3 +#include <asm/firmware.h> +#endif #include "../core/hcd.h" @@ -944,9 +947,12 @@ static int __init ohci_hcd_mod_init(void) sizeof (struct ed), sizeof (struct td)); #ifdef PS3_SYSTEM_BUS_DRIVER - retval = ps3_system_bus_driver_register(&PS3_SYSTEM_BUS_DRIVER); - if (retval < 0) - goto error_ps3; + if (firmware_has_feature(FW_FEATURE_PS3_LV1)) { + retval = ps3_system_bus_driver_register( + &PS3_SYSTEM_BUS_DRIVER); + if (retval < 0) + goto error_ps3; + } #endif #ifdef PLATFORM_DRIVER @@ -992,7 +998,8 @@ static int __init ohci_hcd_mod_init(void) error_platform: #endif #ifdef PS3_SYSTEM_BUS_DRIVER - ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); + if (firmware_has_feature(FW_FEATURE_PS3_LV1)) + ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); error_ps3: #endif return retval; @@ -1014,7 +1021,8 @@ static void __exit ohci_hcd_mod_exit(void) platform_driver_unregister(&PLATFORM_DRIVER); #endif #ifdef PS3_SYSTEM_BUS_DRIVER - ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); + if (firmware_has_feature(FW_FEATURE_PS3_LV1)) + ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); #endif } module_exit(ohci_hcd_mod_exit); diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 4d8ed3d71a1..ef09952f203 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -515,6 +515,7 @@ void usbhid_close(struct hid_device *hid) #define USB_VENDOR_ID_TURBOX 0x062a #define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201 +#define USB_VENDOR_ID_CIDC 0x1677 /* * Initialize all reports @@ -548,7 +549,6 @@ void usbhid_init_reports(struct hid_device *hid) } #define USB_VENDOR_ID_GTCO 0x078c -#define USB_VENDOR_ID_GTCO_IPANEL_2 0x5543 #define USB_DEVICE_ID_GTCO_90 0x0090 #define USB_DEVICE_ID_GTCO_100 0x0100 #define USB_DEVICE_ID_GTCO_101 0x0101 @@ -594,8 +594,6 @@ void usbhid_init_reports(struct hid_device *hid) #define USB_DEVICE_ID_GTCO_1004 0x1004 #define USB_DEVICE_ID_GTCO_1005 0x1005 #define USB_DEVICE_ID_GTCO_1006 0x1006 -#define USB_DEVICE_ID_GTCO_8 0x0008 -#define USB_DEVICE_ID_GTCO_d 0x000d #define USB_VENDOR_ID_WACOM 0x056a @@ -854,8 +852,6 @@ static const struct hid_blacklist { { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1004, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1005, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO_IPANEL_2, USB_DEVICE_ID_GTCO_8, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO_IPANEL_2, USB_DEVICE_ID_GTCO_d, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY, HID_QUIRK_IGNORE }, @@ -953,6 +949,8 @@ static const struct hid_blacklist { { USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER, HID_QUIRK_SONY_PS3_CONTROLLER }, + { USB_VENDOR_ID_CIDC, 0x0103, HID_QUIRK_IGNORE }, + { 0, 0 } }; diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index a74bf8617e7..4907e8b8007 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -88,6 +88,17 @@ config USB_LCD To compile this driver as a module, choose M here: the module will be called usblcd. +config USB_BERRY_CHARGE + tristate "USB BlackBerry recharge support" + depends on USB + help + Say Y here if you want to connect a BlackBerry device to your + computer's USB port and have it automatically switch to "recharge" + mode. + + To compile this driver as a module, choose M here: the + module will be called berry_charge. + config USB_LED tristate "USB LED driver support" depends on USB diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 2cba07d3197..dac2d5b7156 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_USB_ADUTUX) += adutux.o obj-$(CONFIG_USB_APPLEDISPLAY) += appledisplay.o obj-$(CONFIG_USB_AUERSWALD) += auerswald.o +obj-$(CONFIG_USB_BERRY_CHARGE) += berry_charge.o obj-$(CONFIG_USB_CYPRESS_CY7C63)+= cypress_cy7c63.o obj-$(CONFIG_USB_CYTHERM) += cytherm.o obj-$(CONFIG_USB_EMI26) += emi26.o diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index 32f0e3a5b02..e573c8ba978 100644 --- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c @@ -281,8 +281,8 @@ static int appledisplay_probe(struct usb_interface *iface, /* Register backlight device */ snprintf(bl_name, sizeof(bl_name), "appledisplay%d", atomic_inc_return(&count_displays) - 1); - pdata->bd = backlight_device_register(bl_name, NULL, - pdata, &appledisplay_bl_data); + pdata->bd = backlight_device_register(bl_name, NULL, pdata, + &appledisplay_bl_data); if (IS_ERR(pdata->bd)) { err("appledisplay: Backlight registration failed"); goto error; diff --git a/drivers/usb/misc/berry_charge.c b/drivers/usb/misc/berry_charge.c new file mode 100644 index 00000000000..60893c6c822 --- /dev/null +++ b/drivers/usb/misc/berry_charge.c @@ -0,0 +1,140 @@ +/* + * USB BlackBerry charging module + * + * Copyright (C) 2007 Greg Kroah-Hartman <gregkh@suse.de> + * + * 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. + * + * Information on how to switch configs was taken by the bcharge.cc file + * created by the barry.sf.net project. + * + * bcharge.cc has the following copyright: + * Copyright (C) 2006, Net Direct Inc. (http://www.netdirect.ca/) + * and is released under the GPLv2. + * + * + */ + +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/usb.h> + +#define RIM_VENDOR 0x0fca +#define BLACKBERRY 0x0001 + +static int debug; + +#ifdef dbg +#undef dbg +#endif +#define dbg(dev, format, arg...) \ + if (debug) \ + dev_printk(KERN_DEBUG , dev , format , ## arg) + +static struct usb_device_id id_table [] = { + { USB_DEVICE(RIM_VENDOR, BLACKBERRY) }, + { }, /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, id_table); + +static int magic_charge(struct usb_device *udev) +{ + char *dummy_buffer = kzalloc(2, GFP_KERNEL); + int retval; + + if (!dummy_buffer) + return -ENOMEM; + + /* send two magic commands and then set the configuration. The device + * will then reset itself with the new power usage and should start + * charging. */ + + /* Note, with testing, it only seems that the first message is really + * needed (at least for the 8700c), but to be safe, we emulate what + * other operating systems seem to be sending to their device. We + * really need to get some specs for this device to be sure about what + * is going on here. + */ + dbg(&udev->dev, "Sending first magic command\n"); + retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + 0xa5, 0xc0, 0, 1, dummy_buffer, 2, 100); + if (retval != 2) { + dev_err(&udev->dev, "First magic command failed: %d.\n", + retval); + return retval; + } + + dbg(&udev->dev, "Sending first magic command\n"); + retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + 0xa2, 0x40, 0, 1, dummy_buffer, 0, 100); + if (retval != 0) { + dev_err(&udev->dev, "Second magic command failed: %d.\n", + retval); + return retval; + } + + dbg(&udev->dev, "Calling set_configuration\n"); + retval = usb_driver_set_configuration(udev, 1); + if (retval) + dev_err(&udev->dev, "Set Configuration failed :%d.\n", retval); + + return retval; +} + +static int berry_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(intf); + + dbg(&udev->dev, "Power is set to %dmA\n", + udev->actconfig->desc.bMaxPower * 2); + + /* check the power usage so we don't try to enable something that is + * already enabled */ + if ((udev->actconfig->desc.bMaxPower * 2) == 500) { + dbg(&udev->dev, "device is already charging, power is " + "set to %dmA\n", udev->actconfig->desc.bMaxPower * 2); + return -ENODEV; + } + + /* turn the power on */ + magic_charge(udev); + + /* we don't really want to bind to the device, userspace programs can + * handle the syncing just fine, so get outta here. */ + return -ENODEV; +} + +static void berry_disconnect(struct usb_interface *intf) +{ +} + +static struct usb_driver berry_driver = { + .name = "berry_charge", + .probe = berry_probe, + .disconnect = berry_disconnect, + .id_table = id_table, +}; + +static int __init berry_init(void) +{ + return usb_register(&berry_driver); +} + +static void __exit berry_exit(void) +{ + usb_deregister(&berry_driver); +} + +module_init(berry_init); +module_exit(berry_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@suse.de>"); +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug enabled or not"); diff --git a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig index a2b94ef512b..0f3d7dbb537 100644 --- a/drivers/usb/net/Kconfig +++ b/drivers/usb/net/Kconfig @@ -84,6 +84,7 @@ config USB_PEGASUS config USB_RTL8150 tristate "USB RTL8150 based ethernet device support (EXPERIMENTAL)" depends on EXPERIMENTAL + select MII help Say Y here if you have RTL8150 based usb-ethernet adapter. Send me <petkan@users.sourceforge.net> any comments you may have. @@ -98,7 +99,7 @@ config USB_USBNET_MII config USB_USBNET tristate "Multi-purpose USB Networking Framework" - select MII if USBNET_MII != n + select MII if USB_USBNET_MII != n ---help--- This driver supports several kinds of network links over USB, with "minidrivers" built around a common network driver core @@ -239,6 +240,7 @@ config USB_NET_RNDIS_HOST config USB_NET_CDC_SUBSET tristate "Simple USB Network Links (CDC Ethernet subset)" depends on USB_USBNET + default y help This driver module supports USB network devices that can work without any device-specific information. Select it if you have @@ -298,6 +300,13 @@ config USB_EPSON2888 Choose this option to support the usb networking links used by some sample firmware from Epson. +config USB_KC2190 + boolean "KT Technology KC2190 based cables (InstaNet)" + depends on USB_NET_CDC_SUBSET && EXPERIMENTAL + help + Choose this option if you're using a host-to-host cable + with one of these chips. + config USB_NET_ZAURUS tristate "Sharp Zaurus (stock ROMs) and compatible" depends on USB_USBNET diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c index bd357e178e5..7ef2e4b5e39 100644 --- a/drivers/usb/net/asix.c +++ b/drivers/usb/net/asix.c @@ -351,9 +351,11 @@ static struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb, skb_push(skb, 4); packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4); + cpu_to_le32s(&packet_len); memcpy(skb->data, &packet_len, sizeof(packet_len)); if ((skb->len % 512) == 0) { + cpu_to_le32s(&padbytes); memcpy( skb->tail, &padbytes, sizeof(padbytes)); skb_put(skb, sizeof(padbytes)); } diff --git a/drivers/usb/net/cdc_subset.c b/drivers/usb/net/cdc_subset.c index ae8fb06cf38..bc62b012602 100644 --- a/drivers/usb/net/cdc_subset.c +++ b/drivers/usb/net/cdc_subset.c @@ -79,13 +79,19 @@ static int always_connected (struct usbnet *dev) * * ALi M5632 driver ... does high speed * + * NOTE that the MS-Windows drivers for this chip use some funky and + * (naturally) undocumented 7-byte prefix to each packet, so this is a + * case where we don't currently interoperate. Also, once you unplug + * one end of the cable, you need to replug the other end too ... since + * chip docs are unavailable, there's no way to reset the relevant state + * short of a power cycle. + * *-------------------------------------------------------------------------*/ static const struct driver_info ali_m5632_info = { .description = "ALi M5632", }; - #endif @@ -159,6 +165,11 @@ static const struct driver_info epson2888_info = { #endif /* CONFIG_USB_EPSON2888 */ +/*------------------------------------------------------------------------- + * + * info from Jonathan McDowell <noodles@earth.li> + * + *-------------------------------------------------------------------------*/ #ifdef CONFIG_USB_KC2190 #define HAVE_HARDWARE static const struct driver_info kc2190_info = { @@ -223,6 +234,10 @@ static const struct usb_device_id products [] = { USB_DEVICE (0x0402, 0x5632), // ALi defaults .driver_info = (unsigned long) &ali_m5632_info, }, +{ + USB_DEVICE (0x182d,0x207c), // SiteCom CN-124 + .driver_info = (unsigned long) &ali_m5632_info, +}, #endif #ifdef CONFIG_USB_AN2720 @@ -314,13 +329,13 @@ static struct usb_driver cdc_subset_driver = { static int __init cdc_subset_init(void) { - return usb_register(&cdc_subset_driver); + return usb_register(&cdc_subset_driver); } module_init(cdc_subset_init); static void __exit cdc_subset_exit(void) { - usb_deregister(&cdc_subset_driver); + usb_deregister(&cdc_subset_driver); } module_exit(cdc_subset_exit); diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c index 43ba61abfcc..de69b183bd2 100644 --- a/drivers/usb/net/usbnet.c +++ b/drivers/usb/net/usbnet.c @@ -147,7 +147,7 @@ int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf) if (tmp < 0) return tmp; } - + dev->in = usb_rcvbulkpipe (dev->udev, in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); dev->out = usb_sndbulkpipe (dev->udev, @@ -327,7 +327,7 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) if (netif_running (dev->net) && netif_device_present (dev->net) && !test_bit (EVENT_RX_HALT, &dev->flags)) { - switch (retval = usb_submit_urb (urb, GFP_ATOMIC)){ + switch (retval = usb_submit_urb (urb, GFP_ATOMIC)){ case -EPIPE: usbnet_defer_kevent (dev, EVENT_RX_HALT); break; @@ -443,7 +443,7 @@ block: case -EOVERFLOW: dev->stats.rx_over_errors++; // FALLTHROUGH - + default: entry->state = rx_cleanup; dev->stats.rx_errors++; @@ -560,7 +560,7 @@ static int usbnet_stop (struct net_device *net) if (netif_msg_ifdown (dev)) devinfo (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld", - dev->stats.rx_packets, dev->stats.tx_packets, + dev->stats.rx_packets, dev->stats.tx_packets, dev->stats.rx_errors, dev->stats.tx_errors ); @@ -578,7 +578,7 @@ static int usbnet_stop (struct net_device *net) devdbg (dev, "waited for %d urb completions", temp); } dev->wait = NULL; - remove_wait_queue (&unlink_wakeup, &wait); + remove_wait_queue (&unlink_wakeup, &wait); usb_kill_urb(dev->interrupt); @@ -834,7 +834,7 @@ kevent (struct work_struct *work) } if (test_bit (EVENT_LINK_RESET, &dev->flags)) { - struct driver_info *info = dev->driver_info; + struct driver_info *info = dev->driver_info; int retval = 0; clear_bit (EVENT_LINK_RESET, &dev->flags); @@ -1066,7 +1066,7 @@ static void usbnet_bh (unsigned long param) * USB Device Driver support * *-------------------------------------------------------------------------*/ - + // precondition: never called in_interrupt void usbnet_disconnect (struct usb_interface *intf) @@ -1087,7 +1087,7 @@ void usbnet_disconnect (struct usb_interface *intf) intf->dev.driver->name, xdev->bus->bus_name, xdev->devpath, dev->driver_info->description); - + net = dev->net; unregister_netdev (net); @@ -1111,7 +1111,7 @@ int usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) { struct usbnet *dev; - struct net_device *net; + struct net_device *net; struct usb_host_interface *interface; struct driver_info *info; struct usb_device *xdev; @@ -1181,6 +1181,9 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) // NOTE net->name still not usable ... if (info->bind) { status = info->bind (dev, udev); + if (status < 0) + goto out1; + // heuristic: "usb%d" for links we know are two-host, // else "eth%d" when there's reasonable doubt. userspace // can rename the link if it knows better. @@ -1207,12 +1210,12 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) if (status == 0 && dev->status) status = init_status (dev, udev); if (status < 0) - goto out1; + goto out3; if (!dev->rx_urb_size) dev->rx_urb_size = dev->hard_mtu; dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1); - + SET_NETDEV_DEV(net, &udev->dev); status = register_netdev (net); if (status) @@ -1255,7 +1258,7 @@ EXPORT_SYMBOL_GPL(usbnet_probe); int usbnet_suspend (struct usb_interface *intf, pm_message_t message) { struct usbnet *dev = usb_get_intfdata(intf); - + /* accelerate emptying of the rx and queues, to avoid * having everything error out. */ @@ -1286,7 +1289,7 @@ static int __init usbnet_init(void) < sizeof (struct skb_data)); random_ether_addr(node_id); - return 0; + return 0; } module_init(usbnet_init); diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c index 0af42e32fa0..18816bf96a4 100644 --- a/drivers/usb/serial/airprime.c +++ b/drivers/usb/serial/airprime.c @@ -58,11 +58,6 @@ static void airprime_read_bulk_callback(struct urb *urb) if (urb->status) { dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); - /* something happened, so free up the memory for this urb */ - if (urb->transfer_buffer) { - kfree (urb->transfer_buffer); - urb->transfer_buffer = NULL; - } return; } usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); @@ -146,6 +141,8 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp) airprime_read_bulk_callback, port); result = usb_submit_urb(urb, GFP_KERNEL); if (result) { + usb_free_urb(urb); + kfree(buffer); dev_err(&port->dev, "%s - failed submitting read urb %d for port %d, error %d\n", __FUNCTION__, i, port->number, result); @@ -160,27 +157,12 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp) /* some error happened, cancel any submitted urbs and clean up anything that got allocated successfully */ - for ( ; i >= 0; --i) { + while (i-- != 0) { urb = priv->read_urbp[i]; - if (urb) { - /* This urb was submitted successfully. So we have to - cancel it. - Unlinking the urb will invoke read_bulk_callback() - with an error status, so its transfer buffer will - be freed there */ - if (usb_unlink_urb (urb) != -EINPROGRESS) { - /* comments in drivers/usb/core/urb.c say this - can only happen if the urb was never submitted, - or has completed already. - Either way we may have to free the transfer - buffer here. */ - if (urb->transfer_buffer) { - kfree (urb->transfer_buffer); - urb->transfer_buffer = NULL; - } - } - usb_free_urb (urb); - } + buffer = urb->transfer_buffer; + usb_kill_urb (urb); + usb_free_urb (urb); + kfree (buffer); } out: @@ -194,10 +176,9 @@ static void airprime_close(struct usb_serial_port *port, struct file * filp) dbg("%s - port %d", __FUNCTION__, port->number); - /* killing the urb will invoke read_bulk_callback() with an error status, - so the transfer buffer will be freed there */ for (i = 0; i < NUM_READ_URBS; ++i) { usb_kill_urb (priv->read_urbp[i]); + kfree (priv->read_urbp[i]->transfer_buffer); usb_free_urb (priv->read_urbp[i]); } diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index 3ec24870bca..db623e75489 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -69,6 +69,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C5, 0xEA61) }, /* Silicon Labs MobiData GPRS USB Modem */ { USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */ { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */ { } /* Terminating Entry */ diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 601e0648dec..53baeec8f26 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -66,6 +66,8 @@ struct usb_serial_driver usb_serial_generic_device = { .num_bulk_out = NUM_DONT_CARE, .num_ports = 1, .shutdown = usb_serial_generic_shutdown, + .throttle = usb_serial_generic_throttle, + .unthrottle = usb_serial_generic_unthrottle, }; static int generic_probe(struct usb_interface *interface, @@ -115,6 +117,7 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp) { struct usb_serial *serial = port->serial; int result = 0; + unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); @@ -124,7 +127,13 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp) if (port->tty) port->tty->low_latency = 1; - /* if we have a bulk interrupt, start reading from it */ + /* clear the throttle flags */ + spin_lock_irqsave(&port->lock, flags); + port->throttled = 0; + port->throttle_req = 0; + spin_unlock_irqrestore(&port->lock, flags); + + /* if we have a bulk endpoint, start reading from it */ if (serial->num_bulk_in) { /* Start reading from the device */ usb_fill_bulk_urb (port->read_urb, serial->dev, @@ -253,31 +262,22 @@ int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port) return (chars); } -void usb_serial_generic_read_bulk_callback (struct urb *urb) +/* Push data to tty layer and resubmit the bulk read URB */ +static void flush_and_resubmit_read_urb (struct usb_serial_port *port) { - struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct usb_serial *serial = port->serial; - struct tty_struct *tty; - unsigned char *data = urb->transfer_buffer; + struct urb *urb = port->read_urb; + struct tty_struct *tty = port->tty; int result; - dbg("%s - port %d", __FUNCTION__, port->number); - - if (urb->status) { - dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); - return; - } - - usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); - - tty = port->tty; + /* Push data to tty */ if (tty && urb->actual_length) { tty_buffer_request_room(tty, urb->actual_length); - tty_insert_flip_string(tty, data, urb->actual_length); - tty_flip_buffer_push(tty); + tty_insert_flip_string(tty, urb->transfer_buffer, urb->actual_length); + tty_flip_buffer_push(tty); /* is this allowed from an URB callback ? */ } - /* Continue trying to always read */ + /* Continue reading from device */ usb_fill_bulk_urb (port->read_urb, serial->dev, usb_rcvbulkpipe (serial->dev, port->bulk_in_endpointAddress), @@ -290,6 +290,40 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb) if (result) dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); } + +void usb_serial_generic_read_bulk_callback (struct urb *urb) +{ + struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + unsigned char *data = urb->transfer_buffer; + int is_throttled; + unsigned long flags; + + dbg("%s - port %d", __FUNCTION__, port->number); + + if (urb->status) { + dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); + return; + } + + usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); + + /* Throttle the device if requested by tty */ + if (urb->actual_length) { + spin_lock_irqsave(&port->lock, flags); + is_throttled = port->throttled = port->throttle_req; + spin_unlock_irqrestore(&port->lock, flags); + if (is_throttled) { + /* Let the received data linger in the read URB; + * usb_serial_generic_unthrottle() will pick it + * up later. */ + dbg("%s - throttling device", __FUNCTION__); + return; + } + } + + /* Handle data and continue reading from device */ + flush_and_resubmit_read_urb(port); +} EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback); void usb_serial_generic_write_bulk_callback (struct urb *urb) @@ -308,6 +342,38 @@ void usb_serial_generic_write_bulk_callback (struct urb *urb) } EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); +void usb_serial_generic_throttle (struct usb_serial_port *port) +{ + unsigned long flags; + + dbg("%s - port %d", __FUNCTION__, port->number); + + /* Set the throttle request flag. It will be picked up + * by usb_serial_generic_read_bulk_callback(). */ + spin_lock_irqsave(&port->lock, flags); + port->throttle_req = 1; + spin_unlock_irqrestore(&port->lock, flags); +} + +void usb_serial_generic_unthrottle (struct usb_serial_port *port) +{ + int was_throttled; + unsigned long flags; + + dbg("%s - port %d", __FUNCTION__, port->number); + + /* Clear the throttle flags */ + spin_lock_irqsave(&port->lock, flags); + was_throttled = port->throttled; + port->throttled = port->throttle_req = 0; + spin_unlock_irqrestore(&port->lock, flags); + + if (was_throttled) { + /* Handle pending data and resume reading from device */ + flush_and_resubmit_read_urb(port); + } +} + void usb_serial_generic_shutdown (struct usb_serial *serial) { int i; diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index ced9f32b29d..9963a8b7584 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -69,7 +69,6 @@ static int option_send_setup(struct usb_serial_port *port); /* Vendor and product IDs */ #define OPTION_VENDOR_ID 0x0AF0 #define HUAWEI_VENDOR_ID 0x12D1 -#define AUDIOVOX_VENDOR_ID 0x0F3D #define NOVATELWIRELESS_VENDOR_ID 0x1410 #define ANYDATA_VENDOR_ID 0x16d5 @@ -81,7 +80,6 @@ static int option_send_setup(struct usb_serial_port *port); #define OPTION_PRODUCT_GTMAX36 0x6701 #define HUAWEI_PRODUCT_E600 0x1001 #define HUAWEI_PRODUCT_E220 0x1003 -#define AUDIOVOX_PRODUCT_AIRCARD 0x0112 #define NOVATELWIRELESS_PRODUCT_U740 0x1400 #define ANYDATA_PRODUCT_ID 0x6501 @@ -94,7 +92,6 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTMAX36) }, { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) }, - { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) }, { } /* Terminating entry */ @@ -109,7 +106,6 @@ static struct usb_device_id option_ids1[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTMAX36) }, { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) }, - { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) }, { } /* Terminating entry */ diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 6c083d4e2c9..83dfae93a45 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -83,6 +83,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) }, { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) }, { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ID) }, + { USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index 65a5039665e..f9a71d0c102 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -97,3 +97,8 @@ /* Huawei E620 UMTS/HSDPA card (ID: 12d1:1001) */ #define HUAWEI_VENDOR_ID 0x12d1 #define HUAWEI_PRODUCT_ID 0x1001 + +/* Willcom WS002IN Data Driver (by NetIndex Inc.) */ +#define WS002IN_VENDOR_ID 0x11f6 +#define WS002IN_PRODUCT_ID 0x2001 + diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 70234f5dbee..e227f64d564 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -153,6 +153,12 @@ static int slave_configure(struct scsi_device *sdev) if (us->flags & US_FL_FIX_CAPACITY) sdev->fix_capacity = 1; + /* A few disks have two indistinguishable version, one of + * which reports the correct capacity and the other does not. + * The sd driver has to guess which is the case. */ + if (us->flags & US_FL_CAPACITY_HEURISTICS) + sdev->guess_capacity = 1; + /* Some devices report a SCSI revision level above 2 but are * unable to handle the REPORT LUNS command (for which * support is mandatory at level 3). Since we already have diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index f49a62fc32d..9644a8ea4aa 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1101,6 +1101,15 @@ UNUSUAL_DEV( 0x08bd, 0x1100, 0x0000, 0x0000, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_SINGLE_LUN), +/* Submitted by Dylan Taft <d13f00l@gmail.com> + * US_FL_IGNORE_RESIDUE Needed + */ +UNUSUAL_DEV( 0x08ca, 0x3103, 0x0100, 0x0100, + "AIPTEK", + "Aiptek USB Keychain MP3 Player", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE), + /* Entry needed for flags. Moreover, all devices with this ID use * bulk-only transport, but _some_ falsely report Control/Bulk instead. * One example is "Trumpion Digital Research MYMP3". @@ -1311,12 +1320,13 @@ UNUSUAL_DEV( 0x0fce, 0xd008, 0x0000, 0x0000, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NO_WP_DETECT ), -/* Reported by Jan Mate <mate@fiit.stuba.sk> */ +/* Reported by Jan Mate <mate@fiit.stuba.sk> + * and by Soeren Sonnenburg <kernel@nn7.de> */ UNUSUAL_DEV( 0x0fce, 0xe030, 0x0000, 0x0000, "Sony Ericsson", "P990i", US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_FIX_CAPACITY ), + US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ), /* Reported by Emmanuel Vasilakis <evas@forthnet.gr> */ UNUSUAL_DEV( 0x0fce, 0xe031, 0x0000, 0x0000, @@ -1385,6 +1395,16 @@ UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), +/* Reported by Thomas Baechler <thomas@archlinux.org> + * Fixes I/O errors with Teac HD-35PU devices + */ + +UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201, + "Super Top", + "USB 2.0 IDE DEVICE", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE), + /* patch submitted by Davide Perini <perini.davide@dpsoftware.org> * and Renato Perini <rperini@email.it> */ @@ -1423,7 +1443,7 @@ UNUSUAL_DEV( 0xed06, 0x4500, 0x0001, 0x0001, "DataStor", "USB4500 FW1.04", US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_FIX_CAPACITY), + US_FL_CAPACITY_HEURISTICS), /* Control/Bulk transport for all SubClass values */ USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR), diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index 296b091cf16..46929a1b6f2 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -90,13 +90,15 @@ static int skel_open(struct inode *inode, struct file *file) goto exit; } + /* increment our usage count for the device */ + kref_get(&dev->kref); + /* prevent the device from being autosuspended */ retval = usb_autopm_get_interface(interface); - if (retval) + if (retval) { + kref_put(&dev->kref, skel_delete); goto exit; - - /* increment our usage count for the device */ - kref_get(&dev->kref); + } /* save our object in the file's private structure */ file->private_data = dev; |