diff options
| author | Jeff Garzik <jgarzik@pobox.com> | 2005-08-14 23:10:00 -0400 |
|---|---|---|
| committer | Jeff Garzik <jgarzik@pobox.com> | 2005-08-14 23:10:00 -0400 |
| commit | 4c0e176dd5e4c44dd60f398518f75eedbe1a65f3 (patch) | |
| tree | 07aea7539f78f221c6fc535a94a07befa2afdb63 /drivers | |
| parent | f241be74b803dcf9d70c9978292946370654320f (diff) | |
| parent | 2ba84684e8cf6f980e4e95a2300f53a505eb794e (diff) | |
Merge /spare/repo/linux-2.6/
Diffstat (limited to 'drivers')
121 files changed, 3026 insertions, 2079 deletions
diff --git a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c index 3cd2e968e96c..c0a37d98b4f3 100644 --- a/drivers/acorn/block/fd1772.c +++ b/drivers/acorn/block/fd1772.c | |||
| @@ -1283,8 +1283,7 @@ static void do_fd_request(request_queue_t* q) | |||
| 1283 | if (fdc_busy) return; | 1283 | if (fdc_busy) return; |
| 1284 | save_flags(flags); | 1284 | save_flags(flags); |
| 1285 | cli(); | 1285 | cli(); |
| 1286 | while (fdc_busy) | 1286 | wait_event(fdc_wait, !fdc_busy); |
| 1287 | sleep_on(&fdc_wait); | ||
| 1288 | fdc_busy = 1; | 1287 | fdc_busy = 1; |
| 1289 | ENABLE_IRQ(); | 1288 | ENABLE_IRQ(); |
| 1290 | restore_flags(flags); | 1289 | restore_flags(flags); |
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 986410e7b483..ba13896cae40 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
| @@ -133,9 +133,10 @@ config ACPI_HOTKEY | |||
| 133 | depends on ACPI_INTERPRETER | 133 | depends on ACPI_INTERPRETER |
| 134 | depends on EXPERIMENTAL | 134 | depends on EXPERIMENTAL |
| 135 | depends on !IA64_SGI_SN | 135 | depends on !IA64_SGI_SN |
| 136 | default m | 136 | default n |
| 137 | help | 137 | help |
| 138 | ACPI generic hotkey | 138 | Experimental consolidated hotkey driver. |
| 139 | If you are unsure, say N. | ||
| 139 | 140 | ||
| 140 | config ACPI_FAN | 141 | config ACPI_FAN |
| 141 | tristate "Fan" | 142 | tristate "Fan" |
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 0f45d45f05a0..8162fd0c21a7 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c | |||
| @@ -26,6 +26,9 @@ | |||
| 26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
| 27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
| 28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
| 29 | #include <linux/types.h> | ||
| 30 | #include <linux/proc_fs.h> | ||
| 31 | #include <linux/seq_file.h> | ||
| 29 | #include <acpi/acpi_bus.h> | 32 | #include <acpi/acpi_bus.h> |
| 30 | #include <acpi/acpi_drivers.h> | 33 | #include <acpi/acpi_drivers.h> |
| 31 | 34 | ||
| @@ -33,6 +36,9 @@ | |||
| 33 | #define ACPI_BUTTON_COMPONENT 0x00080000 | 36 | #define ACPI_BUTTON_COMPONENT 0x00080000 |
| 34 | #define ACPI_BUTTON_DRIVER_NAME "ACPI Button Driver" | 37 | #define ACPI_BUTTON_DRIVER_NAME "ACPI Button Driver" |
| 35 | #define ACPI_BUTTON_CLASS "button" | 38 | #define ACPI_BUTTON_CLASS "button" |
| 39 | #define ACPI_BUTTON_FILE_INFO "info" | ||
| 40 | #define ACPI_BUTTON_FILE_STATE "state" | ||
| 41 | #define ACPI_BUTTON_TYPE_UNKNOWN 0x00 | ||
| 36 | #define ACPI_BUTTON_NOTIFY_STATUS 0x80 | 42 | #define ACPI_BUTTON_NOTIFY_STATUS 0x80 |
| 37 | 43 | ||
| 38 | #define ACPI_BUTTON_SUBCLASS_POWER "power" | 44 | #define ACPI_BUTTON_SUBCLASS_POWER "power" |
| @@ -64,6 +70,8 @@ MODULE_LICENSE("GPL"); | |||
| 64 | 70 | ||
| 65 | static int acpi_button_add (struct acpi_device *device); | 71 | static int acpi_button_add (struct acpi_device *device); |
| 66 | static int acpi_button_remove (struct acpi_device *device, int type); | 72 | static int acpi_button_remove (struct acpi_device *device, int type); |
| 73 | static int acpi_button_info_open_fs(struct inode *inode, struct file *file); | ||
| 74 | static int acpi_button_state_open_fs(struct inode *inode, struct file *file); | ||
| 67 | 75 | ||
| 68 | static struct acpi_driver acpi_button_driver = { | 76 | static struct acpi_driver acpi_button_driver = { |
| 69 | .name = ACPI_BUTTON_DRIVER_NAME, | 77 | .name = ACPI_BUTTON_DRIVER_NAME, |
| @@ -82,6 +90,179 @@ struct acpi_button { | |||
| 82 | unsigned long pushed; | 90 | unsigned long pushed; |
| 83 | }; | 91 | }; |
| 84 | 92 | ||
| 93 | static struct file_operations acpi_button_info_fops = { | ||
| 94 | .open = acpi_button_info_open_fs, | ||
| 95 | .read = seq_read, | ||
| 96 | .llseek = seq_lseek, | ||
| 97 | .release = single_release, | ||
| 98 | }; | ||
| 99 | |||
| 100 | static struct file_operations acpi_button_state_fops = { | ||
| 101 | .open = acpi_button_state_open_fs, | ||
| 102 | .read = seq_read, | ||
| 103 | .llseek = seq_lseek, | ||
| 104 | .release = single_release, | ||
| 105 | }; | ||
| 106 | /* -------------------------------------------------------------------------- | ||
| 107 | FS Interface (/proc) | ||
| 108 | -------------------------------------------------------------------------- */ | ||
| 109 | |||
| 110 | static struct proc_dir_entry *acpi_button_dir; | ||
| 111 | |||
| 112 | static int acpi_button_info_seq_show(struct seq_file *seq, void *offset) | ||
| 113 | { | ||
| 114 | struct acpi_button *button = (struct acpi_button *) seq->private; | ||
| 115 | |||
| 116 | ACPI_FUNCTION_TRACE("acpi_button_info_seq_show"); | ||
| 117 | |||
| 118 | if (!button || !button->device) | ||
| 119 | return_VALUE(0); | ||
| 120 | |||
| 121 | seq_printf(seq, "type: %s\n", | ||
| 122 | acpi_device_name(button->device)); | ||
| 123 | |||
| 124 | return_VALUE(0); | ||
| 125 | } | ||
| 126 | |||
| 127 | static int acpi_button_info_open_fs(struct inode *inode, struct file *file) | ||
| 128 | { | ||
| 129 | return single_open(file, acpi_button_info_seq_show, PDE(inode)->data); | ||
| 130 | } | ||
| 131 | |||
| 132 | static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) | ||
| 133 | { | ||
| 134 | struct acpi_button *button = (struct acpi_button *) seq->private; | ||
| 135 | acpi_status status; | ||
| 136 | unsigned long state; | ||
| 137 | |||
| 138 | ACPI_FUNCTION_TRACE("acpi_button_state_seq_show"); | ||
| 139 | |||
| 140 | if (!button || !button->device) | ||
| 141 | return_VALUE(0); | ||
| 142 | |||
| 143 | status = acpi_evaluate_integer(button->handle,"_LID",NULL,&state); | ||
| 144 | if (ACPI_FAILURE(status)) { | ||
| 145 | seq_printf(seq, "state: unsupported\n"); | ||
| 146 | } | ||
| 147 | else{ | ||
| 148 | seq_printf(seq, "state: %s\n", (state ? "open" : "closed")); | ||
| 149 | } | ||
| 150 | |||
| 151 | return_VALUE(0); | ||
| 152 | } | ||
| 153 | |||
| 154 | static int acpi_button_state_open_fs(struct inode *inode, struct file *file) | ||
| 155 | { | ||
| 156 | return single_open(file, acpi_button_state_seq_show, PDE(inode)->data); | ||
| 157 | } | ||
| 158 | |||
| 159 | static struct proc_dir_entry *acpi_power_dir; | ||
| 160 | static struct proc_dir_entry *acpi_sleep_dir; | ||
| 161 | static struct proc_dir_entry *acpi_lid_dir; | ||
| 162 | |||
| 163 | static int | ||
| 164 | acpi_button_add_fs ( | ||
| 165 | struct acpi_device *device) | ||
| 166 | { | ||
| 167 | struct proc_dir_entry *entry = NULL; | ||
| 168 | struct acpi_button *button = NULL; | ||
| 169 | |||
| 170 | ACPI_FUNCTION_TRACE("acpi_button_add_fs"); | ||
| 171 | |||
| 172 | if (!device || !acpi_driver_data(device)) | ||
| 173 | return_VALUE(-EINVAL); | ||
| 174 | |||
| 175 | button = acpi_driver_data(device); | ||
| 176 | |||
| 177 | switch (button->type) { | ||
| 178 | case ACPI_BUTTON_TYPE_POWER: | ||
| 179 | case ACPI_BUTTON_TYPE_POWERF: | ||
| 180 | if (!acpi_power_dir) | ||
| 181 | acpi_power_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_POWER, | ||
| 182 | acpi_button_dir); | ||
| 183 | entry = acpi_power_dir; | ||
| 184 | break; | ||
| 185 | case ACPI_BUTTON_TYPE_SLEEP: | ||
| 186 | case ACPI_BUTTON_TYPE_SLEEPF: | ||
| 187 | if (!acpi_sleep_dir) | ||
| 188 | acpi_sleep_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_SLEEP, | ||
| 189 | acpi_button_dir); | ||
| 190 | entry = acpi_sleep_dir; | ||
| 191 | break; | ||
| 192 | case ACPI_BUTTON_TYPE_LID: | ||
| 193 | if (!acpi_lid_dir) | ||
| 194 | acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID, | ||
| 195 | acpi_button_dir); | ||
| 196 | entry = acpi_lid_dir; | ||
| 197 | break; | ||
| 198 | } | ||
| 199 | |||
| 200 | if (!entry) | ||
| 201 | return_VALUE(-ENODEV); | ||
| 202 | entry->owner = THIS_MODULE; | ||
| 203 | |||
| 204 | acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), entry); | ||
| 205 | if (!acpi_device_dir(device)) | ||
| 206 | return_VALUE(-ENODEV); | ||
| 207 | acpi_device_dir(device)->owner = THIS_MODULE; | ||
| 208 | |||
| 209 | /* 'info' [R] */ | ||
| 210 | entry = create_proc_entry(ACPI_BUTTON_FILE_INFO, | ||
| 211 | S_IRUGO, acpi_device_dir(device)); | ||
| 212 | if (!entry) | ||
| 213 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
| 214 | "Unable to create '%s' fs entry\n", | ||
| 215 | ACPI_BUTTON_FILE_INFO)); | ||
| 216 | else { | ||
| 217 | entry->proc_fops = &acpi_button_info_fops; | ||
| 218 | entry->data = acpi_driver_data(device); | ||
| 219 | entry->owner = THIS_MODULE; | ||
| 220 | } | ||
| 221 | |||
| 222 | /* show lid state [R] */ | ||
| 223 | if (button->type == ACPI_BUTTON_TYPE_LID) { | ||
| 224 | entry = create_proc_entry(ACPI_BUTTON_FILE_STATE, | ||
| 225 | S_IRUGO, acpi_device_dir(device)); | ||
| 226 | if (!entry) | ||
| 227 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
| 228 | "Unable to create '%s' fs entry\n", | ||
| 229 | ACPI_BUTTON_FILE_INFO)); | ||
| 230 | else { | ||
| 231 | entry->proc_fops = &acpi_button_state_fops; | ||
| 232 | entry->data = acpi_driver_data(device); | ||
| 233 | entry->owner = THIS_MODULE; | ||
| 234 | } | ||
| 235 | } | ||
| 236 | |||
| 237 | return_VALUE(0); | ||
| 238 | } | ||
| 239 | |||
| 240 | |||
| 241 | static int | ||
| 242 | acpi_button_remove_fs ( | ||
| 243 | struct acpi_device *device) | ||
| 244 | { | ||
| 245 | struct acpi_button *button = NULL; | ||
| 246 | |||
| 247 | ACPI_FUNCTION_TRACE("acpi_button_remove_fs"); | ||
| 248 | |||
| 249 | button = acpi_driver_data(device); | ||
| 250 | if (acpi_device_dir(device)) { | ||
| 251 | if (button->type == ACPI_BUTTON_TYPE_LID) | ||
| 252 | remove_proc_entry(ACPI_BUTTON_FILE_STATE, | ||
| 253 | acpi_device_dir(device)); | ||
| 254 | remove_proc_entry(ACPI_BUTTON_FILE_INFO, | ||
| 255 | acpi_device_dir(device)); | ||
| 256 | |||
| 257 | remove_proc_entry(acpi_device_bid(device), | ||
| 258 | acpi_device_dir(device)->parent); | ||
| 259 | acpi_device_dir(device) = NULL; | ||
| 260 | } | ||
| 261 | |||
| 262 | return_VALUE(0); | ||
| 263 | } | ||
| 264 | |||
| 265 | |||
| 85 | /* -------------------------------------------------------------------------- | 266 | /* -------------------------------------------------------------------------- |
| 86 | Driver Interface | 267 | Driver Interface |
| 87 | -------------------------------------------------------------------------- */ | 268 | -------------------------------------------------------------------------- */ |
| @@ -121,7 +302,8 @@ acpi_button_notify_fixed ( | |||
| 121 | 302 | ||
| 122 | ACPI_FUNCTION_TRACE("acpi_button_notify_fixed"); | 303 | ACPI_FUNCTION_TRACE("acpi_button_notify_fixed"); |
| 123 | 304 | ||
| 124 | BUG_ON(!button); | 305 | if (!button) |
| 306 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
| 125 | 307 | ||
| 126 | acpi_button_notify(button->handle, ACPI_BUTTON_NOTIFY_STATUS, button); | 308 | acpi_button_notify(button->handle, ACPI_BUTTON_NOTIFY_STATUS, button); |
| 127 | 309 | ||
| @@ -197,6 +379,10 @@ acpi_button_add ( | |||
| 197 | goto end; | 379 | goto end; |
| 198 | } | 380 | } |
| 199 | 381 | ||
| 382 | result = acpi_button_add_fs(device); | ||
| 383 | if (result) | ||
| 384 | goto end; | ||
| 385 | |||
| 200 | switch (button->type) { | 386 | switch (button->type) { |
| 201 | case ACPI_BUTTON_TYPE_POWERF: | 387 | case ACPI_BUTTON_TYPE_POWERF: |
| 202 | status = acpi_install_fixed_event_handler ( | 388 | status = acpi_install_fixed_event_handler ( |
| @@ -240,6 +426,7 @@ acpi_button_add ( | |||
| 240 | 426 | ||
| 241 | end: | 427 | end: |
| 242 | if (result) { | 428 | if (result) { |
| 429 | acpi_button_remove_fs(device); | ||
| 243 | kfree(button); | 430 | kfree(button); |
| 244 | } | 431 | } |
| 245 | 432 | ||
| @@ -280,6 +467,8 @@ acpi_button_remove (struct acpi_device *device, int type) | |||
| 280 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | 467 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
| 281 | "Error removing notify handler\n")); | 468 | "Error removing notify handler\n")); |
| 282 | 469 | ||
| 470 | acpi_button_remove_fs(device); | ||
| 471 | |||
| 283 | kfree(button); | 472 | kfree(button); |
| 284 | 473 | ||
| 285 | return_VALUE(0); | 474 | return_VALUE(0); |
| @@ -293,14 +482,20 @@ acpi_button_init (void) | |||
| 293 | 482 | ||
| 294 | ACPI_FUNCTION_TRACE("acpi_button_init"); | 483 | ACPI_FUNCTION_TRACE("acpi_button_init"); |
| 295 | 484 | ||
| 485 | acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir); | ||
| 486 | if (!acpi_button_dir) | ||
| 487 | return_VALUE(-ENODEV); | ||
| 488 | acpi_button_dir->owner = THIS_MODULE; | ||
| 296 | result = acpi_bus_register_driver(&acpi_button_driver); | 489 | result = acpi_bus_register_driver(&acpi_button_driver); |
| 297 | if (result < 0) { | 490 | if (result < 0) { |
| 491 | remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); | ||
| 298 | return_VALUE(-ENODEV); | 492 | return_VALUE(-ENODEV); |
| 299 | } | 493 | } |
| 300 | 494 | ||
| 301 | return_VALUE(0); | 495 | return_VALUE(0); |
| 302 | } | 496 | } |
| 303 | 497 | ||
| 498 | |||
| 304 | static void __exit | 499 | static void __exit |
| 305 | acpi_button_exit (void) | 500 | acpi_button_exit (void) |
| 306 | { | 501 | { |
| @@ -308,8 +503,17 @@ acpi_button_exit (void) | |||
| 308 | 503 | ||
| 309 | acpi_bus_unregister_driver(&acpi_button_driver); | 504 | acpi_bus_unregister_driver(&acpi_button_driver); |
| 310 | 505 | ||
| 506 | if (acpi_power_dir) | ||
| 507 | remove_proc_entry(ACPI_BUTTON_SUBCLASS_POWER, acpi_button_dir); | ||
| 508 | if (acpi_sleep_dir) | ||
| 509 | remove_proc_entry(ACPI_BUTTON_SUBCLASS_SLEEP, acpi_button_dir); | ||
| 510 | if (acpi_lid_dir) | ||
| 511 | remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir); | ||
| 512 | remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); | ||
| 513 | |||
| 311 | return_VOID; | 514 | return_VOID; |
| 312 | } | 515 | } |
| 313 | 516 | ||
| 517 | |||
| 314 | module_init(acpi_button_init); | 518 | module_init(acpi_button_init); |
| 315 | module_exit(acpi_button_exit); | 519 | module_exit(acpi_button_exit); |
diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c index 1ac197ccfc80..d11620018421 100644 --- a/drivers/acpi/dispatcher/dswload.c +++ b/drivers/acpi/dispatcher/dswload.c | |||
| @@ -491,12 +491,6 @@ acpi_ds_load2_begin_op ( | |||
| 491 | if ((!(walk_state->op_info->flags & AML_NSOPCODE) && | 491 | if ((!(walk_state->op_info->flags & AML_NSOPCODE) && |
| 492 | (walk_state->opcode != AML_INT_NAMEPATH_OP)) || | 492 | (walk_state->opcode != AML_INT_NAMEPATH_OP)) || |
| 493 | (!(walk_state->op_info->flags & AML_NAMED))) { | 493 | (!(walk_state->op_info->flags & AML_NAMED))) { |
| 494 | if ((walk_state->op_info->class == AML_CLASS_EXECUTE) || | ||
| 495 | (walk_state->op_info->class == AML_CLASS_CONTROL)) { | ||
| 496 | ACPI_REPORT_WARNING (( | ||
| 497 | "Encountered executable code at module level, [%s]\n", | ||
| 498 | acpi_ps_get_opcode_name (walk_state->opcode))); | ||
| 499 | } | ||
| 500 | return_ACPI_STATUS (AE_OK); | 494 | return_ACPI_STATUS (AE_OK); |
| 501 | } | 495 | } |
| 502 | 496 | ||
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index fca4140a50a9..1ac5731d45e5 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
| @@ -59,76 +59,186 @@ ACPI_MODULE_NAME ("acpi_ec") | |||
| 59 | #define ACPI_EC_DELAY 50 /* Wait 50ms max. during EC ops */ | 59 | #define ACPI_EC_DELAY 50 /* Wait 50ms max. during EC ops */ |
| 60 | #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ | 60 | #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ |
| 61 | 61 | ||
| 62 | #define ACPI_EC_UDELAY 100 /* Poll @ 100us increments */ | ||
| 63 | #define ACPI_EC_UDELAY_COUNT 1000 /* Wait 10ms max. during EC ops */ | ||
| 64 | |||
| 62 | #define ACPI_EC_COMMAND_READ 0x80 | 65 | #define ACPI_EC_COMMAND_READ 0x80 |
| 63 | #define ACPI_EC_COMMAND_WRITE 0x81 | 66 | #define ACPI_EC_COMMAND_WRITE 0x81 |
| 64 | #define ACPI_EC_BURST_ENABLE 0x82 | 67 | #define ACPI_EC_BURST_ENABLE 0x82 |
| 65 | #define ACPI_EC_BURST_DISABLE 0x83 | 68 | #define ACPI_EC_BURST_DISABLE 0x83 |
| 66 | #define ACPI_EC_COMMAND_QUERY 0x84 | 69 | #define ACPI_EC_COMMAND_QUERY 0x84 |
| 67 | 70 | ||
| 68 | static int acpi_ec_add (struct acpi_device *device); | 71 | #define EC_POLLING 0xFF |
| 72 | #define EC_BURST 0x00 | ||
| 73 | |||
| 74 | |||
| 69 | static int acpi_ec_remove (struct acpi_device *device, int type); | 75 | static int acpi_ec_remove (struct acpi_device *device, int type); |
| 70 | static int acpi_ec_start (struct acpi_device *device); | 76 | static int acpi_ec_start (struct acpi_device *device); |
| 71 | static int acpi_ec_stop (struct acpi_device *device, int type); | 77 | static int acpi_ec_stop (struct acpi_device *device, int type); |
| 78 | static int acpi_ec_burst_add ( struct acpi_device *device); | ||
| 79 | static int acpi_ec_polling_add ( struct acpi_device *device); | ||
| 72 | 80 | ||
| 73 | static struct acpi_driver acpi_ec_driver = { | 81 | static struct acpi_driver acpi_ec_driver = { |
| 74 | .name = ACPI_EC_DRIVER_NAME, | 82 | .name = ACPI_EC_DRIVER_NAME, |
| 75 | .class = ACPI_EC_CLASS, | 83 | .class = ACPI_EC_CLASS, |
| 76 | .ids = ACPI_EC_HID, | 84 | .ids = ACPI_EC_HID, |
| 77 | .ops = { | 85 | .ops = { |
| 78 | .add = acpi_ec_add, | 86 | .add = acpi_ec_polling_add, |
| 79 | .remove = acpi_ec_remove, | 87 | .remove = acpi_ec_remove, |
| 80 | .start = acpi_ec_start, | 88 | .start = acpi_ec_start, |
| 81 | .stop = acpi_ec_stop, | 89 | .stop = acpi_ec_stop, |
| 82 | }, | 90 | }, |
| 83 | }; | 91 | }; |
| 84 | 92 | union acpi_ec { | |
| 85 | struct acpi_ec { | 93 | struct { |
| 86 | acpi_handle handle; | 94 | u32 mode; |
| 87 | unsigned long uid; | 95 | acpi_handle handle; |
| 88 | unsigned long gpe_bit; | 96 | unsigned long uid; |
| 89 | struct acpi_generic_address status_addr; | 97 | unsigned long gpe_bit; |
| 90 | struct acpi_generic_address command_addr; | 98 | struct acpi_generic_address status_addr; |
| 91 | struct acpi_generic_address data_addr; | 99 | struct acpi_generic_address command_addr; |
| 92 | unsigned long global_lock; | 100 | struct acpi_generic_address data_addr; |
| 93 | unsigned int expect_event; | 101 | unsigned long global_lock; |
| 94 | atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort*/ | 102 | } common; |
| 95 | atomic_t pending_gpe; | 103 | |
| 96 | struct semaphore sem; | 104 | struct { |
| 97 | wait_queue_head_t wait; | 105 | u32 mode; |
| 106 | acpi_handle handle; | ||
| 107 | unsigned long uid; | ||
| 108 | unsigned long gpe_bit; | ||
| 109 | struct acpi_generic_address status_addr; | ||
| 110 | struct acpi_generic_address command_addr; | ||
| 111 | struct acpi_generic_address data_addr; | ||
| 112 | unsigned long global_lock; | ||
| 113 | unsigned int expect_event; | ||
| 114 | atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort*/ | ||
| 115 | atomic_t pending_gpe; | ||
| 116 | struct semaphore sem; | ||
| 117 | wait_queue_head_t wait; | ||
| 118 | }burst; | ||
| 119 | |||
| 120 | struct { | ||
| 121 | u32 mode; | ||
| 122 | acpi_handle handle; | ||
| 123 | unsigned long uid; | ||
| 124 | unsigned long gpe_bit; | ||
| 125 | struct acpi_generic_address status_addr; | ||
| 126 | struct acpi_generic_address command_addr; | ||
| 127 | struct acpi_generic_address data_addr; | ||
| 128 | unsigned long global_lock; | ||
| 129 | spinlock_t lock; | ||
| 130 | }polling; | ||
| 98 | }; | 131 | }; |
| 99 | 132 | ||
| 133 | static int acpi_ec_polling_wait ( union acpi_ec *ec, u8 event); | ||
| 134 | static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event); | ||
| 135 | static int acpi_ec_polling_read ( union acpi_ec *ec, u8 address, u32 *data); | ||
| 136 | static int acpi_ec_burst_read( union acpi_ec *ec, u8 address, u32 *data); | ||
| 137 | static int acpi_ec_polling_write ( union acpi_ec *ec, u8 address, u8 data); | ||
| 138 | static int acpi_ec_burst_write ( union acpi_ec *ec, u8 address, u8 data); | ||
| 139 | static int acpi_ec_polling_query ( union acpi_ec *ec, u32 *data); | ||
| 140 | static int acpi_ec_burst_query ( union acpi_ec *ec, u32 *data); | ||
| 141 | static void acpi_ec_gpe_polling_query ( void *ec_cxt); | ||
| 142 | static void acpi_ec_gpe_burst_query ( void *ec_cxt); | ||
| 143 | static u32 acpi_ec_gpe_polling_handler ( void *data); | ||
| 144 | static u32 acpi_ec_gpe_burst_handler ( void *data); | ||
| 145 | static acpi_status __init | ||
| 146 | acpi_fake_ecdt_polling_callback ( | ||
| 147 | acpi_handle handle, | ||
| 148 | u32 Level, | ||
| 149 | void *context, | ||
| 150 | void **retval); | ||
| 151 | |||
| 152 | static acpi_status __init | ||
| 153 | acpi_fake_ecdt_burst_callback ( | ||
| 154 | acpi_handle handle, | ||
| 155 | u32 Level, | ||
| 156 | void *context, | ||
| 157 | void **retval); | ||
| 158 | |||
| 159 | static int __init | ||
| 160 | acpi_ec_polling_get_real_ecdt(void); | ||
| 161 | static int __init | ||
| 162 | acpi_ec_burst_get_real_ecdt(void); | ||
| 100 | /* If we find an EC via the ECDT, we need to keep a ptr to its context */ | 163 | /* If we find an EC via the ECDT, we need to keep a ptr to its context */ |
| 101 | static struct acpi_ec *ec_ecdt; | 164 | static union acpi_ec *ec_ecdt; |
| 102 | 165 | ||
| 103 | /* External interfaces use first EC only, so remember */ | 166 | /* External interfaces use first EC only, so remember */ |
| 104 | static struct acpi_device *first_ec; | 167 | static struct acpi_device *first_ec; |
| 168 | static int acpi_ec_polling_mode = EC_POLLING; | ||
| 105 | 169 | ||
| 106 | /* -------------------------------------------------------------------------- | 170 | /* -------------------------------------------------------------------------- |
| 107 | Transaction Management | 171 | Transaction Management |
| 108 | -------------------------------------------------------------------------- */ | 172 | -------------------------------------------------------------------------- */ |
| 109 | 173 | ||
| 110 | static inline u32 acpi_ec_read_status(struct acpi_ec *ec) | 174 | static inline u32 acpi_ec_read_status(union acpi_ec *ec) |
| 111 | { | 175 | { |
| 112 | u32 status = 0; | 176 | u32 status = 0; |
| 113 | 177 | ||
| 114 | acpi_hw_low_level_read(8, &status, &ec->status_addr); | 178 | acpi_hw_low_level_read(8, &status, &ec->common.status_addr); |
| 115 | return status; | 179 | return status; |
| 116 | } | 180 | } |
| 117 | 181 | ||
| 118 | static int acpi_ec_wait(struct acpi_ec *ec, unsigned int event) | 182 | static int |
| 183 | acpi_ec_wait ( | ||
| 184 | union acpi_ec *ec, | ||
| 185 | u8 event) | ||
| 186 | { | ||
| 187 | if (acpi_ec_polling_mode) | ||
| 188 | return acpi_ec_polling_wait (ec, event); | ||
| 189 | else | ||
| 190 | return acpi_ec_burst_wait (ec, event); | ||
| 191 | } | ||
| 192 | |||
| 193 | static int | ||
| 194 | acpi_ec_polling_wait ( | ||
| 195 | union acpi_ec *ec, | ||
| 196 | u8 event) | ||
| 197 | { | ||
| 198 | u32 acpi_ec_status = 0; | ||
| 199 | u32 i = ACPI_EC_UDELAY_COUNT; | ||
| 200 | |||
| 201 | if (!ec) | ||
| 202 | return -EINVAL; | ||
| 203 | |||
| 204 | /* Poll the EC status register waiting for the event to occur. */ | ||
| 205 | switch (event) { | ||
| 206 | case ACPI_EC_EVENT_OBF: | ||
| 207 | do { | ||
| 208 | acpi_hw_low_level_read(8, &acpi_ec_status, &ec->common.status_addr); | ||
| 209 | if (acpi_ec_status & ACPI_EC_FLAG_OBF) | ||
| 210 | return 0; | ||
| 211 | udelay(ACPI_EC_UDELAY); | ||
| 212 | } while (--i>0); | ||
| 213 | break; | ||
| 214 | case ACPI_EC_EVENT_IBE: | ||
| 215 | do { | ||
| 216 | acpi_hw_low_level_read(8, &acpi_ec_status, &ec->common.status_addr); | ||
| 217 | if (!(acpi_ec_status & ACPI_EC_FLAG_IBF)) | ||
| 218 | return 0; | ||
| 219 | udelay(ACPI_EC_UDELAY); | ||
| 220 | } while (--i>0); | ||
| 221 | break; | ||
| 222 | default: | ||
| 223 | return -EINVAL; | ||
| 224 | } | ||
| 225 | |||
| 226 | return -ETIME; | ||
| 227 | } | ||
| 228 | static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event) | ||
| 119 | { | 229 | { |
| 120 | int result = 0; | 230 | int result = 0; |
| 121 | 231 | ||
| 122 | ACPI_FUNCTION_TRACE("acpi_ec_wait"); | 232 | ACPI_FUNCTION_TRACE("acpi_ec_wait"); |
| 123 | 233 | ||
| 124 | ec->expect_event = event; | 234 | ec->burst.expect_event = event; |
| 125 | smp_mb(); | 235 | smp_mb(); |
| 126 | 236 | ||
| 127 | result = wait_event_interruptible_timeout(ec->wait, | 237 | result = wait_event_interruptible_timeout(ec->burst.wait, |
| 128 | !ec->expect_event, | 238 | !ec->burst.expect_event, |
| 129 | msecs_to_jiffies(ACPI_EC_DELAY)); | 239 | msecs_to_jiffies(ACPI_EC_DELAY)); |
| 130 | 240 | ||
| 131 | ec->expect_event = 0; | 241 | ec->burst.expect_event = 0; |
| 132 | smp_mb(); | 242 | smp_mb(); |
| 133 | 243 | ||
| 134 | if (result < 0){ | 244 | if (result < 0){ |
| @@ -160,7 +270,7 @@ static int acpi_ec_wait(struct acpi_ec *ec, unsigned int event) | |||
| 160 | 270 | ||
| 161 | static int | 271 | static int |
| 162 | acpi_ec_enter_burst_mode ( | 272 | acpi_ec_enter_burst_mode ( |
| 163 | struct acpi_ec *ec) | 273 | union acpi_ec *ec) |
| 164 | { | 274 | { |
| 165 | u32 tmp = 0; | 275 | u32 tmp = 0; |
| 166 | int status = 0; | 276 | int status = 0; |
| @@ -170,43 +280,43 @@ acpi_ec_enter_burst_mode ( | |||
| 170 | status = acpi_ec_read_status(ec); | 280 | status = acpi_ec_read_status(ec); |
| 171 | if (status != -EINVAL && | 281 | if (status != -EINVAL && |
| 172 | !(status & ACPI_EC_FLAG_BURST)){ | 282 | !(status & ACPI_EC_FLAG_BURST)){ |
| 173 | acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->command_addr); | 283 | acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->common.command_addr); |
| 174 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); | 284 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); |
| 175 | if (status){ | 285 | if (status){ |
| 176 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); | 286 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); |
| 177 | return_VALUE(-EINVAL); | 287 | return_VALUE(-EINVAL); |
| 178 | } | 288 | } |
| 179 | acpi_hw_low_level_read(8, &tmp, &ec->data_addr); | 289 | acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr); |
| 180 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); | 290 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); |
| 181 | if(tmp != 0x90 ) {/* Burst ACK byte*/ | 291 | if(tmp != 0x90 ) {/* Burst ACK byte*/ |
| 182 | return_VALUE(-EINVAL); | 292 | return_VALUE(-EINVAL); |
| 183 | } | 293 | } |
| 184 | } | 294 | } |
| 185 | 295 | ||
| 186 | atomic_set(&ec->leaving_burst , 0); | 296 | atomic_set(&ec->burst.leaving_burst , 0); |
| 187 | return_VALUE(0); | 297 | return_VALUE(0); |
| 188 | } | 298 | } |
| 189 | 299 | ||
| 190 | static int | 300 | static int |
| 191 | acpi_ec_leave_burst_mode ( | 301 | acpi_ec_leave_burst_mode ( |
| 192 | struct acpi_ec *ec) | 302 | union acpi_ec *ec) |
| 193 | { | 303 | { |
| 194 | int status =0; | 304 | int status =0; |
| 195 | 305 | ||
| 196 | ACPI_FUNCTION_TRACE("acpi_ec_leave_burst_mode"); | 306 | ACPI_FUNCTION_TRACE("acpi_ec_leave_burst_mode"); |
| 197 | 307 | ||
| 198 | atomic_set(&ec->leaving_burst , 1); | 308 | atomic_set(&ec->burst.leaving_burst , 1); |
| 199 | status = acpi_ec_read_status(ec); | 309 | status = acpi_ec_read_status(ec); |
| 200 | if (status != -EINVAL && | 310 | if (status != -EINVAL && |
| 201 | (status & ACPI_EC_FLAG_BURST)){ | 311 | (status & ACPI_EC_FLAG_BURST)){ |
| 202 | acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, &ec->command_addr); | 312 | acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, &ec->common.command_addr); |
| 203 | status = acpi_ec_wait(ec, ACPI_EC_FLAG_IBF); | 313 | status = acpi_ec_wait(ec, ACPI_EC_FLAG_IBF); |
| 204 | if (status){ | 314 | if (status){ |
| 205 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); | 315 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); |
| 206 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"------->wait fail\n")); | 316 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"------->wait fail\n")); |
| 207 | return_VALUE(-EINVAL); | 317 | return_VALUE(-EINVAL); |
| 208 | } | 318 | } |
| 209 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); | 319 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); |
| 210 | status = acpi_ec_read_status(ec); | 320 | status = acpi_ec_read_status(ec); |
| 211 | } | 321 | } |
| 212 | 322 | ||
| @@ -215,7 +325,131 @@ acpi_ec_leave_burst_mode ( | |||
| 215 | 325 | ||
| 216 | static int | 326 | static int |
| 217 | acpi_ec_read ( | 327 | acpi_ec_read ( |
| 218 | struct acpi_ec *ec, | 328 | union acpi_ec *ec, |
| 329 | u8 address, | ||
| 330 | u32 *data) | ||
| 331 | { | ||
| 332 | if (acpi_ec_polling_mode) | ||
| 333 | return acpi_ec_polling_read(ec, address, data); | ||
| 334 | else | ||
| 335 | return acpi_ec_burst_read(ec, address, data); | ||
| 336 | } | ||
| 337 | static int | ||
| 338 | acpi_ec_write ( | ||
| 339 | union acpi_ec *ec, | ||
| 340 | u8 address, | ||
| 341 | u8 data) | ||
| 342 | { | ||
| 343 | if (acpi_ec_polling_mode) | ||
| 344 | return acpi_ec_polling_write(ec, address, data); | ||
| 345 | else | ||
| 346 | return acpi_ec_burst_write(ec, address, data); | ||
| 347 | } | ||
| 348 | static int | ||
| 349 | acpi_ec_polling_read ( | ||
| 350 | union acpi_ec *ec, | ||
| 351 | u8 address, | ||
| 352 | u32 *data) | ||
| 353 | { | ||
| 354 | acpi_status status = AE_OK; | ||
| 355 | int result = 0; | ||
| 356 | unsigned long flags = 0; | ||
| 357 | u32 glk = 0; | ||
| 358 | |||
| 359 | ACPI_FUNCTION_TRACE("acpi_ec_read"); | ||
| 360 | |||
| 361 | if (!ec || !data) | ||
| 362 | return_VALUE(-EINVAL); | ||
| 363 | |||
| 364 | *data = 0; | ||
| 365 | |||
| 366 | if (ec->common.global_lock) { | ||
| 367 | status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); | ||
| 368 | if (ACPI_FAILURE(status)) | ||
| 369 | return_VALUE(-ENODEV); | ||
| 370 | } | ||
| 371 | |||
| 372 | spin_lock_irqsave(&ec->polling.lock, flags); | ||
| 373 | |||
| 374 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->common.command_addr); | ||
| 375 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | ||
| 376 | if (result) | ||
| 377 | goto end; | ||
| 378 | |||
| 379 | acpi_hw_low_level_write(8, address, &ec->common.data_addr); | ||
| 380 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); | ||
| 381 | if (result) | ||
| 382 | goto end; | ||
| 383 | |||
| 384 | acpi_hw_low_level_read(8, data, &ec->common.data_addr); | ||
| 385 | |||
| 386 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", | ||
| 387 | *data, address)); | ||
| 388 | |||
| 389 | end: | ||
| 390 | spin_unlock_irqrestore(&ec->polling.lock, flags); | ||
| 391 | |||
| 392 | if (ec->common.global_lock) | ||
| 393 | acpi_release_global_lock(glk); | ||
| 394 | |||
| 395 | return_VALUE(result); | ||
| 396 | } | ||
| 397 | |||
| 398 | |||
| 399 | static int | ||
| 400 | acpi_ec_polling_write ( | ||
| 401 | union acpi_ec *ec, | ||
| 402 | u8 address, | ||
| 403 | u8 data) | ||
| 404 | { | ||
| 405 | int result = 0; | ||
| 406 | acpi_status status = AE_OK; | ||
| 407 | unsigned long flags = 0; | ||
| 408 | u32 glk = 0; | ||
| 409 | |||
| 410 | ACPI_FUNCTION_TRACE("acpi_ec_write"); | ||
| 411 | |||
| 412 | if (!ec) | ||
| 413 | return_VALUE(-EINVAL); | ||
| 414 | |||
| 415 | if (ec->common.global_lock) { | ||
| 416 | status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); | ||
| 417 | if (ACPI_FAILURE(status)) | ||
| 418 | return_VALUE(-ENODEV); | ||
| 419 | } | ||
| 420 | |||
| 421 | spin_lock_irqsave(&ec->polling.lock, flags); | ||
| 422 | |||
| 423 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->common.command_addr); | ||
| 424 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | ||
| 425 | if (result) | ||
| 426 | goto end; | ||
| 427 | |||
| 428 | acpi_hw_low_level_write(8, address, &ec->common.data_addr); | ||
| 429 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | ||
| 430 | if (result) | ||
| 431 | goto end; | ||
| 432 | |||
| 433 | acpi_hw_low_level_write(8, data, &ec->common.data_addr); | ||
| 434 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | ||
| 435 | if (result) | ||
| 436 | goto end; | ||
| 437 | |||
| 438 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n", | ||
| 439 | data, address)); | ||
| 440 | |||
| 441 | end: | ||
| 442 | spin_unlock_irqrestore(&ec->polling.lock, flags); | ||
| 443 | |||
| 444 | if (ec->common.global_lock) | ||
| 445 | acpi_release_global_lock(glk); | ||
| 446 | |||
| 447 | return_VALUE(result); | ||
| 448 | } | ||
| 449 | |||
| 450 | static int | ||
| 451 | acpi_ec_burst_read ( | ||
| 452 | union acpi_ec *ec, | ||
| 219 | u8 address, | 453 | u8 address, |
| 220 | u32 *data) | 454 | u32 *data) |
| 221 | { | 455 | { |
| @@ -230,51 +464,51 @@ acpi_ec_read ( | |||
| 230 | retry: | 464 | retry: |
| 231 | *data = 0; | 465 | *data = 0; |
| 232 | 466 | ||
| 233 | if (ec->global_lock) { | 467 | if (ec->common.global_lock) { |
| 234 | status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); | 468 | status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); |
| 235 | if (ACPI_FAILURE(status)) | 469 | if (ACPI_FAILURE(status)) |
| 236 | return_VALUE(-ENODEV); | 470 | return_VALUE(-ENODEV); |
| 237 | } | 471 | } |
| 238 | 472 | ||
| 239 | WARN_ON(in_interrupt()); | 473 | WARN_ON(in_interrupt()); |
| 240 | down(&ec->sem); | 474 | down(&ec->burst.sem); |
| 241 | 475 | ||
| 242 | if(acpi_ec_enter_burst_mode(ec)) | 476 | if(acpi_ec_enter_burst_mode(ec)) |
| 243 | goto end; | 477 | goto end; |
| 244 | 478 | ||
| 245 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->command_addr); | 479 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->common.command_addr); |
| 246 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | 480 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); |
| 247 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); | 481 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); |
| 248 | if (status) { | 482 | if (status) { |
| 249 | goto end; | 483 | goto end; |
| 250 | } | 484 | } |
| 251 | 485 | ||
| 252 | acpi_hw_low_level_write(8, address, &ec->data_addr); | 486 | acpi_hw_low_level_write(8, address, &ec->common.data_addr); |
| 253 | status= acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); | 487 | status= acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); |
| 254 | if (status){ | 488 | if (status){ |
| 255 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); | 489 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); |
| 256 | goto end; | 490 | goto end; |
| 257 | } | 491 | } |
| 258 | 492 | ||
| 259 | acpi_hw_low_level_read(8, data, &ec->data_addr); | 493 | acpi_hw_low_level_read(8, data, &ec->common.data_addr); |
| 260 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); | 494 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); |
| 261 | 495 | ||
| 262 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", | 496 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", |
| 263 | *data, address)); | 497 | *data, address)); |
| 264 | 498 | ||
| 265 | end: | 499 | end: |
| 266 | acpi_ec_leave_burst_mode(ec); | 500 | acpi_ec_leave_burst_mode(ec); |
| 267 | up(&ec->sem); | 501 | up(&ec->burst.sem); |
| 268 | 502 | ||
| 269 | if (ec->global_lock) | 503 | if (ec->common.global_lock) |
| 270 | acpi_release_global_lock(glk); | 504 | acpi_release_global_lock(glk); |
| 271 | 505 | ||
| 272 | if(atomic_read(&ec->leaving_burst) == 2){ | 506 | if(atomic_read(&ec->burst.leaving_burst) == 2){ |
| 273 | ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n")); | 507 | ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n")); |
| 274 | while(atomic_read(&ec->pending_gpe)){ | 508 | while(atomic_read(&ec->burst.pending_gpe)){ |
| 275 | msleep(1); | 509 | msleep(1); |
| 276 | } | 510 | } |
| 277 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); | 511 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); |
| 278 | goto retry; | 512 | goto retry; |
| 279 | } | 513 | } |
| 280 | 514 | ||
| @@ -283,8 +517,8 @@ end: | |||
| 283 | 517 | ||
| 284 | 518 | ||
| 285 | static int | 519 | static int |
| 286 | acpi_ec_write ( | 520 | acpi_ec_burst_write ( |
| 287 | struct acpi_ec *ec, | 521 | union acpi_ec *ec, |
| 288 | u8 address, | 522 | u8 address, |
| 289 | u8 data) | 523 | u8 data) |
| 290 | { | 524 | { |
| @@ -297,14 +531,14 @@ acpi_ec_write ( | |||
| 297 | if (!ec) | 531 | if (!ec) |
| 298 | return_VALUE(-EINVAL); | 532 | return_VALUE(-EINVAL); |
| 299 | retry: | 533 | retry: |
| 300 | if (ec->global_lock) { | 534 | if (ec->common.global_lock) { |
| 301 | status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); | 535 | status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); |
| 302 | if (ACPI_FAILURE(status)) | 536 | if (ACPI_FAILURE(status)) |
| 303 | return_VALUE(-ENODEV); | 537 | return_VALUE(-ENODEV); |
| 304 | } | 538 | } |
| 305 | 539 | ||
| 306 | WARN_ON(in_interrupt()); | 540 | WARN_ON(in_interrupt()); |
| 307 | down(&ec->sem); | 541 | down(&ec->burst.sem); |
| 308 | 542 | ||
| 309 | if(acpi_ec_enter_burst_mode(ec)) | 543 | if(acpi_ec_enter_burst_mode(ec)) |
| 310 | goto end; | 544 | goto end; |
| @@ -312,33 +546,33 @@ retry: | |||
| 312 | status = acpi_ec_read_status(ec); | 546 | status = acpi_ec_read_status(ec); |
| 313 | if (status != -EINVAL && | 547 | if (status != -EINVAL && |
| 314 | !(status & ACPI_EC_FLAG_BURST)){ | 548 | !(status & ACPI_EC_FLAG_BURST)){ |
| 315 | acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->command_addr); | 549 | acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->common.command_addr); |
| 316 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); | 550 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); |
| 317 | if (status) | 551 | if (status) |
| 318 | goto end; | 552 | goto end; |
| 319 | acpi_hw_low_level_read(8, &tmp, &ec->data_addr); | 553 | acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr); |
| 320 | if(tmp != 0x90 ) /* Burst ACK byte*/ | 554 | if(tmp != 0x90 ) /* Burst ACK byte*/ |
| 321 | goto end; | 555 | goto end; |
| 322 | } | 556 | } |
| 323 | /*Now we are in burst mode*/ | 557 | /*Now we are in burst mode*/ |
| 324 | 558 | ||
| 325 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->command_addr); | 559 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->common.command_addr); |
| 326 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | 560 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); |
| 327 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); | 561 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); |
| 328 | if (status){ | 562 | if (status){ |
| 329 | goto end; | 563 | goto end; |
| 330 | } | 564 | } |
| 331 | 565 | ||
| 332 | acpi_hw_low_level_write(8, address, &ec->data_addr); | 566 | acpi_hw_low_level_write(8, address, &ec->common.data_addr); |
| 333 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | 567 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); |
| 334 | if (status){ | 568 | if (status){ |
| 335 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); | 569 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); |
| 336 | goto end; | 570 | goto end; |
| 337 | } | 571 | } |
| 338 | 572 | ||
| 339 | acpi_hw_low_level_write(8, data, &ec->data_addr); | 573 | acpi_hw_low_level_write(8, data, &ec->common.data_addr); |
| 340 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | 574 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); |
| 341 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); | 575 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); |
| 342 | if (status) | 576 | if (status) |
| 343 | goto end; | 577 | goto end; |
| 344 | 578 | ||
| @@ -347,17 +581,17 @@ retry: | |||
| 347 | 581 | ||
| 348 | end: | 582 | end: |
| 349 | acpi_ec_leave_burst_mode(ec); | 583 | acpi_ec_leave_burst_mode(ec); |
| 350 | up(&ec->sem); | 584 | up(&ec->burst.sem); |
| 351 | 585 | ||
| 352 | if (ec->global_lock) | 586 | if (ec->common.global_lock) |
| 353 | acpi_release_global_lock(glk); | 587 | acpi_release_global_lock(glk); |
| 354 | 588 | ||
| 355 | if(atomic_read(&ec->leaving_burst) == 2){ | 589 | if(atomic_read(&ec->burst.leaving_burst) == 2){ |
| 356 | ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n")); | 590 | ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n")); |
| 357 | while(atomic_read(&ec->pending_gpe)){ | 591 | while(atomic_read(&ec->burst.pending_gpe)){ |
| 358 | msleep(1); | 592 | msleep(1); |
| 359 | } | 593 | } |
| 360 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); | 594 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); |
| 361 | goto retry; | 595 | goto retry; |
| 362 | } | 596 | } |
| 363 | 597 | ||
| @@ -370,7 +604,7 @@ end: | |||
| 370 | int | 604 | int |
| 371 | ec_read(u8 addr, u8 *val) | 605 | ec_read(u8 addr, u8 *val) |
| 372 | { | 606 | { |
| 373 | struct acpi_ec *ec; | 607 | union acpi_ec *ec; |
| 374 | int err; | 608 | int err; |
| 375 | u32 temp_data; | 609 | u32 temp_data; |
| 376 | 610 | ||
| @@ -393,7 +627,7 @@ EXPORT_SYMBOL(ec_read); | |||
| 393 | int | 627 | int |
| 394 | ec_write(u8 addr, u8 val) | 628 | ec_write(u8 addr, u8 val) |
| 395 | { | 629 | { |
| 396 | struct acpi_ec *ec; | 630 | union acpi_ec *ec; |
| 397 | int err; | 631 | int err; |
| 398 | 632 | ||
| 399 | if (!first_ec) | 633 | if (!first_ec) |
| @@ -407,10 +641,66 @@ ec_write(u8 addr, u8 val) | |||
| 407 | } | 641 | } |
| 408 | EXPORT_SYMBOL(ec_write); | 642 | EXPORT_SYMBOL(ec_write); |
| 409 | 643 | ||
| 410 | |||
| 411 | static int | 644 | static int |
| 412 | acpi_ec_query ( | 645 | acpi_ec_query ( |
| 413 | struct acpi_ec *ec, | 646 | union acpi_ec *ec, |
| 647 | u32 *data) | ||
| 648 | { | ||
| 649 | if (acpi_ec_polling_mode) | ||
| 650 | return acpi_ec_polling_query(ec, data); | ||
| 651 | else | ||
| 652 | return acpi_ec_burst_query(ec, data); | ||
| 653 | } | ||
| 654 | static int | ||
| 655 | acpi_ec_polling_query ( | ||
| 656 | union acpi_ec *ec, | ||
| 657 | u32 *data) | ||
| 658 | { | ||
| 659 | int result = 0; | ||
| 660 | acpi_status status = AE_OK; | ||
| 661 | unsigned long flags = 0; | ||
| 662 | u32 glk = 0; | ||
| 663 | |||
| 664 | ACPI_FUNCTION_TRACE("acpi_ec_query"); | ||
| 665 | |||
| 666 | if (!ec || !data) | ||
| 667 | return_VALUE(-EINVAL); | ||
| 668 | |||
| 669 | *data = 0; | ||
| 670 | |||
| 671 | if (ec->common.global_lock) { | ||
| 672 | status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); | ||
| 673 | if (ACPI_FAILURE(status)) | ||
| 674 | return_VALUE(-ENODEV); | ||
| 675 | } | ||
| 676 | |||
| 677 | /* | ||
| 678 | * Query the EC to find out which _Qxx method we need to evaluate. | ||
| 679 | * Note that successful completion of the query causes the ACPI_EC_SCI | ||
| 680 | * bit to be cleared (and thus clearing the interrupt source). | ||
| 681 | */ | ||
| 682 | spin_lock_irqsave(&ec->polling.lock, flags); | ||
| 683 | |||
| 684 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->common.command_addr); | ||
| 685 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); | ||
| 686 | if (result) | ||
| 687 | goto end; | ||
| 688 | |||
| 689 | acpi_hw_low_level_read(8, data, &ec->common.data_addr); | ||
| 690 | if (!*data) | ||
| 691 | result = -ENODATA; | ||
| 692 | |||
| 693 | end: | ||
| 694 | spin_unlock_irqrestore(&ec->polling.lock, flags); | ||
| 695 | |||
| 696 | if (ec->common.global_lock) | ||
| 697 | acpi_release_global_lock(glk); | ||
| 698 | |||
| 699 | return_VALUE(result); | ||
| 700 | } | ||
| 701 | static int | ||
| 702 | acpi_ec_burst_query ( | ||
| 703 | union acpi_ec *ec, | ||
| 414 | u32 *data) | 704 | u32 *data) |
| 415 | { | 705 | { |
| 416 | int status = 0; | 706 | int status = 0; |
| @@ -422,13 +712,13 @@ acpi_ec_query ( | |||
| 422 | return_VALUE(-EINVAL); | 712 | return_VALUE(-EINVAL); |
| 423 | *data = 0; | 713 | *data = 0; |
| 424 | 714 | ||
| 425 | if (ec->global_lock) { | 715 | if (ec->common.global_lock) { |
| 426 | status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); | 716 | status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); |
| 427 | if (ACPI_FAILURE(status)) | 717 | if (ACPI_FAILURE(status)) |
| 428 | return_VALUE(-ENODEV); | 718 | return_VALUE(-ENODEV); |
| 429 | } | 719 | } |
| 430 | 720 | ||
| 431 | down(&ec->sem); | 721 | down(&ec->burst.sem); |
| 432 | if(acpi_ec_enter_burst_mode(ec)) | 722 | if(acpi_ec_enter_burst_mode(ec)) |
| 433 | goto end; | 723 | goto end; |
| 434 | /* | 724 | /* |
| @@ -436,28 +726,28 @@ acpi_ec_query ( | |||
| 436 | * Note that successful completion of the query causes the ACPI_EC_SCI | 726 | * Note that successful completion of the query causes the ACPI_EC_SCI |
| 437 | * bit to be cleared (and thus clearing the interrupt source). | 727 | * bit to be cleared (and thus clearing the interrupt source). |
| 438 | */ | 728 | */ |
| 439 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->command_addr); | 729 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->common.command_addr); |
| 440 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); | 730 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); |
| 441 | if (status){ | 731 | if (status){ |
| 442 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); | 732 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); |
| 443 | goto end; | 733 | goto end; |
| 444 | } | 734 | } |
| 445 | 735 | ||
| 446 | acpi_hw_low_level_read(8, data, &ec->data_addr); | 736 | acpi_hw_low_level_read(8, data, &ec->common.data_addr); |
| 447 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); | 737 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); |
| 448 | if (!*data) | 738 | if (!*data) |
| 449 | status = -ENODATA; | 739 | status = -ENODATA; |
| 450 | 740 | ||
| 451 | end: | 741 | end: |
| 452 | acpi_ec_leave_burst_mode(ec); | 742 | acpi_ec_leave_burst_mode(ec); |
| 453 | up(&ec->sem); | 743 | up(&ec->burst.sem); |
| 454 | 744 | ||
| 455 | if (ec->global_lock) | 745 | if (ec->common.global_lock) |
| 456 | acpi_release_global_lock(glk); | 746 | acpi_release_global_lock(glk); |
| 457 | 747 | ||
| 458 | if(atomic_read(&ec->leaving_burst) == 2){ | 748 | if(atomic_read(&ec->burst.leaving_burst) == 2){ |
| 459 | ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n")); | 749 | ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n")); |
| 460 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); | 750 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); |
| 461 | status = -ENODATA; | 751 | status = -ENODATA; |
| 462 | } | 752 | } |
| 463 | return_VALUE(status); | 753 | return_VALUE(status); |
| @@ -468,7 +758,7 @@ end: | |||
| 468 | Event Management | 758 | Event Management |
| 469 | -------------------------------------------------------------------------- */ | 759 | -------------------------------------------------------------------------- */ |
| 470 | 760 | ||
| 471 | struct acpi_ec_query_data { | 761 | union acpi_ec_query_data { |
| 472 | acpi_handle handle; | 762 | acpi_handle handle; |
| 473 | u8 data; | 763 | u8 data; |
| 474 | }; | 764 | }; |
| @@ -477,7 +767,59 @@ static void | |||
| 477 | acpi_ec_gpe_query ( | 767 | acpi_ec_gpe_query ( |
| 478 | void *ec_cxt) | 768 | void *ec_cxt) |
| 479 | { | 769 | { |
| 480 | struct acpi_ec *ec = (struct acpi_ec *) ec_cxt; | 770 | if (acpi_ec_polling_mode) |
| 771 | acpi_ec_gpe_polling_query(ec_cxt); | ||
| 772 | else | ||
| 773 | acpi_ec_gpe_burst_query(ec_cxt); | ||
| 774 | } | ||
| 775 | |||
| 776 | static void | ||
| 777 | acpi_ec_gpe_polling_query ( | ||
| 778 | void *ec_cxt) | ||
| 779 | { | ||
| 780 | union acpi_ec *ec = (union acpi_ec *) ec_cxt; | ||
| 781 | u32 value = 0; | ||
| 782 | unsigned long flags = 0; | ||
| 783 | static char object_name[5] = {'_','Q','0','0','\0'}; | ||
| 784 | const char hex[] = {'0','1','2','3','4','5','6','7', | ||
| 785 | '8','9','A','B','C','D','E','F'}; | ||
| 786 | |||
| 787 | ACPI_FUNCTION_TRACE("acpi_ec_gpe_query"); | ||
| 788 | |||
| 789 | if (!ec_cxt) | ||
| 790 | goto end; | ||
| 791 | |||
| 792 | spin_lock_irqsave(&ec->polling.lock, flags); | ||
| 793 | acpi_hw_low_level_read(8, &value, &ec->common.command_addr); | ||
| 794 | spin_unlock_irqrestore(&ec->polling.lock, flags); | ||
| 795 | |||
| 796 | /* TBD: Implement asynch events! | ||
| 797 | * NOTE: All we care about are EC-SCI's. Other EC events are | ||
| 798 | * handled via polling (yuck!). This is because some systems | ||
| 799 | * treat EC-SCIs as level (versus EDGE!) triggered, preventing | ||
| 800 | * a purely interrupt-driven approach (grumble, grumble). | ||
| 801 | */ | ||
| 802 | if (!(value & ACPI_EC_FLAG_SCI)) | ||
| 803 | goto end; | ||
| 804 | |||
| 805 | if (acpi_ec_query(ec, &value)) | ||
| 806 | goto end; | ||
| 807 | |||
| 808 | object_name[2] = hex[((value >> 4) & 0x0F)]; | ||
| 809 | object_name[3] = hex[(value & 0x0F)]; | ||
| 810 | |||
| 811 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name)); | ||
| 812 | |||
| 813 | acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL); | ||
| 814 | |||
| 815 | end: | ||
| 816 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
| 817 | } | ||
| 818 | static void | ||
| 819 | acpi_ec_gpe_burst_query ( | ||
| 820 | void *ec_cxt) | ||
| 821 | { | ||
| 822 | union acpi_ec *ec = (union acpi_ec *) ec_cxt; | ||
| 481 | u32 value; | 823 | u32 value; |
| 482 | int result = -ENODATA; | 824 | int result = -ENODATA; |
| 483 | static char object_name[5] = {'_','Q','0','0','\0'}; | 825 | static char object_name[5] = {'_','Q','0','0','\0'}; |
| @@ -497,9 +839,9 @@ acpi_ec_gpe_query ( | |||
| 497 | 839 | ||
| 498 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name)); | 840 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name)); |
| 499 | 841 | ||
| 500 | acpi_evaluate_object(ec->handle, object_name, NULL, NULL); | 842 | acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL); |
| 501 | end: | 843 | end: |
| 502 | atomic_dec(&ec->pending_gpe); | 844 | atomic_dec(&ec->burst.pending_gpe); |
| 503 | return; | 845 | return; |
| 504 | } | 846 | } |
| 505 | 847 | ||
| @@ -507,48 +849,77 @@ static u32 | |||
| 507 | acpi_ec_gpe_handler ( | 849 | acpi_ec_gpe_handler ( |
| 508 | void *data) | 850 | void *data) |
| 509 | { | 851 | { |
| 852 | if (acpi_ec_polling_mode) | ||
| 853 | return acpi_ec_gpe_polling_handler(data); | ||
| 854 | else | ||
| 855 | return acpi_ec_gpe_burst_handler(data); | ||
| 856 | } | ||
| 857 | static u32 | ||
| 858 | acpi_ec_gpe_polling_handler ( | ||
| 859 | void *data) | ||
| 860 | { | ||
| 861 | acpi_status status = AE_OK; | ||
| 862 | union acpi_ec *ec = (union acpi_ec *) data; | ||
| 863 | |||
| 864 | if (!ec) | ||
| 865 | return ACPI_INTERRUPT_NOT_HANDLED; | ||
| 866 | |||
| 867 | acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); | ||
| 868 | |||
| 869 | status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, | ||
| 870 | acpi_ec_gpe_query, ec); | ||
| 871 | |||
| 872 | if (status == AE_OK) | ||
| 873 | return ACPI_INTERRUPT_HANDLED; | ||
| 874 | else | ||
| 875 | return ACPI_INTERRUPT_NOT_HANDLED; | ||
| 876 | } | ||
| 877 | static u32 | ||
| 878 | acpi_ec_gpe_burst_handler ( | ||
| 879 | void *data) | ||
| 880 | { | ||
| 510 | acpi_status status = AE_OK; | 881 | acpi_status status = AE_OK; |
| 511 | u32 value; | 882 | u32 value; |
| 512 | struct acpi_ec *ec = (struct acpi_ec *) data; | 883 | union acpi_ec *ec = (union acpi_ec *) data; |
| 513 | 884 | ||
| 514 | if (!ec) | 885 | if (!ec) |
| 515 | return ACPI_INTERRUPT_NOT_HANDLED; | 886 | return ACPI_INTERRUPT_NOT_HANDLED; |
| 516 | 887 | ||
| 517 | acpi_disable_gpe(NULL, ec->gpe_bit, ACPI_ISR); | 888 | acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); |
| 518 | 889 | ||
| 519 | value = acpi_ec_read_status(ec); | 890 | value = acpi_ec_read_status(ec); |
| 520 | 891 | ||
| 521 | if((value & ACPI_EC_FLAG_IBF) && | 892 | if((value & ACPI_EC_FLAG_IBF) && |
| 522 | !(value & ACPI_EC_FLAG_BURST) && | 893 | !(value & ACPI_EC_FLAG_BURST) && |
| 523 | (atomic_read(&ec->leaving_burst) == 0)) { | 894 | (atomic_read(&ec->burst.leaving_burst) == 0)) { |
| 524 | /* | 895 | /* |
| 525 | * the embedded controller disables | 896 | * the embedded controller disables |
| 526 | * burst mode for any reason other | 897 | * burst mode for any reason other |
| 527 | * than the burst disable command | 898 | * than the burst disable command |
| 528 | * to process critical event. | 899 | * to process critical event. |
| 529 | */ | 900 | */ |
| 530 | atomic_set(&ec->leaving_burst , 2); /* block current pending transaction | 901 | atomic_set(&ec->burst.leaving_burst , 2); /* block current pending transaction |
| 531 | and retry */ | 902 | and retry */ |
| 532 | wake_up(&ec->wait); | 903 | wake_up(&ec->burst.wait); |
| 533 | }else { | 904 | }else { |
| 534 | if ((ec->expect_event == ACPI_EC_EVENT_OBF && | 905 | if ((ec->burst.expect_event == ACPI_EC_EVENT_OBF && |
| 535 | (value & ACPI_EC_FLAG_OBF)) || | 906 | (value & ACPI_EC_FLAG_OBF)) || |
| 536 | (ec->expect_event == ACPI_EC_EVENT_IBE && | 907 | (ec->burst.expect_event == ACPI_EC_EVENT_IBE && |
| 537 | !(value & ACPI_EC_FLAG_IBF))) { | 908 | !(value & ACPI_EC_FLAG_IBF))) { |
| 538 | ec->expect_event = 0; | 909 | ec->burst.expect_event = 0; |
| 539 | wake_up(&ec->wait); | 910 | wake_up(&ec->burst.wait); |
| 540 | return ACPI_INTERRUPT_HANDLED; | 911 | return ACPI_INTERRUPT_HANDLED; |
| 541 | } | 912 | } |
| 542 | } | 913 | } |
| 543 | 914 | ||
| 544 | if (value & ACPI_EC_FLAG_SCI){ | 915 | if (value & ACPI_EC_FLAG_SCI){ |
| 545 | atomic_add(1, &ec->pending_gpe) ; | 916 | atomic_add(1, &ec->burst.pending_gpe) ; |
| 546 | status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, | 917 | status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, |
| 547 | acpi_ec_gpe_query, ec); | 918 | acpi_ec_gpe_query, ec); |
| 548 | return status == AE_OK ? | 919 | return status == AE_OK ? |
| 549 | ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; | 920 | ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; |
| 550 | } | 921 | } |
| 551 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_ISR); | 922 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); |
| 552 | return status == AE_OK ? | 923 | return status == AE_OK ? |
| 553 | ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; | 924 | ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; |
| 554 | } | 925 | } |
| @@ -585,7 +956,7 @@ acpi_ec_space_handler ( | |||
| 585 | void *region_context) | 956 | void *region_context) |
| 586 | { | 957 | { |
| 587 | int result = 0; | 958 | int result = 0; |
| 588 | struct acpi_ec *ec = NULL; | 959 | union acpi_ec *ec = NULL; |
| 589 | u64 temp = *value; | 960 | u64 temp = *value; |
| 590 | acpi_integer f_v = 0; | 961 | acpi_integer f_v = 0; |
| 591 | int i = 0; | 962 | int i = 0; |
| @@ -600,7 +971,7 @@ acpi_ec_space_handler ( | |||
| 600 | return_VALUE(AE_BAD_PARAMETER); | 971 | return_VALUE(AE_BAD_PARAMETER); |
| 601 | } | 972 | } |
| 602 | 973 | ||
| 603 | ec = (struct acpi_ec *) handler_context; | 974 | ec = (union acpi_ec *) handler_context; |
| 604 | 975 | ||
| 605 | next_byte: | 976 | next_byte: |
| 606 | switch (function) { | 977 | switch (function) { |
| @@ -661,7 +1032,7 @@ static struct proc_dir_entry *acpi_ec_dir; | |||
| 661 | static int | 1032 | static int |
| 662 | acpi_ec_read_info (struct seq_file *seq, void *offset) | 1033 | acpi_ec_read_info (struct seq_file *seq, void *offset) |
| 663 | { | 1034 | { |
| 664 | struct acpi_ec *ec = (struct acpi_ec *) seq->private; | 1035 | union acpi_ec *ec = (union acpi_ec *) seq->private; |
| 665 | 1036 | ||
| 666 | ACPI_FUNCTION_TRACE("acpi_ec_read_info"); | 1037 | ACPI_FUNCTION_TRACE("acpi_ec_read_info"); |
| 667 | 1038 | ||
| @@ -669,12 +1040,12 @@ acpi_ec_read_info (struct seq_file *seq, void *offset) | |||
| 669 | goto end; | 1040 | goto end; |
| 670 | 1041 | ||
| 671 | seq_printf(seq, "gpe bit: 0x%02x\n", | 1042 | seq_printf(seq, "gpe bit: 0x%02x\n", |
| 672 | (u32) ec->gpe_bit); | 1043 | (u32) ec->common.gpe_bit); |
| 673 | seq_printf(seq, "ports: 0x%02x, 0x%02x\n", | 1044 | seq_printf(seq, "ports: 0x%02x, 0x%02x\n", |
| 674 | (u32) ec->status_addr.address, (u32) ec->data_addr.address); | 1045 | (u32) ec->common.status_addr.address, (u32) ec->common.data_addr.address); |
| 675 | seq_printf(seq, "use global lock: %s\n", | 1046 | seq_printf(seq, "use global lock: %s\n", |
| 676 | ec->global_lock?"yes":"no"); | 1047 | ec->common.global_lock?"yes":"no"); |
| 677 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); | 1048 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); |
| 678 | 1049 | ||
| 679 | end: | 1050 | end: |
| 680 | return_VALUE(0); | 1051 | return_VALUE(0); |
| @@ -697,7 +1068,7 @@ static int | |||
| 697 | acpi_ec_add_fs ( | 1068 | acpi_ec_add_fs ( |
| 698 | struct acpi_device *device) | 1069 | struct acpi_device *device) |
| 699 | { | 1070 | { |
| 700 | struct proc_dir_entry *entry; | 1071 | struct proc_dir_entry *entry = NULL; |
| 701 | 1072 | ||
| 702 | ACPI_FUNCTION_TRACE("acpi_ec_add_fs"); | 1073 | ACPI_FUNCTION_TRACE("acpi_ec_add_fs"); |
| 703 | 1074 | ||
| @@ -744,13 +1115,14 @@ acpi_ec_remove_fs ( | |||
| 744 | Driver Interface | 1115 | Driver Interface |
| 745 | -------------------------------------------------------------------------- */ | 1116 | -------------------------------------------------------------------------- */ |
| 746 | 1117 | ||
| 1118 | |||
| 747 | static int | 1119 | static int |
| 748 | acpi_ec_add ( | 1120 | acpi_ec_polling_add ( |
| 749 | struct acpi_device *device) | 1121 | struct acpi_device *device) |
| 750 | { | 1122 | { |
| 751 | int result; | 1123 | int result = 0; |
| 752 | acpi_status status; | 1124 | acpi_status status = AE_OK; |
| 753 | struct acpi_ec *ec; | 1125 | union acpi_ec *ec = NULL; |
| 754 | unsigned long uid; | 1126 | unsigned long uid; |
| 755 | 1127 | ||
| 756 | ACPI_FUNCTION_TRACE("acpi_ec_add"); | 1128 | ACPI_FUNCTION_TRACE("acpi_ec_add"); |
| @@ -758,39 +1130,107 @@ acpi_ec_add ( | |||
| 758 | if (!device) | 1130 | if (!device) |
| 759 | return_VALUE(-EINVAL); | 1131 | return_VALUE(-EINVAL); |
| 760 | 1132 | ||
| 761 | ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); | 1133 | ec = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); |
| 762 | if (!ec) | 1134 | if (!ec) |
| 763 | return_VALUE(-ENOMEM); | 1135 | return_VALUE(-ENOMEM); |
| 764 | memset(ec, 0, sizeof(struct acpi_ec)); | 1136 | memset(ec, 0, sizeof(union acpi_ec)); |
| 765 | 1137 | ||
| 766 | ec->handle = device->handle; | 1138 | ec->common.handle = device->handle; |
| 767 | ec->uid = -1; | 1139 | ec->common.uid = -1; |
| 768 | atomic_set(&ec->pending_gpe, 0); | 1140 | spin_lock_init(&ec->polling.lock); |
| 769 | atomic_set(&ec->leaving_burst , 1); | ||
| 770 | init_MUTEX(&ec->sem); | ||
| 771 | init_waitqueue_head(&ec->wait); | ||
| 772 | strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); | 1141 | strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); |
| 773 | strcpy(acpi_device_class(device), ACPI_EC_CLASS); | 1142 | strcpy(acpi_device_class(device), ACPI_EC_CLASS); |
| 774 | acpi_driver_data(device) = ec; | 1143 | acpi_driver_data(device) = ec; |
| 775 | 1144 | ||
| 776 | /* Use the global lock for all EC transactions? */ | 1145 | /* Use the global lock for all EC transactions? */ |
| 777 | acpi_evaluate_integer(ec->handle, "_GLK", NULL, &ec->global_lock); | 1146 | acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, &ec->common.global_lock); |
| 778 | 1147 | ||
| 779 | /* If our UID matches the UID for the ECDT-enumerated EC, | 1148 | /* If our UID matches the UID for the ECDT-enumerated EC, |
| 780 | we now have the *real* EC info, so kill the makeshift one.*/ | 1149 | we now have the *real* EC info, so kill the makeshift one.*/ |
| 781 | acpi_evaluate_integer(ec->handle, "_UID", NULL, &uid); | 1150 | acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid); |
| 782 | if (ec_ecdt && ec_ecdt->uid == uid) { | 1151 | if (ec_ecdt && ec_ecdt->common.uid == uid) { |
| 783 | acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, | 1152 | acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, |
| 784 | ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); | 1153 | ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); |
| 1154 | |||
| 1155 | acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, &acpi_ec_gpe_handler); | ||
| 1156 | |||
| 1157 | kfree(ec_ecdt); | ||
| 1158 | } | ||
| 1159 | |||
| 1160 | /* Get GPE bit assignment (EC events). */ | ||
| 1161 | /* TODO: Add support for _GPE returning a package */ | ||
| 1162 | status = acpi_evaluate_integer(ec->common.handle, "_GPE", NULL, &ec->common.gpe_bit); | ||
| 1163 | if (ACPI_FAILURE(status)) { | ||
| 1164 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
| 1165 | "Error obtaining GPE bit assignment\n")); | ||
| 1166 | result = -ENODEV; | ||
| 1167 | goto end; | ||
| 1168 | } | ||
| 785 | 1169 | ||
| 786 | acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit, &acpi_ec_gpe_handler); | 1170 | result = acpi_ec_add_fs(device); |
| 1171 | if (result) | ||
| 1172 | goto end; | ||
| 1173 | |||
| 1174 | printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n", | ||
| 1175 | acpi_device_name(device), acpi_device_bid(device), | ||
| 1176 | (u32) ec->common.gpe_bit); | ||
| 1177 | |||
| 1178 | if (!first_ec) | ||
| 1179 | first_ec = device; | ||
| 1180 | |||
| 1181 | end: | ||
| 1182 | if (result) | ||
| 1183 | kfree(ec); | ||
| 1184 | |||
| 1185 | return_VALUE(result); | ||
| 1186 | } | ||
| 1187 | static int | ||
| 1188 | acpi_ec_burst_add ( | ||
| 1189 | struct acpi_device *device) | ||
| 1190 | { | ||
| 1191 | int result = 0; | ||
| 1192 | acpi_status status = AE_OK; | ||
| 1193 | union acpi_ec *ec = NULL; | ||
| 1194 | unsigned long uid; | ||
| 1195 | |||
| 1196 | ACPI_FUNCTION_TRACE("acpi_ec_add"); | ||
| 1197 | |||
| 1198 | if (!device) | ||
| 1199 | return_VALUE(-EINVAL); | ||
| 1200 | |||
| 1201 | ec = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); | ||
| 1202 | if (!ec) | ||
| 1203 | return_VALUE(-ENOMEM); | ||
| 1204 | memset(ec, 0, sizeof(union acpi_ec)); | ||
| 1205 | |||
| 1206 | ec->common.handle = device->handle; | ||
| 1207 | ec->common.uid = -1; | ||
| 1208 | atomic_set(&ec->burst.pending_gpe, 0); | ||
| 1209 | atomic_set(&ec->burst.leaving_burst , 1); | ||
| 1210 | init_MUTEX(&ec->burst.sem); | ||
| 1211 | init_waitqueue_head(&ec->burst.wait); | ||
| 1212 | strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); | ||
| 1213 | strcpy(acpi_device_class(device), ACPI_EC_CLASS); | ||
| 1214 | acpi_driver_data(device) = ec; | ||
| 1215 | |||
| 1216 | /* Use the global lock for all EC transactions? */ | ||
| 1217 | acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, &ec->common.global_lock); | ||
| 1218 | |||
| 1219 | /* If our UID matches the UID for the ECDT-enumerated EC, | ||
| 1220 | we now have the *real* EC info, so kill the makeshift one.*/ | ||
| 1221 | acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid); | ||
| 1222 | if (ec_ecdt && ec_ecdt->common.uid == uid) { | ||
| 1223 | acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, | ||
| 1224 | ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); | ||
| 1225 | |||
| 1226 | acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, &acpi_ec_gpe_handler); | ||
| 787 | 1227 | ||
| 788 | kfree(ec_ecdt); | 1228 | kfree(ec_ecdt); |
| 789 | } | 1229 | } |
| 790 | 1230 | ||
| 791 | /* Get GPE bit assignment (EC events). */ | 1231 | /* Get GPE bit assignment (EC events). */ |
| 792 | /* TODO: Add support for _GPE returning a package */ | 1232 | /* TODO: Add support for _GPE returning a package */ |
| 793 | status = acpi_evaluate_integer(ec->handle, "_GPE", NULL, &ec->gpe_bit); | 1233 | status = acpi_evaluate_integer(ec->common.handle, "_GPE", NULL, &ec->common.gpe_bit); |
| 794 | if (ACPI_FAILURE(status)) { | 1234 | if (ACPI_FAILURE(status)) { |
| 795 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | 1235 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
| 796 | "Error obtaining GPE bit assignment\n")); | 1236 | "Error obtaining GPE bit assignment\n")); |
| @@ -804,7 +1244,7 @@ acpi_ec_add ( | |||
| 804 | 1244 | ||
| 805 | printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n", | 1245 | printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n", |
| 806 | acpi_device_name(device), acpi_device_bid(device), | 1246 | acpi_device_name(device), acpi_device_bid(device), |
| 807 | (u32) ec->gpe_bit); | 1247 | (u32) ec->common.gpe_bit); |
| 808 | 1248 | ||
| 809 | if (!first_ec) | 1249 | if (!first_ec) |
| 810 | first_ec = device; | 1250 | first_ec = device; |
| @@ -822,7 +1262,7 @@ acpi_ec_remove ( | |||
| 822 | struct acpi_device *device, | 1262 | struct acpi_device *device, |
| 823 | int type) | 1263 | int type) |
| 824 | { | 1264 | { |
| 825 | struct acpi_ec *ec; | 1265 | union acpi_ec *ec = NULL; |
| 826 | 1266 | ||
| 827 | ACPI_FUNCTION_TRACE("acpi_ec_remove"); | 1267 | ACPI_FUNCTION_TRACE("acpi_ec_remove"); |
| 828 | 1268 | ||
| @@ -844,7 +1284,7 @@ acpi_ec_io_ports ( | |||
| 844 | struct acpi_resource *resource, | 1284 | struct acpi_resource *resource, |
| 845 | void *context) | 1285 | void *context) |
| 846 | { | 1286 | { |
| 847 | struct acpi_ec *ec = (struct acpi_ec *) context; | 1287 | union acpi_ec *ec = (union acpi_ec *) context; |
| 848 | struct acpi_generic_address *addr; | 1288 | struct acpi_generic_address *addr; |
| 849 | 1289 | ||
| 850 | if (resource->id != ACPI_RSTYPE_IO) { | 1290 | if (resource->id != ACPI_RSTYPE_IO) { |
| @@ -856,10 +1296,10 @@ acpi_ec_io_ports ( | |||
| 856 | * the second address region returned is the status/command | 1296 | * the second address region returned is the status/command |
| 857 | * port. | 1297 | * port. |
| 858 | */ | 1298 | */ |
| 859 | if (ec->data_addr.register_bit_width == 0) { | 1299 | if (ec->common.data_addr.register_bit_width == 0) { |
| 860 | addr = &ec->data_addr; | 1300 | addr = &ec->common.data_addr; |
| 861 | } else if (ec->command_addr.register_bit_width == 0) { | 1301 | } else if (ec->common.command_addr.register_bit_width == 0) { |
| 862 | addr = &ec->command_addr; | 1302 | addr = &ec->common.command_addr; |
| 863 | } else { | 1303 | } else { |
| 864 | return AE_CTRL_TERMINATE; | 1304 | return AE_CTRL_TERMINATE; |
| 865 | } | 1305 | } |
| @@ -877,8 +1317,8 @@ static int | |||
| 877 | acpi_ec_start ( | 1317 | acpi_ec_start ( |
| 878 | struct acpi_device *device) | 1318 | struct acpi_device *device) |
| 879 | { | 1319 | { |
| 880 | acpi_status status; | 1320 | acpi_status status = AE_OK; |
| 881 | struct acpi_ec *ec; | 1321 | union acpi_ec *ec = NULL; |
| 882 | 1322 | ||
| 883 | ACPI_FUNCTION_TRACE("acpi_ec_start"); | 1323 | ACPI_FUNCTION_TRACE("acpi_ec_start"); |
| 884 | 1324 | ||
| @@ -893,35 +1333,36 @@ acpi_ec_start ( | |||
| 893 | /* | 1333 | /* |
| 894 | * Get I/O port addresses. Convert to GAS format. | 1334 | * Get I/O port addresses. Convert to GAS format. |
| 895 | */ | 1335 | */ |
| 896 | status = acpi_walk_resources(ec->handle, METHOD_NAME__CRS, | 1336 | status = acpi_walk_resources(ec->common.handle, METHOD_NAME__CRS, |
| 897 | acpi_ec_io_ports, ec); | 1337 | acpi_ec_io_ports, ec); |
| 898 | if (ACPI_FAILURE(status) || ec->command_addr.register_bit_width == 0) { | 1338 | if (ACPI_FAILURE(status) || ec->common.command_addr.register_bit_width == 0) { |
| 899 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error getting I/O port addresses")); | 1339 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error getting I/O port addresses")); |
| 900 | return_VALUE(-ENODEV); | 1340 | return_VALUE(-ENODEV); |
| 901 | } | 1341 | } |
| 902 | 1342 | ||
| 903 | ec->status_addr = ec->command_addr; | 1343 | ec->common.status_addr = ec->common.command_addr; |
| 904 | 1344 | ||
| 905 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02x, ports=0x%2x,0x%2x\n", | 1345 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02x, ports=0x%2x,0x%2x\n", |
| 906 | (u32) ec->gpe_bit, (u32) ec->command_addr.address, | 1346 | (u32) ec->common.gpe_bit, (u32) ec->common.command_addr.address, |
| 907 | (u32) ec->data_addr.address)); | 1347 | (u32) ec->common.data_addr.address)); |
| 1348 | |||
| 908 | 1349 | ||
| 909 | /* | 1350 | /* |
| 910 | * Install GPE handler | 1351 | * Install GPE handler |
| 911 | */ | 1352 | */ |
| 912 | status = acpi_install_gpe_handler(NULL, ec->gpe_bit, | 1353 | status = acpi_install_gpe_handler(NULL, ec->common.gpe_bit, |
| 913 | ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler, ec); | 1354 | ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler, ec); |
| 914 | if (ACPI_FAILURE(status)) { | 1355 | if (ACPI_FAILURE(status)) { |
| 915 | return_VALUE(-ENODEV); | 1356 | return_VALUE(-ENODEV); |
| 916 | } | 1357 | } |
| 917 | acpi_set_gpe_type (NULL, ec->gpe_bit, ACPI_GPE_TYPE_RUNTIME); | 1358 | acpi_set_gpe_type (NULL, ec->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME); |
| 918 | acpi_enable_gpe (NULL, ec->gpe_bit, ACPI_NOT_ISR); | 1359 | acpi_enable_gpe (NULL, ec->common.gpe_bit, ACPI_NOT_ISR); |
| 919 | 1360 | ||
| 920 | status = acpi_install_address_space_handler (ec->handle, | 1361 | status = acpi_install_address_space_handler (ec->common.handle, |
| 921 | ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, | 1362 | ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, |
| 922 | &acpi_ec_space_setup, ec); | 1363 | &acpi_ec_space_setup, ec); |
| 923 | if (ACPI_FAILURE(status)) { | 1364 | if (ACPI_FAILURE(status)) { |
| 924 | acpi_remove_gpe_handler(NULL, ec->gpe_bit, &acpi_ec_gpe_handler); | 1365 | acpi_remove_gpe_handler(NULL, ec->common.gpe_bit, &acpi_ec_gpe_handler); |
| 925 | return_VALUE(-ENODEV); | 1366 | return_VALUE(-ENODEV); |
| 926 | } | 1367 | } |
| 927 | 1368 | ||
| @@ -934,8 +1375,8 @@ acpi_ec_stop ( | |||
| 934 | struct acpi_device *device, | 1375 | struct acpi_device *device, |
| 935 | int type) | 1376 | int type) |
| 936 | { | 1377 | { |
| 937 | acpi_status status; | 1378 | acpi_status status = AE_OK; |
| 938 | struct acpi_ec *ec; | 1379 | union acpi_ec *ec = NULL; |
| 939 | 1380 | ||
| 940 | ACPI_FUNCTION_TRACE("acpi_ec_stop"); | 1381 | ACPI_FUNCTION_TRACE("acpi_ec_stop"); |
| 941 | 1382 | ||
| @@ -944,12 +1385,12 @@ acpi_ec_stop ( | |||
| 944 | 1385 | ||
| 945 | ec = acpi_driver_data(device); | 1386 | ec = acpi_driver_data(device); |
| 946 | 1387 | ||
| 947 | status = acpi_remove_address_space_handler(ec->handle, | 1388 | status = acpi_remove_address_space_handler(ec->common.handle, |
| 948 | ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); | 1389 | ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); |
| 949 | if (ACPI_FAILURE(status)) | 1390 | if (ACPI_FAILURE(status)) |
| 950 | return_VALUE(-ENODEV); | 1391 | return_VALUE(-ENODEV); |
| 951 | 1392 | ||
| 952 | status = acpi_remove_gpe_handler(NULL, ec->gpe_bit, &acpi_ec_gpe_handler); | 1393 | status = acpi_remove_gpe_handler(NULL, ec->common.gpe_bit, &acpi_ec_gpe_handler); |
| 953 | if (ACPI_FAILURE(status)) | 1394 | if (ACPI_FAILURE(status)) |
| 954 | return_VALUE(-ENODEV); | 1395 | return_VALUE(-ENODEV); |
| 955 | 1396 | ||
| @@ -963,26 +1404,76 @@ acpi_fake_ecdt_callback ( | |||
| 963 | void *context, | 1404 | void *context, |
| 964 | void **retval) | 1405 | void **retval) |
| 965 | { | 1406 | { |
| 1407 | |||
| 1408 | if (acpi_ec_polling_mode) | ||
| 1409 | return acpi_fake_ecdt_polling_callback(handle, | ||
| 1410 | Level, context, retval); | ||
| 1411 | else | ||
| 1412 | return acpi_fake_ecdt_burst_callback(handle, | ||
| 1413 | Level, context, retval); | ||
| 1414 | } | ||
| 1415 | |||
| 1416 | static acpi_status __init | ||
| 1417 | acpi_fake_ecdt_polling_callback ( | ||
| 1418 | acpi_handle handle, | ||
| 1419 | u32 Level, | ||
| 1420 | void *context, | ||
| 1421 | void **retval) | ||
| 1422 | { | ||
| 966 | acpi_status status; | 1423 | acpi_status status; |
| 967 | 1424 | ||
| 968 | status = acpi_walk_resources(handle, METHOD_NAME__CRS, | 1425 | status = acpi_walk_resources(handle, METHOD_NAME__CRS, |
| 969 | acpi_ec_io_ports, ec_ecdt); | 1426 | acpi_ec_io_ports, ec_ecdt); |
| 970 | if (ACPI_FAILURE(status)) | 1427 | if (ACPI_FAILURE(status)) |
| 971 | return status; | 1428 | return status; |
| 972 | ec_ecdt->status_addr = ec_ecdt->command_addr; | 1429 | ec_ecdt->common.status_addr = ec_ecdt->common.command_addr; |
| 973 | 1430 | ||
| 974 | ec_ecdt->uid = -1; | 1431 | ec_ecdt->common.uid = -1; |
| 975 | acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->uid); | 1432 | acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->common.uid); |
| 976 | 1433 | ||
| 977 | status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->gpe_bit); | 1434 | status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->common.gpe_bit); |
| 978 | if (ACPI_FAILURE(status)) | 1435 | if (ACPI_FAILURE(status)) |
| 979 | return status; | 1436 | return status; |
| 980 | ec_ecdt->global_lock = TRUE; | 1437 | spin_lock_init(&ec_ecdt->polling.lock); |
| 981 | ec_ecdt->handle = handle; | 1438 | ec_ecdt->common.global_lock = TRUE; |
| 1439 | ec_ecdt->common.handle = handle; | ||
| 982 | 1440 | ||
| 983 | printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n", | 1441 | printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n", |
| 984 | (u32) ec_ecdt->gpe_bit, (u32) ec_ecdt->command_addr.address, | 1442 | (u32) ec_ecdt->common.gpe_bit, (u32) ec_ecdt->common.command_addr.address, |
| 985 | (u32) ec_ecdt->data_addr.address); | 1443 | (u32) ec_ecdt->common.data_addr.address); |
| 1444 | |||
| 1445 | return AE_CTRL_TERMINATE; | ||
| 1446 | } | ||
| 1447 | |||
| 1448 | static acpi_status __init | ||
| 1449 | acpi_fake_ecdt_burst_callback ( | ||
| 1450 | acpi_handle handle, | ||
| 1451 | u32 Level, | ||
| 1452 | void *context, | ||
| 1453 | void **retval) | ||
| 1454 | { | ||
| 1455 | acpi_status status; | ||
| 1456 | |||
| 1457 | init_MUTEX(&ec_ecdt->burst.sem); | ||
| 1458 | init_waitqueue_head(&ec_ecdt->burst.wait); | ||
| 1459 | status = acpi_walk_resources(handle, METHOD_NAME__CRS, | ||
| 1460 | acpi_ec_io_ports, ec_ecdt); | ||
| 1461 | if (ACPI_FAILURE(status)) | ||
| 1462 | return status; | ||
| 1463 | ec_ecdt->common.status_addr = ec_ecdt->common.command_addr; | ||
| 1464 | |||
| 1465 | ec_ecdt->common.uid = -1; | ||
| 1466 | acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->common.uid); | ||
| 1467 | |||
| 1468 | status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->common.gpe_bit); | ||
| 1469 | if (ACPI_FAILURE(status)) | ||
| 1470 | return status; | ||
| 1471 | ec_ecdt->common.global_lock = TRUE; | ||
| 1472 | ec_ecdt->common.handle = handle; | ||
| 1473 | |||
| 1474 | printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n", | ||
| 1475 | (u32) ec_ecdt->common.gpe_bit, (u32) ec_ecdt->common.command_addr.address, | ||
| 1476 | (u32) ec_ecdt->common.data_addr.address); | ||
| 986 | 1477 | ||
| 987 | return AE_CTRL_TERMINATE; | 1478 | return AE_CTRL_TERMINATE; |
| 988 | } | 1479 | } |
| @@ -1005,12 +1496,12 @@ acpi_ec_fake_ecdt(void) | |||
| 1005 | 1496 | ||
| 1006 | printk(KERN_INFO PREFIX "Try to make an fake ECDT\n"); | 1497 | printk(KERN_INFO PREFIX "Try to make an fake ECDT\n"); |
| 1007 | 1498 | ||
| 1008 | ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); | 1499 | ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); |
| 1009 | if (!ec_ecdt) { | 1500 | if (!ec_ecdt) { |
| 1010 | ret = -ENOMEM; | 1501 | ret = -ENOMEM; |
| 1011 | goto error; | 1502 | goto error; |
| 1012 | } | 1503 | } |
| 1013 | memset(ec_ecdt, 0, sizeof(struct acpi_ec)); | 1504 | memset(ec_ecdt, 0, sizeof(union acpi_ec)); |
| 1014 | 1505 | ||
| 1015 | status = acpi_get_devices (ACPI_EC_HID, | 1506 | status = acpi_get_devices (ACPI_EC_HID, |
| 1016 | acpi_fake_ecdt_callback, | 1507 | acpi_fake_ecdt_callback, |
| @@ -1031,6 +1522,60 @@ error: | |||
| 1031 | static int __init | 1522 | static int __init |
| 1032 | acpi_ec_get_real_ecdt(void) | 1523 | acpi_ec_get_real_ecdt(void) |
| 1033 | { | 1524 | { |
| 1525 | if (acpi_ec_polling_mode) | ||
| 1526 | return acpi_ec_polling_get_real_ecdt(); | ||
| 1527 | else | ||
| 1528 | return acpi_ec_burst_get_real_ecdt(); | ||
| 1529 | } | ||
| 1530 | |||
| 1531 | static int __init | ||
| 1532 | acpi_ec_polling_get_real_ecdt(void) | ||
| 1533 | { | ||
| 1534 | acpi_status status; | ||
| 1535 | struct acpi_table_ecdt *ecdt_ptr; | ||
| 1536 | |||
| 1537 | status = acpi_get_firmware_table("ECDT", 1, ACPI_LOGICAL_ADDRESSING, | ||
| 1538 | (struct acpi_table_header **) &ecdt_ptr); | ||
| 1539 | if (ACPI_FAILURE(status)) | ||
| 1540 | return -ENODEV; | ||
| 1541 | |||
| 1542 | printk(KERN_INFO PREFIX "Found ECDT\n"); | ||
| 1543 | |||
| 1544 | /* | ||
| 1545 | * Generate a temporary ec context to use until the namespace is scanned | ||
| 1546 | */ | ||
| 1547 | ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); | ||
| 1548 | if (!ec_ecdt) | ||
| 1549 | return -ENOMEM; | ||
| 1550 | memset(ec_ecdt, 0, sizeof(union acpi_ec)); | ||
| 1551 | |||
| 1552 | ec_ecdt->common.command_addr = ecdt_ptr->ec_control; | ||
| 1553 | ec_ecdt->common.status_addr = ecdt_ptr->ec_control; | ||
| 1554 | ec_ecdt->common.data_addr = ecdt_ptr->ec_data; | ||
| 1555 | ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit; | ||
| 1556 | spin_lock_init(&ec_ecdt->polling.lock); | ||
| 1557 | /* use the GL just to be safe */ | ||
| 1558 | ec_ecdt->common.global_lock = TRUE; | ||
| 1559 | ec_ecdt->common.uid = ecdt_ptr->uid; | ||
| 1560 | |||
| 1561 | status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle); | ||
| 1562 | if (ACPI_FAILURE(status)) { | ||
| 1563 | goto error; | ||
| 1564 | } | ||
| 1565 | |||
| 1566 | return 0; | ||
| 1567 | error: | ||
| 1568 | printk(KERN_ERR PREFIX "Could not use ECDT\n"); | ||
| 1569 | kfree(ec_ecdt); | ||
| 1570 | ec_ecdt = NULL; | ||
| 1571 | |||
| 1572 | return -ENODEV; | ||
| 1573 | } | ||
| 1574 | |||
| 1575 | |||
| 1576 | static int __init | ||
| 1577 | acpi_ec_burst_get_real_ecdt(void) | ||
| 1578 | { | ||
| 1034 | acpi_status status; | 1579 | acpi_status status; |
| 1035 | struct acpi_table_ecdt *ecdt_ptr; | 1580 | struct acpi_table_ecdt *ecdt_ptr; |
| 1036 | 1581 | ||
| @@ -1044,22 +1589,22 @@ acpi_ec_get_real_ecdt(void) | |||
| 1044 | /* | 1589 | /* |
| 1045 | * Generate a temporary ec context to use until the namespace is scanned | 1590 | * Generate a temporary ec context to use until the namespace is scanned |
| 1046 | */ | 1591 | */ |
| 1047 | ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); | 1592 | ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); |
| 1048 | if (!ec_ecdt) | 1593 | if (!ec_ecdt) |
| 1049 | return -ENOMEM; | 1594 | return -ENOMEM; |
| 1050 | memset(ec_ecdt, 0, sizeof(struct acpi_ec)); | 1595 | memset(ec_ecdt, 0, sizeof(union acpi_ec)); |
| 1051 | 1596 | ||
| 1052 | init_MUTEX(&ec_ecdt->sem); | 1597 | init_MUTEX(&ec_ecdt->burst.sem); |
| 1053 | init_waitqueue_head(&ec_ecdt->wait); | 1598 | init_waitqueue_head(&ec_ecdt->burst.wait); |
| 1054 | ec_ecdt->command_addr = ecdt_ptr->ec_control; | 1599 | ec_ecdt->common.command_addr = ecdt_ptr->ec_control; |
| 1055 | ec_ecdt->status_addr = ecdt_ptr->ec_control; | 1600 | ec_ecdt->common.status_addr = ecdt_ptr->ec_control; |
| 1056 | ec_ecdt->data_addr = ecdt_ptr->ec_data; | 1601 | ec_ecdt->common.data_addr = ecdt_ptr->ec_data; |
| 1057 | ec_ecdt->gpe_bit = ecdt_ptr->gpe_bit; | 1602 | ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit; |
| 1058 | /* use the GL just to be safe */ | 1603 | /* use the GL just to be safe */ |
| 1059 | ec_ecdt->global_lock = TRUE; | 1604 | ec_ecdt->common.global_lock = TRUE; |
| 1060 | ec_ecdt->uid = ecdt_ptr->uid; | 1605 | ec_ecdt->common.uid = ecdt_ptr->uid; |
| 1061 | 1606 | ||
| 1062 | status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->handle); | 1607 | status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle); |
| 1063 | if (ACPI_FAILURE(status)) { | 1608 | if (ACPI_FAILURE(status)) { |
| 1064 | goto error; | 1609 | goto error; |
| 1065 | } | 1610 | } |
| @@ -1092,20 +1637,20 @@ acpi_ec_ecdt_probe (void) | |||
| 1092 | /* | 1637 | /* |
| 1093 | * Install GPE handler | 1638 | * Install GPE handler |
| 1094 | */ | 1639 | */ |
| 1095 | status = acpi_install_gpe_handler(NULL, ec_ecdt->gpe_bit, | 1640 | status = acpi_install_gpe_handler(NULL, ec_ecdt->common.gpe_bit, |
| 1096 | ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler, | 1641 | ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler, |
| 1097 | ec_ecdt); | 1642 | ec_ecdt); |
| 1098 | if (ACPI_FAILURE(status)) { | 1643 | if (ACPI_FAILURE(status)) { |
| 1099 | goto error; | 1644 | goto error; |
| 1100 | } | 1645 | } |
| 1101 | acpi_set_gpe_type (NULL, ec_ecdt->gpe_bit, ACPI_GPE_TYPE_RUNTIME); | 1646 | acpi_set_gpe_type (NULL, ec_ecdt->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME); |
| 1102 | acpi_enable_gpe (NULL, ec_ecdt->gpe_bit, ACPI_NOT_ISR); | 1647 | acpi_enable_gpe (NULL, ec_ecdt->common.gpe_bit, ACPI_NOT_ISR); |
| 1103 | 1648 | ||
| 1104 | status = acpi_install_address_space_handler (ACPI_ROOT_OBJECT, | 1649 | status = acpi_install_address_space_handler (ACPI_ROOT_OBJECT, |
| 1105 | ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, | 1650 | ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, |
| 1106 | &acpi_ec_space_setup, ec_ecdt); | 1651 | &acpi_ec_space_setup, ec_ecdt); |
| 1107 | if (ACPI_FAILURE(status)) { | 1652 | if (ACPI_FAILURE(status)) { |
| 1108 | acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit, | 1653 | acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, |
| 1109 | &acpi_ec_gpe_handler); | 1654 | &acpi_ec_gpe_handler); |
| 1110 | goto error; | 1655 | goto error; |
| 1111 | } | 1656 | } |
| @@ -1123,7 +1668,7 @@ error: | |||
| 1123 | 1668 | ||
| 1124 | static int __init acpi_ec_init (void) | 1669 | static int __init acpi_ec_init (void) |
| 1125 | { | 1670 | { |
| 1126 | int result; | 1671 | int result = 0; |
| 1127 | 1672 | ||
| 1128 | ACPI_FUNCTION_TRACE("acpi_ec_init"); | 1673 | ACPI_FUNCTION_TRACE("acpi_ec_init"); |
| 1129 | 1674 | ||
| @@ -1166,4 +1711,24 @@ static int __init acpi_fake_ecdt_setup(char *str) | |||
| 1166 | acpi_fake_ecdt_enabled = 1; | 1711 | acpi_fake_ecdt_enabled = 1; |
| 1167 | return 0; | 1712 | return 0; |
| 1168 | } | 1713 | } |
| 1714 | |||
| 1169 | __setup("acpi_fake_ecdt", acpi_fake_ecdt_setup); | 1715 | __setup("acpi_fake_ecdt", acpi_fake_ecdt_setup); |
| 1716 | static int __init acpi_ec_set_polling_mode(char *str) | ||
| 1717 | { | ||
| 1718 | int burst; | ||
| 1719 | |||
| 1720 | if (!get_option(&str, &burst)) | ||
| 1721 | return 0; | ||
| 1722 | |||
| 1723 | if (burst) { | ||
| 1724 | acpi_ec_polling_mode = EC_BURST; | ||
| 1725 | acpi_ec_driver.ops.add = acpi_ec_burst_add; | ||
| 1726 | } else { | ||
| 1727 | acpi_ec_polling_mode = EC_POLLING; | ||
| 1728 | acpi_ec_driver.ops.add = acpi_ec_polling_add; | ||
| 1729 | } | ||
| 1730 | printk(KERN_INFO PREFIX "EC %s mode.\n", | ||
| 1731 | burst ? "burst": "polling"); | ||
| 1732 | return 0; | ||
| 1733 | } | ||
| 1734 | __setup("ec_burst=", acpi_ec_set_polling_mode); | ||
diff --git a/drivers/acpi/hotkey.c b/drivers/acpi/hotkey.c index babdf762eadb..1f76a40badec 100644 --- a/drivers/acpi/hotkey.c +++ b/drivers/acpi/hotkey.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * hotkey.c - ACPI Hotkey Driver ($Revision:$) | 2 | * hotkey.c - ACPI Hotkey Driver ($Revision: 0.2 $) |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2004 Luming Yu <luming.yu@intel.com> | 4 | * Copyright (C) 2004 Luming Yu <luming.yu@intel.com> |
| 5 | * | 5 | * |
| @@ -51,17 +51,18 @@ | |||
| 51 | #define ACPI_HOTKEY_POLLING 0x2 | 51 | #define ACPI_HOTKEY_POLLING 0x2 |
| 52 | #define ACPI_UNDEFINED_EVENT 0xf | 52 | #define ACPI_UNDEFINED_EVENT 0xf |
| 53 | 53 | ||
| 54 | #define MAX_CONFIG_RECORD_LEN 80 | 54 | #define RESULT_STR_LEN 80 |
| 55 | #define MAX_NAME_PATH_LEN 80 | ||
| 56 | #define MAX_CALL_PARM 80 | ||
| 57 | 55 | ||
| 58 | #define IS_EVENT(e) 0xff /* ((e) & 0x40000000) */ | 56 | #define ACTION_METHOD 0 |
| 59 | #define IS_POLL(e) 0xff /* (~((e) & 0x40000000)) */ | 57 | #define POLL_METHOD 1 |
| 60 | 58 | ||
| 59 | #define IS_EVENT(e) ((e) <= 10000 && (e) >0) | ||
| 60 | #define IS_POLL(e) ((e) > 10000) | ||
| 61 | #define IS_OTHERS(e) ((e)<=0 || (e)>=20000) | ||
| 61 | #define _COMPONENT ACPI_HOTKEY_COMPONENT | 62 | #define _COMPONENT ACPI_HOTKEY_COMPONENT |
| 62 | ACPI_MODULE_NAME("acpi_hotkey") | 63 | ACPI_MODULE_NAME("acpi_hotkey") |
| 63 | 64 | ||
| 64 | MODULE_AUTHOR("luming.yu@intel.com"); | 65 | MODULE_AUTHOR("luming.yu@intel.com"); |
| 65 | MODULE_DESCRIPTION(ACPI_HOTK_NAME); | 66 | MODULE_DESCRIPTION(ACPI_HOTK_NAME); |
| 66 | MODULE_LICENSE("GPL"); | 67 | MODULE_LICENSE("GPL"); |
| 67 | 68 | ||
| @@ -114,7 +115,7 @@ struct acpi_event_hotkey { | |||
| 114 | char *action_method; /* action method */ | 115 | char *action_method; /* action method */ |
| 115 | }; | 116 | }; |
| 116 | 117 | ||
| 117 | /* | 118 | /* |
| 118 | * There are two ways to poll status | 119 | * There are two ways to poll status |
| 119 | * 1. directy call read_xxx method, without any arguments passed in | 120 | * 1. directy call read_xxx method, without any arguments passed in |
| 120 | * 2. call write_xxx method, with arguments passed in, you need | 121 | * 2. call write_xxx method, with arguments passed in, you need |
| @@ -131,7 +132,7 @@ struct acpi_polling_hotkey { | |||
| 131 | char *poll_method; /* poll method */ | 132 | char *poll_method; /* poll method */ |
| 132 | acpi_handle action_handle; /* acpi handle attached action method */ | 133 | acpi_handle action_handle; /* acpi handle attached action method */ |
| 133 | char *action_method; /* action method */ | 134 | char *action_method; /* action method */ |
| 134 | void *poll_result; /* polling_result */ | 135 | union acpi_object *poll_result; /* polling_result */ |
| 135 | struct proc_dir_entry *proc; | 136 | struct proc_dir_entry *proc; |
| 136 | }; | 137 | }; |
| 137 | 138 | ||
| @@ -162,20 +163,25 @@ static struct acpi_driver hotkey_driver = { | |||
| 162 | }, | 163 | }, |
| 163 | }; | 164 | }; |
| 164 | 165 | ||
| 166 | static void free_hotkey_device(union acpi_hotkey *key); | ||
| 167 | static void free_hotkey_buffer(union acpi_hotkey *key); | ||
| 168 | static void free_poll_hotkey_buffer(union acpi_hotkey *key); | ||
| 165 | static int hotkey_open_config(struct inode *inode, struct file *file); | 169 | static int hotkey_open_config(struct inode *inode, struct file *file); |
| 170 | static int hotkey_poll_open_config(struct inode *inode, struct file *file); | ||
| 166 | static ssize_t hotkey_write_config(struct file *file, | 171 | static ssize_t hotkey_write_config(struct file *file, |
| 167 | const char __user * buffer, | 172 | const char __user * buffer, |
| 168 | size_t count, loff_t * data); | 173 | size_t count, loff_t * data); |
| 169 | static ssize_t hotkey_write_poll_config(struct file *file, | ||
| 170 | const char __user * buffer, | ||
| 171 | size_t count, loff_t * data); | ||
| 172 | static int hotkey_info_open_fs(struct inode *inode, struct file *file); | 174 | static int hotkey_info_open_fs(struct inode *inode, struct file *file); |
| 173 | static int hotkey_action_open_fs(struct inode *inode, struct file *file); | 175 | static int hotkey_action_open_fs(struct inode *inode, struct file *file); |
| 174 | static ssize_t hotkey_execute_aml_method(struct file *file, | 176 | static ssize_t hotkey_execute_aml_method(struct file *file, |
| 175 | const char __user * buffer, | 177 | const char __user * buffer, |
| 176 | size_t count, loff_t * data); | 178 | size_t count, loff_t * data); |
| 177 | static int hotkey_config_seq_show(struct seq_file *seq, void *offset); | 179 | static int hotkey_config_seq_show(struct seq_file *seq, void *offset); |
| 180 | static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset); | ||
| 178 | static int hotkey_polling_open_fs(struct inode *inode, struct file *file); | 181 | static int hotkey_polling_open_fs(struct inode *inode, struct file *file); |
| 182 | static union acpi_hotkey *get_hotkey_by_event(struct | ||
| 183 | acpi_hotkey_list | ||
| 184 | *hotkey_list, int event); | ||
| 179 | 185 | ||
| 180 | /* event based config */ | 186 | /* event based config */ |
| 181 | static struct file_operations hotkey_config_fops = { | 187 | static struct file_operations hotkey_config_fops = { |
| @@ -188,9 +194,9 @@ static struct file_operations hotkey_config_fops = { | |||
| 188 | 194 | ||
| 189 | /* polling based config */ | 195 | /* polling based config */ |
| 190 | static struct file_operations hotkey_poll_config_fops = { | 196 | static struct file_operations hotkey_poll_config_fops = { |
| 191 | .open = hotkey_open_config, | 197 | .open = hotkey_poll_open_config, |
| 192 | .read = seq_read, | 198 | .read = seq_read, |
| 193 | .write = hotkey_write_poll_config, | 199 | .write = hotkey_write_config, |
| 194 | .llseek = seq_lseek, | 200 | .llseek = seq_lseek, |
| 195 | .release = single_release, | 201 | .release = single_release, |
| 196 | }; | 202 | }; |
| @@ -227,7 +233,7 @@ static int hotkey_info_seq_show(struct seq_file *seq, void *offset) | |||
| 227 | { | 233 | { |
| 228 | ACPI_FUNCTION_TRACE("hotkey_info_seq_show"); | 234 | ACPI_FUNCTION_TRACE("hotkey_info_seq_show"); |
| 229 | 235 | ||
| 230 | seq_printf(seq, "Hotkey generic driver ver: %s", HOTKEY_ACPI_VERSION); | 236 | seq_printf(seq, "Hotkey generic driver ver: %s\n", HOTKEY_ACPI_VERSION); |
| 231 | 237 | ||
| 232 | return_VALUE(0); | 238 | return_VALUE(0); |
| 233 | } | 239 | } |
| @@ -239,27 +245,35 @@ static int hotkey_info_open_fs(struct inode *inode, struct file *file) | |||
| 239 | 245 | ||
| 240 | static char *format_result(union acpi_object *object) | 246 | static char *format_result(union acpi_object *object) |
| 241 | { | 247 | { |
| 242 | char *buf = (char *)kmalloc(sizeof(union acpi_object), GFP_KERNEL); | 248 | char *buf = NULL; |
| 243 | 249 | ||
| 244 | memset(buf, 0, sizeof(union acpi_object)); | 250 | buf = (char *)kmalloc(RESULT_STR_LEN, GFP_KERNEL); |
| 251 | if (buf) | ||
| 252 | memset(buf, 0, RESULT_STR_LEN); | ||
| 253 | else | ||
| 254 | goto do_fail; | ||
| 245 | 255 | ||
| 246 | /* Now, just support integer type */ | 256 | /* Now, just support integer type */ |
| 247 | if (object->type == ACPI_TYPE_INTEGER) | 257 | if (object->type == ACPI_TYPE_INTEGER) |
| 248 | sprintf(buf, "%d", (u32) object->integer.value); | 258 | sprintf(buf, "%d\n", (u32) object->integer.value); |
| 249 | 259 | do_fail: | |
| 250 | return buf; | 260 | return (buf); |
| 251 | } | 261 | } |
| 252 | 262 | ||
| 253 | static int hotkey_polling_seq_show(struct seq_file *seq, void *offset) | 263 | static int hotkey_polling_seq_show(struct seq_file *seq, void *offset) |
| 254 | { | 264 | { |
| 255 | struct acpi_polling_hotkey *poll_hotkey = | 265 | struct acpi_polling_hotkey *poll_hotkey = |
| 256 | (struct acpi_polling_hotkey *)seq->private; | 266 | (struct acpi_polling_hotkey *)seq->private; |
| 267 | char *buf; | ||
| 257 | 268 | ||
| 258 | ACPI_FUNCTION_TRACE("hotkey_polling_seq_show"); | 269 | ACPI_FUNCTION_TRACE("hotkey_polling_seq_show"); |
| 259 | 270 | ||
| 260 | if (poll_hotkey->poll_result) | 271 | if (poll_hotkey->poll_result){ |
| 261 | seq_printf(seq, "%s", format_result(poll_hotkey->poll_result)); | 272 | buf = format_result(poll_hotkey->poll_result); |
| 262 | 273 | if(buf) | |
| 274 | seq_printf(seq, "%s", buf); | ||
| 275 | kfree(buf); | ||
| 276 | } | ||
| 263 | return_VALUE(0); | 277 | return_VALUE(0); |
| 264 | } | 278 | } |
| 265 | 279 | ||
| @@ -276,19 +290,19 @@ static int hotkey_action_open_fs(struct inode *inode, struct file *file) | |||
| 276 | /* Mapping external hotkey number to standardized hotkey event num */ | 290 | /* Mapping external hotkey number to standardized hotkey event num */ |
| 277 | static int hotkey_get_internal_event(int event, struct acpi_hotkey_list *list) | 291 | static int hotkey_get_internal_event(int event, struct acpi_hotkey_list *list) |
| 278 | { | 292 | { |
| 279 | struct list_head *entries, *next; | 293 | struct list_head *entries; |
| 280 | int val = 0; | 294 | int val = -1; |
| 281 | 295 | ||
| 282 | ACPI_FUNCTION_TRACE("hotkey_get_internal_event"); | 296 | ACPI_FUNCTION_TRACE("hotkey_get_internal_event"); |
| 283 | 297 | ||
| 284 | list_for_each_safe(entries, next, list->entries) { | 298 | list_for_each(entries, list->entries) { |
| 285 | union acpi_hotkey *key = | 299 | union acpi_hotkey *key = |
| 286 | container_of(entries, union acpi_hotkey, entries); | 300 | container_of(entries, union acpi_hotkey, entries); |
| 287 | if (key->link.hotkey_type == ACPI_HOTKEY_EVENT | 301 | if (key->link.hotkey_type == ACPI_HOTKEY_EVENT |
| 288 | && key->event_hotkey.external_hotkey_num == event) | 302 | && key->event_hotkey.external_hotkey_num == event){ |
| 289 | val = key->link.hotkey_standard_num; | 303 | val = key->link.hotkey_standard_num; |
| 290 | else | 304 | break; |
| 291 | val = -1; | 305 | } |
| 292 | } | 306 | } |
| 293 | 307 | ||
| 294 | return_VALUE(val); | 308 | return_VALUE(val); |
| @@ -306,7 +320,7 @@ acpi_hotkey_notify_handler(acpi_handle handle, u32 event, void *data) | |||
| 306 | return_VOID; | 320 | return_VOID; |
| 307 | 321 | ||
| 308 | internal_event = hotkey_get_internal_event(event, &global_hotkey_list); | 322 | internal_event = hotkey_get_internal_event(event, &global_hotkey_list); |
| 309 | acpi_bus_generate_event(device, event, 0); | 323 | acpi_bus_generate_event(device, internal_event, 0); |
| 310 | 324 | ||
| 311 | return_VOID; | 325 | return_VOID; |
| 312 | } | 326 | } |
| @@ -329,13 +343,17 @@ static int auto_hotkey_remove(struct acpi_device *device, int type) | |||
| 329 | static int create_polling_proc(union acpi_hotkey *device) | 343 | static int create_polling_proc(union acpi_hotkey *device) |
| 330 | { | 344 | { |
| 331 | struct proc_dir_entry *proc; | 345 | struct proc_dir_entry *proc; |
| 346 | char proc_name[80]; | ||
| 332 | mode_t mode; | 347 | mode_t mode; |
| 333 | 348 | ||
| 334 | ACPI_FUNCTION_TRACE("create_polling_proc"); | 349 | ACPI_FUNCTION_TRACE("create_polling_proc"); |
| 335 | mode = S_IFREG | S_IRUGO | S_IWUGO; | 350 | mode = S_IFREG | S_IRUGO | S_IWUGO; |
| 336 | 351 | ||
| 337 | proc = create_proc_entry(device->poll_hotkey.action_method, | 352 | sprintf(proc_name, "%d", device->link.hotkey_standard_num); |
| 338 | mode, hotkey_proc_dir); | 353 | /* |
| 354 | strcat(proc_name, device->poll_hotkey.poll_method); | ||
| 355 | */ | ||
| 356 | proc = create_proc_entry(proc_name, mode, hotkey_proc_dir); | ||
| 339 | 357 | ||
| 340 | if (!proc) { | 358 | if (!proc) { |
| 341 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | 359 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
| @@ -353,23 +371,6 @@ static int create_polling_proc(union acpi_hotkey *device) | |||
| 353 | return_VALUE(0); | 371 | return_VALUE(0); |
| 354 | } | 372 | } |
| 355 | 373 | ||
| 356 | static int is_valid_acpi_path(const char *pathname) | ||
| 357 | { | ||
| 358 | acpi_handle handle; | ||
| 359 | acpi_status status; | ||
| 360 | ACPI_FUNCTION_TRACE("is_valid_acpi_path"); | ||
| 361 | |||
| 362 | status = acpi_get_handle(NULL, (char *)pathname, &handle); | ||
| 363 | return_VALUE(!ACPI_FAILURE(status)); | ||
| 364 | } | ||
| 365 | |||
| 366 | static int is_valid_hotkey(union acpi_hotkey *device) | ||
| 367 | { | ||
| 368 | ACPI_FUNCTION_TRACE("is_valid_hotkey"); | ||
| 369 | /* Implement valid check */ | ||
| 370 | return_VALUE(1); | ||
| 371 | } | ||
| 372 | |||
| 373 | static int hotkey_add(union acpi_hotkey *device) | 374 | static int hotkey_add(union acpi_hotkey *device) |
| 374 | { | 375 | { |
| 375 | int status = 0; | 376 | int status = 0; |
| @@ -378,15 +379,11 @@ static int hotkey_add(union acpi_hotkey *device) | |||
| 378 | ACPI_FUNCTION_TRACE("hotkey_add"); | 379 | ACPI_FUNCTION_TRACE("hotkey_add"); |
| 379 | 380 | ||
| 380 | if (device->link.hotkey_type == ACPI_HOTKEY_EVENT) { | 381 | if (device->link.hotkey_type == ACPI_HOTKEY_EVENT) { |
| 381 | status = | 382 | acpi_bus_get_device(device->event_hotkey.bus_handle, &dev); |
| 382 | acpi_bus_get_device(device->event_hotkey.bus_handle, &dev); | ||
| 383 | if (status) | ||
| 384 | return_VALUE(status); | ||
| 385 | |||
| 386 | status = acpi_install_notify_handler(dev->handle, | 383 | status = acpi_install_notify_handler(dev->handle, |
| 387 | ACPI_SYSTEM_NOTIFY, | 384 | ACPI_DEVICE_NOTIFY, |
| 388 | acpi_hotkey_notify_handler, | 385 | acpi_hotkey_notify_handler, |
| 389 | device); | 386 | dev); |
| 390 | } else /* Add polling hotkey */ | 387 | } else /* Add polling hotkey */ |
| 391 | create_polling_proc(device); | 388 | create_polling_proc(device); |
| 392 | 389 | ||
| @@ -409,84 +406,143 @@ static int hotkey_remove(union acpi_hotkey *device) | |||
| 409 | if (key->link.hotkey_standard_num == | 406 | if (key->link.hotkey_standard_num == |
| 410 | device->link.hotkey_standard_num) { | 407 | device->link.hotkey_standard_num) { |
| 411 | list_del(&key->link.entries); | 408 | list_del(&key->link.entries); |
| 412 | remove_proc_entry(key->poll_hotkey.action_method, | 409 | free_hotkey_device(key); |
| 413 | hotkey_proc_dir); | ||
| 414 | global_hotkey_list.count--; | 410 | global_hotkey_list.count--; |
| 415 | break; | 411 | break; |
| 416 | } | 412 | } |
| 417 | } | 413 | } |
| 414 | kfree(device); | ||
| 418 | return_VALUE(0); | 415 | return_VALUE(0); |
| 419 | } | 416 | } |
| 420 | 417 | ||
| 421 | static void hotkey_update(union acpi_hotkey *key) | 418 | static int hotkey_update(union acpi_hotkey *key) |
| 422 | { | 419 | { |
| 423 | struct list_head *entries, *next; | 420 | struct list_head *entries; |
| 424 | 421 | ||
| 425 | ACPI_FUNCTION_TRACE("hotkey_update"); | 422 | ACPI_FUNCTION_TRACE("hotkey_update"); |
| 426 | 423 | ||
| 427 | list_for_each_safe(entries, next, global_hotkey_list.entries) { | 424 | list_for_each(entries, global_hotkey_list.entries) { |
| 428 | union acpi_hotkey *key = | 425 | union acpi_hotkey *tmp= |
| 429 | container_of(entries, union acpi_hotkey, entries); | 426 | container_of(entries, union acpi_hotkey, entries); |
| 430 | if (key->link.hotkey_standard_num == | 427 | if (tmp->link.hotkey_standard_num == |
| 431 | key->link.hotkey_standard_num) { | 428 | key->link.hotkey_standard_num) { |
| 432 | key->event_hotkey.bus_handle = | 429 | if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) { |
| 433 | key->event_hotkey.bus_handle; | 430 | free_hotkey_buffer(tmp); |
| 434 | key->event_hotkey.external_hotkey_num = | 431 | tmp->event_hotkey.bus_handle = |
| 435 | key->event_hotkey.external_hotkey_num; | 432 | key->event_hotkey.bus_handle; |
| 436 | key->event_hotkey.action_handle = | 433 | tmp->event_hotkey.external_hotkey_num = |
| 437 | key->event_hotkey.action_handle; | 434 | key->event_hotkey.external_hotkey_num; |
| 438 | key->event_hotkey.action_method = | 435 | tmp->event_hotkey.action_handle = |
| 439 | key->event_hotkey.action_method; | 436 | key->event_hotkey.action_handle; |
| 437 | tmp->event_hotkey.action_method = | ||
| 438 | key->event_hotkey.action_method; | ||
| 439 | kfree(key); | ||
| 440 | } else { | ||
| 441 | /* | ||
| 442 | char proc_name[80]; | ||
| 443 | |||
| 444 | sprintf(proc_name, "%d", tmp->link.hotkey_standard_num); | ||
| 445 | strcat(proc_name, tmp->poll_hotkey.poll_method); | ||
| 446 | remove_proc_entry(proc_name,hotkey_proc_dir); | ||
| 447 | */ | ||
| 448 | free_poll_hotkey_buffer(tmp); | ||
| 449 | tmp->poll_hotkey.poll_handle = | ||
| 450 | key->poll_hotkey.poll_handle; | ||
| 451 | tmp->poll_hotkey.poll_method = | ||
| 452 | key->poll_hotkey.poll_method; | ||
| 453 | tmp->poll_hotkey.action_handle = | ||
| 454 | key->poll_hotkey.action_handle; | ||
| 455 | tmp->poll_hotkey.action_method = | ||
| 456 | key->poll_hotkey.action_method; | ||
| 457 | tmp->poll_hotkey.poll_result = | ||
| 458 | key->poll_hotkey.poll_result; | ||
| 459 | /* | ||
| 460 | create_polling_proc(tmp); | ||
| 461 | */ | ||
| 462 | kfree(key); | ||
| 463 | } | ||
| 464 | return_VALUE(0); | ||
| 440 | break; | 465 | break; |
| 441 | } | 466 | } |
| 442 | } | 467 | } |
| 443 | 468 | ||
| 444 | return_VOID; | 469 | return_VALUE(-ENODEV); |
| 445 | } | 470 | } |
| 446 | 471 | ||
| 447 | static void free_hotkey_device(union acpi_hotkey *key) | 472 | static void free_hotkey_device(union acpi_hotkey *key) |
| 448 | { | 473 | { |
| 449 | struct acpi_device *dev; | 474 | struct acpi_device *dev; |
| 450 | int status; | ||
| 451 | 475 | ||
| 452 | ACPI_FUNCTION_TRACE("free_hotkey_device"); | 476 | ACPI_FUNCTION_TRACE("free_hotkey_device"); |
| 453 | 477 | ||
| 454 | if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) { | 478 | if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) { |
| 455 | status = | 479 | acpi_bus_get_device(key->event_hotkey.bus_handle, &dev); |
| 456 | acpi_bus_get_device(key->event_hotkey.bus_handle, &dev); | ||
| 457 | if (dev->handle) | 480 | if (dev->handle) |
| 458 | acpi_remove_notify_handler(dev->handle, | 481 | acpi_remove_notify_handler(dev->handle, |
| 459 | ACPI_SYSTEM_NOTIFY, | 482 | ACPI_DEVICE_NOTIFY, |
| 460 | acpi_hotkey_notify_handler); | 483 | acpi_hotkey_notify_handler); |
| 461 | } else | 484 | free_hotkey_buffer(key); |
| 462 | remove_proc_entry(key->poll_hotkey.action_method, | 485 | } else { |
| 463 | hotkey_proc_dir); | 486 | char proc_name[80]; |
| 487 | |||
| 488 | sprintf(proc_name, "%d", key->link.hotkey_standard_num); | ||
| 489 | /* | ||
| 490 | strcat(proc_name, key->poll_hotkey.poll_method); | ||
| 491 | */ | ||
| 492 | remove_proc_entry(proc_name,hotkey_proc_dir); | ||
| 493 | free_poll_hotkey_buffer(key); | ||
| 494 | } | ||
| 464 | kfree(key); | 495 | kfree(key); |
| 465 | return_VOID; | 496 | return_VOID; |
| 466 | } | 497 | } |
| 467 | 498 | ||
| 499 | static void | ||
| 500 | free_hotkey_buffer(union acpi_hotkey *key) | ||
| 501 | { | ||
| 502 | kfree(key->event_hotkey.action_method); | ||
| 503 | } | ||
| 504 | |||
| 505 | static void | ||
| 506 | free_poll_hotkey_buffer(union acpi_hotkey *key) | ||
| 507 | { | ||
| 508 | kfree(key->poll_hotkey.action_method); | ||
| 509 | kfree(key->poll_hotkey.poll_method); | ||
| 510 | kfree(key->poll_hotkey.poll_result); | ||
| 511 | } | ||
| 468 | static int | 512 | static int |
| 469 | init_hotkey_device(union acpi_hotkey *key, char *bus_str, char *action_str, | 513 | init_hotkey_device(union acpi_hotkey *key, char *bus_str, char *action_str, |
| 470 | char *method, int std_num, int external_num) | 514 | char *method, int std_num, int external_num) |
| 471 | { | 515 | { |
| 516 | acpi_handle tmp_handle; | ||
| 517 | acpi_status status = AE_OK; | ||
| 518 | |||
| 472 | ACPI_FUNCTION_TRACE("init_hotkey_device"); | 519 | ACPI_FUNCTION_TRACE("init_hotkey_device"); |
| 473 | 520 | ||
| 521 | if(std_num < 0 || IS_POLL(std_num) || !key ) | ||
| 522 | goto do_fail; | ||
| 523 | |||
| 524 | if(!bus_str || !action_str || !method) | ||
| 525 | goto do_fail; | ||
| 526 | |||
| 474 | key->link.hotkey_type = ACPI_HOTKEY_EVENT; | 527 | key->link.hotkey_type = ACPI_HOTKEY_EVENT; |
| 475 | key->link.hotkey_standard_num = std_num; | 528 | key->link.hotkey_standard_num = std_num; |
| 476 | key->event_hotkey.flag = 0; | 529 | key->event_hotkey.flag = 0; |
| 477 | if (is_valid_acpi_path(bus_str)) | 530 | key->event_hotkey.action_method = method; |
| 478 | acpi_get_handle((acpi_handle) 0, | ||
| 479 | bus_str, &(key->event_hotkey.bus_handle)); | ||
| 480 | else | ||
| 481 | return_VALUE(-ENODEV); | ||
| 482 | key->event_hotkey.external_hotkey_num = external_num; | ||
| 483 | if (is_valid_acpi_path(action_str)) | ||
| 484 | acpi_get_handle((acpi_handle) 0, | ||
| 485 | action_str, &(key->event_hotkey.action_handle)); | ||
| 486 | key->event_hotkey.action_method = kmalloc(sizeof(method), GFP_KERNEL); | ||
| 487 | strcpy(key->event_hotkey.action_method, method); | ||
| 488 | 531 | ||
| 489 | return_VALUE(!is_valid_hotkey(key)); | 532 | status = acpi_get_handle(NULL,bus_str, &(key->event_hotkey.bus_handle)); |
| 533 | if(ACPI_FAILURE(status)) | ||
| 534 | goto do_fail; | ||
| 535 | key->event_hotkey.external_hotkey_num = external_num; | ||
| 536 | status = acpi_get_handle(NULL,action_str, &(key->event_hotkey.action_handle)); | ||
| 537 | if(ACPI_FAILURE(status)) | ||
| 538 | goto do_fail; | ||
| 539 | status = acpi_get_handle(key->event_hotkey.action_handle, | ||
| 540 | method, &tmp_handle); | ||
| 541 | if (ACPI_FAILURE(status)) | ||
| 542 | goto do_fail; | ||
| 543 | return_VALUE(AE_OK); | ||
| 544 | do_fail: | ||
| 545 | return_VALUE(-ENODEV); | ||
| 490 | } | 546 | } |
| 491 | 547 | ||
| 492 | static int | 548 | static int |
| @@ -495,34 +551,46 @@ init_poll_hotkey_device(union acpi_hotkey *key, | |||
| 495 | char *poll_method, | 551 | char *poll_method, |
| 496 | char *action_str, char *action_method, int std_num) | 552 | char *action_str, char *action_method, int std_num) |
| 497 | { | 553 | { |
| 554 | acpi_status status = AE_OK; | ||
| 555 | acpi_handle tmp_handle; | ||
| 556 | |||
| 498 | ACPI_FUNCTION_TRACE("init_poll_hotkey_device"); | 557 | ACPI_FUNCTION_TRACE("init_poll_hotkey_device"); |
| 499 | 558 | ||
| 559 | if(std_num < 0 || IS_EVENT(std_num) || !key) | ||
| 560 | goto do_fail; | ||
| 561 | |||
| 562 | if(!poll_str || !poll_method || !action_str || !action_method) | ||
| 563 | goto do_fail; | ||
| 564 | |||
| 500 | key->link.hotkey_type = ACPI_HOTKEY_POLLING; | 565 | key->link.hotkey_type = ACPI_HOTKEY_POLLING; |
| 501 | key->link.hotkey_standard_num = std_num; | 566 | key->link.hotkey_standard_num = std_num; |
| 502 | key->poll_hotkey.flag = 0; | 567 | key->poll_hotkey.flag = 0; |
| 503 | if (is_valid_acpi_path(poll_str)) | ||
| 504 | acpi_get_handle((acpi_handle) 0, | ||
| 505 | poll_str, &(key->poll_hotkey.poll_handle)); | ||
| 506 | else | ||
| 507 | return_VALUE(-ENODEV); | ||
| 508 | key->poll_hotkey.poll_method = poll_method; | 568 | key->poll_hotkey.poll_method = poll_method; |
| 509 | if (is_valid_acpi_path(action_str)) | 569 | key->poll_hotkey.action_method = action_method; |
| 510 | acpi_get_handle((acpi_handle) 0, | 570 | |
| 511 | action_str, &(key->poll_hotkey.action_handle)); | 571 | status = acpi_get_handle(NULL,poll_str, &(key->poll_hotkey.poll_handle)); |
| 512 | key->poll_hotkey.action_method = | 572 | if(ACPI_FAILURE(status)) |
| 513 | kmalloc(sizeof(action_method), GFP_KERNEL); | 573 | goto do_fail; |
| 514 | strcpy(key->poll_hotkey.action_method, action_method); | 574 | status = acpi_get_handle(key->poll_hotkey.poll_handle, |
| 575 | poll_method, &tmp_handle); | ||
| 576 | if (ACPI_FAILURE(status)) | ||
| 577 | goto do_fail; | ||
| 578 | status = acpi_get_handle(NULL,action_str, &(key->poll_hotkey.action_handle)); | ||
| 579 | if (ACPI_FAILURE(status)) | ||
| 580 | goto do_fail; | ||
| 581 | status = acpi_get_handle(key->poll_hotkey.action_handle, | ||
| 582 | action_method, &tmp_handle); | ||
| 583 | if (ACPI_FAILURE(status)) | ||
| 584 | goto do_fail; | ||
| 515 | key->poll_hotkey.poll_result = | 585 | key->poll_hotkey.poll_result = |
| 516 | (union acpi_object *)kmalloc(sizeof(union acpi_object), GFP_KERNEL); | 586 | (union acpi_object *)kmalloc(sizeof(union acpi_object), GFP_KERNEL); |
| 517 | return_VALUE(is_valid_hotkey(key)); | 587 | if(!key->poll_hotkey.poll_result) |
| 588 | goto do_fail; | ||
| 589 | return_VALUE(AE_OK); | ||
| 590 | do_fail: | ||
| 591 | return_VALUE(-ENODEV); | ||
| 518 | } | 592 | } |
| 519 | 593 | ||
| 520 | static int check_hotkey_valid(union acpi_hotkey *key, | ||
| 521 | struct acpi_hotkey_list *list) | ||
| 522 | { | ||
| 523 | ACPI_FUNCTION_TRACE("check_hotkey_valid"); | ||
| 524 | return_VALUE(0); | ||
| 525 | } | ||
| 526 | 594 | ||
| 527 | static int hotkey_open_config(struct inode *inode, struct file *file) | 595 | static int hotkey_open_config(struct inode *inode, struct file *file) |
| 528 | { | 596 | { |
| @@ -531,10 +599,17 @@ static int hotkey_open_config(struct inode *inode, struct file *file) | |||
| 531 | (file, hotkey_config_seq_show, PDE(inode)->data)); | 599 | (file, hotkey_config_seq_show, PDE(inode)->data)); |
| 532 | } | 600 | } |
| 533 | 601 | ||
| 602 | static int hotkey_poll_open_config(struct inode *inode, struct file *file) | ||
| 603 | { | ||
| 604 | ACPI_FUNCTION_TRACE("hotkey_poll_open_config"); | ||
| 605 | return_VALUE(single_open | ||
| 606 | (file, hotkey_poll_config_seq_show, PDE(inode)->data)); | ||
| 607 | } | ||
| 608 | |||
| 534 | static int hotkey_config_seq_show(struct seq_file *seq, void *offset) | 609 | static int hotkey_config_seq_show(struct seq_file *seq, void *offset) |
| 535 | { | 610 | { |
| 536 | struct acpi_hotkey_list *hotkey_list = &global_hotkey_list; | 611 | struct acpi_hotkey_list *hotkey_list = &global_hotkey_list; |
| 537 | struct list_head *entries, *next; | 612 | struct list_head *entries; |
| 538 | char bus_name[ACPI_PATHNAME_MAX] = { 0 }; | 613 | char bus_name[ACPI_PATHNAME_MAX] = { 0 }; |
| 539 | char action_name[ACPI_PATHNAME_MAX] = { 0 }; | 614 | char action_name[ACPI_PATHNAME_MAX] = { 0 }; |
| 540 | struct acpi_buffer bus = { ACPI_PATHNAME_MAX, bus_name }; | 615 | struct acpi_buffer bus = { ACPI_PATHNAME_MAX, bus_name }; |
| @@ -542,10 +617,7 @@ static int hotkey_config_seq_show(struct seq_file *seq, void *offset) | |||
| 542 | 617 | ||
| 543 | ACPI_FUNCTION_TRACE(("hotkey_config_seq_show")); | 618 | ACPI_FUNCTION_TRACE(("hotkey_config_seq_show")); |
| 544 | 619 | ||
| 545 | if (!hotkey_list) | 620 | list_for_each(entries, hotkey_list->entries) { |
| 546 | goto end; | ||
| 547 | |||
| 548 | list_for_each_safe(entries, next, hotkey_list->entries) { | ||
| 549 | union acpi_hotkey *key = | 621 | union acpi_hotkey *key = |
| 550 | container_of(entries, union acpi_hotkey, entries); | 622 | container_of(entries, union acpi_hotkey, entries); |
| 551 | if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) { | 623 | if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) { |
| @@ -553,18 +625,37 @@ static int hotkey_config_seq_show(struct seq_file *seq, void *offset) | |||
| 553 | ACPI_NAME_TYPE_MAX, &bus); | 625 | ACPI_NAME_TYPE_MAX, &bus); |
| 554 | acpi_get_name(key->event_hotkey.action_handle, | 626 | acpi_get_name(key->event_hotkey.action_handle, |
| 555 | ACPI_NAME_TYPE_MAX, &act); | 627 | ACPI_NAME_TYPE_MAX, &act); |
| 556 | seq_printf(seq, "%s:%s:%s:%d:%d", bus_name, | 628 | seq_printf(seq, "%s:%s:%s:%d:%d\n", bus_name, |
| 557 | action_name, | 629 | action_name, |
| 558 | key->event_hotkey.action_method, | 630 | key->event_hotkey.action_method, |
| 559 | key->link.hotkey_standard_num, | 631 | key->link.hotkey_standard_num, |
| 560 | key->event_hotkey.external_hotkey_num); | 632 | key->event_hotkey.external_hotkey_num); |
| 561 | } /* ACPI_HOTKEY_POLLING */ | 633 | } |
| 562 | else { | 634 | } |
| 635 | seq_puts(seq, "\n"); | ||
| 636 | return_VALUE(0); | ||
| 637 | } | ||
| 638 | |||
| 639 | static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset) | ||
| 640 | { | ||
| 641 | struct acpi_hotkey_list *hotkey_list = &global_hotkey_list; | ||
| 642 | struct list_head *entries; | ||
| 643 | char bus_name[ACPI_PATHNAME_MAX] = { 0 }; | ||
| 644 | char action_name[ACPI_PATHNAME_MAX] = { 0 }; | ||
| 645 | struct acpi_buffer bus = { ACPI_PATHNAME_MAX, bus_name }; | ||
| 646 | struct acpi_buffer act = { ACPI_PATHNAME_MAX, action_name }; | ||
| 647 | |||
| 648 | ACPI_FUNCTION_TRACE(("hotkey_config_seq_show")); | ||
| 649 | |||
| 650 | list_for_each(entries, hotkey_list->entries) { | ||
| 651 | union acpi_hotkey *key = | ||
| 652 | container_of(entries, union acpi_hotkey, entries); | ||
| 653 | if (key->link.hotkey_type == ACPI_HOTKEY_POLLING) { | ||
| 563 | acpi_get_name(key->poll_hotkey.poll_handle, | 654 | acpi_get_name(key->poll_hotkey.poll_handle, |
| 564 | ACPI_NAME_TYPE_MAX, &bus); | 655 | ACPI_NAME_TYPE_MAX, &bus); |
| 565 | acpi_get_name(key->poll_hotkey.action_handle, | 656 | acpi_get_name(key->poll_hotkey.action_handle, |
| 566 | ACPI_NAME_TYPE_MAX, &act); | 657 | ACPI_NAME_TYPE_MAX, &act); |
| 567 | seq_printf(seq, "%s:%s:%s:%s:%d", bus_name, | 658 | seq_printf(seq, "%s:%s:%s:%s:%d\n", bus_name, |
| 568 | key->poll_hotkey.poll_method, | 659 | key->poll_hotkey.poll_method, |
| 569 | action_name, | 660 | action_name, |
| 570 | key->poll_hotkey.action_method, | 661 | key->poll_hotkey.action_method, |
| @@ -572,49 +663,83 @@ static int hotkey_config_seq_show(struct seq_file *seq, void *offset) | |||
| 572 | } | 663 | } |
| 573 | } | 664 | } |
| 574 | seq_puts(seq, "\n"); | 665 | seq_puts(seq, "\n"); |
| 575 | end: | ||
| 576 | return_VALUE(0); | 666 | return_VALUE(0); |
| 577 | } | 667 | } |
| 578 | 668 | ||
| 579 | static int | 669 | static int |
| 580 | get_parms(char *config_record, | 670 | get_parms(char *config_record, |
| 581 | int *cmd, | 671 | int *cmd, |
| 582 | char *bus_handle, | 672 | char **bus_handle, |
| 583 | char *bus_method, | 673 | char **bus_method, |
| 584 | char *action_handle, | 674 | char **action_handle, |
| 585 | char *method, int *internal_event_num, int *external_event_num) | 675 | char **method, int *internal_event_num, int *external_event_num) |
| 586 | { | 676 | { |
| 587 | char *tmp, *tmp1; | 677 | char *tmp, *tmp1, count; |
| 588 | ACPI_FUNCTION_TRACE(("get_parms")); | 678 | ACPI_FUNCTION_TRACE(("get_parms")); |
| 589 | 679 | ||
| 590 | sscanf(config_record, "%d", cmd); | 680 | sscanf(config_record, "%d", cmd); |
| 591 | 681 | ||
| 682 | if(*cmd == 1){ | ||
| 683 | if(sscanf(config_record, "%d:%d", cmd, internal_event_num)!=2) | ||
| 684 | goto do_fail; | ||
| 685 | else | ||
| 686 | return (6); | ||
| 687 | } | ||
| 592 | tmp = strchr(config_record, ':'); | 688 | tmp = strchr(config_record, ':'); |
| 689 | if (!tmp) | ||
| 690 | goto do_fail; | ||
| 593 | tmp++; | 691 | tmp++; |
| 594 | tmp1 = strchr(tmp, ':'); | 692 | tmp1 = strchr(tmp, ':'); |
| 595 | strncpy(bus_handle, tmp, tmp1 - tmp); | 693 | if (!tmp1) |
| 596 | bus_handle[tmp1 - tmp] = 0; | 694 | goto do_fail; |
| 695 | |||
| 696 | count = tmp1 - tmp; | ||
| 697 | *bus_handle = (char *) kmalloc(count+1, GFP_KERNEL); | ||
| 698 | if(!*bus_handle) | ||
| 699 | goto do_fail; | ||
| 700 | strncpy(*bus_handle, tmp, count); | ||
| 701 | *(*bus_handle + count) = 0; | ||
| 597 | 702 | ||
| 598 | tmp = tmp1; | 703 | tmp = tmp1; |
| 599 | tmp++; | 704 | tmp++; |
| 600 | tmp1 = strchr(tmp, ':'); | 705 | tmp1 = strchr(tmp, ':'); |
| 601 | strncpy(bus_method, tmp, tmp1 - tmp); | 706 | if (!tmp1) |
| 602 | bus_method[tmp1 - tmp] = 0; | 707 | goto do_fail; |
| 708 | count = tmp1 - tmp; | ||
| 709 | *bus_method = (char *) kmalloc(count+1, GFP_KERNEL); | ||
| 710 | if(!*bus_method) | ||
| 711 | goto do_fail; | ||
| 712 | strncpy(*bus_method, tmp, count); | ||
| 713 | *(*bus_method + count) = 0; | ||
| 603 | 714 | ||
| 604 | tmp = tmp1; | 715 | tmp = tmp1; |
| 605 | tmp++; | 716 | tmp++; |
| 606 | tmp1 = strchr(tmp, ':'); | 717 | tmp1 = strchr(tmp, ':'); |
| 607 | strncpy(action_handle, tmp, tmp1 - tmp); | 718 | if (!tmp1) |
| 608 | action_handle[tmp1 - tmp] = 0; | 719 | goto do_fail; |
| 720 | count = tmp1 - tmp; | ||
| 721 | *action_handle = (char *) kmalloc(count+1, GFP_KERNEL); | ||
| 722 | strncpy(*action_handle, tmp, count); | ||
| 723 | *(*action_handle + count) = 0; | ||
| 609 | 724 | ||
| 610 | tmp = tmp1; | 725 | tmp = tmp1; |
| 611 | tmp++; | 726 | tmp++; |
| 612 | tmp1 = strchr(tmp, ':'); | 727 | tmp1 = strchr(tmp, ':'); |
| 613 | strncpy(method, tmp, tmp1 - tmp); | 728 | if (!tmp1) |
| 614 | method[tmp1 - tmp] = 0; | 729 | goto do_fail; |
| 730 | count = tmp1 - tmp; | ||
| 731 | *method = (char *) kmalloc(count+1, GFP_KERNEL); | ||
| 732 | if(!*method) | ||
| 733 | goto do_fail; | ||
| 734 | strncpy(*method, tmp, count); | ||
| 735 | *(*method + count) = 0; | ||
| 736 | |||
| 737 | if(sscanf(tmp1 + 1, "%d:%d", internal_event_num, external_event_num)<=0) | ||
| 738 | goto do_fail; | ||
| 615 | 739 | ||
| 616 | sscanf(tmp1 + 1, "%d:%d", internal_event_num, external_event_num); | ||
| 617 | return_VALUE(6); | 740 | return_VALUE(6); |
| 741 | do_fail: | ||
| 742 | return_VALUE(-1); | ||
| 618 | } | 743 | } |
| 619 | 744 | ||
| 620 | /* count is length for one input record */ | 745 | /* count is length for one input record */ |
| @@ -622,135 +747,117 @@ static ssize_t hotkey_write_config(struct file *file, | |||
| 622 | const char __user * buffer, | 747 | const char __user * buffer, |
| 623 | size_t count, loff_t * data) | 748 | size_t count, loff_t * data) |
| 624 | { | 749 | { |
| 625 | struct acpi_hotkey_list *hotkey_list = &global_hotkey_list; | 750 | char *config_record = NULL; |
| 626 | char config_record[MAX_CONFIG_RECORD_LEN]; | 751 | char *bus_handle = NULL; |
| 627 | char bus_handle[MAX_NAME_PATH_LEN]; | 752 | char *bus_method = NULL; |
| 628 | char bus_method[MAX_NAME_PATH_LEN]; | 753 | char *action_handle = NULL; |
| 629 | char action_handle[MAX_NAME_PATH_LEN]; | 754 | char *method = NULL; |
| 630 | char method[20]; | ||
| 631 | int cmd, internal_event_num, external_event_num; | 755 | int cmd, internal_event_num, external_event_num; |
| 632 | int ret = 0; | 756 | int ret = 0; |
| 633 | union acpi_hotkey *key = NULL; | 757 | union acpi_hotkey *key = NULL; |
| 634 | 758 | ||
| 635 | ACPI_FUNCTION_TRACE(("hotkey_write_config")); | 759 | ACPI_FUNCTION_TRACE(("hotkey_write_config")); |
| 636 | 760 | ||
| 637 | if (!hotkey_list || count > MAX_CONFIG_RECORD_LEN) { | 761 | config_record = (char *) kmalloc(count+1, GFP_KERNEL); |
| 638 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid arguments\n")); | 762 | if(!config_record) |
| 639 | return_VALUE(-EINVAL); | 763 | return_VALUE(-ENOMEM); |
| 640 | } | ||
| 641 | 764 | ||
| 642 | if (copy_from_user(config_record, buffer, count)) { | 765 | if (copy_from_user(config_record, buffer, count)) { |
| 766 | kfree(config_record); | ||
| 643 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data \n")); | 767 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data \n")); |
| 644 | return_VALUE(-EINVAL); | 768 | return_VALUE(-EINVAL); |
| 645 | } | 769 | } |
| 646 | config_record[count] = '\0'; | 770 | config_record[count] = 0; |
| 647 | 771 | ||
| 648 | ret = get_parms(config_record, | 772 | ret = get_parms(config_record, |
| 649 | &cmd, | 773 | &cmd, |
| 650 | bus_handle, | 774 | &bus_handle, |
| 651 | bus_method, | 775 | &bus_method, |
| 652 | action_handle, | 776 | &action_handle, |
| 653 | method, &internal_event_num, &external_event_num); | 777 | &method, &internal_event_num, &external_event_num); |
| 778 | |||
| 779 | kfree(config_record); | ||
| 780 | if(IS_OTHERS(internal_event_num)) | ||
| 781 | goto do_fail; | ||
| 654 | if (ret != 6) { | 782 | if (ret != 6) { |
| 783 | do_fail: | ||
| 784 | kfree(bus_handle); | ||
| 785 | kfree(bus_method); | ||
| 786 | kfree(action_handle); | ||
| 787 | kfree(method); | ||
| 655 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | 788 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
| 656 | "Invalid data format ret=%d\n", ret)); | 789 | "Invalid data format ret=%d\n", ret)); |
| 657 | return_VALUE(-EINVAL); | 790 | return_VALUE(-EINVAL); |
| 658 | } | 791 | } |
| 659 | 792 | ||
| 660 | key = kmalloc(sizeof(union acpi_hotkey), GFP_KERNEL); | 793 | key = kmalloc(sizeof(union acpi_hotkey), GFP_KERNEL); |
| 661 | ret = init_hotkey_device(key, bus_handle, action_handle, method, | 794 | if(!key) |
| 795 | goto do_fail; | ||
| 796 | memset(key, 0, sizeof(union acpi_hotkey)); | ||
| 797 | if(cmd == 1) { | ||
| 798 | union acpi_hotkey *tmp = NULL; | ||
| 799 | tmp = get_hotkey_by_event(&global_hotkey_list, | ||
| 800 | internal_event_num); | ||
| 801 | if(!tmp) | ||
| 802 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid key")); | ||
| 803 | else | ||
| 804 | memcpy(key, tmp, sizeof(union acpi_hotkey)); | ||
| 805 | goto cont_cmd; | ||
| 806 | } | ||
| 807 | if (IS_EVENT(internal_event_num)) { | ||
| 808 | kfree(bus_method); | ||
| 809 | ret = init_hotkey_device(key, bus_handle, action_handle, method, | ||
| 662 | internal_event_num, external_event_num); | 810 | internal_event_num, external_event_num); |
| 663 | 811 | } else | |
| 664 | if (ret || check_hotkey_valid(key, hotkey_list)) { | 812 | ret = init_poll_hotkey_device(key, bus_handle, bus_method, |
| 813 | action_handle, method, | ||
| 814 | internal_event_num); | ||
| 815 | if (ret) { | ||
| 816 | kfree(bus_handle); | ||
| 817 | kfree(action_handle); | ||
| 818 | if(IS_EVENT(internal_event_num)) | ||
| 819 | free_hotkey_buffer(key); | ||
| 820 | else | ||
| 821 | free_poll_hotkey_buffer(key); | ||
| 665 | kfree(key); | 822 | kfree(key); |
| 666 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid hotkey \n")); | 823 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid hotkey \n")); |
| 667 | return_VALUE(-EINVAL); | 824 | return_VALUE(-EINVAL); |
| 668 | } | 825 | } |
| 669 | switch (cmd) { | ||
| 670 | case 0: | ||
| 671 | hotkey_add(key); | ||
| 672 | break; | ||
| 673 | case 1: | ||
| 674 | hotkey_remove(key); | ||
| 675 | free_hotkey_device(key); | ||
| 676 | break; | ||
| 677 | case 2: | ||
| 678 | hotkey_update(key); | ||
| 679 | break; | ||
| 680 | default: | ||
| 681 | break; | ||
| 682 | } | ||
| 683 | return_VALUE(count); | ||
| 684 | } | ||
| 685 | |||
| 686 | /* count is length for one input record */ | ||
| 687 | static ssize_t hotkey_write_poll_config(struct file *file, | ||
| 688 | const char __user * buffer, | ||
| 689 | size_t count, loff_t * data) | ||
| 690 | { | ||
| 691 | struct seq_file *m = (struct seq_file *)file->private_data; | ||
| 692 | struct acpi_hotkey_list *hotkey_list = | ||
| 693 | (struct acpi_hotkey_list *)m->private; | ||
| 694 | |||
| 695 | char config_record[MAX_CONFIG_RECORD_LEN]; | ||
| 696 | char polling_handle[MAX_NAME_PATH_LEN]; | ||
| 697 | char action_handle[MAX_NAME_PATH_LEN]; | ||
| 698 | char poll_method[20], action_method[20]; | ||
| 699 | int ret, internal_event_num, cmd, external_event_num; | ||
| 700 | union acpi_hotkey *key = NULL; | ||
| 701 | |||
| 702 | ACPI_FUNCTION_TRACE("hotkey_write_poll_config"); | ||
| 703 | |||
| 704 | if (!hotkey_list || count > MAX_CONFIG_RECORD_LEN) { | ||
| 705 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid arguments\n")); | ||
| 706 | return_VALUE(-EINVAL); | ||
| 707 | } | ||
| 708 | |||
| 709 | if (copy_from_user(config_record, buffer, count)) { | ||
| 710 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data \n")); | ||
| 711 | return_VALUE(-EINVAL); | ||
| 712 | } | ||
| 713 | config_record[count] = '\0'; | ||
| 714 | 826 | ||
| 715 | ret = get_parms(config_record, | 827 | cont_cmd: |
| 716 | &cmd, | 828 | kfree(bus_handle); |
| 717 | polling_handle, | 829 | kfree(action_handle); |
| 718 | poll_method, | ||
| 719 | action_handle, | ||
| 720 | action_method, | ||
| 721 | &internal_event_num, &external_event_num); | ||
| 722 | |||
| 723 | if (ret != 6) { | ||
| 724 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data format\n")); | ||
| 725 | return_VALUE(-EINVAL); | ||
| 726 | } | ||
| 727 | 830 | ||
| 728 | key = kmalloc(sizeof(union acpi_hotkey), GFP_KERNEL); | ||
| 729 | ret = init_poll_hotkey_device(key, polling_handle, poll_method, | ||
| 730 | action_handle, action_method, | ||
| 731 | internal_event_num); | ||
| 732 | if (ret || check_hotkey_valid(key, hotkey_list)) { | ||
| 733 | kfree(key); | ||
| 734 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid hotkey \n")); | ||
| 735 | return_VALUE(-EINVAL); | ||
| 736 | } | ||
| 737 | switch (cmd) { | 831 | switch (cmd) { |
| 738 | case 0: | 832 | case 0: |
| 739 | hotkey_add(key); | 833 | if(get_hotkey_by_event(&global_hotkey_list,key->link.hotkey_standard_num)) |
| 834 | goto fail_out; | ||
| 835 | else | ||
| 836 | hotkey_add(key); | ||
| 740 | break; | 837 | break; |
| 741 | case 1: | 838 | case 1: |
| 742 | hotkey_remove(key); | 839 | hotkey_remove(key); |
| 743 | break; | 840 | break; |
| 744 | case 2: | 841 | case 2: |
| 745 | hotkey_update(key); | 842 | if(hotkey_update(key)) |
| 843 | goto fail_out; | ||
| 746 | break; | 844 | break; |
| 747 | default: | 845 | default: |
| 846 | goto fail_out; | ||
| 748 | break; | 847 | break; |
| 749 | } | 848 | } |
| 750 | return_VALUE(count); | 849 | return_VALUE(count); |
| 850 | fail_out: | ||
| 851 | if(IS_EVENT(internal_event_num)) | ||
| 852 | free_hotkey_buffer(key); | ||
| 853 | else | ||
| 854 | free_poll_hotkey_buffer(key); | ||
| 855 | kfree(key); | ||
| 856 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "invalid key\n")); | ||
| 857 | return_VALUE(-EINVAL); | ||
| 751 | } | 858 | } |
| 752 | 859 | ||
| 753 | /* | 860 | /* |
| 754 | * This function evaluates an ACPI method, given an int as parameter, the | 861 | * This function evaluates an ACPI method, given an int as parameter, the |
| 755 | * method is searched within the scope of the handle, can be NULL. The output | 862 | * method is searched within the scope of the handle, can be NULL. The output |
| 756 | * of the method is written is output, which can also be NULL | 863 | * of the method is written is output, which can also be NULL |
| @@ -775,7 +882,7 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val, | |||
| 775 | return_VALUE(status == AE_OK); | 882 | return_VALUE(status == AE_OK); |
| 776 | } | 883 | } |
| 777 | 884 | ||
| 778 | static int read_acpi_int(acpi_handle handle, const char *method, int *val) | 885 | static int read_acpi_int(acpi_handle handle, const char *method, union acpi_object *val) |
| 779 | { | 886 | { |
| 780 | struct acpi_buffer output; | 887 | struct acpi_buffer output; |
| 781 | union acpi_object out_obj; | 888 | union acpi_object out_obj; |
| @@ -786,62 +893,32 @@ static int read_acpi_int(acpi_handle handle, const char *method, int *val) | |||
| 786 | output.pointer = &out_obj; | 893 | output.pointer = &out_obj; |
| 787 | 894 | ||
| 788 | status = acpi_evaluate_object(handle, (char *)method, NULL, &output); | 895 | status = acpi_evaluate_object(handle, (char *)method, NULL, &output); |
| 789 | *val = out_obj.integer.value; | 896 | if(val){ |
| 897 | val->integer.value = out_obj.integer.value; | ||
| 898 | val->type = out_obj.type; | ||
| 899 | } else | ||
| 900 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "null val pointer")); | ||
| 790 | return_VALUE((status == AE_OK) | 901 | return_VALUE((status == AE_OK) |
| 791 | && (out_obj.type == ACPI_TYPE_INTEGER)); | 902 | && (out_obj.type == ACPI_TYPE_INTEGER)); |
| 792 | } | 903 | } |
| 793 | 904 | ||
| 794 | static acpi_handle | 905 | static union acpi_hotkey *get_hotkey_by_event(struct |
| 795 | get_handle_from_hotkeylist(struct acpi_hotkey_list *hotkey_list, int event_num) | 906 | acpi_hotkey_list |
| 907 | *hotkey_list, int event) | ||
| 796 | { | 908 | { |
| 797 | struct list_head *entries, *next; | 909 | struct list_head *entries; |
| 798 | |||
| 799 | list_for_each_safe(entries, next, hotkey_list->entries) { | ||
| 800 | union acpi_hotkey *key = | ||
| 801 | container_of(entries, union acpi_hotkey, entries); | ||
| 802 | if (key->link.hotkey_type == ACPI_HOTKEY_EVENT | ||
| 803 | && key->link.hotkey_standard_num == event_num) { | ||
| 804 | return (key->event_hotkey.action_handle); | ||
| 805 | } | ||
| 806 | } | ||
| 807 | return (NULL); | ||
| 808 | } | ||
| 809 | |||
| 810 | static | ||
| 811 | char *get_method_from_hotkeylist(struct acpi_hotkey_list *hotkey_list, | ||
| 812 | int event_num) | ||
| 813 | { | ||
| 814 | struct list_head *entries, *next; | ||
| 815 | |||
| 816 | list_for_each_safe(entries, next, hotkey_list->entries) { | ||
| 817 | union acpi_hotkey *key = | ||
| 818 | container_of(entries, union acpi_hotkey, entries); | ||
| 819 | |||
| 820 | if (key->link.hotkey_type == ACPI_HOTKEY_EVENT && | ||
| 821 | key->link.hotkey_standard_num == event_num) | ||
| 822 | return (key->event_hotkey.action_method); | ||
| 823 | } | ||
| 824 | return (NULL); | ||
| 825 | } | ||
| 826 | |||
| 827 | static struct acpi_polling_hotkey *get_hotkey_by_event(struct | ||
| 828 | acpi_hotkey_list | ||
| 829 | *hotkey_list, int event) | ||
| 830 | { | ||
| 831 | struct list_head *entries, *next; | ||
| 832 | 910 | ||
| 833 | list_for_each_safe(entries, next, hotkey_list->entries) { | 911 | list_for_each(entries, hotkey_list->entries) { |
| 834 | union acpi_hotkey *key = | 912 | union acpi_hotkey *key = |
| 835 | container_of(entries, union acpi_hotkey, entries); | 913 | container_of(entries, union acpi_hotkey, entries); |
| 836 | if (key->link.hotkey_type == ACPI_HOTKEY_POLLING | 914 | if (key->link.hotkey_standard_num == event) { |
| 837 | && key->link.hotkey_standard_num == event) { | 915 | return(key); |
| 838 | return (&key->poll_hotkey); | ||
| 839 | } | 916 | } |
| 840 | } | 917 | } |
| 841 | return (NULL); | 918 | return(NULL); |
| 842 | } | 919 | } |
| 843 | 920 | ||
| 844 | /* | 921 | /* |
| 845 | * user call AML method interface: | 922 | * user call AML method interface: |
| 846 | * Call convention: | 923 | * Call convention: |
| 847 | * echo "event_num: arg type : value" | 924 | * echo "event_num: arg type : value" |
| @@ -854,48 +931,56 @@ static ssize_t hotkey_execute_aml_method(struct file *file, | |||
| 854 | size_t count, loff_t * data) | 931 | size_t count, loff_t * data) |
| 855 | { | 932 | { |
| 856 | struct acpi_hotkey_list *hotkey_list = &global_hotkey_list; | 933 | struct acpi_hotkey_list *hotkey_list = &global_hotkey_list; |
| 857 | char arg[MAX_CALL_PARM]; | 934 | char *arg; |
| 858 | int event, type, value; | 935 | int event,method_type,type, value; |
| 859 | 936 | union acpi_hotkey *key; | |
| 860 | char *method; | ||
| 861 | acpi_handle handle; | ||
| 862 | 937 | ||
| 863 | ACPI_FUNCTION_TRACE("hotkey_execte_aml_method"); | 938 | ACPI_FUNCTION_TRACE("hotkey_execte_aml_method"); |
| 864 | 939 | ||
| 865 | if (!hotkey_list || count > MAX_CALL_PARM) { | 940 | arg = (char *) kmalloc(count+1, GFP_KERNEL); |
| 866 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument 1")); | 941 | if(!arg) |
| 867 | return_VALUE(-EINVAL); | 942 | return_VALUE(-ENOMEM); |
| 868 | } | 943 | arg[count]=0; |
| 869 | 944 | ||
| 870 | if (copy_from_user(arg, buffer, count)) { | 945 | if (copy_from_user(arg, buffer, count)) { |
| 946 | kfree(arg); | ||
| 871 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument 2")); | 947 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument 2")); |
| 872 | return_VALUE(-EINVAL); | 948 | return_VALUE(-EINVAL); |
| 873 | } | 949 | } |
| 874 | 950 | ||
| 875 | arg[count] = '\0'; | 951 | if (sscanf(arg, "%d:%d:%d:%d", &event, &method_type, &type, &value) != 4) { |
| 876 | 952 | kfree(arg); | |
| 877 | if (sscanf(arg, "%d:%d:%d", &event, &type, &value) != 3) { | ||
| 878 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument 3")); | 953 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument 3")); |
| 879 | return_VALUE(-EINVAL); | 954 | return_VALUE(-EINVAL); |
| 880 | } | 955 | } |
| 881 | 956 | kfree(arg); | |
| 882 | if (type == ACPI_TYPE_INTEGER) { | 957 | if (type == ACPI_TYPE_INTEGER) { |
| 883 | handle = get_handle_from_hotkeylist(hotkey_list, event); | 958 | key = get_hotkey_by_event(hotkey_list, event); |
| 884 | method = (char *)get_method_from_hotkeylist(hotkey_list, event); | 959 | if(!key) |
| 960 | goto do_fail; | ||
| 885 | if (IS_EVENT(event)) | 961 | if (IS_EVENT(event)) |
| 886 | write_acpi_int(handle, method, value, NULL); | 962 | write_acpi_int(key->event_hotkey.action_handle, |
| 963 | key->event_hotkey.action_method, value, NULL); | ||
| 887 | else if (IS_POLL(event)) { | 964 | else if (IS_POLL(event)) { |
| 888 | struct acpi_polling_hotkey *key; | 965 | if ( method_type == POLL_METHOD ) |
| 889 | key = (struct acpi_polling_hotkey *) | 966 | read_acpi_int(key->poll_hotkey.poll_handle, |
| 890 | get_hotkey_by_event(hotkey_list, event); | 967 | key->poll_hotkey.poll_method, |
| 891 | read_acpi_int(handle, method, key->poll_result); | 968 | key->poll_hotkey.poll_result); |
| 969 | else if ( method_type == ACTION_METHOD ) | ||
| 970 | write_acpi_int(key->poll_hotkey.action_handle, | ||
| 971 | key->poll_hotkey.action_method, value, NULL); | ||
| 972 | else | ||
| 973 | goto do_fail; | ||
| 974 | |||
| 892 | } | 975 | } |
| 893 | } else { | 976 | } else { |
| 894 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Not supported")); | 977 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Not supported")); |
| 895 | return_VALUE(-EINVAL); | 978 | return_VALUE(-EINVAL); |
| 896 | } | 979 | } |
| 897 | |||
| 898 | return_VALUE(count); | 980 | return_VALUE(count); |
| 981 | do_fail: | ||
| 982 | return_VALUE(-EINVAL); | ||
| 983 | |||
| 899 | } | 984 | } |
| 900 | 985 | ||
| 901 | static int __init hotkey_init(void) | 986 | static int __init hotkey_init(void) |
| @@ -928,7 +1013,7 @@ static int __init hotkey_init(void) | |||
| 928 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | 1013 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
| 929 | "Hotkey: Unable to create %s entry\n", | 1014 | "Hotkey: Unable to create %s entry\n", |
| 930 | HOTKEY_EV_CONFIG)); | 1015 | HOTKEY_EV_CONFIG)); |
| 931 | return (-ENODEV); | 1016 | goto do_fail1; |
| 932 | } else { | 1017 | } else { |
| 933 | hotkey_config->proc_fops = &hotkey_config_fops; | 1018 | hotkey_config->proc_fops = &hotkey_config_fops; |
| 934 | hotkey_config->data = &global_hotkey_list; | 1019 | hotkey_config->data = &global_hotkey_list; |
| @@ -943,7 +1028,8 @@ static int __init hotkey_init(void) | |||
| 943 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | 1028 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
| 944 | "Hotkey: Unable to create %s entry\n", | 1029 | "Hotkey: Unable to create %s entry\n", |
| 945 | HOTKEY_EV_CONFIG)); | 1030 | HOTKEY_EV_CONFIG)); |
| 946 | return (-ENODEV); | 1031 | |
| 1032 | goto do_fail2; | ||
| 947 | } else { | 1033 | } else { |
| 948 | hotkey_poll_config->proc_fops = &hotkey_poll_config_fops; | 1034 | hotkey_poll_config->proc_fops = &hotkey_poll_config_fops; |
| 949 | hotkey_poll_config->data = &global_hotkey_list; | 1035 | hotkey_poll_config->data = &global_hotkey_list; |
| @@ -957,7 +1043,7 @@ static int __init hotkey_init(void) | |||
| 957 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | 1043 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
| 958 | "Hotkey: Unable to create %s entry\n", | 1044 | "Hotkey: Unable to create %s entry\n", |
| 959 | HOTKEY_ACTION)); | 1045 | HOTKEY_ACTION)); |
| 960 | return (-ENODEV); | 1046 | goto do_fail3; |
| 961 | } else { | 1047 | } else { |
| 962 | hotkey_action->proc_fops = &hotkey_action_fops; | 1048 | hotkey_action->proc_fops = &hotkey_action_fops; |
| 963 | hotkey_action->owner = THIS_MODULE; | 1049 | hotkey_action->owner = THIS_MODULE; |
| @@ -970,7 +1056,7 @@ static int __init hotkey_init(void) | |||
| 970 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | 1056 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
| 971 | "Hotkey: Unable to create %s entry\n", | 1057 | "Hotkey: Unable to create %s entry\n", |
| 972 | HOTKEY_INFO)); | 1058 | HOTKEY_INFO)); |
| 973 | return (-ENODEV); | 1059 | goto do_fail4; |
| 974 | } else { | 1060 | } else { |
| 975 | hotkey_info->proc_fops = &hotkey_info_fops; | 1061 | hotkey_info->proc_fops = &hotkey_info_fops; |
| 976 | hotkey_info->owner = THIS_MODULE; | 1062 | hotkey_info->owner = THIS_MODULE; |
| @@ -979,23 +1065,33 @@ static int __init hotkey_init(void) | |||
| 979 | } | 1065 | } |
| 980 | 1066 | ||
| 981 | result = acpi_bus_register_driver(&hotkey_driver); | 1067 | result = acpi_bus_register_driver(&hotkey_driver); |
| 982 | if (result < 0) { | 1068 | if (result < 0) |
| 983 | remove_proc_entry(HOTKEY_PROC, acpi_root_dir); | 1069 | goto do_fail5; |
| 984 | return (-ENODEV); | ||
| 985 | } | ||
| 986 | global_hotkey_list.count = 0; | 1070 | global_hotkey_list.count = 0; |
| 987 | global_hotkey_list.entries = &hotkey_entries; | 1071 | global_hotkey_list.entries = &hotkey_entries; |
| 988 | 1072 | ||
| 989 | INIT_LIST_HEAD(&hotkey_entries); | 1073 | INIT_LIST_HEAD(&hotkey_entries); |
| 990 | 1074 | ||
| 991 | return (0); | 1075 | return (0); |
| 1076 | |||
| 1077 | do_fail5: | ||
| 1078 | remove_proc_entry(HOTKEY_INFO, hotkey_proc_dir); | ||
| 1079 | do_fail4: | ||
| 1080 | remove_proc_entry(HOTKEY_ACTION, hotkey_proc_dir); | ||
| 1081 | do_fail3: | ||
| 1082 | remove_proc_entry(HOTKEY_PL_CONFIG, hotkey_proc_dir); | ||
| 1083 | do_fail2: | ||
| 1084 | remove_proc_entry(HOTKEY_EV_CONFIG, hotkey_proc_dir); | ||
| 1085 | do_fail1: | ||
| 1086 | remove_proc_entry(HOTKEY_PROC, acpi_root_dir); | ||
| 1087 | return (-ENODEV); | ||
| 992 | } | 1088 | } |
| 993 | 1089 | ||
| 994 | static void __exit hotkey_exit(void) | 1090 | static void __exit hotkey_exit(void) |
| 995 | { | 1091 | { |
| 996 | struct list_head *entries, *next; | 1092 | struct list_head *entries, *next; |
| 997 | 1093 | ||
| 998 | ACPI_FUNCTION_TRACE("hotkey_remove"); | 1094 | ACPI_FUNCTION_TRACE("hotkey_exit"); |
| 999 | 1095 | ||
| 1000 | list_for_each_safe(entries, next, global_hotkey_list.entries) { | 1096 | list_for_each_safe(entries, next, global_hotkey_list.entries) { |
| 1001 | union acpi_hotkey *key = | 1097 | union acpi_hotkey *key = |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index bdd9f37f8101..7289da3c4db6 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
| @@ -145,10 +145,14 @@ acpi_os_vprintf(const char *fmt, va_list args) | |||
| 145 | #endif | 145 | #endif |
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | extern int acpi_in_resume; | ||
| 148 | void * | 149 | void * |
| 149 | acpi_os_allocate(acpi_size size) | 150 | acpi_os_allocate(acpi_size size) |
| 150 | { | 151 | { |
| 151 | return kmalloc(size, GFP_KERNEL); | 152 | if (acpi_in_resume) |
| 153 | return kmalloc(size, GFP_ATOMIC); | ||
| 154 | else | ||
| 155 | return kmalloc(size, GFP_KERNEL); | ||
| 152 | } | 156 | } |
| 153 | 157 | ||
| 154 | void | 158 | void |
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index d1f42b972821..bb973d2109a1 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c | |||
| @@ -269,7 +269,51 @@ acpi_pci_irq_del_prt (int segment, int bus) | |||
| 269 | /* -------------------------------------------------------------------------- | 269 | /* -------------------------------------------------------------------------- |
| 270 | PCI Interrupt Routing Support | 270 | PCI Interrupt Routing Support |
| 271 | -------------------------------------------------------------------------- */ | 271 | -------------------------------------------------------------------------- */ |
| 272 | typedef int (*irq_lookup_func)(struct acpi_prt_entry *, int *, int *, char **); | ||
| 272 | 273 | ||
| 274 | static int | ||
| 275 | acpi_pci_allocate_irq(struct acpi_prt_entry *entry, | ||
| 276 | int *edge_level, | ||
| 277 | int *active_high_low, | ||
| 278 | char **link) | ||
| 279 | { | ||
| 280 | int irq; | ||
| 281 | |||
| 282 | ACPI_FUNCTION_TRACE("acpi_pci_allocate_irq"); | ||
| 283 | |||
| 284 | if (entry->link.handle) { | ||
| 285 | irq = acpi_pci_link_allocate_irq(entry->link.handle, | ||
| 286 | entry->link.index, edge_level, active_high_low, link); | ||
| 287 | if (irq < 0) { | ||
| 288 | ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n")); | ||
| 289 | return_VALUE(-1); | ||
| 290 | } | ||
| 291 | } else { | ||
| 292 | irq = entry->link.index; | ||
| 293 | *edge_level = ACPI_LEVEL_SENSITIVE; | ||
| 294 | *active_high_low = ACPI_ACTIVE_LOW; | ||
| 295 | } | ||
| 296 | |||
| 297 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq)); | ||
| 298 | return_VALUE(irq); | ||
| 299 | } | ||
| 300 | |||
| 301 | static int | ||
| 302 | acpi_pci_free_irq(struct acpi_prt_entry *entry, | ||
| 303 | int *edge_level, | ||
| 304 | int *active_high_low, | ||
| 305 | char **link) | ||
| 306 | { | ||
| 307 | int irq; | ||
| 308 | |||
| 309 | ACPI_FUNCTION_TRACE("acpi_pci_free_irq"); | ||
| 310 | if (entry->link.handle) { | ||
| 311 | irq = acpi_pci_link_free_irq(entry->link.handle); | ||
| 312 | } else { | ||
| 313 | irq = entry->link.index; | ||
| 314 | } | ||
| 315 | return_VALUE(irq); | ||
| 316 | } | ||
| 273 | /* | 317 | /* |
| 274 | * acpi_pci_irq_lookup | 318 | * acpi_pci_irq_lookup |
| 275 | * success: return IRQ >= 0 | 319 | * success: return IRQ >= 0 |
| @@ -282,12 +326,13 @@ acpi_pci_irq_lookup ( | |||
| 282 | int pin, | 326 | int pin, |
| 283 | int *edge_level, | 327 | int *edge_level, |
| 284 | int *active_high_low, | 328 | int *active_high_low, |
| 285 | char **link) | 329 | char **link, |
| 330 | irq_lookup_func func) | ||
| 286 | { | 331 | { |
| 287 | struct acpi_prt_entry *entry = NULL; | 332 | struct acpi_prt_entry *entry = NULL; |
| 288 | int segment = pci_domain_nr(bus); | 333 | int segment = pci_domain_nr(bus); |
| 289 | int bus_nr = bus->number; | 334 | int bus_nr = bus->number; |
| 290 | int irq; | 335 | int ret; |
| 291 | 336 | ||
| 292 | ACPI_FUNCTION_TRACE("acpi_pci_irq_lookup"); | 337 | ACPI_FUNCTION_TRACE("acpi_pci_irq_lookup"); |
| 293 | 338 | ||
| @@ -301,22 +346,8 @@ acpi_pci_irq_lookup ( | |||
| 301 | return_VALUE(-1); | 346 | return_VALUE(-1); |
| 302 | } | 347 | } |
| 303 | 348 | ||
| 304 | if (entry->link.handle) { | 349 | ret = func(entry, edge_level, active_high_low, link); |
| 305 | irq = acpi_pci_link_get_irq(entry->link.handle, | 350 | return_VALUE(ret); |
| 306 | entry->link.index, edge_level, active_high_low, link); | ||
| 307 | if (irq < 0) { | ||
| 308 | ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n")); | ||
| 309 | return_VALUE(-1); | ||
| 310 | } | ||
| 311 | } else { | ||
| 312 | irq = entry->link.index; | ||
| 313 | *edge_level = ACPI_LEVEL_SENSITIVE; | ||
| 314 | *active_high_low = ACPI_ACTIVE_LOW; | ||
| 315 | } | ||
| 316 | |||
| 317 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq)); | ||
| 318 | |||
| 319 | return_VALUE(irq); | ||
| 320 | } | 351 | } |
| 321 | 352 | ||
| 322 | /* | 353 | /* |
| @@ -330,7 +361,8 @@ acpi_pci_irq_derive ( | |||
| 330 | int pin, | 361 | int pin, |
| 331 | int *edge_level, | 362 | int *edge_level, |
| 332 | int *active_high_low, | 363 | int *active_high_low, |
| 333 | char **link) | 364 | char **link, |
| 365 | irq_lookup_func func) | ||
| 334 | { | 366 | { |
| 335 | struct pci_dev *bridge = dev; | 367 | struct pci_dev *bridge = dev; |
| 336 | int irq = -1; | 368 | int irq = -1; |
| @@ -363,7 +395,7 @@ acpi_pci_irq_derive ( | |||
| 363 | } | 395 | } |
| 364 | 396 | ||
| 365 | irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn), | 397 | irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn), |
| 366 | pin, edge_level, active_high_low, link); | 398 | pin, edge_level, active_high_low, link, func); |
| 367 | } | 399 | } |
| 368 | 400 | ||
| 369 | if (irq < 0) { | 401 | if (irq < 0) { |
| @@ -415,7 +447,7 @@ acpi_pci_irq_enable ( | |||
| 415 | * values override any BIOS-assigned IRQs set during boot. | 447 | * values override any BIOS-assigned IRQs set during boot. |
| 416 | */ | 448 | */ |
| 417 | irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, | 449 | irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, |
| 418 | &edge_level, &active_high_low, &link); | 450 | &edge_level, &active_high_low, &link, acpi_pci_allocate_irq); |
| 419 | 451 | ||
| 420 | /* | 452 | /* |
| 421 | * If no PRT entry was found, we'll try to derive an IRQ from the | 453 | * If no PRT entry was found, we'll try to derive an IRQ from the |
| @@ -423,7 +455,7 @@ acpi_pci_irq_enable ( | |||
| 423 | */ | 455 | */ |
| 424 | if (irq < 0) | 456 | if (irq < 0) |
| 425 | irq = acpi_pci_irq_derive(dev, pin, &edge_level, | 457 | irq = acpi_pci_irq_derive(dev, pin, &edge_level, |
| 426 | &active_high_low, &link); | 458 | &active_high_low, &link, acpi_pci_allocate_irq); |
| 427 | 459 | ||
| 428 | /* | 460 | /* |
| 429 | * No IRQ known to the ACPI subsystem - maybe the BIOS / | 461 | * No IRQ known to the ACPI subsystem - maybe the BIOS / |
| @@ -462,7 +494,9 @@ acpi_pci_irq_enable ( | |||
| 462 | EXPORT_SYMBOL(acpi_pci_irq_enable); | 494 | EXPORT_SYMBOL(acpi_pci_irq_enable); |
| 463 | 495 | ||
| 464 | 496 | ||
| 465 | #ifdef CONFIG_ACPI_DEALLOCATE_IRQ | 497 | /* FIXME: implement x86/x86_64 version */ |
| 498 | void __attribute__((weak)) acpi_unregister_gsi(u32 i) {} | ||
| 499 | |||
| 466 | void | 500 | void |
| 467 | acpi_pci_irq_disable ( | 501 | acpi_pci_irq_disable ( |
| 468 | struct pci_dev *dev) | 502 | struct pci_dev *dev) |
| @@ -489,14 +523,14 @@ acpi_pci_irq_disable ( | |||
| 489 | * First we check the PCI IRQ routing table (PRT) for an IRQ. | 523 | * First we check the PCI IRQ routing table (PRT) for an IRQ. |
| 490 | */ | 524 | */ |
| 491 | gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, | 525 | gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, |
| 492 | &edge_level, &active_high_low, NULL); | 526 | &edge_level, &active_high_low, NULL, acpi_pci_free_irq); |
| 493 | /* | 527 | /* |
| 494 | * If no PRT entry was found, we'll try to derive an IRQ from the | 528 | * If no PRT entry was found, we'll try to derive an IRQ from the |
| 495 | * device's parent bridge. | 529 | * device's parent bridge. |
| 496 | */ | 530 | */ |
| 497 | if (gsi < 0) | 531 | if (gsi < 0) |
| 498 | gsi = acpi_pci_irq_derive(dev, pin, | 532 | gsi = acpi_pci_irq_derive(dev, pin, |
| 499 | &edge_level, &active_high_low, NULL); | 533 | &edge_level, &active_high_low, NULL, acpi_pci_free_irq); |
| 500 | if (gsi < 0) | 534 | if (gsi < 0) |
| 501 | return_VOID; | 535 | return_VOID; |
| 502 | 536 | ||
| @@ -512,4 +546,3 @@ acpi_pci_irq_disable ( | |||
| 512 | 546 | ||
| 513 | return_VOID; | 547 | return_VOID; |
| 514 | } | 548 | } |
| 515 | #endif /* CONFIG_ACPI_DEALLOCATE_IRQ */ | ||
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 6ad0e77df9b3..834c2ceff1aa 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c | |||
| @@ -68,6 +68,10 @@ static struct acpi_driver acpi_pci_link_driver = { | |||
| 68 | }, | 68 | }, |
| 69 | }; | 69 | }; |
| 70 | 70 | ||
| 71 | /* | ||
| 72 | * If a link is initialized, we never change its active and initialized | ||
| 73 | * later even the link is disable. Instead, we just repick the active irq | ||
| 74 | */ | ||
| 71 | struct acpi_pci_link_irq { | 75 | struct acpi_pci_link_irq { |
| 72 | u8 active; /* Current IRQ */ | 76 | u8 active; /* Current IRQ */ |
| 73 | u8 edge_level; /* All IRQs */ | 77 | u8 edge_level; /* All IRQs */ |
| @@ -76,8 +80,7 @@ struct acpi_pci_link_irq { | |||
| 76 | u8 possible_count; | 80 | u8 possible_count; |
| 77 | u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE]; | 81 | u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE]; |
| 78 | u8 initialized:1; | 82 | u8 initialized:1; |
| 79 | u8 suspend_resume:1; | 83 | u8 reserved:7; |
| 80 | u8 reserved:6; | ||
| 81 | }; | 84 | }; |
| 82 | 85 | ||
| 83 | struct acpi_pci_link { | 86 | struct acpi_pci_link { |
| @@ -85,12 +88,14 @@ struct acpi_pci_link { | |||
| 85 | struct acpi_device *device; | 88 | struct acpi_device *device; |
| 86 | acpi_handle handle; | 89 | acpi_handle handle; |
| 87 | struct acpi_pci_link_irq irq; | 90 | struct acpi_pci_link_irq irq; |
| 91 | int refcnt; | ||
| 88 | }; | 92 | }; |
| 89 | 93 | ||
| 90 | static struct { | 94 | static struct { |
| 91 | int count; | 95 | int count; |
| 92 | struct list_head entries; | 96 | struct list_head entries; |
| 93 | } acpi_link; | 97 | } acpi_link; |
| 98 | DECLARE_MUTEX(acpi_link_lock); | ||
| 94 | 99 | ||
| 95 | 100 | ||
| 96 | /* -------------------------------------------------------------------------- | 101 | /* -------------------------------------------------------------------------- |
| @@ -532,12 +537,12 @@ static int acpi_pci_link_allocate( | |||
| 532 | 537 | ||
| 533 | ACPI_FUNCTION_TRACE("acpi_pci_link_allocate"); | 538 | ACPI_FUNCTION_TRACE("acpi_pci_link_allocate"); |
| 534 | 539 | ||
| 535 | if (link->irq.suspend_resume) { | 540 | if (link->irq.initialized) { |
| 536 | acpi_pci_link_set(link, link->irq.active); | 541 | if (link->refcnt == 0) |
| 537 | link->irq.suspend_resume = 0; | 542 | /* This means the link is disabled but initialized */ |
| 538 | } | 543 | acpi_pci_link_set(link, link->irq.active); |
| 539 | if (link->irq.initialized) | ||
| 540 | return_VALUE(0); | 544 | return_VALUE(0); |
| 545 | } | ||
| 541 | 546 | ||
| 542 | /* | 547 | /* |
| 543 | * search for active IRQ in list of possible IRQs. | 548 | * search for active IRQ in list of possible IRQs. |
| @@ -596,13 +601,13 @@ static int acpi_pci_link_allocate( | |||
| 596 | } | 601 | } |
| 597 | 602 | ||
| 598 | /* | 603 | /* |
| 599 | * acpi_pci_link_get_irq | 604 | * acpi_pci_link_allocate_irq |
| 600 | * success: return IRQ >= 0 | 605 | * success: return IRQ >= 0 |
| 601 | * failure: return -1 | 606 | * failure: return -1 |
| 602 | */ | 607 | */ |
| 603 | 608 | ||
| 604 | int | 609 | int |
| 605 | acpi_pci_link_get_irq ( | 610 | acpi_pci_link_allocate_irq ( |
| 606 | acpi_handle handle, | 611 | acpi_handle handle, |
| 607 | int index, | 612 | int index, |
| 608 | int *edge_level, | 613 | int *edge_level, |
| @@ -613,7 +618,7 @@ acpi_pci_link_get_irq ( | |||
| 613 | struct acpi_device *device = NULL; | 618 | struct acpi_device *device = NULL; |
| 614 | struct acpi_pci_link *link = NULL; | 619 | struct acpi_pci_link *link = NULL; |
| 615 | 620 | ||
| 616 | ACPI_FUNCTION_TRACE("acpi_pci_link_get_irq"); | 621 | ACPI_FUNCTION_TRACE("acpi_pci_link_allocate_irq"); |
| 617 | 622 | ||
| 618 | result = acpi_bus_get_device(handle, &device); | 623 | result = acpi_bus_get_device(handle, &device); |
| 619 | if (result) { | 624 | if (result) { |
| @@ -633,21 +638,81 @@ acpi_pci_link_get_irq ( | |||
| 633 | return_VALUE(-1); | 638 | return_VALUE(-1); |
| 634 | } | 639 | } |
| 635 | 640 | ||
| 636 | if (acpi_pci_link_allocate(link)) | 641 | down(&acpi_link_lock); |
| 642 | if (acpi_pci_link_allocate(link)) { | ||
| 643 | up(&acpi_link_lock); | ||
| 637 | return_VALUE(-1); | 644 | return_VALUE(-1); |
| 645 | } | ||
| 638 | 646 | ||
| 639 | if (!link->irq.active) { | 647 | if (!link->irq.active) { |
| 648 | up(&acpi_link_lock); | ||
| 640 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link active IRQ is 0!\n")); | 649 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link active IRQ is 0!\n")); |
| 641 | return_VALUE(-1); | 650 | return_VALUE(-1); |
| 642 | } | 651 | } |
| 652 | link->refcnt ++; | ||
| 653 | up(&acpi_link_lock); | ||
| 643 | 654 | ||
| 644 | if (edge_level) *edge_level = link->irq.edge_level; | 655 | if (edge_level) *edge_level = link->irq.edge_level; |
| 645 | if (active_high_low) *active_high_low = link->irq.active_high_low; | 656 | if (active_high_low) *active_high_low = link->irq.active_high_low; |
| 646 | if (name) *name = acpi_device_bid(link->device); | 657 | if (name) *name = acpi_device_bid(link->device); |
| 658 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 659 | "Link %s is referenced\n", acpi_device_bid(link->device))); | ||
| 647 | return_VALUE(link->irq.active); | 660 | return_VALUE(link->irq.active); |
| 648 | } | 661 | } |
| 649 | 662 | ||
| 663 | /* | ||
| 664 | * We don't change link's irq information here. After it is reenabled, we | ||
| 665 | * continue use the info | ||
| 666 | */ | ||
| 667 | int | ||
| 668 | acpi_pci_link_free_irq(acpi_handle handle) | ||
| 669 | { | ||
| 670 | struct acpi_device *device = NULL; | ||
| 671 | struct acpi_pci_link *link = NULL; | ||
| 672 | acpi_status result; | ||
| 673 | |||
| 674 | ACPI_FUNCTION_TRACE("acpi_pci_link_free_irq"); | ||
| 675 | |||
| 676 | result = acpi_bus_get_device(handle, &device); | ||
| 677 | if (result) { | ||
| 678 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link device\n")); | ||
| 679 | return_VALUE(-1); | ||
| 680 | } | ||
| 681 | |||
| 682 | link = (struct acpi_pci_link *) acpi_driver_data(device); | ||
| 683 | if (!link) { | ||
| 684 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n")); | ||
| 685 | return_VALUE(-1); | ||
| 686 | } | ||
| 687 | |||
| 688 | down(&acpi_link_lock); | ||
| 689 | if (!link->irq.initialized) { | ||
| 690 | up(&acpi_link_lock); | ||
| 691 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link isn't initialized\n")); | ||
| 692 | return_VALUE(-1); | ||
| 693 | } | ||
| 650 | 694 | ||
| 695 | #ifdef FUTURE_USE | ||
| 696 | /* | ||
| 697 | * The Link reference count allows us to _DISable an unused link | ||
| 698 | * and suspend time, and set it again on resume. | ||
| 699 | * However, 2.6.12 still has irq_router.resume | ||
| 700 | * which blindly restores the link state. | ||
| 701 | * So we disable the reference count method | ||
| 702 | * to prevent duplicate acpi_pci_link_set() | ||
| 703 | * which would harm some systems | ||
| 704 | */ | ||
| 705 | link->refcnt --; | ||
| 706 | #endif | ||
| 707 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 708 | "Link %s is dereferenced\n", acpi_device_bid(link->device))); | ||
| 709 | |||
| 710 | if (link->refcnt == 0) { | ||
| 711 | acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL); | ||
| 712 | } | ||
| 713 | up(&acpi_link_lock); | ||
| 714 | return_VALUE(link->irq.active); | ||
| 715 | } | ||
| 651 | /* -------------------------------------------------------------------------- | 716 | /* -------------------------------------------------------------------------- |
| 652 | Driver Interface | 717 | Driver Interface |
| 653 | -------------------------------------------------------------------------- */ | 718 | -------------------------------------------------------------------------- */ |
| @@ -677,6 +742,7 @@ acpi_pci_link_add ( | |||
| 677 | strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS); | 742 | strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS); |
| 678 | acpi_driver_data(device) = link; | 743 | acpi_driver_data(device) = link; |
| 679 | 744 | ||
| 745 | down(&acpi_link_lock); | ||
| 680 | result = acpi_pci_link_get_possible(link); | 746 | result = acpi_pci_link_get_possible(link); |
| 681 | if (result) | 747 | if (result) |
| 682 | goto end; | 748 | goto end; |
| @@ -712,6 +778,7 @@ acpi_pci_link_add ( | |||
| 712 | end: | 778 | end: |
| 713 | /* disable all links -- to be activated on use */ | 779 | /* disable all links -- to be activated on use */ |
| 714 | acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL); | 780 | acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL); |
| 781 | up(&acpi_link_lock); | ||
| 715 | 782 | ||
| 716 | if (result) | 783 | if (result) |
| 717 | kfree(link); | 784 | kfree(link); |
| @@ -720,24 +787,42 @@ end: | |||
| 720 | } | 787 | } |
| 721 | 788 | ||
| 722 | static int | 789 | static int |
| 723 | irqrouter_suspend( | 790 | acpi_pci_link_resume( |
| 724 | struct sys_device *dev, | 791 | struct acpi_pci_link *link) |
| 725 | u32 state) | 792 | { |
| 793 | ACPI_FUNCTION_TRACE("acpi_pci_link_resume"); | ||
| 794 | |||
| 795 | if (link->refcnt && link->irq.active && link->irq.initialized) | ||
| 796 | return_VALUE(acpi_pci_link_set(link, link->irq.active)); | ||
| 797 | else | ||
| 798 | return_VALUE(0); | ||
| 799 | } | ||
| 800 | |||
| 801 | /* | ||
| 802 | * FIXME: this is a workaround to avoid nasty warning. It will be removed | ||
| 803 | * after every device calls pci_disable_device in .resume. | ||
| 804 | */ | ||
| 805 | int acpi_in_resume; | ||
| 806 | static int | ||
| 807 | irqrouter_resume( | ||
| 808 | struct sys_device *dev) | ||
| 726 | { | 809 | { |
| 727 | struct list_head *node = NULL; | 810 | struct list_head *node = NULL; |
| 728 | struct acpi_pci_link *link = NULL; | 811 | struct acpi_pci_link *link = NULL; |
| 729 | 812 | ||
| 730 | ACPI_FUNCTION_TRACE("irqrouter_suspend"); | 813 | ACPI_FUNCTION_TRACE("irqrouter_resume"); |
| 731 | 814 | ||
| 815 | acpi_in_resume = 1; | ||
| 732 | list_for_each(node, &acpi_link.entries) { | 816 | list_for_each(node, &acpi_link.entries) { |
| 733 | link = list_entry(node, struct acpi_pci_link, node); | 817 | link = list_entry(node, struct acpi_pci_link, node); |
| 734 | if (!link) { | 818 | if (!link) { |
| 735 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n")); | 819 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
| 820 | "Invalid link context\n")); | ||
| 736 | continue; | 821 | continue; |
| 737 | } | 822 | } |
| 738 | if (link->irq.active && link->irq.initialized) | 823 | acpi_pci_link_resume(link); |
| 739 | link->irq.suspend_resume = 1; | ||
| 740 | } | 824 | } |
| 825 | acpi_in_resume = 0; | ||
| 741 | return_VALUE(0); | 826 | return_VALUE(0); |
| 742 | } | 827 | } |
| 743 | 828 | ||
| @@ -756,8 +841,9 @@ acpi_pci_link_remove ( | |||
| 756 | 841 | ||
| 757 | link = (struct acpi_pci_link *) acpi_driver_data(device); | 842 | link = (struct acpi_pci_link *) acpi_driver_data(device); |
| 758 | 843 | ||
| 759 | /* TBD: Acquire/release lock */ | 844 | down(&acpi_link_lock); |
| 760 | list_del(&link->node); | 845 | list_del(&link->node); |
| 846 | up(&acpi_link_lock); | ||
| 761 | 847 | ||
| 762 | kfree(link); | 848 | kfree(link); |
| 763 | 849 | ||
| @@ -849,9 +935,10 @@ int __init acpi_irq_balance_set(char *str) | |||
| 849 | __setup("acpi_irq_balance", acpi_irq_balance_set); | 935 | __setup("acpi_irq_balance", acpi_irq_balance_set); |
| 850 | 936 | ||
| 851 | 937 | ||
| 938 | /* FIXME: we will remove this interface after all drivers call pci_disable_device */ | ||
| 852 | static struct sysdev_class irqrouter_sysdev_class = { | 939 | static struct sysdev_class irqrouter_sysdev_class = { |
| 853 | set_kset_name("irqrouter"), | 940 | set_kset_name("irqrouter"), |
| 854 | .suspend = irqrouter_suspend, | 941 | .resume = irqrouter_resume, |
| 855 | }; | 942 | }; |
| 856 | 943 | ||
| 857 | 944 | ||
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 893b074e3d1a..2c04740c6543 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
| @@ -81,30 +81,32 @@ module_param(bm_history, uint, 0644); | |||
| 81 | * | 81 | * |
| 82 | * To skip this limit, boot/load with a large max_cstate limit. | 82 | * To skip this limit, boot/load with a large max_cstate limit. |
| 83 | */ | 83 | */ |
| 84 | static int no_c2c3(struct dmi_system_id *id) | 84 | static int set_max_cstate(struct dmi_system_id *id) |
| 85 | { | 85 | { |
| 86 | if (max_cstate > ACPI_PROCESSOR_MAX_POWER) | 86 | if (max_cstate > ACPI_PROCESSOR_MAX_POWER) |
| 87 | return 0; | 87 | return 0; |
| 88 | 88 | ||
| 89 | printk(KERN_NOTICE PREFIX "%s detected - C2,C3 disabled." | 89 | printk(KERN_NOTICE PREFIX "%s detected - limiting to C%ld max_cstate." |
| 90 | " Override with \"processor.max_cstate=%d\"\n", id->ident, | 90 | " Override with \"processor.max_cstate=%d\"\n", id->ident, |
| 91 | ACPI_PROCESSOR_MAX_POWER + 1); | 91 | (long)id->driver_data, ACPI_PROCESSOR_MAX_POWER + 1); |
| 92 | 92 | ||
| 93 | max_cstate = 1; | 93 | max_cstate = (long)id->driver_data; |
| 94 | 94 | ||
| 95 | return 0; | 95 | return 0; |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | 98 | ||
| 99 | |||
| 100 | |||
| 101 | static struct dmi_system_id __initdata processor_power_dmi_table[] = { | 99 | static struct dmi_system_id __initdata processor_power_dmi_table[] = { |
| 102 | { no_c2c3, "IBM ThinkPad R40e", { | 100 | { set_max_cstate, "IBM ThinkPad R40e", { |
| 103 | DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), | 101 | DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), |
| 104 | DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW") }}, | 102 | DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW") }, (void*)1}, |
| 105 | { no_c2c3, "Medion 41700", { | 103 | { set_max_cstate, "Medion 41700", { |
| 104 | DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), | ||
| 105 | DMI_MATCH(DMI_BIOS_VERSION,"R01-A1J") }, (void*)1}, | ||
| 106 | { set_max_cstate, "Clevo 5600D", { | ||
| 106 | DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), | 107 | DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), |
| 107 | DMI_MATCH(DMI_BIOS_VERSION,"R01-A1J") }}, | 108 | DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307") }, |
| 109 | (void*)2}, | ||
| 108 | {}, | 110 | {}, |
| 109 | }; | 111 | }; |
| 110 | 112 | ||
| @@ -549,7 +551,8 @@ static int acpi_processor_get_power_info_default_c1 (struct acpi_processor *pr) | |||
| 549 | ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_default_c1"); | 551 | ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_default_c1"); |
| 550 | 552 | ||
| 551 | for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++) | 553 | for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++) |
| 552 | memset(pr->power.states, 0, sizeof(struct acpi_processor_cx)); | 554 | memset(&(pr->power.states[i]), 0, |
| 555 | sizeof(struct acpi_processor_cx)); | ||
| 553 | 556 | ||
| 554 | /* if info is obtained from pblk/fadt, type equals state */ | 557 | /* if info is obtained from pblk/fadt, type equals state */ |
| 555 | pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; | 558 | pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; |
| @@ -580,7 +583,8 @@ static int acpi_processor_get_power_info_cst (struct acpi_processor *pr) | |||
| 580 | 583 | ||
| 581 | pr->power.count = 0; | 584 | pr->power.count = 0; |
| 582 | for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++) | 585 | for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++) |
| 583 | memset(pr->power.states, 0, sizeof(struct acpi_processor_cx)); | 586 | memset(&(pr->power.states[i]), 0, |
| 587 | sizeof(struct acpi_processor_cx)); | ||
| 584 | 588 | ||
| 585 | status = acpi_evaluate_object(pr->handle, "_CST", NULL, &buffer); | 589 | status = acpi_evaluate_object(pr->handle, "_CST", NULL, &buffer); |
| 586 | if (ACPI_FAILURE(status)) { | 590 | if (ACPI_FAILURE(status)) { |
| @@ -763,7 +767,6 @@ static void acpi_processor_power_verify_c3( | |||
| 763 | } | 767 | } |
| 764 | 768 | ||
| 765 | if (pr->flags.bm_check) { | 769 | if (pr->flags.bm_check) { |
| 766 | printk("Disabling BM access before entering C3\n"); | ||
| 767 | /* bus mastering control is necessary */ | 770 | /* bus mastering control is necessary */ |
| 768 | if (!pr->flags.bm_control) { | 771 | if (!pr->flags.bm_control) { |
| 769 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 772 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| @@ -771,7 +774,6 @@ static void acpi_processor_power_verify_c3( | |||
| 771 | return_VOID; | 774 | return_VOID; |
| 772 | } | 775 | } |
| 773 | } else { | 776 | } else { |
| 774 | printk("Invalidating cache before entering C3\n"); | ||
| 775 | /* | 777 | /* |
| 776 | * WBINVD should be set in fadt, for C3 state to be | 778 | * WBINVD should be set in fadt, for C3 state to be |
| 777 | * supported on when bm_check is not required. | 779 | * supported on when bm_check is not required. |
| @@ -842,7 +844,7 @@ static int acpi_processor_get_power_info ( | |||
| 842 | result = acpi_processor_get_power_info_cst(pr); | 844 | result = acpi_processor_get_power_info_cst(pr); |
| 843 | if ((result) || (acpi_processor_power_verify(pr) < 2)) { | 845 | if ((result) || (acpi_processor_power_verify(pr) < 2)) { |
| 844 | result = acpi_processor_get_power_info_fadt(pr); | 846 | result = acpi_processor_get_power_info_fadt(pr); |
| 845 | if (result) | 847 | if ((result) || (acpi_processor_power_verify(pr) < 2)) |
| 846 | result = acpi_processor_get_power_info_default_c1(pr); | 848 | result = acpi_processor_get_power_info_default_c1(pr); |
| 847 | } | 849 | } |
| 848 | 850 | ||
diff --git a/drivers/block/cfq-iosched.c b/drivers/block/cfq-iosched.c index de5746e38af9..2435a7c99b2b 100644 --- a/drivers/block/cfq-iosched.c +++ b/drivers/block/cfq-iosched.c | |||
| @@ -1281,6 +1281,7 @@ dispatch: | |||
| 1281 | */ | 1281 | */ |
| 1282 | if (!cfq_crq_in_driver(crq) && | 1282 | if (!cfq_crq_in_driver(crq) && |
| 1283 | !cfq_cfqq_idle_window(cfqq) && | 1283 | !cfq_cfqq_idle_window(cfqq) && |
| 1284 | !blk_barrier_rq(rq) && | ||
| 1284 | cfqd->rq_in_driver >= cfqd->cfq_max_depth) | 1285 | cfqd->rq_in_driver >= cfqd->cfq_max_depth) |
| 1285 | return NULL; | 1286 | return NULL; |
| 1286 | 1287 | ||
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 692a5fced76e..3c818544475e 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c | |||
| @@ -719,7 +719,7 @@ struct request *blk_queue_find_tag(request_queue_t *q, int tag) | |||
| 719 | { | 719 | { |
| 720 | struct blk_queue_tag *bqt = q->queue_tags; | 720 | struct blk_queue_tag *bqt = q->queue_tags; |
| 721 | 721 | ||
| 722 | if (unlikely(bqt == NULL || tag >= bqt->max_depth)) | 722 | if (unlikely(bqt == NULL || tag >= bqt->real_max_depth)) |
| 723 | return NULL; | 723 | return NULL; |
| 724 | 724 | ||
| 725 | return bqt->tag_index[tag]; | 725 | return bqt->tag_index[tag]; |
| @@ -798,6 +798,7 @@ init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth) | |||
| 798 | 798 | ||
| 799 | memset(tag_index, 0, depth * sizeof(struct request *)); | 799 | memset(tag_index, 0, depth * sizeof(struct request *)); |
| 800 | memset(tag_map, 0, nr_ulongs * sizeof(unsigned long)); | 800 | memset(tag_map, 0, nr_ulongs * sizeof(unsigned long)); |
| 801 | tags->real_max_depth = depth; | ||
| 801 | tags->max_depth = depth; | 802 | tags->max_depth = depth; |
| 802 | tags->tag_index = tag_index; | 803 | tags->tag_index = tag_index; |
| 803 | tags->tag_map = tag_map; | 804 | tags->tag_map = tag_map; |
| @@ -872,11 +873,22 @@ int blk_queue_resize_tags(request_queue_t *q, int new_depth) | |||
| 872 | return -ENXIO; | 873 | return -ENXIO; |
| 873 | 874 | ||
| 874 | /* | 875 | /* |
| 876 | * if we already have large enough real_max_depth. just | ||
| 877 | * adjust max_depth. *NOTE* as requests with tag value | ||
| 878 | * between new_depth and real_max_depth can be in-flight, tag | ||
| 879 | * map can not be shrunk blindly here. | ||
| 880 | */ | ||
| 881 | if (new_depth <= bqt->real_max_depth) { | ||
| 882 | bqt->max_depth = new_depth; | ||
| 883 | return 0; | ||
| 884 | } | ||
| 885 | |||
| 886 | /* | ||
| 875 | * save the old state info, so we can copy it back | 887 | * save the old state info, so we can copy it back |
| 876 | */ | 888 | */ |
| 877 | tag_index = bqt->tag_index; | 889 | tag_index = bqt->tag_index; |
| 878 | tag_map = bqt->tag_map; | 890 | tag_map = bqt->tag_map; |
| 879 | max_depth = bqt->max_depth; | 891 | max_depth = bqt->real_max_depth; |
| 880 | 892 | ||
| 881 | if (init_tag_map(q, bqt, new_depth)) | 893 | if (init_tag_map(q, bqt, new_depth)) |
| 882 | return -ENOMEM; | 894 | return -ENOMEM; |
| @@ -913,7 +925,7 @@ void blk_queue_end_tag(request_queue_t *q, struct request *rq) | |||
| 913 | 925 | ||
| 914 | BUG_ON(tag == -1); | 926 | BUG_ON(tag == -1); |
| 915 | 927 | ||
| 916 | if (unlikely(tag >= bqt->max_depth)) | 928 | if (unlikely(tag >= bqt->real_max_depth)) |
| 917 | /* | 929 | /* |
| 918 | * This can happen after tag depth has been reduced. | 930 | * This can happen after tag depth has been reduced. |
| 919 | * FIXME: how about a warning or info message here? | 931 | * FIXME: how about a warning or info message here? |
diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c index 2771c861f185..f696da6f417b 100644 --- a/drivers/bluetooth/bpa10x.c +++ b/drivers/bluetooth/bpa10x.c | |||
| @@ -367,11 +367,8 @@ static inline void bpa10x_free_urb(struct urb *urb) | |||
| 367 | if (!urb) | 367 | if (!urb) |
| 368 | return; | 368 | return; |
| 369 | 369 | ||
| 370 | if (urb->setup_packet) | 370 | kfree(urb->setup_packet); |
| 371 | kfree(urb->setup_packet); | 371 | kfree(urb->transfer_buffer); |
| 372 | |||
| 373 | if (urb->transfer_buffer) | ||
| 374 | kfree(urb->transfer_buffer); | ||
| 375 | 372 | ||
| 376 | usb_free_urb(urb); | 373 | usb_free_urb(urb); |
| 377 | } | 374 | } |
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c index c0ed213fc857..858fddb046de 100644 --- a/drivers/bluetooth/hci_bcsp.c +++ b/drivers/bluetooth/hci_bcsp.c | |||
| @@ -58,8 +58,6 @@ | |||
| 58 | #ifndef CONFIG_BT_HCIUART_DEBUG | 58 | #ifndef CONFIG_BT_HCIUART_DEBUG |
| 59 | #undef BT_DBG | 59 | #undef BT_DBG |
| 60 | #define BT_DBG( A... ) | 60 | #define BT_DBG( A... ) |
| 61 | #undef BT_DMP | ||
| 62 | #define BT_DMP( A... ) | ||
| 63 | #endif | 61 | #endif |
| 64 | 62 | ||
| 65 | static int hciextn = 1; | 63 | static int hciextn = 1; |
diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c index ade94a57bb11..533323b60e63 100644 --- a/drivers/bluetooth/hci_h4.c +++ b/drivers/bluetooth/hci_h4.c | |||
| @@ -57,8 +57,6 @@ | |||
| 57 | #ifndef CONFIG_BT_HCIUART_DEBUG | 57 | #ifndef CONFIG_BT_HCIUART_DEBUG |
| 58 | #undef BT_DBG | 58 | #undef BT_DBG |
| 59 | #define BT_DBG( A... ) | 59 | #define BT_DBG( A... ) |
| 60 | #undef BT_DMP | ||
| 61 | #define BT_DMP( A... ) | ||
| 62 | #endif | 60 | #endif |
| 63 | 61 | ||
| 64 | /* Initialize protocol */ | 62 | /* Initialize protocol */ |
| @@ -125,7 +123,6 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len) | |||
| 125 | 123 | ||
| 126 | BT_DBG("len %d room %d", len, room); | 124 | BT_DBG("len %d room %d", len, room); |
| 127 | if (!len) { | 125 | if (!len) { |
| 128 | BT_DMP(h4->rx_skb->data, h4->rx_skb->len); | ||
| 129 | hci_recv_frame(h4->rx_skb); | 126 | hci_recv_frame(h4->rx_skb); |
| 130 | } else if (len > room) { | 127 | } else if (len > room) { |
| 131 | BT_ERR("Data length is too large"); | 128 | BT_ERR("Data length is too large"); |
| @@ -169,8 +166,6 @@ static int h4_recv(struct hci_uart *hu, void *data, int count) | |||
| 169 | case H4_W4_DATA: | 166 | case H4_W4_DATA: |
| 170 | BT_DBG("Complete data"); | 167 | BT_DBG("Complete data"); |
| 171 | 168 | ||
| 172 | BT_DMP(h4->rx_skb->data, h4->rx_skb->len); | ||
| 173 | |||
| 174 | hci_recv_frame(h4->rx_skb); | 169 | hci_recv_frame(h4->rx_skb); |
| 175 | 170 | ||
| 176 | h4->rx_state = H4_W4_PACKET_TYPE; | 171 | h4->rx_state = H4_W4_PACKET_TYPE; |
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index f766bc22c6bb..90be2eae52e0 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c | |||
| @@ -57,8 +57,6 @@ | |||
| 57 | #ifndef CONFIG_BT_HCIUART_DEBUG | 57 | #ifndef CONFIG_BT_HCIUART_DEBUG |
| 58 | #undef BT_DBG | 58 | #undef BT_DBG |
| 59 | #define BT_DBG( A... ) | 59 | #define BT_DBG( A... ) |
| 60 | #undef BT_DMP | ||
| 61 | #define BT_DMP( A... ) | ||
| 62 | #endif | 60 | #endif |
| 63 | 61 | ||
| 64 | static int reset = 0; | 62 | static int reset = 0; |
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c index b120ecf7b8c9..657719b8254f 100644 --- a/drivers/bluetooth/hci_usb.c +++ b/drivers/bluetooth/hci_usb.c | |||
| @@ -57,8 +57,6 @@ | |||
| 57 | #ifndef CONFIG_BT_HCIUSB_DEBUG | 57 | #ifndef CONFIG_BT_HCIUSB_DEBUG |
| 58 | #undef BT_DBG | 58 | #undef BT_DBG |
| 59 | #define BT_DBG(D...) | 59 | #define BT_DBG(D...) |
| 60 | #undef BT_DMP | ||
| 61 | #define BT_DMP(D...) | ||
| 62 | #endif | 60 | #endif |
| 63 | 61 | ||
| 64 | #ifndef CONFIG_BT_HCIUSB_ZERO_PACKET | 62 | #ifndef CONFIG_BT_HCIUSB_ZERO_PACKET |
| @@ -110,6 +108,9 @@ static struct usb_device_id blacklist_ids[] = { | |||
| 110 | /* Microsoft Wireless Transceiver for Bluetooth 2.0 */ | 108 | /* Microsoft Wireless Transceiver for Bluetooth 2.0 */ |
| 111 | { USB_DEVICE(0x045e, 0x009c), .driver_info = HCI_RESET }, | 109 | { USB_DEVICE(0x045e, 0x009c), .driver_info = HCI_RESET }, |
| 112 | 110 | ||
| 111 | /* Kensington Bluetooth USB adapter */ | ||
| 112 | { USB_DEVICE(0x047d, 0x105d), .driver_info = HCI_RESET }, | ||
| 113 | |||
| 113 | /* ISSC Bluetooth Adapter v3.1 */ | 114 | /* ISSC Bluetooth Adapter v3.1 */ |
| 114 | { USB_DEVICE(0x1131, 0x1001), .driver_info = HCI_RESET }, | 115 | { USB_DEVICE(0x1131, 0x1001), .driver_info = HCI_RESET }, |
| 115 | 116 | ||
| @@ -387,10 +388,8 @@ static void hci_usb_unlink_urbs(struct hci_usb *husb) | |||
| 387 | urb = &_urb->urb; | 388 | urb = &_urb->urb; |
| 388 | BT_DBG("%s freeing _urb %p type %d urb %p", | 389 | BT_DBG("%s freeing _urb %p type %d urb %p", |
| 389 | husb->hdev->name, _urb, _urb->type, urb); | 390 | husb->hdev->name, _urb, _urb->type, urb); |
| 390 | if (urb->setup_packet) | 391 | kfree(urb->setup_packet); |
| 391 | kfree(urb->setup_packet); | 392 | kfree(urb->transfer_buffer); |
| 392 | if (urb->transfer_buffer) | ||
| 393 | kfree(urb->transfer_buffer); | ||
| 394 | _urb_free(_urb); | 393 | _urb_free(_urb); |
| 395 | } | 394 | } |
| 396 | 395 | ||
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 42187381506b..850a78c9c4bc 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
| @@ -261,7 +261,11 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma) | |||
| 261 | 261 | ||
| 262 | static int mmap_kmem(struct file * file, struct vm_area_struct * vma) | 262 | static int mmap_kmem(struct file * file, struct vm_area_struct * vma) |
| 263 | { | 263 | { |
| 264 | unsigned long long val; | 264 | unsigned long pfn; |
| 265 | |||
| 266 | /* Turn a kernel-virtual address into a physical page frame */ | ||
| 267 | pfn = __pa((u64)vma->vm_pgoff << PAGE_SHIFT) >> PAGE_SHIFT; | ||
| 268 | |||
| 265 | /* | 269 | /* |
| 266 | * RED-PEN: on some architectures there is more mapped memory | 270 | * RED-PEN: on some architectures there is more mapped memory |
| 267 | * than available in mem_map which pfn_valid checks | 271 | * than available in mem_map which pfn_valid checks |
| @@ -269,10 +273,10 @@ static int mmap_kmem(struct file * file, struct vm_area_struct * vma) | |||
| 269 | * | 273 | * |
| 270 | * RED-PEN: vmalloc is not supported right now. | 274 | * RED-PEN: vmalloc is not supported right now. |
| 271 | */ | 275 | */ |
| 272 | if (!pfn_valid(vma->vm_pgoff)) | 276 | if (!pfn_valid(pfn)) |
| 273 | return -EIO; | 277 | return -EIO; |
| 274 | val = (u64)vma->vm_pgoff << PAGE_SHIFT; | 278 | |
| 275 | vma->vm_pgoff = __pa(val) >> PAGE_SHIFT; | 279 | vma->vm_pgoff = pfn; |
| 276 | return mmap_mem(file, vma); | 280 | return mmap_mem(file, vma); |
| 277 | } | 281 | } |
| 278 | 282 | ||
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index d8f9e94ae475..cd4fe8b1709f 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c | |||
| @@ -1209,6 +1209,7 @@ static int rtc_proc_open(struct inode *inode, struct file *file) | |||
| 1209 | 1209 | ||
| 1210 | void rtc_get_rtc_time(struct rtc_time *rtc_tm) | 1210 | void rtc_get_rtc_time(struct rtc_time *rtc_tm) |
| 1211 | { | 1211 | { |
| 1212 | unsigned long uip_watchdog = jiffies; | ||
| 1212 | unsigned char ctrl; | 1213 | unsigned char ctrl; |
| 1213 | #ifdef CONFIG_MACH_DECSTATION | 1214 | #ifdef CONFIG_MACH_DECSTATION |
| 1214 | unsigned int real_year; | 1215 | unsigned int real_year; |
| @@ -1224,8 +1225,10 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm) | |||
| 1224 | * Once the read clears, read the RTC time (again via ioctl). Easy. | 1225 | * Once the read clears, read the RTC time (again via ioctl). Easy. |
| 1225 | */ | 1226 | */ |
| 1226 | 1227 | ||
| 1227 | if (rtc_is_updating() != 0) | 1228 | while (rtc_is_updating() != 0 && jiffies - uip_watchdog < 2*HZ/100) { |
| 1228 | msleep(20); | 1229 | barrier(); |
| 1230 | cpu_relax(); | ||
| 1231 | } | ||
| 1229 | 1232 | ||
| 1230 | /* | 1233 | /* |
| 1231 | * Only the values that we read from the RTC are set. We leave | 1234 | * Only the values that we read from the RTC are set. We leave |
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index 94a3b3e20bf9..79e9832ef1f3 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig | |||
| @@ -17,6 +17,8 @@ config TCG_TPM | |||
| 17 | obtained at: <http://sourceforge.net/projects/trousers>. To | 17 | obtained at: <http://sourceforge.net/projects/trousers>. To |
| 18 | compile this driver as a module, choose M here; the module | 18 | compile this driver as a module, choose M here; the module |
| 19 | will be called tpm. If unsure, say N. | 19 | will be called tpm. If unsure, say N. |
| 20 | Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI_BUS | ||
| 21 | and CONFIG_PNPACPI. | ||
| 20 | 22 | ||
| 21 | config TCG_NSC | 23 | config TCG_NSC |
| 22 | tristate "National Semiconductor TPM Interface" | 24 | tristate "National Semiconductor TPM Interface" |
| @@ -36,12 +38,13 @@ config TCG_ATMEL | |||
| 36 | as a module, choose M here; the module will be called tpm_atmel. | 38 | as a module, choose M here; the module will be called tpm_atmel. |
| 37 | 39 | ||
| 38 | config TCG_INFINEON | 40 | config TCG_INFINEON |
| 39 | tristate "Infineon Technologies SLD 9630 TPM Interface" | 41 | tristate "Infineon Technologies TPM Interface" |
| 40 | depends on TCG_TPM | 42 | depends on TCG_TPM && PNPACPI |
| 41 | ---help--- | 43 | ---help--- |
| 42 | If you have a TPM security chip from Infineon Technologies | 44 | If you have a TPM security chip from Infineon Technologies |
| 43 | say Yes and it will be accessible from within Linux. To | 45 | (either SLD 9630 TT 1.1 or SLB 9635 TT 1.2) say Yes and it |
| 44 | compile this driver as a module, choose M here; the module | 46 | will be accessible from within Linux. |
| 47 | To compile this driver as a module, choose M here; the module | ||
| 45 | will be called tpm_infineon. | 48 | will be called tpm_infineon. |
| 46 | Further information on this driver and the supported hardware | 49 | Further information on this driver and the supported hardware |
| 47 | can be found at http://www.prosec.rub.de/tpm | 50 | can be found at http://www.prosec.rub.de/tpm |
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c index 0e3241645c19..dc8c540391fd 100644 --- a/drivers/char/tpm/tpm_infineon.c +++ b/drivers/char/tpm/tpm_infineon.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Description: | 2 | * Description: |
| 3 | * Device Driver for the Infineon Technologies | 3 | * Device Driver for the Infineon Technologies |
| 4 | * SLD 9630 TT Trusted Platform Module | 4 | * SLD 9630 TT 1.1 and SLB 9635 TT 1.2 Trusted Platform Module |
| 5 | * Specifications at www.trustedcomputinggroup.org | 5 | * Specifications at www.trustedcomputinggroup.org |
| 6 | * | 6 | * |
| 7 | * Copyright (C) 2005, Marcel Selhorst <selhorst@crypto.rub.de> | 7 | * Copyright (C) 2005, Marcel Selhorst <selhorst@crypto.rub.de> |
| @@ -12,9 +12,10 @@ | |||
| 12 | * modify it under the terms of the GNU General Public License as | 12 | * modify it under the terms of the GNU General Public License as |
| 13 | * published by the Free Software Foundation, version 2 of the | 13 | * published by the Free Software Foundation, version 2 of the |
| 14 | * License. | 14 | * License. |
| 15 | * | ||
| 16 | */ | 15 | */ |
| 17 | 16 | ||
| 17 | #include <acpi/acpi_bus.h> | ||
| 18 | #include <linux/pnp.h> | ||
| 18 | #include "tpm.h" | 19 | #include "tpm.h" |
| 19 | 20 | ||
| 20 | /* Infineon specific definitions */ | 21 | /* Infineon specific definitions */ |
| @@ -26,8 +27,11 @@ | |||
| 26 | #define TPM_MSLEEP_TIME 3 | 27 | #define TPM_MSLEEP_TIME 3 |
| 27 | /* gives number of max. msleep()-calls before throwing timeout */ | 28 | /* gives number of max. msleep()-calls before throwing timeout */ |
| 28 | #define TPM_MAX_TRIES 5000 | 29 | #define TPM_MAX_TRIES 5000 |
| 29 | #define TCPA_INFINEON_DEV_VEN_VALUE 0x15D1 | 30 | #define TPM_INFINEON_DEV_VEN_VALUE 0x15D1 |
| 30 | #define TPM_DATA (TPM_ADDR + 1) & 0xff | 31 | |
| 32 | /* These values will be filled after ACPI-call */ | ||
| 33 | static int TPM_INF_DATA = 0; | ||
| 34 | static int TPM_INF_ADDR = 0; | ||
| 31 | 35 | ||
| 32 | /* TPM header definitions */ | 36 | /* TPM header definitions */ |
| 33 | enum infineon_tpm_header { | 37 | enum infineon_tpm_header { |
| @@ -305,9 +309,10 @@ static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count) | |||
| 305 | 309 | ||
| 306 | static void tpm_inf_cancel(struct tpm_chip *chip) | 310 | static void tpm_inf_cancel(struct tpm_chip *chip) |
| 307 | { | 311 | { |
| 308 | /* Nothing yet! | 312 | /* |
| 309 | This has something to do with the internal functions | 313 | Since we are using the legacy mode to communicate |
| 310 | of the TPM. Abort isn't really necessary... | 314 | with the TPM, we have no cancel functions, but have |
| 315 | a workaround for interrupting the TPM through WTX. | ||
| 311 | */ | 316 | */ |
| 312 | } | 317 | } |
| 313 | 318 | ||
| @@ -345,6 +350,32 @@ static struct tpm_vendor_specific tpm_inf = { | |||
| 345 | .miscdev = {.fops = &inf_ops,}, | 350 | .miscdev = {.fops = &inf_ops,}, |
| 346 | }; | 351 | }; |
| 347 | 352 | ||
| 353 | static const struct pnp_device_id tpm_pnp_tbl[] = { | ||
| 354 | /* Infineon TPMs */ | ||
| 355 | {"IFX0101", 0}, | ||
| 356 | {"IFX0102", 0}, | ||
| 357 | {"", 0} | ||
| 358 | }; | ||
| 359 | |||
| 360 | static int __devinit tpm_inf_acpi_probe(struct pnp_dev *dev, | ||
| 361 | const struct pnp_device_id *dev_id) | ||
| 362 | { | ||
| 363 | TPM_INF_ADDR = (pnp_port_start(dev, 0) & 0xff); | ||
| 364 | TPM_INF_DATA = ((TPM_INF_ADDR + 1) & 0xff); | ||
| 365 | tpm_inf.base = pnp_port_start(dev, 1); | ||
| 366 | dev_info(&dev->dev, "Found %s with ID %s\n", | ||
| 367 | dev->name, dev_id->id); | ||
| 368 | if (!((tpm_inf.base >> 8) & 0xff)) | ||
| 369 | tpm_inf.base = 0; | ||
| 370 | return 0; | ||
| 371 | } | ||
| 372 | |||
| 373 | static struct pnp_driver tpm_inf_pnp = { | ||
| 374 | .name = "tpm_inf_pnp", | ||
| 375 | .id_table = tpm_pnp_tbl, | ||
| 376 | .probe = tpm_inf_acpi_probe, | ||
| 377 | }; | ||
| 378 | |||
| 348 | static int __devinit tpm_inf_probe(struct pci_dev *pci_dev, | 379 | static int __devinit tpm_inf_probe(struct pci_dev *pci_dev, |
| 349 | const struct pci_device_id *pci_id) | 380 | const struct pci_device_id *pci_id) |
| 350 | { | 381 | { |
| @@ -353,64 +384,99 @@ static int __devinit tpm_inf_probe(struct pci_dev *pci_dev, | |||
| 353 | int vendorid[2]; | 384 | int vendorid[2]; |
| 354 | int version[2]; | 385 | int version[2]; |
| 355 | int productid[2]; | 386 | int productid[2]; |
| 387 | char chipname[20]; | ||
| 356 | 388 | ||
| 357 | if (pci_enable_device(pci_dev)) | 389 | if (pci_enable_device(pci_dev)) |
| 358 | return -EIO; | 390 | return -EIO; |
| 359 | 391 | ||
| 360 | dev_info(&pci_dev->dev, "LPC-bus found at 0x%x\n", pci_id->device); | 392 | dev_info(&pci_dev->dev, "LPC-bus found at 0x%x\n", pci_id->device); |
| 361 | 393 | ||
| 394 | /* read IO-ports from ACPI */ | ||
| 395 | pnp_register_driver(&tpm_inf_pnp); | ||
| 396 | pnp_unregister_driver(&tpm_inf_pnp); | ||
| 397 | |||
| 398 | /* Make sure, we have received valid config ports */ | ||
| 399 | if (!TPM_INF_ADDR) { | ||
| 400 | pci_disable_device(pci_dev); | ||
| 401 | return -EIO; | ||
| 402 | } | ||
| 403 | |||
| 362 | /* query chip for its vendor, its version number a.s.o. */ | 404 | /* query chip for its vendor, its version number a.s.o. */ |
| 363 | outb(ENABLE_REGISTER_PAIR, TPM_ADDR); | 405 | outb(ENABLE_REGISTER_PAIR, TPM_INF_ADDR); |
| 364 | outb(IDVENL, TPM_ADDR); | 406 | outb(IDVENL, TPM_INF_ADDR); |
| 365 | vendorid[1] = inb(TPM_DATA); | 407 | vendorid[1] = inb(TPM_INF_DATA); |
| 366 | outb(IDVENH, TPM_ADDR); | 408 | outb(IDVENH, TPM_INF_ADDR); |
| 367 | vendorid[0] = inb(TPM_DATA); | 409 | vendorid[0] = inb(TPM_INF_DATA); |
| 368 | outb(IDPDL, TPM_ADDR); | 410 | outb(IDPDL, TPM_INF_ADDR); |
| 369 | productid[1] = inb(TPM_DATA); | 411 | productid[1] = inb(TPM_INF_DATA); |
| 370 | outb(IDPDH, TPM_ADDR); | 412 | outb(IDPDH, TPM_INF_ADDR); |
| 371 | productid[0] = inb(TPM_DATA); | 413 | productid[0] = inb(TPM_INF_DATA); |
| 372 | outb(CHIP_ID1, TPM_ADDR); | 414 | outb(CHIP_ID1, TPM_INF_ADDR); |
| 373 | version[1] = inb(TPM_DATA); | 415 | version[1] = inb(TPM_INF_DATA); |
| 374 | outb(CHIP_ID2, TPM_ADDR); | 416 | outb(CHIP_ID2, TPM_INF_ADDR); |
| 375 | version[0] = inb(TPM_DATA); | 417 | version[0] = inb(TPM_INF_DATA); |
| 376 | 418 | ||
| 377 | if ((vendorid[0] << 8 | vendorid[1]) == (TCPA_INFINEON_DEV_VEN_VALUE)) { | 419 | switch ((productid[0] << 8) | productid[1]) { |
| 378 | 420 | case 6: | |
| 379 | /* read IO-ports from TPM */ | 421 | sprintf(chipname, " (SLD 9630 TT 1.1)"); |
| 380 | outb(IOLIMH, TPM_ADDR); | 422 | break; |
| 381 | ioh = inb(TPM_DATA); | 423 | case 11: |
| 382 | outb(IOLIML, TPM_ADDR); | 424 | sprintf(chipname, " (SLB 9635 TT 1.2)"); |
| 383 | iol = inb(TPM_DATA); | 425 | break; |
| 384 | tpm_inf.base = (ioh << 8) | iol; | 426 | default: |
| 427 | sprintf(chipname, " (unknown chip)"); | ||
| 428 | break; | ||
| 429 | } | ||
| 430 | chipname[19] = 0; | ||
| 431 | |||
| 432 | if ((vendorid[0] << 8 | vendorid[1]) == (TPM_INFINEON_DEV_VEN_VALUE)) { | ||
| 385 | 433 | ||
| 386 | if (tpm_inf.base == 0) { | 434 | if (tpm_inf.base == 0) { |
| 387 | dev_err(&pci_dev->dev, "No IO-ports set!\n"); | 435 | dev_err(&pci_dev->dev, "No IO-ports found!\n"); |
| 388 | pci_disable_device(pci_dev); | 436 | pci_disable_device(pci_dev); |
| 389 | return -ENODEV; | 437 | return -EIO; |
| 438 | } | ||
| 439 | /* configure TPM with IO-ports */ | ||
| 440 | outb(IOLIMH, TPM_INF_ADDR); | ||
| 441 | outb(((tpm_inf.base >> 8) & 0xff), TPM_INF_DATA); | ||
| 442 | outb(IOLIML, TPM_INF_ADDR); | ||
| 443 | outb((tpm_inf.base & 0xff), TPM_INF_DATA); | ||
| 444 | |||
| 445 | /* control if IO-ports are set correctly */ | ||
| 446 | outb(IOLIMH, TPM_INF_ADDR); | ||
| 447 | ioh = inb(TPM_INF_DATA); | ||
| 448 | outb(IOLIML, TPM_INF_ADDR); | ||
| 449 | iol = inb(TPM_INF_DATA); | ||
| 450 | |||
| 451 | if ((ioh << 8 | iol) != tpm_inf.base) { | ||
| 452 | dev_err(&pci_dev->dev, | ||
| 453 | "Could not set IO-ports to %04x\n", | ||
| 454 | tpm_inf.base); | ||
| 455 | pci_disable_device(pci_dev); | ||
| 456 | return -EIO; | ||
| 390 | } | 457 | } |
| 391 | 458 | ||
| 392 | /* activate register */ | 459 | /* activate register */ |
| 393 | outb(TPM_DAR, TPM_ADDR); | 460 | outb(TPM_DAR, TPM_INF_ADDR); |
| 394 | outb(0x01, TPM_DATA); | 461 | outb(0x01, TPM_INF_DATA); |
| 395 | outb(DISABLE_REGISTER_PAIR, TPM_ADDR); | 462 | outb(DISABLE_REGISTER_PAIR, TPM_INF_ADDR); |
| 396 | 463 | ||
| 397 | /* disable RESET, LP and IRQC */ | 464 | /* disable RESET, LP and IRQC */ |
| 398 | outb(RESET_LP_IRQC_DISABLE, tpm_inf.base + CMD); | 465 | outb(RESET_LP_IRQC_DISABLE, tpm_inf.base + CMD); |
| 399 | 466 | ||
| 400 | /* Finally, we're done, print some infos */ | 467 | /* Finally, we're done, print some infos */ |
| 401 | dev_info(&pci_dev->dev, "TPM found: " | 468 | dev_info(&pci_dev->dev, "TPM found: " |
| 469 | "config base 0x%x, " | ||
| 402 | "io base 0x%x, " | 470 | "io base 0x%x, " |
| 403 | "chip version %02x%02x, " | 471 | "chip version %02x%02x, " |
| 404 | "vendor id %x%x (Infineon), " | 472 | "vendor id %x%x (Infineon), " |
| 405 | "product id %02x%02x" | 473 | "product id %02x%02x" |
| 406 | "%s\n", | 474 | "%s\n", |
| 475 | TPM_INF_ADDR, | ||
| 407 | tpm_inf.base, | 476 | tpm_inf.base, |
| 408 | version[0], version[1], | 477 | version[0], version[1], |
| 409 | vendorid[0], vendorid[1], | 478 | vendorid[0], vendorid[1], |
| 410 | productid[0], productid[1], ((productid[0] == 0) | 479 | productid[0], productid[1], chipname); |
| 411 | && (productid[1] == | ||
| 412 | 6)) ? | ||
| 413 | " (SLD 9630 TT 1.1)" : ""); | ||
| 414 | 480 | ||
| 415 | rc = tpm_register_hardware(pci_dev, &tpm_inf); | 481 | rc = tpm_register_hardware(pci_dev, &tpm_inf); |
| 416 | if (rc < 0) { | 482 | if (rc < 0) { |
| @@ -462,6 +528,6 @@ module_init(init_inf); | |||
| 462 | module_exit(cleanup_inf); | 528 | module_exit(cleanup_inf); |
| 463 | 529 | ||
| 464 | MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>"); | 530 | MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>"); |
| 465 | MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT"); | 531 | MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2"); |
| 466 | MODULE_VERSION("1.4"); | 532 | MODULE_VERSION("1.5"); |
| 467 | MODULE_LICENSE("GPL"); | 533 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/char/watchdog/i8xx_tco.c b/drivers/char/watchdog/i8xx_tco.c index f975dab1ddf9..a13395e2c372 100644 --- a/drivers/char/watchdog/i8xx_tco.c +++ b/drivers/char/watchdog/i8xx_tco.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * i8xx_tco 0.07: TCO timer driver for i8xx chipsets | 2 | * i8xx_tco: TCO timer driver for i8xx chipsets |
| 3 | * | 3 | * |
| 4 | * (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved. | 4 | * (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved. |
| 5 | * http://www.kernelconcepts.de | 5 | * http://www.kernelconcepts.de |
| @@ -63,6 +63,9 @@ | |||
| 63 | * 20050128 Wim Van Sebroeck <wim@iguana.be> | 63 | * 20050128 Wim Van Sebroeck <wim@iguana.be> |
| 64 | * 0.07 Added support for the ICH4-M, ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW | 64 | * 0.07 Added support for the ICH4-M, ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW |
| 65 | * chipsets. Also added support for the "undocumented" ICH7 chipset. | 65 | * chipsets. Also added support for the "undocumented" ICH7 chipset. |
| 66 | * 20050807 Wim Van Sebroeck <wim@iguana.be> | ||
| 67 | * 0.08 Make sure that the watchdog is only "armed" when started. | ||
| 68 | * (Kernel Bug 4251) | ||
| 66 | */ | 69 | */ |
| 67 | 70 | ||
| 68 | /* | 71 | /* |
| @@ -87,7 +90,7 @@ | |||
| 87 | #include "i8xx_tco.h" | 90 | #include "i8xx_tco.h" |
| 88 | 91 | ||
| 89 | /* Module and version information */ | 92 | /* Module and version information */ |
| 90 | #define TCO_VERSION "0.07" | 93 | #define TCO_VERSION "0.08" |
| 91 | #define TCO_MODULE_NAME "i8xx TCO timer" | 94 | #define TCO_MODULE_NAME "i8xx TCO timer" |
| 92 | #define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION | 95 | #define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION |
| 93 | #define PFX TCO_MODULE_NAME ": " | 96 | #define PFX TCO_MODULE_NAME ": " |
| @@ -125,10 +128,18 @@ static int tco_timer_start (void) | |||
| 125 | unsigned char val; | 128 | unsigned char val; |
| 126 | 129 | ||
| 127 | spin_lock(&tco_lock); | 130 | spin_lock(&tco_lock); |
| 131 | |||
| 132 | /* disable chipset's NO_REBOOT bit */ | ||
| 133 | pci_read_config_byte (i8xx_tco_pci, 0xd4, &val); | ||
| 134 | val &= 0xfd; | ||
| 135 | pci_write_config_byte (i8xx_tco_pci, 0xd4, val); | ||
| 136 | |||
| 137 | /* Bit 11: TCO Timer Halt -> 0 = The TCO timer is enabled to count */ | ||
| 128 | val = inb (TCO1_CNT + 1); | 138 | val = inb (TCO1_CNT + 1); |
| 129 | val &= 0xf7; | 139 | val &= 0xf7; |
| 130 | outb (val, TCO1_CNT + 1); | 140 | outb (val, TCO1_CNT + 1); |
| 131 | val = inb (TCO1_CNT + 1); | 141 | val = inb (TCO1_CNT + 1); |
| 142 | |||
| 132 | spin_unlock(&tco_lock); | 143 | spin_unlock(&tco_lock); |
| 133 | 144 | ||
| 134 | if (val & 0x08) | 145 | if (val & 0x08) |
| @@ -138,13 +149,20 @@ static int tco_timer_start (void) | |||
| 138 | 149 | ||
| 139 | static int tco_timer_stop (void) | 150 | static int tco_timer_stop (void) |
| 140 | { | 151 | { |
| 141 | unsigned char val; | 152 | unsigned char val, val1; |
| 142 | 153 | ||
| 143 | spin_lock(&tco_lock); | 154 | spin_lock(&tco_lock); |
| 155 | /* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */ | ||
| 144 | val = inb (TCO1_CNT + 1); | 156 | val = inb (TCO1_CNT + 1); |
| 145 | val |= 0x08; | 157 | val |= 0x08; |
| 146 | outb (val, TCO1_CNT + 1); | 158 | outb (val, TCO1_CNT + 1); |
| 147 | val = inb (TCO1_CNT + 1); | 159 | val = inb (TCO1_CNT + 1); |
| 160 | |||
| 161 | /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ | ||
| 162 | pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1); | ||
| 163 | val1 |= 0x02; | ||
| 164 | pci_write_config_byte (i8xx_tco_pci, 0xd4, val1); | ||
| 165 | |||
| 148 | spin_unlock(&tco_lock); | 166 | spin_unlock(&tco_lock); |
| 149 | 167 | ||
| 150 | if ((val & 0x08) == 0) | 168 | if ((val & 0x08) == 0) |
| @@ -155,6 +173,7 @@ static int tco_timer_stop (void) | |||
| 155 | static int tco_timer_keepalive (void) | 173 | static int tco_timer_keepalive (void) |
| 156 | { | 174 | { |
| 157 | spin_lock(&tco_lock); | 175 | spin_lock(&tco_lock); |
| 176 | /* Reload the timer by writing to the TCO Timer Reload register */ | ||
| 158 | outb (0x01, TCO1_RLD); | 177 | outb (0x01, TCO1_RLD); |
| 159 | spin_unlock(&tco_lock); | 178 | spin_unlock(&tco_lock); |
| 160 | return 0; | 179 | return 0; |
| @@ -417,9 +436,8 @@ static unsigned char __init i8xx_tco_getdevice (void) | |||
| 417 | printk (KERN_ERR PFX "failed to get TCOBASE address\n"); | 436 | printk (KERN_ERR PFX "failed to get TCOBASE address\n"); |
| 418 | return 0; | 437 | return 0; |
| 419 | } | 438 | } |
| 420 | /* | 439 | |
| 421 | * Check chipset's NO_REBOOT bit | 440 | /* Check chipset's NO_REBOOT bit */ |
| 422 | */ | ||
| 423 | pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1); | 441 | pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1); |
| 424 | if (val1 & 0x02) { | 442 | if (val1 & 0x02) { |
| 425 | val1 &= 0xfd; | 443 | val1 &= 0xfd; |
| @@ -430,6 +448,10 @@ static unsigned char __init i8xx_tco_getdevice (void) | |||
| 430 | return 0; /* Cannot reset NO_REBOOT bit */ | 448 | return 0; /* Cannot reset NO_REBOOT bit */ |
| 431 | } | 449 | } |
| 432 | } | 450 | } |
| 451 | /* Disable reboots untill the watchdog starts */ | ||
| 452 | val1 |= 0x02; | ||
| 453 | pci_write_config_byte (i8xx_tco_pci, 0xd4, val1); | ||
| 454 | |||
| 433 | /* Set the TCO_EN bit in SMI_EN register */ | 455 | /* Set the TCO_EN bit in SMI_EN register */ |
| 434 | if (!request_region (SMI_EN + 1, 1, "i8xx TCO")) { | 456 | if (!request_region (SMI_EN + 1, 1, "i8xx TCO")) { |
| 435 | printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", | 457 | printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", |
| @@ -505,17 +527,10 @@ out: | |||
| 505 | 527 | ||
| 506 | static void __exit watchdog_cleanup (void) | 528 | static void __exit watchdog_cleanup (void) |
| 507 | { | 529 | { |
| 508 | u8 val; | ||
| 509 | |||
| 510 | /* Stop the timer before we leave */ | 530 | /* Stop the timer before we leave */ |
| 511 | if (!nowayout) | 531 | if (!nowayout) |
| 512 | tco_timer_stop (); | 532 | tco_timer_stop (); |
| 513 | 533 | ||
| 514 | /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ | ||
| 515 | pci_read_config_byte (i8xx_tco_pci, 0xd4, &val); | ||
| 516 | val |= 0x02; | ||
| 517 | pci_write_config_byte (i8xx_tco_pci, 0xd4, val); | ||
| 518 | |||
| 519 | /* Deregister */ | 534 | /* Deregister */ |
| 520 | misc_deregister (&i8xx_tco_miscdev); | 535 | misc_deregister (&i8xx_tco_miscdev); |
| 521 | unregister_reboot_notifier(&i8xx_tco_notifier); | 536 | unregister_reboot_notifier(&i8xx_tco_notifier); |
diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c index 1b2132617dc3..fb88b4041dca 100644 --- a/drivers/char/watchdog/sa1100_wdt.c +++ b/drivers/char/watchdog/sa1100_wdt.c | |||
| @@ -36,13 +36,10 @@ | |||
| 36 | #include <asm/uaccess.h> | 36 | #include <asm/uaccess.h> |
| 37 | 37 | ||
| 38 | #define OSCR_FREQ CLOCK_TICK_RATE | 38 | #define OSCR_FREQ CLOCK_TICK_RATE |
| 39 | #define SA1100_CLOSE_MAGIC (0x5afc4453) | ||
| 40 | 39 | ||
| 41 | static unsigned long sa1100wdt_users; | 40 | static unsigned long sa1100wdt_users; |
| 42 | static int expect_close; | ||
| 43 | static int pre_margin; | 41 | static int pre_margin; |
| 44 | static int boot_status; | 42 | static int boot_status; |
| 45 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
| 46 | 43 | ||
| 47 | /* | 44 | /* |
| 48 | * Allow only one person to hold it open | 45 | * Allow only one person to hold it open |
| @@ -62,55 +59,33 @@ static int sa1100dog_open(struct inode *inode, struct file *file) | |||
| 62 | } | 59 | } |
| 63 | 60 | ||
| 64 | /* | 61 | /* |
| 65 | * Shut off the timer. | 62 | * The watchdog cannot be disabled. |
| 66 | * Lock it in if it's a module and we defined ...NOWAYOUT | 63 | * |
| 67 | * Oddly, the watchdog can only be enabled, but we can turn off | 64 | * Previous comments suggested that turning off the interrupt by |
| 68 | * the interrupt, which appears to prevent the watchdog timing out. | 65 | * clearing OIER[E3] would prevent the watchdog timing out but this |
| 66 | * does not appear to be true (at least on the PXA255). | ||
| 69 | */ | 67 | */ |
| 70 | static int sa1100dog_release(struct inode *inode, struct file *file) | 68 | static int sa1100dog_release(struct inode *inode, struct file *file) |
| 71 | { | 69 | { |
| 72 | OSMR3 = OSCR + pre_margin; | 70 | printk(KERN_CRIT "WATCHDOG: Device closed - timer will not stop\n"); |
| 73 | |||
| 74 | if (expect_close == SA1100_CLOSE_MAGIC) { | ||
| 75 | OIER &= ~OIER_E3; | ||
| 76 | } else { | ||
| 77 | printk(KERN_CRIT "WATCHDOG: WDT device closed unexpectedly. WDT will not stop!\n"); | ||
| 78 | } | ||
| 79 | 71 | ||
| 80 | clear_bit(1, &sa1100wdt_users); | 72 | clear_bit(1, &sa1100wdt_users); |
| 81 | expect_close = 0; | ||
| 82 | 73 | ||
| 83 | return 0; | 74 | return 0; |
| 84 | } | 75 | } |
| 85 | 76 | ||
| 86 | static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos) | 77 | static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos) |
| 87 | { | 78 | { |
| 88 | if (len) { | 79 | if (len) |
| 89 | if (!nowayout) { | ||
| 90 | size_t i; | ||
| 91 | |||
| 92 | expect_close = 0; | ||
| 93 | |||
| 94 | for (i = 0; i != len; i++) { | ||
| 95 | char c; | ||
| 96 | |||
| 97 | if (get_user(c, data + i)) | ||
| 98 | return -EFAULT; | ||
| 99 | if (c == 'V') | ||
| 100 | expect_close = SA1100_CLOSE_MAGIC; | ||
| 101 | } | ||
| 102 | } | ||
| 103 | /* Refresh OSMR3 timer. */ | 80 | /* Refresh OSMR3 timer. */ |
| 104 | OSMR3 = OSCR + pre_margin; | 81 | OSMR3 = OSCR + pre_margin; |
| 105 | } | ||
| 106 | 82 | ||
| 107 | return len; | 83 | return len; |
| 108 | } | 84 | } |
| 109 | 85 | ||
| 110 | static struct watchdog_info ident = { | 86 | static struct watchdog_info ident = { |
| 111 | .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | | 87 | .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, |
| 112 | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, | 88 | .identity = "SA1100/PXA255 Watchdog", |
| 113 | .identity = "SA1100 Watchdog", | ||
| 114 | }; | 89 | }; |
| 115 | 90 | ||
| 116 | static int sa1100dog_ioctl(struct inode *inode, struct file *file, | 91 | static int sa1100dog_ioctl(struct inode *inode, struct file *file, |
| @@ -172,7 +147,7 @@ static struct file_operations sa1100dog_fops = | |||
| 172 | static struct miscdevice sa1100dog_miscdev = | 147 | static struct miscdevice sa1100dog_miscdev = |
| 173 | { | 148 | { |
| 174 | .minor = WATCHDOG_MINOR, | 149 | .minor = WATCHDOG_MINOR, |
| 175 | .name = "SA1100/PXA2xx watchdog", | 150 | .name = "watchdog", |
| 176 | .fops = &sa1100dog_fops, | 151 | .fops = &sa1100dog_fops, |
| 177 | }; | 152 | }; |
| 178 | 153 | ||
| @@ -194,7 +169,6 @@ static int __init sa1100dog_init(void) | |||
| 194 | if (ret == 0) | 169 | if (ret == 0) |
| 195 | printk("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n", | 170 | printk("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n", |
| 196 | margin); | 171 | margin); |
| 197 | |||
| 198 | return ret; | 172 | return ret; |
| 199 | } | 173 | } |
| 200 | 174 | ||
| @@ -212,8 +186,5 @@ MODULE_DESCRIPTION("SA1100/PXA2xx Watchdog"); | |||
| 212 | module_param(margin, int, 0); | 186 | module_param(margin, int, 0); |
| 213 | MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)"); | 187 | MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)"); |
| 214 | 188 | ||
| 215 | module_param(nowayout, int, 0); | ||
| 216 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); | ||
| 217 | |||
| 218 | MODULE_LICENSE("GPL"); | 189 | MODULE_LICENSE("GPL"); |
| 219 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | 190 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); |
diff --git a/drivers/fc4/fc.c b/drivers/fc4/fc.c index 5d961f5e0ca0..e4710d1d1f9d 100644 --- a/drivers/fc4/fc.c +++ b/drivers/fc4/fc.c | |||
| @@ -1004,8 +1004,8 @@ int fcp_scsi_dev_reset(Scsi_Cmnd *SCpnt) | |||
| 1004 | return FAILED; | 1004 | return FAILED; |
| 1005 | } | 1005 | } |
| 1006 | fc->rst_pkt->eh_state = SCSI_STATE_UNUSED; | 1006 | fc->rst_pkt->eh_state = SCSI_STATE_UNUSED; |
| 1007 | return SUCCESS; | ||
| 1008 | #endif | 1007 | #endif |
| 1008 | return SUCCESS; | ||
| 1009 | } | 1009 | } |
| 1010 | 1010 | ||
| 1011 | static int __fcp_scsi_host_reset(Scsi_Cmnd *SCpnt) | 1011 | static int __fcp_scsi_host_reset(Scsi_Cmnd *SCpnt) |
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index 04adde62a003..9ad3e9262e8a 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c | |||
| @@ -382,100 +382,6 @@ static void __exit fsl_i2c_exit(void) | |||
| 382 | module_init(fsl_i2c_init); | 382 | module_init(fsl_i2c_init); |
| 383 | module_exit(fsl_i2c_exit); | 383 | module_exit(fsl_i2c_exit); |
| 384 | 384 | ||
| 385 | static int fsl_i2c_probe(struct device *device) | ||
| 386 | { | ||
| 387 | int result = 0; | ||
| 388 | struct mpc_i2c *i2c; | ||
| 389 | struct platform_device *pdev = to_platform_device(device); | ||
| 390 | struct fsl_i2c_platform_data *pdata; | ||
| 391 | struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 392 | |||
| 393 | pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data; | ||
| 394 | |||
| 395 | if (!(i2c = kmalloc(sizeof(*i2c), GFP_KERNEL))) { | ||
| 396 | return -ENOMEM; | ||
| 397 | } | ||
| 398 | memset(i2c, 0, sizeof(*i2c)); | ||
| 399 | |||
| 400 | i2c->irq = platform_get_irq(pdev, 0); | ||
| 401 | i2c->flags = pdata->device_flags; | ||
| 402 | init_waitqueue_head(&i2c->queue); | ||
| 403 | |||
| 404 | i2c->base = ioremap((phys_addr_t)r->start, MPC_I2C_REGION); | ||
| 405 | |||
| 406 | if (!i2c->base) { | ||
| 407 | printk(KERN_ERR "i2c-mpc - failed to map controller\n"); | ||
| 408 | result = -ENOMEM; | ||
| 409 | goto fail_map; | ||
| 410 | } | ||
| 411 | |||
| 412 | if (i2c->irq != 0) | ||
| 413 | if ((result = request_irq(i2c->irq, mpc_i2c_isr, | ||
| 414 | SA_SHIRQ, "i2c-mpc", i2c)) < 0) { | ||
| 415 | printk(KERN_ERR | ||
| 416 | "i2c-mpc - failed to attach interrupt\n"); | ||
| 417 | goto fail_irq; | ||
| 418 | } | ||
| 419 | |||
| 420 | mpc_i2c_setclock(i2c); | ||
| 421 | dev_set_drvdata(device, i2c); | ||
| 422 | |||
| 423 | i2c->adap = mpc_ops; | ||
| 424 | i2c_set_adapdata(&i2c->adap, i2c); | ||
| 425 | i2c->adap.dev.parent = &pdev->dev; | ||
| 426 | if ((result = i2c_add_adapter(&i2c->adap)) < 0) { | ||
| 427 | printk(KERN_ERR "i2c-mpc - failed to add adapter\n"); | ||
| 428 | goto fail_add; | ||
| 429 | } | ||
| 430 | |||
| 431 | return result; | ||
| 432 | |||
| 433 | fail_add: | ||
| 434 | if (i2c->irq != 0) | ||
| 435 | free_irq(i2c->irq, NULL); | ||
| 436 | fail_irq: | ||
| 437 | iounmap(i2c->base); | ||
| 438 | fail_map: | ||
| 439 | kfree(i2c); | ||
| 440 | return result; | ||
| 441 | }; | ||
| 442 | |||
| 443 | static int fsl_i2c_remove(struct device *device) | ||
| 444 | { | ||
| 445 | struct mpc_i2c *i2c = dev_get_drvdata(device); | ||
| 446 | |||
| 447 | i2c_del_adapter(&i2c->adap); | ||
| 448 | dev_set_drvdata(device, NULL); | ||
| 449 | |||
| 450 | if (i2c->irq != 0) | ||
| 451 | free_irq(i2c->irq, i2c); | ||
| 452 | |||
| 453 | iounmap(i2c->base); | ||
| 454 | kfree(i2c); | ||
| 455 | return 0; | ||
| 456 | }; | ||
| 457 | |||
| 458 | /* Structure for a device driver */ | ||
| 459 | static struct device_driver fsl_i2c_driver = { | ||
| 460 | .name = "fsl-i2c", | ||
| 461 | .bus = &platform_bus_type, | ||
| 462 | .probe = fsl_i2c_probe, | ||
| 463 | .remove = fsl_i2c_remove, | ||
| 464 | }; | ||
| 465 | |||
| 466 | static int __init fsl_i2c_init(void) | ||
| 467 | { | ||
| 468 | return driver_register(&fsl_i2c_driver); | ||
| 469 | } | ||
| 470 | |||
| 471 | static void __exit fsl_i2c_exit(void) | ||
| 472 | { | ||
| 473 | driver_unregister(&fsl_i2c_driver); | ||
| 474 | } | ||
| 475 | |||
| 476 | module_init(fsl_i2c_init); | ||
| 477 | module_exit(fsl_i2c_exit); | ||
| 478 | |||
| 479 | MODULE_AUTHOR("Adrian Cox <adrian@humboldt.co.uk>"); | 385 | MODULE_AUTHOR("Adrian Cox <adrian@humboldt.co.uk>"); |
| 480 | MODULE_DESCRIPTION | 386 | MODULE_DESCRIPTION |
| 481 | ("I2C-Bus adapter for MPC107 bridge and MPC824x/85xx/52xx processors"); | 387 | ("I2C-Bus adapter for MPC107 bridge and MPC824x/85xx/52xx processors"); |
diff --git a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c index 1c99536b673b..fa503ed9f86d 100644 --- a/drivers/i2c/busses/i2c-sibyte.c +++ b/drivers/i2c/busses/i2c-sibyte.c | |||
| @@ -23,8 +23,8 @@ | |||
| 23 | #include <asm/sibyte/sb1250_smbus.h> | 23 | #include <asm/sibyte/sb1250_smbus.h> |
| 24 | 24 | ||
| 25 | static struct i2c_algo_sibyte_data sibyte_board_data[2] = { | 25 | static struct i2c_algo_sibyte_data sibyte_board_data[2] = { |
| 26 | { NULL, 0, (void *) (KSEG1+A_SMB_BASE(0)) }, | 26 | { NULL, 0, (void *) (CKSEG1+A_SMB_BASE(0)) }, |
| 27 | { NULL, 1, (void *) (KSEG1+A_SMB_BASE(1)) } | 27 | { NULL, 1, (void *) (CKSEG1+A_SMB_BASE(1)) } |
| 28 | }; | 28 | }; |
| 29 | 29 | ||
| 30 | static struct i2c_adapter sibyte_board_adapter[2] = { | 30 | static struct i2c_adapter sibyte_board_adapter[2] = { |
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index f9c1acb4ed6a..c9d3a00a3c0c 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c | |||
| @@ -1220,7 +1220,7 @@ static int ide_disk_probe(struct device *dev) | |||
| 1220 | goto failed; | 1220 | goto failed; |
| 1221 | 1221 | ||
| 1222 | g = alloc_disk_node(1 << PARTN_BITS, | 1222 | g = alloc_disk_node(1 << PARTN_BITS, |
| 1223 | pcibus_to_node(drive->hwif->pci_dev->bus)); | 1223 | hwif_to_node(drive->hwif)); |
| 1224 | if (!g) | 1224 | if (!g) |
| 1225 | goto out_free_idkp; | 1225 | goto out_free_idkp; |
| 1226 | 1226 | ||
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 7df85af75371..c1128ae5cd2f 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c | |||
| @@ -978,8 +978,7 @@ static int ide_init_queue(ide_drive_t *drive) | |||
| 978 | * do not. | 978 | * do not. |
| 979 | */ | 979 | */ |
| 980 | 980 | ||
| 981 | q = blk_init_queue_node(do_ide_request, &ide_lock, | 981 | q = blk_init_queue_node(do_ide_request, &ide_lock, hwif_to_node(hwif)); |
| 982 | pcibus_to_node(drive->hwif->pci_dev->bus)); | ||
| 983 | if (!q) | 982 | if (!q) |
| 984 | return 1; | 983 | return 1; |
| 985 | 984 | ||
| @@ -1048,6 +1047,8 @@ static int init_irq (ide_hwif_t *hwif) | |||
| 1048 | 1047 | ||
| 1049 | BUG_ON(in_interrupt()); | 1048 | BUG_ON(in_interrupt()); |
| 1050 | BUG_ON(irqs_disabled()); | 1049 | BUG_ON(irqs_disabled()); |
| 1050 | BUG_ON(hwif == NULL); | ||
| 1051 | |||
| 1051 | down(&ide_cfg_sem); | 1052 | down(&ide_cfg_sem); |
| 1052 | hwif->hwgroup = NULL; | 1053 | hwif->hwgroup = NULL; |
| 1053 | #if MAX_HWIFS > 1 | 1054 | #if MAX_HWIFS > 1 |
| @@ -1097,7 +1098,7 @@ static int init_irq (ide_hwif_t *hwif) | |||
| 1097 | spin_unlock_irq(&ide_lock); | 1098 | spin_unlock_irq(&ide_lock); |
| 1098 | } else { | 1099 | } else { |
| 1099 | hwgroup = kmalloc_node(sizeof(ide_hwgroup_t), GFP_KERNEL, | 1100 | hwgroup = kmalloc_node(sizeof(ide_hwgroup_t), GFP_KERNEL, |
| 1100 | pcibus_to_node(hwif->drives[0].hwif->pci_dev->bus)); | 1101 | hwif_to_node(hwif->drives[0].hwif)); |
| 1101 | if (!hwgroup) | 1102 | if (!hwgroup) |
| 1102 | goto out_up; | 1103 | goto out_up; |
| 1103 | 1104 | ||
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index 03747439ac9c..f1d1ec4e9677 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c | |||
| @@ -508,5 +508,5 @@ static void __exit exit_ide_cs(void) | |||
| 508 | BUG_ON(dev_list != NULL); | 508 | BUG_ON(dev_list != NULL); |
| 509 | } | 509 | } |
| 510 | 510 | ||
| 511 | module_init(init_ide_cs); | 511 | late_initcall(init_ide_cs); |
| 512 | module_exit(exit_ide_cs); | 512 | module_exit(exit_ide_cs); |
diff --git a/drivers/infiniband/include/ib_cm.h b/drivers/infiniband/include/ib_cm.h index e5d74a730a70..da650115e79a 100644 --- a/drivers/infiniband/include/ib_cm.h +++ b/drivers/infiniband/include/ib_cm.h | |||
| @@ -169,7 +169,8 @@ enum ib_cm_rej_reason { | |||
| 169 | IB_CM_REJ_INVALID_ALT_TRAFFIC_CLASS = __constant_htons(21), | 169 | IB_CM_REJ_INVALID_ALT_TRAFFIC_CLASS = __constant_htons(21), |
| 170 | IB_CM_REJ_INVALID_ALT_HOP_LIMIT = __constant_htons(22), | 170 | IB_CM_REJ_INVALID_ALT_HOP_LIMIT = __constant_htons(22), |
| 171 | IB_CM_REJ_INVALID_ALT_PACKET_RATE = __constant_htons(23), | 171 | IB_CM_REJ_INVALID_ALT_PACKET_RATE = __constant_htons(23), |
| 172 | IB_CM_REJ_PORT_REDIRECT = __constant_htons(24), | 172 | IB_CM_REJ_PORT_CM_REDIRECT = __constant_htons(24), |
| 173 | IB_CM_REJ_PORT_REDIRECT = __constant_htons(25), | ||
| 173 | IB_CM_REJ_INVALID_MTU = __constant_htons(26), | 174 | IB_CM_REJ_INVALID_MTU = __constant_htons(26), |
| 174 | IB_CM_REJ_INSUFFICIENT_RESP_RESOURCES = __constant_htons(27), | 175 | IB_CM_REJ_INSUFFICIENT_RESP_RESOURCES = __constant_htons(27), |
| 175 | IB_CM_REJ_CONSUMER_DEFINED = __constant_htons(28), | 176 | IB_CM_REJ_CONSUMER_DEFINED = __constant_htons(28), |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 6f60abbaebd5..fa00816a3cf7 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
| @@ -600,9 +600,10 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 600 | 600 | ||
| 601 | ipoib_mcast_send(dev, (union ib_gid *) (phdr->hwaddr + 4), skb); | 601 | ipoib_mcast_send(dev, (union ib_gid *) (phdr->hwaddr + 4), skb); |
| 602 | } else { | 602 | } else { |
| 603 | /* unicast GID -- should be ARP reply */ | 603 | /* unicast GID -- should be ARP or RARP reply */ |
| 604 | 604 | ||
| 605 | if (be16_to_cpup((u16 *) skb->data) != ETH_P_ARP) { | 605 | if ((be16_to_cpup((__be16 *) skb->data) != ETH_P_ARP) && |
| 606 | (be16_to_cpup((__be16 *) skb->data) != ETH_P_RARP)) { | ||
| 606 | ipoib_warn(priv, "Unicast, no %s: type %04x, QPN %06x " | 607 | ipoib_warn(priv, "Unicast, no %s: type %04x, QPN %06x " |
| 607 | IPOIB_GID_FMT "\n", | 608 | IPOIB_GID_FMT "\n", |
| 608 | skb->dst ? "neigh" : "dst", | 609 | skb->dst ? "neigh" : "dst", |
diff --git a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c index 1ab5f2dc8a2a..70f051894a3c 100644 --- a/drivers/input/gameport/ns558.c +++ b/drivers/input/gameport/ns558.c | |||
| @@ -275,9 +275,9 @@ static int __init ns558_init(void) | |||
| 275 | 275 | ||
| 276 | static void __exit ns558_exit(void) | 276 | static void __exit ns558_exit(void) |
| 277 | { | 277 | { |
| 278 | struct ns558 *ns558; | 278 | struct ns558 *ns558, *safe; |
| 279 | 279 | ||
| 280 | list_for_each_entry(ns558, &ns558_list, node) { | 280 | list_for_each_entry_safe(ns558, safe, &ns558_list, node) { |
| 281 | gameport_unregister_port(ns558->gameport); | 281 | gameport_unregister_port(ns558->gameport); |
| 282 | release_region(ns558->io & ~(ns558->size - 1), ns558->size); | 282 | release_region(ns558->io & ~(ns558->size - 1), ns558->size); |
| 283 | kfree(ns558); | 283 | kfree(ns558); |
diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c index e0d1b01cc74c..386df71eee74 100644 --- a/drivers/isdn/icn/icn.c +++ b/drivers/isdn/icn/icn.c | |||
| @@ -1650,7 +1650,7 @@ static void __exit icn_exit(void) | |||
| 1650 | { | 1650 | { |
| 1651 | isdn_ctrl cmd; | 1651 | isdn_ctrl cmd; |
| 1652 | icn_card *card = cards; | 1652 | icn_card *card = cards; |
| 1653 | icn_card *last; | 1653 | icn_card *last, *tmpcard; |
| 1654 | int i; | 1654 | int i; |
| 1655 | unsigned long flags; | 1655 | unsigned long flags; |
| 1656 | 1656 | ||
| @@ -1670,8 +1670,9 @@ static void __exit icn_exit(void) | |||
| 1670 | for (i = 0; i < ICN_BCH; i++) | 1670 | for (i = 0; i < ICN_BCH; i++) |
| 1671 | icn_free_queue(card, i); | 1671 | icn_free_queue(card, i); |
| 1672 | } | 1672 | } |
| 1673 | card = card->next; | 1673 | tmpcard = card->next; |
| 1674 | spin_unlock_irqrestore(&card->lock, flags); | 1674 | spin_unlock_irqrestore(&card->lock, flags); |
| 1675 | card = tmpcard; | ||
| 1675 | } | 1676 | } |
| 1676 | card = cards; | 1677 | card = cards; |
| 1677 | cards = NULL; | 1678 | cards = NULL; |
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 70bca955e0de..41df4cda66e2 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c | |||
| @@ -818,8 +818,7 @@ int bitmap_unplug(struct bitmap *bitmap) | |||
| 818 | return 0; | 818 | return 0; |
| 819 | } | 819 | } |
| 820 | 820 | ||
| 821 | static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, | 821 | static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset); |
| 822 | unsigned long sectors, int in_sync); | ||
| 823 | /* * bitmap_init_from_disk -- called at bitmap_create time to initialize | 822 | /* * bitmap_init_from_disk -- called at bitmap_create time to initialize |
| 824 | * the in-memory bitmap from the on-disk bitmap -- also, sets up the | 823 | * the in-memory bitmap from the on-disk bitmap -- also, sets up the |
| 825 | * memory mapping of the bitmap file | 824 | * memory mapping of the bitmap file |
| @@ -828,7 +827,7 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, | |||
| 828 | * previously kicked from the array, we mark all the bits as | 827 | * previously kicked from the array, we mark all the bits as |
| 829 | * 1's in order to cause a full resync. | 828 | * 1's in order to cause a full resync. |
| 830 | */ | 829 | */ |
| 831 | static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync) | 830 | static int bitmap_init_from_disk(struct bitmap *bitmap) |
| 832 | { | 831 | { |
| 833 | unsigned long i, chunks, index, oldindex, bit; | 832 | unsigned long i, chunks, index, oldindex, bit; |
| 834 | struct page *page = NULL, *oldpage = NULL; | 833 | struct page *page = NULL, *oldpage = NULL; |
| @@ -929,8 +928,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync) | |||
| 929 | } | 928 | } |
| 930 | if (test_bit(bit, page_address(page))) { | 929 | if (test_bit(bit, page_address(page))) { |
| 931 | /* if the disk bit is set, set the memory bit */ | 930 | /* if the disk bit is set, set the memory bit */ |
| 932 | bitmap_set_memory_bits(bitmap, | 931 | bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap)); |
| 933 | i << CHUNK_BLOCK_SHIFT(bitmap), 1, in_sync); | ||
| 934 | bit_cnt++; | 932 | bit_cnt++; |
| 935 | } | 933 | } |
| 936 | } | 934 | } |
| @@ -1426,35 +1424,53 @@ void bitmap_close_sync(struct bitmap *bitmap) | |||
| 1426 | } | 1424 | } |
| 1427 | } | 1425 | } |
| 1428 | 1426 | ||
| 1429 | static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, | 1427 | static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset) |
| 1430 | unsigned long sectors, int in_sync) | ||
| 1431 | { | 1428 | { |
| 1432 | /* For each chunk covered by any of these sectors, set the | 1429 | /* For each chunk covered by any of these sectors, set the |
| 1433 | * counter to 1 and set resync_needed unless in_sync. They should all | 1430 | * counter to 1 and set resync_needed. They should all |
| 1434 | * be 0 at this point | 1431 | * be 0 at this point |
| 1435 | */ | 1432 | */ |
| 1436 | while (sectors) { | 1433 | |
| 1437 | int secs; | 1434 | int secs; |
| 1438 | bitmap_counter_t *bmc; | 1435 | bitmap_counter_t *bmc; |
| 1439 | spin_lock_irq(&bitmap->lock); | 1436 | spin_lock_irq(&bitmap->lock); |
| 1440 | bmc = bitmap_get_counter(bitmap, offset, &secs, 1); | 1437 | bmc = bitmap_get_counter(bitmap, offset, &secs, 1); |
| 1441 | if (!bmc) { | 1438 | if (!bmc) { |
| 1442 | spin_unlock_irq(&bitmap->lock); | ||
| 1443 | return; | ||
| 1444 | } | ||
| 1445 | if (! *bmc) { | ||
| 1446 | struct page *page; | ||
| 1447 | *bmc = 1 | (in_sync? 0 : NEEDED_MASK); | ||
| 1448 | bitmap_count_page(bitmap, offset, 1); | ||
| 1449 | page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)); | ||
| 1450 | set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN); | ||
| 1451 | } | ||
| 1452 | spin_unlock_irq(&bitmap->lock); | 1439 | spin_unlock_irq(&bitmap->lock); |
| 1453 | if (sectors > secs) | 1440 | return; |
| 1454 | sectors -= secs; | 1441 | } |
| 1455 | else | 1442 | if (! *bmc) { |
| 1456 | sectors = 0; | 1443 | struct page *page; |
| 1444 | *bmc = 1 | NEEDED_MASK; | ||
| 1445 | bitmap_count_page(bitmap, offset, 1); | ||
| 1446 | page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)); | ||
| 1447 | set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN); | ||
| 1457 | } | 1448 | } |
| 1449 | spin_unlock_irq(&bitmap->lock); | ||
| 1450 | |||
| 1451 | } | ||
| 1452 | |||
| 1453 | /* | ||
| 1454 | * flush out any pending updates | ||
| 1455 | */ | ||
| 1456 | void bitmap_flush(mddev_t *mddev) | ||
| 1457 | { | ||
| 1458 | struct bitmap *bitmap = mddev->bitmap; | ||
| 1459 | int sleep; | ||
| 1460 | |||
| 1461 | if (!bitmap) /* there was no bitmap */ | ||
| 1462 | return; | ||
| 1463 | |||
| 1464 | /* run the daemon_work three time to ensure everything is flushed | ||
| 1465 | * that can be | ||
| 1466 | */ | ||
| 1467 | sleep = bitmap->daemon_sleep; | ||
| 1468 | bitmap->daemon_sleep = 0; | ||
| 1469 | bitmap_daemon_work(bitmap); | ||
| 1470 | bitmap_daemon_work(bitmap); | ||
| 1471 | bitmap_daemon_work(bitmap); | ||
| 1472 | bitmap->daemon_sleep = sleep; | ||
| 1473 | bitmap_update_sb(bitmap); | ||
| 1458 | } | 1474 | } |
| 1459 | 1475 | ||
| 1460 | /* | 1476 | /* |
| @@ -1565,7 +1581,8 @@ int bitmap_create(mddev_t *mddev) | |||
| 1565 | 1581 | ||
| 1566 | /* now that we have some pages available, initialize the in-memory | 1582 | /* now that we have some pages available, initialize the in-memory |
| 1567 | * bitmap from the on-disk bitmap */ | 1583 | * bitmap from the on-disk bitmap */ |
| 1568 | err = bitmap_init_from_disk(bitmap, mddev->recovery_cp == MaxSector); | 1584 | err = bitmap_init_from_disk(bitmap); |
| 1585 | |||
| 1569 | if (err) | 1586 | if (err) |
| 1570 | return err; | 1587 | return err; |
| 1571 | 1588 | ||
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 12031c9d3f1e..b08df8b9b2ca 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c | |||
| @@ -1230,7 +1230,7 @@ static int __init dm_mirror_init(void) | |||
| 1230 | if (r) | 1230 | if (r) |
| 1231 | return r; | 1231 | return r; |
| 1232 | 1232 | ||
| 1233 | _kmirrord_wq = create_workqueue("kmirrord"); | 1233 | _kmirrord_wq = create_singlethread_workqueue("kmirrord"); |
| 1234 | if (!_kmirrord_wq) { | 1234 | if (!_kmirrord_wq) { |
| 1235 | DMERR("couldn't start kmirrord"); | 1235 | DMERR("couldn't start kmirrord"); |
| 1236 | dm_dirty_log_exit(); | 1236 | dm_dirty_log_exit(); |
diff --git a/drivers/md/md.c b/drivers/md/md.c index 6580e0fa4a47..480f658db6f2 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
| @@ -1798,6 +1798,8 @@ static int do_md_stop(mddev_t * mddev, int ro) | |||
| 1798 | goto out; | 1798 | goto out; |
| 1799 | mddev->ro = 1; | 1799 | mddev->ro = 1; |
| 1800 | } else { | 1800 | } else { |
| 1801 | bitmap_flush(mddev); | ||
| 1802 | wait_event(mddev->sb_wait, atomic_read(&mddev->pending_writes)==0); | ||
| 1801 | if (mddev->ro) | 1803 | if (mddev->ro) |
| 1802 | set_disk_ro(disk, 0); | 1804 | set_disk_ro(disk, 0); |
| 1803 | blk_queue_make_request(mddev->queue, md_fail_request); | 1805 | blk_queue_make_request(mddev->queue, md_fail_request); |
| @@ -3484,7 +3486,6 @@ static void md_do_sync(mddev_t *mddev) | |||
| 3484 | goto skip; | 3486 | goto skip; |
| 3485 | } | 3487 | } |
| 3486 | ITERATE_MDDEV(mddev2,tmp) { | 3488 | ITERATE_MDDEV(mddev2,tmp) { |
| 3487 | printk("."); | ||
| 3488 | if (mddev2 == mddev) | 3489 | if (mddev2 == mddev) |
| 3489 | continue; | 3490 | continue; |
| 3490 | if (mddev2->curr_resync && | 3491 | if (mddev2->curr_resync && |
| @@ -4007,3 +4008,4 @@ EXPORT_SYMBOL(md_wakeup_thread); | |||
| 4007 | EXPORT_SYMBOL(md_print_devices); | 4008 | EXPORT_SYMBOL(md_print_devices); |
| 4008 | EXPORT_SYMBOL(md_check_recovery); | 4009 | EXPORT_SYMBOL(md_check_recovery); |
| 4009 | MODULE_LICENSE("GPL"); | 4010 | MODULE_LICENSE("GPL"); |
| 4011 | MODULE_ALIAS("md"); | ||
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index d3a64a04a6d8..51d9645ed09c 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
| @@ -893,7 +893,6 @@ static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error) | |||
| 893 | if (!uptodate) { | 893 | if (!uptodate) { |
| 894 | md_error(r1_bio->mddev, | 894 | md_error(r1_bio->mddev, |
| 895 | conf->mirrors[r1_bio->read_disk].rdev); | 895 | conf->mirrors[r1_bio->read_disk].rdev); |
| 896 | set_bit(R1BIO_Degraded, &r1_bio->state); | ||
| 897 | } else | 896 | } else |
| 898 | set_bit(R1BIO_Uptodate, &r1_bio->state); | 897 | set_bit(R1BIO_Uptodate, &r1_bio->state); |
| 899 | rdev_dec_pending(conf->mirrors[r1_bio->read_disk].rdev, conf->mddev); | 898 | rdev_dec_pending(conf->mirrors[r1_bio->read_disk].rdev, conf->mddev); |
| @@ -918,10 +917,9 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error) | |||
| 918 | mirror = i; | 917 | mirror = i; |
| 919 | break; | 918 | break; |
| 920 | } | 919 | } |
| 921 | if (!uptodate) { | 920 | if (!uptodate) |
| 922 | md_error(mddev, conf->mirrors[mirror].rdev); | 921 | md_error(mddev, conf->mirrors[mirror].rdev); |
| 923 | set_bit(R1BIO_Degraded, &r1_bio->state); | 922 | |
| 924 | } | ||
| 925 | update_head_pos(mirror, r1_bio); | 923 | update_head_pos(mirror, r1_bio); |
| 926 | 924 | ||
| 927 | if (atomic_dec_and_test(&r1_bio->remaining)) { | 925 | if (atomic_dec_and_test(&r1_bio->remaining)) { |
| @@ -1109,6 +1107,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i | |||
| 1109 | int i; | 1107 | int i; |
| 1110 | int write_targets = 0; | 1108 | int write_targets = 0; |
| 1111 | int sync_blocks; | 1109 | int sync_blocks; |
| 1110 | int still_degraded = 0; | ||
| 1112 | 1111 | ||
| 1113 | if (!conf->r1buf_pool) | 1112 | if (!conf->r1buf_pool) |
| 1114 | { | 1113 | { |
| @@ -1137,7 +1136,10 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i | |||
| 1137 | return 0; | 1136 | return 0; |
| 1138 | } | 1137 | } |
| 1139 | 1138 | ||
| 1140 | if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, mddev->degraded) && | 1139 | /* before building a request, check if we can skip these blocks.. |
| 1140 | * This call the bitmap_start_sync doesn't actually record anything | ||
| 1141 | */ | ||
| 1142 | if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) && | ||
| 1141 | !conf->fullsync) { | 1143 | !conf->fullsync) { |
| 1142 | /* We can skip this block, and probably several more */ | 1144 | /* We can skip this block, and probably several more */ |
| 1143 | *skipped = 1; | 1145 | *skipped = 1; |
| @@ -1203,24 +1205,23 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i | |||
| 1203 | if (i == disk) { | 1205 | if (i == disk) { |
| 1204 | bio->bi_rw = READ; | 1206 | bio->bi_rw = READ; |
| 1205 | bio->bi_end_io = end_sync_read; | 1207 | bio->bi_end_io = end_sync_read; |
| 1206 | } else if (conf->mirrors[i].rdev && | 1208 | } else if (conf->mirrors[i].rdev == NULL || |
| 1207 | !conf->mirrors[i].rdev->faulty && | 1209 | conf->mirrors[i].rdev->faulty) { |
| 1208 | (!conf->mirrors[i].rdev->in_sync || | 1210 | still_degraded = 1; |
| 1209 | sector_nr + RESYNC_SECTORS > mddev->recovery_cp)) { | 1211 | continue; |
| 1212 | } else if (!conf->mirrors[i].rdev->in_sync || | ||
| 1213 | sector_nr + RESYNC_SECTORS > mddev->recovery_cp) { | ||
| 1210 | bio->bi_rw = WRITE; | 1214 | bio->bi_rw = WRITE; |
| 1211 | bio->bi_end_io = end_sync_write; | 1215 | bio->bi_end_io = end_sync_write; |
| 1212 | write_targets ++; | 1216 | write_targets ++; |
| 1213 | } else | 1217 | } else |
| 1218 | /* no need to read or write here */ | ||
| 1214 | continue; | 1219 | continue; |
| 1215 | bio->bi_sector = sector_nr + conf->mirrors[i].rdev->data_offset; | 1220 | bio->bi_sector = sector_nr + conf->mirrors[i].rdev->data_offset; |
| 1216 | bio->bi_bdev = conf->mirrors[i].rdev->bdev; | 1221 | bio->bi_bdev = conf->mirrors[i].rdev->bdev; |
| 1217 | bio->bi_private = r1_bio; | 1222 | bio->bi_private = r1_bio; |
| 1218 | } | 1223 | } |
| 1219 | 1224 | ||
| 1220 | if (write_targets + 1 < conf->raid_disks) | ||
| 1221 | /* array degraded, can't clear bitmap */ | ||
| 1222 | set_bit(R1BIO_Degraded, &r1_bio->state); | ||
| 1223 | |||
| 1224 | if (write_targets == 0) { | 1225 | if (write_targets == 0) { |
| 1225 | /* There is nowhere to write, so all non-sync | 1226 | /* There is nowhere to write, so all non-sync |
| 1226 | * drives must be failed - so we are finished | 1227 | * drives must be failed - so we are finished |
| @@ -1243,7 +1244,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i | |||
| 1243 | break; | 1244 | break; |
| 1244 | if (sync_blocks == 0) { | 1245 | if (sync_blocks == 0) { |
| 1245 | if (!bitmap_start_sync(mddev->bitmap, sector_nr, | 1246 | if (!bitmap_start_sync(mddev->bitmap, sector_nr, |
| 1246 | &sync_blocks, mddev->degraded) && | 1247 | &sync_blocks, still_degraded) && |
| 1247 | !conf->fullsync) | 1248 | !conf->fullsync) |
| 1248 | break; | 1249 | break; |
| 1249 | if (sync_blocks < (PAGE_SIZE>>9)) | 1250 | if (sync_blocks < (PAGE_SIZE>>9)) |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 4698d5f79575..43f231a467d5 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
| @@ -1653,6 +1653,7 @@ static int run (mddev_t *mddev) | |||
| 1653 | 1653 | ||
| 1654 | /* device size must be a multiple of chunk size */ | 1654 | /* device size must be a multiple of chunk size */ |
| 1655 | mddev->size &= ~(mddev->chunk_size/1024 -1); | 1655 | mddev->size &= ~(mddev->chunk_size/1024 -1); |
| 1656 | mddev->resync_max_sectors = mddev->size << 1; | ||
| 1656 | 1657 | ||
| 1657 | if (!conf->chunk_size || conf->chunk_size % 4) { | 1658 | if (!conf->chunk_size || conf->chunk_size % 4) { |
| 1658 | printk(KERN_ERR "raid5: invalid chunk size %d for %s\n", | 1659 | printk(KERN_ERR "raid5: invalid chunk size %d for %s\n", |
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c index f5ee16805111..495dee1d1e83 100644 --- a/drivers/md/raid6main.c +++ b/drivers/md/raid6main.c | |||
| @@ -1813,6 +1813,7 @@ static int run (mddev_t *mddev) | |||
| 1813 | 1813 | ||
| 1814 | /* device size must be a multiple of chunk size */ | 1814 | /* device size must be a multiple of chunk size */ |
| 1815 | mddev->size &= ~(mddev->chunk_size/1024 -1); | 1815 | mddev->size &= ~(mddev->chunk_size/1024 -1); |
| 1816 | mddev->resync_max_sectors = mddev->size << 1; | ||
| 1816 | 1817 | ||
| 1817 | if (conf->raid_disks < 4) { | 1818 | if (conf->raid_disks < 4) { |
| 1818 | printk(KERN_ERR "raid6: not enough configured devices for %s (%d, minimum 4)\n", | 1819 | printk(KERN_ERR "raid6: not enough configured devices for %s (%d, minimum 4)\n", |
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index e83256d0fd14..a50a41f6f79d 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig | |||
| @@ -188,7 +188,7 @@ config DVB_BCM3510 | |||
| 188 | support this frontend. | 188 | support this frontend. |
| 189 | 189 | ||
| 190 | config DVB_LGDT330X | 190 | config DVB_LGDT330X |
| 191 | tristate "LGDT3302 or LGDT3303 based (DViCO FusionHDTV Gold)" | 191 | tristate "LG Electronics LGDT3302/LGDT3303 based" |
| 192 | depends on DVB_CORE | 192 | depends on DVB_CORE |
| 193 | help | 193 | help |
| 194 | An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want | 194 | An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want |
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 5264310c070e..536c35d969b7 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c | |||
| @@ -225,6 +225,22 @@ struct dvb_pll_desc dvb_pll_tua6034 = { | |||
| 225 | }; | 225 | }; |
| 226 | EXPORT_SYMBOL(dvb_pll_tua6034); | 226 | EXPORT_SYMBOL(dvb_pll_tua6034); |
| 227 | 227 | ||
| 228 | /* Infineon TUA6034 | ||
| 229 | * used in LG Innotek TDVS-H062F | ||
| 230 | */ | ||
| 231 | struct dvb_pll_desc dvb_pll_tdvs_tua6034 = { | ||
| 232 | .name = "LG/Infineon TUA6034", | ||
| 233 | .min = 54000000, | ||
| 234 | .max = 863000000, | ||
| 235 | .count = 3, | ||
| 236 | .entries = { | ||
| 237 | { 160000000, 44000000, 62500, 0xce, 0x01 }, | ||
| 238 | { 455000000, 44000000, 62500, 0xce, 0x02 }, | ||
| 239 | { 999999999, 44000000, 62500, 0xce, 0x04 }, | ||
| 240 | }, | ||
| 241 | }; | ||
| 242 | EXPORT_SYMBOL(dvb_pll_tdvs_tua6034); | ||
| 243 | |||
| 228 | /* Philips FMD1216ME | 244 | /* Philips FMD1216ME |
| 229 | * used in Medion Hybrid PCMCIA card and USB Box | 245 | * used in Medion Hybrid PCMCIA card and USB Box |
| 230 | */ | 246 | */ |
diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index cb794759d89e..205b2d1a8852 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h | |||
| @@ -31,6 +31,7 @@ extern struct dvb_pll_desc dvb_pll_unknown_1; | |||
| 31 | extern struct dvb_pll_desc dvb_pll_tua6010xs; | 31 | extern struct dvb_pll_desc dvb_pll_tua6010xs; |
| 32 | extern struct dvb_pll_desc dvb_pll_env57h1xd5; | 32 | extern struct dvb_pll_desc dvb_pll_env57h1xd5; |
| 33 | extern struct dvb_pll_desc dvb_pll_tua6034; | 33 | extern struct dvb_pll_desc dvb_pll_tua6034; |
| 34 | extern struct dvb_pll_desc dvb_pll_tdvs_tua6034; | ||
| 34 | extern struct dvb_pll_desc dvb_pll_tda665x; | 35 | extern struct dvb_pll_desc dvb_pll_tda665x; |
| 35 | extern struct dvb_pll_desc dvb_pll_fmd1216me; | 36 | extern struct dvb_pll_desc dvb_pll_fmd1216me; |
| 36 | extern struct dvb_pll_desc dvb_pll_tded4; | 37 | extern struct dvb_pll_desc dvb_pll_tded4; |
diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c index e94dee50eecd..1f1cd7a8d500 100644 --- a/drivers/media/dvb/frontends/lgdt330x.c +++ b/drivers/media/dvb/frontends/lgdt330x.c | |||
| @@ -1,11 +1,8 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Support for LGDT3302 & LGDT3303 (DViCO FusionHDTV Gold) - VSB/QAM | 2 | * Support for LGDT3302 and LGDT3303 - VSB/QAM |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.net> | 4 | * Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.net> |
| 5 | * | 5 | * |
| 6 | * Based on code from Kirk Lapray <kirk_lapray@bigfoot.com> | ||
| 7 | * Copyright (C) 2005 | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
| 10 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
| 11 | * the Free Software Foundation; either version 2 of the License, or | 8 | * the Free Software Foundation; either version 2 of the License, or |
| @@ -25,11 +22,13 @@ | |||
| 25 | /* | 22 | /* |
| 26 | * NOTES ABOUT THIS DRIVER | 23 | * NOTES ABOUT THIS DRIVER |
| 27 | * | 24 | * |
| 28 | * This driver supports DViCO FusionHDTV Gold under Linux. | 25 | * This Linux driver supports: |
| 26 | * DViCO FusionHDTV 3 Gold-Q | ||
| 27 | * DViCO FusionHDTV 3 Gold-T | ||
| 28 | * DViCO FusionHDTV 5 Gold | ||
| 29 | * | 29 | * |
| 30 | * TODO: | 30 | * TODO: |
| 31 | * BER and signal strength always return 0. | 31 | * signal strength always returns 0. |
| 32 | * Include support for LGDT3303 | ||
| 33 | * | 32 | * |
| 34 | */ | 33 | */ |
| 35 | 34 | ||
| @@ -41,7 +40,6 @@ | |||
| 41 | #include <asm/byteorder.h> | 40 | #include <asm/byteorder.h> |
| 42 | 41 | ||
| 43 | #include "dvb_frontend.h" | 42 | #include "dvb_frontend.h" |
| 44 | #include "dvb-pll.h" | ||
| 45 | #include "lgdt330x_priv.h" | 43 | #include "lgdt330x_priv.h" |
| 46 | #include "lgdt330x.h" | 44 | #include "lgdt330x.h" |
| 47 | 45 | ||
| @@ -70,55 +68,37 @@ struct lgdt330x_state | |||
| 70 | u32 current_frequency; | 68 | u32 current_frequency; |
| 71 | }; | 69 | }; |
| 72 | 70 | ||
| 73 | static int i2c_writebytes (struct lgdt330x_state* state, | 71 | static int i2c_write_demod_bytes (struct lgdt330x_state* state, |
| 74 | u8 addr, /* demod_address or pll_address */ | ||
| 75 | u8 *buf, /* data bytes to send */ | 72 | u8 *buf, /* data bytes to send */ |
| 76 | int len /* number of bytes to send */ ) | 73 | int len /* number of bytes to send */ ) |
| 77 | { | 74 | { |
| 78 | u8 tmp[] = { buf[0], buf[1] }; | ||
| 79 | struct i2c_msg msg = | 75 | struct i2c_msg msg = |
| 80 | { .addr = addr, .flags = 0, .buf = tmp, .len = 2 }; | 76 | { .addr = state->config->demod_address, |
| 81 | int err; | 77 | .flags = 0, |
| 78 | .buf = buf, | ||
| 79 | .len = 2 }; | ||
| 82 | int i; | 80 | int i; |
| 81 | int err; | ||
| 83 | 82 | ||
| 84 | for (i=1; i<len; i++) { | 83 | for (i=0; i<len-1; i+=2){ |
| 85 | tmp[1] = buf[i]; | ||
| 86 | if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { | 84 | if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { |
| 87 | printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err == %i)\n", __FUNCTION__, addr, buf[0], err); | 85 | printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __FUNCTION__, msg.buf[0], msg.buf[1], err); |
| 88 | if (err < 0) | 86 | if (err < 0) |
| 89 | return err; | 87 | return err; |
| 90 | else | 88 | else |
| 91 | return -EREMOTEIO; | 89 | return -EREMOTEIO; |
| 92 | } | 90 | } |
| 93 | tmp[0]++; | 91 | msg.buf += 2; |
| 94 | } | 92 | } |
| 95 | return 0; | 93 | return 0; |
| 96 | } | 94 | } |
| 97 | 95 | ||
| 98 | #if 0 | ||
| 99 | static int i2c_readbytes (struct lgdt330x_state* state, | ||
| 100 | u8 addr, /* demod_address or pll_address */ | ||
| 101 | u8 *buf, /* holds data bytes read */ | ||
| 102 | int len /* number of bytes to read */ ) | ||
| 103 | { | ||
| 104 | struct i2c_msg msg = | ||
| 105 | { .addr = addr, .flags = I2C_M_RD, .buf = buf, .len = len }; | ||
| 106 | int err; | ||
| 107 | |||
| 108 | if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { | ||
| 109 | printk(KERN_WARNING "lgdt330x: %s error (addr %02x, err == %i)\n", __FUNCTION__, addr, err); | ||
| 110 | return -EREMOTEIO; | ||
| 111 | } | ||
| 112 | return 0; | ||
| 113 | } | ||
| 114 | #endif | ||
| 115 | |||
| 116 | /* | 96 | /* |
| 117 | * This routine writes the register (reg) to the demod bus | 97 | * This routine writes the register (reg) to the demod bus |
| 118 | * then reads the data returned for (len) bytes. | 98 | * then reads the data returned for (len) bytes. |
| 119 | */ | 99 | */ |
| 120 | 100 | ||
| 121 | static u8 i2c_selectreadbytes (struct lgdt330x_state* state, | 101 | static u8 i2c_read_demod_bytes (struct lgdt330x_state* state, |
| 122 | enum I2C_REG reg, u8* buf, int len) | 102 | enum I2C_REG reg, u8* buf, int len) |
| 123 | { | 103 | { |
| 124 | u8 wr [] = { reg }; | 104 | u8 wr [] = { reg }; |
| @@ -139,7 +119,7 @@ static u8 i2c_selectreadbytes (struct lgdt330x_state* state, | |||
| 139 | } | 119 | } |
| 140 | 120 | ||
| 141 | /* Software reset */ | 121 | /* Software reset */ |
| 142 | int lgdt330x_SwReset(struct lgdt330x_state* state) | 122 | static int lgdt3302_SwReset(struct lgdt330x_state* state) |
| 143 | { | 123 | { |
| 144 | u8 ret; | 124 | u8 ret; |
| 145 | u8 reset[] = { | 125 | u8 reset[] = { |
| @@ -148,23 +128,51 @@ int lgdt330x_SwReset(struct lgdt330x_state* state) | |||
| 148 | * bits 5-0 are 1 to mask interrupts */ | 128 | * bits 5-0 are 1 to mask interrupts */ |
| 149 | }; | 129 | }; |
| 150 | 130 | ||
| 151 | ret = i2c_writebytes(state, | 131 | ret = i2c_write_demod_bytes(state, |
| 152 | state->config->demod_address, | 132 | reset, sizeof(reset)); |
| 133 | if (ret == 0) { | ||
| 134 | |||
| 135 | /* force reset high (inactive) and unmask interrupts */ | ||
| 136 | reset[1] = 0x7f; | ||
| 137 | ret = i2c_write_demod_bytes(state, | ||
| 138 | reset, sizeof(reset)); | ||
| 139 | } | ||
| 140 | return ret; | ||
| 141 | } | ||
| 142 | |||
| 143 | static int lgdt3303_SwReset(struct lgdt330x_state* state) | ||
| 144 | { | ||
| 145 | u8 ret; | ||
| 146 | u8 reset[] = { | ||
| 147 | 0x02, | ||
| 148 | 0x00 /* bit 0 is active low software reset */ | ||
| 149 | }; | ||
| 150 | |||
| 151 | ret = i2c_write_demod_bytes(state, | ||
| 153 | reset, sizeof(reset)); | 152 | reset, sizeof(reset)); |
| 154 | if (ret == 0) { | 153 | if (ret == 0) { |
| 155 | /* spec says reset takes 100 ns why wait */ | 154 | |
| 156 | /* mdelay(100); */ /* keep low for 100mS */ | 155 | /* force reset high (inactive) */ |
| 157 | reset[1] = 0x7f; /* force reset high (inactive) | 156 | reset[1] = 0x01; |
| 158 | * and unmask interrupts */ | 157 | ret = i2c_write_demod_bytes(state, |
| 159 | ret = i2c_writebytes(state, | ||
| 160 | state->config->demod_address, | ||
| 161 | reset, sizeof(reset)); | 158 | reset, sizeof(reset)); |
| 162 | } | 159 | } |
| 163 | /* Spec does not indicate a need for this either */ | ||
| 164 | /*mdelay(5); */ /* wait 5 msec before doing more */ | ||
| 165 | return ret; | 160 | return ret; |
| 166 | } | 161 | } |
| 167 | 162 | ||
| 163 | static int lgdt330x_SwReset(struct lgdt330x_state* state) | ||
| 164 | { | ||
| 165 | switch (state->config->demod_chip) { | ||
| 166 | case LGDT3302: | ||
| 167 | return lgdt3302_SwReset(state); | ||
| 168 | case LGDT3303: | ||
| 169 | return lgdt3303_SwReset(state); | ||
| 170 | default: | ||
| 171 | return -ENODEV; | ||
| 172 | } | ||
| 173 | } | ||
| 174 | |||
| 175 | |||
| 168 | static int lgdt330x_init(struct dvb_frontend* fe) | 176 | static int lgdt330x_init(struct dvb_frontend* fe) |
| 169 | { | 177 | { |
| 170 | /* Hardware reset is done using gpio[0] of cx23880x chip. | 178 | /* Hardware reset is done using gpio[0] of cx23880x chip. |
| @@ -173,22 +181,98 @@ static int lgdt330x_init(struct dvb_frontend* fe) | |||
| 173 | * Maybe there needs to be a callable function in cx88-core or | 181 | * Maybe there needs to be a callable function in cx88-core or |
| 174 | * the caller of this function needs to do it. */ | 182 | * the caller of this function needs to do it. */ |
| 175 | 183 | ||
| 176 | dprintk("%s entered\n", __FUNCTION__); | 184 | /* |
| 177 | return lgdt330x_SwReset((struct lgdt330x_state*) fe->demodulator_priv); | 185 | * Array of byte pairs <address, value> |
| 186 | * to initialize each different chip | ||
| 187 | */ | ||
| 188 | static u8 lgdt3302_init_data[] = { | ||
| 189 | /* Use 50MHz parameter values from spec sheet since xtal is 50 */ | ||
| 190 | /* Change the value of NCOCTFV[25:0] of carrier | ||
| 191 | recovery center frequency register */ | ||
| 192 | VSB_CARRIER_FREQ0, 0x00, | ||
| 193 | VSB_CARRIER_FREQ1, 0x87, | ||
| 194 | VSB_CARRIER_FREQ2, 0x8e, | ||
| 195 | VSB_CARRIER_FREQ3, 0x01, | ||
| 196 | /* Change the TPCLK pin polarity | ||
| 197 | data is valid on falling clock */ | ||
| 198 | DEMUX_CONTROL, 0xfb, | ||
| 199 | /* Change the value of IFBW[11:0] of | ||
| 200 | AGC IF/RF loop filter bandwidth register */ | ||
| 201 | AGC_RF_BANDWIDTH0, 0x40, | ||
| 202 | AGC_RF_BANDWIDTH1, 0x93, | ||
| 203 | AGC_RF_BANDWIDTH2, 0x00, | ||
| 204 | /* Change the value of bit 6, 'nINAGCBY' and | ||
| 205 | 'NSSEL[1:0] of ACG function control register 2 */ | ||
| 206 | AGC_FUNC_CTRL2, 0xc6, | ||
| 207 | /* Change the value of bit 6 'RFFIX' | ||
| 208 | of AGC function control register 3 */ | ||
| 209 | AGC_FUNC_CTRL3, 0x40, | ||
| 210 | /* Set the value of 'INLVTHD' register 0x2a/0x2c | ||
| 211 | to 0x7fe */ | ||
| 212 | AGC_DELAY0, 0x07, | ||
| 213 | AGC_DELAY2, 0xfe, | ||
| 214 | /* Change the value of IAGCBW[15:8] | ||
| 215 | of inner AGC loop filter bandwith */ | ||
| 216 | AGC_LOOP_BANDWIDTH0, 0x08, | ||
| 217 | AGC_LOOP_BANDWIDTH1, 0x9a | ||
| 218 | }; | ||
| 219 | |||
| 220 | static u8 lgdt3303_init_data[] = { | ||
| 221 | 0x4c, 0x14 | ||
| 222 | }; | ||
| 223 | |||
| 224 | struct lgdt330x_state* state = fe->demodulator_priv; | ||
| 225 | char *chip_name; | ||
| 226 | int err; | ||
| 227 | |||
| 228 | switch (state->config->demod_chip) { | ||
| 229 | case LGDT3302: | ||
| 230 | chip_name = "LGDT3302"; | ||
| 231 | err = i2c_write_demod_bytes(state, lgdt3302_init_data, | ||
| 232 | sizeof(lgdt3302_init_data)); | ||
| 233 | break; | ||
| 234 | case LGDT3303: | ||
| 235 | chip_name = "LGDT3303"; | ||
| 236 | err = i2c_write_demod_bytes(state, lgdt3303_init_data, | ||
| 237 | sizeof(lgdt3303_init_data)); | ||
| 238 | break; | ||
| 239 | default: | ||
| 240 | chip_name = "undefined"; | ||
| 241 | printk (KERN_WARNING "Only LGDT3302 and LGDT3303 are supported chips.\n"); | ||
| 242 | err = -ENODEV; | ||
| 243 | } | ||
| 244 | dprintk("%s entered as %s\n", __FUNCTION__, chip_name); | ||
| 245 | if (err < 0) | ||
| 246 | return err; | ||
| 247 | return lgdt330x_SwReset(state); | ||
| 178 | } | 248 | } |
| 179 | 249 | ||
| 180 | static int lgdt330x_read_ber(struct dvb_frontend* fe, u32* ber) | 250 | static int lgdt330x_read_ber(struct dvb_frontend* fe, u32* ber) |
| 181 | { | 251 | { |
| 182 | *ber = 0; /* Dummy out for now */ | 252 | *ber = 0; /* Not supplied by the demod chips */ |
| 183 | return 0; | 253 | return 0; |
| 184 | } | 254 | } |
| 185 | 255 | ||
| 186 | static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) | 256 | static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) |
| 187 | { | 257 | { |
| 188 | struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; | 258 | struct lgdt330x_state* state = fe->demodulator_priv; |
| 259 | int err; | ||
| 189 | u8 buf[2]; | 260 | u8 buf[2]; |
| 190 | 261 | ||
| 191 | i2c_selectreadbytes(state, PACKET_ERR_COUNTER1, buf, sizeof(buf)); | 262 | switch (state->config->demod_chip) { |
| 263 | case LGDT3302: | ||
| 264 | err = i2c_read_demod_bytes(state, LGDT3302_PACKET_ERR_COUNTER1, | ||
| 265 | buf, sizeof(buf)); | ||
| 266 | break; | ||
| 267 | case LGDT3303: | ||
| 268 | err = i2c_read_demod_bytes(state, LGDT3303_PACKET_ERR_COUNTER1, | ||
| 269 | buf, sizeof(buf)); | ||
| 270 | break; | ||
| 271 | default: | ||
| 272 | printk(KERN_WARNING | ||
| 273 | "Only LGDT3302 and LGDT3303 are supported chips.\n"); | ||
| 274 | err = -ENODEV; | ||
| 275 | } | ||
| 192 | 276 | ||
| 193 | *ucblocks = (buf[0] << 8) | buf[1]; | 277 | *ucblocks = (buf[0] << 8) | buf[1]; |
| 194 | return 0; | 278 | return 0; |
| @@ -197,123 +281,113 @@ static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) | |||
| 197 | static int lgdt330x_set_parameters(struct dvb_frontend* fe, | 281 | static int lgdt330x_set_parameters(struct dvb_frontend* fe, |
| 198 | struct dvb_frontend_parameters *param) | 282 | struct dvb_frontend_parameters *param) |
| 199 | { | 283 | { |
| 200 | struct lgdt330x_state* state = | 284 | /* |
| 201 | (struct lgdt330x_state*) fe->demodulator_priv; | 285 | * Array of byte pairs <address, value> |
| 286 | * to initialize 8VSB for lgdt3303 chip 50 MHz IF | ||
| 287 | */ | ||
| 288 | static u8 lgdt3303_8vsb_44_data[] = { | ||
| 289 | 0x04, 0x00, | ||
| 290 | 0x0d, 0x40, | ||
| 291 | 0x0e, 0x87, | ||
| 292 | 0x0f, 0x8e, | ||
| 293 | 0x10, 0x01, | ||
| 294 | 0x47, 0x8b }; | ||
| 295 | |||
| 296 | /* | ||
| 297 | * Array of byte pairs <address, value> | ||
| 298 | * to initialize QAM for lgdt3303 chip | ||
| 299 | */ | ||
| 300 | static u8 lgdt3303_qam_data[] = { | ||
| 301 | 0x04, 0x00, | ||
| 302 | 0x0d, 0x00, | ||
| 303 | 0x0e, 0x00, | ||
| 304 | 0x0f, 0x00, | ||
| 305 | 0x10, 0x00, | ||
| 306 | 0x51, 0x63, | ||
| 307 | 0x47, 0x66, | ||
| 308 | 0x48, 0x66, | ||
| 309 | 0x4d, 0x1a, | ||
| 310 | 0x49, 0x08, | ||
| 311 | 0x4a, 0x9b }; | ||
| 312 | |||
| 313 | struct lgdt330x_state* state = fe->demodulator_priv; | ||
| 202 | 314 | ||
| 203 | /* Use 50MHz parameter values from spec sheet since xtal is 50 */ | ||
| 204 | static u8 top_ctrl_cfg[] = { TOP_CONTROL, 0x03 }; | 315 | static u8 top_ctrl_cfg[] = { TOP_CONTROL, 0x03 }; |
| 205 | static u8 vsb_freq_cfg[] = { VSB_CARRIER_FREQ0, 0x00, 0x87, 0x8e, 0x01 }; | ||
| 206 | static u8 demux_ctrl_cfg[] = { DEMUX_CONTROL, 0xfb }; | ||
| 207 | static u8 agc_rf_cfg[] = { AGC_RF_BANDWIDTH0, 0x40, 0x93, 0x00 }; | ||
| 208 | static u8 agc_ctrl_cfg[] = { AGC_FUNC_CTRL2, 0xc6, 0x40 }; | ||
| 209 | static u8 agc_delay_cfg[] = { AGC_DELAY0, 0x07, 0x00, 0xfe }; | ||
| 210 | static u8 agc_loop_cfg[] = { AGC_LOOP_BANDWIDTH0, 0x08, 0x9a }; | ||
| 211 | 316 | ||
| 317 | int err; | ||
| 212 | /* Change only if we are actually changing the modulation */ | 318 | /* Change only if we are actually changing the modulation */ |
| 213 | if (state->current_modulation != param->u.vsb.modulation) { | 319 | if (state->current_modulation != param->u.vsb.modulation) { |
| 214 | switch(param->u.vsb.modulation) { | 320 | switch(param->u.vsb.modulation) { |
| 215 | case VSB_8: | 321 | case VSB_8: |
| 216 | dprintk("%s: VSB_8 MODE\n", __FUNCTION__); | 322 | dprintk("%s: VSB_8 MODE\n", __FUNCTION__); |
| 217 | 323 | ||
| 218 | /* Select VSB mode and serial MPEG interface */ | 324 | /* Select VSB mode */ |
| 219 | top_ctrl_cfg[1] = 0x07; | 325 | top_ctrl_cfg[1] = 0x03; |
| 220 | 326 | ||
| 221 | /* Select ANT connector if supported by card */ | 327 | /* Select ANT connector if supported by card */ |
| 222 | if (state->config->pll_rf_set) | 328 | if (state->config->pll_rf_set) |
| 223 | state->config->pll_rf_set(fe, 1); | 329 | state->config->pll_rf_set(fe, 1); |
| 330 | |||
| 331 | if (state->config->demod_chip == LGDT3303) { | ||
| 332 | err = i2c_write_demod_bytes(state, lgdt3303_8vsb_44_data, | ||
| 333 | sizeof(lgdt3303_8vsb_44_data)); | ||
| 334 | } | ||
| 224 | break; | 335 | break; |
| 225 | 336 | ||
| 226 | case QAM_64: | 337 | case QAM_64: |
| 227 | dprintk("%s: QAM_64 MODE\n", __FUNCTION__); | 338 | dprintk("%s: QAM_64 MODE\n", __FUNCTION__); |
| 228 | 339 | ||
| 229 | /* Select QAM_64 mode and serial MPEG interface */ | 340 | /* Select QAM_64 mode */ |
| 230 | top_ctrl_cfg[1] = 0x04; | 341 | top_ctrl_cfg[1] = 0x00; |
| 231 | 342 | ||
| 232 | /* Select CABLE connector if supported by card */ | 343 | /* Select CABLE connector if supported by card */ |
| 233 | if (state->config->pll_rf_set) | 344 | if (state->config->pll_rf_set) |
| 234 | state->config->pll_rf_set(fe, 0); | 345 | state->config->pll_rf_set(fe, 0); |
| 346 | |||
| 347 | if (state->config->demod_chip == LGDT3303) { | ||
| 348 | err = i2c_write_demod_bytes(state, lgdt3303_qam_data, | ||
| 349 | sizeof(lgdt3303_qam_data)); | ||
| 350 | } | ||
| 235 | break; | 351 | break; |
| 236 | 352 | ||
| 237 | case QAM_256: | 353 | case QAM_256: |
| 238 | dprintk("%s: QAM_256 MODE\n", __FUNCTION__); | 354 | dprintk("%s: QAM_256 MODE\n", __FUNCTION__); |
| 239 | 355 | ||
| 240 | /* Select QAM_256 mode and serial MPEG interface */ | 356 | /* Select QAM_256 mode */ |
| 241 | top_ctrl_cfg[1] = 0x05; | 357 | top_ctrl_cfg[1] = 0x01; |
| 242 | 358 | ||
| 243 | /* Select CABLE connector if supported by card */ | 359 | /* Select CABLE connector if supported by card */ |
| 244 | if (state->config->pll_rf_set) | 360 | if (state->config->pll_rf_set) |
| 245 | state->config->pll_rf_set(fe, 0); | 361 | state->config->pll_rf_set(fe, 0); |
| 362 | |||
| 363 | if (state->config->demod_chip == LGDT3303) { | ||
| 364 | err = i2c_write_demod_bytes(state, lgdt3303_qam_data, | ||
| 365 | sizeof(lgdt3303_qam_data)); | ||
| 366 | } | ||
| 246 | break; | 367 | break; |
| 247 | default: | 368 | default: |
| 248 | printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __FUNCTION__, param->u.vsb.modulation); | 369 | printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __FUNCTION__, param->u.vsb.modulation); |
| 249 | return -1; | 370 | return -1; |
| 250 | } | 371 | } |
| 251 | /* Initializations common to all modes */ | 372 | /* |
| 373 | * select serial or parallel MPEG harware interface | ||
| 374 | * Serial: 0x04 for LGDT3302 or 0x40 for LGDT3303 | ||
| 375 | * Parallel: 0x00 | ||
| 376 | */ | ||
| 377 | top_ctrl_cfg[1] |= state->config->serial_mpeg; | ||
| 252 | 378 | ||
| 253 | /* Select the requested mode */ | 379 | /* Select the requested mode */ |
| 254 | i2c_writebytes(state, state->config->demod_address, | 380 | i2c_write_demod_bytes(state, top_ctrl_cfg, |
| 255 | top_ctrl_cfg, sizeof(top_ctrl_cfg)); | 381 | sizeof(top_ctrl_cfg)); |
| 256 | |||
| 257 | /* Change the value of IFBW[11:0] | ||
| 258 | of AGC IF/RF loop filter bandwidth register */ | ||
| 259 | i2c_writebytes(state, state->config->demod_address, | ||
| 260 | agc_rf_cfg, sizeof(agc_rf_cfg)); | ||
| 261 | |||
| 262 | /* Change the value of bit 6, 'nINAGCBY' and | ||
| 263 | 'NSSEL[1:0] of ACG function control register 2 */ | ||
| 264 | /* Change the value of bit 6 'RFFIX' | ||
| 265 | of AGC function control register 3 */ | ||
| 266 | i2c_writebytes(state, state->config->demod_address, | ||
| 267 | agc_ctrl_cfg, sizeof(agc_ctrl_cfg)); | ||
| 268 | |||
| 269 | /* Change the TPCLK pin polarity | ||
| 270 | data is valid on falling clock */ | ||
| 271 | i2c_writebytes(state, state->config->demod_address, | ||
| 272 | demux_ctrl_cfg, sizeof(demux_ctrl_cfg)); | ||
| 273 | |||
| 274 | /* Change the value of NCOCTFV[25:0] of carrier | ||
| 275 | recovery center frequency register */ | ||
| 276 | i2c_writebytes(state, state->config->demod_address, | ||
| 277 | vsb_freq_cfg, sizeof(vsb_freq_cfg)); | ||
| 278 | |||
| 279 | /* Set the value of 'INLVTHD' register 0x2a/0x2c to 0x7fe */ | ||
| 280 | i2c_writebytes(state, state->config->demod_address, | ||
| 281 | agc_delay_cfg, sizeof(agc_delay_cfg)); | ||
| 282 | |||
| 283 | /* Change the value of IAGCBW[15:8] | ||
| 284 | of inner AGC loop filter bandwith */ | ||
| 285 | i2c_writebytes(state, state->config->demod_address, | ||
| 286 | agc_loop_cfg, sizeof(agc_loop_cfg)); | ||
| 287 | |||
| 288 | state->config->set_ts_params(fe, 0); | 382 | state->config->set_ts_params(fe, 0); |
| 289 | state->current_modulation = param->u.vsb.modulation; | 383 | state->current_modulation = param->u.vsb.modulation; |
| 290 | } | 384 | } |
| 291 | 385 | ||
| 292 | /* Change only if we are actually changing the channel */ | 386 | /* Change only if we are actually changing the channel */ |
| 293 | if (state->current_frequency != param->frequency) { | 387 | if (state->current_frequency != param->frequency) { |
| 294 | u8 buf[5]; | 388 | /* Tune to the new frequency */ |
| 295 | struct i2c_msg msg = { .flags = 0, .buf = &buf[1], .len = 4 }; | 389 | state->config->pll_set(fe, param); |
| 296 | int err; | 390 | /* Keep track of the new frequency */ |
| 297 | |||
| 298 | state->config->pll_set(fe, param, buf); | ||
| 299 | msg.addr = buf[0]; | ||
| 300 | |||
| 301 | dprintk("%s: tuner at 0x%02x bytes: 0x%02x 0x%02x " | ||
| 302 | "0x%02x 0x%02x\n", __FUNCTION__, | ||
| 303 | buf[0],buf[1],buf[2],buf[3],buf[4]); | ||
| 304 | if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { | ||
| 305 | printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __FUNCTION__, buf[0], buf[1], err); | ||
| 306 | if (err < 0) | ||
| 307 | return err; | ||
| 308 | else | ||
| 309 | return -EREMOTEIO; | ||
| 310 | } | ||
| 311 | #if 0 | ||
| 312 | /* Check the status of the tuner pll */ | ||
| 313 | i2c_readbytes(state, buf[0], &buf[1], 1); | ||
| 314 | dprintk("%s: tuner status byte = 0x%02x\n", __FUNCTION__, buf[1]); | ||
| 315 | #endif | ||
| 316 | /* Update current frequency */ | ||
| 317 | state->current_frequency = param->frequency; | 391 | state->current_frequency = param->frequency; |
| 318 | } | 392 | } |
| 319 | lgdt330x_SwReset(state); | 393 | lgdt330x_SwReset(state); |
| @@ -328,21 +402,15 @@ static int lgdt330x_get_frontend(struct dvb_frontend* fe, | |||
| 328 | return 0; | 402 | return 0; |
| 329 | } | 403 | } |
| 330 | 404 | ||
| 331 | static int lgdt330x_read_status(struct dvb_frontend* fe, fe_status_t* status) | 405 | static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status) |
| 332 | { | 406 | { |
| 333 | struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; | 407 | struct lgdt330x_state* state = fe->demodulator_priv; |
| 334 | u8 buf[3]; | 408 | u8 buf[3]; |
| 335 | 409 | ||
| 336 | *status = 0; /* Reset status result */ | 410 | *status = 0; /* Reset status result */ |
| 337 | 411 | ||
| 338 | /* | ||
| 339 | * You must set the Mask bits to 1 in the IRQ_MASK in order | ||
| 340 | * to see that status bit in the IRQ_STATUS register. | ||
| 341 | * This is done in SwReset(); | ||
| 342 | */ | ||
| 343 | |||
| 344 | /* AGC status register */ | 412 | /* AGC status register */ |
| 345 | i2c_selectreadbytes(state, AGC_STATUS, buf, 1); | 413 | i2c_read_demod_bytes(state, AGC_STATUS, buf, 1); |
| 346 | dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]); | 414 | dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]); |
| 347 | if ((buf[0] & 0x0c) == 0x8){ | 415 | if ((buf[0] & 0x0c) == 0x8){ |
| 348 | /* Test signal does not exist flag */ | 416 | /* Test signal does not exist flag */ |
| @@ -353,16 +421,15 @@ static int lgdt330x_read_status(struct dvb_frontend* fe, fe_status_t* status) | |||
| 353 | return 0; | 421 | return 0; |
| 354 | } | 422 | } |
| 355 | 423 | ||
| 424 | /* | ||
| 425 | * You must set the Mask bits to 1 in the IRQ_MASK in order | ||
| 426 | * to see that status bit in the IRQ_STATUS register. | ||
| 427 | * This is done in SwReset(); | ||
| 428 | */ | ||
| 356 | /* signal status */ | 429 | /* signal status */ |
| 357 | i2c_selectreadbytes(state, TOP_CONTROL, buf, sizeof(buf)); | 430 | i2c_read_demod_bytes(state, TOP_CONTROL, buf, sizeof(buf)); |
| 358 | dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __FUNCTION__, buf[0], buf[1], buf[2]); | 431 | dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __FUNCTION__, buf[0], buf[1], buf[2]); |
| 359 | 432 | ||
| 360 | #if 0 | ||
| 361 | /* Alternative method to check for a signal */ | ||
| 362 | /* using the SNR good/bad interrupts. */ | ||
| 363 | if ((buf[2] & 0x30) == 0x10) | ||
| 364 | *status |= FE_HAS_SIGNAL; | ||
| 365 | #endif | ||
| 366 | 433 | ||
| 367 | /* sync status */ | 434 | /* sync status */ |
| 368 | if ((buf[2] & 0x03) == 0x01) { | 435 | if ((buf[2] & 0x03) == 0x01) { |
| @@ -376,7 +443,7 @@ static int lgdt330x_read_status(struct dvb_frontend* fe, fe_status_t* status) | |||
| 376 | } | 443 | } |
| 377 | 444 | ||
| 378 | /* Carrier Recovery Lock Status Register */ | 445 | /* Carrier Recovery Lock Status Register */ |
| 379 | i2c_selectreadbytes(state, CARRIER_LOCK, buf, 1); | 446 | i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1); |
| 380 | dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]); | 447 | dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]); |
| 381 | switch (state->current_modulation) { | 448 | switch (state->current_modulation) { |
| 382 | case QAM_256: | 449 | case QAM_256: |
| @@ -396,13 +463,75 @@ static int lgdt330x_read_status(struct dvb_frontend* fe, fe_status_t* status) | |||
| 396 | return 0; | 463 | return 0; |
| 397 | } | 464 | } |
| 398 | 465 | ||
| 466 | static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status) | ||
| 467 | { | ||
| 468 | struct lgdt330x_state* state = fe->demodulator_priv; | ||
| 469 | int err; | ||
| 470 | u8 buf[3]; | ||
| 471 | |||
| 472 | *status = 0; /* Reset status result */ | ||
| 473 | |||
| 474 | /* lgdt3303 AGC status register */ | ||
| 475 | err = i2c_read_demod_bytes(state, 0x58, buf, 1); | ||
| 476 | if (err < 0) | ||
| 477 | return err; | ||
| 478 | |||
| 479 | dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]); | ||
| 480 | if ((buf[0] & 0x21) == 0x01){ | ||
| 481 | /* Test input signal does not exist flag */ | ||
| 482 | /* as well as the AGC lock flag. */ | ||
| 483 | *status |= FE_HAS_SIGNAL; | ||
| 484 | } else { | ||
| 485 | /* Without a signal all other status bits are meaningless */ | ||
| 486 | return 0; | ||
| 487 | } | ||
| 488 | |||
| 489 | /* Carrier Recovery Lock Status Register */ | ||
| 490 | i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1); | ||
| 491 | dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]); | ||
| 492 | switch (state->current_modulation) { | ||
| 493 | case QAM_256: | ||
| 494 | case QAM_64: | ||
| 495 | /* Need to undestand why there are 3 lock levels here */ | ||
| 496 | if ((buf[0] & 0x07) == 0x07) | ||
| 497 | *status |= FE_HAS_CARRIER; | ||
| 498 | else | ||
| 499 | break; | ||
| 500 | i2c_read_demod_bytes(state, 0x8a, buf, 1); | ||
| 501 | if ((buf[0] & 0x04) == 0x04) | ||
| 502 | *status |= FE_HAS_SYNC; | ||
| 503 | if ((buf[0] & 0x01) == 0x01) | ||
| 504 | *status |= FE_HAS_LOCK; | ||
| 505 | if ((buf[0] & 0x08) == 0x08) | ||
| 506 | *status |= FE_HAS_VITERBI; | ||
| 507 | break; | ||
| 508 | case VSB_8: | ||
| 509 | if ((buf[0] & 0x80) == 0x80) | ||
| 510 | *status |= FE_HAS_CARRIER; | ||
| 511 | else | ||
| 512 | break; | ||
| 513 | i2c_read_demod_bytes(state, 0x38, buf, 1); | ||
| 514 | if ((buf[0] & 0x02) == 0x00) | ||
| 515 | *status |= FE_HAS_SYNC; | ||
| 516 | if ((buf[0] & 0x01) == 0x01) { | ||
| 517 | *status |= FE_HAS_LOCK; | ||
| 518 | *status |= FE_HAS_VITERBI; | ||
| 519 | } | ||
| 520 | break; | ||
| 521 | default: | ||
| 522 | printk("KERN_WARNING lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__); | ||
| 523 | } | ||
| 524 | return 0; | ||
| 525 | } | ||
| 526 | |||
| 399 | static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength) | 527 | static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength) |
| 400 | { | 528 | { |
| 401 | /* not directly available. */ | 529 | /* not directly available. */ |
| 530 | *strength = 0; | ||
| 402 | return 0; | 531 | return 0; |
| 403 | } | 532 | } |
| 404 | 533 | ||
| 405 | static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr) | 534 | static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr) |
| 406 | { | 535 | { |
| 407 | #ifdef SNR_IN_DB | 536 | #ifdef SNR_IN_DB |
| 408 | /* | 537 | /* |
| @@ -451,7 +580,7 @@ static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr) | |||
| 451 | 91, 115, 144, 182, 229, 288, 362, 456, 574, 722, | 580 | 91, 115, 144, 182, 229, 288, 362, 456, 574, 722, |
| 452 | 909, 1144, 1440, 1813, 2282, 2873, 3617, 4553, 5732, 7216, | 581 | 909, 1144, 1440, 1813, 2282, 2873, 3617, 4553, 5732, 7216, |
| 453 | 9084, 11436, 14396, 18124, 22817, 28724, 36161, 45524, 57312, 72151, | 582 | 9084, 11436, 14396, 18124, 22817, 28724, 36161, 45524, 57312, 72151, |
| 454 | 90833, 114351, 143960, 181235, 228161, 0x040000 | 583 | 90833, 114351, 143960, 181235, 228161, 0x080000 |
| 455 | }; | 584 | }; |
| 456 | 585 | ||
| 457 | static u8 buf[5];/* read data buffer */ | 586 | static u8 buf[5];/* read data buffer */ |
| @@ -459,8 +588,8 @@ static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr) | |||
| 459 | static u32 snr_db; /* index into SNR_EQ[] */ | 588 | static u32 snr_db; /* index into SNR_EQ[] */ |
| 460 | struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; | 589 | struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; |
| 461 | 590 | ||
| 462 | /* read both equalizer and pase tracker noise data */ | 591 | /* read both equalizer and phase tracker noise data */ |
| 463 | i2c_selectreadbytes(state, EQPH_ERR0, buf, sizeof(buf)); | 592 | i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf)); |
| 464 | 593 | ||
| 465 | if (state->current_modulation == VSB_8) { | 594 | if (state->current_modulation == VSB_8) { |
| 466 | /* Equalizer Mean-Square Error Register for VSB */ | 595 | /* Equalizer Mean-Square Error Register for VSB */ |
| @@ -496,19 +625,20 @@ static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr) | |||
| 496 | struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; | 625 | struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; |
| 497 | 626 | ||
| 498 | /* read both equalizer and pase tracker noise data */ | 627 | /* read both equalizer and pase tracker noise data */ |
| 499 | i2c_selectreadbytes(state, EQPH_ERR0, buf, sizeof(buf)); | 628 | i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf)); |
| 500 | 629 | ||
| 501 | if (state->current_modulation == VSB_8) { | 630 | if (state->current_modulation == VSB_8) { |
| 502 | /* Equalizer Mean-Square Error Register for VSB */ | 631 | /* Phase Tracker Mean-Square Error Register for VSB */ |
| 503 | noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2]; | ||
| 504 | } else { | ||
| 505 | /* Phase Tracker Mean-Square Error Register for QAM */ | ||
| 506 | noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4]; | 632 | noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4]; |
| 633 | } else { | ||
| 634 | |||
| 635 | /* Carrier Recovery Mean-Square Error for QAM */ | ||
| 636 | i2c_read_demod_bytes(state, 0x1a, buf, 2); | ||
| 637 | noise = ((buf[0] & 3) << 8) | buf[1]; | ||
| 507 | } | 638 | } |
| 508 | 639 | ||
| 509 | /* Small values for noise mean signal is better so invert noise */ | 640 | /* Small values for noise mean signal is better so invert noise */ |
| 510 | /* Noise is 19 bit value so discard 3 LSB*/ | 641 | *snr = ~noise; |
| 511 | *snr = ~noise>>3; | ||
| 512 | #endif | 642 | #endif |
| 513 | 643 | ||
| 514 | dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr); | 644 | dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr); |
| @@ -516,6 +646,32 @@ static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr) | |||
| 516 | return 0; | 646 | return 0; |
| 517 | } | 647 | } |
| 518 | 648 | ||
| 649 | static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr) | ||
| 650 | { | ||
| 651 | /* Return the raw noise value */ | ||
| 652 | static u8 buf[5];/* read data buffer */ | ||
| 653 | static u32 noise; /* noise value */ | ||
| 654 | struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; | ||
| 655 | |||
| 656 | if (state->current_modulation == VSB_8) { | ||
| 657 | |||
| 658 | /* Phase Tracker Mean-Square Error Register for VSB */ | ||
| 659 | noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4]; | ||
| 660 | } else { | ||
| 661 | |||
| 662 | /* Carrier Recovery Mean-Square Error for QAM */ | ||
| 663 | i2c_read_demod_bytes(state, 0x1a, buf, 2); | ||
| 664 | noise = (buf[0] << 8) | buf[1]; | ||
| 665 | } | ||
| 666 | |||
| 667 | /* Small values for noise mean signal is better so invert noise */ | ||
| 668 | *snr = ~noise; | ||
| 669 | |||
| 670 | dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr); | ||
| 671 | |||
| 672 | return 0; | ||
| 673 | } | ||
| 674 | |||
| 519 | static int lgdt330x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings) | 675 | static int lgdt330x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings) |
| 520 | { | 676 | { |
| 521 | /* I have no idea about this - it may not be needed */ | 677 | /* I have no idea about this - it may not be needed */ |
| @@ -531,7 +687,8 @@ static void lgdt330x_release(struct dvb_frontend* fe) | |||
| 531 | kfree(state); | 687 | kfree(state); |
| 532 | } | 688 | } |
| 533 | 689 | ||
| 534 | static struct dvb_frontend_ops lgdt330x_ops; | 690 | static struct dvb_frontend_ops lgdt3302_ops; |
| 691 | static struct dvb_frontend_ops lgdt3303_ops; | ||
| 535 | 692 | ||
| 536 | struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config, | 693 | struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config, |
| 537 | struct i2c_adapter* i2c) | 694 | struct i2c_adapter* i2c) |
| @@ -548,9 +705,19 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config, | |||
| 548 | /* Setup the state */ | 705 | /* Setup the state */ |
| 549 | state->config = config; | 706 | state->config = config; |
| 550 | state->i2c = i2c; | 707 | state->i2c = i2c; |
| 551 | memcpy(&state->ops, &lgdt330x_ops, sizeof(struct dvb_frontend_ops)); | 708 | switch (config->demod_chip) { |
| 709 | case LGDT3302: | ||
| 710 | memcpy(&state->ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops)); | ||
| 711 | break; | ||
| 712 | case LGDT3303: | ||
| 713 | memcpy(&state->ops, &lgdt3303_ops, sizeof(struct dvb_frontend_ops)); | ||
| 714 | break; | ||
| 715 | default: | ||
| 716 | goto error; | ||
| 717 | } | ||
| 718 | |||
| 552 | /* Verify communication with demod chip */ | 719 | /* Verify communication with demod chip */ |
| 553 | if (i2c_selectreadbytes(state, 2, buf, 1)) | 720 | if (i2c_read_demod_bytes(state, 2, buf, 1)) |
| 554 | goto error; | 721 | goto error; |
| 555 | 722 | ||
| 556 | state->current_frequency = -1; | 723 | state->current_frequency = -1; |
| @@ -568,9 +735,33 @@ error: | |||
| 568 | return NULL; | 735 | return NULL; |
| 569 | } | 736 | } |
| 570 | 737 | ||
| 571 | static struct dvb_frontend_ops lgdt330x_ops = { | 738 | static struct dvb_frontend_ops lgdt3302_ops = { |
| 739 | .info = { | ||
| 740 | .name= "LG Electronics LGDT3302 VSB/QAM Frontend", | ||
| 741 | .type = FE_ATSC, | ||
| 742 | .frequency_min= 54000000, | ||
| 743 | .frequency_max= 858000000, | ||
| 744 | .frequency_stepsize= 62500, | ||
| 745 | /* Symbol rate is for all VSB modes need to check QAM */ | ||
| 746 | .symbol_rate_min = 10762000, | ||
| 747 | .symbol_rate_max = 10762000, | ||
| 748 | .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB | ||
| 749 | }, | ||
| 750 | .init = lgdt330x_init, | ||
| 751 | .set_frontend = lgdt330x_set_parameters, | ||
| 752 | .get_frontend = lgdt330x_get_frontend, | ||
| 753 | .get_tune_settings = lgdt330x_get_tune_settings, | ||
| 754 | .read_status = lgdt3302_read_status, | ||
| 755 | .read_ber = lgdt330x_read_ber, | ||
| 756 | .read_signal_strength = lgdt330x_read_signal_strength, | ||
| 757 | .read_snr = lgdt3302_read_snr, | ||
| 758 | .read_ucblocks = lgdt330x_read_ucblocks, | ||
| 759 | .release = lgdt330x_release, | ||
| 760 | }; | ||
| 761 | |||
| 762 | static struct dvb_frontend_ops lgdt3303_ops = { | ||
| 572 | .info = { | 763 | .info = { |
| 573 | .name= "LG Electronics lgdt330x VSB/QAM Frontend", | 764 | .name= "LG Electronics LGDT3303 VSB/QAM Frontend", |
| 574 | .type = FE_ATSC, | 765 | .type = FE_ATSC, |
| 575 | .frequency_min= 54000000, | 766 | .frequency_min= 54000000, |
| 576 | .frequency_max= 858000000, | 767 | .frequency_max= 858000000, |
| @@ -584,15 +775,15 @@ static struct dvb_frontend_ops lgdt330x_ops = { | |||
| 584 | .set_frontend = lgdt330x_set_parameters, | 775 | .set_frontend = lgdt330x_set_parameters, |
| 585 | .get_frontend = lgdt330x_get_frontend, | 776 | .get_frontend = lgdt330x_get_frontend, |
| 586 | .get_tune_settings = lgdt330x_get_tune_settings, | 777 | .get_tune_settings = lgdt330x_get_tune_settings, |
| 587 | .read_status = lgdt330x_read_status, | 778 | .read_status = lgdt3303_read_status, |
| 588 | .read_ber = lgdt330x_read_ber, | 779 | .read_ber = lgdt330x_read_ber, |
| 589 | .read_signal_strength = lgdt330x_read_signal_strength, | 780 | .read_signal_strength = lgdt330x_read_signal_strength, |
| 590 | .read_snr = lgdt330x_read_snr, | 781 | .read_snr = lgdt3303_read_snr, |
| 591 | .read_ucblocks = lgdt330x_read_ucblocks, | 782 | .read_ucblocks = lgdt330x_read_ucblocks, |
| 592 | .release = lgdt330x_release, | 783 | .release = lgdt330x_release, |
| 593 | }; | 784 | }; |
| 594 | 785 | ||
| 595 | MODULE_DESCRIPTION("lgdt330x [DViCO FusionHDTV 3 Gold] (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver"); | 786 | MODULE_DESCRIPTION("LGDT330X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver"); |
| 596 | MODULE_AUTHOR("Wilson Michaels"); | 787 | MODULE_AUTHOR("Wilson Michaels"); |
| 597 | MODULE_LICENSE("GPL"); | 788 | MODULE_LICENSE("GPL"); |
| 598 | 789 | ||
| @@ -601,6 +792,5 @@ EXPORT_SYMBOL(lgdt330x_attach); | |||
| 601 | /* | 792 | /* |
| 602 | * Local variables: | 793 | * Local variables: |
| 603 | * c-basic-offset: 8 | 794 | * c-basic-offset: 8 |
| 604 | * compile-command: "make DVB=1" | ||
| 605 | * End: | 795 | * End: |
| 606 | */ | 796 | */ |
diff --git a/drivers/media/dvb/frontends/lgdt330x.h b/drivers/media/dvb/frontends/lgdt330x.h index 04986f8e7565..e209ba1e47c5 100644 --- a/drivers/media/dvb/frontends/lgdt330x.h +++ b/drivers/media/dvb/frontends/lgdt330x.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Support for LGDT3302 & LGDT3303 (DViCO FustionHDTV Gold) - VSB/QAM | 2 | * Support for LGDT3302 and LGDT3303 - VSB/QAM |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.net> | 4 | * Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.net> |
| 5 | * | 5 | * |
| @@ -24,14 +24,26 @@ | |||
| 24 | 24 | ||
| 25 | #include <linux/dvb/frontend.h> | 25 | #include <linux/dvb/frontend.h> |
| 26 | 26 | ||
| 27 | typedef enum lg_chip_t { | ||
| 28 | UNDEFINED, | ||
| 29 | LGDT3302, | ||
| 30 | LGDT3303 | ||
| 31 | }lg_chip_type; | ||
| 32 | |||
| 27 | struct lgdt330x_config | 33 | struct lgdt330x_config |
| 28 | { | 34 | { |
| 29 | /* The demodulator's i2c address */ | 35 | /* The demodulator's i2c address */ |
| 30 | u8 demod_address; | 36 | u8 demod_address; |
| 31 | 37 | ||
| 38 | /* LG demodulator chip LGDT3302 or LGDT3303 */ | ||
| 39 | lg_chip_type demod_chip; | ||
| 40 | |||
| 41 | /* MPEG hardware interface - 0:parallel 1:serial */ | ||
| 42 | int serial_mpeg; | ||
| 43 | |||
| 32 | /* PLL interface */ | 44 | /* PLL interface */ |
| 33 | int (*pll_rf_set) (struct dvb_frontend* fe, int index); | 45 | int (*pll_rf_set) (struct dvb_frontend* fe, int index); |
| 34 | int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pll_address); | 46 | int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); |
| 35 | 47 | ||
| 36 | /* Need to set device param for start_dma */ | 48 | /* Need to set device param for start_dma */ |
| 37 | int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured); | 49 | int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured); |
diff --git a/drivers/media/dvb/frontends/lgdt330x_priv.h b/drivers/media/dvb/frontends/lgdt330x_priv.h index 4143ce8f1a95..59b7c5b9012d 100644 --- a/drivers/media/dvb/frontends/lgdt330x_priv.h +++ b/drivers/media/dvb/frontends/lgdt330x_priv.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Support for LGDT3302 & LGDT3303 (DViCO FustionHDTV Gold) - VSB/QAM | 2 | * Support for LGDT3302 and LGDT3303 - VSB/QAM |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.net> | 4 | * Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.net> |
| 5 | * | 5 | * |
| @@ -57,8 +57,10 @@ enum I2C_REG { | |||
| 57 | PH_ERR1= 0x4a, | 57 | PH_ERR1= 0x4a, |
| 58 | PH_ERR2= 0x4b, | 58 | PH_ERR2= 0x4b, |
| 59 | DEMUX_CONTROL= 0x66, | 59 | DEMUX_CONTROL= 0x66, |
| 60 | PACKET_ERR_COUNTER1= 0x6a, | 60 | LGDT3302_PACKET_ERR_COUNTER1= 0x6a, |
| 61 | PACKET_ERR_COUNTER2= 0x6b, | 61 | LGDT3302_PACKET_ERR_COUNTER2= 0x6b, |
| 62 | LGDT3303_PACKET_ERR_COUNTER1= 0x8b, | ||
| 63 | LGDT3303_PACKET_ERR_COUNTER2= 0x8c, | ||
| 62 | }; | 64 | }; |
| 63 | 65 | ||
| 64 | #endif /* _LGDT330X_PRIV_ */ | 66 | #endif /* _LGDT330X_PRIV_ */ |
diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 6c52fd0bb7df..a97b9b958ed6 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c | |||
| @@ -95,7 +95,7 @@ static int __devinit pvr_boot(struct bttv *btv); | |||
| 95 | static unsigned int triton1=0; | 95 | static unsigned int triton1=0; |
| 96 | static unsigned int vsfx=0; | 96 | static unsigned int vsfx=0; |
| 97 | static unsigned int latency = UNSET; | 97 | static unsigned int latency = UNSET; |
| 98 | static unsigned int no_overlay=-1; | 98 | int no_overlay=-1; |
| 99 | 99 | ||
| 100 | static unsigned int card[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; | 100 | static unsigned int card[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; |
| 101 | static unsigned int pll[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; | 101 | static unsigned int pll[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; |
| @@ -4296,9 +4296,11 @@ void __devinit bttv_check_chipset(void) | |||
| 4296 | printk(KERN_INFO "bttv: Host bridge needs VSFX enabled.\n"); | 4296 | printk(KERN_INFO "bttv: Host bridge needs VSFX enabled.\n"); |
| 4297 | if (pcipci_fail) { | 4297 | if (pcipci_fail) { |
| 4298 | printk(KERN_WARNING "bttv: BT848 and your chipset may not work together.\n"); | 4298 | printk(KERN_WARNING "bttv: BT848 and your chipset may not work together.\n"); |
| 4299 | if (UNSET == no_overlay) { | 4299 | if (!no_overlay) { |
| 4300 | printk(KERN_WARNING "bttv: going to disable overlay.\n"); | 4300 | printk(KERN_WARNING "bttv: overlay will be disabled.\n"); |
| 4301 | no_overlay = 1; | 4301 | no_overlay = 1; |
| 4302 | } else { | ||
| 4303 | printk(KERN_WARNING "bttv: overlay forced. Use this option at your own risk.\n"); | ||
| 4302 | } | 4304 | } |
| 4303 | } | 4305 | } |
| 4304 | if (UNSET != latency) | 4306 | if (UNSET != latency) |
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index 51a0f6d68e73..eee9322ce21b 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | $Id: bttv-driver.c,v 1.42 2005/07/05 17:37:35 nsh Exp $ | 2 | $Id: bttv-driver.c,v 1.52 2005/08/04 00:55:16 mchehab Exp $ |
| 3 | 3 | ||
| 4 | bttv - Bt848 frame grabber driver | 4 | bttv - Bt848 frame grabber driver |
| 5 | 5 | ||
| @@ -80,6 +80,7 @@ static unsigned int irq_iswitch = 0; | |||
| 80 | static unsigned int uv_ratio = 50; | 80 | static unsigned int uv_ratio = 50; |
| 81 | static unsigned int full_luma_range = 0; | 81 | static unsigned int full_luma_range = 0; |
| 82 | static unsigned int coring = 0; | 82 | static unsigned int coring = 0; |
| 83 | extern int no_overlay; | ||
| 83 | 84 | ||
| 84 | /* API features (turn on/off stuff for testing) */ | 85 | /* API features (turn on/off stuff for testing) */ |
| 85 | static unsigned int v4l2 = 1; | 86 | static unsigned int v4l2 = 1; |
| @@ -2151,6 +2152,10 @@ static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv, | |||
| 2151 | return 0; | 2152 | return 0; |
| 2152 | } | 2153 | } |
| 2153 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | 2154 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: |
| 2155 | if (no_overlay > 0) { | ||
| 2156 | printk ("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); | ||
| 2157 | return -EINVAL; | ||
| 2158 | } | ||
| 2154 | return setup_window(fh, btv, &f->fmt.win, 1); | 2159 | return setup_window(fh, btv, &f->fmt.win, 1); |
| 2155 | case V4L2_BUF_TYPE_VBI_CAPTURE: | 2160 | case V4L2_BUF_TYPE_VBI_CAPTURE: |
| 2156 | retval = bttv_switch_type(fh,f->type); | 2161 | retval = bttv_switch_type(fh,f->type); |
| @@ -2224,9 +2229,11 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, | |||
| 2224 | /* others */ | 2229 | /* others */ |
| 2225 | cap->type = VID_TYPE_CAPTURE| | 2230 | cap->type = VID_TYPE_CAPTURE| |
| 2226 | VID_TYPE_TUNER| | 2231 | VID_TYPE_TUNER| |
| 2227 | VID_TYPE_OVERLAY| | ||
| 2228 | VID_TYPE_CLIPPING| | 2232 | VID_TYPE_CLIPPING| |
| 2229 | VID_TYPE_SCALES; | 2233 | VID_TYPE_SCALES; |
| 2234 | if (no_overlay <= 0) | ||
| 2235 | cap->type |= VID_TYPE_OVERLAY; | ||
| 2236 | |||
| 2230 | cap->maxwidth = bttv_tvnorms[btv->tvnorm].swidth; | 2237 | cap->maxwidth = bttv_tvnorms[btv->tvnorm].swidth; |
| 2231 | cap->maxheight = bttv_tvnorms[btv->tvnorm].sheight; | 2238 | cap->maxheight = bttv_tvnorms[btv->tvnorm].sheight; |
| 2232 | cap->minwidth = 48; | 2239 | cap->minwidth = 48; |
| @@ -2302,6 +2309,11 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, | |||
| 2302 | struct video_window *win = arg; | 2309 | struct video_window *win = arg; |
| 2303 | struct v4l2_window w2; | 2310 | struct v4l2_window w2; |
| 2304 | 2311 | ||
| 2312 | if (no_overlay > 0) { | ||
| 2313 | printk ("VIDIOCSWIN: no_overlay\n"); | ||
| 2314 | return -EINVAL; | ||
| 2315 | } | ||
| 2316 | |||
| 2305 | w2.field = V4L2_FIELD_ANY; | 2317 | w2.field = V4L2_FIELD_ANY; |
| 2306 | w2.w.left = win->x; | 2318 | w2.w.left = win->x; |
| 2307 | w2.w.top = win->y; | 2319 | w2.w.top = win->y; |
| @@ -2577,10 +2589,12 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, | |||
| 2577 | cap->version = BTTV_VERSION_CODE; | 2589 | cap->version = BTTV_VERSION_CODE; |
| 2578 | cap->capabilities = | 2590 | cap->capabilities = |
| 2579 | V4L2_CAP_VIDEO_CAPTURE | | 2591 | V4L2_CAP_VIDEO_CAPTURE | |
| 2580 | V4L2_CAP_VIDEO_OVERLAY | | ||
| 2581 | V4L2_CAP_VBI_CAPTURE | | 2592 | V4L2_CAP_VBI_CAPTURE | |
| 2582 | V4L2_CAP_READWRITE | | 2593 | V4L2_CAP_READWRITE | |
| 2583 | V4L2_CAP_STREAMING; | 2594 | V4L2_CAP_STREAMING; |
| 2595 | if (no_overlay <= 0) | ||
| 2596 | cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY; | ||
| 2597 | |||
| 2584 | if (bttv_tvcards[btv->c.type].tuner != UNSET && | 2598 | if (bttv_tvcards[btv->c.type].tuner != UNSET && |
| 2585 | bttv_tvcards[btv->c.type].tuner != TUNER_ABSENT) | 2599 | bttv_tvcards[btv->c.type].tuner != TUNER_ABSENT) |
| 2586 | cap->capabilities |= V4L2_CAP_TUNER; | 2600 | cap->capabilities |= V4L2_CAP_TUNER; |
| @@ -3076,7 +3090,7 @@ static struct file_operations bttv_fops = | |||
| 3076 | static struct video_device bttv_video_template = | 3090 | static struct video_device bttv_video_template = |
| 3077 | { | 3091 | { |
| 3078 | .name = "UNSET", | 3092 | .name = "UNSET", |
| 3079 | .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_OVERLAY| | 3093 | .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER| |
| 3080 | VID_TYPE_CLIPPING|VID_TYPE_SCALES, | 3094 | VID_TYPE_CLIPPING|VID_TYPE_SCALES, |
| 3081 | .hardware = VID_HARDWARE_BT848, | 3095 | .hardware = VID_HARDWARE_BT848, |
| 3082 | .fops = &bttv_fops, | 3096 | .fops = &bttv_fops, |
| @@ -3756,6 +3770,12 @@ static void bttv_unregister_video(struct bttv *btv) | |||
| 3756 | /* register video4linux devices */ | 3770 | /* register video4linux devices */ |
| 3757 | static int __devinit bttv_register_video(struct bttv *btv) | 3771 | static int __devinit bttv_register_video(struct bttv *btv) |
| 3758 | { | 3772 | { |
| 3773 | if (no_overlay <= 0) { | ||
| 3774 | bttv_video_template.type |= VID_TYPE_OVERLAY; | ||
| 3775 | } else { | ||
| 3776 | printk("bttv: Overlay support disabled.\n"); | ||
| 3777 | } | ||
| 3778 | |||
| 3759 | /* video */ | 3779 | /* video */ |
| 3760 | btv->video_dev = vdev_init(btv, &bttv_video_template, "video"); | 3780 | btv->video_dev = vdev_init(btv, &bttv_video_template, "video"); |
| 3761 | if (NULL == btv->video_dev) | 3781 | if (NULL == btv->video_dev) |
| @@ -3869,11 +3889,6 @@ static int __devinit bttv_probe(struct pci_dev *dev, | |||
| 3869 | pci_set_master(dev); | 3889 | pci_set_master(dev); |
| 3870 | pci_set_command(dev); | 3890 | pci_set_command(dev); |
| 3871 | pci_set_drvdata(dev,btv); | 3891 | pci_set_drvdata(dev,btv); |
| 3872 | if (!pci_dma_supported(dev,0xffffffff)) { | ||
| 3873 | printk("bttv%d: Oops: no 32bit PCI DMA ???\n", btv->c.nr); | ||
| 3874 | result = -EIO; | ||
| 3875 | goto fail1; | ||
| 3876 | } | ||
| 3877 | 3892 | ||
| 3878 | pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision); | 3893 | pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision); |
| 3879 | pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); | 3894 | pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); |
diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h index 191eaf1714ba..f2af9e1454f0 100644 --- a/drivers/media/video/bttv.h +++ b/drivers/media/video/bttv.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * $Id: bttv.h,v 1.18 2005/05/24 23:41:42 nsh Exp $ | 2 | * $Id: bttv.h,v 1.22 2005/07/28 18:41:21 mchehab Exp $ |
| 3 | * | 3 | * |
| 4 | * bttv - Bt848 frame grabber driver | 4 | * bttv - Bt848 frame grabber driver |
| 5 | * | 5 | * |
| @@ -135,7 +135,9 @@ | |||
| 135 | #define BTTV_DVICO_DVBT_LITE 0x80 | 135 | #define BTTV_DVICO_DVBT_LITE 0x80 |
| 136 | #define BTTV_TIBET_CS16 0x83 | 136 | #define BTTV_TIBET_CS16 0x83 |
| 137 | #define BTTV_KODICOM_4400R 0x84 | 137 | #define BTTV_KODICOM_4400R 0x84 |
| 138 | #define BTTV_ADLINK_RTV24 0x85 | 138 | #define BTTV_ADLINK_RTV24 0x86 |
| 139 | #define BTTV_DVICO_FUSIONHDTV_5_LITE 0x87 | ||
| 140 | #define BTTV_ACORP_Y878F 0x88 | ||
| 139 | 141 | ||
| 140 | /* i2c address list */ | 142 | /* i2c address list */ |
| 141 | #define I2C_TSA5522 0xc2 | 143 | #define I2C_TSA5522 0xc2 |
diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h index f3293e4a15ad..aab094bc243d 100644 --- a/drivers/media/video/bttvp.h +++ b/drivers/media/video/bttvp.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | $Id: bttvp.h,v 1.19 2005/06/16 21:38:45 nsh Exp $ | 2 | $Id: bttvp.h,v 1.21 2005/07/15 21:44:14 mchehab Exp $ |
| 3 | 3 | ||
| 4 | bttv - Bt848 frame grabber driver | 4 | bttv - Bt848 frame grabber driver |
| 5 | 5 | ||
| @@ -27,7 +27,7 @@ | |||
| 27 | #define _BTTVP_H_ | 27 | #define _BTTVP_H_ |
| 28 | 28 | ||
| 29 | #include <linux/version.h> | 29 | #include <linux/version.h> |
| 30 | #define BTTV_VERSION_CODE KERNEL_VERSION(0,9,15) | 30 | #define BTTV_VERSION_CODE KERNEL_VERSION(0,9,16) |
| 31 | 31 | ||
| 32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
| 33 | #include <linux/wait.h> | 33 | #include <linux/wait.h> |
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 3d0c784b376f..ebf02a7f81e8 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * $Id: cx88-cards.c,v 1.86 2005/07/14 03:06:43 mchehab Exp $ | 2 | * $Id: cx88-cards.c,v 1.90 2005/07/28 02:47:42 mkrufky Exp $ |
| 3 | * | 3 | * |
| 4 | * device driver for Conexant 2388x based TV cards | 4 | * device driver for Conexant 2388x based TV cards |
| 5 | * card-specific stuff. | 5 | * card-specific stuff. |
| @@ -90,6 +90,9 @@ struct cx88_board cx88_boards[] = { | |||
| 90 | .input = {{ | 90 | .input = {{ |
| 91 | .type = CX88_VMUX_TELEVISION, | 91 | .type = CX88_VMUX_TELEVISION, |
| 92 | .vmux = 0, | 92 | .vmux = 0, |
| 93 | },{ | ||
| 94 | .type = CX88_VMUX_SVIDEO, | ||
| 95 | .vmux = 2, | ||
| 93 | }}, | 96 | }}, |
| 94 | }, | 97 | }, |
| 95 | [CX88_BOARD_PIXELVIEW] = { | 98 | [CX88_BOARD_PIXELVIEW] = { |
| @@ -496,6 +499,9 @@ struct cx88_board cx88_boards[] = { | |||
| 496 | .input = {{ | 499 | .input = {{ |
| 497 | .type = CX88_VMUX_DVB, | 500 | .type = CX88_VMUX_DVB, |
| 498 | .vmux = 0, | 501 | .vmux = 0, |
| 502 | },{ | ||
| 503 | .type = CX88_VMUX_SVIDEO, | ||
| 504 | .vmux = 2, | ||
| 499 | }}, | 505 | }}, |
| 500 | .dvb = 1, | 506 | .dvb = 1, |
| 501 | }, | 507 | }, |
| @@ -753,6 +759,27 @@ struct cx88_board cx88_boards[] = { | |||
| 753 | }}, | 759 | }}, |
| 754 | .dvb = 1, | 760 | .dvb = 1, |
| 755 | }, | 761 | }, |
| 762 | [CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD] = { | ||
| 763 | .name = "DViCO FusionHDTV 5 Gold", | ||
| 764 | .tuner_type = TUNER_LG_TDVS_H062F, | ||
| 765 | .radio_type = UNSET, | ||
| 766 | .tuner_addr = ADDR_UNSET, | ||
| 767 | .radio_addr = ADDR_UNSET, | ||
| 768 | /* See DViCO FusionHDTV 3 Gold-Q for GPIO documentation. */ | ||
| 769 | .input = {{ | ||
| 770 | .type = CX88_VMUX_TELEVISION, | ||
| 771 | .vmux = 0, | ||
| 772 | .gpio0 = 0x0f0d, | ||
| 773 | },{ | ||
| 774 | .type = CX88_VMUX_COMPOSITE1, | ||
| 775 | .vmux = 1, | ||
| 776 | .gpio0 = 0x0f00, | ||
| 777 | },{ | ||
| 778 | .type = CX88_VMUX_SVIDEO, | ||
| 779 | .vmux = 2, | ||
| 780 | .gpio0 = 0x0f00, | ||
| 781 | }}, | ||
| 782 | }, | ||
| 756 | }; | 783 | }; |
| 757 | const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); | 784 | const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); |
| 758 | 785 | ||
| @@ -880,6 +907,10 @@ struct cx88_subid cx88_subids[] = { | |||
| 880 | .subvendor = 0x153b, | 907 | .subvendor = 0x153b, |
| 881 | .subdevice = 0x1166, | 908 | .subdevice = 0x1166, |
| 882 | .card = CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1, | 909 | .card = CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1, |
| 910 | },{ | ||
| 911 | .subvendor = 0x18ac, | ||
| 912 | .subdevice = 0xd500, | ||
| 913 | .card = CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD, | ||
| 883 | }, | 914 | }, |
| 884 | }; | 915 | }; |
| 885 | const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids); | 916 | const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids); |
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index ef0e9a85c359..78d223257a68 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * $Id: cx88-dvb.c,v 1.54 2005/07/25 05:13:50 mkrufky Exp $ | 2 | * $Id: cx88-dvb.c,v 1.58 2005/08/07 09:24:08 mkrufky Exp $ |
| 3 | * | 3 | * |
| 4 | * device driver for Conexant 2388x based TV cards | 4 | * device driver for Conexant 2388x based TV cards |
| 5 | * MPEG Transport Stream (DVB) routines | 5 | * MPEG Transport Stream (DVB) routines |
| @@ -208,14 +208,26 @@ static struct or51132_config pchdtv_hd3000 = { | |||
| 208 | 208 | ||
| 209 | #ifdef HAVE_LGDT330X | 209 | #ifdef HAVE_LGDT330X |
| 210 | static int lgdt330x_pll_set(struct dvb_frontend* fe, | 210 | static int lgdt330x_pll_set(struct dvb_frontend* fe, |
| 211 | struct dvb_frontend_parameters* params, | 211 | struct dvb_frontend_parameters* params) |
| 212 | u8* pllbuf) | ||
| 213 | { | 212 | { |
| 214 | struct cx8802_dev *dev= fe->dvb->priv; | 213 | struct cx8802_dev *dev= fe->dvb->priv; |
| 214 | u8 buf[4]; | ||
| 215 | struct i2c_msg msg = | ||
| 216 | { .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 }; | ||
| 217 | int err; | ||
| 215 | 218 | ||
| 216 | pllbuf[0] = dev->core->pll_addr; | 219 | dvb_pll_configure(dev->core->pll_desc, buf, params->frequency, 0); |
| 217 | dvb_pll_configure(dev->core->pll_desc, &pllbuf[1], | 220 | dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n", |
| 218 | params->frequency, 0); | 221 | __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]); |
| 222 | if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { | ||
| 223 | printk(KERN_WARNING "cx88-dvb: %s error " | ||
| 224 | "(addr %02x <- %02x, err = %i)\n", | ||
| 225 | __FUNCTION__, buf[0], buf[1], err); | ||
| 226 | if (err < 0) | ||
| 227 | return err; | ||
| 228 | else | ||
| 229 | return -EREMOTEIO; | ||
| 230 | } | ||
| 219 | return 0; | 231 | return 0; |
| 220 | } | 232 | } |
| 221 | 233 | ||
| @@ -244,6 +256,8 @@ static int lgdt330x_set_ts_param(struct dvb_frontend* fe, int is_punctured) | |||
| 244 | 256 | ||
| 245 | static struct lgdt330x_config fusionhdtv_3_gold = { | 257 | static struct lgdt330x_config fusionhdtv_3_gold = { |
| 246 | .demod_address = 0x0e, | 258 | .demod_address = 0x0e, |
| 259 | .demod_chip = LGDT3302, | ||
| 260 | .serial_mpeg = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */ | ||
| 247 | .pll_set = lgdt330x_pll_set, | 261 | .pll_set = lgdt330x_pll_set, |
| 248 | .set_ts_params = lgdt330x_set_ts_param, | 262 | .set_ts_params = lgdt330x_set_ts_param, |
| 249 | }; | 263 | }; |
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 5588a3aeecb4..5f58c103198a 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * $Id: cx88-video.c,v 1.80 2005/07/13 08:49:08 mchehab Exp $ | 2 | * $Id: cx88-video.c,v 1.82 2005/07/22 05:13:34 mkrufky Exp $ |
| 3 | * | 3 | * |
| 4 | * device driver for Conexant 2388x based TV cards | 4 | * device driver for Conexant 2388x based TV cards |
| 5 | * video4linux video interface | 5 | * video4linux video interface |
| @@ -758,10 +758,10 @@ static int video_open(struct inode *inode, struct file *file) | |||
| 758 | struct cx88_core *core = dev->core; | 758 | struct cx88_core *core = dev->core; |
| 759 | int board = core->board; | 759 | int board = core->board; |
| 760 | dprintk(1,"video_open: setting radio device\n"); | 760 | dprintk(1,"video_open: setting radio device\n"); |
| 761 | cx_write(MO_GP3_IO, cx88_boards[board].radio.gpio3); | ||
| 761 | cx_write(MO_GP0_IO, cx88_boards[board].radio.gpio0); | 762 | cx_write(MO_GP0_IO, cx88_boards[board].radio.gpio0); |
| 762 | cx_write(MO_GP1_IO, cx88_boards[board].radio.gpio1); | 763 | cx_write(MO_GP1_IO, cx88_boards[board].radio.gpio1); |
| 763 | cx_write(MO_GP2_IO, cx88_boards[board].radio.gpio2); | 764 | cx_write(MO_GP2_IO, cx88_boards[board].radio.gpio2); |
| 764 | cx_write(MO_GP3_IO, cx88_boards[board].radio.gpio3); | ||
| 765 | dev->core->tvaudio = WW_FM; | 765 | dev->core->tvaudio = WW_FM; |
| 766 | cx88_set_tvaudio(core); | 766 | cx88_set_tvaudio(core); |
| 767 | cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1); | 767 | cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1); |
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index b008f7db6dfd..da65dc92787c 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * $Id: cx88.h,v 1.69 2005/07/13 17:25:25 mchehab Exp $ | 2 | * $Id: cx88.h,v 1.70 2005/07/24 17:44:09 mkrufky Exp $ |
| 3 | * | 3 | * |
| 4 | * v4l2 device driver for cx2388x based TV cards | 4 | * v4l2 device driver for cx2388x based TV cards |
| 5 | * | 5 | * |
| @@ -171,6 +171,7 @@ extern struct sram_channel cx88_sram_channels[]; | |||
| 171 | #define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T 28 | 171 | #define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T 28 |
| 172 | #define CX88_BOARD_ADSTECH_DVB_T_PCI 29 | 172 | #define CX88_BOARD_ADSTECH_DVB_T_PCI 29 |
| 173 | #define CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1 30 | 173 | #define CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1 30 |
| 174 | #define CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD 31 | ||
| 174 | 175 | ||
| 175 | enum cx88_itype { | 176 | enum cx88_itype { |
| 176 | CX88_VMUX_COMPOSITE1 = 1, | 177 | CX88_VMUX_COMPOSITE1 = 1, |
diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c index 6239254db27e..62f1b8ddb98b 100644 --- a/drivers/media/video/msp3400.c +++ b/drivers/media/video/msp3400.c | |||
| @@ -741,11 +741,9 @@ static int msp34xx_sleep(struct msp3400c *msp, int timeout) | |||
| 741 | schedule_timeout(msecs_to_jiffies(timeout)); | 741 | schedule_timeout(msecs_to_jiffies(timeout)); |
| 742 | } | 742 | } |
| 743 | } | 743 | } |
| 744 | if (current->flags & PF_FREEZE) { | ||
| 745 | refrigerator (); | ||
| 746 | } | ||
| 747 | 744 | ||
| 748 | remove_wait_queue(&msp->wq, &wait); | 745 | remove_wait_queue(&msp->wq, &wait); |
| 746 | try_to_freeze(); | ||
| 749 | return msp->restart; | 747 | return msp->restart; |
| 750 | } | 748 | } |
| 751 | 749 | ||
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index 93dd61978541..1203b93a572c 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * $Id: saa7134-i2c.c,v 1.19 2005/07/07 01:49:30 mkrufky Exp $ | 2 | * $Id: saa7134-i2c.c,v 1.22 2005/07/22 04:09:41 mkrufky Exp $ |
| 3 | * | 3 | * |
| 4 | * device driver for philips saa7134 based TV cards | 4 | * device driver for philips saa7134 based TV cards |
| 5 | * i2c interface support | 5 | * i2c interface support |
| @@ -300,6 +300,8 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap, | |||
| 300 | status = i2c_get_status(dev); | 300 | status = i2c_get_status(dev); |
| 301 | if (i2c_is_error(status)) | 301 | if (i2c_is_error(status)) |
| 302 | goto err; | 302 | goto err; |
| 303 | /* ensure that the bus is idle for at least one bit slot */ | ||
| 304 | msleep(1); | ||
| 303 | 305 | ||
| 304 | d1printk("\n"); | 306 | d1printk("\n"); |
| 305 | return num; | 307 | return num; |
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 6836c07794fc..2af0cb2a731b 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * $Id: saa7134.h,v 1.48 2005/07/01 08:22:24 nsh Exp $ | 2 | * $Id: saa7134.h,v 1.49 2005/07/13 17:25:25 mchehab Exp $ |
| 3 | * | 3 | * |
| 4 | * v4l2 device driver for philips saa7134 based TV cards | 4 | * v4l2 device driver for philips saa7134 based TV cards |
| 5 | * | 5 | * |
| @@ -21,7 +21,7 @@ | |||
| 21 | */ | 21 | */ |
| 22 | 22 | ||
| 23 | #include <linux/version.h> | 23 | #include <linux/version.h> |
| 24 | #define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,13) | 24 | #define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,14) |
| 25 | 25 | ||
| 26 | #include <linux/pci.h> | 26 | #include <linux/pci.h> |
| 27 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c index 4d27ac1b7fb8..cebcc1fa68d1 100644 --- a/drivers/media/video/tea5767.c +++ b/drivers/media/video/tea5767.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * For Philips TEA5767 FM Chip used on some TV Cards like Prolink Pixelview | 2 | * For Philips TEA5767 FM Chip used on some TV Cards like Prolink Pixelview |
| 3 | * I2C address is allways 0xC0. | 3 | * I2C address is allways 0xC0. |
| 4 | * | 4 | * |
| 5 | * $Id: tea5767.c,v 1.21 2005/07/14 03:06:43 mchehab Exp $ | 5 | * $Id: tea5767.c,v 1.27 2005/07/31 12:10:56 mchehab Exp $ |
| 6 | * | 6 | * |
| 7 | * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@brturbo.com.br) | 7 | * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@brturbo.com.br) |
| 8 | * This code is placed under the terms of the GNU General Public License | 8 | * This code is placed under the terms of the GNU General Public License |
| @@ -15,7 +15,6 @@ | |||
| 15 | #include <linux/videodev.h> | 15 | #include <linux/videodev.h> |
| 16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
| 17 | #include <media/tuner.h> | 17 | #include <media/tuner.h> |
| 18 | #include <media/tuner.h> | ||
| 19 | 18 | ||
| 20 | #define PREFIX "TEA5767 " | 19 | #define PREFIX "TEA5767 " |
| 21 | 20 | ||
| @@ -293,16 +292,16 @@ static int tea5767_stereo(struct i2c_client *c) | |||
| 293 | 292 | ||
| 294 | int tea5767_autodetection(struct i2c_client *c) | 293 | int tea5767_autodetection(struct i2c_client *c) |
| 295 | { | 294 | { |
| 296 | unsigned char buffer[5] = { 0xff, 0xff, 0xff, 0xff, 0xff }; | 295 | unsigned char buffer[7] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; |
| 297 | int rc; | 296 | int rc; |
| 298 | struct tuner *t = i2c_get_clientdata(c); | 297 | struct tuner *t = i2c_get_clientdata(c); |
| 299 | 298 | ||
| 300 | if (5 != (rc = i2c_master_recv(c, buffer, 5))) { | 299 | if (7 != (rc = i2c_master_recv(c, buffer, 7))) { |
| 301 | tuner_warn("It is not a TEA5767. Received %i bytes.\n", rc); | 300 | tuner_warn("It is not a TEA5767. Received %i bytes.\n", rc); |
| 302 | return EINVAL; | 301 | return EINVAL; |
| 303 | } | 302 | } |
| 304 | 303 | ||
| 305 | /* If all bytes are the same then it's a TV tuner and not a tea5767 chip. */ | 304 | /* If all bytes are the same then it's a TV tuner and not a tea5767 */ |
| 306 | if (buffer[0] == buffer[1] && buffer[0] == buffer[2] && | 305 | if (buffer[0] == buffer[1] && buffer[0] == buffer[2] && |
| 307 | buffer[0] == buffer[3] && buffer[0] == buffer[4]) { | 306 | buffer[0] == buffer[3] && buffer[0] == buffer[4]) { |
| 308 | tuner_warn("All bytes are equal. It is not a TEA5767\n"); | 307 | tuner_warn("All bytes are equal. It is not a TEA5767\n"); |
| @@ -318,6 +317,17 @@ int tea5767_autodetection(struct i2c_client *c) | |||
| 318 | tuner_warn("Chip ID is not zero. It is not a TEA5767\n"); | 317 | tuner_warn("Chip ID is not zero. It is not a TEA5767\n"); |
| 319 | return EINVAL; | 318 | return EINVAL; |
| 320 | } | 319 | } |
| 320 | /* It seems that tea5767 returns 0xff after the 5th byte */ | ||
| 321 | if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) { | ||
| 322 | tuner_warn("Returned more than 5 bytes. It is not a TEA5767\n"); | ||
| 323 | return EINVAL; | ||
| 324 | } | ||
| 325 | |||
| 326 | /* It seems that tea5767 returns 0xff after the 5th byte */ | ||
| 327 | if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) { | ||
| 328 | tuner_warn("Returned more than 5 bytes. It is not a TEA5767\n"); | ||
| 329 | return EINVAL; | ||
| 330 | } | ||
| 321 | 331 | ||
| 322 | tuner_warn("TEA5767 detected.\n"); | 332 | tuner_warn("TEA5767 detected.\n"); |
| 323 | return 0; | 333 | return 0; |
| @@ -327,10 +337,8 @@ int tea5767_tuner_init(struct i2c_client *c) | |||
| 327 | { | 337 | { |
| 328 | struct tuner *t = i2c_get_clientdata(c); | 338 | struct tuner *t = i2c_get_clientdata(c); |
| 329 | 339 | ||
| 330 | if (tea5767_autodetection(c) == EINVAL) | 340 | tuner_info("type set to %d (%s)\n", t->type, |
| 331 | return EINVAL; | 341 | "Philips TEA5767HN FM Radio"); |
| 332 | |||
| 333 | tuner_info("type set to %d (%s)\n", t->type, "Philips TEA5767HN FM Radio"); | ||
| 334 | strlcpy(c->name, "tea5767", sizeof(c->name)); | 342 | strlcpy(c->name, "tea5767", sizeof(c->name)); |
| 335 | 343 | ||
| 336 | t->tv_freq = set_tv_freq; | 344 | t->tv_freq = set_tv_freq; |
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index b25a9c08ac02..f0a579827a24 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * $Id: tuner-core.c,v 1.58 2005/07/14 03:06:43 mchehab Exp $ | 2 | * $Id: tuner-core.c,v 1.63 2005/07/28 18:19:55 mchehab Exp $ |
| 3 | * | 3 | * |
| 4 | * i2c tv tuner chip device driver | 4 | * i2c tv tuner chip device driver |
| 5 | * core core, i.e. kernel interfaces, registering and so on | 5 | * core core, i.e. kernel interfaces, registering and so on |
| @@ -23,6 +23,8 @@ | |||
| 23 | #include <media/tuner.h> | 23 | #include <media/tuner.h> |
| 24 | #include <media/audiochip.h> | 24 | #include <media/audiochip.h> |
| 25 | 25 | ||
| 26 | #include "msp3400.h" | ||
| 27 | |||
| 26 | #define UNSET (-1U) | 28 | #define UNSET (-1U) |
| 27 | 29 | ||
| 28 | /* standard i2c insmod options */ | 30 | /* standard i2c insmod options */ |
| @@ -42,6 +44,9 @@ module_param(addr, int, 0444); | |||
| 42 | static unsigned int no_autodetect = 0; | 44 | static unsigned int no_autodetect = 0; |
| 43 | module_param(no_autodetect, int, 0444); | 45 | module_param(no_autodetect, int, 0444); |
| 44 | 46 | ||
| 47 | static unsigned int show_i2c = 0; | ||
| 48 | module_param(show_i2c, int, 0444); | ||
| 49 | |||
| 45 | /* insmod options used at runtime => read/write */ | 50 | /* insmod options used at runtime => read/write */ |
| 46 | unsigned int tuner_debug = 0; | 51 | unsigned int tuner_debug = 0; |
| 47 | module_param(tuner_debug, int, 0644); | 52 | module_param(tuner_debug, int, 0644); |
| @@ -320,6 +325,17 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) | |||
| 320 | 325 | ||
| 321 | tuner_info("chip found @ 0x%x (%s)\n", addr << 1, adap->name); | 326 | tuner_info("chip found @ 0x%x (%s)\n", addr << 1, adap->name); |
| 322 | 327 | ||
| 328 | if (show_i2c) { | ||
| 329 | unsigned char buffer[16]; | ||
| 330 | int i,rc; | ||
| 331 | |||
| 332 | memset(buffer, 0, sizeof(buffer)); | ||
| 333 | rc = i2c_master_recv(&t->i2c, buffer, sizeof(buffer)); | ||
| 334 | printk("tuner-%04x I2C RECV = ",addr); | ||
| 335 | for (i=0;i<rc;i++) | ||
| 336 | printk("%02x ",buffer[i]); | ||
| 337 | printk("\n"); | ||
| 338 | } | ||
| 323 | /* TEA5767 autodetection code - only for addr = 0xc0 */ | 339 | /* TEA5767 autodetection code - only for addr = 0xc0 */ |
| 324 | if (!no_autodetect) { | 340 | if (!no_autodetect) { |
| 325 | if (addr == 0x60) { | 341 | if (addr == 0x60) { |
| @@ -451,6 +467,17 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
| 451 | break; | 467 | break; |
| 452 | } | 468 | } |
| 453 | break; | 469 | break; |
| 470 | case VIDIOCSAUDIO: | ||
| 471 | if (check_mode(t, "VIDIOCSAUDIO") == EINVAL) | ||
| 472 | return 0; | ||
| 473 | if (check_v4l2(t) == EINVAL) | ||
| 474 | return 0; | ||
| 475 | |||
| 476 | /* Should be implemented, since bttv calls it */ | ||
| 477 | tuner_dbg("VIDIOCSAUDIO not implemented.\n"); | ||
| 478 | |||
| 479 | break; | ||
| 480 | case MSP_SET_MATRIX: | ||
| 454 | case TDA9887_SET_CONFIG: | 481 | case TDA9887_SET_CONFIG: |
| 455 | break; | 482 | break; |
| 456 | /* --- v4l ioctls --- */ | 483 | /* --- v4l ioctls --- */ |
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index a3f8e83f5314..de0c93aeb75d 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * $Id: tuner-simple.c,v 1.39 2005/07/07 01:49:30 mkrufky Exp $ | 2 | * $Id: tuner-simple.c,v 1.43 2005/07/28 18:41:21 mchehab Exp $ |
| 3 | * | 3 | * |
| 4 | * i2c tv tuner chip device driver | 4 | * i2c tv tuner chip device driver |
| 5 | * controls all those simple 4-control-bytes style tuners. | 5 | * controls all those simple 4-control-bytes style tuners. |
| @@ -245,6 +245,12 @@ static struct tunertype tuners[] = { | |||
| 245 | /* see tea5767.c for details */}, | 245 | /* see tea5767.c for details */}, |
| 246 | { "Philips FMD1216ME MK3 Hybrid Tuner", Philips, PAL, | 246 | { "Philips FMD1216ME MK3 Hybrid Tuner", Philips, PAL, |
| 247 | 16*160.00,16*442.00,0x51,0x52,0x54,0x86,623 }, | 247 | 16*160.00,16*442.00,0x51,0x52,0x54,0x86,623 }, |
| 248 | |||
| 249 | { "LG TDVS-H062F/TUA6034", LGINNOTEK, NTSC, | ||
| 250 | 16*160.00,16*455.00,0x01,0x02,0x04,0x8e,732}, | ||
| 251 | |||
| 252 | { "Ymec TVF66T5-B/DFF", Philips, PAL, | ||
| 253 | 16*160.25,16*464.25,0x01,0x02,0x08,0x8e,623}, | ||
| 248 | }; | 254 | }; |
| 249 | 255 | ||
| 250 | unsigned const int tuner_count = ARRAY_SIZE(tuners); | 256 | unsigned const int tuner_count = ARRAY_SIZE(tuners); |
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 62b03ef091e0..127ec38ebd60 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c | |||
| @@ -189,7 +189,7 @@ hauppauge_tuner[] = | |||
| 189 | { TUNER_ABSENT, "Philips FQ1236 MK3"}, | 189 | { TUNER_ABSENT, "Philips FQ1236 MK3"}, |
| 190 | { TUNER_ABSENT, "Samsung TCPN 2121P30A"}, | 190 | { TUNER_ABSENT, "Samsung TCPN 2121P30A"}, |
| 191 | { TUNER_ABSENT, "Samsung TCPE 4121P30A"}, | 191 | { TUNER_ABSENT, "Samsung TCPE 4121P30A"}, |
| 192 | { TUNER_ABSENT, "TCL MFPE05 2"}, | 192 | { TUNER_PHILIPS_FM1216ME_MK3, "TCL MFPE05 2"}, |
| 193 | /* 90-99 */ | 193 | /* 90-99 */ |
| 194 | { TUNER_ABSENT, "LG TALN H202T"}, | 194 | { TUNER_ABSENT, "LG TALN H202T"}, |
| 195 | { TUNER_PHILIPS_FQ1216AME_MK4, "Philips FQ1216AME MK4"}, | 195 | { TUNER_PHILIPS_FQ1216AME_MK4, "Philips FQ1216AME MK4"}, |
diff --git a/drivers/message/i2o/Kconfig b/drivers/message/i2o/Kconfig index 06e8eb19a05c..43a942a29c2e 100644 --- a/drivers/message/i2o/Kconfig +++ b/drivers/message/i2o/Kconfig | |||
| @@ -53,6 +53,9 @@ config I2O_CONFIG | |||
| 53 | To compile this support as a module, choose M here: the | 53 | To compile this support as a module, choose M here: the |
| 54 | module will be called i2o_config. | 54 | module will be called i2o_config. |
| 55 | 55 | ||
| 56 | Note: If you want to use the new API you have to download the | ||
| 57 | i2o_config patch from http://i2o.shadowconnect.com/ | ||
| 58 | |||
| 56 | config I2O_CONFIG_OLD_IOCTL | 59 | config I2O_CONFIG_OLD_IOCTL |
| 57 | bool "Enable ioctls (OBSOLETE)" | 60 | bool "Enable ioctls (OBSOLETE)" |
| 58 | depends on I2O_CONFIG | 61 | depends on I2O_CONFIG |
diff --git a/drivers/message/i2o/config-osm.c b/drivers/message/i2o/config-osm.c index fe2e7afc9eae..af32ab4e90cd 100644 --- a/drivers/message/i2o/config-osm.c +++ b/drivers/message/i2o/config-osm.c | |||
| @@ -30,503 +30,9 @@ | |||
| 30 | 30 | ||
| 31 | static struct i2o_driver i2o_config_driver; | 31 | static struct i2o_driver i2o_config_driver; |
| 32 | 32 | ||
| 33 | /* Special file operations for sysfs */ | ||
| 34 | struct fops_attribute { | ||
| 35 | struct bin_attribute bin; | ||
| 36 | struct file_operations fops; | ||
| 37 | }; | ||
| 38 | |||
| 39 | /** | ||
| 40 | * sysfs_read_dummy | ||
| 41 | */ | ||
| 42 | static ssize_t sysfs_read_dummy(struct kobject *kobj, char *buf, loff_t offset, | ||
| 43 | size_t count) | ||
| 44 | { | ||
| 45 | return 0; | ||
| 46 | }; | ||
| 47 | |||
| 48 | /** | ||
| 49 | * sysfs_write_dummy | ||
| 50 | */ | ||
| 51 | static ssize_t sysfs_write_dummy(struct kobject *kobj, char *buf, loff_t offset, | ||
| 52 | size_t count) | ||
| 53 | { | ||
| 54 | return 0; | ||
| 55 | }; | ||
| 56 | |||
| 57 | /** | ||
| 58 | * sysfs_create_fops_file - Creates attribute with special file operations | ||
| 59 | * @kobj: kobject which should contains the attribute | ||
| 60 | * @attr: attributes which should be used to create file | ||
| 61 | * | ||
| 62 | * First creates attribute @attr in kobject @kobj. If it is the first time | ||
| 63 | * this function is called, merge old fops from sysfs with new one and | ||
| 64 | * write it back. Afterwords the new fops will be set for the created | ||
| 65 | * attribute. | ||
| 66 | * | ||
| 67 | * Returns 0 on success or negative error code on failure. | ||
| 68 | */ | ||
| 69 | static int sysfs_create_fops_file(struct kobject *kobj, | ||
| 70 | struct fops_attribute *attr) | ||
| 71 | { | ||
| 72 | struct file_operations tmp, *fops; | ||
| 73 | struct dentry *d; | ||
| 74 | struct qstr qstr; | ||
| 75 | int rc; | ||
| 76 | |||
| 77 | fops = &attr->fops; | ||
| 78 | |||
| 79 | if (fops->read) | ||
| 80 | attr->bin.read = sysfs_read_dummy; | ||
| 81 | |||
| 82 | if (fops->write) | ||
| 83 | attr->bin.write = sysfs_write_dummy; | ||
| 84 | |||
| 85 | if ((rc = sysfs_create_bin_file(kobj, &attr->bin))) | ||
| 86 | return rc; | ||
| 87 | |||
| 88 | qstr.name = attr->bin.attr.name; | ||
| 89 | qstr.len = strlen(qstr.name); | ||
| 90 | qstr.hash = full_name_hash(qstr.name, qstr.len); | ||
| 91 | |||
| 92 | if ((d = lookup_hash(&qstr, kobj->dentry))) { | ||
| 93 | if (!fops->owner) { | ||
| 94 | memcpy(&tmp, d->d_inode->i_fop, sizeof(tmp)); | ||
| 95 | if (fops->read) | ||
| 96 | tmp.read = fops->read; | ||
| 97 | if (fops->write) | ||
| 98 | tmp.write = fops->write; | ||
| 99 | memcpy(fops, &tmp, sizeof(tmp)); | ||
| 100 | } | ||
| 101 | |||
| 102 | d->d_inode->i_fop = fops; | ||
| 103 | } else | ||
| 104 | sysfs_remove_bin_file(kobj, &attr->bin); | ||
| 105 | |||
| 106 | return -ENOENT; | ||
| 107 | }; | ||
| 108 | |||
| 109 | /** | ||
| 110 | * sysfs_remove_fops_file - Remove attribute with special file operations | ||
| 111 | * @kobj: kobject which contains the attribute | ||
| 112 | * @attr: attributes which are used to create file | ||
| 113 | * | ||
| 114 | * Only wrapper arround sysfs_remove_bin_file() | ||
| 115 | * | ||
| 116 | * Returns 0 on success or negative error code on failure. | ||
| 117 | */ | ||
| 118 | static inline int sysfs_remove_fops_file(struct kobject *kobj, | ||
| 119 | struct fops_attribute *attr) | ||
| 120 | { | ||
| 121 | return sysfs_remove_bin_file(kobj, &attr->bin); | ||
| 122 | }; | ||
| 123 | |||
| 124 | /** | ||
| 125 | * i2o_config_read_hrt - Returns the HRT of the controller | ||
| 126 | * @kob: kernel object handle | ||
| 127 | * @buf: buffer into which the HRT should be copied | ||
| 128 | * @off: file offset | ||
| 129 | * @count: number of bytes to read | ||
| 130 | * | ||
| 131 | * Put @count bytes starting at @off into @buf from the HRT of the I2O | ||
| 132 | * controller corresponding to @kobj. | ||
| 133 | * | ||
| 134 | * Returns number of bytes copied into buffer. | ||
| 135 | */ | ||
| 136 | static ssize_t i2o_config_read_hrt(struct kobject *kobj, char *buf, | ||
| 137 | loff_t offset, size_t count) | ||
| 138 | { | ||
| 139 | struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop; | ||
| 140 | i2o_hrt *hrt = c->hrt.virt; | ||
| 141 | |||
| 142 | u32 size = (hrt->num_entries * hrt->entry_len + 2) * 4; | ||
| 143 | |||
| 144 | if (offset > size) | ||
| 145 | return 0; | ||
| 146 | |||
| 147 | if (offset + count > size) | ||
| 148 | count = size - offset; | ||
| 149 | |||
| 150 | memcpy(buf, (u8 *) hrt + offset, count); | ||
| 151 | |||
| 152 | return count; | ||
| 153 | }; | ||
| 154 | |||
| 155 | /** | ||
| 156 | * i2o_config_read_lct - Returns the LCT of the controller | ||
| 157 | * @kob: kernel object handle | ||
| 158 | * @buf: buffer into which the LCT should be copied | ||
| 159 | * @off: file offset | ||
| 160 | * @count: number of bytes to read | ||
| 161 | * | ||
| 162 | * Put @count bytes starting at @off into @buf from the LCT of the I2O | ||
| 163 | * controller corresponding to @kobj. | ||
| 164 | * | ||
| 165 | * Returns number of bytes copied into buffer. | ||
| 166 | */ | ||
| 167 | static ssize_t i2o_config_read_lct(struct kobject *kobj, char *buf, | ||
| 168 | loff_t offset, size_t count) | ||
| 169 | { | ||
| 170 | struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop; | ||
| 171 | u32 size = c->lct->table_size * 4; | ||
| 172 | |||
| 173 | if (offset > size) | ||
| 174 | return 0; | ||
| 175 | |||
| 176 | if (offset + count > size) | ||
| 177 | count = size - offset; | ||
| 178 | |||
| 179 | memcpy(buf, (u8 *) c->lct + offset, count); | ||
| 180 | |||
| 181 | return count; | ||
| 182 | }; | ||
| 183 | |||
| 184 | #define I2O_CONFIG_SW_ATTR(_name,_mode,_type,_swid) \ | ||
| 185 | static ssize_t i2o_config_##_name##_read(struct file *file, char __user *buf, size_t count, loff_t * offset) { \ | ||
| 186 | return i2o_config_sw_read(file, buf, count, offset, _type, _swid); \ | ||
| 187 | };\ | ||
| 188 | \ | ||
| 189 | static ssize_t i2o_config_##_name##_write(struct file *file, const char __user *buf, size_t count, loff_t * offset) { \ | ||
| 190 | return i2o_config_sw_write(file, buf, count, offset, _type, _swid); \ | ||
| 191 | }; \ | ||
| 192 | \ | ||
| 193 | static struct fops_attribute i2o_config_attr_##_name = { \ | ||
| 194 | .bin = { .attr = { .name = __stringify(_name), .mode = _mode, \ | ||
| 195 | .owner = THIS_MODULE }, \ | ||
| 196 | .size = 0, }, \ | ||
| 197 | .fops = { .write = i2o_config_##_name##_write, \ | ||
| 198 | .read = i2o_config_##_name##_read} \ | ||
| 199 | }; | ||
| 200 | |||
| 201 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
| 202 | |||
| 203 | /** | ||
| 204 | * i2o_config_dpt_reagion - Converts type and id to flash region | ||
| 205 | * @swtype: type of software module reading | ||
| 206 | * @swid: id of software which should be read | ||
| 207 | * | ||
| 208 | * Converts type and id from I2O spec to the matching region for DPT / | ||
| 209 | * Adaptec controllers. | ||
| 210 | * | ||
| 211 | * Returns region which match type and id or -1 on error. | ||
| 212 | */ | ||
| 213 | static u32 i2o_config_dpt_region(u8 swtype, u8 swid) | ||
| 214 | { | ||
| 215 | switch (swtype) { | ||
| 216 | case I2O_SOFTWARE_MODULE_IRTOS: | ||
| 217 | /* | ||
| 218 | * content: operation firmware | ||
| 219 | * region size: | ||
| 220 | * 0xbc000 for 2554, 3754, 2564, 3757 | ||
| 221 | * 0x170000 for 2865 | ||
| 222 | * 0x17c000 for 3966 | ||
| 223 | */ | ||
| 224 | if (!swid) | ||
| 225 | return 0; | ||
| 226 | |||
| 227 | break; | ||
| 228 | |||
| 229 | case I2O_SOFTWARE_MODULE_IOP_PRIVATE: | ||
| 230 | /* | ||
| 231 | * content: BIOS and SMOR | ||
| 232 | * BIOS size: first 0x8000 bytes | ||
| 233 | * region size: | ||
| 234 | * 0x40000 for 2554, 3754, 2564, 3757 | ||
| 235 | * 0x80000 for 2865, 3966 | ||
| 236 | */ | ||
| 237 | if (!swid) | ||
| 238 | return 1; | ||
| 239 | |||
| 240 | break; | ||
| 241 | |||
| 242 | case I2O_SOFTWARE_MODULE_IOP_CONFIG: | ||
| 243 | switch (swid) { | ||
| 244 | case 0: | ||
| 245 | /* | ||
| 246 | * content: NVRAM defaults | ||
| 247 | * region size: 0x2000 bytes | ||
| 248 | */ | ||
| 249 | return 2; | ||
| 250 | case 1: | ||
| 251 | /* | ||
| 252 | * content: serial number | ||
| 253 | * region size: 0x2000 bytes | ||
| 254 | */ | ||
| 255 | return 3; | ||
| 256 | } | ||
| 257 | break; | ||
| 258 | } | ||
| 259 | |||
| 260 | return -1; | ||
| 261 | }; | ||
| 262 | |||
| 263 | #endif | ||
| 264 | |||
| 265 | /** | ||
| 266 | * i2o_config_sw_read - Read a software module from controller | ||
| 267 | * @file: file pointer | ||
| 268 | * @buf: buffer into which the data should be copied | ||
| 269 | * @count: number of bytes to read | ||
| 270 | * @off: file offset | ||
| 271 | * @swtype: type of software module reading | ||
| 272 | * @swid: id of software which should be read | ||
| 273 | * | ||
| 274 | * Transfers @count bytes at offset @offset from IOP into buffer using | ||
| 275 | * type @swtype and id @swid as described in I2O spec. | ||
| 276 | * | ||
| 277 | * Returns number of bytes copied into buffer or error code on failure. | ||
| 278 | */ | ||
| 279 | static ssize_t i2o_config_sw_read(struct file *file, char __user * buf, | ||
| 280 | size_t count, loff_t * offset, u8 swtype, | ||
| 281 | u32 swid) | ||
| 282 | { | ||
| 283 | struct sysfs_dirent *sd = file->f_dentry->d_parent->d_fsdata; | ||
| 284 | struct kobject *kobj = sd->s_element; | ||
| 285 | struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop; | ||
| 286 | u32 m, function = I2O_CMD_SW_UPLOAD; | ||
| 287 | struct i2o_dma buffer; | ||
| 288 | struct i2o_message __iomem *msg; | ||
| 289 | u32 __iomem *mptr; | ||
| 290 | int rc, status; | ||
| 291 | |||
| 292 | m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); | ||
| 293 | if (m == I2O_QUEUE_EMPTY) | ||
| 294 | return -EBUSY; | ||
| 295 | |||
| 296 | mptr = &msg->body[3]; | ||
| 297 | |||
| 298 | if ((rc = i2o_dma_alloc(&c->pdev->dev, &buffer, count, GFP_KERNEL))) { | ||
| 299 | i2o_msg_nop(c, m); | ||
| 300 | return rc; | ||
| 301 | } | ||
| 302 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
| 303 | if (c->adaptec) { | ||
| 304 | mptr = &msg->body[4]; | ||
| 305 | function = I2O_CMD_PRIVATE; | ||
| 306 | |||
| 307 | writel(TEN_WORD_MSG_SIZE | SGL_OFFSET_8, &msg->u.head[0]); | ||
| 308 | |||
| 309 | writel(I2O_VENDOR_DPT << 16 | I2O_DPT_FLASH_READ, | ||
| 310 | &msg->body[0]); | ||
| 311 | writel(i2o_config_dpt_region(swtype, swid), &msg->body[1]); | ||
| 312 | writel(*offset, &msg->body[2]); | ||
| 313 | writel(count, &msg->body[3]); | ||
| 314 | } else | ||
| 315 | #endif | ||
| 316 | writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]); | ||
| 317 | |||
| 318 | writel(0xD0000000 | count, mptr++); | ||
| 319 | writel(buffer.phys, mptr); | ||
| 320 | |||
| 321 | writel(function << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]); | ||
| 322 | writel(i2o_config_driver.context, &msg->u.head[2]); | ||
| 323 | writel(0, &msg->u.head[3]); | ||
| 324 | |||
| 325 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
| 326 | if (!c->adaptec) | ||
| 327 | #endif | ||
| 328 | { | ||
| 329 | writel((u32) swtype << 16 | (u32) 1 << 8, &msg->body[0]); | ||
| 330 | writel(0, &msg->body[1]); | ||
| 331 | writel(swid, &msg->body[2]); | ||
| 332 | } | ||
| 333 | |||
| 334 | status = i2o_msg_post_wait_mem(c, m, 60, &buffer); | ||
| 335 | |||
| 336 | if (status == I2O_POST_WAIT_OK) { | ||
| 337 | if (!(rc = copy_to_user(buf, buffer.virt, count))) { | ||
| 338 | rc = count; | ||
| 339 | *offset += count; | ||
| 340 | } | ||
| 341 | } else | ||
| 342 | rc = -EIO; | ||
| 343 | |||
| 344 | if (status != -ETIMEDOUT) | ||
| 345 | i2o_dma_free(&c->pdev->dev, &buffer); | ||
| 346 | |||
| 347 | return rc; | ||
| 348 | }; | ||
| 349 | |||
| 350 | /** | ||
| 351 | * i2o_config_sw_write - Write a software module to controller | ||
| 352 | * @file: file pointer | ||
| 353 | * @buf: buffer into which the data should be copied | ||
| 354 | * @count: number of bytes to read | ||
| 355 | * @off: file offset | ||
| 356 | * @swtype: type of software module writing | ||
| 357 | * @swid: id of software which should be written | ||
| 358 | * | ||
| 359 | * Transfers @count bytes at offset @offset from buffer to IOP using | ||
| 360 | * type @swtype and id @swid as described in I2O spec. | ||
| 361 | * | ||
| 362 | * Returns number of bytes copied from buffer or error code on failure. | ||
| 363 | */ | ||
| 364 | static ssize_t i2o_config_sw_write(struct file *file, const char __user * buf, | ||
| 365 | size_t count, loff_t * offset, u8 swtype, | ||
| 366 | u32 swid) | ||
| 367 | { | ||
| 368 | struct sysfs_dirent *sd = file->f_dentry->d_parent->d_fsdata; | ||
| 369 | struct kobject *kobj = sd->s_element; | ||
| 370 | struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop; | ||
| 371 | u32 m, function = I2O_CMD_SW_DOWNLOAD; | ||
| 372 | struct i2o_dma buffer; | ||
| 373 | struct i2o_message __iomem *msg; | ||
| 374 | u32 __iomem *mptr; | ||
| 375 | int rc, status; | ||
| 376 | |||
| 377 | m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); | ||
| 378 | if (m == I2O_QUEUE_EMPTY) | ||
| 379 | return -EBUSY; | ||
| 380 | |||
| 381 | mptr = &msg->body[3]; | ||
| 382 | |||
| 383 | if ((rc = i2o_dma_alloc(&c->pdev->dev, &buffer, count, GFP_KERNEL))) | ||
| 384 | goto nop_msg; | ||
| 385 | |||
| 386 | if ((rc = copy_from_user(buffer.virt, buf, count))) | ||
| 387 | goto free_buffer; | ||
| 388 | |||
| 389 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
| 390 | if (c->adaptec) { | ||
| 391 | mptr = &msg->body[4]; | ||
| 392 | function = I2O_CMD_PRIVATE; | ||
| 393 | |||
| 394 | writel(TEN_WORD_MSG_SIZE | SGL_OFFSET_8, &msg->u.head[0]); | ||
| 395 | |||
| 396 | writel(I2O_VENDOR_DPT << 16 | I2O_DPT_FLASH_WRITE, | ||
| 397 | &msg->body[0]); | ||
| 398 | writel(i2o_config_dpt_region(swtype, swid), &msg->body[1]); | ||
| 399 | writel(*offset, &msg->body[2]); | ||
| 400 | writel(count, &msg->body[3]); | ||
| 401 | } else | ||
| 402 | #endif | ||
| 403 | writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]); | ||
| 404 | |||
| 405 | writel(0xD4000000 | count, mptr++); | ||
| 406 | writel(buffer.phys, mptr); | ||
| 407 | |||
| 408 | writel(function << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]); | ||
| 409 | writel(i2o_config_driver.context, &msg->u.head[2]); | ||
| 410 | writel(0, &msg->u.head[3]); | ||
| 411 | |||
| 412 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
| 413 | if (!c->adaptec) | ||
| 414 | #endif | ||
| 415 | { | ||
| 416 | writel((u32) swtype << 16 | (u32) 1 << 8, &msg->body[0]); | ||
| 417 | writel(0, &msg->body[1]); | ||
| 418 | writel(swid, &msg->body[2]); | ||
| 419 | } | ||
| 420 | |||
| 421 | status = i2o_msg_post_wait_mem(c, m, 60, &buffer); | ||
| 422 | |||
| 423 | if (status != -ETIMEDOUT) | ||
| 424 | i2o_dma_free(&c->pdev->dev, &buffer); | ||
| 425 | |||
| 426 | if (status != I2O_POST_WAIT_OK) | ||
| 427 | return -EIO; | ||
| 428 | |||
| 429 | *offset += count; | ||
| 430 | |||
| 431 | return count; | ||
| 432 | |||
| 433 | free_buffer: | ||
| 434 | i2o_dma_free(&c->pdev->dev, &buffer); | ||
| 435 | |||
| 436 | nop_msg: | ||
| 437 | i2o_msg_nop(c, m); | ||
| 438 | |||
| 439 | return rc; | ||
| 440 | }; | ||
| 441 | |||
| 442 | /* attribute for HRT in sysfs */ | ||
| 443 | static struct bin_attribute i2o_config_hrt_attr = { | ||
| 444 | .attr = { | ||
| 445 | .name = "hrt", | ||
| 446 | .mode = S_IRUGO, | ||
| 447 | .owner = THIS_MODULE}, | ||
| 448 | .size = 0, | ||
| 449 | .read = i2o_config_read_hrt | ||
| 450 | }; | ||
| 451 | |||
| 452 | /* attribute for LCT in sysfs */ | ||
| 453 | static struct bin_attribute i2o_config_lct_attr = { | ||
| 454 | .attr = { | ||
| 455 | .name = "lct", | ||
| 456 | .mode = S_IRUGO, | ||
| 457 | .owner = THIS_MODULE}, | ||
| 458 | .size = 0, | ||
| 459 | .read = i2o_config_read_lct | ||
| 460 | }; | ||
| 461 | |||
| 462 | /* IRTOS firmware access */ | ||
| 463 | I2O_CONFIG_SW_ATTR(irtos, S_IWRSR, I2O_SOFTWARE_MODULE_IRTOS, 0); | ||
| 464 | |||
| 465 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
| 466 | |||
| 467 | /* | ||
| 468 | * attribute for BIOS / SMOR, nvram and serial number access on DPT / Adaptec | ||
| 469 | * controllers | ||
| 470 | */ | ||
| 471 | I2O_CONFIG_SW_ATTR(bios, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_PRIVATE, 0); | ||
| 472 | I2O_CONFIG_SW_ATTR(nvram, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_CONFIG, 0); | ||
| 473 | I2O_CONFIG_SW_ATTR(serial, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_CONFIG, 1); | ||
| 474 | |||
| 475 | #endif | ||
| 476 | |||
| 477 | /** | ||
| 478 | * i2o_config_notify_controller_add - Notify of added controller | ||
| 479 | * @c: the controller which was added | ||
| 480 | * | ||
| 481 | * If a I2O controller is added, we catch the notification to add sysfs | ||
| 482 | * entries. | ||
| 483 | */ | ||
| 484 | static void i2o_config_notify_controller_add(struct i2o_controller *c) | ||
| 485 | { | ||
| 486 | struct kobject *kobj = &c->exec->device.kobj; | ||
| 487 | |||
| 488 | sysfs_create_bin_file(kobj, &i2o_config_hrt_attr); | ||
| 489 | sysfs_create_bin_file(kobj, &i2o_config_lct_attr); | ||
| 490 | |||
| 491 | sysfs_create_fops_file(kobj, &i2o_config_attr_irtos); | ||
| 492 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
| 493 | if (c->adaptec) { | ||
| 494 | sysfs_create_fops_file(kobj, &i2o_config_attr_bios); | ||
| 495 | sysfs_create_fops_file(kobj, &i2o_config_attr_nvram); | ||
| 496 | sysfs_create_fops_file(kobj, &i2o_config_attr_serial); | ||
| 497 | } | ||
| 498 | #endif | ||
| 499 | }; | ||
| 500 | |||
| 501 | /** | ||
| 502 | * i2o_config_notify_controller_remove - Notify of removed controller | ||
| 503 | * @c: the controller which was removed | ||
| 504 | * | ||
| 505 | * If a I2O controller is removed, we catch the notification to remove the | ||
| 506 | * sysfs entries. | ||
| 507 | */ | ||
| 508 | static void i2o_config_notify_controller_remove(struct i2o_controller *c) | ||
| 509 | { | ||
| 510 | struct kobject *kobj = &c->exec->device.kobj; | ||
| 511 | |||
| 512 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
| 513 | if (c->adaptec) { | ||
| 514 | sysfs_remove_fops_file(kobj, &i2o_config_attr_serial); | ||
| 515 | sysfs_remove_fops_file(kobj, &i2o_config_attr_nvram); | ||
| 516 | sysfs_remove_fops_file(kobj, &i2o_config_attr_bios); | ||
| 517 | } | ||
| 518 | #endif | ||
| 519 | sysfs_remove_fops_file(kobj, &i2o_config_attr_irtos); | ||
| 520 | |||
| 521 | sysfs_remove_bin_file(kobj, &i2o_config_lct_attr); | ||
| 522 | sysfs_remove_bin_file(kobj, &i2o_config_hrt_attr); | ||
| 523 | }; | ||
| 524 | |||
| 525 | /* Config OSM driver struct */ | 33 | /* Config OSM driver struct */ |
| 526 | static struct i2o_driver i2o_config_driver = { | 34 | static struct i2o_driver i2o_config_driver = { |
| 527 | .name = OSM_NAME, | 35 | .name = OSM_NAME, |
| 528 | .notify_controller_add = i2o_config_notify_controller_add, | ||
| 529 | .notify_controller_remove = i2o_config_notify_controller_remove | ||
| 530 | }; | 36 | }; |
| 531 | 37 | ||
| 532 | #ifdef CONFIG_I2O_CONFIG_OLD_IOCTL | 38 | #ifdef CONFIG_I2O_CONFIG_OLD_IOCTL |
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c index 7a60fd7be8ad..66c03e882570 100644 --- a/drivers/message/i2o/pci.c +++ b/drivers/message/i2o/pci.c | |||
| @@ -32,6 +32,8 @@ | |||
| 32 | #include <linux/i2o.h> | 32 | #include <linux/i2o.h> |
| 33 | #include "core.h" | 33 | #include "core.h" |
| 34 | 34 | ||
| 35 | #define OSM_DESCRIPTION "I2O-subsystem" | ||
| 36 | |||
| 35 | /* PCI device id table for all I2O controllers */ | 37 | /* PCI device id table for all I2O controllers */ |
| 36 | static struct pci_device_id __devinitdata i2o_pci_ids[] = { | 38 | static struct pci_device_id __devinitdata i2o_pci_ids[] = { |
| 37 | {PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)}, | 39 | {PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)}, |
| @@ -66,6 +68,8 @@ static void i2o_pci_free(struct i2o_controller *c) | |||
| 66 | 68 | ||
| 67 | if (c->base.virt) | 69 | if (c->base.virt) |
| 68 | iounmap(c->base.virt); | 70 | iounmap(c->base.virt); |
| 71 | |||
| 72 | pci_release_regions(c->pdev); | ||
| 69 | } | 73 | } |
| 70 | 74 | ||
| 71 | /** | 75 | /** |
| @@ -84,6 +88,11 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) | |||
| 84 | struct device *dev = &pdev->dev; | 88 | struct device *dev = &pdev->dev; |
| 85 | int i; | 89 | int i; |
| 86 | 90 | ||
| 91 | if (pci_request_regions(pdev, OSM_DESCRIPTION)) { | ||
| 92 | printk(KERN_ERR "%s: device already claimed\n", c->name); | ||
| 93 | return -ENODEV; | ||
| 94 | } | ||
| 95 | |||
| 87 | for (i = 0; i < 6; i++) { | 96 | for (i = 0; i < 6; i++) { |
| 88 | /* Skip I/O spaces */ | 97 | /* Skip I/O spaces */ |
| 89 | if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) { | 98 | if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) { |
| @@ -138,6 +147,7 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) | |||
| 138 | c->base.virt = ioremap_nocache(c->base.phys, c->base.len); | 147 | c->base.virt = ioremap_nocache(c->base.phys, c->base.len); |
| 139 | if (!c->base.virt) { | 148 | if (!c->base.virt) { |
| 140 | printk(KERN_ERR "%s: Unable to map controller.\n", c->name); | 149 | printk(KERN_ERR "%s: Unable to map controller.\n", c->name); |
| 150 | i2o_pci_free(c); | ||
| 141 | return -ENOMEM; | 151 | return -ENOMEM; |
| 142 | } | 152 | } |
| 143 | 153 | ||
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c index 8b487ed1069c..974f2f36bdbe 100644 --- a/drivers/mmc/wbsd.c +++ b/drivers/mmc/wbsd.c | |||
| @@ -42,7 +42,7 @@ | |||
| 42 | #include "wbsd.h" | 42 | #include "wbsd.h" |
| 43 | 43 | ||
| 44 | #define DRIVER_NAME "wbsd" | 44 | #define DRIVER_NAME "wbsd" |
| 45 | #define DRIVER_VERSION "1.2" | 45 | #define DRIVER_VERSION "1.3" |
| 46 | 46 | ||
| 47 | #ifdef CONFIG_MMC_DEBUG | 47 | #ifdef CONFIG_MMC_DEBUG |
| 48 | #define DBG(x...) \ | 48 | #define DBG(x...) \ |
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index 2c6dc24c3728..b780307093eb 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c | |||
| @@ -417,6 +417,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) | |||
| 417 | struct net_local *lp = netdev_priv(dev); | 417 | struct net_local *lp = netdev_priv(dev); |
| 418 | static unsigned version_printed; | 418 | static unsigned version_printed; |
| 419 | int i; | 419 | int i; |
| 420 | int tmp; | ||
| 420 | unsigned rev_type = 0; | 421 | unsigned rev_type = 0; |
| 421 | int eeprom_buff[CHKSUM_LEN]; | 422 | int eeprom_buff[CHKSUM_LEN]; |
| 422 | int retval; | 423 | int retval; |
| @@ -492,14 +493,17 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) | |||
| 492 | goto out2; | 493 | goto out2; |
| 493 | } | 494 | } |
| 494 | } | 495 | } |
| 495 | printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT)); | 496 | printk(KERN_DEBUG "PP_addr at %x: 0x%x\n", |
| 497 | ioaddr + ADD_PORT, inw(ioaddr + ADD_PORT)); | ||
| 496 | 498 | ||
| 497 | ioaddr &= ~3; | 499 | ioaddr &= ~3; |
| 498 | outw(PP_ChipID, ioaddr + ADD_PORT); | 500 | outw(PP_ChipID, ioaddr + ADD_PORT); |
| 499 | 501 | ||
| 500 | if (inw(ioaddr + DATA_PORT) != CHIP_EISA_ID_SIG) { | 502 | tmp = inw(ioaddr + DATA_PORT); |
| 501 | printk(KERN_ERR "%s: incorrect signature 0x%x\n", | 503 | if (tmp != CHIP_EISA_ID_SIG) { |
| 502 | dev->name, inw(ioaddr + DATA_PORT)); | 504 | printk(KERN_DEBUG "%s: incorrect signature at %x: 0x%x!=" |
| 505 | CHIP_EISA_ID_SIG_STR "\n", | ||
| 506 | dev->name, ioaddr + DATA_PORT, tmp); | ||
| 503 | retval = -ENODEV; | 507 | retval = -ENODEV; |
| 504 | goto out2; | 508 | goto out2; |
| 505 | } | 509 | } |
diff --git a/drivers/net/cs89x0.h b/drivers/net/cs89x0.h index bd3ad8e6cce9..decea264f121 100644 --- a/drivers/net/cs89x0.h +++ b/drivers/net/cs89x0.h | |||
| @@ -93,6 +93,7 @@ | |||
| 93 | #endif | 93 | #endif |
| 94 | 94 | ||
| 95 | #define CHIP_EISA_ID_SIG 0x630E /* Product ID Code for Crystal Chip (CS8900 spec 4.3) */ | 95 | #define CHIP_EISA_ID_SIG 0x630E /* Product ID Code for Crystal Chip (CS8900 spec 4.3) */ |
| 96 | #define CHIP_EISA_ID_SIG_STR "0x630E" | ||
| 96 | 97 | ||
| 97 | #ifdef IBMEIPKT | 98 | #ifdef IBMEIPKT |
| 98 | #define EISA_ID_SIG 0x4D24 /* IBM */ | 99 | #define EISA_ID_SIG 0x4D24 /* IBM */ |
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 5e5d2c3c7ce4..b82fd15d0891 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
| @@ -3789,6 +3789,7 @@ e1000_netpoll(struct net_device *netdev) | |||
| 3789 | struct e1000_adapter *adapter = netdev_priv(netdev); | 3789 | struct e1000_adapter *adapter = netdev_priv(netdev); |
| 3790 | disable_irq(adapter->pdev->irq); | 3790 | disable_irq(adapter->pdev->irq); |
| 3791 | e1000_intr(adapter->pdev->irq, netdev, NULL); | 3791 | e1000_intr(adapter->pdev->irq, netdev, NULL); |
| 3792 | e1000_clean_tx_irq(adapter); | ||
| 3792 | enable_irq(adapter->pdev->irq); | 3793 | enable_irq(adapter->pdev->irq); |
| 3793 | } | 3794 | } |
| 3794 | #endif | 3795 | #endif |
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index e44f8e9055ef..f9e3be96963c 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c | |||
| @@ -130,12 +130,11 @@ struct sixpack { | |||
| 130 | 130 | ||
| 131 | #define AX25_6PACK_HEADER_LEN 0 | 131 | #define AX25_6PACK_HEADER_LEN 0 |
| 132 | 132 | ||
| 133 | static void sp_start_tx_timer(struct sixpack *); | ||
| 134 | static void sixpack_decode(struct sixpack *, unsigned char[], int); | 133 | static void sixpack_decode(struct sixpack *, unsigned char[], int); |
| 135 | static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char); | 134 | static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char); |
| 136 | 135 | ||
| 137 | /* | 136 | /* |
| 138 | * perform the persistence/slottime algorithm for CSMA access. If the | 137 | * Perform the persistence/slottime algorithm for CSMA access. If the |
| 139 | * persistence check was successful, write the data to the serial driver. | 138 | * persistence check was successful, write the data to the serial driver. |
| 140 | * Note that in case of DAMA operation, the data is not sent here. | 139 | * Note that in case of DAMA operation, the data is not sent here. |
| 141 | */ | 140 | */ |
| @@ -143,7 +142,7 @@ static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char); | |||
| 143 | static void sp_xmit_on_air(unsigned long channel) | 142 | static void sp_xmit_on_air(unsigned long channel) |
| 144 | { | 143 | { |
| 145 | struct sixpack *sp = (struct sixpack *) channel; | 144 | struct sixpack *sp = (struct sixpack *) channel; |
| 146 | int actual; | 145 | int actual, when = sp->slottime; |
| 147 | static unsigned char random; | 146 | static unsigned char random; |
| 148 | 147 | ||
| 149 | random = random * 17 + 41; | 148 | random = random * 17 + 41; |
| @@ -159,20 +158,10 @@ static void sp_xmit_on_air(unsigned long channel) | |||
| 159 | sp->tty->driver->write(sp->tty, &sp->led_state, 1); | 158 | sp->tty->driver->write(sp->tty, &sp->led_state, 1); |
| 160 | sp->status2 = 0; | 159 | sp->status2 = 0; |
| 161 | } else | 160 | } else |
| 162 | sp_start_tx_timer(sp); | 161 | mod_timer(&sp->tx_t, jiffies + ((when + 1) * HZ) / 100); |
| 163 | } | 162 | } |
| 164 | 163 | ||
| 165 | /* ----> 6pack timer interrupt handler and friends. <---- */ | 164 | /* ----> 6pack timer interrupt handler and friends. <---- */ |
| 166 | static void sp_start_tx_timer(struct sixpack *sp) | ||
| 167 | { | ||
| 168 | int when = sp->slottime; | ||
| 169 | |||
| 170 | del_timer(&sp->tx_t); | ||
| 171 | sp->tx_t.data = (unsigned long) sp; | ||
| 172 | sp->tx_t.function = sp_xmit_on_air; | ||
| 173 | sp->tx_t.expires = jiffies + ((when + 1) * HZ) / 100; | ||
| 174 | add_timer(&sp->tx_t); | ||
| 175 | } | ||
| 176 | 165 | ||
| 177 | /* Encapsulate one AX.25 frame and stuff into a TTY queue. */ | 166 | /* Encapsulate one AX.25 frame and stuff into a TTY queue. */ |
| 178 | static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len) | 167 | static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len) |
| @@ -243,8 +232,7 @@ static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len) | |||
| 243 | sp->xleft = count; | 232 | sp->xleft = count; |
| 244 | sp->xhead = sp->xbuff; | 233 | sp->xhead = sp->xbuff; |
| 245 | sp->status2 = count; | 234 | sp->status2 = count; |
| 246 | if (sp->duplex == 0) | 235 | sp_xmit_on_air((unsigned long)sp); |
| 247 | sp_start_tx_timer(sp); | ||
| 248 | } | 236 | } |
| 249 | 237 | ||
| 250 | return; | 238 | return; |
diff --git a/drivers/net/hamradio/Kconfig b/drivers/net/hamradio/Kconfig index 7cdebe1a0b61..0cd54306e636 100644 --- a/drivers/net/hamradio/Kconfig +++ b/drivers/net/hamradio/Kconfig | |||
| @@ -17,7 +17,7 @@ config MKISS | |||
| 17 | 17 | ||
| 18 | config 6PACK | 18 | config 6PACK |
| 19 | tristate "Serial port 6PACK driver" | 19 | tristate "Serial port 6PACK driver" |
| 20 | depends on AX25 && BROKEN_ON_SMP | 20 | depends on AX25 |
| 21 | ---help--- | 21 | ---help--- |
| 22 | 6pack is a transmission protocol for the data exchange between your | 22 | 6pack is a transmission protocol for the data exchange between your |
| 23 | PC and your TNC (the Terminal Node Controller acts as a kind of | 23 | PC and your TNC (the Terminal Node Controller acts as a kind of |
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index 82570ec44d8e..6ee4771addf1 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c | |||
| @@ -5133,6 +5133,84 @@ static void __devexit skge_remove_one(struct pci_dev *pdev) | |||
| 5133 | kfree(pAC); | 5133 | kfree(pAC); |
| 5134 | } | 5134 | } |
| 5135 | 5135 | ||
| 5136 | #ifdef CONFIG_PM | ||
| 5137 | static int skge_suspend(struct pci_dev *pdev, pm_message_t state) | ||
| 5138 | { | ||
| 5139 | struct net_device *dev = pci_get_drvdata(pdev); | ||
| 5140 | DEV_NET *pNet = netdev_priv(dev); | ||
| 5141 | SK_AC *pAC = pNet->pAC; | ||
| 5142 | struct net_device *otherdev = pAC->dev[1]; | ||
| 5143 | |||
| 5144 | if (netif_running(dev)) { | ||
| 5145 | netif_carrier_off(dev); | ||
| 5146 | DoPrintInterfaceChange = SK_FALSE; | ||
| 5147 | SkDrvDeInitAdapter(pAC, 0); /* performs SkGeClose */ | ||
| 5148 | netif_device_detach(dev); | ||
| 5149 | } | ||
| 5150 | if (otherdev != dev) { | ||
| 5151 | if (netif_running(otherdev)) { | ||
| 5152 | netif_carrier_off(otherdev); | ||
| 5153 | DoPrintInterfaceChange = SK_FALSE; | ||
| 5154 | SkDrvDeInitAdapter(pAC, 1); /* performs SkGeClose */ | ||
| 5155 | netif_device_detach(otherdev); | ||
| 5156 | } | ||
| 5157 | } | ||
| 5158 | |||
| 5159 | pci_save_state(pdev); | ||
| 5160 | pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); | ||
| 5161 | if (pAC->AllocFlag & SK_ALLOC_IRQ) { | ||
| 5162 | free_irq(dev->irq, dev); | ||
| 5163 | } | ||
| 5164 | pci_disable_device(pdev); | ||
| 5165 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | ||
| 5166 | |||
| 5167 | return 0; | ||
| 5168 | } | ||
| 5169 | |||
| 5170 | static int skge_resume(struct pci_dev *pdev) | ||
| 5171 | { | ||
| 5172 | struct net_device *dev = pci_get_drvdata(pdev); | ||
| 5173 | DEV_NET *pNet = netdev_priv(dev); | ||
| 5174 | SK_AC *pAC = pNet->pAC; | ||
| 5175 | struct net_device *otherdev = pAC->dev[1]; | ||
| 5176 | int ret; | ||
| 5177 | |||
| 5178 | pci_set_power_state(pdev, PCI_D0); | ||
| 5179 | pci_restore_state(pdev); | ||
| 5180 | pci_enable_device(pdev); | ||
| 5181 | pci_set_master(pdev); | ||
| 5182 | if (pAC->GIni.GIMacsFound == 2) | ||
| 5183 | ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, pAC->Name, dev); | ||
| 5184 | else | ||
| 5185 | ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ, pAC->Name, dev); | ||
| 5186 | if (ret) { | ||
| 5187 | printk(KERN_WARNING "sk98lin: unable to acquire IRQ %d\n", dev->irq); | ||
| 5188 | pAC->AllocFlag &= ~SK_ALLOC_IRQ; | ||
| 5189 | dev->irq = 0; | ||
| 5190 | pci_disable_device(pdev); | ||
| 5191 | return -EBUSY; | ||
| 5192 | } | ||
| 5193 | |||
| 5194 | netif_device_attach(dev); | ||
| 5195 | if (netif_running(dev)) { | ||
| 5196 | DoPrintInterfaceChange = SK_FALSE; | ||
| 5197 | SkDrvInitAdapter(pAC, 0); /* first device */ | ||
| 5198 | } | ||
| 5199 | if (otherdev != dev) { | ||
| 5200 | netif_device_attach(otherdev); | ||
| 5201 | if (netif_running(otherdev)) { | ||
| 5202 | DoPrintInterfaceChange = SK_FALSE; | ||
| 5203 | SkDrvInitAdapter(pAC, 1); /* second device */ | ||
| 5204 | } | ||
| 5205 | } | ||
| 5206 | |||
| 5207 | return 0; | ||
| 5208 | } | ||
| 5209 | #else | ||
| 5210 | #define skge_suspend NULL | ||
| 5211 | #define skge_resume NULL | ||
| 5212 | #endif | ||
| 5213 | |||
| 5136 | static struct pci_device_id skge_pci_tbl[] = { | 5214 | static struct pci_device_id skge_pci_tbl[] = { |
| 5137 | { PCI_VENDOR_ID_3COM, 0x1700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 5215 | { PCI_VENDOR_ID_3COM, 0x1700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
| 5138 | { PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 5216 | { PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
| @@ -5158,6 +5236,8 @@ static struct pci_driver skge_driver = { | |||
| 5158 | .id_table = skge_pci_tbl, | 5236 | .id_table = skge_pci_tbl, |
| 5159 | .probe = skge_probe_one, | 5237 | .probe = skge_probe_one, |
| 5160 | .remove = __devexit_p(skge_remove_one), | 5238 | .remove = __devexit_p(skge_remove_one), |
| 5239 | .suspend = skge_suspend, | ||
| 5240 | .resume = skge_resume, | ||
| 5161 | }; | 5241 | }; |
| 5162 | 5242 | ||
| 5163 | static int __init skge_init(void) | 5243 | static int __init skge_init(void) |
diff --git a/drivers/net/sk98lin/skgeinit.c b/drivers/net/sk98lin/skgeinit.c index df4483429a77..6cb49dd02251 100644 --- a/drivers/net/sk98lin/skgeinit.c +++ b/drivers/net/sk98lin/skgeinit.c | |||
| @@ -2016,7 +2016,7 @@ SK_IOC IoC) /* IO context */ | |||
| 2016 | * we set the PHY to coma mode and switch to D3 power state. | 2016 | * we set the PHY to coma mode and switch to D3 power state. |
| 2017 | */ | 2017 | */ |
| 2018 | if (pAC->GIni.GIYukonLite && | 2018 | if (pAC->GIni.GIYukonLite && |
| 2019 | pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { | 2019 | pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { |
| 2020 | 2020 | ||
| 2021 | /* for all ports switch PHY to coma mode */ | 2021 | /* for all ports switch PHY to coma mode */ |
| 2022 | for (i = 0; i < pAC->GIni.GIMacsFound; i++) { | 2022 | for (i = 0; i < pAC->GIni.GIMacsFound; i++) { |
diff --git a/drivers/net/sk98lin/skxmac2.c b/drivers/net/sk98lin/skxmac2.c index 94a09deecb32..42d2d963150a 100644 --- a/drivers/net/sk98lin/skxmac2.c +++ b/drivers/net/sk98lin/skxmac2.c | |||
| @@ -1065,7 +1065,7 @@ int Port) /* Port Index (MAC_1 + n) */ | |||
| 1065 | 1065 | ||
| 1066 | /* WA code for COMA mode */ | 1066 | /* WA code for COMA mode */ |
| 1067 | if (pAC->GIni.GIYukonLite && | 1067 | if (pAC->GIni.GIYukonLite && |
| 1068 | pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { | 1068 | pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { |
| 1069 | 1069 | ||
| 1070 | SK_IN32(IoC, B2_GP_IO, &DWord); | 1070 | SK_IN32(IoC, B2_GP_IO, &DWord); |
| 1071 | 1071 | ||
| @@ -1110,7 +1110,7 @@ int Port) /* Port Index (MAC_1 + n) */ | |||
| 1110 | 1110 | ||
| 1111 | /* WA code for COMA mode */ | 1111 | /* WA code for COMA mode */ |
| 1112 | if (pAC->GIni.GIYukonLite && | 1112 | if (pAC->GIni.GIYukonLite && |
| 1113 | pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { | 1113 | pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { |
| 1114 | 1114 | ||
| 1115 | SK_IN32(IoC, B2_GP_IO, &DWord); | 1115 | SK_IN32(IoC, B2_GP_IO, &DWord); |
| 1116 | 1116 | ||
| @@ -2126,7 +2126,7 @@ SK_U8 Mode) /* low power mode */ | |||
| 2126 | int Ret = 0; | 2126 | int Ret = 0; |
| 2127 | 2127 | ||
| 2128 | if (pAC->GIni.GIYukonLite && | 2128 | if (pAC->GIni.GIYukonLite && |
| 2129 | pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { | 2129 | pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { |
| 2130 | 2130 | ||
| 2131 | /* save current power mode */ | 2131 | /* save current power mode */ |
| 2132 | LastMode = pAC->GIni.GP[Port].PPhyPowerState; | 2132 | LastMode = pAC->GIni.GP[Port].PPhyPowerState; |
| @@ -2253,7 +2253,7 @@ int Port) /* Port Index (e.g. MAC_1) */ | |||
| 2253 | int Ret = 0; | 2253 | int Ret = 0; |
| 2254 | 2254 | ||
| 2255 | if (pAC->GIni.GIYukonLite && | 2255 | if (pAC->GIni.GIYukonLite && |
| 2256 | pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { | 2256 | pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { |
| 2257 | 2257 | ||
| 2258 | /* save current power mode */ | 2258 | /* save current power mode */ |
| 2259 | LastMode = pAC->GIni.GP[Port].PPhyPowerState; | 2259 | LastMode = pAC->GIni.GP[Port].PPhyPowerState; |
diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 5cacc7ad9e79..f15739481d62 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c | |||
| @@ -42,7 +42,7 @@ | |||
| 42 | #include "skge.h" | 42 | #include "skge.h" |
| 43 | 43 | ||
| 44 | #define DRV_NAME "skge" | 44 | #define DRV_NAME "skge" |
| 45 | #define DRV_VERSION "0.7" | 45 | #define DRV_VERSION "0.8" |
| 46 | #define PFX DRV_NAME " " | 46 | #define PFX DRV_NAME " " |
| 47 | 47 | ||
| 48 | #define DEFAULT_TX_RING_SIZE 128 | 48 | #define DEFAULT_TX_RING_SIZE 128 |
| @@ -55,7 +55,7 @@ | |||
| 55 | #define ETH_JUMBO_MTU 9000 | 55 | #define ETH_JUMBO_MTU 9000 |
| 56 | #define TX_WATCHDOG (5 * HZ) | 56 | #define TX_WATCHDOG (5 * HZ) |
| 57 | #define NAPI_WEIGHT 64 | 57 | #define NAPI_WEIGHT 64 |
| 58 | #define BLINK_HZ (HZ/4) | 58 | #define BLINK_MS 250 |
| 59 | 59 | ||
| 60 | MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver"); | 60 | MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver"); |
| 61 | MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>"); | 61 | MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>"); |
| @@ -75,7 +75,6 @@ static const struct pci_device_id skge_id_table[] = { | |||
| 75 | { PCI_DEVICE(PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940B) }, | 75 | { PCI_DEVICE(PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940B) }, |
| 76 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE) }, | 76 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE) }, |
| 77 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU) }, | 77 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU) }, |
| 78 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, /* SK-9Exx */ | ||
| 79 | { PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T), }, | 78 | { PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T), }, |
| 80 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) }, | 79 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) }, |
| 81 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */ | 80 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */ |
| @@ -249,7 +248,7 @@ static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
| 249 | } else { | 248 | } else { |
| 250 | u32 setting; | 249 | u32 setting; |
| 251 | 250 | ||
| 252 | switch(ecmd->speed) { | 251 | switch (ecmd->speed) { |
| 253 | case SPEED_1000: | 252 | case SPEED_1000: |
| 254 | if (ecmd->duplex == DUPLEX_FULL) | 253 | if (ecmd->duplex == DUPLEX_FULL) |
| 255 | setting = SUPPORTED_1000baseT_Full; | 254 | setting = SUPPORTED_1000baseT_Full; |
| @@ -620,84 +619,98 @@ static int skge_set_coalesce(struct net_device *dev, | |||
| 620 | return 0; | 619 | return 0; |
| 621 | } | 620 | } |
| 622 | 621 | ||
| 623 | static void skge_led_on(struct skge_hw *hw, int port) | 622 | enum led_mode { LED_MODE_OFF, LED_MODE_ON, LED_MODE_TST }; |
| 623 | static void skge_led(struct skge_port *skge, enum led_mode mode) | ||
| 624 | { | 624 | { |
| 625 | struct skge_hw *hw = skge->hw; | ||
| 626 | int port = skge->port; | ||
| 627 | |||
| 628 | spin_lock_bh(&hw->phy_lock); | ||
| 625 | if (hw->chip_id == CHIP_ID_GENESIS) { | 629 | if (hw->chip_id == CHIP_ID_GENESIS) { |
| 626 | skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON); | 630 | switch (mode) { |
| 627 | skge_write8(hw, B0_LED, LED_STAT_ON); | 631 | case LED_MODE_OFF: |
| 632 | xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF); | ||
| 633 | skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF); | ||
| 634 | skge_write32(hw, SK_REG(port, RX_LED_VAL), 0); | ||
| 635 | skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF); | ||
| 636 | break; | ||
| 628 | 637 | ||
| 629 | skge_write8(hw, SK_REG(port, RX_LED_TST), LED_T_ON); | 638 | case LED_MODE_ON: |
| 630 | skge_write32(hw, SK_REG(port, RX_LED_VAL), 100); | 639 | skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON); |
| 631 | skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START); | 640 | skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_LINKSYNC_ON); |
| 632 | 641 | ||
| 633 | /* For Broadcom Phy only */ | 642 | skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START); |
| 634 | xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON); | 643 | skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START); |
| 635 | } else { | ||
| 636 | gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); | ||
| 637 | gm_phy_write(hw, port, PHY_MARV_LED_OVER, | ||
| 638 | PHY_M_LED_MO_DUP(MO_LED_ON) | | ||
| 639 | PHY_M_LED_MO_10(MO_LED_ON) | | ||
| 640 | PHY_M_LED_MO_100(MO_LED_ON) | | ||
| 641 | PHY_M_LED_MO_1000(MO_LED_ON) | | ||
| 642 | PHY_M_LED_MO_RX(MO_LED_ON)); | ||
| 643 | } | ||
| 644 | } | ||
| 645 | 644 | ||
| 646 | static void skge_led_off(struct skge_hw *hw, int port) | 645 | break; |
| 647 | { | ||
| 648 | if (hw->chip_id == CHIP_ID_GENESIS) { | ||
| 649 | skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF); | ||
| 650 | skge_write8(hw, B0_LED, LED_STAT_OFF); | ||
| 651 | 646 | ||
| 652 | skge_write32(hw, SK_REG(port, RX_LED_VAL), 0); | 647 | case LED_MODE_TST: |
| 653 | skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF); | 648 | skge_write8(hw, SK_REG(port, RX_LED_TST), LED_T_ON); |
| 649 | skge_write32(hw, SK_REG(port, RX_LED_VAL), 100); | ||
| 650 | skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START); | ||
| 654 | 651 | ||
| 655 | /* Broadcom only */ | 652 | xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON); |
| 656 | xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF); | 653 | break; |
| 654 | } | ||
| 657 | } else { | 655 | } else { |
| 658 | gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); | 656 | switch (mode) { |
| 659 | gm_phy_write(hw, port, PHY_MARV_LED_OVER, | 657 | case LED_MODE_OFF: |
| 660 | PHY_M_LED_MO_DUP(MO_LED_OFF) | | 658 | gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); |
| 661 | PHY_M_LED_MO_10(MO_LED_OFF) | | 659 | gm_phy_write(hw, port, PHY_MARV_LED_OVER, |
| 662 | PHY_M_LED_MO_100(MO_LED_OFF) | | 660 | PHY_M_LED_MO_DUP(MO_LED_OFF) | |
| 663 | PHY_M_LED_MO_1000(MO_LED_OFF) | | 661 | PHY_M_LED_MO_10(MO_LED_OFF) | |
| 664 | PHY_M_LED_MO_RX(MO_LED_OFF)); | 662 | PHY_M_LED_MO_100(MO_LED_OFF) | |
| 663 | PHY_M_LED_MO_1000(MO_LED_OFF) | | ||
| 664 | PHY_M_LED_MO_RX(MO_LED_OFF)); | ||
| 665 | break; | ||
| 666 | case LED_MODE_ON: | ||
| 667 | gm_phy_write(hw, port, PHY_MARV_LED_CTRL, | ||
| 668 | PHY_M_LED_PULS_DUR(PULS_170MS) | | ||
| 669 | PHY_M_LED_BLINK_RT(BLINK_84MS) | | ||
| 670 | PHY_M_LEDC_TX_CTRL | | ||
| 671 | PHY_M_LEDC_DP_CTRL); | ||
| 672 | |||
| 673 | gm_phy_write(hw, port, PHY_MARV_LED_OVER, | ||
| 674 | PHY_M_LED_MO_RX(MO_LED_OFF) | | ||
| 675 | (skge->speed == SPEED_100 ? | ||
| 676 | PHY_M_LED_MO_100(MO_LED_ON) : 0)); | ||
| 677 | break; | ||
| 678 | case LED_MODE_TST: | ||
| 679 | gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); | ||
| 680 | gm_phy_write(hw, port, PHY_MARV_LED_OVER, | ||
| 681 | PHY_M_LED_MO_DUP(MO_LED_ON) | | ||
| 682 | PHY_M_LED_MO_10(MO_LED_ON) | | ||
| 683 | PHY_M_LED_MO_100(MO_LED_ON) | | ||
| 684 | PHY_M_LED_MO_1000(MO_LED_ON) | | ||
| 685 | PHY_M_LED_MO_RX(MO_LED_ON)); | ||
| 686 | } | ||
| 665 | } | 687 | } |
| 666 | } | 688 | spin_unlock_bh(&hw->phy_lock); |
| 667 | |||
| 668 | static void skge_blink_timer(unsigned long data) | ||
| 669 | { | ||
| 670 | struct skge_port *skge = (struct skge_port *) data; | ||
| 671 | struct skge_hw *hw = skge->hw; | ||
| 672 | unsigned long flags; | ||
| 673 | |||
| 674 | spin_lock_irqsave(&hw->phy_lock, flags); | ||
| 675 | if (skge->blink_on) | ||
| 676 | skge_led_on(hw, skge->port); | ||
| 677 | else | ||
| 678 | skge_led_off(hw, skge->port); | ||
| 679 | spin_unlock_irqrestore(&hw->phy_lock, flags); | ||
| 680 | |||
| 681 | skge->blink_on = !skge->blink_on; | ||
| 682 | mod_timer(&skge->led_blink, jiffies + BLINK_HZ); | ||
| 683 | } | 689 | } |
| 684 | 690 | ||
| 685 | /* blink LED's for finding board */ | 691 | /* blink LED's for finding board */ |
| 686 | static int skge_phys_id(struct net_device *dev, u32 data) | 692 | static int skge_phys_id(struct net_device *dev, u32 data) |
| 687 | { | 693 | { |
| 688 | struct skge_port *skge = netdev_priv(dev); | 694 | struct skge_port *skge = netdev_priv(dev); |
| 695 | unsigned long ms; | ||
| 696 | enum led_mode mode = LED_MODE_TST; | ||
| 689 | 697 | ||
| 690 | if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) | 698 | if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) |
| 691 | data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); | 699 | ms = jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT / HZ) * 1000; |
| 700 | else | ||
| 701 | ms = data * 1000; | ||
| 692 | 702 | ||
| 693 | /* start blinking */ | 703 | while (ms > 0) { |
| 694 | skge->blink_on = 1; | 704 | skge_led(skge, mode); |
| 695 | mod_timer(&skge->led_blink, jiffies+1); | 705 | mode ^= LED_MODE_TST; |
| 696 | 706 | ||
| 697 | msleep_interruptible(data * 1000); | 707 | if (msleep_interruptible(BLINK_MS)) |
| 698 | del_timer_sync(&skge->led_blink); | 708 | break; |
| 709 | ms -= BLINK_MS; | ||
| 710 | } | ||
| 699 | 711 | ||
| 700 | skge_led_off(skge->hw, skge->port); | 712 | /* back to regular LED state */ |
| 713 | skge_led(skge, netif_running(dev) ? LED_MODE_ON : LED_MODE_OFF); | ||
| 701 | 714 | ||
| 702 | return 0; | 715 | return 0; |
| 703 | } | 716 | } |
| @@ -1028,7 +1041,7 @@ static void bcom_check_link(struct skge_hw *hw, int port) | |||
| 1028 | } | 1041 | } |
| 1029 | 1042 | ||
| 1030 | /* Check Duplex mismatch */ | 1043 | /* Check Duplex mismatch */ |
| 1031 | switch(aux & PHY_B_AS_AN_RES_MSK) { | 1044 | switch (aux & PHY_B_AS_AN_RES_MSK) { |
| 1032 | case PHY_B_RES_1000FD: | 1045 | case PHY_B_RES_1000FD: |
| 1033 | skge->duplex = DUPLEX_FULL; | 1046 | skge->duplex = DUPLEX_FULL; |
| 1034 | break; | 1047 | break; |
| @@ -1099,7 +1112,7 @@ static void bcom_phy_init(struct skge_port *skge, int jumbo) | |||
| 1099 | r |= XM_MMU_NO_PRE; | 1112 | r |= XM_MMU_NO_PRE; |
| 1100 | xm_write16(hw, port, XM_MMU_CMD,r); | 1113 | xm_write16(hw, port, XM_MMU_CMD,r); |
| 1101 | 1114 | ||
| 1102 | switch(id1) { | 1115 | switch (id1) { |
| 1103 | case PHY_BCOM_ID1_C0: | 1116 | case PHY_BCOM_ID1_C0: |
| 1104 | /* | 1117 | /* |
| 1105 | * Workaround BCOM Errata for the C0 type. | 1118 | * Workaround BCOM Errata for the C0 type. |
| @@ -1194,13 +1207,6 @@ static void genesis_mac_init(struct skge_hw *hw, int port) | |||
| 1194 | xm_write16(hw, port, XM_STAT_CMD, | 1207 | xm_write16(hw, port, XM_STAT_CMD, |
| 1195 | XM_SC_CLR_RXC | XM_SC_CLR_TXC); | 1208 | XM_SC_CLR_RXC | XM_SC_CLR_TXC); |
| 1196 | 1209 | ||
| 1197 | /* initialize Rx, Tx and Link LED */ | ||
| 1198 | skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON); | ||
| 1199 | skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_LINKSYNC_ON); | ||
| 1200 | |||
| 1201 | skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START); | ||
| 1202 | skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START); | ||
| 1203 | |||
| 1204 | /* Unreset the XMAC. */ | 1210 | /* Unreset the XMAC. */ |
| 1205 | skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); | 1211 | skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); |
| 1206 | 1212 | ||
| @@ -1209,7 +1215,6 @@ static void genesis_mac_init(struct skge_hw *hw, int port) | |||
| 1209 | * namely for the 1000baseTX cards that use the XMAC's | 1215 | * namely for the 1000baseTX cards that use the XMAC's |
| 1210 | * GMII mode. | 1216 | * GMII mode. |
| 1211 | */ | 1217 | */ |
| 1212 | spin_lock_bh(&hw->phy_lock); | ||
| 1213 | /* Take external Phy out of reset */ | 1218 | /* Take external Phy out of reset */ |
| 1214 | r = skge_read32(hw, B2_GP_IO); | 1219 | r = skge_read32(hw, B2_GP_IO); |
| 1215 | if (port == 0) | 1220 | if (port == 0) |
| @@ -1219,7 +1224,6 @@ static void genesis_mac_init(struct skge_hw *hw, int port) | |||
| 1219 | 1224 | ||
| 1220 | skge_write32(hw, B2_GP_IO, r); | 1225 | skge_write32(hw, B2_GP_IO, r); |
| 1221 | skge_read32(hw, B2_GP_IO); | 1226 | skge_read32(hw, B2_GP_IO); |
| 1222 | spin_unlock_bh(&hw->phy_lock); | ||
| 1223 | 1227 | ||
| 1224 | /* Enable GMII interfac */ | 1228 | /* Enable GMII interfac */ |
| 1225 | xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD); | 1229 | xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD); |
| @@ -1569,7 +1573,6 @@ static void yukon_init(struct skge_hw *hw, int port) | |||
| 1569 | { | 1573 | { |
| 1570 | struct skge_port *skge = netdev_priv(hw->dev[port]); | 1574 | struct skge_port *skge = netdev_priv(hw->dev[port]); |
| 1571 | u16 ctrl, ct1000, adv; | 1575 | u16 ctrl, ct1000, adv; |
| 1572 | u16 ledctrl, ledover; | ||
| 1573 | 1576 | ||
| 1574 | pr_debug("yukon_init\n"); | 1577 | pr_debug("yukon_init\n"); |
| 1575 | if (skge->autoneg == AUTONEG_ENABLE) { | 1578 | if (skge->autoneg == AUTONEG_ENABLE) { |
| @@ -1641,32 +1644,11 @@ static void yukon_init(struct skge_hw *hw, int port) | |||
| 1641 | gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv); | 1644 | gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv); |
| 1642 | gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); | 1645 | gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); |
| 1643 | 1646 | ||
| 1644 | /* Setup Phy LED's */ | ||
| 1645 | ledctrl = PHY_M_LED_PULS_DUR(PULS_170MS); | ||
| 1646 | ledover = 0; | ||
| 1647 | |||
| 1648 | ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) | PHY_M_LEDC_TX_CTRL; | ||
| 1649 | |||
| 1650 | /* turn off the Rx LED (LED_RX) */ | ||
| 1651 | ledover |= PHY_M_LED_MO_RX(MO_LED_OFF); | ||
| 1652 | |||
| 1653 | /* disable blink mode (LED_DUPLEX) on collisions */ | ||
| 1654 | ctrl |= PHY_M_LEDC_DP_CTRL; | ||
| 1655 | gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); | ||
| 1656 | |||
| 1657 | if (skge->autoneg == AUTONEG_DISABLE || skge->speed == SPEED_100) { | ||
| 1658 | /* turn on 100 Mbps LED (LED_LINK100) */ | ||
| 1659 | ledover |= PHY_M_LED_MO_100(MO_LED_ON); | ||
| 1660 | } | ||
| 1661 | |||
| 1662 | if (ledover) | ||
| 1663 | gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover); | ||
| 1664 | |||
| 1665 | /* Enable phy interrupt on autonegotiation complete (or link up) */ | 1647 | /* Enable phy interrupt on autonegotiation complete (or link up) */ |
| 1666 | if (skge->autoneg == AUTONEG_ENABLE) | 1648 | if (skge->autoneg == AUTONEG_ENABLE) |
| 1667 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL); | 1649 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_MSK); |
| 1668 | else | 1650 | else |
| 1669 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); | 1651 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_DEF_MSK); |
| 1670 | } | 1652 | } |
| 1671 | 1653 | ||
| 1672 | static void yukon_reset(struct skge_hw *hw, int port) | 1654 | static void yukon_reset(struct skge_hw *hw, int port) |
| @@ -1691,7 +1673,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port) | |||
| 1691 | 1673 | ||
| 1692 | /* WA code for COMA mode -- set PHY reset */ | 1674 | /* WA code for COMA mode -- set PHY reset */ |
| 1693 | if (hw->chip_id == CHIP_ID_YUKON_LITE && | 1675 | if (hw->chip_id == CHIP_ID_YUKON_LITE && |
| 1694 | hw->chip_rev == CHIP_REV_YU_LITE_A3) | 1676 | hw->chip_rev >= CHIP_REV_YU_LITE_A3) |
| 1695 | skge_write32(hw, B2_GP_IO, | 1677 | skge_write32(hw, B2_GP_IO, |
| 1696 | (skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9)); | 1678 | (skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9)); |
| 1697 | 1679 | ||
| @@ -1701,7 +1683,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port) | |||
| 1701 | 1683 | ||
| 1702 | /* WA code for COMA mode -- clear PHY reset */ | 1684 | /* WA code for COMA mode -- clear PHY reset */ |
| 1703 | if (hw->chip_id == CHIP_ID_YUKON_LITE && | 1685 | if (hw->chip_id == CHIP_ID_YUKON_LITE && |
| 1704 | hw->chip_rev == CHIP_REV_YU_LITE_A3) | 1686 | hw->chip_rev >= CHIP_REV_YU_LITE_A3) |
| 1705 | skge_write32(hw, B2_GP_IO, | 1687 | skge_write32(hw, B2_GP_IO, |
| 1706 | (skge_read32(hw, B2_GP_IO) | GP_DIR_9) | 1688 | (skge_read32(hw, B2_GP_IO) | GP_DIR_9) |
| 1707 | & ~GP_IO_9); | 1689 | & ~GP_IO_9); |
| @@ -1745,9 +1727,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port) | |||
| 1745 | gma_write16(hw, port, GM_GP_CTRL, reg); | 1727 | gma_write16(hw, port, GM_GP_CTRL, reg); |
| 1746 | skge_read16(hw, GMAC_IRQ_SRC); | 1728 | skge_read16(hw, GMAC_IRQ_SRC); |
| 1747 | 1729 | ||
| 1748 | spin_lock_bh(&hw->phy_lock); | ||
| 1749 | yukon_init(hw, port); | 1730 | yukon_init(hw, port); |
| 1750 | spin_unlock_bh(&hw->phy_lock); | ||
| 1751 | 1731 | ||
| 1752 | /* MIB clear */ | 1732 | /* MIB clear */ |
| 1753 | reg = gma_read16(hw, port, GM_PHY_ADDR); | 1733 | reg = gma_read16(hw, port, GM_PHY_ADDR); |
| @@ -1796,7 +1776,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port) | |||
| 1796 | skge_write16(hw, SK_REG(port, RX_GMF_FL_MSK), RX_FF_FL_DEF_MSK); | 1776 | skge_write16(hw, SK_REG(port, RX_GMF_FL_MSK), RX_FF_FL_DEF_MSK); |
| 1797 | reg = GMF_OPER_ON | GMF_RX_F_FL_ON; | 1777 | reg = GMF_OPER_ON | GMF_RX_F_FL_ON; |
| 1798 | if (hw->chip_id == CHIP_ID_YUKON_LITE && | 1778 | if (hw->chip_id == CHIP_ID_YUKON_LITE && |
| 1799 | hw->chip_rev == CHIP_REV_YU_LITE_A3) | 1779 | hw->chip_rev >= CHIP_REV_YU_LITE_A3) |
| 1800 | reg &= ~GMF_RX_F_FL_ON; | 1780 | reg &= ~GMF_RX_F_FL_ON; |
| 1801 | skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR); | 1781 | skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR); |
| 1802 | skge_write16(hw, SK_REG(port, RX_GMF_CTRL_T), reg); | 1782 | skge_write16(hw, SK_REG(port, RX_GMF_CTRL_T), reg); |
| @@ -1813,19 +1793,19 @@ static void yukon_stop(struct skge_port *skge) | |||
| 1813 | int port = skge->port; | 1793 | int port = skge->port; |
| 1814 | 1794 | ||
| 1815 | if (hw->chip_id == CHIP_ID_YUKON_LITE && | 1795 | if (hw->chip_id == CHIP_ID_YUKON_LITE && |
| 1816 | hw->chip_rev == CHIP_REV_YU_LITE_A3) { | 1796 | hw->chip_rev >= CHIP_REV_YU_LITE_A3) { |
| 1817 | skge_write32(hw, B2_GP_IO, | 1797 | skge_write32(hw, B2_GP_IO, |
| 1818 | skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9); | 1798 | skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9); |
| 1819 | } | 1799 | } |
| 1820 | 1800 | ||
| 1821 | gma_write16(hw, port, GM_GP_CTRL, | 1801 | gma_write16(hw, port, GM_GP_CTRL, |
| 1822 | gma_read16(hw, port, GM_GP_CTRL) | 1802 | gma_read16(hw, port, GM_GP_CTRL) |
| 1823 | & ~(GM_GPCR_RX_ENA|GM_GPCR_RX_ENA)); | 1803 | & ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA)); |
| 1824 | gma_read16(hw, port, GM_GP_CTRL); | 1804 | gma_read16(hw, port, GM_GP_CTRL); |
| 1825 | 1805 | ||
| 1826 | /* set GPHY Control reset */ | 1806 | /* set GPHY Control reset */ |
| 1827 | gma_write32(hw, port, GPHY_CTRL, GPC_RST_SET); | 1807 | skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); |
| 1828 | gma_write32(hw, port, GMAC_CTRL, GMC_RST_SET); | 1808 | skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET); |
| 1829 | } | 1809 | } |
| 1830 | 1810 | ||
| 1831 | static void yukon_get_stats(struct skge_port *skge, u64 *data) | 1811 | static void yukon_get_stats(struct skge_port *skge, u64 *data) |
| @@ -1856,11 +1836,12 @@ static void yukon_mac_intr(struct skge_hw *hw, int port) | |||
| 1856 | 1836 | ||
| 1857 | if (status & GM_IS_RX_FF_OR) { | 1837 | if (status & GM_IS_RX_FF_OR) { |
| 1858 | ++skge->net_stats.rx_fifo_errors; | 1838 | ++skge->net_stats.rx_fifo_errors; |
| 1859 | gma_write8(hw, port, RX_GMF_CTRL_T, GMF_CLI_RX_FO); | 1839 | skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_CLI_RX_FO); |
| 1860 | } | 1840 | } |
| 1841 | |||
| 1861 | if (status & GM_IS_TX_FF_UR) { | 1842 | if (status & GM_IS_TX_FF_UR) { |
| 1862 | ++skge->net_stats.tx_fifo_errors; | 1843 | ++skge->net_stats.tx_fifo_errors; |
| 1863 | gma_write8(hw, port, TX_GMF_CTRL_T, GMF_CLI_TX_FU); | 1844 | skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_FU); |
| 1864 | } | 1845 | } |
| 1865 | 1846 | ||
| 1866 | } | 1847 | } |
| @@ -1896,7 +1877,7 @@ static void yukon_link_up(struct skge_port *skge) | |||
| 1896 | reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA; | 1877 | reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA; |
| 1897 | gma_write16(hw, port, GM_GP_CTRL, reg); | 1878 | gma_write16(hw, port, GM_GP_CTRL, reg); |
| 1898 | 1879 | ||
| 1899 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); | 1880 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_DEF_MSK); |
| 1900 | skge_link_up(skge); | 1881 | skge_link_up(skge); |
| 1901 | } | 1882 | } |
| 1902 | 1883 | ||
| @@ -1904,12 +1885,14 @@ static void yukon_link_down(struct skge_port *skge) | |||
| 1904 | { | 1885 | { |
| 1905 | struct skge_hw *hw = skge->hw; | 1886 | struct skge_hw *hw = skge->hw; |
| 1906 | int port = skge->port; | 1887 | int port = skge->port; |
| 1888 | u16 ctrl; | ||
| 1907 | 1889 | ||
| 1908 | pr_debug("yukon_link_down\n"); | 1890 | pr_debug("yukon_link_down\n"); |
| 1909 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0); | 1891 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0); |
| 1910 | gm_phy_write(hw, port, GM_GP_CTRL, | 1892 | |
| 1911 | gm_phy_read(hw, port, GM_GP_CTRL) | 1893 | ctrl = gma_read16(hw, port, GM_GP_CTRL); |
| 1912 | & ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA)); | 1894 | ctrl &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); |
| 1895 | gma_write16(hw, port, GM_GP_CTRL, ctrl); | ||
| 1913 | 1896 | ||
| 1914 | if (skge->flow_control == FLOW_MODE_REM_SEND) { | 1897 | if (skge->flow_control == FLOW_MODE_REM_SEND) { |
| 1915 | /* restore Asymmetric Pause bit */ | 1898 | /* restore Asymmetric Pause bit */ |
| @@ -2097,10 +2080,12 @@ static int skge_up(struct net_device *dev) | |||
| 2097 | skge_write32(hw, B0_IMSK, hw->intr_mask); | 2080 | skge_write32(hw, B0_IMSK, hw->intr_mask); |
| 2098 | 2081 | ||
| 2099 | /* Initialze MAC */ | 2082 | /* Initialze MAC */ |
| 2083 | spin_lock_bh(&hw->phy_lock); | ||
| 2100 | if (hw->chip_id == CHIP_ID_GENESIS) | 2084 | if (hw->chip_id == CHIP_ID_GENESIS) |
| 2101 | genesis_mac_init(hw, port); | 2085 | genesis_mac_init(hw, port); |
| 2102 | else | 2086 | else |
| 2103 | yukon_mac_init(hw, port); | 2087 | yukon_mac_init(hw, port); |
| 2088 | spin_unlock_bh(&hw->phy_lock); | ||
| 2104 | 2089 | ||
| 2105 | /* Configure RAMbuffers */ | 2090 | /* Configure RAMbuffers */ |
| 2106 | chunk = hw->ram_size / ((hw->ports + 1)*2); | 2091 | chunk = hw->ram_size / ((hw->ports + 1)*2); |
| @@ -2116,6 +2101,7 @@ static int skge_up(struct net_device *dev) | |||
| 2116 | /* Start receiver BMU */ | 2101 | /* Start receiver BMU */ |
| 2117 | wmb(); | 2102 | wmb(); |
| 2118 | skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F); | 2103 | skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F); |
| 2104 | skge_led(skge, LED_MODE_ON); | ||
| 2119 | 2105 | ||
| 2120 | pr_debug("skge_up completed\n"); | 2106 | pr_debug("skge_up completed\n"); |
| 2121 | return 0; | 2107 | return 0; |
| @@ -2140,8 +2126,6 @@ static int skge_down(struct net_device *dev) | |||
| 2140 | 2126 | ||
| 2141 | netif_stop_queue(dev); | 2127 | netif_stop_queue(dev); |
| 2142 | 2128 | ||
| 2143 | del_timer_sync(&skge->led_blink); | ||
| 2144 | |||
| 2145 | /* Stop transmitter */ | 2129 | /* Stop transmitter */ |
| 2146 | skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP); | 2130 | skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP); |
| 2147 | skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), | 2131 | skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), |
| @@ -2175,15 +2159,12 @@ static int skge_down(struct net_device *dev) | |||
| 2175 | if (hw->chip_id == CHIP_ID_GENESIS) { | 2159 | if (hw->chip_id == CHIP_ID_GENESIS) { |
| 2176 | skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_RST_SET); | 2160 | skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_RST_SET); |
| 2177 | skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_RST_SET); | 2161 | skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_RST_SET); |
| 2178 | skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_STOP); | ||
| 2179 | skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_STOP); | ||
| 2180 | } else { | 2162 | } else { |
| 2181 | skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); | 2163 | skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); |
| 2182 | skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET); | 2164 | skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET); |
| 2183 | } | 2165 | } |
| 2184 | 2166 | ||
| 2185 | /* turn off led's */ | 2167 | skge_led(skge, LED_MODE_OFF); |
| 2186 | skge_write16(hw, B0_LED, LED_STAT_OFF); | ||
| 2187 | 2168 | ||
| 2188 | skge_tx_clean(skge); | 2169 | skge_tx_clean(skge); |
| 2189 | skge_rx_clean(skge); | 2170 | skge_rx_clean(skge); |
| @@ -2633,11 +2614,17 @@ static inline void skge_tx_intr(struct net_device *dev) | |||
| 2633 | spin_unlock(&skge->tx_lock); | 2614 | spin_unlock(&skge->tx_lock); |
| 2634 | } | 2615 | } |
| 2635 | 2616 | ||
| 2617 | /* Parity errors seem to happen when Genesis is connected to a switch | ||
| 2618 | * with no other ports present. Heartbeat error?? | ||
| 2619 | */ | ||
| 2636 | static void skge_mac_parity(struct skge_hw *hw, int port) | 2620 | static void skge_mac_parity(struct skge_hw *hw, int port) |
| 2637 | { | 2621 | { |
| 2638 | printk(KERN_ERR PFX "%s: mac data parity error\n", | 2622 | struct net_device *dev = hw->dev[port]; |
| 2639 | hw->dev[port] ? hw->dev[port]->name | 2623 | |
| 2640 | : (port == 0 ? "(port A)": "(port B")); | 2624 | if (dev) { |
| 2625 | struct skge_port *skge = netdev_priv(dev); | ||
| 2626 | ++skge->net_stats.tx_heartbeat_errors; | ||
| 2627 | } | ||
| 2641 | 2628 | ||
| 2642 | if (hw->chip_id == CHIP_ID_GENESIS) | 2629 | if (hw->chip_id == CHIP_ID_GENESIS) |
| 2643 | skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), | 2630 | skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), |
| @@ -3083,10 +3070,6 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, | |||
| 3083 | 3070 | ||
| 3084 | spin_lock_init(&skge->tx_lock); | 3071 | spin_lock_init(&skge->tx_lock); |
| 3085 | 3072 | ||
| 3086 | init_timer(&skge->led_blink); | ||
| 3087 | skge->led_blink.function = skge_blink_timer; | ||
| 3088 | skge->led_blink.data = (unsigned long) skge; | ||
| 3089 | |||
| 3090 | if (hw->chip_id != CHIP_ID_GENESIS) { | 3073 | if (hw->chip_id != CHIP_ID_GENESIS) { |
| 3091 | dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; | 3074 | dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; |
| 3092 | skge->rx_csum = 1; | 3075 | skge->rx_csum = 1; |
diff --git a/drivers/net/skge.h b/drivers/net/skge.h index fced3d2bc072..b432f1bb8168 100644 --- a/drivers/net/skge.h +++ b/drivers/net/skge.h | |||
| @@ -1449,10 +1449,12 @@ enum { | |||
| 1449 | PHY_M_IS_DTE_CHANGE = 1<<2, /* DTE Power Det. Status Changed */ | 1449 | PHY_M_IS_DTE_CHANGE = 1<<2, /* DTE Power Det. Status Changed */ |
| 1450 | PHY_M_IS_POL_CHANGE = 1<<1, /* Polarity Changed */ | 1450 | PHY_M_IS_POL_CHANGE = 1<<1, /* Polarity Changed */ |
| 1451 | PHY_M_IS_JABBER = 1<<0, /* Jabber */ | 1451 | PHY_M_IS_JABBER = 1<<0, /* Jabber */ |
| 1452 | }; | ||
| 1453 | 1452 | ||
| 1454 | #define PHY_M_DEF_MSK ( PHY_M_IS_AN_ERROR | PHY_M_IS_LSP_CHANGE | \ | 1453 | PHY_M_IS_DEF_MSK = PHY_M_IS_AN_ERROR | PHY_M_IS_LSP_CHANGE | |
| 1455 | PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR) | 1454 | PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR, |
| 1455 | |||
| 1456 | PHY_M_IS_AN_MSK = PHY_M_IS_AN_ERROR | PHY_M_IS_AN_COMPL, | ||
| 1457 | }; | ||
| 1456 | 1458 | ||
| 1457 | /***** PHY_MARV_EXT_CTRL 16 bit r/w Ext. PHY Specific Ctrl *****/ | 1459 | /***** PHY_MARV_EXT_CTRL 16 bit r/w Ext. PHY Specific Ctrl *****/ |
| 1458 | enum { | 1460 | enum { |
| @@ -1509,7 +1511,7 @@ enum { | |||
| 1509 | PHY_M_LEDC_TX_C_MSB = 1<<0, /* Tx Control (MSB, 88E1111 only) */ | 1511 | PHY_M_LEDC_TX_C_MSB = 1<<0, /* Tx Control (MSB, 88E1111 only) */ |
| 1510 | }; | 1512 | }; |
| 1511 | 1513 | ||
| 1512 | #define PHY_M_LED_PULS_DUR(x) ( ((x)<<12) & PHY_M_LEDC_PULS_MSK) | 1514 | #define PHY_M_LED_PULS_DUR(x) (((x)<<12) & PHY_M_LEDC_PULS_MSK) |
| 1513 | 1515 | ||
| 1514 | enum { | 1516 | enum { |
| 1515 | PULS_NO_STR = 0,/* no pulse stretching */ | 1517 | PULS_NO_STR = 0,/* no pulse stretching */ |
| @@ -1522,7 +1524,7 @@ enum { | |||
| 1522 | PULS_1300MS = 7,/* 1.3 s to 2.7 s */ | 1524 | PULS_1300MS = 7,/* 1.3 s to 2.7 s */ |
| 1523 | }; | 1525 | }; |
| 1524 | 1526 | ||
| 1525 | #define PHY_M_LED_BLINK_RT(x) ( ((x)<<8) & PHY_M_LEDC_BL_R_MSK) | 1527 | #define PHY_M_LED_BLINK_RT(x) (((x)<<8) & PHY_M_LEDC_BL_R_MSK) |
| 1526 | 1528 | ||
| 1527 | enum { | 1529 | enum { |
| 1528 | BLINK_42MS = 0,/* 42 ms */ | 1530 | BLINK_42MS = 0,/* 42 ms */ |
| @@ -1602,9 +1604,9 @@ enum { | |||
| 1602 | PHY_M_FELP_LED0_MSK = 0xf, /* Bit 3.. 0: LED0 Mask (SPEED) */ | 1604 | PHY_M_FELP_LED0_MSK = 0xf, /* Bit 3.. 0: LED0 Mask (SPEED) */ |
| 1603 | }; | 1605 | }; |
| 1604 | 1606 | ||
| 1605 | #define PHY_M_FELP_LED2_CTRL(x) ( ((x)<<8) & PHY_M_FELP_LED2_MSK) | 1607 | #define PHY_M_FELP_LED2_CTRL(x) (((x)<<8) & PHY_M_FELP_LED2_MSK) |
| 1606 | #define PHY_M_FELP_LED1_CTRL(x) ( ((x)<<4) & PHY_M_FELP_LED1_MSK) | 1608 | #define PHY_M_FELP_LED1_CTRL(x) (((x)<<4) & PHY_M_FELP_LED1_MSK) |
| 1607 | #define PHY_M_FELP_LED0_CTRL(x) ( ((x)<<0) & PHY_M_FELP_LED0_MSK) | 1609 | #define PHY_M_FELP_LED0_CTRL(x) (((x)<<0) & PHY_M_FELP_LED0_MSK) |
| 1608 | 1610 | ||
| 1609 | enum { | 1611 | enum { |
| 1610 | LED_PAR_CTRL_COLX = 0x00, | 1612 | LED_PAR_CTRL_COLX = 0x00, |
| @@ -1640,7 +1642,7 @@ enum { | |||
| 1640 | PHY_M_MAC_MD_COPPER = 5,/* Copper only */ | 1642 | PHY_M_MAC_MD_COPPER = 5,/* Copper only */ |
| 1641 | PHY_M_MAC_MD_1000BX = 7,/* 1000Base-X only */ | 1643 | PHY_M_MAC_MD_1000BX = 7,/* 1000Base-X only */ |
| 1642 | }; | 1644 | }; |
| 1643 | #define PHY_M_MAC_MODE_SEL(x) ( ((x)<<7) & PHY_M_MAC_MD_MSK) | 1645 | #define PHY_M_MAC_MODE_SEL(x) (((x)<<7) & PHY_M_MAC_MD_MSK) |
| 1644 | 1646 | ||
| 1645 | /***** PHY_MARV_PHY_CTRL (page 3) 16 bit r/w LED Control Reg. *****/ | 1647 | /***** PHY_MARV_PHY_CTRL (page 3) 16 bit r/w LED Control Reg. *****/ |
| 1646 | enum { | 1648 | enum { |
| @@ -1650,10 +1652,10 @@ enum { | |||
| 1650 | PHY_M_LEDC_STA0_MSK = 0xf, /* Bit 3.. 0: STAT0 LED Ctrl. Mask */ | 1652 | PHY_M_LEDC_STA0_MSK = 0xf, /* Bit 3.. 0: STAT0 LED Ctrl. Mask */ |
| 1651 | }; | 1653 | }; |
| 1652 | 1654 | ||
| 1653 | #define PHY_M_LEDC_LOS_CTRL(x) ( ((x)<<12) & PHY_M_LEDC_LOS_MSK) | 1655 | #define PHY_M_LEDC_LOS_CTRL(x) (((x)<<12) & PHY_M_LEDC_LOS_MSK) |
| 1654 | #define PHY_M_LEDC_INIT_CTRL(x) ( ((x)<<8) & PHY_M_LEDC_INIT_MSK) | 1656 | #define PHY_M_LEDC_INIT_CTRL(x) (((x)<<8) & PHY_M_LEDC_INIT_MSK) |
| 1655 | #define PHY_M_LEDC_STA1_CTRL(x) ( ((x)<<4) & PHY_M_LEDC_STA1_MSK) | 1657 | #define PHY_M_LEDC_STA1_CTRL(x) (((x)<<4) & PHY_M_LEDC_STA1_MSK) |
| 1656 | #define PHY_M_LEDC_STA0_CTRL(x) ( ((x)<<0) & PHY_M_LEDC_STA0_MSK) | 1658 | #define PHY_M_LEDC_STA0_CTRL(x) (((x)<<0) & PHY_M_LEDC_STA0_MSK) |
| 1657 | 1659 | ||
| 1658 | /* GMAC registers */ | 1660 | /* GMAC registers */ |
| 1659 | /* Port Registers */ | 1661 | /* Port Registers */ |
| @@ -2505,8 +2507,6 @@ struct skge_port { | |||
| 2505 | dma_addr_t dma; | 2507 | dma_addr_t dma; |
| 2506 | unsigned long mem_size; | 2508 | unsigned long mem_size; |
| 2507 | unsigned int rx_buf_size; | 2509 | unsigned int rx_buf_size; |
| 2508 | |||
| 2509 | struct timer_list led_blink; | ||
| 2510 | }; | 2510 | }; |
| 2511 | 2511 | ||
| 2512 | 2512 | ||
| @@ -2606,17 +2606,6 @@ static inline void gma_write16(const struct skge_hw *hw, int port, int r, u16 v) | |||
| 2606 | skge_write16(hw, SK_GMAC_REG(port,r), v); | 2606 | skge_write16(hw, SK_GMAC_REG(port,r), v); |
| 2607 | } | 2607 | } |
| 2608 | 2608 | ||
| 2609 | static inline void gma_write32(const struct skge_hw *hw, int port, int r, u32 v) | ||
| 2610 | { | ||
| 2611 | skge_write16(hw, SK_GMAC_REG(port, r), (u16) v); | ||
| 2612 | skge_write32(hw, SK_GMAC_REG(port, r+4), (u16)(v >> 16)); | ||
| 2613 | } | ||
| 2614 | |||
| 2615 | static inline void gma_write8(const struct skge_hw *hw, int port, int r, u8 v) | ||
| 2616 | { | ||
| 2617 | skge_write8(hw, SK_GMAC_REG(port,r), v); | ||
| 2618 | } | ||
| 2619 | |||
| 2620 | static inline void gma_set_addr(struct skge_hw *hw, int port, int reg, | 2609 | static inline void gma_set_addr(struct skge_hw *hw, int port, int reg, |
| 2621 | const u8 *addr) | 2610 | const u8 *addr) |
| 2622 | { | 2611 | { |
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index 7089d86e857a..a9b06b8d8e3f 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h | |||
| @@ -188,7 +188,7 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg) | |||
| 188 | #define SMC_IRQ_TRIGGER_TYPE (( \ | 188 | #define SMC_IRQ_TRIGGER_TYPE (( \ |
| 189 | machine_is_omap_h2() \ | 189 | machine_is_omap_h2() \ |
| 190 | || machine_is_omap_h3() \ | 190 | || machine_is_omap_h3() \ |
| 191 | || (machine_is_omap_innovator() && !cpu_is_omap150()) \ | 191 | || (machine_is_omap_innovator() && !cpu_is_omap1510()) \ |
| 192 | ) ? IRQT_FALLING : IRQT_RISING) | 192 | ) ? IRQT_FALLING : IRQT_RISING) |
| 193 | 193 | ||
| 194 | 194 | ||
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 201a550f0bcc..368b8fb14023 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
| @@ -66,8 +66,8 @@ | |||
| 66 | 66 | ||
| 67 | #define DRV_MODULE_NAME "tg3" | 67 | #define DRV_MODULE_NAME "tg3" |
| 68 | #define PFX DRV_MODULE_NAME ": " | 68 | #define PFX DRV_MODULE_NAME ": " |
| 69 | #define DRV_MODULE_VERSION "3.34" | 69 | #define DRV_MODULE_VERSION "3.35" |
| 70 | #define DRV_MODULE_RELDATE "July 25, 2005" | 70 | #define DRV_MODULE_RELDATE "August 6, 2005" |
| 71 | 71 | ||
| 72 | #define TG3_DEF_MAC_MODE 0 | 72 | #define TG3_DEF_MAC_MODE 0 |
| 73 | #define TG3_DEF_RX_MODE 0 | 73 | #define TG3_DEF_RX_MODE 0 |
| @@ -10421,6 +10421,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, | |||
| 10421 | 10421 | ||
| 10422 | tg3_init_coal(tp); | 10422 | tg3_init_coal(tp); |
| 10423 | 10423 | ||
| 10424 | /* Now that we have fully setup the chip, save away a snapshot | ||
| 10425 | * of the PCI config space. We need to restore this after | ||
| 10426 | * GRC_MISC_CFG core clock resets and some resume events. | ||
| 10427 | */ | ||
| 10428 | pci_save_state(tp->pdev); | ||
| 10429 | |||
| 10424 | err = register_netdev(dev); | 10430 | err = register_netdev(dev); |
| 10425 | if (err) { | 10431 | if (err) { |
| 10426 | printk(KERN_ERR PFX "Cannot register net device, " | 10432 | printk(KERN_ERR PFX "Cannot register net device, " |
| @@ -10430,12 +10436,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, | |||
| 10430 | 10436 | ||
| 10431 | pci_set_drvdata(pdev, dev); | 10437 | pci_set_drvdata(pdev, dev); |
| 10432 | 10438 | ||
| 10433 | /* Now that we have fully setup the chip, save away a snapshot | ||
| 10434 | * of the PCI config space. We need to restore this after | ||
| 10435 | * GRC_MISC_CFG core clock resets and some resume events. | ||
| 10436 | */ | ||
| 10437 | pci_save_state(tp->pdev); | ||
| 10438 | |||
| 10439 | printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (PCI%s:%s:%s) %sBaseT Ethernet ", | 10439 | printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (PCI%s:%s:%s) %sBaseT Ethernet ", |
| 10440 | dev->name, | 10440 | dev->name, |
| 10441 | tp->board_part_number, | 10441 | tp->board_part_number, |
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index fedae89d8f7d..fb9a11243d2a 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c | |||
| @@ -60,7 +60,9 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, | |||
| 60 | continue; | 60 | continue; |
| 61 | 61 | ||
| 62 | /* Ok, try it out.. */ | 62 | /* Ok, try it out.. */ |
| 63 | ret = allocate_resource(r, res, size, min, -1, align, | 63 | ret = allocate_resource(r, res, size, |
| 64 | r->start ? : min, | ||
| 65 | -1, align, | ||
| 64 | alignf, alignf_data); | 66 | alignf, alignf_data); |
| 65 | if (ret == 0) | 67 | if (ret == 0) |
| 66 | break; | 68 | break; |
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 8d0968bd527e..a9160ad16581 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
| @@ -373,6 +373,25 @@ static void __devinit quirk_vt82c686_acpi(struct pci_dev *dev) | |||
| 373 | } | 373 | } |
| 374 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt82c686_acpi ); | 374 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt82c686_acpi ); |
| 375 | 375 | ||
| 376 | /* | ||
| 377 | * VIA VT8235 ISA Bridge: Two IO regions pointed to by words at | ||
| 378 | * 0x88 (128 bytes of power management registers) | ||
| 379 | * 0xd0 (16 bytes of SMB registers) | ||
| 380 | */ | ||
| 381 | static void __devinit quirk_vt8235_acpi(struct pci_dev *dev) | ||
| 382 | { | ||
| 383 | u16 pm, smb; | ||
| 384 | |||
| 385 | pci_read_config_word(dev, 0x88, &pm); | ||
| 386 | pm &= PCI_BASE_ADDRESS_IO_MASK; | ||
| 387 | quirk_io_region(dev, pm, 128, PCI_BRIDGE_RESOURCES); | ||
| 388 | |||
| 389 | pci_read_config_word(dev, 0xd0, &smb); | ||
| 390 | smb &= PCI_BASE_ADDRESS_IO_MASK; | ||
| 391 | quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 1); | ||
| 392 | } | ||
| 393 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, quirk_vt8235_acpi); | ||
| 394 | |||
| 376 | 395 | ||
| 377 | #ifdef CONFIG_X86_IO_APIC | 396 | #ifdef CONFIG_X86_IO_APIC |
| 378 | 397 | ||
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 1ca21d2ba11c..84eedc965688 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c | |||
| @@ -33,6 +33,11 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno) | |||
| 33 | u32 new, check, mask; | 33 | u32 new, check, mask; |
| 34 | int reg; | 34 | int reg; |
| 35 | 35 | ||
| 36 | /* Ignore resources for unimplemented BARs and unused resource slots | ||
| 37 | for 64 bit BARs. */ | ||
| 38 | if (!res->flags) | ||
| 39 | return; | ||
| 40 | |||
| 36 | pcibios_resource_to_bus(dev, ®ion, res); | 41 | pcibios_resource_to_bus(dev, ®ion, res); |
| 37 | 42 | ||
| 38 | pr_debug(" got res [%lx:%lx] bus [%lx:%lx] flags %lx for " | 43 | pr_debug(" got res [%lx:%lx] bus [%lx:%lx] flags %lx for " |
| @@ -67,7 +72,7 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno) | |||
| 67 | 72 | ||
| 68 | if ((new & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == | 73 | if ((new & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == |
| 69 | (PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64)) { | 74 | (PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64)) { |
| 70 | new = 0; /* currently everyone zeros the high address */ | 75 | new = region.start >> 16 >> 16; |
| 71 | pci_write_config_dword(dev, reg + 4, new); | 76 | pci_write_config_dword(dev, reg + 4, new); |
| 72 | pci_read_config_dword(dev, reg + 4, &check); | 77 | pci_read_config_dword(dev, reg + 4, &check); |
| 73 | if (check != new) { | 78 | if (check != new) { |
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index d63f22a5bf7e..43da2e92d50f 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
| @@ -589,8 +589,8 @@ static void pcmcia_delayed_add_pseudo_device(void *data) | |||
| 589 | static inline void pcmcia_add_pseudo_device(struct pcmcia_socket *s) | 589 | static inline void pcmcia_add_pseudo_device(struct pcmcia_socket *s) |
| 590 | { | 590 | { |
| 591 | if (!s->pcmcia_state.device_add_pending) { | 591 | if (!s->pcmcia_state.device_add_pending) { |
| 592 | schedule_work(&s->device_add); | ||
| 593 | s->pcmcia_state.device_add_pending = 1; | 592 | s->pcmcia_state.device_add_pending = 1; |
| 593 | schedule_work(&s->device_add); | ||
| 594 | } | 594 | } |
| 595 | return; | 595 | return; |
| 596 | } | 596 | } |
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 744e469a9eda..62fd705203fb 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c | |||
| @@ -605,9 +605,8 @@ static int yenta_search_res(struct yenta_socket *socket, struct resource *res, | |||
| 605 | 605 | ||
| 606 | static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end) | 606 | static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end) |
| 607 | { | 607 | { |
| 608 | struct pci_bus *bus; | ||
| 609 | struct resource *root, *res; | 608 | struct resource *root, *res; |
| 610 | u32 start, end; | 609 | struct pci_bus_region region; |
| 611 | unsigned mask; | 610 | unsigned mask; |
| 612 | 611 | ||
| 613 | res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr; | 612 | res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr; |
| @@ -620,15 +619,13 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ | |||
| 620 | if (type & IORESOURCE_IO) | 619 | if (type & IORESOURCE_IO) |
| 621 | mask = ~3; | 620 | mask = ~3; |
| 622 | 621 | ||
| 623 | bus = socket->dev->subordinate; | 622 | res->name = socket->dev->subordinate->name; |
| 624 | res->name = bus->name; | ||
| 625 | res->flags = type; | 623 | res->flags = type; |
| 626 | 624 | ||
| 627 | start = config_readl(socket, addr_start) & mask; | 625 | region.start = config_readl(socket, addr_start) & mask; |
| 628 | end = config_readl(socket, addr_end) | ~mask; | 626 | region.end = config_readl(socket, addr_end) | ~mask; |
| 629 | if (start && end > start && !override_bios) { | 627 | if (region.start && region.end > region.start && !override_bios) { |
| 630 | res->start = start; | 628 | pcibios_bus_to_resource(socket->dev, res, ®ion); |
| 631 | res->end = end; | ||
| 632 | root = pci_find_parent_resource(socket->dev, res); | 629 | root = pci_find_parent_resource(socket->dev, res); |
| 633 | if (root && (request_resource(root, res) == 0)) | 630 | if (root && (request_resource(root, res) == 0)) |
| 634 | return; | 631 | return; |
| @@ -642,6 +639,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ | |||
| 642 | (yenta_search_res(socket, res, BRIDGE_IO_MIN))) { | 639 | (yenta_search_res(socket, res, BRIDGE_IO_MIN))) { |
| 643 | config_writel(socket, addr_start, res->start); | 640 | config_writel(socket, addr_start, res->start); |
| 644 | config_writel(socket, addr_end, res->end); | 641 | config_writel(socket, addr_end, res->end); |
| 642 | return; | ||
| 645 | } | 643 | } |
| 646 | } else { | 644 | } else { |
| 647 | if (type & IORESOURCE_PREFETCH) { | 645 | if (type & IORESOURCE_PREFETCH) { |
| @@ -650,6 +648,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ | |||
| 650 | (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) { | 648 | (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) { |
| 651 | config_writel(socket, addr_start, res->start); | 649 | config_writel(socket, addr_start, res->start); |
| 652 | config_writel(socket, addr_end, res->end); | 650 | config_writel(socket, addr_end, res->end); |
| 651 | return; | ||
| 653 | } | 652 | } |
| 654 | /* Approximating prefetchable by non-prefetchable */ | 653 | /* Approximating prefetchable by non-prefetchable */ |
| 655 | res->flags = IORESOURCE_MEM; | 654 | res->flags = IORESOURCE_MEM; |
| @@ -659,6 +658,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ | |||
| 659 | (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) { | 658 | (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) { |
| 660 | config_writel(socket, addr_start, res->start); | 659 | config_writel(socket, addr_start, res->start); |
| 661 | config_writel(socket, addr_end, res->end); | 660 | config_writel(socket, addr_end, res->end); |
| 661 | return; | ||
| 662 | } | 662 | } |
| 663 | } | 663 | } |
| 664 | 664 | ||
| @@ -1107,8 +1107,6 @@ static int yenta_dev_suspend (struct pci_dev *dev, pm_message_t state) | |||
| 1107 | pci_read_config_dword(dev, 17*4, &socket->saved_state[1]); | 1107 | pci_read_config_dword(dev, 17*4, &socket->saved_state[1]); |
| 1108 | pci_disable_device(dev); | 1108 | pci_disable_device(dev); |
| 1109 | 1109 | ||
| 1110 | free_irq(dev->irq, socket); | ||
| 1111 | |||
| 1112 | /* | 1110 | /* |
| 1113 | * Some laptops (IBM T22) do not like us putting the Cardbus | 1111 | * Some laptops (IBM T22) do not like us putting the Cardbus |
| 1114 | * bridge into D3. At a guess, some other laptop will | 1112 | * bridge into D3. At a guess, some other laptop will |
| @@ -1134,13 +1132,6 @@ static int yenta_dev_resume (struct pci_dev *dev) | |||
| 1134 | pci_enable_device(dev); | 1132 | pci_enable_device(dev); |
| 1135 | pci_set_master(dev); | 1133 | pci_set_master(dev); |
| 1136 | 1134 | ||
| 1137 | if (socket->cb_irq) | ||
| 1138 | if (request_irq(socket->cb_irq, yenta_interrupt, | ||
| 1139 | SA_SHIRQ, "yenta", socket)) { | ||
| 1140 | printk(KERN_WARNING "Yenta: request_irq() failed on resume!\n"); | ||
| 1141 | socket->cb_irq = 0; | ||
| 1142 | } | ||
| 1143 | |||
| 1144 | if (socket->type && socket->type->restore_state) | 1135 | if (socket->type && socket->type->restore_state) |
| 1145 | socket->type->restore_state(socket); | 1136 | socket->type->restore_state(socket); |
| 1146 | } | 1137 | } |
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 8f4d2999af8e..79c74f3a11f5 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c | |||
| @@ -8120,20 +8120,22 @@ static struct notifier_block qeth_ip6_notifier = { | |||
| 8120 | #endif | 8120 | #endif |
| 8121 | 8121 | ||
| 8122 | static int | 8122 | static int |
| 8123 | qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr) | 8123 | __qeth_reboot_event_card(struct device *dev, void *data) |
| 8124 | { | 8124 | { |
| 8125 | |||
| 8126 | struct device *entry; | ||
| 8127 | struct qeth_card *card; | 8125 | struct qeth_card *card; |
| 8128 | 8126 | ||
| 8129 | down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); | 8127 | card = (struct qeth_card *) dev->driver_data; |
| 8130 | list_for_each_entry(entry, &qeth_ccwgroup_driver.driver.devices, | 8128 | qeth_clear_ip_list(card, 0, 0); |
| 8131 | driver_list) { | 8129 | qeth_qdio_clear_card(card, 0); |
| 8132 | card = (struct qeth_card *) entry->driver_data; | 8130 | return 0; |
| 8133 | qeth_clear_ip_list(card, 0, 0); | 8131 | } |
| 8134 | qeth_qdio_clear_card(card, 0); | 8132 | |
| 8135 | } | 8133 | static int |
| 8136 | up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); | 8134 | qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr) |
| 8135 | { | ||
| 8136 | |||
| 8137 | driver_for_each_device(&qeth_ccwgroup_driver.driver, NULL, NULL, | ||
| 8138 | __qeth_reboot_event_card); | ||
| 8137 | return NOTIFY_DONE; | 8139 | return NOTIFY_DONE; |
| 8138 | } | 8140 | } |
| 8139 | 8141 | ||
diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c index 04719196fd20..f2ccfea8fdb8 100644 --- a/drivers/s390/net/qeth_proc.c +++ b/drivers/s390/net/qeth_proc.c | |||
| @@ -27,23 +27,33 @@ const char *VERSION_QETH_PROC_C = "$Revision: 1.13 $"; | |||
| 27 | #define QETH_PROCFILE_NAME "qeth" | 27 | #define QETH_PROCFILE_NAME "qeth" |
| 28 | static struct proc_dir_entry *qeth_procfile; | 28 | static struct proc_dir_entry *qeth_procfile; |
| 29 | 29 | ||
| 30 | static int | ||
| 31 | qeth_procfile_seq_match(struct device *dev, void *data) | ||
| 32 | { | ||
| 33 | return 1; | ||
| 34 | } | ||
| 35 | |||
| 30 | static void * | 36 | static void * |
| 31 | qeth_procfile_seq_start(struct seq_file *s, loff_t *offset) | 37 | qeth_procfile_seq_start(struct seq_file *s, loff_t *offset) |
| 32 | { | 38 | { |
| 33 | struct list_head *next_card = NULL; | 39 | struct device *dev; |
| 34 | int i = 0; | 40 | loff_t nr; |
| 35 | 41 | ||
| 36 | down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); | 42 | down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); |
| 37 | 43 | ||
| 38 | if (*offset == 0) | 44 | nr = *offset; |
| 45 | if (nr == 0) | ||
| 39 | return SEQ_START_TOKEN; | 46 | return SEQ_START_TOKEN; |
| 40 | 47 | ||
| 41 | /* get card at pos *offset */ | 48 | dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL, |
| 42 | list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices) | 49 | NULL, qeth_procfile_seq_match); |
| 43 | if (++i == *offset) | ||
| 44 | return next_card; | ||
| 45 | 50 | ||
| 46 | return NULL; | 51 | /* get card at pos *offset */ |
| 52 | nr = *offset; | ||
| 53 | while (nr-- > 1 && dev) | ||
| 54 | dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev, | ||
| 55 | NULL, qeth_procfile_seq_match); | ||
| 56 | return (void *) dev; | ||
| 47 | } | 57 | } |
| 48 | 58 | ||
| 49 | static void | 59 | static void |
| @@ -55,23 +65,21 @@ qeth_procfile_seq_stop(struct seq_file *s, void* it) | |||
| 55 | static void * | 65 | static void * |
| 56 | qeth_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset) | 66 | qeth_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset) |
| 57 | { | 67 | { |
| 58 | struct list_head *next_card = NULL; | 68 | struct device *prev, *next; |
| 59 | struct list_head *current_card; | ||
| 60 | 69 | ||
| 61 | if (it == SEQ_START_TOKEN) { | 70 | if (it == SEQ_START_TOKEN) { |
| 62 | next_card = qeth_ccwgroup_driver.driver.devices.next; | 71 | next = driver_find_device(&qeth_ccwgroup_driver.driver, |
| 63 | if (next_card->next == next_card) /* list empty */ | 72 | NULL, NULL, qeth_procfile_seq_match); |
| 64 | return NULL; | 73 | if (next) |
| 65 | (*offset)++; | 74 | (*offset)++; |
| 66 | } else { | 75 | return (void *) next; |
| 67 | current_card = (struct list_head *)it; | ||
| 68 | if (current_card->next == &qeth_ccwgroup_driver.driver.devices) | ||
| 69 | return NULL; /* end of list reached */ | ||
| 70 | next_card = current_card->next; | ||
| 71 | (*offset)++; | ||
| 72 | } | 76 | } |
| 73 | 77 | prev = (struct device *) it; | |
| 74 | return next_card; | 78 | next = driver_find_device(&qeth_ccwgroup_driver.driver, |
| 79 | prev, NULL, qeth_procfile_seq_match); | ||
| 80 | if (next) | ||
| 81 | (*offset)++; | ||
| 82 | return (void *) next; | ||
| 75 | } | 83 | } |
| 76 | 84 | ||
| 77 | static inline const char * | 85 | static inline const char * |
| @@ -126,7 +134,7 @@ qeth_procfile_seq_show(struct seq_file *s, void *it) | |||
| 126 | "-------------- ---- ------ ---------- ---- " | 134 | "-------------- ---- ------ ---------- ---- " |
| 127 | "---- ----- -----\n"); | 135 | "---- ----- -----\n"); |
| 128 | } else { | 136 | } else { |
| 129 | device = list_entry(it, struct device, driver_list); | 137 | device = (struct device *) it; |
| 130 | card = device->driver_data; | 138 | card = device->driver_data; |
| 131 | seq_printf(s, "%s/%s/%s x%02X %-10s %-14s %-4i ", | 139 | seq_printf(s, "%s/%s/%s x%02X %-10s %-14s %-4i ", |
| 132 | CARD_RDEV_ID(card), | 140 | CARD_RDEV_ID(card), |
| @@ -180,17 +188,20 @@ static struct proc_dir_entry *qeth_perf_procfile; | |||
| 180 | static void * | 188 | static void * |
| 181 | qeth_perf_procfile_seq_start(struct seq_file *s, loff_t *offset) | 189 | qeth_perf_procfile_seq_start(struct seq_file *s, loff_t *offset) |
| 182 | { | 190 | { |
| 183 | struct list_head *next_card = NULL; | 191 | struct device *dev = NULL; |
| 184 | int i = 0; | 192 | int nr; |
| 185 | 193 | ||
| 186 | down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); | 194 | down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); |
| 187 | /* get card at pos *offset */ | 195 | /* get card at pos *offset */ |
| 188 | list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices){ | 196 | dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL, NULL, |
| 189 | if (i == *offset) | 197 | qeth_procfile_seq_match); |
| 190 | return next_card; | 198 | |
| 191 | i++; | 199 | /* get card at pos *offset */ |
| 192 | } | 200 | nr = *offset; |
| 193 | return NULL; | 201 | while (nr-- > 1 && dev) |
| 202 | dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev, | ||
| 203 | NULL, qeth_procfile_seq_match); | ||
| 204 | return (void *) dev; | ||
| 194 | } | 205 | } |
| 195 | 206 | ||
| 196 | static void | 207 | static void |
| @@ -202,12 +213,14 @@ qeth_perf_procfile_seq_stop(struct seq_file *s, void* it) | |||
| 202 | static void * | 213 | static void * |
| 203 | qeth_perf_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset) | 214 | qeth_perf_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset) |
| 204 | { | 215 | { |
| 205 | struct list_head *current_card = (struct list_head *)it; | 216 | struct device *prev, *next; |
| 206 | 217 | ||
| 207 | if (current_card->next == &qeth_ccwgroup_driver.driver.devices) | 218 | prev = (struct device *) it; |
| 208 | return NULL; /* end of list reached */ | 219 | next = driver_find_device(&qeth_ccwgroup_driver.driver, prev, |
| 209 | (*offset)++; | 220 | NULL, qeth_procfile_seq_match); |
| 210 | return current_card->next; | 221 | if (next) |
| 222 | (*offset)++; | ||
| 223 | return (void *) next; | ||
| 211 | } | 224 | } |
| 212 | 225 | ||
| 213 | static int | 226 | static int |
| @@ -216,7 +229,7 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it) | |||
| 216 | struct device *device; | 229 | struct device *device; |
| 217 | struct qeth_card *card; | 230 | struct qeth_card *card; |
| 218 | 231 | ||
| 219 | device = list_entry(it, struct device, driver_list); | 232 | device = (struct device *) it; |
| 220 | card = device->driver_data; | 233 | card = device->driver_data; |
| 221 | seq_printf(s, "For card with devnos %s/%s/%s (%s):\n", | 234 | seq_printf(s, "For card with devnos %s/%s/%s (%s):\n", |
| 222 | CARD_RDEV_ID(card), | 235 | CARD_RDEV_ID(card), |
| @@ -318,8 +331,8 @@ static struct proc_dir_entry *qeth_ipato_procfile; | |||
| 318 | static void * | 331 | static void * |
| 319 | qeth_ipato_procfile_seq_start(struct seq_file *s, loff_t *offset) | 332 | qeth_ipato_procfile_seq_start(struct seq_file *s, loff_t *offset) |
| 320 | { | 333 | { |
| 321 | struct list_head *next_card = NULL; | 334 | struct device *dev; |
| 322 | int i = 0; | 335 | loff_t nr; |
| 323 | 336 | ||
| 324 | down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); | 337 | down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); |
| 325 | /* TODO: finish this */ | 338 | /* TODO: finish this */ |
| @@ -328,13 +341,16 @@ qeth_ipato_procfile_seq_start(struct seq_file *s, loff_t *offset) | |||
| 328 | * output driver settings then; | 341 | * output driver settings then; |
| 329 | * else output setting for respective card | 342 | * else output setting for respective card |
| 330 | */ | 343 | */ |
| 344 | |||
| 345 | dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL, NULL, | ||
| 346 | qeth_procfile_seq_match); | ||
| 347 | |||
| 331 | /* get card at pos *offset */ | 348 | /* get card at pos *offset */ |
| 332 | list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices){ | 349 | nr = *offset; |
| 333 | if (i == *offset) | 350 | while (nr-- > 1 && dev) |
| 334 | return next_card; | 351 | dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev, |
| 335 | i++; | 352 | NULL, qeth_procfile_seq_match); |
| 336 | } | 353 | return (void *) dev; |
| 337 | return NULL; | ||
| 338 | } | 354 | } |
| 339 | 355 | ||
| 340 | static void | 356 | static void |
| @@ -346,18 +362,14 @@ qeth_ipato_procfile_seq_stop(struct seq_file *s, void* it) | |||
| 346 | static void * | 362 | static void * |
| 347 | qeth_ipato_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset) | 363 | qeth_ipato_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset) |
| 348 | { | 364 | { |
| 349 | struct list_head *current_card = (struct list_head *)it; | 365 | struct device *prev, *next; |
| 350 | 366 | ||
| 351 | /* TODO: finish this */ | 367 | prev = (struct device *) it; |
| 352 | /* | 368 | next = driver_find_device(&qeth_ccwgroup_driver.driver, prev, |
| 353 | * maybe SEQ_SATRT_TOKEN can be returned for offset 0 | 369 | NULL, qeth_procfile_seq_match); |
| 354 | * output driver settings then; | 370 | if (next) |
| 355 | * else output setting for respective card | 371 | (*offset)++; |
| 356 | */ | 372 | return (void *) next; |
| 357 | if (current_card->next == &qeth_ccwgroup_driver.driver.devices) | ||
| 358 | return NULL; /* end of list reached */ | ||
| 359 | (*offset)++; | ||
| 360 | return current_card->next; | ||
| 361 | } | 373 | } |
| 362 | 374 | ||
| 363 | static int | 375 | static int |
| @@ -372,7 +384,7 @@ qeth_ipato_procfile_seq_show(struct seq_file *s, void *it) | |||
| 372 | * output driver settings then; | 384 | * output driver settings then; |
| 373 | * else output setting for respective card | 385 | * else output setting for respective card |
| 374 | */ | 386 | */ |
| 375 | device = list_entry(it, struct device, driver_list); | 387 | device = (struct device *) it; |
| 376 | card = device->driver_data; | 388 | card = device->driver_data; |
| 377 | 389 | ||
| 378 | return 0; | 390 | return 0; |
diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c index b8a2c7353b0a..d44205d52bf3 100644 --- a/drivers/sbus/char/bbc_envctrl.c +++ b/drivers/sbus/char/bbc_envctrl.c | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #define __KERNEL_SYSCALLS__ | 7 | #define __KERNEL_SYSCALLS__ |
| 8 | 8 | ||
| 9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
| 10 | #include <linux/kthread.h> | ||
| 10 | #include <linux/sched.h> | 11 | #include <linux/sched.h> |
| 11 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| 12 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
| @@ -459,10 +460,6 @@ static struct task_struct *kenvctrld_task; | |||
| 459 | 460 | ||
| 460 | static int kenvctrld(void *__unused) | 461 | static int kenvctrld(void *__unused) |
| 461 | { | 462 | { |
| 462 | daemonize("kenvctrld"); | ||
| 463 | allow_signal(SIGKILL); | ||
| 464 | kenvctrld_task = current; | ||
| 465 | |||
| 466 | printk(KERN_INFO "bbc_envctrl: kenvctrld starting...\n"); | 463 | printk(KERN_INFO "bbc_envctrl: kenvctrld starting...\n"); |
| 467 | last_warning_jiffies = jiffies - WARN_INTERVAL; | 464 | last_warning_jiffies = jiffies - WARN_INTERVAL; |
| 468 | for (;;) { | 465 | for (;;) { |
| @@ -470,7 +467,7 @@ static int kenvctrld(void *__unused) | |||
| 470 | struct bbc_fan_control *fp; | 467 | struct bbc_fan_control *fp; |
| 471 | 468 | ||
| 472 | msleep_interruptible(POLL_INTERVAL); | 469 | msleep_interruptible(POLL_INTERVAL); |
| 473 | if (signal_pending(current)) | 470 | if (kthread_should_stop()) |
| 474 | break; | 471 | break; |
| 475 | 472 | ||
| 476 | for (tp = all_bbc_temps; tp; tp = tp->next) { | 473 | for (tp = all_bbc_temps; tp; tp = tp->next) { |
| @@ -577,7 +574,6 @@ int bbc_envctrl_init(void) | |||
| 577 | int temp_index = 0; | 574 | int temp_index = 0; |
| 578 | int fan_index = 0; | 575 | int fan_index = 0; |
| 579 | int devidx = 0; | 576 | int devidx = 0; |
| 580 | int err = 0; | ||
| 581 | 577 | ||
| 582 | while ((echild = bbc_i2c_getdev(devidx++)) != NULL) { | 578 | while ((echild = bbc_i2c_getdev(devidx++)) != NULL) { |
| 583 | if (!strcmp(echild->prom_name, "temperature")) | 579 | if (!strcmp(echild->prom_name, "temperature")) |
| @@ -585,9 +581,13 @@ int bbc_envctrl_init(void) | |||
| 585 | if (!strcmp(echild->prom_name, "fan-control")) | 581 | if (!strcmp(echild->prom_name, "fan-control")) |
| 586 | attach_one_fan(echild, fan_index++); | 582 | attach_one_fan(echild, fan_index++); |
| 587 | } | 583 | } |
| 588 | if (temp_index != 0 && fan_index != 0) | 584 | if (temp_index != 0 && fan_index != 0) { |
| 589 | err = kernel_thread(kenvctrld, NULL, CLONE_FS | CLONE_FILES); | 585 | kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld"); |
| 590 | return err; | 586 | if (IS_ERR(kenvctrld_task)) |
| 587 | return PTR_ERR(kenvctrld_task); | ||
| 588 | } | ||
| 589 | |||
| 590 | return 0; | ||
| 591 | } | 591 | } |
| 592 | 592 | ||
| 593 | static void destroy_one_temp(struct bbc_cpu_temperature *tp) | 593 | static void destroy_one_temp(struct bbc_cpu_temperature *tp) |
| @@ -607,26 +607,7 @@ void bbc_envctrl_cleanup(void) | |||
| 607 | struct bbc_cpu_temperature *tp; | 607 | struct bbc_cpu_temperature *tp; |
| 608 | struct bbc_fan_control *fp; | 608 | struct bbc_fan_control *fp; |
| 609 | 609 | ||
| 610 | if (kenvctrld_task != NULL) { | 610 | kthread_stop(kenvctrld_task); |
| 611 | force_sig(SIGKILL, kenvctrld_task); | ||
| 612 | for (;;) { | ||
| 613 | struct task_struct *p; | ||
| 614 | int found = 0; | ||
| 615 | |||
| 616 | read_lock(&tasklist_lock); | ||
| 617 | for_each_process(p) { | ||
| 618 | if (p == kenvctrld_task) { | ||
| 619 | found = 1; | ||
| 620 | break; | ||
| 621 | } | ||
| 622 | } | ||
| 623 | read_unlock(&tasklist_lock); | ||
| 624 | if (!found) | ||
| 625 | break; | ||
| 626 | msleep(1000); | ||
| 627 | } | ||
| 628 | kenvctrld_task = NULL; | ||
| 629 | } | ||
| 630 | 611 | ||
| 631 | tp = all_bbc_temps; | 612 | tp = all_bbc_temps; |
| 632 | while (tp != NULL) { | 613 | while (tp != NULL) { |
diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c index 9a8c572554f5..d765cc1bf060 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/config.h> | 24 | #include <linux/config.h> |
| 25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
| 26 | #include <linux/sched.h> | 26 | #include <linux/sched.h> |
| 27 | #include <linux/kthread.h> | ||
| 27 | #include <linux/errno.h> | 28 | #include <linux/errno.h> |
| 28 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
| 29 | #include <linux/ioport.h> | 30 | #include <linux/ioport.h> |
| @@ -1010,16 +1011,13 @@ static int kenvctrld(void *__unused) | |||
| 1010 | 1011 | ||
| 1011 | poll_interval = 5000; /* TODO env_mon_interval */ | 1012 | poll_interval = 5000; /* TODO env_mon_interval */ |
| 1012 | 1013 | ||
| 1013 | daemonize("kenvctrld"); | ||
| 1014 | allow_signal(SIGKILL); | ||
| 1015 | |||
| 1016 | kenvctrld_task = current; | ||
| 1017 | |||
| 1018 | printk(KERN_INFO "envctrl: %s starting...\n", current->comm); | 1014 | printk(KERN_INFO "envctrl: %s starting...\n", current->comm); |
| 1019 | for (;;) { | 1015 | for (;;) { |
| 1020 | if(msleep_interruptible(poll_interval)) | 1016 | msleep_interruptible(poll_interval); |
| 1021 | break; | ||
| 1022 | 1017 | ||
| 1018 | if (kthread_should_stop()) | ||
| 1019 | break; | ||
| 1020 | |||
| 1023 | for (whichcpu = 0; whichcpu < ENVCTRL_MAX_CPU; ++whichcpu) { | 1021 | for (whichcpu = 0; whichcpu < ENVCTRL_MAX_CPU; ++whichcpu) { |
| 1024 | if (0 < envctrl_read_cpu_info(whichcpu, cputemp, | 1022 | if (0 < envctrl_read_cpu_info(whichcpu, cputemp, |
| 1025 | ENVCTRL_CPUTEMP_MON, | 1023 | ENVCTRL_CPUTEMP_MON, |
| @@ -1041,7 +1039,6 @@ static int kenvctrld(void *__unused) | |||
| 1041 | 1039 | ||
| 1042 | static int __init envctrl_init(void) | 1040 | static int __init envctrl_init(void) |
| 1043 | { | 1041 | { |
| 1044 | #ifdef CONFIG_PCI | ||
| 1045 | struct linux_ebus *ebus = NULL; | 1042 | struct linux_ebus *ebus = NULL; |
| 1046 | struct linux_ebus_device *edev = NULL; | 1043 | struct linux_ebus_device *edev = NULL; |
| 1047 | struct linux_ebus_child *edev_child = NULL; | 1044 | struct linux_ebus_child *edev_child = NULL; |
| @@ -1118,9 +1115,11 @@ done: | |||
| 1118 | i2c_childlist[i].addr, (0 == i) ? ("\n") : (" ")); | 1115 | i2c_childlist[i].addr, (0 == i) ? ("\n") : (" ")); |
| 1119 | } | 1116 | } |
| 1120 | 1117 | ||
| 1121 | err = kernel_thread(kenvctrld, NULL, CLONE_FS | CLONE_FILES); | 1118 | kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld"); |
| 1122 | if (err < 0) | 1119 | if (IS_ERR(kenvctrld_task)) { |
| 1120 | err = PTR_ERR(kenvctrld_task); | ||
| 1123 | goto out_deregister; | 1121 | goto out_deregister; |
| 1122 | } | ||
| 1124 | 1123 | ||
| 1125 | return 0; | 1124 | return 0; |
| 1126 | 1125 | ||
| @@ -1133,37 +1132,13 @@ out_iounmap: | |||
| 1133 | kfree(i2c_childlist[i].tables); | 1132 | kfree(i2c_childlist[i].tables); |
| 1134 | } | 1133 | } |
| 1135 | return err; | 1134 | return err; |
| 1136 | #else | ||
| 1137 | return -ENODEV; | ||
| 1138 | #endif | ||
| 1139 | } | 1135 | } |
| 1140 | 1136 | ||
| 1141 | static void __exit envctrl_cleanup(void) | 1137 | static void __exit envctrl_cleanup(void) |
| 1142 | { | 1138 | { |
| 1143 | int i; | 1139 | int i; |
| 1144 | 1140 | ||
| 1145 | if (NULL != kenvctrld_task) { | 1141 | kthread_stop(kenvctrld_task); |
| 1146 | force_sig(SIGKILL, kenvctrld_task); | ||
| 1147 | for (;;) { | ||
| 1148 | struct task_struct *p; | ||
| 1149 | int found = 0; | ||
| 1150 | |||
| 1151 | read_lock(&tasklist_lock); | ||
| 1152 | for_each_process(p) { | ||
| 1153 | if (p == kenvctrld_task) { | ||
| 1154 | found = 1; | ||
| 1155 | break; | ||
| 1156 | } | ||
| 1157 | } | ||
| 1158 | read_unlock(&tasklist_lock); | ||
| 1159 | |||
| 1160 | if (!found) | ||
| 1161 | break; | ||
| 1162 | |||
| 1163 | msleep(1000); | ||
| 1164 | } | ||
| 1165 | kenvctrld_task = NULL; | ||
| 1166 | } | ||
| 1167 | 1142 | ||
| 1168 | iounmap(i2c); | 1143 | iounmap(i2c); |
| 1169 | misc_deregister(&envctrl_dev); | 1144 | misc_deregister(&envctrl_dev); |
diff --git a/drivers/sbus/char/vfc.h b/drivers/sbus/char/vfc.h index e56a43af0f62..a7782e7da42e 100644 --- a/drivers/sbus/char/vfc.h +++ b/drivers/sbus/char/vfc.h | |||
| @@ -129,8 +129,6 @@ struct vfc_dev { | |||
| 129 | struct vfc_regs *phys_regs; | 129 | struct vfc_regs *phys_regs; |
| 130 | unsigned int control_reg; | 130 | unsigned int control_reg; |
| 131 | struct semaphore device_lock_sem; | 131 | struct semaphore device_lock_sem; |
| 132 | struct timer_list poll_timer; | ||
| 133 | wait_queue_head_t poll_wait; | ||
| 134 | int instance; | 132 | int instance; |
| 135 | int busy; | 133 | int busy; |
| 136 | unsigned long which_io; | 134 | unsigned long which_io; |
diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c index 86ce54130954..7a103698fa3c 100644 --- a/drivers/sbus/char/vfc_dev.c +++ b/drivers/sbus/char/vfc_dev.c | |||
| @@ -137,7 +137,6 @@ int init_vfc_devstruct(struct vfc_dev *dev, int instance) | |||
| 137 | dev->instance=instance; | 137 | dev->instance=instance; |
| 138 | init_MUTEX(&dev->device_lock_sem); | 138 | init_MUTEX(&dev->device_lock_sem); |
| 139 | dev->control_reg=0; | 139 | dev->control_reg=0; |
| 140 | init_waitqueue_head(&dev->poll_wait); | ||
| 141 | dev->busy=0; | 140 | dev->busy=0; |
| 142 | return 0; | 141 | return 0; |
| 143 | } | 142 | } |
diff --git a/drivers/sbus/char/vfc_i2c.c b/drivers/sbus/char/vfc_i2c.c index 1faf1e75f71f..739cad9b19a1 100644 --- a/drivers/sbus/char/vfc_i2c.c +++ b/drivers/sbus/char/vfc_i2c.c | |||
| @@ -79,25 +79,10 @@ int vfc_pcf8584_init(struct vfc_dev *dev) | |||
| 79 | return 0; | 79 | return 0; |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | void vfc_i2c_delay_wakeup(struct vfc_dev *dev) | ||
| 83 | { | ||
| 84 | /* Used to profile code and eliminate too many delays */ | ||
| 85 | VFC_I2C_DEBUG_PRINTK(("vfc%d: Delaying\n", dev->instance)); | ||
| 86 | wake_up(&dev->poll_wait); | ||
| 87 | } | ||
| 88 | |||
| 89 | void vfc_i2c_delay_no_busy(struct vfc_dev *dev, unsigned long usecs) | 82 | void vfc_i2c_delay_no_busy(struct vfc_dev *dev, unsigned long usecs) |
| 90 | { | 83 | { |
| 91 | DEFINE_WAIT(wait); | 84 | set_current_state(TASK_UNINTERRUPTIBLE); |
| 92 | init_timer(&dev->poll_timer); | 85 | schedule_timeout(usecs_to_jiffies(usecs)); |
| 93 | dev->poll_timer.expires = jiffies + usecs_to_jiffies(usecs); | ||
| 94 | dev->poll_timer.data=(unsigned long)dev; | ||
| 95 | dev->poll_timer.function=(void *)(unsigned long)vfc_i2c_delay_wakeup; | ||
| 96 | add_timer(&dev->poll_timer); | ||
| 97 | prepare_to_wait(&dev->poll_wait, &wait, TASK_UNINTERRUPTIBLE); | ||
| 98 | schedule(); | ||
| 99 | del_timer(&dev->poll_timer); | ||
| 100 | finish_wait(&dev->poll_wait, &wait); | ||
| 101 | } | 86 | } |
| 102 | 87 | ||
| 103 | void inline vfc_i2c_delay(struct vfc_dev *dev) | 88 | void inline vfc_i2c_delay(struct vfc_dev *dev) |
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 96df148ed969..f1e8c4223ed1 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
| @@ -424,7 +424,7 @@ config SCSI_IN2000 | |||
| 424 | source "drivers/scsi/megaraid/Kconfig.megaraid" | 424 | source "drivers/scsi/megaraid/Kconfig.megaraid" |
| 425 | 425 | ||
| 426 | config SCSI_SATA | 426 | config SCSI_SATA |
| 427 | bool "Serial ATA (SATA) support" | 427 | tristate "Serial ATA (SATA) support" |
| 428 | depends on SCSI | 428 | depends on SCSI |
| 429 | help | 429 | help |
| 430 | This driver family supports Serial ATA host controllers | 430 | This driver family supports Serial ATA host controllers |
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 3a11a536c0da..4ab07861b457 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h | |||
| @@ -15,11 +15,7 @@ | |||
| 15 | #define AAC_MAX_LUN (8) | 15 | #define AAC_MAX_LUN (8) |
| 16 | 16 | ||
| 17 | #define AAC_MAX_HOSTPHYSMEMPAGES (0xfffff) | 17 | #define AAC_MAX_HOSTPHYSMEMPAGES (0xfffff) |
| 18 | /* | 18 | #define AAC_MAX_32BIT_SGBCOUNT ((unsigned short)512) |
| 19 | * max_sectors is an unsigned short, otherwise limit is 0x100000000 / 512 | ||
| 20 | * Linux has starvation problems if we permit larger than 4MB I/O ... | ||
| 21 | */ | ||
| 22 | #define AAC_MAX_32BIT_SGBCOUNT ((unsigned short)8192) | ||
| 23 | 19 | ||
| 24 | /* | 20 | /* |
| 25 | * These macros convert from physical channels to virtual channels | 21 | * These macros convert from physical channels to virtual channels |
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index c1a4f978fcba..562da90480a1 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c | |||
| @@ -374,7 +374,8 @@ static int aac_slave_configure(struct scsi_device *sdev) | |||
| 374 | else | 374 | else |
| 375 | scsi_adjust_queue_depth(sdev, 0, 1); | 375 | scsi_adjust_queue_depth(sdev, 0, 1); |
| 376 | 376 | ||
| 377 | if (host->max_sectors < AAC_MAX_32BIT_SGBCOUNT) | 377 | if (!(((struct aac_dev *)host->hostdata)->adapter_info.options |
| 378 | & AAC_OPT_NEW_COMM)) | ||
| 378 | blk_queue_max_segment_size(sdev->request_queue, 65536); | 379 | blk_queue_max_segment_size(sdev->request_queue, 65536); |
| 379 | 380 | ||
| 380 | return 0; | 381 | return 0; |
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 116d0f51ca2c..687f19e9cf03 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c | |||
| @@ -1264,14 +1264,12 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, | |||
| 1264 | } | 1264 | } |
| 1265 | switch ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED))) { | 1265 | switch ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED))) { |
| 1266 | case AHC_DEV_Q_BASIC: | 1266 | case AHC_DEV_Q_BASIC: |
| 1267 | scsi_adjust_queue_depth(sdev, | 1267 | scsi_set_tag_type(sdev, MSG_SIMPLE_TAG); |
| 1268 | MSG_SIMPLE_TASK, | 1268 | scsi_activate_tcq(sdev, dev->openings + dev->active); |
| 1269 | dev->openings + dev->active); | ||
| 1270 | break; | 1269 | break; |
| 1271 | case AHC_DEV_Q_TAGGED: | 1270 | case AHC_DEV_Q_TAGGED: |
| 1272 | scsi_adjust_queue_depth(sdev, | 1271 | scsi_set_tag_type(sdev, MSG_ORDERED_TAG); |
| 1273 | MSG_ORDERED_TASK, | 1272 | scsi_activate_tcq(sdev, dev->openings + dev->active); |
| 1274 | dev->openings + dev->active); | ||
| 1275 | break; | 1273 | break; |
| 1276 | default: | 1274 | default: |
| 1277 | /* | 1275 | /* |
| @@ -1280,9 +1278,7 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, | |||
| 1280 | * serially on the controller/device. This should | 1278 | * serially on the controller/device. This should |
| 1281 | * remove some latency. | 1279 | * remove some latency. |
| 1282 | */ | 1280 | */ |
| 1283 | scsi_adjust_queue_depth(sdev, | 1281 | scsi_deactivate_tcq(sdev, 2); |
| 1284 | /*NON-TAGGED*/0, | ||
| 1285 | /*queue depth*/2); | ||
| 1286 | break; | 1282 | break; |
| 1287 | } | 1283 | } |
| 1288 | } | 1284 | } |
| @@ -1635,9 +1631,9 @@ ahc_send_async(struct ahc_softc *ahc, char channel, | |||
| 1635 | spi_period(starget) = tinfo->curr.period; | 1631 | spi_period(starget) = tinfo->curr.period; |
| 1636 | spi_width(starget) = tinfo->curr.width; | 1632 | spi_width(starget) = tinfo->curr.width; |
| 1637 | spi_offset(starget) = tinfo->curr.offset; | 1633 | spi_offset(starget) = tinfo->curr.offset; |
| 1638 | spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ; | 1634 | spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ ? 1 : 0; |
| 1639 | spi_qas(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ; | 1635 | spi_qas(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ ? 1 : 0; |
| 1640 | spi_iu(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ; | 1636 | spi_iu(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ ? 1 : 0; |
| 1641 | spi_display_xfer_agreement(starget); | 1637 | spi_display_xfer_agreement(starget); |
| 1642 | break; | 1638 | break; |
| 1643 | } | 1639 | } |
| @@ -2429,12 +2425,14 @@ static void ahc_linux_set_dt(struct scsi_target *starget, int dt) | |||
| 2429 | unsigned int ppr_options = tinfo->goal.ppr_options | 2425 | unsigned int ppr_options = tinfo->goal.ppr_options |
| 2430 | & ~MSG_EXT_PPR_DT_REQ; | 2426 | & ~MSG_EXT_PPR_DT_REQ; |
| 2431 | unsigned int period = tinfo->goal.period; | 2427 | unsigned int period = tinfo->goal.period; |
| 2428 | unsigned int width = tinfo->goal.width; | ||
| 2432 | unsigned long flags; | 2429 | unsigned long flags; |
| 2433 | struct ahc_syncrate *syncrate; | 2430 | struct ahc_syncrate *syncrate; |
| 2434 | 2431 | ||
| 2435 | if (dt) { | 2432 | if (dt) { |
| 2436 | period = 9; /* 12.5ns is the only period valid for DT */ | ||
| 2437 | ppr_options |= MSG_EXT_PPR_DT_REQ; | 2433 | ppr_options |= MSG_EXT_PPR_DT_REQ; |
| 2434 | if (!width) | ||
| 2435 | ahc_linux_set_width(starget, 1); | ||
| 2438 | } else if (period == 9) | 2436 | } else if (period == 9) |
| 2439 | period = 10; /* if resetting DT, period must be >= 25ns */ | 2437 | period = 10; /* if resetting DT, period must be >= 25ns */ |
| 2440 | 2438 | ||
diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm.c b/drivers/scsi/aic7xxx/aicasm/aicasm.c index c34639481904..f936b691232f 100644 --- a/drivers/scsi/aic7xxx/aicasm/aicasm.c +++ b/drivers/scsi/aic7xxx/aicasm/aicasm.c | |||
| @@ -369,7 +369,7 @@ output_code() | |||
| 369 | 369 | ||
| 370 | fprintf(ofile, "%s\t0x%02x, 0x%02x, 0x%02x, 0x%02x", | 370 | fprintf(ofile, "%s\t0x%02x, 0x%02x, 0x%02x, 0x%02x", |
| 371 | cur_instr == STAILQ_FIRST(&seq_program) ? "" : ",\n", | 371 | cur_instr == STAILQ_FIRST(&seq_program) ? "" : ",\n", |
| 372 | #if BYTE_ORDER == LITTLE_ENDIAN | 372 | #ifdef __LITTLE_ENDIAN |
| 373 | cur_instr->format.bytes[0], | 373 | cur_instr->format.bytes[0], |
| 374 | cur_instr->format.bytes[1], | 374 | cur_instr->format.bytes[1], |
| 375 | cur_instr->format.bytes[2], | 375 | cur_instr->format.bytes[2], |
| @@ -613,7 +613,7 @@ output_listing(char *ifilename) | |||
| 613 | line++; | 613 | line++; |
| 614 | } | 614 | } |
| 615 | fprintf(listfile, "%03x %02x%02x%02x%02x", instrptr, | 615 | fprintf(listfile, "%03x %02x%02x%02x%02x", instrptr, |
| 616 | #if BYTE_ORDER == LITTLE_ENDIAN | 616 | #ifdef __LITTLE_ENDIAN |
| 617 | cur_instr->format.bytes[0], | 617 | cur_instr->format.bytes[0], |
| 618 | cur_instr->format.bytes[1], | 618 | cur_instr->format.bytes[1], |
| 619 | cur_instr->format.bytes[2], | 619 | cur_instr->format.bytes[2], |
diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h b/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h index 3e80f07df49c..e64f802bbaaa 100644 --- a/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h +++ b/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h | |||
| @@ -42,8 +42,10 @@ | |||
| 42 | * $FreeBSD$ | 42 | * $FreeBSD$ |
| 43 | */ | 43 | */ |
| 44 | 44 | ||
| 45 | #include <asm/byteorder.h> | ||
| 46 | |||
| 45 | struct ins_format1 { | 47 | struct ins_format1 { |
| 46 | #if BYTE_ORDER == LITTLE_ENDIAN | 48 | #ifdef __LITTLE_ENDIAN |
| 47 | uint32_t immediate : 8, | 49 | uint32_t immediate : 8, |
| 48 | source : 9, | 50 | source : 9, |
| 49 | destination : 9, | 51 | destination : 9, |
| @@ -61,7 +63,7 @@ struct ins_format1 { | |||
| 61 | }; | 63 | }; |
| 62 | 64 | ||
| 63 | struct ins_format2 { | 65 | struct ins_format2 { |
| 64 | #if BYTE_ORDER == LITTLE_ENDIAN | 66 | #ifdef __LITTLE_ENDIAN |
| 65 | uint32_t shift_control : 8, | 67 | uint32_t shift_control : 8, |
| 66 | source : 9, | 68 | source : 9, |
| 67 | destination : 9, | 69 | destination : 9, |
| @@ -79,7 +81,7 @@ struct ins_format2 { | |||
| 79 | }; | 81 | }; |
| 80 | 82 | ||
| 81 | struct ins_format3 { | 83 | struct ins_format3 { |
| 82 | #if BYTE_ORDER == LITTLE_ENDIAN | 84 | #ifdef __LITTLE_ENDIAN |
| 83 | uint32_t immediate : 8, | 85 | uint32_t immediate : 8, |
| 84 | source : 9, | 86 | source : 9, |
| 85 | address : 10, | 87 | address : 10, |
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index 929170dcd3cb..600ba1202864 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c | |||
| @@ -183,7 +183,7 @@ | |||
| 183 | * cross a page boundy. | 183 | * cross a page boundy. |
| 184 | */ | 184 | */ |
| 185 | #define SEGMENTX_LEN (sizeof(struct SGentry)*DC395x_MAX_SG_LISTENTRY) | 185 | #define SEGMENTX_LEN (sizeof(struct SGentry)*DC395x_MAX_SG_LISTENTRY) |
| 186 | #define VIRTX_LEN (sizeof(void *) * DC395x_MAX_SG_LISTENTRY) | 186 | |
| 187 | 187 | ||
| 188 | struct SGentry { | 188 | struct SGentry { |
| 189 | u32 address; /* bus! address */ | 189 | u32 address; /* bus! address */ |
| @@ -235,7 +235,6 @@ struct ScsiReqBlk { | |||
| 235 | u8 sg_count; /* No of HW sg entries for this request */ | 235 | u8 sg_count; /* No of HW sg entries for this request */ |
| 236 | u8 sg_index; /* Index of HW sg entry for this request */ | 236 | u8 sg_index; /* Index of HW sg entry for this request */ |
| 237 | u32 total_xfer_length; /* Total number of bytes remaining to be transfered */ | 237 | u32 total_xfer_length; /* Total number of bytes remaining to be transfered */ |
| 238 | void **virt_map; | ||
| 239 | unsigned char *virt_addr; /* Virtual address of current transfer position */ | 238 | unsigned char *virt_addr; /* Virtual address of current transfer position */ |
| 240 | 239 | ||
| 241 | /* | 240 | /* |
| @@ -1022,14 +1021,14 @@ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb, | |||
| 1022 | reqlen, cmd->request_buffer, cmd->use_sg, | 1021 | reqlen, cmd->request_buffer, cmd->use_sg, |
| 1023 | srb->sg_count); | 1022 | srb->sg_count); |
| 1024 | 1023 | ||
| 1024 | srb->virt_addr = page_address(sl->page); | ||
| 1025 | for (i = 0; i < srb->sg_count; i++) { | 1025 | for (i = 0; i < srb->sg_count; i++) { |
| 1026 | u32 seglen = (u32)sg_dma_len(sl + i); | 1026 | u32 busaddr = (u32)sg_dma_address(&sl[i]); |
| 1027 | sgp[i].address = (u32)sg_dma_address(sl + i); | 1027 | u32 seglen = (u32)sl[i].length; |
| 1028 | sgp[i].address = busaddr; | ||
| 1028 | sgp[i].length = seglen; | 1029 | sgp[i].length = seglen; |
| 1029 | srb->total_xfer_length += seglen; | 1030 | srb->total_xfer_length += seglen; |
| 1030 | srb->virt_map[i] = kmap(sl[i].page); | ||
| 1031 | } | 1031 | } |
| 1032 | srb->virt_addr = srb->virt_map[0]; | ||
| 1033 | sgp += srb->sg_count - 1; | 1032 | sgp += srb->sg_count - 1; |
| 1034 | 1033 | ||
| 1035 | /* | 1034 | /* |
| @@ -1976,7 +1975,6 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left) | |||
| 1976 | int segment = cmd->use_sg; | 1975 | int segment = cmd->use_sg; |
| 1977 | u32 xferred = srb->total_xfer_length - left; /* bytes transfered */ | 1976 | u32 xferred = srb->total_xfer_length - left; /* bytes transfered */ |
| 1978 | struct SGentry *psge = srb->segment_x + srb->sg_index; | 1977 | struct SGentry *psge = srb->segment_x + srb->sg_index; |
| 1979 | void **virt = srb->virt_map; | ||
| 1980 | 1978 | ||
| 1981 | dprintkdbg(DBG_0, | 1979 | dprintkdbg(DBG_0, |
| 1982 | "sg_update_list: Transfered %i of %i bytes, %i remain\n", | 1980 | "sg_update_list: Transfered %i of %i bytes, %i remain\n", |
| @@ -2016,16 +2014,16 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left) | |||
| 2016 | 2014 | ||
| 2017 | /* We have to walk the scatterlist to find it */ | 2015 | /* We have to walk the scatterlist to find it */ |
| 2018 | sg = (struct scatterlist *)cmd->request_buffer; | 2016 | sg = (struct scatterlist *)cmd->request_buffer; |
| 2019 | idx = 0; | ||
| 2020 | while (segment--) { | 2017 | while (segment--) { |
| 2021 | unsigned long mask = | 2018 | unsigned long mask = |
| 2022 | ~((unsigned long)sg->length - 1) & PAGE_MASK; | 2019 | ~((unsigned long)sg->length - 1) & PAGE_MASK; |
| 2023 | if ((sg_dma_address(sg) & mask) == (psge->address & mask)) { | 2020 | if ((sg_dma_address(sg) & mask) == (psge->address & mask)) { |
| 2024 | srb->virt_addr = virt[idx] + (psge->address & ~PAGE_MASK); | 2021 | srb->virt_addr = (page_address(sg->page) |
| 2022 | + psge->address - | ||
| 2023 | (psge->address & PAGE_MASK)); | ||
| 2025 | return; | 2024 | return; |
| 2026 | } | 2025 | } |
| 2027 | ++sg; | 2026 | ++sg; |
| 2028 | ++idx; | ||
| 2029 | } | 2027 | } |
| 2030 | 2028 | ||
| 2031 | dprintkl(KERN_ERR, "sg_update_list: sg_to_virt failed\n"); | 2029 | dprintkl(KERN_ERR, "sg_update_list: sg_to_virt failed\n"); |
| @@ -2151,7 +2149,7 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, | |||
| 2151 | DC395x_read32(acb, TRM_S1040_DMA_CXCNT)); | 2149 | DC395x_read32(acb, TRM_S1040_DMA_CXCNT)); |
| 2152 | } | 2150 | } |
| 2153 | /* | 2151 | /* |
| 2154 | * calculate all the residue data that not yet transfered | 2152 | * calculate all the residue data that not yet tranfered |
| 2155 | * SCSI transfer counter + left in SCSI FIFO data | 2153 | * SCSI transfer counter + left in SCSI FIFO data |
| 2156 | * | 2154 | * |
| 2157 | * .....TRM_S1040_SCSI_COUNTER (24bits) | 2155 | * .....TRM_S1040_SCSI_COUNTER (24bits) |
| @@ -3269,7 +3267,6 @@ static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) | |||
| 3269 | struct scsi_cmnd *cmd = srb->cmd; | 3267 | struct scsi_cmnd *cmd = srb->cmd; |
| 3270 | enum dma_data_direction dir = cmd->sc_data_direction; | 3268 | enum dma_data_direction dir = cmd->sc_data_direction; |
| 3271 | if (cmd->use_sg && dir != PCI_DMA_NONE) { | 3269 | if (cmd->use_sg && dir != PCI_DMA_NONE) { |
| 3272 | int i; | ||
| 3273 | /* unmap DC395x SG list */ | 3270 | /* unmap DC395x SG list */ |
| 3274 | dprintkdbg(DBG_SG, "pci_unmap_srb: list=%08x(%05x)\n", | 3271 | dprintkdbg(DBG_SG, "pci_unmap_srb: list=%08x(%05x)\n", |
| 3275 | srb->sg_bus_addr, SEGMENTX_LEN); | 3272 | srb->sg_bus_addr, SEGMENTX_LEN); |
| @@ -3279,8 +3276,6 @@ static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) | |||
| 3279 | dprintkdbg(DBG_SG, "pci_unmap_srb: segs=%i buffer=%p\n", | 3276 | dprintkdbg(DBG_SG, "pci_unmap_srb: segs=%i buffer=%p\n", |
| 3280 | cmd->use_sg, cmd->request_buffer); | 3277 | cmd->use_sg, cmd->request_buffer); |
| 3281 | /* unmap the sg segments */ | 3278 | /* unmap the sg segments */ |
| 3282 | for (i = 0; i < srb->sg_count; i++) | ||
| 3283 | kunmap(virt_to_page(srb->virt_map[i])); | ||
| 3284 | pci_unmap_sg(acb->dev, | 3279 | pci_unmap_sg(acb->dev, |
| 3285 | (struct scatterlist *)cmd->request_buffer, | 3280 | (struct scatterlist *)cmd->request_buffer, |
| 3286 | cmd->use_sg, dir); | 3281 | cmd->use_sg, dir); |
| @@ -3327,7 +3322,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, | |||
| 3327 | 3322 | ||
| 3328 | if (cmd->use_sg) { | 3323 | if (cmd->use_sg) { |
| 3329 | struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer; | 3324 | struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer; |
| 3330 | ptr = (struct ScsiInqData *)(srb->virt_map[0] + sg->offset); | 3325 | ptr = (struct ScsiInqData *)(page_address(sg->page) + sg->offset); |
| 3331 | } else { | 3326 | } else { |
| 3332 | ptr = (struct ScsiInqData *)(cmd->request_buffer); | 3327 | ptr = (struct ScsiInqData *)(cmd->request_buffer); |
| 3333 | } | 3328 | } |
| @@ -4262,9 +4257,8 @@ static void adapter_sg_tables_free(struct AdapterCtlBlk *acb) | |||
| 4262 | const unsigned srbs_per_page = PAGE_SIZE/SEGMENTX_LEN; | 4257 | const unsigned srbs_per_page = PAGE_SIZE/SEGMENTX_LEN; |
| 4263 | 4258 | ||
| 4264 | for (i = 0; i < DC395x_MAX_SRB_CNT; i += srbs_per_page) | 4259 | for (i = 0; i < DC395x_MAX_SRB_CNT; i += srbs_per_page) |
| 4265 | kfree(acb->srb_array[i].segment_x); | 4260 | if (acb->srb_array[i].segment_x) |
| 4266 | 4261 | kfree(acb->srb_array[i].segment_x); | |
| 4267 | vfree(acb->srb_array[0].virt_map); | ||
| 4268 | } | 4262 | } |
| 4269 | 4263 | ||
| 4270 | 4264 | ||
| @@ -4280,12 +4274,9 @@ static int __devinit adapter_sg_tables_alloc(struct AdapterCtlBlk *acb) | |||
| 4280 | int srb_idx = 0; | 4274 | int srb_idx = 0; |
| 4281 | unsigned i = 0; | 4275 | unsigned i = 0; |
| 4282 | struct SGentry *ptr; | 4276 | struct SGentry *ptr; |
| 4283 | void **virt_array; | ||
| 4284 | 4277 | ||
| 4285 | for (i = 0; i < DC395x_MAX_SRB_CNT; i++) { | 4278 | for (i = 0; i < DC395x_MAX_SRB_CNT; i++) |
| 4286 | acb->srb_array[i].segment_x = NULL; | 4279 | acb->srb_array[i].segment_x = NULL; |
| 4287 | acb->srb_array[i].virt_map = NULL; | ||
| 4288 | } | ||
| 4289 | 4280 | ||
| 4290 | dprintkdbg(DBG_1, "Allocate %i pages for SG tables\n", pages); | 4281 | dprintkdbg(DBG_1, "Allocate %i pages for SG tables\n", pages); |
| 4291 | while (pages--) { | 4282 | while (pages--) { |
| @@ -4306,19 +4297,6 @@ static int __devinit adapter_sg_tables_alloc(struct AdapterCtlBlk *acb) | |||
| 4306 | ptr + (i * DC395x_MAX_SG_LISTENTRY); | 4297 | ptr + (i * DC395x_MAX_SG_LISTENTRY); |
| 4307 | else | 4298 | else |
| 4308 | dprintkl(KERN_DEBUG, "No space for tmsrb SG table reserved?!\n"); | 4299 | dprintkl(KERN_DEBUG, "No space for tmsrb SG table reserved?!\n"); |
| 4309 | |||
| 4310 | virt_array = vmalloc((DC395x_MAX_SRB_CNT + 1) * DC395x_MAX_SG_LISTENTRY * sizeof(void*)); | ||
| 4311 | |||
| 4312 | if (!virt_array) { | ||
| 4313 | adapter_sg_tables_free(acb); | ||
| 4314 | return 1; | ||
| 4315 | } | ||
| 4316 | |||
| 4317 | for (i = 0; i < DC395x_MAX_SRB_CNT + 1; i++) { | ||
| 4318 | acb->srb_array[i].virt_map = virt_array; | ||
| 4319 | virt_array += DC395x_MAX_SG_LISTENTRY; | ||
| 4320 | } | ||
| 4321 | |||
| 4322 | return 0; | 4300 | return 0; |
| 4323 | } | 4301 | } |
| 4324 | 4302 | ||
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index e2370529c632..7235f94f1191 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c | |||
| @@ -907,9 +907,13 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev | |||
| 907 | raptorFlag = TRUE; | 907 | raptorFlag = TRUE; |
| 908 | } | 908 | } |
| 909 | 909 | ||
| 910 | 910 | if (pci_request_regions(pDev, "dpt_i2o")) { | |
| 911 | PERROR("dpti: adpt_config_hba: pci request region failed\n"); | ||
| 912 | return -EINVAL; | ||
| 913 | } | ||
| 911 | base_addr_virt = ioremap(base_addr0_phys,hba_map0_area_size); | 914 | base_addr_virt = ioremap(base_addr0_phys,hba_map0_area_size); |
| 912 | if (!base_addr_virt) { | 915 | if (!base_addr_virt) { |
| 916 | pci_release_regions(pDev); | ||
| 913 | PERROR("dpti: adpt_config_hba: io remap failed\n"); | 917 | PERROR("dpti: adpt_config_hba: io remap failed\n"); |
| 914 | return -EINVAL; | 918 | return -EINVAL; |
| 915 | } | 919 | } |
| @@ -919,6 +923,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev | |||
| 919 | if (!msg_addr_virt) { | 923 | if (!msg_addr_virt) { |
| 920 | PERROR("dpti: adpt_config_hba: io remap failed on BAR1\n"); | 924 | PERROR("dpti: adpt_config_hba: io remap failed on BAR1\n"); |
| 921 | iounmap(base_addr_virt); | 925 | iounmap(base_addr_virt); |
| 926 | pci_release_regions(pDev); | ||
| 922 | return -EINVAL; | 927 | return -EINVAL; |
| 923 | } | 928 | } |
| 924 | } else { | 929 | } else { |
| @@ -932,6 +937,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev | |||
| 932 | iounmap(msg_addr_virt); | 937 | iounmap(msg_addr_virt); |
| 933 | } | 938 | } |
| 934 | iounmap(base_addr_virt); | 939 | iounmap(base_addr_virt); |
| 940 | pci_release_regions(pDev); | ||
| 935 | return -ENOMEM; | 941 | return -ENOMEM; |
| 936 | } | 942 | } |
| 937 | memset(pHba, 0, sizeof(adpt_hba)); | 943 | memset(pHba, 0, sizeof(adpt_hba)); |
| @@ -1027,6 +1033,7 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba) | |||
| 1027 | up(&adpt_configuration_lock); | 1033 | up(&adpt_configuration_lock); |
| 1028 | 1034 | ||
| 1029 | iounmap(pHba->base_addr_virt); | 1035 | iounmap(pHba->base_addr_virt); |
| 1036 | pci_release_regions(pHba->pDev); | ||
| 1030 | if(pHba->msg_addr_virt != pHba->base_addr_virt){ | 1037 | if(pHba->msg_addr_virt != pHba->base_addr_virt){ |
| 1031 | iounmap(pHba->msg_addr_virt); | 1038 | iounmap(pHba->msg_addr_virt); |
| 1032 | } | 1039 | } |
diff --git a/drivers/scsi/ibmvscsi/srp.h b/drivers/scsi/ibmvscsi/srp.h index 2ae5154fd89c..7d8e4c4accb9 100644 --- a/drivers/scsi/ibmvscsi/srp.h +++ b/drivers/scsi/ibmvscsi/srp.h | |||
| @@ -35,7 +35,7 @@ | |||
| 35 | enum srp_types { | 35 | enum srp_types { |
| 36 | SRP_LOGIN_REQ_TYPE = 0x00, | 36 | SRP_LOGIN_REQ_TYPE = 0x00, |
| 37 | SRP_LOGIN_RSP_TYPE = 0xC0, | 37 | SRP_LOGIN_RSP_TYPE = 0xC0, |
| 38 | SRP_LOGIN_REJ_TYPE = 0x80, | 38 | SRP_LOGIN_REJ_TYPE = 0xC2, |
| 39 | SRP_I_LOGOUT_TYPE = 0x03, | 39 | SRP_I_LOGOUT_TYPE = 0x03, |
| 40 | SRP_T_LOGOUT_TYPE = 0x80, | 40 | SRP_T_LOGOUT_TYPE = 0x80, |
| 41 | SRP_TSK_MGMT_TYPE = 0x01, | 41 | SRP_TSK_MGMT_TYPE = 0x01, |
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index 6dfcb4fbccdd..4cdd891781b1 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c | |||
| @@ -133,10 +133,12 @@ | |||
| 133 | /* 6.10.00 - Remove 1G Addressing Limitations */ | 133 | /* 6.10.00 - Remove 1G Addressing Limitations */ |
| 134 | /* 6.11.xx - Get VersionInfo buffer off the stack ! DDTS 60401 */ | 134 | /* 6.11.xx - Get VersionInfo buffer off the stack ! DDTS 60401 */ |
| 135 | /* 6.11.xx - Make Logical Drive Info structure safe for DMA DDTS 60639 */ | 135 | /* 6.11.xx - Make Logical Drive Info structure safe for DMA DDTS 60639 */ |
| 136 | /* 7.10.xx - Add highmem_io flag in SCSI Templete for 2.4 kernels */ | 136 | /* 7.10.18 - Add highmem_io flag in SCSI Templete for 2.4 kernels */ |
| 137 | /* - Fix path/name for scsi_hosts.h include for 2.6 kernels */ | 137 | /* - Fix path/name for scsi_hosts.h include for 2.6 kernels */ |
| 138 | /* - Fix sort order of 7k */ | 138 | /* - Fix sort order of 7k */ |
| 139 | /* - Remove 3 unused "inline" functions */ | 139 | /* - Remove 3 unused "inline" functions */ |
| 140 | /* 7.12.xx - Use STATIC functions whereever possible */ | ||
| 141 | /* - Clean up deprecated MODULE_PARM calls */ | ||
| 140 | /*****************************************************************************/ | 142 | /*****************************************************************************/ |
| 141 | 143 | ||
| 142 | /* | 144 | /* |
| @@ -207,8 +209,8 @@ module_param(ips, charp, 0); | |||
| 207 | /* | 209 | /* |
| 208 | * DRIVER_VER | 210 | * DRIVER_VER |
| 209 | */ | 211 | */ |
| 210 | #define IPS_VERSION_HIGH "7.10" | 212 | #define IPS_VERSION_HIGH "7.12" |
| 211 | #define IPS_VERSION_LOW ".18 " | 213 | #define IPS_VERSION_LOW ".02 " |
| 212 | 214 | ||
| 213 | #if !defined(__i386__) && !defined(__ia64__) && !defined(__x86_64__) | 215 | #if !defined(__i386__) && !defined(__ia64__) && !defined(__x86_64__) |
| 214 | #warning "This driver has only been tested on the x86/ia64/x86_64 platforms" | 216 | #warning "This driver has only been tested on the x86/ia64/x86_64 platforms" |
diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h index 480e06f4d6ae..505e967013de 100644 --- a/drivers/scsi/ips.h +++ b/drivers/scsi/ips.h | |||
| @@ -87,15 +87,14 @@ | |||
| 87 | #define scsi_set_pci_device(sh,dev) (0) | 87 | #define scsi_set_pci_device(sh,dev) (0) |
| 88 | #endif | 88 | #endif |
| 89 | 89 | ||
| 90 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | 90 | #ifndef IRQ_NONE |
| 91 | 91 | typedef void irqreturn_t; | |
| 92 | #ifndef irqreturn_t | ||
| 93 | typedef void irqreturn_t; | ||
| 94 | #endif | ||
| 95 | |||
| 96 | #define IRQ_NONE | 92 | #define IRQ_NONE |
| 97 | #define IRQ_HANDLED | 93 | #define IRQ_HANDLED |
| 98 | #define IRQ_RETVAL(x) | 94 | #define IRQ_RETVAL(x) |
| 95 | #endif | ||
| 96 | |||
| 97 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | ||
| 99 | #define IPS_REGISTER_HOSTS(SHT) scsi_register_module(MODULE_SCSI_HA,SHT) | 98 | #define IPS_REGISTER_HOSTS(SHT) scsi_register_module(MODULE_SCSI_HA,SHT) |
| 100 | #define IPS_UNREGISTER_HOSTS(SHT) scsi_unregister_module(MODULE_SCSI_HA,SHT) | 99 | #define IPS_UNREGISTER_HOSTS(SHT) scsi_unregister_module(MODULE_SCSI_HA,SHT) |
| 101 | #define IPS_ADD_HOST(shost,device) | 100 | #define IPS_ADD_HOST(shost,device) |
| @@ -123,6 +122,10 @@ | |||
| 123 | #ifndef min | 122 | #ifndef min |
| 124 | #define min(x,y) ((x) < (y) ? x : y) | 123 | #define min(x,y) ((x) < (y) ? x : y) |
| 125 | #endif | 124 | #endif |
| 125 | |||
| 126 | #ifndef __iomem /* For clean compiles in earlier kernels without __iomem annotations */ | ||
| 127 | #define __iomem | ||
| 128 | #endif | ||
| 126 | 129 | ||
| 127 | #define pci_dma_hi32(a) ((a >> 16) >> 16) | 130 | #define pci_dma_hi32(a) ((a >> 16) >> 16) |
| 128 | #define pci_dma_lo32(a) (a & 0xffffffff) | 131 | #define pci_dma_lo32(a) (a & 0xffffffff) |
| @@ -1206,13 +1209,13 @@ typedef struct { | |||
| 1206 | 1209 | ||
| 1207 | #define IPS_VER_MAJOR 7 | 1210 | #define IPS_VER_MAJOR 7 |
| 1208 | #define IPS_VER_MAJOR_STRING "7" | 1211 | #define IPS_VER_MAJOR_STRING "7" |
| 1209 | #define IPS_VER_MINOR 10 | 1212 | #define IPS_VER_MINOR 12 |
| 1210 | #define IPS_VER_MINOR_STRING "10" | 1213 | #define IPS_VER_MINOR_STRING "12" |
| 1211 | #define IPS_VER_BUILD 18 | 1214 | #define IPS_VER_BUILD 02 |
| 1212 | #define IPS_VER_BUILD_STRING "18" | 1215 | #define IPS_VER_BUILD_STRING "02" |
| 1213 | #define IPS_VER_STRING "7.10.18" | 1216 | #define IPS_VER_STRING "7.12.02" |
| 1214 | #define IPS_RELEASE_ID 0x00020000 | 1217 | #define IPS_RELEASE_ID 0x00020000 |
| 1215 | #define IPS_BUILD_IDENT 731 | 1218 | #define IPS_BUILD_IDENT 761 |
| 1216 | #define IPS_LEGALCOPYRIGHT_STRING "(C) Copyright IBM Corp. 1994, 2002. All Rights Reserved." | 1219 | #define IPS_LEGALCOPYRIGHT_STRING "(C) Copyright IBM Corp. 1994, 2002. All Rights Reserved." |
| 1217 | #define IPS_ADAPTECCOPYRIGHT_STRING "(c) Copyright Adaptec, Inc. 2002 to 2004. All Rights Reserved." | 1220 | #define IPS_ADAPTECCOPYRIGHT_STRING "(c) Copyright Adaptec, Inc. 2002 to 2004. All Rights Reserved." |
| 1218 | #define IPS_DELLCOPYRIGHT_STRING "(c) Copyright Dell 2004. All Rights Reserved." | 1221 | #define IPS_DELLCOPYRIGHT_STRING "(c) Copyright Dell 2004. All Rights Reserved." |
| @@ -1223,12 +1226,12 @@ typedef struct { | |||
| 1223 | #define IPS_VER_SERVERAID2 "2.88.13" | 1226 | #define IPS_VER_SERVERAID2 "2.88.13" |
| 1224 | #define IPS_VER_NAVAJO "2.88.13" | 1227 | #define IPS_VER_NAVAJO "2.88.13" |
| 1225 | #define IPS_VER_SERVERAID3 "6.10.24" | 1228 | #define IPS_VER_SERVERAID3 "6.10.24" |
| 1226 | #define IPS_VER_SERVERAID4H "7.10.11" | 1229 | #define IPS_VER_SERVERAID4H "7.12.02" |
| 1227 | #define IPS_VER_SERVERAID4MLx "7.10.18" | 1230 | #define IPS_VER_SERVERAID4MLx "7.12.02" |
| 1228 | #define IPS_VER_SARASOTA "7.10.18" | 1231 | #define IPS_VER_SARASOTA "7.12.02" |
| 1229 | #define IPS_VER_MARCO "7.10.18" | 1232 | #define IPS_VER_MARCO "7.12.02" |
| 1230 | #define IPS_VER_SEBRING "7.10.18" | 1233 | #define IPS_VER_SEBRING "7.12.02" |
| 1231 | #define IPS_VER_KEYWEST "7.10.18" | 1234 | #define IPS_VER_KEYWEST "7.12.02" |
| 1232 | 1235 | ||
| 1233 | /* Compatability IDs for various adapters */ | 1236 | /* Compatability IDs for various adapters */ |
| 1234 | #define IPS_COMPAT_UNKNOWN "" | 1237 | #define IPS_COMPAT_UNKNOWN "" |
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 794fb559efb0..6a75ec2187fd 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c | |||
| @@ -385,6 +385,7 @@ int ata_scsi_error(struct Scsi_Host *host) | |||
| 385 | * appropriate place | 385 | * appropriate place |
| 386 | */ | 386 | */ |
| 387 | host->host_failed--; | 387 | host->host_failed--; |
| 388 | INIT_LIST_HEAD(&host->eh_cmd_q); | ||
| 388 | 389 | ||
| 389 | DPRINTK("EXIT\n"); | 390 | DPRINTK("EXIT\n"); |
| 390 | return 0; | 391 | return 0; |
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index 140cea05de3f..efd7d7a61135 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c | |||
| @@ -468,7 +468,7 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc) | |||
| 468 | for (i = 0; i < last; i++) { | 468 | for (i = 0; i < last; i++) { |
| 469 | buf[idx++] = cpu_to_le32(sg_dma_address(&sg[i])); | 469 | buf[idx++] = cpu_to_le32(sg_dma_address(&sg[i])); |
| 470 | buf[idx++] = cpu_to_le32(sg_dma_len(&sg[i])); | 470 | buf[idx++] = cpu_to_le32(sg_dma_len(&sg[i])); |
| 471 | total_len += sg[i].length; | 471 | total_len += sg_dma_len(&sg[i]); |
| 472 | } | 472 | } |
| 473 | buf[idx - 1] |= cpu_to_le32(ATA_PRD_EOT); | 473 | buf[idx - 1] |= cpu_to_le32(ATA_PRD_EOT); |
| 474 | sgt_len = idx * 4; | 474 | sgt_len = idx * 4; |
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 2d3c4ac475f2..48edd67982a5 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
| @@ -336,9 +336,23 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, | |||
| 336 | unsigned long flags; | 336 | unsigned long flags; |
| 337 | const int size = sizeof(struct scsi_target) | 337 | const int size = sizeof(struct scsi_target) |
| 338 | + shost->transportt->target_size; | 338 | + shost->transportt->target_size; |
| 339 | struct scsi_target *starget = kmalloc(size, GFP_ATOMIC); | 339 | struct scsi_target *starget; |
| 340 | struct scsi_target *found_target; | 340 | struct scsi_target *found_target; |
| 341 | 341 | ||
| 342 | /* | ||
| 343 | * Obtain the real parent from the transport. The transport | ||
| 344 | * is allowed to fail (no error) if there is nothing at that | ||
| 345 | * target id. | ||
| 346 | */ | ||
| 347 | if (shost->transportt->target_parent) { | ||
| 348 | spin_lock_irqsave(shost->host_lock, flags); | ||
| 349 | parent = shost->transportt->target_parent(shost, channel, id); | ||
| 350 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
| 351 | if (!parent) | ||
| 352 | return NULL; | ||
| 353 | } | ||
| 354 | |||
| 355 | starget = kmalloc(size, GFP_KERNEL); | ||
| 342 | if (!starget) { | 356 | if (!starget) { |
| 343 | printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__); | 357 | printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__); |
| 344 | return NULL; | 358 | return NULL; |
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 35d1c1e8e345..e6412fce423c 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c | |||
| @@ -1022,6 +1022,23 @@ static int fc_rport_match(struct attribute_container *cont, | |||
| 1022 | return &i->rport_attr_cont.ac == cont; | 1022 | return &i->rport_attr_cont.ac == cont; |
| 1023 | } | 1023 | } |
| 1024 | 1024 | ||
| 1025 | |||
| 1026 | /* | ||
| 1027 | * Must be called with shost->host_lock held | ||
| 1028 | */ | ||
| 1029 | static struct device *fc_target_parent(struct Scsi_Host *shost, | ||
| 1030 | int channel, uint id) | ||
| 1031 | { | ||
| 1032 | struct fc_rport *rport; | ||
| 1033 | |||
| 1034 | list_for_each_entry(rport, &fc_host_rports(shost), peers) | ||
| 1035 | if ((rport->channel == channel) && | ||
| 1036 | (rport->scsi_target_id == id)) | ||
| 1037 | return &rport->dev; | ||
| 1038 | |||
| 1039 | return NULL; | ||
| 1040 | } | ||
| 1041 | |||
| 1025 | struct scsi_transport_template * | 1042 | struct scsi_transport_template * |
| 1026 | fc_attach_transport(struct fc_function_template *ft) | 1043 | fc_attach_transport(struct fc_function_template *ft) |
| 1027 | { | 1044 | { |
| @@ -1057,6 +1074,8 @@ fc_attach_transport(struct fc_function_template *ft) | |||
| 1057 | 1074 | ||
| 1058 | /* Transport uses the shost workq for scsi scanning */ | 1075 | /* Transport uses the shost workq for scsi scanning */ |
| 1059 | i->t.create_work_queue = 1; | 1076 | i->t.create_work_queue = 1; |
| 1077 | |||
| 1078 | i->t.target_parent = fc_target_parent; | ||
| 1060 | 1079 | ||
| 1061 | /* | 1080 | /* |
| 1062 | * Setup SCSI Target Attributes. | 1081 | * Setup SCSI Target Attributes. |
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 0291a8fb654d..0a7839db5752 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c | |||
| @@ -4149,12 +4149,10 @@ static int __init init_st(void) | |||
| 4149 | do_create_driverfs_files(); | 4149 | do_create_driverfs_files(); |
| 4150 | return 0; | 4150 | return 0; |
| 4151 | } | 4151 | } |
| 4152 | if (st_sysfs_class) | ||
| 4153 | class_destroy(st_sysfs_class); | ||
| 4154 | unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0), | 4152 | unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0), |
| 4155 | |||
| 4156 | ST_MAX_TAPE_ENTRIES); | 4153 | ST_MAX_TAPE_ENTRIES); |
| 4157 | } | 4154 | } |
| 4155 | class_destroy(st_sysfs_class); | ||
| 4158 | 4156 | ||
| 4159 | printk(KERN_ERR "Unable to get major %d for SCSI tapes\n", SCSI_TAPE_MAJOR); | 4157 | printk(KERN_ERR "Unable to get major %d for SCSI tapes\n", SCSI_TAPE_MAJOR); |
| 4160 | return 1; | 4158 | return 1; |
| @@ -4162,13 +4160,11 @@ static int __init init_st(void) | |||
| 4162 | 4160 | ||
| 4163 | static void __exit exit_st(void) | 4161 | static void __exit exit_st(void) |
| 4164 | { | 4162 | { |
| 4165 | if (st_sysfs_class) | ||
| 4166 | class_destroy(st_sysfs_class); | ||
| 4167 | st_sysfs_class = NULL; | ||
| 4168 | do_remove_driverfs_files(); | 4163 | do_remove_driverfs_files(); |
| 4169 | scsi_unregister_driver(&st_template.gendrv); | 4164 | scsi_unregister_driver(&st_template.gendrv); |
| 4170 | unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0), | 4165 | unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0), |
| 4171 | ST_MAX_TAPE_ENTRIES); | 4166 | ST_MAX_TAPE_ENTRIES); |
| 4167 | class_destroy(st_sysfs_class); | ||
| 4172 | kfree(scsi_tapes); | 4168 | kfree(scsi_tapes); |
| 4173 | printk(KERN_INFO "st: Unloaded.\n"); | 4169 | printk(KERN_INFO "st: Unloaded.\n"); |
| 4174 | } | 4170 | } |
diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h index 5f6187baad86..73c8a088c160 100644 --- a/drivers/serial/cpm_uart/cpm_uart.h +++ b/drivers/serial/cpm_uart/cpm_uart.h | |||
| @@ -40,13 +40,15 @@ | |||
| 40 | #define TX_NUM_FIFO 4 | 40 | #define TX_NUM_FIFO 4 |
| 41 | #define TX_BUF_SIZE 32 | 41 | #define TX_BUF_SIZE 32 |
| 42 | 42 | ||
| 43 | #define SCC_WAIT_CLOSING 100 | ||
| 44 | |||
| 43 | struct uart_cpm_port { | 45 | struct uart_cpm_port { |
| 44 | struct uart_port port; | 46 | struct uart_port port; |
| 45 | u16 rx_nrfifos; | 47 | u16 rx_nrfifos; |
| 46 | u16 rx_fifosize; | 48 | u16 rx_fifosize; |
| 47 | u16 tx_nrfifos; | 49 | u16 tx_nrfifos; |
| 48 | u16 tx_fifosize; | 50 | u16 tx_fifosize; |
| 49 | smc_t *smcp; | 51 | smc_t *smcp; |
| 50 | smc_uart_t *smcup; | 52 | smc_uart_t *smcup; |
| 51 | scc_t *sccp; | 53 | scc_t *sccp; |
| 52 | scc_uart_t *sccup; | 54 | scc_uart_t *sccup; |
| @@ -67,6 +69,8 @@ struct uart_cpm_port { | |||
| 67 | int bits; | 69 | int bits; |
| 68 | /* Keep track of 'odd' SMC2 wirings */ | 70 | /* Keep track of 'odd' SMC2 wirings */ |
| 69 | int is_portb; | 71 | int is_portb; |
| 72 | /* wait on close if needed */ | ||
| 73 | int wait_closing; | ||
| 70 | }; | 74 | }; |
| 71 | 75 | ||
| 72 | extern int cpm_uart_port_map[UART_NR]; | 76 | extern int cpm_uart_port_map[UART_NR]; |
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 29db677d4284..d639ac92a117 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c | |||
| @@ -9,9 +9,10 @@ | |||
| 9 | * | 9 | * |
| 10 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2) | 10 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2) |
| 11 | * Pantelis Antoniou (panto@intracom.gr) (CPM1) | 11 | * Pantelis Antoniou (panto@intracom.gr) (CPM1) |
| 12 | * | 12 | * |
| 13 | * Copyright (C) 2004 Freescale Semiconductor, Inc. | 13 | * Copyright (C) 2004 Freescale Semiconductor, Inc. |
| 14 | * (C) 2004 Intracom, S.A. | 14 | * (C) 2004 Intracom, S.A. |
| 15 | * (C) 2005 MontaVista Software, Inc. by Vitaly Bordug <vbordug@ru.mvista.com> | ||
| 15 | * | 16 | * |
| 16 | * This program is free software; you can redistribute it and/or modify | 17 | * This program is free software; you can redistribute it and/or modify |
| 17 | * it under the terms of the GNU General Public License as published by | 18 | * it under the terms of the GNU General Public License as published by |
| @@ -70,8 +71,22 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo); | |||
| 70 | 71 | ||
| 71 | /**************************************************************/ | 72 | /**************************************************************/ |
| 72 | 73 | ||
| 74 | static inline unsigned long cpu2cpm_addr(void *addr) | ||
| 75 | { | ||
| 76 | if ((unsigned long)addr >= CPM_ADDR) | ||
| 77 | return (unsigned long)addr; | ||
| 78 | return virt_to_bus(addr); | ||
| 79 | } | ||
| 80 | |||
| 81 | static inline void *cpm2cpu_addr(unsigned long addr) | ||
| 82 | { | ||
| 83 | if (addr >= CPM_ADDR) | ||
| 84 | return (void *)addr; | ||
| 85 | return bus_to_virt(addr); | ||
| 86 | } | ||
| 87 | |||
| 73 | /* | 88 | /* |
| 74 | * Check, if transmit buffers are processed | 89 | * Check, if transmit buffers are processed |
| 75 | */ | 90 | */ |
| 76 | static unsigned int cpm_uart_tx_empty(struct uart_port *port) | 91 | static unsigned int cpm_uart_tx_empty(struct uart_port *port) |
| 77 | { | 92 | { |
| @@ -143,15 +158,18 @@ static void cpm_uart_start_tx(struct uart_port *port, unsigned int tty_start) | |||
| 143 | } | 158 | } |
| 144 | 159 | ||
| 145 | if (cpm_uart_tx_pump(port) != 0) { | 160 | if (cpm_uart_tx_pump(port) != 0) { |
| 146 | if (IS_SMC(pinfo)) | 161 | if (IS_SMC(pinfo)) { |
| 147 | smcp->smc_smcm |= SMCM_TX; | 162 | smcp->smc_smcm |= SMCM_TX; |
| 148 | else | 163 | smcp->smc_smcmr |= SMCMR_TEN; |
| 164 | } else { | ||
| 149 | sccp->scc_sccm |= UART_SCCM_TX; | 165 | sccp->scc_sccm |= UART_SCCM_TX; |
| 166 | pinfo->sccp->scc_gsmrl |= SCC_GSMRL_ENT; | ||
| 167 | } | ||
| 150 | } | 168 | } |
| 151 | } | 169 | } |
| 152 | 170 | ||
| 153 | /* | 171 | /* |
| 154 | * Stop receiver | 172 | * Stop receiver |
| 155 | */ | 173 | */ |
| 156 | static void cpm_uart_stop_rx(struct uart_port *port) | 174 | static void cpm_uart_stop_rx(struct uart_port *port) |
| 157 | { | 175 | { |
| @@ -176,7 +194,7 @@ static void cpm_uart_enable_ms(struct uart_port *port) | |||
| 176 | } | 194 | } |
| 177 | 195 | ||
| 178 | /* | 196 | /* |
| 179 | * Generate a break. | 197 | * Generate a break. |
| 180 | */ | 198 | */ |
| 181 | static void cpm_uart_break_ctl(struct uart_port *port, int break_state) | 199 | static void cpm_uart_break_ctl(struct uart_port *port, int break_state) |
| 182 | { | 200 | { |
| @@ -231,7 +249,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs) | |||
| 231 | /* get number of characters, and check spce in flip-buffer */ | 249 | /* get number of characters, and check spce in flip-buffer */ |
| 232 | i = bdp->cbd_datlen; | 250 | i = bdp->cbd_datlen; |
| 233 | 251 | ||
| 234 | /* If we have not enough room in tty flip buffer, then we try | 252 | /* If we have not enough room in tty flip buffer, then we try |
| 235 | * later, which will be the next rx-interrupt or a timeout | 253 | * later, which will be the next rx-interrupt or a timeout |
| 236 | */ | 254 | */ |
| 237 | if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE) { | 255 | if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE) { |
| @@ -243,7 +261,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs) | |||
| 243 | } | 261 | } |
| 244 | 262 | ||
| 245 | /* get pointer */ | 263 | /* get pointer */ |
| 246 | cp = (unsigned char *)bus_to_virt(bdp->cbd_bufaddr); | 264 | cp = cpm2cpu_addr(bdp->cbd_bufaddr); |
| 247 | 265 | ||
| 248 | /* loop through the buffer */ | 266 | /* loop through the buffer */ |
| 249 | while (i-- > 0) { | 267 | while (i-- > 0) { |
| @@ -265,13 +283,14 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs) | |||
| 265 | } /* End while (i--) */ | 283 | } /* End while (i--) */ |
| 266 | 284 | ||
| 267 | /* This BD is ready to be used again. Clear status. get next */ | 285 | /* This BD is ready to be used again. Clear status. get next */ |
| 268 | bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV); | 286 | bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV | BD_SC_ID); |
| 269 | bdp->cbd_sc |= BD_SC_EMPTY; | 287 | bdp->cbd_sc |= BD_SC_EMPTY; |
| 270 | 288 | ||
| 271 | if (bdp->cbd_sc & BD_SC_WRAP) | 289 | if (bdp->cbd_sc & BD_SC_WRAP) |
| 272 | bdp = pinfo->rx_bd_base; | 290 | bdp = pinfo->rx_bd_base; |
| 273 | else | 291 | else |
| 274 | bdp++; | 292 | bdp++; |
| 293 | |||
| 275 | } /* End for (;;) */ | 294 | } /* End for (;;) */ |
| 276 | 295 | ||
| 277 | /* Write back buffer pointer */ | 296 | /* Write back buffer pointer */ |
| @@ -336,22 +355,22 @@ static irqreturn_t cpm_uart_int(int irq, void *data, struct pt_regs *regs) | |||
| 336 | 355 | ||
| 337 | if (IS_SMC(pinfo)) { | 356 | if (IS_SMC(pinfo)) { |
| 338 | events = smcp->smc_smce; | 357 | events = smcp->smc_smce; |
| 358 | smcp->smc_smce = events; | ||
| 339 | if (events & SMCM_BRKE) | 359 | if (events & SMCM_BRKE) |
| 340 | uart_handle_break(port); | 360 | uart_handle_break(port); |
| 341 | if (events & SMCM_RX) | 361 | if (events & SMCM_RX) |
| 342 | cpm_uart_int_rx(port, regs); | 362 | cpm_uart_int_rx(port, regs); |
| 343 | if (events & SMCM_TX) | 363 | if (events & SMCM_TX) |
| 344 | cpm_uart_int_tx(port, regs); | 364 | cpm_uart_int_tx(port, regs); |
| 345 | smcp->smc_smce = events; | ||
| 346 | } else { | 365 | } else { |
| 347 | events = sccp->scc_scce; | 366 | events = sccp->scc_scce; |
| 367 | sccp->scc_scce = events; | ||
| 348 | if (events & UART_SCCM_BRKE) | 368 | if (events & UART_SCCM_BRKE) |
| 349 | uart_handle_break(port); | 369 | uart_handle_break(port); |
| 350 | if (events & UART_SCCM_RX) | 370 | if (events & UART_SCCM_RX) |
| 351 | cpm_uart_int_rx(port, regs); | 371 | cpm_uart_int_rx(port, regs); |
| 352 | if (events & UART_SCCM_TX) | 372 | if (events & UART_SCCM_TX) |
| 353 | cpm_uart_int_tx(port, regs); | 373 | cpm_uart_int_tx(port, regs); |
| 354 | sccp->scc_scce = events; | ||
| 355 | } | 374 | } |
| 356 | return (events) ? IRQ_HANDLED : IRQ_NONE; | 375 | return (events) ? IRQ_HANDLED : IRQ_NONE; |
| 357 | } | 376 | } |
| @@ -360,6 +379,7 @@ static int cpm_uart_startup(struct uart_port *port) | |||
| 360 | { | 379 | { |
| 361 | int retval; | 380 | int retval; |
| 362 | struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; | 381 | struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; |
| 382 | int line = pinfo - cpm_uart_ports; | ||
| 363 | 383 | ||
| 364 | pr_debug("CPM uart[%d]:startup\n", port->line); | 384 | pr_debug("CPM uart[%d]:startup\n", port->line); |
| 365 | 385 | ||
| @@ -376,9 +396,19 @@ static int cpm_uart_startup(struct uart_port *port) | |||
| 376 | pinfo->sccp->scc_sccm |= UART_SCCM_RX; | 396 | pinfo->sccp->scc_sccm |= UART_SCCM_RX; |
| 377 | } | 397 | } |
| 378 | 398 | ||
| 399 | if (!(pinfo->flags & FLAG_CONSOLE)) | ||
| 400 | cpm_line_cr_cmd(line,CPM_CR_INIT_TRX); | ||
| 379 | return 0; | 401 | return 0; |
| 380 | } | 402 | } |
| 381 | 403 | ||
| 404 | inline void cpm_uart_wait_until_send(struct uart_cpm_port *pinfo) | ||
| 405 | { | ||
| 406 | unsigned long target_jiffies = jiffies + pinfo->wait_closing; | ||
| 407 | |||
| 408 | while (!time_after(jiffies, target_jiffies)) | ||
| 409 | schedule(); | ||
| 410 | } | ||
| 411 | |||
| 382 | /* | 412 | /* |
| 383 | * Shutdown the uart | 413 | * Shutdown the uart |
| 384 | */ | 414 | */ |
| @@ -394,6 +424,12 @@ static void cpm_uart_shutdown(struct uart_port *port) | |||
| 394 | 424 | ||
| 395 | /* If the port is not the console, disable Rx and Tx. */ | 425 | /* If the port is not the console, disable Rx and Tx. */ |
| 396 | if (!(pinfo->flags & FLAG_CONSOLE)) { | 426 | if (!(pinfo->flags & FLAG_CONSOLE)) { |
| 427 | /* Wait for all the BDs marked sent */ | ||
| 428 | while(!cpm_uart_tx_empty(port)) | ||
| 429 | schedule_timeout(2); | ||
| 430 | if(pinfo->wait_closing) | ||
| 431 | cpm_uart_wait_until_send(pinfo); | ||
| 432 | |||
| 397 | /* Stop uarts */ | 433 | /* Stop uarts */ |
| 398 | if (IS_SMC(pinfo)) { | 434 | if (IS_SMC(pinfo)) { |
| 399 | volatile smc_t *smcp = pinfo->smcp; | 435 | volatile smc_t *smcp = pinfo->smcp; |
| @@ -502,7 +538,7 @@ static void cpm_uart_set_termios(struct uart_port *port, | |||
| 502 | */ | 538 | */ |
| 503 | if ((termios->c_cflag & CREAD) == 0) | 539 | if ((termios->c_cflag & CREAD) == 0) |
| 504 | port->read_status_mask &= ~BD_SC_EMPTY; | 540 | port->read_status_mask &= ~BD_SC_EMPTY; |
| 505 | 541 | ||
| 506 | spin_lock_irqsave(&port->lock, flags); | 542 | spin_lock_irqsave(&port->lock, flags); |
| 507 | 543 | ||
| 508 | /* Start bit has not been added (so don't, because we would just | 544 | /* Start bit has not been added (so don't, because we would just |
| @@ -569,7 +605,8 @@ static int cpm_uart_tx_pump(struct uart_port *port) | |||
| 569 | /* Pick next descriptor and fill from buffer */ | 605 | /* Pick next descriptor and fill from buffer */ |
| 570 | bdp = pinfo->tx_cur; | 606 | bdp = pinfo->tx_cur; |
| 571 | 607 | ||
| 572 | p = bus_to_virt(bdp->cbd_bufaddr); | 608 | p = cpm2cpu_addr(bdp->cbd_bufaddr); |
| 609 | |||
| 573 | *p++ = xmit->buf[xmit->tail]; | 610 | *p++ = xmit->buf[xmit->tail]; |
| 574 | bdp->cbd_datlen = 1; | 611 | bdp->cbd_datlen = 1; |
| 575 | bdp->cbd_sc |= BD_SC_READY; | 612 | bdp->cbd_sc |= BD_SC_READY; |
| @@ -595,7 +632,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) | |||
| 595 | 632 | ||
| 596 | while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) { | 633 | while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) { |
| 597 | count = 0; | 634 | count = 0; |
| 598 | p = bus_to_virt(bdp->cbd_bufaddr); | 635 | p = cpm2cpu_addr(bdp->cbd_bufaddr); |
| 599 | while (count < pinfo->tx_fifosize) { | 636 | while (count < pinfo->tx_fifosize) { |
| 600 | *p++ = xmit->buf[xmit->tail]; | 637 | *p++ = xmit->buf[xmit->tail]; |
| 601 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | 638 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); |
| @@ -606,6 +643,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) | |||
| 606 | } | 643 | } |
| 607 | bdp->cbd_datlen = count; | 644 | bdp->cbd_datlen = count; |
| 608 | bdp->cbd_sc |= BD_SC_READY; | 645 | bdp->cbd_sc |= BD_SC_READY; |
| 646 | __asm__("eieio"); | ||
| 609 | /* Get next BD. */ | 647 | /* Get next BD. */ |
| 610 | if (bdp->cbd_sc & BD_SC_WRAP) | 648 | if (bdp->cbd_sc & BD_SC_WRAP) |
| 611 | bdp = pinfo->tx_bd_base; | 649 | bdp = pinfo->tx_bd_base; |
| @@ -643,12 +681,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo) | |||
| 643 | mem_addr = pinfo->mem_addr; | 681 | mem_addr = pinfo->mem_addr; |
| 644 | bdp = pinfo->rx_cur = pinfo->rx_bd_base; | 682 | bdp = pinfo->rx_cur = pinfo->rx_bd_base; |
| 645 | for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) { | 683 | for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) { |
| 646 | bdp->cbd_bufaddr = virt_to_bus(mem_addr); | 684 | bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); |
| 647 | bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT; | 685 | bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT; |
| 648 | mem_addr += pinfo->rx_fifosize; | 686 | mem_addr += pinfo->rx_fifosize; |
| 649 | } | 687 | } |
| 650 | 688 | ||
| 651 | bdp->cbd_bufaddr = virt_to_bus(mem_addr); | 689 | bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); |
| 652 | bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT; | 690 | bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT; |
| 653 | 691 | ||
| 654 | /* Set the physical address of the host memory | 692 | /* Set the physical address of the host memory |
| @@ -658,12 +696,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo) | |||
| 658 | mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize); | 696 | mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize); |
| 659 | bdp = pinfo->tx_cur = pinfo->tx_bd_base; | 697 | bdp = pinfo->tx_cur = pinfo->tx_bd_base; |
| 660 | for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) { | 698 | for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) { |
| 661 | bdp->cbd_bufaddr = virt_to_bus(mem_addr); | 699 | bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); |
| 662 | bdp->cbd_sc = BD_SC_INTRPT; | 700 | bdp->cbd_sc = BD_SC_INTRPT; |
| 663 | mem_addr += pinfo->tx_fifosize; | 701 | mem_addr += pinfo->tx_fifosize; |
| 664 | } | 702 | } |
| 665 | 703 | ||
| 666 | bdp->cbd_bufaddr = virt_to_bus(mem_addr); | 704 | bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); |
| 667 | bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT; | 705 | bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT; |
| 668 | } | 706 | } |
| 669 | 707 | ||
| @@ -763,6 +801,8 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo) | |||
| 763 | /* Using idle charater time requires some additional tuning. */ | 801 | /* Using idle charater time requires some additional tuning. */ |
| 764 | up->smc_mrblr = pinfo->rx_fifosize; | 802 | up->smc_mrblr = pinfo->rx_fifosize; |
| 765 | up->smc_maxidl = pinfo->rx_fifosize; | 803 | up->smc_maxidl = pinfo->rx_fifosize; |
| 804 | up->smc_brklen = 0; | ||
| 805 | up->smc_brkec = 0; | ||
| 766 | up->smc_brkcr = 1; | 806 | up->smc_brkcr = 1; |
| 767 | 807 | ||
| 768 | cpm_line_cr_cmd(line, CPM_CR_INIT_TRX); | 808 | cpm_line_cr_cmd(line, CPM_CR_INIT_TRX); |
| @@ -796,7 +836,7 @@ static int cpm_uart_request_port(struct uart_port *port) | |||
| 796 | /* | 836 | /* |
| 797 | * Setup any port IO, connect any baud rate generators, | 837 | * Setup any port IO, connect any baud rate generators, |
| 798 | * etc. This is expected to be handled by board | 838 | * etc. This is expected to be handled by board |
| 799 | * dependant code | 839 | * dependant code |
| 800 | */ | 840 | */ |
| 801 | if (pinfo->set_lineif) | 841 | if (pinfo->set_lineif) |
| 802 | pinfo->set_lineif(pinfo); | 842 | pinfo->set_lineif(pinfo); |
| @@ -815,6 +855,10 @@ static int cpm_uart_request_port(struct uart_port *port) | |||
| 815 | return ret; | 855 | return ret; |
| 816 | 856 | ||
| 817 | cpm_uart_initbd(pinfo); | 857 | cpm_uart_initbd(pinfo); |
| 858 | if (IS_SMC(pinfo)) | ||
| 859 | cpm_uart_init_smc(pinfo); | ||
| 860 | else | ||
| 861 | cpm_uart_init_scc(pinfo); | ||
| 818 | 862 | ||
| 819 | return 0; | 863 | return 0; |
| 820 | } | 864 | } |
| @@ -869,7 +913,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { | |||
| 869 | .flags = FLAG_SMC, | 913 | .flags = FLAG_SMC, |
| 870 | .tx_nrfifos = TX_NUM_FIFO, | 914 | .tx_nrfifos = TX_NUM_FIFO, |
| 871 | .tx_fifosize = TX_BUF_SIZE, | 915 | .tx_fifosize = TX_BUF_SIZE, |
| 872 | .rx_nrfifos = RX_NUM_FIFO, | 916 | .rx_nrfifos = RX_NUM_FIFO, |
| 873 | .rx_fifosize = RX_BUF_SIZE, | 917 | .rx_fifosize = RX_BUF_SIZE, |
| 874 | .set_lineif = smc1_lineif, | 918 | .set_lineif = smc1_lineif, |
| 875 | }, | 919 | }, |
| @@ -883,7 +927,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { | |||
| 883 | .flags = FLAG_SMC, | 927 | .flags = FLAG_SMC, |
| 884 | .tx_nrfifos = TX_NUM_FIFO, | 928 | .tx_nrfifos = TX_NUM_FIFO, |
| 885 | .tx_fifosize = TX_BUF_SIZE, | 929 | .tx_fifosize = TX_BUF_SIZE, |
| 886 | .rx_nrfifos = RX_NUM_FIFO, | 930 | .rx_nrfifos = RX_NUM_FIFO, |
| 887 | .rx_fifosize = RX_BUF_SIZE, | 931 | .rx_fifosize = RX_BUF_SIZE, |
| 888 | .set_lineif = smc2_lineif, | 932 | .set_lineif = smc2_lineif, |
| 889 | #ifdef CONFIG_SERIAL_CPM_ALT_SMC2 | 933 | #ifdef CONFIG_SERIAL_CPM_ALT_SMC2 |
| @@ -899,9 +943,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { | |||
| 899 | }, | 943 | }, |
| 900 | .tx_nrfifos = TX_NUM_FIFO, | 944 | .tx_nrfifos = TX_NUM_FIFO, |
| 901 | .tx_fifosize = TX_BUF_SIZE, | 945 | .tx_fifosize = TX_BUF_SIZE, |
| 902 | .rx_nrfifos = RX_NUM_FIFO, | 946 | .rx_nrfifos = RX_NUM_FIFO, |
| 903 | .rx_fifosize = RX_BUF_SIZE, | 947 | .rx_fifosize = RX_BUF_SIZE, |
| 904 | .set_lineif = scc1_lineif, | 948 | .set_lineif = scc1_lineif, |
| 949 | .wait_closing = SCC_WAIT_CLOSING, | ||
| 905 | }, | 950 | }, |
| 906 | [UART_SCC2] = { | 951 | [UART_SCC2] = { |
| 907 | .port = { | 952 | .port = { |
| @@ -912,9 +957,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { | |||
| 912 | }, | 957 | }, |
| 913 | .tx_nrfifos = TX_NUM_FIFO, | 958 | .tx_nrfifos = TX_NUM_FIFO, |
| 914 | .tx_fifosize = TX_BUF_SIZE, | 959 | .tx_fifosize = TX_BUF_SIZE, |
| 915 | .rx_nrfifos = RX_NUM_FIFO, | 960 | .rx_nrfifos = RX_NUM_FIFO, |
| 916 | .rx_fifosize = RX_BUF_SIZE, | 961 | .rx_fifosize = RX_BUF_SIZE, |
| 917 | .set_lineif = scc2_lineif, | 962 | .set_lineif = scc2_lineif, |
| 963 | .wait_closing = SCC_WAIT_CLOSING, | ||
| 918 | }, | 964 | }, |
| 919 | [UART_SCC3] = { | 965 | [UART_SCC3] = { |
| 920 | .port = { | 966 | .port = { |
| @@ -925,9 +971,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { | |||
| 925 | }, | 971 | }, |
| 926 | .tx_nrfifos = TX_NUM_FIFO, | 972 | .tx_nrfifos = TX_NUM_FIFO, |
| 927 | .tx_fifosize = TX_BUF_SIZE, | 973 | .tx_fifosize = TX_BUF_SIZE, |
| 928 | .rx_nrfifos = RX_NUM_FIFO, | 974 | .rx_nrfifos = RX_NUM_FIFO, |
| 929 | .rx_fifosize = RX_BUF_SIZE, | 975 | .rx_fifosize = RX_BUF_SIZE, |
| 930 | .set_lineif = scc3_lineif, | 976 | .set_lineif = scc3_lineif, |
| 977 | .wait_closing = SCC_WAIT_CLOSING, | ||
| 931 | }, | 978 | }, |
| 932 | [UART_SCC4] = { | 979 | [UART_SCC4] = { |
| 933 | .port = { | 980 | .port = { |
| @@ -938,9 +985,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { | |||
| 938 | }, | 985 | }, |
| 939 | .tx_nrfifos = TX_NUM_FIFO, | 986 | .tx_nrfifos = TX_NUM_FIFO, |
| 940 | .tx_fifosize = TX_BUF_SIZE, | 987 | .tx_fifosize = TX_BUF_SIZE, |
| 941 | .rx_nrfifos = RX_NUM_FIFO, | 988 | .rx_nrfifos = RX_NUM_FIFO, |
| 942 | .rx_fifosize = RX_BUF_SIZE, | 989 | .rx_fifosize = RX_BUF_SIZE, |
| 943 | .set_lineif = scc4_lineif, | 990 | .set_lineif = scc4_lineif, |
| 991 | .wait_closing = SCC_WAIT_CLOSING, | ||
| 944 | }, | 992 | }, |
| 945 | }; | 993 | }; |
| 946 | 994 | ||
| @@ -983,11 +1031,8 @@ static void cpm_uart_console_write(struct console *co, const char *s, | |||
| 983 | * If the buffer address is in the CPM DPRAM, don't | 1031 | * If the buffer address is in the CPM DPRAM, don't |
| 984 | * convert it. | 1032 | * convert it. |
| 985 | */ | 1033 | */ |
| 986 | if ((uint) (bdp->cbd_bufaddr) > (uint) CPM_ADDR) | 1034 | cp = cpm2cpu_addr(bdp->cbd_bufaddr); |
| 987 | cp = (unsigned char *) (bdp->cbd_bufaddr); | 1035 | |
| 988 | else | ||
| 989 | cp = bus_to_virt(bdp->cbd_bufaddr); | ||
| 990 | |||
| 991 | *cp = *s; | 1036 | *cp = *s; |
| 992 | 1037 | ||
| 993 | bdp->cbd_datlen = 1; | 1038 | bdp->cbd_datlen = 1; |
| @@ -1003,10 +1048,7 @@ static void cpm_uart_console_write(struct console *co, const char *s, | |||
| 1003 | while ((bdp->cbd_sc & BD_SC_READY) != 0) | 1048 | while ((bdp->cbd_sc & BD_SC_READY) != 0) |
| 1004 | ; | 1049 | ; |
| 1005 | 1050 | ||
| 1006 | if ((uint) (bdp->cbd_bufaddr) > (uint) CPM_ADDR) | 1051 | cp = cpm2cpu_addr(bdp->cbd_bufaddr); |
| 1007 | cp = (unsigned char *) (bdp->cbd_bufaddr); | ||
| 1008 | else | ||
| 1009 | cp = bus_to_virt(bdp->cbd_bufaddr); | ||
| 1010 | 1052 | ||
| 1011 | *cp = 13; | 1053 | *cp = 13; |
| 1012 | bdp->cbd_datlen = 1; | 1054 | bdp->cbd_datlen = 1; |
| @@ -1045,7 +1087,7 @@ static int __init cpm_uart_console_setup(struct console *co, char *options) | |||
| 1045 | port = | 1087 | port = |
| 1046 | (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]]; | 1088 | (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]]; |
| 1047 | pinfo = (struct uart_cpm_port *)port; | 1089 | pinfo = (struct uart_cpm_port *)port; |
| 1048 | 1090 | ||
| 1049 | pinfo->flags |= FLAG_CONSOLE; | 1091 | pinfo->flags |= FLAG_CONSOLE; |
| 1050 | 1092 | ||
| 1051 | if (options) { | 1093 | if (options) { |
| @@ -1062,7 +1104,7 @@ static int __init cpm_uart_console_setup(struct console *co, char *options) | |||
| 1062 | /* | 1104 | /* |
| 1063 | * Setup any port IO, connect any baud rate generators, | 1105 | * Setup any port IO, connect any baud rate generators, |
| 1064 | * etc. This is expected to be handled by board | 1106 | * etc. This is expected to be handled by board |
| 1065 | * dependant code | 1107 | * dependant code |
| 1066 | */ | 1108 | */ |
| 1067 | if (pinfo->set_lineif) | 1109 | if (pinfo->set_lineif) |
| 1068 | pinfo->set_lineif(pinfo); | 1110 | pinfo->set_lineif(pinfo); |
| @@ -1092,14 +1134,14 @@ static int __init cpm_uart_console_setup(struct console *co, char *options) | |||
| 1092 | return 0; | 1134 | return 0; |
| 1093 | } | 1135 | } |
| 1094 | 1136 | ||
| 1095 | extern struct uart_driver cpm_reg; | 1137 | static struct uart_driver cpm_reg; |
| 1096 | static struct console cpm_scc_uart_console = { | 1138 | static struct console cpm_scc_uart_console = { |
| 1097 | .name "ttyCPM", | 1139 | .name = "ttyCPM", |
| 1098 | .write cpm_uart_console_write, | 1140 | .write = cpm_uart_console_write, |
| 1099 | .device uart_console_device, | 1141 | .device = uart_console_device, |
| 1100 | .setup cpm_uart_console_setup, | 1142 | .setup = cpm_uart_console_setup, |
| 1101 | .flags CON_PRINTBUFFER, | 1143 | .flags = CON_PRINTBUFFER, |
| 1102 | .index -1, | 1144 | .index = -1, |
| 1103 | .data = &cpm_reg, | 1145 | .data = &cpm_reg, |
| 1104 | }; | 1146 | }; |
| 1105 | 1147 | ||
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c index 8efbd6d1d6a4..4b0786e7eb7f 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2) | 6 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2) |
| 7 | * Pantelis Antoniou (panto@intracom.gr) (CPM1) | 7 | * Pantelis Antoniou (panto@intracom.gr) (CPM1) |
| 8 | * | 8 | * |
| 9 | * Copyright (C) 2004 Freescale Semiconductor, Inc. | 9 | * Copyright (C) 2004 Freescale Semiconductor, Inc. |
| 10 | * (C) 2004 Intracom, S.A. | 10 | * (C) 2004 Intracom, S.A. |
| 11 | * | 11 | * |
| @@ -82,6 +82,17 @@ void cpm_line_cr_cmd(int line, int cmd) | |||
| 82 | void smc1_lineif(struct uart_cpm_port *pinfo) | 82 | void smc1_lineif(struct uart_cpm_port *pinfo) |
| 83 | { | 83 | { |
| 84 | volatile cpm8xx_t *cp = cpmp; | 84 | volatile cpm8xx_t *cp = cpmp; |
| 85 | |||
| 86 | (void)cp; /* fix warning */ | ||
| 87 | #if defined (CONFIG_MPC885ADS) | ||
| 88 | /* Enable SMC1 transceivers */ | ||
| 89 | { | ||
| 90 | cp->cp_pepar |= 0x000000c0; | ||
| 91 | cp->cp_pedir &= ~0x000000c0; | ||
| 92 | cp->cp_peso &= ~0x00000040; | ||
| 93 | cp->cp_peso |= 0x00000080; | ||
| 94 | } | ||
| 95 | #elif defined (CONFIG_MPC86XADS) | ||
| 85 | unsigned int iobits = 0x000000c0; | 96 | unsigned int iobits = 0x000000c0; |
| 86 | 97 | ||
| 87 | if (!pinfo->is_portb) { | 98 | if (!pinfo->is_portb) { |
| @@ -93,41 +104,33 @@ void smc1_lineif(struct uart_cpm_port *pinfo) | |||
| 93 | ((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits; | 104 | ((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits; |
| 94 | ((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits; | 105 | ((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits; |
| 95 | } | 106 | } |
| 96 | |||
| 97 | #ifdef CONFIG_MPC885ADS | ||
| 98 | /* Enable SMC1 transceivers */ | ||
| 99 | { | ||
| 100 | volatile uint __iomem *bcsr1 = ioremap(BCSR1, 4); | ||
| 101 | uint tmp; | ||
| 102 | |||
| 103 | tmp = in_be32(bcsr1); | ||
| 104 | tmp &= ~BCSR1_RS232EN_1; | ||
| 105 | out_be32(bcsr1, tmp); | ||
| 106 | iounmap(bcsr1); | ||
| 107 | } | ||
| 108 | #endif | 107 | #endif |
| 109 | |||
| 110 | pinfo->brg = 1; | 108 | pinfo->brg = 1; |
| 111 | } | 109 | } |
| 112 | 110 | ||
| 113 | void smc2_lineif(struct uart_cpm_port *pinfo) | 111 | void smc2_lineif(struct uart_cpm_port *pinfo) |
| 114 | { | 112 | { |
| 115 | #ifdef CONFIG_MPC885ADS | ||
| 116 | volatile cpm8xx_t *cp = cpmp; | 113 | volatile cpm8xx_t *cp = cpmp; |
| 117 | volatile uint __iomem *bcsr1; | ||
| 118 | uint tmp; | ||
| 119 | 114 | ||
| 115 | (void)cp; /* fix warning */ | ||
| 116 | #if defined (CONFIG_MPC885ADS) | ||
| 120 | cp->cp_pepar |= 0x00000c00; | 117 | cp->cp_pepar |= 0x00000c00; |
| 121 | cp->cp_pedir &= ~0x00000c00; | 118 | cp->cp_pedir &= ~0x00000c00; |
| 122 | cp->cp_peso &= ~0x00000400; | 119 | cp->cp_peso &= ~0x00000400; |
| 123 | cp->cp_peso |= 0x00000800; | 120 | cp->cp_peso |= 0x00000800; |
| 121 | #elif defined (CONFIG_MPC86XADS) | ||
| 122 | unsigned int iobits = 0x00000c00; | ||
| 123 | |||
| 124 | if (!pinfo->is_portb) { | ||
| 125 | cp->cp_pbpar |= iobits; | ||
| 126 | cp->cp_pbdir &= ~iobits; | ||
| 127 | cp->cp_pbodr &= ~iobits; | ||
| 128 | } else { | ||
| 129 | ((immap_t *)IMAP_ADDR)->im_ioport.iop_papar |= iobits; | ||
| 130 | ((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits; | ||
| 131 | ((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits; | ||
| 132 | } | ||
| 124 | 133 | ||
| 125 | /* Enable SMC2 transceivers */ | ||
| 126 | bcsr1 = ioremap(BCSR1, 4); | ||
| 127 | tmp = in_be32(bcsr1); | ||
| 128 | tmp &= ~BCSR1_RS232EN_2; | ||
| 129 | out_be32(bcsr1, tmp); | ||
| 130 | iounmap(bcsr1); | ||
| 131 | #endif | 134 | #endif |
| 132 | 135 | ||
| 133 | pinfo->brg = 2; | 136 | pinfo->brg = 2; |
| @@ -158,7 +161,7 @@ void scc4_lineif(struct uart_cpm_port *pinfo) | |||
| 158 | } | 161 | } |
| 159 | 162 | ||
| 160 | /* | 163 | /* |
| 161 | * Allocate DP-Ram and memory buffers. We need to allocate a transmit and | 164 | * Allocate DP-Ram and memory buffers. We need to allocate a transmit and |
| 162 | * receive buffer descriptors from dual port ram, and a character | 165 | * receive buffer descriptors from dual port ram, and a character |
| 163 | * buffer area from host mem. If we are allocating for the console we need | 166 | * buffer area from host mem. If we are allocating for the console we need |
| 164 | * to do it from bootmem | 167 | * to do it from bootmem |
| @@ -185,6 +188,8 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) | |||
| 185 | memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) + | 188 | memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) + |
| 186 | L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize); | 189 | L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize); |
| 187 | if (is_con) { | 190 | if (is_con) { |
| 191 | /* was hostalloc but changed cause it blows away the */ | ||
| 192 | /* large tlb mapping when pinning the kernel area */ | ||
| 188 | mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8)); | 193 | mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8)); |
| 189 | dma_addr = 0; | 194 | dma_addr = 0; |
| 190 | } else | 195 | } else |
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 50cb01831075..b01efb6b36f6 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c | |||
| @@ -527,7 +527,7 @@ show_periodic (struct class_device *class_dev, char *buf) | |||
| 527 | p.qh->period, | 527 | p.qh->period, |
| 528 | le32_to_cpup (&p.qh->hw_info2) | 528 | le32_to_cpup (&p.qh->hw_info2) |
| 529 | /* uframe masks */ | 529 | /* uframe masks */ |
| 530 | & 0xffff, | 530 | & (QH_CMASK | QH_SMASK), |
| 531 | p.qh); | 531 | p.qh); |
| 532 | size -= temp; | 532 | size -= temp; |
| 533 | next += temp; | 533 | next += temp; |
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 4f97a4ad1ed3..20df01a79b2e 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c | |||
| @@ -222,7 +222,7 @@ __acquires(ehci->lock) | |||
| 222 | struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv; | 222 | struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv; |
| 223 | 223 | ||
| 224 | /* S-mask in a QH means it's an interrupt urb */ | 224 | /* S-mask in a QH means it's an interrupt urb */ |
| 225 | if ((qh->hw_info2 & __constant_cpu_to_le32 (0x00ff)) != 0) { | 225 | if ((qh->hw_info2 & __constant_cpu_to_le32 (QH_SMASK)) != 0) { |
| 226 | 226 | ||
| 227 | /* ... update hc-wide periodic stats (for usbfs) */ | 227 | /* ... update hc-wide periodic stats (for usbfs) */ |
| 228 | ehci_to_hcd(ehci)->self.bandwidth_int_reqs--; | 228 | ehci_to_hcd(ehci)->self.bandwidth_int_reqs--; |
| @@ -428,7 +428,8 @@ halt: | |||
| 428 | /* should be rare for periodic transfers, | 428 | /* should be rare for periodic transfers, |
| 429 | * except maybe high bandwidth ... | 429 | * except maybe high bandwidth ... |
| 430 | */ | 430 | */ |
| 431 | if (qh->period) { | 431 | if ((__constant_cpu_to_le32 (QH_SMASK) |
| 432 | & qh->hw_info2) != 0) { | ||
| 432 | intr_deschedule (ehci, qh); | 433 | intr_deschedule (ehci, qh); |
| 433 | (void) qh_schedule (ehci, qh); | 434 | (void) qh_schedule (ehci, qh); |
| 434 | } else | 435 | } else |
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 9af4f64532a9..b56f25864ed6 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
| @@ -301,7 +301,7 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
| 301 | 301 | ||
| 302 | dev_dbg (&qh->dev->dev, | 302 | dev_dbg (&qh->dev->dev, |
| 303 | "link qh%d-%04x/%p start %d [%d/%d us]\n", | 303 | "link qh%d-%04x/%p start %d [%d/%d us]\n", |
| 304 | period, le32_to_cpup (&qh->hw_info2) & 0xffff, | 304 | period, le32_to_cpup (&qh->hw_info2) & (QH_CMASK | QH_SMASK), |
| 305 | qh, qh->start, qh->usecs, qh->c_usecs); | 305 | qh, qh->start, qh->usecs, qh->c_usecs); |
| 306 | 306 | ||
| 307 | /* high bandwidth, or otherwise every microframe */ | 307 | /* high bandwidth, or otherwise every microframe */ |
| @@ -385,7 +385,8 @@ static void qh_unlink_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
| 385 | 385 | ||
| 386 | dev_dbg (&qh->dev->dev, | 386 | dev_dbg (&qh->dev->dev, |
| 387 | "unlink qh%d-%04x/%p start %d [%d/%d us]\n", | 387 | "unlink qh%d-%04x/%p start %d [%d/%d us]\n", |
| 388 | qh->period, le32_to_cpup (&qh->hw_info2) & 0xffff, | 388 | qh->period, |
| 389 | le32_to_cpup (&qh->hw_info2) & (QH_CMASK | QH_SMASK), | ||
| 389 | qh, qh->start, qh->usecs, qh->c_usecs); | 390 | qh, qh->start, qh->usecs, qh->c_usecs); |
| 390 | 391 | ||
| 391 | /* qh->qh_next still "live" to HC */ | 392 | /* qh->qh_next still "live" to HC */ |
| @@ -411,7 +412,7 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
| 411 | * active high speed queues may need bigger delays... | 412 | * active high speed queues may need bigger delays... |
| 412 | */ | 413 | */ |
| 413 | if (list_empty (&qh->qtd_list) | 414 | if (list_empty (&qh->qtd_list) |
| 414 | || (__constant_cpu_to_le32 (0x0ff << 8) | 415 | || (__constant_cpu_to_le32 (QH_CMASK) |
| 415 | & qh->hw_info2) != 0) | 416 | & qh->hw_info2) != 0) |
| 416 | wait = 2; | 417 | wait = 2; |
| 417 | else | 418 | else |
| @@ -533,7 +534,7 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
| 533 | 534 | ||
| 534 | /* reuse the previous schedule slots, if we can */ | 535 | /* reuse the previous schedule slots, if we can */ |
| 535 | if (frame < qh->period) { | 536 | if (frame < qh->period) { |
| 536 | uframe = ffs (le32_to_cpup (&qh->hw_info2) & 0x00ff); | 537 | uframe = ffs (le32_to_cpup (&qh->hw_info2) & QH_SMASK); |
| 537 | status = check_intr_schedule (ehci, frame, --uframe, | 538 | status = check_intr_schedule (ehci, frame, --uframe, |
| 538 | qh, &c_mask); | 539 | qh, &c_mask); |
| 539 | } else { | 540 | } else { |
| @@ -569,10 +570,10 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
| 569 | qh->start = frame; | 570 | qh->start = frame; |
| 570 | 571 | ||
| 571 | /* reset S-frame and (maybe) C-frame masks */ | 572 | /* reset S-frame and (maybe) C-frame masks */ |
| 572 | qh->hw_info2 &= __constant_cpu_to_le32 (~0xffff); | 573 | qh->hw_info2 &= __constant_cpu_to_le32(~(QH_CMASK | QH_SMASK)); |
| 573 | qh->hw_info2 |= qh->period | 574 | qh->hw_info2 |= qh->period |
| 574 | ? cpu_to_le32 (1 << uframe) | 575 | ? cpu_to_le32 (1 << uframe) |
| 575 | : __constant_cpu_to_le32 (0xff); | 576 | : __constant_cpu_to_le32 (QH_SMASK); |
| 576 | qh->hw_info2 |= c_mask; | 577 | qh->hw_info2 |= c_mask; |
| 577 | } else | 578 | } else |
| 578 | ehci_dbg (ehci, "reused qh %p schedule\n", qh); | 579 | ehci_dbg (ehci, "reused qh %p schedule\n", qh); |
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 4df498231752..a7542157534c 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h | |||
| @@ -385,6 +385,11 @@ struct ehci_qh { | |||
| 385 | __le32 hw_info1; /* see EHCI 3.6.2 */ | 385 | __le32 hw_info1; /* see EHCI 3.6.2 */ |
| 386 | #define QH_HEAD 0x00008000 | 386 | #define QH_HEAD 0x00008000 |
| 387 | __le32 hw_info2; /* see EHCI 3.6.2 */ | 387 | __le32 hw_info2; /* see EHCI 3.6.2 */ |
| 388 | #define QH_SMASK 0x000000ff | ||
| 389 | #define QH_CMASK 0x0000ff00 | ||
| 390 | #define QH_HUBADDR 0x007f0000 | ||
| 391 | #define QH_HUBPORT 0x3f800000 | ||
| 392 | #define QH_MULT 0xc0000000 | ||
| 388 | __le32 hw_current; /* qtd list - see EHCI 3.6.4 */ | 393 | __le32 hw_current; /* qtd list - see EHCI 3.6.4 */ |
| 389 | 394 | ||
| 390 | /* qtd overlay (hardware parts of a struct ehci_qtd) */ | 395 | /* qtd overlay (hardware parts of a struct ehci_qtd) */ |
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 50b1970fe6b6..76cb496c5836 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c | |||
| @@ -229,9 +229,11 @@ static void preproc_atl_queue(struct isp116x *isp116x) | |||
| 229 | struct isp116x_ep *ep; | 229 | struct isp116x_ep *ep; |
| 230 | struct urb *urb; | 230 | struct urb *urb; |
| 231 | struct ptd *ptd; | 231 | struct ptd *ptd; |
| 232 | u16 toggle = 0, dir = PTD_DIR_SETUP, len; | 232 | u16 len; |
| 233 | 233 | ||
| 234 | for (ep = isp116x->atl_active; ep; ep = ep->active) { | 234 | for (ep = isp116x->atl_active; ep; ep = ep->active) { |
| 235 | u16 toggle = 0, dir = PTD_DIR_SETUP; | ||
| 236 | |||
| 235 | BUG_ON(list_empty(&ep->hep->urb_list)); | 237 | BUG_ON(list_empty(&ep->hep->urb_list)); |
| 236 | urb = container_of(ep->hep->urb_list.next, | 238 | urb = container_of(ep->hep->urb_list.next, |
| 237 | struct urb, urb_list); | 239 | struct urb, urb_list); |
diff --git a/drivers/usb/mon/Kconfig b/drivers/usb/mon/Kconfig index 777642e26b9a..deb9ddffa402 100644 --- a/drivers/usb/mon/Kconfig +++ b/drivers/usb/mon/Kconfig | |||
| @@ -9,9 +9,8 @@ config USB_MON | |||
| 9 | help | 9 | help |
| 10 | If you say Y here, a component which captures the USB traffic | 10 | If you say Y here, a component which captures the USB traffic |
| 11 | between peripheral-specific drivers and HC drivers will be built. | 11 | between peripheral-specific drivers and HC drivers will be built. |
| 12 | The USB_MON is similar in spirit and may be compatible with Dave | 12 | For more information, see <file:Documentation/usb/usbmon.txt>. |
| 13 | Harding's USBMon. | ||
| 14 | 13 | ||
| 15 | This is somewhat experimental at this time, but it should be safe, | 14 | This is somewhat experimental at this time, but it should be safe. |
| 16 | as long as you aren't using modular USB and try to remove this | 15 | |
| 17 | module. | 16 | If unsure, say Y. |
diff --git a/drivers/usb/mon/Makefile b/drivers/usb/mon/Makefile index f18d10ce91f9..b0015b8a1d1f 100644 --- a/drivers/usb/mon/Makefile +++ b/drivers/usb/mon/Makefile | |||
| @@ -4,4 +4,5 @@ | |||
| 4 | 4 | ||
| 5 | usbmon-objs := mon_main.o mon_stat.o mon_text.o | 5 | usbmon-objs := mon_main.o mon_stat.o mon_text.o |
| 6 | 6 | ||
| 7 | # This does not use CONFIG_USB_MON because we want this to use a tristate. | ||
| 7 | obj-$(CONFIG_USB) += usbmon.o | 8 | obj-$(CONFIG_USB) += usbmon.o |
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index ed1d4d1ac4f7..1147b899f007 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c | |||
| @@ -414,6 +414,13 @@ static ssize_t show_pan(struct class_device *class_device, char *buf) | |||
| 414 | fb_info->var.xoffset); | 414 | fb_info->var.xoffset); |
| 415 | } | 415 | } |
| 416 | 416 | ||
| 417 | static ssize_t show_name(struct class_device *class_device, char *buf) | ||
| 418 | { | ||
| 419 | struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device); | ||
| 420 | |||
| 421 | return snprintf(buf, PAGE_SIZE, "%s\n", fb_info->fix.id); | ||
| 422 | } | ||
| 423 | |||
| 417 | static struct class_device_attribute class_device_attrs[] = { | 424 | static struct class_device_attribute class_device_attrs[] = { |
| 418 | __ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp), | 425 | __ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp), |
| 419 | __ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank), | 426 | __ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank), |
| @@ -424,6 +431,7 @@ static struct class_device_attribute class_device_attrs[] = { | |||
| 424 | __ATTR(modes, S_IRUGO|S_IWUSR, show_modes, store_modes), | 431 | __ATTR(modes, S_IRUGO|S_IWUSR, show_modes, store_modes), |
| 425 | __ATTR(pan, S_IRUGO|S_IWUSR, show_pan, store_pan), | 432 | __ATTR(pan, S_IRUGO|S_IWUSR, show_pan, store_pan), |
| 426 | __ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual), | 433 | __ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual), |
| 434 | __ATTR(name, S_IRUGO, show_name, NULL), | ||
| 427 | }; | 435 | }; |
| 428 | 436 | ||
| 429 | int fb_init_class_device(struct fb_info *fb_info) | 437 | int fb_init_class_device(struct fb_info *fb_info) |
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c index fbf659b6dab0..3edc9f49344b 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c | |||
| @@ -246,6 +246,11 @@ static const struct fb_videomode modedb[] = { | |||
| 246 | /* 480x300 @ 72 Hz, 48.0 kHz hsync */ | 246 | /* 480x300 @ 72 Hz, 48.0 kHz hsync */ |
| 247 | NULL, 72, 480, 300, 33386, 40, 24, 11, 19, 80, 3, | 247 | NULL, 72, 480, 300, 33386, 40, 24, 11, 19, 80, 3, |
| 248 | 0, FB_VMODE_DOUBLE | 248 | 0, FB_VMODE_DOUBLE |
| 249 | }, { | ||
| 250 | /* 1920x1200 @ 60 Hz, 74.5 Khz hsync */ | ||
| 251 | NULL, 60, 1920, 1200, 5177, 128, 336, 1, 38, 208, 3, | ||
| 252 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 253 | FB_VMODE_NONINTERLACED | ||
| 249 | }, | 254 | }, |
| 250 | }; | 255 | }; |
| 251 | 256 | ||
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index b2e6b2407869..52b16850a54e 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c | |||
| @@ -1324,6 +1324,13 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info) | |||
| 1324 | 1324 | ||
| 1325 | fb_videomode_to_var(&nvidiafb_default_var, &modedb); | 1325 | fb_videomode_to_var(&nvidiafb_default_var, &modedb); |
| 1326 | nvidiafb_default_var.bits_per_pixel = 8; | 1326 | nvidiafb_default_var.bits_per_pixel = 8; |
| 1327 | } else if (par->fpWidth && par->fpHeight) { | ||
| 1328 | char buf[16]; | ||
| 1329 | |||
| 1330 | memset(buf, 0, 16); | ||
| 1331 | snprintf(buf, 15, "%dx%d", par->fpWidth, par->fpHeight); | ||
| 1332 | fb_find_mode(&nvidiafb_default_var, info, buf, specs->modedb, | ||
| 1333 | specs->modedb_len, &modedb, 8); | ||
| 1327 | } | 1334 | } |
| 1328 | 1335 | ||
| 1329 | if (mode_option) | 1336 | if (mode_option) |
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 16e37a535d85..30112816420c 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c | |||
| @@ -717,6 +717,9 @@ static void pxafb_enable_controller(struct pxafb_info *fbi) | |||
| 717 | DPRINTK("reg_lccr2 0x%08x\n", (unsigned int) fbi->reg_lccr2); | 717 | DPRINTK("reg_lccr2 0x%08x\n", (unsigned int) fbi->reg_lccr2); |
| 718 | DPRINTK("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3); | 718 | DPRINTK("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3); |
| 719 | 719 | ||
| 720 | /* enable LCD controller clock */ | ||
| 721 | pxa_set_cken(CKEN16_LCD, 1); | ||
| 722 | |||
| 720 | /* Sequence from 11.7.10 */ | 723 | /* Sequence from 11.7.10 */ |
| 721 | LCCR3 = fbi->reg_lccr3; | 724 | LCCR3 = fbi->reg_lccr3; |
| 722 | LCCR2 = fbi->reg_lccr2; | 725 | LCCR2 = fbi->reg_lccr2; |
| @@ -750,6 +753,9 @@ static void pxafb_disable_controller(struct pxafb_info *fbi) | |||
| 750 | 753 | ||
| 751 | schedule_timeout(20 * HZ / 1000); | 754 | schedule_timeout(20 * HZ / 1000); |
| 752 | remove_wait_queue(&fbi->ctrlr_wait, &wait); | 755 | remove_wait_queue(&fbi->ctrlr_wait, &wait); |
| 756 | |||
| 757 | /* disable LCD controller clock */ | ||
| 758 | pxa_set_cken(CKEN16_LCD, 0); | ||
| 753 | } | 759 | } |
| 754 | 760 | ||
| 755 | /* | 761 | /* |
| @@ -1299,8 +1305,6 @@ int __init pxafb_probe(struct device *dev) | |||
| 1299 | ret = -ENOMEM; | 1305 | ret = -ENOMEM; |
| 1300 | goto failed; | 1306 | goto failed; |
| 1301 | } | 1307 | } |
| 1302 | /* enable LCD controller clock */ | ||
| 1303 | pxa_set_cken(CKEN16_LCD, 1); | ||
| 1304 | 1308 | ||
| 1305 | ret = request_irq(IRQ_LCD, pxafb_handle_irq, SA_INTERRUPT, "LCD", fbi); | 1309 | ret = request_irq(IRQ_LCD, pxafb_handle_irq, SA_INTERRUPT, "LCD", fbi); |
| 1306 | if (ret) { | 1310 | if (ret) { |
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index 2d29db7ef800..beeec7b51425 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c | |||
| @@ -598,7 +598,7 @@ sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | |||
| 598 | * requests for the LCD controller. If we hit this, it means we're | 598 | * requests for the LCD controller. If we hit this, it means we're |
| 599 | * doing nothing but LCD DMA. | 599 | * doing nothing but LCD DMA. |
| 600 | */ | 600 | */ |
| 601 | static unsigned int sa1100fb_display_dma_period(struct fb_var_screeninfo *var) | 601 | static inline unsigned int sa1100fb_display_dma_period(struct fb_var_screeninfo *var) |
| 602 | { | 602 | { |
| 603 | /* | 603 | /* |
| 604 | * Period = pixclock * bits_per_byte * bytes_per_transfer | 604 | * Period = pixclock * bits_per_byte * bytes_per_transfer |
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c index da8004e5d03d..698ca9232e73 100644 --- a/drivers/video/tridentfb.c +++ b/drivers/video/tridentfb.c | |||
| @@ -454,13 +454,16 @@ static struct accel_switch accel_image = { | |||
| 454 | static void tridentfb_fillrect(struct fb_info * info, const struct fb_fillrect *fr) | 454 | static void tridentfb_fillrect(struct fb_info * info, const struct fb_fillrect *fr) |
| 455 | { | 455 | { |
| 456 | int bpp = info->var.bits_per_pixel; | 456 | int bpp = info->var.bits_per_pixel; |
| 457 | int col; | 457 | int col = 0; |
| 458 | 458 | ||
| 459 | switch (bpp) { | 459 | switch (bpp) { |
| 460 | default: | 460 | default: |
| 461 | case 8: col = fr->color; | 461 | case 8: col |= fr->color; |
| 462 | col |= col << 8; | ||
| 463 | col |= col << 16; | ||
| 462 | break; | 464 | break; |
| 463 | case 16: col = ((u32 *)(info->pseudo_palette))[fr->color]; | 465 | case 16: col = ((u32 *)(info->pseudo_palette))[fr->color]; |
| 466 | |||
| 464 | break; | 467 | break; |
| 465 | case 32: col = ((u32 *)(info->pseudo_palette))[fr->color]; | 468 | case 32: col = ((u32 *)(info->pseudo_palette))[fr->color]; |
| 466 | break; | 469 | break; |
| @@ -882,8 +885,9 @@ static int tridentfb_set_par(struct fb_info *info) | |||
| 882 | 885 | ||
| 883 | write3X4(GraphEngReg, 0x80); //enable GE for text acceleration | 886 | write3X4(GraphEngReg, 0x80); //enable GE for text acceleration |
| 884 | 887 | ||
| 885 | // if (info->var.accel_flags & FB_ACCELF_TEXT) | 888 | #ifdef CONFIG_FB_TRIDENT_ACCEL |
| 886 | //FIXME acc->init_accel(info->var.xres,bpp); | 889 | acc->init_accel(info->var.xres,bpp); |
| 890 | #endif | ||
| 887 | 891 | ||
| 888 | switch (bpp) { | 892 | switch (bpp) { |
| 889 | case 8: tmp = 0x00; break; | 893 | case 8: tmp = 0x00; break; |
| @@ -900,7 +904,7 @@ static int tridentfb_set_par(struct fb_info *info) | |||
| 900 | write3X4(DRAMControl, tmp); //both IO,linear enable | 904 | write3X4(DRAMControl, tmp); //both IO,linear enable |
| 901 | 905 | ||
| 902 | write3X4(InterfaceSel, read3X4(InterfaceSel) | 0x40); | 906 | write3X4(InterfaceSel, read3X4(InterfaceSel) | 0x40); |
| 903 | write3X4(Performance,0x20); | 907 | write3X4(Performance,0x92); |
| 904 | write3X4(PCIReg,0x07); //MMIO & PCI read and write burst enable | 908 | write3X4(PCIReg,0x07); //MMIO & PCI read and write burst enable |
| 905 | 909 | ||
| 906 | /* convert from picoseconds to MHz */ | 910 | /* convert from picoseconds to MHz */ |
| @@ -981,12 +985,14 @@ static int tridentfb_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
| 981 | t_outb(green>>10,0x3C9); | 985 | t_outb(green>>10,0x3C9); |
| 982 | t_outb(blue>>10,0x3C9); | 986 | t_outb(blue>>10,0x3C9); |
| 983 | 987 | ||
| 984 | } else | 988 | } else if (bpp == 16) { /* RGB 565 */ |
| 985 | if (bpp == 16) /* RGB 565 */ | 989 | u32 col; |
| 986 | ((u32*)info->pseudo_palette)[regno] = (red & 0xF800) | | 990 | |
| 987 | ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11); | 991 | col = (red & 0xF800) | ((green & 0xFC00) >> 5) | |
| 988 | else | 992 | ((blue & 0xF800) >> 11); |
| 989 | if (bpp == 32) /* ARGB 8888 */ | 993 | col |= col << 16; |
| 994 | ((u32 *)(info->pseudo_palette))[regno] = col; | ||
| 995 | } else if (bpp == 32) /* ARGB 8888 */ | ||
| 990 | ((u32*)info->pseudo_palette)[regno] = | 996 | ((u32*)info->pseudo_palette)[regno] = |
| 991 | ((transp & 0xFF00) <<16) | | 997 | ((transp & 0xFF00) <<16) | |
| 992 | ((red & 0xFF00) << 8) | | 998 | ((red & 0xFF00) << 8) | |
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 8a9c42822502..0bbf029b1ef1 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c | |||
| @@ -593,7 +593,7 @@ void w1_search(struct w1_master *dev, w1_slave_found_callback cb) | |||
| 593 | * Return 0 - device(s) present, 1 - no devices present. | 593 | * Return 0 - device(s) present, 1 - no devices present. |
| 594 | */ | 594 | */ |
| 595 | if (w1_reset_bus(dev)) { | 595 | if (w1_reset_bus(dev)) { |
| 596 | dev_info(&dev->dev, "No devices present on the wire.\n"); | 596 | dev_dbg(&dev->dev, "No devices present on the wire.\n"); |
| 597 | break; | 597 | break; |
| 598 | } | 598 | } |
| 599 | 599 | ||
