diff options
Diffstat (limited to 'drivers')
57 files changed, 1805 insertions, 280 deletions
diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c index 1022e38994c2..0f2805899210 100644 --- a/drivers/acpi/dispatcher/dsobject.c +++ b/drivers/acpi/dispatcher/dsobject.c | |||
@@ -496,7 +496,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, | |||
496 | arg = arg->common.next; | 496 | arg = arg->common.next; |
497 | } | 497 | } |
498 | 498 | ||
499 | ACPI_ERROR((AE_INFO, | 499 | ACPI_WARNING((AE_INFO, |
500 | "Package List length (%X) larger than NumElements count (%X), truncated\n", | 500 | "Package List length (%X) larger than NumElements count (%X), truncated\n", |
501 | i, element_count)); | 501 | i, element_count)); |
502 | } else if (i < element_count) { | 502 | } else if (i < element_count) { |
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index bb7c51f712bd..7d2edf143f16 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c | |||
@@ -563,9 +563,6 @@ EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device); | |||
563 | */ | 563 | */ |
564 | static int handle_eject_request(struct dock_station *ds, u32 event) | 564 | static int handle_eject_request(struct dock_station *ds, u32 event) |
565 | { | 565 | { |
566 | if (!dock_present(ds)) | ||
567 | return -ENODEV; | ||
568 | |||
569 | if (dock_in_progress(ds)) | 566 | if (dock_in_progress(ds)) |
570 | return -EBUSY; | 567 | return -EBUSY; |
571 | 568 | ||
@@ -573,8 +570,16 @@ static int handle_eject_request(struct dock_station *ds, u32 event) | |||
573 | * here we need to generate the undock | 570 | * here we need to generate the undock |
574 | * event prior to actually doing the undock | 571 | * event prior to actually doing the undock |
575 | * so that the device struct still exists. | 572 | * so that the device struct still exists. |
573 | * Also, even send the dock event if the | ||
574 | * device is not present anymore | ||
576 | */ | 575 | */ |
577 | dock_event(ds, event, UNDOCK_EVENT); | 576 | dock_event(ds, event, UNDOCK_EVENT); |
577 | |||
578 | if (!dock_present(ds)) { | ||
579 | complete_undock(ds); | ||
580 | return -ENODEV; | ||
581 | } | ||
582 | |||
578 | hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST); | 583 | hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST); |
579 | undock(ds); | 584 | undock(ds); |
580 | eject_dock(ds); | 585 | eject_dock(ds); |
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 5622aee996b2..13593f9f2197 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
@@ -110,6 +110,31 @@ static struct acpi_ec { | |||
110 | u8 handlers_installed; | 110 | u8 handlers_installed; |
111 | } *boot_ec, *first_ec; | 111 | } *boot_ec, *first_ec; |
112 | 112 | ||
113 | /* | ||
114 | * Some Asus system have exchanged ECDT data/command IO addresses. | ||
115 | */ | ||
116 | static int print_ecdt_error(const struct dmi_system_id *id) | ||
117 | { | ||
118 | printk(KERN_NOTICE PREFIX "%s detected - " | ||
119 | "ECDT has exchanged control/data I/O address\n", | ||
120 | id->ident); | ||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static struct dmi_system_id __cpuinitdata ec_dmi_table[] = { | ||
125 | { | ||
126 | print_ecdt_error, "Asus L4R", { | ||
127 | DMI_MATCH(DMI_BIOS_VERSION, "1008.006"), | ||
128 | DMI_MATCH(DMI_PRODUCT_NAME, "L4R"), | ||
129 | DMI_MATCH(DMI_BOARD_NAME, "L4R") }, NULL}, | ||
130 | { | ||
131 | print_ecdt_error, "Asus M6R", { | ||
132 | DMI_MATCH(DMI_BIOS_VERSION, "0207"), | ||
133 | DMI_MATCH(DMI_PRODUCT_NAME, "M6R"), | ||
134 | DMI_MATCH(DMI_BOARD_NAME, "M6R") }, NULL}, | ||
135 | {}, | ||
136 | }; | ||
137 | |||
113 | /* -------------------------------------------------------------------------- | 138 | /* -------------------------------------------------------------------------- |
114 | Transaction Management | 139 | Transaction Management |
115 | -------------------------------------------------------------------------- */ | 140 | -------------------------------------------------------------------------- */ |
@@ -196,6 +221,8 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) | |||
196 | return 0; | 221 | return 0; |
197 | msleep(1); | 222 | msleep(1); |
198 | } | 223 | } |
224 | if (acpi_ec_check_status(ec,event)) | ||
225 | return 0; | ||
199 | } | 226 | } |
200 | pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n", | 227 | pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n", |
201 | acpi_ec_read_status(ec), | 228 | acpi_ec_read_status(ec), |
@@ -911,6 +938,15 @@ int __init acpi_ec_ecdt_probe(void) | |||
911 | pr_info(PREFIX "EC description table is found, configuring boot EC\n"); | 938 | pr_info(PREFIX "EC description table is found, configuring boot EC\n"); |
912 | boot_ec->command_addr = ecdt_ptr->control.address; | 939 | boot_ec->command_addr = ecdt_ptr->control.address; |
913 | boot_ec->data_addr = ecdt_ptr->data.address; | 940 | boot_ec->data_addr = ecdt_ptr->data.address; |
941 | if (dmi_check_system(ec_dmi_table)) { | ||
942 | /* | ||
943 | * If the board falls into ec_dmi_table, it means | ||
944 | * that ECDT table gives the incorrect command/status | ||
945 | * & data I/O address. Just fix it. | ||
946 | */ | ||
947 | boot_ec->data_addr = ecdt_ptr->control.address; | ||
948 | boot_ec->command_addr = ecdt_ptr->data.address; | ||
949 | } | ||
914 | boot_ec->gpe = ecdt_ptr->gpe; | 950 | boot_ec->gpe = ecdt_ptr->gpe; |
915 | boot_ec->handle = ACPI_ROOT_OBJECT; | 951 | boot_ec->handle = ACPI_ROOT_OBJECT; |
916 | acpi_get_handle(ACPI_ROOT_OBJECT, ecdt_ptr->id, &boot_ec->handle); | 952 | acpi_get_handle(ACPI_ROOT_OBJECT, ecdt_ptr->id, &boot_ec->handle); |
diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index 2a32c843cb4a..8892b9824fae 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c | |||
@@ -479,5 +479,8 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) | |||
479 | 479 | ||
480 | acpi_tb_set_table_loaded_flag(table_index, FALSE); | 480 | acpi_tb_set_table_loaded_flag(table_index, FALSE); |
481 | 481 | ||
482 | /* Table unloaded, remove a reference to the ddb_handle object */ | ||
483 | |||
484 | acpi_ut_remove_reference(ddb_handle); | ||
482 | return_ACPI_STATUS(AE_OK); | 485 | return_ACPI_STATUS(AE_OK); |
483 | } | 486 | } |
diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c index 549db42f16cf..bd5773878009 100644 --- a/drivers/acpi/namespace/nsnames.c +++ b/drivers/acpi/namespace/nsnames.c | |||
@@ -56,13 +56,14 @@ ACPI_MODULE_NAME("nsnames") | |||
56 | * Size - Size of the pathname | 56 | * Size - Size of the pathname |
57 | * *name_buffer - Where to return the pathname | 57 | * *name_buffer - Where to return the pathname |
58 | * | 58 | * |
59 | * RETURN: Places the pathname into the name_buffer, in external format | 59 | * RETURN: Status |
60 | * Places the pathname into the name_buffer, in external format | ||
60 | * (name segments separated by path separators) | 61 | * (name segments separated by path separators) |
61 | * | 62 | * |
62 | * DESCRIPTION: Generate a full pathaname | 63 | * DESCRIPTION: Generate a full pathaname |
63 | * | 64 | * |
64 | ******************************************************************************/ | 65 | ******************************************************************************/ |
65 | void | 66 | acpi_status |
66 | acpi_ns_build_external_path(struct acpi_namespace_node *node, | 67 | acpi_ns_build_external_path(struct acpi_namespace_node *node, |
67 | acpi_size size, char *name_buffer) | 68 | acpi_size size, char *name_buffer) |
68 | { | 69 | { |
@@ -77,7 +78,7 @@ acpi_ns_build_external_path(struct acpi_namespace_node *node, | |||
77 | if (index < ACPI_NAME_SIZE) { | 78 | if (index < ACPI_NAME_SIZE) { |
78 | name_buffer[0] = AML_ROOT_PREFIX; | 79 | name_buffer[0] = AML_ROOT_PREFIX; |
79 | name_buffer[1] = 0; | 80 | name_buffer[1] = 0; |
80 | return; | 81 | return (AE_OK); |
81 | } | 82 | } |
82 | 83 | ||
83 | /* Store terminator byte, then build name backwards */ | 84 | /* Store terminator byte, then build name backwards */ |
@@ -105,11 +106,13 @@ acpi_ns_build_external_path(struct acpi_namespace_node *node, | |||
105 | 106 | ||
106 | if (index != 0) { | 107 | if (index != 0) { |
107 | ACPI_ERROR((AE_INFO, | 108 | ACPI_ERROR((AE_INFO, |
108 | "Could not construct pathname; index=%X, size=%X, Path=%s", | 109 | "Could not construct external pathname; index=%X, size=%X, Path=%s", |
109 | (u32) index, (u32) size, &name_buffer[size])); | 110 | (u32) index, (u32) size, &name_buffer[size])); |
111 | |||
112 | return (AE_BAD_PARAMETER); | ||
110 | } | 113 | } |
111 | 114 | ||
112 | return; | 115 | return (AE_OK); |
113 | } | 116 | } |
114 | 117 | ||
115 | #ifdef ACPI_DEBUG_OUTPUT | 118 | #ifdef ACPI_DEBUG_OUTPUT |
@@ -129,6 +132,7 @@ acpi_ns_build_external_path(struct acpi_namespace_node *node, | |||
129 | 132 | ||
130 | char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node) | 133 | char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node) |
131 | { | 134 | { |
135 | acpi_status status; | ||
132 | char *name_buffer; | 136 | char *name_buffer; |
133 | acpi_size size; | 137 | acpi_size size; |
134 | 138 | ||
@@ -138,8 +142,7 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node) | |||
138 | 142 | ||
139 | size = acpi_ns_get_pathname_length(node); | 143 | size = acpi_ns_get_pathname_length(node); |
140 | if (!size) { | 144 | if (!size) { |
141 | ACPI_ERROR((AE_INFO, "Invalid node failure")); | 145 | return (NULL); |
142 | return_PTR(NULL); | ||
143 | } | 146 | } |
144 | 147 | ||
145 | /* Allocate a buffer to be returned to caller */ | 148 | /* Allocate a buffer to be returned to caller */ |
@@ -152,7 +155,11 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node) | |||
152 | 155 | ||
153 | /* Build the path in the allocated buffer */ | 156 | /* Build the path in the allocated buffer */ |
154 | 157 | ||
155 | acpi_ns_build_external_path(node, size, name_buffer); | 158 | status = acpi_ns_build_external_path(node, size, name_buffer); |
159 | if (ACPI_FAILURE(status)) { | ||
160 | return (NULL); | ||
161 | } | ||
162 | |||
156 | return_PTR(name_buffer); | 163 | return_PTR(name_buffer); |
157 | } | 164 | } |
158 | #endif | 165 | #endif |
@@ -186,7 +193,7 @@ acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node) | |||
186 | while (next_node && (next_node != acpi_gbl_root_node)) { | 193 | while (next_node && (next_node != acpi_gbl_root_node)) { |
187 | if (ACPI_GET_DESCRIPTOR_TYPE(next_node) != ACPI_DESC_TYPE_NAMED) { | 194 | if (ACPI_GET_DESCRIPTOR_TYPE(next_node) != ACPI_DESC_TYPE_NAMED) { |
188 | ACPI_ERROR((AE_INFO, | 195 | ACPI_ERROR((AE_INFO, |
189 | "Invalid NS Node (%p) while traversing path", | 196 | "Invalid Namespace Node (%p) while traversing namespace", |
190 | next_node)); | 197 | next_node)); |
191 | return 0; | 198 | return 0; |
192 | } | 199 | } |
@@ -234,8 +241,7 @@ acpi_ns_handle_to_pathname(acpi_handle target_handle, | |||
234 | 241 | ||
235 | required_size = acpi_ns_get_pathname_length(node); | 242 | required_size = acpi_ns_get_pathname_length(node); |
236 | if (!required_size) { | 243 | if (!required_size) { |
237 | ACPI_ERROR((AE_INFO, "Invalid node failure")); | 244 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
238 | return_ACPI_STATUS(AE_ERROR); | ||
239 | } | 245 | } |
240 | 246 | ||
241 | /* Validate/Allocate/Clear caller buffer */ | 247 | /* Validate/Allocate/Clear caller buffer */ |
@@ -247,7 +253,11 @@ acpi_ns_handle_to_pathname(acpi_handle target_handle, | |||
247 | 253 | ||
248 | /* Build the path in the caller buffer */ | 254 | /* Build the path in the caller buffer */ |
249 | 255 | ||
250 | acpi_ns_build_external_path(node, required_size, buffer->pointer); | 256 | status = |
257 | acpi_ns_build_external_path(node, required_size, buffer->pointer); | ||
258 | if (ACPI_FAILURE(status)) { | ||
259 | return_ACPI_STATUS(status); | ||
260 | } | ||
251 | 261 | ||
252 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s [%X]\n", | 262 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s [%X]\n", |
253 | (char *)buffer->pointer, (u32) required_size)); | 263 | (char *)buffer->pointer, (u32) required_size)); |
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 89f3b2abfdc7..cf47805a7448 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c | |||
@@ -849,7 +849,7 @@ static int __init acpi_irq_penalty_update(char *str, int used) | |||
849 | if (irq < 0) | 849 | if (irq < 0) |
850 | continue; | 850 | continue; |
851 | 851 | ||
852 | if (irq >= ACPI_MAX_IRQS) | 852 | if (irq >= ARRAY_SIZE(acpi_irq_penalty)) |
853 | continue; | 853 | continue; |
854 | 854 | ||
855 | if (used) | 855 | if (used) |
@@ -872,10 +872,12 @@ static int __init acpi_irq_penalty_update(char *str, int used) | |||
872 | */ | 872 | */ |
873 | void acpi_penalize_isa_irq(int irq, int active) | 873 | void acpi_penalize_isa_irq(int irq, int active) |
874 | { | 874 | { |
875 | if (active) | 875 | if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) { |
876 | acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED; | 876 | if (active) |
877 | else | 877 | acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED; |
878 | acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING; | 878 | else |
879 | acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING; | ||
880 | } | ||
879 | } | 881 | } |
880 | 882 | ||
881 | /* | 883 | /* |
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index e36422a7122c..ee68ac54c0d4 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c | |||
@@ -123,7 +123,7 @@ struct acpi_processor_errata errata __read_mostly; | |||
123 | static int set_no_mwait(const struct dmi_system_id *id) | 123 | static int set_no_mwait(const struct dmi_system_id *id) |
124 | { | 124 | { |
125 | printk(KERN_NOTICE PREFIX "%s detected - " | 125 | printk(KERN_NOTICE PREFIX "%s detected - " |
126 | "disable mwait for CPU C-stetes\n", id->ident); | 126 | "disabling mwait for CPU C-states\n", id->ident); |
127 | idle_nomwait = 1; | 127 | idle_nomwait = 1; |
128 | return 0; | 128 | return 0; |
129 | } | 129 | } |
@@ -138,7 +138,7 @@ static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = { | |||
138 | { | 138 | { |
139 | set_no_mwait, "Extensa 5220", { | 139 | set_no_mwait, "Extensa 5220", { |
140 | DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), | 140 | DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), |
141 | DMI_MATCH(DMI_SYS_VENDOR, "ACER"), | 141 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
142 | DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), | 142 | DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), |
143 | DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL}, | 143 | DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL}, |
144 | {}, | 144 | {}, |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 283c08f5f4d4..cf5b1b7b684f 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -41,7 +41,6 @@ | |||
41 | #include <linux/pm_qos_params.h> | 41 | #include <linux/pm_qos_params.h> |
42 | #include <linux/clockchips.h> | 42 | #include <linux/clockchips.h> |
43 | #include <linux/cpuidle.h> | 43 | #include <linux/cpuidle.h> |
44 | #include <linux/cpuidle.h> | ||
45 | 44 | ||
46 | /* | 45 | /* |
47 | * Include the apic definitions for x86 to have the APIC timer related defines | 46 | * Include the apic definitions for x86 to have the APIC timer related defines |
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 0133af49cf06..80c251ec6d2a 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c | |||
@@ -70,8 +70,8 @@ static DEFINE_MUTEX(performance_mutex); | |||
70 | * 0 -> cpufreq low level drivers initialized -> consider _PPC values | 70 | * 0 -> cpufreq low level drivers initialized -> consider _PPC values |
71 | * 1 -> ignore _PPC totally -> forced by user through boot param | 71 | * 1 -> ignore _PPC totally -> forced by user through boot param |
72 | */ | 72 | */ |
73 | static unsigned int ignore_ppc = -1; | 73 | static int ignore_ppc = -1; |
74 | module_param(ignore_ppc, uint, 0644); | 74 | module_param(ignore_ppc, int, 0644); |
75 | MODULE_PARM_DESC(ignore_ppc, "If the frequency of your machine gets wrongly" \ | 75 | MODULE_PARM_DESC(ignore_ppc, "If the frequency of your machine gets wrongly" \ |
76 | "limited by BIOS, this should help"); | 76 | "limited by BIOS, this should help"); |
77 | 77 | ||
diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c index f61ebc679e66..d9063ea414e3 100644 --- a/drivers/acpi/resources/rscalc.c +++ b/drivers/acpi/resources/rscalc.c | |||
@@ -587,6 +587,9 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, | |||
587 | } else { | 587 | } else { |
588 | temp_size_needed += | 588 | temp_size_needed += |
589 | acpi_ns_get_pathname_length((*sub_object_list)->reference.node); | 589 | acpi_ns_get_pathname_length((*sub_object_list)->reference.node); |
590 | if (!temp_size_needed) { | ||
591 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
592 | } | ||
590 | } | 593 | } |
591 | } else { | 594 | } else { |
592 | /* | 595 | /* |
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index c3419182c9a7..775c97a282bd 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c | |||
@@ -300,6 +300,8 @@ int __init acpi_table_init(void) | |||
300 | 300 | ||
301 | static int __init acpi_parse_apic_instance(char *str) | 301 | static int __init acpi_parse_apic_instance(char *str) |
302 | { | 302 | { |
303 | if (!str) | ||
304 | return -EINVAL; | ||
303 | 305 | ||
304 | acpi_apic_instance = simple_strtoul(str, NULL, 0); | 306 | acpi_apic_instance = simple_strtoul(str, NULL, 0); |
305 | 307 | ||
diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c index e7bf34a7b1d2..7dcb67e0b215 100644 --- a/drivers/acpi/utilities/utalloc.c +++ b/drivers/acpi/utilities/utalloc.c | |||
@@ -242,10 +242,12 @@ acpi_ut_initialize_buffer(struct acpi_buffer * buffer, | |||
242 | { | 242 | { |
243 | acpi_status status = AE_OK; | 243 | acpi_status status = AE_OK; |
244 | 244 | ||
245 | if (!required_length) { | 245 | /* Parameter validation */ |
246 | WARN_ON(1); | 246 | |
247 | return AE_ERROR; | 247 | if (!buffer || !required_length) { |
248 | return (AE_BAD_PARAMETER); | ||
248 | } | 249 | } |
250 | |||
249 | switch (buffer->length) { | 251 | switch (buffer->length) { |
250 | case ACPI_NO_BUFFER: | 252 | case ACPI_NO_BUFFER: |
251 | 253 | ||
diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c index c5c791a575c9..42609d3a8aa9 100644 --- a/drivers/acpi/utilities/utdelete.c +++ b/drivers/acpi/utilities/utdelete.c | |||
@@ -135,6 +135,10 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) | |||
135 | obj_pointer = object->package.elements; | 135 | obj_pointer = object->package.elements; |
136 | break; | 136 | break; |
137 | 137 | ||
138 | /* | ||
139 | * These objects have a possible list of notify handlers. | ||
140 | * Device object also may have a GPE block. | ||
141 | */ | ||
138 | case ACPI_TYPE_DEVICE: | 142 | case ACPI_TYPE_DEVICE: |
139 | 143 | ||
140 | if (object->device.gpe_block) { | 144 | if (object->device.gpe_block) { |
@@ -142,9 +146,14 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) | |||
142 | gpe_block); | 146 | gpe_block); |
143 | } | 147 | } |
144 | 148 | ||
145 | /* Walk the handler list for this device */ | 149 | /*lint -fallthrough */ |
150 | |||
151 | case ACPI_TYPE_PROCESSOR: | ||
152 | case ACPI_TYPE_THERMAL: | ||
153 | |||
154 | /* Walk the notify handler list for this object */ | ||
146 | 155 | ||
147 | handler_desc = object->device.handler; | 156 | handler_desc = object->common_notify.handler; |
148 | while (handler_desc) { | 157 | while (handler_desc) { |
149 | next_desc = handler_desc->address_space.next; | 158 | next_desc = handler_desc->address_space.next; |
150 | acpi_ut_remove_reference(handler_desc); | 159 | acpi_ut_remove_reference(handler_desc); |
diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c index e25484495e65..916eff399eb3 100644 --- a/drivers/acpi/utilities/utobject.c +++ b/drivers/acpi/utilities/utobject.c | |||
@@ -425,6 +425,7 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, | |||
425 | acpi_size * obj_length) | 425 | acpi_size * obj_length) |
426 | { | 426 | { |
427 | acpi_size length; | 427 | acpi_size length; |
428 | acpi_size size; | ||
428 | acpi_status status = AE_OK; | 429 | acpi_status status = AE_OK; |
429 | 430 | ||
430 | ACPI_FUNCTION_TRACE_PTR(ut_get_simple_object_size, internal_object); | 431 | ACPI_FUNCTION_TRACE_PTR(ut_get_simple_object_size, internal_object); |
@@ -484,10 +485,14 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, | |||
484 | * Get the actual length of the full pathname to this object. | 485 | * Get the actual length of the full pathname to this object. |
485 | * The reference will be converted to the pathname to the object | 486 | * The reference will be converted to the pathname to the object |
486 | */ | 487 | */ |
487 | length += | 488 | size = |
488 | ACPI_ROUND_UP_TO_NATIVE_WORD | 489 | acpi_ns_get_pathname_length(internal_object-> |
489 | (acpi_ns_get_pathname_length | 490 | reference.node); |
490 | (internal_object->reference.node)); | 491 | if (!size) { |
492 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
493 | } | ||
494 | |||
495 | length += ACPI_ROUND_UP_TO_NATIVE_WORD(size); | ||
491 | break; | 496 | break; |
492 | 497 | ||
493 | default: | 498 | default: |
diff --git a/drivers/acpi/wmi.c b/drivers/acpi/wmi.c index c33b1c6e93b1..cfe2c833474d 100644 --- a/drivers/acpi/wmi.c +++ b/drivers/acpi/wmi.c | |||
@@ -347,7 +347,7 @@ struct acpi_buffer *out) | |||
347 | strcpy(method, "WQ"); | 347 | strcpy(method, "WQ"); |
348 | strncat(method, block->object_id, 2); | 348 | strncat(method, block->object_id, 2); |
349 | 349 | ||
350 | status = acpi_evaluate_object(handle, method, NULL, out); | 350 | status = acpi_evaluate_object(handle, method, &input, out); |
351 | 351 | ||
352 | /* | 352 | /* |
353 | * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method, even if | 353 | * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method, even if |
diff --git a/drivers/char/pcmcia/ipwireless/tty.c b/drivers/char/pcmcia/ipwireless/tty.c index b1414507997c..3a23e7694d55 100644 --- a/drivers/char/pcmcia/ipwireless/tty.c +++ b/drivers/char/pcmcia/ipwireless/tty.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include <linux/tty_driver.h> | 29 | #include <linux/tty_driver.h> |
30 | #include <linux/tty_flip.h> | 30 | #include <linux/tty_flip.h> |
31 | #include <linux/uaccess.h> | 31 | #include <linux/uaccess.h> |
32 | #include <linux/version.h> | ||
33 | 32 | ||
34 | #include "tty.h" | 33 | #include "tty.h" |
35 | #include "network.h" | 34 | #include "network.h" |
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 509c89ac5bd3..08911ed66494 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
@@ -47,7 +47,6 @@ | |||
47 | 47 | ||
48 | 48 | ||
49 | #include <linux/module.h> | 49 | #include <linux/module.h> |
50 | #include <linux/version.h> | ||
51 | #include <linux/errno.h> | 50 | #include <linux/errno.h> |
52 | #include <linux/signal.h> | 51 | #include <linux/signal.h> |
53 | #include <linux/sched.h> | 52 | #include <linux/sched.h> |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 0e6866fe0f96..a27160ba21d7 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -2496,45 +2496,25 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg) | |||
2496 | } | 2496 | } |
2497 | 2497 | ||
2498 | /** | 2498 | /** |
2499 | * tiocswinsz - implement window size set ioctl | 2499 | * tty_do_resize - resize event |
2500 | * @tty; tty | 2500 | * @tty: tty being resized |
2501 | * @arg: user buffer for result | 2501 | * @real_tty: real tty (if using a pty/tty pair) |
2502 | * @rows: rows (character) | ||
2503 | * @cols: cols (character) | ||
2502 | * | 2504 | * |
2503 | * Copies the user idea of the window size to the kernel. Traditionally | 2505 | * Update the termios variables and send the neccessary signals to |
2504 | * this is just advisory information but for the Linux console it | 2506 | * peform a terminal resize correctly |
2505 | * actually has driver level meaning and triggers a VC resize. | ||
2506 | * | ||
2507 | * Locking: | ||
2508 | * Called function use the console_sem is used to ensure we do | ||
2509 | * not try and resize the console twice at once. | ||
2510 | * The tty->termios_mutex is used to ensure we don't double | ||
2511 | * resize and get confused. Lock order - tty->termios_mutex before | ||
2512 | * console sem | ||
2513 | */ | 2507 | */ |
2514 | 2508 | ||
2515 | static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, | 2509 | int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty, |
2516 | struct winsize __user *arg) | 2510 | struct winsize *ws) |
2517 | { | 2511 | { |
2518 | struct winsize tmp_ws; | ||
2519 | struct pid *pgrp, *rpgrp; | 2512 | struct pid *pgrp, *rpgrp; |
2520 | unsigned long flags; | 2513 | unsigned long flags; |
2521 | 2514 | ||
2522 | if (copy_from_user(&tmp_ws, arg, sizeof(*arg))) | ||
2523 | return -EFAULT; | ||
2524 | |||
2525 | mutex_lock(&tty->termios_mutex); | 2515 | mutex_lock(&tty->termios_mutex); |
2526 | if (!memcmp(&tmp_ws, &tty->winsize, sizeof(*arg))) | 2516 | if (!memcmp(ws, &tty->winsize, sizeof(*ws))) |
2527 | goto done; | 2517 | goto done; |
2528 | |||
2529 | #ifdef CONFIG_VT | ||
2530 | if (tty->driver->type == TTY_DRIVER_TYPE_CONSOLE) { | ||
2531 | if (vc_lock_resize(tty->driver_data, tmp_ws.ws_col, | ||
2532 | tmp_ws.ws_row)) { | ||
2533 | mutex_unlock(&tty->termios_mutex); | ||
2534 | return -ENXIO; | ||
2535 | } | ||
2536 | } | ||
2537 | #endif | ||
2538 | /* Get the PID values and reference them so we can | 2518 | /* Get the PID values and reference them so we can |
2539 | avoid holding the tty ctrl lock while sending signals */ | 2519 | avoid holding the tty ctrl lock while sending signals */ |
2540 | spin_lock_irqsave(&tty->ctrl_lock, flags); | 2520 | spin_lock_irqsave(&tty->ctrl_lock, flags); |
@@ -2550,14 +2530,42 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, | |||
2550 | put_pid(pgrp); | 2530 | put_pid(pgrp); |
2551 | put_pid(rpgrp); | 2531 | put_pid(rpgrp); |
2552 | 2532 | ||
2553 | tty->winsize = tmp_ws; | 2533 | tty->winsize = *ws; |
2554 | real_tty->winsize = tmp_ws; | 2534 | real_tty->winsize = *ws; |
2555 | done: | 2535 | done: |
2556 | mutex_unlock(&tty->termios_mutex); | 2536 | mutex_unlock(&tty->termios_mutex); |
2557 | return 0; | 2537 | return 0; |
2558 | } | 2538 | } |
2559 | 2539 | ||
2560 | /** | 2540 | /** |
2541 | * tiocswinsz - implement window size set ioctl | ||
2542 | * @tty; tty | ||
2543 | * @arg: user buffer for result | ||
2544 | * | ||
2545 | * Copies the user idea of the window size to the kernel. Traditionally | ||
2546 | * this is just advisory information but for the Linux console it | ||
2547 | * actually has driver level meaning and triggers a VC resize. | ||
2548 | * | ||
2549 | * Locking: | ||
2550 | * Driver dependant. The default do_resize method takes the | ||
2551 | * tty termios mutex and ctrl_lock. The console takes its own lock | ||
2552 | * then calls into the default method. | ||
2553 | */ | ||
2554 | |||
2555 | static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, | ||
2556 | struct winsize __user *arg) | ||
2557 | { | ||
2558 | struct winsize tmp_ws; | ||
2559 | if (copy_from_user(&tmp_ws, arg, sizeof(*arg))) | ||
2560 | return -EFAULT; | ||
2561 | |||
2562 | if (tty->ops->resize) | ||
2563 | return tty->ops->resize(tty, real_tty, &tmp_ws); | ||
2564 | else | ||
2565 | return tty_do_resize(tty, real_tty, &tmp_ws); | ||
2566 | } | ||
2567 | |||
2568 | /** | ||
2561 | * tioccons - allow admin to move logical console | 2569 | * tioccons - allow admin to move logical console |
2562 | * @file: the file to become console | 2570 | * @file: the file to become console |
2563 | * | 2571 | * |
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 1bc00c9d860d..60359c360912 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
@@ -803,7 +803,25 @@ static inline int resize_screen(struct vc_data *vc, int width, int height, | |||
803 | */ | 803 | */ |
804 | #define VC_RESIZE_MAXCOL (32767) | 804 | #define VC_RESIZE_MAXCOL (32767) |
805 | #define VC_RESIZE_MAXROW (32767) | 805 | #define VC_RESIZE_MAXROW (32767) |
806 | int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) | 806 | |
807 | /** | ||
808 | * vc_do_resize - resizing method for the tty | ||
809 | * @tty: tty being resized | ||
810 | * @real_tty: real tty (different to tty if a pty/tty pair) | ||
811 | * @vc: virtual console private data | ||
812 | * @cols: columns | ||
813 | * @lines: lines | ||
814 | * | ||
815 | * Resize a virtual console, clipping according to the actual constraints. | ||
816 | * If the caller passes a tty structure then update the termios winsize | ||
817 | * information and perform any neccessary signal handling. | ||
818 | * | ||
819 | * Caller must hold the console semaphore. Takes the termios mutex and | ||
820 | * ctrl_lock of the tty IFF a tty is passed. | ||
821 | */ | ||
822 | |||
823 | static int vc_do_resize(struct tty_struct *tty, struct tty_struct *real_tty, | ||
824 | struct vc_data *vc, unsigned int cols, unsigned int lines) | ||
807 | { | 825 | { |
808 | unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; | 826 | unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; |
809 | unsigned int old_cols, old_rows, old_row_size, old_screen_size; | 827 | unsigned int old_cols, old_rows, old_row_size, old_screen_size; |
@@ -907,24 +925,15 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) | |||
907 | gotoxy(vc, vc->vc_x, vc->vc_y); | 925 | gotoxy(vc, vc->vc_x, vc->vc_y); |
908 | save_cur(vc); | 926 | save_cur(vc); |
909 | 927 | ||
910 | if (vc->vc_tty) { | 928 | if (tty) { |
911 | struct winsize ws, *cws = &vc->vc_tty->winsize; | 929 | /* Rewrite the requested winsize data with the actual |
912 | struct pid *pgrp = NULL; | 930 | resulting sizes */ |
913 | 931 | struct winsize ws; | |
914 | memset(&ws, 0, sizeof(ws)); | 932 | memset(&ws, 0, sizeof(ws)); |
915 | ws.ws_row = vc->vc_rows; | 933 | ws.ws_row = vc->vc_rows; |
916 | ws.ws_col = vc->vc_cols; | 934 | ws.ws_col = vc->vc_cols; |
917 | ws.ws_ypixel = vc->vc_scan_lines; | 935 | ws.ws_ypixel = vc->vc_scan_lines; |
918 | 936 | tty_do_resize(tty, real_tty, &ws); | |
919 | spin_lock_irq(&vc->vc_tty->ctrl_lock); | ||
920 | if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col)) | ||
921 | pgrp = get_pid(vc->vc_tty->pgrp); | ||
922 | spin_unlock_irq(&vc->vc_tty->ctrl_lock); | ||
923 | if (pgrp) { | ||
924 | kill_pgrp(vc->vc_tty->pgrp, SIGWINCH, 1); | ||
925 | put_pid(pgrp); | ||
926 | } | ||
927 | *cws = ws; | ||
928 | } | 937 | } |
929 | 938 | ||
930 | if (CON_IS_VISIBLE(vc)) | 939 | if (CON_IS_VISIBLE(vc)) |
@@ -932,14 +941,47 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) | |||
932 | return err; | 941 | return err; |
933 | } | 942 | } |
934 | 943 | ||
935 | int vc_lock_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) | 944 | /** |
945 | * vc_resize - resize a VT | ||
946 | * @vc: virtual console | ||
947 | * @cols: columns | ||
948 | * @rows: rows | ||
949 | * | ||
950 | * Resize a virtual console as seen from the console end of things. We | ||
951 | * use the common vc_do_resize methods to update the structures. The | ||
952 | * caller must hold the console sem to protect console internals and | ||
953 | * vc->vc_tty | ||
954 | */ | ||
955 | |||
956 | int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows) | ||
957 | { | ||
958 | return vc_do_resize(vc->vc_tty, vc->vc_tty, vc, cols, rows); | ||
959 | } | ||
960 | |||
961 | /** | ||
962 | * vt_resize - resize a VT | ||
963 | * @tty: tty to resize | ||
964 | * @real_tty: tty if a pty/tty pair | ||
965 | * @ws: winsize attributes | ||
966 | * | ||
967 | * Resize a virtual terminal. This is called by the tty layer as we | ||
968 | * register our own handler for resizing. The mutual helper does all | ||
969 | * the actual work. | ||
970 | * | ||
971 | * Takes the console sem and the called methods then take the tty | ||
972 | * termios_mutex and the tty ctrl_lock in that order. | ||
973 | */ | ||
974 | |||
975 | int vt_resize(struct tty_struct *tty, struct tty_struct *real_tty, | ||
976 | struct winsize *ws) | ||
936 | { | 977 | { |
937 | int rc; | 978 | struct vc_data *vc = tty->driver_data; |
979 | int ret; | ||
938 | 980 | ||
939 | acquire_console_sem(); | 981 | acquire_console_sem(); |
940 | rc = vc_resize(vc, cols, lines); | 982 | ret = vc_do_resize(tty, real_tty, vc, ws->ws_col, ws->ws_row); |
941 | release_console_sem(); | 983 | release_console_sem(); |
942 | return rc; | 984 | return ret; |
943 | } | 985 | } |
944 | 986 | ||
945 | void vc_deallocate(unsigned int currcons) | 987 | void vc_deallocate(unsigned int currcons) |
@@ -2907,6 +2949,7 @@ static const struct tty_operations con_ops = { | |||
2907 | .start = con_start, | 2949 | .start = con_start, |
2908 | .throttle = con_throttle, | 2950 | .throttle = con_throttle, |
2909 | .unthrottle = con_unthrottle, | 2951 | .unthrottle = con_unthrottle, |
2952 | .resize = vt_resize, | ||
2910 | }; | 2953 | }; |
2911 | 2954 | ||
2912 | int __init vty_init(void) | 2955 | int __init vty_init(void) |
@@ -4061,7 +4104,6 @@ EXPORT_SYMBOL(default_blu); | |||
4061 | EXPORT_SYMBOL(update_region); | 4104 | EXPORT_SYMBOL(update_region); |
4062 | EXPORT_SYMBOL(redraw_screen); | 4105 | EXPORT_SYMBOL(redraw_screen); |
4063 | EXPORT_SYMBOL(vc_resize); | 4106 | EXPORT_SYMBOL(vc_resize); |
4064 | EXPORT_SYMBOL(vc_lock_resize); | ||
4065 | EXPORT_SYMBOL(fg_console); | 4107 | EXPORT_SYMBOL(fg_console); |
4066 | EXPORT_SYMBOL(console_blank_hook); | 4108 | EXPORT_SYMBOL(console_blank_hook); |
4067 | EXPORT_SYMBOL(console_blanked); | 4109 | EXPORT_SYMBOL(console_blanked); |
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index 3211afd9d57e..c904e9ad4a71 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c | |||
@@ -947,14 +947,16 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
947 | get_user(cc, &vtsizes->v_cols)) | 947 | get_user(cc, &vtsizes->v_cols)) |
948 | ret = -EFAULT; | 948 | ret = -EFAULT; |
949 | else { | 949 | else { |
950 | acquire_console_sem(); | ||
950 | for (i = 0; i < MAX_NR_CONSOLES; i++) { | 951 | for (i = 0; i < MAX_NR_CONSOLES; i++) { |
951 | vc = vc_cons[i].d; | 952 | vc = vc_cons[i].d; |
952 | 953 | ||
953 | if (vc) { | 954 | if (vc) { |
954 | vc->vc_resize_user = 1; | 955 | vc->vc_resize_user = 1; |
955 | vc_lock_resize(vc_cons[i].d, cc, ll); | 956 | vc_resize(vc_cons[i].d, cc, ll); |
956 | } | 957 | } |
957 | } | 958 | } |
959 | release_console_sem(); | ||
958 | } | 960 | } |
959 | break; | 961 | break; |
960 | } | 962 | } |
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c index 8bfee5fb7223..278c9857bcf5 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c | |||
@@ -74,7 +74,6 @@ | |||
74 | * currently programmed in the FPGA. | 74 | * currently programmed in the FPGA. |
75 | */ | 75 | */ |
76 | 76 | ||
77 | #include <linux/version.h> | ||
78 | #include <linux/module.h> | 77 | #include <linux/module.h> |
79 | #include <linux/kernel.h> | 78 | #include <linux/kernel.h> |
80 | #include <linux/types.h> | 79 | #include <linux/types.h> |
diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c index ba7b9a6b17a1..a4bec3f919aa 100644 --- a/drivers/cpuidle/governors/ladder.c +++ b/drivers/cpuidle/governors/ladder.c | |||
@@ -67,10 +67,17 @@ static int ladder_select_state(struct cpuidle_device *dev) | |||
67 | struct ladder_device *ldev = &__get_cpu_var(ladder_devices); | 67 | struct ladder_device *ldev = &__get_cpu_var(ladder_devices); |
68 | struct ladder_device_state *last_state; | 68 | struct ladder_device_state *last_state; |
69 | int last_residency, last_idx = ldev->last_state_idx; | 69 | int last_residency, last_idx = ldev->last_state_idx; |
70 | int latency_req = pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY); | ||
70 | 71 | ||
71 | if (unlikely(!ldev)) | 72 | if (unlikely(!ldev)) |
72 | return 0; | 73 | return 0; |
73 | 74 | ||
75 | /* Special case when user has set very strict latency requirement */ | ||
76 | if (unlikely(latency_req == 0)) { | ||
77 | ladder_do_selection(ldev, last_idx, 0); | ||
78 | return 0; | ||
79 | } | ||
80 | |||
74 | last_state = &ldev->states[last_idx]; | 81 | last_state = &ldev->states[last_idx]; |
75 | 82 | ||
76 | if (dev->states[last_idx].flags & CPUIDLE_FLAG_TIME_VALID) | 83 | if (dev->states[last_idx].flags & CPUIDLE_FLAG_TIME_VALID) |
@@ -81,8 +88,7 @@ static int ladder_select_state(struct cpuidle_device *dev) | |||
81 | /* consider promotion */ | 88 | /* consider promotion */ |
82 | if (last_idx < dev->state_count - 1 && | 89 | if (last_idx < dev->state_count - 1 && |
83 | last_residency > last_state->threshold.promotion_time && | 90 | last_residency > last_state->threshold.promotion_time && |
84 | dev->states[last_idx + 1].exit_latency <= | 91 | dev->states[last_idx + 1].exit_latency <= latency_req) { |
85 | pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY)) { | ||
86 | last_state->stats.promotion_count++; | 92 | last_state->stats.promotion_count++; |
87 | last_state->stats.demotion_count = 0; | 93 | last_state->stats.demotion_count = 0; |
88 | if (last_state->stats.promotion_count >= last_state->threshold.promotion_count) { | 94 | if (last_state->stats.promotion_count >= last_state->threshold.promotion_count) { |
@@ -92,7 +98,19 @@ static int ladder_select_state(struct cpuidle_device *dev) | |||
92 | } | 98 | } |
93 | 99 | ||
94 | /* consider demotion */ | 100 | /* consider demotion */ |
95 | if (last_idx > 0 && | 101 | if (last_idx > CPUIDLE_DRIVER_STATE_START && |
102 | dev->states[last_idx].exit_latency > latency_req) { | ||
103 | int i; | ||
104 | |||
105 | for (i = last_idx - 1; i > CPUIDLE_DRIVER_STATE_START; i--) { | ||
106 | if (dev->states[i].exit_latency <= latency_req) | ||
107 | break; | ||
108 | } | ||
109 | ladder_do_selection(ldev, last_idx, i); | ||
110 | return i; | ||
111 | } | ||
112 | |||
113 | if (last_idx > CPUIDLE_DRIVER_STATE_START && | ||
96 | last_residency < last_state->threshold.demotion_time) { | 114 | last_residency < last_state->threshold.demotion_time) { |
97 | last_state->stats.demotion_count++; | 115 | last_state->stats.demotion_count++; |
98 | last_state->stats.promotion_count = 0; | 116 | last_state->stats.promotion_count = 0; |
@@ -117,7 +135,7 @@ static int ladder_enable_device(struct cpuidle_device *dev) | |||
117 | struct ladder_device_state *lstate; | 135 | struct ladder_device_state *lstate; |
118 | struct cpuidle_state *state; | 136 | struct cpuidle_state *state; |
119 | 137 | ||
120 | ldev->last_state_idx = 0; | 138 | ldev->last_state_idx = CPUIDLE_DRIVER_STATE_START; |
121 | 139 | ||
122 | for (i = 0; i < dev->state_count; i++) { | 140 | for (i = 0; i < dev->state_count; i++) { |
123 | state = &dev->states[i]; | 141 | state = &dev->states[i]; |
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 78d77c5dc35c..8d7cf3f31450 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c | |||
@@ -34,21 +34,28 @@ static DEFINE_PER_CPU(struct menu_device, menu_devices); | |||
34 | static int menu_select(struct cpuidle_device *dev) | 34 | static int menu_select(struct cpuidle_device *dev) |
35 | { | 35 | { |
36 | struct menu_device *data = &__get_cpu_var(menu_devices); | 36 | struct menu_device *data = &__get_cpu_var(menu_devices); |
37 | int latency_req = pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY); | ||
37 | int i; | 38 | int i; |
38 | 39 | ||
40 | /* Special case when user has set very strict latency requirement */ | ||
41 | if (unlikely(latency_req == 0)) { | ||
42 | data->last_state_idx = 0; | ||
43 | return 0; | ||
44 | } | ||
45 | |||
39 | /* determine the expected residency time */ | 46 | /* determine the expected residency time */ |
40 | data->expected_us = | 47 | data->expected_us = |
41 | (u32) ktime_to_ns(tick_nohz_get_sleep_length()) / 1000; | 48 | (u32) ktime_to_ns(tick_nohz_get_sleep_length()) / 1000; |
42 | 49 | ||
43 | /* find the deepest idle state that satisfies our constraints */ | 50 | /* find the deepest idle state that satisfies our constraints */ |
44 | for (i = 1; i < dev->state_count; i++) { | 51 | for (i = CPUIDLE_DRIVER_STATE_START + 1; i < dev->state_count; i++) { |
45 | struct cpuidle_state *s = &dev->states[i]; | 52 | struct cpuidle_state *s = &dev->states[i]; |
46 | 53 | ||
47 | if (s->target_residency > data->expected_us) | 54 | if (s->target_residency > data->expected_us) |
48 | break; | 55 | break; |
49 | if (s->target_residency > data->predicted_us) | 56 | if (s->target_residency > data->predicted_us) |
50 | break; | 57 | break; |
51 | if (s->exit_latency > pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY)) | 58 | if (s->exit_latency > latency_req) |
52 | break; | 59 | break; |
53 | } | 60 | } |
54 | 61 | ||
@@ -67,9 +74,9 @@ static void menu_reflect(struct cpuidle_device *dev) | |||
67 | { | 74 | { |
68 | struct menu_device *data = &__get_cpu_var(menu_devices); | 75 | struct menu_device *data = &__get_cpu_var(menu_devices); |
69 | int last_idx = data->last_state_idx; | 76 | int last_idx = data->last_state_idx; |
70 | unsigned int measured_us = | 77 | unsigned int last_idle_us = cpuidle_get_last_residency(dev); |
71 | cpuidle_get_last_residency(dev) + data->elapsed_us; | ||
72 | struct cpuidle_state *target = &dev->states[last_idx]; | 78 | struct cpuidle_state *target = &dev->states[last_idx]; |
79 | unsigned int measured_us; | ||
73 | 80 | ||
74 | /* | 81 | /* |
75 | * Ugh, this idle state doesn't support residency measurements, so we | 82 | * Ugh, this idle state doesn't support residency measurements, so we |
@@ -77,20 +84,27 @@ static void menu_reflect(struct cpuidle_device *dev) | |||
77 | * for one full standard timer tick. However, be aware that this | 84 | * for one full standard timer tick. However, be aware that this |
78 | * could potentially result in a suboptimal state transition. | 85 | * could potentially result in a suboptimal state transition. |
79 | */ | 86 | */ |
80 | if (!(target->flags & CPUIDLE_FLAG_TIME_VALID)) | 87 | if (unlikely(!(target->flags & CPUIDLE_FLAG_TIME_VALID))) |
81 | measured_us = USEC_PER_SEC / HZ; | 88 | last_idle_us = USEC_PER_SEC / HZ; |
89 | |||
90 | /* | ||
91 | * measured_us and elapsed_us are the cumulative idle time, since the | ||
92 | * last time we were woken out of idle by an interrupt. | ||
93 | */ | ||
94 | if (data->elapsed_us <= data->elapsed_us + last_idle_us) | ||
95 | measured_us = data->elapsed_us + last_idle_us; | ||
96 | else | ||
97 | measured_us = -1; | ||
98 | |||
99 | /* Predict time until next break event */ | ||
100 | data->predicted_us = max(measured_us, data->last_measured_us); | ||
82 | 101 | ||
83 | /* Predict time remaining until next break event */ | 102 | if (last_idle_us + BREAK_FUZZ < |
84 | if (measured_us + BREAK_FUZZ < data->expected_us - target->exit_latency) { | 103 | data->expected_us - target->exit_latency) { |
85 | data->predicted_us = max(measured_us, data->last_measured_us); | ||
86 | data->last_measured_us = measured_us; | 104 | data->last_measured_us = measured_us; |
87 | data->elapsed_us = 0; | 105 | data->elapsed_us = 0; |
88 | } else { | 106 | } else { |
89 | if (data->elapsed_us < data->elapsed_us + measured_us) | 107 | data->elapsed_us = measured_us; |
90 | data->elapsed_us = measured_us; | ||
91 | else | ||
92 | data->elapsed_us = -1; | ||
93 | data->predicted_us = max(measured_us, data->last_measured_us); | ||
94 | } | 108 | } |
95 | } | 109 | } |
96 | 110 | ||
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index a4e4494663bf..0328da020a10 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/memory.h> | 27 | #include <linux/memory.h> |
28 | #include <asm/plat-orion/mv_xor.h> | 28 | #include <plat/mv_xor.h> |
29 | #include "mv_xor.h" | 29 | #include "mv_xor.h" |
30 | 30 | ||
31 | static void mv_xor_issue_pending(struct dma_chan *chan); | 31 | static void mv_xor_issue_pending(struct dma_chan *chan); |
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 61e78a4369b9..b15f88249639 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
@@ -654,12 +654,12 @@ static const struct hid_blacklist { | |||
654 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN }, | 654 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN }, |
655 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD }, | 655 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD }, |
656 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN }, | 656 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN }, |
657 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI, HID_QUIRK_APPLE_HAS_FN }, | 657 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, |
658 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD }, | 658 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD | HID_QUIRK_IGNORE_MOUSE}, |
659 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS, HID_QUIRK_APPLE_HAS_FN }, | 659 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE}, |
660 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI, HID_QUIRK_APPLE_HAS_FN }, | 660 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE}, |
661 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD }, | 661 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD | HID_QUIRK_IGNORE_MOUSE }, |
662 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS, HID_QUIRK_APPLE_HAS_FN }, | 662 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, |
663 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | 663 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, |
664 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | 664 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, |
665 | 665 | ||
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index bf4ebfb86fa5..d402e8d813ce 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -77,6 +77,22 @@ config SENSORS_AD7418 | |||
77 | This driver can also be built as a module. If so, the module | 77 | This driver can also be built as a module. If so, the module |
78 | will be called ad7418. | 78 | will be called ad7418. |
79 | 79 | ||
80 | config SENSORS_ADCXX | ||
81 | tristate "National Semiconductor ADCxxxSxxx" | ||
82 | depends on SPI_MASTER && EXPERIMENTAL | ||
83 | help | ||
84 | If you say yes here you get support for the National Semiconductor | ||
85 | ADC<bb><c>S<sss> chip family, where | ||
86 | * bb is the resolution in number of bits (8, 10, 12) | ||
87 | * c is the number of channels (1, 2, 4, 8) | ||
88 | * sss is the maximum conversion speed (021 for 200 kSPS, 051 for 500 | ||
89 | kSPS and 101 for 1 MSPS) | ||
90 | |||
91 | Examples : ADC081S101, ADC124S501, ... | ||
92 | |||
93 | This driver can also be built as a module. If so, the module | ||
94 | will be called adcxx. | ||
95 | |||
80 | config SENSORS_ADM1021 | 96 | config SENSORS_ADM1021 |
81 | tristate "Analog Devices ADM1021 and compatibles" | 97 | tristate "Analog Devices ADM1021 and compatibles" |
82 | depends on I2C | 98 | depends on I2C |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 7943e5cefb06..950134ab8426 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
@@ -17,6 +17,7 @@ obj-$(CONFIG_SENSORS_ABITUGURU) += abituguru.o | |||
17 | obj-$(CONFIG_SENSORS_ABITUGURU3)+= abituguru3.o | 17 | obj-$(CONFIG_SENSORS_ABITUGURU3)+= abituguru3.o |
18 | obj-$(CONFIG_SENSORS_AD7414) += ad7414.o | 18 | obj-$(CONFIG_SENSORS_AD7414) += ad7414.o |
19 | obj-$(CONFIG_SENSORS_AD7418) += ad7418.o | 19 | obj-$(CONFIG_SENSORS_AD7418) += ad7418.o |
20 | obj-$(CONFIG_SENSORS_ADCXX) += adcxx.o | ||
20 | obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o | 21 | obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o |
21 | obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o | 22 | obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o |
22 | obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o | 23 | obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o |
diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c index f00f497b9ca9..d568c65c1370 100644 --- a/drivers/hwmon/abituguru3.c +++ b/drivers/hwmon/abituguru3.c | |||
@@ -1,5 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | abituguru3.c Copyright (c) 2006 Hans de Goede <j.w.r.degoede@hhs.nl> | 2 | abituguru3.c |
3 | |||
4 | Copyright (c) 2006-2008 Hans de Goede <j.w.r.degoede@hhs.nl> | ||
5 | Copyright (c) 2008 Alistair John Strachan <alistair@devzero.co.uk> | ||
3 | 6 | ||
4 | This program is free software; you can redistribute it and/or modify | 7 | This program is free software; you can redistribute it and/or modify |
5 | it under the terms of the GNU General Public License as published by | 8 | it under the terms of the GNU General Public License as published by |
@@ -116,7 +119,7 @@ struct abituguru3_sensor_info { | |||
116 | 119 | ||
117 | struct abituguru3_motherboard_info { | 120 | struct abituguru3_motherboard_info { |
118 | u16 id; | 121 | u16 id; |
119 | const char *name; | 122 | const char *dmi_name; |
120 | /* + 1 -> end of sensors indicated by a sensor with name == NULL */ | 123 | /* + 1 -> end of sensors indicated by a sensor with name == NULL */ |
121 | struct abituguru3_sensor_info sensors[ABIT_UGURU3_MAX_NO_SENSORS + 1]; | 124 | struct abituguru3_sensor_info sensors[ABIT_UGURU3_MAX_NO_SENSORS + 1]; |
122 | }; | 125 | }; |
@@ -161,7 +164,7 @@ struct abituguru3_data { | |||
161 | 164 | ||
162 | /* Constants */ | 165 | /* Constants */ |
163 | static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { | 166 | static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { |
164 | { 0x000C, "unknown", { | 167 | { 0x000C, NULL /* Unknown, need DMI string */, { |
165 | { "CPU Core", 0, 0, 10, 1, 0 }, | 168 | { "CPU Core", 0, 0, 10, 1, 0 }, |
166 | { "DDR", 1, 0, 10, 1, 0 }, | 169 | { "DDR", 1, 0, 10, 1, 0 }, |
167 | { "DDR VTT", 2, 0, 10, 1, 0 }, | 170 | { "DDR VTT", 2, 0, 10, 1, 0 }, |
@@ -183,7 +186,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { | |||
183 | { "AUX1 Fan", 35, 2, 60, 1, 0 }, | 186 | { "AUX1 Fan", 35, 2, 60, 1, 0 }, |
184 | { NULL, 0, 0, 0, 0, 0 } } | 187 | { NULL, 0, 0, 0, 0, 0 } } |
185 | }, | 188 | }, |
186 | { 0x000D, "Abit AW8", { | 189 | { 0x000D, NULL /* Abit AW8, need DMI string */, { |
187 | { "CPU Core", 0, 0, 10, 1, 0 }, | 190 | { "CPU Core", 0, 0, 10, 1, 0 }, |
188 | { "DDR", 1, 0, 10, 1, 0 }, | 191 | { "DDR", 1, 0, 10, 1, 0 }, |
189 | { "DDR VTT", 2, 0, 10, 1, 0 }, | 192 | { "DDR VTT", 2, 0, 10, 1, 0 }, |
@@ -212,7 +215,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { | |||
212 | { "AUX5 Fan", 39, 2, 60, 1, 0 }, | 215 | { "AUX5 Fan", 39, 2, 60, 1, 0 }, |
213 | { NULL, 0, 0, 0, 0, 0 } } | 216 | { NULL, 0, 0, 0, 0, 0 } } |
214 | }, | 217 | }, |
215 | { 0x000E, "AL-8", { | 218 | { 0x000E, NULL /* AL-8, need DMI string */, { |
216 | { "CPU Core", 0, 0, 10, 1, 0 }, | 219 | { "CPU Core", 0, 0, 10, 1, 0 }, |
217 | { "DDR", 1, 0, 10, 1, 0 }, | 220 | { "DDR", 1, 0, 10, 1, 0 }, |
218 | { "DDR VTT", 2, 0, 10, 1, 0 }, | 221 | { "DDR VTT", 2, 0, 10, 1, 0 }, |
@@ -233,7 +236,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { | |||
233 | { "SYS Fan", 34, 2, 60, 1, 0 }, | 236 | { "SYS Fan", 34, 2, 60, 1, 0 }, |
234 | { NULL, 0, 0, 0, 0, 0 } } | 237 | { NULL, 0, 0, 0, 0, 0 } } |
235 | }, | 238 | }, |
236 | { 0x000F, "unknown", { | 239 | { 0x000F, NULL /* Unknown, need DMI string */, { |
237 | { "CPU Core", 0, 0, 10, 1, 0 }, | 240 | { "CPU Core", 0, 0, 10, 1, 0 }, |
238 | { "DDR", 1, 0, 10, 1, 0 }, | 241 | { "DDR", 1, 0, 10, 1, 0 }, |
239 | { "DDR VTT", 2, 0, 10, 1, 0 }, | 242 | { "DDR VTT", 2, 0, 10, 1, 0 }, |
@@ -254,7 +257,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { | |||
254 | { "SYS Fan", 34, 2, 60, 1, 0 }, | 257 | { "SYS Fan", 34, 2, 60, 1, 0 }, |
255 | { NULL, 0, 0, 0, 0, 0 } } | 258 | { NULL, 0, 0, 0, 0, 0 } } |
256 | }, | 259 | }, |
257 | { 0x0010, "Abit NI8 SLI GR", { | 260 | { 0x0010, NULL /* Abit NI8 SLI GR, need DMI string */, { |
258 | { "CPU Core", 0, 0, 10, 1, 0 }, | 261 | { "CPU Core", 0, 0, 10, 1, 0 }, |
259 | { "DDR", 1, 0, 10, 1, 0 }, | 262 | { "DDR", 1, 0, 10, 1, 0 }, |
260 | { "DDR VTT", 2, 0, 10, 1, 0 }, | 263 | { "DDR VTT", 2, 0, 10, 1, 0 }, |
@@ -276,7 +279,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { | |||
276 | { "OTES1 Fan", 36, 2, 60, 1, 0 }, | 279 | { "OTES1 Fan", 36, 2, 60, 1, 0 }, |
277 | { NULL, 0, 0, 0, 0, 0 } } | 280 | { NULL, 0, 0, 0, 0, 0 } } |
278 | }, | 281 | }, |
279 | { 0x0011, "Abit AT8 32X", { | 282 | { 0x0011, NULL /* Abit AT8 32X, need DMI string */, { |
280 | { "CPU Core", 0, 0, 10, 1, 0 }, | 283 | { "CPU Core", 0, 0, 10, 1, 0 }, |
281 | { "DDR", 1, 0, 20, 1, 0 }, | 284 | { "DDR", 1, 0, 20, 1, 0 }, |
282 | { "DDR VTT", 2, 0, 10, 1, 0 }, | 285 | { "DDR VTT", 2, 0, 10, 1, 0 }, |
@@ -302,7 +305,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { | |||
302 | { "AUX2 Fan", 36, 2, 60, 1, 0 }, | 305 | { "AUX2 Fan", 36, 2, 60, 1, 0 }, |
303 | { NULL, 0, 0, 0, 0, 0 } } | 306 | { NULL, 0, 0, 0, 0, 0 } } |
304 | }, | 307 | }, |
305 | { 0x0012, "Abit AN8 32X", { | 308 | { 0x0012, NULL /* Abit AN8 32X, need DMI string */, { |
306 | { "CPU Core", 0, 0, 10, 1, 0 }, | 309 | { "CPU Core", 0, 0, 10, 1, 0 }, |
307 | { "DDR", 1, 0, 20, 1, 0 }, | 310 | { "DDR", 1, 0, 20, 1, 0 }, |
308 | { "DDR VTT", 2, 0, 10, 1, 0 }, | 311 | { "DDR VTT", 2, 0, 10, 1, 0 }, |
@@ -324,7 +327,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { | |||
324 | { "AUX1 Fan", 36, 2, 60, 1, 0 }, | 327 | { "AUX1 Fan", 36, 2, 60, 1, 0 }, |
325 | { NULL, 0, 0, 0, 0, 0 } } | 328 | { NULL, 0, 0, 0, 0, 0 } } |
326 | }, | 329 | }, |
327 | { 0x0013, "Abit AW8D", { | 330 | { 0x0013, NULL /* Abit AW8D, need DMI string */, { |
328 | { "CPU Core", 0, 0, 10, 1, 0 }, | 331 | { "CPU Core", 0, 0, 10, 1, 0 }, |
329 | { "DDR", 1, 0, 10, 1, 0 }, | 332 | { "DDR", 1, 0, 10, 1, 0 }, |
330 | { "DDR VTT", 2, 0, 10, 1, 0 }, | 333 | { "DDR VTT", 2, 0, 10, 1, 0 }, |
@@ -353,7 +356,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { | |||
353 | { "AUX5 Fan", 39, 2, 60, 1, 0 }, | 356 | { "AUX5 Fan", 39, 2, 60, 1, 0 }, |
354 | { NULL, 0, 0, 0, 0, 0 } } | 357 | { NULL, 0, 0, 0, 0, 0 } } |
355 | }, | 358 | }, |
356 | { 0x0014, "Abit AB9 Pro", { | 359 | { 0x0014, NULL /* Abit AB9 Pro, need DMI string */, { |
357 | { "CPU Core", 0, 0, 10, 1, 0 }, | 360 | { "CPU Core", 0, 0, 10, 1, 0 }, |
358 | { "DDR", 1, 0, 10, 1, 0 }, | 361 | { "DDR", 1, 0, 10, 1, 0 }, |
359 | { "DDR VTT", 2, 0, 10, 1, 0 }, | 362 | { "DDR VTT", 2, 0, 10, 1, 0 }, |
@@ -374,7 +377,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { | |||
374 | { "SYS Fan", 34, 2, 60, 1, 0 }, | 377 | { "SYS Fan", 34, 2, 60, 1, 0 }, |
375 | { NULL, 0, 0, 0, 0, 0 } } | 378 | { NULL, 0, 0, 0, 0, 0 } } |
376 | }, | 379 | }, |
377 | { 0x0015, "unknown", { | 380 | { 0x0015, NULL /* Unknown, need DMI string */, { |
378 | { "CPU Core", 0, 0, 10, 1, 0 }, | 381 | { "CPU Core", 0, 0, 10, 1, 0 }, |
379 | { "DDR", 1, 0, 20, 1, 0 }, | 382 | { "DDR", 1, 0, 20, 1, 0 }, |
380 | { "DDR VTT", 2, 0, 10, 1, 0 }, | 383 | { "DDR VTT", 2, 0, 10, 1, 0 }, |
@@ -398,7 +401,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { | |||
398 | { "AUX3 Fan", 36, 2, 60, 1, 0 }, | 401 | { "AUX3 Fan", 36, 2, 60, 1, 0 }, |
399 | { NULL, 0, 0, 0, 0, 0 } } | 402 | { NULL, 0, 0, 0, 0, 0 } } |
400 | }, | 403 | }, |
401 | { 0x0016, "AW9D-MAX", { | 404 | { 0x0016, NULL /* AW9D-MAX, need DMI string */, { |
402 | { "CPU Core", 0, 0, 10, 1, 0 }, | 405 | { "CPU Core", 0, 0, 10, 1, 0 }, |
403 | { "DDR2", 1, 0, 20, 1, 0 }, | 406 | { "DDR2", 1, 0, 20, 1, 0 }, |
404 | { "DDR2 VTT", 2, 0, 10, 1, 0 }, | 407 | { "DDR2 VTT", 2, 0, 10, 1, 0 }, |
@@ -426,7 +429,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { | |||
426 | { "OTES1 Fan", 38, 2, 60, 1, 0 }, | 429 | { "OTES1 Fan", 38, 2, 60, 1, 0 }, |
427 | { NULL, 0, 0, 0, 0, 0 } } | 430 | { NULL, 0, 0, 0, 0, 0 } } |
428 | }, | 431 | }, |
429 | { 0x0017, "unknown", { | 432 | { 0x0017, NULL /* Unknown, need DMI string */, { |
430 | { "CPU Core", 0, 0, 10, 1, 0 }, | 433 | { "CPU Core", 0, 0, 10, 1, 0 }, |
431 | { "DDR2", 1, 0, 20, 1, 0 }, | 434 | { "DDR2", 1, 0, 20, 1, 0 }, |
432 | { "DDR2 VTT", 2, 0, 10, 1, 0 }, | 435 | { "DDR2 VTT", 2, 0, 10, 1, 0 }, |
@@ -451,7 +454,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { | |||
451 | { "AUX3 FAN", 37, 2, 60, 1, 0 }, | 454 | { "AUX3 FAN", 37, 2, 60, 1, 0 }, |
452 | { NULL, 0, 0, 0, 0, 0 } } | 455 | { NULL, 0, 0, 0, 0, 0 } } |
453 | }, | 456 | }, |
454 | { 0x0018, "unknown", { | 457 | { 0x0018, NULL /* Unknown, need DMI string */, { |
455 | { "CPU Core", 0, 0, 10, 1, 0 }, | 458 | { "CPU Core", 0, 0, 10, 1, 0 }, |
456 | { "DDR2", 1, 0, 20, 1, 0 }, | 459 | { "DDR2", 1, 0, 20, 1, 0 }, |
457 | { "DDR2 VTT", 2, 0, 10, 1, 0 }, | 460 | { "DDR2 VTT", 2, 0, 10, 1, 0 }, |
@@ -478,7 +481,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { | |||
478 | { "AUX3 Fan", 36, 2, 60, 1, 0 }, | 481 | { "AUX3 Fan", 36, 2, 60, 1, 0 }, |
479 | { NULL, 0, 0, 0, 0, 0 } } | 482 | { NULL, 0, 0, 0, 0, 0 } } |
480 | }, | 483 | }, |
481 | { 0x0019, "unknown", { | 484 | { 0x0019, NULL /* Unknown, need DMI string */, { |
482 | { "CPU Core", 7, 0, 10, 1, 0 }, | 485 | { "CPU Core", 7, 0, 10, 1, 0 }, |
483 | { "DDR2", 13, 0, 20, 1, 0 }, | 486 | { "DDR2", 13, 0, 20, 1, 0 }, |
484 | { "DDR2 VTT", 14, 0, 10, 1, 0 }, | 487 | { "DDR2 VTT", 14, 0, 10, 1, 0 }, |
@@ -505,7 +508,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { | |||
505 | { "AUX3 FAN", 36, 2, 60, 1, 0 }, | 508 | { "AUX3 FAN", 36, 2, 60, 1, 0 }, |
506 | { NULL, 0, 0, 0, 0, 0 } } | 509 | { NULL, 0, 0, 0, 0, 0 } } |
507 | }, | 510 | }, |
508 | { 0x001A, "Abit IP35 Pro", { | 511 | { 0x001A, "IP35 Pro(Intel P35-ICH9R)", { |
509 | { "CPU Core", 0, 0, 10, 1, 0 }, | 512 | { "CPU Core", 0, 0, 10, 1, 0 }, |
510 | { "DDR2", 1, 0, 20, 1, 0 }, | 513 | { "DDR2", 1, 0, 20, 1, 0 }, |
511 | { "DDR2 VTT", 2, 0, 10, 1, 0 }, | 514 | { "DDR2 VTT", 2, 0, 10, 1, 0 }, |
@@ -533,7 +536,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { | |||
533 | { "AUX4 Fan", 37, 2, 60, 1, 0 }, | 536 | { "AUX4 Fan", 37, 2, 60, 1, 0 }, |
534 | { NULL, 0, 0, 0, 0, 0 } } | 537 | { NULL, 0, 0, 0, 0, 0 } } |
535 | }, | 538 | }, |
536 | { 0x001B, "unknown", { | 539 | { 0x001B, NULL /* Unknown, need DMI string */, { |
537 | { "CPU Core", 0, 0, 10, 1, 0 }, | 540 | { "CPU Core", 0, 0, 10, 1, 0 }, |
538 | { "DDR3", 1, 0, 20, 1, 0 }, | 541 | { "DDR3", 1, 0, 20, 1, 0 }, |
539 | { "DDR3 VTT", 2, 0, 10, 1, 0 }, | 542 | { "DDR3 VTT", 2, 0, 10, 1, 0 }, |
@@ -560,7 +563,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { | |||
560 | { "AUX3 Fan", 36, 2, 60, 1, 0 }, | 563 | { "AUX3 Fan", 36, 2, 60, 1, 0 }, |
561 | { NULL, 0, 0, 0, 0, 0 } } | 564 | { NULL, 0, 0, 0, 0, 0 } } |
562 | }, | 565 | }, |
563 | { 0x001C, "unknown", { | 566 | { 0x001C, NULL /* Unknown, need DMI string */, { |
564 | { "CPU Core", 0, 0, 10, 1, 0 }, | 567 | { "CPU Core", 0, 0, 10, 1, 0 }, |
565 | { "DDR2", 1, 0, 20, 1, 0 }, | 568 | { "DDR2", 1, 0, 20, 1, 0 }, |
566 | { "DDR2 VTT", 2, 0, 10, 1, 0 }, | 569 | { "DDR2 VTT", 2, 0, 10, 1, 0 }, |
@@ -935,9 +938,18 @@ static int __devinit abituguru3_probe(struct platform_device *pdev) | |||
935 | goto abituguru3_probe_error; | 938 | goto abituguru3_probe_error; |
936 | } | 939 | } |
937 | data->sensors = abituguru3_motherboards[i].sensors; | 940 | data->sensors = abituguru3_motherboards[i].sensors; |
941 | |||
938 | printk(KERN_INFO ABIT_UGURU3_NAME ": found Abit uGuru3, motherboard " | 942 | printk(KERN_INFO ABIT_UGURU3_NAME ": found Abit uGuru3, motherboard " |
939 | "ID: %04X (%s)\n", (unsigned int)id, | 943 | "ID: %04X\n", (unsigned int)id); |
940 | abituguru3_motherboards[i].name); | 944 | |
945 | #ifdef CONFIG_DMI | ||
946 | if (!abituguru3_motherboards[i].dmi_name) { | ||
947 | printk(KERN_WARNING ABIT_UGURU3_NAME ": this motherboard was " | ||
948 | "not detected using DMI. Please send the output of " | ||
949 | "\"dmidecode\" to the abituguru3 maintainer" | ||
950 | "(see MAINTAINERS)\n"); | ||
951 | } | ||
952 | #endif | ||
941 | 953 | ||
942 | /* Fill the sysfs attr array */ | 954 | /* Fill the sysfs attr array */ |
943 | sysfs_attr_i = 0; | 955 | sysfs_attr_i = 0; |
@@ -1109,6 +1121,46 @@ static struct platform_driver abituguru3_driver = { | |||
1109 | .resume = abituguru3_resume | 1121 | .resume = abituguru3_resume |
1110 | }; | 1122 | }; |
1111 | 1123 | ||
1124 | #ifdef CONFIG_DMI | ||
1125 | |||
1126 | static int __init abituguru3_dmi_detect(void) | ||
1127 | { | ||
1128 | const char *board_vendor, *board_name; | ||
1129 | int i, err = (force) ? 1 : -ENODEV; | ||
1130 | |||
1131 | board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); | ||
1132 | if (!board_vendor || strcmp(board_vendor, "http://www.abit.com.tw/")) | ||
1133 | return err; | ||
1134 | |||
1135 | board_name = dmi_get_system_info(DMI_BOARD_NAME); | ||
1136 | if (!board_name) | ||
1137 | return err; | ||
1138 | |||
1139 | for (i = 0; abituguru3_motherboards[i].id; i++) { | ||
1140 | const char *dmi_name = abituguru3_motherboards[i].dmi_name; | ||
1141 | if (dmi_name && !strcmp(dmi_name, board_name)) | ||
1142 | break; | ||
1143 | } | ||
1144 | |||
1145 | if (!abituguru3_motherboards[i].id) | ||
1146 | return 1; | ||
1147 | |||
1148 | return 0; | ||
1149 | } | ||
1150 | |||
1151 | #else /* !CONFIG_DMI */ | ||
1152 | |||
1153 | static inline int abituguru3_dmi_detect(void) | ||
1154 | { | ||
1155 | return -ENODEV; | ||
1156 | } | ||
1157 | |||
1158 | #endif /* CONFIG_DMI */ | ||
1159 | |||
1160 | /* FIXME: Manual detection should die eventually; we need to collect stable | ||
1161 | * DMI model names first before we can rely entirely on CONFIG_DMI. | ||
1162 | */ | ||
1163 | |||
1112 | static int __init abituguru3_detect(void) | 1164 | static int __init abituguru3_detect(void) |
1113 | { | 1165 | { |
1114 | /* See if there is an uguru3 there. An idle uGuru3 will hold 0x00 or | 1166 | /* See if there is an uguru3 there. An idle uGuru3 will hold 0x00 or |
@@ -1119,7 +1171,7 @@ static int __init abituguru3_detect(void) | |||
1119 | if (((data_val == 0x00) || (data_val == 0x08)) && | 1171 | if (((data_val == 0x00) || (data_val == 0x08)) && |
1120 | ((cmd_val == 0xAC) || (cmd_val == 0x05) || | 1172 | ((cmd_val == 0xAC) || (cmd_val == 0x05) || |
1121 | (cmd_val == 0x55))) | 1173 | (cmd_val == 0x55))) |
1122 | return ABIT_UGURU3_BASE; | 1174 | return 0; |
1123 | 1175 | ||
1124 | ABIT_UGURU3_DEBUG("no Abit uGuru3 found, data = 0x%02X, cmd = " | 1176 | ABIT_UGURU3_DEBUG("no Abit uGuru3 found, data = 0x%02X, cmd = " |
1125 | "0x%02X\n", (unsigned int)data_val, (unsigned int)cmd_val); | 1177 | "0x%02X\n", (unsigned int)data_val, (unsigned int)cmd_val); |
@@ -1127,7 +1179,7 @@ static int __init abituguru3_detect(void) | |||
1127 | if (force) { | 1179 | if (force) { |
1128 | printk(KERN_INFO ABIT_UGURU3_NAME ": Assuming Abit uGuru3 is " | 1180 | printk(KERN_INFO ABIT_UGURU3_NAME ": Assuming Abit uGuru3 is " |
1129 | "present because of \"force\" parameter\n"); | 1181 | "present because of \"force\" parameter\n"); |
1130 | return ABIT_UGURU3_BASE; | 1182 | return 0; |
1131 | } | 1183 | } |
1132 | 1184 | ||
1133 | /* No uGuru3 found */ | 1185 | /* No uGuru3 found */ |
@@ -1138,27 +1190,29 @@ static struct platform_device *abituguru3_pdev; | |||
1138 | 1190 | ||
1139 | static int __init abituguru3_init(void) | 1191 | static int __init abituguru3_init(void) |
1140 | { | 1192 | { |
1141 | int address, err; | ||
1142 | struct resource res = { .flags = IORESOURCE_IO }; | 1193 | struct resource res = { .flags = IORESOURCE_IO }; |
1143 | 1194 | int err; | |
1144 | #ifdef CONFIG_DMI | 1195 | |
1145 | const char *board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); | 1196 | /* Attempt DMI detection first */ |
1146 | 1197 | err = abituguru3_dmi_detect(); | |
1147 | /* safety check, refuse to load on non Abit motherboards */ | 1198 | if (err < 0) |
1148 | if (!force && (!board_vendor || | 1199 | return err; |
1149 | strcmp(board_vendor, "http://www.abit.com.tw/"))) | 1200 | |
1150 | return -ENODEV; | 1201 | /* Fall back to manual detection if there was no exact |
1151 | #endif | 1202 | * board name match, or force was specified. |
1152 | 1203 | */ | |
1153 | address = abituguru3_detect(); | 1204 | if (err > 0) { |
1154 | if (address < 0) | 1205 | err = abituguru3_detect(); |
1155 | return address; | 1206 | if (err) |
1207 | return err; | ||
1208 | } | ||
1156 | 1209 | ||
1157 | err = platform_driver_register(&abituguru3_driver); | 1210 | err = platform_driver_register(&abituguru3_driver); |
1158 | if (err) | 1211 | if (err) |
1159 | goto exit; | 1212 | goto exit; |
1160 | 1213 | ||
1161 | abituguru3_pdev = platform_device_alloc(ABIT_UGURU3_NAME, address); | 1214 | abituguru3_pdev = platform_device_alloc(ABIT_UGURU3_NAME, |
1215 | ABIT_UGURU3_BASE); | ||
1162 | if (!abituguru3_pdev) { | 1216 | if (!abituguru3_pdev) { |
1163 | printk(KERN_ERR ABIT_UGURU3_NAME | 1217 | printk(KERN_ERR ABIT_UGURU3_NAME |
1164 | ": Device allocation failed\n"); | 1218 | ": Device allocation failed\n"); |
@@ -1166,8 +1220,8 @@ static int __init abituguru3_init(void) | |||
1166 | goto exit_driver_unregister; | 1220 | goto exit_driver_unregister; |
1167 | } | 1221 | } |
1168 | 1222 | ||
1169 | res.start = address; | 1223 | res.start = ABIT_UGURU3_BASE; |
1170 | res.end = address + ABIT_UGURU3_REGION_LENGTH - 1; | 1224 | res.end = ABIT_UGURU3_BASE + ABIT_UGURU3_REGION_LENGTH - 1; |
1171 | res.name = ABIT_UGURU3_NAME; | 1225 | res.name = ABIT_UGURU3_NAME; |
1172 | 1226 | ||
1173 | err = platform_device_add_resources(abituguru3_pdev, &res, 1); | 1227 | err = platform_device_add_resources(abituguru3_pdev, &res, 1); |
diff --git a/drivers/hwmon/adcxx.c b/drivers/hwmon/adcxx.c new file mode 100644 index 000000000000..242294db3db6 --- /dev/null +++ b/drivers/hwmon/adcxx.c | |||
@@ -0,0 +1,329 @@ | |||
1 | /* | ||
2 | * adcxx.c | ||
3 | * | ||
4 | * The adcxx4s is an AD converter family from National Semiconductor (NS). | ||
5 | * | ||
6 | * Copyright (c) 2008 Marc Pignat <marc.pignat@hevs.ch> | ||
7 | * | ||
8 | * The adcxx4s communicates with a host processor via an SPI/Microwire Bus | ||
9 | * interface. This driver supports the whole family of devices with name | ||
10 | * ADC<bb><c>S<sss>, where | ||
11 | * * bb is the resolution in number of bits (8, 10, 12) | ||
12 | * * c is the number of channels (1, 2, 4, 8) | ||
13 | * * sss is the maximum conversion speed (021 for 200 kSPS, 051 for 500 kSPS | ||
14 | * and 101 for 1 MSPS) | ||
15 | * | ||
16 | * Complete datasheets are available at National's website here: | ||
17 | * http://www.national.com/ds/DC/ADC<bb><c>S<sss>.pdf | ||
18 | * | ||
19 | * Handling of 8, 10 and 12 bits converters are the same, the | ||
20 | * unavailable bits are 0 :) | ||
21 | * | ||
22 | * This program is free software; you can redistribute it and/or modify | ||
23 | * it under the terms of the GNU General Public License as published by | ||
24 | * the Free Software Foundation; either version 2 of the License, or | ||
25 | * (at your option) any later version. | ||
26 | * | ||
27 | * This program is distributed in the hope that it will be useful, | ||
28 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
29 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
30 | * GNU General Public License for more details. | ||
31 | * | ||
32 | * You should have received a copy of the GNU General Public License | ||
33 | * along with this program; if not, write to the Free Software | ||
34 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
35 | */ | ||
36 | |||
37 | #include <linux/init.h> | ||
38 | #include <linux/module.h> | ||
39 | #include <linux/kernel.h> | ||
40 | #include <linux/device.h> | ||
41 | #include <linux/err.h> | ||
42 | #include <linux/sysfs.h> | ||
43 | #include <linux/hwmon.h> | ||
44 | #include <linux/hwmon-sysfs.h> | ||
45 | #include <linux/mutex.h> | ||
46 | #include <linux/spi/spi.h> | ||
47 | |||
48 | #define DRVNAME "adcxx" | ||
49 | |||
50 | struct adcxx { | ||
51 | struct device *hwmon_dev; | ||
52 | struct mutex lock; | ||
53 | u32 channels; | ||
54 | u32 reference; /* in millivolts */ | ||
55 | }; | ||
56 | |||
57 | /* sysfs hook function */ | ||
58 | static ssize_t adcxx_read(struct device *dev, | ||
59 | struct device_attribute *devattr, char *buf) | ||
60 | { | ||
61 | struct spi_device *spi = to_spi_device(dev); | ||
62 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
63 | struct adcxx *adc = dev_get_drvdata(&spi->dev); | ||
64 | u8 tx_buf[2] = { attr->index << 3 }; /* other bits are don't care */ | ||
65 | u8 rx_buf[2]; | ||
66 | int status; | ||
67 | int value; | ||
68 | |||
69 | if (mutex_lock_interruptible(&adc->lock)) | ||
70 | return -ERESTARTSYS; | ||
71 | |||
72 | status = spi_write_then_read(spi, tx_buf, sizeof(tx_buf), | ||
73 | rx_buf, sizeof(rx_buf)); | ||
74 | if (status < 0) { | ||
75 | dev_warn(dev, "spi_write_then_read failed with status %d\n", | ||
76 | status); | ||
77 | goto out; | ||
78 | } | ||
79 | |||
80 | value = (rx_buf[0] << 8) + rx_buf[1]; | ||
81 | dev_dbg(dev, "raw value = 0x%x\n", value); | ||
82 | |||
83 | value = value * adc->reference >> 12; | ||
84 | status = sprintf(buf, "%d\n", value); | ||
85 | out: | ||
86 | mutex_unlock(&adc->lock); | ||
87 | return status; | ||
88 | } | ||
89 | |||
90 | static ssize_t adcxx_show_min(struct device *dev, | ||
91 | struct device_attribute *devattr, char *buf) | ||
92 | { | ||
93 | /* The minimum reference is 0 for this chip family */ | ||
94 | return sprintf(buf, "0\n"); | ||
95 | } | ||
96 | |||
97 | static ssize_t adcxx_show_max(struct device *dev, | ||
98 | struct device_attribute *devattr, char *buf) | ||
99 | { | ||
100 | struct spi_device *spi = to_spi_device(dev); | ||
101 | struct adcxx *adc = dev_get_drvdata(&spi->dev); | ||
102 | u32 reference; | ||
103 | |||
104 | if (mutex_lock_interruptible(&adc->lock)) | ||
105 | return -ERESTARTSYS; | ||
106 | |||
107 | reference = adc->reference; | ||
108 | |||
109 | mutex_unlock(&adc->lock); | ||
110 | |||
111 | return sprintf(buf, "%d\n", reference); | ||
112 | } | ||
113 | |||
114 | static ssize_t adcxx_set_max(struct device *dev, | ||
115 | struct device_attribute *devattr, const char *buf, size_t count) | ||
116 | { | ||
117 | struct spi_device *spi = to_spi_device(dev); | ||
118 | struct adcxx *adc = dev_get_drvdata(&spi->dev); | ||
119 | unsigned long value; | ||
120 | |||
121 | if (strict_strtoul(buf, 10, &value)) | ||
122 | return -EINVAL; | ||
123 | |||
124 | if (mutex_lock_interruptible(&adc->lock)) | ||
125 | return -ERESTARTSYS; | ||
126 | |||
127 | adc->reference = value; | ||
128 | |||
129 | mutex_unlock(&adc->lock); | ||
130 | |||
131 | return count; | ||
132 | } | ||
133 | |||
134 | static ssize_t adcxx_show_name(struct device *dev, struct device_attribute | ||
135 | *devattr, char *buf) | ||
136 | { | ||
137 | struct spi_device *spi = to_spi_device(dev); | ||
138 | struct adcxx *adc = dev_get_drvdata(&spi->dev); | ||
139 | |||
140 | return sprintf(buf, "adcxx%ds\n", adc->channels); | ||
141 | } | ||
142 | |||
143 | static struct sensor_device_attribute ad_input[] = { | ||
144 | SENSOR_ATTR(name, S_IRUGO, adcxx_show_name, NULL, 0), | ||
145 | SENSOR_ATTR(in_min, S_IRUGO, adcxx_show_min, NULL, 0), | ||
146 | SENSOR_ATTR(in_max, S_IWUSR | S_IRUGO, adcxx_show_max, | ||
147 | adcxx_set_max, 0), | ||
148 | SENSOR_ATTR(in0_input, S_IRUGO, adcxx_read, NULL, 0), | ||
149 | SENSOR_ATTR(in1_input, S_IRUGO, adcxx_read, NULL, 1), | ||
150 | SENSOR_ATTR(in2_input, S_IRUGO, adcxx_read, NULL, 2), | ||
151 | SENSOR_ATTR(in3_input, S_IRUGO, adcxx_read, NULL, 3), | ||
152 | SENSOR_ATTR(in4_input, S_IRUGO, adcxx_read, NULL, 4), | ||
153 | SENSOR_ATTR(in5_input, S_IRUGO, adcxx_read, NULL, 5), | ||
154 | SENSOR_ATTR(in6_input, S_IRUGO, adcxx_read, NULL, 6), | ||
155 | SENSOR_ATTR(in7_input, S_IRUGO, adcxx_read, NULL, 7), | ||
156 | }; | ||
157 | |||
158 | /*----------------------------------------------------------------------*/ | ||
159 | |||
160 | static int __devinit adcxx_probe(struct spi_device *spi, int channels) | ||
161 | { | ||
162 | struct adcxx *adc; | ||
163 | int status; | ||
164 | int i; | ||
165 | |||
166 | adc = kzalloc(sizeof *adc, GFP_KERNEL); | ||
167 | if (!adc) | ||
168 | return -ENOMEM; | ||
169 | |||
170 | /* set a default value for the reference */ | ||
171 | adc->reference = 3300; | ||
172 | adc->channels = channels; | ||
173 | mutex_init(&adc->lock); | ||
174 | |||
175 | mutex_lock(&adc->lock); | ||
176 | |||
177 | dev_set_drvdata(&spi->dev, adc); | ||
178 | |||
179 | for (i = 0; i < 3 + adc->channels; i++) { | ||
180 | status = device_create_file(&spi->dev, &ad_input[i].dev_attr); | ||
181 | if (status) { | ||
182 | dev_err(&spi->dev, "device_create_file failed.\n"); | ||
183 | goto out_err; | ||
184 | } | ||
185 | } | ||
186 | |||
187 | adc->hwmon_dev = hwmon_device_register(&spi->dev); | ||
188 | if (IS_ERR(adc->hwmon_dev)) { | ||
189 | dev_err(&spi->dev, "hwmon_device_register failed.\n"); | ||
190 | status = PTR_ERR(adc->hwmon_dev); | ||
191 | goto out_err; | ||
192 | } | ||
193 | |||
194 | mutex_unlock(&adc->lock); | ||
195 | return 0; | ||
196 | |||
197 | out_err: | ||
198 | for (i--; i >= 0; i--) | ||
199 | device_remove_file(&spi->dev, &ad_input[i].dev_attr); | ||
200 | |||
201 | dev_set_drvdata(&spi->dev, NULL); | ||
202 | mutex_unlock(&adc->lock); | ||
203 | kfree(adc); | ||
204 | return status; | ||
205 | } | ||
206 | |||
207 | static int __devinit adcxx1s_probe(struct spi_device *spi) | ||
208 | { | ||
209 | return adcxx_probe(spi, 1); | ||
210 | } | ||
211 | |||
212 | static int __devinit adcxx2s_probe(struct spi_device *spi) | ||
213 | { | ||
214 | return adcxx_probe(spi, 2); | ||
215 | } | ||
216 | |||
217 | static int __devinit adcxx4s_probe(struct spi_device *spi) | ||
218 | { | ||
219 | return adcxx_probe(spi, 4); | ||
220 | } | ||
221 | |||
222 | static int __devinit adcxx8s_probe(struct spi_device *spi) | ||
223 | { | ||
224 | return adcxx_probe(spi, 8); | ||
225 | } | ||
226 | |||
227 | static int __devexit adcxx_remove(struct spi_device *spi) | ||
228 | { | ||
229 | struct adcxx *adc = dev_get_drvdata(&spi->dev); | ||
230 | int i; | ||
231 | |||
232 | mutex_lock(&adc->lock); | ||
233 | hwmon_device_unregister(adc->hwmon_dev); | ||
234 | for (i = 0; i < 3 + adc->channels; i++) | ||
235 | device_remove_file(&spi->dev, &ad_input[i].dev_attr); | ||
236 | |||
237 | dev_set_drvdata(&spi->dev, NULL); | ||
238 | mutex_unlock(&adc->lock); | ||
239 | kfree(adc); | ||
240 | |||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | static struct spi_driver adcxx1s_driver = { | ||
245 | .driver = { | ||
246 | .name = "adcxx1s", | ||
247 | .owner = THIS_MODULE, | ||
248 | }, | ||
249 | .probe = adcxx1s_probe, | ||
250 | .remove = __devexit_p(adcxx_remove), | ||
251 | }; | ||
252 | |||
253 | static struct spi_driver adcxx2s_driver = { | ||
254 | .driver = { | ||
255 | .name = "adcxx2s", | ||
256 | .owner = THIS_MODULE, | ||
257 | }, | ||
258 | .probe = adcxx2s_probe, | ||
259 | .remove = __devexit_p(adcxx_remove), | ||
260 | }; | ||
261 | |||
262 | static struct spi_driver adcxx4s_driver = { | ||
263 | .driver = { | ||
264 | .name = "adcxx4s", | ||
265 | .owner = THIS_MODULE, | ||
266 | }, | ||
267 | .probe = adcxx4s_probe, | ||
268 | .remove = __devexit_p(adcxx_remove), | ||
269 | }; | ||
270 | |||
271 | static struct spi_driver adcxx8s_driver = { | ||
272 | .driver = { | ||
273 | .name = "adcxx8s", | ||
274 | .owner = THIS_MODULE, | ||
275 | }, | ||
276 | .probe = adcxx8s_probe, | ||
277 | .remove = __devexit_p(adcxx_remove), | ||
278 | }; | ||
279 | |||
280 | static int __init init_adcxx(void) | ||
281 | { | ||
282 | int status; | ||
283 | status = spi_register_driver(&adcxx1s_driver); | ||
284 | if (status) | ||
285 | goto reg_1_failed; | ||
286 | |||
287 | status = spi_register_driver(&adcxx2s_driver); | ||
288 | if (status) | ||
289 | goto reg_2_failed; | ||
290 | |||
291 | status = spi_register_driver(&adcxx4s_driver); | ||
292 | if (status) | ||
293 | goto reg_4_failed; | ||
294 | |||
295 | status = spi_register_driver(&adcxx8s_driver); | ||
296 | if (status) | ||
297 | goto reg_8_failed; | ||
298 | |||
299 | return status; | ||
300 | |||
301 | reg_8_failed: | ||
302 | spi_unregister_driver(&adcxx4s_driver); | ||
303 | reg_4_failed: | ||
304 | spi_unregister_driver(&adcxx2s_driver); | ||
305 | reg_2_failed: | ||
306 | spi_unregister_driver(&adcxx1s_driver); | ||
307 | reg_1_failed: | ||
308 | return status; | ||
309 | } | ||
310 | |||
311 | static void __exit exit_adcxx(void) | ||
312 | { | ||
313 | spi_unregister_driver(&adcxx1s_driver); | ||
314 | spi_unregister_driver(&adcxx2s_driver); | ||
315 | spi_unregister_driver(&adcxx4s_driver); | ||
316 | spi_unregister_driver(&adcxx8s_driver); | ||
317 | } | ||
318 | |||
319 | module_init(init_adcxx); | ||
320 | module_exit(exit_adcxx); | ||
321 | |||
322 | MODULE_AUTHOR("Marc Pignat"); | ||
323 | MODULE_DESCRIPTION("National Semiconductor adcxx8sxxx Linux driver"); | ||
324 | MODULE_LICENSE("GPL"); | ||
325 | |||
326 | MODULE_ALIAS("adcxx1s"); | ||
327 | MODULE_ALIAS("adcxx2s"); | ||
328 | MODULE_ALIAS("adcxx4s"); | ||
329 | MODULE_ALIAS("adcxx8s"); | ||
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index aacc0c4b809c..b06b8e090a27 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c | |||
@@ -98,6 +98,12 @@ static const char* temperature_sensors_sets[][36] = { | |||
98 | "TH1P", "TH2P", "TH3P", "TMAP", "TMAS", "TMBS", "TM0P", "TM0S", | 98 | "TH1P", "TH2P", "TH3P", "TMAP", "TMAS", "TMBS", "TM0P", "TM0S", |
99 | "TM1P", "TM1S", "TM2P", "TM2S", "TM3S", "TM8P", "TM8S", "TM9P", | 99 | "TM1P", "TM1S", "TM2P", "TM2S", "TM3S", "TM8P", "TM8S", "TM9P", |
100 | "TM9S", "TN0H", "TS0C", NULL }, | 100 | "TM9S", "TN0H", "TS0C", NULL }, |
101 | /* Set 5: iMac */ | ||
102 | { "TC0D", "TA0P", "TG0P", "TG0D", "TG0H", "TH0P", "Tm0P", "TO0P", | ||
103 | "Tp0C", NULL }, | ||
104 | /* Set 6: Macbook3 set */ | ||
105 | { "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TTF0", "TW0P", "Th0H", | ||
106 | "Th0S", "Th1H", NULL }, | ||
101 | }; | 107 | }; |
102 | 108 | ||
103 | /* List of keys used to read/write fan speeds */ | 109 | /* List of keys used to read/write fan speeds */ |
@@ -1223,6 +1229,10 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = { | |||
1223 | { .accelerometer = 0, .light = 0, .temperature_set = 3 }, | 1229 | { .accelerometer = 0, .light = 0, .temperature_set = 3 }, |
1224 | /* MacPro: temperature set 4 */ | 1230 | /* MacPro: temperature set 4 */ |
1225 | { .accelerometer = 0, .light = 0, .temperature_set = 4 }, | 1231 | { .accelerometer = 0, .light = 0, .temperature_set = 4 }, |
1232 | /* iMac: temperature set 5 */ | ||
1233 | { .accelerometer = 0, .light = 0, .temperature_set = 5 }, | ||
1234 | /* MacBook3: accelerometer and temperature set 6 */ | ||
1235 | { .accelerometer = 1, .light = 0, .temperature_set = 6 }, | ||
1226 | }; | 1236 | }; |
1227 | 1237 | ||
1228 | /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". | 1238 | /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". |
@@ -1232,10 +1242,14 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = { | |||
1232 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), | 1242 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), |
1233 | DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro") }, | 1243 | DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro") }, |
1234 | (void*)&applesmc_dmi_data[0]}, | 1244 | (void*)&applesmc_dmi_data[0]}, |
1235 | { applesmc_dmi_match, "Apple MacBook", { | 1245 | { applesmc_dmi_match, "Apple MacBook (v2)", { |
1236 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), | 1246 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), |
1237 | DMI_MATCH(DMI_PRODUCT_NAME,"MacBook2") }, | 1247 | DMI_MATCH(DMI_PRODUCT_NAME,"MacBook2") }, |
1238 | (void*)&applesmc_dmi_data[1]}, | 1248 | (void*)&applesmc_dmi_data[1]}, |
1249 | { applesmc_dmi_match, "Apple MacBook (v3)", { | ||
1250 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), | ||
1251 | DMI_MATCH(DMI_PRODUCT_NAME,"MacBook3") }, | ||
1252 | (void*)&applesmc_dmi_data[6]}, | ||
1239 | { applesmc_dmi_match, "Apple MacBook", { | 1253 | { applesmc_dmi_match, "Apple MacBook", { |
1240 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), | 1254 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), |
1241 | DMI_MATCH(DMI_PRODUCT_NAME,"MacBook") }, | 1255 | DMI_MATCH(DMI_PRODUCT_NAME,"MacBook") }, |
@@ -1248,6 +1262,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = { | |||
1248 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), | 1262 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), |
1249 | DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") }, | 1263 | DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") }, |
1250 | (void*)&applesmc_dmi_data[4]}, | 1264 | (void*)&applesmc_dmi_data[4]}, |
1265 | { applesmc_dmi_match, "Apple iMac", { | ||
1266 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), | ||
1267 | DMI_MATCH(DMI_PRODUCT_NAME,"iMac") }, | ||
1268 | (void*)&applesmc_dmi_data[5]}, | ||
1251 | { .ident = NULL } | 1269 | { .ident = NULL } |
1252 | }; | 1270 | }; |
1253 | 1271 | ||
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 70239acecc8e..93c17223b527 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c | |||
@@ -413,10 +413,11 @@ static int __init coretemp_init(void) | |||
413 | for_each_online_cpu(i) { | 413 | for_each_online_cpu(i) { |
414 | struct cpuinfo_x86 *c = &cpu_data(i); | 414 | struct cpuinfo_x86 *c = &cpu_data(i); |
415 | 415 | ||
416 | /* check if family 6, models 0xe, 0xf, 0x16, 0x17 */ | 416 | /* check if family 6, models 0xe, 0xf, 0x16, 0x17, 0x1A */ |
417 | if ((c->cpuid_level < 0) || (c->x86 != 0x6) || | 417 | if ((c->cpuid_level < 0) || (c->x86 != 0x6) || |
418 | !((c->x86_model == 0xe) || (c->x86_model == 0xf) || | 418 | !((c->x86_model == 0xe) || (c->x86_model == 0xf) || |
419 | (c->x86_model == 0x16) || (c->x86_model == 0x17))) { | 419 | (c->x86_model == 0x16) || (c->x86_model == 0x17) || |
420 | (c->x86_model == 0x1A))) { | ||
420 | 421 | ||
421 | /* supported CPU not found, but report the unknown | 422 | /* supported CPU not found, but report the unknown |
422 | family 6 CPU */ | 423 | family 6 CPU */ |
diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c index 7b0a32c4dcfb..c54eff92be4a 100644 --- a/drivers/hwmon/hwmon-vid.c +++ b/drivers/hwmon/hwmon-vid.c | |||
@@ -37,13 +37,21 @@ | |||
37 | * For VRD 10.0 and up, "VRD x.y Design Guide", | 37 | * For VRD 10.0 and up, "VRD x.y Design Guide", |
38 | * available at http://developer.intel.com/. | 38 | * available at http://developer.intel.com/. |
39 | * | 39 | * |
40 | * AMD NPT 0Fh (Athlon64 & Opteron), AMD Publication 32559, | 40 | * AMD Athlon 64 and AMD Opteron Processors, AMD Publication 26094, |
41 | * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/26094.PDF | ||
42 | * Table 74. VID Code Voltages | ||
43 | * This corresponds to an arbitrary VRM code of 24 in the functions below. | ||
44 | * These CPU models (K8 revision <= E) have 5 VID pins. See also: | ||
45 | * Revision Guide for AMD Athlon 64 and AMD Opteron Processors, AMD Publication 25759, | ||
46 | * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/25759.pdf | ||
47 | * | ||
48 | * AMD NPT Family 0Fh Processors, AMD Publication 32559, | ||
41 | * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/32559.pdf | 49 | * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/32559.pdf |
42 | * Table 71. VID Code Voltages | 50 | * Table 71. VID Code Voltages |
43 | * AMD Opteron processors don't follow the Intel specifications. | 51 | * This corresponds to an arbitrary VRM code of 25 in the functions below. |
44 | * I'm going to "make up" 2.4 as the spec number for the Opterons. | 52 | * These CPU models (K8 revision >= F) have 6 VID pins. See also: |
45 | * No good reason just a mnemonic for the 24x Opteron processor | 53 | * Revision Guide for AMD NPT Family 0Fh Processors, AMD Publication 33610, |
46 | * series. | 54 | * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/33610.pdf |
47 | * | 55 | * |
48 | * The 17 specification is in fact Intel Mobile Voltage Positioning - | 56 | * The 17 specification is in fact Intel Mobile Voltage Positioning - |
49 | * (IMVP-II). You can find more information in the datasheet of Max1718 | 57 | * (IMVP-II). You can find more information in the datasheet of Max1718 |
@@ -95,7 +103,12 @@ int vid_from_reg(int val, u8 vrm) | |||
95 | return 0; | 103 | return 0; |
96 | return((1600000 - (val - 2) * 6250 + 500) / 1000); | 104 | return((1600000 - (val - 2) * 6250 + 500) / 1000); |
97 | 105 | ||
98 | case 24: /* AMD NPT 0Fh (Athlon64 & Opteron) */ | 106 | case 24: /* Athlon64 & Opteron */ |
107 | val &= 0x1f; | ||
108 | if (val == 0x1f) | ||
109 | return 0; | ||
110 | /* fall through */ | ||
111 | case 25: /* AMD NPT 0Fh */ | ||
99 | val &= 0x3f; | 112 | val &= 0x3f; |
100 | return (val < 32) ? 1550 - 25 * val | 113 | return (val < 32) ? 1550 - 25 * val |
101 | : 775 - (25 * (val - 31)) / 2; | 114 | : 775 - (25 * (val - 31)) / 2; |
@@ -157,11 +170,16 @@ struct vrm_model { | |||
157 | 170 | ||
158 | #ifdef CONFIG_X86 | 171 | #ifdef CONFIG_X86 |
159 | 172 | ||
160 | /* the stepping parameter is highest acceptable stepping for current line */ | 173 | /* |
174 | * The stepping parameter is highest acceptable stepping for current line. | ||
175 | * The model match must be exact for 4-bit values. For model values 0x10 | ||
176 | * and above (extended model), all models below the parameter will match. | ||
177 | */ | ||
161 | 178 | ||
162 | static struct vrm_model vrm_models[] = { | 179 | static struct vrm_model vrm_models[] = { |
163 | {X86_VENDOR_AMD, 0x6, ANY, ANY, 90}, /* Athlon Duron etc */ | 180 | {X86_VENDOR_AMD, 0x6, ANY, ANY, 90}, /* Athlon Duron etc */ |
164 | {X86_VENDOR_AMD, 0xF, ANY, ANY, 24}, /* Athlon 64, Opteron and above VRM 24 */ | 181 | {X86_VENDOR_AMD, 0xF, 0x3F, ANY, 24}, /* Athlon 64, Opteron */ |
182 | {X86_VENDOR_AMD, 0xF, ANY, ANY, 25}, /* NPT family 0Fh */ | ||
165 | {X86_VENDOR_INTEL, 0x6, 0x9, ANY, 13}, /* Pentium M (130 nm) */ | 183 | {X86_VENDOR_INTEL, 0x6, 0x9, ANY, 13}, /* Pentium M (130 nm) */ |
166 | {X86_VENDOR_INTEL, 0x6, 0xB, ANY, 85}, /* Tualatin */ | 184 | {X86_VENDOR_INTEL, 0x6, 0xB, ANY, 85}, /* Tualatin */ |
167 | {X86_VENDOR_INTEL, 0x6, 0xD, ANY, 13}, /* Pentium M (90 nm) */ | 185 | {X86_VENDOR_INTEL, 0x6, 0xD, ANY, 13}, /* Pentium M (90 nm) */ |
@@ -189,6 +207,8 @@ static u8 find_vrm(u8 eff_family, u8 eff_model, u8 eff_stepping, u8 vendor) | |||
189 | if (vrm_models[i].vendor==vendor) | 207 | if (vrm_models[i].vendor==vendor) |
190 | if ((vrm_models[i].eff_family==eff_family) | 208 | if ((vrm_models[i].eff_family==eff_family) |
191 | && ((vrm_models[i].eff_model==eff_model) || | 209 | && ((vrm_models[i].eff_model==eff_model) || |
210 | (vrm_models[i].eff_model >= 0x10 && | ||
211 | eff_model <= vrm_models[i].eff_model) || | ||
192 | (vrm_models[i].eff_model==ANY)) && | 212 | (vrm_models[i].eff_model==ANY)) && |
193 | (eff_stepping <= vrm_models[i].eff_stepping)) | 213 | (eff_stepping <= vrm_models[i].eff_stepping)) |
194 | return vrm_models[i].vrm_type; | 214 | return vrm_models[i].vrm_type; |
diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c index f9e2ed621f7b..2ede9388096b 100644 --- a/drivers/hwmon/i5k_amb.c +++ b/drivers/hwmon/i5k_amb.c | |||
@@ -81,6 +81,8 @@ static unsigned long amb_reg_temp(unsigned int amb) | |||
81 | #define MAX_AMBS_PER_CHANNEL 16 | 81 | #define MAX_AMBS_PER_CHANNEL 16 |
82 | #define MAX_AMBS (MAX_MEM_CHANNELS * \ | 82 | #define MAX_AMBS (MAX_MEM_CHANNELS * \ |
83 | MAX_AMBS_PER_CHANNEL) | 83 | MAX_AMBS_PER_CHANNEL) |
84 | #define CHANNEL_SHIFT 4 | ||
85 | #define DIMM_MASK 0xF | ||
84 | /* | 86 | /* |
85 | * Ugly hack: For some reason the highest bit is set if there | 87 | * Ugly hack: For some reason the highest bit is set if there |
86 | * are _any_ DIMMs in the channel. Attempting to read from | 88 | * are _any_ DIMMs in the channel. Attempting to read from |
@@ -89,7 +91,7 @@ static unsigned long amb_reg_temp(unsigned int amb) | |||
89 | * might prevent us from seeing the 16th DIMM in the channel. | 91 | * might prevent us from seeing the 16th DIMM in the channel. |
90 | */ | 92 | */ |
91 | #define REAL_MAX_AMBS_PER_CHANNEL 15 | 93 | #define REAL_MAX_AMBS_PER_CHANNEL 15 |
92 | #define KNOBS_PER_AMB 5 | 94 | #define KNOBS_PER_AMB 6 |
93 | 95 | ||
94 | static unsigned long amb_num_from_reg(unsigned int byte_num, unsigned int bit) | 96 | static unsigned long amb_num_from_reg(unsigned int byte_num, unsigned int bit) |
95 | { | 97 | { |
@@ -238,6 +240,16 @@ static ssize_t show_amb_temp(struct device *dev, | |||
238 | 500 * amb_read_byte(data, amb_reg_temp(attr->index))); | 240 | 500 * amb_read_byte(data, amb_reg_temp(attr->index))); |
239 | } | 241 | } |
240 | 242 | ||
243 | static ssize_t show_label(struct device *dev, | ||
244 | struct device_attribute *devattr, | ||
245 | char *buf) | ||
246 | { | ||
247 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
248 | |||
249 | return sprintf(buf, "Ch. %d DIMM %d\n", attr->index >> CHANNEL_SHIFT, | ||
250 | attr->index & DIMM_MASK); | ||
251 | } | ||
252 | |||
241 | static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev) | 253 | static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev) |
242 | { | 254 | { |
243 | int i, j, k, d = 0; | 255 | int i, j, k, d = 0; |
@@ -268,6 +280,20 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev) | |||
268 | continue; | 280 | continue; |
269 | d++; | 281 | d++; |
270 | 282 | ||
283 | /* sysfs label */ | ||
284 | iattr = data->attrs + data->num_attrs; | ||
285 | snprintf(iattr->name, AMB_SYSFS_NAME_LEN, | ||
286 | "temp%d_label", d); | ||
287 | iattr->s_attr.dev_attr.attr.name = iattr->name; | ||
288 | iattr->s_attr.dev_attr.attr.mode = S_IRUGO; | ||
289 | iattr->s_attr.dev_attr.show = show_label; | ||
290 | iattr->s_attr.index = k; | ||
291 | res = device_create_file(&pdev->dev, | ||
292 | &iattr->s_attr.dev_attr); | ||
293 | if (res) | ||
294 | goto exit_remove; | ||
295 | data->num_attrs++; | ||
296 | |||
271 | /* Temperature sysfs knob */ | 297 | /* Temperature sysfs knob */ |
272 | iattr = data->attrs + data->num_attrs; | 298 | iattr = data->attrs + data->num_attrs; |
273 | snprintf(iattr->name, AMB_SYSFS_NAME_LEN, | 299 | snprintf(iattr->name, AMB_SYSFS_NAME_LEN, |
diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c index c9416e657487..0f70dc204105 100644 --- a/drivers/hwmon/ibmaem.c +++ b/drivers/hwmon/ibmaem.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * A hwmon driver for the IBM Active Energy Manager temperature/power sensors | 2 | * A hwmon driver for the IBM System Director Active Energy Manager (AEM) |
3 | * and capping functionality. | 3 | * temperature/power/energy sensors and capping functionality. |
4 | * Copyright (C) 2008 IBM | 4 | * Copyright (C) 2008 IBM |
5 | * | 5 | * |
6 | * Author: Darrick J. Wong <djwong@us.ibm.com> | 6 | * Author: Darrick J. Wong <djwong@us.ibm.com> |
@@ -463,12 +463,18 @@ static int aem_read_sensor(struct aem_data *data, u8 elt, u8 reg, | |||
463 | } | 463 | } |
464 | 464 | ||
465 | /* Update AEM energy registers */ | 465 | /* Update AEM energy registers */ |
466 | static void update_aem_energy_one(struct aem_data *data, int which) | ||
467 | { | ||
468 | aem_read_sensor(data, AEM_ENERGY_ELEMENT, which, | ||
469 | &data->energy[which], 8); | ||
470 | } | ||
471 | |||
466 | static void update_aem_energy(struct aem_data *data) | 472 | static void update_aem_energy(struct aem_data *data) |
467 | { | 473 | { |
468 | aem_read_sensor(data, AEM_ENERGY_ELEMENT, 0, &data->energy[0], 8); | 474 | update_aem_energy_one(data, 0); |
469 | if (data->ver_major < 2) | 475 | if (data->ver_major < 2) |
470 | return; | 476 | return; |
471 | aem_read_sensor(data, AEM_ENERGY_ELEMENT, 1, &data->energy[1], 8); | 477 | update_aem_energy_one(data, 1); |
472 | } | 478 | } |
473 | 479 | ||
474 | /* Update all AEM1 sensors */ | 480 | /* Update all AEM1 sensors */ |
@@ -676,7 +682,8 @@ static int aem_find_aem2(struct aem_ipmi_data *data, | |||
676 | return -ETIMEDOUT; | 682 | return -ETIMEDOUT; |
677 | 683 | ||
678 | if (data->rx_result || data->rx_msg_len != sizeof(*fi_resp) || | 684 | if (data->rx_result || data->rx_msg_len != sizeof(*fi_resp) || |
679 | memcmp(&fi_resp->id, &system_x_id, sizeof(system_x_id))) | 685 | memcmp(&fi_resp->id, &system_x_id, sizeof(system_x_id)) || |
686 | fi_resp->num_instances <= instance_num) | ||
680 | return -ENOENT; | 687 | return -ENOENT; |
681 | 688 | ||
682 | return 0; | 689 | return 0; |
@@ -849,7 +856,7 @@ static ssize_t aem_show_power(struct device *dev, | |||
849 | struct timespec b, a; | 856 | struct timespec b, a; |
850 | 857 | ||
851 | mutex_lock(&data->lock); | 858 | mutex_lock(&data->lock); |
852 | update_aem_energy(data); | 859 | update_aem_energy_one(data, attr->index); |
853 | getnstimeofday(&b); | 860 | getnstimeofday(&b); |
854 | before = data->energy[attr->index]; | 861 | before = data->energy[attr->index]; |
855 | 862 | ||
@@ -861,7 +868,7 @@ static ssize_t aem_show_power(struct device *dev, | |||
861 | return 0; | 868 | return 0; |
862 | } | 869 | } |
863 | 870 | ||
864 | update_aem_energy(data); | 871 | update_aem_energy_one(data, attr->index); |
865 | getnstimeofday(&a); | 872 | getnstimeofday(&a); |
866 | after = data->energy[attr->index]; | 873 | after = data->energy[attr->index]; |
867 | mutex_unlock(&data->lock); | 874 | mutex_unlock(&data->lock); |
@@ -880,7 +887,9 @@ static ssize_t aem_show_energy(struct device *dev, | |||
880 | { | 887 | { |
881 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 888 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
882 | struct aem_data *a = dev_get_drvdata(dev); | 889 | struct aem_data *a = dev_get_drvdata(dev); |
883 | a->update(a); | 890 | mutex_lock(&a->lock); |
891 | update_aem_energy_one(a, attr->index); | ||
892 | mutex_unlock(&a->lock); | ||
884 | 893 | ||
885 | return sprintf(buf, "%llu\n", | 894 | return sprintf(buf, "%llu\n", |
886 | (unsigned long long)a->energy[attr->index] * 1000); | 895 | (unsigned long long)a->energy[attr->index] * 1000); |
@@ -1104,7 +1113,7 @@ static void __exit aem_exit(void) | |||
1104 | } | 1113 | } |
1105 | 1114 | ||
1106 | MODULE_AUTHOR("Darrick J. Wong <djwong@us.ibm.com>"); | 1115 | MODULE_AUTHOR("Darrick J. Wong <djwong@us.ibm.com>"); |
1107 | MODULE_DESCRIPTION("IBM Active Energy Manager power/temp sensor driver"); | 1116 | MODULE_DESCRIPTION("IBM AEM power/temp/energy sensor driver"); |
1108 | MODULE_LICENSE("GPL"); | 1117 | MODULE_LICENSE("GPL"); |
1109 | 1118 | ||
1110 | module_init(aem_init); | 1119 | module_init(aem_init); |
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c index daa7d121483b..de21142d106c 100644 --- a/drivers/hwmon/w83791d.c +++ b/drivers/hwmon/w83791d.c | |||
@@ -1055,9 +1055,10 @@ static int w83791d_probe(struct i2c_client *client, | |||
1055 | { | 1055 | { |
1056 | struct w83791d_data *data; | 1056 | struct w83791d_data *data; |
1057 | struct device *dev = &client->dev; | 1057 | struct device *dev = &client->dev; |
1058 | int i, val1, err; | 1058 | int i, err; |
1059 | 1059 | ||
1060 | #ifdef DEBUG | 1060 | #ifdef DEBUG |
1061 | int val1; | ||
1061 | val1 = w83791d_read(client, W83791D_REG_DID_VID4); | 1062 | val1 = w83791d_read(client, W83791D_REG_DID_VID4); |
1062 | dev_dbg(dev, "Device ID version: %d.%d (0x%02x)\n", | 1063 | dev_dbg(dev, "Device ID version: %d.%d (0x%02x)\n", |
1063 | (val1 >> 5) & 0x07, (val1 >> 1) & 0x0f, val1); | 1064 | (val1 >> 5) & 0x07, (val1 >> 1) & 0x0f, val1); |
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 2d65411f6763..a92d81567559 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
@@ -647,6 +647,47 @@ static int str_to_user(const char *str, unsigned int maxlen, void __user *p) | |||
647 | return copy_to_user(p, str, len) ? -EFAULT : len; | 647 | return copy_to_user(p, str, len) ? -EFAULT : len; |
648 | } | 648 | } |
649 | 649 | ||
650 | #define OLD_KEY_MAX 0x1ff | ||
651 | static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user *p, int compat_mode) | ||
652 | { | ||
653 | static unsigned long keymax_warn_time; | ||
654 | unsigned long *bits; | ||
655 | int len; | ||
656 | |||
657 | switch (_IOC_NR(cmd) & EV_MAX) { | ||
658 | |||
659 | case 0: bits = dev->evbit; len = EV_MAX; break; | ||
660 | case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; | ||
661 | case EV_REL: bits = dev->relbit; len = REL_MAX; break; | ||
662 | case EV_ABS: bits = dev->absbit; len = ABS_MAX; break; | ||
663 | case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break; | ||
664 | case EV_LED: bits = dev->ledbit; len = LED_MAX; break; | ||
665 | case EV_SND: bits = dev->sndbit; len = SND_MAX; break; | ||
666 | case EV_FF: bits = dev->ffbit; len = FF_MAX; break; | ||
667 | case EV_SW: bits = dev->swbit; len = SW_MAX; break; | ||
668 | default: return -EINVAL; | ||
669 | } | ||
670 | |||
671 | /* | ||
672 | * Work around bugs in userspace programs that like to do | ||
673 | * EVIOCGBIT(EV_KEY, KEY_MAX) and not realize that 'len' | ||
674 | * should be in bytes, not in bits. | ||
675 | */ | ||
676 | if ((_IOC_NR(cmd) & EV_MAX) == EV_KEY && _IOC_SIZE(cmd) == OLD_KEY_MAX) { | ||
677 | len = OLD_KEY_MAX; | ||
678 | if (printk_timed_ratelimit(&keymax_warn_time, 10 * 1000)) | ||
679 | printk(KERN_WARNING | ||
680 | "evdev.c(EVIOCGBIT): Suspicious buffer size %d, " | ||
681 | "limiting output to %d bytes. See " | ||
682 | "http://userweb.kernel.org/~dtor/eviocgbit-bug.html\n", | ||
683 | OLD_KEY_MAX, | ||
684 | BITS_TO_LONGS(OLD_KEY_MAX) * sizeof(long)); | ||
685 | } | ||
686 | |||
687 | return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode); | ||
688 | } | ||
689 | #undef OLD_KEY_MAX | ||
690 | |||
650 | static long evdev_do_ioctl(struct file *file, unsigned int cmd, | 691 | static long evdev_do_ioctl(struct file *file, unsigned int cmd, |
651 | void __user *p, int compat_mode) | 692 | void __user *p, int compat_mode) |
652 | { | 693 | { |
@@ -733,26 +774,8 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
733 | 774 | ||
734 | if (_IOC_DIR(cmd) == _IOC_READ) { | 775 | if (_IOC_DIR(cmd) == _IOC_READ) { |
735 | 776 | ||
736 | if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0))) { | 777 | if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0))) |
737 | 778 | return handle_eviocgbit(dev, cmd, p, compat_mode); | |
738 | unsigned long *bits; | ||
739 | int len; | ||
740 | |||
741 | switch (_IOC_NR(cmd) & EV_MAX) { | ||
742 | |||
743 | case 0: bits = dev->evbit; len = EV_MAX; break; | ||
744 | case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; | ||
745 | case EV_REL: bits = dev->relbit; len = REL_MAX; break; | ||
746 | case EV_ABS: bits = dev->absbit; len = ABS_MAX; break; | ||
747 | case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break; | ||
748 | case EV_LED: bits = dev->ledbit; len = LED_MAX; break; | ||
749 | case EV_SND: bits = dev->sndbit; len = SND_MAX; break; | ||
750 | case EV_FF: bits = dev->ffbit; len = FF_MAX; break; | ||
751 | case EV_SW: bits = dev->swbit; len = SW_MAX; break; | ||
752 | default: return -EINVAL; | ||
753 | } | ||
754 | return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode); | ||
755 | } | ||
756 | 779 | ||
757 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) | 780 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) |
758 | return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd), | 781 | return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd), |
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 87d3e7eabffd..6791be81eb29 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c | |||
@@ -127,6 +127,7 @@ static const struct xpad_device { | |||
127 | { 0x0738, 0x4716, "Mad Catz Wired Xbox 360 Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, | 127 | { 0x0738, 0x4716, "Mad Catz Wired Xbox 360 Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, |
128 | { 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, | 128 | { 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, |
129 | { 0x0c12, 0x8802, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 129 | { 0x0c12, 0x8802, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
130 | { 0x0c12, 0x880a, "Pelican Eclipse PL-2023", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | ||
130 | { 0x0c12, 0x8810, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 131 | { 0x0c12, 0x8810, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
131 | { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 132 | { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
132 | { 0x0e4c, 0x1097, "Radica Gamester Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 133 | { 0x0e4c, 0x1097, "Radica Gamester Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index be58730e636a..3f48279f2195 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c | |||
@@ -118,6 +118,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
118 | unsigned int type = button->type ?: EV_KEY; | 118 | unsigned int type = button->type ?: EV_KEY; |
119 | 119 | ||
120 | bdata->input = input; | 120 | bdata->input = input; |
121 | bdata->button = button; | ||
121 | setup_timer(&bdata->timer, | 122 | setup_timer(&bdata->timer, |
122 | gpio_check_button, (unsigned long)bdata); | 123 | gpio_check_button, (unsigned long)bdata); |
123 | 124 | ||
@@ -256,7 +257,7 @@ static int gpio_keys_resume(struct platform_device *pdev) | |||
256 | #define gpio_keys_resume NULL | 257 | #define gpio_keys_resume NULL |
257 | #endif | 258 | #endif |
258 | 259 | ||
259 | struct platform_driver gpio_keys_device_driver = { | 260 | static struct platform_driver gpio_keys_device_driver = { |
260 | .probe = gpio_keys_probe, | 261 | .probe = gpio_keys_probe, |
261 | .remove = __devexit_p(gpio_keys_remove), | 262 | .remove = __devexit_p(gpio_keys_remove), |
262 | .suspend = gpio_keys_suspend, | 263 | .suspend = gpio_keys_suspend, |
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 7bbea097cda2..f996546fc443 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig | |||
@@ -130,6 +130,29 @@ config MOUSE_APPLETOUCH | |||
130 | To compile this driver as a module, choose M here: the | 130 | To compile this driver as a module, choose M here: the |
131 | module will be called appletouch. | 131 | module will be called appletouch. |
132 | 132 | ||
133 | config MOUSE_BCM5974 | ||
134 | tristate "Apple USB BCM5974 Multitouch trackpad support" | ||
135 | depends on USB_ARCH_HAS_HCD | ||
136 | select USB | ||
137 | help | ||
138 | Say Y here if you have an Apple USB BCM5974 Multitouch | ||
139 | trackpad. | ||
140 | |||
141 | The BCM5974 is the multitouch trackpad found in the Macbook | ||
142 | Air (JAN2008) and Macbook Pro Penryn (FEB2008) laptops. | ||
143 | |||
144 | It is also found in the IPhone (2007) and Ipod Touch (2008). | ||
145 | |||
146 | This driver provides multitouch functionality together with | ||
147 | the synaptics X11 driver. | ||
148 | |||
149 | The interface is currently identical to the appletouch interface, | ||
150 | for further information, see | ||
151 | <file:Documentation/input/appletouch.txt>. | ||
152 | |||
153 | To compile this driver as a module, choose M here: the | ||
154 | module will be called bcm5974. | ||
155 | |||
133 | config MOUSE_INPORT | 156 | config MOUSE_INPORT |
134 | tristate "InPort/MS/ATIXL busmouse" | 157 | tristate "InPort/MS/ATIXL busmouse" |
135 | depends on ISA | 158 | depends on ISA |
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 9e6e36330820..d4d202516090 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile | |||
@@ -6,6 +6,7 @@ | |||
6 | 6 | ||
7 | obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o | 7 | obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o |
8 | obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o | 8 | obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o |
9 | obj-$(CONFIG_MOUSE_BCM5974) += bcm5974.o | ||
9 | obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o | 10 | obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o |
10 | obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o | 11 | obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o |
11 | obj-$(CONFIG_MOUSE_INPORT) += inport.o | 12 | obj-$(CONFIG_MOUSE_INPORT) += inport.o |
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c new file mode 100644 index 000000000000..2ec921bf3c60 --- /dev/null +++ b/drivers/input/mouse/bcm5974.c | |||
@@ -0,0 +1,681 @@ | |||
1 | /* | ||
2 | * Apple USB BCM5974 (Macbook Air and Penryn Macbook Pro) multitouch driver | ||
3 | * | ||
4 | * Copyright (C) 2008 Henrik Rydberg (rydberg@euromail.se) | ||
5 | * | ||
6 | * The USB initialization and package decoding was made by | ||
7 | * Scott Shawcroft as part of the touchd user-space driver project: | ||
8 | * Copyright (C) 2008 Scott Shawcroft (scott.shawcroft@gmail.com) | ||
9 | * | ||
10 | * The BCM5974 driver is based on the appletouch driver: | ||
11 | * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) | ||
12 | * Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net) | ||
13 | * Copyright (C) 2005 Stelian Pop (stelian@popies.net) | ||
14 | * Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de) | ||
15 | * Copyright (C) 2005 Peter Osterlund (petero2@telia.com) | ||
16 | * Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch) | ||
17 | * Copyright (C) 2006 Nicolas Boichat (nicolas@boichat.ch) | ||
18 | * | ||
19 | * This program is free software; you can redistribute it and/or modify | ||
20 | * it under the terms of the GNU General Public License as published by | ||
21 | * the Free Software Foundation; either version 2 of the License, or | ||
22 | * (at your option) any later version. | ||
23 | * | ||
24 | * This program is distributed in the hope that it will be useful, | ||
25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
27 | * GNU General Public License for more details. | ||
28 | * | ||
29 | * You should have received a copy of the GNU General Public License | ||
30 | * along with this program; if not, write to the Free Software | ||
31 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
32 | * | ||
33 | */ | ||
34 | |||
35 | #include <linux/kernel.h> | ||
36 | #include <linux/errno.h> | ||
37 | #include <linux/init.h> | ||
38 | #include <linux/slab.h> | ||
39 | #include <linux/module.h> | ||
40 | #include <linux/usb/input.h> | ||
41 | #include <linux/hid.h> | ||
42 | #include <linux/mutex.h> | ||
43 | |||
44 | #define USB_VENDOR_ID_APPLE 0x05ac | ||
45 | |||
46 | /* MacbookAir, aka wellspring */ | ||
47 | #define USB_DEVICE_ID_APPLE_WELLSPRING_ANSI 0x0223 | ||
48 | #define USB_DEVICE_ID_APPLE_WELLSPRING_ISO 0x0224 | ||
49 | #define USB_DEVICE_ID_APPLE_WELLSPRING_JIS 0x0225 | ||
50 | /* MacbookProPenryn, aka wellspring2 */ | ||
51 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230 | ||
52 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231 | ||
53 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232 | ||
54 | |||
55 | #define BCM5974_DEVICE(prod) { \ | ||
56 | .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ | ||
57 | USB_DEVICE_ID_MATCH_INT_CLASS | \ | ||
58 | USB_DEVICE_ID_MATCH_INT_PROTOCOL), \ | ||
59 | .idVendor = USB_VENDOR_ID_APPLE, \ | ||
60 | .idProduct = (prod), \ | ||
61 | .bInterfaceClass = USB_INTERFACE_CLASS_HID, \ | ||
62 | .bInterfaceProtocol = USB_INTERFACE_PROTOCOL_MOUSE \ | ||
63 | } | ||
64 | |||
65 | /* table of devices that work with this driver */ | ||
66 | static const struct usb_device_id bcm5974_table [] = { | ||
67 | /* MacbookAir1.1 */ | ||
68 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_ANSI), | ||
69 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_ISO), | ||
70 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_JIS), | ||
71 | /* MacbookProPenryn */ | ||
72 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI), | ||
73 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ISO), | ||
74 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_JIS), | ||
75 | /* Terminating entry */ | ||
76 | {} | ||
77 | }; | ||
78 | MODULE_DEVICE_TABLE(usb, bcm5974_table); | ||
79 | |||
80 | MODULE_AUTHOR("Henrik Rydberg"); | ||
81 | MODULE_DESCRIPTION("Apple USB BCM5974 multitouch driver"); | ||
82 | MODULE_LICENSE("GPL"); | ||
83 | |||
84 | #define dprintk(level, format, a...)\ | ||
85 | { if (debug >= level) printk(KERN_DEBUG format, ##a); } | ||
86 | |||
87 | static int debug = 1; | ||
88 | module_param(debug, int, 0644); | ||
89 | MODULE_PARM_DESC(debug, "Activate debugging output"); | ||
90 | |||
91 | /* button data structure */ | ||
92 | struct bt_data { | ||
93 | u8 unknown1; /* constant */ | ||
94 | u8 button; /* left button */ | ||
95 | u8 rel_x; /* relative x coordinate */ | ||
96 | u8 rel_y; /* relative y coordinate */ | ||
97 | }; | ||
98 | |||
99 | /* trackpad header structure */ | ||
100 | struct tp_header { | ||
101 | u8 unknown1[16]; /* constants, timers, etc */ | ||
102 | u8 fingers; /* number of fingers on trackpad */ | ||
103 | u8 unknown2[9]; /* constants, timers, etc */ | ||
104 | }; | ||
105 | |||
106 | /* trackpad finger structure */ | ||
107 | struct tp_finger { | ||
108 | __le16 origin; /* left/right origin? */ | ||
109 | __le16 abs_x; /* absolute x coodinate */ | ||
110 | __le16 abs_y; /* absolute y coodinate */ | ||
111 | __le16 rel_x; /* relative x coodinate */ | ||
112 | __le16 rel_y; /* relative y coodinate */ | ||
113 | __le16 size_major; /* finger size, major axis? */ | ||
114 | __le16 size_minor; /* finger size, minor axis? */ | ||
115 | __le16 orientation; /* 16384 when point, else 15 bit angle */ | ||
116 | __le16 force_major; /* trackpad force, major axis? */ | ||
117 | __le16 force_minor; /* trackpad force, minor axis? */ | ||
118 | __le16 unused[3]; /* zeros */ | ||
119 | __le16 multi; /* one finger: varies, more fingers: constant */ | ||
120 | }; | ||
121 | |||
122 | /* trackpad data structure, empirically at least ten fingers */ | ||
123 | struct tp_data { | ||
124 | struct tp_header header; | ||
125 | struct tp_finger finger[16]; | ||
126 | }; | ||
127 | |||
128 | /* device-specific parameters */ | ||
129 | struct bcm5974_param { | ||
130 | int dim; /* logical dimension */ | ||
131 | int fuzz; /* logical noise value */ | ||
132 | int devmin; /* device minimum reading */ | ||
133 | int devmax; /* device maximum reading */ | ||
134 | }; | ||
135 | |||
136 | /* device-specific configuration */ | ||
137 | struct bcm5974_config { | ||
138 | int ansi, iso, jis; /* the product id of this device */ | ||
139 | int bt_ep; /* the endpoint of the button interface */ | ||
140 | int bt_datalen; /* data length of the button interface */ | ||
141 | int tp_ep; /* the endpoint of the trackpad interface */ | ||
142 | int tp_datalen; /* data length of the trackpad interface */ | ||
143 | struct bcm5974_param p; /* finger pressure limits */ | ||
144 | struct bcm5974_param w; /* finger width limits */ | ||
145 | struct bcm5974_param x; /* horizontal limits */ | ||
146 | struct bcm5974_param y; /* vertical limits */ | ||
147 | }; | ||
148 | |||
149 | /* logical device structure */ | ||
150 | struct bcm5974 { | ||
151 | char phys[64]; | ||
152 | struct usb_device *udev; /* usb device */ | ||
153 | struct usb_interface *intf; /* our interface */ | ||
154 | struct input_dev *input; /* input dev */ | ||
155 | struct bcm5974_config cfg; /* device configuration */ | ||
156 | struct mutex pm_mutex; /* serialize access to open/suspend */ | ||
157 | int opened; /* 1: opened, 0: closed */ | ||
158 | struct urb *bt_urb; /* button usb request block */ | ||
159 | struct bt_data *bt_data; /* button transferred data */ | ||
160 | struct urb *tp_urb; /* trackpad usb request block */ | ||
161 | struct tp_data *tp_data; /* trackpad transferred data */ | ||
162 | }; | ||
163 | |||
164 | /* logical dimensions */ | ||
165 | #define DIM_PRESSURE 256 /* maximum finger pressure */ | ||
166 | #define DIM_WIDTH 16 /* maximum finger width */ | ||
167 | #define DIM_X 1280 /* maximum trackpad x value */ | ||
168 | #define DIM_Y 800 /* maximum trackpad y value */ | ||
169 | |||
170 | /* logical signal quality */ | ||
171 | #define SN_PRESSURE 45 /* pressure signal-to-noise ratio */ | ||
172 | #define SN_WIDTH 100 /* width signal-to-noise ratio */ | ||
173 | #define SN_COORD 250 /* coordinate signal-to-noise ratio */ | ||
174 | |||
175 | /* device constants */ | ||
176 | static const struct bcm5974_config bcm5974_config_table[] = { | ||
177 | { | ||
178 | USB_DEVICE_ID_APPLE_WELLSPRING_ANSI, | ||
179 | USB_DEVICE_ID_APPLE_WELLSPRING_ISO, | ||
180 | USB_DEVICE_ID_APPLE_WELLSPRING_JIS, | ||
181 | 0x84, sizeof(struct bt_data), | ||
182 | 0x81, sizeof(struct tp_data), | ||
183 | { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 }, | ||
184 | { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, | ||
185 | { DIM_X, DIM_X / SN_COORD, -4824, 5342 }, | ||
186 | { DIM_Y, DIM_Y / SN_COORD, -172, 5820 } | ||
187 | }, | ||
188 | { | ||
189 | USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI, | ||
190 | USB_DEVICE_ID_APPLE_WELLSPRING2_ISO, | ||
191 | USB_DEVICE_ID_APPLE_WELLSPRING2_JIS, | ||
192 | 0x84, sizeof(struct bt_data), | ||
193 | 0x81, sizeof(struct tp_data), | ||
194 | { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 }, | ||
195 | { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, | ||
196 | { DIM_X, DIM_X / SN_COORD, -4824, 4824 }, | ||
197 | { DIM_Y, DIM_Y / SN_COORD, -172, 4290 } | ||
198 | }, | ||
199 | {} | ||
200 | }; | ||
201 | |||
202 | /* return the device-specific configuration by device */ | ||
203 | static const struct bcm5974_config *bcm5974_get_config(struct usb_device *udev) | ||
204 | { | ||
205 | u16 id = le16_to_cpu(udev->descriptor.idProduct); | ||
206 | const struct bcm5974_config *cfg; | ||
207 | |||
208 | for (cfg = bcm5974_config_table; cfg->ansi; ++cfg) | ||
209 | if (cfg->ansi == id || cfg->iso == id || cfg->jis == id) | ||
210 | return cfg; | ||
211 | |||
212 | return bcm5974_config_table; | ||
213 | } | ||
214 | |||
215 | /* convert 16-bit little endian to signed integer */ | ||
216 | static inline int raw2int(__le16 x) | ||
217 | { | ||
218 | return (signed short)le16_to_cpu(x); | ||
219 | } | ||
220 | |||
221 | /* scale device data to logical dimensions (asserts devmin < devmax) */ | ||
222 | static inline int int2scale(const struct bcm5974_param *p, int x) | ||
223 | { | ||
224 | return x * p->dim / (p->devmax - p->devmin); | ||
225 | } | ||
226 | |||
227 | /* all logical value ranges are [0,dim). */ | ||
228 | static inline int int2bound(const struct bcm5974_param *p, int x) | ||
229 | { | ||
230 | int s = int2scale(p, x); | ||
231 | |||
232 | return clamp_val(s, 0, p->dim - 1); | ||
233 | } | ||
234 | |||
235 | /* setup which logical events to report */ | ||
236 | static void setup_events_to_report(struct input_dev *input_dev, | ||
237 | const struct bcm5974_config *cfg) | ||
238 | { | ||
239 | __set_bit(EV_ABS, input_dev->evbit); | ||
240 | |||
241 | input_set_abs_params(input_dev, ABS_PRESSURE, | ||
242 | 0, cfg->p.dim, cfg->p.fuzz, 0); | ||
243 | input_set_abs_params(input_dev, ABS_TOOL_WIDTH, | ||
244 | 0, cfg->w.dim, cfg->w.fuzz, 0); | ||
245 | input_set_abs_params(input_dev, ABS_X, | ||
246 | 0, cfg->x.dim, cfg->x.fuzz, 0); | ||
247 | input_set_abs_params(input_dev, ABS_Y, | ||
248 | 0, cfg->y.dim, cfg->y.fuzz, 0); | ||
249 | |||
250 | __set_bit(EV_KEY, input_dev->evbit); | ||
251 | __set_bit(BTN_TOOL_FINGER, input_dev->keybit); | ||
252 | __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); | ||
253 | __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); | ||
254 | __set_bit(BTN_LEFT, input_dev->keybit); | ||
255 | } | ||
256 | |||
257 | /* report button data as logical button state */ | ||
258 | static int report_bt_state(struct bcm5974 *dev, int size) | ||
259 | { | ||
260 | if (size != sizeof(struct bt_data)) | ||
261 | return -EIO; | ||
262 | |||
263 | input_report_key(dev->input, BTN_LEFT, dev->bt_data->button); | ||
264 | input_sync(dev->input); | ||
265 | |||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | /* report trackpad data as logical trackpad state */ | ||
270 | static int report_tp_state(struct bcm5974 *dev, int size) | ||
271 | { | ||
272 | const struct bcm5974_config *c = &dev->cfg; | ||
273 | const struct tp_finger *f = dev->tp_data->finger; | ||
274 | struct input_dev *input = dev->input; | ||
275 | const int fingers = (size - 26) / 28; | ||
276 | int p = 0, w, x, y, n = 0; | ||
277 | |||
278 | if (size < 26 || (size - 26) % 28 != 0) | ||
279 | return -EIO; | ||
280 | |||
281 | if (fingers) { | ||
282 | p = raw2int(f->force_major); | ||
283 | w = raw2int(f->size_major); | ||
284 | x = raw2int(f->abs_x); | ||
285 | y = raw2int(f->abs_y); | ||
286 | n = p > 0 ? fingers : 0; | ||
287 | |||
288 | dprintk(9, | ||
289 | "bcm5974: p: %+05d w: %+05d x: %+05d y: %+05d n: %d\n", | ||
290 | p, w, x, y, n); | ||
291 | |||
292 | input_report_abs(input, ABS_TOOL_WIDTH, int2bound(&c->w, w)); | ||
293 | input_report_abs(input, ABS_X, int2bound(&c->x, x - c->x.devmin)); | ||
294 | input_report_abs(input, ABS_Y, int2bound(&c->y, c->y.devmax - y)); | ||
295 | } | ||
296 | |||
297 | input_report_abs(input, ABS_PRESSURE, int2bound(&c->p, p)); | ||
298 | |||
299 | input_report_key(input, BTN_TOOL_FINGER, n == 1); | ||
300 | input_report_key(input, BTN_TOOL_DOUBLETAP, n == 2); | ||
301 | input_report_key(input, BTN_TOOL_TRIPLETAP, n > 2); | ||
302 | |||
303 | input_sync(input); | ||
304 | |||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | /* Wellspring initialization constants */ | ||
309 | #define BCM5974_WELLSPRING_MODE_READ_REQUEST_ID 1 | ||
310 | #define BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID 9 | ||
311 | #define BCM5974_WELLSPRING_MODE_REQUEST_VALUE 0x300 | ||
312 | #define BCM5974_WELLSPRING_MODE_REQUEST_INDEX 0 | ||
313 | #define BCM5974_WELLSPRING_MODE_VENDOR_VALUE 0x01 | ||
314 | |||
315 | static int bcm5974_wellspring_mode(struct bcm5974 *dev) | ||
316 | { | ||
317 | char *data = kmalloc(8, GFP_KERNEL); | ||
318 | int retval = 0, size; | ||
319 | |||
320 | if (!data) { | ||
321 | err("bcm5974: out of memory"); | ||
322 | retval = -ENOMEM; | ||
323 | goto out; | ||
324 | } | ||
325 | |||
326 | /* read configuration */ | ||
327 | size = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), | ||
328 | BCM5974_WELLSPRING_MODE_READ_REQUEST_ID, | ||
329 | USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
330 | BCM5974_WELLSPRING_MODE_REQUEST_VALUE, | ||
331 | BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000); | ||
332 | |||
333 | if (size != 8) { | ||
334 | err("bcm5974: could not read from device"); | ||
335 | retval = -EIO; | ||
336 | goto out; | ||
337 | } | ||
338 | |||
339 | /* apply the mode switch */ | ||
340 | data[0] = BCM5974_WELLSPRING_MODE_VENDOR_VALUE; | ||
341 | |||
342 | /* write configuration */ | ||
343 | size = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), | ||
344 | BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID, | ||
345 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
346 | BCM5974_WELLSPRING_MODE_REQUEST_VALUE, | ||
347 | BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000); | ||
348 | |||
349 | if (size != 8) { | ||
350 | err("bcm5974: could not write to device"); | ||
351 | retval = -EIO; | ||
352 | goto out; | ||
353 | } | ||
354 | |||
355 | dprintk(2, "bcm5974: switched to wellspring mode.\n"); | ||
356 | |||
357 | out: | ||
358 | kfree(data); | ||
359 | return retval; | ||
360 | } | ||
361 | |||
362 | static void bcm5974_irq_button(struct urb *urb) | ||
363 | { | ||
364 | struct bcm5974 *dev = urb->context; | ||
365 | int error; | ||
366 | |||
367 | switch (urb->status) { | ||
368 | case 0: | ||
369 | break; | ||
370 | case -EOVERFLOW: | ||
371 | case -ECONNRESET: | ||
372 | case -ENOENT: | ||
373 | case -ESHUTDOWN: | ||
374 | dbg("bcm5974: button urb shutting down: %d", urb->status); | ||
375 | return; | ||
376 | default: | ||
377 | dbg("bcm5974: button urb status: %d", urb->status); | ||
378 | goto exit; | ||
379 | } | ||
380 | |||
381 | if (report_bt_state(dev, dev->bt_urb->actual_length)) | ||
382 | dprintk(1, "bcm5974: bad button package, length: %d\n", | ||
383 | dev->bt_urb->actual_length); | ||
384 | |||
385 | exit: | ||
386 | error = usb_submit_urb(dev->bt_urb, GFP_ATOMIC); | ||
387 | if (error) | ||
388 | err("bcm5974: button urb failed: %d", error); | ||
389 | } | ||
390 | |||
391 | static void bcm5974_irq_trackpad(struct urb *urb) | ||
392 | { | ||
393 | struct bcm5974 *dev = urb->context; | ||
394 | int error; | ||
395 | |||
396 | switch (urb->status) { | ||
397 | case 0: | ||
398 | break; | ||
399 | case -EOVERFLOW: | ||
400 | case -ECONNRESET: | ||
401 | case -ENOENT: | ||
402 | case -ESHUTDOWN: | ||
403 | dbg("bcm5974: trackpad urb shutting down: %d", urb->status); | ||
404 | return; | ||
405 | default: | ||
406 | dbg("bcm5974: trackpad urb status: %d", urb->status); | ||
407 | goto exit; | ||
408 | } | ||
409 | |||
410 | /* control response ignored */ | ||
411 | if (dev->tp_urb->actual_length == 2) | ||
412 | goto exit; | ||
413 | |||
414 | if (report_tp_state(dev, dev->tp_urb->actual_length)) | ||
415 | dprintk(1, "bcm5974: bad trackpad package, length: %d\n", | ||
416 | dev->tp_urb->actual_length); | ||
417 | |||
418 | exit: | ||
419 | error = usb_submit_urb(dev->tp_urb, GFP_ATOMIC); | ||
420 | if (error) | ||
421 | err("bcm5974: trackpad urb failed: %d", error); | ||
422 | } | ||
423 | |||
424 | /* | ||
425 | * The Wellspring trackpad, like many recent Apple trackpads, share | ||
426 | * the usb device with the keyboard. Since keyboards are usually | ||
427 | * handled by the HID system, the device ends up being handled by two | ||
428 | * modules. Setting up the device therefore becomes slightly | ||
429 | * complicated. To enable multitouch features, a mode switch is | ||
430 | * required, which is usually applied via the control interface of the | ||
431 | * device. It can be argued where this switch should take place. In | ||
432 | * some drivers, like appletouch, the switch is made during | ||
433 | * probe. However, the hid module may also alter the state of the | ||
434 | * device, resulting in trackpad malfunction under certain | ||
435 | * circumstances. To get around this problem, there is at least one | ||
436 | * example that utilizes the USB_QUIRK_RESET_RESUME quirk in order to | ||
437 | * recieve a reset_resume request rather than the normal resume. | ||
438 | * Since the implementation of reset_resume is equal to mode switch | ||
439 | * plus start_traffic, it seems easier to always do the switch when | ||
440 | * starting traffic on the device. | ||
441 | */ | ||
442 | static int bcm5974_start_traffic(struct bcm5974 *dev) | ||
443 | { | ||
444 | if (bcm5974_wellspring_mode(dev)) { | ||
445 | dprintk(1, "bcm5974: mode switch failed\n"); | ||
446 | goto error; | ||
447 | } | ||
448 | |||
449 | if (usb_submit_urb(dev->bt_urb, GFP_KERNEL)) | ||
450 | goto error; | ||
451 | |||
452 | if (usb_submit_urb(dev->tp_urb, GFP_KERNEL)) | ||
453 | goto err_kill_bt; | ||
454 | |||
455 | return 0; | ||
456 | |||
457 | err_kill_bt: | ||
458 | usb_kill_urb(dev->bt_urb); | ||
459 | error: | ||
460 | return -EIO; | ||
461 | } | ||
462 | |||
463 | static void bcm5974_pause_traffic(struct bcm5974 *dev) | ||
464 | { | ||
465 | usb_kill_urb(dev->tp_urb); | ||
466 | usb_kill_urb(dev->bt_urb); | ||
467 | } | ||
468 | |||
469 | /* | ||
470 | * The code below implements open/close and manual suspend/resume. | ||
471 | * All functions may be called in random order. | ||
472 | * | ||
473 | * Opening a suspended device fails with EACCES - permission denied. | ||
474 | * | ||
475 | * Failing a resume leaves the device resumed but closed. | ||
476 | */ | ||
477 | static int bcm5974_open(struct input_dev *input) | ||
478 | { | ||
479 | struct bcm5974 *dev = input_get_drvdata(input); | ||
480 | int error; | ||
481 | |||
482 | error = usb_autopm_get_interface(dev->intf); | ||
483 | if (error) | ||
484 | return error; | ||
485 | |||
486 | mutex_lock(&dev->pm_mutex); | ||
487 | |||
488 | error = bcm5974_start_traffic(dev); | ||
489 | if (!error) | ||
490 | dev->opened = 1; | ||
491 | |||
492 | mutex_unlock(&dev->pm_mutex); | ||
493 | |||
494 | if (error) | ||
495 | usb_autopm_put_interface(dev->intf); | ||
496 | |||
497 | return error; | ||
498 | } | ||
499 | |||
500 | static void bcm5974_close(struct input_dev *input) | ||
501 | { | ||
502 | struct bcm5974 *dev = input_get_drvdata(input); | ||
503 | |||
504 | mutex_lock(&dev->pm_mutex); | ||
505 | |||
506 | bcm5974_pause_traffic(dev); | ||
507 | dev->opened = 0; | ||
508 | |||
509 | mutex_unlock(&dev->pm_mutex); | ||
510 | |||
511 | usb_autopm_put_interface(dev->intf); | ||
512 | } | ||
513 | |||
514 | static int bcm5974_suspend(struct usb_interface *iface, pm_message_t message) | ||
515 | { | ||
516 | struct bcm5974 *dev = usb_get_intfdata(iface); | ||
517 | |||
518 | mutex_lock(&dev->pm_mutex); | ||
519 | |||
520 | if (dev->opened) | ||
521 | bcm5974_pause_traffic(dev); | ||
522 | |||
523 | mutex_unlock(&dev->pm_mutex); | ||
524 | |||
525 | return 0; | ||
526 | } | ||
527 | |||
528 | static int bcm5974_resume(struct usb_interface *iface) | ||
529 | { | ||
530 | struct bcm5974 *dev = usb_get_intfdata(iface); | ||
531 | int error = 0; | ||
532 | |||
533 | mutex_lock(&dev->pm_mutex); | ||
534 | |||
535 | if (dev->opened) | ||
536 | error = bcm5974_start_traffic(dev); | ||
537 | |||
538 | mutex_unlock(&dev->pm_mutex); | ||
539 | |||
540 | return error; | ||
541 | } | ||
542 | |||
543 | static int bcm5974_probe(struct usb_interface *iface, | ||
544 | const struct usb_device_id *id) | ||
545 | { | ||
546 | struct usb_device *udev = interface_to_usbdev(iface); | ||
547 | const struct bcm5974_config *cfg; | ||
548 | struct bcm5974 *dev; | ||
549 | struct input_dev *input_dev; | ||
550 | int error = -ENOMEM; | ||
551 | |||
552 | /* find the product index */ | ||
553 | cfg = bcm5974_get_config(udev); | ||
554 | |||
555 | /* allocate memory for our device state and initialize it */ | ||
556 | dev = kzalloc(sizeof(struct bcm5974), GFP_KERNEL); | ||
557 | input_dev = input_allocate_device(); | ||
558 | if (!dev || !input_dev) { | ||
559 | err("bcm5974: out of memory"); | ||
560 | goto err_free_devs; | ||
561 | } | ||
562 | |||
563 | dev->udev = udev; | ||
564 | dev->intf = iface; | ||
565 | dev->input = input_dev; | ||
566 | dev->cfg = *cfg; | ||
567 | mutex_init(&dev->pm_mutex); | ||
568 | |||
569 | /* setup urbs */ | ||
570 | dev->bt_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
571 | if (!dev->bt_urb) | ||
572 | goto err_free_devs; | ||
573 | |||
574 | dev->tp_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
575 | if (!dev->tp_urb) | ||
576 | goto err_free_bt_urb; | ||
577 | |||
578 | dev->bt_data = usb_buffer_alloc(dev->udev, | ||
579 | dev->cfg.bt_datalen, GFP_KERNEL, | ||
580 | &dev->bt_urb->transfer_dma); | ||
581 | if (!dev->bt_data) | ||
582 | goto err_free_urb; | ||
583 | |||
584 | dev->tp_data = usb_buffer_alloc(dev->udev, | ||
585 | dev->cfg.tp_datalen, GFP_KERNEL, | ||
586 | &dev->tp_urb->transfer_dma); | ||
587 | if (!dev->tp_data) | ||
588 | goto err_free_bt_buffer; | ||
589 | |||
590 | usb_fill_int_urb(dev->bt_urb, udev, | ||
591 | usb_rcvintpipe(udev, cfg->bt_ep), | ||
592 | dev->bt_data, dev->cfg.bt_datalen, | ||
593 | bcm5974_irq_button, dev, 1); | ||
594 | |||
595 | usb_fill_int_urb(dev->tp_urb, udev, | ||
596 | usb_rcvintpipe(udev, cfg->tp_ep), | ||
597 | dev->tp_data, dev->cfg.tp_datalen, | ||
598 | bcm5974_irq_trackpad, dev, 1); | ||
599 | |||
600 | /* create bcm5974 device */ | ||
601 | usb_make_path(udev, dev->phys, sizeof(dev->phys)); | ||
602 | strlcat(dev->phys, "/input0", sizeof(dev->phys)); | ||
603 | |||
604 | input_dev->name = "bcm5974"; | ||
605 | input_dev->phys = dev->phys; | ||
606 | usb_to_input_id(dev->udev, &input_dev->id); | ||
607 | input_dev->dev.parent = &iface->dev; | ||
608 | |||
609 | input_set_drvdata(input_dev, dev); | ||
610 | |||
611 | input_dev->open = bcm5974_open; | ||
612 | input_dev->close = bcm5974_close; | ||
613 | |||
614 | setup_events_to_report(input_dev, cfg); | ||
615 | |||
616 | error = input_register_device(dev->input); | ||
617 | if (error) | ||
618 | goto err_free_buffer; | ||
619 | |||
620 | /* save our data pointer in this interface device */ | ||
621 | usb_set_intfdata(iface, dev); | ||
622 | |||
623 | return 0; | ||
624 | |||
625 | err_free_buffer: | ||
626 | usb_buffer_free(dev->udev, dev->cfg.tp_datalen, | ||
627 | dev->tp_data, dev->tp_urb->transfer_dma); | ||
628 | err_free_bt_buffer: | ||
629 | usb_buffer_free(dev->udev, dev->cfg.bt_datalen, | ||
630 | dev->bt_data, dev->bt_urb->transfer_dma); | ||
631 | err_free_urb: | ||
632 | usb_free_urb(dev->tp_urb); | ||
633 | err_free_bt_urb: | ||
634 | usb_free_urb(dev->bt_urb); | ||
635 | err_free_devs: | ||
636 | usb_set_intfdata(iface, NULL); | ||
637 | input_free_device(input_dev); | ||
638 | kfree(dev); | ||
639 | return error; | ||
640 | } | ||
641 | |||
642 | static void bcm5974_disconnect(struct usb_interface *iface) | ||
643 | { | ||
644 | struct bcm5974 *dev = usb_get_intfdata(iface); | ||
645 | |||
646 | usb_set_intfdata(iface, NULL); | ||
647 | |||
648 | input_unregister_device(dev->input); | ||
649 | usb_buffer_free(dev->udev, dev->cfg.tp_datalen, | ||
650 | dev->tp_data, dev->tp_urb->transfer_dma); | ||
651 | usb_buffer_free(dev->udev, dev->cfg.bt_datalen, | ||
652 | dev->bt_data, dev->bt_urb->transfer_dma); | ||
653 | usb_free_urb(dev->tp_urb); | ||
654 | usb_free_urb(dev->bt_urb); | ||
655 | kfree(dev); | ||
656 | } | ||
657 | |||
658 | static struct usb_driver bcm5974_driver = { | ||
659 | .name = "bcm5974", | ||
660 | .probe = bcm5974_probe, | ||
661 | .disconnect = bcm5974_disconnect, | ||
662 | .suspend = bcm5974_suspend, | ||
663 | .resume = bcm5974_resume, | ||
664 | .reset_resume = bcm5974_resume, | ||
665 | .id_table = bcm5974_table, | ||
666 | .supports_autosuspend = 1, | ||
667 | }; | ||
668 | |||
669 | static int __init bcm5974_init(void) | ||
670 | { | ||
671 | return usb_register(&bcm5974_driver); | ||
672 | } | ||
673 | |||
674 | static void __exit bcm5974_exit(void) | ||
675 | { | ||
676 | usb_deregister(&bcm5974_driver); | ||
677 | } | ||
678 | |||
679 | module_init(bcm5974_init); | ||
680 | module_exit(bcm5974_exit); | ||
681 | |||
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index fe732a574ec2..3282b741e246 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
@@ -394,6 +394,13 @@ static struct dmi_system_id __initdata i8042_dmi_dritek_table[] = { | |||
394 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2490"), | 394 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2490"), |
395 | }, | 395 | }, |
396 | }, | 396 | }, |
397 | { | ||
398 | .ident = "Acer TravelMate 4280", | ||
399 | .matches = { | ||
400 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | ||
401 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4280"), | ||
402 | }, | ||
403 | }, | ||
397 | { } | 404 | { } |
398 | }; | 405 | }; |
399 | 406 | ||
diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c index 0ed044d5e685..765007899d9a 100644 --- a/drivers/input/serio/xilinx_ps2.c +++ b/drivers/input/serio/xilinx_ps2.c | |||
@@ -269,8 +269,8 @@ static int xps2_setup(struct device *dev, struct resource *regs_res, | |||
269 | * we have the PS2 in a good state */ | 269 | * we have the PS2 in a good state */ |
270 | out_be32(drvdata->base_address + XPS2_SRST_OFFSET, XPS2_SRST_RESET); | 270 | out_be32(drvdata->base_address + XPS2_SRST_OFFSET, XPS2_SRST_RESET); |
271 | 271 | ||
272 | dev_info(dev, "Xilinx PS2 at 0x%08X mapped to 0x%08X, irq=%d\n", | 272 | dev_info(dev, "Xilinx PS2 at 0x%08X mapped to 0x%p, irq=%d\n", |
273 | drvdata->phys_addr, (u32)drvdata->base_address, drvdata->irq); | 273 | drvdata->phys_addr, drvdata->base_address, drvdata->irq); |
274 | 274 | ||
275 | serio = &drvdata->serio; | 275 | serio = &drvdata->serio; |
276 | serio->id.type = SERIO_8042; | 276 | serio->id.type = SERIO_8042; |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 6e60a97a234c..25287e80e236 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -249,29 +249,26 @@ config TOUCHSCREEN_WM97XX | |||
249 | config TOUCHSCREEN_WM9705 | 249 | config TOUCHSCREEN_WM9705 |
250 | bool "WM9705 Touchscreen interface support" | 250 | bool "WM9705 Touchscreen interface support" |
251 | depends on TOUCHSCREEN_WM97XX | 251 | depends on TOUCHSCREEN_WM97XX |
252 | default y | ||
252 | help | 253 | help |
253 | Say Y here if you have a Wolfson Microelectronics WM9705 | 254 | Say Y here to enable support for the Wolfson Microelectronics |
254 | touchscreen controller connected to your system. | 255 | WM9705 touchscreen controller. |
255 | |||
256 | If unsure, say N. | ||
257 | 256 | ||
258 | config TOUCHSCREEN_WM9712 | 257 | config TOUCHSCREEN_WM9712 |
259 | bool "WM9712 Touchscreen interface support" | 258 | bool "WM9712 Touchscreen interface support" |
260 | depends on TOUCHSCREEN_WM97XX | 259 | depends on TOUCHSCREEN_WM97XX |
260 | default y | ||
261 | help | 261 | help |
262 | Say Y here if you have a Wolfson Microelectronics WM9712 | 262 | Say Y here to enable support for the Wolfson Microelectronics |
263 | touchscreen controller connected to your system. | 263 | WM9712 touchscreen controller. |
264 | |||
265 | If unsure, say N. | ||
266 | 264 | ||
267 | config TOUCHSCREEN_WM9713 | 265 | config TOUCHSCREEN_WM9713 |
268 | bool "WM9713 Touchscreen interface support" | 266 | bool "WM9713 Touchscreen interface support" |
269 | depends on TOUCHSCREEN_WM97XX | 267 | depends on TOUCHSCREEN_WM97XX |
268 | default y | ||
270 | help | 269 | help |
271 | Say Y here if you have a Wolfson Microelectronics WM9713 touchscreen | 270 | Say Y here to enable support for the Wolfson Microelectronics |
272 | controller connected to your system. | 271 | WM9713 touchscreen controller. |
273 | |||
274 | If unsure, say N. | ||
275 | 272 | ||
276 | config TOUCHSCREEN_WM97XX_MAINSTONE | 273 | config TOUCHSCREEN_WM97XX_MAINSTONE |
277 | tristate "WM97xx Mainstone accelerated touch" | 274 | tristate "WM97xx Mainstone accelerated touch" |
diff --git a/drivers/md/md.c b/drivers/md/md.c index c7aae66c6f9b..8cfadc5bd2ba 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -2393,6 +2393,8 @@ static void analyze_sbs(mddev_t * mddev) | |||
2393 | 2393 | ||
2394 | } | 2394 | } |
2395 | 2395 | ||
2396 | static void md_safemode_timeout(unsigned long data); | ||
2397 | |||
2396 | static ssize_t | 2398 | static ssize_t |
2397 | safe_delay_show(mddev_t *mddev, char *page) | 2399 | safe_delay_show(mddev_t *mddev, char *page) |
2398 | { | 2400 | { |
@@ -2432,9 +2434,12 @@ safe_delay_store(mddev_t *mddev, const char *cbuf, size_t len) | |||
2432 | if (msec == 0) | 2434 | if (msec == 0) |
2433 | mddev->safemode_delay = 0; | 2435 | mddev->safemode_delay = 0; |
2434 | else { | 2436 | else { |
2437 | unsigned long old_delay = mddev->safemode_delay; | ||
2435 | mddev->safemode_delay = (msec*HZ)/1000; | 2438 | mddev->safemode_delay = (msec*HZ)/1000; |
2436 | if (mddev->safemode_delay == 0) | 2439 | if (mddev->safemode_delay == 0) |
2437 | mddev->safemode_delay = 1; | 2440 | mddev->safemode_delay = 1; |
2441 | if (mddev->safemode_delay < old_delay) | ||
2442 | md_safemode_timeout((unsigned long)mddev); | ||
2438 | } | 2443 | } |
2439 | return len; | 2444 | return len; |
2440 | } | 2445 | } |
@@ -4634,6 +4639,11 @@ static int update_size(mddev_t *mddev, sector_t num_sectors) | |||
4634 | */ | 4639 | */ |
4635 | if (mddev->sync_thread) | 4640 | if (mddev->sync_thread) |
4636 | return -EBUSY; | 4641 | return -EBUSY; |
4642 | if (mddev->bitmap) | ||
4643 | /* Sorry, cannot grow a bitmap yet, just remove it, | ||
4644 | * grow, and re-add. | ||
4645 | */ | ||
4646 | return -EBUSY; | ||
4637 | rdev_for_each(rdev, tmp, mddev) { | 4647 | rdev_for_each(rdev, tmp, mddev) { |
4638 | sector_t avail; | 4648 | sector_t avail; |
4639 | avail = rdev->size * 2; | 4649 | avail = rdev->size * 2; |
@@ -5993,7 +6003,7 @@ static int remove_and_add_spares(mddev_t *mddev) | |||
5993 | } | 6003 | } |
5994 | } | 6004 | } |
5995 | 6005 | ||
5996 | if (mddev->degraded) { | 6006 | if (mddev->degraded && ! mddev->ro) { |
5997 | rdev_for_each(rdev, rtmp, mddev) { | 6007 | rdev_for_each(rdev, rtmp, mddev) { |
5998 | if (rdev->raid_disk >= 0 && | 6008 | if (rdev->raid_disk >= 0 && |
5999 | !test_bit(In_sync, &rdev->flags) && | 6009 | !test_bit(In_sync, &rdev->flags) && |
@@ -6067,6 +6077,8 @@ void md_check_recovery(mddev_t *mddev) | |||
6067 | flush_signals(current); | 6077 | flush_signals(current); |
6068 | } | 6078 | } |
6069 | 6079 | ||
6080 | if (mddev->ro && !test_bit(MD_RECOVERY_NEEDED, &mddev->recovery)) | ||
6081 | return; | ||
6070 | if ( ! ( | 6082 | if ( ! ( |
6071 | (mddev->flags && !mddev->external) || | 6083 | (mddev->flags && !mddev->external) || |
6072 | test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) || | 6084 | test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) || |
@@ -6080,6 +6092,15 @@ void md_check_recovery(mddev_t *mddev) | |||
6080 | if (mddev_trylock(mddev)) { | 6092 | if (mddev_trylock(mddev)) { |
6081 | int spares = 0; | 6093 | int spares = 0; |
6082 | 6094 | ||
6095 | if (mddev->ro) { | ||
6096 | /* Only thing we do on a ro array is remove | ||
6097 | * failed devices. | ||
6098 | */ | ||
6099 | remove_and_add_spares(mddev); | ||
6100 | clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery); | ||
6101 | goto unlock; | ||
6102 | } | ||
6103 | |||
6083 | if (!mddev->external) { | 6104 | if (!mddev->external) { |
6084 | int did_change = 0; | 6105 | int did_change = 0; |
6085 | spin_lock_irq(&mddev->write_lock); | 6106 | spin_lock_irq(&mddev->write_lock); |
@@ -6117,7 +6138,8 @@ void md_check_recovery(mddev_t *mddev) | |||
6117 | /* resync has finished, collect result */ | 6138 | /* resync has finished, collect result */ |
6118 | md_unregister_thread(mddev->sync_thread); | 6139 | md_unregister_thread(mddev->sync_thread); |
6119 | mddev->sync_thread = NULL; | 6140 | mddev->sync_thread = NULL; |
6120 | if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { | 6141 | if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) && |
6142 | !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) { | ||
6121 | /* success...*/ | 6143 | /* success...*/ |
6122 | /* activate any spares */ | 6144 | /* activate any spares */ |
6123 | if (mddev->pers->spare_active(mddev)) | 6145 | if (mddev->pers->spare_active(mddev)) |
@@ -6169,6 +6191,7 @@ void md_check_recovery(mddev_t *mddev) | |||
6169 | } else if ((spares = remove_and_add_spares(mddev))) { | 6191 | } else if ((spares = remove_and_add_spares(mddev))) { |
6170 | clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); | 6192 | clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); |
6171 | clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); | 6193 | clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); |
6194 | clear_bit(MD_RECOVERY_REQUESTED, &mddev->recovery); | ||
6172 | set_bit(MD_RECOVERY_RECOVER, &mddev->recovery); | 6195 | set_bit(MD_RECOVERY_RECOVER, &mddev->recovery); |
6173 | } else if (mddev->recovery_cp < MaxSector) { | 6196 | } else if (mddev->recovery_cp < MaxSector) { |
6174 | set_bit(MD_RECOVERY_SYNC, &mddev->recovery); | 6197 | set_bit(MD_RECOVERY_SYNC, &mddev->recovery); |
@@ -6232,7 +6255,11 @@ static int md_notify_reboot(struct notifier_block *this, | |||
6232 | 6255 | ||
6233 | for_each_mddev(mddev, tmp) | 6256 | for_each_mddev(mddev, tmp) |
6234 | if (mddev_trylock(mddev)) { | 6257 | if (mddev_trylock(mddev)) { |
6235 | do_md_stop (mddev, 1, 0); | 6258 | /* Force a switch to readonly even array |
6259 | * appears to still be in use. Hence | ||
6260 | * the '100'. | ||
6261 | */ | ||
6262 | do_md_stop (mddev, 1, 100); | ||
6236 | mddev_unlock(mddev); | 6263 | mddev_unlock(mddev); |
6237 | } | 6264 | } |
6238 | /* | 6265 | /* |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index d41bebb6da0f..e34cd0e62473 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -76,11 +76,13 @@ static void r10bio_pool_free(void *r10_bio, void *data) | |||
76 | kfree(r10_bio); | 76 | kfree(r10_bio); |
77 | } | 77 | } |
78 | 78 | ||
79 | /* Maximum size of each resync request */ | ||
79 | #define RESYNC_BLOCK_SIZE (64*1024) | 80 | #define RESYNC_BLOCK_SIZE (64*1024) |
80 | //#define RESYNC_BLOCK_SIZE PAGE_SIZE | ||
81 | #define RESYNC_SECTORS (RESYNC_BLOCK_SIZE >> 9) | ||
82 | #define RESYNC_PAGES ((RESYNC_BLOCK_SIZE + PAGE_SIZE-1) / PAGE_SIZE) | 81 | #define RESYNC_PAGES ((RESYNC_BLOCK_SIZE + PAGE_SIZE-1) / PAGE_SIZE) |
83 | #define RESYNC_WINDOW (2048*1024) | 82 | /* amount of memory to reserve for resync requests */ |
83 | #define RESYNC_WINDOW (1024*1024) | ||
84 | /* maximum number of concurrent requests, memory permitting */ | ||
85 | #define RESYNC_DEPTH (32*1024*1024/RESYNC_BLOCK_SIZE) | ||
84 | 86 | ||
85 | /* | 87 | /* |
86 | * When performing a resync, we need to read and compare, so | 88 | * When performing a resync, we need to read and compare, so |
@@ -690,7 +692,6 @@ static int flush_pending_writes(conf_t *conf) | |||
690 | * there is no normal IO happeing. It must arrange to call | 692 | * there is no normal IO happeing. It must arrange to call |
691 | * lower_barrier when the particular background IO completes. | 693 | * lower_barrier when the particular background IO completes. |
692 | */ | 694 | */ |
693 | #define RESYNC_DEPTH 32 | ||
694 | 695 | ||
695 | static void raise_barrier(conf_t *conf, int force) | 696 | static void raise_barrier(conf_t *conf, int force) |
696 | { | 697 | { |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 40e939675657..224de022e7c5 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -2568,10 +2568,10 @@ static bool handle_stripe5(struct stripe_head *sh) | |||
2568 | if (dev->written) | 2568 | if (dev->written) |
2569 | s.written++; | 2569 | s.written++; |
2570 | rdev = rcu_dereference(conf->disks[i].rdev); | 2570 | rdev = rcu_dereference(conf->disks[i].rdev); |
2571 | if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) { | 2571 | if (blocked_rdev == NULL && |
2572 | rdev && unlikely(test_bit(Blocked, &rdev->flags))) { | ||
2572 | blocked_rdev = rdev; | 2573 | blocked_rdev = rdev; |
2573 | atomic_inc(&rdev->nr_pending); | 2574 | atomic_inc(&rdev->nr_pending); |
2574 | break; | ||
2575 | } | 2575 | } |
2576 | if (!rdev || !test_bit(In_sync, &rdev->flags)) { | 2576 | if (!rdev || !test_bit(In_sync, &rdev->flags)) { |
2577 | /* The ReadError flag will just be confusing now */ | 2577 | /* The ReadError flag will just be confusing now */ |
@@ -2588,8 +2588,14 @@ static bool handle_stripe5(struct stripe_head *sh) | |||
2588 | rcu_read_unlock(); | 2588 | rcu_read_unlock(); |
2589 | 2589 | ||
2590 | if (unlikely(blocked_rdev)) { | 2590 | if (unlikely(blocked_rdev)) { |
2591 | set_bit(STRIPE_HANDLE, &sh->state); | 2591 | if (s.syncing || s.expanding || s.expanded || |
2592 | goto unlock; | 2592 | s.to_write || s.written) { |
2593 | set_bit(STRIPE_HANDLE, &sh->state); | ||
2594 | goto unlock; | ||
2595 | } | ||
2596 | /* There is nothing for the blocked_rdev to block */ | ||
2597 | rdev_dec_pending(blocked_rdev, conf->mddev); | ||
2598 | blocked_rdev = NULL; | ||
2593 | } | 2599 | } |
2594 | 2600 | ||
2595 | if (s.to_fill && !test_bit(STRIPE_BIOFILL_RUN, &sh->state)) { | 2601 | if (s.to_fill && !test_bit(STRIPE_BIOFILL_RUN, &sh->state)) { |
@@ -2832,10 +2838,10 @@ static bool handle_stripe6(struct stripe_head *sh, struct page *tmp_page) | |||
2832 | if (dev->written) | 2838 | if (dev->written) |
2833 | s.written++; | 2839 | s.written++; |
2834 | rdev = rcu_dereference(conf->disks[i].rdev); | 2840 | rdev = rcu_dereference(conf->disks[i].rdev); |
2835 | if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) { | 2841 | if (blocked_rdev == NULL && |
2842 | rdev && unlikely(test_bit(Blocked, &rdev->flags))) { | ||
2836 | blocked_rdev = rdev; | 2843 | blocked_rdev = rdev; |
2837 | atomic_inc(&rdev->nr_pending); | 2844 | atomic_inc(&rdev->nr_pending); |
2838 | break; | ||
2839 | } | 2845 | } |
2840 | if (!rdev || !test_bit(In_sync, &rdev->flags)) { | 2846 | if (!rdev || !test_bit(In_sync, &rdev->flags)) { |
2841 | /* The ReadError flag will just be confusing now */ | 2847 | /* The ReadError flag will just be confusing now */ |
@@ -2853,9 +2859,16 @@ static bool handle_stripe6(struct stripe_head *sh, struct page *tmp_page) | |||
2853 | rcu_read_unlock(); | 2859 | rcu_read_unlock(); |
2854 | 2860 | ||
2855 | if (unlikely(blocked_rdev)) { | 2861 | if (unlikely(blocked_rdev)) { |
2856 | set_bit(STRIPE_HANDLE, &sh->state); | 2862 | if (s.syncing || s.expanding || s.expanded || |
2857 | goto unlock; | 2863 | s.to_write || s.written) { |
2864 | set_bit(STRIPE_HANDLE, &sh->state); | ||
2865 | goto unlock; | ||
2866 | } | ||
2867 | /* There is nothing for the blocked_rdev to block */ | ||
2868 | rdev_dec_pending(blocked_rdev, conf->mddev); | ||
2869 | blocked_rdev = NULL; | ||
2858 | } | 2870 | } |
2871 | |||
2859 | pr_debug("locked=%d uptodate=%d to_read=%d" | 2872 | pr_debug("locked=%d uptodate=%d to_read=%d" |
2860 | " to_write=%d failed=%d failed_num=%d,%d\n", | 2873 | " to_write=%d failed=%d failed_num=%d,%d\n", |
2861 | s.locked, s.uptodate, s.to_read, s.to_write, s.failed, | 2874 | s.locked, s.uptodate, s.to_read, s.to_write, s.failed, |
@@ -4446,6 +4459,9 @@ static int raid5_check_reshape(mddev_t *mddev) | |||
4446 | return -EINVAL; /* Cannot shrink array or change level yet */ | 4459 | return -EINVAL; /* Cannot shrink array or change level yet */ |
4447 | if (mddev->delta_disks == 0) | 4460 | if (mddev->delta_disks == 0) |
4448 | return 0; /* nothing to do */ | 4461 | return 0; /* nothing to do */ |
4462 | if (mddev->bitmap) | ||
4463 | /* Cannot grow a bitmap yet */ | ||
4464 | return -EBUSY; | ||
4449 | 4465 | ||
4450 | /* Can only proceed if there are plenty of stripe_heads. | 4466 | /* Can only proceed if there are plenty of stripe_heads. |
4451 | * We need a minimum of one full stripe,, and for sensible progress | 4467 | * We need a minimum of one full stripe,, and for sensible progress |
diff --git a/drivers/misc/acer-wmi.c b/drivers/misc/acer-wmi.c index e7a3fe508dff..b2d9878dc3f0 100644 --- a/drivers/misc/acer-wmi.c +++ b/drivers/misc/acer-wmi.c | |||
@@ -803,11 +803,30 @@ static acpi_status get_u32(u32 *value, u32 cap) | |||
803 | 803 | ||
804 | static acpi_status set_u32(u32 value, u32 cap) | 804 | static acpi_status set_u32(u32 value, u32 cap) |
805 | { | 805 | { |
806 | acpi_status status; | ||
807 | |||
806 | if (interface->capability & cap) { | 808 | if (interface->capability & cap) { |
807 | switch (interface->type) { | 809 | switch (interface->type) { |
808 | case ACER_AMW0: | 810 | case ACER_AMW0: |
809 | return AMW0_set_u32(value, cap, interface); | 811 | return AMW0_set_u32(value, cap, interface); |
810 | case ACER_AMW0_V2: | 812 | case ACER_AMW0_V2: |
813 | if (cap == ACER_CAP_MAILLED) | ||
814 | return AMW0_set_u32(value, cap, interface); | ||
815 | |||
816 | /* | ||
817 | * On some models, some WMID methods don't toggle | ||
818 | * properly. For those cases, we want to run the AMW0 | ||
819 | * method afterwards to be certain we've really toggled | ||
820 | * the device state. | ||
821 | */ | ||
822 | if (cap == ACER_CAP_WIRELESS || | ||
823 | cap == ACER_CAP_BLUETOOTH) { | ||
824 | status = WMID_set_u32(value, cap, interface); | ||
825 | if (ACPI_FAILURE(status)) | ||
826 | return status; | ||
827 | |||
828 | return AMW0_set_u32(value, cap, interface); | ||
829 | } | ||
811 | case ACER_WMID: | 830 | case ACER_WMID: |
812 | return WMID_set_u32(value, cap, interface); | 831 | return WMID_set_u32(value, cap, interface); |
813 | default: | 832 | default: |
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index 64002488c6ee..917cf8d3ae95 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #include <asm/io.h> | 19 | #include <asm/io.h> |
20 | #include <asm/sizes.h> | 20 | #include <asm/sizes.h> |
21 | #include <mach/hardware.h> | 21 | #include <mach/hardware.h> |
22 | #include <asm/plat-orion/orion_nand.h> | 22 | #include <plat/orion_nand.h> |
23 | 23 | ||
24 | #ifdef CONFIG_MTD_CMDLINE_PARTS | 24 | #ifdef CONFIG_MTD_CMDLINE_PARTS |
25 | static const char *part_probes[] = { "cmdlinepart", NULL }; | 25 | static const char *part_probes[] = { "cmdlinepart", NULL }; |
diff --git a/drivers/pcmcia/pxa2xx_palmtx.c b/drivers/pcmcia/pxa2xx_palmtx.c index a8771ffc61e8..e07b5c51ec5b 100644 --- a/drivers/pcmcia/pxa2xx_palmtx.c +++ b/drivers/pcmcia/pxa2xx_palmtx.c | |||
@@ -23,12 +23,57 @@ | |||
23 | 23 | ||
24 | static int palmtx_pcmcia_hw_init(struct soc_pcmcia_socket *skt) | 24 | static int palmtx_pcmcia_hw_init(struct soc_pcmcia_socket *skt) |
25 | { | 25 | { |
26 | skt->irq = IRQ_GPIO(GPIO_NR_PALMTX_PCMCIA_READY); | 26 | int ret; |
27 | |||
28 | ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_POWER1, "PCMCIA PWR1"); | ||
29 | if (ret) | ||
30 | goto err1; | ||
31 | ret = gpio_direction_output(GPIO_NR_PALMTX_PCMCIA_POWER1, 0); | ||
32 | if (ret) | ||
33 | goto err2; | ||
34 | |||
35 | ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_POWER2, "PCMCIA PWR2"); | ||
36 | if (ret) | ||
37 | goto err2; | ||
38 | ret = gpio_direction_output(GPIO_NR_PALMTX_PCMCIA_POWER2, 0); | ||
39 | if (ret) | ||
40 | goto err3; | ||
41 | |||
42 | ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_RESET, "PCMCIA RST"); | ||
43 | if (ret) | ||
44 | goto err3; | ||
45 | ret = gpio_direction_output(GPIO_NR_PALMTX_PCMCIA_RESET, 1); | ||
46 | if (ret) | ||
47 | goto err4; | ||
48 | |||
49 | ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_READY, "PCMCIA RDY"); | ||
50 | if (ret) | ||
51 | goto err4; | ||
52 | ret = gpio_direction_input(GPIO_NR_PALMTX_PCMCIA_READY); | ||
53 | if (ret) | ||
54 | goto err5; | ||
55 | |||
56 | skt->irq = gpio_to_irq(GPIO_NR_PALMTX_PCMCIA_READY); | ||
27 | return 0; | 57 | return 0; |
58 | |||
59 | err5: | ||
60 | gpio_free(GPIO_NR_PALMTX_PCMCIA_READY); | ||
61 | err4: | ||
62 | gpio_free(GPIO_NR_PALMTX_PCMCIA_RESET); | ||
63 | err3: | ||
64 | gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER2); | ||
65 | err2: | ||
66 | gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER1); | ||
67 | err1: | ||
68 | return ret; | ||
28 | } | 69 | } |
29 | 70 | ||
30 | static void palmtx_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) | 71 | static void palmtx_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) |
31 | { | 72 | { |
73 | gpio_free(GPIO_NR_PALMTX_PCMCIA_READY); | ||
74 | gpio_free(GPIO_NR_PALMTX_PCMCIA_RESET); | ||
75 | gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER2); | ||
76 | gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER1); | ||
32 | } | 77 | } |
33 | 78 | ||
34 | static void palmtx_pcmcia_socket_state(struct soc_pcmcia_socket *skt, | 79 | static void palmtx_pcmcia_socket_state(struct soc_pcmcia_socket *skt, |
@@ -109,7 +154,7 @@ static void __exit palmtx_pcmcia_exit(void) | |||
109 | platform_device_unregister(palmtx_pcmcia_device); | 154 | platform_device_unregister(palmtx_pcmcia_device); |
110 | } | 155 | } |
111 | 156 | ||
112 | fs_initcall(palmtx_pcmcia_init); | 157 | module_init(palmtx_pcmcia_init); |
113 | module_exit(palmtx_pcmcia_exit); | 158 | module_exit(palmtx_pcmcia_exit); |
114 | 159 | ||
115 | MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); | 160 | MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); |
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index d7e9f2152df0..95015cbfd33f 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c | |||
@@ -405,8 +405,6 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, | |||
405 | 405 | ||
406 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: | 406 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: |
407 | extended_irq = &res->data.extended_irq; | 407 | extended_irq = &res->data.extended_irq; |
408 | if (extended_irq->producer_consumer == ACPI_PRODUCER) | ||
409 | return AE_OK; | ||
410 | 408 | ||
411 | if (extended_irq->interrupt_count == 0) | 409 | if (extended_irq->interrupt_count == 0) |
412 | pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED); | 410 | pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED); |
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 3b4a14e355c1..77cb34270fc1 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -449,6 +449,7 @@ config SERIAL_CLPS711X_CONSOLE | |||
449 | config SERIAL_SAMSUNG | 449 | config SERIAL_SAMSUNG |
450 | tristate "Samsung SoC serial support" | 450 | tristate "Samsung SoC serial support" |
451 | depends on ARM && PLAT_S3C24XX | 451 | depends on ARM && PLAT_S3C24XX |
452 | select SERIAL_CORE | ||
452 | help | 453 | help |
453 | Support for the on-chip UARTs on the Samsung S3C24XX series CPUs, | 454 | Support for the on-chip UARTs on the Samsung S3C24XX series CPUs, |
454 | providing /dev/ttySAC0, 1 and 2 (note, some machines may not | 455 | providing /dev/ttySAC0, 1 and 2 (note, some machines may not |
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 964124b60db2..75e86865234c 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
@@ -226,10 +226,11 @@ EXPORT_SYMBOL_GPL(spi_alloc_device); | |||
226 | * Companion function to spi_alloc_device. Devices allocated with | 226 | * Companion function to spi_alloc_device. Devices allocated with |
227 | * spi_alloc_device can be added onto the spi bus with this function. | 227 | * spi_alloc_device can be added onto the spi bus with this function. |
228 | * | 228 | * |
229 | * Returns 0 on success; non-zero on failure | 229 | * Returns 0 on success; negative errno on failure |
230 | */ | 230 | */ |
231 | int spi_add_device(struct spi_device *spi) | 231 | int spi_add_device(struct spi_device *spi) |
232 | { | 232 | { |
233 | static DEFINE_MUTEX(spi_add_lock); | ||
233 | struct device *dev = spi->master->dev.parent; | 234 | struct device *dev = spi->master->dev.parent; |
234 | int status; | 235 | int status; |
235 | 236 | ||
@@ -246,26 +247,43 @@ int spi_add_device(struct spi_device *spi) | |||
246 | "%s.%u", spi->master->dev.bus_id, | 247 | "%s.%u", spi->master->dev.bus_id, |
247 | spi->chip_select); | 248 | spi->chip_select); |
248 | 249 | ||
249 | /* drivers may modify this initial i/o setup */ | 250 | |
251 | /* We need to make sure there's no other device with this | ||
252 | * chipselect **BEFORE** we call setup(), else we'll trash | ||
253 | * its configuration. Lock against concurrent add() calls. | ||
254 | */ | ||
255 | mutex_lock(&spi_add_lock); | ||
256 | |||
257 | if (bus_find_device_by_name(&spi_bus_type, NULL, spi->dev.bus_id) | ||
258 | != NULL) { | ||
259 | dev_err(dev, "chipselect %d already in use\n", | ||
260 | spi->chip_select); | ||
261 | status = -EBUSY; | ||
262 | goto done; | ||
263 | } | ||
264 | |||
265 | /* Drivers may modify this initial i/o setup, but will | ||
266 | * normally rely on the device being setup. Devices | ||
267 | * using SPI_CS_HIGH can't coexist well otherwise... | ||
268 | */ | ||
250 | status = spi->master->setup(spi); | 269 | status = spi->master->setup(spi); |
251 | if (status < 0) { | 270 | if (status < 0) { |
252 | dev_err(dev, "can't %s %s, status %d\n", | 271 | dev_err(dev, "can't %s %s, status %d\n", |
253 | "setup", spi->dev.bus_id, status); | 272 | "setup", spi->dev.bus_id, status); |
254 | return status; | 273 | goto done; |
255 | } | 274 | } |
256 | 275 | ||
257 | /* driver core catches callers that misbehave by defining | 276 | /* Device may be bound to an active driver when this returns */ |
258 | * devices that already exist. | ||
259 | */ | ||
260 | status = device_add(&spi->dev); | 277 | status = device_add(&spi->dev); |
261 | if (status < 0) { | 278 | if (status < 0) |
262 | dev_err(dev, "can't %s %s, status %d\n", | 279 | dev_err(dev, "can't %s %s, status %d\n", |
263 | "add", spi->dev.bus_id, status); | 280 | "add", spi->dev.bus_id, status); |
264 | return status; | 281 | else |
265 | } | 282 | dev_dbg(dev, "registered child %s\n", spi->dev.bus_id); |
266 | 283 | ||
267 | dev_dbg(dev, "registered child %s\n", spi->dev.bus_id); | 284 | done: |
268 | return 0; | 285 | mutex_unlock(&spi_add_lock); |
286 | return status; | ||
269 | } | 287 | } |
270 | EXPORT_SYMBOL_GPL(spi_add_device); | 288 | EXPORT_SYMBOL_GPL(spi_add_device); |
271 | 289 | ||
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index 5fbdc14e63b3..5416cf969005 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c | |||
@@ -12,7 +12,7 @@ | |||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/platform_device.h> | 13 | #include <linux/platform_device.h> |
14 | #include <linux/mbus.h> | 14 | #include <linux/mbus.h> |
15 | #include <asm/plat-orion/ehci-orion.h> | 15 | #include <plat/ehci-orion.h> |
16 | 16 | ||
17 | #define rdl(off) __raw_readl(hcd->regs + (off)) | 17 | #define rdl(off) __raw_readl(hcd->regs + (off)) |
18 | #define wrl(off, val) __raw_writel((val), hcd->regs + (off)) | 18 | #define wrl(off, val) __raw_writel((val), hcd->regs + (off)) |
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index bd320a2bfb7c..fb51197d1c98 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c | |||
@@ -479,6 +479,10 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var, | |||
479 | base_plane_width = machine_data->fsl_diu_info[0]->var.xres; | 479 | base_plane_width = machine_data->fsl_diu_info[0]->var.xres; |
480 | base_plane_height = machine_data->fsl_diu_info[0]->var.yres; | 480 | base_plane_height = machine_data->fsl_diu_info[0]->var.yres; |
481 | 481 | ||
482 | if (mfbi->x_aoi_d < 0) | ||
483 | mfbi->x_aoi_d = 0; | ||
484 | if (mfbi->y_aoi_d < 0) | ||
485 | mfbi->y_aoi_d = 0; | ||
482 | switch (index) { | 486 | switch (index) { |
483 | case 0: | 487 | case 0: |
484 | if (mfbi->x_aoi_d != 0) | 488 | if (mfbi->x_aoi_d != 0) |
@@ -778,6 +782,22 @@ static void unmap_video_memory(struct fb_info *info) | |||
778 | } | 782 | } |
779 | 783 | ||
780 | /* | 784 | /* |
785 | * Using the fb_var_screeninfo in fb_info we set the aoi of this | ||
786 | * particular framebuffer. It is a light version of fsl_diu_set_par. | ||
787 | */ | ||
788 | static int fsl_diu_set_aoi(struct fb_info *info) | ||
789 | { | ||
790 | struct fb_var_screeninfo *var = &info->var; | ||
791 | struct mfb_info *mfbi = info->par; | ||
792 | struct diu_ad *ad = mfbi->ad; | ||
793 | |||
794 | /* AOI should not be greater than display size */ | ||
795 | ad->offset_xyi = cpu_to_le32((var->yoffset << 16) | var->xoffset); | ||
796 | ad->offset_xyd = cpu_to_le32((mfbi->y_aoi_d << 16) | mfbi->x_aoi_d); | ||
797 | return 0; | ||
798 | } | ||
799 | |||
800 | /* | ||
781 | * Using the fb_var_screeninfo in fb_info we set the resolution of this | 801 | * Using the fb_var_screeninfo in fb_info we set the resolution of this |
782 | * particular framebuffer. This function alters the fb_fix_screeninfo stored | 802 | * particular framebuffer. This function alters the fb_fix_screeninfo stored |
783 | * in fb_info. It does not alter var in fb_info since we are using that | 803 | * in fb_info. It does not alter var in fb_info since we are using that |
@@ -817,11 +837,11 @@ static int fsl_diu_set_par(struct fb_info *info) | |||
817 | diu_ops.get_pixel_format(var->bits_per_pixel, | 837 | diu_ops.get_pixel_format(var->bits_per_pixel, |
818 | machine_data->monitor_port); | 838 | machine_data->monitor_port); |
819 | ad->addr = cpu_to_le32(info->fix.smem_start); | 839 | ad->addr = cpu_to_le32(info->fix.smem_start); |
820 | ad->src_size_g_alpha = cpu_to_le32((var->yres << 12) | | 840 | ad->src_size_g_alpha = cpu_to_le32((var->yres_virtual << 12) | |
821 | var->xres) | mfbi->g_alpha; | 841 | var->xres_virtual) | mfbi->g_alpha; |
822 | /* fix me. AOI should not be greater than display size */ | 842 | /* AOI should not be greater than display size */ |
823 | ad->aoi_size = cpu_to_le32((var->yres << 16) | var->xres); | 843 | ad->aoi_size = cpu_to_le32((var->yres << 16) | var->xres); |
824 | ad->offset_xyi = 0; | 844 | ad->offset_xyi = cpu_to_le32((var->yoffset << 16) | var->xoffset); |
825 | ad->offset_xyd = cpu_to_le32((mfbi->y_aoi_d << 16) | mfbi->x_aoi_d); | 845 | ad->offset_xyd = cpu_to_le32((mfbi->y_aoi_d << 16) | mfbi->x_aoi_d); |
826 | 846 | ||
827 | /* Disable chroma keying function */ | 847 | /* Disable chroma keying function */ |
@@ -921,6 +941,8 @@ static int fsl_diu_pan_display(struct fb_var_screeninfo *var, | |||
921 | else | 941 | else |
922 | info->var.vmode &= ~FB_VMODE_YWRAP; | 942 | info->var.vmode &= ~FB_VMODE_YWRAP; |
923 | 943 | ||
944 | fsl_diu_set_aoi(info); | ||
945 | |||
924 | return 0; | 946 | return 0; |
925 | } | 947 | } |
926 | 948 | ||
@@ -989,7 +1011,7 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd, | |||
989 | pr_debug("set AOI display offset of index %d to (%d,%d)\n", | 1011 | pr_debug("set AOI display offset of index %d to (%d,%d)\n", |
990 | mfbi->index, aoi_d.x_aoi_d, aoi_d.y_aoi_d); | 1012 | mfbi->index, aoi_d.x_aoi_d, aoi_d.y_aoi_d); |
991 | fsl_diu_check_var(&info->var, info); | 1013 | fsl_diu_check_var(&info->var, info); |
992 | fsl_diu_set_par(info); | 1014 | fsl_diu_set_aoi(info); |
993 | break; | 1015 | break; |
994 | case MFB_GET_AOID: | 1016 | case MFB_GET_AOID: |
995 | aoi_d.x_aoi_d = mfbi->x_aoi_d; | 1017 | aoi_d.x_aoi_d = mfbi->x_aoi_d; |
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index e7aa7ae8fca8..97204497d9f7 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c | |||
@@ -1031,7 +1031,9 @@ static void pxafb_setup_gpio(struct pxafb_info *fbi) | |||
1031 | pxa_gpio_mode(GPIO74_LCD_FCLK_MD); | 1031 | pxa_gpio_mode(GPIO74_LCD_FCLK_MD); |
1032 | pxa_gpio_mode(GPIO75_LCD_LCLK_MD); | 1032 | pxa_gpio_mode(GPIO75_LCD_LCLK_MD); |
1033 | pxa_gpio_mode(GPIO76_LCD_PCLK_MD); | 1033 | pxa_gpio_mode(GPIO76_LCD_PCLK_MD); |
1034 | pxa_gpio_mode(GPIO77_LCD_ACBIAS_MD); | 1034 | |
1035 | if ((lccr0 & LCCR0_PAS) == 0) | ||
1036 | pxa_gpio_mode(GPIO77_LCD_ACBIAS_MD); | ||
1035 | } | 1037 | } |
1036 | 1038 | ||
1037 | static void pxafb_enable_controller(struct pxafb_info *fbi) | 1039 | static void pxafb_enable_controller(struct pxafb_info *fbi) |
@@ -1400,6 +1402,8 @@ static void pxafb_decode_mach_info(struct pxafb_info *fbi, | |||
1400 | if (lcd_conn == LCD_MONO_STN_8BPP) | 1402 | if (lcd_conn == LCD_MONO_STN_8BPP) |
1401 | fbi->lccr0 |= LCCR0_DPD; | 1403 | fbi->lccr0 |= LCCR0_DPD; |
1402 | 1404 | ||
1405 | fbi->lccr0 |= (lcd_conn & LCD_ALTERNATE_MAPPING) ? LCCR0_LDDALT : 0; | ||
1406 | |||
1403 | fbi->lccr3 = LCCR3_Acb((inf->lcd_conn >> 10) & 0xff); | 1407 | fbi->lccr3 = LCCR3_Acb((inf->lcd_conn >> 10) & 0xff); |
1404 | fbi->lccr3 |= (lcd_conn & LCD_BIAS_ACTIVE_LOW) ? LCCR3_OEP : 0; | 1408 | fbi->lccr3 |= (lcd_conn & LCD_BIAS_ACTIVE_LOW) ? LCCR3_OEP : 0; |
1405 | fbi->lccr3 |= (lcd_conn & LCD_PCLK_EDGE_FALL) ? LCCR3_PCP : 0; | 1409 | fbi->lccr3 |= (lcd_conn & LCD_PCLK_EDGE_FALL) ? LCCR3_PCP : 0; |
@@ -1673,53 +1677,63 @@ MODULE_PARM_DESC(options, "LCD parameters (see Documentation/fb/pxafb.txt)"); | |||
1673 | #define pxafb_setup_options() (0) | 1677 | #define pxafb_setup_options() (0) |
1674 | #endif | 1678 | #endif |
1675 | 1679 | ||
1676 | static int __devinit pxafb_probe(struct platform_device *dev) | ||
1677 | { | ||
1678 | struct pxafb_info *fbi; | ||
1679 | struct pxafb_mach_info *inf; | ||
1680 | struct resource *r; | ||
1681 | int irq, ret; | ||
1682 | |||
1683 | dev_dbg(&dev->dev, "pxafb_probe\n"); | ||
1684 | |||
1685 | inf = dev->dev.platform_data; | ||
1686 | ret = -ENOMEM; | ||
1687 | fbi = NULL; | ||
1688 | if (!inf) | ||
1689 | goto failed; | ||
1690 | |||
1691 | ret = pxafb_parse_options(&dev->dev, g_options); | ||
1692 | if (ret < 0) | ||
1693 | goto failed; | ||
1694 | |||
1695 | #ifdef DEBUG_VAR | 1680 | #ifdef DEBUG_VAR |
1696 | /* Check for various illegal bit-combinations. Currently only | 1681 | /* Check for various illegal bit-combinations. Currently only |
1697 | * a warning is given. */ | 1682 | * a warning is given. */ |
1683 | static void __devinit pxafb_check_options(struct device *dev, | ||
1684 | struct pxafb_mach_info *inf) | ||
1685 | { | ||
1686 | if (inf->lcd_conn) | ||
1687 | return; | ||
1698 | 1688 | ||
1699 | if (inf->lccr0 & LCCR0_INVALID_CONFIG_MASK) | 1689 | if (inf->lccr0 & LCCR0_INVALID_CONFIG_MASK) |
1700 | dev_warn(&dev->dev, "machine LCCR0 setting contains " | 1690 | dev_warn(dev, "machine LCCR0 setting contains " |
1701 | "illegal bits: %08x\n", | 1691 | "illegal bits: %08x\n", |
1702 | inf->lccr0 & LCCR0_INVALID_CONFIG_MASK); | 1692 | inf->lccr0 & LCCR0_INVALID_CONFIG_MASK); |
1703 | if (inf->lccr3 & LCCR3_INVALID_CONFIG_MASK) | 1693 | if (inf->lccr3 & LCCR3_INVALID_CONFIG_MASK) |
1704 | dev_warn(&dev->dev, "machine LCCR3 setting contains " | 1694 | dev_warn(dev, "machine LCCR3 setting contains " |
1705 | "illegal bits: %08x\n", | 1695 | "illegal bits: %08x\n", |
1706 | inf->lccr3 & LCCR3_INVALID_CONFIG_MASK); | 1696 | inf->lccr3 & LCCR3_INVALID_CONFIG_MASK); |
1707 | if (inf->lccr0 & LCCR0_DPD && | 1697 | if (inf->lccr0 & LCCR0_DPD && |
1708 | ((inf->lccr0 & LCCR0_PAS) != LCCR0_Pas || | 1698 | ((inf->lccr0 & LCCR0_PAS) != LCCR0_Pas || |
1709 | (inf->lccr0 & LCCR0_SDS) != LCCR0_Sngl || | 1699 | (inf->lccr0 & LCCR0_SDS) != LCCR0_Sngl || |
1710 | (inf->lccr0 & LCCR0_CMS) != LCCR0_Mono)) | 1700 | (inf->lccr0 & LCCR0_CMS) != LCCR0_Mono)) |
1711 | dev_warn(&dev->dev, "Double Pixel Data (DPD) mode is " | 1701 | dev_warn(dev, "Double Pixel Data (DPD) mode is " |
1712 | "only valid in passive mono" | 1702 | "only valid in passive mono" |
1713 | " single panel mode\n"); | 1703 | " single panel mode\n"); |
1714 | if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Act && | 1704 | if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Act && |
1715 | (inf->lccr0 & LCCR0_SDS) == LCCR0_Dual) | 1705 | (inf->lccr0 & LCCR0_SDS) == LCCR0_Dual) |
1716 | dev_warn(&dev->dev, "Dual panel only valid in passive mode\n"); | 1706 | dev_warn(dev, "Dual panel only valid in passive mode\n"); |
1717 | if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Pas && | 1707 | if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Pas && |
1718 | (inf->modes->upper_margin || inf->modes->lower_margin)) | 1708 | (inf->modes->upper_margin || inf->modes->lower_margin)) |
1719 | dev_warn(&dev->dev, "Upper and lower margins must be 0 in " | 1709 | dev_warn(dev, "Upper and lower margins must be 0 in " |
1720 | "passive mode\n"); | 1710 | "passive mode\n"); |
1711 | } | ||
1712 | #else | ||
1713 | #define pxafb_check_options(...) do {} while (0) | ||
1721 | #endif | 1714 | #endif |
1722 | 1715 | ||
1716 | static int __devinit pxafb_probe(struct platform_device *dev) | ||
1717 | { | ||
1718 | struct pxafb_info *fbi; | ||
1719 | struct pxafb_mach_info *inf; | ||
1720 | struct resource *r; | ||
1721 | int irq, ret; | ||
1722 | |||
1723 | dev_dbg(&dev->dev, "pxafb_probe\n"); | ||
1724 | |||
1725 | inf = dev->dev.platform_data; | ||
1726 | ret = -ENOMEM; | ||
1727 | fbi = NULL; | ||
1728 | if (!inf) | ||
1729 | goto failed; | ||
1730 | |||
1731 | ret = pxafb_parse_options(&dev->dev, g_options); | ||
1732 | if (ret < 0) | ||
1733 | goto failed; | ||
1734 | |||
1735 | pxafb_check_options(&dev->dev, inf); | ||
1736 | |||
1723 | dev_dbg(&dev->dev, "got a %dx%dx%d LCD\n", | 1737 | dev_dbg(&dev->dev, "got a %dx%dx%d LCD\n", |
1724 | inf->modes->xres, | 1738 | inf->modes->xres, |
1725 | inf->modes->yres, | 1739 | inf->modes->yres, |
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index 3da2b90d2fe6..22715e3be5e7 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c | |||
@@ -157,8 +157,6 @@ static void s3c2410wdt_start(void) | |||
157 | writel(wdt_count, wdt_base + S3C2410_WTCNT); | 157 | writel(wdt_count, wdt_base + S3C2410_WTCNT); |
158 | writel(wtcon, wdt_base + S3C2410_WTCON); | 158 | writel(wtcon, wdt_base + S3C2410_WTCON); |
159 | spin_unlock(&wdt_lock); | 159 | spin_unlock(&wdt_lock); |
160 | |||
161 | return 0; | ||
162 | } | 160 | } |
163 | 161 | ||
164 | static int s3c2410wdt_set_heartbeat(int timeout) | 162 | static int s3c2410wdt_set_heartbeat(int timeout) |