diff options
Diffstat (limited to 'drivers')
111 files changed, 4927 insertions, 1862 deletions
diff --git a/drivers/Makefile b/drivers/Makefile index 46c8681a07f..a0a2e3b675d 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -82,6 +82,7 @@ obj-$(CONFIG_EISA) += eisa/ obj-y += lguest/ obj-$(CONFIG_CPU_FREQ) += cpufreq/ obj-$(CONFIG_CPU_IDLE) += cpuidle/ +obj-y += idle/ obj-$(CONFIG_MMC) += mmc/ obj-$(CONFIG_MEMSTICK) += memstick/ obj-$(CONFIG_NEW_LEDS) += leds/ diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index da49b006bcc..dc1de722442 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -42,7 +42,7 @@ if ACPI config ACPI_SLEEP bool - depends on PM_SLEEP + depends on SUSPEND || HIBERNATION default y config ACPI_PROCFS @@ -160,15 +160,8 @@ config ACPI_DOCK tristate "Dock" depends on EXPERIMENTAL help - This driver adds support for ACPI controlled docking stations - -config ACPI_BAY - tristate "Removable Drive Bay (EXPERIMENTAL)" - depends on EXPERIMENTAL - depends on ACPI_DOCK - help - This driver adds support for ACPI controlled removable drive - bays such as the IBM ultrabay or the Dell Module Bay. + This driver adds support for ACPI controlled docking stations and removable + drive bays such as the IBM ultrabay or the Dell Module Bay. config ACPI_PROCESSOR tristate "Processor" diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 52a4cd4b81d..ad4bfd558ff 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -45,7 +45,6 @@ obj-$(CONFIG_ACPI_BATTERY) += battery.o obj-$(CONFIG_ACPI_BUTTON) += button.o 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-y += pci_root.o pci_link.o pci_irq.o pci_bind.o obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 831883b7d6c..d72a1b6c8a9 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -85,7 +85,7 @@ struct acpi_ac { struct power_supply charger; #endif struct acpi_device * device; - unsigned long state; + unsigned long long state; }; #define to_acpi_ac(x) container_of(x, struct acpi_ac, charger); @@ -269,7 +269,7 @@ static int acpi_ac_add(struct acpi_device *device) ac->device = device; strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_AC_CLASS); - acpi_driver_data(device) = ac; + device->driver_data = ac; result = acpi_ac_get_state(ac); if (result) diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 5f1127ad5a9..71d21c51c45 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -194,8 +194,7 @@ acpi_memory_get_device(acpi_handle handle, static int acpi_memory_check_device(struct acpi_memory_device *mem_device) { - unsigned long current_status; - + unsigned long long current_status; /* Get device present/absent information from the _STA */ if (ACPI_FAILURE(acpi_evaluate_integer(mem_device->device->handle, "_STA", @@ -264,7 +263,7 @@ static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device) acpi_status status; struct acpi_object_list arg_list; union acpi_object arg; - unsigned long current_status; + unsigned long long current_status; /* Issue the _EJ0 command */ @@ -403,7 +402,7 @@ static int acpi_memory_device_add(struct acpi_device *device) mem_device->device = device; sprintf(acpi_device_name(device), "%s", ACPI_MEMORY_DEVICE_NAME); sprintf(acpi_device_class(device), "%s", ACPI_MEMORY_DEVICE_CLASS); - acpi_driver_data(device) = mem_device; + device->driver_data = mem_device; /* Get the range from the _CRS */ result = acpi_memory_get_device_resources(mem_device); @@ -454,8 +453,8 @@ static int acpi_memory_device_start (struct acpi_device *device) /* call add_memory func */ result = acpi_memory_enable_device(mem_device); if (result) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error in acpi_memory_enable_device\n")); + printk(KERN_ERR PREFIX + "Error in acpi_memory_enable_device\n"); } return result; } diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c index d3d0886d637..1e74988c7b2 100644 --- a/drivers/acpi/asus_acpi.c +++ b/drivers/acpi/asus_acpi.c @@ -42,7 +42,7 @@ #define ASUS_ACPI_VERSION "0.30" -#define PROC_ASUS "asus" //the directory +#define PROC_ASUS "asus" /* The directory */ #define PROC_MLED "mled" #define PROC_WLED "wled" #define PROC_TLED "tled" @@ -66,10 +66,10 @@ /* * Flags for hotk status */ -#define MLED_ON 0x01 //mail LED -#define WLED_ON 0x02 //wireless LED -#define TLED_ON 0x04 //touchpad LED -#define BT_ON 0x08 //internal Bluetooth +#define MLED_ON 0x01 /* Mail LED */ +#define WLED_ON 0x02 /* Wireless LED */ +#define TLED_ON 0x04 /* Touchpad LED */ +#define BT_ON 0x08 /* Internal Bluetooth */ MODULE_AUTHOR("Julien Lerouge, Karol Kozimor"); MODULE_DESCRIPTION(ACPI_HOTK_NAME); @@ -82,28 +82,28 @@ MODULE_PARM_DESC(asus_uid, "UID for entries in /proc/acpi/asus"); module_param(asus_gid, uint, 0); MODULE_PARM_DESC(asus_gid, "GID for entries in /proc/acpi/asus"); -/* For each model, all features implemented, +/* For each model, all features implemented, * those marked with R are relative to HOTK, A for absolute */ struct model_data { - char *name; //name of the laptop________________A - char *mt_mled; //method to handle mled_____________R - char *mled_status; //node to handle mled reading_______A - char *mt_wled; //method to handle wled_____________R - char *wled_status; //node to handle wled reading_______A - char *mt_tled; //method to handle tled_____________R - char *tled_status; //node to handle tled reading_______A - char *mt_ledd; //method to handle LED display______R - char *mt_bt_switch; //method to switch Bluetooth on/off_R - char *bt_status; //no model currently supports this__? - char *mt_lcd_switch; //method to turn LCD on/off_________A - char *lcd_status; //node to read LCD panel state______A - char *brightness_up; //method to set brightness up_______A - char *brightness_down; //guess what ?______________________A - char *brightness_set; //method to set absolute brightness_R - char *brightness_get; //method to get absolute brightness_R - char *brightness_status; //node to get brightness____________A - char *display_set; //method to set video output________R - char *display_get; //method to get video output________R + char *name; /* name of the laptop________________A */ + char *mt_mled; /* method to handle mled_____________R */ + char *mled_status; /* node to handle mled reading_______A */ + char *mt_wled; /* method to handle wled_____________R */ + char *wled_status; /* node to handle wled reading_______A */ + char *mt_tled; /* method to handle tled_____________R */ + char *tled_status; /* node to handle tled reading_______A */ + char *mt_ledd; /* method to handle LED display______R */ + char *mt_bt_switch; /* method to switch Bluetooth on/off_R */ + char *bt_status; /* no model currently supports this__? */ + char *mt_lcd_switch; /* method to turn LCD on/off_________A */ + char *lcd_status; /* node to read LCD panel state______A */ + char *brightness_up; /* method to set brightness up_______A */ + char *brightness_down; /* method to set brightness down ____A */ + char *brightness_set; /* method to set absolute brightness_R */ + char *brightness_get; /* method to get absolute brightness_R */ + char *brightness_status;/* node to get brightness____________A */ + char *display_set; /* method to set video output________R */ + char *display_get; /* method to get video output________R */ }; /* @@ -111,41 +111,41 @@ struct model_data { * about the hotk device */ struct asus_hotk { - struct acpi_device *device; //the device we are in - acpi_handle handle; //the handle of the hotk device - char status; //status of the hotk, for LEDs, ... - u32 ledd_status; //status of the LED display - struct model_data *methods; //methods available on the laptop - u8 brightness; //brightness level + struct acpi_device *device; /* the device we are in */ + acpi_handle handle; /* the handle of the hotk device */ + char status; /* status of the hotk, for LEDs */ + u32 ledd_status; /* status of the LED display */ + struct model_data *methods; /* methods available on the laptop */ + u8 brightness; /* brightness level */ enum { - A1x = 0, //A1340D, A1300F - A2x, //A2500H - A4G, //A4700G - D1x, //D1 - L2D, //L2000D - L3C, //L3800C - L3D, //L3400D - L3H, //L3H, L2000E, L5D - L4R, //L4500R - L5x, //L5800C - L8L, //L8400L - M1A, //M1300A - M2E, //M2400E, L4400L - M6N, //M6800N, W3400N - M6R, //M6700R, A3000G - P30, //Samsung P30 - S1x, //S1300A, but also L1400B and M2400A (L84F) - S2x, //S200 (J1 reported), Victor MP-XP7210 - W1N, //W1000N - W5A, //W5A - W3V, //W3030V - xxN, //M2400N, M3700N, M5200N, M6800N, S1300N, S5200N - A4S, //Z81sp - //(Centrino) - F3Sa, + A1x = 0, /* A1340D, A1300F */ + A2x, /* A2500H */ + A4G, /* A4700G */ + D1x, /* D1 */ + L2D, /* L2000D */ + L3C, /* L3800C */ + L3D, /* L3400D */ + L3H, /* L3H, L2000E, L5D */ + L4R, /* L4500R */ + L5x, /* L5800C */ + L8L, /* L8400L */ + M1A, /* M1300A */ + M2E, /* M2400E, L4400L */ + M6N, /* M6800N, W3400N */ + M6R, /* M6700R, A3000G */ + P30, /* Samsung P30 */ + S1x, /* S1300A, but also L1400B and M2400A (L84F) */ + S2x, /* S200 (J1 reported), Victor MP-XP7210 */ + W1N, /* W1000N */ + W5A, /* W5A */ + W3V, /* W3030V */ + xxN, /* M2400N, M3700N, M5200N, M6800N, + S1300N, S5200N*/ + A4S, /* Z81sp */ + F3Sa, /* (Centrino) */ END_MODEL - } model; //Models currently supported - u16 event_count[128]; //count for each event TODO make this better + } model; /* Models currently supported */ + u16 event_count[128]; /* Count for each event TODO make this better */ }; /* Here we go */ @@ -459,18 +459,18 @@ static struct acpi_driver asus_hotk_driver = { }, }; -/* +/* * 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. + * 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 + struct acpi_object_list params; /* list of input parameters (int) */ + union acpi_object in_obj; /* the only param we use */ acpi_status status; params.count = 1; @@ -507,18 +507,18 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof, { int len = 0; int temp; - char buf[16]; //enough for all info + char buf[16]; /* enough for all info */ /* - * We use the easy way, we don't care of off and count, so we don't set eof - * to 1 + * We use the easy way, we don't care of off and count, + * so we don't set eof to 1 */ len += sprintf(page, ACPI_HOTK_NAME " " ASUS_ACPI_VERSION "\n"); len += sprintf(page + len, "Model reference : %s\n", hotk->methods->name); - /* - * The SFUN method probably allows the original driver to get the list - * of features supported by a given model. For now, 0x0100 or 0x0800 + /* + * The SFUN method probably allows the original driver to get the list + * of features supported by a given model. For now, 0x0100 or 0x0800 * bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card. * The significance of others is yet to be found. */ @@ -528,7 +528,7 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof, /* * Another value for userspace: the ASYM method returns 0x02 for * battery low and 0x04 for battery critical, its readings tend to be - * more accurate than those provided by _BST. + * more accurate than those provided by _BST. * Note: since not all the laptops provide this method, errors are * silently ignored. */ @@ -579,7 +579,7 @@ static int read_led(const char *ledname, int ledmask) return (hotk->status & ledmask) ? 1 : 0; } -static int parse_arg(const char __user * buf, unsigned long count, int *val) +static int parse_arg(const char __user *buf, unsigned long count, int *val) { char s[32]; if (!count) @@ -596,7 +596,7 @@ static int parse_arg(const char __user * buf, unsigned long count, int *val) /* FIXME: kill extraneous args so it can be called independently */ static int -write_led(const char __user * buffer, unsigned long count, +write_led(const char __user *buffer, unsigned long count, char *ledname, int ledmask, int invert) { int rv, value; @@ -631,7 +631,7 @@ proc_read_mled(char *page, char **start, off_t off, int count, int *eof, } static int -proc_write_mled(struct file *file, const char __user * buffer, +proc_write_mled(struct file *file, const char __user *buffer, unsigned long count, void *data) { return write_led(buffer, count, hotk->methods->mt_mled, MLED_ON, 1); @@ -648,7 +648,7 @@ proc_read_ledd(char *page, char **start, off_t off, int count, int *eof, } static int -proc_write_ledd(struct file *file, const char __user * buffer, +proc_write_ledd(struct file *file, const char __user *buffer, unsigned long count, void *data) { int rv, value; @@ -677,7 +677,7 @@ proc_read_wled(char *page, char **start, off_t off, int count, int *eof, } static int -proc_write_wled(struct file *file, const char __user * buffer, +proc_write_wled(struct file *file, const char __user *buffer, unsigned long count, void *data) { return write_led(buffer, count, hotk->methods->mt_wled, WLED_ON, 0); @@ -694,10 +694,10 @@ proc_read_bluetooth(char *page, char **start, off_t off, int count, int *eof, } static int -proc_write_bluetooth(struct file *file, const char __user * buffer, +proc_write_bluetooth(struct file *file, const char __user *buffer, unsigned long count, void *data) { - /* Note: mt_bt_switch controls both internal Bluetooth adapter's + /* Note: mt_bt_switch controls both internal Bluetooth adapter's presence and its LED */ return write_led(buffer, count, hotk->methods->mt_bt_switch, BT_ON, 0); } @@ -714,7 +714,7 @@ proc_read_tled(char *page, char **start, off_t off, int count, int *eof, } static int -proc_write_tled(struct file *file, const char __user * buffer, +proc_write_tled(struct file *file, const char __user *buffer, unsigned long count, void *data) { return write_led(buffer, count, hotk->methods->mt_tled, TLED_ON, 0); @@ -734,7 +734,7 @@ static int get_lcd_state(void) input.count = 2; input.pointer = mt_params; - /* Note: the following values are partly guessed up, but + /* Note: the following values are partly guessed up, but otherwise they seem to work */ mt_params[0].type = ACPI_TYPE_INTEGER; mt_params[0].integer.value = 0x02; @@ -753,7 +753,7 @@ static int get_lcd_state(void) /* That's what the AML code does */ lcd = out_obj.integer.value >> 8; } else if (hotk->model == F3Sa) { - unsigned long tmp; + unsigned long long tmp; union acpi_object param; struct acpi_object_list input; acpi_status status; @@ -796,12 +796,13 @@ static int set_lcd_state(int value) acpi_evaluate_object(NULL, hotk->methods->mt_lcd_switch, NULL, NULL); - } else { /* L3H and the like have to be handled differently */ + } else { + /* L3H and the like must be handled differently */ if (!write_acpi_int (hotk->handle, hotk->methods->mt_lcd_switch, 0x07, NULL)) status = AE_ERROR; - /* L3H's AML executes EHK (0x07) upon Fn+F7 keypress, + /* L3H's AML executes EHK (0x07) upon Fn+F7 keypress, the exact behaviour is simulated here */ } if (ACPI_FAILURE(status)) @@ -819,7 +820,7 @@ proc_read_lcd(char *page, char **start, off_t off, int count, int *eof, } static int -proc_write_lcd(struct file *file, const char __user * buffer, +proc_write_lcd(struct file *file, const char __user *buffer, unsigned long count, void *data) { int rv, value; @@ -897,7 +898,7 @@ proc_read_brn(char *page, char **start, off_t off, int count, int *eof, } static int -proc_write_brn(struct file *file, const char __user * buffer, +proc_write_brn(struct file *file, const char __user *buffer, unsigned long count, void *data) { int rv, value; @@ -921,7 +922,7 @@ static void set_display(int value) } /* - * Now, *this* one could be more user-friendly, but so far, no-one has + * Now, *this* one could be more user-friendly, but so far, no-one has * complained. The significance of bits is the same as in proc_write_disp() */ static int @@ -933,18 +934,18 @@ proc_read_disp(char *page, char **start, off_t off, int count, int *eof, if (!read_acpi_int(hotk->handle, hotk->methods->display_get, &value)) printk(KERN_WARNING "Asus ACPI: Error reading display status\n"); - value &= 0x07; /* needed for some models, shouldn't hurt others */ + value &= 0x07; /* needed for some models, shouldn't hurt others */ return sprintf(page, "%d\n", value); } /* - * Experimental support for display switching. As of now: 1 should activate - * the LCD output, 2 should do for CRT, and 4 for TV-Out. Any combination - * (bitwise) of these will suffice. I never actually tested 3 displays hooked up - * simultaneously, so be warned. See the acpi4asus README for more info. + * Experimental support for display switching. As of now: 1 should activate + * the LCD output, 2 should do for CRT, and 4 for TV-Out. Any combination + * (bitwise) of these will suffice. I never actually tested 3 displays hooked + * up simultaneously, so be warned. See the acpi4asus README for more info. */ static int -proc_write_disp(struct file *file, const char __user * buffer, +proc_write_disp(struct file *file, const char __user *buffer, unsigned long count, void *data) { int rv, value; @@ -957,12 +958,12 @@ proc_write_disp(struct file *file, const char __user * buffer, typedef int (proc_readfunc) (char *page, char **start, off_t off, int count, int *eof, void *data); -typedef int (proc_writefunc) (struct file * file, const char __user * buffer, +typedef int (proc_writefunc) (struct file *file, const char __user *buffer, unsigned long count, void *data); static int -asus_proc_add(char *name, proc_writefunc * writefunc, - proc_readfunc * readfunc, mode_t mode, +asus_proc_add(char *name, proc_writefunc *writefunc, + proc_readfunc *readfunc, mode_t mode, struct acpi_device *device) { struct proc_dir_entry *proc = @@ -1040,9 +1041,9 @@ static int asus_hotk_add_fs(struct acpi_device *device) &proc_read_bluetooth, mode, device); } - /* - * We need both read node and write method as LCD switch is also accessible - * from keyboard + /* + * We need both read node and write method as LCD switch is also + * accessible from the keyboard */ if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status) { asus_proc_add(PROC_LCD, &proc_write_lcd, &proc_read_lcd, mode, @@ -1096,11 +1097,10 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) if (!hotk) return; - if ((event & ~((u32) BR_UP)) < 16) { + if ((event & ~((u32) BR_UP)) < 16) hotk->brightness = (event & ~((u32) BR_UP)); - } else if ((event & ~((u32) BR_DOWN)) < 16) { + else if ((event & ~((u32) BR_DOWN)) < 16) hotk->brightness = (event & ~((u32) BR_DOWN)); - } acpi_bus_generate_proc_event(hotk->device, event, hotk->event_count[event % 128]++); @@ -1186,8 +1186,8 @@ static int asus_hotk_get_info(void) acpi_status status; /* - * Get DSDT headers early enough to allow for differentiating between - * models, but late enough to allow acpi_bus_register_driver() to fail + * Get DSDT headers early enough to allow for differentiating between + * models, but late enough to allow acpi_bus_register_driver() to fail * before doing anything ACPI-specific. Should we encounter a machine, * which needs special handling (i.e. its hotkey device has a different * HID), this bit will be moved. A global variable asus_info contains @@ -1212,8 +1212,8 @@ static int asus_hotk_get_info(void) /* * Try to match the object returned by INIT to the specific model. - * Handle every possible object (or the lack of thereof) the DSDT - * writers might throw at us. When in trouble, we pass NULL to + * Handle every possible object (or the lack of thereof) the DSDT + * writers might throw at us. When in trouble, we pass NULL to * asus_model_match() and try something completely different. */ if (buffer.pointer) { @@ -1244,6 +1244,8 @@ static int asus_hotk_get_info(void) "default values\n", string); printk(KERN_NOTICE " send /proc/acpi/dsdt to the developers\n"); + kfree(model); + return -ENODEV; } hotk->methods = &model_conf[hotk->model]; return AE_OK; @@ -1254,7 +1256,7 @@ static int asus_hotk_get_info(void) /* Sort of per-model blacklist */ if (strncmp(string, "L2B", 3) == 0) hotk->methods->lcd_status = NULL; - /* L2B is similar enough to L3C to use its settings, with this only + /* L2B is similar enough to L3C to use its settings, with this only exception */ else if (strncmp(string, "A3G", 3) == 0) hotk->methods->lcd_status = "\\BLFG"; @@ -1321,7 +1323,7 @@ static int asus_hotk_add(struct acpi_device *device) hotk->handle = device->handle; strcpy(acpi_device_name(device), ACPI_HOTK_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_HOTK_CLASS); - acpi_driver_data(device) = hotk; + device->driver_data = hotk; hotk->device = device; result = asus_hotk_check(); @@ -1366,10 +1368,9 @@ static int asus_hotk_add(struct acpi_device *device) /* LED display is off by default */ hotk->ledd_status = 0xFFF; - end: - if (result) { +end: + if (result) kfree(hotk); - } return result; } @@ -1394,8 +1395,8 @@ static int asus_hotk_remove(struct acpi_device *device, int type) } static struct backlight_ops asus_backlight_data = { - .get_brightness = read_brightness, - .update_status = set_brightness_status, + .get_brightness = read_brightness, + .update_status = set_brightness_status, }; static void asus_acpi_exit(void) @@ -1442,15 +1443,15 @@ static int __init asus_acpi_init(void) return -ENODEV; } - asus_backlight_device = backlight_device_register("asus",NULL,NULL, + asus_backlight_device = backlight_device_register("asus", NULL, NULL, &asus_backlight_data); - if (IS_ERR(asus_backlight_device)) { + if (IS_ERR(asus_backlight_device)) { printk(KERN_ERR "Could not register asus backlight device\n"); asus_backlight_device = NULL; asus_acpi_exit(); return -ENODEV; } - asus_backlight_device->props.max_brightness = 15; + asus_backlight_device->props.max_brightness = 15; return 0; } diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 70f7f60929c..b2133e89ad9 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -804,7 +804,7 @@ static int acpi_battery_add(struct acpi_device *device) battery->device = device; strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS); - acpi_driver_data(device) = battery; + device->driver_data = battery; mutex_init(&battery->lock); acpi_battery_update(battery); #ifdef CONFIG_ACPI_PROCFS_POWER diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c deleted file mode 100644 index 61b6c5beb2d..00000000000 --- a/drivers/acpi/bay.c +++ /dev/null @@ -1,411 +0,0 @@ -/* - * bay.c - ACPI removable drive bay driver - * - * Copyright (C) 2006 Kristen Carlson Accardi <kristen.c.accardi@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/notifier.h> -#include <acpi/acpi_bus.h> -#include <acpi/acpi_drivers.h> -#include <linux/seq_file.h> -#include <asm/uaccess.h> -#include <linux/platform_device.h> - -ACPI_MODULE_NAME("bay"); -MODULE_AUTHOR("Kristen Carlson Accardi"); -MODULE_DESCRIPTION("ACPI Removable Drive Bay Driver"); -MODULE_LICENSE("GPL"); -#define ACPI_BAY_CLASS "bay" -#define ACPI_BAY_COMPONENT 0x10000000 -#define _COMPONENT ACPI_BAY_COMPONENT -#define bay_dprintk(h,s) {\ - char prefix[80] = {'\0'};\ - struct acpi_buffer buffer = {sizeof(prefix), prefix};\ - 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 const struct acpi_device_id bay_device_ids[] = { - {"LNXIOBAY", 0}, - {"", 0}, -}; -MODULE_DEVICE_TABLE(acpi, bay_device_ids); - -struct bay { - acpi_handle handle; - char *name; - struct list_head list; - struct platform_device *pdev; -}; - -static LIST_HEAD(drive_bays); - - -/***************************************************************************** - * Drive Bay functions * - *****************************************************************************/ -/** - * is_ejectable - see if a device is ejectable - * @handle: acpi handle of the device - * - * If an acpi object has a _EJ0 method, then it is ejectable - */ -static int is_ejectable(acpi_handle handle) -{ - acpi_status status; - acpi_handle tmp; - - status = acpi_get_handle(handle, "_EJ0", &tmp); - if (ACPI_FAILURE(status)) - return 0; - return 1; -} - -/** - * bay_present - see if the bay device is present - * @bay: the drive bay - * - * execute the _STA method. - */ -static int bay_present(struct bay *bay) -{ - unsigned long sta; - acpi_status status; - - if (bay) { - status = acpi_evaluate_integer(bay->handle, "_STA", NULL, &sta); - if (ACPI_SUCCESS(status) && sta) - return 1; - } - return 0; -} - -/** - * eject_device - respond to an eject request - * @handle - the device to eject - * - * Call this devices _EJ0 method. - */ -static void eject_device(acpi_handle handle) -{ - struct acpi_object_list arg_list; - union acpi_object arg; - - bay_dprintk(handle, "Ejecting device"); - - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = 1; - - if (ACPI_FAILURE(acpi_evaluate_object(handle, "_EJ0", - &arg_list, NULL))) - pr_debug("Failed to evaluate _EJ0!\n"); -} - -/* - * show_present - read method for "present" file in sysfs - */ -static ssize_t show_present(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct bay *bay = dev_get_drvdata(dev); - return snprintf(buf, PAGE_SIZE, "%d\n", bay_present(bay)); - -} -static DEVICE_ATTR(present, S_IRUGO, show_present, NULL); - -/* - * write_eject - write method for "eject" file in sysfs - */ -static ssize_t write_eject(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct bay *bay = dev_get_drvdata(dev); - - if (!count) - return -EINVAL; - - eject_device(bay->handle); - return count; -} -static DEVICE_ATTR(eject, S_IWUSR, NULL, write_eject); - -/** - * is_ata - see if a device is an ata device - * @handle: acpi handle of the device - * - * If an acpi object has one of 4 ATA ACPI methods defined, - * then it is an ATA device - */ -static int is_ata(acpi_handle handle) -{ - acpi_handle tmp; - - if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp)))) - return 1; - - return 0; -} - -/** - * parent_is_ata(acpi_handle handle) - * - */ -static int parent_is_ata(acpi_handle handle) -{ - acpi_handle phandle; - - if (acpi_get_parent(handle, &phandle)) - return 0; - - return is_ata(phandle); -} - -/** - * is_ejectable_bay - see if a device is an ejectable drive bay - * @handle: acpi handle of the device - * - * If an acpi object is ejectable and has one of the ACPI ATA - * methods defined, then we can safely call it an ejectable - * drive bay - */ -static int is_ejectable_bay(acpi_handle handle) -{ - if ((is_ata(handle) || parent_is_ata(handle)) && is_ejectable(handle)) - return 1; - return 0; -} - -#if 0 -/** - * eject_removable_drive - try to eject this drive - * @dev : the device structure of the drive - * - * If a device is a removable drive that requires an _EJ0 method - * to be executed in order to safely remove from the system, do - * it. ATM - always returns success - */ -int eject_removable_drive(struct device *dev) -{ - acpi_handle handle = DEVICE_ACPI_HANDLE(dev); - - if (handle) { - bay_dprintk(handle, "Got device handle"); - if (is_ejectable_bay(handle)) - eject_device(handle); - } else { - printk("No acpi handle for device\n"); - } - - /* should I return an error code? */ - return 0; -} -EXPORT_SYMBOL_GPL(eject_removable_drive); -#endif /* 0 */ - -static int acpi_bay_add_fs(struct bay *bay) -{ - int ret; - struct device *dev = &bay->pdev->dev; - - ret = device_create_file(dev, &dev_attr_present); - if (ret) - goto add_fs_err; - ret = device_create_file(dev, &dev_attr_eject); - if (ret) { - device_remove_file(dev, &dev_attr_present); - goto add_fs_err; - } - return 0; - - add_fs_err: - bay_dprintk(bay->handle, "Error adding sysfs files\n"); - return ret; -} - -static void acpi_bay_remove_fs(struct bay *bay) -{ - struct device *dev = &bay->pdev->dev; - - /* cleanup sysfs */ - device_remove_file(dev, &dev_attr_present); - device_remove_file(dev, &dev_attr_eject); -} - -static int bay_is_dock_device(acpi_handle handle) -{ - acpi_handle parent; - - acpi_get_parent(handle, &parent); - - /* if the device or it's parent is dependent on the - * dock, then we are a dock device - */ - return (is_dock_device(handle) || is_dock_device(parent)); -} - -static int bay_add(acpi_handle handle, int id) -{ - acpi_status status; - struct bay *new_bay; - struct platform_device *pdev; - struct acpi_buffer nbuffer = {ACPI_ALLOCATE_BUFFER, NULL}; - acpi_get_name(handle, ACPI_FULL_PATHNAME, &nbuffer); - - bay_dprintk(handle, "Adding notify handler"); - - /* - * Initialize bay device structure - */ - new_bay = kzalloc(sizeof(*new_bay), GFP_ATOMIC); - INIT_LIST_HEAD(&new_bay->list); - new_bay->handle = handle; - new_bay->name = (char *)nbuffer.pointer; - - /* initialize platform device stuff */ - pdev = platform_device_register_simple(ACPI_BAY_CLASS, id, NULL, 0); - if (IS_ERR(pdev)) { - printk(KERN_ERR PREFIX "Error registering bay device\n"); - goto bay_add_err; - } - new_bay->pdev = pdev; - platform_set_drvdata(pdev, new_bay); - - /* - * we want the bay driver to be able to send uevents - */ - pdev->dev.uevent_suppress = 0; - - /* register for events on this device */ - status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, - bay_notify, new_bay); - if (ACPI_FAILURE(status)) { - printk(KERN_INFO PREFIX "Error installing bay notify handler\n"); - platform_device_unregister(new_bay->pdev); - goto bay_add_err; - } - - if (acpi_bay_add_fs(new_bay)) { - acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, - bay_notify); - platform_device_unregister(new_bay->pdev); - goto bay_add_err; - } - - /* if we are on a dock station, we should register for dock - * notifications. - */ - if (bay_is_dock_device(handle)) { - bay_dprintk(handle, "Is dependent on dock\n"); - register_hotplug_dock_device(handle, bay_notify, new_bay); - } - list_add(&new_bay->list, &drive_bays); - printk(KERN_INFO PREFIX "Bay [%s] Added\n", new_bay->name); - return 0; - -bay_add_err: - kfree(new_bay->name); - kfree(new_bay); - return -ENODEV; -} - -/** - * bay_notify - act upon an acpi bay notification - * @handle: the bay handle - * @event: the acpi event - * @data: our driver data struct - * - */ -static void bay_notify(acpi_handle handle, u32 event, void *data) -{ - struct bay *bay_dev = (struct bay *)data; - struct device *dev = &bay_dev->pdev->dev; - char event_string[12]; - char *envp[] = { event_string, NULL }; - - bay_dprintk(handle, "Bay event"); - sprintf(event_string, "BAY_EVENT=%d", event); - kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); -} - -static acpi_status -find_bay(acpi_handle handle, u32 lvl, void *context, void **rv) -{ - int *count = (int *)context; - - /* - * there could be more than one ejectable bay. - * so, just return AE_OK always so that every object - * will be checked. - */ - if (is_ejectable_bay(handle)) { - bay_dprintk(handle, "found ejectable bay"); - if (!bay_add(handle, *count)) - (*count)++; - } - return AE_OK; -} - -static int __init bay_init(void) -{ - int bays = 0; - - INIT_LIST_HEAD(&drive_bays); - - if (acpi_disabled) - return -ENODEV; - - /* look for dockable drive bays */ - acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, find_bay, &bays, NULL); - - if (!bays) - return -ENODEV; - - return 0; -} - -static void __exit bay_exit(void) -{ - struct bay *bay, *tmp; - - list_for_each_entry_safe(bay, tmp, &drive_bays, list) { - if (is_dock_device(bay->handle)) - unregister_hotplug_dock_device(bay->handle); - acpi_bay_remove_fs(bay); - acpi_remove_notify_handler(bay->handle, ACPI_SYSTEM_NOTIFY, - bay_notify); - platform_device_unregister(bay->pdev); - kfree(bay->name); - kfree(bay); - } -} - -postcore_initcall(bay_init); -module_exit(bay_exit); - diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index ccae305ee55..c797c6473f3 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -48,6 +48,23 @@ EXPORT_SYMBOL(acpi_root_dir); #define STRUCT_TO_INT(s) (*((int*)&s)) +static int set_power_nocheck(const struct dmi_system_id *id) +{ + printk(KERN_NOTICE PREFIX "%s detected - " + "disable power check in power transistion\n", id->ident); + acpi_power_nocheck = 1; + return 0; +} +static struct dmi_system_id __cpuinitdata power_nocheck_dmi_table[] = { + { + set_power_nocheck, "HP Pavilion 05", { + DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), + DMI_MATCH(DMI_SYS_VENDOR, "HP Pavilion 05"), + DMI_MATCH(DMI_PRODUCT_VERSION, "2001211RE101GLEND") }, NULL}, + {}, +}; + + /* -------------------------------------------------------------------------- Device Management -------------------------------------------------------------------------- */ @@ -77,7 +94,7 @@ EXPORT_SYMBOL(acpi_bus_get_device); int acpi_bus_get_status(struct acpi_device *device) { acpi_status status = AE_OK; - unsigned long sta = 0; + unsigned long long sta = 0; if (!device) @@ -95,21 +112,21 @@ int acpi_bus_get_status(struct acpi_device *device) } /* - * Otherwise we assume the status of our parent (unless we don't - * have one, in which case status is implied). + * According to ACPI spec some device can be present and functional + * even if the parent is not present but functional. + * In such conditions the child device should not inherit the status + * from the parent. */ - else if (device->parent) - device->status = device->parent->status; else STRUCT_TO_INT(device->status) = ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING; if (device->status.functional && !device->status.present) { - printk(KERN_WARNING PREFIX "Device [%s] status [%08x]: " - "functional but not present; setting present\n", - device->pnp.bus_id, (u32) STRUCT_TO_INT(device->status)); - device->status.present = 1; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]: " + "functional but not present;\n", + device->pnp.bus_id, + (u32) STRUCT_TO_INT(device->status))); } ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n", @@ -155,7 +172,7 @@ int acpi_bus_get_power(acpi_handle handle, int *state) int result = 0; acpi_status status = 0; struct acpi_device *device = NULL; - unsigned long psc = 0; + unsigned long long psc = 0; result = acpi_bus_get_device(handle, &device); @@ -223,7 +240,19 @@ int acpi_bus_set_power(acpi_handle handle, int state) /* * Get device's current power state */ - acpi_bus_get_power(device->handle, &device->power.state); + if (!acpi_power_nocheck) { + /* + * Maybe the incorrect power state is returned on the bogus + * bios, which is different with the real power state. + * For example: the bios returns D0 state and the real power + * state is D3. OS expects to set the device to D0 state. In + * such case if OS uses the power state returned by the BIOS, + * the device can't be transisted to the correct power state. + * So if the acpi_power_nocheck is set, it is unnecessary to + * get the power state by calling acpi_bus_get_power. + */ + 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)); @@ -496,6 +525,19 @@ static int acpi_bus_check_scope(struct acpi_device *device) return 0; } +static BLOCKING_NOTIFIER_HEAD(acpi_bus_notify_list); +int register_acpi_bus_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&acpi_bus_notify_list, nb); +} +EXPORT_SYMBOL_GPL(register_acpi_bus_notifier); + +void unregister_acpi_bus_notifier(struct notifier_block *nb) +{ + blocking_notifier_chain_unregister(&acpi_bus_notify_list, nb); +} +EXPORT_SYMBOL_GPL(unregister_acpi_bus_notifier); + /** * acpi_bus_notify * --------------- @@ -506,6 +548,8 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) int result = 0; struct acpi_device *device = NULL; + blocking_notifier_call_chain(&acpi_bus_notify_list, + type, (void *)handle); if (acpi_bus_get_device(handle, &device)) return; @@ -749,6 +793,12 @@ static int __init acpi_bus_init(void) goto error1; } + /* + * Maybe EC region is required at bus_scan/acpi_get_devices. So it + * is necessary to enable it as early as possible. + */ + acpi_boot_ec_enable(); + printk(KERN_INFO PREFIX "Interpreter enabled\n"); /* Initialize sleep structures */ @@ -818,7 +868,11 @@ static int __init acpi_init(void) } } else disable_acpi(); - + /* + * If the laptop falls into the DMI check table, the power state check + * will be disabled in the course of device power transistion. + */ + dmi_check_system(power_nocheck_dmi_table); return result; } diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 1dfec413588..9d568d417ea 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -145,7 +145,7 @@ static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) { struct acpi_button *button = seq->private; acpi_status status; - unsigned long state; + unsigned long long state; if (!button || !button->device) return 0; @@ -253,7 +253,7 @@ static int acpi_button_remove_fs(struct acpi_device *device) -------------------------------------------------------------------------- */ static int acpi_lid_send_state(struct acpi_button *button) { - unsigned long state; + unsigned long long state; acpi_status status; status = acpi_evaluate_integer(button->device->handle, "_LID", NULL, @@ -384,7 +384,7 @@ static int acpi_button_add(struct acpi_device *device) return -ENOMEM; button->device = device; - acpi_driver_data(device) = button; + device->driver_data = button; button->input = input = input_allocate_device(); if (!input) { diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c index f9db4f444bd..4441e84b28a 100644 --- a/drivers/acpi/cm_sbs.c +++ b/drivers/acpi/cm_sbs.c @@ -52,8 +52,8 @@ struct proc_dir_entry *acpi_lock_ac_dir(void) if (acpi_ac_dir) { lock_ac_dir_cnt++; } else { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Cannot create %s\n", ACPI_AC_CLASS)); + printk(KERN_ERR PREFIX + "Cannot create %s\n", ACPI_AC_CLASS); } mutex_unlock(&cm_sbs_mutex); return acpi_ac_dir; @@ -83,8 +83,8 @@ struct proc_dir_entry *acpi_lock_battery_dir(void) if (acpi_battery_dir) { lock_battery_dir_cnt++; } else { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Cannot create %s\n", ACPI_BATTERY_CLASS)); + printk(KERN_ERR PREFIX + "Cannot create %s\n", ACPI_BATTERY_CLASS); } mutex_unlock(&cm_sbs_mutex); return acpi_battery_dir; diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 3c25ec7a187..134818b265a 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -76,7 +76,7 @@ static int is_device_present(acpi_handle handle) { acpi_handle temp; acpi_status status; - unsigned long sta; + unsigned long long sta; status = acpi_get_handle(handle, "_STA", &temp); @@ -108,7 +108,7 @@ static int acpi_container_add(struct acpi_device *device) container->handle = device->handle; strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS); - acpi_driver_data(device) = container; + device->driver_data = container; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>\n", acpi_device_name(device), acpi_device_bid(device))); diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c index 6df564f4ca6..abf36b4b1d1 100644 --- a/drivers/acpi/debug.c +++ b/drivers/acpi/debug.c @@ -47,8 +47,6 @@ static const struct acpi_dlayer acpi_debug_layers[] = { }; static const struct acpi_dlevel acpi_debug_levels[] = { - ACPI_DEBUG_INIT(ACPI_LV_ERROR), - ACPI_DEBUG_INIT(ACPI_LV_WARN), ACPI_DEBUG_INIT(ACPI_LV_INIT), ACPI_DEBUG_INIT(ACPI_LV_DEBUG_OBJECT), ACPI_DEBUG_INIT(ACPI_LV_INFO), diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index 4613b9ca579..279a5a60a0d 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c @@ -103,6 +103,9 @@ acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state) NULL); acpi_ex_enter_interpreter(); } + + acpi_ds_clear_implicit_return(walk_state); + #ifdef ACPI_DISASSEMBLER if (ACPI_FAILURE(status)) { diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c index 13c43eac35d..d03f81bd1bc 100644 --- a/drivers/acpi/dispatcher/dsmthdat.c +++ b/drivers/acpi/dispatcher/dsmthdat.c @@ -43,7 +43,6 @@ #include <acpi/acpi.h> #include <acpi/acdispat.h> -#include <acpi/amlcode.h> #include <acpi/acnamesp.h> #include <acpi/acinterp.h> @@ -52,11 +51,11 @@ ACPI_MODULE_NAME("dsmthdat") /* Local prototypes */ static void -acpi_ds_method_data_delete_value(u16 opcode, +acpi_ds_method_data_delete_value(u8 type, u32 index, struct acpi_walk_state *walk_state); static acpi_status -acpi_ds_method_data_set_value(u16 opcode, +acpi_ds_method_data_set_value(u8 type, u32 index, union acpi_operand_object *object, struct acpi_walk_state *walk_state); @@ -216,7 +215,7 @@ acpi_ds_method_data_init_args(union acpi_operand_object **params, * Store the argument in the method/walk descriptor. * Do not copy the arg in order to implement call by reference */ - status = acpi_ds_method_data_set_value(AML_ARG_OP, index, + status = acpi_ds_method_data_set_value(ACPI_REFCLASS_ARG, index, params[index], walk_state); if (ACPI_FAILURE(status)) { @@ -234,7 +233,8 @@ acpi_ds_method_data_init_args(union acpi_operand_object **params, * * FUNCTION: acpi_ds_method_data_get_node * - * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP + * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or + * ACPI_REFCLASS_ARG * Index - Which Local or Arg whose type to get * walk_state - Current walk state object * Node - Where the node is returned. @@ -246,7 +246,7 @@ acpi_ds_method_data_init_args(union acpi_operand_object **params, ******************************************************************************/ acpi_status -acpi_ds_method_data_get_node(u16 opcode, +acpi_ds_method_data_get_node(u8 type, u32 index, struct acpi_walk_state *walk_state, struct acpi_namespace_node **node) @@ -256,8 +256,8 @@ acpi_ds_method_data_get_node(u16 opcode, /* * Method Locals and Arguments are supported */ - switch (opcode) { - case AML_LOCAL_OP: + switch (type) { + case ACPI_REFCLASS_LOCAL: if (index > ACPI_METHOD_MAX_LOCAL) { ACPI_ERROR((AE_INFO, @@ -271,7 +271,7 @@ acpi_ds_method_data_get_node(u16 opcode, *node = &walk_state->local_variables[index]; break; - case AML_ARG_OP: + case ACPI_REFCLASS_ARG: if (index > ACPI_METHOD_MAX_ARG) { ACPI_ERROR((AE_INFO, @@ -286,8 +286,8 @@ acpi_ds_method_data_get_node(u16 opcode, break; default: - ACPI_ERROR((AE_INFO, "Opcode %d is invalid", opcode)); - return_ACPI_STATUS(AE_AML_BAD_OPCODE); + ACPI_ERROR((AE_INFO, "Type %d is invalid", type)); + return_ACPI_STATUS(AE_TYPE); } return_ACPI_STATUS(AE_OK); @@ -297,7 +297,8 @@ acpi_ds_method_data_get_node(u16 opcode, * * FUNCTION: acpi_ds_method_data_set_value * - * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP + * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or + * ACPI_REFCLASS_ARG * Index - Which Local or Arg to get * Object - Object to be inserted into the stack entry * walk_state - Current walk state object @@ -310,7 +311,7 @@ acpi_ds_method_data_get_node(u16 opcode, ******************************************************************************/ static acpi_status -acpi_ds_method_data_set_value(u16 opcode, +acpi_ds_method_data_set_value(u8 type, u32 index, union acpi_operand_object *object, struct acpi_walk_state *walk_state) @@ -321,13 +322,13 @@ acpi_ds_method_data_set_value(u16 opcode, ACPI_FUNCTION_TRACE(ds_method_data_set_value); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "NewObj %p Opcode %X, Refs=%d [%s]\n", object, - opcode, object->common.reference_count, + "NewObj %p Type %2.2X, Refs=%d [%s]\n", object, + type, object->common.reference_count, acpi_ut_get_type_name(object->common.type))); /* Get the namespace node for the arg/local */ - status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node); + status = acpi_ds_method_data_get_node(type, index, walk_state, &node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -350,7 +351,8 @@ acpi_ds_method_data_set_value(u16 opcode, * * FUNCTION: acpi_ds_method_data_get_value * - * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP + * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or + * ACPI_REFCLASS_ARG * Index - Which local_var or argument to get * walk_state - Current walk state object * dest_desc - Where Arg or Local value is returned @@ -363,7 +365,7 @@ acpi_ds_method_data_set_value(u16 opcode, ******************************************************************************/ acpi_status -acpi_ds_method_data_get_value(u16 opcode, +acpi_ds_method_data_get_value(u8 type, u32 index, struct acpi_walk_state *walk_state, union acpi_operand_object **dest_desc) @@ -383,7 +385,7 @@ acpi_ds_method_data_get_value(u16 opcode, /* Get the namespace node for the arg/local */ - status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node); + status = acpi_ds_method_data_get_node(type, index, walk_state, &node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -419,8 +421,8 @@ acpi_ds_method_data_get_value(u16 opcode, /* Otherwise, return the error */ else - switch (opcode) { - case AML_ARG_OP: + switch (type) { + case ACPI_REFCLASS_ARG: ACPI_ERROR((AE_INFO, "Uninitialized Arg[%d] at node %p", @@ -428,7 +430,7 @@ acpi_ds_method_data_get_value(u16 opcode, return_ACPI_STATUS(AE_AML_UNINITIALIZED_ARG); - case AML_LOCAL_OP: + case ACPI_REFCLASS_LOCAL: ACPI_ERROR((AE_INFO, "Uninitialized Local[%d] at node %p", @@ -437,9 +439,10 @@ acpi_ds_method_data_get_value(u16 opcode, return_ACPI_STATUS(AE_AML_UNINITIALIZED_LOCAL); default: + ACPI_ERROR((AE_INFO, "Not a Arg/Local opcode: %X", - opcode)); + type)); return_ACPI_STATUS(AE_AML_INTERNAL); } } @@ -458,7 +461,8 @@ acpi_ds_method_data_get_value(u16 opcode, * * FUNCTION: acpi_ds_method_data_delete_value * - * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP + * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or + * ACPI_REFCLASS_ARG * Index - Which local_var or argument to delete * walk_state - Current walk state object * @@ -470,7 +474,7 @@ acpi_ds_method_data_get_value(u16 opcode, ******************************************************************************/ static void -acpi_ds_method_data_delete_value(u16 opcode, +acpi_ds_method_data_delete_value(u8 type, u32 index, struct acpi_walk_state *walk_state) { acpi_status status; @@ -481,7 +485,7 @@ acpi_ds_method_data_delete_value(u16 opcode, /* Get the namespace node for the arg/local */ - status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node); + status = acpi_ds_method_data_get_node(type, index, walk_state, &node); if (ACPI_FAILURE(status)) { return_VOID; } @@ -514,7 +518,8 @@ acpi_ds_method_data_delete_value(u16 opcode, * * FUNCTION: acpi_ds_store_object_to_local * - * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP + * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or + * ACPI_REFCLASS_ARG * Index - Which Local or Arg to set * obj_desc - Value to be stored * walk_state - Current walk state @@ -528,7 +533,7 @@ acpi_ds_method_data_delete_value(u16 opcode, ******************************************************************************/ acpi_status -acpi_ds_store_object_to_local(u16 opcode, +acpi_ds_store_object_to_local(u8 type, u32 index, union acpi_operand_object *obj_desc, struct acpi_walk_state *walk_state) @@ -539,8 +544,8 @@ acpi_ds_store_object_to_local(u16 opcode, union acpi_operand_object *new_obj_desc; ACPI_FUNCTION_TRACE(ds_store_object_to_local); - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Opcode=%X Index=%d Obj=%p\n", - opcode, index, obj_desc)); + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Type=%2.2X Index=%d Obj=%p\n", + type, index, obj_desc)); /* Parameter validation */ @@ -550,7 +555,7 @@ acpi_ds_store_object_to_local(u16 opcode, /* Get the namespace node for the arg/local */ - status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node); + status = acpi_ds_method_data_get_node(type, index, walk_state, &node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -602,7 +607,7 @@ acpi_ds_store_object_to_local(u16 opcode, * * Weird, but true. */ - if (opcode == AML_ARG_OP) { + if (type == ACPI_REFCLASS_ARG) { /* * If we have a valid reference object that came from ref_of(), * do the indirect store @@ -611,8 +616,8 @@ acpi_ds_store_object_to_local(u16 opcode, ACPI_DESC_TYPE_OPERAND) && (current_obj_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) - && (current_obj_desc->reference.opcode == - AML_REF_OF_OP)) { + && (current_obj_desc->reference.class == + ACPI_REFCLASS_REFOF)) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Arg (%p) is an ObjRef(Node), storing in node %p\n", new_obj_desc, @@ -640,11 +645,9 @@ acpi_ds_store_object_to_local(u16 opcode, } } - /* - * Delete the existing object - * before storing the new one - */ - acpi_ds_method_data_delete_value(opcode, index, walk_state); + /* Delete the existing object before storing the new one */ + + acpi_ds_method_data_delete_value(type, index, walk_state); } /* @@ -653,7 +656,7 @@ acpi_ds_store_object_to_local(u16 opcode, * (increments the object reference count by one) */ status = - acpi_ds_method_data_set_value(opcode, index, new_obj_desc, + acpi_ds_method_data_set_value(type, index, new_obj_desc, walk_state); /* Remove local reference if we copied the object above */ diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c index 0f280589921..4f08e599d07 100644 --- a/drivers/acpi/dispatcher/dsobject.c +++ b/drivers/acpi/dispatcher/dsobject.c @@ -731,54 +731,70 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, switch (op_info->type) { case AML_TYPE_LOCAL_VARIABLE: - /* Split the opcode into a base opcode + offset */ + /* Local ID (0-7) is (AML opcode - base AML_LOCAL_OP) */ - obj_desc->reference.opcode = AML_LOCAL_OP; - obj_desc->reference.offset = opcode - AML_LOCAL_OP; + obj_desc->reference.value = opcode - AML_LOCAL_OP; + obj_desc->reference.class = ACPI_REFCLASS_LOCAL; #ifndef ACPI_NO_METHOD_EXECUTION - status = acpi_ds_method_data_get_node(AML_LOCAL_OP, - obj_desc-> - reference.offset, - walk_state, - (struct - acpi_namespace_node - **)&obj_desc-> - reference.object); + status = + acpi_ds_method_data_get_node(ACPI_REFCLASS_LOCAL, + obj_desc->reference. + value, walk_state, + ACPI_CAST_INDIRECT_PTR + (struct + acpi_namespace_node, + &obj_desc->reference. + object)); #endif break; case AML_TYPE_METHOD_ARGUMENT: - /* Split the opcode into a base opcode + offset */ + /* Arg ID (0-6) is (AML opcode - base AML_ARG_OP) */ - obj_desc->reference.opcode = AML_ARG_OP; - obj_desc->reference.offset = opcode - AML_ARG_OP; + obj_desc->reference.value = opcode - AML_ARG_OP; + obj_desc->reference.class = ACPI_REFCLASS_ARG; #ifndef ACPI_NO_METHOD_EXECUTION - status = acpi_ds_method_data_get_node(AML_ARG_OP, + status = acpi_ds_method_data_get_node(ACPI_REFCLASS_ARG, obj_desc-> - reference.offset, + reference.value, walk_state, + ACPI_CAST_INDIRECT_PTR (struct - acpi_namespace_node - **)&obj_desc-> - reference.object); + acpi_namespace_node, + &obj_desc-> + reference. + object)); #endif break; - default: /* Other literals, etc.. */ + default: /* Object name or Debug object */ - if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) { + switch (op->common.aml_opcode) { + case AML_INT_NAMEPATH_OP: /* Node was saved in Op */ obj_desc->reference.node = op->common.node; obj_desc->reference.object = op->common.node->object; - } + obj_desc->reference.class = ACPI_REFCLASS_NAME; + break; + + case AML_DEBUG_OP: - obj_desc->reference.opcode = opcode; + obj_desc->reference.class = ACPI_REFCLASS_DEBUG; + break; + + default: + + ACPI_ERROR((AE_INFO, + "Unimplemented reference type for AML opcode: %4.4X", + opcode)); + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } break; } break; diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c index 6a81c4400ed..69fae5905bb 100644 --- a/drivers/acpi/dispatcher/dsopcode.c +++ b/drivers/acpi/dispatcher/dsopcode.c @@ -1330,7 +1330,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, (walk_state->results->results.obj_desc[0]) == ACPI_TYPE_LOCAL_REFERENCE) && ((walk_state->results->results.obj_desc[0])-> - reference.opcode != AML_INDEX_OP)) { + reference.class != ACPI_REFCLASS_INDEX)) { status = acpi_ex_resolve_to_value(&walk_state-> results->results. diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c index b5072fa9c92..396fe12078c 100644 --- a/drivers/acpi/dispatcher/dswexec.c +++ b/drivers/acpi/dispatcher/dswexec.c @@ -166,6 +166,10 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state, status = AE_CTRL_FALSE; } + /* Predicate can be used for an implicit return value */ + + (void)acpi_ds_do_implicit_return(local_obj_desc, walk_state, TRUE); + cleanup: ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Completed a predicate eval=%X Op=%p\n", @@ -429,10 +433,10 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) ACPI_TYPE_LOCAL_REFERENCE) && (walk_state->operands[1]->common.type == ACPI_TYPE_LOCAL_REFERENCE) - && (walk_state->operands[0]->reference.opcode == - walk_state->operands[1]->reference.opcode) - && (walk_state->operands[0]->reference.offset == - walk_state->operands[1]->reference.offset)) { + && (walk_state->operands[0]->reference.class == + walk_state->operands[1]->reference.class) + && (walk_state->operands[0]->reference.value == + walk_state->operands[1]->reference.value)) { status = AE_OK; } else { ACPI_EXCEPTION((AE_INFO, status, diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 7d2edf143f1..5b30b8d91d7 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -48,7 +48,6 @@ MODULE_PARM_DESC(immediate_undock, "1 (default) will cause the driver to " " before undocking"); static struct atomic_notifier_head dock_notifier_list; -static struct platform_device *dock_device; static char dock_device_name[] = "dock"; static const struct acpi_device_id dock_device_ids[] = { @@ -65,23 +64,29 @@ struct dock_station { struct mutex hp_lock; struct list_head dependent_devices; struct list_head hotplug_devices; + + struct list_head sibiling; + struct platform_device *dock_device; }; +static LIST_HEAD(dock_stations); +static int dock_station_count; struct dock_dependent_device { struct list_head list; struct list_head hotplug_list; acpi_handle handle; - acpi_notify_handler handler; + struct acpi_dock_ops *ops; void *context; }; #define DOCK_DOCKING 0x00000001 #define DOCK_UNDOCKING 0x00000002 +#define DOCK_IS_DOCK 0x00000010 +#define DOCK_IS_ATA 0x00000020 +#define DOCK_IS_BAT 0x00000040 #define DOCK_EVENT 3 #define UNDOCK_EVENT 2 -static struct dock_station *dock_station; - /***************************************************************************** * Dock Dependent device functions * *****************************************************************************/ @@ -199,6 +204,60 @@ static int is_dock(acpi_handle handle) return 1; } +static int is_ejectable(acpi_handle handle) +{ + acpi_status status; + acpi_handle tmp; + + status = acpi_get_handle(handle, "_EJ0", &tmp); + if (ACPI_FAILURE(status)) + return 0; + return 1; +} + +static int is_ata(acpi_handle handle) +{ + acpi_handle tmp; + + if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) || + (ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) || + (ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) || + (ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp)))) + return 1; + + return 0; +} + +static int is_battery(acpi_handle handle) +{ + struct acpi_device_info *info; + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + int ret = 1; + + if (!ACPI_SUCCESS(acpi_get_object_info(handle, &buffer))) + return 0; + info = buffer.pointer; + if (!(info->valid & ACPI_VALID_HID)) + ret = 0; + else + ret = !strcmp("PNP0C0A", info->hardware_id.value); + + kfree(buffer.pointer); + return ret; +} + +static int is_ejectable_bay(acpi_handle handle) +{ + acpi_handle phandle; + if (!is_ejectable(handle)) + return 0; + if (is_battery(handle) || is_ata(handle)) + return 1; + if (!acpi_get_parent(handle, &phandle) && is_ata(phandle)) + return 1; + return 0; +} + /** * is_dock_device - see if a device is on a dock station * @handle: acpi handle of the device @@ -209,11 +268,17 @@ static int is_dock(acpi_handle handle) */ int is_dock_device(acpi_handle handle) { - if (!dock_station) + struct dock_station *dock_station; + + if (!dock_station_count) return 0; - if (is_dock(handle) || find_dock_dependent_device(dock_station, handle)) + if (is_dock(handle)) return 1; + list_for_each_entry(dock_station, &dock_stations, sibiling) { + if (find_dock_dependent_device(dock_station, handle)) + return 1; + } return 0; } @@ -229,7 +294,7 @@ EXPORT_SYMBOL_GPL(is_dock_device); */ static int dock_present(struct dock_station *ds) { - unsigned long sta; + unsigned long long sta; acpi_status status; if (ds) { @@ -320,8 +385,8 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event) * First call driver specific hotplug functions */ list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) { - if (dd->handler) - dd->handler(dd->handle, event, dd->context); + if (dd->ops && dd->ops->handler) + dd->ops->handler(dd->handle, event, dd->context); } /* @@ -341,9 +406,10 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event) static void dock_event(struct dock_station *ds, u32 event, int num) { - struct device *dev = &dock_device->dev; + struct device *dev = &ds->dock_device->dev; char event_string[13]; char *envp[] = { event_string, NULL }; + struct dock_dependent_device *dd; if (num == UNDOCK_EVENT) sprintf(event_string, "EVENT=undock"); @@ -354,7 +420,14 @@ static void dock_event(struct dock_station *ds, u32 event, int num) * Indicate that the status of the dock station has * changed. */ - kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); + if (num == DOCK_EVENT) + kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); + + list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) + if (dd->ops && dd->ops->uevent) + dd->ops->uevent(dd->handle, event, dd->context); + if (num != DOCK_EVENT) + kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); } /** @@ -414,9 +487,10 @@ static void handle_dock(struct dock_station *ds, int dock) arg.type = ACPI_TYPE_INTEGER; arg.integer.value = dock; status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer); - if (ACPI_FAILURE(status)) - printk(KERN_ERR PREFIX "%s - failed to execute _DCK\n", - (char *)name_buffer.pointer); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) + ACPI_EXCEPTION((AE_INFO, status, "%s - failed to execute" + " _DCK\n", (char *)name_buffer.pointer)); + kfree(buffer.pointer); kfree(name_buffer.pointer); } @@ -452,6 +526,25 @@ static inline void complete_undock(struct dock_station *ds) ds->flags &= ~(DOCK_UNDOCKING); } +static void dock_lock(struct dock_station *ds, int lock) +{ + struct acpi_object_list arg_list; + union acpi_object arg; + acpi_status status; + + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = !!lock; + status = acpi_evaluate_object(ds->handle, "_LCK", &arg_list, NULL); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + if (lock) + printk(KERN_WARNING PREFIX "Locking device failed\n"); + else + printk(KERN_WARNING PREFIX "Unlocking device failed\n"); + } +} + /** * dock_in_progress - see if we are in the middle of handling a dock event * @ds: the dock station @@ -479,7 +572,7 @@ static int dock_in_progress(struct dock_station *ds) */ int register_dock_notifier(struct notifier_block *nb) { - if (!dock_station) + if (!dock_station_count) return -ENODEV; return atomic_notifier_chain_register(&dock_notifier_list, nb); @@ -493,7 +586,7 @@ EXPORT_SYMBOL_GPL(register_dock_notifier); */ void unregister_dock_notifier(struct notifier_block *nb) { - if (!dock_station) + if (!dock_station_count) return; atomic_notifier_chain_unregister(&dock_notifier_list, nb); @@ -504,7 +597,7 @@ EXPORT_SYMBOL_GPL(unregister_dock_notifier); /** * register_hotplug_dock_device - register a hotplug function * @handle: the handle of the device - * @handler: the acpi_notifier_handler to call after docking + * @ops: handlers to call after docking * @context: device specific data * * If a driver would like to perform a hotplug operation after a dock @@ -512,27 +605,36 @@ EXPORT_SYMBOL_GPL(unregister_dock_notifier); * the dock driver after _DCK is executed. */ int -register_hotplug_dock_device(acpi_handle handle, acpi_notify_handler handler, +register_hotplug_dock_device(acpi_handle handle, struct acpi_dock_ops *ops, void *context) { struct dock_dependent_device *dd; + struct dock_station *dock_station; + int ret = -EINVAL; - if (!dock_station) + if (!dock_station_count) return -ENODEV; /* * make sure this handle is for a device dependent on the dock, * this would include the dock station itself */ - dd = find_dock_dependent_device(dock_station, handle); - if (dd) { - dd->handler = handler; - dd->context = context; - dock_add_hotplug_device(dock_station, dd); - return 0; + list_for_each_entry(dock_station, &dock_stations, sibiling) { + /* + * An ATA bay can be in a dock and itself can be ejected + * seperately, so there are two 'dock stations' which need the + * ops + */ + dd = find_dock_dependent_device(dock_station, handle); + if (dd) { + dd->ops = ops; + dd->context = context; + dock_add_hotplug_device(dock_station, dd); + ret = 0; + } } - return -EINVAL; + return ret; } EXPORT_SYMBOL_GPL(register_hotplug_dock_device); @@ -544,13 +646,16 @@ EXPORT_SYMBOL_GPL(register_hotplug_dock_device); void unregister_hotplug_dock_device(acpi_handle handle) { struct dock_dependent_device *dd; + struct dock_station *dock_station; - if (!dock_station) + if (!dock_station_count) return; - dd = find_dock_dependent_device(dock_station, handle); - if (dd) - dock_del_hotplug_device(dock_station, dd); + list_for_each_entry(dock_station, &dock_stations, sibiling) { + dd = find_dock_dependent_device(dock_station, handle); + if (dd) + dock_del_hotplug_device(dock_station, dd); + } } EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device); @@ -575,13 +680,9 @@ static int handle_eject_request(struct dock_station *ds, u32 event) */ dock_event(ds, event, UNDOCK_EVENT); - if (!dock_present(ds)) { - complete_undock(ds); - return -ENODEV; - } - hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST); undock(ds); + dock_lock(ds, 0); eject_dock(ds); if (dock_present(ds)) { printk(KERN_ERR PREFIX "Unable to undock!\n"); @@ -604,14 +705,36 @@ static int handle_eject_request(struct dock_station *ds, u32 event) static void dock_notify(acpi_handle handle, u32 event, void *data) { struct dock_station *ds = data; + struct acpi_device *tmp; + int surprise_removal = 0; + + /* + * According to acpi spec 3.0a, if a DEVICE_CHECK notification + * is sent and _DCK is present, it is assumed to mean an undock + * request. + */ + if ((ds->flags & DOCK_IS_DOCK) && event == ACPI_NOTIFY_DEVICE_CHECK) + event = ACPI_NOTIFY_EJECT_REQUEST; + /* + * dock station: BUS_CHECK - docked or surprise removal + * DEVICE_CHECK - undocked + * other device: BUS_CHECK/DEVICE_CHECK - added or surprise removal + * + * To simplify event handling, dock dependent device handler always + * get ACPI_NOTIFY_BUS_CHECK/ACPI_NOTIFY_DEVICE_CHECK for add and + * ACPI_NOTIFY_EJECT_REQUEST for removal + */ switch (event) { case ACPI_NOTIFY_BUS_CHECK: - if (!dock_in_progress(ds) && dock_present(ds)) { + case ACPI_NOTIFY_DEVICE_CHECK: + if (!dock_in_progress(ds) && acpi_bus_get_device(ds->handle, + &tmp)) { begin_dock(ds); dock(ds); if (!dock_present(ds)) { printk(KERN_ERR PREFIX "Unable to dock!\n"); + complete_dock(ds); break; } atomic_notifier_call_chain(&dock_notifier_list, @@ -619,20 +742,19 @@ static void dock_notify(acpi_handle handle, u32 event, void *data) hotplug_dock_devices(ds, event); complete_dock(ds); dock_event(ds, event, DOCK_EVENT); + dock_lock(ds, 1); + break; } - break; - case ACPI_NOTIFY_DEVICE_CHECK: - /* - * According to acpi spec 3.0a, if a DEVICE_CHECK notification - * is sent and _DCK is present, it is assumed to mean an - * undock request. This notify routine will only be called - * for objects defining _DCK, so we will fall through to eject - * request here. However, we will pass an eject request through - * to the driver who wish to hotplug. - */ + if (dock_present(ds) || dock_in_progress(ds)) + break; + /* This is a surprise removal */ + surprise_removal = 1; + event = ACPI_NOTIFY_EJECT_REQUEST; + /* Fall back */ case ACPI_NOTIFY_EJECT_REQUEST: begin_undock(ds); - if (immediate_undock) + if ((immediate_undock && !(ds->flags & DOCK_IS_ATA)) + || surprise_removal) handle_eject_request(ds, event); else dock_event(ds, event, UNDOCK_EVENT); @@ -642,6 +764,51 @@ static void dock_notify(acpi_handle handle, u32 event, void *data) } } +struct dock_data { + acpi_handle handle; + unsigned long event; + struct dock_station *ds; +}; + +static void acpi_dock_deferred_cb(void *context) +{ + struct dock_data *data = (struct dock_data *)context; + + dock_notify(data->handle, data->event, data->ds); + kfree(data); +} + +static int acpi_dock_notifier_call(struct notifier_block *this, + unsigned long event, void *data) +{ + struct dock_station *dock_station; + acpi_handle handle = (acpi_handle)data; + + if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK + && event != ACPI_NOTIFY_EJECT_REQUEST) + return 0; + list_for_each_entry(dock_station, &dock_stations, sibiling) { + if (dock_station->handle == handle) { + struct dock_data *dock_data; + + dock_data = kmalloc(sizeof(*dock_data), GFP_KERNEL); + if (!dock_data) + return 0; + dock_data->handle = handle; + dock_data->event = event; + dock_data->ds = dock_station; + acpi_os_hotplug_execute(acpi_dock_deferred_cb, + dock_data); + return 0 ; + } + } + return 0; +} + +static struct notifier_block dock_acpi_notifier = { + .notifier_call = acpi_dock_notifier_call, +}; + /** * find_dock_devices - find devices on the dock station * @handle: the handle of the device we are examining @@ -688,6 +855,8 @@ fdd_out: static ssize_t show_docked(struct device *dev, struct device_attribute *attr, char *buf) { + struct dock_station *dock_station = *((struct dock_station **) + dev->platform_data); return snprintf(buf, PAGE_SIZE, "%d\n", dock_present(dock_station)); } @@ -699,6 +868,8 @@ static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL); static ssize_t show_flags(struct device *dev, struct device_attribute *attr, char *buf) { + struct dock_station *dock_station = *((struct dock_station **) + dev->platform_data); return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags); } @@ -711,6 +882,8 @@ static ssize_t write_undock(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int ret; + struct dock_station *dock_station = *((struct dock_station **) + dev->platform_data); if (!count) return -EINVAL; @@ -727,16 +900,38 @@ static DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock); static ssize_t show_dock_uid(struct device *dev, struct device_attribute *attr, char *buf) { - unsigned long lbuf; + unsigned long long lbuf; + struct dock_station *dock_station = *((struct dock_station **) + dev->platform_data); acpi_status status = acpi_evaluate_integer(dock_station->handle, "_UID", NULL, &lbuf); if (ACPI_FAILURE(status)) return 0; - return snprintf(buf, PAGE_SIZE, "%lx\n", lbuf); + return snprintf(buf, PAGE_SIZE, "%llx\n", lbuf); } static DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL); +static ssize_t show_dock_type(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct dock_station *dock_station = *((struct dock_station **) + dev->platform_data); + char *type; + + if (dock_station->flags & DOCK_IS_DOCK) + type = "dock_station"; + else if (dock_station->flags & DOCK_IS_ATA) + type = "ata_bay"; + else if (dock_station->flags & DOCK_IS_BAT) + type = "battery_bay"; + else + type = "unknown"; + + return snprintf(buf, PAGE_SIZE, "%s\n", type); +} +static DEVICE_ATTR(type, S_IRUGO, show_dock_type, NULL); + /** * dock_add - add a new dock station * @handle: the dock station handle @@ -747,8 +942,9 @@ static DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL); static int dock_add(acpi_handle handle) { int ret; - acpi_status status; struct dock_dependent_device *dd; + struct dock_station *dock_station; + struct platform_device *dock_device; /* allocate & initialize the dock_station private data */ dock_station = kzalloc(sizeof(*dock_station), GFP_KERNEL); @@ -758,22 +954,34 @@ static int dock_add(acpi_handle handle) dock_station->last_dock_time = jiffies - HZ; INIT_LIST_HEAD(&dock_station->dependent_devices); INIT_LIST_HEAD(&dock_station->hotplug_devices); + INIT_LIST_HEAD(&dock_station->sibiling); spin_lock_init(&dock_station->dd_lock); mutex_init(&dock_station->hp_lock); ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list); /* initialize platform device stuff */ - dock_device = - platform_device_register_simple(dock_device_name, 0, NULL, 0); + dock_station->dock_device = + platform_device_register_simple(dock_device_name, + dock_station_count, NULL, 0); + dock_device = dock_station->dock_device; if (IS_ERR(dock_device)) { kfree(dock_station); dock_station = NULL; return PTR_ERR(dock_device); } + platform_device_add_data(dock_device, &dock_station, + sizeof(struct dock_station *)); /* we want the dock device to send uevents */ dock_device->dev.uevent_suppress = 0; + if (is_dock(handle)) + dock_station->flags |= DOCK_IS_DOCK; + if (is_ata(handle)) + dock_station->flags |= DOCK_IS_ATA; + if (is_battery(handle)) + dock_station->flags |= DOCK_IS_BAT; + ret = device_create_file(&dock_device->dev, &dev_attr_docked); if (ret) { printk("Error %d adding sysfs file\n", ret); @@ -812,6 +1020,9 @@ static int dock_add(acpi_handle handle) dock_station = NULL; return ret; } + ret = device_create_file(&dock_device->dev, &dev_attr_type); + if (ret) + printk(KERN_ERR"Error %d adding sysfs file\n", ret); /* Find dependent devices */ acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, @@ -828,24 +1039,12 @@ static int dock_add(acpi_handle handle) } add_dock_dependent_device(dock_station, dd); - /* register for dock events */ - status = acpi_install_notify_handler(dock_station->handle, - ACPI_SYSTEM_NOTIFY, - dock_notify, dock_station); - - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX "Error installing notify handler\n"); - ret = -ENODEV; - goto dock_add_err; - } - - printk(KERN_INFO PREFIX "%s\n", ACPI_DOCK_DRIVER_DESCRIPTION); - + dock_station_count++; + list_add(&dock_station->sibiling, &dock_stations); return 0; -dock_add_err: - kfree(dd); dock_add_err_unregister: + device_remove_file(&dock_device->dev, &dev_attr_type); device_remove_file(&dock_device->dev, &dev_attr_docked); device_remove_file(&dock_device->dev, &dev_attr_undock); device_remove_file(&dock_device->dev, &dev_attr_uid); @@ -859,12 +1058,12 @@ dock_add_err_unregister: /** * dock_remove - free up resources related to the dock station */ -static int dock_remove(void) +static int dock_remove(struct dock_station *dock_station) { struct dock_dependent_device *dd, *tmp; - acpi_status status; + struct platform_device *dock_device = dock_station->dock_device; - if (!dock_station) + if (!dock_station_count) return 0; /* remove dependent devices */ @@ -872,14 +1071,8 @@ static int dock_remove(void) list) kfree(dd); - /* remove dock notify handler */ - status = acpi_remove_notify_handler(dock_station->handle, - ACPI_SYSTEM_NOTIFY, - dock_notify); - if (ACPI_FAILURE(status)) - printk(KERN_ERR "Error removing notify handler\n"); - /* cleanup sysfs */ + device_remove_file(&dock_device->dev, &dev_attr_type); device_remove_file(&dock_device->dev, &dev_attr_docked); device_remove_file(&dock_device->dev, &dev_attr_undock); device_remove_file(&dock_device->dev, &dev_attr_uid); @@ -904,41 +1097,60 @@ static int dock_remove(void) static acpi_status find_dock(acpi_handle handle, u32 lvl, void *context, void **rv) { - int *count = context; acpi_status status = AE_OK; if (is_dock(handle)) { if (dock_add(handle) >= 0) { - (*count)++; status = AE_CTRL_TERMINATE; } } return status; } -static int __init dock_init(void) +static acpi_status +find_bay(acpi_handle handle, u32 lvl, void *context, void **rv) { - int num = 0; - - dock_station = NULL; + /* If bay is a dock, it's already handled */ + if (is_ejectable_bay(handle) && !is_dock(handle)) + dock_add(handle); + return AE_OK; +} +static int __init dock_init(void) +{ if (acpi_disabled) return 0; /* look for a dock station */ acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, find_dock, &num, NULL); + ACPI_UINT32_MAX, find_dock, NULL, NULL); - if (!num) - printk(KERN_INFO "No dock devices found.\n"); + /* look for bay */ + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, find_bay, NULL, NULL); + if (!dock_station_count) { + printk(KERN_INFO PREFIX "No dock devices found.\n"); + return 0; + } + register_acpi_bus_notifier(&dock_acpi_notifier); + printk(KERN_INFO PREFIX "%s: %d docks/bays found\n", + ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count); return 0; } static void __exit dock_exit(void) { - dock_remove(); + struct dock_station *dock_station; + + unregister_acpi_bus_notifier(&dock_acpi_notifier); + list_for_each_entry(dock_station, &dock_stations, sibiling) + dock_remove(dock_station); } -postcore_initcall(dock_init); +/* + * Must be called before drivers of devices in dock, otherwise we can't know + * which devices are in a dock + */ +subsys_initcall(dock_init); module_exit(dock_exit); diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 13593f9f219..ef42316f89f 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -1,7 +1,7 @@ /* - * ec.c - ACPI Embedded Controller Driver (v2.0) + * ec.c - ACPI Embedded Controller Driver (v2.1) * - * Copyright (C) 2006, 2007 Alexey Starikovskiy <alexey.y.starikovskiy@intel.com> + * Copyright (C) 2006-2008 Alexey Starikovskiy <astarikovskiy@suse.de> * Copyright (C) 2006 Denis Sadykov <denis.m.sadykov@intel.com> * Copyright (C) 2004 Luming Yu <luming.yu@intel.com> * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> @@ -26,7 +26,7 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -/* Uncomment next line to get verbose print outs*/ +/* Uncomment next line to get verbose printout */ /* #define DEBUG */ #include <linux/kernel.h> @@ -38,6 +38,7 @@ #include <linux/seq_file.h> #include <linux/interrupt.h> #include <linux/list.h> +#include <linux/spinlock.h> #include <asm/io.h> #include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h> @@ -65,22 +66,21 @@ enum ec_command { ACPI_EC_COMMAND_QUERY = 0x84, }; -/* EC events */ -enum ec_event { - ACPI_EC_EVENT_OBF_1 = 1, /* Output buffer full */ - ACPI_EC_EVENT_IBF_0, /* Input buffer empty */ -}; - #define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */ #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ #define ACPI_EC_UDELAY 100 /* Wait 100us before polling EC again */ +#define ACPI_EC_STORM_THRESHOLD 20 /* number of false interrupts + per one transaction */ + enum { - EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */ EC_FLAGS_QUERY_PENDING, /* Query is pending */ - EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */ + EC_FLAGS_GPE_MODE, /* Expect GPE to be sent + * for status change */ EC_FLAGS_NO_GPE, /* Don't use GPE mode */ - EC_FLAGS_RESCHEDULE_POLL /* Re-schedule poll */ + EC_FLAGS_GPE_STORM, /* GPE storm detected */ + EC_FLAGS_HANDLERS_INSTALLED /* Handlers for GPE and + * OpReg are installed */ }; /* If we find an EC via the ECDT, we need to keep a ptr to its context */ @@ -95,6 +95,15 @@ struct acpi_ec_query_handler { u8 query_bit; }; +struct transaction { + const u8 *wdata; + u8 *rdata; + unsigned short irq_count; + u8 command; + u8 wlen; + u8 rlen; +}; + static struct acpi_ec { acpi_handle handle; unsigned long gpe; @@ -105,9 +114,8 @@ static struct acpi_ec { struct mutex lock; wait_queue_head_t wait; struct list_head list; - struct delayed_work work; - atomic_t irq_count; - u8 handlers_installed; + struct transaction *curr; + spinlock_t curr_lock; } *boot_ec, *first_ec; /* @@ -150,7 +158,7 @@ static inline u8 acpi_ec_read_data(struct acpi_ec *ec) { u8 x = inb(ec->data_addr); pr_debug(PREFIX "---> data = 0x%2.2x\n", x); - return inb(ec->data_addr); + return x; } static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command) @@ -165,158 +173,172 @@ static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) outb(data, ec->data_addr); } -static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event) +static int ec_transaction_done(struct acpi_ec *ec) { - if (test_bit(EC_FLAGS_WAIT_GPE, &ec->flags)) - return 0; - if (event == ACPI_EC_EVENT_OBF_1) { - if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_OBF) - return 1; - } else if (event == ACPI_EC_EVENT_IBF_0) { - if (!(acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF)) - return 1; - } - - return 0; + unsigned long flags; + int ret = 0; + spin_lock_irqsave(&ec->curr_lock, flags); + if (!ec->curr || (!ec->curr->wlen && !ec->curr->rlen)) + ret = 1; + spin_unlock_irqrestore(&ec->curr_lock, flags); + return ret; } -static void ec_schedule_ec_poll(struct acpi_ec *ec) +static void gpe_transaction(struct acpi_ec *ec, u8 status) { - if (test_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags)) - schedule_delayed_work(&ec->work, - msecs_to_jiffies(ACPI_EC_DELAY)); + unsigned long flags; + spin_lock_irqsave(&ec->curr_lock, flags); + if (!ec->curr) + goto unlock; + if (ec->curr->wlen > 0) { + if ((status & ACPI_EC_FLAG_IBF) == 0) { + acpi_ec_write_data(ec, *(ec->curr->wdata++)); + --ec->curr->wlen; + } else + /* false interrupt, state didn't change */ + ++ec->curr->irq_count; + + } else if (ec->curr->rlen > 0) { + if ((status & ACPI_EC_FLAG_OBF) == 1) { + *(ec->curr->rdata++) = acpi_ec_read_data(ec); + --ec->curr->rlen; + } else + /* false interrupt, state didn't change */ + ++ec->curr->irq_count; + } +unlock: + spin_unlock_irqrestore(&ec->curr_lock, flags); } -static void ec_switch_to_poll_mode(struct acpi_ec *ec) +static int acpi_ec_wait(struct acpi_ec *ec) { + if (wait_event_timeout(ec->wait, ec_transaction_done(ec), + msecs_to_jiffies(ACPI_EC_DELAY))) + return 0; + /* missing GPEs, switch back to poll mode */ + if (printk_ratelimit()) + pr_info(PREFIX "missing confirmations, " + "switch off interrupt mode.\n"); set_bit(EC_FLAGS_NO_GPE, &ec->flags); clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); - acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); - set_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); + return 1; } -static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) +static void acpi_ec_gpe_query(void *ec_cxt); + +static int ec_check_sci(struct acpi_ec *ec, u8 state) { - atomic_set(&ec->irq_count, 0); - if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) && - likely(!force_poll)) { - if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event), - msecs_to_jiffies(ACPI_EC_DELAY))) - return 0; - clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); - if (acpi_ec_check_status(ec, event)) { - /* missing GPEs, switch back to poll mode */ - if (printk_ratelimit()) - pr_info(PREFIX "missing confirmations, " - "switch off interrupt mode.\n"); - ec_switch_to_poll_mode(ec); - ec_schedule_ec_poll(ec); - return 0; - } - } else { - unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); - clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); - while (time_before(jiffies, delay)) { - if (acpi_ec_check_status(ec, event)) - return 0; - msleep(1); - } - if (acpi_ec_check_status(ec,event)) + if (state & ACPI_EC_FLAG_SCI) { + if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) + return acpi_os_execute(OSL_EC_BURST_HANDLER, + acpi_ec_gpe_query, ec); + } + return 0; +} + +static int ec_poll(struct acpi_ec *ec) +{ + unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); + msleep(1); + while (time_before(jiffies, delay)) { + gpe_transaction(ec, acpi_ec_read_status(ec)); + msleep(1); + if (ec_transaction_done(ec)) return 0; } - pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n", - acpi_ec_read_status(ec), - (event == ACPI_EC_EVENT_OBF_1) ? "\"b0=1\"" : "\"b1=0\""); return -ETIME; } -static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, - const u8 * wdata, unsigned wdata_len, - u8 * rdata, unsigned rdata_len, +static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, + struct transaction *t, int force_poll) { - int result = 0; - set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); + unsigned long tmp; + int ret = 0; pr_debug(PREFIX "transaction start\n"); - acpi_ec_write_cmd(ec, command); - for (; wdata_len > 0; --wdata_len) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); - if (result) { - pr_err(PREFIX - "write_cmd timeout, command = %d\n", command); - goto end; - } - set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); - acpi_ec_write_data(ec, *(wdata++)); + /* disable GPE during transaction if storm is detected */ + if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { + clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); + acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); } - - if (!rdata_len) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); - if (result) { - pr_err(PREFIX - "finish-write timeout, command = %d\n", command); - goto end; - } - } else if (command == ACPI_EC_COMMAND_QUERY) + /* start transaction */ + spin_lock_irqsave(&ec->curr_lock, tmp); + /* following two actions should be kept atomic */ + t->irq_count = 0; + ec->curr = t; + acpi_ec_write_cmd(ec, ec->curr->command); + if (ec->curr->command == ACPI_EC_COMMAND_QUERY) clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); - - for (; rdata_len > 0; --rdata_len) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, force_poll); - if (result) { - pr_err(PREFIX "read timeout, command = %d\n", command); - goto end; - } - /* Don't expect GPE after last read */ - if (rdata_len > 1) - set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); - *(rdata++) = acpi_ec_read_data(ec); - } - end: + spin_unlock_irqrestore(&ec->curr_lock, tmp); + /* if we selected poll mode or failed in GPE-mode do a poll loop */ + if (force_poll || + !test_bit(EC_FLAGS_GPE_MODE, &ec->flags) || + acpi_ec_wait(ec)) + ret = ec_poll(ec); pr_debug(PREFIX "transaction end\n"); - return result; + spin_lock_irqsave(&ec->curr_lock, tmp); + ec->curr = NULL; + spin_unlock_irqrestore(&ec->curr_lock, tmp); + if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { + /* check if we received SCI during transaction */ + ec_check_sci(ec, acpi_ec_read_status(ec)); + /* it is safe to enable GPE outside of transaction */ + acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); + } else if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && + t->irq_count > ACPI_EC_STORM_THRESHOLD) { + pr_debug(PREFIX "GPE storm detected\n"); + set_bit(EC_FLAGS_GPE_STORM, &ec->flags); + } + return ret; +} + +static int ec_check_ibf0(struct acpi_ec *ec) +{ + u8 status = acpi_ec_read_status(ec); + return (status & ACPI_EC_FLAG_IBF) == 0; } -static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, - const u8 * wdata, unsigned wdata_len, - u8 * rdata, unsigned rdata_len, +static int ec_wait_ibf0(struct acpi_ec *ec) +{ + unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); + /* interrupt wait manually if GPE mode is not active */ + unsigned long timeout = test_bit(EC_FLAGS_GPE_MODE, &ec->flags) ? + msecs_to_jiffies(ACPI_EC_DELAY) : msecs_to_jiffies(1); + while (time_before(jiffies, delay)) + if (wait_event_timeout(ec->wait, ec_check_ibf0(ec), timeout)) + return 0; + return -ETIME; +} + +static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t, int force_poll) { int status; u32 glk; - - if (!ec || (wdata_len && !wdata) || (rdata_len && !rdata)) + if (!ec || (!t) || (t->wlen && !t->wdata) || (t->rlen && !t->rdata)) return -EINVAL; - - if (rdata) - memset(rdata, 0, rdata_len); - + if (t->rdata) + memset(t->rdata, 0, t->rlen); mutex_lock(&ec->lock); if (ec->global_lock) { status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); if (ACPI_FAILURE(status)) { - mutex_unlock(&ec->lock); - return -ENODEV; + status = -ENODEV; + goto unlock; } } - - status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0); - if (status) { + if (ec_wait_ibf0(ec)) { pr_err(PREFIX "input buffer is not empty, " "aborting transaction\n"); + status = -ETIME; goto end; } - - status = acpi_ec_transaction_unlocked(ec, command, - wdata, wdata_len, - rdata, rdata_len, - force_poll); - - end: - + status = acpi_ec_transaction_unlocked(ec, t, force_poll); +end: if (ec->global_lock) acpi_release_global_lock(glk); +unlock: mutex_unlock(&ec->lock); - return status; } @@ -327,21 +349,32 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, int acpi_ec_burst_enable(struct acpi_ec *ec) { u8 d; - return acpi_ec_transaction(ec, ACPI_EC_BURST_ENABLE, NULL, 0, &d, 1, 0); + struct transaction t = {.command = ACPI_EC_BURST_ENABLE, + .wdata = NULL, .rdata = &d, + .wlen = 0, .rlen = 1}; + + return acpi_ec_transaction(ec, &t, 0); } int acpi_ec_burst_disable(struct acpi_ec *ec) { - return acpi_ec_transaction(ec, ACPI_EC_BURST_DISABLE, NULL, 0, NULL, 0, 0); + struct transaction t = {.command = ACPI_EC_BURST_DISABLE, + .wdata = NULL, .rdata = NULL, + .wlen = 0, .rlen = 0}; + + return (acpi_ec_read_status(ec) & ACPI_EC_FLAG_BURST) ? + acpi_ec_transaction(ec, &t, 0) : 0; } static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data) { int result; u8 d; + struct transaction t = {.command = ACPI_EC_COMMAND_READ, + .wdata = &address, .rdata = &d, + .wlen = 1, .rlen = 1}; - result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_READ, - &address, 1, &d, 1, 0); + result = acpi_ec_transaction(ec, &t, 0); *data = d; return result; } @@ -349,8 +382,11 @@ static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data) static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data) { u8 wdata[2] = { address, data }; - return acpi_ec_transaction(ec, ACPI_EC_COMMAND_WRITE, - wdata, 2, NULL, 0, 0); + struct transaction t = {.command = ACPI_EC_COMMAND_WRITE, + .wdata = wdata, .rdata = NULL, + .wlen = 2, .rlen = 0}; + + return acpi_ec_transaction(ec, &t, 0); } /* @@ -412,12 +448,13 @@ int ec_transaction(u8 command, u8 * rdata, unsigned rdata_len, int force_poll) { + struct transaction t = {.command = command, + .wdata = wdata, .rdata = rdata, + .wlen = wdata_len, .rlen = rdata_len}; if (!first_ec) return -ENODEV; - return acpi_ec_transaction(first_ec, command, wdata, - wdata_len, rdata, rdata_len, - force_poll); + return acpi_ec_transaction(first_ec, &t, force_poll); } EXPORT_SYMBOL(ec_transaction); @@ -426,7 +463,9 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data) { int result; u8 d; - + struct transaction t = {.command = ACPI_EC_COMMAND_QUERY, + .wdata = NULL, .rdata = &d, + .wlen = 0, .rlen = 1}; if (!ec || !data) return -EINVAL; @@ -436,7 +475,7 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data) * bit to be cleared (and thus clearing the interrupt source). */ - result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1, 0); + result = acpi_ec_transaction(ec, &t, 0); if (result) return result; @@ -513,46 +552,26 @@ static void acpi_ec_gpe_query(void *ec_cxt) static u32 acpi_ec_gpe_handler(void *data) { - acpi_status status = AE_OK; struct acpi_ec *ec = data; - u8 state = acpi_ec_read_status(ec); + u8 status; pr_debug(PREFIX "~~~> interrupt\n"); - atomic_inc(&ec->irq_count); - if (atomic_read(&ec->irq_count) > 5) { - pr_err(PREFIX "GPE storm detected, disabling EC GPE\n"); - ec_switch_to_poll_mode(ec); - goto end; - } - clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); - if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) + status = acpi_ec_read_status(ec); + + gpe_transaction(ec, status); + if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0) wake_up(&ec->wait); - if (state & ACPI_EC_FLAG_SCI) { - if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) - status = acpi_os_execute(OSL_EC_BURST_HANDLER, - acpi_ec_gpe_query, ec); - } else if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && - !test_bit(EC_FLAGS_NO_GPE, &ec->flags) && - in_interrupt()) { + ec_check_sci(ec, status); + if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && + !test_bit(EC_FLAGS_NO_GPE, &ec->flags)) { /* this is non-query, must be confirmation */ if (printk_ratelimit()) pr_info(PREFIX "non-query interrupt received," " switching to interrupt mode\n"); set_bit(EC_FLAGS_GPE_MODE, &ec->flags); - clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); } -end: - ec_schedule_ec_poll(ec); - return ACPI_SUCCESS(status) ? - ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; -} - -static void do_ec_poll(struct work_struct *work) -{ - struct acpi_ec *ec = container_of(work, struct acpi_ec, work.work); - atomic_set(&ec->irq_count, 0); - (void)acpi_ec_gpe_handler(ec); + return ACPI_INTERRUPT_HANDLED; } /* -------------------------------------------------------------------------- @@ -696,8 +715,7 @@ static struct acpi_ec *make_acpi_ec(void) mutex_init(&ec->lock); init_waitqueue_head(&ec->wait); INIT_LIST_HEAD(&ec->list); - INIT_DELAYED_WORK_DEFERRABLE(&ec->work, do_ec_poll); - atomic_set(&ec->irq_count, 0); + spin_lock_init(&ec->curr_lock); return ec; } @@ -718,6 +736,7 @@ static acpi_status ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) { acpi_status status; + unsigned long long tmp; struct acpi_ec *ec = context; status = acpi_walk_resources(handle, METHOD_NAME__CRS, @@ -727,31 +746,26 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) /* Get GPE bit assignment (EC events). */ /* TODO: Add support for _GPE returning a package */ - status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe); + status = acpi_evaluate_integer(handle, "_GPE", NULL, &tmp); if (ACPI_FAILURE(status)) return status; + ec->gpe = tmp; /* Use the global lock for all EC transactions? */ - acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock); + acpi_evaluate_integer(handle, "_GLK", NULL, &tmp); + ec->global_lock = tmp; ec->handle = handle; return AE_CTRL_TERMINATE; } -static void ec_poll_stop(struct acpi_ec *ec) -{ - clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); - cancel_delayed_work(&ec->work); -} - static void ec_remove_handlers(struct acpi_ec *ec) { - ec_poll_stop(ec); if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler))) pr_err(PREFIX "failed to remove space handler\n"); if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler))) pr_err(PREFIX "failed to remove gpe handler\n"); - ec->handlers_installed = 0; + clear_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags); } static int acpi_ec_add(struct acpi_device *device) @@ -788,7 +802,7 @@ static int acpi_ec_add(struct acpi_device *device) if (!first_ec) first_ec = ec; - acpi_driver_data(device) = ec; + device->driver_data = ec; acpi_ec_add_fs(device); pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", ec->gpe, ec->command_addr, ec->data_addr); @@ -813,7 +827,7 @@ static int acpi_ec_remove(struct acpi_device *device, int type) } mutex_unlock(&ec->lock); acpi_ec_remove_fs(device); - acpi_driver_data(device) = NULL; + device->driver_data = NULL; if (ec == first_ec) first_ec = NULL; kfree(ec); @@ -846,27 +860,36 @@ ec_parse_io_ports(struct acpi_resource *resource, void *context) static int ec_install_handlers(struct acpi_ec *ec) { acpi_status status; - if (ec->handlers_installed) + if (test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags)) return 0; status = acpi_install_gpe_handler(NULL, ec->gpe, - ACPI_GPE_EDGE_TRIGGERED, - &acpi_ec_gpe_handler, ec); + ACPI_GPE_EDGE_TRIGGERED, + &acpi_ec_gpe_handler, ec); if (ACPI_FAILURE(status)) return -ENODEV; - acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME); acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); - status = acpi_install_address_space_handler(ec->handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, NULL, ec); if (ACPI_FAILURE(status)) { - acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler); - return -ENODEV; + if (status == AE_NOT_FOUND) { + /* + * Maybe OS fails in evaluating the _REG object. + * The AE_NOT_FOUND error will be ignored and OS + * continue to initialize EC. + */ + printk(KERN_ERR "Fail in evaluating the _REG object" + " of EC device. Broken bios is suspected.\n"); + } else { + acpi_remove_gpe_handler(NULL, ec->gpe, + &acpi_ec_gpe_handler); + return -ENODEV; + } } - ec->handlers_installed = 1; + set_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags); return 0; } @@ -887,7 +910,6 @@ static int acpi_ec_start(struct acpi_device *device) /* EC is fully operational, allow queries */ clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); - ec_schedule_ec_poll(ec); return ret; } @@ -906,7 +928,7 @@ static int acpi_ec_stop(struct acpi_device *device, int type) int __init acpi_boot_ec_enable(void) { - if (!boot_ec || boot_ec->handlers_installed) + if (!boot_ec || test_bit(EC_FLAGS_HANDLERS_INSTALLED, &boot_ec->flags)) return 0; if (!ec_install_handlers(boot_ec)) { first_ec = boot_ec; diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index 8892b9824fa..74da6fa52ef 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -43,7 +43,6 @@ #include <acpi/acpi.h> #include <acpi/acinterp.h> -#include <acpi/amlcode.h> #include <acpi/acnamesp.h> #include <acpi/actables.h> #include <acpi/acdispat.h> @@ -91,13 +90,12 @@ acpi_ex_add_table(u32 table_index, /* Init the table handle */ - obj_desc->reference.opcode = AML_LOAD_OP; + obj_desc->reference.class = ACPI_REFCLASS_TABLE; *ddb_handle = obj_desc; /* Install the new table into the local data structures */ - obj_desc->reference.object = ACPI_CAST_PTR(void, - (unsigned long)table_index); + obj_desc->reference.value = table_index; /* Add the table to the namespace */ @@ -280,6 +278,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, struct acpi_walk_state *walk_state) { union acpi_operand_object *ddb_handle; + struct acpi_table_header *table; struct acpi_table_desc table_desc; u32 table_index; acpi_status status; @@ -294,9 +293,8 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { case ACPI_TYPE_REGION: - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n", - obj_desc, - acpi_ut_get_object_type_name(obj_desc))); + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Load table from Region %p\n", obj_desc)); /* Region must be system_memory (from ACPI spec) */ @@ -316,61 +314,112 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, } /* - * We will simply map the memory region for the table. However, the - * memory region is technically not guaranteed to remain stable and - * we may eventually have to copy the table to a local buffer. + * Map the table header and get the actual table length. The region + * length is not guaranteed to be the same as the table length. + */ + table = acpi_os_map_memory(obj_desc->region.address, + sizeof(struct acpi_table_header)); + if (!table) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + length = table->length; + acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); + + /* Must have at least an ACPI table header */ + + if (length < sizeof(struct acpi_table_header)) { + return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); + } + + /* + * The memory region is not guaranteed to remain stable and we must + * copy the table to a local buffer. For example, the memory region + * is corrupted after suspend on some machines. Dynamically loaded + * tables are usually small, so this overhead is minimal. */ + + /* Allocate a buffer for the table */ + + table_desc.pointer = ACPI_ALLOCATE(length); + if (!table_desc.pointer) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Map the entire table and copy it */ + + table = acpi_os_map_memory(obj_desc->region.address, length); + if (!table) { + ACPI_FREE(table_desc.pointer); + return_ACPI_STATUS(AE_NO_MEMORY); + } + + ACPI_MEMCPY(table_desc.pointer, table, length); + acpi_os_unmap_memory(table, length); + table_desc.address = obj_desc->region.address; - table_desc.length = obj_desc->region.length; - table_desc.flags = ACPI_TABLE_ORIGIN_MAPPED; break; case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Load from Buffer or Field %p %s\n", obj_desc, - acpi_ut_get_object_type_name(obj_desc))); - - length = obj_desc->buffer.length; + "Load table from Buffer or Field %p\n", + obj_desc)); /* Must have at least an ACPI table header */ - if (length < sizeof(struct acpi_table_header)) { + if (obj_desc->buffer.length < sizeof(struct acpi_table_header)) { return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); } - /* Validate checksum here. It won't get validated in tb_add_table */ + /* Get the actual table length from the table header */ - status = - acpi_tb_verify_checksum(ACPI_CAST_PTR - (struct acpi_table_header, - obj_desc->buffer.pointer), length); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + table = + ACPI_CAST_PTR(struct acpi_table_header, + obj_desc->buffer.pointer); + length = table->length; + + /* Table cannot extend beyond the buffer */ + + if (length > obj_desc->buffer.length) { + return_ACPI_STATUS(AE_AML_BUFFER_LIMIT); + } + if (length < sizeof(struct acpi_table_header)) { + return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); } /* - * We need to copy the buffer since the original buffer could be - * changed or deleted in the future + * Copy the table from the buffer because the buffer could be modified + * or even deleted in the future */ table_desc.pointer = ACPI_ALLOCATE(length); if (!table_desc.pointer) { return_ACPI_STATUS(AE_NO_MEMORY); } - ACPI_MEMCPY(table_desc.pointer, obj_desc->buffer.pointer, - length); - table_desc.length = length; - table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; + ACPI_MEMCPY(table_desc.pointer, table, length); + table_desc.address = ACPI_TO_INTEGER(table_desc.pointer); break; default: return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } - /* - * Install the new table into the local data structures - */ + /* Validate table checksum (will not get validated in tb_add_table) */ + + status = acpi_tb_verify_checksum(table_desc.pointer, length); + if (ACPI_FAILURE(status)) { + ACPI_FREE(table_desc.pointer); + return_ACPI_STATUS(status); + } + + /* Complete the table descriptor */ + + table_desc.length = length; + table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; + + /* Install the new table into the local data structures */ + status = acpi_tb_add_table(&table_desc, &table_index); if (ACPI_FAILURE(status)) { goto cleanup; @@ -379,7 +428,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, /* * Add the table to the namespace. * - * Note: We load the table objects relative to the root of the namespace. + * Note: Load the table objects relative to the root of the namespace. * This appears to go against the ACPI specification, but we do it for * compatibility with other ACPI implementations. */ @@ -415,7 +464,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, cleanup: if (ACPI_FAILURE(status)) { - /* Delete allocated buffer or mapping */ + /* Delete allocated table buffer */ acpi_tb_delete_table(&table_desc); } @@ -455,9 +504,9 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Get the table index from the ddb_handle (acpi_size for 64-bit case) */ + /* Get the table index from the ddb_handle */ - table_index = (u32) (acpi_size) table_desc->reference.object; + table_index = table_desc->reference.value; /* Invoke table handler if present */ diff --git a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c index 261d97516d9..1d1f35adddd 100644 --- a/drivers/acpi/executer/exconvrt.c +++ b/drivers/acpi/executer/exconvrt.c @@ -57,7 +57,7 @@ acpi_ex_convert_to_ascii(acpi_integer integer, * * FUNCTION: acpi_ex_convert_to_integer * - * PARAMETERS: obj_desc - Object to be converted. Must be an + * PARAMETERS: obj_desc - Object to be converted. Must be an * Integer, Buffer, or String * result_desc - Where the new Integer object is returned * Flags - Used for string conversion @@ -103,7 +103,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, } /* - * Convert the buffer/string to an integer. Note that both buffers and + * Convert the buffer/string to an integer. Note that both buffers and * strings are treated as raw data - we don't convert ascii to hex for * strings. * @@ -120,7 +120,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, /* * Convert string to an integer - for most cases, the string must be - * hexadecimal as per the ACPI specification. The only exception (as + * hexadecimal as per the ACPI specification. The only exception (as * of ACPI 3.0) is that the to_integer() operator allows both decimal * and hexadecimal strings (hex prefixed with "0x"). */ @@ -159,6 +159,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, break; default: + /* No other types can get here */ break; } @@ -185,7 +186,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, * * FUNCTION: acpi_ex_convert_to_buffer * - * PARAMETERS: obj_desc - Object to be converted. Must be an + * PARAMETERS: obj_desc - Object to be converted. Must be an * Integer, Buffer, or String * result_desc - Where the new buffer object is returned * @@ -365,7 +366,7 @@ acpi_ex_convert_to_ascii(acpi_integer integer, } /* - * Since leading zeros are supressed, we must check for the case where + * Since leading zeros are suppressed, we must check for the case where * the integer equals 0 * * Finally, null terminate the string and return the length @@ -383,7 +384,7 @@ acpi_ex_convert_to_ascii(acpi_integer integer, * * FUNCTION: acpi_ex_convert_to_string * - * PARAMETERS: obj_desc - Object to be converted. Must be an + * PARAMETERS: obj_desc - Object to be converted. Must be an * Integer, Buffer, or String * result_desc - Where the string object is returned * Type - String flags (base and conversion type) @@ -472,7 +473,7 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc, base = 10; /* - * Calculate the final string length. Individual string values + * Calculate the final string length. Individual string values * are variable length (include separator for each) */ for (i = 0; i < obj_desc->buffer.length; i++) { @@ -511,9 +512,14 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc, /* * Create a new string object and string buffer * (-1 because of extra separator included in string_length from above) + * Allow creation of zero-length strings from zero-length buffers. */ + if (string_length) { + string_length--; + } + return_desc = acpi_ut_create_string_object((acpi_size) - (string_length - 1)); + string_length); if (!return_desc) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -536,7 +542,9 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc, * Null terminate the string * (overwrites final comma/space from above) */ - new_buf--; + if (obj_desc->buffer.length) { + new_buf--; + } *new_buf = 0; break; @@ -617,7 +625,7 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type, case ACPI_TYPE_LOCAL_BANK_FIELD: case ACPI_TYPE_LOCAL_INDEX_FIELD: /* - * These types require an Integer operand. We can convert + * These types require an Integer operand. We can convert * a Buffer or a String to an Integer if necessary. */ status = @@ -627,7 +635,7 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type, case ACPI_TYPE_STRING: /* - * The operand must be a String. We can convert an + * The operand must be a String. We can convert an * Integer or Buffer if necessary */ status = @@ -637,7 +645,7 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type, case ACPI_TYPE_BUFFER: /* - * The operand must be a Buffer. We can convert an + * The operand must be a Buffer. We can convert an * Integer or String if necessary */ status = diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c index 2be2e2bf95b..d087a7d28aa 100644 --- a/drivers/acpi/executer/exdump.c +++ b/drivers/acpi/executer/exdump.c @@ -45,7 +45,6 @@ #include <acpi/acinterp.h> #include <acpi/amlcode.h> #include <acpi/acnamesp.h> -#include <acpi/acparser.h> #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exdump") @@ -214,10 +213,11 @@ static struct acpi_exdump_info acpi_ex_dump_index_field[5] = { {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(index_field.data_obj), "Data Object"} }; -static struct acpi_exdump_info acpi_ex_dump_reference[7] = { +static struct acpi_exdump_info acpi_ex_dump_reference[8] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_reference), NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(reference.class), "Class"}, {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(reference.target_type), "Target Type"}, - {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(reference.offset), "Offset"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(reference.value), "Value"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.object), "Object Desc"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.node), "Node"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.where), "Where"}, @@ -413,10 +413,10 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, case ACPI_EXD_REFERENCE: - acpi_ex_out_string("Opcode", - (acpi_ps_get_opcode_info - (obj_desc->reference.opcode))-> - name); + acpi_ex_out_string("Class Name", + (char *) + acpi_ut_get_reference_name + (obj_desc)); acpi_ex_dump_reference_obj(obj_desc); break; @@ -494,40 +494,41 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { case ACPI_TYPE_LOCAL_REFERENCE: - switch (obj_desc->reference.opcode) { - case AML_DEBUG_OP: + acpi_os_printf("Reference: [%s] ", + acpi_ut_get_reference_name(obj_desc)); + + switch (obj_desc->reference.class) { + case ACPI_REFCLASS_DEBUG: - acpi_os_printf("Reference: Debug\n"); + acpi_os_printf("\n"); break; - case AML_INDEX_OP: + case ACPI_REFCLASS_INDEX: - acpi_os_printf("Reference: Index %p\n", - obj_desc->reference.object); + acpi_os_printf("%p\n", obj_desc->reference.object); break; - case AML_LOAD_OP: + case ACPI_REFCLASS_TABLE: - acpi_os_printf("Reference: [DdbHandle] TableIndex %p\n", - obj_desc->reference.object); + acpi_os_printf("Table Index %X\n", + obj_desc->reference.value); break; - case AML_REF_OF_OP: + case ACPI_REFCLASS_REFOF: - acpi_os_printf("Reference: (RefOf) %p [%s]\n", - obj_desc->reference.object, + acpi_os_printf("%p [%s]\n", obj_desc->reference.object, acpi_ut_get_type_name(((union acpi_operand_object - *)obj_desc-> + *) + obj_desc-> reference. object)->common. type)); break; - case AML_ARG_OP: + case ACPI_REFCLASS_ARG: - acpi_os_printf("Reference: Arg%d", - obj_desc->reference.offset); + acpi_os_printf("%X", obj_desc->reference.value); if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { @@ -542,10 +543,9 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) acpi_os_printf("\n"); break; - case AML_LOCAL_OP: + case ACPI_REFCLASS_LOCAL: - acpi_os_printf("Reference: Local%d", - obj_desc->reference.offset); + acpi_os_printf("%X", obj_desc->reference.value); if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { @@ -560,21 +560,16 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) acpi_os_printf("\n"); break; - case AML_INT_NAMEPATH_OP: + case ACPI_REFCLASS_NAME: - acpi_os_printf("Reference: Namepath %X [%4.4s]\n", - obj_desc->reference.node->name.integer, + acpi_os_printf("- [%4.4s]\n", obj_desc->reference.node->name.ascii); break; - default: - - /* Unknown opcode */ + default: /* Unknown reference class */ - acpi_os_printf("Unknown Reference opcode=%X\n", - obj_desc->reference.opcode); + acpi_os_printf("%2.2X\n", obj_desc->reference.class); break; - } break; @@ -865,8 +860,8 @@ static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc) ret_buf.length = ACPI_ALLOCATE_LOCAL_BUFFER; - if (obj_desc->reference.opcode == AML_INT_NAMEPATH_OP) { - acpi_os_printf(" Named Object %p ", obj_desc->reference.node); + if (obj_desc->reference.class == ACPI_REFCLASS_NAME) { + acpi_os_printf(" %p ", obj_desc->reference.node); status = acpi_ns_handle_to_pathname(obj_desc->reference.node, @@ -882,14 +877,12 @@ static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc) ACPI_DESC_TYPE_OPERAND) { acpi_os_printf(" Target: %p", obj_desc->reference.object); - if (obj_desc->reference.opcode == AML_LOAD_OP) { - /* - * For DDBHandle reference, - * obj_desc->Reference.Object is the table index - */ - acpi_os_printf(" [DDBHandle]\n"); + if (obj_desc->reference.class == ACPI_REFCLASS_TABLE) { + acpi_os_printf(" Table Index: %X\n", + obj_desc->reference.value); } else { - acpi_os_printf(" [%s]\n", + acpi_os_printf(" Target: %p [%s]\n", + obj_desc->reference.object, acpi_ut_get_type_name(((union acpi_operand_object *) @@ -988,9 +981,9 @@ acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc, case ACPI_TYPE_LOCAL_REFERENCE: - acpi_os_printf("[Object Reference] %s", - (acpi_ps_get_opcode_info - (obj_desc->reference.opcode))->name); + acpi_os_printf("[Object Reference] Type [%s] %2.2X", + acpi_ut_get_reference_name(obj_desc), + obj_desc->reference.class); acpi_ex_dump_reference_obj(obj_desc); break; diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c index 731414a581a..efb19134005 100644 --- a/drivers/acpi/executer/exmisc.c +++ b/drivers/acpi/executer/exmisc.c @@ -86,10 +86,10 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc, /* * Must be a reference to a Local or Arg */ - switch (obj_desc->reference.opcode) { - case AML_LOCAL_OP: - case AML_ARG_OP: - case AML_DEBUG_OP: + switch (obj_desc->reference.class) { + case ACPI_REFCLASS_LOCAL: + case ACPI_REFCLASS_ARG: + case ACPI_REFCLASS_DEBUG: /* The referenced object is the pseudo-node for the local/arg */ @@ -98,8 +98,8 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc, default: - ACPI_ERROR((AE_INFO, "Unknown Reference opcode %X", - obj_desc->reference.opcode)); + ACPI_ERROR((AE_INFO, "Unknown Reference Class %2.2X", + obj_desc->reference.class)); return_ACPI_STATUS(AE_AML_INTERNAL); } break; @@ -127,7 +127,7 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_NO_MEMORY); } - reference_obj->reference.opcode = AML_REF_OF_OP; + reference_obj->reference.class = ACPI_REFCLASS_REFOF; reference_obj->reference.object = referenced_obj; *return_desc = reference_obj; diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c index 7c3bea575e0..f622f9eac8a 100644 --- a/drivers/acpi/executer/exoparg1.c +++ b/drivers/acpi/executer/exoparg1.c @@ -825,16 +825,16 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) * * Must resolve/dereference the local/arg reference first */ - switch (operand[0]->reference.opcode) { - case AML_LOCAL_OP: - case AML_ARG_OP: + switch (operand[0]->reference.class) { + case ACPI_REFCLASS_LOCAL: + case ACPI_REFCLASS_ARG: /* Set Operand[0] to the value of the local/arg */ status = acpi_ds_method_data_get_value - (operand[0]->reference.opcode, - operand[0]->reference.offset, + (operand[0]->reference.class, + operand[0]->reference.value, walk_state, &temp_desc); if (ACPI_FAILURE(status)) { goto cleanup; @@ -848,7 +848,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) operand[0] = temp_desc; break; - case AML_REF_OF_OP: + case ACPI_REFCLASS_REFOF: /* Get the object to which the reference refers */ @@ -928,8 +928,8 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) * This must be a reference object produced by either the * Index() or ref_of() operator */ - switch (operand[0]->reference.opcode) { - case AML_INDEX_OP: + switch (operand[0]->reference.class) { + case ACPI_REFCLASS_INDEX: /* * The target type for the Index operator must be @@ -965,7 +965,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) return_desc->integer.value = temp_desc->buffer. pointer[operand[0]->reference. - offset]; + value]; break; case ACPI_TYPE_PACKAGE: @@ -985,7 +985,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) default: ACPI_ERROR((AE_INFO, - "Unknown Index TargetType %X in obj %p", + "Unknown Index TargetType %X in reference object %p", operand[0]->reference. target_type, operand[0])); status = AE_AML_OPERAND_TYPE; @@ -993,7 +993,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) } break; - case AML_REF_OF_OP: + case ACPI_REFCLASS_REFOF: return_desc = operand[0]->reference.object; @@ -1013,9 +1013,9 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) default: ACPI_ERROR((AE_INFO, - "Unknown opcode in reference(%p) - %X", + "Unknown class in reference(%p) - %2.2X", operand[0], - operand[0]->reference.opcode)); + operand[0]->reference.class)); status = AE_TYPE; goto cleanup; diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c index 8e8bbb6cceb..368def5dffc 100644 --- a/drivers/acpi/executer/exoparg2.c +++ b/drivers/acpi/executer/exoparg2.c @@ -391,8 +391,8 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) /* Initialize the Index reference object */ index = operand[1]->integer.value; - return_desc->reference.offset = (u32) index; - return_desc->reference.opcode = AML_INDEX_OP; + return_desc->reference.value = (u32) index; + return_desc->reference.class = ACPI_REFCLASS_INDEX; /* * At this point, the Source operand is a String, Buffer, or Package. diff --git a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c index 5596f42c967..423ad3635f3 100644 --- a/drivers/acpi/executer/exresnte.c +++ b/drivers/acpi/executer/exresnte.c @@ -46,8 +46,6 @@ #include <acpi/acdispat.h> #include <acpi/acinterp.h> #include <acpi/acnamesp.h> -#include <acpi/acparser.h> -#include <acpi/amlcode.h> #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exresnte") @@ -238,10 +236,10 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, case ACPI_TYPE_LOCAL_REFERENCE: - switch (source_desc->reference.opcode) { - case AML_LOAD_OP: /* This is a ddb_handle */ - case AML_REF_OF_OP: - case AML_INDEX_OP: + switch (source_desc->reference.class) { + case ACPI_REFCLASS_TABLE: /* This is a ddb_handle */ + case ACPI_REFCLASS_REFOF: + case ACPI_REFCLASS_INDEX: /* Return an additional reference to the object */ @@ -253,10 +251,8 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, /* No named references are allowed here */ ACPI_ERROR((AE_INFO, - "Unsupported Reference opcode %X (%s)", - source_desc->reference.opcode, - acpi_ps_get_opcode_name(source_desc-> - reference.opcode))); + "Unsupported Reference type %X", + source_desc->reference.class)); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c index b35f7c817ac..89571b92a52 100644 --- a/drivers/acpi/executer/exresolv.c +++ b/drivers/acpi/executer/exresolv.c @@ -47,7 +47,6 @@ #include <acpi/acdispat.h> #include <acpi/acinterp.h> #include <acpi/acnamesp.h> -#include <acpi/acparser.h> #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exresolv") @@ -141,7 +140,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, acpi_status status = AE_OK; union acpi_operand_object *stack_desc; union acpi_operand_object *obj_desc = NULL; - u16 opcode; + u8 ref_type; ACPI_FUNCTION_TRACE(ex_resolve_object_to_value); @@ -152,19 +151,19 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, switch (ACPI_GET_OBJECT_TYPE(stack_desc)) { case ACPI_TYPE_LOCAL_REFERENCE: - opcode = stack_desc->reference.opcode; + ref_type = stack_desc->reference.class; - switch (opcode) { - case AML_LOCAL_OP: - case AML_ARG_OP: + switch (ref_type) { + case ACPI_REFCLASS_LOCAL: + case ACPI_REFCLASS_ARG: /* * Get the local from the method's state info * Note: this increments the local's object reference count */ - status = acpi_ds_method_data_get_value(opcode, + status = acpi_ds_method_data_get_value(ref_type, stack_desc-> - reference.offset, + reference.value, walk_state, &obj_desc); if (ACPI_FAILURE(status)) { @@ -173,7 +172,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[Arg/Local %X] ValueObj is %p\n", - stack_desc->reference.offset, + stack_desc->reference.value, obj_desc)); /* @@ -184,7 +183,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, *stack_ptr = obj_desc; break; - case AML_INDEX_OP: + case ACPI_REFCLASS_INDEX: switch (stack_desc->reference.target_type) { case ACPI_TYPE_BUFFER_FIELD: @@ -239,15 +238,15 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, } break; - case AML_REF_OF_OP: - case AML_DEBUG_OP: - case AML_LOAD_OP: + case ACPI_REFCLASS_REFOF: + case ACPI_REFCLASS_DEBUG: + case ACPI_REFCLASS_TABLE: /* Just leave the object as-is, do not dereference */ break; - case AML_INT_NAMEPATH_OP: /* Reference to a named object */ + case ACPI_REFCLASS_NAME: /* Reference to a named object */ /* Dereference the name */ @@ -273,8 +272,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, default: ACPI_ERROR((AE_INFO, - "Unknown Reference opcode %X (%s) in %p", - opcode, acpi_ps_get_opcode_name(opcode), + "Unknown Reference type %X in %p", ref_type, stack_desc)); status = AE_AML_INTERNAL; break; @@ -388,13 +386,13 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, * traversing the list of possibly many nested references. */ while (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) { - switch (obj_desc->reference.opcode) { - case AML_REF_OF_OP: - case AML_INT_NAMEPATH_OP: + switch (obj_desc->reference.class) { + case ACPI_REFCLASS_REFOF: + case ACPI_REFCLASS_NAME: /* Dereference the reference pointer */ - if (obj_desc->reference.opcode == AML_REF_OF_OP) { + if (obj_desc->reference.class == ACPI_REFCLASS_REFOF) { node = obj_desc->reference.object; } else { /* AML_INT_NAMEPATH_OP */ @@ -429,7 +427,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, } break; - case AML_INDEX_OP: + case ACPI_REFCLASS_INDEX: /* Get the type of this reference (index into another object) */ @@ -455,22 +453,22 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, } break; - case AML_LOAD_OP: + case ACPI_REFCLASS_TABLE: type = ACPI_TYPE_DDB_HANDLE; goto exit; - case AML_LOCAL_OP: - case AML_ARG_OP: + case ACPI_REFCLASS_LOCAL: + case ACPI_REFCLASS_ARG: if (return_desc) { status = acpi_ds_method_data_get_value(obj_desc-> reference. - opcode, + class, obj_desc-> reference. - offset, + value, walk_state, &obj_desc); if (ACPI_FAILURE(status)) { @@ -481,10 +479,10 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, status = acpi_ds_method_data_get_node(obj_desc-> reference. - opcode, + class, obj_desc-> reference. - offset, + value, walk_state, &node); if (ACPI_FAILURE(status)) { @@ -499,7 +497,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, } break; - case AML_DEBUG_OP: + case ACPI_REFCLASS_DEBUG: /* The Debug Object is of type "DebugObject" */ @@ -509,8 +507,8 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, default: ACPI_ERROR((AE_INFO, - "Unknown Reference subtype %X", - obj_desc->reference.opcode)); + "Unknown Reference Class %2.2X", + obj_desc->reference.class)); return_ACPI_STATUS(AE_AML_INTERNAL); } } diff --git a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c index 54085f16ec2..0bb82593da7 100644 --- a/drivers/acpi/executer/exresop.c +++ b/drivers/acpi/executer/exresop.c @@ -225,41 +225,36 @@ acpi_ex_resolve_operands(u16 opcode, if (object_type == (u8) ACPI_TYPE_LOCAL_REFERENCE) { - /* Decode the Reference */ + /* Validate the Reference */ - op_info = acpi_ps_get_opcode_info(opcode); - if (op_info->class == AML_CLASS_UNKNOWN) { - return_ACPI_STATUS(AE_AML_BAD_OPCODE); - } + switch (obj_desc->reference.class) { + case ACPI_REFCLASS_DEBUG: - switch (obj_desc->reference.opcode) { - case AML_DEBUG_OP: target_op = AML_DEBUG_OP; /*lint -fallthrough */ - case AML_INDEX_OP: - case AML_REF_OF_OP: - case AML_ARG_OP: - case AML_LOCAL_OP: - case AML_LOAD_OP: /* ddb_handle from LOAD_OP or LOAD_TABLE_OP */ - case AML_INT_NAMEPATH_OP: /* Reference to a named object */ - - ACPI_DEBUG_ONLY_MEMBERS(ACPI_DEBUG_PRINT - ((ACPI_DB_EXEC, - "Operand is a Reference, RefOpcode [%s]\n", - (acpi_ps_get_opcode_info - (obj_desc-> - reference. - opcode))-> - name))); + case ACPI_REFCLASS_ARG: + case ACPI_REFCLASS_LOCAL: + case ACPI_REFCLASS_INDEX: + case ACPI_REFCLASS_REFOF: + case ACPI_REFCLASS_TABLE: /* ddb_handle from LOAD_OP or LOAD_TABLE_OP */ + case ACPI_REFCLASS_NAME: /* Reference to a named object */ + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Operand is a Reference, Class [%s] %2.2X\n", + acpi_ut_get_reference_name + (obj_desc), + obj_desc->reference. + class)); break; default: + ACPI_ERROR((AE_INFO, - "Operand is a Reference, Unknown Reference Opcode: %X", - obj_desc->reference. - opcode)); + "Unknown Reference Class %2.2X in %p", + obj_desc->reference.class, + obj_desc)); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -270,8 +265,7 @@ acpi_ex_resolve_operands(u16 opcode, /* Invalid descriptor */ - ACPI_ERROR((AE_INFO, - "Invalid descriptor %p [%s]", + ACPI_ERROR((AE_INFO, "Invalid descriptor %p [%s]", obj_desc, acpi_ut_get_descriptor_name(obj_desc))); @@ -343,7 +337,7 @@ acpi_ex_resolve_operands(u16 opcode, if ((opcode == AML_STORE_OP) && (ACPI_GET_OBJECT_TYPE(*stack_ptr) == ACPI_TYPE_LOCAL_REFERENCE) - && ((*stack_ptr)->reference.opcode == AML_INDEX_OP)) { + && ((*stack_ptr)->reference.class == ACPI_REFCLASS_INDEX)) { goto next_operand; } break; diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c index 38b55e35249..3318df4cbd9 100644 --- a/drivers/acpi/executer/exstore.c +++ b/drivers/acpi/executer/exstore.c @@ -47,7 +47,6 @@ #include <acpi/acinterp.h> #include <acpi/amlcode.h> #include <acpi/acnamesp.h> -#include <acpi/acparser.h> #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exstore") @@ -179,22 +178,26 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, case ACPI_TYPE_LOCAL_REFERENCE: - if (source_desc->reference.opcode == AML_INDEX_OP) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, - "[%s, 0x%X]\n", - acpi_ps_get_opcode_name - (source_desc->reference.opcode), - source_desc->reference.offset)); - } else { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s]", - acpi_ps_get_opcode_name - (source_desc->reference.opcode))); - } + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s] ", + acpi_ut_get_reference_name(source_desc))); + + /* Decode the reference */ + + switch (source_desc->reference.class) { + case ACPI_REFCLASS_INDEX: + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "0x%X\n", + source_desc->reference.value)); + break; + + case ACPI_REFCLASS_TABLE: - if (source_desc->reference.opcode == AML_LOAD_OP) { /* Load and load_table */ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, - " Table OwnerId %p\n", - source_desc->reference.object)); + "Table Index 0x%X\n", + source_desc->reference.value)); + break; + + default: break; } @@ -347,15 +350,15 @@ acpi_ex_store(union acpi_operand_object *source_desc, } /* - * Examine the Reference opcode. These cases are handled: + * Examine the Reference class. These cases are handled: * * 1) Store to Name (Change the object associated with a name) * 2) Store to an indexed area of a Buffer or Package * 3) Store to a Method Local or Arg * 4) Store to the debug object */ - switch (ref_desc->reference.opcode) { - case AML_REF_OF_OP: + switch (ref_desc->reference.class) { + case ACPI_REFCLASS_REFOF: /* Storing an object into a Name "container" */ @@ -365,7 +368,7 @@ acpi_ex_store(union acpi_operand_object *source_desc, ACPI_IMPLICIT_CONVERSION); break; - case AML_INDEX_OP: + case ACPI_REFCLASS_INDEX: /* Storing to an Index (pointer into a packager or buffer) */ @@ -374,18 +377,18 @@ acpi_ex_store(union acpi_operand_object *source_desc, walk_state); break; - case AML_LOCAL_OP: - case AML_ARG_OP: + case ACPI_REFCLASS_LOCAL: + case ACPI_REFCLASS_ARG: /* Store to a method local/arg */ status = - acpi_ds_store_object_to_local(ref_desc->reference.opcode, - ref_desc->reference.offset, + acpi_ds_store_object_to_local(ref_desc->reference.class, + ref_desc->reference.value, source_desc, walk_state); break; - case AML_DEBUG_OP: + case ACPI_REFCLASS_DEBUG: /* * Storing to the Debug object causes the value stored to be @@ -401,9 +404,9 @@ acpi_ex_store(union acpi_operand_object *source_desc, default: - ACPI_ERROR((AE_INFO, "Unknown Reference opcode %X", - ref_desc->reference.opcode)); - ACPI_DUMP_ENTRY(ref_desc, ACPI_LV_ERROR); + ACPI_ERROR((AE_INFO, "Unknown Reference Class %2.2X", + ref_desc->reference.class)); + ACPI_DUMP_ENTRY(ref_desc, ACPI_LV_INFO); status = AE_AML_INTERNAL; break; @@ -458,7 +461,7 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, if (ACPI_GET_OBJECT_TYPE(source_desc) == ACPI_TYPE_LOCAL_REFERENCE - && source_desc->reference.opcode == AML_LOAD_OP) { + && source_desc->reference.class == ACPI_REFCLASS_TABLE) { /* This is a DDBHandle, just add a reference to it */ @@ -553,7 +556,7 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, /* Store the source value into the target buffer byte */ - obj_desc->buffer.pointer[index_desc->reference.offset] = value; + obj_desc->buffer.pointer[index_desc->reference.value] = value; break; default: diff --git a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c index a6d2168b81f..eef61a00803 100644 --- a/drivers/acpi/executer/exstoren.c +++ b/drivers/acpi/executer/exstoren.c @@ -121,7 +121,8 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr, (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_STRING) && !((ACPI_GET_OBJECT_TYPE(source_desc) == ACPI_TYPE_LOCAL_REFERENCE) - && (source_desc->reference.opcode == AML_LOAD_OP))) { + && (source_desc->reference.class == + ACPI_REFCLASS_TABLE))) { /* Conversion successful but still not a valid type */ diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 2655bc1b4ee..60d54d1f6b1 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -265,7 +265,7 @@ static int acpi_fan_add(struct acpi_device *device) dev_info(&device->dev, "registered as cooling_device%d\n", cdev->id); - acpi_driver_data(device) = cdev; + device->driver_data = cdev; result = sysfs_create_link(&device->dev.kobj, &cdev->device.kobj, "thermal_cooling"); @@ -327,8 +327,8 @@ static int acpi_fan_resume(struct acpi_device *device) result = acpi_bus_get_power(device->handle, &power_state); if (result) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error reading fan power state\n")); + printk(KERN_ERR PREFIX + "Error reading fan power state\n"); return result; } diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c index dba3cfbe8cb..25dccdf179b 100644 --- a/drivers/acpi/hardware/hwsleep.c +++ b/drivers/acpi/hardware/hwsleep.c @@ -78,19 +78,17 @@ acpi_set_firmware_waking_vector(acpi_physical_address physical_address) return_ACPI_STATUS(status); } - /* Set the vector */ + /* + * According to the ACPI specification 2.0c and later, the 64-bit + * waking vector should be cleared and the 32-bit waking vector should + * be used, unless we want the wake-up code to be called by the BIOS in + * Protected Mode. Some systems (for example HP dv5-1004nr) are known + * to fail to resume if the 64-bit vector is used. + */ + if (facs->version >= 1) + facs->xfirmware_waking_vector = 0; - if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) { - /* - * ACPI 1.0 FACS or short table or optional X_ field is zero - */ - facs->firmware_waking_vector = (u32) physical_address; - } else { - /* - * ACPI 2.0 FACS with valid X_ field - */ - facs->xfirmware_waking_vector = physical_address; - } + facs->firmware_waking_vector = (u32)physical_address; return_ACPI_STATUS(AE_OK); } @@ -134,20 +132,7 @@ acpi_get_firmware_waking_vector(acpi_physical_address * physical_address) } /* Get the vector */ - - if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) { - /* - * ACPI 1.0 FACS or short table or optional X_ field is zero - */ - *physical_address = - (acpi_physical_address) facs->firmware_waking_vector; - } else { - /* - * ACPI 2.0 FACS with valid X_ field - */ - *physical_address = - (acpi_physical_address) facs->xfirmware_waking_vector; - } + *physical_address = (acpi_physical_address)facs->firmware_waking_vector; return_ACPI_STATUS(AE_OK); } @@ -627,6 +612,13 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) } /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */ + /* + * Some BIOSes assume that WAK_STS will be cleared on resume and use + * it to determine whether the system is rebooting or resuming. Clear + * it for compatibility. + */ + acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1); + acpi_gbl_system_awake_and_running = TRUE; /* Enable power button */ diff --git a/drivers/acpi/namespace/Makefile b/drivers/acpi/namespace/Makefile index 3f63d364069..371a2daf837 100644 --- a/drivers/acpi/namespace/Makefile +++ b/drivers/acpi/namespace/Makefile @@ -5,7 +5,7 @@ obj-y := nsaccess.o nsload.o nssearch.o nsxfeval.o \ nsalloc.o nseval.o nsnames.o nsutils.o nsxfname.o \ nsdump.o nsinit.o nsobject.o nswalk.o nsxfobj.o \ - nsparse.o + nsparse.o nspredef.o obj-$(ACPI_FUTURE_USAGE) += nsdumpdv.o diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c index 0ab22004728..cc0ae39440e 100644 --- a/drivers/acpi/namespace/nsdump.c +++ b/drivers/acpi/namespace/nsdump.c @@ -43,7 +43,6 @@ #include <acpi/acpi.h> #include <acpi/acnamesp.h> -#include <acpi/acparser.h> #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsdump") @@ -334,9 +333,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, case ACPI_TYPE_LOCAL_REFERENCE: acpi_os_printf("[%s]\n", - acpi_ps_get_opcode_name(obj_desc-> - reference. - opcode)); + acpi_ut_get_reference_name(obj_desc)); break; case ACPI_TYPE_BUFFER_FIELD: diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c index d369164e00b..4cdf03ac2b4 100644 --- a/drivers/acpi/namespace/nseval.c +++ b/drivers/acpi/namespace/nseval.c @@ -78,6 +78,7 @@ ACPI_MODULE_NAME("nseval") acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) { acpi_status status; + struct acpi_namespace_node *node; ACPI_FUNCTION_TRACE(ns_evaluate); @@ -117,6 +118,8 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) info->resolved_node, acpi_ns_get_attached_object(info->resolved_node))); + node = info->resolved_node; + /* * Two major cases here: * @@ -148,21 +151,22 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) info->param_count++; } - /* Error if too few arguments were passed in */ + /* + * Warning if too few or too many arguments have been passed by the + * caller. We don't want to abort here with an error because an + * incorrect number of arguments may not cause the method to fail. + * However, the method will fail if there are too few arguments passed + * and the method attempts to use one of the missing ones. + */ if (info->param_count < info->obj_desc->method.param_count) { - ACPI_ERROR((AE_INFO, + ACPI_WARNING((AE_INFO, "Insufficient arguments - " "method [%4.4s] needs %d, found %d", acpi_ut_get_node_name(info->resolved_node), info->obj_desc->method.param_count, info->param_count)); - return_ACPI_STATUS(AE_MISSING_ARGUMENTS); - } - - /* Just a warning if too many arguments */ - - else if (info->param_count > + } else if (info->param_count > info->obj_desc->method.param_count) { ACPI_WARNING((AE_INFO, "Excess arguments - " @@ -195,7 +199,28 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) } else { /* * 2) Object is not a method, return its current value + * + * Disallow certain object types. For these, "evaluation" is undefined. */ + switch (info->resolved_node->type) { + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_EVENT: + case ACPI_TYPE_MUTEX: + case ACPI_TYPE_REGION: + case ACPI_TYPE_THERMAL: + case ACPI_TYPE_LOCAL_SCOPE: + + ACPI_ERROR((AE_INFO, + "[%4.4s] Evaluation of object type [%s] is not supported", + info->resolved_node->name.ascii, + acpi_ut_get_type_name(info->resolved_node-> + type))); + + return_ACPI_STATUS(AE_TYPE); + + default: + break; + } /* * Objects require additional resolution steps (e.g., the Node may be @@ -239,9 +264,35 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) } } - /* - * Check if there is a return value that must be dealt with - */ + /* Validation of return values for ACPI-predefined methods and objects */ + + if ((status == AE_OK) || (status == AE_CTRL_RETURN_VALUE)) { + /* + * If this is the first evaluation, check the return value. This + * ensures that any warnings will only be emitted during the very + * first evaluation of the object. + */ + if (!(node->flags & ANOBJ_EVALUATED)) { + /* + * Check for a predefined ACPI name. If found, validate the + * returned object. + * + * Note: Ignore return status for now, emit warnings if there are + * problems with the returned object. May change later to abort + * the method on invalid return object. + */ + (void)acpi_ns_check_predefined_names(node, + info-> + return_object); + } + + /* Mark the node as having been evaluated */ + + node->flags |= ANOBJ_EVALUATED; + } + + /* Check if there is a return value that must be dealt with */ + if (status == AE_CTRL_RETURN_VALUE) { /* If caller does not want the return value, delete it */ diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c index bd577387800..42a39a7c96e 100644 --- a/drivers/acpi/namespace/nsnames.c +++ b/drivers/acpi/namespace/nsnames.c @@ -115,7 +115,6 @@ acpi_ns_build_external_path(struct acpi_namespace_node *node, return (AE_OK); } -#ifdef ACPI_DEBUG_OUTPUT /******************************************************************************* * * FUNCTION: acpi_ns_get_external_pathname @@ -142,7 +141,7 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node) size = acpi_ns_get_pathname_length(node); if (!size) { - return (NULL); + return_PTR(NULL); } /* Allocate a buffer to be returned to caller */ @@ -157,12 +156,12 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node) status = acpi_ns_build_external_path(node, size, name_buffer); if (ACPI_FAILURE(status)) { - return (NULL); + ACPI_FREE(name_buffer); + return_PTR(NULL); } return_PTR(name_buffer); } -#endif /******************************************************************************* * diff --git a/drivers/acpi/namespace/nspredef.c b/drivers/acpi/namespace/nspredef.c new file mode 100644 index 00000000000..0f17cf0898c --- /dev/null +++ b/drivers/acpi/namespace/nspredef.c @@ -0,0 +1,900 @@ +/****************************************************************************** + * + * Module Name: nspredef - Validation of ACPI predefined methods and objects + * $Revision: 1.1 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include <acpi/acnamesp.h> +#include <acpi/acpredef.h> + +#define _COMPONENT ACPI_NAMESPACE +ACPI_MODULE_NAME("nspredef") + +/******************************************************************************* + * + * This module validates predefined ACPI objects that appear in the namespace, + * at the time they are evaluated (via acpi_evaluate_object). The purpose of this + * validation is to detect problems with BIOS-exposed predefined ACPI objects + * before the results are returned to the ACPI-related drivers. + * + * There are several areas that are validated: + * + * 1) The number of input arguments as defined by the method/object in the + * ASL is validated against the ACPI specification. + * 2) The type of the return object (if any) is validated against the ACPI + * specification. + * 3) For returned package objects, the count of package elements is + * validated, as well as the type of each package element. Nested + * packages are supported. + * + * For any problems found, a warning message is issued. + * + ******************************************************************************/ +/* Local prototypes */ +static acpi_status +acpi_ns_check_package(char *pathname, + union acpi_operand_object *return_object, + const union acpi_predefined_info *predefined); + +static acpi_status +acpi_ns_check_package_elements(char *pathname, + union acpi_operand_object **elements, + u8 type1, u32 count1, u8 type2, u32 count2); + +static acpi_status +acpi_ns_check_object_type(char *pathname, + union acpi_operand_object *return_object, + u32 expected_btypes, u32 package_index); + +static acpi_status +acpi_ns_check_reference(char *pathname, + union acpi_operand_object *return_object); + +/* + * Names for the types that can be returned by the predefined objects. + * Used for warning messages. Must be in the same order as the ACPI_RTYPEs + */ +static const char *acpi_rtype_names[] = { + "/Integer", + "/String", + "/Buffer", + "/Package", + "/Reference", +}; + +#define ACPI_NOT_PACKAGE ACPI_UINT32_MAX + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_predefined_names + * + * PARAMETERS: Node - Namespace node for the method/object + * return_object - Object returned from the evaluation of this + * method/object + * + * RETURN: Status + * + * DESCRIPTION: Check an ACPI name for a match in the predefined name list. + * + ******************************************************************************/ + +acpi_status +acpi_ns_check_predefined_names(struct acpi_namespace_node *node, + union acpi_operand_object *return_object) +{ + acpi_status status = AE_OK; + const union acpi_predefined_info *predefined; + char *pathname; + + /* Match the name for this method/object against the predefined list */ + + predefined = acpi_ns_check_for_predefined_name(node); + if (!predefined) { + + /* Name was not one of the predefined names */ + + return (AE_OK); + } + + /* Get the full pathname to the object, for use in error messages */ + + pathname = acpi_ns_get_external_pathname(node); + if (!pathname) { + pathname = ACPI_CAST_PTR(char, predefined->info.name); + } + + /* + * Check that the parameter count for this method is in accordance + * with the ACPI specification. + */ + acpi_ns_check_parameter_count(pathname, node, predefined); + + /* + * If there is no return value, check if we require a return value for + * this predefined name. Either one return value is expected, or none, + * for both methods and other objects. + * + * Exit now if there is no return object. Warning if one was expected. + */ + if (!return_object) { + if ((predefined->info.expected_btypes) && + (!(predefined->info.expected_btypes & ACPI_RTYPE_NONE))) { + ACPI_ERROR((AE_INFO, + "%s: Missing expected return value", + pathname)); + + status = AE_AML_NO_RETURN_VALUE; + } + goto exit; + } + + /* + * We have a return value, but if one wasn't expected, just exit, this is + * not a problem + * + * For example, if "Implicit return value" is enabled, methods will + * always return a value + */ + if (!predefined->info.expected_btypes) { + goto exit; + } + + /* + * Check that the type of the return object is what is expected for + * this predefined name + */ + status = acpi_ns_check_object_type(pathname, return_object, + predefined->info.expected_btypes, + ACPI_NOT_PACKAGE); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* For returned Package objects, check the type of all sub-objects */ + + if (ACPI_GET_OBJECT_TYPE(return_object) == ACPI_TYPE_PACKAGE) { + status = + acpi_ns_check_package(pathname, return_object, predefined); + } + + exit: + if (pathname) { + ACPI_FREE(pathname); + } + + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_parameter_count + * + * PARAMETERS: Pathname - Full pathname to the node (for error msgs) + * Node - Namespace node for the method/object + * Predefined - Pointer to entry in predefined name table + * + * RETURN: None + * + * DESCRIPTION: Check that the declared (in ASL/AML) parameter count for a + * predefined name is what is expected (i.e., what is defined in + * the ACPI specification for this predefined name.) + * + ******************************************************************************/ + +void +acpi_ns_check_parameter_count(char *pathname, + struct acpi_namespace_node *node, + const union acpi_predefined_info *predefined) +{ + u32 param_count; + u32 required_params_current; + u32 required_params_old; + + /* + * Check that the ASL-defined parameter count is what is expected for + * this predefined name. + * + * Methods have 0-7 parameters. All other types have zero. + */ + param_count = 0; + if (node->type == ACPI_TYPE_METHOD) { + param_count = node->object->method.param_count; + } + + /* Validate parameter count - allow two different legal counts (_SCP) */ + + required_params_current = predefined->info.param_count & 0x0F; + required_params_old = predefined->info.param_count >> 4; + + if ((param_count != required_params_current) && + (param_count != required_params_old)) { + ACPI_WARNING((AE_INFO, + "%s: Parameter count mismatch - ASL declared %d, expected %d", + pathname, param_count, required_params_current)); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_for_predefined_name + * + * PARAMETERS: Node - Namespace node for the method/object + * + * RETURN: Pointer to entry in predefined table. NULL indicates not found. + * + * DESCRIPTION: Check an object name against the predefined object list. + * + ******************************************************************************/ + +const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct + acpi_namespace_node + *node) +{ + const union acpi_predefined_info *this_name; + + /* Quick check for a predefined name, first character must be underscore */ + + if (node->name.ascii[0] != '_') { + return (NULL); + } + + /* Search info table for a predefined method/object name */ + + this_name = predefined_names; + while (this_name->info.name[0]) { + if (ACPI_COMPARE_NAME(node->name.ascii, this_name->info.name)) { + + /* Return pointer to this table entry */ + + return (this_name); + } + + /* + * Skip next entry in the table if this name returns a Package + * (next entry contains the package info) + */ + if (this_name->info.expected_btypes & ACPI_RTYPE_PACKAGE) { + this_name++; + } + + this_name++; + } + + return (NULL); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_package + * + * PARAMETERS: Pathname - Full pathname to the node (for error msgs) + * return_object - Object returned from the evaluation of a + * method or object + * Predefined - Pointer to entry in predefined name table + * + * RETURN: Status + * + * DESCRIPTION: Check a returned package object for the correct count and + * correct type of all sub-objects. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_check_package(char *pathname, + union acpi_operand_object *return_object, + const union acpi_predefined_info *predefined) +{ + const union acpi_predefined_info *package; + union acpi_operand_object *sub_package; + union acpi_operand_object **elements; + union acpi_operand_object **sub_elements; + acpi_status status; + u32 expected_count; + u32 count; + u32 i; + u32 j; + + ACPI_FUNCTION_NAME(ns_check_package); + + /* The package info for this name is in the next table entry */ + + package = predefined + 1; + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "%s Validating return Package of Type %X, Count %X\n", + pathname, package->ret_info.type, + return_object->package.count)); + + /* Extract package count and elements array */ + + elements = return_object->package.elements; + count = return_object->package.count; + + /* The package must have at least one element, else invalid */ + + if (!count) { + ACPI_WARNING((AE_INFO, + "%s: Return Package has no elements (empty)", + pathname)); + + return (AE_AML_OPERAND_VALUE); + } + + /* + * Decode the type of the expected package contents + * + * PTYPE1 packages contain no subpackages + * PTYPE2 packages contain sub-packages + */ + switch (package->ret_info.type) { + case ACPI_PTYPE1_FIXED: + + /* + * The package count is fixed and there are no sub-packages + * + * If package is too small, exit. + * If package is larger than expected, issue warning but continue + */ + expected_count = + package->ret_info.count1 + package->ret_info.count2; + if (count < expected_count) { + goto package_too_small; + } else if (count > expected_count) { + ACPI_WARNING((AE_INFO, + "%s: Return Package is larger than needed - " + "found %u, expected %u", pathname, count, + expected_count)); + } + + /* Validate all elements of the returned package */ + + status = acpi_ns_check_package_elements(pathname, elements, + package->ret_info. + object_type1, + package->ret_info. + count1, + package->ret_info. + object_type2, + package->ret_info. + count2); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + + case ACPI_PTYPE1_VAR: + + /* + * The package count is variable, there are no sub-packages, and all + * elements must be of the same type + */ + for (i = 0; i < count; i++) { + status = acpi_ns_check_object_type(pathname, *elements, + package->ret_info. + object_type1, i); + if (ACPI_FAILURE(status)) { + return (status); + } + elements++; + } + break; + + case ACPI_PTYPE1_OPTION: + + /* + * The package count is variable, there are no sub-packages. There are + * a fixed number of required elements, and a variable number of + * optional elements. + * + * Check if package is at least as large as the minimum required + */ + expected_count = package->ret_info3.count; + if (count < expected_count) { + goto package_too_small; + } + + /* Variable number of sub-objects */ + + for (i = 0; i < count; i++) { + if (i < package->ret_info3.count) { + + /* These are the required package elements (0, 1, or 2) */ + + status = + acpi_ns_check_object_type(pathname, + *elements, + package-> + ret_info3. + object_type[i], + i); + if (ACPI_FAILURE(status)) { + return (status); + } + } else { + /* These are the optional package elements */ + + status = + acpi_ns_check_object_type(pathname, + *elements, + package-> + ret_info3. + tail_object_type, + i); + if (ACPI_FAILURE(status)) { + return (status); + } + } + elements++; + } + break; + + case ACPI_PTYPE2_PKG_COUNT: + + /* First element is the (Integer) count of sub-packages to follow */ + + status = acpi_ns_check_object_type(pathname, *elements, + ACPI_RTYPE_INTEGER, 0); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* + * Count cannot be larger than the parent package length, but allow it + * to be smaller. The >= accounts for the Integer above. + */ + expected_count = (u32) (*elements)->integer.value; + if (expected_count >= count) { + goto package_too_small; + } + + count = expected_count; + elements++; + + /* Now we can walk the sub-packages */ + + /*lint -fallthrough */ + + case ACPI_PTYPE2: + case ACPI_PTYPE2_FIXED: + case ACPI_PTYPE2_MIN: + case ACPI_PTYPE2_COUNT: + + /* + * These types all return a single package that consists of a variable + * number of sub-packages + */ + for (i = 0; i < count; i++) { + sub_package = *elements; + sub_elements = sub_package->package.elements; + + /* Each sub-object must be of type Package */ + + status = + acpi_ns_check_object_type(pathname, sub_package, + ACPI_RTYPE_PACKAGE, i); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Examine the different types of sub-packages */ + + switch (package->ret_info.type) { + case ACPI_PTYPE2: + case ACPI_PTYPE2_PKG_COUNT: + + /* Each subpackage has a fixed number of elements */ + + expected_count = + package->ret_info.count1 + + package->ret_info.count2; + if (sub_package->package.count != + expected_count) { + count = sub_package->package.count; + goto package_too_small; + } + + status = + acpi_ns_check_package_elements(pathname, + sub_elements, + package-> + ret_info. + object_type1, + package-> + ret_info. + count1, + package-> + ret_info. + object_type2, + package-> + ret_info. + count2); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + + case ACPI_PTYPE2_FIXED: + + /* Each sub-package has a fixed length */ + + expected_count = package->ret_info2.count; + if (sub_package->package.count < expected_count) { + count = sub_package->package.count; + goto package_too_small; + } + + /* Check the type of each sub-package element */ + + for (j = 0; j < expected_count; j++) { + status = + acpi_ns_check_object_type(pathname, + sub_elements + [j], + package-> + ret_info2. + object_type + [j], j); + if (ACPI_FAILURE(status)) { + return (status); + } + } + break; + + case ACPI_PTYPE2_MIN: + + /* Each sub-package has a variable but minimum length */ + + expected_count = package->ret_info.count1; + if (sub_package->package.count < expected_count) { + count = sub_package->package.count; + goto package_too_small; + } + + /* Check the type of each sub-package element */ + + status = + acpi_ns_check_package_elements(pathname, + sub_elements, + package-> + ret_info. + object_type1, + sub_package-> + package. + count, 0, 0); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + + case ACPI_PTYPE2_COUNT: + + /* First element is the (Integer) count of elements to follow */ + + status = + acpi_ns_check_object_type(pathname, + *sub_elements, + ACPI_RTYPE_INTEGER, + 0); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Make sure package is large enough for the Count */ + + expected_count = + (u32) (*sub_elements)->integer.value; + if (sub_package->package.count < expected_count) { + count = sub_package->package.count; + goto package_too_small; + } + + /* Check the type of each sub-package element */ + + status = + acpi_ns_check_package_elements(pathname, + (sub_elements + + 1), + package-> + ret_info. + object_type1, + (expected_count + - 1), 0, 0); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + + default: + break; + } + + elements++; + } + break; + + default: + + /* Should not get here if predefined info table is correct */ + + ACPI_WARNING((AE_INFO, + "%s: Invalid internal return type in table entry: %X", + pathname, package->ret_info.type)); + + return (AE_AML_INTERNAL); + } + + return (AE_OK); + + package_too_small: + + /* Error exit for the case with an incorrect package count */ + + ACPI_WARNING((AE_INFO, "%s: Return Package is too small - " + "found %u, expected %u", pathname, count, + expected_count)); + + return (AE_AML_OPERAND_VALUE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_package_elements + * + * PARAMETERS: Pathname - Full pathname to the node (for error msgs) + * Elements - Pointer to the package elements array + * Type1 - Object type for first group + * Count1 - Count for first group + * Type2 - Object type for second group + * Count2 - Count for second group + * + * RETURN: Status + * + * DESCRIPTION: Check that all elements of a package are of the correct object + * type. Supports up to two groups of different object types. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_check_package_elements(char *pathname, + union acpi_operand_object **elements, + u8 type1, u32 count1, u8 type2, u32 count2) +{ + union acpi_operand_object **this_element = elements; + acpi_status status; + u32 i; + + /* + * Up to two groups of package elements are supported by the data + * structure. All elements in each group must be of the same type. + * The second group can have a count of zero. + */ + for (i = 0; i < count1; i++) { + status = acpi_ns_check_object_type(pathname, *this_element, + type1, i); + if (ACPI_FAILURE(status)) { + return (status); + } + this_element++; + } + + for (i = 0; i < count2; i++) { + status = acpi_ns_check_object_type(pathname, *this_element, + type2, (i + count1)); + if (ACPI_FAILURE(status)) { + return (status); + } + this_element++; + } + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_object_type + * + * PARAMETERS: Pathname - Full pathname to the node (for error msgs) + * return_object - Object return from the execution of this + * method/object + * expected_btypes - Bitmap of expected return type(s) + * package_index - Index of object within parent package (if + * applicable - ACPI_NOT_PACKAGE otherwise) + * + * RETURN: Status + * + * DESCRIPTION: Check the type of the return object against the expected object + * type(s). Use of Btype allows multiple expected object types. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_check_object_type(char *pathname, + union acpi_operand_object *return_object, + u32 expected_btypes, u32 package_index) +{ + acpi_status status = AE_OK; + u32 return_btype; + char type_buffer[48]; /* Room for 5 types */ + u32 this_rtype; + u32 i; + u32 j; + + /* + * If we get a NULL return_object here, it is a NULL package element, + * and this is always an error. + */ + if (!return_object) { + goto type_error_exit; + } + + /* A Namespace node should not get here, but make sure */ + + if (ACPI_GET_DESCRIPTOR_TYPE(return_object) == ACPI_DESC_TYPE_NAMED) { + ACPI_WARNING((AE_INFO, + "%s: Invalid return type - Found a Namespace node [%4.4s] type %s", + pathname, return_object->node.name.ascii, + acpi_ut_get_type_name(return_object->node.type))); + return (AE_AML_OPERAND_TYPE); + } + + /* + * Convert the object type (ACPI_TYPE_xxx) to a bitmapped object type. + * The bitmapped type allows multiple possible return types. + * + * Note, the cases below must handle all of the possible types returned + * from all of the predefined names (including elements of returned + * packages) + */ + switch (ACPI_GET_OBJECT_TYPE(return_object)) { + case ACPI_TYPE_INTEGER: + return_btype = ACPI_RTYPE_INTEGER; + break; + + case ACPI_TYPE_BUFFER: + return_btype = ACPI_RTYPE_BUFFER; + break; + + case ACPI_TYPE_STRING: + return_btype = ACPI_RTYPE_STRING; + break; + + case ACPI_TYPE_PACKAGE: + return_btype = ACPI_RTYPE_PACKAGE; + break; + + case ACPI_TYPE_LOCAL_REFERENCE: + return_btype = ACPI_RTYPE_REFERENCE; + break; + + default: + /* Not one of the supported objects, must be incorrect */ + + goto type_error_exit; + } + + /* Is the object one of the expected types? */ + + if (!(return_btype & expected_btypes)) { + goto type_error_exit; + } + + /* For reference objects, check that the reference type is correct */ + + if (ACPI_GET_OBJECT_TYPE(return_object) == ACPI_TYPE_LOCAL_REFERENCE) { + status = acpi_ns_check_reference(pathname, return_object); + } + + return (status); + + type_error_exit: + + /* Create a string with all expected types for this predefined object */ + + j = 1; + type_buffer[0] = 0; + this_rtype = ACPI_RTYPE_INTEGER; + + for (i = 0; i < ACPI_NUM_RTYPES; i++) { + + /* If one of the expected types, concatenate the name of this type */ + + if (expected_btypes & this_rtype) { + ACPI_STRCAT(type_buffer, &acpi_rtype_names[i][j]); + j = 0; /* Use name separator from now on */ + } + this_rtype <<= 1; /* Next Rtype */ + } + + if (package_index == ACPI_NOT_PACKAGE) { + ACPI_WARNING((AE_INFO, + "%s: Return type mismatch - found %s, expected %s", + pathname, + acpi_ut_get_object_type_name(return_object), + type_buffer)); + } else { + ACPI_WARNING((AE_INFO, + "%s: Return Package type mismatch at index %u - " + "found %s, expected %s", pathname, package_index, + acpi_ut_get_object_type_name(return_object), + type_buffer)); + } + + return (AE_AML_OPERAND_TYPE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_reference + * + * PARAMETERS: Pathname - Full pathname to the node (for error msgs) + * return_object - Object returned from the evaluation of a + * method or object + * + * RETURN: Status + * + * DESCRIPTION: Check a returned reference object for the correct reference + * type. The only reference type that can be returned from a + * predefined method is a named reference. All others are invalid. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_check_reference(char *pathname, + union acpi_operand_object *return_object) +{ + + /* + * Check the reference object for the correct reference type (opcode). + * The only type of reference that can be converted to an union acpi_object is + * a reference to a named object (reference class: NAME) + */ + if (return_object->reference.class == ACPI_REFCLASS_NAME) { + return (AE_OK); + } + + ACPI_WARNING((AE_INFO, + "%s: Return type mismatch - unexpected reference object type [%s] %2.2X", + pathname, acpi_ut_get_reference_name(return_object), + return_object->reference.class)); + + return (AE_AML_OPERAND_TYPE); +} diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c index 8399276cba1..a9a80bf811b 100644 --- a/drivers/acpi/namespace/nssearch.c +++ b/drivers/acpi/namespace/nssearch.c @@ -331,7 +331,7 @@ acpi_ns_search_and_enter(u32 target_name, "Found bad character(s) in name, repaired: [%4.4s]\n", ACPI_CAST_PTR(char, &target_name))); } else { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found bad character(s) in name, repaired: [%4.4s]\n", ACPI_CAST_PTR(char, &target_name))); } diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c index 38be5865d95..a085cc39c05 100644 --- a/drivers/acpi/namespace/nsxfeval.c +++ b/drivers/acpi/namespace/nsxfeval.c @@ -48,6 +48,10 @@ #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsxfeval") + +/* Local prototypes */ +static void acpi_ns_resolve_references(struct acpi_evaluate_info *info); + #ifdef ACPI_FUTURE_USAGE /******************************************************************************* * @@ -69,6 +73,7 @@ ACPI_MODULE_NAME("nsxfeval") * be valid (non-null) * ******************************************************************************/ + acpi_status acpi_evaluate_object_typed(acpi_handle handle, acpi_string pathname, @@ -283,6 +288,10 @@ acpi_evaluate_object(acpi_handle handle, if (ACPI_SUCCESS(status)) { + /* Dereference Index and ref_of references */ + + acpi_ns_resolve_references(info); + /* Get the size of the returned object */ status = @@ -352,6 +361,74 @@ ACPI_EXPORT_SYMBOL(acpi_evaluate_object) /******************************************************************************* * + * FUNCTION: acpi_ns_resolve_references + * + * PARAMETERS: Info - Evaluation info block + * + * RETURN: Info->return_object is replaced with the dereferenced object + * + * DESCRIPTION: Dereference certain reference objects. Called before an + * internal return object is converted to an external union acpi_object. + * + * Performs an automatic dereference of Index and ref_of reference objects. + * These reference objects are not supported by the union acpi_object, so this is a + * last resort effort to return something useful. Also, provides compatibility + * with other ACPI implementations. + * + * NOTE: does not handle references within returned package objects or nested + * references, but this support could be added later if found to be necessary. + * + ******************************************************************************/ +static void acpi_ns_resolve_references(struct acpi_evaluate_info *info) +{ + union acpi_operand_object *obj_desc = NULL; + struct acpi_namespace_node *node; + + /* We are interested in reference objects only */ + + if (ACPI_GET_OBJECT_TYPE(info->return_object) != + ACPI_TYPE_LOCAL_REFERENCE) { + return; + } + + /* + * Two types of references are supported - those created by Index and + * ref_of operators. A name reference (AML_NAMEPATH_OP) can be converted + * to an union acpi_object, so it is not dereferenced here. A ddb_handle + * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to + * an union acpi_object. + */ + switch (info->return_object->reference.class) { + case ACPI_REFCLASS_INDEX: + + obj_desc = *(info->return_object->reference.where); + break; + + case ACPI_REFCLASS_REFOF: + + node = info->return_object->reference.object; + if (node) { + obj_desc = node->object; + } + break; + + default: + return; + } + + /* Replace the existing reference object */ + + if (obj_desc) { + acpi_ut_add_reference(obj_desc); + acpi_ut_remove_reference(info->return_object); + info->return_object = obj_desc; + } + + return; +} + +/******************************************************************************* + * * FUNCTION: acpi_walk_namespace * * PARAMETERS: Type - acpi_object_type to search for @@ -379,6 +456,7 @@ ACPI_EXPORT_SYMBOL(acpi_evaluate_object) * function, etc. * ******************************************************************************/ + acpi_status acpi_walk_namespace(acpi_object_type type, acpi_handle start_object, diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c index a287ed550f5..5efa4e7ddb0 100644 --- a/drivers/acpi/namespace/nsxfname.c +++ b/drivers/acpi/namespace/nsxfname.c @@ -253,6 +253,7 @@ acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer) node = acpi_ns_map_handle_to_node(handle); if (!node) { (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + status = AE_BAD_PARAMETER; goto cleanup; } @@ -264,6 +265,10 @@ acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer) info->name = node->name.integer; info->valid = 0; + if (node->type == ACPI_TYPE_METHOD) { + info->param_count = node->object->method.param_count; + } + status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { goto cleanup; diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index cb9864e39ba..25ceae9191e 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -258,7 +258,7 @@ int __init acpi_numa_init(void) int acpi_get_pxm(acpi_handle h) { - unsigned long pxm; + unsigned long long pxm; acpi_status status; acpi_handle handle; acpi_handle phandle = h; diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 235a1386888..4be252145cb 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -608,7 +608,7 @@ static void acpi_os_derive_pci_id_2(acpi_handle rhandle, /* upper bound */ acpi_handle handle; struct acpi_pci_id *pci_id = *id; acpi_status status; - unsigned long temp; + unsigned long long temp; acpi_object_type type; acpi_get_parent(chandle, &handle); @@ -620,8 +620,7 @@ static void acpi_os_derive_pci_id_2(acpi_handle rhandle, /* upper bound */ if ((ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE)) return; - status = - acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, + status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &temp); if (ACPI_SUCCESS(status)) { u32 val; @@ -682,6 +681,22 @@ static void acpi_os_execute_deferred(struct work_struct *work) return; } +static void acpi_os_execute_hp_deferred(struct work_struct *work) +{ + struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); + if (!dpc) { + printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); + return; + } + + acpi_os_wait_events_complete(NULL); + + dpc->function(dpc->context); + kfree(dpc); + + return; +} + /******************************************************************************* * * FUNCTION: acpi_os_execute @@ -697,12 +712,13 @@ static void acpi_os_execute_deferred(struct work_struct *work) * ******************************************************************************/ -acpi_status acpi_os_execute(acpi_execute_type type, - acpi_osd_exec_callback function, void *context) +static acpi_status __acpi_os_execute(acpi_execute_type type, + acpi_osd_exec_callback function, void *context, int hp) { acpi_status status = AE_OK; struct acpi_os_dpc *dpc; struct workqueue_struct *queue; + int ret; ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Scheduling function [%p(%p)] for deferred execution.\n", function, context)); @@ -726,19 +742,38 @@ acpi_status acpi_os_execute(acpi_execute_type type, dpc->function = function; dpc->context = context; - INIT_WORK(&dpc->work, acpi_os_execute_deferred); - queue = (type == OSL_NOTIFY_HANDLER) ? kacpi_notify_wq : kacpid_wq; - if (!queue_work(queue, &dpc->work)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Call to queue_work() failed.\n")); + if (!hp) { + INIT_WORK(&dpc->work, acpi_os_execute_deferred); + queue = (type == OSL_NOTIFY_HANDLER) ? + kacpi_notify_wq : kacpid_wq; + ret = queue_work(queue, &dpc->work); + } else { + INIT_WORK(&dpc->work, acpi_os_execute_hp_deferred); + ret = schedule_work(&dpc->work); + } + + if (!ret) { + printk(KERN_ERR PREFIX + "Call to queue_work() failed.\n"); status = AE_ERROR; kfree(dpc); } return_ACPI_STATUS(status); } +acpi_status acpi_os_execute(acpi_execute_type type, + acpi_osd_exec_callback function, void *context) +{ + return __acpi_os_execute(type, function, context, 0); +} EXPORT_SYMBOL(acpi_os_execute); +acpi_status acpi_os_hotplug_execute(acpi_osd_exec_callback function, + void *context) +{ + return __acpi_os_execute(0, function, context, 1); +} + void acpi_os_wait_events_complete(void *context) { flush_workqueue(kacpid_wq); diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c index c06238e55d9..4647039a0d8 100644 --- a/drivers/acpi/parser/psloop.c +++ b/drivers/acpi/parser/psloop.c @@ -719,6 +719,8 @@ acpi_ps_complete_op(struct acpi_walk_state *walk_state, *op = NULL; } + ACPI_PREEMPTION_POINT(); + return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c index 15e1702e48d..68e932f215e 100644 --- a/drivers/acpi/parser/psparse.c +++ b/drivers/acpi/parser/psparse.c @@ -137,6 +137,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, union acpi_parse_object *next; const struct acpi_opcode_info *parent_info; union acpi_parse_object *replacement_op = NULL; + acpi_status status = AE_OK; ACPI_FUNCTION_TRACE_PTR(ps_complete_this_op, op); @@ -186,7 +187,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, replacement_op = acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP); if (!replacement_op) { - goto allocate_error; + status = AE_NO_MEMORY; } break; @@ -211,7 +212,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, replacement_op = acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP); if (!replacement_op) { - goto allocate_error; + status = AE_NO_MEMORY; } } else if ((op->common.parent->common.aml_opcode == @@ -226,13 +227,13 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, acpi_ps_alloc_op(op->common. aml_opcode); if (!replacement_op) { - goto allocate_error; + status = AE_NO_MEMORY; + } else { + replacement_op->named.data = + op->named.data; + replacement_op->named.length = + op->named.length; } - - replacement_op->named.data = - op->named.data; - replacement_op->named.length = - op->named.length; } } break; @@ -242,7 +243,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, replacement_op = acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP); if (!replacement_op) { - goto allocate_error; + status = AE_NO_MEMORY; } } @@ -302,14 +303,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, /* Now we can actually delete the subtree rooted at Op */ acpi_ps_delete_parse_tree(op); - return_ACPI_STATUS(AE_OK); - - allocate_error: - - /* Always delete the subtree, even on error */ - - acpi_ps_delete_parse_tree(op); - return_ACPI_STATUS(AE_NO_MEMORY); + return_ACPI_STATUS(status); } /******************************************************************************* @@ -641,10 +635,12 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) ACPI_WALK_METHOD_RESTART; } } else { - /* On error, delete any return object */ + /* On error, delete any return object or implicit return */ acpi_ut_remove_reference(previous_walk_state-> return_desc); + acpi_ds_clear_implicit_return + (previous_walk_state); } } diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index cf47805a744..fcfdef7b4fd 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -709,7 +709,7 @@ int acpi_pci_link_free_irq(acpi_handle handle) acpi_device_bid(link->device))); if (link->refcnt == 0) { - acpi_ut_evaluate_object(link->device->handle, "_DIS", 0, NULL); + acpi_evaluate_object(link->device->handle, "_DIS", NULL, NULL); } mutex_unlock(&acpi_link_lock); return (link->irq.active); @@ -737,7 +737,7 @@ static int acpi_pci_link_add(struct acpi_device *device) link->device = device; strcpy(acpi_device_name(device), ACPI_PCI_LINK_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS); - acpi_driver_data(device) = link; + device->driver_data = link; mutex_lock(&acpi_link_lock); result = acpi_pci_link_get_possible(link); @@ -773,7 +773,7 @@ static int acpi_pci_link_add(struct acpi_device *device) end: /* disable all links -- to be activated on use */ - acpi_ut_evaluate_object(device->handle, "_DIS", 0, NULL); + acpi_evaluate_object(device->handle, "_DIS", NULL, NULL); mutex_unlock(&acpi_link_lock); if (result) diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index c3fed31166b..1b8f67d21d5 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -190,7 +190,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) struct acpi_pci_root *root = NULL; struct acpi_pci_root *tmp; acpi_status status = AE_OK; - unsigned long value = 0; + unsigned long long value = 0; acpi_handle handle = NULL; struct acpi_device *child; @@ -206,7 +206,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) root->device = device; strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); - acpi_driver_data(device) = root; + device->driver_data = root; device->ops.bind = acpi_pci_bind; diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c index d5b4ef89887..9bb84d4596b 100644 --- a/drivers/acpi/pci_slot.c +++ b/drivers/acpi/pci_slot.c @@ -76,10 +76,10 @@ static struct acpi_pci_driver acpi_pci_slot_driver = { }; static int -check_slot(acpi_handle handle, unsigned long *sun) +check_slot(acpi_handle handle, unsigned long long *sun) { int device = -1; - unsigned long adr, sta; + unsigned long long adr, sta; acpi_status status; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -132,7 +132,7 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) { int device; - unsigned long sun; + unsigned long long sun; char name[SLOT_NAME_SIZE]; struct acpi_pci_slot *slot; struct pci_slot *pci_slot; @@ -182,7 +182,7 @@ static acpi_status walk_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) { int device, function; - unsigned long adr; + unsigned long long adr; acpi_status status; acpi_handle dummy_handle; acpi_walk_callback user_function; @@ -239,7 +239,7 @@ static int walk_root_bridge(acpi_handle handle, acpi_walk_callback user_function) { int seg, bus; - unsigned long tmp; + unsigned long long tmp; acpi_status status; acpi_handle dummy_handle; struct pci_bus *pci_bus; diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 4ab21cb1c8c..a1718e56103 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -54,6 +54,14 @@ ACPI_MODULE_NAME("power"); #define ACPI_POWER_RESOURCE_STATE_OFF 0x00 #define ACPI_POWER_RESOURCE_STATE_ON 0x01 #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF + +#ifdef MODULE_PARAM_PREFIX +#undef MODULE_PARAM_PREFIX +#endif +#define MODULE_PARAM_PREFIX "acpi." +int acpi_power_nocheck; +module_param_named(power_nocheck, acpi_power_nocheck, bool, 000); + 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); @@ -128,16 +136,16 @@ acpi_power_get_context(acpi_handle handle, return 0; } -static int acpi_power_get_state(struct acpi_power_resource *resource, int *state) +static int acpi_power_get_state(acpi_handle handle, int *state) { acpi_status status = AE_OK; - unsigned long sta = 0; + unsigned long long sta = 0; - if (!resource || !state) + if (!handle || !state) return -EINVAL; - status = acpi_evaluate_integer(resource->device->handle, "_STA", NULL, &sta); + status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); if (ACPI_FAILURE(status)) return -ENODEV; @@ -145,7 +153,7 @@ static int acpi_power_get_state(struct acpi_power_resource *resource, int *state ACPI_POWER_RESOURCE_STATE_OFF; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n", - resource->name, state ? "on" : "off")); + acpi_ut_get_node_name(handle), state ? "on" : "off")); return 0; } @@ -153,7 +161,6 @@ static int acpi_power_get_state(struct acpi_power_resource *resource, int *state static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) { int result = 0, state1; - struct acpi_power_resource *resource = NULL; u32 i = 0; @@ -161,12 +168,15 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) return -EINVAL; /* The state of the list is 'on' IFF all resources are 'on'. */ + /* */ for (i = 0; i < list->count; i++) { - result = acpi_power_get_context(list->handles[i], &resource); - if (result) - return result; - result = acpi_power_get_state(resource, &state1); + /* + * The state of the power resource can be obtained by + * using the ACPI handle. In such case it is unnecessary to + * get the Power resource first and then get its state again. + */ + result = acpi_power_get_state(list->handles[i], &state1); if (result) return result; @@ -226,12 +236,18 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev) if (ACPI_FAILURE(status)) return -ENODEV; - result = acpi_power_get_state(resource, &state); - if (result) - return result; - if (state != ACPI_POWER_RESOURCE_STATE_ON) - return -ENOEXEC; - + if (!acpi_power_nocheck) { + /* + * If acpi_power_nocheck is set, it is unnecessary to check + * the power state after power transition. + */ + result = acpi_power_get_state(resource->device->handle, + &state); + if (result) + return result; + if (state != ACPI_POWER_RESOURCE_STATE_ON) + return -ENOEXEC; + } /* Update the power resource's _device_ power state */ resource->device->power.state = ACPI_STATE_D0; @@ -277,11 +293,17 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev) if (ACPI_FAILURE(status)) return -ENODEV; - result = acpi_power_get_state(resource, &state); - if (result) - return result; - if (state != ACPI_POWER_RESOURCE_STATE_OFF) - return -ENOEXEC; + if (!acpi_power_nocheck) { + /* + * If acpi_power_nocheck is set, it is unnecessary to check + * the power state after power transition. + */ + result = acpi_power_get_state(handle, &state); + if (result) + return result; + if (state != ACPI_POWER_RESOURCE_STATE_OFF) + return -ENOEXEC; + } /* Update the power resource's _device_ power state */ resource->device->power.state = ACPI_STATE_D3; @@ -555,7 +577,7 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset) if (!resource) goto end; - result = acpi_power_get_state(resource, &state); + result = acpi_power_get_state(resource->device->handle, &state); if (result) goto end; @@ -657,7 +679,7 @@ static int acpi_power_add(struct acpi_device *device) strcpy(resource->name, device->pnp.bus_id); strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_POWER_CLASS); - acpi_driver_data(device) = resource; + device->driver_data = resource; /* Evalute the object to get the system level and resource order. */ status = acpi_evaluate_object(device->handle, NULL, NULL, &buffer); @@ -668,7 +690,7 @@ static int acpi_power_add(struct acpi_device *device) resource->system_level = acpi_object.power_resource.system_level; resource->order = acpi_object.power_resource.resource_order; - result = acpi_power_get_state(resource, &state); + result = acpi_power_get_state(device->handle, &state); if (result) goto end; @@ -733,9 +755,9 @@ static int acpi_power_resume(struct acpi_device *device) if (!device || !acpi_driver_data(device)) return -EINVAL; - resource = (struct acpi_power_resource *)acpi_driver_data(device); + resource = acpi_driver_data(device); - result = acpi_power_get_state(resource, &state); + result = acpi_power_get_state(device->handle, &state); if (result) return result; diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index ee68ac54c0d..24a362f8034 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -563,7 +563,7 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid) /* Check if it is a Device with HID and UID */ if (has_uid) { - unsigned long value; + unsigned long long value; status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID, NULL, &value); if (ACPI_FAILURE(status)) { @@ -818,7 +818,7 @@ static int acpi_processor_add(struct acpi_device *device) pr->handle = device->handle; strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS); - acpi_driver_data(device) = pr; + device->driver_data = pr; return 0; } @@ -875,7 +875,7 @@ static int acpi_processor_remove(struct acpi_device *device, int type) static int is_processor_present(acpi_handle handle) { acpi_status status; - unsigned long sta = 0; + unsigned long long sta = 0; status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index cf5b1b7b684..81b40ed5379 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -1587,6 +1587,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, if (acpi_idle_bm_check()) { if (dev->safe_state) { + dev->last_state = dev->safe_state; return dev->safe_state->enter(dev, dev->safe_state); } else { local_irq_disable(); diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 80c251ec6d2..dc98f7a6f2c 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -38,6 +38,7 @@ #include <asm/uaccess.h> #endif +#include <asm/cpufeature.h> #include <acpi/acpi_bus.h> #include <acpi/processor.h> @@ -126,7 +127,7 @@ static struct notifier_block acpi_ppc_notifier_block = { static int acpi_processor_get_platform_limit(struct acpi_processor *pr) { acpi_status status = 0; - unsigned long ppc = 0; + unsigned long long ppc = 0; if (!pr) @@ -334,7 +335,6 @@ static int acpi_processor_get_performance_info(struct acpi_processor *pr) acpi_status status = AE_OK; acpi_handle handle = NULL; - if (!pr || !pr->performance || !pr->handle) return -EINVAL; @@ -347,13 +347,25 @@ static int acpi_processor_get_performance_info(struct acpi_processor *pr) result = acpi_processor_get_performance_control(pr); if (result) - return result; + goto update_bios; result = acpi_processor_get_performance_states(pr); if (result) - return result; + goto update_bios; return 0; + + /* + * Having _PPC but missing frequencies (_PSS, _PCT) is a very good hint that + * the BIOS is older than the CPU and does not know its frequencies + */ + update_bios: + if (ACPI_SUCCESS(acpi_get_handle(pr->handle, "_PPC", &handle))){ + if(boot_cpu_has(X86_FEATURE_EST)) + printk(KERN_WARNING FW_BUG "BIOS needs update for CPU " + "frequency support\n"); + } + return result; } int acpi_processor_notify_smm(struct module *calling_module) @@ -524,13 +536,13 @@ static int acpi_processor_get_psd(struct acpi_processor *pr) psd = buffer.pointer; if (!psd || (psd->type != ACPI_TYPE_PACKAGE)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n")); + printk(KERN_ERR PREFIX "Invalid _PSD data\n"); result = -EFAULT; goto end; } if (psd->package.count != 1) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n")); + printk(KERN_ERR PREFIX "Invalid _PSD data\n"); result = -EFAULT; goto end; } @@ -543,19 +555,19 @@ static int acpi_processor_get_psd(struct acpi_processor *pr) status = acpi_extract_package(&(psd->package.elements[0]), &format, &state); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n")); + printk(KERN_ERR PREFIX "Invalid _PSD data\n"); result = -EFAULT; goto end; } if (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:num_entries\n")); + printk(KERN_ERR PREFIX "Unknown _PSD:num_entries\n"); result = -EFAULT; goto end; } if (pdomain->revision != ACPI_PSD_REV0_REVISION) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:revision\n")); + printk(KERN_ERR PREFIX "Unknown _PSD:revision\n"); result = -EFAULT; goto end; } diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index a56fc6c4394..3da2df93d92 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -274,7 +274,7 @@ static int acpi_processor_throttling_notifier(unsigned long event, void *data) static int acpi_processor_get_platform_limit(struct acpi_processor *pr) { acpi_status status = 0; - unsigned long tpc = 0; + unsigned long long tpc = 0; if (!pr) return -EINVAL; @@ -528,13 +528,13 @@ static int acpi_processor_get_tsd(struct acpi_processor *pr) tsd = buffer.pointer; if (!tsd || (tsd->type != ACPI_TYPE_PACKAGE)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n")); + printk(KERN_ERR PREFIX "Invalid _TSD data\n"); result = -EFAULT; goto end; } if (tsd->package.count != 1) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n")); + printk(KERN_ERR PREFIX "Invalid _TSD data\n"); result = -EFAULT; goto end; } @@ -547,19 +547,19 @@ static int acpi_processor_get_tsd(struct acpi_processor *pr) status = acpi_extract_package(&(tsd->package.elements[0]), &format, &state); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n")); + printk(KERN_ERR PREFIX "Invalid _TSD data\n"); result = -EFAULT; goto end; } if (pdomain->num_entries != ACPI_TSD_REV0_ENTRIES) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _TSD:num_entries\n")); + printk(KERN_ERR PREFIX "Unknown _TSD:num_entries\n"); result = -EFAULT; goto end; } if (pdomain->revision != ACPI_TSD_REV0_REVISION) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _TSD:revision\n")); + printk(KERN_ERR PREFIX "Unknown _TSD:revision\n"); result = -EFAULT; goto end; } diff --git a/drivers/acpi/reboot.c b/drivers/acpi/reboot.c index a6b662c00b6..755baf2ca70 100644 --- a/drivers/acpi/reboot.c +++ b/drivers/acpi/reboot.c @@ -15,9 +15,28 @@ void acpi_reboot(void) rr = &acpi_gbl_FADT.reset_register; - /* Is the reset register supported? */ - if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) || - rr->bit_width != 8 || rr->bit_offset != 0) + /* + * Is the ACPI reset register supported? + * + * According to ACPI 3.0, FADT.flags.RESET_REG_SUP indicates + * whether the ACPI reset mechanism is supported. + * + * However, some boxes have this bit clear, yet a valid + * ACPI_RESET_REG & RESET_VALUE, and ACPI reboot is the only + * mechanism that works for them after S3. + * + * This suggests that other operating systems may not be checking + * the RESET_REG_SUP bit, and are using other means to decide + * whether to use the ACPI reboot mechanism or not. + * + * So when acpi reboot is requested, + * only the reset_register is checked. If the following + * conditions are met, it indicates that the reset register is supported. + * a. reset_register is not zero + * b. the access width is eight + * c. the bit_offset is zero + */ + if (!(rr->address) || rr->bit_width != 8 || rr->bit_offset != 0) return; reset_value = acpi_gbl_FADT.reset_value; diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c index d9063ea414e..8eaaecf9200 100644 --- a/drivers/acpi/resources/rscalc.c +++ b/drivers/acpi/resources/rscalc.c @@ -43,7 +43,6 @@ #include <acpi/acpi.h> #include <acpi/acresrc.h> -#include <acpi/amlcode.h> #include <acpi/acnamesp.h> #define _COMPONENT ACPI_RESOURCES @@ -560,8 +559,8 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, ACPI_GET_OBJECT_TYPE(*sub_object_list)) || ((ACPI_TYPE_LOCAL_REFERENCE == ACPI_GET_OBJECT_TYPE(*sub_object_list)) && - ((*sub_object_list)->reference.opcode == - AML_INT_NAMEPATH_OP)))) { + ((*sub_object_list)->reference.class == + ACPI_REFCLASS_NAME)))) { name_found = TRUE; } else { /* Look at the next element */ diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c index 7804a8c40e7..c0bbfa2c419 100644 --- a/drivers/acpi/resources/rscreate.c +++ b/drivers/acpi/resources/rscreate.c @@ -43,7 +43,6 @@ #include <acpi/acpi.h> #include <acpi/acresrc.h> -#include <acpi/amlcode.h> #include <acpi/acnamesp.h> #define _COMPONENT ACPI_RESOURCES @@ -310,13 +309,12 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { case ACPI_TYPE_LOCAL_REFERENCE: - if (obj_desc->reference.opcode != - AML_INT_NAMEPATH_OP) { + if (obj_desc->reference.class != + ACPI_REFCLASS_NAME) { ACPI_ERROR((AE_INFO, - "(PRT[%X].Source) Need name, found reference op %X", + "(PRT[%X].Source) Need name, found Reference Class %X", index, - obj_desc->reference. - opcode)); + obj_desc->reference.class)); return_ACPI_STATUS(AE_BAD_DATA); } diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 7b011e7e29f..6050ce48187 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -931,7 +931,7 @@ static int acpi_sbs_add(struct acpi_device *device) sbs->device = device; strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_SBS_CLASS); - acpi_driver_data(device) = sbs; + device->driver_data = sbs; result = acpi_charger_add(sbs); if (result) diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c index a4e3767b8c6..e53e590252c 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c @@ -258,7 +258,7 @@ extern int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit, static int acpi_smbus_hc_add(struct acpi_device *device) { int status; - unsigned long val; + unsigned long long val; struct acpi_smb_hc *hc; if (!device) @@ -282,7 +282,7 @@ static int acpi_smbus_hc_add(struct acpi_device *device) hc->ec = acpi_driver_data(device->parent); hc->offset = (val >> 8) & 0xff; hc->query_bit = val & 0xff; - acpi_driver_data(device) = hc; + device->driver_data = hc; acpi_ec_add_query_handler(hc->ec, hc->query_bit, NULL, smbus_alarm, hc); printk(KERN_INFO PREFIX "SBS HC: EC = 0x%p, offset = 0x%0x, query_bit = 0x%0x\n", @@ -303,7 +303,7 @@ static int acpi_smbus_hc_remove(struct acpi_device *device, int type) hc = acpi_driver_data(device); acpi_ec_remove_query_handler(hc->ec, hc->query_bit); kfree(hc); - acpi_driver_data(device) = NULL; + device->driver_data = NULL; return 0; } diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index f6f52c1a2ab..a9dda8e0f9f 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -113,16 +113,16 @@ static int acpi_bus_hot_remove_device(void *context) if (acpi_bus_trim(device, 1)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Removing device failed\n")); + printk(KERN_ERR PREFIX + "Removing device failed\n"); return -1; } /* power off device */ status = acpi_evaluate_object(handle, "_PS3", NULL, NULL); if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "Power-off device failed\n")); + printk(KERN_WARNING PREFIX + "Power-off device failed\n"); if (device->flags.lockable) { arg_list.count = 1; @@ -276,6 +276,13 @@ int acpi_match_device_ids(struct acpi_device *device, { const struct acpi_device_id *id; + /* + * If the device is not present, it is unnecessary to load device + * driver for it. + */ + if (!device->status.present) + return -ENODEV; + if (device->flags.hardware_id) { for (id = ids; id->id[0]; id++) { if (!strcmp((char*)id->id, device->pnp.hardware_id)) @@ -384,7 +391,7 @@ static int acpi_device_remove(struct device * dev) acpi_drv->ops.remove(acpi_dev, acpi_dev->removal_type); } acpi_dev->driver = NULL; - acpi_driver_data(dev) = NULL; + acpi_dev->driver_data = NULL; put_device(dev); return 0; @@ -477,7 +484,7 @@ static int acpi_device_register(struct acpi_device *device, result = acpi_device_setup_files(device); if(result) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error creating sysfs interface for device %s\n", device->dev.bus_id)); + printk(KERN_ERR PREFIX "Error creating sysfs interface for device %s\n", device->dev.bus_id); device->removal_type = ACPI_BUS_REMOVAL_NORMAL; return 0; @@ -537,7 +544,7 @@ acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver) result = driver->ops.add(device); if (result) { device->driver = NULL; - acpi_driver_data(device) = NULL; + device->driver_data = NULL; return result; } @@ -744,6 +751,16 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) if (!acpi_match_device_ids(device, button_device_ids)) device->wakeup.flags.run_wake = 1; + /* + * Don't set Power button GPE as run_wake + * if Fixed Power button is used + */ + if (!strcmp(device->pnp.hardware_id, "PNP0C0C") && + !(acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON)) { + device->wakeup.flags.run_wake = 0; + device->wakeup.flags.valid = 0; + } + end: if (ACPI_FAILURE(status)) device->flags.wake_capable = 0; @@ -807,6 +824,7 @@ static int acpi_bus_get_power_flags(struct acpi_device *device) /* TBD: System wake support and resource requirements. */ device->power.state = ACPI_STATE_UNKNOWN; + acpi_bus_get_power(device->handle, &(device->power.state)); return 0; } @@ -1153,20 +1171,6 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice) } static int -acpi_is_child_device(struct acpi_device *device, - int (*matcher)(struct acpi_device *)) -{ - int result = -ENODEV; - - do { - if (ACPI_SUCCESS(matcher(device))) - return AE_OK; - } while ((device = device->parent)); - - return result; -} - -static int acpi_add_single_object(struct acpi_device **child, struct acpi_device *parent, acpi_handle handle, int type, struct acpi_bus_ops *ops) @@ -1221,15 +1225,18 @@ acpi_add_single_object(struct acpi_device **child, result = -ENODEV; goto end; } - if (!device->status.present) { - /* Bay and dock should be handled even if absent */ - if (!ACPI_SUCCESS( - acpi_is_child_device(device, acpi_bay_match)) && - !ACPI_SUCCESS( - acpi_is_child_device(device, acpi_dock_match))) { - result = -ENODEV; - goto end; - } + /* + * When the device is neither present nor functional, the + * device should not be added to Linux ACPI device tree. + * When the status of the device is not present but functinal, + * it should be added to Linux ACPI tree. For example : bay + * device , dock device. + * In such conditions it is unncessary to check whether it is + * bay device or dock device. + */ + if (!device->status.present && !device->status.functional) { + result = -ENODEV; + goto end; } break; default: @@ -1252,6 +1259,16 @@ acpi_add_single_object(struct acpi_device **child, acpi_device_set_id(device, parent, handle, type); /* + * The ACPI device is attached to acpi handle before getting + * the power/wakeup/peformance flags. Otherwise OS can't get + * the corresponding ACPI device by the acpi handle in the course + * of getting the power/wakeup/performance flags. + */ + result = acpi_device_set_context(device, type); + if (result) + goto end; + + /* * Power Management * ---------------- */ @@ -1281,8 +1298,6 @@ acpi_add_single_object(struct acpi_device **child, goto end; } - if ((result = acpi_device_set_context(device, type))) - goto end; result = acpi_device_register(device, parent); @@ -1402,7 +1417,12 @@ static int acpi_bus_scan(struct acpi_device *start, struct acpi_bus_ops *ops) * TBD: Need notifications and other detection mechanisms * in place before we can fully implement this. */ - if (child->status.present) { + /* + * When the device is not present but functional, it is also + * necessary to scan the children of this device. + */ + if (child->status.present || (!child->status.present && + child->status.functional)) { status = acpi_get_next_object(ACPI_TYPE_ANY, chandle, NULL, NULL); if (ACPI_SUCCESS(status)) { @@ -1545,7 +1565,6 @@ static int acpi_bus_scan_fixed(struct acpi_device *root) return result; } -int __init acpi_boot_ec_enable(void); static int __init acpi_scan_init(void) { @@ -1579,9 +1598,6 @@ static int __init acpi_scan_init(void) */ result = acpi_bus_scan_fixed(acpi_root); - /* EC region might be needed at bus_scan, so enable it now */ - acpi_boot_ec_enable(); - if (!result) result = acpi_bus_scan(acpi_root, &ops); diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index d13194a031b..76037883cd1 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c @@ -15,6 +15,7 @@ #include <linux/dmi.h> #include <linux/device.h> #include <linux/suspend.h> +#include <linux/reboot.h> #include <asm/io.h> @@ -23,6 +24,37 @@ #include "sleep.h" u8 sleep_states[ACPI_S_STATE_COUNT]; +static u32 acpi_target_sleep_state = ACPI_STATE_S0; + +static void acpi_sleep_tts_switch(u32 acpi_state) +{ + union acpi_object in_arg = { ACPI_TYPE_INTEGER }; + struct acpi_object_list arg_list = { 1, &in_arg }; + acpi_status status = AE_OK; + + in_arg.integer.value = acpi_state; + status = acpi_evaluate_object(NULL, "\\_TTS", &arg_list, NULL); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + /* + * OS can't evaluate the _TTS object correctly. Some warning + * message will be printed. But it won't break anything. + */ + printk(KERN_NOTICE "Failure in evaluating _TTS object\n"); + } +} + +static int tts_notify_reboot(struct notifier_block *this, + unsigned long code, void *x) +{ + acpi_sleep_tts_switch(ACPI_STATE_S5); + return NOTIFY_DONE; +} + +static struct notifier_block tts_notifier = { + .notifier_call = tts_notify_reboot, + .next = NULL, + .priority = 0, +}; static int acpi_sleep_prepare(u32 acpi_state) { @@ -45,9 +77,7 @@ static int acpi_sleep_prepare(u32 acpi_state) return 0; } -#ifdef CONFIG_PM_SLEEP -static u32 acpi_target_sleep_state = ACPI_STATE_S0; - +#ifdef CONFIG_ACPI_SLEEP /* * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the * user to request that behavior by using the 'acpi_old_suspend_ordering' @@ -131,8 +161,9 @@ static void acpi_pm_end(void) * failing transition to a sleep state. */ acpi_target_sleep_state = ACPI_STATE_S0; + acpi_sleep_tts_switch(acpi_target_sleep_state); } -#endif /* CONFIG_PM_SLEEP */ +#endif /* CONFIG_ACPI_SLEEP */ #ifdef CONFIG_SUSPEND extern void do_suspend_lowlevel(void); @@ -155,6 +186,7 @@ static int acpi_suspend_begin(suspend_state_t pm_state) if (sleep_states[acpi_state]) { acpi_target_sleep_state = acpi_state; + acpi_sleep_tts_switch(acpi_target_sleep_state); } else { printk(KERN_ERR "ACPI does not support this state: %d\n", pm_state); @@ -200,6 +232,8 @@ static int acpi_suspend_enter(suspend_state_t pm_state) break; } + /* If ACPI is not enabled by the BIOS, we need to enable it here. */ + acpi_enable(); /* Reprogram control registers and execute _BFS */ acpi_leave_sleep_state_prep(acpi_state); @@ -296,6 +330,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"), }, }, + { + .callback = init_old_suspend_ordering, + .ident = "HP xw4600 Workstation", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"), + }, + }, {}, }; #endif /* CONFIG_SUSPEND */ @@ -313,6 +355,7 @@ void __init acpi_no_s4_hw_signature(void) static int acpi_hibernation_begin(void) { acpi_target_sleep_state = ACPI_STATE_S4; + acpi_sleep_tts_switch(acpi_target_sleep_state); return 0; } @@ -376,7 +419,15 @@ static struct platform_hibernation_ops acpi_hibernation_ops = { */ static int acpi_hibernation_begin_old(void) { - int error = acpi_sleep_prepare(ACPI_STATE_S4); + int error; + /* + * The _TTS object should always be evaluated before the _PTS object. + * When the old_suspended_ordering is true, the _PTS object is + * evaluated in the acpi_sleep_prepare. + */ + acpi_sleep_tts_switch(ACPI_STATE_S4); + + error = acpi_sleep_prepare(ACPI_STATE_S4); if (!error) acpi_target_sleep_state = ACPI_STATE_S4; @@ -444,7 +495,7 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) acpi_handle handle = DEVICE_ACPI_HANDLE(dev); struct acpi_device *adev; char acpi_method[] = "_SxD"; - unsigned long d_min, d_max; + unsigned long long d_min, d_max; if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) { printk(KERN_DEBUG "ACPI handle has no context!\n"); @@ -596,5 +647,10 @@ int __init acpi_sleep_init(void) pm_power_off = acpi_power_off; } printk(")\n"); + /* + * Register the tts_notifier to reboot notifier list so that the _TTS + * object can also be evaluated when the system enters S5. + */ + register_reboot_notifier(&tts_notifier); return 0; } diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 24e80fd927e..1d74171b794 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -386,8 +386,8 @@ static ssize_t counter_set(struct kobject *kobj, goto end; if (!(all_counters[index].flags & ACPI_EVENT_VALID)) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "Can not change Invalid GPE/Fixed Event status\n")); + printk(KERN_WARNING PREFIX + "Can not change Invalid GPE/Fixed Event status\n"); return -EINVAL; } diff --git a/drivers/acpi/tables/tbfadt.c b/drivers/acpi/tables/tbfadt.c index a4a41ba2484..2c7885e7ffb 100644 --- a/drivers/acpi/tables/tbfadt.c +++ b/drivers/acpi/tables/tbfadt.c @@ -50,7 +50,7 @@ ACPI_MODULE_NAME("tbfadt") /* Local prototypes */ static void inline acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, - u8 bit_width, u64 address); + u8 byte_width, u64 address); static void acpi_tb_convert_fadt(void); @@ -111,7 +111,7 @@ static struct acpi_fadt_info fadt_info_table[] = { * FUNCTION: acpi_tb_init_generic_address * * PARAMETERS: generic_address - GAS struct to be initialized - * bit_width - Width of this register + * byte_width - Width of this register * Address - Address of the register * * RETURN: None @@ -124,7 +124,7 @@ static struct acpi_fadt_info fadt_info_table[] = { static void inline acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, - u8 bit_width, u64 address) + u8 byte_width, u64 address) { /* @@ -136,7 +136,7 @@ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, /* All other fields are byte-wide */ generic_address->space_id = ACPI_ADR_SPACE_SYSTEM_IO; - generic_address->bit_width = bit_width; + generic_address->bit_width = byte_width << 3; generic_address->bit_offset = 0; generic_address->access_width = 0; } @@ -342,9 +342,20 @@ static void acpi_tb_convert_fadt(void) * useful to calculate them once, here. * * The PM event blocks are split into two register blocks, first is the - * PM Status Register block, followed immediately by the PM Enable Register - * block. Each is of length (pm1_event_length/2) + * PM Status Register block, followed immediately by the PM Enable + * Register block. Each is of length (xpm1x_event_block.bit_width/2). + * + * On various systems the v2 fields (and particularly the bit widths) + * cannot be relied upon, though. Hence resort to using the v1 length + * here (and warn about the inconsistency). */ + if (acpi_gbl_FADT.xpm1a_event_block.bit_width + != acpi_gbl_FADT.pm1_event_length * 8) + printk(KERN_WARNING "FADT: " + "X_PM1a_EVT_BLK.bit_width (%u) does not match" + " PM1_EVT_LEN (%u)\n", + acpi_gbl_FADT.xpm1a_event_block.bit_width, + acpi_gbl_FADT.pm1_event_length); pm1_register_length = (u8) ACPI_DIV_2(acpi_gbl_FADT.pm1_event_length); /* The PM1A register block is required */ @@ -360,13 +371,20 @@ static void acpi_tb_convert_fadt(void) /* The PM1B register block is optional, ignore if not present */ if (acpi_gbl_FADT.xpm1b_event_block.address) { + if (acpi_gbl_FADT.xpm1b_event_block.bit_width + != acpi_gbl_FADT.pm1_event_length * 8) + printk(KERN_WARNING "FADT: " + "X_PM1b_EVT_BLK.bit_width (%u) does not match" + " PM1_EVT_LEN (%u)\n", + acpi_gbl_FADT.xpm1b_event_block.bit_width, + acpi_gbl_FADT.pm1_event_length); acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, pm1_register_length, (acpi_gbl_FADT.xpm1b_event_block. address + pm1_register_length)); /* Don't forget to copy space_id of the GAS */ acpi_gbl_xpm1b_enable.space_id = - acpi_gbl_FADT.xpm1a_event_block.space_id; + acpi_gbl_FADT.xpm1b_event_block.space_id; } } diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c index b22185f55a1..18747ce8dd2 100644 --- a/drivers/acpi/tables/tbinstal.c +++ b/drivers/acpi/tables/tbinstal.c @@ -110,7 +110,6 @@ acpi_status acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) { u32 i; - u32 length; acpi_status status = AE_OK; ACPI_FUNCTION_TRACE(tb_add_table); @@ -145,25 +144,64 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) } } - length = ACPI_MIN(table_desc->length, - acpi_gbl_root_table_list.tables[i].length); + /* + * Check for a table match on the entire table length, + * not just the header. + */ + if (table_desc->length != + acpi_gbl_root_table_list.tables[i].length) { + continue; + } + if (ACPI_MEMCMP(table_desc->pointer, acpi_gbl_root_table_list.tables[i].pointer, - length)) { + acpi_gbl_root_table_list.tables[i].length)) { continue; } - /* Table is already registered */ - + /* + * Note: the current mechanism does not unregister a table if it is + * dynamically unloaded. The related namespace entries are deleted, + * but the table remains in the root table list. + * + * The assumption here is that the number of different tables that + * will be loaded is actually small, and there is minimal overhead + * in just keeping the table in case it is needed again. + * + * If this assumption changes in the future (perhaps on large + * machines with many table load/unload operations), tables will + * need to be unregistered when they are unloaded, and slots in the + * root table list should be reused when empty. + */ + + /* + * Table is already registered. + * We can delete the table that was passed as a parameter. + */ acpi_tb_delete_table(table_desc); *table_index = i; - status = AE_ALREADY_EXISTS; - goto release; + + if (acpi_gbl_root_table_list.tables[i]. + flags & ACPI_TABLE_IS_LOADED) { + + /* Table is still loaded, this is an error */ + + status = AE_ALREADY_EXISTS; + goto release; + } else { + /* Table was unloaded, allow it to be reloaded */ + + table_desc->pointer = + acpi_gbl_root_table_list.tables[i].pointer; + table_desc->address = + acpi_gbl_root_table_list.tables[i].address; + status = AE_OK; + goto print_header; + } } - /* - * Add the table to the global table list - */ + /* Add the table to the global root table list */ + status = acpi_tb_store_table(table_desc->address, table_desc->pointer, table_desc->length, table_desc->flags, table_index); @@ -171,6 +209,7 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) goto release; } + print_header: acpi_tb_print_table_header(table_desc->address, table_desc->pointer); release: diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 912703691d3..ad6cae938f0 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -246,18 +246,18 @@ static const struct file_operations acpi_thermal_polling_fops = { static int acpi_thermal_get_temperature(struct acpi_thermal *tz) { acpi_status status = AE_OK; - + unsigned long long tmp; if (!tz) return -EINVAL; tz->last_temperature = tz->temperature; - status = - acpi_evaluate_integer(tz->device->handle, "_TMP", NULL, &tz->temperature); + status = acpi_evaluate_integer(tz->device->handle, "_TMP", NULL, &tmp); if (ACPI_FAILURE(status)) return -ENODEV; + tz->temperature = tmp; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Temperature is %lu dK\n", tz->temperature)); @@ -267,17 +267,16 @@ static int acpi_thermal_get_temperature(struct acpi_thermal *tz) static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz) { acpi_status status = AE_OK; - + unsigned long long tmp; if (!tz) return -EINVAL; - status = - acpi_evaluate_integer(tz->device->handle, "_TZP", NULL, - &tz->polling_frequency); + status = acpi_evaluate_integer(tz->device->handle, "_TZP", NULL, &tmp); if (ACPI_FAILURE(status)) return -ENODEV; + tz->polling_frequency = tmp; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency is %lu dS\n", tz->polling_frequency)); @@ -356,6 +355,7 @@ do { \ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) { acpi_status status = AE_OK; + unsigned long long tmp; struct acpi_handle_list devices; int valid = 0; int i; @@ -363,7 +363,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) /* Critical Shutdown (required) */ if (flag & ACPI_TRIPS_CRITICAL) { status = acpi_evaluate_integer(tz->device->handle, - "_CRT", NULL, &tz->trips.critical.temperature); + "_CRT", NULL, &tmp); + tz->trips.critical.temperature = tmp; /* * Treat freezing temperatures as invalid as well; some * BIOSes return really low values and cause reboots at startup. @@ -388,10 +389,12 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) } else if (crt > 0) { unsigned long crt_k = CELSIUS_TO_KELVIN(crt); /* - * Allow override to lower critical threshold + * Allow override critical threshold */ - if (crt_k < tz->trips.critical.temperature) - tz->trips.critical.temperature = crt_k; + if (crt_k > tz->trips.critical.temperature) + printk(KERN_WARNING PREFIX + "Critical threshold %d C\n", crt); + tz->trips.critical.temperature = crt_k; } } } @@ -399,12 +402,13 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) /* Critical Sleep (optional) */ if (flag & ACPI_TRIPS_HOT) { status = acpi_evaluate_integer(tz->device->handle, - "_HOT", NULL, &tz->trips.hot.temperature); + "_HOT", NULL, &tmp); if (ACPI_FAILURE(status)) { tz->trips.hot.flags.valid = 0; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No hot threshold\n")); } else { + tz->trips.hot.temperature = tmp; tz->trips.hot.flags.valid = 1; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found hot threshold [%lu]\n", @@ -418,33 +422,40 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) if (psv == -1) { status = AE_SUPPORT; } else if (psv > 0) { - tz->trips.passive.temperature = CELSIUS_TO_KELVIN(psv); + tmp = CELSIUS_TO_KELVIN(psv); status = AE_OK; } else { status = acpi_evaluate_integer(tz->device->handle, - "_PSV", NULL, &tz->trips.passive.temperature); + "_PSV", NULL, &tmp); } if (ACPI_FAILURE(status)) tz->trips.passive.flags.valid = 0; else { + tz->trips.passive.temperature = tmp; tz->trips.passive.flags.valid = 1; if (flag == ACPI_TRIPS_INIT) { status = acpi_evaluate_integer( tz->device->handle, "_TC1", - NULL, &tz->trips.passive.tc1); + NULL, &tmp); if (ACPI_FAILURE(status)) tz->trips.passive.flags.valid = 0; + else + tz->trips.passive.tc1 = tmp; status = acpi_evaluate_integer( tz->device->handle, "_TC2", - NULL, &tz->trips.passive.tc2); + NULL, &tmp); if (ACPI_FAILURE(status)) tz->trips.passive.flags.valid = 0; + else + tz->trips.passive.tc2 = tmp; status = acpi_evaluate_integer( tz->device->handle, "_TSP", - NULL, &tz->trips.passive.tsp); + NULL, &tmp); if (ACPI_FAILURE(status)) tz->trips.passive.flags.valid = 0; + else + tz->trips.passive.tsp = tmp; } } } @@ -479,7 +490,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) if (flag & ACPI_TRIPS_ACTIVE) { status = acpi_evaluate_integer(tz->device->handle, - name, NULL, &tz->trips.active[i].temperature); + name, NULL, &tmp); if (ACPI_FAILURE(status)) { tz->trips.active[i].flags.valid = 0; if (i == 0) @@ -500,8 +511,10 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) tz->trips.active[i - 2].temperature : CELSIUS_TO_KELVIN(act)); break; - } else + } else { + tz->trips.active[i].temperature = tmp; tz->trips.active[i].flags.valid = 1; + } } name[2] = 'L'; @@ -1213,8 +1226,8 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) acpi_bus_private_data_handler, tz->thermal_zone); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error attaching device data\n")); + printk(KERN_ERR PREFIX + "Error attaching device data\n"); return -ENODEV; } @@ -1647,7 +1660,7 @@ static int acpi_thermal_add(struct acpi_device *device) strcpy(tz->name, device->pnp.bus_id); strcpy(acpi_device_name(device), ACPI_THERMAL_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS); - acpi_driver_data(device) = tz; + device->driver_data = tz; mutex_init(&tz->lock); diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c index 8a649f40d16..2a632f8b7a0 100644 --- a/drivers/acpi/toshiba_acpi.c +++ b/drivers/acpi/toshiba_acpi.c @@ -548,7 +548,7 @@ static unsigned long write_video(const char *buffer, unsigned long count) hci_read1(HCI_VIDEO_OUT, &video_out, &hci_result); if (hci_result == HCI_SUCCESS) { - int new_video_out = video_out; + unsigned int new_video_out = video_out; if (lcd_out != -1) _set_bit(&new_video_out, HCI_VIDEO_OUT_LCD, lcd_out); if (crt_out != -1) diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c index 7dcb67e0b21..241c535c175 100644 --- a/drivers/acpi/utilities/utalloc.c +++ b/drivers/acpi/utilities/utalloc.c @@ -232,7 +232,7 @@ acpi_status acpi_ut_validate_buffer(struct acpi_buffer * buffer) * RETURN: Status * * DESCRIPTION: Validate that the buffer is of the required length or - * allocate a new buffer. Returned buffer is always zeroed. + * allocate a new buffer. Returned buffer is always zeroed. * ******************************************************************************/ @@ -240,7 +240,7 @@ acpi_status acpi_ut_initialize_buffer(struct acpi_buffer * buffer, acpi_size required_length) { - acpi_status status = AE_OK; + acpi_size input_buffer_length; /* Parameter validation */ @@ -248,55 +248,58 @@ acpi_ut_initialize_buffer(struct acpi_buffer * buffer, return (AE_BAD_PARAMETER); } - switch (buffer->length) { + /* + * Buffer->Length is used as both an input and output parameter. Get the + * input actual length and set the output required buffer length. + */ + input_buffer_length = buffer->length; + buffer->length = required_length; + + /* + * The input buffer length contains the actual buffer length, or the type + * of buffer to be allocated by this routine. + */ + switch (input_buffer_length) { case ACPI_NO_BUFFER: - /* Set the exception and returned the required length */ + /* Return the exception (and the required buffer length) */ - status = AE_BUFFER_OVERFLOW; - break; + return (AE_BUFFER_OVERFLOW); case ACPI_ALLOCATE_BUFFER: /* Allocate a new buffer */ buffer->pointer = acpi_os_allocate(required_length); - if (!buffer->pointer) { - return (AE_NO_MEMORY); - } - - /* Clear the buffer */ - - ACPI_MEMSET(buffer->pointer, 0, required_length); break; case ACPI_ALLOCATE_LOCAL_BUFFER: /* Allocate a new buffer with local interface to allow tracking */ - buffer->pointer = ACPI_ALLOCATE_ZEROED(required_length); - if (!buffer->pointer) { - return (AE_NO_MEMORY); - } + buffer->pointer = ACPI_ALLOCATE(required_length); break; default: /* Existing buffer: Validate the size of the buffer */ - if (buffer->length < required_length) { - status = AE_BUFFER_OVERFLOW; - break; + if (input_buffer_length < required_length) { + return (AE_BUFFER_OVERFLOW); } + break; + } - /* Clear the buffer */ + /* Validate allocation from above or input buffer pointer */ - ACPI_MEMSET(buffer->pointer, 0, required_length); - break; + if (!buffer->pointer) { + return (AE_NO_MEMORY); } - buffer->length = required_length; - return (status); + /* Have a valid buffer, clear it */ + + ACPI_MEMSET(buffer->pointer, 0, required_length); + return (AE_OK); } #ifdef NOT_USED_BY_LINUX diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c index 53499ac9098..5b2f7c27b70 100644 --- a/drivers/acpi/utilities/utcopy.c +++ b/drivers/acpi/utilities/utcopy.c @@ -42,7 +42,6 @@ */ #include <acpi/acpi.h> -#include <acpi/amlcode.h> #include <acpi/acnamesp.h> @@ -176,20 +175,24 @@ acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object, /* This is an object reference. */ - switch (internal_object->reference.opcode) { - case AML_INT_NAMEPATH_OP: - - /* For namepath, return the object handle ("reference") */ - - default: - - /* We are referring to the namespace node */ + switch (internal_object->reference.class) { + case ACPI_REFCLASS_NAME: + /* + * For namepath, return the object handle ("reference") + * We are referring to the namespace node + */ external_object->reference.handle = internal_object->reference.node; external_object->reference.actual_type = acpi_ns_get_type(internal_object->reference.node); break; + + default: + + /* All other reference types are unsupported */ + + return_ACPI_STATUS(AE_TYPE); } break; @@ -533,7 +536,7 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, /* TBD: should validate incoming handle */ - internal_object->reference.opcode = AML_INT_NAMEPATH_OP; + internal_object->reference.class = ACPI_REFCLASS_NAME; internal_object->reference.node = external_object->reference.handle; break; @@ -743,11 +746,11 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc, * We copied the reference object, so we now must add a reference * to the object pointed to by the reference * - * DDBHandle reference (from Load/load_table is a special reference, - * it's Reference.Object is the table index, so does not need to + * DDBHandle reference (from Load/load_table) is a special reference, + * it does not have a Reference.Object, so does not need to * increase the reference count */ - if (source_desc->reference.opcode == AML_LOAD_OP) { + if (source_desc->reference.class == ACPI_REFCLASS_TABLE) { break; } diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c index 42609d3a8aa..d197c6b29e1 100644 --- a/drivers/acpi/utilities/utdelete.c +++ b/drivers/acpi/utilities/utdelete.c @@ -45,7 +45,6 @@ #include <acpi/acinterp.h> #include <acpi/acnamesp.h> #include <acpi/acevents.h> -#include <acpi/amlcode.h> #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utdelete") @@ -548,8 +547,8 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) * reference must track changes to the ref count of the index or * target object. */ - if ((object->reference.opcode == AML_INDEX_OP) || - (object->reference.opcode == AML_INT_NAMEPATH_OP)) { + if ((object->reference.class == ACPI_REFCLASS_INDEX) || + (object->reference.class == ACPI_REFCLASS_NAME)) { next_object = object->reference.object; } break; @@ -586,6 +585,13 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) ACPI_EXCEPTION((AE_INFO, status, "Could not update object reference count")); + /* Free any stacked Update State objects */ + + while (state_list) { + state = acpi_ut_pop_generic_state(&state_list); + acpi_ut_delete_generic_state(state); + } + return_ACPI_STATUS(status); } diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index a6e71b801d2..670551b95e5 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c @@ -281,7 +281,6 @@ struct acpi_bit_register_info acpi_gbl_bit_register_info[ACPI_NUM_BITREG] = { /* ACPI_BITREG_RT_CLOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_RT_CLOCK_ENABLE, ACPI_BITMASK_RT_CLOCK_ENABLE}, - /* ACPI_BITREG_WAKE_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, 0, 0}, /* ACPI_BITREG_PCIEXP_WAKE_DISABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_PCIEXP_WAKE_DISABLE, ACPI_BITMASK_PCIEXP_WAKE_DISABLE}, @@ -575,6 +574,47 @@ char *acpi_ut_get_descriptor_name(void *object) } +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_reference_name + * + * PARAMETERS: Object - An ACPI reference object + * + * RETURN: Pointer to a string + * + * DESCRIPTION: Decode a reference object sub-type to a string. + * + ******************************************************************************/ + +/* Printable names of reference object sub-types */ + +static const char *acpi_gbl_ref_class_names[] = { + /* 00 */ "Local", + /* 01 */ "Argument", + /* 02 */ "RefOf", + /* 03 */ "Index", + /* 04 */ "DdbHandle", + /* 05 */ "Named Object", + /* 06 */ "Debug" +}; + +const char *acpi_ut_get_reference_name(union acpi_operand_object *object) +{ + if (!object) + return "NULL Object"; + + if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) + return "Not an Operand object"; + + if (object->common.type != ACPI_TYPE_LOCAL_REFERENCE) + return "Not a Reference object"; + + if (object->reference.class > ACPI_REFCLASS_MAX) + return "Unknown Reference class"; + + return acpi_gbl_ref_class_names[object->reference.class]; +} + #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) /* * Strings and procedures used for debug only @@ -677,14 +717,14 @@ u8 acpi_ut_valid_object_type(acpi_object_type type) * * PARAMETERS: None * - * RETURN: None + * RETURN: Status * * DESCRIPTION: Init library globals. All globals that require specific * initialization should be initialized here! * ******************************************************************************/ -void acpi_ut_init_globals(void) +acpi_status acpi_ut_init_globals(void) { acpi_status status; u32 i; @@ -695,7 +735,7 @@ void acpi_ut_init_globals(void) status = acpi_ut_create_caches(); if (ACPI_FAILURE(status)) { - return; + return_ACPI_STATUS(status); } /* Mutex locked flags */ @@ -772,8 +812,8 @@ void acpi_ut_init_globals(void) acpi_gbl_display_final_mem_stats = FALSE; #endif - return_VOID; + return_ACPI_STATUS(AE_OK); } ACPI_EXPORT_SYMBOL(acpi_dbg_level) - ACPI_EXPORT_SYMBOL(acpi_dbg_layer) +ACPI_EXPORT_SYMBOL(acpi_dbg_layer) diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c index f34be677355..9089a158a87 100644 --- a/drivers/acpi/utilities/utmisc.c +++ b/drivers/acpi/utilities/utmisc.c @@ -995,6 +995,15 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object, state->pkg. this_target_obj, 0); if (!state) { + + /* Free any stacked Update State objects */ + + while (state_list) { + state = + acpi_ut_pop_generic_state + (&state_list); + acpi_ut_delete_generic_state(state); + } return_ACPI_STATUS(AE_NO_MEMORY); } } diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c index 916eff399eb..c354e7a42bc 100644 --- a/drivers/acpi/utilities/utobject.c +++ b/drivers/acpi/utilities/utobject.c @@ -43,7 +43,6 @@ #include <acpi/acpi.h> #include <acpi/acnamesp.h> -#include <acpi/amlcode.h> #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utobject") @@ -478,8 +477,8 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, case ACPI_TYPE_LOCAL_REFERENCE: - switch (internal_object->reference.opcode) { - case AML_INT_NAMEPATH_OP: + switch (internal_object->reference.class) { + case ACPI_REFCLASS_NAME: /* * Get the actual length of the full pathname to this object. @@ -503,8 +502,10 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, * required eventually. */ ACPI_ERROR((AE_INFO, - "Unsupported Reference opcode=%X in object %p", - internal_object->reference.opcode, + "Cannot convert to external object - " + "unsupported Reference Class [%s] %X in object %p", + acpi_ut_get_reference_name(internal_object), + internal_object->reference.class, internal_object)); status = AE_TYPE; break; @@ -513,7 +514,9 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, default: - ACPI_ERROR((AE_INFO, "Unsupported type=%X in object %p", + ACPI_ERROR((AE_INFO, "Cannot convert to external object - " + "unsupported type [%s] %X in object %p", + acpi_ut_get_object_type_name(internal_object), ACPI_GET_OBJECT_TYPE(internal_object), internal_object)); status = AE_TYPE; diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c index f8bdadf3c32..c198a4d4058 100644 --- a/drivers/acpi/utilities/utxface.c +++ b/drivers/acpi/utilities/utxface.c @@ -81,7 +81,12 @@ acpi_status __init acpi_initialize_subsystem(void) /* Initialize all globals used by the subsystem */ - acpi_ut_init_globals(); + status = acpi_ut_init_globals(); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "During initialization of globals")); + return_ACPI_STATUS(status); + } /* Create the default mutex objects */ diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 10092614381..e827be36ee8 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -256,7 +256,7 @@ EXPORT_SYMBOL(acpi_extract_package); acpi_status acpi_evaluate_integer(acpi_handle handle, acpi_string pathname, - struct acpi_object_list *arguments, unsigned long *data) + struct acpi_object_list *arguments, unsigned long long *data) { acpi_status status = AE_OK; union acpi_object *element; @@ -288,7 +288,7 @@ acpi_evaluate_integer(acpi_handle handle, *data = element->integer.value; kfree(element); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%lu]\n", *data)); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%llu]\n", *data)); return AE_OK; } diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index e8a51a1700f..a29b0ccac65 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -291,20 +291,20 @@ static int acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level); static int acpi_video_device_lcd_get_level_current( struct acpi_video_device *device, - unsigned long *level); + unsigned long long *level); static int acpi_video_get_next_level(struct acpi_video_device *device, u32 level_current, u32 event); static void acpi_video_switch_brightness(struct acpi_video_device *device, int event); static int acpi_video_device_get_state(struct acpi_video_device *device, - unsigned long *state); + unsigned long long *state); static int acpi_video_output_get(struct output_device *od); static int acpi_video_device_set_state(struct acpi_video_device *device, int state); /*backlight device sysfs support*/ static int acpi_video_get_brightness(struct backlight_device *bd) { - unsigned long cur_level; + unsigned long long cur_level; int i; struct acpi_video_device *vd = (struct acpi_video_device *)bl_get_data(bd); @@ -336,7 +336,7 @@ static struct backlight_ops acpi_backlight_ops = { /*video output device sysfs support*/ static int acpi_video_output_get(struct output_device *od) { - unsigned long state; + unsigned long long state; struct acpi_video_device *vd = (struct acpi_video_device *)dev_get_drvdata(&od->dev); acpi_video_device_get_state(vd, &state); @@ -370,7 +370,7 @@ static int video_get_cur_state(struct thermal_cooling_device *cdev, char *buf) { struct acpi_device *device = cdev->devdata; struct acpi_video_device *video = acpi_driver_data(device); - unsigned long level; + unsigned long long level; int state; acpi_video_device_lcd_get_level_current(video, &level); @@ -410,7 +410,7 @@ static struct thermal_cooling_device_ops video_cooling_ops = { /* device */ static int -acpi_video_device_query(struct acpi_video_device *device, unsigned long *state) +acpi_video_device_query(struct acpi_video_device *device, unsigned long long *state) { int status; @@ -421,7 +421,7 @@ acpi_video_device_query(struct acpi_video_device *device, unsigned long *state) static int acpi_video_device_get_state(struct acpi_video_device *device, - unsigned long *state) + unsigned long long *state) { int status; @@ -436,7 +436,7 @@ acpi_video_device_set_state(struct acpi_video_device *device, int state) int status; union acpi_object arg0 = { ACPI_TYPE_INTEGER }; struct acpi_object_list args = { 1, &arg0 }; - unsigned long ret; + unsigned long long ret; arg0.integer.value = state; @@ -495,7 +495,7 @@ acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level) static int acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, - unsigned long *level) + unsigned long long *level) { if (device->cap._BQC) return acpi_evaluate_integer(device->dev->handle, "_BQC", NULL, @@ -549,7 +549,7 @@ static int acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option) { int status; - unsigned long tmp; + unsigned long long tmp; union acpi_object arg0 = { ACPI_TYPE_INTEGER }; struct acpi_object_list args = { 1, &arg0 }; @@ -564,7 +564,7 @@ acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option) } static int -acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long *id) +acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long long *id) { int status; @@ -575,7 +575,7 @@ acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long *id) static int acpi_video_bus_POST_options(struct acpi_video_bus *video, - unsigned long *options) + unsigned long long *options) { int status; @@ -918,7 +918,7 @@ static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset) { int status; struct acpi_video_device *dev = seq->private; - unsigned long state; + unsigned long long state; if (!dev) @@ -927,14 +927,14 @@ static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset) status = acpi_video_device_get_state(dev, &state); seq_printf(seq, "state: "); if (ACPI_SUCCESS(status)) - seq_printf(seq, "0x%02lx\n", state); + seq_printf(seq, "0x%02llx\n", state); else seq_printf(seq, "<not supported>\n"); status = acpi_video_device_query(dev, &state); seq_printf(seq, "query: "); if (ACPI_SUCCESS(status)) - seq_printf(seq, "0x%02lx\n", state); + seq_printf(seq, "0x%02llx\n", state); else seq_printf(seq, "<not supported>\n"); @@ -1217,7 +1217,7 @@ static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file) static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset) { struct acpi_video_bus *video = seq->private; - unsigned long options; + unsigned long long options; int status; @@ -1232,7 +1232,7 @@ static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset) printk(KERN_WARNING PREFIX "This indicates a BIOS bug. Please contact the manufacturer.\n"); } - printk("%lx\n", options); + printk("%llx\n", options); seq_printf(seq, "can POST: <integrated video>"); if (options & 2) seq_printf(seq, " <PCI video>"); @@ -1256,7 +1256,7 @@ static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset) { struct acpi_video_bus *video = seq->private; int status; - unsigned long id; + unsigned long long id; if (!video) @@ -1303,7 +1303,7 @@ acpi_video_bus_write_POST(struct file *file, struct seq_file *m = file->private_data; struct acpi_video_bus *video = m->private; char str[12] = { 0 }; - unsigned long opt, options; + unsigned long long opt, options; if (!video || count + 1 > sizeof str) @@ -1473,7 +1473,7 @@ static int acpi_video_bus_get_one_device(struct acpi_device *device, struct acpi_video_bus *video) { - unsigned long device_id; + unsigned long long device_id; int status; struct acpi_video_device *data; struct acpi_video_device_attrib* attribute; @@ -1491,7 +1491,7 @@ acpi_video_bus_get_one_device(struct acpi_device *device, strcpy(acpi_device_name(device), ACPI_VIDEO_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS); - acpi_driver_data(device) = data; + device->driver_data = data; data->device_id = device_id; data->video = video; @@ -1530,8 +1530,8 @@ acpi_video_bus_get_one_device(struct acpi_device *device, acpi_video_device_notify, data); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error installing notify handler\n")); + printk(KERN_ERR PREFIX + "Error installing notify handler\n"); if(data->brightness) kfree(data->brightness->levels); kfree(data->brightness); @@ -1724,7 +1724,7 @@ acpi_video_get_next_level(struct acpi_video_device *device, static void acpi_video_switch_brightness(struct acpi_video_device *device, int event) { - unsigned long level_current, level_next; + unsigned long long level_current, level_next; if (!device->brightness) return; acpi_video_device_lcd_get_level_current(device, &level_current); @@ -1745,8 +1745,8 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video, status = acpi_video_bus_get_one_device(dev, video); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "Cant attach device")); + printk(KERN_WARNING PREFIX + "Cant attach device"); continue; } } @@ -1982,7 +1982,7 @@ static int acpi_video_bus_add(struct acpi_device *device) video->device = device; strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME); strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS); - acpi_driver_data(device) = video; + device->driver_data = video; acpi_video_bus_find_cap(video); error = acpi_video_bus_check(video); @@ -2003,8 +2003,8 @@ static int acpi_video_bus_add(struct acpi_device *device) ACPI_DEVICE_NOTIFY, acpi_video_bus_notify, video); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error installing notify handler\n")); + printk(KERN_ERR PREFIX + "Error installing notify handler\n"); error = -ENODEV; goto err_stop_video; } @@ -2058,7 +2058,7 @@ static int acpi_video_bus_add(struct acpi_device *device) acpi_video_bus_remove_fs(device); err_free_video: kfree(video); - acpi_driver_data(device) = NULL; + device->driver_data = NULL; return error; } diff --git a/drivers/acpi/wmi.c b/drivers/acpi/wmi.c index cfe2c833474..47cd7baf9b1 100644 --- a/drivers/acpi/wmi.c +++ b/drivers/acpi/wmi.c @@ -217,6 +217,35 @@ static bool find_guid(const char *guid_string, struct wmi_block **out) return 0; } +static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable) +{ + struct guid_block *block = NULL; + char method[5]; + struct acpi_object_list input; + union acpi_object params[1]; + acpi_status status; + acpi_handle handle; + + block = &wblock->gblock; + handle = wblock->handle; + + if (!block) + return AE_NOT_EXIST; + + input.count = 1; + input.pointer = params; + params[0].type = ACPI_TYPE_INTEGER; + params[0].integer.value = enable; + + snprintf(method, 5, "WE%02X", block->notify_id); + status = acpi_evaluate_object(handle, method, &input, NULL); + + if (status != AE_OK && status != AE_NOT_FOUND) + return status; + else + return AE_OK; +} + /* * Exported WMI functions */ @@ -242,7 +271,7 @@ u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out) char method[4] = "WM"; if (!find_guid(guid_string, &wblock)) - return AE_BAD_ADDRESS; + return AE_ERROR; block = &wblock->gblock; handle = wblock->handle; @@ -304,7 +333,7 @@ struct acpi_buffer *out) return AE_BAD_PARAMETER; if (!find_guid(guid_string, &wblock)) - return AE_BAD_ADDRESS; + return AE_ERROR; block = &wblock->gblock; handle = wblock->handle; @@ -314,7 +343,7 @@ struct acpi_buffer *out) /* Check GUID is a data block */ if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD)) - return AE_BAD_ADDRESS; + return AE_ERROR; input.count = 1; input.pointer = wq_params; @@ -385,7 +414,7 @@ const struct acpi_buffer *in) return AE_BAD_DATA; if (!find_guid(guid_string, &wblock)) - return AE_BAD_ADDRESS; + return AE_ERROR; block = &wblock->gblock; handle = wblock->handle; @@ -395,7 +424,7 @@ const struct acpi_buffer *in) /* Check GUID is a data block */ if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD)) - return AE_BAD_ADDRESS; + return AE_ERROR; input.count = 2; input.pointer = params; @@ -427,6 +456,7 @@ acpi_status wmi_install_notify_handler(const char *guid, wmi_notify_handler handler, void *data) { struct wmi_block *block; + acpi_status status; if (!guid || !handler) return AE_BAD_PARAMETER; @@ -441,7 +471,9 @@ wmi_notify_handler handler, void *data) block->handler = handler; block->handler_data = data; - return AE_OK; + status = wmi_method_enable(block, 1); + + return status; } EXPORT_SYMBOL_GPL(wmi_install_notify_handler); @@ -453,6 +485,7 @@ EXPORT_SYMBOL_GPL(wmi_install_notify_handler); acpi_status wmi_remove_notify_handler(const char *guid) { struct wmi_block *block; + acpi_status status; if (!guid) return AE_BAD_PARAMETER; @@ -464,10 +497,12 @@ acpi_status wmi_remove_notify_handler(const char *guid) if (!block->handler) return AE_NULL_ENTRY; + status = wmi_method_enable(block, 0); + block->handler = NULL; block->handler_data = NULL; - return AE_OK; + return status; } EXPORT_SYMBOL_GPL(wmi_remove_notify_handler); diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 9330b7922f6..c012307d0ba 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -120,21 +120,6 @@ static void ata_acpi_associate_ide_port(struct ata_port *ap) ap->pflags |= ATA_PFLAG_INIT_GTM_VALID; } -static void ata_acpi_eject_device(acpi_handle handle) -{ - struct acpi_object_list arg_list; - union acpi_object arg; - - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = 1; - - if (ACPI_FAILURE(acpi_evaluate_object(handle, "_EJ0", - &arg_list, NULL))) - printk(KERN_ERR "Failed to evaluate _EJ0!\n"); -} - /* @ap and @dev are the same as ata_acpi_handle_hotplug() */ static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev) { @@ -157,7 +142,6 @@ static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev) * @ap: ATA port ACPI event occurred * @dev: ATA device ACPI event occurred (can be NULL) * @event: ACPI event which occurred - * @is_dock_event: boolean indicating whether the event was a dock one * * All ACPI bay / device realted events end up in this function. If * the event is port-wide @dev is NULL. If the event is specific to a @@ -171,117 +155,100 @@ static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev) * ACPI notify handler context. May sleep. */ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev, - u32 event, int is_dock_event) + u32 event) { - char event_string[12]; - char *envp[] = { event_string, NULL }; struct ata_eh_info *ehi = &ap->link.eh_info; - struct kobject *kobj = NULL; int wait = 0; unsigned long flags; - acpi_handle handle, tmphandle; - unsigned long sta; - acpi_status status; + acpi_handle handle; - if (dev) { - if (dev->sdev) - kobj = &dev->sdev->sdev_gendev.kobj; + if (dev) handle = dev->acpi_handle; - } else { - kobj = &ap->dev->kobj; + else handle = ap->acpi_handle; - } - - status = acpi_get_handle(handle, "_EJ0", &tmphandle); - if (ACPI_FAILURE(status)) - /* This device does not support hotplug */ - return; - - if (event == ACPI_NOTIFY_BUS_CHECK || - event == ACPI_NOTIFY_DEVICE_CHECK) - status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); spin_lock_irqsave(ap->lock, flags); - + /* + * When dock driver calls into the routine, it will always use + * ACPI_NOTIFY_BUS_CHECK/ACPI_NOTIFY_DEVICE_CHECK for add and + * ACPI_NOTIFY_EJECT_REQUEST for remove + */ switch (event) { case ACPI_NOTIFY_BUS_CHECK: case ACPI_NOTIFY_DEVICE_CHECK: ata_ehi_push_desc(ehi, "ACPI event"); - if (ACPI_FAILURE(status)) { - ata_port_printk(ap, KERN_ERR, - "acpi: failed to determine bay status (0x%x)\n", - status); - break; - } - - if (sta) { - ata_ehi_hotplugged(ehi); - ata_port_freeze(ap); - } else { - /* The device has gone - unplug it */ - ata_acpi_detach_device(ap, dev); - wait = 1; - } + ata_ehi_hotplugged(ehi); + ata_port_freeze(ap); break; case ACPI_NOTIFY_EJECT_REQUEST: ata_ehi_push_desc(ehi, "ACPI event"); - if (!is_dock_event) - break; - - /* undock event - immediate unplug */ ata_acpi_detach_device(ap, dev); wait = 1; break; } - /* make sure kobj doesn't go away while ap->lock is released */ - kobject_get(kobj); - spin_unlock_irqrestore(ap->lock, flags); - if (wait) { + if (wait) ata_port_wait_eh(ap); - ata_acpi_eject_device(handle); - } - - if (kobj && !is_dock_event) { - sprintf(event_string, "BAY_EVENT=%d", event); - kobject_uevent_env(kobj, KOBJ_CHANGE, envp); - } - - kobject_put(kobj); } static void ata_acpi_dev_notify_dock(acpi_handle handle, u32 event, void *data) { struct ata_device *dev = data; - ata_acpi_handle_hotplug(dev->link->ap, dev, event, 1); + ata_acpi_handle_hotplug(dev->link->ap, dev, event); } static void ata_acpi_ap_notify_dock(acpi_handle handle, u32 event, void *data) { struct ata_port *ap = data; - ata_acpi_handle_hotplug(ap, NULL, event, 1); + ata_acpi_handle_hotplug(ap, NULL, event); } -static void ata_acpi_dev_notify(acpi_handle handle, u32 event, void *data) +static void ata_acpi_uevent(struct ata_port *ap, struct ata_device *dev, + u32 event) { - struct ata_device *dev = data; + struct kobject *kobj = NULL; + char event_string[20]; + char *envp[] = { event_string, NULL }; + + if (dev) { + if (dev->sdev) + kobj = &dev->sdev->sdev_gendev.kobj; + } else + kobj = &ap->dev->kobj; - ata_acpi_handle_hotplug(dev->link->ap, dev, event, 0); + if (kobj) { + snprintf(event_string, 20, "BAY_EVENT=%d", event); + kobject_uevent_env(kobj, KOBJ_CHANGE, envp); + } } -static void ata_acpi_ap_notify(acpi_handle handle, u32 event, void *data) +static void ata_acpi_ap_uevent(acpi_handle handle, u32 event, void *data) { - struct ata_port *ap = data; + ata_acpi_uevent(data, NULL, event); +} - ata_acpi_handle_hotplug(ap, NULL, event, 0); +static void ata_acpi_dev_uevent(acpi_handle handle, u32 event, void *data) +{ + struct ata_device *dev = data; + ata_acpi_uevent(dev->link->ap, dev, event); } +static struct acpi_dock_ops ata_acpi_dev_dock_ops = { + .handler = ata_acpi_dev_notify_dock, + .uevent = ata_acpi_dev_uevent, +}; + +static struct acpi_dock_ops ata_acpi_ap_dock_ops = { + .handler = ata_acpi_ap_notify_dock, + .uevent = ata_acpi_ap_uevent, +}; + /** * ata_acpi_associate - associate ATA host with ACPI objects * @host: target ATA host @@ -315,24 +282,18 @@ void ata_acpi_associate(struct ata_host *host) ata_acpi_associate_ide_port(ap); if (ap->acpi_handle) { - acpi_install_notify_handler(ap->acpi_handle, - ACPI_SYSTEM_NOTIFY, - ata_acpi_ap_notify, ap); /* we might be on a docking station */ register_hotplug_dock_device(ap->acpi_handle, - ata_acpi_ap_notify_dock, ap); + &ata_acpi_ap_dock_ops, ap); } for (j = 0; j < ata_link_max_devices(&ap->link); j++) { struct ata_device *dev = &ap->link.device[j]; if (dev->acpi_handle) { - acpi_install_notify_handler(dev->acpi_handle, - ACPI_SYSTEM_NOTIFY, - ata_acpi_dev_notify, dev); /* we might be on a docking station */ register_hotplug_dock_device(dev->acpi_handle, - ata_acpi_dev_notify_dock, dev); + &ata_acpi_dev_dock_ops, dev); } } } diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 5ce07b517c5..bb6e3b33804 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -56,7 +56,11 @@ static void cpuidle_idle_call(void) if (pm_idle_old) pm_idle_old(); else +#if defined(CONFIG_ARCH_HAS_DEFAULT_IDLE) + default_idle(); +#else local_irq_enable(); +#endif return; } @@ -67,8 +71,11 @@ static void cpuidle_idle_call(void) target_state = &dev->states[next_state]; /* enter the state and update stats */ - dev->last_residency = target_state->enter(dev, target_state); dev->last_state = target_state; + dev->last_residency = target_state->enter(dev, target_state); + if (dev->last_state) + target_state = dev->last_state; + target_state->time += (unsigned long long)dev->last_residency; target_state->usage++; diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c index 1ef68b31565..43b8cefad2c 100644 --- a/drivers/dma/ioat_dma.c +++ b/drivers/dma/ioat_dma.c @@ -171,6 +171,9 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device) xfercap_scale = readb(device->reg_base + IOAT_XFERCAP_OFFSET); xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale)); +#if CONFIG_I7300_IDLE_IOAT_CHANNEL + device->common.chancnt--; +#endif for (i = 0; i < device->common.chancnt; i++) { ioat_chan = kzalloc(sizeof(*ioat_chan), GFP_KERNEL); if (!ioat_chan) { diff --git a/drivers/idle/Kconfig b/drivers/idle/Kconfig new file mode 100644 index 00000000000..f5b26dd579e --- /dev/null +++ b/drivers/idle/Kconfig @@ -0,0 +1,16 @@ + +menu "Memory power savings" + +config I7300_IDLE_IOAT_CHANNEL + bool + +config I7300_IDLE + tristate "Intel chipset idle power saving driver" + select I7300_IDLE_IOAT_CHANNEL + depends on X86_64 + help + Enable idle power savings with certain Intel server chipsets. + The chipset must have I/O AT support, such as the Intel 7300. + The power savings depends on the type and quantity of DRAM devices. + +endmenu diff --git a/drivers/idle/Makefile b/drivers/idle/Makefile new file mode 100644 index 00000000000..5f68fc377e2 --- /dev/null +++ b/drivers/idle/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_I7300_IDLE) += i7300_idle.o + diff --git a/drivers/idle/i7300_idle.c b/drivers/idle/i7300_idle.c new file mode 100644 index 00000000000..59d1bbc3cd3 --- /dev/null +++ b/drivers/idle/i7300_idle.c @@ -0,0 +1,674 @@ +/* + * (C) Copyright 2008 Intel Corporation + * Authors: + * Andy Henroid <andrew.d.henroid@intel.com> + * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> + */ + +/* + * Save DIMM power on Intel 7300-based platforms when all CPUs/cores + * are idle, using the DIMM thermal throttling capability. + * + * This driver depends on the Intel integrated DMA controller (I/O AT). + * If the driver for I/O AT (drivers/dma/ioatdma*) is also enabled, + * this driver should work cooperatively. + */ + +/* #define DEBUG */ + +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/sched.h> +#include <linux/notifier.h> +#include <linux/cpumask.h> +#include <linux/ktime.h> +#include <linux/delay.h> +#include <linux/debugfs.h> +#include <linux/stop_machine.h> + +#include <asm/idle.h> + +#include "../dma/ioatdma_hw.h" +#include "../dma/ioatdma_registers.h" + +#define I7300_IDLE_DRIVER_VERSION "1.55" +#define I7300_PRINT "i7300_idle:" + +static int debug; +module_param_named(debug, debug, uint, 0644); +MODULE_PARM_DESC(debug, "Enable debug printks in this driver"); + +#define dprintk(fmt, arg...) \ + do { if (debug) printk(KERN_INFO I7300_PRINT fmt, ##arg); } while (0) + +/* + * Value to set THRTLOW to when initiating throttling + * 0 = No throttling + * 1 = Throttle when > 4 activations per eval window (Maximum throttling) + * 2 = Throttle when > 8 activations + * 168 = Throttle when > 168 activations (Minimum throttling) + */ +#define MAX_THRTLWLIMIT 168 +static uint i7300_idle_thrtlowlm = 1; +module_param_named(thrtlwlimit, i7300_idle_thrtlowlm, uint, 0644); +MODULE_PARM_DESC(thrtlwlimit, + "Value for THRTLOWLM activation field " + "(0 = disable throttle, 1 = Max throttle, 168 = Min throttle)"); + +/* + * simple invocation and duration statistics + */ +static unsigned long total_starts; +static unsigned long total_us; + +#ifdef DEBUG +static unsigned long past_skip; +#endif + +static struct pci_dev *fbd_dev; + +static spinlock_t i7300_idle_lock; +static int i7300_idle_active; + +static u8 i7300_idle_thrtctl_saved; +static u8 i7300_idle_thrtlow_saved; +static u32 i7300_idle_mc_saved; + +static cpumask_t idle_cpumask; +static ktime_t start_ktime; +static unsigned long avg_idle_us; + +static struct dentry *debugfs_dir; + +/* Begin: I/O AT Helper routines */ + +#define IOAT_CHANBASE(ioat_ctl, chan) (ioat_ctl + 0x80 + 0x80 * chan) +/* Snoop control (disable snoops when coherency is not important) */ +#define IOAT_DESC_SADDR_SNP_CTL (1UL << 1) +#define IOAT_DESC_DADDR_SNP_CTL (1UL << 2) + +static struct pci_dev *ioat_dev; +static struct ioat_dma_descriptor *ioat_desc; /* I/O AT desc & data (1 page) */ +static unsigned long ioat_desc_phys; +static u8 *ioat_iomap; /* I/O AT memory-mapped control regs (aka CB_BAR) */ +static u8 *ioat_chanbase; + +/* Start I/O AT memory copy */ +static int i7300_idle_ioat_start(void) +{ + u32 err; + /* Clear error (due to circular descriptor pointer) */ + err = readl(ioat_chanbase + IOAT_CHANERR_OFFSET); + if (err) + writel(err, ioat_chanbase + IOAT_CHANERR_OFFSET); + + writeb(IOAT_CHANCMD_START, ioat_chanbase + IOAT1_CHANCMD_OFFSET); + return 0; +} + +/* Stop I/O AT memory copy */ +static void i7300_idle_ioat_stop(void) +{ + int i; + u8 sts; + + for (i = 0; i < 5; i++) { + writeb(IOAT_CHANCMD_RESET, + ioat_chanbase + IOAT1_CHANCMD_OFFSET); + + udelay(10); + + sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) & + IOAT_CHANSTS_DMA_TRANSFER_STATUS; + + if (sts != IOAT_CHANSTS_DMA_TRANSFER_STATUS_ACTIVE) + break; + + } + + if (i == 5) + dprintk("failed to suspend+reset I/O AT after 5 retries\n"); + +} + +/* Test I/O AT by copying 1024 byte from 2k to 1k */ +static int __init i7300_idle_ioat_selftest(u8 *ctl, + struct ioat_dma_descriptor *desc, unsigned long desc_phys) +{ + u64 chan_sts; + + memset(desc, 0, 2048); + memset((u8 *) desc + 2048, 0xab, 1024); + + desc[0].size = 1024; + desc[0].ctl = 0; + desc[0].src_addr = desc_phys + 2048; + desc[0].dst_addr = desc_phys + 1024; + desc[0].next = 0; + + writeb(IOAT_CHANCMD_RESET, ioat_chanbase + IOAT1_CHANCMD_OFFSET); + writeb(IOAT_CHANCMD_START, ioat_chanbase + IOAT1_CHANCMD_OFFSET); + + udelay(1000); + + chan_sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) & + IOAT_CHANSTS_DMA_TRANSFER_STATUS; + + if (chan_sts != IOAT_CHANSTS_DMA_TRANSFER_STATUS_DONE) { + /* Not complete, reset the channel */ + writeb(IOAT_CHANCMD_RESET, + ioat_chanbase + IOAT1_CHANCMD_OFFSET); + return -1; + } + + if (*(u32 *) ((u8 *) desc + 3068) != 0xabababab || + *(u32 *) ((u8 *) desc + 2044) != 0xabababab) { + dprintk("Data values src 0x%x, dest 0x%x, memset 0x%x\n", + *(u32 *) ((u8 *) desc + 2048), + *(u32 *) ((u8 *) desc + 1024), + *(u32 *) ((u8 *) desc + 3072)); + return -1; + } + return 0; +} + +static struct device dummy_dma_dev = { + .bus_id = "fallback device", + .coherent_dma_mask = DMA_64BIT_MASK, + .dma_mask = &dummy_dma_dev.coherent_dma_mask, +}; + +/* Setup and initialize I/O AT */ +/* This driver needs I/O AT as the throttling takes effect only when there is + * some memory activity. We use I/O AT to set up a dummy copy, while all CPUs + * go idle and memory is throttled. + */ +static int __init i7300_idle_ioat_init(void) +{ + u8 ver, chan_count, ioat_chan; + u16 chan_ctl; + + ioat_iomap = (u8 *) ioremap_nocache(pci_resource_start(ioat_dev, 0), + pci_resource_len(ioat_dev, 0)); + + if (!ioat_iomap) { + printk(KERN_ERR I7300_PRINT "failed to map I/O AT registers\n"); + goto err_ret; + } + + ver = readb(ioat_iomap + IOAT_VER_OFFSET); + if (ver != IOAT_VER_1_2) { + printk(KERN_ERR I7300_PRINT "unknown I/O AT version (%u.%u)\n", + ver >> 4, ver & 0xf); + goto err_unmap; + } + + chan_count = readb(ioat_iomap + IOAT_CHANCNT_OFFSET); + if (!chan_count) { + printk(KERN_ERR I7300_PRINT "unexpected # of I/O AT channels " + "(%u)\n", + chan_count); + goto err_unmap; + } + + ioat_chan = chan_count - 1; + ioat_chanbase = IOAT_CHANBASE(ioat_iomap, ioat_chan); + + chan_ctl = readw(ioat_chanbase + IOAT_CHANCTRL_OFFSET); + if (chan_ctl & IOAT_CHANCTRL_CHANNEL_IN_USE) { + printk(KERN_ERR I7300_PRINT "channel %d in use\n", ioat_chan); + goto err_unmap; + } + + writew(IOAT_CHANCTRL_CHANNEL_IN_USE, + ioat_chanbase + IOAT_CHANCTRL_OFFSET); + + ioat_desc = (struct ioat_dma_descriptor *)dma_alloc_coherent( + &dummy_dma_dev, 4096, + (dma_addr_t *)&ioat_desc_phys, GFP_KERNEL); + if (!ioat_desc) { + printk(KERN_ERR I7300_PRINT "failed to allocate I/O AT desc\n"); + goto err_mark_unused; + } + + writel(ioat_desc_phys & 0xffffffffUL, + ioat_chanbase + IOAT1_CHAINADDR_OFFSET_LOW); + writel(ioat_desc_phys >> 32, + ioat_chanbase + IOAT1_CHAINADDR_OFFSET_HIGH); + + if (i7300_idle_ioat_selftest(ioat_iomap, ioat_desc, ioat_desc_phys)) { + printk(KERN_ERR I7300_PRINT "I/O AT self-test failed\n"); + goto err_free; + } + + /* Setup circular I/O AT descriptor chain */ + ioat_desc[0].ctl = IOAT_DESC_SADDR_SNP_CTL | IOAT_DESC_DADDR_SNP_CTL; + ioat_desc[0].src_addr = ioat_desc_phys + 2048; + ioat_desc[0].dst_addr = ioat_desc_phys + 3072; + ioat_desc[0].size = 128; + ioat_desc[0].next = ioat_desc_phys + sizeof(struct ioat_dma_descriptor); + + ioat_desc[1].ctl = ioat_desc[0].ctl; + ioat_desc[1].src_addr = ioat_desc[0].src_addr; + ioat_desc[1].dst_addr = ioat_desc[0].dst_addr; + ioat_desc[1].size = ioat_desc[0].size; + ioat_desc[1].next = ioat_desc_phys; + + return 0; + +err_free: + dma_free_coherent(&dummy_dma_dev, 4096, (void *)ioat_desc, 0); +err_mark_unused: + writew(0, ioat_chanbase + IOAT_CHANCTRL_OFFSET); +err_unmap: + iounmap(ioat_iomap); +err_ret: + return -ENODEV; +} + +/* Cleanup I/O AT */ +static void __exit i7300_idle_ioat_exit(void) +{ + int i; + u64 chan_sts; + + i7300_idle_ioat_stop(); + + /* Wait for a while for the channel to halt before releasing */ + for (i = 0; i < 10; i++) { + writeb(IOAT_CHANCMD_RESET, + ioat_chanbase + IOAT1_CHANCMD_OFFSET); + + chan_sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) & + IOAT_CHANSTS_DMA_TRANSFER_STATUS; + + if (chan_sts != IOAT_CHANSTS_DMA_TRANSFER_STATUS_ACTIVE) { + writew(0, ioat_chanbase + IOAT_CHANCTRL_OFFSET); + break; + } + udelay(1000); + } + + chan_sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) & + IOAT_CHANSTS_DMA_TRANSFER_STATUS; + + /* + * We tried to reset multiple times. If IO A/T channel is still active + * flag an error and return without cleanup. Memory leak is better + * than random corruption in that extreme error situation. + */ + if (chan_sts == IOAT_CHANSTS_DMA_TRANSFER_STATUS_ACTIVE) { + printk(KERN_ERR I7300_PRINT "Unable to stop IO A/T channels." + " Not freeing resources\n"); + return; + } + + dma_free_coherent(&dummy_dma_dev, 4096, (void *)ioat_desc, 0); + iounmap(ioat_iomap); +} + +/* End: I/O AT Helper routines */ + +#define DIMM_THRTLOW 0x64 +#define DIMM_THRTCTL 0x67 +#define DIMM_THRTCTL_THRMHUNT (1UL << 0) +#define DIMM_MC 0x40 +#define DIMM_GTW_MODE (1UL << 17) +#define DIMM_GBLACT 0x60 + +/* + * Keep track of an exponential-decaying average of recent idle durations. + * The latest duration gets DURATION_WEIGHT_PCT percentage weight + * in this average, with the old average getting the remaining weight. + * + * High weights emphasize recent history, low weights include long history. + */ +#define DURATION_WEIGHT_PCT 55 + +/* + * When the decaying average of recent durations or the predicted duration + * of the next timer interrupt is shorter than duration_threshold, the + * driver will decline to throttle. + */ +#define DURATION_THRESHOLD_US 100 + + +/* Store DIMM thermal throttle configuration */ +static int i7300_idle_thrt_save(void) +{ + u32 new_mc_val; + u8 gblactlm; + + pci_read_config_byte(fbd_dev, DIMM_THRTCTL, &i7300_idle_thrtctl_saved); + pci_read_config_byte(fbd_dev, DIMM_THRTLOW, &i7300_idle_thrtlow_saved); + pci_read_config_dword(fbd_dev, DIMM_MC, &i7300_idle_mc_saved); + /* + * Make sure we have Global Throttling Window Mode set to have a + * "short" window. This (mostly) works around an issue where + * throttling persists until the end of the global throttling window + * size. On the tested system, this was resulting in a maximum of + * 64 ms to exit throttling (average 32 ms). The actual numbers + * depends on system frequencies. Setting the short window reduces + * this by a factor of 4096. + * + * We will only do this only if the system is set for + * unlimited-activations while in open-loop throttling (i.e., when + * Global Activation Throttle Limit is zero). + */ + pci_read_config_byte(fbd_dev, DIMM_GBLACT, &gblactlm); + dprintk("thrtctl_saved = 0x%02x, thrtlow_saved = 0x%02x\n", + i7300_idle_thrtctl_saved, + i7300_idle_thrtlow_saved); + dprintk("mc_saved = 0x%08x, gblactlm = 0x%02x\n", + i7300_idle_mc_saved, + gblactlm); + if (gblactlm == 0) { + new_mc_val = i7300_idle_mc_saved | DIMM_GTW_MODE; + pci_write_config_dword(fbd_dev, DIMM_MC, new_mc_val); + return 0; + } else { + dprintk("could not set GTW_MODE = 1 (OLTT enabled)\n"); + return -ENODEV; + } +} + +/* Restore DIMM thermal throttle configuration */ +static void i7300_idle_thrt_restore(void) +{ + pci_write_config_dword(fbd_dev, DIMM_MC, i7300_idle_mc_saved); + pci_write_config_byte(fbd_dev, DIMM_THRTLOW, i7300_idle_thrtlow_saved); + pci_write_config_byte(fbd_dev, DIMM_THRTCTL, i7300_idle_thrtctl_saved); +} + +/* Enable DIMM thermal throttling */ +static void i7300_idle_start(void) +{ + u8 new_ctl; + u8 limit; + + new_ctl = i7300_idle_thrtctl_saved & ~DIMM_THRTCTL_THRMHUNT; + pci_write_config_byte(fbd_dev, DIMM_THRTCTL, new_ctl); + + limit = i7300_idle_thrtlowlm; + if (unlikely(limit > MAX_THRTLWLIMIT)) + limit = MAX_THRTLWLIMIT; + + pci_write_config_byte(fbd_dev, DIMM_THRTLOW, limit); + + new_ctl = i7300_idle_thrtctl_saved | DIMM_THRTCTL_THRMHUNT; + pci_write_config_byte(fbd_dev, DIMM_THRTCTL, new_ctl); +} + +/* Disable DIMM thermal throttling */ +static void i7300_idle_stop(void) +{ + u8 new_ctl; + u8 got_ctl; + + new_ctl = i7300_idle_thrtctl_saved & ~DIMM_THRTCTL_THRMHUNT; + pci_write_config_byte(fbd_dev, DIMM_THRTCTL, new_ctl); + + pci_write_config_byte(fbd_dev, DIMM_THRTLOW, i7300_idle_thrtlow_saved); + pci_write_config_byte(fbd_dev, DIMM_THRTCTL, i7300_idle_thrtctl_saved); + pci_read_config_byte(fbd_dev, DIMM_THRTCTL, &got_ctl); + WARN_ON_ONCE(got_ctl != i7300_idle_thrtctl_saved); +} + + +/* + * i7300_avg_duration_check() + * return 0 if the decaying average of recent idle durations is + * more than DURATION_THRESHOLD_US + */ +static int i7300_avg_duration_check(void) +{ + if (avg_idle_us >= DURATION_THRESHOLD_US) + return 0; + +#ifdef DEBUG + past_skip++; +#endif + return 1; +} + +/* Idle notifier to look at idle CPUs */ +static int i7300_idle_notifier(struct notifier_block *nb, unsigned long val, + void *data) +{ + unsigned long flags; + ktime_t now_ktime; + static ktime_t idle_begin_time; + static int time_init = 1; + + if (!i7300_idle_thrtlowlm) + return 0; + + if (unlikely(time_init)) { + time_init = 0; + idle_begin_time = ktime_get(); + } + + spin_lock_irqsave(&i7300_idle_lock, flags); + if (val == IDLE_START) { + + cpu_set(smp_processor_id(), idle_cpumask); + + if (cpus_weight(idle_cpumask) != num_online_cpus()) + goto end; + + now_ktime = ktime_get(); + idle_begin_time = now_ktime; + + if (i7300_avg_duration_check()) + goto end; + + i7300_idle_active = 1; + total_starts++; + start_ktime = now_ktime; + + i7300_idle_start(); + i7300_idle_ioat_start(); + + } else if (val == IDLE_END) { + cpu_clear(smp_processor_id(), idle_cpumask); + if (cpus_weight(idle_cpumask) == (num_online_cpus() - 1)) { + /* First CPU coming out of idle */ + u64 idle_duration_us; + + now_ktime = ktime_get(); + + idle_duration_us = ktime_to_us(ktime_sub + (now_ktime, idle_begin_time)); + + avg_idle_us = + ((100 - DURATION_WEIGHT_PCT) * avg_idle_us + + DURATION_WEIGHT_PCT * idle_duration_us) / 100; + + if (i7300_idle_active) { + ktime_t idle_ktime; + + idle_ktime = ktime_sub(now_ktime, start_ktime); + total_us += ktime_to_us(idle_ktime); + + i7300_idle_ioat_stop(); + i7300_idle_stop(); + i7300_idle_active = 0; + } + } + } +end: + spin_unlock_irqrestore(&i7300_idle_lock, flags); + return 0; +} + +static struct notifier_block i7300_idle_nb = { + .notifier_call = i7300_idle_notifier, +}; + +/* + * I/O AT controls (PCI bus 0 device 8 function 0) + * DIMM controls (PCI bus 0 device 16 function 1) + */ +#define IOAT_BUS 0 +#define IOAT_DEVFN PCI_DEVFN(8, 0) +#define MEMCTL_BUS 0 +#define MEMCTL_DEVFN PCI_DEVFN(16, 1) + +struct fbd_ioat { + unsigned int vendor; + unsigned int ioat_dev; +}; + +/* + * The i5000 chip-set has the same hooks as the i7300 + * but support is disabled by default because this driver + * has not been validated on that platform. + */ +#define SUPPORT_I5000 0 + +static const struct fbd_ioat fbd_ioat_list[] = { + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_CNB}, +#if SUPPORT_I5000 + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT}, +#endif + {0, 0} +}; + +/* table of devices that work with this driver */ +static const struct pci_device_id pci_tbl[] = { + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_FBD_CNB) }, +#if SUPPORT_I5000 + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5000_ERR) }, +#endif + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(pci, pci_tbl); + +/* Check for known platforms with I/O-AT */ +static int __init i7300_idle_platform_probe(void) +{ + int i; + + fbd_dev = pci_get_bus_and_slot(MEMCTL_BUS, MEMCTL_DEVFN); + if (!fbd_dev) + return -ENODEV; + + for (i = 0; pci_tbl[i].vendor != 0; i++) { + if (fbd_dev->vendor == pci_tbl[i].vendor && + fbd_dev->device == pci_tbl[i].device) { + break; + } + } + if (pci_tbl[i].vendor == 0) + return -ENODEV; + + ioat_dev = pci_get_bus_and_slot(IOAT_BUS, IOAT_DEVFN); + if (!ioat_dev) + return -ENODEV; + + for (i = 0; fbd_ioat_list[i].vendor != 0; i++) { + if (ioat_dev->vendor == fbd_ioat_list[i].vendor && + ioat_dev->device == fbd_ioat_list[i].ioat_dev) { + return 0; + } + } + return -ENODEV; +} + +int stats_open_generic(struct inode *inode, struct file *fp) +{ + fp->private_data = inode->i_private; + return 0; +} + +static ssize_t stats_read_ul(struct file *fp, char __user *ubuf, size_t count, + loff_t *off) +{ + unsigned long *p = fp->private_data; + char buf[32]; + int len; + + len = snprintf(buf, 32, "%lu\n", *p); + return simple_read_from_buffer(ubuf, count, off, buf, len); +} + +static const struct file_operations idle_fops = { + .open = stats_open_generic, + .read = stats_read_ul, +}; + +struct debugfs_file_info { + void *ptr; + char name[32]; + struct dentry *file; +} debugfs_file_list[] = { + {&total_starts, "total_starts", NULL}, + {&total_us, "total_us", NULL}, +#ifdef DEBUG + {&past_skip, "past_skip", NULL}, +#endif + {NULL, "", NULL} + }; + +static int __init i7300_idle_init(void) +{ + spin_lock_init(&i7300_idle_lock); + cpus_clear(idle_cpumask); + total_us = 0; + + if (i7300_idle_platform_probe()) + return -ENODEV; + + if (i7300_idle_thrt_save()) + return -ENODEV; + + if (i7300_idle_ioat_init()) + return -ENODEV; + + debugfs_dir = debugfs_create_dir("i7300_idle", NULL); + if (debugfs_dir) { + int i = 0; + + while (debugfs_file_list[i].ptr != NULL) { + debugfs_file_list[i].file = debugfs_create_file( + debugfs_file_list[i].name, + S_IRUSR, + debugfs_dir, + debugfs_file_list[i].ptr, + &idle_fops); + i++; + } + } + + idle_notifier_register(&i7300_idle_nb); + + printk(KERN_INFO "i7300_idle: loaded v%s\n", I7300_IDLE_DRIVER_VERSION); + return 0; +} + +static void __exit i7300_idle_exit(void) +{ + idle_notifier_unregister(&i7300_idle_nb); + + if (debugfs_dir) { + int i = 0; + + while (debugfs_file_list[i].file != NULL) { + debugfs_remove(debugfs_file_list[i].file); + i++; + } + + debugfs_remove(debugfs_dir); + } + i7300_idle_thrt_restore(); + i7300_idle_ioat_exit(); +} + +module_init(i7300_idle_init); +module_exit(i7300_idle_exit); + +MODULE_AUTHOR("Andy Henroid <andrew.d.henroid@intel.com>"); +MODULE_DESCRIPTION("Intel Chipset DIMM Idle Power Saving Driver v" + I7300_IDLE_DRIVER_VERSION); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index efd3aa08b88..9494400e8fd 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -145,6 +145,7 @@ config ACER_WMI depends on NEW_LEDS depends on BACKLIGHT_CLASS_DEVICE depends on SERIO_I8042 + depends on RFKILL select ACPI_WMI ---help--- This is a driver for newer Acer (and Wistron) laptops. It adds @@ -245,6 +246,17 @@ config MSI_LAPTOP If you have an MSI S270 laptop, say Y or M here. +config PANASONIC_LAPTOP + tristate "Panasonic Laptop Extras" + depends on X86 && INPUT && ACPI + depends on BACKLIGHT_CLASS_DEVICE + ---help--- + This driver adds support for access to backlight control and hotkeys + on Panasonic Let's Note laptops. + + If you have a Panasonic Let's note laptop (such as the R1(N variant), + R2, R3, R5, T2, W2 and Y2 series), say Y. + config COMPAL_LAPTOP tristate "Compal Laptop Extras" depends on X86 diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index c6c13f60b45..909e2468cdc 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_SGI_IOC4) += ioc4.o obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o +obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o diff --git a/drivers/misc/acer-wmi.c b/drivers/misc/acer-wmi.c index d8b0d326e45..0532a2de2ce 100644 --- a/drivers/misc/acer-wmi.c +++ b/drivers/misc/acer-wmi.c @@ -33,6 +33,8 @@ #include <linux/platform_device.h> #include <linux/acpi.h> #include <linux/i8042.h> +#include <linux/rfkill.h> +#include <linux/workqueue.h> #include <linux/debugfs.h> #include <acpi/acpi_drivers.h> @@ -123,21 +125,15 @@ enum interface_flags { static int max_brightness = 0xF; -static int wireless = -1; -static int bluetooth = -1; static int mailled = -1; static int brightness = -1; static int threeg = -1; static int force_series; module_param(mailled, int, 0444); -module_param(wireless, int, 0444); -module_param(bluetooth, int, 0444); module_param(brightness, int, 0444); module_param(threeg, int, 0444); module_param(force_series, int, 0444); -MODULE_PARM_DESC(wireless, "Set initial state of Wireless hardware"); -MODULE_PARM_DESC(bluetooth, "Set initial state of Bluetooth hardware"); MODULE_PARM_DESC(mailled, "Set initial state of Mail LED"); MODULE_PARM_DESC(brightness, "Set initial LCD backlight brightness"); MODULE_PARM_DESC(threeg, "Set initial state of 3G hardware"); @@ -145,8 +141,6 @@ MODULE_PARM_DESC(force_series, "Force a different laptop series"); struct acer_data { int mailled; - int wireless; - int bluetooth; int threeg; int brightness; }; @@ -157,6 +151,9 @@ struct acer_debug { u32 wmid_devices; }; +static struct rfkill *wireless_rfkill; +static struct rfkill *bluetooth_rfkill; + /* Each low-level interface must define at least some of the following */ struct wmi_interface { /* The WMI device type */ @@ -476,7 +473,7 @@ struct wmi_interface *iface) } break; default: - return AE_BAD_ADDRESS; + return AE_ERROR; } return AE_OK; } @@ -514,7 +511,7 @@ static acpi_status AMW0_set_u32(u32 value, u32 cap, struct wmi_interface *iface) break; } default: - return AE_BAD_ADDRESS; + return AE_ERROR; } /* Actually do the set */ @@ -689,7 +686,7 @@ struct wmi_interface *iface) return 0; } default: - return AE_BAD_ADDRESS; + return AE_ERROR; } status = WMI_execute_u32(method_id, 0, &result); @@ -735,7 +732,7 @@ static acpi_status WMID_set_u32(u32 value, u32 cap, struct wmi_interface *iface) } break; default: - return AE_BAD_ADDRESS; + return AE_ERROR; } return WMI_execute_u32(method_id, (u32)value, NULL); } @@ -785,7 +782,7 @@ static struct wmi_interface wmid_interface = { static acpi_status get_u32(u32 *value, u32 cap) { - acpi_status status = AE_BAD_ADDRESS; + acpi_status status = AE_ERROR; switch (interface->type) { case ACER_AMW0: @@ -846,8 +843,6 @@ static void __init acer_commandline_init(void) * capability isn't available on the given interface */ set_u32(mailled, ACER_CAP_MAILLED); - set_u32(wireless, ACER_CAP_WIRELESS); - set_u32(bluetooth, ACER_CAP_BLUETOOTH); set_u32(threeg, ACER_CAP_THREEG); set_u32(brightness, ACER_CAP_BRIGHTNESS); } @@ -933,40 +928,135 @@ static void acer_backlight_exit(void) } /* - * Read/ write bool sysfs macro + * Rfkill devices */ -#define show_set_bool(value, cap) \ -static ssize_t \ -show_bool_##value(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - u32 result; \ - acpi_status status = get_u32(&result, cap); \ - if (ACPI_SUCCESS(status)) \ - return sprintf(buf, "%u\n", result); \ - return sprintf(buf, "Read error\n"); \ -} \ -\ -static ssize_t \ -set_bool_##value(struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - u32 tmp = simple_strtoul(buf, NULL, 10); \ - acpi_status status = set_u32(tmp, cap); \ - if (ACPI_FAILURE(status)) \ - return -EINVAL; \ - return count; \ -} \ -static DEVICE_ATTR(value, S_IWUGO | S_IRUGO | S_IWUSR, \ - show_bool_##value, set_bool_##value); - -show_set_bool(wireless, ACER_CAP_WIRELESS); -show_set_bool(bluetooth, ACER_CAP_BLUETOOTH); -show_set_bool(threeg, ACER_CAP_THREEG); +static void acer_rfkill_update(struct work_struct *ignored); +static DECLARE_DELAYED_WORK(acer_rfkill_work, acer_rfkill_update); +static void acer_rfkill_update(struct work_struct *ignored) +{ + u32 state; + acpi_status status; + + status = get_u32(&state, ACER_CAP_WIRELESS); + if (ACPI_SUCCESS(status)) + rfkill_force_state(wireless_rfkill, state ? + RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED); + + if (has_cap(ACER_CAP_BLUETOOTH)) { + status = get_u32(&state, ACER_CAP_BLUETOOTH); + if (ACPI_SUCCESS(status)) + rfkill_force_state(bluetooth_rfkill, state ? + RFKILL_STATE_UNBLOCKED : + RFKILL_STATE_SOFT_BLOCKED); + } + + schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ)); +} + +static int acer_rfkill_set(void *data, enum rfkill_state state) +{ + acpi_status status; + u32 *cap = data; + status = set_u32((u32) (state == RFKILL_STATE_UNBLOCKED), *cap); + if (ACPI_FAILURE(status)) + return -ENODEV; + return 0; +} + +static struct rfkill * acer_rfkill_register(struct device *dev, +enum rfkill_type type, char *name, u32 cap) +{ + int err; + u32 state; + u32 *data; + struct rfkill *rfkill_dev; + + rfkill_dev = rfkill_allocate(dev, type); + if (!rfkill_dev) + return ERR_PTR(-ENOMEM); + rfkill_dev->name = name; + get_u32(&state, cap); + rfkill_dev->state = state ? RFKILL_STATE_UNBLOCKED : + RFKILL_STATE_SOFT_BLOCKED; + data = kzalloc(sizeof(u32), GFP_KERNEL); + if (!data) { + rfkill_free(rfkill_dev); + return ERR_PTR(-ENOMEM); + } + *data = cap; + rfkill_dev->data = data; + rfkill_dev->toggle_radio = acer_rfkill_set; + rfkill_dev->user_claim_unsupported = 1; + + err = rfkill_register(rfkill_dev); + if (err) { + kfree(rfkill_dev->data); + rfkill_free(rfkill_dev); + return ERR_PTR(err); + } + return rfkill_dev; +} + +static int acer_rfkill_init(struct device *dev) +{ + wireless_rfkill = acer_rfkill_register(dev, RFKILL_TYPE_WLAN, + "acer-wireless", ACER_CAP_WIRELESS); + if (IS_ERR(wireless_rfkill)) + return PTR_ERR(wireless_rfkill); + + if (has_cap(ACER_CAP_BLUETOOTH)) { + bluetooth_rfkill = acer_rfkill_register(dev, + RFKILL_TYPE_BLUETOOTH, "acer-bluetooth", + ACER_CAP_BLUETOOTH); + if (IS_ERR(bluetooth_rfkill)) { + kfree(wireless_rfkill->data); + rfkill_unregister(wireless_rfkill); + return PTR_ERR(bluetooth_rfkill); + } + } + + schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ)); + + return 0; +} + +static void acer_rfkill_exit(void) +{ + cancel_delayed_work_sync(&acer_rfkill_work); + kfree(wireless_rfkill->data); + rfkill_unregister(wireless_rfkill); + if (has_cap(ACER_CAP_BLUETOOTH)) { + kfree(wireless_rfkill->data); + rfkill_unregister(bluetooth_rfkill); + } + return; +} /* - * Read interface sysfs macro + * sysfs interface */ +static ssize_t show_bool_threeg(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u32 result; \ + acpi_status status = get_u32(&result, ACER_CAP_THREEG); + if (ACPI_SUCCESS(status)) + return sprintf(buf, "%u\n", result); + return sprintf(buf, "Read error\n"); +} + +static ssize_t set_bool_threeg(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + u32 tmp = simple_strtoul(buf, NULL, 10); + acpi_status status = set_u32(tmp, ACER_CAP_THREEG); + if (ACPI_FAILURE(status)) + return -EINVAL; + return count; +} +static DEVICE_ATTR(threeg, S_IWUGO | S_IRUGO | S_IWUSR, show_bool_threeg, + set_bool_threeg); + static ssize_t show_interface(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1026,7 +1116,9 @@ static int __devinit acer_platform_probe(struct platform_device *device) goto error_brightness; } - return 0; + err = acer_rfkill_init(&device->dev); + + return err; error_brightness: acer_led_exit(); @@ -1040,6 +1132,8 @@ static int acer_platform_remove(struct platform_device *device) acer_led_exit(); if (has_cap(ACER_CAP_BRIGHTNESS)) acer_backlight_exit(); + + acer_rfkill_exit(); return 0; } @@ -1052,16 +1146,6 @@ pm_message_t state) if (!data) return -ENOMEM; - if (has_cap(ACER_CAP_WIRELESS)) { - get_u32(&value, ACER_CAP_WIRELESS); - data->wireless = value; - } - - if (has_cap(ACER_CAP_BLUETOOTH)) { - get_u32(&value, ACER_CAP_BLUETOOTH); - data->bluetooth = value; - } - if (has_cap(ACER_CAP_MAILLED)) { get_u32(&value, ACER_CAP_MAILLED); data->mailled = value; @@ -1082,15 +1166,6 @@ static int acer_platform_resume(struct platform_device *device) if (!data) return -ENOMEM; - if (has_cap(ACER_CAP_WIRELESS)) - set_u32(data->wireless, ACER_CAP_WIRELESS); - - if (has_cap(ACER_CAP_BLUETOOTH)) - set_u32(data->bluetooth, ACER_CAP_BLUETOOTH); - - if (has_cap(ACER_CAP_THREEG)) - set_u32(data->threeg, ACER_CAP_THREEG); - if (has_cap(ACER_CAP_MAILLED)) set_u32(data->mailled, ACER_CAP_MAILLED); @@ -1115,12 +1190,6 @@ static struct platform_device *acer_platform_device; static int remove_sysfs(struct platform_device *device) { - if (has_cap(ACER_CAP_WIRELESS)) - device_remove_file(&device->dev, &dev_attr_wireless); - - if (has_cap(ACER_CAP_BLUETOOTH)) - device_remove_file(&device->dev, &dev_attr_bluetooth); - if (has_cap(ACER_CAP_THREEG)) device_remove_file(&device->dev, &dev_attr_threeg); @@ -1133,20 +1202,6 @@ static int create_sysfs(void) { int retval = -ENOMEM; - if (has_cap(ACER_CAP_WIRELESS)) { - retval = device_create_file(&acer_platform_device->dev, - &dev_attr_wireless); - if (retval) - goto error_sysfs; - } - - if (has_cap(ACER_CAP_BLUETOOTH)) { - retval = device_create_file(&acer_platform_device->dev, - &dev_attr_bluetooth); - if (retval) - goto error_sysfs; - } - if (has_cap(ACER_CAP_THREEG)) { retval = device_create_file(&acer_platform_device->dev, &dev_attr_threeg); diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c index 7c6dfd03de9..a9d5228724a 100644 --- a/drivers/misc/asus-laptop.c +++ b/drivers/misc/asus-laptop.c @@ -139,6 +139,7 @@ ASUS_HANDLE(lcd_switch, "\\_SB.PCI0.SBRG.EC0._Q10", /* All new models */ "\\_SB.PCI0.PX40.ECD0._Q10", /* L3C */ "\\_SB.PCI0.PX40.EC0.Q10", /* M1A */ "\\_SB.PCI0.LPCB.EC0._Q10", /* P30 */ + "\\_SB.PCI0.LPCB.EC0._Q0E", /* P30/P35 */ "\\_SB.PCI0.PX40.Q10", /* S1x */ "\\Q10"); /* A2x, L2D, L3D, M2E */ @@ -280,7 +281,7 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val, static int read_wireless_status(int mask) { - ulong status; + unsigned long long status; acpi_status rv = AE_OK; if (!wireless_status_handle) @@ -297,7 +298,7 @@ static int read_wireless_status(int mask) static int read_gps_status(void) { - ulong status; + unsigned long long status; acpi_status rv = AE_OK; rv = acpi_evaluate_integer(gps_status_handle, NULL, NULL, &status); @@ -350,7 +351,7 @@ static void write_status(acpi_handle handle, int out, int mask) static void object##_led_set(struct led_classdev *led_cdev, \ enum led_brightness value) \ { \ - object##_led_wk = value; \ + object##_led_wk = (value > 0) ? 1 : 0; \ queue_work(led_workqueue, &object##_led_work); \ } \ static void object##_led_update(struct work_struct *ignored) \ @@ -404,7 +405,7 @@ static void lcd_blank(int blank) static int read_brightness(struct backlight_device *bd) { - ulong value; + unsigned long long value; acpi_status rv = AE_OK; rv = acpi_evaluate_integer(brightness_get_handle, NULL, NULL, &value); @@ -455,7 +456,7 @@ static ssize_t show_infos(struct device *dev, struct device_attribute *attr, char *page) { int len = 0; - ulong temp; + unsigned long long temp; char buf[16]; //enough for all info acpi_status rv = AE_OK; @@ -603,7 +604,7 @@ static void set_display(int value) static int read_display(void) { - ulong value = 0; + unsigned long long value = 0; acpi_status rv = AE_OK; /* In most of the case, we know how to set the display, but sometime @@ -849,7 +850,7 @@ static int asus_hotk_get_info(void) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *model = NULL; - ulong bsts_result, hwrs_result; + unsigned long long bsts_result, hwrs_result; char *string = NULL; acpi_status status; @@ -996,7 +997,7 @@ static int asus_hotk_add(struct acpi_device *device) hotk->handle = device->handle; strcpy(acpi_device_name(device), ASUS_HOTK_DEVICE_NAME); strcpy(acpi_device_class(device), ASUS_HOTK_CLASS); - acpi_driver_data(device) = hotk; + device->driver_data = hotk; hotk->device = device; result = asus_hotk_check(); diff --git a/drivers/misc/eeepc-laptop.c b/drivers/misc/eeepc-laptop.c index 1ee8501e90f..9ef98b2d503 100644 --- a/drivers/misc/eeepc-laptop.c +++ b/drivers/misc/eeepc-laptop.c @@ -28,6 +28,8 @@ #include <acpi/acpi_drivers.h> #include <acpi/acpi_bus.h> #include <linux/uaccess.h> +#include <linux/input.h> +#include <linux/rfkill.h> #define EEEPC_LAPTOP_VERSION "0.1" @@ -125,6 +127,10 @@ struct eeepc_hotk { by this BIOS */ uint init_flag; /* Init flags */ u16 event_count[128]; /* count for each event */ + struct input_dev *inputdev; + u16 *keycode_map; + struct rfkill *eeepc_wlan_rfkill; + struct rfkill *eeepc_bluetooth_rfkill; }; /* The actual device the driver binds to */ @@ -140,6 +146,27 @@ static struct platform_driver platform_driver = { static struct platform_device *platform_device; +struct key_entry { + char type; + u8 code; + u16 keycode; +}; + +enum { KE_KEY, KE_END }; + +static struct key_entry eeepc_keymap[] = { + /* Sleep already handled via generic ACPI code */ + {KE_KEY, 0x10, KEY_WLAN }, + {KE_KEY, 0x12, KEY_PROG1 }, + {KE_KEY, 0x13, KEY_MUTE }, + {KE_KEY, 0x14, KEY_VOLUMEDOWN }, + {KE_KEY, 0x15, KEY_VOLUMEUP }, + {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE }, + {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE }, + {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE }, + {KE_END, 0}, +}; + /* * The hotkey driver declaration */ @@ -204,7 +231,7 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val, static int read_acpi_int(acpi_handle handle, const char *method, int *val) { acpi_status status; - ulong result; + unsigned long long result; status = acpi_evaluate_integer(handle, (char *)method, NULL, &result); if (ACPI_FAILURE(status)) { @@ -261,6 +288,44 @@ static int update_bl_status(struct backlight_device *bd) } /* + * Rfkill helpers + */ + +static int eeepc_wlan_rfkill_set(void *data, enum rfkill_state state) +{ + if (state == RFKILL_STATE_SOFT_BLOCKED) + return set_acpi(CM_ASL_WLAN, 0); + else + return set_acpi(CM_ASL_WLAN, 1); +} + +static int eeepc_wlan_rfkill_state(void *data, enum rfkill_state *state) +{ + if (get_acpi(CM_ASL_WLAN) == 1) + *state = RFKILL_STATE_UNBLOCKED; + else + *state = RFKILL_STATE_SOFT_BLOCKED; + return 0; +} + +static int eeepc_bluetooth_rfkill_set(void *data, enum rfkill_state state) +{ + if (state == RFKILL_STATE_SOFT_BLOCKED) + return set_acpi(CM_ASL_BLUETOOTH, 0); + else + return set_acpi(CM_ASL_BLUETOOTH, 1); +} + +static int eeepc_bluetooth_rfkill_state(void *data, enum rfkill_state *state) +{ + if (get_acpi(CM_ASL_BLUETOOTH) == 1) + *state = RFKILL_STATE_UNBLOCKED; + else + *state = RFKILL_STATE_SOFT_BLOCKED; + return 0; +} + +/* * Sys helpers */ static int parse_arg(const char *buf, unsigned long count, int *val) @@ -311,13 +376,11 @@ static ssize_t show_sys_acpi(int cm, char *buf) EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA); EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER); EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH); -EEEPC_CREATE_DEVICE_ATTR(wlan, CM_ASL_WLAN); static struct attribute *platform_attributes[] = { &dev_attr_camera.attr, &dev_attr_cardr.attr, &dev_attr_disp.attr, - &dev_attr_wlan.attr, NULL }; @@ -328,8 +391,64 @@ static struct attribute_group platform_attribute_group = { /* * Hotkey functions */ +static struct key_entry *eepc_get_entry_by_scancode(int code) +{ + struct key_entry *key; + + for (key = eeepc_keymap; key->type != KE_END; key++) + if (code == key->code) + return key; + + return NULL; +} + +static struct key_entry *eepc_get_entry_by_keycode(int code) +{ + struct key_entry *key; + + for (key = eeepc_keymap; key->type != KE_END; key++) + if (code == key->keycode && key->type == KE_KEY) + return key; + + return NULL; +} + +static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode) +{ + struct key_entry *key = eepc_get_entry_by_scancode(scancode); + + if (key && key->type == KE_KEY) { + *keycode = key->keycode; + return 0; + } + + return -EINVAL; +} + +static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode) +{ + struct key_entry *key; + int old_keycode; + + if (keycode < 0 || keycode > KEY_MAX) + return -EINVAL; + + key = eepc_get_entry_by_scancode(scancode); + if (key && key->type == KE_KEY) { + old_keycode = key->keycode; + key->keycode = keycode; + set_bit(keycode, dev->keybit); + if (!eepc_get_entry_by_keycode(old_keycode)) + clear_bit(old_keycode, dev->keybit); + return 0; + } + + return -EINVAL; +} + static int eeepc_hotk_check(void) { + const struct key_entry *key; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; int result; @@ -356,6 +475,31 @@ static int eeepc_hotk_check(void) "Get control methods supported: 0x%x\n", ehotk->cm_supported); } + ehotk->inputdev = input_allocate_device(); + if (!ehotk->inputdev) { + printk(EEEPC_INFO "Unable to allocate input device\n"); + return 0; + } + ehotk->inputdev->name = "Asus EeePC extra buttons"; + ehotk->inputdev->phys = EEEPC_HOTK_FILE "/input0"; + ehotk->inputdev->id.bustype = BUS_HOST; + ehotk->inputdev->getkeycode = eeepc_getkeycode; + ehotk->inputdev->setkeycode = eeepc_setkeycode; + + for (key = eeepc_keymap; key->type != KE_END; key++) { + switch (key->type) { + case KE_KEY: + set_bit(EV_KEY, ehotk->inputdev->evbit); + set_bit(key->keycode, ehotk->inputdev->keybit); + break; + } + } + result = input_register_device(ehotk->inputdev); + if (result) { + printk(EEEPC_INFO "Unable to register input device\n"); + input_free_device(ehotk->inputdev); + return 0; + } } else { printk(EEEPC_ERR "Hotkey device not present, aborting\n"); return -EINVAL; @@ -363,21 +507,6 @@ static int eeepc_hotk_check(void) return 0; } -static void notify_wlan(u32 *event) -{ - /* if DISABLE_ASL_WLAN is set, the notify code for fn+f2 - will always be 0x10 */ - if (ehotk->cm_supported & (0x1 << CM_ASL_WLAN)) { - const char *method = cm_getv[CM_ASL_WLAN]; - int value; - if (read_acpi_int(ehotk->handle, method, &value)) - printk(EEEPC_WARNING "Error reading %s\n", - method); - else if (value == 1) - *event = 0x11; - } -} - static void notify_brn(void) { struct backlight_device *bd = eeepc_backlight_device; @@ -386,14 +515,28 @@ static void notify_brn(void) static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) { + static struct key_entry *key; if (!ehotk) return; - if (event == NOTIFY_WLAN_ON && (DISABLE_ASL_WLAN & ehotk->init_flag)) - notify_wlan(&event); if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) notify_brn(); acpi_bus_generate_proc_event(ehotk->device, event, ehotk->event_count[event % 128]++); + if (ehotk->inputdev) { + key = eepc_get_entry_by_scancode(event); + if (key) { + switch (key->type) { + case KE_KEY: + input_report_key(ehotk->inputdev, key->keycode, + 1); + input_sync(ehotk->inputdev); + input_report_key(ehotk->inputdev, key->keycode, + 0); + input_sync(ehotk->inputdev); + break; + } + } + } } static int eeepc_hotk_add(struct acpi_device *device) @@ -411,7 +554,7 @@ static int eeepc_hotk_add(struct acpi_device *device) ehotk->handle = device->handle; strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME); strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS); - acpi_driver_data(device) = ehotk; + device->driver_data = ehotk; ehotk->device = device; result = eeepc_hotk_check(); if (result) @@ -420,6 +563,47 @@ static int eeepc_hotk_add(struct acpi_device *device) eeepc_hotk_notify, ehotk); if (ACPI_FAILURE(status)) printk(EEEPC_ERR "Error installing notify handler\n"); + + if (get_acpi(CM_ASL_WLAN) != -1) { + ehotk->eeepc_wlan_rfkill = rfkill_allocate(&device->dev, + RFKILL_TYPE_WLAN); + + if (!ehotk->eeepc_wlan_rfkill) + goto end; + + ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan"; + ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set; + ehotk->eeepc_wlan_rfkill->get_state = eeepc_wlan_rfkill_state; + if (get_acpi(CM_ASL_WLAN) == 1) + ehotk->eeepc_wlan_rfkill->state = + RFKILL_STATE_UNBLOCKED; + else + ehotk->eeepc_wlan_rfkill->state = + RFKILL_STATE_SOFT_BLOCKED; + rfkill_register(ehotk->eeepc_wlan_rfkill); + } + + if (get_acpi(CM_ASL_BLUETOOTH) != -1) { + ehotk->eeepc_bluetooth_rfkill = + rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH); + + if (!ehotk->eeepc_bluetooth_rfkill) + goto end; + + ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth"; + ehotk->eeepc_bluetooth_rfkill->toggle_radio = + eeepc_bluetooth_rfkill_set; + ehotk->eeepc_bluetooth_rfkill->get_state = + eeepc_bluetooth_rfkill_state; + if (get_acpi(CM_ASL_BLUETOOTH) == 1) + ehotk->eeepc_bluetooth_rfkill->state = + RFKILL_STATE_UNBLOCKED; + else + ehotk->eeepc_bluetooth_rfkill->state = + RFKILL_STATE_SOFT_BLOCKED; + rfkill_register(ehotk->eeepc_bluetooth_rfkill); + } + end: if (result) { kfree(ehotk); @@ -553,6 +737,12 @@ static void eeepc_backlight_exit(void) { if (eeepc_backlight_device) backlight_device_unregister(eeepc_backlight_device); + if (ehotk->inputdev) + input_unregister_device(ehotk->inputdev); + if (ehotk->eeepc_wlan_rfkill) + rfkill_unregister(ehotk->eeepc_wlan_rfkill); + if (ehotk->eeepc_bluetooth_rfkill) + rfkill_unregister(ehotk->eeepc_bluetooth_rfkill); eeepc_backlight_device = NULL; } diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c index 3e56203e494..d2cf0bfe316 100644 --- a/drivers/misc/fujitsu-laptop.c +++ b/drivers/misc/fujitsu-laptop.c @@ -44,8 +44,9 @@ * Hotkeys present on certain Fujitsu laptops (eg: the S6xxx series) are * also supported by this driver. * - * This driver has been tested on a Fujitsu Lifebook S6410 and S7020. It - * should work on most P-series and S-series Lifebooks, but YMMV. + * This driver has been tested on a Fujitsu Lifebook S6410, S7020 and + * P8010. It should work on most P-series and S-series Lifebooks, but + * YMMV. * * The module parameter use_alt_lcd_levels switches between different ACPI * brightness controls which are used by different Fujitsu laptops. In most @@ -65,7 +66,7 @@ #include <linux/video_output.h> #include <linux/platform_device.h> -#define FUJITSU_DRIVER_VERSION "0.4.2" +#define FUJITSU_DRIVER_VERSION "0.4.3" #define FUJITSU_LCD_N_LEVELS 8 @@ -83,10 +84,10 @@ #define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x87 /* Hotkey details */ -#define LOCK_KEY 0x410 /* codes for the keys in the GIRB register */ -#define DISPLAY_KEY 0x411 /* keys are mapped to KEY_SCREENLOCK (the key with the key symbol) */ -#define ENERGY_KEY 0x412 /* KEY_MEDIA (the key with the laptop symbol, KEY_EMAIL (E key)) */ -#define REST_KEY 0x413 /* KEY_SUSPEND (R key) */ +#define KEY1_CODE 0x410 /* codes for the keys in the GIRB register */ +#define KEY2_CODE 0x411 +#define KEY3_CODE 0x412 +#define KEY4_CODE 0x413 #define MAX_HOTKEY_RINGBUFFER_SIZE 100 #define RINGBUFFERSIZE 40 @@ -123,6 +124,7 @@ struct fujitsu_t { char phys[32]; struct backlight_device *bl_device; struct platform_device *pf_device; + int keycode1, keycode2, keycode3, keycode4; unsigned int max_brightness; unsigned int brightness_changed; @@ -224,7 +226,7 @@ static int set_lcd_level_alt(int level) static int get_lcd_level(void) { - unsigned long state = 0; + unsigned long long state = 0; acpi_status status = AE_OK; vdbg_printk(FUJLAPTOP_DBG_TRACE, "get lcd level via GBLL\n"); @@ -246,7 +248,7 @@ static int get_lcd_level(void) static int get_max_brightness(void) { - unsigned long state = 0; + unsigned long long state = 0; acpi_status status = AE_OK; vdbg_printk(FUJLAPTOP_DBG_TRACE, "get max lcd level via RBLL\n"); @@ -263,7 +265,7 @@ static int get_max_brightness(void) static int get_lcd_level_alt(void) { - unsigned long state = 0; + unsigned long long state = 0; acpi_status status = AE_OK; vdbg_printk(FUJLAPTOP_DBG_TRACE, "get lcd level via GBLS\n"); @@ -384,7 +386,7 @@ static ssize_t store_lcd_level(struct device *dev, static int get_irb(void) { - unsigned long state = 0; + unsigned long long state = 0; acpi_status status = AE_OK; vdbg_printk(FUJLAPTOP_DBG_TRACE, "Get irb\n"); @@ -430,7 +432,7 @@ static struct platform_driver fujitsupf_driver = { } }; -static int dmi_check_cb_s6410(const struct dmi_system_id *id) +static void dmi_check_cb_common(const struct dmi_system_id *id) { acpi_handle handle; int have_blnf; @@ -452,24 +454,40 @@ static int dmi_check_cb_s6410(const struct dmi_system_id *id) "auto-detecting disable_adjust\n"); disable_brightness_adjust = have_blnf ? 0 : 1; } +} + +static int dmi_check_cb_s6410(const struct dmi_system_id *id) +{ + dmi_check_cb_common(id); + fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */ + fujitsu->keycode2 = KEY_HELP; /* "Mobility Center" */ + return 0; +} + +static int dmi_check_cb_p8010(const struct dmi_system_id *id) +{ + dmi_check_cb_common(id); + fujitsu->keycode1 = KEY_HELP; /* "Support" */ + fujitsu->keycode3 = KEY_SWITCHVIDEOMODE; /* "Presentation" */ + fujitsu->keycode4 = KEY_WWW; /* "Internet" */ return 0; } static struct dmi_system_id __initdata fujitsu_dmi_table[] = { { - .ident = "Fujitsu Siemens", + .ident = "Fujitsu Siemens S6410", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6410"), }, .callback = dmi_check_cb_s6410}, { - .ident = "FUJITSU LifeBook P8010", + .ident = "Fujitsu LifeBook P8010", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P8010"), - }, - .callback = dmi_check_cb_s6410}, + }, + .callback = dmi_check_cb_p8010}, {} }; @@ -490,7 +508,7 @@ static int acpi_fujitsu_add(struct acpi_device *device) fujitsu->acpi_handle = device->handle; sprintf(acpi_device_name(device), "%s", ACPI_FUJITSU_DEVICE_NAME); sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS); - acpi_driver_data(device) = fujitsu; + device->driver_data = fujitsu; status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, @@ -547,7 +565,6 @@ static int acpi_fujitsu_add(struct acpi_device *device) } /* do config (detect defaults) */ - dmi_check_system(fujitsu_dmi_table); use_alt_lcd_levels = use_alt_lcd_levels == 1 ? 1 : 0; disable_brightness_keys = disable_brightness_keys == 1 ? 1 : 0; disable_brightness_adjust = disable_brightness_adjust == 1 ? 1 : 0; @@ -623,17 +640,17 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data) keycode = 0; if (disable_brightness_keys != 1) { if (oldb == 0) { - acpi_bus_generate_proc_event(fujitsu-> - dev, - ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS, - 0); + acpi_bus_generate_proc_event + (fujitsu->dev, + ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS, + 0); keycode = KEY_BRIGHTNESSDOWN; } else if (oldb == (fujitsu->max_brightness) - 1) { - acpi_bus_generate_proc_event(fujitsu-> - dev, - ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS, - 0); + acpi_bus_generate_proc_event + (fujitsu->dev, + ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS, + 0); keycode = KEY_BRIGHTNESSUP; } } @@ -646,8 +663,7 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data) } if (disable_brightness_keys != 1) { acpi_bus_generate_proc_event(fujitsu->dev, - ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS, - 0); + ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS, 0); keycode = KEY_BRIGHTNESSUP; } } else if (oldb > newb) { @@ -659,8 +675,7 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data) } if (disable_brightness_keys != 1) { acpi_bus_generate_proc_event(fujitsu->dev, - ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS, - 0); + ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS, 0); keycode = KEY_BRIGHTNESSDOWN; } } else { @@ -703,7 +718,7 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device) sprintf(acpi_device_name(device), "%s", ACPI_FUJITSU_HOTKEY_DEVICE_NAME); sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS); - acpi_driver_data(device) = fujitsu_hotkey; + device->driver_data = fujitsu_hotkey; status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, @@ -742,10 +757,10 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device) input->id.product = 0x06; input->dev.parent = &device->dev; input->evbit[0] = BIT(EV_KEY); - set_bit(KEY_SCREENLOCK, input->keybit); - set_bit(KEY_MEDIA, input->keybit); - set_bit(KEY_EMAIL, input->keybit); - set_bit(KEY_SUSPEND, input->keybit); + set_bit(fujitsu->keycode1, input->keybit); + set_bit(fujitsu->keycode2, input->keybit); + set_bit(fujitsu->keycode3, input->keybit); + set_bit(fujitsu->keycode4, input->keybit); set_bit(KEY_UNKNOWN, input->keybit); error = input_register_device(input); @@ -833,24 +848,24 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event, irb); switch (irb & 0x4ff) { - case LOCK_KEY: - keycode = KEY_SCREENLOCK; + case KEY1_CODE: + keycode = fujitsu->keycode1; break; - case DISPLAY_KEY: - keycode = KEY_MEDIA; + case KEY2_CODE: + keycode = fujitsu->keycode2; break; - case ENERGY_KEY: - keycode = KEY_EMAIL; + case KEY3_CODE: + keycode = fujitsu->keycode3; break; - case REST_KEY: - keycode = KEY_SUSPEND; + case KEY4_CODE: + keycode = fujitsu->keycode4; break; case 0: keycode = 0; break; default: vdbg_printk(FUJLAPTOP_DBG_WARN, - "Unknown GIRB result [%x]\n", irb); + "Unknown GIRB result [%x]\n", irb); keycode = -1; break; } @@ -859,12 +874,12 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event, "Push keycode into ringbuffer [%d]\n", keycode); status = kfifo_put(fujitsu_hotkey->fifo, - (unsigned char *)&keycode, - sizeof(keycode)); + (unsigned char *)&keycode, + sizeof(keycode)); if (status != sizeof(keycode)) { vdbg_printk(FUJLAPTOP_DBG_WARN, - "Could not push keycode [0x%x]\n", - keycode); + "Could not push keycode [0x%x]\n", + keycode); } else { input_report_key(input, keycode, 1); input_sync(input); @@ -879,8 +894,8 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event, input_report_key(input, keycode_r, 0); input_sync(input); vdbg_printk(FUJLAPTOP_DBG_TRACE, - "Pop keycode from ringbuffer [%d]\n", - keycode_r); + "Pop keycode from ringbuffer [%d]\n", + keycode_r); } } } @@ -943,6 +958,11 @@ static int __init fujitsu_init(void) if (!fujitsu) return -ENOMEM; memset(fujitsu, 0, sizeof(struct fujitsu_t)); + fujitsu->keycode1 = KEY_PROG1; + fujitsu->keycode2 = KEY_PROG2; + fujitsu->keycode3 = KEY_PROG3; + fujitsu->keycode4 = KEY_PROG4; + dmi_check_system(fujitsu_dmi_table); result = acpi_bus_register_driver(&acpi_fujitsu_driver); if (result < 0) { @@ -1076,15 +1096,14 @@ MODULE_DESCRIPTION("Fujitsu laptop extras support"); MODULE_VERSION(FUJITSU_DRIVER_VERSION); MODULE_LICENSE("GPL"); -MODULE_ALIAS - ("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*"); -MODULE_ALIAS - ("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*"); +MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*"); +MODULE_ALIAS("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*"); static struct pnp_device_id pnp_ids[] = { - { .id = "FUJ02bf" }, - { .id = "FUJ02B1" }, - { .id = "FUJ02E3" }, - { .id = "" } + {.id = "FUJ02bf"}, + {.id = "FUJ02B1"}, + {.id = "FUJ02E3"}, + {.id = ""} }; + MODULE_DEVICE_TABLE(pnp, pnp_ids); diff --git a/drivers/misc/intel_menlow.c b/drivers/misc/intel_menlow.c index 80a13635240..a78274385d5 100644 --- a/drivers/misc/intel_menlow.c +++ b/drivers/misc/intel_menlow.c @@ -57,7 +57,7 @@ static int memory_get_int_max_bandwidth(struct thermal_cooling_device *cdev, { struct acpi_device *device = cdev->devdata; acpi_handle handle = device->handle; - unsigned long value; + unsigned long long value; struct acpi_object_list arg_list; union acpi_object arg; acpi_status status = AE_OK; @@ -90,7 +90,7 @@ static int memory_get_cur_bandwidth(struct thermal_cooling_device *cdev, { struct acpi_device *device = cdev->devdata; acpi_handle handle = device->handle; - unsigned long value; + unsigned long long value; struct acpi_object_list arg_list; union acpi_object arg; acpi_status status = AE_OK; @@ -115,7 +115,7 @@ static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev, struct acpi_object_list arg_list; union acpi_object arg; acpi_status status; - int temp; + unsigned long long temp; unsigned long max_state; if (memory_get_int_max_bandwidth(cdev, &max_state)) @@ -131,7 +131,7 @@ static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev, status = acpi_evaluate_integer(handle, MEMORY_SET_BANDWIDTH, &arg_list, - (unsigned long *)&temp); + &temp); printk(KERN_INFO "Bandwidth value was %d: status is %d\n", state, status); @@ -175,7 +175,7 @@ static int intel_menlow_memory_add(struct acpi_device *device) goto end; } - acpi_driver_data(device) = cdev; + device->driver_data = cdev; result = sysfs_create_link(&device->dev.kobj, &cdev->device.kobj, "thermal_cooling"); if (result) @@ -252,7 +252,8 @@ static DEFINE_MUTEX(intel_menlow_attr_lock); * @auxtype : AUX0/AUX1 * @buf: syfs buffer */ -static int sensor_get_auxtrip(acpi_handle handle, int index, int *value) +static int sensor_get_auxtrip(acpi_handle handle, int index, + unsigned long long *value) { acpi_status status; @@ -260,7 +261,7 @@ static int sensor_get_auxtrip(acpi_handle handle, int index, int *value) return -EINVAL; status = acpi_evaluate_integer(handle, index ? GET_AUX1 : GET_AUX0, - NULL, (unsigned long *)value); + NULL, value); if (ACPI_FAILURE(status)) return -EIO; @@ -282,13 +283,13 @@ static int sensor_set_auxtrip(acpi_handle handle, int index, int value) struct acpi_object_list args = { 1, &arg }; - int temp; + unsigned long long temp; if (index != 0 && index != 1) return -EINVAL; status = acpi_evaluate_integer(handle, index ? GET_AUX0 : GET_AUX1, - NULL, (unsigned long *)&temp); + NULL, &temp); if (ACPI_FAILURE(status)) return -EIO; if ((index && value < temp) || (!index && value > temp)) @@ -296,7 +297,7 @@ static int sensor_set_auxtrip(acpi_handle handle, int index, int value) arg.integer.value = value; status = acpi_evaluate_integer(handle, index ? SET_AUX1 : SET_AUX0, - &args, (unsigned long *)&temp); + &args, &temp); if (ACPI_FAILURE(status)) return -EIO; @@ -312,7 +313,7 @@ static ssize_t aux0_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { struct intel_menlow_attribute *attr = to_intel_menlow_attr(dev_attr); - int value; + unsigned long long value; int result; result = sensor_get_auxtrip(attr->handle, 0, &value); @@ -324,7 +325,7 @@ static ssize_t aux1_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { struct intel_menlow_attribute *attr = to_intel_menlow_attr(dev_attr); - int value; + unsigned long long value; int result; result = sensor_get_auxtrip(attr->handle, 1, &value); @@ -376,7 +377,7 @@ static ssize_t bios_enabled_show(struct device *dev, struct device_attribute *attr, char *buf) { acpi_status status; - unsigned long bios_enabled; + unsigned long long bios_enabled; status = acpi_evaluate_integer(NULL, BIOS_ENABLED, NULL, &bios_enabled); if (ACPI_FAILURE(status)) @@ -492,7 +493,7 @@ static int __init intel_menlow_module_init(void) { int result = -ENODEV; acpi_status status; - unsigned long enable; + unsigned long long enable; if (acpi_disabled) return result; diff --git a/drivers/misc/panasonic-laptop.c b/drivers/misc/panasonic-laptop.c new file mode 100644 index 00000000000..a2cb598d8ab --- /dev/null +++ b/drivers/misc/panasonic-laptop.c @@ -0,0 +1,767 @@ +/* + * Panasonic HotKey and LCD brightness control driver + * (C) 2004 Hiroshi Miura <miura@da-cha.org> + * (C) 2004 NTT DATA Intellilink Co. http://www.intellilink.co.jp/ + * (C) YOKOTA Hiroshi <yokota (at) netlab. is. tsukuba. ac. jp> + * (C) 2004 David Bronaugh <dbronaugh> + * (C) 2006-2008 Harald Welte <laforge@gnumonks.org> + * + * derived from toshiba_acpi.c, Copyright (C) 2002-2004 John Belmonte + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * publicshed by the Free Software Foundation. + * + * 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 + * + *--------------------------------------------------------------------------- + * + * ChangeLog: + * Sep.23, 2008 Harald Welte <laforge@gnumonks.org> + * -v0.95 rename driver from drivers/acpi/pcc_acpi.c to + * drivers/misc/panasonic-laptop.c + * + * Jul.04, 2008 Harald Welte <laforge@gnumonks.org> + * -v0.94 replace /proc interface with device attributes + * support {set,get}keycode on th input device + * + * Jun.27, 2008 Harald Welte <laforge@gnumonks.org> + * -v0.92 merge with 2.6.26-rc6 input API changes + * remove broken <= 2.6.15 kernel support + * resolve all compiler warnings + * various coding style fixes (checkpatch.pl) + * add support for backlight api + * major code restructuring + * + * Dac.28, 2007 Harald Welte <laforge@gnumonks.org> + * -v0.91 merge with 2.6.24-rc6 ACPI changes + * + * Nov.04, 2006 Hiroshi Miura <miura@da-cha.org> + * -v0.9 remove warning about section reference. + * remove acpi_os_free + * add /proc/acpi/pcc/brightness interface for HAL access + * merge dbronaugh's enhancement + * Aug.17, 2004 David Bronaugh (dbronaugh) + * - Added screen brightness setting interface + * Thanks to FreeBSD crew (acpi_panasonic.c) + * for the ideas I needed to accomplish it + * + * May.29, 2006 Hiroshi Miura <miura@da-cha.org> + * -v0.8.4 follow to change keyinput structure + * thanks Fabian Yamaguchi <fabs@cs.tu-berlin.de>, + * Jacob Bower <jacob.bower@ic.ac.uk> and + * Hiroshi Yokota for providing solutions. + * + * Oct.02, 2004 Hiroshi Miura <miura@da-cha.org> + * -v0.8.2 merge code of YOKOTA Hiroshi + * <yokota@netlab.is.tsukuba.ac.jp>. + * Add sticky key mode interface. + * Refactoring acpi_pcc_generate_keyinput(). + * + * Sep.15, 2004 Hiroshi Miura <miura@da-cha.org> + * -v0.8 Generate key input event on input subsystem. + * This is based on yet another driver written by + * Ryuta Nakanishi. + * + * Sep.10, 2004 Hiroshi Miura <miura@da-cha.org> + * -v0.7 Change proc interface functions using seq_file + * facility as same as other ACPI drivers. + * + * Aug.28, 2004 Hiroshi Miura <miura@da-cha.org> + * -v0.6.4 Fix a silly error with status checking + * + * Aug.25, 2004 Hiroshi Miura <miura@da-cha.org> + * -v0.6.3 replace read_acpi_int by standard function + * acpi_evaluate_integer + * some clean up and make smart copyright notice. + * fix return value of pcc_acpi_get_key() + * fix checking return value of acpi_bus_register_driver() + * + * Aug.22, 2004 David Bronaugh <dbronaugh@linuxboxen.org> + * -v0.6.2 Add check on ACPI data (num_sifr) + * Coding style cleanups, better error messages/handling + * Fixed an off-by-one error in memory allocation + * + * Aug.21, 2004 David Bronaugh <dbronaugh@linuxboxen.org> + * -v0.6.1 Fix a silly error with status checking + * + * Aug.20, 2004 David Bronaugh <dbronaugh@linuxboxen.org> + * - v0.6 Correct brightness controls to reflect reality + * based on information gleaned by Hiroshi Miura + * and discussions with Hiroshi Miura + * + * Aug.10, 2004 Hiroshi Miura <miura@da-cha.org> + * - v0.5 support LCD brightness control + * based on the disclosed information by MEI. + * + * Jul.25, 2004 Hiroshi Miura <miura@da-cha.org> + * - v0.4 first post version + * add function to retrive SIFR + * + * Jul.24, 2004 Hiroshi Miura <miura@da-cha.org> + * - v0.3 get proper status of hotkey + * + * Jul.22, 2004 Hiroshi Miura <miura@da-cha.org> + * - v0.2 add HotKey handler + * + * Jul.17, 2004 Hiroshi Miura <miura@da-cha.org> + * - v0.1 start from toshiba_acpi driver written by John Belmonte + * + */ + +#include <linux/version.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/backlight.h> +#include <linux/ctype.h> +#include <linux/seq_file.h> +#include <linux/uaccess.h> +#include <acpi/acpi_bus.h> +#include <acpi/acpi_drivers.h> +#include <linux/input.h> + + +#ifndef ACPI_HOTKEY_COMPONENT +#define ACPI_HOTKEY_COMPONENT 0x10000000 +#endif + +#define _COMPONENT ACPI_HOTKEY_COMPONENT + +MODULE_AUTHOR("Hiroshi Miura, David Bronaugh and Harald Welte"); +MODULE_DESCRIPTION("ACPI HotKey driver for Panasonic Let's Note laptops"); +MODULE_LICENSE("GPL"); + +#define LOGPREFIX "pcc_acpi: " + +/* Define ACPI PATHs */ +/* Lets note hotkeys */ +#define METHOD_HKEY_QUERY "HINF" +#define METHOD_HKEY_SQTY "SQTY" +#define METHOD_HKEY_SINF "SINF" +#define METHOD_HKEY_SSET "SSET" +#define HKEY_NOTIFY 0x80 + +#define ACPI_PCC_DRIVER_NAME "Panasonic Laptop Support" +#define ACPI_PCC_DEVICE_NAME "Hotkey" +#define ACPI_PCC_CLASS "pcc" + +#define ACPI_PCC_INPUT_PHYS "panasonic/hkey0" + +/* LCD_TYPEs: 0 = Normal, 1 = Semi-transparent + ENV_STATEs: Normal temp=0x01, High temp=0x81, N/A=0x00 +*/ +enum SINF_BITS { SINF_NUM_BATTERIES = 0, + SINF_LCD_TYPE, + SINF_AC_MAX_BRIGHT, + SINF_AC_MIN_BRIGHT, + SINF_AC_CUR_BRIGHT, + SINF_DC_MAX_BRIGHT, + SINF_DC_MIN_BRIGHT, + SINF_DC_CUR_BRIGHT, + SINF_MUTE, + SINF_RESERVED, + SINF_ENV_STATE, + SINF_STICKY_KEY = 0x80, + }; +/* R1 handles SINF_AC_CUR_BRIGHT as SINF_CUR_BRIGHT, doesn't know AC state */ + +static int acpi_pcc_hotkey_add(struct acpi_device *device); +static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type); +static int acpi_pcc_hotkey_resume(struct acpi_device *device); + +static const struct acpi_device_id pcc_device_ids[] = { + { "MAT0012", 0}, + { "MAT0013", 0}, + { "MAT0018", 0}, + { "MAT0019", 0}, + { "", 0}, +}; + +static struct acpi_driver acpi_pcc_driver = { + .name = ACPI_PCC_DRIVER_NAME, + .class = ACPI_PCC_CLASS, + .ids = pcc_device_ids, + .ops = { + .add = acpi_pcc_hotkey_add, + .remove = acpi_pcc_hotkey_remove, + .resume = acpi_pcc_hotkey_resume, + }, +}; + +#define KEYMAP_SIZE 11 +static const int initial_keymap[KEYMAP_SIZE] = { + /* 0 */ KEY_RESERVED, + /* 1 */ KEY_BRIGHTNESSDOWN, + /* 2 */ KEY_BRIGHTNESSUP, + /* 3 */ KEY_DISPLAYTOGGLE, + /* 4 */ KEY_MUTE, + /* 5 */ KEY_VOLUMEDOWN, + /* 6 */ KEY_VOLUMEUP, + /* 7 */ KEY_SLEEP, + /* 8 */ KEY_PROG1, /* Change CPU boost */ + /* 9 */ KEY_BATTERY, + /* 10 */ KEY_SUSPEND, +}; + +struct pcc_acpi { + acpi_handle handle; + unsigned long num_sifr; + int sticky_mode; + u32 *sinf; + struct acpi_device *device; + struct input_dev *input_dev; + struct backlight_device *backlight; + int keymap[KEYMAP_SIZE]; +}; + +struct pcc_keyinput { + struct acpi_hotkey *hotkey; +}; + +/* method access functions */ +static int acpi_pcc_write_sset(struct pcc_acpi *pcc, int func, int val) +{ + union acpi_object in_objs[] = { + { .integer.type = ACPI_TYPE_INTEGER, + .integer.value = func, }, + { .integer.type = ACPI_TYPE_INTEGER, + .integer.value = val, }, + }; + struct acpi_object_list params = { + .count = ARRAY_SIZE(in_objs), + .pointer = in_objs, + }; + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE("acpi_pcc_write_sset"); + + status = acpi_evaluate_object(pcc->handle, METHOD_HKEY_SSET, + ¶ms, NULL); + + return status == AE_OK; +} + +static inline int acpi_pcc_get_sqty(struct acpi_device *device) +{ + unsigned long long s; + acpi_status status; + + ACPI_FUNCTION_TRACE("acpi_pcc_get_sqty"); + + status = acpi_evaluate_integer(device->handle, METHOD_HKEY_SQTY, + NULL, &s); + if (ACPI_SUCCESS(status)) + return s; + else { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "evaluation error HKEY.SQTY\n")); + return -EINVAL; + } +} + +static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc, u32 *sinf) +{ + acpi_status status; + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + union acpi_object *hkey = NULL; + int i; + + ACPI_FUNCTION_TRACE("acpi_pcc_retrieve_biosdata"); + + status = acpi_evaluate_object(pcc->handle, METHOD_HKEY_SINF, 0, + &buffer); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "evaluation error HKEY.SINF\n")); + return 0; + } + + hkey = buffer.pointer; + if (!hkey || (hkey->type != ACPI_TYPE_PACKAGE)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid HKEY.SINF\n")); + goto end; + } + + if (pcc->num_sifr < hkey->package.count) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "SQTY reports bad SINF length\n")); + status = AE_ERROR; + goto end; + } + + for (i = 0; i < hkey->package.count; i++) { + union acpi_object *element = &(hkey->package.elements[i]); + if (likely(element->type == ACPI_TYPE_INTEGER)) { + sinf[i] = element->integer.value; + } else + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Invalid HKEY.SINF data\n")); + } + sinf[hkey->package.count] = -1; + +end: + kfree(buffer.pointer); + return status == AE_OK; +} + +/* backlight API interface functions */ + +/* This driver currently treats AC and DC brightness identical, + * since we don't need to invent an interface to the core ACPI + * logic to receive events in case a power supply is plugged in + * or removed */ + +static int bl_get(struct backlight_device *bd) +{ + struct pcc_acpi *pcc = bl_get_data(bd); + + if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) + return -EIO; + + return pcc->sinf[SINF_AC_CUR_BRIGHT]; +} + +static int bl_set_status(struct backlight_device *bd) +{ + struct pcc_acpi *pcc = bl_get_data(bd); + int bright = bd->props.brightness; + int rc; + + if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) + return -EIO; + + if (bright < pcc->sinf[SINF_AC_MIN_BRIGHT]) + bright = pcc->sinf[SINF_AC_MIN_BRIGHT]; + + if (bright < pcc->sinf[SINF_DC_MIN_BRIGHT]) + bright = pcc->sinf[SINF_DC_MIN_BRIGHT]; + + if (bright < pcc->sinf[SINF_AC_MIN_BRIGHT] || + bright > pcc->sinf[SINF_AC_MAX_BRIGHT]) + return -EINVAL; + + rc = acpi_pcc_write_sset(pcc, SINF_AC_CUR_BRIGHT, bright); + if (rc < 0) + return rc; + + return acpi_pcc_write_sset(pcc, SINF_DC_CUR_BRIGHT, bright); +} + +static struct backlight_ops pcc_backlight_ops = { + .get_brightness = bl_get, + .update_status = bl_set_status, +}; + + +/* sysfs user interface functions */ + +static ssize_t show_numbatt(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi = to_acpi_device(dev); + struct pcc_acpi *pcc = acpi_driver_data(acpi); + + if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) + return -EIO; + + return sprintf(buf, "%u\n", pcc->sinf[SINF_NUM_BATTERIES]); +} + +static ssize_t show_lcdtype(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi = to_acpi_device(dev); + struct pcc_acpi *pcc = acpi_driver_data(acpi); + + if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) + return -EIO; + + return sprintf(buf, "%u\n", pcc->sinf[SINF_LCD_TYPE]); +} + +static ssize_t show_mute(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi = to_acpi_device(dev); + struct pcc_acpi *pcc = acpi_driver_data(acpi); + + if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) + return -EIO; + + return sprintf(buf, "%u\n", pcc->sinf[SINF_MUTE]); +} + +static ssize_t show_sticky(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi = to_acpi_device(dev); + struct pcc_acpi *pcc = acpi_driver_data(acpi); + + if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) + return -EIO; + + return sprintf(buf, "%u\n", pcc->sinf[SINF_STICKY_KEY]); +} + +static ssize_t set_sticky(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct acpi_device *acpi = to_acpi_device(dev); + struct pcc_acpi *pcc = acpi_driver_data(acpi); + int val; + + if (count && sscanf(buf, "%i", &val) == 1 && + (val == 0 || val == 1)) { + acpi_pcc_write_sset(pcc, SINF_STICKY_KEY, val); + pcc->sticky_mode = val; + } + + return count; +} + +static DEVICE_ATTR(numbatt, S_IRUGO, show_numbatt, NULL); +static DEVICE_ATTR(lcdtype, S_IRUGO, show_lcdtype, NULL); +static DEVICE_ATTR(mute, S_IRUGO, show_mute, NULL); +static DEVICE_ATTR(sticky_key, S_IRUGO | S_IWUSR, show_sticky, set_sticky); + +static struct attribute *pcc_sysfs_entries[] = { + &dev_attr_numbatt.attr, + &dev_attr_lcdtype.attr, + &dev_attr_mute.attr, + &dev_attr_sticky_key.attr, + NULL, +}; + +static struct attribute_group pcc_attr_group = { + .name = NULL, /* put in device directory */ + .attrs = pcc_sysfs_entries, +}; + + +/* hotkey input device driver */ + +static int pcc_getkeycode(struct input_dev *dev, int scancode, int *keycode) +{ + struct pcc_acpi *pcc = input_get_drvdata(dev); + + if (scancode >= ARRAY_SIZE(pcc->keymap)) + return -EINVAL; + + *keycode = pcc->keymap[scancode]; + + return 0; +} + +static int keymap_get_by_keycode(struct pcc_acpi *pcc, int keycode) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(pcc->keymap); i++) { + if (pcc->keymap[i] == keycode) + return i+1; + } + + return 0; +} + +static int pcc_setkeycode(struct input_dev *dev, int scancode, int keycode) +{ + struct pcc_acpi *pcc = input_get_drvdata(dev); + int oldkeycode; + + if (scancode >= ARRAY_SIZE(pcc->keymap)) + return -EINVAL; + + if (keycode < 0 || keycode > KEY_MAX) + return -EINVAL; + + oldkeycode = pcc->keymap[scancode]; + pcc->keymap[scancode] = keycode; + + set_bit(keycode, dev->keybit); + + if (!keymap_get_by_keycode(pcc, oldkeycode)) + clear_bit(oldkeycode, dev->keybit); + + return 0; +} + +static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc) +{ + struct input_dev *hotk_input_dev = pcc->input_dev; + int rc; + int key_code, hkey_num; + unsigned long long result; + + ACPI_FUNCTION_TRACE("acpi_pcc_generate_keyinput"); + + rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY, + NULL, &result); + if (!ACPI_SUCCESS(rc)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "error getting hotkey status\n")); + return; + } + + acpi_bus_generate_proc_event(pcc->device, HKEY_NOTIFY, result); + + hkey_num = result & 0xf; + + if (hkey_num < 0 || hkey_num > ARRAY_SIZE(pcc->keymap)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "hotkey number out of range: %d\n", + hkey_num)); + return; + } + + key_code = pcc->keymap[hkey_num]; + + if (key_code != KEY_RESERVED) { + int pushed = (result & 0x80) ? TRUE : FALSE; + + input_report_key(hotk_input_dev, key_code, pushed); + input_sync(hotk_input_dev); + } + + return; +} + +static void acpi_pcc_hotkey_notify(acpi_handle handle, u32 event, void *data) +{ + struct pcc_acpi *pcc = (struct pcc_acpi *) data; + + ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_notify"); + + switch (event) { + case HKEY_NOTIFY: + acpi_pcc_generate_keyinput(pcc); + break; + default: + /* nothing to do */ + break; + } +} + +static int acpi_pcc_init_input(struct pcc_acpi *pcc) +{ + int i, rc; + + ACPI_FUNCTION_TRACE("acpi_pcc_init_input"); + + pcc->input_dev = input_allocate_device(); + if (!pcc->input_dev) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Couldn't allocate input device for hotkey")); + return -ENOMEM; + } + + pcc->input_dev->evbit[0] = BIT(EV_KEY); + + pcc->input_dev->name = ACPI_PCC_DRIVER_NAME; + pcc->input_dev->phys = ACPI_PCC_INPUT_PHYS; + pcc->input_dev->id.bustype = BUS_HOST; + pcc->input_dev->id.vendor = 0x0001; + pcc->input_dev->id.product = 0x0001; + pcc->input_dev->id.version = 0x0100; + pcc->input_dev->getkeycode = pcc_getkeycode; + pcc->input_dev->setkeycode = pcc_setkeycode; + + /* load initial keymap */ + memcpy(pcc->keymap, initial_keymap, sizeof(pcc->keymap)); + + for (i = 0; i < ARRAY_SIZE(pcc->keymap); i++) + __set_bit(pcc->keymap[i], pcc->input_dev->keybit); + __clear_bit(KEY_RESERVED, pcc->input_dev->keybit); + + input_set_drvdata(pcc->input_dev, pcc); + + rc = input_register_device(pcc->input_dev); + if (rc < 0) + input_free_device(pcc->input_dev); + + return rc; +} + +/* kernel module interface */ + +static int acpi_pcc_hotkey_resume(struct acpi_device *device) +{ + struct pcc_acpi *pcc = acpi_driver_data(device); + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_resume"); + + if (device == NULL || pcc == NULL) + return -EINVAL; + + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Sticky mode restore: %d\n", + pcc->sticky_mode)); + + status = acpi_pcc_write_sset(pcc, SINF_STICKY_KEY, pcc->sticky_mode); + + return status == AE_OK ? 0 : -EINVAL; +} + +static int acpi_pcc_hotkey_add(struct acpi_device *device) +{ + acpi_status status; + struct pcc_acpi *pcc; + int num_sifr, result; + + ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_add"); + + if (!device) + return -EINVAL; + + num_sifr = acpi_pcc_get_sqty(device); + + if (num_sifr > 255) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "num_sifr too large")); + return -ENODEV; + } + + pcc = kzalloc(sizeof(struct pcc_acpi), GFP_KERNEL); + if (!pcc) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Couldn't allocate mem for pcc")); + return -ENOMEM; + } + + pcc->sinf = kzalloc(sizeof(u32) * (num_sifr + 1), GFP_KERNEL); + if (!pcc->sinf) { + result = -ENOMEM; + goto out_hotkey; + } + + pcc->device = device; + pcc->handle = device->handle; + pcc->num_sifr = num_sifr; + device->driver_data = pcc; + strcpy(acpi_device_name(device), ACPI_PCC_DEVICE_NAME); + strcpy(acpi_device_class(device), ACPI_PCC_CLASS); + + result = acpi_pcc_init_input(pcc); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error installing keyinput handler\n")); + goto out_sinf; + } + + /* initialize hotkey input device */ + status = acpi_install_notify_handler(pcc->handle, ACPI_DEVICE_NOTIFY, + acpi_pcc_hotkey_notify, pcc); + + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error installing notify handler\n")); + result = -ENODEV; + goto out_input; + } + + /* initialize backlight */ + pcc->backlight = backlight_device_register("panasonic", NULL, pcc, + &pcc_backlight_ops); + if (IS_ERR(pcc->backlight)) + goto out_notify; + + if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Couldn't retrieve BIOS data\n")); + goto out_backlight; + } + + /* read the initial brightness setting from the hardware */ + pcc->backlight->props.max_brightness = + pcc->sinf[SINF_AC_MAX_BRIGHT]; + pcc->backlight->props.brightness = pcc->sinf[SINF_AC_CUR_BRIGHT]; + + /* read the initial sticky key mode from the hardware */ + pcc->sticky_mode = pcc->sinf[SINF_STICKY_KEY]; + + /* add sysfs attributes */ + result = sysfs_create_group(&device->dev.kobj, &pcc_attr_group); + if (result) + goto out_backlight; + + return 0; + +out_backlight: + backlight_device_unregister(pcc->backlight); +out_notify: + acpi_remove_notify_handler(pcc->handle, ACPI_DEVICE_NOTIFY, + acpi_pcc_hotkey_notify); +out_input: + input_unregister_device(pcc->input_dev); + /* no need to input_free_device() since core input API refcount and + * free()s the device */ +out_sinf: + kfree(pcc->sinf); +out_hotkey: + kfree(pcc); + + return result; +} + +static int __init acpi_pcc_init(void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_pcc_init"); + + if (acpi_disabled) + return -ENODEV; + + result = acpi_bus_register_driver(&acpi_pcc_driver); + if (result < 0) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error registering hotkey driver\n")); + return -ENODEV; + } + + return 0; +} + +static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type) +{ + struct pcc_acpi *pcc = acpi_driver_data(device); + + ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_remove"); + + if (!device || !pcc) + return -EINVAL; + + sysfs_remove_group(&device->dev.kobj, &pcc_attr_group); + + backlight_device_unregister(pcc->backlight); + + acpi_remove_notify_handler(pcc->handle, ACPI_DEVICE_NOTIFY, + acpi_pcc_hotkey_notify); + + input_unregister_device(pcc->input_dev); + /* no need to input_free_device() since core input API refcount and + * free()s the device */ + + kfree(pcc->sinf); + kfree(pcc); + + return 0; +} + +static void __exit acpi_pcc_exit(void) +{ + ACPI_FUNCTION_TRACE("acpi_pcc_exit"); + + acpi_bus_unregister_driver(&acpi_pcc_driver); +} + +module_init(acpi_pcc_init); +module_exit(acpi_pcc_exit); diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c index 60775be2282..5a97d3a9d74 100644 --- a/drivers/misc/sony-laptop.c +++ b/drivers/misc/sony-laptop.c @@ -970,7 +970,7 @@ static int sony_nc_resume(struct acpi_device *device) /* set the last requested brightness level */ if (sony_backlight_device && !sony_backlight_update_status(sony_backlight_device)) - printk(KERN_WARNING DRV_PFX "unable to restore brightness level"); + printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n"); /* re-initialize models with specific requirements */ dmi_check_system(sony_nc_ids); diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 6b9300779a4..4db1cf9078d 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -159,7 +159,6 @@ enum { #define TPACPI_DEBUG KERN_DEBUG TPACPI_LOG #define TPACPI_DBG_ALL 0xffff -#define TPACPI_DBG_ALL 0xffff #define TPACPI_DBG_INIT 0x0001 #define TPACPI_DBG_EXIT 0x0002 #define dbg_printk(a_dbg_level, format, arg...) \ @@ -543,7 +542,7 @@ static int __init setup_acpi_notify(struct ibm_struct *ibm) return -ENODEV; } - acpi_driver_data(ibm->acpi->device) = ibm; + ibm->acpi->device->driver_data = ibm; sprintf(acpi_device_class(ibm->acpi->device), "%s/%s", TPACPI_ACPI_EVENT_PREFIX, ibm->name); @@ -582,7 +581,8 @@ static int __init register_tpacpi_subdriver(struct ibm_struct *ibm) ibm->acpi->driver = kzalloc(sizeof(struct acpi_driver), GFP_KERNEL); if (!ibm->acpi->driver) { - printk(TPACPI_ERR "kzalloc(ibm->driver) failed\n"); + printk(TPACPI_ERR + "failed to allocate memory for ibm->acpi->driver\n"); return -ENOMEM; } @@ -838,6 +838,13 @@ static int parse_strtoul(const char *buf, return 0; } +static void tpacpi_disable_brightness_delay(void) +{ + if (acpi_evalf(hkey_handle, NULL, "PWMS", "qvd", 0)) + printk(TPACPI_NOTICE + "ACPI backlight control delay disabled\n"); +} + static int __init tpacpi_query_bcl_levels(acpi_handle handle) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -2139,6 +2146,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) if (!tp_features.hotkey) return 1; + tpacpi_disable_brightness_delay(); + hotkey_dev_attributes = create_attr_set(13, NULL); if (!hotkey_dev_attributes) return -ENOMEM; @@ -2512,6 +2521,8 @@ static void hotkey_suspend(pm_message_t state) static void hotkey_resume(void) { + tpacpi_disable_brightness_delay(); + if (hotkey_mask_get()) printk(TPACPI_ERR "error while trying to read hot key mask " @@ -5983,6 +5994,52 @@ static void fan_exit(void) flush_workqueue(tpacpi_wq); } +static void fan_suspend(pm_message_t state) +{ + if (!fan_control_allowed) + return; + + /* Store fan status in cache */ + fan_get_status_safe(NULL); + if (tp_features.fan_ctrl_status_undef) + fan_control_desired_level = TP_EC_FAN_AUTO; +} + +static void fan_resume(void) +{ + u8 saved_fan_level; + u8 current_level = 7; + bool do_set = false; + + /* DSDT *always* updates status on resume */ + tp_features.fan_ctrl_status_undef = 0; + + saved_fan_level = fan_control_desired_level; + if (!fan_control_allowed || + (fan_get_status_safe(¤t_level) < 0)) + return; + + switch (fan_control_access_mode) { + case TPACPI_FAN_WR_ACPI_SFAN: + do_set = (saved_fan_level > current_level); + break; + case TPACPI_FAN_WR_ACPI_FANS: + case TPACPI_FAN_WR_TPEC: + do_set = ((saved_fan_level & TP_EC_FAN_FULLSPEED) || + (saved_fan_level == 7 && + !(current_level & TP_EC_FAN_FULLSPEED))); + break; + default: + return; + } + if (do_set) { + printk(TPACPI_NOTICE + "restoring fan level to 0x%02x\n", + saved_fan_level); + fan_set_level_safe(saved_fan_level); + } +} + static int fan_read(char *p) { int len = 0; @@ -6174,6 +6231,8 @@ static struct ibm_struct fan_driver_data = { .read = fan_read, .write = fan_write, .exit = fan_exit, + .suspend = fan_suspend, + .resume = fan_resume, }; /**************************************************************************** diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index a3e4705dd8f..955aae4071f 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -169,7 +169,9 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val, } - +static struct acpi_dock_ops acpiphp_dock_ops = { + .handler = handle_hotplug_event_func, +}; /* callback routine to register each ACPI PCI slot object */ static acpi_status @@ -180,7 +182,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) struct acpiphp_func *newfunc; acpi_handle tmp; acpi_status status = AE_OK; - unsigned long adr, sun; + unsigned long long adr, sun; int device, function, retval; status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); @@ -285,7 +287,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) */ newfunc->flags &= ~FUNC_HAS_EJ0; if (register_hotplug_dock_device(handle, - handle_hotplug_event_func, newfunc)) + &acpiphp_dock_ops, newfunc)) dbg("failed to register dock device\n"); /* we need to be notified when dock events happen @@ -528,7 +530,7 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) { acpi_status status; acpi_handle dummy_handle; - unsigned long tmp; + unsigned long long tmp; int device, function; struct pci_dev *dev; struct pci_bus *pci_bus = context; @@ -573,7 +575,7 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) static int add_bridge(acpi_handle handle) { acpi_status status; - unsigned long tmp; + unsigned long long tmp; int seg, bus; acpi_handle dummy_handle; struct pci_bus *pci_bus; @@ -767,7 +769,7 @@ static int get_gsi_base(acpi_handle handle, u32 *gsi_base) { acpi_status status; int result = -1; - unsigned long gsb; + unsigned long long gsb; struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; union acpi_object *obj; void *table; @@ -808,7 +810,7 @@ static acpi_status ioapic_add(acpi_handle handle, u32 lvl, void *context, void **rv) { acpi_status status; - unsigned long sta; + unsigned long long sta; acpi_handle tmp; struct pci_dev *pdev; u32 gsi_base; @@ -872,7 +874,7 @@ static acpi_status ioapic_remove(acpi_handle handle, u32 lvl, void *context, void **rv) { acpi_status status; - unsigned long sta; + unsigned long long sta; acpi_handle tmp; u32 gsi_base; struct acpiphp_ioapic *pos, *n, *ioapic = NULL; @@ -1264,7 +1266,7 @@ static int disable_device(struct acpiphp_slot *slot) static unsigned int get_slot_status(struct acpiphp_slot *slot) { acpi_status status; - unsigned long sta = 0; + unsigned long long sta = 0; u32 dvid; struct list_head *l; struct acpiphp_func *func; diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index 2b7c45e3937..b291ee68b4f 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c @@ -183,7 +183,7 @@ static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status) union acpi_object args[2]; struct acpi_object_list params = { .pointer = args, .count = 2 }; acpi_status stat; - unsigned long rc; + unsigned long long rc; union apci_descriptor *ibm_slot; ibm_slot = ibm_slot_from_id(hpslot_to_sun(slot)); diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index 410fe0394a8..59f42501acc 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c @@ -418,7 +418,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) /* * Add the slot's devices to the ACPI infrastructure */ if (SN_ACPI_BASE_SUPPORT() && ssdt) { - unsigned long adr; + unsigned long long adr; struct acpi_device *pdevice; struct acpi_device *device; acpi_handle phandle; @@ -510,7 +510,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) /* free the ACPI resources for the slot */ if (SN_ACPI_BASE_SUPPORT() && PCI_CONTROLLER(slot->pci_bus)->acpi_handle) { - unsigned long adr; + unsigned long long adr; struct acpi_device *device; acpi_handle phandle; acpi_handle chandle = NULL; diff --git a/drivers/pnp/Kconfig b/drivers/pnp/Kconfig index 821933f9aa5..2a37b3fedb8 100644 --- a/drivers/pnp/Kconfig +++ b/drivers/pnp/Kconfig @@ -20,13 +20,21 @@ menuconfig PNP If unsure, say Y. -if PNP - -config PNP_DEBUG - bool "PnP Debug Messages" +config PNP_DEBUG_MESSAGES + default y + bool "PNP debugging messages" + depends on PNP help - Say Y if you want the Plug and Play Layer to print debug messages. - This is useful if you are developing a PnP driver or troubleshooting. + Say Y here if you want the PNP layer to be able to produce debugging + messages if needed. The messages can be enabled at boot-time with + the pnp.debug kernel parameter. + + This option allows you to save a bit of space if you do not want + the messages to even be built into the kernel. + + If you have any doubts about this, say Y here. + +if PNP comment "Protocols" diff --git a/drivers/pnp/Makefile b/drivers/pnp/Makefile index e83f34f1b5b..8de3775ec24 100644 --- a/drivers/pnp/Makefile +++ b/drivers/pnp/Makefile @@ -10,7 +10,3 @@ obj-$(CONFIG_ISAPNP) += isapnp/ # pnp_system_init goes after pnpacpi/pnpbios init obj-y += system.o - -ifeq ($(CONFIG_PNP_DEBUG),y) -EXTRA_CFLAGS += -DDEBUG -endif diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index 3b8b9d3cb03..0b8d14050ef 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h @@ -166,3 +166,13 @@ struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev, struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev, resource_size_t start, resource_size_t end, int flags); + +extern int pnp_debug; + +#if defined(CONFIG_PNP_DEBUG_MESSAGES) +#define pnp_dbg(dev, format, arg...) \ + ({ if (pnp_debug) dev_printk(KERN_DEBUG, dev, format, ## arg); 0; }) +#else +#define pnp_dbg(dev, format, arg...) \ + ({ if (0) dev_printk(KERN_DEBUG, dev, format, ## arg); 0; }) +#endif diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c index 817fe626e15..16c01c6fa7c 100644 --- a/drivers/pnp/core.c +++ b/drivers/pnp/core.c @@ -177,6 +177,9 @@ int __pnp_add_device(struct pnp_dev *dev) int pnp_add_device(struct pnp_dev *dev) { int ret; + char buf[128]; + int len = 0; + struct pnp_id *id; if (dev->card) return -EINVAL; @@ -185,17 +188,12 @@ int pnp_add_device(struct pnp_dev *dev) if (ret) return ret; -#ifdef CONFIG_PNP_DEBUG - { - struct pnp_id *id; + buf[0] = '\0'; + for (id = dev->id; id; id = id->next) + len += scnprintf(buf + len, sizeof(buf) - len, " %s", id->id); - dev_printk(KERN_DEBUG, &dev->dev, "%s device, IDs", - dev->protocol->name); - for (id = dev->id; id; id = id->next) - printk(" %s", id->id); - printk(" (%s)\n", dev->active ? "active" : "disabled"); - } -#endif + pnp_dbg(&dev->dev, "%s device, IDs%s (%s)\n", + dev->protocol->name, buf, dev->active ? "active" : "disabled"); return 0; } @@ -214,3 +212,14 @@ static int __init pnp_init(void) } subsys_initcall(pnp_init); + +int pnp_debug; + +#if defined(CONFIG_PNP_DEBUG_MESSAGES) +static int __init pnp_debug_setup(char *__unused) +{ + pnp_debug = 1; + return 1; +} +__setup("pnp.debug", pnp_debug_setup); +#endif diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c index e3f7e89c4df..527ee764c93 100644 --- a/drivers/pnp/driver.c +++ b/drivers/pnp/driver.c @@ -114,7 +114,6 @@ static int pnp_device_probe(struct device *dev) } else goto fail; - dev_dbg(dev, "driver attached\n"); return error; fail: @@ -211,8 +210,6 @@ struct bus_type pnp_bus_type = { int pnp_register_driver(struct pnp_driver *drv) { - pnp_dbg("the driver '%s' has been registered", drv->name); - drv->driver.name = drv->name; drv->driver.bus = &pnp_bus_type; @@ -222,7 +219,6 @@ int pnp_register_driver(struct pnp_driver *drv) void pnp_unregister_driver(struct pnp_driver *drv) { driver_unregister(&drv->driver); - pnp_dbg("the driver '%s' has been unregistered", drv->name); } /** diff --git a/drivers/pnp/isapnp/Makefile b/drivers/pnp/isapnp/Makefile index 3e38f06f8d7..cac18bbfb81 100644 --- a/drivers/pnp/isapnp/Makefile +++ b/drivers/pnp/isapnp/Makefile @@ -5,7 +5,3 @@ isapnp-proc-$(CONFIG_PROC_FS) = proc.o obj-y := core.o compat.o $(isapnp-proc-y) - -ifeq ($(CONFIG_PNP_DEBUG),y) -EXTRA_CFLAGS += -DDEBUG -endif diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index 46455fbab6d..e851160e14f 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -901,7 +901,7 @@ static int isapnp_get_resources(struct pnp_dev *dev) { int i, ret; - dev_dbg(&dev->dev, "get resources\n"); + pnp_dbg(&dev->dev, "get resources\n"); pnp_init_resources(dev); isapnp_cfg_begin(dev->card->number, dev->number); dev->active = isapnp_read_byte(ISAPNP_CFG_ACTIVATE); @@ -939,13 +939,13 @@ static int isapnp_set_resources(struct pnp_dev *dev) struct resource *res; int tmp; - dev_dbg(&dev->dev, "set resources\n"); + pnp_dbg(&dev->dev, "set resources\n"); isapnp_cfg_begin(dev->card->number, dev->number); dev->active = 1; for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) { res = pnp_get_resource(dev, IORESOURCE_IO, tmp); if (pnp_resource_enabled(res)) { - dev_dbg(&dev->dev, " set io %d to %#llx\n", + pnp_dbg(&dev->dev, " set io %d to %#llx\n", tmp, (unsigned long long) res->start); isapnp_write_word(ISAPNP_CFG_PORT + (tmp << 1), res->start); @@ -957,14 +957,14 @@ static int isapnp_set_resources(struct pnp_dev *dev) int irq = res->start; if (irq == 2) irq = 9; - dev_dbg(&dev->dev, " set irq %d to %d\n", tmp, irq); + pnp_dbg(&dev->dev, " set irq %d to %d\n", tmp, irq); isapnp_write_byte(ISAPNP_CFG_IRQ + (tmp << 1), irq); } } for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) { res = pnp_get_resource(dev, IORESOURCE_DMA, tmp); if (pnp_resource_enabled(res)) { - dev_dbg(&dev->dev, " set dma %d to %lld\n", + pnp_dbg(&dev->dev, " set dma %d to %lld\n", tmp, (unsigned long long) res->start); isapnp_write_byte(ISAPNP_CFG_DMA + tmp, res->start); } @@ -972,7 +972,7 @@ static int isapnp_set_resources(struct pnp_dev *dev) for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) { res = pnp_get_resource(dev, IORESOURCE_MEM, tmp); if (pnp_resource_enabled(res)) { - dev_dbg(&dev->dev, " set mem %d to %#llx\n", + pnp_dbg(&dev->dev, " set mem %d to %#llx\n", tmp, (unsigned long long) res->start); isapnp_write_word(ISAPNP_CFG_MEM + (tmp << 3), (res->start >> 8) & 0xffff); diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index b526eaad3f6..00fd3577b98 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c @@ -25,7 +25,7 @@ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) res = pnp_get_resource(dev, IORESOURCE_IO, idx); if (res) { - dev_dbg(&dev->dev, " io %d already set to %#llx-%#llx " + pnp_dbg(&dev->dev, " io %d already set to %#llx-%#llx " "flags %#lx\n", idx, (unsigned long long) res->start, (unsigned long long) res->end, res->flags); return 0; @@ -38,7 +38,7 @@ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) if (!rule->size) { res->flags |= IORESOURCE_DISABLED; - dev_dbg(&dev->dev, " io %d disabled\n", idx); + pnp_dbg(&dev->dev, " io %d disabled\n", idx); goto __add; } @@ -49,7 +49,7 @@ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) res->start += rule->align; res->end = res->start + rule->size - 1; if (res->start > rule->max || !rule->align) { - dev_dbg(&dev->dev, " couldn't assign io %d " + pnp_dbg(&dev->dev, " couldn't assign io %d " "(min %#llx max %#llx)\n", idx, (unsigned long long) rule->min, (unsigned long long) rule->max); @@ -68,7 +68,7 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) res = pnp_get_resource(dev, IORESOURCE_MEM, idx); if (res) { - dev_dbg(&dev->dev, " mem %d already set to %#llx-%#llx " + pnp_dbg(&dev->dev, " mem %d already set to %#llx-%#llx " "flags %#lx\n", idx, (unsigned long long) res->start, (unsigned long long) res->end, res->flags); return 0; @@ -90,7 +90,7 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) if (!rule->size) { res->flags |= IORESOURCE_DISABLED; - dev_dbg(&dev->dev, " mem %d disabled\n", idx); + pnp_dbg(&dev->dev, " mem %d disabled\n", idx); goto __add; } @@ -101,7 +101,7 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) res->start += rule->align; res->end = res->start + rule->size - 1; if (res->start > rule->max || !rule->align) { - dev_dbg(&dev->dev, " couldn't assign mem %d " + pnp_dbg(&dev->dev, " couldn't assign mem %d " "(min %#llx max %#llx)\n", idx, (unsigned long long) rule->min, (unsigned long long) rule->max); @@ -126,7 +126,7 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) res = pnp_get_resource(dev, IORESOURCE_IRQ, idx); if (res) { - dev_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n", + pnp_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n", idx, (int) res->start, res->flags); return 0; } @@ -138,7 +138,7 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) if (bitmap_empty(rule->map.bits, PNP_IRQ_NR)) { res->flags |= IORESOURCE_DISABLED; - dev_dbg(&dev->dev, " irq %d disabled\n", idx); + pnp_dbg(&dev->dev, " irq %d disabled\n", idx); goto __add; } @@ -160,11 +160,11 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) res->start = -1; res->end = -1; res->flags |= IORESOURCE_DISABLED; - dev_dbg(&dev->dev, " irq %d disabled (optional)\n", idx); + pnp_dbg(&dev->dev, " irq %d disabled (optional)\n", idx); goto __add; } - dev_dbg(&dev->dev, " couldn't assign irq %d\n", idx); + pnp_dbg(&dev->dev, " couldn't assign irq %d\n", idx); return -EBUSY; __add: @@ -184,7 +184,7 @@ static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) res = pnp_get_resource(dev, IORESOURCE_DMA, idx); if (res) { - dev_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n", + pnp_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n", idx, (int) res->start, res->flags); return 0; } @@ -205,7 +205,7 @@ static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) res->start = res->end = MAX_DMA_CHANNELS; #endif res->flags |= IORESOURCE_DISABLED; - dev_dbg(&dev->dev, " disable dma %d\n", idx); + pnp_dbg(&dev->dev, " disable dma %d\n", idx); __add: pnp_add_dma_resource(dev, res->start, res->flags); @@ -238,7 +238,7 @@ static int pnp_assign_resources(struct pnp_dev *dev, int set) int nport = 0, nmem = 0, nirq = 0, ndma = 0; int ret = 0; - dev_dbg(&dev->dev, "pnp_assign_resources, try dependent set %d\n", set); + pnp_dbg(&dev->dev, "pnp_assign_resources, try dependent set %d\n", set); mutex_lock(&pnp_res_mutex); pnp_clean_resource_table(dev); @@ -270,7 +270,7 @@ static int pnp_assign_resources(struct pnp_dev *dev, int set) mutex_unlock(&pnp_res_mutex); if (ret < 0) { - dev_dbg(&dev->dev, "pnp_assign_resources failed (%d)\n", ret); + pnp_dbg(&dev->dev, "pnp_assign_resources failed (%d)\n", ret); pnp_clean_resource_table(dev); } else dbg_pnp_show_resources(dev, "pnp_assign_resources succeeded"); @@ -286,7 +286,7 @@ int pnp_auto_config_dev(struct pnp_dev *dev) int i, ret; if (!pnp_can_configure(dev)) { - dev_dbg(&dev->dev, "configuration not supported\n"); + pnp_dbg(&dev->dev, "configuration not supported\n"); return -ENODEV; } @@ -313,7 +313,7 @@ int pnp_auto_config_dev(struct pnp_dev *dev) int pnp_start_dev(struct pnp_dev *dev) { if (!pnp_can_write(dev)) { - dev_dbg(&dev->dev, "activation not supported\n"); + pnp_dbg(&dev->dev, "activation not supported\n"); return -EINVAL; } @@ -336,7 +336,7 @@ int pnp_start_dev(struct pnp_dev *dev) int pnp_stop_dev(struct pnp_dev *dev) { if (!pnp_can_disable(dev)) { - dev_dbg(&dev->dev, "disabling not supported\n"); + pnp_dbg(&dev->dev, "disabling not supported\n"); return -EINVAL; } if (dev->protocol->disable(dev) < 0) { diff --git a/drivers/pnp/pnpacpi/Makefile b/drivers/pnp/pnpacpi/Makefile index 2d7a1e6908b..905326fcca8 100644 --- a/drivers/pnp/pnpacpi/Makefile +++ b/drivers/pnp/pnpacpi/Makefile @@ -3,7 +3,3 @@ # obj-y := core.o rsparser.o - -ifeq ($(CONFIG_PNP_DEBUG),y) -EXTRA_CFLAGS += -DDEBUG -endif diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 53561d72b4e..383e47c392a 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -75,7 +75,7 @@ static int __init ispnpidacpi(char *id) static int pnpacpi_get_resources(struct pnp_dev *dev) { - dev_dbg(&dev->dev, "get resources\n"); + pnp_dbg(&dev->dev, "get resources\n"); return pnpacpi_parse_allocated_resource(dev); } @@ -86,7 +86,7 @@ static int pnpacpi_set_resources(struct pnp_dev *dev) int ret; acpi_status status; - dev_dbg(&dev->dev, "set resources\n"); + pnp_dbg(&dev->dev, "set resources\n"); ret = pnpacpi_build_resource_template(dev, &buffer); if (ret) return ret; @@ -148,9 +148,13 @@ static int __init pnpacpi_add_device(struct acpi_device *device) acpi_status status; struct pnp_dev *dev; + /* + * If a PnPacpi device is not present , the device + * driver should not be loaded. + */ status = acpi_get_handle(device->handle, "_CRS", &temp); if (ACPI_FAILURE(status) || !ispnpidacpi(acpi_device_hid(device)) || - is_exclusive_device(device)) + is_exclusive_device(device) || (!device->status.present)) return 0; dev = pnp_alloc_dev(&pnpacpi_protocol, num, acpi_device_hid(device)); @@ -255,14 +259,14 @@ int pnpacpi_disabled __initdata; static int __init pnpacpi_init(void) { if (acpi_disabled || pnpacpi_disabled) { - pnp_info("PnP ACPI: disabled"); + printk(KERN_INFO "pnp: PnP ACPI: disabled\n"); return 0; } - pnp_info("PnP ACPI init"); + printk(KERN_INFO "pnp: PnP ACPI init\n"); pnp_register_protocol(&pnpacpi_protocol); register_acpi_bus_type(&acpi_pnp_bus); acpi_get_devices(NULL, pnpacpi_add_device_handler, NULL, NULL); - pnp_info("PnP ACPI: found %d devices", num); + printk(KERN_INFO "pnp: PnP ACPI: found %d devices\n", num); unregister_acpi_bus_type(&acpi_pnp_bus); pnp_platform_devices = 1; return 0; diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 95015cbfd33..adf17856bac 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -132,7 +132,8 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev, pnp_add_irq_resource(dev, irq, flags); } -static int dma_flags(int type, int bus_master, int transfer) +static int dma_flags(struct pnp_dev *dev, int type, int bus_master, + int transfer) { int flags = 0; @@ -154,7 +155,7 @@ static int dma_flags(int type, int bus_master, int transfer) default: /* Set a default value ? */ flags |= IORESOURCE_DMA_COMPATIBLE; - pnp_err("Invalid DMA type"); + dev_err(&dev->dev, "invalid DMA type %d\n", type); } switch (transfer) { case ACPI_TRANSFER_8: @@ -169,7 +170,7 @@ static int dma_flags(int type, int bus_master, int transfer) default: /* Set a default value ? */ flags |= IORESOURCE_DMA_8AND16BIT; - pnp_err("Invalid DMA transfer type"); + dev_err(&dev->dev, "invalid DMA transfer type %d\n", transfer); } return flags; @@ -336,7 +337,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, case ACPI_RESOURCE_TYPE_DMA: dma = &res->data.dma; if (dma->channel_count > 0 && dma->channels[0] != (u8) -1) - flags = dma_flags(dma->type, dma->bus_master, + flags = dma_flags(dev, dma->type, dma->bus_master, dma->transfer); else flags = IORESOURCE_DISABLED; @@ -449,7 +450,7 @@ int pnpacpi_parse_allocated_resource(struct pnp_dev *dev) acpi_handle handle = dev->data; acpi_status status; - dev_dbg(&dev->dev, "parse allocated resources\n"); + pnp_dbg(&dev->dev, "parse allocated resources\n"); pnp_init_resources(dev); @@ -477,7 +478,7 @@ static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev, for (i = 0; i < p->channel_count; i++) map |= 1 << p->channels[i]; - flags = dma_flags(p->type, p->bus_master, p->transfer); + flags = dma_flags(dev, p->type, p->bus_master, p->transfer); pnp_register_dma_resource(dev, option_flags, map, flags); } @@ -608,8 +609,8 @@ static __init void pnpacpi_parse_address_option(struct pnp_dev *dev, unsigned char flags = 0; status = acpi_resource_to_address64(r, p); - if (!ACPI_SUCCESS(status)) { - pnp_warn("PnPACPI: failed to convert resource type %d", + if (ACPI_FAILURE(status)) { + dev_warn(&dev->dev, "can't convert resource type %d\n", r->type); return; } @@ -735,7 +736,7 @@ int __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev) acpi_status status; struct acpipnp_parse_option_s parse_data; - dev_dbg(&dev->dev, "parse resource options\n"); + pnp_dbg(&dev->dev, "parse resource options\n"); parse_data.dev = dev; parse_data.option_flags = 0; @@ -843,7 +844,7 @@ static void pnpacpi_encode_irq(struct pnp_dev *dev, if (!pnp_resource_enabled(p)) { irq->interrupt_count = 0; - dev_dbg(&dev->dev, " encode irq (%s)\n", + pnp_dbg(&dev->dev, " encode irq (%s)\n", p ? "disabled" : "missing"); return; } @@ -855,7 +856,7 @@ static void pnpacpi_encode_irq(struct pnp_dev *dev, irq->interrupt_count = 1; irq->interrupts[0] = p->start; - dev_dbg(&dev->dev, " encode irq %d %s %s %s (%d-byte descriptor)\n", + pnp_dbg(&dev->dev, " encode irq %d %s %s %s (%d-byte descriptor)\n", (int) p->start, triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge", polarity == ACPI_ACTIVE_LOW ? "low" : "high", @@ -872,7 +873,7 @@ static void pnpacpi_encode_ext_irq(struct pnp_dev *dev, if (!pnp_resource_enabled(p)) { extended_irq->interrupt_count = 0; - dev_dbg(&dev->dev, " encode extended irq (%s)\n", + pnp_dbg(&dev->dev, " encode extended irq (%s)\n", p ? "disabled" : "missing"); return; } @@ -885,7 +886,7 @@ static void pnpacpi_encode_ext_irq(struct pnp_dev *dev, extended_irq->interrupt_count = 1; extended_irq->interrupts[0] = p->start; - dev_dbg(&dev->dev, " encode irq %d %s %s %s\n", (int) p->start, + pnp_dbg(&dev->dev, " encode irq %d %s %s %s\n", (int) p->start, triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge", polarity == ACPI_ACTIVE_LOW ? "low" : "high", extended_irq->sharable == ACPI_SHARED ? "shared" : "exclusive"); @@ -899,7 +900,7 @@ static void pnpacpi_encode_dma(struct pnp_dev *dev, if (!pnp_resource_enabled(p)) { dma->channel_count = 0; - dev_dbg(&dev->dev, " encode dma (%s)\n", + pnp_dbg(&dev->dev, " encode dma (%s)\n", p ? "disabled" : "missing"); return; } @@ -934,7 +935,7 @@ static void pnpacpi_encode_dma(struct pnp_dev *dev, dma->channel_count = 1; dma->channels[0] = p->start; - dev_dbg(&dev->dev, " encode dma %d " + pnp_dbg(&dev->dev, " encode dma %d " "type %#x transfer %#x master %d\n", (int) p->start, dma->type, dma->transfer, dma->bus_master); } @@ -958,7 +959,7 @@ static void pnpacpi_encode_io(struct pnp_dev *dev, io->address_length = 0; } - dev_dbg(&dev->dev, " encode io %#x-%#x decode %#x\n", io->minimum, + pnp_dbg(&dev->dev, " encode io %#x-%#x decode %#x\n", io->minimum, io->minimum + io->address_length - 1, io->io_decode); } @@ -976,7 +977,7 @@ static void pnpacpi_encode_fixed_io(struct pnp_dev *dev, fixed_io->address_length = 0; } - dev_dbg(&dev->dev, " encode fixed_io %#x-%#x\n", fixed_io->address, + pnp_dbg(&dev->dev, " encode fixed_io %#x-%#x\n", fixed_io->address, fixed_io->address + fixed_io->address_length - 1); } @@ -999,7 +1000,7 @@ static void pnpacpi_encode_mem24(struct pnp_dev *dev, memory24->address_length = 0; } - dev_dbg(&dev->dev, " encode mem24 %#x-%#x write_protect %#x\n", + pnp_dbg(&dev->dev, " encode mem24 %#x-%#x write_protect %#x\n", memory24->minimum, memory24->minimum + memory24->address_length - 1, memory24->write_protect); @@ -1023,7 +1024,7 @@ static void pnpacpi_encode_mem32(struct pnp_dev *dev, memory32->alignment = 0; } - dev_dbg(&dev->dev, " encode mem32 %#x-%#x write_protect %#x\n", + pnp_dbg(&dev->dev, " encode mem32 %#x-%#x write_protect %#x\n", memory32->minimum, memory32->minimum + memory32->address_length - 1, memory32->write_protect); @@ -1046,7 +1047,7 @@ static void pnpacpi_encode_fixed_mem32(struct pnp_dev *dev, fixed_memory32->address_length = 0; } - dev_dbg(&dev->dev, " encode fixed_mem32 %#x-%#x write_protect %#x\n", + pnp_dbg(&dev->dev, " encode fixed_mem32 %#x-%#x write_protect %#x\n", fixed_memory32->address, fixed_memory32->address + fixed_memory32->address_length - 1, fixed_memory32->write_protect); @@ -1060,7 +1061,7 @@ int pnpacpi_encode_resources(struct pnp_dev *dev, struct acpi_buffer *buffer) struct acpi_resource *resource = buffer->pointer; int port = 0, irq = 0, dma = 0, mem = 0; - dev_dbg(&dev->dev, "encode %d resources\n", res_cnt); + pnp_dbg(&dev->dev, "encode %d resources\n", res_cnt); while (i < res_cnt) { switch (resource->type) { case ACPI_RESOURCE_TYPE_IRQ: diff --git a/drivers/pnp/pnpbios/Makefile b/drivers/pnp/pnpbios/Makefile index 310e2b3a771..3cd3ed76060 100644 --- a/drivers/pnp/pnpbios/Makefile +++ b/drivers/pnp/pnpbios/Makefile @@ -5,7 +5,3 @@ pnpbios-proc-$(CONFIG_PNPBIOS_PROC_FS) = proc.o obj-y := core.o bioscalls.o rsparser.o $(pnpbios-proc-y) - -ifeq ($(CONFIG_PNP_DEBUG),y) -EXTRA_CFLAGS += -DDEBUG -endif diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c index 2bfe13369df..996f6483807 100644 --- a/drivers/pnp/pnpbios/core.c +++ b/drivers/pnp/pnpbios/core.c @@ -211,7 +211,7 @@ static int pnpbios_get_resources(struct pnp_dev *dev) if (!pnpbios_is_dynamic(dev)) return -EPERM; - dev_dbg(&dev->dev, "get resources\n"); + pnp_dbg(&dev->dev, "get resources\n"); node = kzalloc(node_info.max_node_size, GFP_KERNEL); if (!node) return -1; @@ -234,7 +234,7 @@ static int pnpbios_set_resources(struct pnp_dev *dev) if (!pnpbios_is_dynamic(dev)) return -EPERM; - dev_dbg(&dev->dev, "set resources\n"); + pnp_dbg(&dev->dev, "set resources\n"); node = kzalloc(node_info.max_node_size, GFP_KERNEL); if (!node) return -1; diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c index ca567671379..87b4f49a525 100644 --- a/drivers/pnp/pnpbios/rsparser.c +++ b/drivers/pnp/pnpbios/rsparser.c @@ -87,7 +87,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(struct pnp_dev *dev, if (!p) return NULL; - dev_dbg(&dev->dev, "parse allocated resources\n"); + pnp_dbg(&dev->dev, "parse allocated resources\n"); pnp_init_resources(dev); @@ -324,7 +324,7 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, if (!p) return NULL; - dev_dbg(&dev->dev, "parse resource options\n"); + pnp_dbg(&dev->dev, "parse resource options\n"); option_flags = 0; while ((char *)p < (char *)end) { @@ -519,7 +519,7 @@ static void pnpbios_encode_mem(struct pnp_dev *dev, unsigned char *p, p[10] = (len >> 8) & 0xff; p[11] = ((len >> 8) >> 8) & 0xff; - dev_dbg(&dev->dev, " encode mem %#lx-%#lx\n", base, base + len - 1); + pnp_dbg(&dev->dev, " encode mem %#lx-%#lx\n", base, base + len - 1); } static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p, @@ -549,7 +549,7 @@ static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p, p[18] = (len >> 16) & 0xff; p[19] = (len >> 24) & 0xff; - dev_dbg(&dev->dev, " encode mem32 %#lx-%#lx\n", base, base + len - 1); + pnp_dbg(&dev->dev, " encode mem32 %#lx-%#lx\n", base, base + len - 1); } static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p, @@ -575,7 +575,7 @@ static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p, p[10] = (len >> 16) & 0xff; p[11] = (len >> 24) & 0xff; - dev_dbg(&dev->dev, " encode fixed_mem32 %#lx-%#lx\n", base, + pnp_dbg(&dev->dev, " encode fixed_mem32 %#lx-%#lx\n", base, base + len - 1); } @@ -592,7 +592,7 @@ static void pnpbios_encode_irq(struct pnp_dev *dev, unsigned char *p, p[1] = map & 0xff; p[2] = (map >> 8) & 0xff; - dev_dbg(&dev->dev, " encode irq mask %#lx\n", map); + pnp_dbg(&dev->dev, " encode irq mask %#lx\n", map); } static void pnpbios_encode_dma(struct pnp_dev *dev, unsigned char *p, @@ -607,7 +607,7 @@ static void pnpbios_encode_dma(struct pnp_dev *dev, unsigned char *p, p[1] = map & 0xff; - dev_dbg(&dev->dev, " encode dma mask %#lx\n", map); + pnp_dbg(&dev->dev, " encode dma mask %#lx\n", map); } static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p, @@ -630,7 +630,7 @@ static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p, p[5] = (base >> 8) & 0xff; p[7] = len & 0xff; - dev_dbg(&dev->dev, " encode io %#lx-%#lx\n", base, base + len - 1); + pnp_dbg(&dev->dev, " encode io %#lx-%#lx\n", base, base + len - 1); } static void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p, @@ -651,7 +651,7 @@ static void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p, p[2] = (base >> 8) & 0xff; p[3] = len & 0xff; - dev_dbg(&dev->dev, " encode fixed_io %#lx-%#lx\n", base, + pnp_dbg(&dev->dev, " encode fixed_io %#lx-%#lx\n", base, base + len - 1); } diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c index c144bd57561..8473fe5ed7f 100644 --- a/drivers/pnp/quirks.c +++ b/drivers/pnp/quirks.c @@ -337,9 +337,8 @@ void pnp_fixup_device(struct pnp_dev *dev) for (f = pnp_fixups; *f->id; f++) { if (!compare_pnp_id(dev->id, f->id)) continue; -#ifdef DEBUG - dev_dbg(&dev->dev, "%s: calling %pF\n", f->id, f->quirk_function); -#endif + pnp_dbg(&dev->dev, "%s: calling %pF\n", f->id, + f->quirk_function); f->quirk_function(dev); } } diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index dbae23acdd5..f604061d2bb 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -294,7 +294,7 @@ static int pci_dev_uses_irq(struct pnp_dev *pnp, struct pci_dev *pci, u8 progif; if (pci->irq == irq) { - dev_dbg(&pnp->dev, "device %s using irq %d\n", + pnp_dbg(&pnp->dev, " device %s using irq %d\n", pci_name(pci), irq); return 1; } @@ -316,7 +316,7 @@ static int pci_dev_uses_irq(struct pnp_dev *pnp, struct pci_dev *pci, if ((progif & 0x5) != 0x5) if (pci_get_legacy_ide_irq(pci, 0) == irq || pci_get_legacy_ide_irq(pci, 1) == irq) { - dev_dbg(&pnp->dev, "legacy IDE device %s " + pnp_dbg(&pnp->dev, " legacy IDE device %s " "using irq %d\n", pci_name(pci), irq); return 1; } @@ -517,7 +517,7 @@ struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, res->start = irq; res->end = irq; - dev_dbg(&dev->dev, " add irq %d flags %#x\n", irq, flags); + pnp_dbg(&dev->dev, " add irq %d flags %#x\n", irq, flags); return pnp_res; } @@ -538,7 +538,7 @@ struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma, res->start = dma; res->end = dma; - dev_dbg(&dev->dev, " add dma %d flags %#x\n", dma, flags); + pnp_dbg(&dev->dev, " add dma %d flags %#x\n", dma, flags); return pnp_res; } @@ -562,7 +562,7 @@ struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev, res->start = start; res->end = end; - dev_dbg(&dev->dev, " add io %#llx-%#llx flags %#x\n", + pnp_dbg(&dev->dev, " add io %#llx-%#llx flags %#x\n", (unsigned long long) start, (unsigned long long) end, flags); return pnp_res; } @@ -587,7 +587,7 @@ struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev, res->start = start; res->end = end; - dev_dbg(&dev->dev, " add mem %#llx-%#llx flags %#x\n", + pnp_dbg(&dev->dev, " add mem %#llx-%#llx flags %#x\n", (unsigned long long) start, (unsigned long long) end, flags); return pnp_res; } diff --git a/drivers/pnp/support.c b/drivers/pnp/support.c index b42df162071..63087d5ce60 100644 --- a/drivers/pnp/support.c +++ b/drivers/pnp/support.c @@ -75,18 +75,17 @@ char *pnp_resource_type_name(struct resource *res) void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc) { -#ifdef DEBUG char buf[128]; int len; struct pnp_resource *pnp_res; struct resource *res; if (list_empty(&dev->resources)) { - dev_dbg(&dev->dev, "%s: no current resources\n", desc); + pnp_dbg(&dev->dev, "%s: no current resources\n", desc); return; } - dev_dbg(&dev->dev, "%s: current resources:\n", desc); + pnp_dbg(&dev->dev, "%s: current resources:\n", desc); list_for_each_entry(pnp_res, &dev->resources, list) { res = &pnp_res->res; len = 0; @@ -95,7 +94,7 @@ void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc) pnp_resource_type_name(res)); if (res->flags & IORESOURCE_DISABLED) { - dev_dbg(&dev->dev, "%sdisabled\n", buf); + pnp_dbg(&dev->dev, "%sdisabled\n", buf); continue; } @@ -116,9 +115,8 @@ void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc) res->flags); break; } - dev_dbg(&dev->dev, "%s\n", buf); + pnp_dbg(&dev->dev, "%s\n", buf); } -#endif } char *pnp_option_priority_name(struct pnp_option *option) @@ -136,7 +134,6 @@ char *pnp_option_priority_name(struct pnp_option *option) void dbg_pnp_show_option(struct pnp_dev *dev, struct pnp_option *option) { -#ifdef DEBUG char buf[128]; int len = 0, i; struct pnp_port *port; @@ -208,6 +205,5 @@ void dbg_pnp_show_option(struct pnp_dev *dev, struct pnp_option *option) "flags %#x", dma->map, dma->flags); break; } - dev_dbg(&dev->dev, "%s\n", buf); -#endif + pnp_dbg(&dev->dev, "%s\n", buf); } |