diff options
Diffstat (limited to 'drivers')
219 files changed, 4073 insertions, 2891 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) if (fdc_busy) return; save_flags(flags); cli(); - while (fdc_busy) - sleep_on(&fdc_wait); + wait_event(fdc_wait, !fdc_busy); fdc_busy = 1; ENABLE_IRQ(); 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 depends on ACPI_INTERPRETER depends on EXPERIMENTAL depends on !IA64_SGI_SN - default m + default n help - ACPI generic hotkey + Experimental consolidated hotkey driver. + If you are unsure, say N. config ACPI_FAN 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 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> +#include <linux/types.h> +#include <linux/proc_fs.h> +#include <linux/seq_file.h> #include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h> @@ -33,6 +36,9 @@ #define ACPI_BUTTON_COMPONENT 0x00080000 #define ACPI_BUTTON_DRIVER_NAME "ACPI Button Driver" #define ACPI_BUTTON_CLASS "button" +#define ACPI_BUTTON_FILE_INFO "info" +#define ACPI_BUTTON_FILE_STATE "state" +#define ACPI_BUTTON_TYPE_UNKNOWN 0x00 #define ACPI_BUTTON_NOTIFY_STATUS 0x80 #define ACPI_BUTTON_SUBCLASS_POWER "power" @@ -64,6 +70,8 @@ MODULE_LICENSE("GPL"); static int acpi_button_add (struct acpi_device *device); static int acpi_button_remove (struct acpi_device *device, int type); +static int acpi_button_info_open_fs(struct inode *inode, struct file *file); +static int acpi_button_state_open_fs(struct inode *inode, struct file *file); static struct acpi_driver acpi_button_driver = { .name = ACPI_BUTTON_DRIVER_NAME, @@ -82,6 +90,179 @@ struct acpi_button { unsigned long pushed; }; +static struct file_operations acpi_button_info_fops = { + .open = acpi_button_info_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static struct file_operations acpi_button_state_fops = { + .open = acpi_button_state_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +/* -------------------------------------------------------------------------- + FS Interface (/proc) + -------------------------------------------------------------------------- */ + +static struct proc_dir_entry *acpi_button_dir; + +static int acpi_button_info_seq_show(struct seq_file *seq, void *offset) +{ + struct acpi_button *button = (struct acpi_button *) seq->private; + + ACPI_FUNCTION_TRACE("acpi_button_info_seq_show"); + + if (!button || !button->device) + return_VALUE(0); + + seq_printf(seq, "type: %s\n", + acpi_device_name(button->device)); + + return_VALUE(0); +} + +static int acpi_button_info_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_button_info_seq_show, PDE(inode)->data); +} + +static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) +{ + struct acpi_button *button = (struct acpi_button *) seq->private; + acpi_status status; + unsigned long state; + + ACPI_FUNCTION_TRACE("acpi_button_state_seq_show"); + + if (!button || !button->device) + return_VALUE(0); + + status = acpi_evaluate_integer(button->handle,"_LID",NULL,&state); + if (ACPI_FAILURE(status)) { + seq_printf(seq, "state: unsupported\n"); + } + else{ + seq_printf(seq, "state: %s\n", (state ? "open" : "closed")); + } + + return_VALUE(0); +} + +static int acpi_button_state_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_button_state_seq_show, PDE(inode)->data); +} + +static struct proc_dir_entry *acpi_power_dir; +static struct proc_dir_entry *acpi_sleep_dir; +static struct proc_dir_entry *acpi_lid_dir; + +static int +acpi_button_add_fs ( + struct acpi_device *device) +{ + struct proc_dir_entry *entry = NULL; + struct acpi_button *button = NULL; + + ACPI_FUNCTION_TRACE("acpi_button_add_fs"); + + if (!device || !acpi_driver_data(device)) + return_VALUE(-EINVAL); + + button = acpi_driver_data(device); + + switch (button->type) { + case ACPI_BUTTON_TYPE_POWER: + case ACPI_BUTTON_TYPE_POWERF: + if (!acpi_power_dir) + acpi_power_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_POWER, + acpi_button_dir); + entry = acpi_power_dir; + break; + case ACPI_BUTTON_TYPE_SLEEP: + case ACPI_BUTTON_TYPE_SLEEPF: + if (!acpi_sleep_dir) + acpi_sleep_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_SLEEP, + acpi_button_dir); + entry = acpi_sleep_dir; + break; + case ACPI_BUTTON_TYPE_LID: + if (!acpi_lid_dir) + acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID, + acpi_button_dir); + entry = acpi_lid_dir; + break; + } + + if (!entry) + return_VALUE(-ENODEV); + entry->owner = THIS_MODULE; + + acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), entry); + if (!acpi_device_dir(device)) + return_VALUE(-ENODEV); + acpi_device_dir(device)->owner = THIS_MODULE; + + /* 'info' [R] */ + entry = create_proc_entry(ACPI_BUTTON_FILE_INFO, + S_IRUGO, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_BUTTON_FILE_INFO)); + else { + entry->proc_fops = &acpi_button_info_fops; + entry->data = acpi_driver_data(device); + entry->owner = THIS_MODULE; + } + + /* show lid state [R] */ + if (button->type == ACPI_BUTTON_TYPE_LID) { + entry = create_proc_entry(ACPI_BUTTON_FILE_STATE, + S_IRUGO, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_BUTTON_FILE_INFO)); + else { + entry->proc_fops = &acpi_button_state_fops; + entry->data = acpi_driver_data(device); + entry->owner = THIS_MODULE; + } + } + + return_VALUE(0); +} + + +static int +acpi_button_remove_fs ( + struct acpi_device *device) +{ + struct acpi_button *button = NULL; + + ACPI_FUNCTION_TRACE("acpi_button_remove_fs"); + + button = acpi_driver_data(device); + if (acpi_device_dir(device)) { + if (button->type == ACPI_BUTTON_TYPE_LID) + remove_proc_entry(ACPI_BUTTON_FILE_STATE, + acpi_device_dir(device)); + remove_proc_entry(ACPI_BUTTON_FILE_INFO, + acpi_device_dir(device)); + + remove_proc_entry(acpi_device_bid(device), + acpi_device_dir(device)->parent); + acpi_device_dir(device) = NULL; + } + + return_VALUE(0); +} + + /* -------------------------------------------------------------------------- Driver Interface -------------------------------------------------------------------------- */ @@ -121,7 +302,8 @@ acpi_button_notify_fixed ( ACPI_FUNCTION_TRACE("acpi_button_notify_fixed"); - BUG_ON(!button); + if (!button) + return_ACPI_STATUS(AE_BAD_PARAMETER); acpi_button_notify(button->handle, ACPI_BUTTON_NOTIFY_STATUS, button); @@ -197,6 +379,10 @@ acpi_button_add ( goto end; } + result = acpi_button_add_fs(device); + if (result) + goto end; + switch (button->type) { case ACPI_BUTTON_TYPE_POWERF: status = acpi_install_fixed_event_handler ( @@ -240,6 +426,7 @@ acpi_button_add ( end: if (result) { + acpi_button_remove_fs(device); kfree(button); } @@ -280,6 +467,8 @@ acpi_button_remove (struct acpi_device *device, int type) ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error removing notify handler\n")); + acpi_button_remove_fs(device); + kfree(button); return_VALUE(0); @@ -293,14 +482,20 @@ acpi_button_init (void) ACPI_FUNCTION_TRACE("acpi_button_init"); + acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir); + if (!acpi_button_dir) + return_VALUE(-ENODEV); + acpi_button_dir->owner = THIS_MODULE; result = acpi_bus_register_driver(&acpi_button_driver); if (result < 0) { + remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); return_VALUE(-ENODEV); } return_VALUE(0); } + static void __exit acpi_button_exit (void) { @@ -308,8 +503,17 @@ acpi_button_exit (void) acpi_bus_unregister_driver(&acpi_button_driver); + if (acpi_power_dir) + remove_proc_entry(ACPI_BUTTON_SUBCLASS_POWER, acpi_button_dir); + if (acpi_sleep_dir) + remove_proc_entry(ACPI_BUTTON_SUBCLASS_SLEEP, acpi_button_dir); + if (acpi_lid_dir) + remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir); + remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); + return_VOID; } + module_init(acpi_button_init); 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 ( if ((!(walk_state->op_info->flags & AML_NSOPCODE) && (walk_state->opcode != AML_INT_NAMEPATH_OP)) || (!(walk_state->op_info->flags & AML_NAMED))) { - if ((walk_state->op_info->class == AML_CLASS_EXECUTE) || - (walk_state->op_info->class == AML_CLASS_CONTROL)) { - ACPI_REPORT_WARNING (( - "Encountered executable code at module level, [%s]\n", - acpi_ps_get_opcode_name (walk_state->opcode))); - } return_ACPI_STATUS (AE_OK); } 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") #define ACPI_EC_DELAY 50 /* Wait 50ms max. during EC ops */ #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ +#define ACPI_EC_UDELAY 100 /* Poll @ 100us increments */ +#define ACPI_EC_UDELAY_COUNT 1000 /* Wait 10ms max. during EC ops */ + #define ACPI_EC_COMMAND_READ 0x80 #define ACPI_EC_COMMAND_WRITE 0x81 #define ACPI_EC_BURST_ENABLE 0x82 #define ACPI_EC_BURST_DISABLE 0x83 #define ACPI_EC_COMMAND_QUERY 0x84 -static int acpi_ec_add (struct acpi_device *device); +#define EC_POLLING 0xFF +#define EC_BURST 0x00 + + static int acpi_ec_remove (struct acpi_device *device, int type); static int acpi_ec_start (struct acpi_device *device); static int acpi_ec_stop (struct acpi_device *device, int type); +static int acpi_ec_burst_add ( struct acpi_device *device); +static int acpi_ec_polling_add ( struct acpi_device *device); static struct acpi_driver acpi_ec_driver = { .name = ACPI_EC_DRIVER_NAME, .class = ACPI_EC_CLASS, .ids = ACPI_EC_HID, .ops = { - .add = acpi_ec_add, + .add = acpi_ec_polling_add, .remove = acpi_ec_remove, .start = acpi_ec_start, .stop = acpi_ec_stop, }, }; - -struct acpi_ec { - acpi_handle handle; - unsigned long uid; - unsigned long gpe_bit; - struct acpi_generic_address status_addr; - struct acpi_generic_address command_addr; - struct acpi_generic_address data_addr; - unsigned long global_lock; - unsigned int expect_event; - atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort*/ - atomic_t pending_gpe; - struct semaphore sem; - wait_queue_head_t wait; +union acpi_ec { + struct { + u32 mode; + acpi_handle handle; + unsigned long uid; + unsigned long gpe_bit; + struct acpi_generic_address status_addr; + struct acpi_generic_address command_addr; + struct acpi_generic_address data_addr; + unsigned long global_lock; + } common; + + struct { + u32 mode; + acpi_handle handle; + unsigned long uid; + unsigned long gpe_bit; + struct acpi_generic_address status_addr; + struct acpi_generic_address command_addr; + struct acpi_generic_address data_addr; + unsigned long global_lock; + unsigned int expect_event; + atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort*/ + atomic_t pending_gpe; + struct semaphore sem; + wait_queue_head_t wait; + }burst; + + struct { + u32 mode; + acpi_handle handle; + unsigned long uid; + unsigned long gpe_bit; + struct acpi_generic_address status_addr; + struct acpi_generic_address command_addr; + struct acpi_generic_address data_addr; + unsigned long global_lock; + spinlock_t lock; + }polling; }; +static int acpi_ec_polling_wait ( union acpi_ec *ec, u8 event); +static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event); +static int acpi_ec_polling_read ( union acpi_ec *ec, u8 address, u32 *data); +static int acpi_ec_burst_read( union acpi_ec *ec, u8 address, u32 *data); +static int acpi_ec_polling_write ( union acpi_ec *ec, u8 address, u8 data); +static int acpi_ec_burst_write ( union acpi_ec *ec, u8 address, u8 data); +static int acpi_ec_polling_query ( union acpi_ec *ec, u32 *data); +static int acpi_ec_burst_query ( union acpi_ec *ec, u32 *data); +static void acpi_ec_gpe_polling_query ( void *ec_cxt); +static void acpi_ec_gpe_burst_query ( void *ec_cxt); +static u32 acpi_ec_gpe_polling_handler ( void *data); +static u32 acpi_ec_gpe_burst_handler ( void *data); +static acpi_status __init +acpi_fake_ecdt_polling_callback ( + acpi_handle handle, + u32 Level, + void *context, + void **retval); + +static acpi_status __init +acpi_fake_ecdt_burst_callback ( + acpi_handle handle, + u32 Level, + void *context, + void **retval); + +static int __init +acpi_ec_polling_get_real_ecdt(void); +static int __init +acpi_ec_burst_get_real_ecdt(void); /* If we find an EC via the ECDT, we need to keep a ptr to its context */ -static struct acpi_ec *ec_ecdt; +static union acpi_ec *ec_ecdt; /* External interfaces use first EC only, so remember */ static struct acpi_device *first_ec; +static int acpi_ec_polling_mode = EC_POLLING; /* -------------------------------------------------------------------------- Transaction Management -------------------------------------------------------------------------- */ -static inline u32 acpi_ec_read_status(struct acpi_ec *ec) +static inline u32 acpi_ec_read_status(union acpi_ec *ec) { u32 status = 0; - acpi_hw_low_level_read(8, &status, &ec->status_addr); + acpi_hw_low_level_read(8, &status, &ec->common.status_addr); return status; } -static int acpi_ec_wait(struct acpi_ec *ec, unsigned int event) +static int +acpi_ec_wait ( + union acpi_ec *ec, + u8 event) +{ + if (acpi_ec_polling_mode) + return acpi_ec_polling_wait (ec, event); + else + return acpi_ec_burst_wait (ec, event); +} + +static int +acpi_ec_polling_wait ( + union acpi_ec *ec, + u8 event) +{ + u32 acpi_ec_status = 0; + u32 i = ACPI_EC_UDELAY_COUNT; + + if (!ec) + return -EINVAL; + + /* Poll the EC status register waiting for the event to occur. */ + switch (event) { + case ACPI_EC_EVENT_OBF: + do { + acpi_hw_low_level_read(8, &acpi_ec_status, &ec->common.status_addr); + if (acpi_ec_status & ACPI_EC_FLAG_OBF) + return 0; + udelay(ACPI_EC_UDELAY); + } while (--i>0); + break; + case ACPI_EC_EVENT_IBE: + do { + acpi_hw_low_level_read(8, &acpi_ec_status, &ec->common.status_addr); + if (!(acpi_ec_status & ACPI_EC_FLAG_IBF)) + return 0; + udelay(ACPI_EC_UDELAY); + } while (--i>0); + break; + default: + return -EINVAL; + } + + return -ETIME; +} +static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event) { int result = 0; ACPI_FUNCTION_TRACE("acpi_ec_wait"); - ec->expect_event = event; + ec->burst.expect_event = event; smp_mb(); - result = wait_event_interruptible_timeout(ec->wait, - !ec->expect_event, + result = wait_event_interruptible_timeout(ec->burst.wait, + !ec->burst.expect_event, msecs_to_jiffies(ACPI_EC_DELAY)); - ec->expect_event = 0; + ec->burst.expect_event = 0; smp_mb(); if (result < 0){ @@ -160,7 +270,7 @@ static int acpi_ec_wait(struct acpi_ec *ec, unsigned int event) static int acpi_ec_enter_burst_mode ( - struct acpi_ec *ec) + union acpi_ec *ec) { u32 tmp = 0; int status = 0; @@ -170,43 +280,43 @@ acpi_ec_enter_burst_mode ( status = acpi_ec_read_status(ec); if (status != -EINVAL && !(status & ACPI_EC_FLAG_BURST)){ - acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->command_addr); + acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->common.command_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); if (status){ - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); return_VALUE(-EINVAL); } - acpi_hw_low_level_read(8, &tmp, &ec->data_addr); - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); if(tmp != 0x90 ) {/* Burst ACK byte*/ return_VALUE(-EINVAL); } } - atomic_set(&ec->leaving_burst , 0); + atomic_set(&ec->burst.leaving_burst , 0); return_VALUE(0); } static int acpi_ec_leave_burst_mode ( - struct acpi_ec *ec) + union acpi_ec *ec) { int status =0; ACPI_FUNCTION_TRACE("acpi_ec_leave_burst_mode"); - atomic_set(&ec->leaving_burst , 1); + atomic_set(&ec->burst.leaving_burst , 1); status = acpi_ec_read_status(ec); if (status != -EINVAL && (status & ACPI_EC_FLAG_BURST)){ - acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, &ec->command_addr); + acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, &ec->common.command_addr); status = acpi_ec_wait(ec, ACPI_EC_FLAG_IBF); if (status){ - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"------->wait fail\n")); return_VALUE(-EINVAL); } - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); status = acpi_ec_read_status(ec); } @@ -215,7 +325,131 @@ acpi_ec_leave_burst_mode ( static int acpi_ec_read ( - struct acpi_ec *ec, + union acpi_ec *ec, + u8 address, + u32 *data) +{ + if (acpi_ec_polling_mode) + return acpi_ec_polling_read(ec, address, data); + else + return acpi_ec_burst_read(ec, address, data); +} +static int +acpi_ec_write ( + union acpi_ec *ec, + u8 address, + u8 data) +{ + if (acpi_ec_polling_mode) + return acpi_ec_polling_write(ec, address, data); + else + return acpi_ec_burst_write(ec, address, data); +} +static int +acpi_ec_polling_read ( + union acpi_ec *ec, + u8 address, + u32 *data) +{ + acpi_status status = AE_OK; + int result = 0; + unsigned long flags = 0; + u32 glk = 0; + + ACPI_FUNCTION_TRACE("acpi_ec_read"); + + if (!ec || !data) + return_VALUE(-EINVAL); + + *data = 0; + + if (ec->common.global_lock) { + status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + } + + spin_lock_irqsave(&ec->polling.lock, flags); + + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->common.command_addr); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + if (result) + goto end; + + acpi_hw_low_level_write(8, address, &ec->common.data_addr); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); + if (result) + goto end; + + acpi_hw_low_level_read(8, data, &ec->common.data_addr); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", + *data, address)); + +end: + spin_unlock_irqrestore(&ec->polling.lock, flags); + + if (ec->common.global_lock) + acpi_release_global_lock(glk); + + return_VALUE(result); +} + + +static int +acpi_ec_polling_write ( + union acpi_ec *ec, + u8 address, + u8 data) +{ + int result = 0; + acpi_status status = AE_OK; + unsigned long flags = 0; + u32 glk = 0; + + ACPI_FUNCTION_TRACE("acpi_ec_write"); + + if (!ec) + return_VALUE(-EINVAL); + + if (ec->common.global_lock) { + status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + } + + spin_lock_irqsave(&ec->polling.lock, flags); + + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->common.command_addr); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + if (result) + goto end; + + acpi_hw_low_level_write(8, address, &ec->common.data_addr); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + if (result) + goto end; + + acpi_hw_low_level_write(8, data, &ec->common.data_addr); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + if (result) + goto end; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n", + data, address)); + +end: + spin_unlock_irqrestore(&ec->polling.lock, flags); + + if (ec->common.global_lock) + acpi_release_global_lock(glk); + + return_VALUE(result); +} + +static int +acpi_ec_burst_read ( + union acpi_ec *ec, u8 address, u32 *data) { @@ -230,51 +464,51 @@ acpi_ec_read ( retry: *data = 0; - if (ec->global_lock) { + if (ec->common.global_lock) { status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); if (ACPI_FAILURE(status)) return_VALUE(-ENODEV); } WARN_ON(in_interrupt()); - down(&ec->sem); + down(&ec->burst.sem); if(acpi_ec_enter_burst_mode(ec)) goto end; - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->command_addr); + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->common.command_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); if (status) { goto end; } - acpi_hw_low_level_write(8, address, &ec->data_addr); + acpi_hw_low_level_write(8, address, &ec->common.data_addr); status= acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); if (status){ - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); goto end; } - acpi_hw_low_level_read(8, data, &ec->data_addr); - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_hw_low_level_read(8, data, &ec->common.data_addr); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", *data, address)); end: acpi_ec_leave_burst_mode(ec); - up(&ec->sem); + up(&ec->burst.sem); - if (ec->global_lock) + if (ec->common.global_lock) acpi_release_global_lock(glk); - if(atomic_read(&ec->leaving_burst) == 2){ + if(atomic_read(&ec->burst.leaving_burst) == 2){ ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n")); - while(atomic_read(&ec->pending_gpe)){ + while(atomic_read(&ec->burst.pending_gpe)){ msleep(1); } - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); goto retry; } @@ -283,8 +517,8 @@ end: static int -acpi_ec_write ( - struct acpi_ec *ec, +acpi_ec_burst_write ( + union acpi_ec *ec, u8 address, u8 data) { @@ -297,14 +531,14 @@ acpi_ec_write ( if (!ec) return_VALUE(-EINVAL); retry: - if (ec->global_lock) { + if (ec->common.global_lock) { status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); if (ACPI_FAILURE(status)) return_VALUE(-ENODEV); } WARN_ON(in_interrupt()); - down(&ec->sem); + down(&ec->burst.sem); if(acpi_ec_enter_burst_mode(ec)) goto end; @@ -312,33 +546,33 @@ retry: status = acpi_ec_read_status(ec); if (status != -EINVAL && !(status & ACPI_EC_FLAG_BURST)){ - acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->command_addr); + acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->common.command_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); if (status) goto end; - acpi_hw_low_level_read(8, &tmp, &ec->data_addr); + acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr); if(tmp != 0x90 ) /* Burst ACK byte*/ goto end; } /*Now we are in burst mode*/ - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->command_addr); + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->common.command_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); if (status){ goto end; } - acpi_hw_low_level_write(8, address, &ec->data_addr); + acpi_hw_low_level_write(8, address, &ec->common.data_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); if (status){ - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); goto end; } - acpi_hw_low_level_write(8, data, &ec->data_addr); + acpi_hw_low_level_write(8, data, &ec->common.data_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); if (status) goto end; @@ -347,17 +581,17 @@ retry: end: acpi_ec_leave_burst_mode(ec); - up(&ec->sem); + up(&ec->burst.sem); - if (ec->global_lock) + if (ec->common.global_lock) acpi_release_global_lock(glk); - if(atomic_read(&ec->leaving_burst) == 2){ + if(atomic_read(&ec->burst.leaving_burst) == 2){ ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n")); - while(atomic_read(&ec->pending_gpe)){ + while(atomic_read(&ec->burst.pending_gpe)){ msleep(1); } - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); goto retry; } @@ -370,7 +604,7 @@ end: int ec_read(u8 addr, u8 *val) { - struct acpi_ec *ec; + union acpi_ec *ec; int err; u32 temp_data; @@ -393,7 +627,7 @@ EXPORT_SYMBOL(ec_read); int ec_write(u8 addr, u8 val) { - struct acpi_ec *ec; + union acpi_ec *ec; int err; if (!first_ec) @@ -407,10 +641,66 @@ ec_write(u8 addr, u8 val) } EXPORT_SYMBOL(ec_write); - static int acpi_ec_query ( - struct acpi_ec *ec, + union acpi_ec *ec, + u32 *data) +{ + if (acpi_ec_polling_mode) + return acpi_ec_polling_query(ec, data); + else + return acpi_ec_burst_query(ec, data); +} +static int +acpi_ec_polling_query ( + union acpi_ec *ec, + u32 *data) +{ + int result = 0; + acpi_status status = AE_OK; + unsigned long flags = 0; + u32 glk = 0; + + ACPI_FUNCTION_TRACE("acpi_ec_query"); + + if (!ec || !data) + return_VALUE(-EINVAL); + + *data = 0; + + if (ec->common.global_lock) { + status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + } + + /* + * Query the EC to find out which _Qxx method we need to evaluate. + * Note that successful completion of the query causes the ACPI_EC_SCI + * bit to be cleared (and thus clearing the interrupt source). + */ + spin_lock_irqsave(&ec->polling.lock, flags); + + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->common.command_addr); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); + if (result) + goto end; + + acpi_hw_low_level_read(8, data, &ec->common.data_addr); + if (!*data) + result = -ENODATA; + +end: + spin_unlock_irqrestore(&ec->polling.lock, flags); + + if (ec->common.global_lock) + acpi_release_global_lock(glk); + + return_VALUE(result); +} +static int +acpi_ec_burst_query ( + union acpi_ec *ec, u32 *data) { int status = 0; @@ -422,13 +712,13 @@ acpi_ec_query ( return_VALUE(-EINVAL); *data = 0; - if (ec->global_lock) { + if (ec->common.global_lock) { status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); if (ACPI_FAILURE(status)) return_VALUE(-ENODEV); } - down(&ec->sem); + down(&ec->burst.sem); if(acpi_ec_enter_burst_mode(ec)) goto end; /* @@ -436,28 +726,28 @@ acpi_ec_query ( * Note that successful completion of the query causes the ACPI_EC_SCI * bit to be cleared (and thus clearing the interrupt source). */ - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->command_addr); + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->common.command_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); if (status){ - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); goto end; } - acpi_hw_low_level_read(8, data, &ec->data_addr); - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_hw_low_level_read(8, data, &ec->common.data_addr); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); if (!*data) status = -ENODATA; end: acpi_ec_leave_burst_mode(ec); - up(&ec->sem); + up(&ec->burst.sem); - if (ec->global_lock) + if (ec->common.global_lock) acpi_release_global_lock(glk); - if(atomic_read(&ec->leaving_burst) == 2){ + if(atomic_read(&ec->burst.leaving_burst) == 2){ ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n")); - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); status = -ENODATA; } return_VALUE(status); @@ -468,7 +758,7 @@ end: Event Management -------------------------------------------------------------------------- */ -struct acpi_ec_query_data { +union acpi_ec_query_data { acpi_handle handle; u8 data; }; @@ -477,7 +767,59 @@ static void acpi_ec_gpe_query ( void *ec_cxt) { - struct acpi_ec *ec = (struct acpi_ec *) ec_cxt; + if (acpi_ec_polling_mode) + acpi_ec_gpe_polling_query(ec_cxt); + else + acpi_ec_gpe_burst_query(ec_cxt); +} + +static void +acpi_ec_gpe_polling_query ( + void *ec_cxt) +{ + union acpi_ec *ec = (union acpi_ec *) ec_cxt; + u32 value = 0; + unsigned long flags = 0; + static char object_name[5] = {'_','Q','0','0','\0'}; + const char hex[] = {'0','1','2','3','4','5','6','7', + '8','9','A','B','C','D','E','F'}; + + ACPI_FUNCTION_TRACE("acpi_ec_gpe_query"); + + if (!ec_cxt) + goto end; + + spin_lock_irqsave(&ec->polling.lock, flags); + acpi_hw_low_level_read(8, &value, &ec->common.command_addr); + spin_unlock_irqrestore(&ec->polling.lock, flags); + + /* TBD: Implement asynch events! + * NOTE: All we care about are EC-SCI's. Other EC events are + * handled via polling (yuck!). This is because some systems + * treat EC-SCIs as level (versus EDGE!) triggered, preventing + * a purely interrupt-driven approach (grumble, grumble). + */ + if (!(value & ACPI_EC_FLAG_SCI)) + goto end; + + if (acpi_ec_query(ec, &value)) + goto end; + + object_name[2] = hex[((value >> 4) & 0x0F)]; + object_name[3] = hex[(value & 0x0F)]; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name)); + + acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL); + +end: + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); +} +static void +acpi_ec_gpe_burst_query ( + void *ec_cxt) +{ + union acpi_ec *ec = (union acpi_ec *) ec_cxt; u32 value; int result = -ENODATA; static char object_name[5] = {'_','Q','0','0','\0'}; @@ -497,9 +839,9 @@ acpi_ec_gpe_query ( ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name)); - acpi_evaluate_object(ec->handle, object_name, NULL, NULL); + acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL); end: - atomic_dec(&ec->pending_gpe); + atomic_dec(&ec->burst.pending_gpe); return; } @@ -507,48 +849,77 @@ static u32 acpi_ec_gpe_handler ( void *data) { + if (acpi_ec_polling_mode) + return acpi_ec_gpe_polling_handler(data); + else + return acpi_ec_gpe_burst_handler(data); +} +static u32 +acpi_ec_gpe_polling_handler ( + void *data) +{ + acpi_status status = AE_OK; + union acpi_ec *ec = (union acpi_ec *) data; + + if (!ec) + return ACPI_INTERRUPT_NOT_HANDLED; + + acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); + + status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, + acpi_ec_gpe_query, ec); + + if (status == AE_OK) + return ACPI_INTERRUPT_HANDLED; + else + return ACPI_INTERRUPT_NOT_HANDLED; +} +static u32 +acpi_ec_gpe_burst_handler ( + void *data) +{ acpi_status status = AE_OK; u32 value; - struct acpi_ec *ec = (struct acpi_ec *) data; + union acpi_ec *ec = (union acpi_ec *) data; if (!ec) return ACPI_INTERRUPT_NOT_HANDLED; - acpi_disable_gpe(NULL, ec->gpe_bit, ACPI_ISR); + acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); value = acpi_ec_read_status(ec); if((value & ACPI_EC_FLAG_IBF) && !(value & ACPI_EC_FLAG_BURST) && - (atomic_read(&ec->leaving_burst) == 0)) { + (atomic_read(&ec->burst.leaving_burst) == 0)) { /* * the embedded controller disables * burst mode for any reason other * than the burst disable command * to process critical event. */ - atomic_set(&ec->leaving_burst , 2); /* block current pending transaction + atomic_set(&ec->burst.leaving_burst , 2); /* block current pending transaction and retry */ - wake_up(&ec->wait); + wake_up(&ec->burst.wait); }else { - if ((ec->expect_event == ACPI_EC_EVENT_OBF && + if ((ec->burst.expect_event == ACPI_EC_EVENT_OBF && (value & ACPI_EC_FLAG_OBF)) || - (ec->expect_event == ACPI_EC_EVENT_IBE && + (ec->burst.expect_event == ACPI_EC_EVENT_IBE && !(value & ACPI_EC_FLAG_IBF))) { - ec->expect_event = 0; - wake_up(&ec->wait); + ec->burst.expect_event = 0; + wake_up(&ec->burst.wait); return ACPI_INTERRUPT_HANDLED; } } if (value & ACPI_EC_FLAG_SCI){ - atomic_add(1, &ec->pending_gpe) ; + atomic_add(1, &ec->burst.pending_gpe) ; status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, acpi_ec_gpe_query, ec); return status == AE_OK ? ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; } - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); return status == AE_OK ? ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; } @@ -585,7 +956,7 @@ acpi_ec_space_handler ( void *region_context) { int result = 0; - struct acpi_ec *ec = NULL; + union acpi_ec *ec = NULL; u64 temp = *value; acpi_integer f_v = 0; int i = 0; @@ -600,7 +971,7 @@ acpi_ec_space_handler ( return_VALUE(AE_BAD_PARAMETER); } - ec = (struct acpi_ec *) handler_context; + ec = (union acpi_ec *) handler_context; next_byte: switch (function) { @@ -661,7 +1032,7 @@ static struct proc_dir_entry *acpi_ec_dir; static int acpi_ec_read_info (struct seq_file *seq, void *offset) { - struct acpi_ec *ec = (struct acpi_ec *) seq->private; + union acpi_ec *ec = (union acpi_ec *) seq->private; ACPI_FUNCTION_TRACE("acpi_ec_read_info"); @@ -669,12 +1040,12 @@ acpi_ec_read_info (struct seq_file *seq, void *offset) goto end; seq_printf(seq, "gpe bit: 0x%02x\n", - (u32) ec->gpe_bit); + (u32) ec->common.gpe_bit); seq_printf(seq, "ports: 0x%02x, 0x%02x\n", - (u32) ec->status_addr.address, (u32) ec->data_addr.address); + (u32) ec->common.status_addr.address, (u32) ec->common.data_addr.address); seq_printf(seq, "use global lock: %s\n", - ec->global_lock?"yes":"no"); - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + ec->common.global_lock?"yes":"no"); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); end: return_VALUE(0); @@ -697,7 +1068,7 @@ static int acpi_ec_add_fs ( struct acpi_device *device) { - struct proc_dir_entry *entry; + struct proc_dir_entry *entry = NULL; ACPI_FUNCTION_TRACE("acpi_ec_add_fs"); @@ -744,13 +1115,14 @@ acpi_ec_remove_fs ( Driver Interface -------------------------------------------------------------------------- */ + static int -acpi_ec_add ( +acpi_ec_polling_add ( struct acpi_device *device) { - int result; - acpi_status status; - struct acpi_ec *ec; + int result = 0; + acpi_status status = AE_OK; + union acpi_ec *ec = NULL; unsigned long uid; ACPI_FUNCTION_TRACE("acpi_ec_add"); @@ -758,39 +1130,107 @@ acpi_ec_add ( if (!device) return_VALUE(-EINVAL); - ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); + ec = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); if (!ec) return_VALUE(-ENOMEM); - memset(ec, 0, sizeof(struct acpi_ec)); - - ec->handle = device->handle; - ec->uid = -1; - atomic_set(&ec->pending_gpe, 0); - atomic_set(&ec->leaving_burst , 1); - init_MUTEX(&ec->sem); - init_waitqueue_head(&ec->wait); + memset(ec, 0, sizeof(union acpi_ec)); + + ec->common.handle = device->handle; + ec->common.uid = -1; + spin_lock_init(&ec->polling.lock); strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_EC_CLASS); acpi_driver_data(device) = ec; /* Use the global lock for all EC transactions? */ - acpi_evaluate_integer(ec->handle, "_GLK", NULL, &ec->global_lock); + acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, &ec->common.global_lock); /* If our UID matches the UID for the ECDT-enumerated EC, we now have the *real* EC info, so kill the makeshift one.*/ - acpi_evaluate_integer(ec->handle, "_UID", NULL, &uid); - if (ec_ecdt && ec_ecdt->uid == uid) { + acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid); + if (ec_ecdt && ec_ecdt->common.uid == uid) { acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); + + acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, &acpi_ec_gpe_handler); + + kfree(ec_ecdt); + } + + /* Get GPE bit assignment (EC events). */ + /* TODO: Add support for _GPE returning a package */ + status = acpi_evaluate_integer(ec->common.handle, "_GPE", NULL, &ec->common.gpe_bit); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error obtaining GPE bit assignment\n")); + result = -ENODEV; + goto end; + } - acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit, &acpi_ec_gpe_handler); + result = acpi_ec_add_fs(device); + if (result) + goto end; + + printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n", + acpi_device_name(device), acpi_device_bid(device), + (u32) ec->common.gpe_bit); + + if (!first_ec) + first_ec = device; + +end: + if (result) + kfree(ec); + + return_VALUE(result); +} +static int +acpi_ec_burst_add ( + struct acpi_device *device) +{ + int result = 0; + acpi_status status = AE_OK; + union acpi_ec *ec = NULL; + unsigned long uid; + + ACPI_FUNCTION_TRACE("acpi_ec_add"); + + if (!device) + return_VALUE(-EINVAL); + + ec = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); + if (!ec) + return_VALUE(-ENOMEM); + memset(ec, 0, sizeof(union acpi_ec)); + + ec->common.handle = device->handle; + ec->common.uid = -1; + atomic_set(&ec->burst.pending_gpe, 0); + atomic_set(&ec->burst.leaving_burst , 1); + init_MUTEX(&ec->burst.sem); + init_waitqueue_head(&ec->burst.wait); + strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); + strcpy(acpi_device_class(device), ACPI_EC_CLASS); + acpi_driver_data(device) = ec; + + /* Use the global lock for all EC transactions? */ + acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, &ec->common.global_lock); + + /* If our UID matches the UID for the ECDT-enumerated EC, + we now have the *real* EC info, so kill the makeshift one.*/ + acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid); + if (ec_ecdt && ec_ecdt->common.uid == uid) { + acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, + ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); + + acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, &acpi_ec_gpe_handler); kfree(ec_ecdt); } /* Get GPE bit assignment (EC events). */ /* TODO: Add support for _GPE returning a package */ - status = acpi_evaluate_integer(ec->handle, "_GPE", NULL, &ec->gpe_bit); + status = acpi_evaluate_integer(ec->common.handle, "_GPE", NULL, &ec->common.gpe_bit); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error obtaining GPE bit assignment\n")); @@ -804,7 +1244,7 @@ acpi_ec_add ( printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n", acpi_device_name(device), acpi_device_bid(device), - (u32) ec->gpe_bit); + (u32) ec->common.gpe_bit); if (!first_ec) first_ec = device; @@ -822,7 +1262,7 @@ acpi_ec_remove ( struct acpi_device *device, int type) { - struct acpi_ec *ec; + union acpi_ec *ec = NULL; ACPI_FUNCTION_TRACE("acpi_ec_remove"); @@ -844,7 +1284,7 @@ acpi_ec_io_ports ( struct acpi_resource *resource, void *context) { - struct acpi_ec *ec = (struct acpi_ec *) context; + union acpi_ec *ec = (union acpi_ec *) context; struct acpi_generic_address *addr; if (resource->id != ACPI_RSTYPE_IO) { @@ -856,10 +1296,10 @@ acpi_ec_io_ports ( * the second address region returned is the status/command * port. */ - if (ec->data_addr.register_bit_width == 0) { - addr = &ec->data_addr; - } else if (ec->command_addr.register_bit_width == 0) { - addr = &ec->command_addr; + if (ec->common.data_addr.register_bit_width == 0) { + addr = &ec->common.data_addr; + } else if (ec->common.command_addr.register_bit_width == 0) { + addr = &ec->common.command_addr; } else { return AE_CTRL_TERMINATE; } @@ -877,8 +1317,8 @@ static int acpi_ec_start ( struct acpi_device *device) { - acpi_status status; - struct acpi_ec *ec; + acpi_status status = AE_OK; + union acpi_ec *ec = NULL; ACPI_FUNCTION_TRACE("acpi_ec_start"); @@ -893,35 +1333,36 @@ acpi_ec_start ( /* * Get I/O port addresses. Convert to GAS format. */ - status = acpi_walk_resources(ec->handle, METHOD_NAME__CRS, + status = acpi_walk_resources(ec->common.handle, METHOD_NAME__CRS, acpi_ec_io_ports, ec); - if (ACPI_FAILURE(status) || ec->command_addr.register_bit_width == 0) { + if (ACPI_FAILURE(status) || ec->common.command_addr.register_bit_width == 0) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error getting I/O port addresses")); return_VALUE(-ENODEV); } - ec->status_addr = ec->command_addr; + ec->common.status_addr = ec->common.command_addr; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02x, ports=0x%2x,0x%2x\n", - (u32) ec->gpe_bit, (u32) ec->command_addr.address, - (u32) ec->data_addr.address)); + (u32) ec->common.gpe_bit, (u32) ec->common.command_addr.address, + (u32) ec->common.data_addr.address)); + /* * Install GPE handler */ - status = acpi_install_gpe_handler(NULL, ec->gpe_bit, + status = acpi_install_gpe_handler(NULL, ec->common.gpe_bit, ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler, ec); if (ACPI_FAILURE(status)) { return_VALUE(-ENODEV); } - acpi_set_gpe_type (NULL, ec->gpe_bit, ACPI_GPE_TYPE_RUNTIME); - acpi_enable_gpe (NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_set_gpe_type (NULL, ec->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME); + acpi_enable_gpe (NULL, ec->common.gpe_bit, ACPI_NOT_ISR); - status = acpi_install_address_space_handler (ec->handle, + status = acpi_install_address_space_handler (ec->common.handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, &acpi_ec_space_setup, ec); if (ACPI_FAILURE(status)) { - acpi_remove_gpe_handler(NULL, ec->gpe_bit, &acpi_ec_gpe_handler); + acpi_remove_gpe_handler(NULL, ec->common.gpe_bit, &acpi_ec_gpe_handler); return_VALUE(-ENODEV); } @@ -934,8 +1375,8 @@ acpi_ec_stop ( struct acpi_device *device, int type) { - acpi_status status; - struct acpi_ec *ec; + acpi_status status = AE_OK; + union acpi_ec *ec = NULL; ACPI_FUNCTION_TRACE("acpi_ec_stop"); @@ -944,12 +1385,12 @@ acpi_ec_stop ( ec = acpi_driver_data(device); - status = acpi_remove_address_space_handler(ec->handle, + status = acpi_remove_address_space_handler(ec->common.handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); if (ACPI_FAILURE(status)) return_VALUE(-ENODEV); - status = acpi_remove_gpe_handler(NULL, ec->gpe_bit, &acpi_ec_gpe_handler); + status = acpi_remove_gpe_handler(NULL, ec->common.gpe_bit, &acpi_ec_gpe_handler); if (ACPI_FAILURE(status)) return_VALUE(-ENODEV); @@ -963,26 +1404,76 @@ acpi_fake_ecdt_callback ( void *context, void **retval) { + + if (acpi_ec_polling_mode) + return acpi_fake_ecdt_polling_callback(handle, + Level, context, retval); + else + return acpi_fake_ecdt_burst_callback(handle, + Level, context, retval); +} + +static acpi_status __init +acpi_fake_ecdt_polling_callback ( + acpi_handle handle, + u32 Level, + void *context, + void **retval) +{ acpi_status status; status = acpi_walk_resources(handle, METHOD_NAME__CRS, acpi_ec_io_ports, ec_ecdt); if (ACPI_FAILURE(status)) return status; - ec_ecdt->status_addr = ec_ecdt->command_addr; + ec_ecdt->common.status_addr = ec_ecdt->common.command_addr; - ec_ecdt->uid = -1; - acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->uid); + ec_ecdt->common.uid = -1; + acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->common.uid); - status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->gpe_bit); + status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->common.gpe_bit); if (ACPI_FAILURE(status)) return status; - ec_ecdt->global_lock = TRUE; - ec_ecdt->handle = handle; + spin_lock_init(&ec_ecdt->polling.lock); + ec_ecdt->common.global_lock = TRUE; + ec_ecdt->common.handle = handle; printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n", - (u32) ec_ecdt->gpe_bit, (u32) ec_ecdt->command_addr.address, - (u32) ec_ecdt->data_addr.address); + (u32) ec_ecdt->common.gpe_bit, (u32) ec_ecdt->common.command_addr.address, + (u32) ec_ecdt->common.data_addr.address); + + return AE_CTRL_TERMINATE; +} + +static acpi_status __init +acpi_fake_ecdt_burst_callback ( + acpi_handle handle, + u32 Level, + void *context, + void **retval) +{ + acpi_status status; + + init_MUTEX(&ec_ecdt->burst.sem); + init_waitqueue_head(&ec_ecdt->burst.wait); + status = acpi_walk_resources(handle, METHOD_NAME__CRS, + acpi_ec_io_ports, ec_ecdt); + if (ACPI_FAILURE(status)) + return status; + ec_ecdt->common.status_addr = ec_ecdt->common.command_addr; + + ec_ecdt->common.uid = -1; + acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->common.uid); + + status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->common.gpe_bit); + if (ACPI_FAILURE(status)) + return status; + ec_ecdt->common.global_lock = TRUE; + ec_ecdt->common.handle = handle; + + printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n", + (u32) ec_ecdt->common.gpe_bit, (u32) ec_ecdt->common.command_addr.address, + (u32) ec_ecdt->common.data_addr.address); return AE_CTRL_TERMINATE; } @@ -1005,12 +1496,12 @@ acpi_ec_fake_ecdt(void) printk(KERN_INFO PREFIX "Try to make an fake ECDT\n"); - ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); + ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); if (!ec_ecdt) { ret = -ENOMEM; goto error; } - memset(ec_ecdt, 0, sizeof(struct acpi_ec)); + memset(ec_ecdt, 0, sizeof(union acpi_ec)); status = acpi_get_devices (ACPI_EC_HID, acpi_fake_ecdt_callback, @@ -1031,6 +1522,60 @@ error: static int __init acpi_ec_get_real_ecdt(void) { + if (acpi_ec_polling_mode) + return acpi_ec_polling_get_real_ecdt(); + else + return acpi_ec_burst_get_real_ecdt(); +} + +static int __init +acpi_ec_polling_get_real_ecdt(void) +{ + acpi_status status; + struct acpi_table_ecdt *ecdt_ptr; + + status = acpi_get_firmware_table("ECDT", 1, ACPI_LOGICAL_ADDRESSING, + (struct acpi_table_header **) &ecdt_ptr); + if (ACPI_FAILURE(status)) + return -ENODEV; + + printk(KERN_INFO PREFIX "Found ECDT\n"); + + /* + * Generate a temporary ec context to use until the namespace is scanned + */ + ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); + if (!ec_ecdt) + return -ENOMEM; + memset(ec_ecdt, 0, sizeof(union acpi_ec)); + + ec_ecdt->common.command_addr = ecdt_ptr->ec_control; + ec_ecdt->common.status_addr = ecdt_ptr->ec_control; + ec_ecdt->common.data_addr = ecdt_ptr->ec_data; + ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit; + spin_lock_init(&ec_ecdt->polling.lock); + /* use the GL just to be safe */ + ec_ecdt->common.global_lock = TRUE; + ec_ecdt->common.uid = ecdt_ptr->uid; + + status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle); + if (ACPI_FAILURE(status)) { + goto error; + } + + return 0; +error: + printk(KERN_ERR PREFIX "Could not use ECDT\n"); + kfree(ec_ecdt); + ec_ecdt = NULL; + + return -ENODEV; +} + + +static int __init +acpi_ec_burst_get_real_ecdt(void) +{ acpi_status status; struct acpi_table_ecdt *ecdt_ptr; @@ -1044,22 +1589,22 @@ acpi_ec_get_real_ecdt(void) /* * Generate a temporary ec context to use until the namespace is scanned */ - ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); + ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); if (!ec_ecdt) return -ENOMEM; - memset(ec_ecdt, 0, sizeof(struct acpi_ec)); - - init_MUTEX(&ec_ecdt->sem); - init_waitqueue_head(&ec_ecdt->wait); - ec_ecdt->command_addr = ecdt_ptr->ec_control; - ec_ecdt->status_addr = ecdt_ptr->ec_control; - ec_ecdt->data_addr = ecdt_ptr->ec_data; - ec_ecdt->gpe_bit = ecdt_ptr->gpe_bit; + memset(ec_ecdt, 0, sizeof(union acpi_ec)); + + init_MUTEX(&ec_ecdt->burst.sem); + init_waitqueue_head(&ec_ecdt->burst.wait); + ec_ecdt->common.command_addr = ecdt_ptr->ec_control; + ec_ecdt->common.status_addr = ecdt_ptr->ec_control; + ec_ecdt->common.data_addr = ecdt_ptr->ec_data; + ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit; /* use the GL just to be safe */ - ec_ecdt->global_lock = TRUE; - ec_ecdt->uid = ecdt_ptr->uid; + ec_ecdt->common.global_lock = TRUE; + ec_ecdt->common.uid = ecdt_ptr->uid; - status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->handle); + status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle); if (ACPI_FAILURE(status)) { goto error; } @@ -1092,20 +1637,20 @@ acpi_ec_ecdt_probe (void) /* * Install GPE handler */ - status = acpi_install_gpe_handler(NULL, ec_ecdt->gpe_bit, + status = acpi_install_gpe_handler(NULL, ec_ecdt->common.gpe_bit, ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler, ec_ecdt); if (ACPI_FAILURE(status)) { goto error; } - acpi_set_gpe_type (NULL, ec_ecdt->gpe_bit, ACPI_GPE_TYPE_RUNTIME); - acpi_enable_gpe (NULL, ec_ecdt->gpe_bit, ACPI_NOT_ISR); + acpi_set_gpe_type (NULL, ec_ecdt->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME); + acpi_enable_gpe (NULL, ec_ecdt->common.gpe_bit, ACPI_NOT_ISR); status = acpi_install_address_space_handler (ACPI_ROOT_OBJECT, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, &acpi_ec_space_setup, ec_ecdt); if (ACPI_FAILURE(status)) { - acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit, + acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, &acpi_ec_gpe_handler); goto error; } @@ -1123,7 +1668,7 @@ error: static int __init acpi_ec_init (void) { - int result; + int result = 0; ACPI_FUNCTION_TRACE("acpi_ec_init"); @@ -1166,4 +1711,24 @@ static int __init acpi_fake_ecdt_setup(char *str) acpi_fake_ecdt_enabled = 1; return 0; } + __setup("acpi_fake_ecdt", acpi_fake_ecdt_setup); +static int __init acpi_ec_set_polling_mode(char *str) +{ + int burst; + + if (!get_option(&str, &burst)) + return 0; + + if (burst) { + acpi_ec_polling_mode = EC_BURST; + acpi_ec_driver.ops.add = acpi_ec_burst_add; + } else { + acpi_ec_polling_mode = EC_POLLING; + acpi_ec_driver.ops.add = acpi_ec_polling_add; + } + printk(KERN_INFO PREFIX "EC %s mode.\n", + burst ? "burst": "polling"); + return 0; +} +__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 @@ -/* - * hotkey.c - ACPI Hotkey Driver ($Revision:$) +/* + * hotkey.c - ACPI Hotkey Driver ($Revision: 0.2 $) * * Copyright (C) 2004 Luming Yu <luming.yu@intel.com> * @@ -51,17 +51,18 @@ #define ACPI_HOTKEY_POLLING 0x2 #define ACPI_UNDEFINED_EVENT 0xf -#define MAX_CONFIG_RECORD_LEN 80 -#define MAX_NAME_PATH_LEN 80 -#define MAX_CALL_PARM 80 +#define RESULT_STR_LEN 80 -#define IS_EVENT(e) 0xff /* ((e) & 0x40000000) */ -#define IS_POLL(e) 0xff /* (~((e) & 0x40000000)) */ +#define ACTION_METHOD 0 +#define POLL_METHOD 1 +#define IS_EVENT(e) ((e) <= 10000 && (e) >0) +#define IS_POLL(e) ((e) > 10000) +#define IS_OTHERS(e) ((e)<=0 || (e)>=20000) #define _COMPONENT ACPI_HOTKEY_COMPONENT ACPI_MODULE_NAME("acpi_hotkey") - MODULE_AUTHOR("luming.yu@intel.com"); +MODULE_AUTHOR("luming.yu@intel.com"); MODULE_DESCRIPTION(ACPI_HOTK_NAME); MODULE_LICENSE("GPL"); @@ -114,7 +115,7 @@ struct acpi_event_hotkey { char *action_method; /* action method */ }; -/* +/* * There are two ways to poll status * 1. directy call read_xxx method, without any arguments passed in * 2. call write_xxx method, with arguments passed in, you need @@ -131,7 +132,7 @@ struct acpi_polling_hotkey { char *poll_method; /* poll method */ acpi_handle action_handle; /* acpi handle attached action method */ char *action_method; /* action method */ - void *poll_result; /* polling_result */ + union acpi_object *poll_result; /* polling_result */ struct proc_dir_entry *proc; }; @@ -162,20 +163,25 @@ static struct acpi_driver hotkey_driver = { }, }; +static void free_hotkey_device(union acpi_hotkey *key); +static void free_hotkey_buffer(union acpi_hotkey *key); +static void free_poll_hotkey_buffer(union acpi_hotkey *key); static int hotkey_open_config(struct inode *inode, struct file *file); +static int hotkey_poll_open_config(struct inode *inode, struct file *file); static ssize_t hotkey_write_config(struct file *file, const char __user * buffer, size_t count, loff_t * data); -static ssize_t hotkey_write_poll_config(struct file *file, - const char __user * buffer, - size_t count, loff_t * data); static int hotkey_info_open_fs(struct inode *inode, struct file *file); static int hotkey_action_open_fs(struct inode *inode, struct file *file); static ssize_t hotkey_execute_aml_method(struct file *file, const char __user * buffer, size_t count, loff_t * data); static int hotkey_config_seq_show(struct seq_file *seq, void *offset); +static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset); static int hotkey_polling_open_fs(struct inode *inode, struct file *file); +static union acpi_hotkey *get_hotkey_by_event(struct + acpi_hotkey_list + *hotkey_list, int event); /* event based config */ static struct file_operations hotkey_config_fops = { @@ -188,9 +194,9 @@ static struct file_operations hotkey_config_fops = { /* polling based config */ static struct file_operations hotkey_poll_config_fops = { - .open = hotkey_open_config, + .open = hotkey_poll_open_config, .read = seq_read, - .write = hotkey_write_poll_config, + .write = hotkey_write_config, .llseek = seq_lseek, .release = single_release, }; @@ -227,7 +233,7 @@ static int hotkey_info_seq_show(struct seq_file *seq, void *offset) { ACPI_FUNCTION_TRACE("hotkey_info_seq_show"); - seq_printf(seq, "Hotkey generic driver ver: %s", HOTKEY_ACPI_VERSION); + seq_printf(seq, "Hotkey generic driver ver: %s\n", HOTKEY_ACPI_VERSION); return_VALUE(0); } @@ -239,27 +245,35 @@ static int hotkey_info_open_fs(struct inode *inode, struct file *file) static char *format_result(union acpi_object *object) { - char *buf = (char *)kmalloc(sizeof(union acpi_object), GFP_KERNEL); - - memset(buf, 0, sizeof(union acpi_object)); + char *buf = NULL; + + buf = (char *)kmalloc(RESULT_STR_LEN, GFP_KERNEL); + if (buf) + memset(buf, 0, RESULT_STR_LEN); + else + goto do_fail; /* Now, just support integer type */ if (object->type == ACPI_TYPE_INTEGER) - sprintf(buf, "%d", (u32) object->integer.value); - - return buf; + sprintf(buf, "%d\n", (u32) object->integer.value); +do_fail: + return (buf); } static int hotkey_polling_seq_show(struct seq_file *seq, void *offset) { struct acpi_polling_hotkey *poll_hotkey = (struct acpi_polling_hotkey *)seq->private; + char *buf; ACPI_FUNCTION_TRACE("hotkey_polling_seq_show"); - if (poll_hotkey->poll_result) - seq_printf(seq, "%s", format_result(poll_hotkey->poll_result)); - + if (poll_hotkey->poll_result){ + buf = format_result(poll_hotkey->poll_result); + if(buf) + seq_printf(seq, "%s", buf); + kfree(buf); + } return_VALUE(0); } @@ -276,19 +290,19 @@ static int hotkey_action_open_fs(struct inode *inode, struct file *file) /* Mapping external hotkey number to standardized hotkey event num */ static int hotkey_get_internal_event(int event, struct acpi_hotkey_list *list) { - struct list_head *entries, *next; - int val = 0; + struct list_head *entries; + int val = -1; ACPI_FUNCTION_TRACE("hotkey_get_internal_event"); - list_for_each_safe(entries, next, list->entries) { + list_for_each(entries, list->entries) { union acpi_hotkey *key = container_of(entries, union acpi_hotkey, entries); if (key->link.hotkey_type == ACPI_HOTKEY_EVENT - && key->event_hotkey.external_hotkey_num == event) + && key->event_hotkey.external_hotkey_num == event){ val = key->link.hotkey_standard_num; - else - val = -1; + break; + } } return_VALUE(val); @@ -306,7 +320,7 @@ acpi_hotkey_notify_handler(acpi_handle handle, u32 event, void *data) return_VOID; internal_event = hotkey_get_internal_event(event, &global_hotkey_list); - acpi_bus_generate_event(device, event, 0); + acpi_bus_generate_event(device, internal_event, 0); return_VOID; } @@ -329,13 +343,17 @@ static int auto_hotkey_remove(struct acpi_device *device, int type) static int create_polling_proc(union acpi_hotkey *device) { struct proc_dir_entry *proc; + char proc_name[80]; mode_t mode; ACPI_FUNCTION_TRACE("create_polling_proc"); mode = S_IFREG | S_IRUGO | S_IWUGO; - proc = create_proc_entry(device->poll_hotkey.action_method, - mode, hotkey_proc_dir); + sprintf(proc_name, "%d", device->link.hotkey_standard_num); + /* + strcat(proc_name, device->poll_hotkey.poll_method); + */ + proc = create_proc_entry(proc_name, mode, hotkey_proc_dir); if (!proc) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, @@ -353,23 +371,6 @@ static int create_polling_proc(union acpi_hotkey *device) return_VALUE(0); } -static int is_valid_acpi_path(const char *pathname) -{ - acpi_handle handle; - acpi_status status; - ACPI_FUNCTION_TRACE("is_valid_acpi_path"); - - status = acpi_get_handle(NULL, (char *)pathname, &handle); - return_VALUE(!ACPI_FAILURE(status)); -} - -static int is_valid_hotkey(union acpi_hotkey *device) -{ - ACPI_FUNCTION_TRACE("is_valid_hotkey"); - /* Implement valid check */ - return_VALUE(1); -} - static int hotkey_add(union acpi_hotkey *device) { int status = 0; @@ -378,15 +379,11 @@ static int hotkey_add(union acpi_hotkey *device) ACPI_FUNCTION_TRACE("hotkey_add"); if (device->link.hotkey_type == ACPI_HOTKEY_EVENT) { - status = - acpi_bus_get_device(device->event_hotkey.bus_handle, &dev); - if (status) - return_VALUE(status); - + acpi_bus_get_device(device->event_hotkey.bus_handle, &dev); status = acpi_install_notify_handler(dev->handle, - ACPI_SYSTEM_NOTIFY, + ACPI_DEVICE_NOTIFY, acpi_hotkey_notify_handler, - device); + dev); } else /* Add polling hotkey */ create_polling_proc(device); @@ -409,84 +406,143 @@ static int hotkey_remove(union acpi_hotkey *device) if (key->link.hotkey_standard_num == device->link.hotkey_standard_num) { list_del(&key->link.entries); - remove_proc_entry(key->poll_hotkey.action_method, - hotkey_proc_dir); + free_hotkey_device(key); global_hotkey_list.count--; break; } } + kfree(device); return_VALUE(0); } -static void hotkey_update(union acpi_hotkey *key) +static int hotkey_update(union acpi_hotkey *key) { - struct list_head *entries, *next; + struct list_head *entries; ACPI_FUNCTION_TRACE("hotkey_update"); - list_for_each_safe(entries, next, global_hotkey_list.entries) { - union acpi_hotkey *key = + list_for_each(entries, global_hotkey_list.entries) { + union acpi_hotkey *tmp= container_of(entries, union acpi_hotkey, entries); - if (key->link.hotkey_standard_num == + if (tmp->link.hotkey_standard_num == key->link.hotkey_standard_num) { - key->event_hotkey.bus_handle = - key->event_hotkey.bus_handle; - key->event_hotkey.external_hotkey_num = - key->event_hotkey.external_hotkey_num; - key->event_hotkey.action_handle = - key->event_hotkey.action_handle; - key->event_hotkey.action_method = - key->event_hotkey.action_method; + if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) { + free_hotkey_buffer(tmp); + tmp->event_hotkey.bus_handle = + key->event_hotkey.bus_handle; + tmp->event_hotkey.external_hotkey_num = + key->event_hotkey.external_hotkey_num; + tmp->event_hotkey.action_handle = + key->event_hotkey.action_handle; + tmp->event_hotkey.action_method = + key->event_hotkey.action_method; + kfree(key); + } else { + /* + char proc_name[80]; + + sprintf(proc_name, "%d", tmp->link.hotkey_standard_num); + strcat(proc_name, tmp->poll_hotkey.poll_method); + remove_proc_entry(proc_name,hotkey_proc_dir); + */ + free_poll_hotkey_buffer(tmp); + tmp->poll_hotkey.poll_handle = + key->poll_hotkey.poll_handle; + tmp->poll_hotkey.poll_method = + key->poll_hotkey.poll_method; + tmp->poll_hotkey.action_handle = + key->poll_hotkey.action_handle; + tmp->poll_hotkey.action_method = + key->poll_hotkey.action_method; + tmp->poll_hotkey.poll_result = + key->poll_hotkey.poll_result; + /* + create_polling_proc(tmp); + */ + kfree(key); + } + return_VALUE(0); break; } } - return_VOID; + return_VALUE(-ENODEV); } static void free_hotkey_device(union acpi_hotkey *key) { struct acpi_device *dev; - int status; ACPI_FUNCTION_TRACE("free_hotkey_device"); if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) { - status = - acpi_bus_get_device(key->event_hotkey.bus_handle, &dev); + acpi_bus_get_device(key->event_hotkey.bus_handle, &dev); if (dev->handle) acpi_remove_notify_handler(dev->handle, - ACPI_SYSTEM_NOTIFY, + ACPI_DEVICE_NOTIFY, acpi_hotkey_notify_handler); - } else - remove_proc_entry(key->poll_hotkey.action_method, - hotkey_proc_dir); + free_hotkey_buffer(key); + } else { + char proc_name[80]; + + sprintf(proc_name, "%d", key->link.hotkey_standard_num); + /* + strcat(proc_name, key->poll_hotkey.poll_method); + */ + remove_proc_entry(proc_name,hotkey_proc_dir); + free_poll_hotkey_buffer(key); + } kfree(key); return_VOID; } +static void +free_hotkey_buffer(union acpi_hotkey *key) +{ + kfree(key->event_hotkey.action_method); +} + +static void +free_poll_hotkey_buffer(union acpi_hotkey *key) +{ + kfree(key->poll_hotkey.action_method); + kfree(key->poll_hotkey.poll_method); + kfree(key->poll_hotkey.poll_result); +} static int init_hotkey_device(union acpi_hotkey *key, char *bus_str, char *action_str, char *method, int std_num, int external_num) { + acpi_handle tmp_handle; + acpi_status status = AE_OK; + ACPI_FUNCTION_TRACE("init_hotkey_device"); + if(std_num < 0 || IS_POLL(std_num) || !key ) + goto do_fail; + + if(!bus_str || !action_str || !method) + goto do_fail; + key->link.hotkey_type = ACPI_HOTKEY_EVENT; key->link.hotkey_standard_num = std_num; key->event_hotkey.flag = 0; - if (is_valid_acpi_path(bus_str)) - acpi_get_handle((acpi_handle) 0, - bus_str, &(key->event_hotkey.bus_handle)); - else - return_VALUE(-ENODEV); - key->event_hotkey.external_hotkey_num = external_num; - if (is_valid_acpi_path(action_str)) - acpi_get_handle((acpi_handle) 0, - action_str, &(key->event_hotkey.action_handle)); - key->event_hotkey.action_method = kmalloc(sizeof(method), GFP_KERNEL); - strcpy(key->event_hotkey.action_method, method); + key->event_hotkey.action_method = method; - return_VALUE(!is_valid_hotkey(key)); + status = acpi_get_handle(NULL,bus_str, &(key->event_hotkey.bus_handle)); + if(ACPI_FAILURE(status)) + goto do_fail; + key->event_hotkey.external_hotkey_num = external_num; + status = acpi_get_handle(NULL,action_str, &(key->event_hotkey.action_handle)); + if(ACPI_FAILURE(status)) + goto do_fail; + status = acpi_get_handle(key->event_hotkey.action_handle, + method, &tmp_handle); + if (ACPI_FAILURE(status)) + goto do_fail; + return_VALUE(AE_OK); +do_fail: + return_VALUE(-ENODEV); } static int @@ -495,34 +551,46 @@ init_poll_hotkey_device(union acpi_hotkey *key, char *poll_method, char *action_str, char *action_method, int std_num) { + acpi_status status = AE_OK; + acpi_handle tmp_handle; + ACPI_FUNCTION_TRACE("init_poll_hotkey_device"); + if(std_num < 0 || IS_EVENT(std_num) || !key) + goto do_fail; + + if(!poll_str || !poll_method || !action_str || !action_method) + goto do_fail; + key->link.hotkey_type = ACPI_HOTKEY_POLLING; key->link.hotkey_standard_num = std_num; key->poll_hotkey.flag = 0; - if (is_valid_acpi_path(poll_str)) - acpi_get_handle((acpi_handle) 0, - poll_str, &(key->poll_hotkey.poll_handle)); - else - return_VALUE(-ENODEV); key->poll_hotkey.poll_method = poll_method; - if (is_valid_acpi_path(action_str)) - acpi_get_handle((acpi_handle) 0, - action_str, &(key->poll_hotkey.action_handle)); - key->poll_hotkey.action_method = - kmalloc(sizeof(action_method), GFP_KERNEL); - strcpy(key->poll_hotkey.action_method, action_method); + key->poll_hotkey.action_method = action_method; + + status = acpi_get_handle(NULL,poll_str, &(key->poll_hotkey.poll_handle)); + if(ACPI_FAILURE(status)) + goto do_fail; + status = acpi_get_handle(key->poll_hotkey.poll_handle, + poll_method, &tmp_handle); + if (ACPI_FAILURE(status)) + goto do_fail; + status = acpi_get_handle(NULL,action_str, &(key->poll_hotkey.action_handle)); + if (ACPI_FAILURE(status)) + goto do_fail; + status = acpi_get_handle(key->poll_hotkey.action_handle, + action_method, &tmp_handle); + if (ACPI_FAILURE(status)) + goto do_fail; key->poll_hotkey.poll_result = (union acpi_object *)kmalloc(sizeof(union acpi_object), GFP_KERNEL); - return_VALUE(is_valid_hotkey(key)); + if(!key->poll_hotkey.poll_result) + goto do_fail; + return_VALUE(AE_OK); +do_fail: + return_VALUE(-ENODEV); } -static int check_hotkey_valid(union acpi_hotkey *key, - struct acpi_hotkey_list *list) -{ - ACPI_FUNCTION_TRACE("check_hotkey_valid"); - return_VALUE(0); -} static int hotkey_open_config(struct inode *inode, struct file *file) { @@ -531,10 +599,17 @@ static int hotkey_open_config(struct inode *inode, struct file *file) (file, hotkey_config_seq_show, PDE(inode)->data)); } +static int hotkey_poll_open_config(struct inode *inode, struct file *file) +{ + ACPI_FUNCTION_TRACE("hotkey_poll_open_config"); + return_VALUE(single_open + (file, hotkey_poll_config_seq_show, PDE(inode)->data)); +} + static int hotkey_config_seq_show(struct seq_file *seq, void *offset) { struct acpi_hotkey_list *hotkey_list = &global_hotkey_list; - struct list_head *entries, *next; + struct list_head *entries; char bus_name[ACPI_PATHNAME_MAX] = { 0 }; char action_name[ACPI_PATHNAME_MAX] = { 0 }; struct acpi_buffer bus = { ACPI_PATHNAME_MAX, bus_name }; @@ -542,10 +617,7 @@ static int hotkey_config_seq_show(struct seq_file *seq, void *offset) ACPI_FUNCTION_TRACE(("hotkey_config_seq_show")); - if (!hotkey_list) - goto end; - - list_for_each_safe(entries, next, hotkey_list->entries) { + list_for_each(entries, hotkey_list->entries) { union acpi_hotkey *key = container_of(entries, union acpi_hotkey, entries); if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) { @@ -553,18 +625,37 @@ static int hotkey_config_seq_show(struct seq_file *seq, void *offset) ACPI_NAME_TYPE_MAX, &bus); acpi_get_name(key->event_hotkey.action_handle, ACPI_NAME_TYPE_MAX, &act); - seq_printf(seq, "%s:%s:%s:%d:%d", bus_name, + seq_printf(seq, "%s:%s:%s:%d:%d\n", bus_name, action_name, key->event_hotkey.action_method, key->link.hotkey_standard_num, key->event_hotkey.external_hotkey_num); - } /* ACPI_HOTKEY_POLLING */ - else { + } + } + seq_puts(seq, "\n"); + return_VALUE(0); +} + +static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset) +{ + struct acpi_hotkey_list *hotkey_list = &global_hotkey_list; + struct list_head *entries; + char bus_name[ACPI_PATHNAME_MAX] = { 0 }; + char action_name[ACPI_PATHNAME_MAX] = { 0 }; + struct acpi_buffer bus = { ACPI_PATHNAME_MAX, bus_name }; + struct acpi_buffer act = { ACPI_PATHNAME_MAX, action_name }; + + ACPI_FUNCTION_TRACE(("hotkey_config_seq_show")); + + list_for_each(entries, hotkey_list->entries) { + union acpi_hotkey *key = + container_of(entries, union acpi_hotkey, entries); + if (key->link.hotkey_type == ACPI_HOTKEY_POLLING) { acpi_get_name(key->poll_hotkey.poll_handle, ACPI_NAME_TYPE_MAX, &bus); acpi_get_name(key->poll_hotkey.action_handle, ACPI_NAME_TYPE_MAX, &act); - seq_printf(seq, "%s:%s:%s:%s:%d", bus_name, + seq_printf(seq, "%s:%s:%s:%s:%d\n", bus_name, key->poll_hotkey.poll_method, action_name, key->poll_hotkey.action_method, @@ -572,49 +663,83 @@ static int hotkey_config_seq_show(struct seq_file *seq, void *offset) } } seq_puts(seq, "\n"); - end: return_VALUE(0); } static int get_parms(char *config_record, int *cmd, - char *bus_handle, - char *bus_method, - char *action_handle, - char *method, int *internal_event_num, int *external_event_num) + char **bus_handle, + char **bus_method, + char **action_handle, + char **method, int *internal_event_num, int *external_event_num) { - char *tmp, *tmp1; + char *tmp, *tmp1, count; ACPI_FUNCTION_TRACE(("get_parms")); sscanf(config_record, "%d", cmd); + if(*cmd == 1){ + if(sscanf(config_record, "%d:%d", cmd, internal_event_num)!=2) + goto do_fail; + else + return (6); + } tmp = strchr(config_record, ':'); + if (!tmp) + goto do_fail; tmp++; tmp1 = strchr(tmp, ':'); - strncpy(bus_handle, tmp, tmp1 - tmp); - bus_handle[tmp1 - tmp] = 0; + if (!tmp1) + goto do_fail; + + count = tmp1 - tmp; + *bus_handle = (char *) kmalloc(count+1, GFP_KERNEL); + if(!*bus_handle) + goto do_fail; + strncpy(*bus_handle, tmp, count); + *(*bus_handle + count) = 0; tmp = tmp1; tmp++; tmp1 = strchr(tmp, ':'); - strncpy(bus_method, tmp, tmp1 - tmp); - bus_method[tmp1 - tmp] = 0; + if (!tmp1) + goto do_fail; + count = tmp1 - tmp; + *bus_method = (char *) kmalloc(count+1, GFP_KERNEL); + if(!*bus_method) + goto do_fail; + strncpy(*bus_method, tmp, count); + *(*bus_method + count) = 0; tmp = tmp1; tmp++; tmp1 = strchr(tmp, ':'); - strncpy(action_handle, tmp, tmp1 - tmp); - action_handle[tmp1 - tmp] = 0; + if (!tmp1) + goto do_fail; + count = tmp1 - tmp; + *action_handle = (char *) kmalloc(count+1, GFP_KERNEL); + strncpy(*action_handle, tmp, count); + *(*action_handle + count) = 0; tmp = tmp1; tmp++; tmp1 = strchr(tmp, ':'); - strncpy(method, tmp, tmp1 - tmp); - method[tmp1 - tmp] = 0; + if (!tmp1) + goto do_fail; + count = tmp1 - tmp; + *method = (char *) kmalloc(count+1, GFP_KERNEL); + if(!*method) + goto do_fail; + strncpy(*method, tmp, count); + *(*method + count) = 0; + + if(sscanf(tmp1 + 1, "%d:%d", internal_event_num, external_event_num)<=0) + goto do_fail; - sscanf(tmp1 + 1, "%d:%d", internal_event_num, external_event_num); return_VALUE(6); +do_fail: + return_VALUE(-1); } /* count is length for one input record */ @@ -622,135 +747,117 @@ static ssize_t hotkey_write_config(struct file *file, const char __user * buffer, size_t count, loff_t * data) { - struct acpi_hotkey_list *hotkey_list = &global_hotkey_list; - char config_record[MAX_CONFIG_RECORD_LEN]; - char bus_handle[MAX_NAME_PATH_LEN]; - char bus_method[MAX_NAME_PATH_LEN]; - char action_handle[MAX_NAME_PATH_LEN]; - char method[20]; + char *config_record = NULL; + char *bus_handle = NULL; + char *bus_method = NULL; + char *action_handle = NULL; + char *method = NULL; int cmd, internal_event_num, external_event_num; int ret = 0; union acpi_hotkey *key = NULL; ACPI_FUNCTION_TRACE(("hotkey_write_config")); - if (!hotkey_list || count > MAX_CONFIG_RECORD_LEN) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid arguments\n")); - return_VALUE(-EINVAL); - } + config_record = (char *) kmalloc(count+1, GFP_KERNEL); + if(!config_record) + return_VALUE(-ENOMEM); if (copy_from_user(config_record, buffer, count)) { + kfree(config_record); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data \n")); return_VALUE(-EINVAL); } - config_record[count] = '\0'; + config_record[count] = 0; ret = get_parms(config_record, &cmd, - bus_handle, - bus_method, - action_handle, - method, &internal_event_num, &external_event_num); + &bus_handle, + &bus_method, + &action_handle, + &method, &internal_event_num, &external_event_num); + + kfree(config_record); + if(IS_OTHERS(internal_event_num)) + goto do_fail; if (ret != 6) { +do_fail: + kfree(bus_handle); + kfree(bus_method); + kfree(action_handle); + kfree(method); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data format ret=%d\n", ret)); return_VALUE(-EINVAL); } key = kmalloc(sizeof(union acpi_hotkey), GFP_KERNEL); - ret = init_hotkey_device(key, bus_handle, action_handle, method, + if(!key) + goto do_fail; + memset(key, 0, sizeof(union acpi_hotkey)); + if(cmd == 1) { + union acpi_hotkey *tmp = NULL; + tmp = get_hotkey_by_event(&global_hotkey_list, + internal_event_num); + if(!tmp) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid key")); + else + memcpy(key, tmp, sizeof(union acpi_hotkey)); + goto cont_cmd; + } + if (IS_EVENT(internal_event_num)) { + kfree(bus_method); + ret = init_hotkey_device(key, bus_handle, action_handle, method, internal_event_num, external_event_num); - - if (ret || check_hotkey_valid(key, hotkey_list)) { + } else + ret = init_poll_hotkey_device(key, bus_handle, bus_method, + action_handle, method, + internal_event_num); + if (ret) { + kfree(bus_handle); + kfree(action_handle); + if(IS_EVENT(internal_event_num)) + free_hotkey_buffer(key); + else + free_poll_hotkey_buffer(key); kfree(key); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid hotkey \n")); return_VALUE(-EINVAL); } - switch (cmd) { - case 0: - hotkey_add(key); - break; - case 1: - hotkey_remove(key); - free_hotkey_device(key); - break; - case 2: - hotkey_update(key); - break; - default: - break; - } - return_VALUE(count); -} - -/* count is length for one input record */ -static ssize_t hotkey_write_poll_config(struct file *file, - const char __user * buffer, - size_t count, loff_t * data) -{ - struct seq_file *m = (struct seq_file *)file->private_data; - struct acpi_hotkey_list *hotkey_list = - (struct acpi_hotkey_list *)m->private; - - char config_record[MAX_CONFIG_RECORD_LEN]; - char polling_handle[MAX_NAME_PATH_LEN]; - char action_handle[MAX_NAME_PATH_LEN]; - char poll_method[20], action_method[20]; - int ret, internal_event_num, cmd, external_event_num; - union acpi_hotkey *key = NULL; - - ACPI_FUNCTION_TRACE("hotkey_write_poll_config"); - - if (!hotkey_list || count > MAX_CONFIG_RECORD_LEN) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid arguments\n")); - return_VALUE(-EINVAL); - } - - if (copy_from_user(config_record, buffer, count)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data \n")); - return_VALUE(-EINVAL); - } - config_record[count] = '\0'; - ret = get_parms(config_record, - &cmd, - polling_handle, - poll_method, - action_handle, - action_method, - &internal_event_num, &external_event_num); - - if (ret != 6) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data format\n")); - return_VALUE(-EINVAL); - } +cont_cmd: + kfree(bus_handle); + kfree(action_handle); - key = kmalloc(sizeof(union acpi_hotkey), GFP_KERNEL); - ret = init_poll_hotkey_device(key, polling_handle, poll_method, - action_handle, action_method, - internal_event_num); - if (ret || check_hotkey_valid(key, hotkey_list)) { - kfree(key); - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid hotkey \n")); - return_VALUE(-EINVAL); - } switch (cmd) { case 0: - hotkey_add(key); + if(get_hotkey_by_event(&global_hotkey_list,key->link.hotkey_standard_num)) + goto fail_out; + else + hotkey_add(key); break; case 1: hotkey_remove(key); break; case 2: - hotkey_update(key); + if(hotkey_update(key)) + goto fail_out; break; default: + goto fail_out; break; } return_VALUE(count); +fail_out: + if(IS_EVENT(internal_event_num)) + free_hotkey_buffer(key); + else + free_poll_hotkey_buffer(key); + kfree(key); + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "invalid key\n")); + return_VALUE(-EINVAL); } -/* +/* * This function evaluates an ACPI method, given an int as parameter, the * method is searched within the scope of the handle, can be NULL. The output * of the method is written is output, which can also be NULL @@ -775,7 +882,7 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val, return_VALUE(status == AE_OK); } -static int read_acpi_int(acpi_handle handle, const char *method, int *val) +static int read_acpi_int(acpi_handle handle, const char *method, union acpi_object *val) { struct acpi_buffer output; union acpi_object out_obj; @@ -786,62 +893,32 @@ static int read_acpi_int(acpi_handle handle, const char *method, int *val) output.pointer = &out_obj; status = acpi_evaluate_object(handle, (char *)method, NULL, &output); - *val = out_obj.integer.value; + if(val){ + val->integer.value = out_obj.integer.value; + val->type = out_obj.type; + } else + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "null val pointer")); return_VALUE((status == AE_OK) && (out_obj.type == ACPI_TYPE_INTEGER)); } -static acpi_handle -get_handle_from_hotkeylist(struct acpi_hotkey_list *hotkey_list, int event_num) +static union acpi_hotkey *get_hotkey_by_event(struct + acpi_hotkey_list + *hotkey_list, int event) { - struct list_head *entries, *next; - - list_for_each_safe(entries, next, hotkey_list->entries) { - union acpi_hotkey *key = - container_of(entries, union acpi_hotkey, entries); - if (key->link.hotkey_type == ACPI_HOTKEY_EVENT - && key->link.hotkey_standard_num == event_num) { - return (key->event_hotkey.action_handle); - } - } - return (NULL); -} - -static -char *get_method_from_hotkeylist(struct acpi_hotkey_list *hotkey_list, - int event_num) -{ - struct list_head *entries, *next; - - list_for_each_safe(entries, next, hotkey_list->entries) { - union acpi_hotkey *key = - container_of(entries, union acpi_hotkey, entries); - - if (key->link.hotkey_type == ACPI_HOTKEY_EVENT && - key->link.hotkey_standard_num == event_num) - return (key->event_hotkey.action_method); - } - return (NULL); -} - -static struct acpi_polling_hotkey *get_hotkey_by_event(struct - acpi_hotkey_list - *hotkey_list, int event) -{ - struct list_head *entries, *next; + struct list_head *entries; - list_for_each_safe(entries, next, hotkey_list->entries) { + list_for_each(entries, hotkey_list->entries) { union acpi_hotkey *key = container_of(entries, union acpi_hotkey, entries); - if (key->link.hotkey_type == ACPI_HOTKEY_POLLING - && key->link.hotkey_standard_num == event) { - return (&key->poll_hotkey); + if (key->link.hotkey_standard_num == event) { + return(key); } } - return (NULL); + return(NULL); } -/* +/* * user call AML method interface: * Call convention: * echo "event_num: arg type : value" @@ -854,48 +931,56 @@ static ssize_t hotkey_execute_aml_method(struct file *file, size_t count, loff_t * data) { struct acpi_hotkey_list *hotkey_list = &global_hotkey_list; - char arg[MAX_CALL_PARM]; - int event, type, value; - - char *method; - acpi_handle handle; + char *arg; + int event,method_type,type, value; + union acpi_hotkey *key; ACPI_FUNCTION_TRACE("hotkey_execte_aml_method"); - if (!hotkey_list || count > MAX_CALL_PARM) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument 1")); - return_VALUE(-EINVAL); - } + arg = (char *) kmalloc(count+1, GFP_KERNEL); + if(!arg) + return_VALUE(-ENOMEM); + arg[count]=0; if (copy_from_user(arg, buffer, count)) { + kfree(arg); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument 2")); return_VALUE(-EINVAL); } - arg[count] = '\0'; - - if (sscanf(arg, "%d:%d:%d", &event, &type, &value) != 3) { + if (sscanf(arg, "%d:%d:%d:%d", &event, &method_type, &type, &value) != 4) { + kfree(arg); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument 3")); return_VALUE(-EINVAL); } - + kfree(arg); if (type == ACPI_TYPE_INTEGER) { - handle = get_handle_from_hotkeylist(hotkey_list, event); - method = (char *)get_method_from_hotkeylist(hotkey_list, event); + key = get_hotkey_by_event(hotkey_list, event); + if(!key) + goto do_fail; if (IS_EVENT(event)) - write_acpi_int(handle, method, value, NULL); + write_acpi_int(key->event_hotkey.action_handle, + key->event_hotkey.action_method, value, NULL); else if (IS_POLL(event)) { - struct acpi_polling_hotkey *key; - key = (struct acpi_polling_hotkey *) - get_hotkey_by_event(hotkey_list, event); - read_acpi_int(handle, method, key->poll_result); + if ( method_type == POLL_METHOD ) + read_acpi_int(key->poll_hotkey.poll_handle, + key->poll_hotkey.poll_method, + key->poll_hotkey.poll_result); + else if ( method_type == ACTION_METHOD ) + write_acpi_int(key->poll_hotkey.action_handle, + key->poll_hotkey.action_method, value, NULL); + else + goto do_fail; + } } else { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Not supported")); return_VALUE(-EINVAL); } - return_VALUE(count); +do_fail: + return_VALUE(-EINVAL); + } static int __init hotkey_init(void) @@ -928,7 +1013,7 @@ static int __init hotkey_init(void) ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Hotkey: Unable to create %s entry\n", HOTKEY_EV_CONFIG)); - return (-ENODEV); + goto do_fail1; } else { hotkey_config->proc_fops = &hotkey_config_fops; hotkey_config->data = &global_hotkey_list; @@ -943,7 +1028,8 @@ static int __init hotkey_init(void) ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Hotkey: Unable to create %s entry\n", HOTKEY_EV_CONFIG)); - return (-ENODEV); + + goto do_fail2; } else { hotkey_poll_config->proc_fops = &hotkey_poll_config_fops; hotkey_poll_config->data = &global_hotkey_list; @@ -957,7 +1043,7 @@ static int __init hotkey_init(void) ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Hotkey: Unable to create %s entry\n", HOTKEY_ACTION)); - return (-ENODEV); + goto do_fail3; } else { hotkey_action->proc_fops = &hotkey_action_fops; hotkey_action->owner = THIS_MODULE; @@ -970,7 +1056,7 @@ static int __init hotkey_init(void) ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Hotkey: Unable to create %s entry\n", HOTKEY_INFO)); - return (-ENODEV); + goto do_fail4; } else { hotkey_info->proc_fops = &hotkey_info_fops; hotkey_info->owner = THIS_MODULE; @@ -979,23 +1065,33 @@ static int __init hotkey_init(void) } result = acpi_bus_register_driver(&hotkey_driver); - if (result < 0) { - remove_proc_entry(HOTKEY_PROC, acpi_root_dir); - return (-ENODEV); - } + if (result < 0) + goto do_fail5; global_hotkey_list.count = 0; global_hotkey_list.entries = &hotkey_entries; INIT_LIST_HEAD(&hotkey_entries); return (0); + +do_fail5: + remove_proc_entry(HOTKEY_INFO, hotkey_proc_dir); +do_fail4: + remove_proc_entry(HOTKEY_ACTION, hotkey_proc_dir); +do_fail3: + remove_proc_entry(HOTKEY_PL_CONFIG, hotkey_proc_dir); +do_fail2: + remove_proc_entry(HOTKEY_EV_CONFIG, hotkey_proc_dir); +do_fail1: + remove_proc_entry(HOTKEY_PROC, acpi_root_dir); + return (-ENODEV); } static void __exit hotkey_exit(void) { struct list_head *entries, *next; - ACPI_FUNCTION_TRACE("hotkey_remove"); + ACPI_FUNCTION_TRACE("hotkey_exit"); list_for_each_safe(entries, next, global_hotkey_list.entries) { union acpi_hotkey *key = diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index bdd9f37f8101..0d11d6e6abd6 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -71,7 +71,7 @@ EXPORT_SYMBOL(acpi_in_debugger); extern char line_buf[80]; #endif /*ENABLE_DEBUGGER*/ -int acpi_specific_hotkey_enabled; +int acpi_specific_hotkey_enabled = TRUE; EXPORT_SYMBOL(acpi_specific_hotkey_enabled); static unsigned int acpi_irq_irq; @@ -145,10 +145,14 @@ acpi_os_vprintf(const char *fmt, va_list args) #endif } +extern int acpi_in_resume; void * acpi_os_allocate(acpi_size size) { - return kmalloc(size, GFP_KERNEL); + if (acpi_in_resume) + return kmalloc(size, GFP_ATOMIC); + else + return kmalloc(size, GFP_KERNEL); } void @@ -1158,11 +1162,11 @@ __setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup); int __init acpi_hotkey_setup(char *str) { - acpi_specific_hotkey_enabled = TRUE; + acpi_specific_hotkey_enabled = FALSE; return 1; } -__setup("acpi_specific_hotkey", acpi_hotkey_setup); +__setup("acpi_generic_hotkey", acpi_hotkey_setup); /* * max_cstate is defined in the base kernel so modules can 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) /* -------------------------------------------------------------------------- PCI Interrupt Routing Support -------------------------------------------------------------------------- */ +typedef int (*irq_lookup_func)(struct acpi_prt_entry *, int *, int *, char **); +static int +acpi_pci_allocate_irq(struct acpi_prt_entry *entry, + int *edge_level, + int *active_high_low, + char **link) +{ + int irq; + + ACPI_FUNCTION_TRACE("acpi_pci_allocate_irq"); + + if (entry->link.handle) { + irq = acpi_pci_link_allocate_irq(entry->link.handle, + entry->link.index, edge_level, active_high_low, link); + if (irq < 0) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n")); + return_VALUE(-1); + } + } else { + irq = entry->link.index; + *edge_level = ACPI_LEVEL_SENSITIVE; + *active_high_low = ACPI_ACTIVE_LOW; + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq)); + return_VALUE(irq); +} + +static int +acpi_pci_free_irq(struct acpi_prt_entry *entry, + int *edge_level, + int *active_high_low, + char **link) +{ + int irq; + + ACPI_FUNCTION_TRACE("acpi_pci_free_irq"); + if (entry->link.handle) { + irq = acpi_pci_link_free_irq(entry->link.handle); + } else { + irq = entry->link.index; + } + return_VALUE(irq); +} /* * acpi_pci_irq_lookup * success: return IRQ >= 0 @@ -282,12 +326,13 @@ acpi_pci_irq_lookup ( int pin, int *edge_level, int *active_high_low, - char **link) + char **link, + irq_lookup_func func) { struct acpi_prt_entry *entry = NULL; int segment = pci_domain_nr(bus); int bus_nr = bus->number; - int irq; + int ret; ACPI_FUNCTION_TRACE("acpi_pci_irq_lookup"); @@ -301,22 +346,8 @@ acpi_pci_irq_lookup ( return_VALUE(-1); } - if (entry->link.handle) { - irq = acpi_pci_link_get_irq(entry->link.handle, - entry->link.index, edge_level, active_high_low, link); - if (irq < 0) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n")); - return_VALUE(-1); - } - } else { - irq = entry->link.index; - *edge_level = ACPI_LEVEL_SENSITIVE; - *active_high_low = ACPI_ACTIVE_LOW; - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq)); - - return_VALUE(irq); + ret = func(entry, edge_level, active_high_low, link); + return_VALUE(ret); } /* @@ -330,7 +361,8 @@ acpi_pci_irq_derive ( int pin, int *edge_level, int *active_high_low, - char **link) + char **link, + irq_lookup_func func) { struct pci_dev *bridge = dev; int irq = -1; @@ -363,7 +395,7 @@ acpi_pci_irq_derive ( } irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn), - pin, edge_level, active_high_low, link); + pin, edge_level, active_high_low, link, func); } if (irq < 0) { @@ -415,7 +447,7 @@ acpi_pci_irq_enable ( * values override any BIOS-assigned IRQs set during boot. */ irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, - &edge_level, &active_high_low, &link); + &edge_level, &active_high_low, &link, acpi_pci_allocate_irq); /* * If no PRT entry was found, we'll try to derive an IRQ from the @@ -423,7 +455,7 @@ acpi_pci_irq_enable ( */ if (irq < 0) irq = acpi_pci_irq_derive(dev, pin, &edge_level, - &active_high_low, &link); + &active_high_low, &link, acpi_pci_allocate_irq); /* * No IRQ known to the ACPI subsystem - maybe the BIOS / @@ -462,7 +494,9 @@ acpi_pci_irq_enable ( EXPORT_SYMBOL(acpi_pci_irq_enable); -#ifdef CONFIG_ACPI_DEALLOCATE_IRQ +/* FIXME: implement x86/x86_64 version */ +void __attribute__((weak)) acpi_unregister_gsi(u32 i) {} + void acpi_pci_irq_disable ( struct pci_dev *dev) @@ -489,14 +523,14 @@ acpi_pci_irq_disable ( * First we check the PCI IRQ routing table (PRT) for an IRQ. */ gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, - &edge_level, &active_high_low, NULL); + &edge_level, &active_high_low, NULL, acpi_pci_free_irq); /* * If no PRT entry was found, we'll try to derive an IRQ from the * device's parent bridge. */ if (gsi < 0) gsi = acpi_pci_irq_derive(dev, pin, - &edge_level, &active_high_low, NULL); + &edge_level, &active_high_low, NULL, acpi_pci_free_irq); if (gsi < 0) return_VOID; @@ -512,4 +546,3 @@ acpi_pci_irq_disable ( return_VOID; } -#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 = { }, }; +/* + * If a link is initialized, we never change its active and initialized + * later even the link is disable. Instead, we just repick the active irq + */ struct acpi_pci_link_irq { u8 active; /* Current IRQ */ u8 edge_level; /* All IRQs */ @@ -76,8 +80,7 @@ struct acpi_pci_link_irq { u8 possible_count; u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE]; u8 initialized:1; - u8 suspend_resume:1; - u8 reserved:6; + u8 reserved:7; }; struct acpi_pci_link { @@ -85,12 +88,14 @@ struct acpi_pci_link { struct acpi_device *device; acpi_handle handle; struct acpi_pci_link_irq irq; + int refcnt; }; static struct { int count; struct list_head entries; } acpi_link; +DECLARE_MUTEX(acpi_link_lock); /* -------------------------------------------------------------------------- @@ -532,12 +537,12 @@ static int acpi_pci_link_allocate( ACPI_FUNCTION_TRACE("acpi_pci_link_allocate"); - if (link->irq.suspend_resume) { - acpi_pci_link_set(link, link->irq.active); - link->irq.suspend_resume = 0; - } - if (link->irq.initialized) + if (link->irq.initialized) { + if (link->refcnt == 0) + /* This means the link is disabled but initialized */ + acpi_pci_link_set(link, link->irq.active); return_VALUE(0); + } /* * search for active IRQ in list of possible IRQs. @@ -596,13 +601,13 @@ static int acpi_pci_link_allocate( } /* - * acpi_pci_link_get_irq + * acpi_pci_link_allocate_irq * success: return IRQ >= 0 * failure: return -1 */ int -acpi_pci_link_get_irq ( +acpi_pci_link_allocate_irq ( acpi_handle handle, int index, int *edge_level, @@ -613,7 +618,7 @@ acpi_pci_link_get_irq ( struct acpi_device *device = NULL; struct acpi_pci_link *link = NULL; - ACPI_FUNCTION_TRACE("acpi_pci_link_get_irq"); + ACPI_FUNCTION_TRACE("acpi_pci_link_allocate_irq"); result = acpi_bus_get_device(handle, &device); if (result) { @@ -633,21 +638,81 @@ acpi_pci_link_get_irq ( return_VALUE(-1); } - if (acpi_pci_link_allocate(link)) + down(&acpi_link_lock); + if (acpi_pci_link_allocate(link)) { + up(&acpi_link_lock); return_VALUE(-1); + } if (!link->irq.active) { + up(&acpi_link_lock); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link active IRQ is 0!\n")); return_VALUE(-1); } + link->refcnt ++; + up(&acpi_link_lock); if (edge_level) *edge_level = link->irq.edge_level; if (active_high_low) *active_high_low = link->irq.active_high_low; if (name) *name = acpi_device_bid(link->device); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Link %s is referenced\n", acpi_device_bid(link->device))); return_VALUE(link->irq.active); } +/* + * We don't change link's irq information here. After it is reenabled, we + * continue use the info + */ +int +acpi_pci_link_free_irq(acpi_handle handle) +{ + struct acpi_device *device = NULL; + struct acpi_pci_link *link = NULL; + acpi_status result; + + ACPI_FUNCTION_TRACE("acpi_pci_link_free_irq"); + + result = acpi_bus_get_device(handle, &device); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link device\n")); + return_VALUE(-1); + } + + link = (struct acpi_pci_link *) acpi_driver_data(device); + if (!link) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n")); + return_VALUE(-1); + } + + down(&acpi_link_lock); + if (!link->irq.initialized) { + up(&acpi_link_lock); + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link isn't initialized\n")); + return_VALUE(-1); + } +#ifdef FUTURE_USE + /* + * The Link reference count allows us to _DISable an unused link + * and suspend time, and set it again on resume. + * However, 2.6.12 still has irq_router.resume + * which blindly restores the link state. + * So we disable the reference count method + * to prevent duplicate acpi_pci_link_set() + * which would harm some systems + */ + link->refcnt --; +#endif + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Link %s is dereferenced\n", acpi_device_bid(link->device))); + + if (link->refcnt == 0) { + acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL); + } + up(&acpi_link_lock); + return_VALUE(link->irq.active); +} /* -------------------------------------------------------------------------- Driver Interface -------------------------------------------------------------------------- */ @@ -677,6 +742,7 @@ acpi_pci_link_add ( strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS); acpi_driver_data(device) = link; + down(&acpi_link_lock); result = acpi_pci_link_get_possible(link); if (result) goto end; @@ -712,6 +778,7 @@ acpi_pci_link_add ( end: /* disable all links -- to be activated on use */ acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL); + up(&acpi_link_lock); if (result) kfree(link); @@ -720,24 +787,42 @@ end: } static int -irqrouter_suspend( - struct sys_device *dev, - u32 state) +acpi_pci_link_resume( + struct acpi_pci_link *link) +{ + ACPI_FUNCTION_TRACE("acpi_pci_link_resume"); + + if (link->refcnt && link->irq.active && link->irq.initialized) + return_VALUE(acpi_pci_link_set(link, link->irq.active)); + else + return_VALUE(0); +} + +/* + * FIXME: this is a workaround to avoid nasty warning. It will be removed + * after every device calls pci_disable_device in .resume. + */ +int acpi_in_resume; +static int +irqrouter_resume( + struct sys_device *dev) { struct list_head *node = NULL; struct acpi_pci_link *link = NULL; - ACPI_FUNCTION_TRACE("irqrouter_suspend"); + ACPI_FUNCTION_TRACE("irqrouter_resume"); + acpi_in_resume = 1; list_for_each(node, &acpi_link.entries) { link = list_entry(node, struct acpi_pci_link, node); if (!link) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n")); + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Invalid link context\n")); continue; } - if (link->irq.active && link->irq.initialized) - link->irq.suspend_resume = 1; + acpi_pci_link_resume(link); } + acpi_in_resume = 0; return_VALUE(0); } @@ -756,8 +841,9 @@ acpi_pci_link_remove ( link = (struct acpi_pci_link *) acpi_driver_data(device); - /* TBD: Acquire/release lock */ + down(&acpi_link_lock); list_del(&link->node); + up(&acpi_link_lock); kfree(link); @@ -849,9 +935,10 @@ int __init acpi_irq_balance_set(char *str) __setup("acpi_irq_balance", acpi_irq_balance_set); +/* FIXME: we will remove this interface after all drivers call pci_disable_device */ static struct sysdev_class irqrouter_sysdev_class = { set_kset_name("irqrouter"), - .suspend = irqrouter_suspend, + .resume = irqrouter_resume, }; 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); * * To skip this limit, boot/load with a large max_cstate limit. */ -static int no_c2c3(struct dmi_system_id *id) +static int set_max_cstate(struct dmi_system_id *id) { if (max_cstate > ACPI_PROCESSOR_MAX_POWER) return 0; - printk(KERN_NOTICE PREFIX "%s detected - C2,C3 disabled." + printk(KERN_NOTICE PREFIX "%s detected - limiting to C%ld max_cstate." " Override with \"processor.max_cstate=%d\"\n", id->ident, - ACPI_PROCESSOR_MAX_POWER + 1); + (long)id->driver_data, ACPI_PROCESSOR_MAX_POWER + 1); - max_cstate = 1; + max_cstate = (long)id->driver_data; return 0; } - - static struct dmi_system_id __initdata processor_power_dmi_table[] = { - { no_c2c3, "IBM ThinkPad R40e", { + { set_max_cstate, "IBM ThinkPad R40e", { DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW") }}, - { no_c2c3, "Medion 41700", { + DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW") }, (void*)1}, + { set_max_cstate, "Medion 41700", { + DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), + DMI_MATCH(DMI_BIOS_VERSION,"R01-A1J") }, (void*)1}, + { set_max_cstate, "Clevo 5600D", { DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), - DMI_MATCH(DMI_BIOS_VERSION,"R01-A1J") }}, + DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307") }, + (void*)2}, {}, }; @@ -549,7 +551,8 @@ static int acpi_processor_get_power_info_default_c1 (struct acpi_processor *pr) ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_default_c1"); for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++) - memset(pr->power.states, 0, sizeof(struct acpi_processor_cx)); + memset(&(pr->power.states[i]), 0, + sizeof(struct acpi_processor_cx)); /* if info is obtained from pblk/fadt, type equals state */ 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) pr->power.count = 0; for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++) - memset(pr->power.states, 0, sizeof(struct acpi_processor_cx)); + memset(&(pr->power.states[i]), 0, + sizeof(struct acpi_processor_cx)); status = acpi_evaluate_object(pr->handle, "_CST", NULL, &buffer); if (ACPI_FAILURE(status)) { @@ -763,7 +767,6 @@ static void acpi_processor_power_verify_c3( } if (pr->flags.bm_check) { - printk("Disabling BM access before entering C3\n"); /* bus mastering control is necessary */ if (!pr->flags.bm_control) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -771,7 +774,6 @@ static void acpi_processor_power_verify_c3( return_VOID; } } else { - printk("Invalidating cache before entering C3\n"); /* * WBINVD should be set in fadt, for C3 state to be * supported on when bm_check is not required. @@ -842,7 +844,7 @@ static int acpi_processor_get_power_info ( result = acpi_processor_get_power_info_cst(pr); if ((result) || (acpi_processor_power_verify(pr) < 2)) { result = acpi_processor_get_power_info_fadt(pr); - if (result) + if ((result) || (acpi_processor_power_verify(pr) < 2)) result = acpi_processor_get_power_info_default_c1(pr); } diff --git a/drivers/acpi/sleep/poweroff.c b/drivers/acpi/sleep/poweroff.c index 186b182c5825..f93d2ee54800 100644 --- a/drivers/acpi/sleep/poweroff.c +++ b/drivers/acpi/sleep/poweroff.c @@ -55,7 +55,11 @@ void acpi_power_off(void) static int acpi_shutdown(struct sys_device *x) { - return acpi_sleep_prepare(ACPI_STATE_S5); + if (system_state == SYSTEM_POWER_OFF) { + /* Prepare if we are going to power off the system */ + return acpi_sleep_prepare(ACPI_STATE_S5); + } + return 0; } static struct sysdev_class acpi_sysclass = { diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 96fe2f956754..ab53832d57e5 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -180,7 +180,9 @@ static ssize_t driver_bind(struct device_driver *drv, up(&dev->sem); put_device(dev); } - return err; + if (err) + return err; + return count; } static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind); diff --git a/drivers/base/class.c b/drivers/base/class.c index 479c12570881..0154a1623b21 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -299,6 +299,11 @@ static void class_dev_release(struct kobject * kobj) pr_debug("device class '%s': release.\n", cd->class_id); + if (cd->devt_attr) { + kfree(cd->devt_attr); + cd->devt_attr = NULL; + } + if (cls->release) cls->release(cd); else { @@ -591,11 +596,8 @@ void class_device_del(struct class_device *class_dev) if (class_dev->dev) sysfs_remove_link(&class_dev->kobj, "device"); - if (class_dev->devt_attr) { + if (class_dev->devt_attr) class_device_remove_file(class_dev, class_dev->devt_attr); - kfree(class_dev->devt_attr); - class_dev->devt_attr = NULL; - } class_device_remove_attrs(class_dev); kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE); diff --git a/drivers/block/cfq-iosched.c b/drivers/block/cfq-iosched.c index de5746e38af9..cd056e7e64ec 100644 --- a/drivers/block/cfq-iosched.c +++ b/drivers/block/cfq-iosched.c @@ -47,7 +47,7 @@ static int cfq_slice_idle = HZ / 100; /* * disable queueing at the driver/hardware level */ -static int cfq_max_depth = 1; +static int cfq_max_depth = 2; /* * for the hash of cfqq inside the cfqd @@ -385,9 +385,15 @@ cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2) return crq2; if (crq2 == NULL) return crq1; - if (cfq_crq_requeued(crq1)) + + if (cfq_crq_requeued(crq1) && !cfq_crq_requeued(crq2)) return crq1; - if (cfq_crq_requeued(crq2)) + else if (cfq_crq_requeued(crq2) && !cfq_crq_requeued(crq1)) + return crq2; + + if (cfq_crq_is_sync(crq1) && !cfq_crq_is_sync(crq2)) + return crq1; + else if (cfq_crq_is_sync(crq2) && !cfq_crq_is_sync(crq1)) return crq2; s1 = crq1->request->sector; @@ -1281,6 +1287,7 @@ dispatch: */ if (!cfq_crq_in_driver(crq) && !cfq_cfqq_idle_window(cfqq) && + !blk_barrier_rq(rq) && cfqd->rq_in_driver >= cfqd->cfq_max_depth) return NULL; @@ -1768,18 +1775,23 @@ static void cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq, struct cfq_rq *crq) { - const int sync = cfq_crq_is_sync(crq); + struct cfq_io_context *cic; cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq); - if (sync) { - struct cfq_io_context *cic = crq->io_context; + /* + * we never wait for an async request and we don't allow preemption + * of an async request. so just return early + */ + if (!cfq_crq_is_sync(crq)) + return; - cfq_update_io_thinktime(cfqd, cic); - cfq_update_idle_window(cfqd, cfqq, cic); + cic = crq->io_context; - cic->last_queue = jiffies; - } + cfq_update_io_thinktime(cfqd, cic); + cfq_update_idle_window(cfqd, cfqq, cic); + + cic->last_queue = jiffies; if (cfqq == cfqd->active_queue) { /* diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 692a5fced76e..0c7599563b65 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -284,6 +284,7 @@ static inline void rq_init(request_queue_t *q, struct request *rq) rq->special = NULL; rq->data_len = 0; rq->data = NULL; + rq->nr_phys_segments = 0; rq->sense = NULL; rq->end_io = NULL; rq->end_io_data = NULL; @@ -719,7 +720,7 @@ struct request *blk_queue_find_tag(request_queue_t *q, int tag) { struct blk_queue_tag *bqt = q->queue_tags; - if (unlikely(bqt == NULL || tag >= bqt->max_depth)) + if (unlikely(bqt == NULL || tag >= bqt->real_max_depth)) return NULL; return bqt->tag_index[tag]; @@ -798,6 +799,7 @@ init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth) memset(tag_index, 0, depth * sizeof(struct request *)); memset(tag_map, 0, nr_ulongs * sizeof(unsigned long)); + tags->real_max_depth = depth; tags->max_depth = depth; tags->tag_index = tag_index; tags->tag_map = tag_map; @@ -872,11 +874,22 @@ int blk_queue_resize_tags(request_queue_t *q, int new_depth) return -ENXIO; /* + * if we already have large enough real_max_depth. just + * adjust max_depth. *NOTE* as requests with tag value + * between new_depth and real_max_depth can be in-flight, tag + * map can not be shrunk blindly here. + */ + if (new_depth <= bqt->real_max_depth) { + bqt->max_depth = new_depth; + return 0; + } + + /* * save the old state info, so we can copy it back */ tag_index = bqt->tag_index; tag_map = bqt->tag_map; - max_depth = bqt->max_depth; + max_depth = bqt->real_max_depth; if (init_tag_map(q, bqt, new_depth)) return -ENOMEM; @@ -913,7 +926,7 @@ void blk_queue_end_tag(request_queue_t *q, struct request *rq) BUG_ON(tag == -1); - if (unlikely(tag >= bqt->max_depth)) + if (unlikely(tag >= bqt->real_max_depth)) /* * This can happen after tag depth has been reduced. * FIXME: how about a warning or info message here? @@ -2103,7 +2116,7 @@ EXPORT_SYMBOL(blk_insert_request); /** * blk_rq_map_user - map user data to a request, for REQ_BLOCK_PC usage * @q: request queue where request should be inserted - * @rw: READ or WRITE data + * @rq: request structure to fill * @ubuf: the user buffer * @len: length of user data * @@ -2120,21 +2133,19 @@ EXPORT_SYMBOL(blk_insert_request); * original bio must be passed back in to blk_rq_unmap_user() for proper * unmapping. */ -struct request *blk_rq_map_user(request_queue_t *q, int rw, void __user *ubuf, - unsigned int len) +int blk_rq_map_user(request_queue_t *q, struct request *rq, void __user *ubuf, + unsigned int len) { unsigned long uaddr; - struct request *rq; struct bio *bio; + int reading; if (len > (q->max_sectors << 9)) - return ERR_PTR(-EINVAL); - if ((!len && ubuf) || (len && !ubuf)) - return ERR_PTR(-EINVAL); + return -EINVAL; + if (!len || !ubuf) + return -EINVAL; - rq = blk_get_request(q, rw, __GFP_WAIT); - if (!rq) - return ERR_PTR(-ENOMEM); + reading = rq_data_dir(rq) == READ; /* * if alignment requirement is satisfied, map in user pages for @@ -2142,9 +2153,9 @@ struct request *blk_rq_map_user(request_queue_t *q, int rw, void __user *ubuf, */ uaddr = (unsigned long) ubuf; if (!(uaddr & queue_dma_alignment(q)) && !(len & queue_dma_alignment(q))) - bio = bio_map_user(q, NULL, uaddr, len, rw == READ); + bio = bio_map_user(q, NULL, uaddr, len, reading); else - bio = bio_copy_user(q, uaddr, len, rw == READ); + bio = bio_copy_user(q, uaddr, len, reading); if (!IS_ERR(bio)) { rq->bio = rq->biotail = bio; @@ -2152,28 +2163,70 @@ struct request *blk_rq_map_user(request_queue_t *q, int rw, void __user *ubuf, rq->buffer = rq->data = NULL; rq->data_len = len; - return rq; + return 0; } /* * bio is the err-ptr */ - blk_put_request(rq); - return (struct request *) bio; + return PTR_ERR(bio); } EXPORT_SYMBOL(blk_rq_map_user); /** + * blk_rq_map_user_iov - map user data to a request, for REQ_BLOCK_PC usage + * @q: request queue where request should be inserted + * @rq: request to map data to + * @iov: pointer to the iovec + * @iov_count: number of elements in the iovec + * + * Description: + * Data will be mapped directly for zero copy io, if possible. Otherwise + * a kernel bounce buffer is used. + * + * A matching blk_rq_unmap_user() must be issued at the end of io, while + * still in process context. + * + * Note: The mapped bio may need to be bounced through blk_queue_bounce() + * before being submitted to the device, as pages mapped may be out of + * reach. It's the callers responsibility to make sure this happens. The + * original bio must be passed back in to blk_rq_unmap_user() for proper + * unmapping. + */ +int blk_rq_map_user_iov(request_queue_t *q, struct request *rq, + struct sg_iovec *iov, int iov_count) +{ + struct bio *bio; + + if (!iov || iov_count <= 0) + return -EINVAL; + + /* we don't allow misaligned data like bio_map_user() does. If the + * user is using sg, they're expected to know the alignment constraints + * and respect them accordingly */ + bio = bio_map_user_iov(q, NULL, iov, iov_count, rq_data_dir(rq)== READ); + if (IS_ERR(bio)) + return PTR_ERR(bio); + + rq->bio = rq->biotail = bio; + blk_rq_bio_prep(q, rq, bio); + rq->buffer = rq->data = NULL; + rq->data_len = bio->bi_size; + return 0; +} + +EXPORT_SYMBOL(blk_rq_map_user_iov); + +/** * blk_rq_unmap_user - unmap a request with user data - * @rq: request to be unmapped - * @bio: bio for the request + * @bio: bio to be unmapped * @ulen: length of user buffer * * Description: - * Unmap a request previously mapped by blk_rq_map_user(). + * Unmap a bio previously mapped by blk_rq_map_user(). */ -int blk_rq_unmap_user(struct request *rq, struct bio *bio, unsigned int ulen) +int blk_rq_unmap_user(struct bio *bio, unsigned int ulen) { int ret = 0; @@ -2184,31 +2237,89 @@ int blk_rq_unmap_user(struct request *rq, struct bio *bio, unsigned int ulen) ret = bio_uncopy_user(bio); } - blk_put_request(rq); - return ret; + return 0; } EXPORT_SYMBOL(blk_rq_unmap_user); /** + * blk_rq_map_kern - map kernel data to a request, for REQ_BLOCK_PC usage + * @q: request queue where request should be inserted + * @rq: request to fill + * @kbuf: the kernel buffer + * @len: length of user data + * @gfp_mask: memory allocation flags + */ +int blk_rq_map_kern(request_queue_t *q, struct request *rq, void *kbuf, + unsigned int len, unsigned int gfp_mask) +{ + struct bio *bio; + + if (len > (q->max_sectors << 9)) + return -EINVAL; + if (!len || !kbuf) + return -EINVAL; + + bio = bio_map_kern(q, kbuf, len, gfp_mask); + if (IS_ERR(bio)) + return PTR_ERR(bio); + + if (rq_data_dir(rq) == WRITE) + bio->bi_rw |= (1 << BIO_RW); + + rq->bio = rq->biotail = bio; + blk_rq_bio_prep(q, rq, bio); + + rq->buffer = rq->data = NULL; + rq->data_len = len; + return 0; +} + +EXPORT_SYMBOL(blk_rq_map_kern); + +/** + * blk_execute_rq_nowait - insert a request into queue for execution + * @q: queue to insert the request in + * @bd_disk: matching gendisk + * @rq: request to insert + * @at_head: insert request at head or tail of queue + * @done: I/O completion handler + * + * Description: + * Insert a fully prepared request at the back of the io scheduler queue + * for execution. Don't wait for completion. + */ +void blk_execute_rq_nowait(request_queue_t *q, struct gendisk *bd_disk, + struct request *rq, int at_head, + void (*done)(struct request *)) +{ + int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK; + + rq->rq_disk = bd_disk; + rq->flags |= REQ_NOMERGE; + rq->end_io = done; + elv_add_request(q, rq, where, 1); + generic_unplug_device(q); +} + +/** * blk_execute_rq - insert a request into queue for execution * @q: queue to insert the request in * @bd_disk: matching gendisk * @rq: request to insert + * @at_head: insert request at head or tail of queue * * Description: * Insert a fully prepared request at the back of the io scheduler queue - * for execution. + * for execution and wait for completion. */ int blk_execute_rq(request_queue_t *q, struct gendisk *bd_disk, - struct request *rq) + struct request *rq, int at_head) { DECLARE_COMPLETION(wait); char sense[SCSI_SENSE_BUFFERSIZE]; int err = 0; - rq->rq_disk = bd_disk; - /* * we need an extra reference to the request, so we can look at * it after io completion @@ -2221,11 +2332,8 @@ int blk_execute_rq(request_queue_t *q, struct gendisk *bd_disk, rq->sense_len = 0; } - rq->flags |= REQ_NOMERGE; rq->waiting = &wait; - rq->end_io = blk_end_sync_rq; - elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1); - generic_unplug_device(q); + blk_execute_rq_nowait(q, bd_disk, rq, at_head, blk_end_sync_rq); wait_for_completion(&wait); rq->waiting = NULL; @@ -2265,6 +2373,44 @@ int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector) EXPORT_SYMBOL(blkdev_issue_flush); +/** + * blkdev_scsi_issue_flush_fn - issue flush for SCSI devices + * @q: device queue + * @disk: gendisk + * @error_sector: error offset + * + * Description: + * Devices understanding the SCSI command set, can use this function as + * a helper for issuing a cache flush. Note: driver is required to store + * the error offset (in case of error flushing) in ->sector of struct + * request. + */ +int blkdev_scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk, + sector_t *error_sector) +{ + struct request *rq = blk_get_request(q, WRITE, __GFP_WAIT); + int ret; + + rq->flags |= REQ_BLOCK_PC | REQ_SOFTBARRIER; + rq->sector = 0; + memset(rq->cmd, 0, sizeof(rq->cmd)); + rq->cmd[0] = 0x35; + rq->cmd_len = 12; + rq->data = NULL; + rq->data_len = 0; + rq->timeout = 60 * HZ; + + ret = blk_execute_rq(q, disk, rq, 0); + + if (ret && error_sector) + *error_sector = rq->sector; + + blk_put_request(rq); + return ret; +} + +EXPORT_SYMBOL(blkdev_scsi_issue_flush_fn); + static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io) { int rw = rq_data_dir(rq); diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c index 681871ca5d60..abb2df249fd3 100644 --- a/drivers/block/scsi_ioctl.c +++ b/drivers/block/scsi_ioctl.c @@ -216,7 +216,7 @@ static int sg_io(struct file *file, request_queue_t *q, struct gendisk *bd_disk, struct sg_io_hdr *hdr) { unsigned long start_time; - int reading, writing; + int writing = 0, ret = 0; struct request *rq; struct bio *bio; char sense[SCSI_SENSE_BUFFERSIZE]; @@ -231,38 +231,48 @@ static int sg_io(struct file *file, request_queue_t *q, if (verify_command(file, cmd)) return -EPERM; - /* - * we'll do that later - */ - if (hdr->iovec_count) - return -EOPNOTSUPP; - if (hdr->dxfer_len > (q->max_sectors << 9)) return -EIO; - reading = writing = 0; - if (hdr->dxfer_len) { + if (hdr->dxfer_len) switch (hdr->dxfer_direction) { default: return -EINVAL; case SG_DXFER_TO_FROM_DEV: - reading = 1; - /* fall through */ case SG_DXFER_TO_DEV: writing = 1; break; case SG_DXFER_FROM_DEV: - reading = 1; break; } - rq = blk_rq_map_user(q, writing ? WRITE : READ, hdr->dxferp, - hdr->dxfer_len); + rq = blk_get_request(q, writing ? WRITE : READ, GFP_KERNEL); + if (!rq) + return -ENOMEM; + + if (hdr->iovec_count) { + const int size = sizeof(struct sg_iovec) * hdr->iovec_count; + struct sg_iovec *iov; + + iov = kmalloc(size, GFP_KERNEL); + if (!iov) { + ret = -ENOMEM; + goto out; + } + + if (copy_from_user(iov, hdr->dxferp, size)) { + kfree(iov); + ret = -EFAULT; + goto out; + } + + ret = blk_rq_map_user_iov(q, rq, iov, hdr->iovec_count); + kfree(iov); + } else if (hdr->dxfer_len) + ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len); - if (IS_ERR(rq)) - return PTR_ERR(rq); - } else - rq = blk_get_request(q, READ, __GFP_WAIT); + if (ret) + goto out; /* * fill in request structure @@ -298,7 +308,7 @@ static int sg_io(struct file *file, request_queue_t *q, * (if he doesn't check that is his problem). * N.B. a non-zero SCSI status is _not_ necessarily an error. */ - blk_execute_rq(q, bd_disk, rq); + blk_execute_rq(q, bd_disk, rq, 0); /* write to all output members */ hdr->status = 0xff & rq->errors; @@ -320,12 +330,14 @@ static int sg_io(struct file *file, request_queue_t *q, hdr->sb_len_wr = len; } - if (blk_rq_unmap_user(rq, bio, hdr->dxfer_len)) - return -EFAULT; + if (blk_rq_unmap_user(bio, hdr->dxfer_len)) + ret = -EFAULT; /* may not have succeeded, but output values written to control * structure (struct sg_io_hdr). */ - return 0; +out: + blk_put_request(rq); + return ret; } #define OMAX_SB_LEN 16 /* For backward compatibility */ @@ -408,7 +420,7 @@ static int sg_scsi_ioctl(struct file *file, request_queue_t *q, rq->data_len = bytes; rq->flags |= REQ_BLOCK_PC; - blk_execute_rq(q, bd_disk, rq); + blk_execute_rq(q, bd_disk, rq, 0); err = rq->errors & 0xff; /* only 8 bit SCSI status */ if (err) { if (rq->sense_len && rq->sense) { @@ -561,7 +573,7 @@ int scsi_cmd_ioctl(struct file *file, struct gendisk *bd_disk, unsigned int cmd, rq->cmd[0] = GPCMD_START_STOP_UNIT; rq->cmd[4] = 0x02 + (close != 0); rq->cmd_len = 6; - err = blk_execute_rq(q, bd_disk, rq); + err = blk_execute_rq(q, bd_disk, rq, 0); blk_put_request(rq); break; default: 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) if (!urb) return; - if (urb->setup_packet) - kfree(urb->setup_packet); - - if (urb->transfer_buffer) - kfree(urb->transfer_buffer); + kfree(urb->setup_packet); + kfree(urb->transfer_buffer); usb_free_urb(urb); } 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 @@ #ifndef CONFIG_BT_HCIUART_DEBUG #undef BT_DBG #define BT_DBG( A... ) -#undef BT_DMP -#define BT_DMP( A... ) #endif 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 @@ #ifndef CONFIG_BT_HCIUART_DEBUG #undef BT_DBG #define BT_DBG( A... ) -#undef BT_DMP -#define BT_DMP( A... ) #endif /* Initialize protocol */ @@ -125,7 +123,6 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len) BT_DBG("len %d room %d", len, room); if (!len) { - BT_DMP(h4->rx_skb->data, h4->rx_skb->len); hci_recv_frame(h4->rx_skb); } else if (len > room) { BT_ERR("Data length is too large"); @@ -169,8 +166,6 @@ static int h4_recv(struct hci_uart *hu, void *data, int count) case H4_W4_DATA: BT_DBG("Complete data"); - BT_DMP(h4->rx_skb->data, h4->rx_skb->len); - hci_recv_frame(h4->rx_skb); 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 @@ #ifndef CONFIG_BT_HCIUART_DEBUG #undef BT_DBG #define BT_DBG( A... ) -#undef BT_DMP -#define BT_DMP( A... ) #endif 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 @@ #ifndef CONFIG_BT_HCIUSB_DEBUG #undef BT_DBG #define BT_DBG(D...) -#undef BT_DMP -#define BT_DMP(D...) #endif #ifndef CONFIG_BT_HCIUSB_ZERO_PACKET @@ -110,6 +108,9 @@ static struct usb_device_id blacklist_ids[] = { /* Microsoft Wireless Transceiver for Bluetooth 2.0 */ { USB_DEVICE(0x045e, 0x009c), .driver_info = HCI_RESET }, + /* Kensington Bluetooth USB adapter */ + { USB_DEVICE(0x047d, 0x105d), .driver_info = HCI_RESET }, + /* ISSC Bluetooth Adapter v3.1 */ { USB_DEVICE(0x1131, 0x1001), .driver_info = HCI_RESET }, @@ -387,10 +388,8 @@ static void hci_usb_unlink_urbs(struct hci_usb *husb) urb = &_urb->urb; BT_DBG("%s freeing _urb %p type %d urb %p", husb->hdev->name, _urb, _urb->type, urb); - if (urb->setup_packet) - kfree(urb->setup_packet); - if (urb->transfer_buffer) - kfree(urb->transfer_buffer); + kfree(urb->setup_packet); + kfree(urb->transfer_buffer); _urb_free(_urb); } diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index beaa561f2ed8..153960348414 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -2097,6 +2097,10 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf, if (!q) return -ENXIO; + rq = blk_get_request(q, READ, GFP_KERNEL); + if (!rq) + return -ENOMEM; + cdi->last_sense = 0; while (nframes) { @@ -2108,9 +2112,9 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf, len = nr * CD_FRAMESIZE_RAW; - rq = blk_rq_map_user(q, READ, ubuf, len); - if (IS_ERR(rq)) - return PTR_ERR(rq); + ret = blk_rq_map_user(q, rq, ubuf, len); + if (ret) + break; memset(rq->cmd, 0, sizeof(rq->cmd)); rq->cmd[0] = GPCMD_READ_CD; @@ -2132,13 +2136,13 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf, if (rq->bio) blk_queue_bounce(q, &rq->bio); - if (blk_execute_rq(q, cdi->disk, rq)) { + if (blk_execute_rq(q, cdi->disk, rq, 0)) { struct request_sense *s = rq->sense; ret = -EIO; cdi->last_sense = s->sense_key; } - if (blk_rq_unmap_user(rq, bio, len)) + if (blk_rq_unmap_user(bio, len)) ret = -EFAULT; if (ret) @@ -2149,6 +2153,7 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf, ubuf += len; } + blk_put_request(rq); return ret; } diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 4f27e5519296..7333b41d4224 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -80,7 +80,7 @@ config SERIAL_NONSTANDARD config COMPUTONE tristate "Computone IntelliPort Plus serial support" - depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP + depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP && (BROKEN || !SPARC32) ---help--- This driver supports the entire family of Intelliport II/Plus controllers with the exception of the MicroChannel controllers and @@ -138,7 +138,7 @@ config CYZ_INTR config DIGIEPCA tristate "Digiboard Intelligent Async Support" - depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP + depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP && (!64BIT || BROKEN) ---help--- This is a driver for Digi International's Xx, Xeve, and Xem series of cards which provide multiple serial ports. You would need @@ -208,7 +208,7 @@ config SYNCLINK config SYNCLINKMP tristate "SyncLink Multiport support" - depends on SERIAL_NONSTANDARD + depends on SERIAL_NONSTANDARD && (BROKEN || !SPARC32) help Enable support for the SyncLink Multiport (2 or 4 ports) serial adapter, running asynchronous and HDLC communications up @@ -735,7 +735,7 @@ config SGI_IP27_RTC config GEN_RTC tristate "Generic /dev/rtc emulation" - depends on RTC!=y && !IA64 && !ARM && !PPC64 + depends on RTC!=y && !IA64 && !ARM && !PPC64 && !M32R && !SPARC32 ---help--- If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you 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) static int mmap_kmem(struct file * file, struct vm_area_struct * vma) { - unsigned long long val; + unsigned long pfn; + + /* Turn a kernel-virtual address into a physical page frame */ + pfn = __pa((u64)vma->vm_pgoff << PAGE_SHIFT) >> PAGE_SHIFT; + /* * RED-PEN: on some architectures there is more mapped memory * 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) * * RED-PEN: vmalloc is not supported right now. */ - if (!pfn_valid(vma->vm_pgoff)) + if (!pfn_valid(pfn)) return -EIO; - val = (u64)vma->vm_pgoff << PAGE_SHIFT; - vma->vm_pgoff = __pa(val) >> PAGE_SHIFT; + + vma->vm_pgoff = pfn; return mmap_mem(file, vma); } 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) void rtc_get_rtc_time(struct rtc_time *rtc_tm) { + unsigned long uip_watchdog = jiffies; unsigned char ctrl; #ifdef CONFIG_MACH_DECSTATION unsigned int real_year; @@ -1224,8 +1225,10 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm) * Once the read clears, read the RTC time (again via ioctl). Easy. */ - if (rtc_is_updating() != 0) - msleep(20); + while (rtc_is_updating() != 0 && jiffies - uip_watchdog < 2*HZ/100) { + barrier(); + cpu_relax(); + } /* * 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 obtained at: <http://sourceforge.net/projects/trousers>. To compile this driver as a module, choose M here; the module will be called tpm. If unsure, say N. + Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI_BUS + and CONFIG_PNPACPI. config TCG_NSC tristate "National Semiconductor TPM Interface" @@ -36,12 +38,13 @@ config TCG_ATMEL as a module, choose M here; the module will be called tpm_atmel. config TCG_INFINEON - tristate "Infineon Technologies SLD 9630 TPM Interface" - depends on TCG_TPM + tristate "Infineon Technologies TPM Interface" + depends on TCG_TPM && PNPACPI ---help--- If you have a TPM security chip from Infineon Technologies - say Yes and it will be accessible from within Linux. To - compile this driver as a module, choose M here; the module + (either SLD 9630 TT 1.1 or SLB 9635 TT 1.2) say Yes and it + will be accessible from within Linux. + To compile this driver as a module, choose M here; the module will be called tpm_infineon. Further information on this driver and the supported hardware 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 @@ /* * Description: * Device Driver for the Infineon Technologies - * SLD 9630 TT Trusted Platform Module + * SLD 9630 TT 1.1 and SLB 9635 TT 1.2 Trusted Platform Module * Specifications at www.trustedcomputinggroup.org * * Copyright (C) 2005, Marcel Selhorst <selhorst@crypto.rub.de> @@ -12,9 +12,10 @@ * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2 of the * License. - * */ +#include <acpi/acpi_bus.h> +#include <linux/pnp.h> #include "tpm.h" /* Infineon specific definitions */ @@ -26,8 +27,11 @@ #define TPM_MSLEEP_TIME 3 /* gives number of max. msleep()-calls before throwing timeout */ #define TPM_MAX_TRIES 5000 -#define TCPA_INFINEON_DEV_VEN_VALUE 0x15D1 -#define TPM_DATA (TPM_ADDR + 1) & 0xff +#define TPM_INFINEON_DEV_VEN_VALUE 0x15D1 + +/* These values will be filled after ACPI-call */ +static int TPM_INF_DATA = 0; +static int TPM_INF_ADDR = 0; /* TPM header definitions */ enum infineon_tpm_header { @@ -305,9 +309,10 @@ static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count) static void tpm_inf_cancel(struct tpm_chip *chip) { - /* Nothing yet! - This has something to do with the internal functions - of the TPM. Abort isn't really necessary... + /* + Since we are using the legacy mode to communicate + with the TPM, we have no cancel functions, but have + a workaround for interrupting the TPM through WTX. */ } @@ -345,6 +350,32 @@ static struct tpm_vendor_specific tpm_inf = { .miscdev = {.fops = &inf_ops,}, }; +static const struct pnp_device_id tpm_pnp_tbl[] = { + /* Infineon TPMs */ + {"IFX0101", 0}, + {"IFX0102", 0}, + {"", 0} +}; + +static int __devinit tpm_inf_acpi_probe(struct pnp_dev *dev, + const struct pnp_device_id *dev_id) +{ + TPM_INF_ADDR = (pnp_port_start(dev, 0) & 0xff); + TPM_INF_DATA = ((TPM_INF_ADDR + 1) & 0xff); + tpm_inf.base = pnp_port_start(dev, 1); + dev_info(&dev->dev, "Found %s with ID %s\n", + dev->name, dev_id->id); + if (!((tpm_inf.base >> 8) & 0xff)) + tpm_inf.base = 0; + return 0; +} + +static struct pnp_driver tpm_inf_pnp = { + .name = "tpm_inf_pnp", + .id_table = tpm_pnp_tbl, + .probe = tpm_inf_acpi_probe, +}; + static int __devinit tpm_inf_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) { @@ -353,64 +384,99 @@ static int __devinit tpm_inf_probe(struct pci_dev *pci_dev, int vendorid[2]; int version[2]; int productid[2]; + char chipname[20]; if (pci_enable_device(pci_dev)) return -EIO; dev_info(&pci_dev->dev, "LPC-bus found at 0x%x\n", pci_id->device); + /* read IO-ports from ACPI */ + pnp_register_driver(&tpm_inf_pnp); + pnp_unregister_driver(&tpm_inf_pnp); + + /* Make sure, we have received valid config ports */ + if (!TPM_INF_ADDR) { + pci_disable_device(pci_dev); + return -EIO; + } + /* query chip for its vendor, its version number a.s.o. */ - outb(ENABLE_REGISTER_PAIR, TPM_ADDR); - outb(IDVENL, TPM_ADDR); - vendorid[1] = inb(TPM_DATA); - outb(IDVENH, TPM_ADDR); - vendorid[0] = inb(TPM_DATA); - outb(IDPDL, TPM_ADDR); - productid[1] = inb(TPM_DATA); - outb(IDPDH, TPM_ADDR); - productid[0] = inb(TPM_DATA); - outb(CHIP_ID1, TPM_ADDR); - version[1] = inb(TPM_DATA); - outb(CHIP_ID2, TPM_ADDR); - version[0] = inb(TPM_DATA); - - if ((vendorid[0] << 8 | vendorid[1]) == (TCPA_INFINEON_DEV_VEN_VALUE)) { - - /* read IO-ports from TPM */ - outb(IOLIMH, TPM_ADDR); - ioh = inb(TPM_DATA); - outb(IOLIML, TPM_ADDR); - iol = inb(TPM_DATA); - tpm_inf.base = (ioh << 8) | iol; + outb(ENABLE_REGISTER_PAIR, TPM_INF_ADDR); + outb(IDVENL, TPM_INF_ADDR); + vendorid[1] = inb(TPM_INF_DATA); + outb(IDVENH, TPM_INF_ADDR); + vendorid[0] = inb(TPM_INF_DATA); + outb(IDPDL, TPM_INF_ADDR); + productid[1] = inb(TPM_INF_DATA); + outb(IDPDH, TPM_INF_ADDR); + productid[0] = inb(TPM_INF_DATA); + outb(CHIP_ID1, TPM_INF_ADDR); + version[1] = inb(TPM_INF_DATA); + outb(CHIP_ID2, TPM_INF_ADDR); + version[0] = inb(TPM_INF_DATA); + + switch ((productid[0] << 8) | productid[1]) { + case 6: + sprintf(chipname, " (SLD 9630 TT 1.1)"); + break; + case 11: + sprintf(chipname, " (SLB 9635 TT 1.2)"); + break; + default: + sprintf(chipname, " (unknown chip)"); + break; + } + chipname[19] = 0; + + if ((vendorid[0] << 8 | vendorid[1]) == (TPM_INFINEON_DEV_VEN_VALUE)) { if (tpm_inf.base == 0) { - dev_err(&pci_dev->dev, "No IO-ports set!\n"); + dev_err(&pci_dev->dev, "No IO-ports found!\n"); pci_disable_device(pci_dev); - return -ENODEV; + return -EIO; + } + /* configure TPM with IO-ports */ + outb(IOLIMH, TPM_INF_ADDR); + outb(((tpm_inf.base >> 8) & 0xff), TPM_INF_DATA); + outb(IOLIML, TPM_INF_ADDR); + outb((tpm_inf.base & 0xff), TPM_INF_DATA); + + /* control if IO-ports are set correctly */ + outb(IOLIMH, TPM_INF_ADDR); + ioh = inb(TPM_INF_DATA); + outb(IOLIML, TPM_INF_ADDR); + iol = inb(TPM_INF_DATA); + + if ((ioh << 8 | iol) != tpm_inf.base) { + dev_err(&pci_dev->dev, + "Could not set IO-ports to %04x\n", + tpm_inf.base); + pci_disable_device(pci_dev); + return -EIO; } /* activate register */ - outb(TPM_DAR, TPM_ADDR); - outb(0x01, TPM_DATA); - outb(DISABLE_REGISTER_PAIR, TPM_ADDR); + outb(TPM_DAR, TPM_INF_ADDR); + outb(0x01, TPM_INF_DATA); + outb(DISABLE_REGISTER_PAIR, TPM_INF_ADDR); /* disable RESET, LP and IRQC */ outb(RESET_LP_IRQC_DISABLE, tpm_inf.base + CMD); /* Finally, we're done, print some infos */ dev_info(&pci_dev->dev, "TPM found: " + "config base 0x%x, " "io base 0x%x, " "chip version %02x%02x, " "vendor id %x%x (Infineon), " "product id %02x%02x" "%s\n", + TPM_INF_ADDR, tpm_inf.base, version[0], version[1], vendorid[0], vendorid[1], - productid[0], productid[1], ((productid[0] == 0) - && (productid[1] == - 6)) ? - " (SLD 9630 TT 1.1)" : ""); + productid[0], productid[1], chipname); rc = tpm_register_hardware(pci_dev, &tpm_inf); if (rc < 0) { @@ -462,6 +528,6 @@ module_init(init_inf); module_exit(cleanup_inf); MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>"); -MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT"); -MODULE_VERSION("1.4"); +MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2"); +MODULE_VERSION("1.5"); MODULE_LICENSE("GPL"); diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 30d96739fb23..665103ccaee8 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -2433,7 +2433,7 @@ static int con_open(struct tty_struct *tty, struct file *filp) int ret = 0; acquire_console_sem(); - if (tty->count == 1) { + if (tty->driver_data == NULL) { ret = vc_allocate(currcons); if (ret == 0) { struct vc_data *vc = vc_cons[currcons].d; 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 @@ /* - * i8xx_tco 0.07: TCO timer driver for i8xx chipsets + * i8xx_tco: TCO timer driver for i8xx chipsets * * (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved. * http://www.kernelconcepts.de @@ -63,6 +63,9 @@ * 20050128 Wim Van Sebroeck <wim@iguana.be> * 0.07 Added support for the ICH4-M, ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW * chipsets. Also added support for the "undocumented" ICH7 chipset. + * 20050807 Wim Van Sebroeck <wim@iguana.be> + * 0.08 Make sure that the watchdog is only "armed" when started. + * (Kernel Bug 4251) */ /* @@ -87,7 +90,7 @@ #include "i8xx_tco.h" /* Module and version information */ -#define TCO_VERSION "0.07" +#define TCO_VERSION "0.08" #define TCO_MODULE_NAME "i8xx TCO timer" #define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION #define PFX TCO_MODULE_NAME ": " @@ -125,10 +128,18 @@ static int tco_timer_start (void) unsigned char val; spin_lock(&tco_lock); + + /* disable chipset's NO_REBOOT bit */ + pci_read_config_byte (i8xx_tco_pci, 0xd4, &val); + val &= 0xfd; + pci_write_config_byte (i8xx_tco_pci, 0xd4, val); + + /* Bit 11: TCO Timer Halt -> 0 = The TCO timer is enabled to count */ val = inb (TCO1_CNT + 1); val &= 0xf7; outb (val, TCO1_CNT + 1); val = inb (TCO1_CNT + 1); + spin_unlock(&tco_lock); if (val & 0x08) @@ -138,13 +149,20 @@ static int tco_timer_start (void) static int tco_timer_stop (void) { - unsigned char val; + unsigned char val, val1; spin_lock(&tco_lock); + /* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */ val = inb (TCO1_CNT + 1); val |= 0x08; outb (val, TCO1_CNT + 1); val = inb (TCO1_CNT + 1); + + /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ + pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1); + val1 |= 0x02; + pci_write_config_byte (i8xx_tco_pci, 0xd4, val1); + spin_unlock(&tco_lock); if ((val & 0x08) == 0) @@ -155,6 +173,7 @@ static int tco_timer_stop (void) static int tco_timer_keepalive (void) { spin_lock(&tco_lock); + /* Reload the timer by writing to the TCO Timer Reload register */ outb (0x01, TCO1_RLD); spin_unlock(&tco_lock); return 0; @@ -417,9 +436,8 @@ static unsigned char __init i8xx_tco_getdevice (void) printk (KERN_ERR PFX "failed to get TCOBASE address\n"); return 0; } - /* - * Check chipset's NO_REBOOT bit - */ + + /* Check chipset's NO_REBOOT bit */ pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1); if (val1 & 0x02) { val1 &= 0xfd; @@ -430,6 +448,10 @@ static unsigned char __init i8xx_tco_getdevice (void) return 0; /* Cannot reset NO_REBOOT bit */ } } + /* Disable reboots untill the watchdog starts */ + val1 |= 0x02; + pci_write_config_byte (i8xx_tco_pci, 0xd4, val1); + /* Set the TCO_EN bit in SMI_EN register */ if (!request_region (SMI_EN + 1, 1, "i8xx TCO")) { printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", @@ -505,17 +527,10 @@ out: static void __exit watchdog_cleanup (void) { - u8 val; - /* Stop the timer before we leave */ if (!nowayout) tco_timer_stop (); - /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ - pci_read_config_byte (i8xx_tco_pci, 0xd4, &val); - val |= 0x02; - pci_write_config_byte (i8xx_tco_pci, 0xd4, val); - /* Deregister */ misc_deregister (&i8xx_tco_miscdev); 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 @@ #include <asm/uaccess.h> #define OSCR_FREQ CLOCK_TICK_RATE -#define SA1100_CLOSE_MAGIC (0x5afc4453) static unsigned long sa1100wdt_users; -static int expect_close; static int pre_margin; static int boot_status; -static int nowayout = WATCHDOG_NOWAYOUT; /* * Allow only one person to hold it open @@ -62,55 +59,33 @@ static int sa1100dog_open(struct inode *inode, struct file *file) } /* - * Shut off the timer. - * Lock it in if it's a module and we defined ...NOWAYOUT - * Oddly, the watchdog can only be enabled, but we can turn off - * the interrupt, which appears to prevent the watchdog timing out. + * The watchdog cannot be disabled. + * + * Previous comments suggested that turning off the interrupt by + * clearing OIER[E3] would prevent the watchdog timing out but this + * does not appear to be true (at least on the PXA255). */ static int sa1100dog_release(struct inode *inode, struct file *file) { - OSMR3 = OSCR + pre_margin; - - if (expect_close == SA1100_CLOSE_MAGIC) { - OIER &= ~OIER_E3; - } else { - printk(KERN_CRIT "WATCHDOG: WDT device closed unexpectedly. WDT will not stop!\n"); - } + printk(KERN_CRIT "WATCHDOG: Device closed - timer will not stop\n"); clear_bit(1, &sa1100wdt_users); - expect_close = 0; return 0; } static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos) { - if (len) { - if (!nowayout) { - size_t i; - - expect_close = 0; - - for (i = 0; i != len; i++) { - char c; - - if (get_user(c, data + i)) - return -EFAULT; - if (c == 'V') - expect_close = SA1100_CLOSE_MAGIC; - } - } + if (len) /* Refresh OSMR3 timer. */ OSMR3 = OSCR + pre_margin; - } return len; } static struct watchdog_info ident = { - .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | - WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, - .identity = "SA1100 Watchdog", + .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, + .identity = "SA1100/PXA255 Watchdog", }; static int sa1100dog_ioctl(struct inode *inode, struct file *file, @@ -172,7 +147,7 @@ static struct file_operations sa1100dog_fops = static struct miscdevice sa1100dog_miscdev = { .minor = WATCHDOG_MINOR, - .name = "SA1100/PXA2xx watchdog", + .name = "watchdog", .fops = &sa1100dog_fops, }; @@ -194,7 +169,6 @@ static int __init sa1100dog_init(void) if (ret == 0) printk("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n", margin); - return ret; } @@ -212,8 +186,5 @@ MODULE_DESCRIPTION("SA1100/PXA2xx Watchdog"); module_param(margin, int, 0); MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)"); -module_param(nowayout, int, 0); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); - MODULE_LICENSE("GPL"); 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) return FAILED; } fc->rst_pkt->eh_state = SCSI_STATE_UNUSED; - return SUCCESS; #endif + return SUCCESS; } static int __fcp_scsi_host_reset(Scsi_Cmnd *SCpnt) diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c index 4fa17c76eea2..c8a7f47911f9 100644 --- a/drivers/hwmon/adm1026.c +++ b/drivers/hwmon/adm1026.c @@ -325,7 +325,7 @@ int adm1026_attach_adapter(struct i2c_adapter *adapter) int adm1026_detach_client(struct i2c_client *client) { i2c_detach_client(client); - kfree(client); + kfree(i2c_get_clientdata(client)); return 0; } @@ -1691,7 +1691,7 @@ int adm1026_detect(struct i2c_adapter *adapter, int address, /* Error out and cleanup code */ exitfree: - kfree(new_client); + kfree(data); exit: return err; } diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c index 9168e983ca1d..936250957270 100644 --- a/drivers/hwmon/adm1031.c +++ b/drivers/hwmon/adm1031.c @@ -834,7 +834,7 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind) return 0; exit_free: - kfree(new_client); + kfree(data); exit: return err; } @@ -845,7 +845,7 @@ static int adm1031_detach_client(struct i2c_client *client) if ((ret = i2c_detach_client(client)) != 0) { return ret; } - kfree(client); + kfree(i2c_get_clientdata(client)); return 0; } diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c index 5c68e9c311aa..ce2a6eb93f6e 100644 --- a/drivers/hwmon/adm9240.c +++ b/drivers/hwmon/adm9240.c @@ -616,7 +616,7 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind) return 0; exit_free: - kfree(new_client); + kfree(data); exit: return err; } diff --git a/drivers/hwmon/fscpos.c b/drivers/hwmon/fscpos.c index 270015b626ad..301ae98bd0ad 100644 --- a/drivers/hwmon/fscpos.c +++ b/drivers/hwmon/fscpos.c @@ -167,7 +167,7 @@ static ssize_t set_temp_reset(struct i2c_client *client, struct fscpos_data "experience to the module author.\n"); /* Supported value: 2 (clears the status) */ - fscpos_write_value(client, FSCPOS_REG_TEMP_STATE[nr], 2); + fscpos_write_value(client, FSCPOS_REG_TEMP_STATE[nr - 1], 2); return count; } diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c index 251ac2659554..fdeeb3ab6f2f 100644 --- a/drivers/hwmon/smsc47b397.c +++ b/drivers/hwmon/smsc47b397.c @@ -298,7 +298,7 @@ static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind) return 0; error_free: - kfree(new_client); + kfree(data); error_release: release_region(addr, SMSC_EXTENT); return err; diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c index 897117a7213f..7166ad0b2fda 100644 --- a/drivers/hwmon/smsc47m1.c +++ b/drivers/hwmon/smsc47m1.c @@ -495,7 +495,7 @@ static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind) return 0; error_free: - kfree(new_client); + kfree(data); error_release: release_region(address, SMSC_EXTENT); return err; 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) module_init(fsl_i2c_init); module_exit(fsl_i2c_exit); -static int fsl_i2c_probe(struct device *device) -{ - int result = 0; - struct mpc_i2c *i2c; - struct platform_device *pdev = to_platform_device(device); - struct fsl_i2c_platform_data *pdata; - struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data; - - if (!(i2c = kmalloc(sizeof(*i2c), GFP_KERNEL))) { - return -ENOMEM; - } - memset(i2c, 0, sizeof(*i2c)); - - i2c->irq = platform_get_irq(pdev, 0); - i2c->flags = pdata->device_flags; - init_waitqueue_head(&i2c->queue); - - i2c->base = ioremap((phys_addr_t)r->start, MPC_I2C_REGION); - - if (!i2c->base) { - printk(KERN_ERR "i2c-mpc - failed to map controller\n"); - result = -ENOMEM; - goto fail_map; - } - - if (i2c->irq != 0) - if ((result = request_irq(i2c->irq, mpc_i2c_isr, - SA_SHIRQ, "i2c-mpc", i2c)) < 0) { - printk(KERN_ERR - "i2c-mpc - failed to attach interrupt\n"); - goto fail_irq; - } - - mpc_i2c_setclock(i2c); - dev_set_drvdata(device, i2c); - - i2c->adap = mpc_ops; - i2c_set_adapdata(&i2c->adap, i2c); - i2c->adap.dev.parent = &pdev->dev; - if ((result = i2c_add_adapter(&i2c->adap)) < 0) { - printk(KERN_ERR "i2c-mpc - failed to add adapter\n"); - goto fail_add; - } - - return result; - - fail_add: - if (i2c->irq != 0) - free_irq(i2c->irq, NULL); - fail_irq: - iounmap(i2c->base); - fail_map: - kfree(i2c); - return result; -}; - -static int fsl_i2c_remove(struct device *device) -{ - struct mpc_i2c *i2c = dev_get_drvdata(device); - - i2c_del_adapter(&i2c->adap); - dev_set_drvdata(device, NULL); - - if (i2c->irq != 0) - free_irq(i2c->irq, i2c); - - iounmap(i2c->base); - kfree(i2c); - return 0; -}; - -/* Structure for a device driver */ -static struct device_driver fsl_i2c_driver = { - .name = "fsl-i2c", - .bus = &platform_bus_type, - .probe = fsl_i2c_probe, - .remove = fsl_i2c_remove, -}; - -static int __init fsl_i2c_init(void) -{ - return driver_register(&fsl_i2c_driver); -} - -static void __exit fsl_i2c_exit(void) -{ - driver_unregister(&fsl_i2c_driver); -} - -module_init(fsl_i2c_init); -module_exit(fsl_i2c_exit); - MODULE_AUTHOR("Adrian Cox <adrian@humboldt.co.uk>"); MODULE_DESCRIPTION ("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 @@ #include <asm/sibyte/sb1250_smbus.h> static struct i2c_algo_sibyte_data sibyte_board_data[2] = { - { NULL, 0, (void *) (KSEG1+A_SMB_BASE(0)) }, - { NULL, 1, (void *) (KSEG1+A_SMB_BASE(1)) } + { NULL, 0, (void *) (CKSEG1+A_SMB_BASE(0)) }, + { NULL, 1, (void *) (CKSEG1+A_SMB_BASE(1)) } }; static struct i2c_adapter sibyte_board_adapter[2] = { diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 5f33df47aa74..1cadd2c3cadd 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -764,6 +764,7 @@ config BLK_DEV_IDE_PMAC_ATA100FIRST config BLK_DEV_IDEDMA_PMAC bool "PowerMac IDE DMA support" depends on BLK_DEV_IDE_PMAC + select BLK_DEV_IDEDMA_PCI help This option allows the driver for the built-in IDE controller on Power Macintoshes and PowerBooks to use DMA (direct memory access) diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index f9c1acb4ed6a..234f5de3e929 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -754,7 +754,7 @@ static int idedisk_issue_flush(request_queue_t *q, struct gendisk *disk, idedisk_prepare_flush(q, rq); - ret = blk_execute_rq(q, disk, rq); + ret = blk_execute_rq(q, disk, rq, 0); /* * if we failed and caller wants error offset, get it @@ -1220,7 +1220,7 @@ static int ide_disk_probe(struct device *dev) goto failed; g = alloc_disk_node(1 << PARTN_BITS, - pcibus_to_node(drive->hwif->pci_dev->bus)); + hwif_to_node(drive->hwif)); if (!g) goto out_free_idkp; diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 9eab6426148e..29c22fc278c6 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -317,7 +317,7 @@ typedef struct ide_floppy_obj { unsigned long flags; } idefloppy_floppy_t; -#define IDEFLOPPY_TICKS_DELAY 3 /* default delay for ZIP 100 */ +#define IDEFLOPPY_TICKS_DELAY HZ/20 /* default delay for ZIP 100 (50ms) */ /* * Floppy flag bits values. 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) * do not. */ - q = blk_init_queue_node(do_ide_request, &ide_lock, - pcibus_to_node(drive->hwif->pci_dev->bus)); + q = blk_init_queue_node(do_ide_request, &ide_lock, hwif_to_node(hwif)); if (!q) return 1; @@ -1048,6 +1047,8 @@ static int init_irq (ide_hwif_t *hwif) BUG_ON(in_interrupt()); BUG_ON(irqs_disabled()); + BUG_ON(hwif == NULL); + down(&ide_cfg_sem); hwif->hwgroup = NULL; #if MAX_HWIFS > 1 @@ -1097,7 +1098,7 @@ static int init_irq (ide_hwif_t *hwif) spin_unlock_irq(&ide_lock); } else { hwgroup = kmalloc_node(sizeof(ide_hwgroup_t), GFP_KERNEL, - pcibus_to_node(hwif->drives[0].hwif->pci_dev->bus)); + hwif_to_node(hwif->drives[0].hwif)); if (!hwgroup) goto out_up; 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) BUG_ON(dev_list != NULL); } -module_init(init_ide_cs); +late_initcall(init_ide_cs); module_exit(exit_ide_cs); diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c index da46577380f3..6e3ab0c38c4d 100644 --- a/drivers/ide/pci/generic.c +++ b/drivers/ide/pci/generic.c @@ -173,6 +173,12 @@ static ide_pci_device_t generic_chipsets[] __devinitdata = { .channels = 2, .autodma = NOAUTODMA, .bootable = ON_BOARD, + },{ /* 14 */ + .name = "Revolution", + .init_hwif = init_hwif_generic, + .channels = 2, + .autodma = AUTODMA, + .bootable = OFF_BOARD, } }; @@ -231,6 +237,7 @@ static struct pci_device_id generic_pci_tbl[] = { { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11}, { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12}, { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13}, + { PCI_VENDOR_ID_NETCELL,PCI_DEVICE_ID_REVOLUTION, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14}, /* Must come last. If you add entries adjust this table appropriately and the init_one code */ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 0}, { 0, }, diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c index c6f5fa4b4ca6..ff2e217a8c84 100644 --- a/drivers/ide/pci/serverworks.c +++ b/drivers/ide/pci/serverworks.c @@ -21,6 +21,9 @@ * * CSB6: `Champion South Bridge' IDE Interface (optional: third channel) * + * HT1000: AKA BCM5785 - Hypertransport Southbridge for Opteron systems. IDE + * controller same as the CSB6. Single channel ATA100 only. + * * Documentation: * Available under NDA only. Errata info very hard to get. * @@ -71,6 +74,8 @@ static u8 svwks_ratemask (ide_drive_t *drive) if (!svwks_revision) pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision); + if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE) + return 2; if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { u32 reg = 0; if (isa_dev) @@ -109,6 +114,7 @@ static u8 svwks_csb_check (struct pci_dev *dev) case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE: case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2: + case PCI_DEVICE_ID_SERVERWORKS_HT1000IDE: return 1; default: break; @@ -438,6 +444,13 @@ static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const cha btr |= (svwks_revision >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2; pci_write_config_byte(dev, 0x5A, btr); } + /* Setup HT1000 SouthBridge Controller - Single Channel Only */ + else if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE) { + pci_read_config_byte(dev, 0x5A, &btr); + btr &= ~0x40; + btr |= 0x3; + pci_write_config_byte(dev, 0x5A, btr); + } return (dev->irq) ? dev->irq : 0; } @@ -629,6 +642,15 @@ static ide_pci_device_t serverworks_chipsets[] __devinitdata = { .channels = 1, /* 2 */ .autodma = AUTODMA, .bootable = ON_BOARD, + },{ /* 4 */ + .name = "SvrWks HT1000", + .init_setup = init_setup_svwks, + .init_chipset = init_chipset_svwks, + .init_hwif = init_hwif_svwks, + .init_dma = init_dma_svwks, + .channels = 1, /* 2 */ + .autodma = AUTODMA, + .bootable = ON_BOARD, } }; @@ -653,6 +675,7 @@ static struct pci_device_id svwks_pci_tbl[] = { { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, + { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, { 0, }, }; MODULE_DEVICE_TABLE(pci, svwks_pci_tbl); diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index be0fcc8f4b15..ea65b070a367 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -1664,7 +1664,7 @@ static struct macio_driver pmac_ide_macio_driver = }; static struct pci_device_id pmac_ide_pci_match[] = { - { PCI_VENDOR_ID_APPLE, PCI_DEVIEC_ID_APPLE_UNI_N_ATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_ATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_SH_ATA, diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 77da827b2898..18ed7765417c 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -229,6 +229,7 @@ second_chance_to_dma: case PCI_DEVICE_ID_AMD_VIPER_7409: case PCI_DEVICE_ID_CMD_643: case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: + case PCI_DEVICE_ID_REVOLUTION: simplex_stat = hwif->INB(dma_base + 2); hwif->OUTB((simplex_stat&0x60),(dma_base + 2)); simplex_stat = hwif->INB(dma_base + 2); diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index b12a970cc9a3..27018c8efc24 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -478,7 +478,6 @@ static void ohci_initialize(struct ti_ohci *ohci) int num_ports, i; spin_lock_init(&ohci->phy_reg_lock); - spin_lock_init(&ohci->event_lock); /* Put some defaults to these undefined bus options */ buf = reg_read(ohci, OHCI1394_BusOptions); @@ -3402,7 +3401,14 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev, /* We hopefully don't have to pre-allocate IT DMA like we did * for IR DMA above. Allocate it on-demand and mark inactive. */ ohci->it_legacy_context.ohci = NULL; + spin_lock_init(&ohci->event_lock); + /* + * interrupts are disabled, all right, but... due to SA_SHIRQ we + * might get called anyway. We'll see no event, of course, but + * we need to get to that "no event", so enough should be initialized + * by that point. + */ if (request_irq(dev->irq, ohci_irq_handler, SA_SHIRQ, OHCI1394_DRIVER_NAME, ohci)) FAIL(-ENOMEM, "Failed to allocate shared interrupt %d", dev->irq); diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig index 79c8e2dd9c33..32cdfb30e9b4 100644 --- a/drivers/infiniband/Kconfig +++ b/drivers/infiniband/Kconfig @@ -1,6 +1,7 @@ menu "InfiniBand support" config INFINIBAND + depends on PCI || BROKEN tristate "InfiniBand support" ---help--- Core support for InfiniBand (IB). Make sure to also select diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index eb99e693dec2..5f6e9ea29cd7 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -130,13 +130,14 @@ static int ib_dealloc_ucontext(struct ib_ucontext *context) list_for_each_entry_safe(uobj, tmp, &context->mr_list, list) { struct ib_mr *mr = idr_find(&ib_uverbs_mr_idr, uobj->id); + struct ib_device *mrdev = mr->device; struct ib_umem_object *memobj; idr_remove(&ib_uverbs_mr_idr, uobj->id); ib_dereg_mr(mr); memobj = container_of(uobj, struct ib_umem_object, uobject); - ib_umem_release_on_close(mr->device, &memobj->umem); + ib_umem_release_on_close(mrdev, &memobj->umem); list_del(&uobj->list); kfree(memobj); 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 { IB_CM_REJ_INVALID_ALT_TRAFFIC_CLASS = __constant_htons(21), IB_CM_REJ_INVALID_ALT_HOP_LIMIT = __constant_htons(22), IB_CM_REJ_INVALID_ALT_PACKET_RATE = __constant_htons(23), - IB_CM_REJ_PORT_REDIRECT = __constant_htons(24), + IB_CM_REJ_PORT_CM_REDIRECT = __constant_htons(24), + IB_CM_REJ_PORT_REDIRECT = __constant_htons(25), IB_CM_REJ_INVALID_MTU = __constant_htons(26), IB_CM_REJ_INSUFFICIENT_RESP_RESOURCES = __constant_htons(27), 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) ipoib_mcast_send(dev, (union ib_gid *) (phdr->hwaddr + 4), skb); } else { - /* unicast GID -- should be ARP reply */ + /* unicast GID -- should be ARP or RARP reply */ - if (be16_to_cpup((u16 *) skb->data) != ETH_P_ARP) { + if ((be16_to_cpup((__be16 *) skb->data) != ETH_P_ARP) && + (be16_to_cpup((__be16 *) skb->data) != ETH_P_RARP)) { ipoib_warn(priv, "Unicast, no %s: type %04x, QPN %06x " IPOIB_GID_FMT "\n", 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) static void __exit ns558_exit(void) { - struct ns558 *ns558; + struct ns558 *ns558, *safe; - list_for_each_entry(ns558, &ns558_list, node) { + list_for_each_entry_safe(ns558, safe, &ns558_list, node) { gameport_unregister_port(ns558->gameport); release_region(ns558->io & ~(ns558->size - 1), ns558->size); kfree(ns558); diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c index f8570fd9d2ab..3abd7fc6e5ef 100644 --- a/drivers/isdn/capi/capifs.c +++ b/drivers/isdn/capi/capifs.c @@ -191,8 +191,10 @@ static int __init capifs_init(void) err = register_filesystem(&capifs_fs_type); if (!err) { capifs_mnt = kern_mount(&capifs_fs_type); - if (IS_ERR(capifs_mnt)) + if (IS_ERR(capifs_mnt)) { err = PTR_ERR(capifs_mnt); + unregister_filesystem(&capifs_fs_type); + } } if (!err) printk(KERN_NOTICE "capifs: Rev %s\n", rev); diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig index 6c7b8bffc6fd..801c98f30e5c 100644 --- a/drivers/isdn/hisax/Kconfig +++ b/drivers/isdn/hisax/Kconfig @@ -134,6 +134,7 @@ config HISAX_AVM_A1 config HISAX_FRITZPCI bool "AVM PnP/PCI (Fritz!PnP/PCI)" + depends on BROKEN || !PPC64 help This enables HiSax support for the AVM "Fritz!PnP" and "Fritz!PCI". See <file:Documentation/isdn/README.HiSax> on how to configure it. 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) { isdn_ctrl cmd; icn_card *card = cards; - icn_card *last; + icn_card *last, *tmpcard; int i; unsigned long flags; @@ -1670,8 +1670,9 @@ static void __exit icn_exit(void) for (i = 0; i < ICN_BCH; i++) icn_free_queue(card, i); } - card = card->next; + tmpcard = card->next; spin_unlock_irqrestore(&card->lock, flags); + card = tmpcard; } card = cards; cards = NULL; diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig index 65ab64c43b3e..bc3e096d84f7 100644 --- a/drivers/macintosh/Kconfig +++ b/drivers/macintosh/Kconfig @@ -103,7 +103,7 @@ config PMAC_MEDIABAY # on non-powerbook machines (but only on PMU based ones AFAIK) config PMAC_BACKLIGHT bool "Backlight control for LCD screens" - depends on ADB_PMU + depends on ADB_PMU && (BROKEN || !PPC64) help Say Y here to build in code to manage the LCD backlight on a Macintosh PowerBook. With this code, the backlight will be turned 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) return 0; } -static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, - unsigned long sectors, int in_sync); +static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset); /* * bitmap_init_from_disk -- called at bitmap_create time to initialize * the in-memory bitmap from the on-disk bitmap -- also, sets up the * memory mapping of the bitmap file @@ -828,7 +827,7 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, * previously kicked from the array, we mark all the bits as * 1's in order to cause a full resync. */ -static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync) +static int bitmap_init_from_disk(struct bitmap *bitmap) { unsigned long i, chunks, index, oldindex, bit; struct page *page = NULL, *oldpage = NULL; @@ -929,8 +928,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync) } if (test_bit(bit, page_address(page))) { /* if the disk bit is set, set the memory bit */ - bitmap_set_memory_bits(bitmap, - i << CHUNK_BLOCK_SHIFT(bitmap), 1, in_sync); + bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap)); bit_cnt++; } } @@ -1426,35 +1424,53 @@ void bitmap_close_sync(struct bitmap *bitmap) } } -static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, - unsigned long sectors, int in_sync) +static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset) { /* For each chunk covered by any of these sectors, set the - * counter to 1 and set resync_needed unless in_sync. They should all + * counter to 1 and set resync_needed. They should all * be 0 at this point */ - while (sectors) { - int secs; - bitmap_counter_t *bmc; - spin_lock_irq(&bitmap->lock); - bmc = bitmap_get_counter(bitmap, offset, &secs, 1); - if (!bmc) { - spin_unlock_irq(&bitmap->lock); - return; - } - if (! *bmc) { - struct page *page; - *bmc = 1 | (in_sync? 0 : NEEDED_MASK); - bitmap_count_page(bitmap, offset, 1); - page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)); - set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN); - } + + int secs; + bitmap_counter_t *bmc; + spin_lock_irq(&bitmap->lock); + bmc = bitmap_get_counter(bitmap, offset, &secs, 1); + if (!bmc) { spin_unlock_irq(&bitmap->lock); - if (sectors > secs) - sectors -= secs; - else - sectors = 0; + return; + } + if (! *bmc) { + struct page *page; + *bmc = 1 | NEEDED_MASK; + bitmap_count_page(bitmap, offset, 1); + page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)); + set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN); } + spin_unlock_irq(&bitmap->lock); + +} + +/* + * flush out any pending updates + */ +void bitmap_flush(mddev_t *mddev) +{ + struct bitmap *bitmap = mddev->bitmap; + int sleep; + + if (!bitmap) /* there was no bitmap */ + return; + + /* run the daemon_work three time to ensure everything is flushed + * that can be + */ + sleep = bitmap->daemon_sleep; + bitmap->daemon_sleep = 0; + bitmap_daemon_work(bitmap); + bitmap_daemon_work(bitmap); + bitmap_daemon_work(bitmap); + bitmap->daemon_sleep = sleep; + bitmap_update_sb(bitmap); } /* @@ -1565,7 +1581,8 @@ int bitmap_create(mddev_t *mddev) /* now that we have some pages available, initialize the in-memory * bitmap from the on-disk bitmap */ - err = bitmap_init_from_disk(bitmap, mddev->recovery_cp == MaxSector); + err = bitmap_init_from_disk(bitmap); + if (err) return err; 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) if (r) return r; - _kmirrord_wq = create_workqueue("kmirrord"); + _kmirrord_wq = create_singlethread_workqueue("kmirrord"); if (!_kmirrord_wq) { DMERR("couldn't start kmirrord"); dm_dirty_log_exit(); diff --git a/drivers/md/md.c b/drivers/md/md.c index 6580e0fa4a47..20ca80b7dc20 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -256,8 +256,7 @@ static inline void mddev_unlock(mddev_t * mddev) { up(&mddev->reconfig_sem); - if (mddev->thread) - md_wakeup_thread(mddev->thread); + md_wakeup_thread(mddev->thread); } mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr) @@ -623,6 +622,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev) mddev->raid_disks = sb->raid_disks; mddev->size = sb->size; mddev->events = md_event(sb); + mddev->bitmap_offset = 0; if (sb->state & (1<<MD_SB_CLEAN)) mddev->recovery_cp = MaxSector; @@ -938,6 +938,7 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) mddev->raid_disks = le32_to_cpu(sb->raid_disks); mddev->size = le64_to_cpu(sb->size)/2; mddev->events = le64_to_cpu(sb->events); + mddev->bitmap_offset = 0; mddev->recovery_cp = le64_to_cpu(sb->resync_offset); memcpy(mddev->uuid, sb->set_uuid, 16); @@ -1688,6 +1689,7 @@ static int do_md_run(mddev_t * mddev) mddev->pers = pers[pnum]; spin_unlock(&pers_lock); + mddev->recovery = 0; mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */ /* before we start the array running, initialise the bitmap */ @@ -1712,6 +1714,7 @@ static int do_md_run(mddev_t * mddev) mddev->in_sync = 1; set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); + md_wakeup_thread(mddev->thread); if (mddev->sb_dirty) md_update_sb(mddev); @@ -1798,6 +1801,8 @@ static int do_md_stop(mddev_t * mddev, int ro) goto out; mddev->ro = 1; } else { + bitmap_flush(mddev); + wait_event(mddev->sb_wait, atomic_read(&mddev->pending_writes)==0); if (mddev->ro) set_disk_ro(disk, 0); blk_queue_make_request(mddev->queue, md_fail_request); @@ -1822,6 +1827,7 @@ static int do_md_stop(mddev_t * mddev, int ro) fput(mddev->bitmap_file); mddev->bitmap_file = NULL; } + mddev->bitmap_offset = 0; /* * Free resources if final stop @@ -2231,8 +2237,7 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) export_rdev(rdev); set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); - if (mddev->thread) - md_wakeup_thread(mddev->thread); + md_wakeup_thread(mddev->thread); return err; } @@ -3484,7 +3489,6 @@ static void md_do_sync(mddev_t *mddev) goto skip; } ITERATE_MDDEV(mddev2,tmp) { - printk("."); if (mddev2 == mddev) continue; if (mddev2->curr_resync && @@ -4007,3 +4011,5 @@ EXPORT_SYMBOL(md_wakeup_thread); EXPORT_SYMBOL(md_print_devices); EXPORT_SYMBOL(md_check_recovery); MODULE_LICENSE("GPL"); +MODULE_ALIAS("md"); +MODULE_ALIAS_BLOCKDEV_MAJOR(MD_MAJOR); 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) if (!uptodate) { md_error(r1_bio->mddev, conf->mirrors[r1_bio->read_disk].rdev); - set_bit(R1BIO_Degraded, &r1_bio->state); } else set_bit(R1BIO_Uptodate, &r1_bio->state); 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) mirror = i; break; } - if (!uptodate) { + if (!uptodate) md_error(mddev, conf->mirrors[mirror].rdev); - set_bit(R1BIO_Degraded, &r1_bio->state); - } + update_head_pos(mirror, r1_bio); 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 int i; int write_targets = 0; int sync_blocks; + int still_degraded = 0; if (!conf->r1buf_pool) { @@ -1137,7 +1136,10 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i return 0; } - if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, mddev->degraded) && + /* before building a request, check if we can skip these blocks.. + * This call the bitmap_start_sync doesn't actually record anything + */ + if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) && !conf->fullsync) { /* We can skip this block, and probably several more */ *skipped = 1; @@ -1203,24 +1205,23 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i if (i == disk) { bio->bi_rw = READ; bio->bi_end_io = end_sync_read; - } else if (conf->mirrors[i].rdev && - !conf->mirrors[i].rdev->faulty && - (!conf->mirrors[i].rdev->in_sync || - sector_nr + RESYNC_SECTORS > mddev->recovery_cp)) { + } else if (conf->mirrors[i].rdev == NULL || + conf->mirrors[i].rdev->faulty) { + still_degraded = 1; + continue; + } else if (!conf->mirrors[i].rdev->in_sync || + sector_nr + RESYNC_SECTORS > mddev->recovery_cp) { bio->bi_rw = WRITE; bio->bi_end_io = end_sync_write; write_targets ++; } else + /* no need to read or write here */ continue; bio->bi_sector = sector_nr + conf->mirrors[i].rdev->data_offset; bio->bi_bdev = conf->mirrors[i].rdev->bdev; bio->bi_private = r1_bio; } - if (write_targets + 1 < conf->raid_disks) - /* array degraded, can't clear bitmap */ - set_bit(R1BIO_Degraded, &r1_bio->state); - if (write_targets == 0) { /* There is nowhere to write, so all non-sync * 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 break; if (sync_blocks == 0) { if (!bitmap_start_sync(mddev->bitmap, sector_nr, - &sync_blocks, mddev->degraded) && + &sync_blocks, still_degraded) && !conf->fullsync) break; 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) /* device size must be a multiple of chunk size */ mddev->size &= ~(mddev->chunk_size/1024 -1); + mddev->resync_max_sectors = mddev->size << 1; if (!conf->chunk_size || conf->chunk_size % 4) { 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) /* device size must be a multiple of chunk size */ mddev->size &= ~(mddev->chunk_size/1024 -1); + mddev->resync_max_sectors = mddev->size << 1; if (conf->raid_disks < 4) { printk(KERN_ERR "raid6: not enough configured devices for %s (%d, minimum 4)\n", diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c index 63b626f70c81..9b9d6f8ee74e 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-common.c +++ b/drivers/media/dvb/dvb-usb/dibusb-common.c @@ -70,13 +70,22 @@ EXPORT_SYMBOL(dibusb_power_ctrl); int dibusb2_0_streaming_ctrl(struct dvb_usb_device *d, int onoff) { - u8 b[2]; - b[0] = DIBUSB_REQ_SET_IOCTL; - b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM; + u8 b[3] = { 0 }; + int ret; + + if ((ret = dibusb_streaming_ctrl(d,onoff)) < 0) + return ret; - dvb_usb_generic_write(d,b,3); + if (onoff) { + b[0] = DIBUSB_REQ_SET_STREAMING_MODE; + b[1] = 0x00; + if ((ret = dvb_usb_generic_write(d,b,2)) < 0) + return ret; + } - return dibusb_streaming_ctrl(d,onoff); + b[0] = DIBUSB_REQ_SET_IOCTL; + b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM; + return dvb_usb_generic_write(d,b,3); } EXPORT_SYMBOL(dibusb2_0_streaming_ctrl); diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c index 3491ff40885c..6fa92100248b 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c @@ -23,12 +23,12 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) */ if (newfeedcount == 0) { deb_ts("stop feeding\n"); + dvb_usb_urb_kill(d); if (d->props.streaming_ctrl != NULL) if ((ret = d->props.streaming_ctrl(d,0))) err("error while stopping stream."); - dvb_usb_urb_kill(d); } d->feedcount = newfeedcount; @@ -44,6 +44,8 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) * for reception. */ if (d->feedcount == onoff && d->feedcount > 0) { + deb_ts("submitting all URBs\n"); + dvb_usb_urb_submit(d); deb_ts("controlling pid parser\n"); if (d->props.caps & DVB_USB_HAS_PID_FILTER && @@ -59,7 +61,6 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) return -ENODEV; } - dvb_usb_urb_submit(d); } return 0; } 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 support this frontend. config DVB_LGDT330X - tristate "LGDT3302 or LGDT3303 based (DViCO FusionHDTV Gold)" + tristate "LG Electronics LGDT3302/LGDT3303 based" depends on DVB_CORE help 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 = { }; EXPORT_SYMBOL(dvb_pll_tua6034); +/* Infineon TUA6034 + * used in LG Innotek TDVS-H062F + */ +struct dvb_pll_desc dvb_pll_tdvs_tua6034 = { + .name = "LG/Infineon TUA6034", + .min = 54000000, + .max = 863000000, + .count = 3, + .entries = { + { 160000000, 44000000, 62500, 0xce, 0x01 }, + { 455000000, 44000000, 62500, 0xce, 0x02 }, + { 999999999, 44000000, 62500, 0xce, 0x04 }, + }, +}; +EXPORT_SYMBOL(dvb_pll_tdvs_tua6034); + /* Philips FMD1216ME * used in Medion Hybrid PCMCIA card and USB Box */ 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; extern struct dvb_pll_desc dvb_pll_tua6010xs; extern struct dvb_pll_desc dvb_pll_env57h1xd5; extern struct dvb_pll_desc dvb_pll_tua6034; +extern struct dvb_pll_desc dvb_pll_tdvs_tua6034; extern struct dvb_pll_desc dvb_pll_tda665x; extern struct dvb_pll_desc dvb_pll_fmd1216me; 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 @@ /* - * Support for LGDT3302 & LGDT3303 (DViCO FusionHDTV Gold) - VSB/QAM + * Support for LGDT3302 and LGDT3303 - VSB/QAM * * Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.net> * - * Based on code from Kirk Lapray <kirk_lapray@bigfoot.com> - * Copyright (C) 2005 - * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -25,11 +22,13 @@ /* * NOTES ABOUT THIS DRIVER * - * This driver supports DViCO FusionHDTV Gold under Linux. + * This Linux driver supports: + * DViCO FusionHDTV 3 Gold-Q + * DViCO FusionHDTV 3 Gold-T + * DViCO FusionHDTV 5 Gold * * TODO: - * BER and signal strength always return 0. - * Include support for LGDT3303 + * signal strength always returns 0. * */ @@ -41,7 +40,6 @@ #include <asm/byteorder.h> #include "dvb_frontend.h" -#include "dvb-pll.h" #include "lgdt330x_priv.h" #include "lgdt330x.h" @@ -70,55 +68,37 @@ struct lgdt330x_state u32 current_frequency; }; -static int i2c_writebytes (struct lgdt330x_state* state, - u8 addr, /* demod_address or pll_address */ +static int i2c_write_demod_bytes (struct lgdt330x_state* state, u8 *buf, /* data bytes to send */ int len /* number of bytes to send */ ) { - u8 tmp[] = { buf[0], buf[1] }; struct i2c_msg msg = - { .addr = addr, .flags = 0, .buf = tmp, .len = 2 }; - int err; + { .addr = state->config->demod_address, + .flags = 0, + .buf = buf, + .len = 2 }; int i; + int err; - for (i=1; i<len; i++) { - tmp[1] = buf[i]; + for (i=0; i<len-1; i+=2){ if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { - printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err == %i)\n", __FUNCTION__, addr, buf[0], err); + printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __FUNCTION__, msg.buf[0], msg.buf[1], err); if (err < 0) return err; else return -EREMOTEIO; } - tmp[0]++; + msg.buf += 2; } return 0; } -#if 0 -static int i2c_readbytes (struct lgdt330x_state* state, - u8 addr, /* demod_address or pll_address */ - u8 *buf, /* holds data bytes read */ - int len /* number of bytes to read */ ) -{ - struct i2c_msg msg = - { .addr = addr, .flags = I2C_M_RD, .buf = buf, .len = len }; - int err; - - if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { - printk(KERN_WARNING "lgdt330x: %s error (addr %02x, err == %i)\n", __FUNCTION__, addr, err); - return -EREMOTEIO; - } - return 0; -} -#endif - /* * This routine writes the register (reg) to the demod bus * then reads the data returned for (len) bytes. */ -static u8 i2c_selectreadbytes (struct lgdt330x_state* state, +static u8 i2c_read_demod_bytes (struct lgdt330x_state* state, enum I2C_REG reg, u8* buf, int len) { u8 wr [] = { reg }; @@ -139,7 +119,7 @@ static u8 i2c_selectreadbytes (struct lgdt330x_state* state, } /* Software reset */ -int lgdt330x_SwReset(struct lgdt330x_state* state) +static int lgdt3302_SwReset(struct lgdt330x_state* state) { u8 ret; u8 reset[] = { @@ -148,23 +128,51 @@ int lgdt330x_SwReset(struct lgdt330x_state* state) * bits 5-0 are 1 to mask interrupts */ }; - ret = i2c_writebytes(state, - state->config->demod_address, + ret = i2c_write_demod_bytes(state, + reset, sizeof(reset)); + if (ret == 0) { + + /* force reset high (inactive) and unmask interrupts */ + reset[1] = 0x7f; + ret = i2c_write_demod_bytes(state, + reset, sizeof(reset)); + } + return ret; +} + +static int lgdt3303_SwReset(struct lgdt330x_state* state) +{ + u8 ret; + u8 reset[] = { + 0x02, + 0x00 /* bit 0 is active low software reset */ + }; + + ret = i2c_write_demod_bytes(state, reset, sizeof(reset)); if (ret == 0) { - /* spec says reset takes 100 ns why wait */ - /* mdelay(100); */ /* keep low for 100mS */ - reset[1] = 0x7f; /* force reset high (inactive) - * and unmask interrupts */ - ret = i2c_writebytes(state, - state->config->demod_address, + + /* force reset high (inactive) */ + reset[1] = 0x01; + ret = i2c_write_demod_bytes(state, reset, sizeof(reset)); } - /* Spec does not indicate a need for this either */ - /*mdelay(5); */ /* wait 5 msec before doing more */ return ret; } +static int lgdt330x_SwReset(struct lgdt330x_state* state) +{ + switch (state->config->demod_chip) { + case LGDT3302: + return lgdt3302_SwReset(state); + case LGDT3303: + return lgdt3303_SwReset(state); + default: + return -ENODEV; + } +} + + static int lgdt330x_init(struct dvb_frontend* fe) { /* Hardware reset is done using gpio[0] of cx23880x chip. @@ -173,22 +181,98 @@ static int lgdt330x_init(struct dvb_frontend* fe) * Maybe there needs to be a callable function in cx88-core or * the caller of this function needs to do it. */ - dprintk("%s entered\n", __FUNCTION__); - return lgdt330x_SwReset((struct lgdt330x_state*) fe->demodulator_priv); + /* + * Array of byte pairs <address, value> + * to initialize each different chip + */ + static u8 lgdt3302_init_data[] = { + /* Use 50MHz parameter values from spec sheet since xtal is 50 */ + /* Change the value of NCOCTFV[25:0] of carrier + recovery center frequency register */ + VSB_CARRIER_FREQ0, 0x00, + VSB_CARRIER_FREQ1, 0x87, + VSB_CARRIER_FREQ2, 0x8e, + VSB_CARRIER_FREQ3, 0x01, + /* Change the TPCLK pin polarity + data is valid on falling clock */ + DEMUX_CONTROL, 0xfb, + /* Change the value of IFBW[11:0] of + AGC IF/RF loop filter bandwidth register */ + AGC_RF_BANDWIDTH0, 0x40, + AGC_RF_BANDWIDTH1, 0x93, + AGC_RF_BANDWIDTH2, 0x00, + /* Change the value of bit 6, 'nINAGCBY' and + 'NSSEL[1:0] of ACG function control register 2 */ + AGC_FUNC_CTRL2, 0xc6, + /* Change the value of bit 6 'RFFIX' + of AGC function control register 3 */ + AGC_FUNC_CTRL3, 0x40, + /* Set the value of 'INLVTHD' register 0x2a/0x2c + to 0x7fe */ + AGC_DELAY0, 0x07, + AGC_DELAY2, 0xfe, + /* Change the value of IAGCBW[15:8] + of inner AGC loop filter bandwith */ + AGC_LOOP_BANDWIDTH0, 0x08, + AGC_LOOP_BANDWIDTH1, 0x9a + }; + + static u8 lgdt3303_init_data[] = { + 0x4c, 0x14 + }; + + struct lgdt330x_state* state = fe->demodulator_priv; + char *chip_name; + int err; + + switch (state->config->demod_chip) { + case LGDT3302: + chip_name = "LGDT3302"; + err = i2c_write_demod_bytes(state, lgdt3302_init_data, + sizeof(lgdt3302_init_data)); + break; + case LGDT3303: + chip_name = "LGDT3303"; + err = i2c_write_demod_bytes(state, lgdt3303_init_data, + sizeof(lgdt3303_init_data)); + break; + default: + chip_name = "undefined"; + printk (KERN_WARNING "Only LGDT3302 and LGDT3303 are supported chips.\n"); + err = -ENODEV; + } + dprintk("%s entered as %s\n", __FUNCTION__, chip_name); + if (err < 0) + return err; + return lgdt330x_SwReset(state); } static int lgdt330x_read_ber(struct dvb_frontend* fe, u32* ber) { - *ber = 0; /* Dummy out for now */ + *ber = 0; /* Not supplied by the demod chips */ return 0; } static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) { - struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; + struct lgdt330x_state* state = fe->demodulator_priv; + int err; u8 buf[2]; - i2c_selectreadbytes(state, PACKET_ERR_COUNTER1, buf, sizeof(buf)); + switch (state->config->demod_chip) { + case LGDT3302: + err = i2c_read_demod_bytes(state, LGDT3302_PACKET_ERR_COUNTER1, + buf, sizeof(buf)); + break; + case LGDT3303: + err = i2c_read_demod_bytes(state, LGDT3303_PACKET_ERR_COUNTER1, + buf, sizeof(buf)); + break; + default: + printk(KERN_WARNING + "Only LGDT3302 and LGDT3303 are supported chips.\n"); + err = -ENODEV; + } *ucblocks = (buf[0] << 8) | buf[1]; return 0; @@ -197,123 +281,113 @@ static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) static int lgdt330x_set_parameters(struct dvb_frontend* fe, struct dvb_frontend_parameters *param) { - struct lgdt330x_state* state = - (struct lgdt330x_state*) fe->demodulator_priv; + /* + * Array of byte pairs <address, value> + * to initialize 8VSB for lgdt3303 chip 50 MHz IF + */ + static u8 lgdt3303_8vsb_44_data[] = { + 0x04, 0x00, + 0x0d, 0x40, + 0x0e, 0x87, + 0x0f, 0x8e, + 0x10, 0x01, + 0x47, 0x8b }; + + /* + * Array of byte pairs <address, value> + * to initialize QAM for lgdt3303 chip + */ + static u8 lgdt3303_qam_data[] = { + 0x04, 0x00, + 0x0d, 0x00, + 0x0e, 0x00, + 0x0f, 0x00, + 0x10, 0x00, + 0x51, 0x63, + 0x47, 0x66, + 0x48, 0x66, + 0x4d, 0x1a, + 0x49, 0x08, + 0x4a, 0x9b }; + + struct lgdt330x_state* state = fe->demodulator_priv; - /* Use 50MHz parameter values from spec sheet since xtal is 50 */ static u8 top_ctrl_cfg[] = { TOP_CONTROL, 0x03 }; - static u8 vsb_freq_cfg[] = { VSB_CARRIER_FREQ0, 0x00, 0x87, 0x8e, 0x01 }; - static u8 demux_ctrl_cfg[] = { DEMUX_CONTROL, 0xfb }; - static u8 agc_rf_cfg[] = { AGC_RF_BANDWIDTH0, 0x40, 0x93, 0x00 }; - static u8 agc_ctrl_cfg[] = { AGC_FUNC_CTRL2, 0xc6, 0x40 }; - static u8 agc_delay_cfg[] = { AGC_DELAY0, 0x07, 0x00, 0xfe }; - static u8 agc_loop_cfg[] = { AGC_LOOP_BANDWIDTH0, 0x08, 0x9a }; + int err; /* Change only if we are actually changing the modulation */ if (state->current_modulation != param->u.vsb.modulation) { switch(param->u.vsb.modulation) { case VSB_8: dprintk("%s: VSB_8 MODE\n", __FUNCTION__); - /* Select VSB mode and serial MPEG interface */ - top_ctrl_cfg[1] = 0x07; + /* Select VSB mode */ + top_ctrl_cfg[1] = 0x03; /* Select ANT connector if supported by card */ if (state->config->pll_rf_set) state->config->pll_rf_set(fe, 1); + + if (state->config->demod_chip == LGDT3303) { + err = i2c_write_demod_bytes(state, lgdt3303_8vsb_44_data, + sizeof(lgdt3303_8vsb_44_data)); + } break; case QAM_64: dprintk("%s: QAM_64 MODE\n", __FUNCTION__); - /* Select QAM_64 mode and serial MPEG interface */ - top_ctrl_cfg[1] = 0x04; + /* Select QAM_64 mode */ + top_ctrl_cfg[1] = 0x00; /* Select CABLE connector if supported by card */ if (state->config->pll_rf_set) state->config->pll_rf_set(fe, 0); + + if (state->config->demod_chip == LGDT3303) { + err = i2c_write_demod_bytes(state, lgdt3303_qam_data, + sizeof(lgdt3303_qam_data)); + } break; case QAM_256: dprintk("%s: QAM_256 MODE\n", __FUNCTION__); - /* Select QAM_256 mode and serial MPEG interface */ - top_ctrl_cfg[1] = 0x05; + /* Select QAM_256 mode */ + top_ctrl_cfg[1] = 0x01; /* Select CABLE connector if supported by card */ if (state->config->pll_rf_set) state->config->pll_rf_set(fe, 0); + + if (state->config->demod_chip == LGDT3303) { + err = i2c_write_demod_bytes(state, lgdt3303_qam_data, + sizeof(lgdt3303_qam_data)); + } break; default: printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __FUNCTION__, param->u.vsb.modulation); return -1; } - /* Initializations common to all modes */ + /* + * select serial or parallel MPEG harware interface + * Serial: 0x04 for LGDT3302 or 0x40 for LGDT3303 + * Parallel: 0x00 + */ + top_ctrl_cfg[1] |= state->config->serial_mpeg; /* Select the requested mode */ - i2c_writebytes(state, state->config->demod_address, - top_ctrl_cfg, sizeof(top_ctrl_cfg)); - - /* Change the value of IFBW[11:0] - of AGC IF/RF loop filter bandwidth register */ - i2c_writebytes(state, state->config->demod_address, - agc_rf_cfg, sizeof(agc_rf_cfg)); - - /* Change the value of bit 6, 'nINAGCBY' and - 'NSSEL[1:0] of ACG function control register 2 */ - /* Change the value of bit 6 'RFFIX' - of AGC function control register 3 */ - i2c_writebytes(state, state->config->demod_address, - agc_ctrl_cfg, sizeof(agc_ctrl_cfg)); - - /* Change the TPCLK pin polarity - data is valid on falling clock */ - i2c_writebytes(state, state->config->demod_address, - demux_ctrl_cfg, sizeof(demux_ctrl_cfg)); - - /* Change the value of NCOCTFV[25:0] of carrier - recovery center frequency register */ - i2c_writebytes(state, state->config->demod_address, - vsb_freq_cfg, sizeof(vsb_freq_cfg)); - - /* Set the value of 'INLVTHD' register 0x2a/0x2c to 0x7fe */ - i2c_writebytes(state, state->config->demod_address, - agc_delay_cfg, sizeof(agc_delay_cfg)); - - /* Change the value of IAGCBW[15:8] - of inner AGC loop filter bandwith */ - i2c_writebytes(state, state->config->demod_address, - agc_loop_cfg, sizeof(agc_loop_cfg)); - + i2c_write_demod_bytes(state, top_ctrl_cfg, + sizeof(top_ctrl_cfg)); state->config->set_ts_params(fe, 0); state->current_modulation = param->u.vsb.modulation; } /* Change only if we are actually changing the channel */ if (state->current_frequency != param->frequency) { - u8 buf[5]; - struct i2c_msg msg = { .flags = 0, .buf = &buf[1], .len = 4 }; - int err; - - state->config->pll_set(fe, param, buf); - msg.addr = buf[0]; - - dprintk("%s: tuner at 0x%02x bytes: 0x%02x 0x%02x " - "0x%02x 0x%02x\n", __FUNCTION__, - buf[0],buf[1],buf[2],buf[3],buf[4]); - if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { - printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __FUNCTION__, buf[0], buf[1], err); - if (err < 0) - return err; - else - return -EREMOTEIO; - } -#if 0 - /* Check the status of the tuner pll */ - i2c_readbytes(state, buf[0], &buf[1], 1); - dprintk("%s: tuner status byte = 0x%02x\n", __FUNCTION__, buf[1]); -#endif - /* Update current frequency */ + /* Tune to the new frequency */ + state->config->pll_set(fe, param); + /* Keep track of the new frequency */ state->current_frequency = param->frequency; } lgdt330x_SwReset(state); @@ -328,21 +402,15 @@ static int lgdt330x_get_frontend(struct dvb_frontend* fe, return 0; } -static int lgdt330x_read_status(struct dvb_frontend* fe, fe_status_t* status) +static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status) { - struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; + struct lgdt330x_state* state = fe->demodulator_priv; u8 buf[3]; *status = 0; /* Reset status result */ - /* - * You must set the Mask bits to 1 in the IRQ_MASK in order - * to see that status bit in the IRQ_STATUS register. - * This is done in SwReset(); - */ - /* AGC status register */ - i2c_selectreadbytes(state, AGC_STATUS, buf, 1); + i2c_read_demod_bytes(state, AGC_STATUS, buf, 1); dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]); if ((buf[0] & 0x0c) == 0x8){ /* Test signal does not exist flag */ @@ -353,16 +421,15 @@ static int lgdt330x_read_status(struct dvb_frontend* fe, fe_status_t* status) return 0; } + /* + * You must set the Mask bits to 1 in the IRQ_MASK in order + * to see that status bit in the IRQ_STATUS register. + * This is done in SwReset(); + */ /* signal status */ - i2c_selectreadbytes(state, TOP_CONTROL, buf, sizeof(buf)); + i2c_read_demod_bytes(state, TOP_CONTROL, buf, sizeof(buf)); dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __FUNCTION__, buf[0], buf[1], buf[2]); -#if 0 - /* Alternative method to check for a signal */ - /* using the SNR good/bad interrupts. */ - if ((buf[2] & 0x30) == 0x10) - *status |= FE_HAS_SIGNAL; -#endif /* sync status */ if ((buf[2] & 0x03) == 0x01) { @@ -376,7 +443,7 @@ static int lgdt330x_read_status(struct dvb_frontend* fe, fe_status_t* status) } /* Carrier Recovery Lock Status Register */ - i2c_selectreadbytes(state, CARRIER_LOCK, buf, 1); + i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1); dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]); switch (state->current_modulation) { case QAM_256: @@ -396,13 +463,75 @@ static int lgdt330x_read_status(struct dvb_frontend* fe, fe_status_t* status) return 0; } +static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status) +{ + struct lgdt330x_state* state = fe->demodulator_priv; + int err; + u8 buf[3]; + + *status = 0; /* Reset status result */ + + /* lgdt3303 AGC status register */ + err = i2c_read_demod_bytes(state, 0x58, buf, 1); + if (err < 0) + return err; + + dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]); + if ((buf[0] & 0x21) == 0x01){ + /* Test input signal does not exist flag */ + /* as well as the AGC lock flag. */ + *status |= FE_HAS_SIGNAL; + } else { + /* Without a signal all other status bits are meaningless */ + return 0; + } + + /* Carrier Recovery Lock Status Register */ + i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1); + dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]); + switch (state->current_modulation) { + case QAM_256: + case QAM_64: + /* Need to undestand why there are 3 lock levels here */ + if ((buf[0] & 0x07) == 0x07) + *status |= FE_HAS_CARRIER; + else + break; + i2c_read_demod_bytes(state, 0x8a, buf, 1); + if ((buf[0] & 0x04) == 0x04) + *status |= FE_HAS_SYNC; + if ((buf[0] & 0x01) == 0x01) + *status |= FE_HAS_LOCK; + if ((buf[0] & 0x08) == 0x08) + *status |= FE_HAS_VITERBI; + break; + case VSB_8: + if ((buf[0] & 0x80) == 0x80) + *status |= FE_HAS_CARRIER; + else + break; + i2c_read_demod_bytes(state, 0x38, buf, 1); + if ((buf[0] & 0x02) == 0x00) + *status |= FE_HAS_SYNC; + if ((buf[0] & 0x01) == 0x01) { + *status |= FE_HAS_LOCK; + *status |= FE_HAS_VITERBI; + } + break; + default: + printk("KERN_WARNING lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__); + } + return 0; +} + static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength) { /* not directly available. */ + *strength = 0; return 0; } -static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr) +static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr) { #ifdef SNR_IN_DB /* @@ -451,7 +580,7 @@ static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr) 91, 115, 144, 182, 229, 288, 362, 456, 574, 722, 909, 1144, 1440, 1813, 2282, 2873, 3617, 4553, 5732, 7216, 9084, 11436, 14396, 18124, 22817, 28724, 36161, 45524, 57312, 72151, - 90833, 114351, 143960, 181235, 228161, 0x040000 + 90833, 114351, 143960, 181235, 228161, 0x080000 }; static u8 buf[5];/* read data buffer */ @@ -459,8 +588,8 @@ static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr) static u32 snr_db; /* index into SNR_EQ[] */ struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; - /* read both equalizer and pase tracker noise data */ - i2c_selectreadbytes(state, EQPH_ERR0, buf, sizeof(buf)); + /* read both equalizer and phase tracker noise data */ + i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf)); if (state->current_modulation == VSB_8) { /* Equalizer Mean-Square Error Register for VSB */ @@ -496,19 +625,20 @@ static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr) struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; /* read both equalizer and pase tracker noise data */ - i2c_selectreadbytes(state, EQPH_ERR0, buf, sizeof(buf)); + i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf)); if (state->current_modulation == VSB_8) { - /* Equalizer Mean-Square Error Register for VSB */ - noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2]; - } else { - /* Phase Tracker Mean-Square Error Register for QAM */ + /* Phase Tracker Mean-Square Error Register for VSB */ noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4]; + } else { + + /* Carrier Recovery Mean-Square Error for QAM */ + i2c_read_demod_bytes(state, 0x1a, buf, 2); + noise = ((buf[0] & 3) << 8) | buf[1]; } /* Small values for noise mean signal is better so invert noise */ - /* Noise is 19 bit value so discard 3 LSB*/ - *snr = ~noise>>3; + *snr = ~noise; #endif 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) return 0; } +static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr) +{ + /* Return the raw noise value */ + static u8 buf[5];/* read data buffer */ + static u32 noise; /* noise value */ + struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; + + if (state->current_modulation == VSB_8) { + + /* Phase Tracker Mean-Square Error Register for VSB */ + noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4]; + } else { + + /* Carrier Recovery Mean-Square Error for QAM */ + i2c_read_demod_bytes(state, 0x1a, buf, 2); + noise = (buf[0] << 8) | buf[1]; + } + + /* Small values for noise mean signal is better so invert noise */ + *snr = ~noise; + + dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr); + + return 0; +} + static int lgdt330x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings) { /* I have no idea about this - it may not be needed */ @@ -531,7 +687,8 @@ static void lgdt330x_release(struct dvb_frontend* fe) kfree(state); } -static struct dvb_frontend_ops lgdt330x_ops; +static struct dvb_frontend_ops lgdt3302_ops; +static struct dvb_frontend_ops lgdt3303_ops; struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config, struct i2c_adapter* i2c) @@ -548,9 +705,19 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config, /* Setup the state */ state->config = config; state->i2c = i2c; - memcpy(&state->ops, &lgdt330x_ops, sizeof(struct dvb_frontend_ops)); + switch (config->demod_chip) { + case LGDT3302: + memcpy(&state->ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops)); + break; + case LGDT3303: + memcpy(&state->ops, &lgdt3303_ops, sizeof(struct dvb_frontend_ops)); + break; + default: + goto error; + } + /* Verify communication with demod chip */ - if (i2c_selectreadbytes(state, 2, buf, 1)) + if (i2c_read_demod_bytes(state, 2, buf, 1)) goto error; state->current_frequency = -1; @@ -568,9 +735,33 @@ error: return NULL; } -static struct dvb_frontend_ops lgdt330x_ops = { +static struct dvb_frontend_ops lgdt3302_ops = { + .info = { + .name= "LG Electronics LGDT3302 VSB/QAM Frontend", + .type = FE_ATSC, + .frequency_min= 54000000, + .frequency_max= 858000000, + .frequency_stepsize= 62500, + /* Symbol rate is for all VSB modes need to check QAM */ + .symbol_rate_min = 10762000, + .symbol_rate_max = 10762000, + .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB + }, + .init = lgdt330x_init, + .set_frontend = lgdt330x_set_parameters, + .get_frontend = lgdt330x_get_frontend, + .get_tune_settings = lgdt330x_get_tune_settings, + .read_status = lgdt3302_read_status, + .read_ber = lgdt330x_read_ber, + .read_signal_strength = lgdt330x_read_signal_strength, + .read_snr = lgdt3302_read_snr, + .read_ucblocks = lgdt330x_read_ucblocks, + .release = lgdt330x_release, +}; + +static struct dvb_frontend_ops lgdt3303_ops = { .info = { - .name= "LG Electronics lgdt330x VSB/QAM Frontend", + .name= "LG Electronics LGDT3303 VSB/QAM Frontend", .type = FE_ATSC, .frequency_min= 54000000, .frequency_max= 858000000, @@ -584,15 +775,15 @@ static struct dvb_frontend_ops lgdt330x_ops = { .set_frontend = lgdt330x_set_parameters, .get_frontend = lgdt330x_get_frontend, .get_tune_settings = lgdt330x_get_tune_settings, - .read_status = lgdt330x_read_status, + .read_status = lgdt3303_read_status, .read_ber = lgdt330x_read_ber, .read_signal_strength = lgdt330x_read_signal_strength, - .read_snr = lgdt330x_read_snr, + .read_snr = lgdt3303_read_snr, .read_ucblocks = lgdt330x_read_ucblocks, .release = lgdt330x_release, }; -MODULE_DESCRIPTION("lgdt330x [DViCO FusionHDTV 3 Gold] (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver"); +MODULE_DESCRIPTION("LGDT330X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver"); MODULE_AUTHOR("Wilson Michaels"); MODULE_LICENSE("GPL"); @@ -601,6 +792,5 @@ EXPORT_SYMBOL(lgdt330x_attach); /* * Local variables: * c-basic-offset: 8 - * compile-command: "make DVB=1" * End: */ 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 @@ /* - * Support for LGDT3302 & LGDT3303 (DViCO FustionHDTV Gold) - VSB/QAM + * Support for LGDT3302 and LGDT3303 - VSB/QAM * * Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.net> * @@ -24,14 +24,26 @@ #include <linux/dvb/frontend.h> +typedef enum lg_chip_t { + UNDEFINED, + LGDT3302, + LGDT3303 +}lg_chip_type; + struct lgdt330x_config { /* The demodulator's i2c address */ u8 demod_address; + /* LG demodulator chip LGDT3302 or LGDT3303 */ + lg_chip_type demod_chip; + + /* MPEG hardware interface - 0:parallel 1:serial */ + int serial_mpeg; + /* PLL interface */ int (*pll_rf_set) (struct dvb_frontend* fe, int index); - int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pll_address); + int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); /* Need to set device param for start_dma */ 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 @@ /* - * Support for LGDT3302 & LGDT3303 (DViCO FustionHDTV Gold) - VSB/QAM + * Support for LGDT3302 and LGDT3303 - VSB/QAM * * Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.net> * @@ -57,8 +57,10 @@ enum I2C_REG { PH_ERR1= 0x4a, PH_ERR2= 0x4b, DEMUX_CONTROL= 0x66, - PACKET_ERR_COUNTER1= 0x6a, - PACKET_ERR_COUNTER2= 0x6b, + LGDT3302_PACKET_ERR_COUNTER1= 0x6a, + LGDT3302_PACKET_ERR_COUNTER2= 0x6b, + LGDT3303_PACKET_ERR_COUNTER1= 0x8b, + LGDT3303_PACKET_ERR_COUNTER2= 0x8c, }; #endif /* _LGDT330X_PRIV_ */ diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index ac81e5e01a9a..3f5742396096 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -356,7 +356,7 @@ config VIDEO_M32R_AR config VIDEO_M32R_AR_M64278 tristate "Use Colour AR module M64278(VGA)" - depends on VIDEO_M32R_AR + depends on VIDEO_M32R_AR && PLAT_M32700UT ---help--- Say Y here to use the Renesas M64278E-800 camera module, which supports VGA(640x480 pixcels) size of images. 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); static unsigned int triton1=0; static unsigned int vsfx=0; static unsigned int latency = UNSET; -static unsigned int no_overlay=-1; +int no_overlay=-1; static unsigned int card[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; static unsigned int pll[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; @@ -4296,9 +4296,11 @@ void __devinit bttv_check_chipset(void) printk(KERN_INFO "bttv: Host bridge needs VSFX enabled.\n"); if (pcipci_fail) { printk(KERN_WARNING "bttv: BT848 and your chipset may not work together.\n"); - if (UNSET == no_overlay) { - printk(KERN_WARNING "bttv: going to disable overlay.\n"); + if (!no_overlay) { + printk(KERN_WARNING "bttv: overlay will be disabled.\n"); no_overlay = 1; + } else { + printk(KERN_WARNING "bttv: overlay forced. Use this option at your own risk.\n"); } } 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 @@ /* - $Id: bttv-driver.c,v 1.42 2005/07/05 17:37:35 nsh Exp $ + $Id: bttv-driver.c,v 1.52 2005/08/04 00:55:16 mchehab Exp $ bttv - Bt848 frame grabber driver @@ -80,6 +80,7 @@ static unsigned int irq_iswitch = 0; static unsigned int uv_ratio = 50; static unsigned int full_luma_range = 0; static unsigned int coring = 0; +extern int no_overlay; /* API features (turn on/off stuff for testing) */ static unsigned int v4l2 = 1; @@ -2151,6 +2152,10 @@ static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv, return 0; } case V4L2_BUF_TYPE_VIDEO_OVERLAY: + if (no_overlay > 0) { + printk ("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); + return -EINVAL; + } return setup_window(fh, btv, &f->fmt.win, 1); case V4L2_BUF_TYPE_VBI_CAPTURE: retval = bttv_switch_type(fh,f->type); @@ -2224,9 +2229,11 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, /* others */ cap->type = VID_TYPE_CAPTURE| VID_TYPE_TUNER| - VID_TYPE_OVERLAY| VID_TYPE_CLIPPING| VID_TYPE_SCALES; + if (no_overlay <= 0) + cap->type |= VID_TYPE_OVERLAY; + cap->maxwidth = bttv_tvnorms[btv->tvnorm].swidth; cap->maxheight = bttv_tvnorms[btv->tvnorm].sheight; cap->minwidth = 48; @@ -2302,6 +2309,11 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, struct video_window *win = arg; struct v4l2_window w2; + if (no_overlay > 0) { + printk ("VIDIOCSWIN: no_overlay\n"); + return -EINVAL; + } + w2.field = V4L2_FIELD_ANY; w2.w.left = win->x; w2.w.top = win->y; @@ -2577,10 +2589,12 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, cap->version = BTTV_VERSION_CODE; cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; + if (no_overlay <= 0) + cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY; + if (bttv_tvcards[btv->c.type].tuner != UNSET && bttv_tvcards[btv->c.type].tuner != TUNER_ABSENT) cap->capabilities |= V4L2_CAP_TUNER; @@ -3076,7 +3090,7 @@ static struct file_operations bttv_fops = static struct video_device bttv_video_template = { .name = "UNSET", - .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_OVERLAY| + .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER| VID_TYPE_CLIPPING|VID_TYPE_SCALES, .hardware = VID_HARDWARE_BT848, .fops = &bttv_fops, @@ -3756,6 +3770,12 @@ static void bttv_unregister_video(struct bttv *btv) /* register video4linux devices */ static int __devinit bttv_register_video(struct bttv *btv) { + if (no_overlay <= 0) { + bttv_video_template.type |= VID_TYPE_OVERLAY; + } else { + printk("bttv: Overlay support disabled.\n"); + } + /* video */ btv->video_dev = vdev_init(btv, &bttv_video_template, "video"); if (NULL == btv->video_dev) @@ -3869,11 +3889,6 @@ static int __devinit bttv_probe(struct pci_dev *dev, pci_set_master(dev); pci_set_command(dev); pci_set_drvdata(dev,btv); - if (!pci_dma_supported(dev,0xffffffff)) { - printk("bttv%d: Oops: no 32bit PCI DMA ???\n", btv->c.nr); - result = -EIO; - goto fail1; - } pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision); 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 @@ /* - * $Id: bttv.h,v 1.18 2005/05/24 23:41:42 nsh Exp $ + * $Id: bttv.h,v 1.22 2005/07/28 18:41:21 mchehab Exp $ * * bttv - Bt848 frame grabber driver * @@ -135,7 +135,9 @@ #define BTTV_DVICO_DVBT_LITE 0x80 #define BTTV_TIBET_CS16 0x83 #define BTTV_KODICOM_4400R 0x84 -#define BTTV_ADLINK_RTV24 0x85 +#define BTTV_ADLINK_RTV24 0x86 +#define BTTV_DVICO_FUSIONHDTV_5_LITE 0x87 +#define BTTV_ACORP_Y878F 0x88 /* i2c address list */ #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 @@ /* - $Id: bttvp.h,v 1.19 2005/06/16 21:38:45 nsh Exp $ + $Id: bttvp.h,v 1.21 2005/07/15 21:44:14 mchehab Exp $ bttv - Bt848 frame grabber driver @@ -27,7 +27,7 @@ #define _BTTVP_H_ #include <linux/version.h> -#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,15) +#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,16) #include <linux/types.h> #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 @@ /* - * $Id: cx88-cards.c,v 1.86 2005/07/14 03:06:43 mchehab Exp $ + * $Id: cx88-cards.c,v 1.90 2005/07/28 02:47:42 mkrufky Exp $ * * device driver for Conexant 2388x based TV cards * card-specific stuff. @@ -90,6 +90,9 @@ struct cx88_board cx88_boards[] = { .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, }}, }, [CX88_BOARD_PIXELVIEW] = { @@ -496,6 +499,9 @@ struct cx88_board cx88_boards[] = { .input = {{ .type = CX88_VMUX_DVB, .vmux = 0, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, }}, .dvb = 1, }, @@ -753,6 +759,27 @@ struct cx88_board cx88_boards[] = { }}, .dvb = 1, }, + [CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD] = { + .name = "DViCO FusionHDTV 5 Gold", + .tuner_type = TUNER_LG_TDVS_H062F, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + /* See DViCO FusionHDTV 3 Gold-Q for GPIO documentation. */ + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x0f0d, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x0f00, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x0f00, + }}, + }, }; const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); @@ -880,6 +907,10 @@ struct cx88_subid cx88_subids[] = { .subvendor = 0x153b, .subdevice = 0x1166, .card = CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1, + },{ + .subvendor = 0x18ac, + .subdevice = 0xd500, + .card = CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD, }, }; 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 @@ /* - * $Id: cx88-dvb.c,v 1.54 2005/07/25 05:13:50 mkrufky Exp $ + * $Id: cx88-dvb.c,v 1.58 2005/08/07 09:24:08 mkrufky Exp $ * * device driver for Conexant 2388x based TV cards * MPEG Transport Stream (DVB) routines @@ -208,14 +208,26 @@ static struct or51132_config pchdtv_hd3000 = { #ifdef HAVE_LGDT330X static int lgdt330x_pll_set(struct dvb_frontend* fe, - struct dvb_frontend_parameters* params, - u8* pllbuf) + struct dvb_frontend_parameters* params) { struct cx8802_dev *dev= fe->dvb->priv; + u8 buf[4]; + struct i2c_msg msg = + { .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 }; + int err; - pllbuf[0] = dev->core->pll_addr; - dvb_pll_configure(dev->core->pll_desc, &pllbuf[1], - params->frequency, 0); + dvb_pll_configure(dev->core->pll_desc, buf, params->frequency, 0); + dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n", + __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]); + if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { + printk(KERN_WARNING "cx88-dvb: %s error " + "(addr %02x <- %02x, err = %i)\n", + __FUNCTION__, buf[0], buf[1], err); + if (err < 0) + return err; + else + return -EREMOTEIO; + } return 0; } @@ -244,6 +256,8 @@ static int lgdt330x_set_ts_param(struct dvb_frontend* fe, int is_punctured) static struct lgdt330x_config fusionhdtv_3_gold = { .demod_address = 0x0e, + .demod_chip = LGDT3302, + .serial_mpeg = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */ .pll_set = lgdt330x_pll_set, .set_ts_params = lgdt330x_set_ts_param, }; 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 @@ /* - * $Id: cx88-video.c,v 1.80 2005/07/13 08:49:08 mchehab Exp $ + * $Id: cx88-video.c,v 1.82 2005/07/22 05:13:34 mkrufky Exp $ * * device driver for Conexant 2388x based TV cards * video4linux video interface @@ -758,10 +758,10 @@ static int video_open(struct inode *inode, struct file *file) struct cx88_core *core = dev->core; int board = core->board; dprintk(1,"video_open: setting radio device\n"); + cx_write(MO_GP3_IO, cx88_boards[board].radio.gpio3); cx_write(MO_GP0_IO, cx88_boards[board].radio.gpio0); cx_write(MO_GP1_IO, cx88_boards[board].radio.gpio1); cx_write(MO_GP2_IO, cx88_boards[board].radio.gpio2); - cx_write(MO_GP3_IO, cx88_boards[board].radio.gpio3); dev->core->tvaudio = WW_FM; cx88_set_tvaudio(core); 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 @@ /* - * $Id: cx88.h,v 1.69 2005/07/13 17:25:25 mchehab Exp $ + * $Id: cx88.h,v 1.70 2005/07/24 17:44:09 mkrufky Exp $ * * v4l2 device driver for cx2388x based TV cards * @@ -171,6 +171,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T 28 #define CX88_BOARD_ADSTECH_DVB_T_PCI 29 #define CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1 30 +#define CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD 31 enum cx88_itype { 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) schedule_timeout(msecs_to_jiffies(timeout)); } } - if (current->flags & PF_FREEZE) { - refrigerator (); - } remove_wait_queue(&msp->wq, &wait); + try_to_freeze(); return msp->restart; } 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 @@ /* - * $Id: saa7134-i2c.c,v 1.19 2005/07/07 01:49:30 mkrufky Exp $ + * $Id: saa7134-i2c.c,v 1.22 2005/07/22 04:09:41 mkrufky Exp $ * * device driver for philips saa7134 based TV cards * i2c interface support @@ -300,6 +300,8 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap, status = i2c_get_status(dev); if (i2c_is_error(status)) goto err; + /* ensure that the bus is idle for at least one bit slot */ + msleep(1); d1printk("\n"); 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 @@ /* - * $Id: saa7134.h,v 1.48 2005/07/01 08:22:24 nsh Exp $ + * $Id: saa7134.h,v 1.49 2005/07/13 17:25:25 mchehab Exp $ * * v4l2 device driver for philips saa7134 based TV cards * @@ -21,7 +21,7 @@ */ #include <linux/version.h> -#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,13) +#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,14) #include <linux/pci.h> #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 @@ * For Philips TEA5767 FM Chip used on some TV Cards like Prolink Pixelview * I2C address is allways 0xC0. * - * $Id: tea5767.c,v 1.21 2005/07/14 03:06:43 mchehab Exp $ + * $Id: tea5767.c,v 1.27 2005/07/31 12:10:56 mchehab Exp $ * * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@brturbo.com.br) * This code is placed under the terms of the GNU General Public License @@ -15,7 +15,6 @@ #include <linux/videodev.h> #include <linux/delay.h> #include <media/tuner.h> -#include <media/tuner.h> #define PREFIX "TEA5767 " @@ -293,16 +292,16 @@ static int tea5767_stereo(struct i2c_client *c) int tea5767_autodetection(struct i2c_client *c) { - unsigned char buffer[5] = { 0xff, 0xff, 0xff, 0xff, 0xff }; + unsigned char buffer[7] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; int rc; struct tuner *t = i2c_get_clientdata(c); - if (5 != (rc = i2c_master_recv(c, buffer, 5))) { + if (7 != (rc = i2c_master_recv(c, buffer, 7))) { tuner_warn("It is not a TEA5767. Received %i bytes.\n", rc); return EINVAL; } - /* If all bytes are the same then it's a TV tuner and not a tea5767 chip. */ + /* If all bytes are the same then it's a TV tuner and not a tea5767 */ if (buffer[0] == buffer[1] && buffer[0] == buffer[2] && buffer[0] == buffer[3] && buffer[0] == buffer[4]) { tuner_warn("All bytes are equal. It is not a TEA5767\n"); @@ -318,6 +317,17 @@ int tea5767_autodetection(struct i2c_client *c) tuner_warn("Chip ID is not zero. It is not a TEA5767\n"); return EINVAL; } + /* It seems that tea5767 returns 0xff after the 5th byte */ + if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) { + tuner_warn("Returned more than 5 bytes. It is not a TEA5767\n"); + return EINVAL; + } + + /* It seems that tea5767 returns 0xff after the 5th byte */ + if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) { + tuner_warn("Returned more than 5 bytes. It is not a TEA5767\n"); + return EINVAL; + } tuner_warn("TEA5767 detected.\n"); return 0; @@ -327,10 +337,8 @@ int tea5767_tuner_init(struct i2c_client *c) { struct tuner *t = i2c_get_clientdata(c); - if (tea5767_autodetection(c) == EINVAL) - return EINVAL; - - tuner_info("type set to %d (%s)\n", t->type, "Philips TEA5767HN FM Radio"); + tuner_info("type set to %d (%s)\n", t->type, + "Philips TEA5767HN FM Radio"); strlcpy(c->name, "tea5767", sizeof(c->name)); 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 @@ /* - * $Id: tuner-core.c,v 1.58 2005/07/14 03:06:43 mchehab Exp $ + * $Id: tuner-core.c,v 1.63 2005/07/28 18:19:55 mchehab Exp $ * * i2c tv tuner chip device driver * core core, i.e. kernel interfaces, registering and so on @@ -23,6 +23,8 @@ #include <media/tuner.h> #include <media/audiochip.h> +#include "msp3400.h" + #define UNSET (-1U) /* standard i2c insmod options */ @@ -42,6 +44,9 @@ module_param(addr, int, 0444); static unsigned int no_autodetect = 0; module_param(no_autodetect, int, 0444); +static unsigned int show_i2c = 0; +module_param(show_i2c, int, 0444); + /* insmod options used at runtime => read/write */ unsigned int tuner_debug = 0; module_param(tuner_debug, int, 0644); @@ -320,6 +325,17 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) tuner_info("chip found @ 0x%x (%s)\n", addr << 1, adap->name); + if (show_i2c) { + unsigned char buffer[16]; + int i,rc; + + memset(buffer, 0, sizeof(buffer)); + rc = i2c_master_recv(&t->i2c, buffer, sizeof(buffer)); + printk("tuner-%04x I2C RECV = ",addr); + for (i=0;i<rc;i++) + printk("%02x ",buffer[i]); + printk("\n"); + } /* TEA5767 autodetection code - only for addr = 0xc0 */ if (!no_autodetect) { if (addr == 0x60) { @@ -451,6 +467,17 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) break; } break; + case VIDIOCSAUDIO: + if (check_mode(t, "VIDIOCSAUDIO") == EINVAL) + return 0; + if (check_v4l2(t) == EINVAL) + return 0; + + /* Should be implemented, since bttv calls it */ + tuner_dbg("VIDIOCSAUDIO not implemented.\n"); + + break; + case MSP_SET_MATRIX: case TDA9887_SET_CONFIG: break; /* --- 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 @@ /* - * $Id: tuner-simple.c,v 1.39 2005/07/07 01:49:30 mkrufky Exp $ + * $Id: tuner-simple.c,v 1.43 2005/07/28 18:41:21 mchehab Exp $ * * i2c tv tuner chip device driver * controls all those simple 4-control-bytes style tuners. @@ -245,6 +245,12 @@ static struct tunertype tuners[] = { /* see tea5767.c for details */}, { "Philips FMD1216ME MK3 Hybrid Tuner", Philips, PAL, 16*160.00,16*442.00,0x51,0x52,0x54,0x86,623 }, + + { "LG TDVS-H062F/TUA6034", LGINNOTEK, NTSC, + 16*160.00,16*455.00,0x01,0x02,0x04,0x8e,732}, + + { "Ymec TVF66T5-B/DFF", Philips, PAL, + 16*160.25,16*464.25,0x01,0x02,0x08,0x8e,623}, }; 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[] = { TUNER_ABSENT, "Philips FQ1236 MK3"}, { TUNER_ABSENT, "Samsung TCPN 2121P30A"}, { TUNER_ABSENT, "Samsung TCPE 4121P30A"}, - { TUNER_ABSENT, "TCL MFPE05 2"}, + { TUNER_PHILIPS_FM1216ME_MK3, "TCL MFPE05 2"}, /* 90-99 */ { TUNER_ABSENT, "LG TALN H202T"}, { 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 To compile this support as a module, choose M here: the module will be called i2o_config. + Note: If you want to use the new API you have to download the + i2o_config patch from http://i2o.shadowconnect.com/ + config I2O_CONFIG_OLD_IOCTL bool "Enable ioctls (OBSOLETE)" 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 @@ static struct i2o_driver i2o_config_driver; -/* Special file operations for sysfs */ -struct fops_attribute { - struct bin_attribute bin; - struct file_operations fops; -}; - -/** - * sysfs_read_dummy - */ -static ssize_t sysfs_read_dummy(struct kobject *kobj, char *buf, loff_t offset, - size_t count) -{ - return 0; -}; - -/** - * sysfs_write_dummy - */ -static ssize_t sysfs_write_dummy(struct kobject *kobj, char *buf, loff_t offset, - size_t count) -{ - return 0; -}; - -/** - * sysfs_create_fops_file - Creates attribute with special file operations - * @kobj: kobject which should contains the attribute - * @attr: attributes which should be used to create file - * - * First creates attribute @attr in kobject @kobj. If it is the first time - * this function is called, merge old fops from sysfs with new one and - * write it back. Afterwords the new fops will be set for the created - * attribute. - * - * Returns 0 on success or negative error code on failure. - */ -static int sysfs_create_fops_file(struct kobject *kobj, - struct fops_attribute *attr) -{ - struct file_operations tmp, *fops; - struct dentry *d; - struct qstr qstr; - int rc; - - fops = &attr->fops; - - if (fops->read) - attr->bin.read = sysfs_read_dummy; - - if (fops->write) - attr->bin.write = sysfs_write_dummy; - - if ((rc = sysfs_create_bin_file(kobj, &attr->bin))) - return rc; - - qstr.name = attr->bin.attr.name; - qstr.len = strlen(qstr.name); - qstr.hash = full_name_hash(qstr.name, qstr.len); - - if ((d = lookup_hash(&qstr, kobj->dentry))) { - if (!fops->owner) { - memcpy(&tmp, d->d_inode->i_fop, sizeof(tmp)); - if (fops->read) - tmp.read = fops->read; - if (fops->write) - tmp.write = fops->write; - memcpy(fops, &tmp, sizeof(tmp)); - } - - d->d_inode->i_fop = fops; - } else - sysfs_remove_bin_file(kobj, &attr->bin); - - return -ENOENT; -}; - -/** - * sysfs_remove_fops_file - Remove attribute with special file operations - * @kobj: kobject which contains the attribute - * @attr: attributes which are used to create file - * - * Only wrapper arround sysfs_remove_bin_file() - * - * Returns 0 on success or negative error code on failure. - */ -static inline int sysfs_remove_fops_file(struct kobject *kobj, - struct fops_attribute *attr) -{ - return sysfs_remove_bin_file(kobj, &attr->bin); -}; - -/** - * i2o_config_read_hrt - Returns the HRT of the controller - * @kob: kernel object handle - * @buf: buffer into which the HRT should be copied - * @off: file offset - * @count: number of bytes to read - * - * Put @count bytes starting at @off into @buf from the HRT of the I2O - * controller corresponding to @kobj. - * - * Returns number of bytes copied into buffer. - */ -static ssize_t i2o_config_read_hrt(struct kobject *kobj, char *buf, - loff_t offset, size_t count) -{ - struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop; - i2o_hrt *hrt = c->hrt.virt; - - u32 size = (hrt->num_entries * hrt->entry_len + 2) * 4; - - if (offset > size) - return 0; - - if (offset + count > size) - count = size - offset; - - memcpy(buf, (u8 *) hrt + offset, count); - - return count; -}; - -/** - * i2o_config_read_lct - Returns the LCT of the controller - * @kob: kernel object handle - * @buf: buffer into which the LCT should be copied - * @off: file offset - * @count: number of bytes to read - * - * Put @count bytes starting at @off into @buf from the LCT of the I2O - * controller corresponding to @kobj. - * - * Returns number of bytes copied into buffer. - */ -static ssize_t i2o_config_read_lct(struct kobject *kobj, char *buf, - loff_t offset, size_t count) -{ - struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop; - u32 size = c->lct->table_size * 4; - - if (offset > size) - return 0; - - if (offset + count > size) - count = size - offset; - - memcpy(buf, (u8 *) c->lct + offset, count); - - return count; -}; - -#define I2O_CONFIG_SW_ATTR(_name,_mode,_type,_swid) \ -static ssize_t i2o_config_##_name##_read(struct file *file, char __user *buf, size_t count, loff_t * offset) { \ - return i2o_config_sw_read(file, buf, count, offset, _type, _swid); \ -};\ -\ -static ssize_t i2o_config_##_name##_write(struct file *file, const char __user *buf, size_t count, loff_t * offset) { \ - return i2o_config_sw_write(file, buf, count, offset, _type, _swid); \ -}; \ -\ -static struct fops_attribute i2o_config_attr_##_name = { \ - .bin = { .attr = { .name = __stringify(_name), .mode = _mode, \ - .owner = THIS_MODULE }, \ - .size = 0, }, \ - .fops = { .write = i2o_config_##_name##_write, \ - .read = i2o_config_##_name##_read} \ -}; - -#ifdef CONFIG_I2O_EXT_ADAPTEC - -/** - * i2o_config_dpt_reagion - Converts type and id to flash region - * @swtype: type of software module reading - * @swid: id of software which should be read - * - * Converts type and id from I2O spec to the matching region for DPT / - * Adaptec controllers. - * - * Returns region which match type and id or -1 on error. - */ -static u32 i2o_config_dpt_region(u8 swtype, u8 swid) -{ - switch (swtype) { - case I2O_SOFTWARE_MODULE_IRTOS: - /* - * content: operation firmware - * region size: - * 0xbc000 for 2554, 3754, 2564, 3757 - * 0x170000 for 2865 - * 0x17c000 for 3966 - */ - if (!swid) - return 0; - - break; - - case I2O_SOFTWARE_MODULE_IOP_PRIVATE: - /* - * content: BIOS and SMOR - * BIOS size: first 0x8000 bytes - * region size: - * 0x40000 for 2554, 3754, 2564, 3757 - * 0x80000 for 2865, 3966 - */ - if (!swid) - return 1; - - break; - - case I2O_SOFTWARE_MODULE_IOP_CONFIG: - switch (swid) { - case 0: - /* - * content: NVRAM defaults - * region size: 0x2000 bytes - */ - return 2; - case 1: - /* - * content: serial number - * region size: 0x2000 bytes - */ - return 3; - } - break; - } - - return -1; -}; - -#endif - -/** - * i2o_config_sw_read - Read a software module from controller - * @file: file pointer - * @buf: buffer into which the data should be copied - * @count: number of bytes to read - * @off: file offset - * @swtype: type of software module reading - * @swid: id of software which should be read - * - * Transfers @count bytes at offset @offset from IOP into buffer using - * type @swtype and id @swid as described in I2O spec. - * - * Returns number of bytes copied into buffer or error code on failure. - */ -static ssize_t i2o_config_sw_read(struct file *file, char __user * buf, - size_t count, loff_t * offset, u8 swtype, - u32 swid) -{ - struct sysfs_dirent *sd = file->f_dentry->d_parent->d_fsdata; - struct kobject *kobj = sd->s_element; - struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop; - u32 m, function = I2O_CMD_SW_UPLOAD; - struct i2o_dma buffer; - struct i2o_message __iomem *msg; - u32 __iomem *mptr; - int rc, status; - - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -EBUSY; - - mptr = &msg->body[3]; - - if ((rc = i2o_dma_alloc(&c->pdev->dev, &buffer, count, GFP_KERNEL))) { - i2o_msg_nop(c, m); - return rc; - } -#ifdef CONFIG_I2O_EXT_ADAPTEC - if (c->adaptec) { - mptr = &msg->body[4]; - function = I2O_CMD_PRIVATE; - - writel(TEN_WORD_MSG_SIZE | SGL_OFFSET_8, &msg->u.head[0]); - - writel(I2O_VENDOR_DPT << 16 | I2O_DPT_FLASH_READ, - &msg->body[0]); - writel(i2o_config_dpt_region(swtype, swid), &msg->body[1]); - writel(*offset, &msg->body[2]); - writel(count, &msg->body[3]); - } else -#endif - writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]); - - writel(0xD0000000 | count, mptr++); - writel(buffer.phys, mptr); - - writel(function << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]); - writel(i2o_config_driver.context, &msg->u.head[2]); - writel(0, &msg->u.head[3]); - -#ifdef CONFIG_I2O_EXT_ADAPTEC - if (!c->adaptec) -#endif - { - writel((u32) swtype << 16 | (u32) 1 << 8, &msg->body[0]); - writel(0, &msg->body[1]); - writel(swid, &msg->body[2]); - } - - status = i2o_msg_post_wait_mem(c, m, 60, &buffer); - - if (status == I2O_POST_WAIT_OK) { - if (!(rc = copy_to_user(buf, buffer.virt, count))) { - rc = count; - *offset += count; - } - } else - rc = -EIO; - - if (status != -ETIMEDOUT) - i2o_dma_free(&c->pdev->dev, &buffer); - - return rc; -}; - -/** - * i2o_config_sw_write - Write a software module to controller - * @file: file pointer - * @buf: buffer into which the data should be copied - * @count: number of bytes to read - * @off: file offset - * @swtype: type of software module writing - * @swid: id of software which should be written - * - * Transfers @count bytes at offset @offset from buffer to IOP using - * type @swtype and id @swid as described in I2O spec. - * - * Returns number of bytes copied from buffer or error code on failure. - */ -static ssize_t i2o_config_sw_write(struct file *file, const char __user * buf, - size_t count, loff_t * offset, u8 swtype, - u32 swid) -{ - struct sysfs_dirent *sd = file->f_dentry->d_parent->d_fsdata; - struct kobject *kobj = sd->s_element; - struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop; - u32 m, function = I2O_CMD_SW_DOWNLOAD; - struct i2o_dma buffer; - struct i2o_message __iomem *msg; - u32 __iomem *mptr; - int rc, status; - - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -EBUSY; - - mptr = &msg->body[3]; - - if ((rc = i2o_dma_alloc(&c->pdev->dev, &buffer, count, GFP_KERNEL))) - goto nop_msg; - - if ((rc = copy_from_user(buffer.virt, buf, count))) - goto free_buffer; - -#ifdef CONFIG_I2O_EXT_ADAPTEC - if (c->adaptec) { - mptr = &msg->body[4]; - function = I2O_CMD_PRIVATE; - - writel(TEN_WORD_MSG_SIZE | SGL_OFFSET_8, &msg->u.head[0]); - - writel(I2O_VENDOR_DPT << 16 | I2O_DPT_FLASH_WRITE, - &msg->body[0]); - writel(i2o_config_dpt_region(swtype, swid), &msg->body[1]); - writel(*offset, &msg->body[2]); - writel(count, &msg->body[3]); - } else -#endif - writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]); - - writel(0xD4000000 | count, mptr++); - writel(buffer.phys, mptr); - - writel(function << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]); - writel(i2o_config_driver.context, &msg->u.head[2]); - writel(0, &msg->u.head[3]); - -#ifdef CONFIG_I2O_EXT_ADAPTEC - if (!c->adaptec) -#endif - { - writel((u32) swtype << 16 | (u32) 1 << 8, &msg->body[0]); - writel(0, &msg->body[1]); - writel(swid, &msg->body[2]); - } - - status = i2o_msg_post_wait_mem(c, m, 60, &buffer); - - if (status != -ETIMEDOUT) - i2o_dma_free(&c->pdev->dev, &buffer); - - if (status != I2O_POST_WAIT_OK) - return -EIO; - - *offset += count; - - return count; - - free_buffer: - i2o_dma_free(&c->pdev->dev, &buffer); - - nop_msg: - i2o_msg_nop(c, m); - - return rc; -}; - -/* attribute for HRT in sysfs */ -static struct bin_attribute i2o_config_hrt_attr = { - .attr = { - .name = "hrt", - .mode = S_IRUGO, - .owner = THIS_MODULE}, - .size = 0, - .read = i2o_config_read_hrt -}; - -/* attribute for LCT in sysfs */ -static struct bin_attribute i2o_config_lct_attr = { - .attr = { - .name = "lct", - .mode = S_IRUGO, - .owner = THIS_MODULE}, - .size = 0, - .read = i2o_config_read_lct -}; - -/* IRTOS firmware access */ -I2O_CONFIG_SW_ATTR(irtos, S_IWRSR, I2O_SOFTWARE_MODULE_IRTOS, 0); - -#ifdef CONFIG_I2O_EXT_ADAPTEC - -/* - * attribute for BIOS / SMOR, nvram and serial number access on DPT / Adaptec - * controllers - */ -I2O_CONFIG_SW_ATTR(bios, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_PRIVATE, 0); -I2O_CONFIG_SW_ATTR(nvram, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_CONFIG, 0); -I2O_CONFIG_SW_ATTR(serial, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_CONFIG, 1); - -#endif - -/** - * i2o_config_notify_controller_add - Notify of added controller - * @c: the controller which was added - * - * If a I2O controller is added, we catch the notification to add sysfs - * entries. - */ -static void i2o_config_notify_controller_add(struct i2o_controller *c) -{ - struct kobject *kobj = &c->exec->device.kobj; - - sysfs_create_bin_file(kobj, &i2o_config_hrt_attr); - sysfs_create_bin_file(kobj, &i2o_config_lct_attr); - - sysfs_create_fops_file(kobj, &i2o_config_attr_irtos); -#ifdef CONFIG_I2O_EXT_ADAPTEC - if (c->adaptec) { - sysfs_create_fops_file(kobj, &i2o_config_attr_bios); - sysfs_create_fops_file(kobj, &i2o_config_attr_nvram); - sysfs_create_fops_file(kobj, &i2o_config_attr_serial); - } -#endif -}; - -/** - * i2o_config_notify_controller_remove - Notify of removed controller - * @c: the controller which was removed - * - * If a I2O controller is removed, we catch the notification to remove the - * sysfs entries. - */ -static void i2o_config_notify_controller_remove(struct i2o_controller *c) -{ - struct kobject *kobj = &c->exec->device.kobj; - -#ifdef CONFIG_I2O_EXT_ADAPTEC - if (c->adaptec) { - sysfs_remove_fops_file(kobj, &i2o_config_attr_serial); - sysfs_remove_fops_file(kobj, &i2o_config_attr_nvram); - sysfs_remove_fops_file(kobj, &i2o_config_attr_bios); - } -#endif - sysfs_remove_fops_file(kobj, &i2o_config_attr_irtos); - - sysfs_remove_bin_file(kobj, &i2o_config_lct_attr); - sysfs_remove_bin_file(kobj, &i2o_config_hrt_attr); -}; - /* Config OSM driver struct */ static struct i2o_driver i2o_config_driver = { .name = OSM_NAME, - .notify_controller_add = i2o_config_notify_controller_add, - .notify_controller_remove = i2o_config_notify_controller_remove }; #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 @@ #include <linux/i2o.h> #include "core.h" +#define OSM_DESCRIPTION "I2O-subsystem" + /* PCI device id table for all I2O controllers */ static struct pci_device_id __devinitdata i2o_pci_ids[] = { {PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)}, @@ -66,6 +68,8 @@ static void i2o_pci_free(struct i2o_controller *c) if (c->base.virt) iounmap(c->base.virt); + + pci_release_regions(c->pdev); } /** @@ -84,6 +88,11 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) struct device *dev = &pdev->dev; int i; + if (pci_request_regions(pdev, OSM_DESCRIPTION)) { + printk(KERN_ERR "%s: device already claimed\n", c->name); + return -ENODEV; + } + for (i = 0; i < 6; i++) { /* Skip I/O spaces */ if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) { @@ -138,6 +147,7 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) c->base.virt = ioremap_nocache(c->base.phys, c->base.len); if (!c->base.virt) { printk(KERN_ERR "%s: Unable to map controller.\n", c->name); + i2o_pci_free(c); return -ENOMEM; } 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 @@ #include "wbsd.h" #define DRIVER_NAME "wbsd" -#define DRIVER_VERSION "1.2" +#define DRIVER_VERSION "1.3" #ifdef CONFIG_MMC_DEBUG #define DBG(x...) \ diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 7b293f01c9ed..34b80de34fae 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -1897,6 +1897,7 @@ static int cp_resume (struct pci_dev *pdev) { struct net_device *dev; struct cp_private *cp; + unsigned long flags; dev = pci_get_drvdata (pdev); cp = netdev_priv(dev); @@ -1910,6 +1911,12 @@ static int cp_resume (struct pci_dev *pdev) cp_init_hw (cp); netif_start_queue (dev); + + spin_lock_irqsave (&cp->lock, flags); + + mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE); + + spin_unlock_irqrestore (&cp->lock, flags); return 0; } diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 8a835eb58808..8edb6936fb9b 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1145,7 +1145,7 @@ config IBMVETH be called ibmveth. config IBM_EMAC - tristate "IBM PPC4xx EMAC driver support" + bool "IBM PPC4xx EMAC driver support" depends on 4xx select CRC32 ---help--- @@ -1154,7 +1154,7 @@ config IBM_EMAC config IBM_EMAC_ERRMSG bool "Verbose error messages" - depends on IBM_EMAC + depends on IBM_EMAC && BROKEN config IBM_EMAC_RXB int "Number of receive buffers" 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) struct net_local *lp = netdev_priv(dev); static unsigned version_printed; int i; + int tmp; unsigned rev_type = 0; int eeprom_buff[CHKSUM_LEN]; int retval; @@ -492,14 +493,17 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) goto out2; } } -printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT)); + printk(KERN_DEBUG "PP_addr at %x: 0x%x\n", + ioaddr + ADD_PORT, inw(ioaddr + ADD_PORT)); ioaddr &= ~3; outw(PP_ChipID, ioaddr + ADD_PORT); - if (inw(ioaddr + DATA_PORT) != CHIP_EISA_ID_SIG) { - printk(KERN_ERR "%s: incorrect signature 0x%x\n", - dev->name, inw(ioaddr + DATA_PORT)); + tmp = inw(ioaddr + DATA_PORT); + if (tmp != CHIP_EISA_ID_SIG) { + printk(KERN_DEBUG "%s: incorrect signature at %x: 0x%x!=" + CHIP_EISA_ID_SIG_STR "\n", + dev->name, ioaddr + DATA_PORT, tmp); retval = -ENODEV; goto out2; } 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 @@ #endif #define CHIP_EISA_ID_SIG 0x630E /* Product ID Code for Crystal Chip (CS8900 spec 4.3) */ +#define CHIP_EISA_ID_SIG_STR "0x630E" #ifdef IBMEIPKT #define EISA_ID_SIG 0x4D24 /* IBM */ diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index 5fddc0ff8878..6440a892bb81 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -48,6 +48,10 @@ * net_device_stats * * introduced tx_timeout function * * reworked locking + * + * 01-Jul-2005 Ben Dooks <ben@simtec.co.uk> + * * fixed spinlock call without pointer + * * ensure spinlock is initialised */ #include <linux/module.h> @@ -148,7 +152,6 @@ static int dm9000_probe(struct device *); static int dm9000_open(struct net_device *); static int dm9000_start_xmit(struct sk_buff *, struct net_device *); static int dm9000_stop(struct net_device *); -static int dm9000_do_ioctl(struct net_device *, struct ifreq *, int); static void dm9000_timer(unsigned long); @@ -322,7 +325,7 @@ static void dm9000_timeout(struct net_device *dev) /* Save previous register address */ reg_save = readb(db->io_addr); - spin_lock_irqsave(db->lock,flags); + spin_lock_irqsave(&db->lock,flags); netif_stop_queue(dev); dm9000_reset(db); @@ -333,7 +336,7 @@ static void dm9000_timeout(struct net_device *dev) /* Restore previous register address */ writeb(reg_save, db->io_addr); - spin_unlock_irqrestore(db->lock,flags); + spin_unlock_irqrestore(&db->lock,flags); } @@ -387,8 +390,6 @@ dm9000_probe(struct device *dev) int i; u32 id_val; - printk(KERN_INFO "%s Ethernet Driver\n", CARDNAME); - /* Init network device */ ndev = alloc_etherdev(sizeof (struct board_info)); if (!ndev) { @@ -405,6 +406,8 @@ dm9000_probe(struct device *dev) db = (struct board_info *) ndev->priv; memset(db, 0, sizeof (*db)); + spin_lock_init(&db->lock); + if (pdev->num_resources < 2) { ret = -ENODEV; goto out; @@ -541,7 +544,6 @@ dm9000_probe(struct device *dev) ndev->stop = &dm9000_stop; ndev->get_stats = &dm9000_get_stats; ndev->set_multicast_list = &dm9000_hash_table; - ndev->do_ioctl = &dm9000_do_ioctl; #ifdef DM9000_PROGRAM_EEPROM program_eeprom(db); @@ -612,7 +614,7 @@ dm9000_open(struct net_device *dev) /* set and active a timer process */ init_timer(&db->timer); - db->timer.expires = DM9000_TIMER_WUT * 2; + db->timer.expires = DM9000_TIMER_WUT; db->timer.data = (unsigned long) dev; db->timer.function = &dm9000_timer; add_timer(&db->timer); @@ -845,15 +847,6 @@ dm9000_get_stats(struct net_device *dev) return &db->stats; } -/* - * Process the upper socket ioctl command - */ -static int -dm9000_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - PRINTK1("entering %s\n",__FUNCTION__); - return 0; -} /* * A periodic timer routine @@ -864,21 +857,11 @@ dm9000_timer(unsigned long data) { struct net_device *dev = (struct net_device *) data; board_info_t *db = (board_info_t *) dev->priv; - u8 reg_save; - unsigned long flags; PRINTK3("dm9000_timer()\n"); - spin_lock_irqsave(db->lock,flags); - /* Save previous register address */ - reg_save = readb(db->io_addr); - mii_check_media(&db->mii, netif_msg_link(db), 0); - /* Restore previous register address */ - writeb(reg_save, db->io_addr); - spin_unlock_irqrestore(db->lock,flags); - /* Set timer again */ db->timer.expires = DM9000_TIMER_WUT; add_timer(&db->timer); @@ -1098,9 +1081,14 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg) { board_info_t *db = (board_info_t *) dev->priv; unsigned long flags; + unsigned int reg_save; int ret; spin_lock_irqsave(&db->lock,flags); + + /* Save previous register address */ + reg_save = readb(db->io_addr); + /* Fill the phyxcer register into REG_0C */ iow(db, DM9000_EPAR, DM9000_PHY | reg); @@ -1111,6 +1099,9 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg) /* The read data keeps on REG_0D & REG_0E */ ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL); + /* restore the previous address */ + writeb(reg_save, db->io_addr); + spin_unlock_irqrestore(&db->lock,flags); return ret; @@ -1124,9 +1115,13 @@ dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value) { board_info_t *db = (board_info_t *) dev->priv; unsigned long flags; + unsigned long reg_save; spin_lock_irqsave(&db->lock,flags); + /* Save previous register address */ + reg_save = readb(db->io_addr); + /* Fill the phyxcer register into REG_0C */ iow(db, DM9000_EPAR, DM9000_PHY | reg); @@ -1138,6 +1133,9 @@ dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value) udelay(500); /* Wait write complete */ iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer write command */ + /* restore the previous address */ + writeb(reg_save, db->io_addr); + spin_unlock_irqrestore(&db->lock,flags); } @@ -1202,6 +1200,8 @@ static struct device_driver dm9000_driver = { static int __init dm9000_init(void) { + printk(KERN_INFO "%s Ethernet Driver\n", CARDNAME); + return driver_register(&dm9000_driver); /* search board and register */ } 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) struct e1000_adapter *adapter = netdev_priv(netdev); disable_irq(adapter->pdev->irq); e1000_intr(adapter->pdev->irq, netdev, NULL); + e1000_clean_tx_irq(adapter); enable_irq(adapter->pdev->irq); } #endif diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index e44f8e9055ef..0b230222bfea 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -130,12 +130,11 @@ struct sixpack { #define AX25_6PACK_HEADER_LEN 0 -static void sp_start_tx_timer(struct sixpack *); static void sixpack_decode(struct sixpack *, unsigned char[], int); static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char); /* - * perform the persistence/slottime algorithm for CSMA access. If the + * Perform the persistence/slottime algorithm for CSMA access. If the * persistence check was successful, write the data to the serial driver. * Note that in case of DAMA operation, the data is not sent here. */ @@ -143,7 +142,7 @@ static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char); static void sp_xmit_on_air(unsigned long channel) { struct sixpack *sp = (struct sixpack *) channel; - int actual; + int actual, when = sp->slottime; static unsigned char random; random = random * 17 + 41; @@ -159,20 +158,10 @@ static void sp_xmit_on_air(unsigned long channel) sp->tty->driver->write(sp->tty, &sp->led_state, 1); sp->status2 = 0; } else - sp_start_tx_timer(sp); + mod_timer(&sp->tx_t, jiffies + ((when + 1) * HZ) / 100); } /* ----> 6pack timer interrupt handler and friends. <---- */ -static void sp_start_tx_timer(struct sixpack *sp) -{ - int when = sp->slottime; - - del_timer(&sp->tx_t); - sp->tx_t.data = (unsigned long) sp; - sp->tx_t.function = sp_xmit_on_air; - sp->tx_t.expires = jiffies + ((when + 1) * HZ) / 100; - add_timer(&sp->tx_t); -} /* Encapsulate one AX.25 frame and stuff into a TTY queue. */ 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) sp->xleft = count; sp->xhead = sp->xbuff; sp->status2 = count; - if (sp->duplex == 0) - sp_start_tx_timer(sp); + sp_xmit_on_air((unsigned long)sp); } return; @@ -320,12 +308,6 @@ static int sp_set_mac_address(struct net_device *dev, void *addr) { struct sockaddr_ax25 *sa = addr; - if (sa->sax25_family != AF_AX25) - return -EINVAL; - - if (!sa->sax25_ndigis) - return -EINVAL; - spin_lock_irq(&dev->xmit_lock); memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN); spin_unlock_irq(&dev->xmit_lock); @@ -680,6 +662,9 @@ static int sixpack_open(struct tty_struct *tty) netif_start_queue(dev); init_timer(&sp->tx_t); + sp->tx_t.function = sp_xmit_on_air; + sp->tx_t.data = (unsigned long) sp; + init_timer(&sp->resync_t); spin_unlock_bh(&sp->lock); 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 config 6PACK tristate "Serial port 6PACK driver" - depends on AX25 && BROKEN_ON_SMP + depends on AX25 ---help--- 6pack is a transmission protocol for the data exchange between your PC and your TNC (the Terminal Node Controller acts as a kind of diff --git a/drivers/net/ibm_emac/ibm_emac_core.c b/drivers/net/ibm_emac/ibm_emac_core.c index 6482d994d489..0de3bb906174 100644 --- a/drivers/net/ibm_emac/ibm_emac_core.c +++ b/drivers/net/ibm_emac/ibm_emac_core.c @@ -1253,7 +1253,7 @@ static int emac_init_tah(struct ocp_enet_private *fep) TAH_MR_CVR | TAH_MR_ST_768 | TAH_MR_TFS_10KB | TAH_MR_DTFP | TAH_MR_DIG); - iounmap(&tahp); + iounmap(tahp); return 0; } @@ -1712,11 +1712,10 @@ struct mal_commac_ops emac_commac_ops = { }; #ifdef CONFIG_NET_POLL_CONTROLLER -static int emac_netpoll(struct net_device *ndev) +static void emac_netpoll(struct net_device *ndev) { emac_rxeob_dev((void *)ndev, 0); emac_txeob_dev((void *)ndev, 0); - return 0; } #endif diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index d520b5920d6c..49e5467bdd73 100644 --- a/drivers/net/ioc3-eth.c +++ b/drivers/net/ioc3-eth.c @@ -499,7 +499,7 @@ static int ioc3_mdio_read(struct net_device *dev, int phy, int reg) ioc3_w_micr((phy << MICR_PHYADDR_SHIFT) | reg | MICR_READTRIG); while (ioc3_r_micr() & MICR_BUSY); - return ioc3_r_micr() & MIDR_DATA_MASK; + return ioc3_r_midr_r() & MIDR_DATA_MASK; } static void ioc3_mdio_write(struct net_device *dev, int phy, int reg, int data) @@ -1291,7 +1291,6 @@ static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dev->features = NETIF_F_IP_CSUM; #endif - ioc3_setup_duplex(ip); sw_physid1 = ioc3_mdio_read(dev, ip->mii.phy_id, MII_PHYSID1); sw_physid2 = ioc3_mdio_read(dev, ip->mii.phy_id, MII_PHYSID2); @@ -1300,6 +1299,7 @@ static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_stop; mii_check_media(&ip->mii, 1, 1); + ioc3_setup_duplex(ip); vendor = (sw_physid1 << 12) | (sw_physid2 >> 4); model = (sw_physid2 >> 4) & 0x3f; @@ -1524,7 +1524,7 @@ static void ioc3_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *info) { struct ioc3_private *ip = netdev_priv(dev); - + strcpy (info->driver, IOC3_NAME); strcpy (info->version, IOC3_VERSION); strcpy (info->bus_info, pci_name(ip->pdev)); @@ -1550,7 +1550,7 @@ static int ioc3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) spin_lock_irq(&ip->ioc3_lock); rc = mii_ethtool_sset(&ip->mii, cmd); spin_unlock_irq(&ip->ioc3_lock); - + return rc; } diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index b33111e21313..1f61f0cc95d8 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -214,7 +214,7 @@ struct net_device loopback_dev = { .ethtool_ops = &loopback_ethtool_ops, }; -/* Setup and register the of the LOOPBACK device. */ +/* Setup and register the loopback device. */ int __init loopback_init(void) { struct net_device_stats *stats; 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) kfree(pAC); } +#ifdef CONFIG_PM +static int skge_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct net_device *dev = pci_get_drvdata(pdev); + DEV_NET *pNet = netdev_priv(dev); + SK_AC *pAC = pNet->pAC; + struct net_device *otherdev = pAC->dev[1]; + + if (netif_running(dev)) { + netif_carrier_off(dev); + DoPrintInterfaceChange = SK_FALSE; + SkDrvDeInitAdapter(pAC, 0); /* performs SkGeClose */ + netif_device_detach(dev); + } + if (otherdev != dev) { + if (netif_running(otherdev)) { + netif_carrier_off(otherdev); + DoPrintInterfaceChange = SK_FALSE; + SkDrvDeInitAdapter(pAC, 1); /* performs SkGeClose */ + netif_device_detach(otherdev); + } + } + + pci_save_state(pdev); + pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); + if (pAC->AllocFlag & SK_ALLOC_IRQ) { + free_irq(dev->irq, dev); + } + pci_disable_device(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + + return 0; +} + +static int skge_resume(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + DEV_NET *pNet = netdev_priv(dev); + SK_AC *pAC = pNet->pAC; + struct net_device *otherdev = pAC->dev[1]; + int ret; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + pci_enable_device(pdev); + pci_set_master(pdev); + if (pAC->GIni.GIMacsFound == 2) + ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, pAC->Name, dev); + else + ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ, pAC->Name, dev); + if (ret) { + printk(KERN_WARNING "sk98lin: unable to acquire IRQ %d\n", dev->irq); + pAC->AllocFlag &= ~SK_ALLOC_IRQ; + dev->irq = 0; + pci_disable_device(pdev); + return -EBUSY; + } + + netif_device_attach(dev); + if (netif_running(dev)) { + DoPrintInterfaceChange = SK_FALSE; + SkDrvInitAdapter(pAC, 0); /* first device */ + } + if (otherdev != dev) { + netif_device_attach(otherdev); + if (netif_running(otherdev)) { + DoPrintInterfaceChange = SK_FALSE; + SkDrvInitAdapter(pAC, 1); /* second device */ + } + } + + return 0; +} +#else +#define skge_suspend NULL +#define skge_resume NULL +#endif + static struct pci_device_id skge_pci_tbl[] = { { PCI_VENDOR_ID_3COM, 0x1700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, @@ -5158,6 +5236,8 @@ static struct pci_driver skge_driver = { .id_table = skge_pci_tbl, .probe = skge_probe_one, .remove = __devexit_p(skge_remove_one), + .suspend = skge_suspend, + .resume = skge_resume, }; 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 */ * we set the PHY to coma mode and switch to D3 power state. */ if (pAC->GIni.GIYukonLite && - pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { + pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { /* for all ports switch PHY to coma mode */ 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) */ /* WA code for COMA mode */ if (pAC->GIni.GIYukonLite && - pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { + pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { SK_IN32(IoC, B2_GP_IO, &DWord); @@ -1110,7 +1110,7 @@ int Port) /* Port Index (MAC_1 + n) */ /* WA code for COMA mode */ if (pAC->GIni.GIYukonLite && - pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { + pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { SK_IN32(IoC, B2_GP_IO, &DWord); @@ -2126,7 +2126,7 @@ SK_U8 Mode) /* low power mode */ int Ret = 0; if (pAC->GIni.GIYukonLite && - pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { + pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { /* save current power mode */ LastMode = pAC->GIni.GP[Port].PPhyPowerState; @@ -2253,7 +2253,7 @@ int Port) /* Port Index (e.g. MAC_1) */ int Ret = 0; if (pAC->GIni.GIYukonLite && - pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { + pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { /* save current power mode */ 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 @@ #include "skge.h" #define DRV_NAME "skge" -#define DRV_VERSION "0.7" +#define DRV_VERSION "0.8" #define PFX DRV_NAME " " #define DEFAULT_TX_RING_SIZE 128 @@ -55,7 +55,7 @@ #define ETH_JUMBO_MTU 9000 #define TX_WATCHDOG (5 * HZ) #define NAPI_WEIGHT 64 -#define BLINK_HZ (HZ/4) +#define BLINK_MS 250 MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver"); MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>"); @@ -75,7 +75,6 @@ static const struct pci_device_id skge_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940B) }, { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE) }, { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU) }, - { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, /* SK-9Exx */ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T), }, { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) }, { 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) } else { u32 setting; - switch(ecmd->speed) { + switch (ecmd->speed) { case SPEED_1000: if (ecmd->duplex == DUPLEX_FULL) setting = SUPPORTED_1000baseT_Full; @@ -620,84 +619,98 @@ static int skge_set_coalesce(struct net_device *dev, return 0; } -static void skge_led_on(struct skge_hw *hw, int port) +enum led_mode { LED_MODE_OFF, LED_MODE_ON, LED_MODE_TST }; +static void skge_led(struct skge_port *skge, enum led_mode mode) { + struct skge_hw *hw = skge->hw; + int port = skge->port; + + spin_lock_bh(&hw->phy_lock); if (hw->chip_id == CHIP_ID_GENESIS) { - skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON); - skge_write8(hw, B0_LED, LED_STAT_ON); + switch (mode) { + case LED_MODE_OFF: + xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF); + skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF); + skge_write32(hw, SK_REG(port, RX_LED_VAL), 0); + skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF); + break; - skge_write8(hw, SK_REG(port, RX_LED_TST), LED_T_ON); - skge_write32(hw, SK_REG(port, RX_LED_VAL), 100); - skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START); + case LED_MODE_ON: + skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON); + skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_LINKSYNC_ON); - /* For Broadcom Phy only */ - xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON); - } else { - gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); - gm_phy_write(hw, port, PHY_MARV_LED_OVER, - PHY_M_LED_MO_DUP(MO_LED_ON) | - PHY_M_LED_MO_10(MO_LED_ON) | - PHY_M_LED_MO_100(MO_LED_ON) | - PHY_M_LED_MO_1000(MO_LED_ON) | - PHY_M_LED_MO_RX(MO_LED_ON)); - } -} + skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START); + skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START); -static void skge_led_off(struct skge_hw *hw, int port) -{ - if (hw->chip_id == CHIP_ID_GENESIS) { - skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF); - skge_write8(hw, B0_LED, LED_STAT_OFF); + break; - skge_write32(hw, SK_REG(port, RX_LED_VAL), 0); - skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF); + case LED_MODE_TST: + skge_write8(hw, SK_REG(port, RX_LED_TST), LED_T_ON); + skge_write32(hw, SK_REG(port, RX_LED_VAL), 100); + skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START); - /* Broadcom only */ - xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF); + xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON); + break; + } } else { - gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); - gm_phy_write(hw, port, PHY_MARV_LED_OVER, - PHY_M_LED_MO_DUP(MO_LED_OFF) | - PHY_M_LED_MO_10(MO_LED_OFF) | - PHY_M_LED_MO_100(MO_LED_OFF) | - PHY_M_LED_MO_1000(MO_LED_OFF) | - PHY_M_LED_MO_RX(MO_LED_OFF)); + switch (mode) { + case LED_MODE_OFF: + gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); + gm_phy_write(hw, port, PHY_MARV_LED_OVER, + PHY_M_LED_MO_DUP(MO_LED_OFF) | + PHY_M_LED_MO_10(MO_LED_OFF) | + PHY_M_LED_MO_100(MO_LED_OFF) | + PHY_M_LED_MO_1000(MO_LED_OFF) | + PHY_M_LED_MO_RX(MO_LED_OFF)); + break; + case LED_MODE_ON: + gm_phy_write(hw, port, PHY_MARV_LED_CTRL, + PHY_M_LED_PULS_DUR(PULS_170MS) | + PHY_M_LED_BLINK_RT(BLINK_84MS) | + PHY_M_LEDC_TX_CTRL | + PHY_M_LEDC_DP_CTRL); + + gm_phy_write(hw, port, PHY_MARV_LED_OVER, + PHY_M_LED_MO_RX(MO_LED_OFF) | + (skge->speed == SPEED_100 ? + PHY_M_LED_MO_100(MO_LED_ON) : 0)); + break; + case LED_MODE_TST: + gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); + gm_phy_write(hw, port, PHY_MARV_LED_OVER, + PHY_M_LED_MO_DUP(MO_LED_ON) | + PHY_M_LED_MO_10(MO_LED_ON) | + PHY_M_LED_MO_100(MO_LED_ON) | + PHY_M_LED_MO_1000(MO_LED_ON) | + PHY_M_LED_MO_RX(MO_LED_ON)); + } } -} - -static void skge_blink_timer(unsigned long data) -{ - struct skge_port *skge = (struct skge_port *) data; - struct skge_hw *hw = skge->hw; - unsigned long flags; - - spin_lock_irqsave(&hw->phy_lock, flags); - if (skge->blink_on) - skge_led_on(hw, skge->port); - else - skge_led_off(hw, skge->port); - spin_unlock_irqrestore(&hw->phy_lock, flags); - - skge->blink_on = !skge->blink_on; - mod_timer(&skge->led_blink, jiffies + BLINK_HZ); + spin_unlock_bh(&hw->phy_lock); } /* blink LED's for finding board */ static int skge_phys_id(struct net_device *dev, u32 data) { struct skge_port *skge = netdev_priv(dev); + unsigned long ms; + enum led_mode mode = LED_MODE_TST; if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); + ms = jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT / HZ) * 1000; + else + ms = data * 1000; - /* start blinking */ - skge->blink_on = 1; - mod_timer(&skge->led_blink, jiffies+1); + while (ms > 0) { + skge_led(skge, mode); + mode ^= LED_MODE_TST; - msleep_interruptible(data * 1000); - del_timer_sync(&skge->led_blink); + if (msleep_interruptible(BLINK_MS)) + break; + ms -= BLINK_MS; + } - skge_led_off(skge->hw, skge->port); + /* back to regular LED state */ + skge_led(skge, netif_running(dev) ? LED_MODE_ON : LED_MODE_OFF); return 0; } @@ -1028,7 +1041,7 @@ static void bcom_check_link(struct skge_hw *hw, int port) } /* Check Duplex mismatch */ - switch(aux & PHY_B_AS_AN_RES_MSK) { + switch (aux & PHY_B_AS_AN_RES_MSK) { case PHY_B_RES_1000FD: skge->duplex = DUPLEX_FULL; break; @@ -1099,7 +1112,7 @@ static void bcom_phy_init(struct skge_port *skge, int jumbo) r |= XM_MMU_NO_PRE; xm_write16(hw, port, XM_MMU_CMD,r); - switch(id1) { + switch (id1) { case PHY_BCOM_ID1_C0: /* * Workaround BCOM Errata for the C0 type. @@ -1194,13 +1207,6 @@ static void genesis_mac_init(struct skge_hw *hw, int port) xm_write16(hw, port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC); - /* initialize Rx, Tx and Link LED */ - skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON); - skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_LINKSYNC_ON); - - skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START); - skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START); - /* Unreset the XMAC. */ skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); @@ -1209,7 +1215,6 @@ static void genesis_mac_init(struct skge_hw *hw, int port) * namely for the 1000baseTX cards that use the XMAC's * GMII mode. */ - spin_lock_bh(&hw->phy_lock); /* Take external Phy out of reset */ r = skge_read32(hw, B2_GP_IO); if (port == 0) @@ -1219,7 +1224,6 @@ static void genesis_mac_init(struct skge_hw *hw, int port) skge_write32(hw, B2_GP_IO, r); skge_read32(hw, B2_GP_IO); - spin_unlock_bh(&hw->phy_lock); /* Enable GMII interfac */ 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) { struct skge_port *skge = netdev_priv(hw->dev[port]); u16 ctrl, ct1000, adv; - u16 ledctrl, ledover; pr_debug("yukon_init\n"); if (skge->autoneg == AUTONEG_ENABLE) { @@ -1641,32 +1644,11 @@ static void yukon_init(struct skge_hw *hw, int port) gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv); gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); - /* Setup Phy LED's */ - ledctrl = PHY_M_LED_PULS_DUR(PULS_170MS); - ledover = 0; - - ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) | PHY_M_LEDC_TX_CTRL; - - /* turn off the Rx LED (LED_RX) */ - ledover |= PHY_M_LED_MO_RX(MO_LED_OFF); - - /* disable blink mode (LED_DUPLEX) on collisions */ - ctrl |= PHY_M_LEDC_DP_CTRL; - gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); - - if (skge->autoneg == AUTONEG_DISABLE || skge->speed == SPEED_100) { - /* turn on 100 Mbps LED (LED_LINK100) */ - ledover |= PHY_M_LED_MO_100(MO_LED_ON); - } - - if (ledover) - gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover); - /* Enable phy interrupt on autonegotiation complete (or link up) */ if (skge->autoneg == AUTONEG_ENABLE) - gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL); + gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_MSK); else - gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); + gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_DEF_MSK); } 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) /* WA code for COMA mode -- set PHY reset */ if (hw->chip_id == CHIP_ID_YUKON_LITE && - hw->chip_rev == CHIP_REV_YU_LITE_A3) + hw->chip_rev >= CHIP_REV_YU_LITE_A3) skge_write32(hw, B2_GP_IO, (skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9)); @@ -1701,7 +1683,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port) /* WA code for COMA mode -- clear PHY reset */ if (hw->chip_id == CHIP_ID_YUKON_LITE && - hw->chip_rev == CHIP_REV_YU_LITE_A3) + hw->chip_rev >= CHIP_REV_YU_LITE_A3) skge_write32(hw, B2_GP_IO, (skge_read32(hw, B2_GP_IO) | GP_DIR_9) & ~GP_IO_9); @@ -1745,9 +1727,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port) gma_write16(hw, port, GM_GP_CTRL, reg); skge_read16(hw, GMAC_IRQ_SRC); - spin_lock_bh(&hw->phy_lock); yukon_init(hw, port); - spin_unlock_bh(&hw->phy_lock); /* MIB clear */ reg = gma_read16(hw, port, GM_PHY_ADDR); @@ -1796,7 +1776,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port) skge_write16(hw, SK_REG(port, RX_GMF_FL_MSK), RX_FF_FL_DEF_MSK); reg = GMF_OPER_ON | GMF_RX_F_FL_ON; if (hw->chip_id == CHIP_ID_YUKON_LITE && - hw->chip_rev == CHIP_REV_YU_LITE_A3) + hw->chip_rev >= CHIP_REV_YU_LITE_A3) reg &= ~GMF_RX_F_FL_ON; skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR); skge_write16(hw, SK_REG(port, RX_GMF_CTRL_T), reg); @@ -1813,19 +1793,19 @@ static void yukon_stop(struct skge_port *skge) int port = skge->port; if (hw->chip_id == CHIP_ID_YUKON_LITE && - hw->chip_rev == CHIP_REV_YU_LITE_A3) { + hw->chip_rev >= CHIP_REV_YU_LITE_A3) { skge_write32(hw, B2_GP_IO, skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9); } gma_write16(hw, port, GM_GP_CTRL, gma_read16(hw, port, GM_GP_CTRL) - & ~(GM_GPCR_RX_ENA|GM_GPCR_RX_ENA)); + & ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA)); gma_read16(hw, port, GM_GP_CTRL); /* set GPHY Control reset */ - gma_write32(hw, port, GPHY_CTRL, GPC_RST_SET); - gma_write32(hw, port, GMAC_CTRL, GMC_RST_SET); + skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); + skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET); } 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) if (status & GM_IS_RX_FF_OR) { ++skge->net_stats.rx_fifo_errors; - gma_write8(hw, port, RX_GMF_CTRL_T, GMF_CLI_RX_FO); + skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_CLI_RX_FO); } + if (status & GM_IS_TX_FF_UR) { ++skge->net_stats.tx_fifo_errors; - gma_write8(hw, port, TX_GMF_CTRL_T, GMF_CLI_TX_FU); + skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_FU); } } @@ -1896,7 +1877,7 @@ static void yukon_link_up(struct skge_port *skge) reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA; gma_write16(hw, port, GM_GP_CTRL, reg); - gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); + gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_DEF_MSK); skge_link_up(skge); } @@ -1904,12 +1885,14 @@ static void yukon_link_down(struct skge_port *skge) { struct skge_hw *hw = skge->hw; int port = skge->port; + u16 ctrl; pr_debug("yukon_link_down\n"); gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0); - gm_phy_write(hw, port, GM_GP_CTRL, - gm_phy_read(hw, port, GM_GP_CTRL) - & ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA)); + + ctrl = gma_read16(hw, port, GM_GP_CTRL); + ctrl &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); + gma_write16(hw, port, GM_GP_CTRL, ctrl); if (skge->flow_control == FLOW_MODE_REM_SEND) { /* restore Asymmetric Pause bit */ @@ -2097,10 +2080,12 @@ static int skge_up(struct net_device *dev) skge_write32(hw, B0_IMSK, hw->intr_mask); /* Initialze MAC */ + spin_lock_bh(&hw->phy_lock); if (hw->chip_id == CHIP_ID_GENESIS) genesis_mac_init(hw, port); else yukon_mac_init(hw, port); + spin_unlock_bh(&hw->phy_lock); /* Configure RAMbuffers */ chunk = hw->ram_size / ((hw->ports + 1)*2); @@ -2116,6 +2101,7 @@ static int skge_up(struct net_device *dev) /* Start receiver BMU */ wmb(); skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F); + skge_led(skge, LED_MODE_ON); pr_debug("skge_up completed\n"); return 0; @@ -2140,8 +2126,6 @@ static int skge_down(struct net_device *dev) netif_stop_queue(dev); - del_timer_sync(&skge->led_blink); - /* Stop transmitter */ skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP); skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), @@ -2175,15 +2159,12 @@ static int skge_down(struct net_device *dev) if (hw->chip_id == CHIP_ID_GENESIS) { skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_RST_SET); skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_RST_SET); - skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_STOP); - skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_STOP); } else { skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET); } - /* turn off led's */ - skge_write16(hw, B0_LED, LED_STAT_OFF); + skge_led(skge, LED_MODE_OFF); skge_tx_clean(skge); skge_rx_clean(skge); @@ -2633,11 +2614,17 @@ static inline void skge_tx_intr(struct net_device *dev) spin_unlock(&skge->tx_lock); } +/* Parity errors seem to happen when Genesis is connected to a switch + * with no other ports present. Heartbeat error?? + */ static void skge_mac_parity(struct skge_hw *hw, int port) { - printk(KERN_ERR PFX "%s: mac data parity error\n", - hw->dev[port] ? hw->dev[port]->name - : (port == 0 ? "(port A)": "(port B")); + struct net_device *dev = hw->dev[port]; + + if (dev) { + struct skge_port *skge = netdev_priv(dev); + ++skge->net_stats.tx_heartbeat_errors; + } if (hw->chip_id == CHIP_ID_GENESIS) 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, spin_lock_init(&skge->tx_lock); - init_timer(&skge->led_blink); - skge->led_blink.function = skge_blink_timer; - skge->led_blink.data = (unsigned long) skge; - if (hw->chip_id != CHIP_ID_GENESIS) { dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; 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 { PHY_M_IS_DTE_CHANGE = 1<<2, /* DTE Power Det. Status Changed */ PHY_M_IS_POL_CHANGE = 1<<1, /* Polarity Changed */ PHY_M_IS_JABBER = 1<<0, /* Jabber */ -}; -#define PHY_M_DEF_MSK ( PHY_M_IS_AN_ERROR | PHY_M_IS_LSP_CHANGE | \ - PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR) + PHY_M_IS_DEF_MSK = PHY_M_IS_AN_ERROR | PHY_M_IS_LSP_CHANGE | + PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR, + + PHY_M_IS_AN_MSK = PHY_M_IS_AN_ERROR | PHY_M_IS_AN_COMPL, +}; /***** PHY_MARV_EXT_CTRL 16 bit r/w Ext. PHY Specific Ctrl *****/ enum { @@ -1509,7 +1511,7 @@ enum { PHY_M_LEDC_TX_C_MSB = 1<<0, /* Tx Control (MSB, 88E1111 only) */ }; -#define PHY_M_LED_PULS_DUR(x) ( ((x)<<12) & PHY_M_LEDC_PULS_MSK) +#define PHY_M_LED_PULS_DUR(x) (((x)<<12) & PHY_M_LEDC_PULS_MSK) enum { PULS_NO_STR = 0,/* no pulse stretching */ @@ -1522,7 +1524,7 @@ enum { PULS_1300MS = 7,/* 1.3 s to 2.7 s */ }; -#define PHY_M_LED_BLINK_RT(x) ( ((x)<<8) & PHY_M_LEDC_BL_R_MSK) +#define PHY_M_LED_BLINK_RT(x) (((x)<<8) & PHY_M_LEDC_BL_R_MSK) enum { BLINK_42MS = 0,/* 42 ms */ @@ -1602,9 +1604,9 @@ enum { PHY_M_FELP_LED0_MSK = 0xf, /* Bit 3.. 0: LED0 Mask (SPEED) */ }; -#define PHY_M_FELP_LED2_CTRL(x) ( ((x)<<8) & PHY_M_FELP_LED2_MSK) -#define PHY_M_FELP_LED1_CTRL(x) ( ((x)<<4) & PHY_M_FELP_LED1_MSK) -#define PHY_M_FELP_LED0_CTRL(x) ( ((x)<<0) & PHY_M_FELP_LED0_MSK) +#define PHY_M_FELP_LED2_CTRL(x) (((x)<<8) & PHY_M_FELP_LED2_MSK) +#define PHY_M_FELP_LED1_CTRL(x) (((x)<<4) & PHY_M_FELP_LED1_MSK) +#define PHY_M_FELP_LED0_CTRL(x) (((x)<<0) & PHY_M_FELP_LED0_MSK) enum { LED_PAR_CTRL_COLX = 0x00, @@ -1640,7 +1642,7 @@ enum { PHY_M_MAC_MD_COPPER = 5,/* Copper only */ PHY_M_MAC_MD_1000BX = 7,/* 1000Base-X only */ }; -#define PHY_M_MAC_MODE_SEL(x) ( ((x)<<7) & PHY_M_MAC_MD_MSK) +#define PHY_M_MAC_MODE_SEL(x) (((x)<<7) & PHY_M_MAC_MD_MSK) /***** PHY_MARV_PHY_CTRL (page 3) 16 bit r/w LED Control Reg. *****/ enum { @@ -1650,10 +1652,10 @@ enum { PHY_M_LEDC_STA0_MSK = 0xf, /* Bit 3.. 0: STAT0 LED Ctrl. Mask */ }; -#define PHY_M_LEDC_LOS_CTRL(x) ( ((x)<<12) & PHY_M_LEDC_LOS_MSK) -#define PHY_M_LEDC_INIT_CTRL(x) ( ((x)<<8) & PHY_M_LEDC_INIT_MSK) -#define PHY_M_LEDC_STA1_CTRL(x) ( ((x)<<4) & PHY_M_LEDC_STA1_MSK) -#define PHY_M_LEDC_STA0_CTRL(x) ( ((x)<<0) & PHY_M_LEDC_STA0_MSK) +#define PHY_M_LEDC_LOS_CTRL(x) (((x)<<12) & PHY_M_LEDC_LOS_MSK) +#define PHY_M_LEDC_INIT_CTRL(x) (((x)<<8) & PHY_M_LEDC_INIT_MSK) +#define PHY_M_LEDC_STA1_CTRL(x) (((x)<<4) & PHY_M_LEDC_STA1_MSK) +#define PHY_M_LEDC_STA0_CTRL(x) (((x)<<0) & PHY_M_LEDC_STA0_MSK) /* GMAC registers */ /* Port Registers */ @@ -2505,8 +2507,6 @@ struct skge_port { dma_addr_t dma; unsigned long mem_size; unsigned int rx_buf_size; - - struct timer_list led_blink; }; @@ -2606,17 +2606,6 @@ static inline void gma_write16(const struct skge_hw *hw, int port, int r, u16 v) skge_write16(hw, SK_GMAC_REG(port,r), v); } -static inline void gma_write32(const struct skge_hw *hw, int port, int r, u32 v) -{ - skge_write16(hw, SK_GMAC_REG(port, r), (u16) v); - skge_write32(hw, SK_GMAC_REG(port, r+4), (u16)(v >> 16)); -} - -static inline void gma_write8(const struct skge_hw *hw, int port, int r, u8 v) -{ - skge_write8(hw, SK_GMAC_REG(port,r), v); -} - static inline void gma_set_addr(struct skge_hw *hw, int port, int reg, const u8 *addr) { 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) #define SMC_IRQ_TRIGGER_TYPE (( \ machine_is_omap_h2() \ || machine_is_omap_h3() \ - || (machine_is_omap_innovator() && !cpu_is_omap150()) \ + || (machine_is_omap_innovator() && !cpu_is_omap1510()) \ ) ? IRQT_FALLING : IRQT_RISING) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 201a550f0bcc..6d4ab1e333b5 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -66,8 +66,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.34" -#define DRV_MODULE_RELDATE "July 25, 2005" +#define DRV_MODULE_VERSION "3.37" +#define DRV_MODULE_RELDATE "August 25, 2005" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -7865,8 +7865,6 @@ static int tg3_test_loopback(struct tg3 *tp) err = -EIO; - tg3_abort_hw(tp, 1); - tg3_reset_hw(tp); mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) | @@ -8970,6 +8968,8 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) tp->phy_id = hw_phy_id; if (hw_phy_id_masked == PHY_ID_BCM8002) tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES; + else + tp->tg3_flags2 &= ~TG3_FLG2_PHY_SERDES; } else { if (tp->phy_id != PHY_ID_INVALID) { /* Do nothing, phy ID already set up in @@ -10421,6 +10421,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tg3_init_coal(tp); + /* Now that we have fully setup the chip, save away a snapshot + * of the PCI config space. We need to restore this after + * GRC_MISC_CFG core clock resets and some resume events. + */ + pci_save_state(tp->pdev); + err = register_netdev(dev); if (err) { printk(KERN_ERR PFX "Cannot register net device, " @@ -10430,12 +10436,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, pci_set_drvdata(pdev, dev); - /* Now that we have fully setup the chip, save away a snapshot - * of the PCI config space. We need to restore this after - * GRC_MISC_CFG core clock resets and some resume events. - */ - pci_save_state(tp->pdev); - printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (PCI%s:%s:%s) %sBaseT Ethernet ", dev->name, tp->board_part_number, diff --git a/drivers/net/tokenring/Kconfig b/drivers/net/tokenring/Kconfig index 23d0fa4bbceb..7e99e9f8045e 100644 --- a/drivers/net/tokenring/Kconfig +++ b/drivers/net/tokenring/Kconfig @@ -84,7 +84,7 @@ config 3C359 config TMS380TR tristate "Generic TMS380 Token Ring ISA/PCI adapter support" - depends on TR && (PCI || ISA) + depends on TR && (PCI || ISA && ISA_DMA_API) select FW_LOADER ---help--- This driver provides generic support for token ring adapters diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 1d3231cc471a..ec3f75a030d2 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -270,7 +270,7 @@ config PCMCIA_HERMES config AIRO_CS tristate "Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards" - depends on NET_RADIO && PCMCIA + depends on NET_RADIO && PCMCIA && (BROKEN || !M32R) ---help--- This is the standard Linux driver to support Cisco/Aironet PCMCIA 802.11 wireless cards. This driver is the same as the Aironet diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig index 16a2e6ae37f4..725a14119f2a 100644 --- a/drivers/parport/Kconfig +++ b/drivers/parport/Kconfig @@ -34,7 +34,7 @@ config PARPORT config PARPORT_PC tristate "PC-style hardware" - depends on PARPORT && (!SPARC64 || PCI) && !SPARC32 + depends on PARPORT && (!SPARC64 || PCI) && !SPARC32 && !M32R ---help--- You should say Y here if you have a PC-style parallel port. All IBM PC compatible computers and some Alphas have PC-style 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, continue; /* Ok, try it out.. */ - ret = allocate_resource(r, res, size, min, -1, align, + ret = allocate_resource(r, res, size, + r->start ? : min, + -1, align, alignf, alignf_data); if (ret == 0) break; diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 46b294a12418..2b92b9e8c910 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -23,7 +23,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com> + * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com> * */ #ifndef _PCIEHP_H diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index df4915dbc321..cafc7eadcf80 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -23,7 +23,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com> + * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com> * */ diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 0dbcf04aa35e..0e0947601526 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -23,7 +23,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com> + * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com> * */ diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 1cda30bd6e47..7a0e27f0e063 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -23,7 +23,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to <greg@kroah.com>,<dely.l.sy@intel.com> + * Send feedback to <greg@kroah.com>,<kristen.c.accardi@intel.com> * */ diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 723b12c0bb7c..33b539b34f7e 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c @@ -23,7 +23,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com> + * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com> * */ diff --git a/drivers/pci/hotplug/pciehprm.h b/drivers/pci/hotplug/pciehprm.h index 966775ffb0ff..05f20fbc5f50 100644 --- a/drivers/pci/hotplug/pciehprm.h +++ b/drivers/pci/hotplug/pciehprm.h @@ -23,7 +23,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com> + * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com> * */ diff --git a/drivers/pci/hotplug/pciehprm_acpi.c b/drivers/pci/hotplug/pciehprm_acpi.c index 57f4e6d1b27c..305b47ec2f2c 100644 --- a/drivers/pci/hotplug/pciehprm_acpi.c +++ b/drivers/pci/hotplug/pciehprm_acpi.c @@ -20,7 +20,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to <dely.l.sy@intel.com> + * Send feedback to <kristen.c.accardi@intel.com> * */ diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.c b/drivers/pci/hotplug/pciehprm_nonacpi.c index 79a0aa6238ef..3622965f8961 100644 --- a/drivers/pci/hotplug/pciehprm_nonacpi.c +++ b/drivers/pci/hotplug/pciehprm_nonacpi.c @@ -23,7 +23,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com> + * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com> * */ diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.h b/drivers/pci/hotplug/pciehprm_nonacpi.h index 87c90e85ede9..b10603b0e958 100644 --- a/drivers/pci/hotplug/pciehprm_nonacpi.h +++ b/drivers/pci/hotplug/pciehprm_nonacpi.h @@ -23,7 +23,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com> + * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com> * */ diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 67b6a3370ceb..fe4d653da188 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -23,7 +23,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to <greg@kroah.com>,<dely.l.sy@intel.com> + * Send feedback to <greg@kroah.com>,<kristen.c.accardi@intel.com> * */ #ifndef _SHPCHP_H diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index a70a5c5705f2..6f7d8a29957a 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -23,7 +23,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com> + * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com> * */ diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 490a9553a062..783b5abb0717 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -23,7 +23,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com> + * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com> * */ diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 38c5d9066697..8d98410bf1c0 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -23,7 +23,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to <greg@kroah.com>,<dely.l.sy@intel.com> + * Send feedback to <greg@kroah.com>,<kristen.c.accardi@intel.com> * */ diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index 90113e9cd69b..d867099114ec 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c @@ -23,7 +23,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com> + * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com> * */ diff --git a/drivers/pci/hotplug/shpchprm.h b/drivers/pci/hotplug/shpchprm.h index 88aeb978c911..057b192ce589 100644 --- a/drivers/pci/hotplug/shpchprm.h +++ b/drivers/pci/hotplug/shpchprm.h @@ -23,7 +23,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com> + * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com> * */ diff --git a/drivers/pci/hotplug/shpchprm_acpi.c b/drivers/pci/hotplug/shpchprm_acpi.c index 7957cdc72cd0..d37b31658edf 100644 --- a/drivers/pci/hotplug/shpchprm_acpi.c +++ b/drivers/pci/hotplug/shpchprm_acpi.c @@ -20,7 +20,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to <dely.l.sy@intel.com> + * Send feedback to <kristen.c.accardi@intel.com> * */ diff --git a/drivers/pci/hotplug/shpchprm_legacy.c b/drivers/pci/hotplug/shpchprm_legacy.c index 37fa77a98289..ba6c549c9b9d 100644 --- a/drivers/pci/hotplug/shpchprm_legacy.c +++ b/drivers/pci/hotplug/shpchprm_legacy.c @@ -23,7 +23,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to <greg@kroah.com>,<dely.l.sy@intel.com> + * Send feedback to <greg@kroah.com>,<kristen.c.accardi@intel.com> * */ diff --git a/drivers/pci/hotplug/shpchprm_legacy.h b/drivers/pci/hotplug/shpchprm_legacy.h index 29ccea5e57e5..21bda74ddfa5 100644 --- a/drivers/pci/hotplug/shpchprm_legacy.h +++ b/drivers/pci/hotplug/shpchprm_legacy.h @@ -23,7 +23,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com> + * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com> * */ diff --git a/drivers/pci/hotplug/shpchprm_nonacpi.c b/drivers/pci/hotplug/shpchprm_nonacpi.c index 88f4d9f41886..5f75ef7f3df2 100644 --- a/drivers/pci/hotplug/shpchprm_nonacpi.c +++ b/drivers/pci/hotplug/shpchprm_nonacpi.c @@ -23,7 +23,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com> + * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com> * */ diff --git a/drivers/pci/hotplug/shpchprm_nonacpi.h b/drivers/pci/hotplug/shpchprm_nonacpi.h index 6bc8668023c3..cddaaa5ee1b3 100644 --- a/drivers/pci/hotplug/shpchprm_nonacpi.h +++ b/drivers/pci/hotplug/shpchprm_nonacpi.h @@ -23,7 +23,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com> + * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com> * */ diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index b5ab9aa6ff7c..2b85aa39f954 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -453,7 +453,7 @@ static void enable_msi_mode(struct pci_dev *dev, int pos, int type) } } -static void disable_msi_mode(struct pci_dev *dev, int pos, int type) +void disable_msi_mode(struct pci_dev *dev, int pos, int type) { u16 control; @@ -699,6 +699,9 @@ int pci_enable_msi(struct pci_dev* dev) if (!pci_msi_enable || !dev) return status; + if (dev->no_msi) + return status; + temp = dev->irq; if ((status = msi_init()) < 0) diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index d94d7af4f7a0..d00168b1f662 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -47,6 +47,12 @@ extern int pci_msi_quirk; #define pci_msi_quirk 0 #endif +#ifdef CONFIG_PCI_MSI +void disable_msi_mode(struct pci_dev *dev, int pos, int type); +#else +static inline void disable_msi_mode(struct pci_dev *dev, int pos, int type) { } +#endif + extern int pcie_mch_quirk; extern struct device_attribute pci_dev_attrs[]; extern struct class_device_attribute class_device_attr_cpuaffinity; diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 8d0968bd527e..bb36bb69803f 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) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt82c686_acpi ); +/* + * VIA VT8235 ISA Bridge: Two IO regions pointed to by words at + * 0x88 (128 bytes of power management registers) + * 0xd0 (16 bytes of SMB registers) + */ +static void __devinit quirk_vt8235_acpi(struct pci_dev *dev) +{ + u16 pm, smb; + + pci_read_config_word(dev, 0x88, &pm); + pm &= PCI_BASE_ADDRESS_IO_MASK; + quirk_io_region(dev, pm, 128, PCI_BRIDGE_RESOURCES); + + pci_read_config_word(dev, 0xd0, &smb); + smb &= PCI_BASE_ADDRESS_IO_MASK; + quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 1); +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, quirk_vt8235_acpi); + #ifdef CONFIG_X86_IO_APIC @@ -1272,6 +1291,27 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, quir DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quirk_pcie_mch ); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_pcie_mch ); + +/* + * It's possible for the MSI to get corrupted if shpc and acpi + * are used together on certain PXH-based systems. + */ +static void __devinit quirk_pcie_pxh(struct pci_dev *dev) +{ + disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI), + PCI_CAP_ID_MSI); + dev->no_msi = 1; + + printk(KERN_WARNING "PCI: PXH quirk detected, " + "disabling MSI for SHPC device\n"); +} +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXHD_0, quirk_pcie_pxh); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXHD_1, quirk_pcie_pxh); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_0, quirk_pcie_pxh); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_1, quirk_pcie_pxh); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXHV, quirk_pcie_pxh); + + static void __devinit quirk_netmos(struct pci_dev *dev) { unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4; diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index a2eebc6eaacc..6d864c502a1f 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -40,7 +40,7 @@ * FIXME: IO should be max 256 bytes. However, since we may * have a P2P bridge below a cardbus bridge, we need 4K. */ -#define CARDBUS_IO_SIZE (4096) +#define CARDBUS_IO_SIZE (256) #define CARDBUS_MEM_SIZE (32*1024*1024) static void __devinit diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 1ca21d2ba11c..5598b4714f77 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) u32 new, check, mask; int reg; + /* Ignore resources for unimplemented BARs and unused resource slots + for 64 bit BARs. */ + if (!res->flags) + return; + pcibios_resource_to_bus(dev, ®ion, res); pr_debug(" got res [%lx:%lx] bus [%lx:%lx] flags %lx for " @@ -48,7 +53,9 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno) if (resno < 6) { reg = PCI_BASE_ADDRESS_0 + 4 * resno; } else if (resno == PCI_ROM_RESOURCE) { - new |= res->flags & IORESOURCE_ROM_ENABLE; + if (!(res->flags & IORESOURCE_ROM_ENABLE)) + return; + new |= PCI_ROM_ADDRESS_ENABLE; reg = dev->rom_base_reg; } else { /* Hmm, non-standard resource. */ @@ -67,7 +74,7 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno) if ((new & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == (PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64)) { - new = 0; /* currently everyone zeros the high address */ + new = region.start >> 16 >> 16; pci_write_config_dword(dev, reg + 4, new); pci_read_config_dword(dev, reg + 4, &check); 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) static inline void pcmcia_add_pseudo_device(struct pcmcia_socket *s) { if (!s->pcmcia_state.device_add_pending) { - schedule_work(&s->device_add); s->pcmcia_state.device_add_pending = 1; + schedule_work(&s->device_add); } return; } diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 6f9fdb276402..599b116d9747 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -41,6 +41,7 @@ module_param(io_speed, int, 0444); #ifdef CONFIG_PCMCIA_PROBE +#include <asm/irq.h> /* mask of IRQs already reserved by other cards, we should avoid using them */ static u8 pcmcia_used_irq[NR_IRQS]; #endif 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, static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end) { - struct pci_bus *bus; struct resource *root, *res; - u32 start, end; + struct pci_bus_region region; unsigned mask; 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 if (type & IORESOURCE_IO) mask = ~3; - bus = socket->dev->subordinate; - res->name = bus->name; + res->name = socket->dev->subordinate->name; res->flags = type; - start = config_readl(socket, addr_start) & mask; - end = config_readl(socket, addr_end) | ~mask; - if (start && end > start && !override_bios) { - res->start = start; - res->end = end; + region.start = config_readl(socket, addr_start) & mask; + region.end = config_readl(socket, addr_end) | ~mask; + if (region.start && region.end > region.start && !override_bios) { + pcibios_bus_to_resource(socket->dev, res, ®ion); root = pci_find_parent_resource(socket->dev, res); if (root && (request_resource(root, res) == 0)) return; @@ -642,6 +639,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ (yenta_search_res(socket, res, BRIDGE_IO_MIN))) { config_writel(socket, addr_start, res->start); config_writel(socket, addr_end, res->end); + return; } } else { if (type & IORESOURCE_PREFETCH) { @@ -650,6 +648,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) { config_writel(socket, addr_start, res->start); config_writel(socket, addr_end, res->end); + return; } /* Approximating prefetchable by non-prefetchable */ res->flags = IORESOURCE_MEM; @@ -659,6 +658,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) { config_writel(socket, addr_start, res->start); config_writel(socket, addr_end, res->end); + return; } } @@ -1107,8 +1107,6 @@ static int yenta_dev_suspend (struct pci_dev *dev, pm_message_t state) pci_read_config_dword(dev, 17*4, &socket->saved_state[1]); pci_disable_device(dev); - free_irq(dev->irq, socket); - /* * Some laptops (IBM T22) do not like us putting the Cardbus * bridge into D3. At a guess, some other laptop will @@ -1134,13 +1132,6 @@ static int yenta_dev_resume (struct pci_dev *dev) pci_enable_device(dev); pci_set_master(dev); - if (socket->cb_irq) - if (request_irq(socket->cb_irq, yenta_interrupt, - SA_SHIRQ, "yenta", socket)) { - printk(KERN_WARNING "Yenta: request_irq() failed on resume!\n"); - socket->cb_irq = 0; - } - if (socket->type && socket->type->restore_state) socket->type->restore_state(socket); } diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c index add12f7c489a..6e5229e92fbc 100644 --- a/drivers/pnp/card.c +++ b/drivers/pnp/card.c @@ -312,6 +312,8 @@ found: if (drv->link.driver.probe) { if (drv->link.driver.probe(&dev->dev)) { dev->dev.driver = NULL; + dev->card_link = NULL; + up_write(&dev->dev.bus->subsys.rwsem); return NULL; } } diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index d36258d6665f..381f339e3200 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c @@ -112,7 +112,7 @@ qdio_min(int a,int b) /***************** SCRUBBER HELPER ROUTINES **********************/ -static inline volatile __u64 +static inline __u64 qdio_get_micros(void) { return (get_clock() >> 10); /* time>>12 is microseconds */ @@ -230,7 +230,7 @@ qdio_siga_input(struct qdio_q *q) } /* locked by the locks in qdio_activate and qdio_cleanup */ -static __u32 * volatile +static __u32 volatile * qdio_get_indicator(void) { int i; diff --git a/drivers/s390/crypto/z90crypt.h b/drivers/s390/crypto/z90crypt.h index 82a1d97001d7..0a3bb5a10dd4 100644 --- a/drivers/s390/crypto/z90crypt.h +++ b/drivers/s390/crypto/z90crypt.h @@ -36,15 +36,6 @@ #define z90crypt_VARIANT 2 // 2 = added PCIXCC MCL3 and CEX2C support /** - * If we are not using the sparse checker, __user has no use. - */ -#ifdef __CHECKER__ -# define __user __attribute__((noderef, address_space(1))) -#else -# define __user -#endif - -/** * struct ica_rsa_modexpo * * Requirements: 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 = { #endif static int -qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr) +__qeth_reboot_event_card(struct device *dev, void *data) { - - struct device *entry; struct qeth_card *card; - down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); - list_for_each_entry(entry, &qeth_ccwgroup_driver.driver.devices, - driver_list) { - card = (struct qeth_card *) entry->driver_data; - qeth_clear_ip_list(card, 0, 0); - qeth_qdio_clear_card(card, 0); - } - up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); + card = (struct qeth_card *) dev->driver_data; + qeth_clear_ip_list(card, 0, 0); + qeth_qdio_clear_card(card, 0); + return 0; +} + +static int +qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + + driver_for_each_device(&qeth_ccwgroup_driver.driver, NULL, NULL, + __qeth_reboot_event_card); return NOTIFY_DONE; } 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 $"; #define QETH_PROCFILE_NAME "qeth" static struct proc_dir_entry *qeth_procfile; +static int +qeth_procfile_seq_match(struct device *dev, void *data) +{ + return 1; +} + static void * qeth_procfile_seq_start(struct seq_file *s, loff_t *offset) { - struct list_head *next_card = NULL; - int i = 0; + struct device *dev; + loff_t nr; down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); - if (*offset == 0) + nr = *offset; + if (nr == 0) return SEQ_START_TOKEN; - /* get card at pos *offset */ - list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices) - if (++i == *offset) - return next_card; + dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL, + NULL, qeth_procfile_seq_match); - return NULL; + /* get card at pos *offset */ + nr = *offset; + while (nr-- > 1 && dev) + dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev, + NULL, qeth_procfile_seq_match); + return (void *) dev; } static void @@ -55,23 +65,21 @@ qeth_procfile_seq_stop(struct seq_file *s, void* it) static void * qeth_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset) { - struct list_head *next_card = NULL; - struct list_head *current_card; + struct device *prev, *next; if (it == SEQ_START_TOKEN) { - next_card = qeth_ccwgroup_driver.driver.devices.next; - if (next_card->next == next_card) /* list empty */ - return NULL; - (*offset)++; - } else { - current_card = (struct list_head *)it; - if (current_card->next == &qeth_ccwgroup_driver.driver.devices) - return NULL; /* end of list reached */ - next_card = current_card->next; - (*offset)++; + next = driver_find_device(&qeth_ccwgroup_driver.driver, + NULL, NULL, qeth_procfile_seq_match); + if (next) + (*offset)++; + return (void *) next; } - - return next_card; + prev = (struct device *) it; + next = driver_find_device(&qeth_ccwgroup_driver.driver, + prev, NULL, qeth_procfile_seq_match); + if (next) + (*offset)++; + return (void *) next; } static inline const char * @@ -126,7 +134,7 @@ qeth_procfile_seq_show(struct seq_file *s, void *it) "-------------- ---- ------ ---------- ---- " "---- ----- -----\n"); } else { - device = list_entry(it, struct device, driver_list); + device = (struct device *) it; card = device->driver_data; seq_printf(s, "%s/%s/%s x%02X %-10s %-14s %-4i ", CARD_RDEV_ID(card), @@ -180,17 +188,20 @@ static struct proc_dir_entry *qeth_perf_procfile; static void * qeth_perf_procfile_seq_start(struct seq_file *s, loff_t *offset) { - struct list_head *next_card = NULL; - int i = 0; + struct device *dev = NULL; + int nr; down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); /* get card at pos *offset */ - list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices){ - if (i == *offset) - return next_card; - i++; - } - return NULL; + dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL, NULL, + qeth_procfile_seq_match); + + /* get card at pos *offset */ + nr = *offset; + while (nr-- > 1 && dev) + dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev, + NULL, qeth_procfile_seq_match); + return (void *) dev; } static void @@ -202,12 +213,14 @@ qeth_perf_procfile_seq_stop(struct seq_file *s, void* it) static void * qeth_perf_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset) { - struct list_head *current_card = (struct list_head *)it; + struct device *prev, *next; - if (current_card->next == &qeth_ccwgroup_driver.driver.devices) - return NULL; /* end of list reached */ - (*offset)++; - return current_card->next; + prev = (struct device *) it; + next = driver_find_device(&qeth_ccwgroup_driver.driver, prev, + NULL, qeth_procfile_seq_match); + if (next) + (*offset)++; + return (void *) next; } static int @@ -216,7 +229,7 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it) struct device *device; struct qeth_card *card; - device = list_entry(it, struct device, driver_list); + device = (struct device *) it; card = device->driver_data; seq_printf(s, "For card with devnos %s/%s/%s (%s):\n", CARD_RDEV_ID(card), @@ -318,8 +331,8 @@ static struct proc_dir_entry *qeth_ipato_procfile; static void * qeth_ipato_procfile_seq_start(struct seq_file *s, loff_t *offset) { - struct list_head *next_card = NULL; - int i = 0; + struct device *dev; + loff_t nr; down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); /* TODO: finish this */ @@ -328,13 +341,16 @@ qeth_ipato_procfile_seq_start(struct seq_file *s, loff_t *offset) * output driver settings then; * else output setting for respective card */ + + dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL, NULL, + qeth_procfile_seq_match); + /* get card at pos *offset */ - list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices){ - if (i == *offset) - return next_card; - i++; - } - return NULL; + nr = *offset; + while (nr-- > 1 && dev) + dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev, + NULL, qeth_procfile_seq_match); + return (void *) dev; } static void @@ -346,18 +362,14 @@ qeth_ipato_procfile_seq_stop(struct seq_file *s, void* it) static void * qeth_ipato_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset) { - struct list_head *current_card = (struct list_head *)it; + struct device *prev, *next; - /* TODO: finish this */ - /* - * maybe SEQ_SATRT_TOKEN can be returned for offset 0 - * output driver settings then; - * else output setting for respective card - */ - if (current_card->next == &qeth_ccwgroup_driver.driver.devices) - return NULL; /* end of list reached */ - (*offset)++; - return current_card->next; + prev = (struct device *) it; + next = driver_find_device(&qeth_ccwgroup_driver.driver, prev, + NULL, qeth_procfile_seq_match); + if (next) + (*offset)++; + return (void *) next; } static int @@ -372,7 +384,7 @@ qeth_ipato_procfile_seq_show(struct seq_file *s, void *it) * output driver settings then; * else output setting for respective card */ - device = list_entry(it, struct device, driver_list); + device = (struct device *) it; card = device->driver_data; return 0; diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index e17b4d58a9f6..6fed4a532ca3 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -1299,13 +1299,10 @@ struct zfcp_port * zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status, u32 d_id) { - struct zfcp_port *port, *tmp_port; + struct zfcp_port *port; int check_wwpn; - scsi_id_t scsi_id; - int found; check_wwpn = !(status & ZFCP_STATUS_PORT_NO_WWPN); - /* * check that there is no port with this WWPN already in list */ @@ -1368,7 +1365,7 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status, } else { snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE, "0x%016llx", wwpn); - port->sysfs_device.parent = &adapter->ccw_device->dev; + port->sysfs_device.parent = &adapter->ccw_device->dev; } port->sysfs_device.release = zfcp_sysfs_port_release; dev_set_drvdata(&port->sysfs_device, port); @@ -1388,24 +1385,8 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status, zfcp_port_get(port); - scsi_id = 1; - found = 0; write_lock_irq(&zfcp_data.config_lock); - list_for_each_entry(tmp_port, &adapter->port_list_head, list) { - if (atomic_test_mask(ZFCP_STATUS_PORT_NO_SCSI_ID, - &tmp_port->status)) - continue; - if (tmp_port->scsi_id != scsi_id) { - found = 1; - break; - } - scsi_id++; - } - port->scsi_id = scsi_id; - if (found) - list_add_tail(&port->list, &tmp_port->list); - else - list_add_tail(&port->list, &adapter->port_list_head); + list_add_tail(&port->list, &adapter->port_list_head); atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status); if (d_id == ZFCP_DID_DIRECTORY_SERVICE) @@ -1422,11 +1403,15 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status, void zfcp_port_dequeue(struct zfcp_port *port) { + struct fc_port *rport; + zfcp_port_wait(port); write_lock_irq(&zfcp_data.config_lock); list_del(&port->list); port->adapter->ports--; write_unlock_irq(&zfcp_data.config_lock); + if (port->rport) + fc_remote_port_delete(rport); zfcp_adapter_put(port->adapter); zfcp_sysfs_port_remove_files(&port->sysfs_device, atomic_read(&port->status)); diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index 0fc46381fc22..3c65aedaa97f 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c @@ -202,9 +202,19 @@ static int zfcp_ccw_set_offline(struct ccw_device *ccw_device) { struct zfcp_adapter *adapter; + struct zfcp_port *port; + struct fc_port *rport; down(&zfcp_data.config_sema); adapter = dev_get_drvdata(&ccw_device->dev); + /* might be racy, but we cannot take config_lock due to the fact that + fc_remote_port_delete might sleep */ + list_for_each_entry(port, &adapter->port_list_head, list) + if (port->rport) { + rport = port->rport; + port->rport = NULL; + fc_remote_port_delete(rport); + } zfcp_erp_adapter_shutdown(adapter, 0); zfcp_erp_wait(adapter); zfcp_adapter_scsi_unregister(adapter); diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 4103b5be7683..455e902533a9 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -906,6 +906,7 @@ struct zfcp_adapter { */ struct zfcp_port { struct device sysfs_device; /* sysfs device */ + struct fc_rport *rport; /* rport of fc transport class */ struct list_head list; /* list of remote ports */ atomic_t refcount; /* reference count */ wait_queue_head_t remove_wq; /* can be used to wait for @@ -916,7 +917,6 @@ struct zfcp_port { list */ u32 units; /* # of logical units in list */ atomic_t status; /* status of this remote port */ - scsi_id_t scsi_id; /* own SCSI ID */ wwn_t wwnn; /* WWNN if known */ wwn_t wwpn; /* WWPN */ fc_id_t d_id; /* D_ID */ diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 0cf31f7d1c0f..cb4f612550ba 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -3360,13 +3360,32 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter, if ((result == ZFCP_ERP_SUCCEEDED) && (!atomic_test_mask(ZFCP_STATUS_UNIT_TEMPORARY, &unit->status)) - && (!unit->device)) - scsi_add_device(unit->port->adapter->scsi_host, 0, - unit->port->scsi_id, unit->scsi_lun); + && !unit->device + && port->rport) + scsi_add_device(port->adapter->scsi_host, 0, + port->rport->scsi_target_id, + unit->scsi_lun); zfcp_unit_put(unit); break; case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: case ZFCP_ERP_ACTION_REOPEN_PORT: + if ((result == ZFCP_ERP_SUCCEEDED) + && !atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN, + &port->status) + && !port->rport) { + struct fc_rport_identifiers ids; + ids.node_name = port->wwnn; + ids.port_name = port->wwpn; + ids.port_id = port->d_id; + ids.roles = FC_RPORT_ROLE_FCP_TARGET; + port->rport = + fc_remote_port_add(adapter->scsi_host, 0, &ids); + if (!port->rport) + ZFCP_LOG_NORMAL("failed registration of rport" + "(adapter %s, wwpn=0x%016Lx)\n", + zfcp_get_busid_by_port(port), + port->wwpn); + } zfcp_port_put(port); break; case ZFCP_ERP_ACTION_REOPEN_ADAPTER: diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 42df7e57eeae..cd98a2de9f8f 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -143,6 +143,8 @@ extern int zfcp_scsi_command_async(struct zfcp_adapter *,struct zfcp_unit *, struct scsi_cmnd *, struct timer_list *); extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *, struct timer_list *); +extern void zfcp_set_fc_host_attrs(struct zfcp_adapter *); +extern void zfcp_set_fc_rport_attrs(struct zfcp_port *); extern struct scsi_transport_template *zfcp_transport_template; extern struct fc_function_template zfcp_transport_functions; diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 0d9f20edc490..c007b6424e74 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -2062,6 +2062,7 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) zfcp_erp_adapter_shutdown(adapter, 0); return -EIO; } + zfcp_set_fc_host_attrs(adapter); return 0; } diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index b61d309352c3..31a76065cf28 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -389,7 +389,7 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id, struct zfcp_unit *unit, *retval = NULL; list_for_each_entry(port, &adapter->port_list_head, list) { - if (id != port->scsi_id) + if (!port->rport || (id != port->rport->scsi_target_id)) continue; list_for_each_entry(unit, &port->unit_list_head, list) { if (lun == unit->scsi_lun) { @@ -408,7 +408,7 @@ zfcp_port_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id) struct zfcp_port *port; list_for_each_entry(port, &adapter->port_list_head, list) { - if (id == port->scsi_id) + if (port->rport && (id == port->rport->scsi_target_id)) return port; } return (struct zfcp_port *) NULL; @@ -634,7 +634,6 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) { int retval; struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata; - struct Scsi_Host *scsi_host = scpnt->device->host; if (!unit) { ZFCP_LOG_NORMAL("bug: Tried reset for nonexistent unit\n"); @@ -729,7 +728,6 @@ zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *scpnt) { int retval = 0; struct zfcp_unit *unit; - struct Scsi_Host *scsi_host = scpnt->device->host; unit = (struct zfcp_unit *) scpnt->device->hostdata; ZFCP_LOG_NORMAL("bus reset because of problems with " @@ -753,7 +751,6 @@ zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) { int retval = 0; struct zfcp_unit *unit; - struct Scsi_Host *scsi_host = scpnt->device->host; unit = (struct zfcp_unit *) scpnt->device->hostdata; ZFCP_LOG_NORMAL("host reset because of problems with " @@ -833,6 +830,7 @@ zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter) shost = adapter->scsi_host; if (!shost) return; + fc_remove_host(shost); scsi_remove_host(shost); scsi_host_put(shost); adapter->scsi_host = NULL; @@ -906,6 +904,18 @@ zfcp_get_node_name(struct scsi_target *starget) read_unlock_irqrestore(&zfcp_data.config_lock, flags); } +void +zfcp_set_fc_host_attrs(struct zfcp_adapter *adapter) +{ + struct Scsi_Host *shost = adapter->scsi_host; + + fc_host_node_name(shost) = adapter->wwnn; + fc_host_port_name(shost) = adapter->wwpn; + strncpy(fc_host_serial_number(shost), adapter->serial_number, + min(FC_SERIAL_NUMBER_SIZE, 32)); + fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3; +} + struct fc_function_template zfcp_transport_functions = { .get_starget_port_id = zfcp_get_port_id, .get_starget_port_name = zfcp_get_port_name, @@ -913,6 +923,11 @@ struct fc_function_template zfcp_transport_functions = { .show_starget_port_id = 1, .show_starget_port_name = 1, .show_starget_node_name = 1, + .show_rport_supported_classes = 1, + .show_host_node_name = 1, + .show_host_port_name = 1, + .show_host_supported_classes = 1, + .show_host_serial_number = 1, }; /** 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 @@ #define __KERNEL_SYSCALLS__ #include <linux/kernel.h> +#include <linux/kthread.h> #include <linux/sched.h> #include <linux/slab.h> #include <linux/delay.h> @@ -459,10 +460,6 @@ static struct task_struct *kenvctrld_task; static int kenvctrld(void *__unused) { - daemonize("kenvctrld"); - allow_signal(SIGKILL); - kenvctrld_task = current; - printk(KERN_INFO "bbc_envctrl: kenvctrld starting...\n"); last_warning_jiffies = jiffies - WARN_INTERVAL; for (;;) { @@ -470,7 +467,7 @@ static int kenvctrld(void *__unused) struct bbc_fan_control *fp; msleep_interruptible(POLL_INTERVAL); - if (signal_pending(current)) + if (kthread_should_stop()) break; for (tp = all_bbc_temps; tp; tp = tp->next) { @@ -577,7 +574,6 @@ int bbc_envctrl_init(void) int temp_index = 0; int fan_index = 0; int devidx = 0; - int err = 0; while ((echild = bbc_i2c_getdev(devidx++)) != NULL) { if (!strcmp(echild->prom_name, "temperature")) @@ -585,9 +581,13 @@ int bbc_envctrl_init(void) if (!strcmp(echild->prom_name, "fan-control")) attach_one_fan(echild, fan_index++); } - if (temp_index != 0 && fan_index != 0) - err = kernel_thread(kenvctrld, NULL, CLONE_FS | CLONE_FILES); - return err; + if (temp_index != 0 && fan_index != 0) { + kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld"); + if (IS_ERR(kenvctrld_task)) + return PTR_ERR(kenvctrld_task); + } + + return 0; } static void destroy_one_temp(struct bbc_cpu_temperature *tp) @@ -607,26 +607,7 @@ void bbc_envctrl_cleanup(void) struct bbc_cpu_temperature *tp; struct bbc_fan_control *fp; - if (kenvctrld_task != NULL) { - force_sig(SIGKILL, kenvctrld_task); - for (;;) { - struct task_struct *p; - int found = 0; - - read_lock(&tasklist_lock); - for_each_process(p) { - if (p == kenvctrld_task) { - found = 1; - break; - } - } - read_unlock(&tasklist_lock); - if (!found) - break; - msleep(1000); - } - kenvctrld_task = NULL; - } + kthread_stop(kenvctrld_task); tp = all_bbc_temps; 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 @@ #include <linux/config.h> #include <linux/module.h> #include <linux/sched.h> +#include <linux/kthread.h> #include <linux/errno.h> #include <linux/delay.h> #include <linux/ioport.h> @@ -1010,16 +1011,13 @@ static int kenvctrld(void *__unused) poll_interval = 5000; /* TODO env_mon_interval */ - daemonize("kenvctrld"); - allow_signal(SIGKILL); - - kenvctrld_task = current; - printk(KERN_INFO "envctrl: %s starting...\n", current->comm); for (;;) { - if(msleep_interruptible(poll_interval)) - break; + msleep_interruptible(poll_interval); + if (kthread_should_stop()) + break; + for (whichcpu = 0; whichcpu < ENVCTRL_MAX_CPU; ++whichcpu) { if (0 < envctrl_read_cpu_info(whichcpu, cputemp, ENVCTRL_CPUTEMP_MON, @@ -1041,7 +1039,6 @@ static int kenvctrld(void *__unused) static int __init envctrl_init(void) { -#ifdef CONFIG_PCI struct linux_ebus *ebus = NULL; struct linux_ebus_device *edev = NULL; struct linux_ebus_child *edev_child = NULL; @@ -1118,9 +1115,11 @@ done: i2c_childlist[i].addr, (0 == i) ? ("\n") : (" ")); } - err = kernel_thread(kenvctrld, NULL, CLONE_FS | CLONE_FILES); - if (err < 0) + kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld"); + if (IS_ERR(kenvctrld_task)) { + err = PTR_ERR(kenvctrld_task); goto out_deregister; + } return 0; @@ -1133,37 +1132,13 @@ out_iounmap: kfree(i2c_childlist[i].tables); } return err; -#else - return -ENODEV; -#endif } static void __exit envctrl_cleanup(void) { int i; - if (NULL != kenvctrld_task) { - force_sig(SIGKILL, kenvctrld_task); - for (;;) { - struct task_struct *p; - int found = 0; - - read_lock(&tasklist_lock); - for_each_process(p) { - if (p == kenvctrld_task) { - found = 1; - break; - } - } - read_unlock(&tasklist_lock); - - if (!found) - break; - - msleep(1000); - } - kenvctrld_task = NULL; - } + kthread_stop(kenvctrld_task); iounmap(i2c); 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 { struct vfc_regs *phys_regs; unsigned int control_reg; struct semaphore device_lock_sem; - struct timer_list poll_timer; - wait_queue_head_t poll_wait; int instance; int busy; 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) dev->instance=instance; init_MUTEX(&dev->device_lock_sem); dev->control_reg=0; - init_waitqueue_head(&dev->poll_wait); dev->busy=0; return 0; } 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) return 0; } -void vfc_i2c_delay_wakeup(struct vfc_dev *dev) -{ - /* Used to profile code and eliminate too many delays */ - VFC_I2C_DEBUG_PRINTK(("vfc%d: Delaying\n", dev->instance)); - wake_up(&dev->poll_wait); -} - void vfc_i2c_delay_no_busy(struct vfc_dev *dev, unsigned long usecs) { - DEFINE_WAIT(wait); - init_timer(&dev->poll_timer); - dev->poll_timer.expires = jiffies + usecs_to_jiffies(usecs); - dev->poll_timer.data=(unsigned long)dev; - dev->poll_timer.function=(void *)(unsigned long)vfc_i2c_delay_wakeup; - add_timer(&dev->poll_timer); - prepare_to_wait(&dev->poll_wait, &wait, TASK_UNINTERRUPTIBLE); - schedule(); - del_timer(&dev->poll_timer); - finish_wait(&dev->poll_wait, &wait); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(usecs_to_jiffies(usecs)); } void inline vfc_i2c_delay(struct vfc_dev *dev) diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index 973c51fb0fe2..ae9e0203e9de 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c @@ -1499,22 +1499,43 @@ static int tw_scsiop_inquiry(TW_Device_Extension *tw_dev, int request_id) return 0; } /* End tw_scsiop_inquiry() */ +static void tw_transfer_internal(TW_Device_Extension *tw_dev, int request_id, + void *data, unsigned int len) +{ + struct scsi_cmnd *cmd = tw_dev->srb[request_id]; + void *buf; + unsigned int transfer_len; + + if (cmd->use_sg) { + struct scatterlist *sg = + (struct scatterlist *)cmd->request_buffer; + buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; + transfer_len = min(sg->length, len); + } else { + buf = cmd->request_buffer; + transfer_len = min(cmd->request_bufflen, len); + } + + memcpy(buf, data, transfer_len); + + if (cmd->use_sg) { + struct scatterlist *sg; + + sg = (struct scatterlist *)cmd->request_buffer; + kunmap_atomic(buf - sg->offset, KM_IRQ0); + } +} + /* This function is called by the isr to complete an inquiry command */ static int tw_scsiop_inquiry_complete(TW_Device_Extension *tw_dev, int request_id) { unsigned char *is_unit_present; - unsigned char *request_buffer; + unsigned char request_buffer[36]; TW_Param *param; dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry_complete()\n"); - /* Fill request buffer */ - if (tw_dev->srb[request_id]->request_buffer == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry_complete(): Request buffer NULL.\n"); - return 1; - } - request_buffer = tw_dev->srb[request_id]->request_buffer; - memset(request_buffer, 0, tw_dev->srb[request_id]->request_bufflen); + memset(request_buffer, 0, sizeof(request_buffer)); request_buffer[0] = TYPE_DISK; /* Peripheral device type */ request_buffer[1] = 0; /* Device type modifier */ request_buffer[2] = 0; /* No ansi/iso compliance */ @@ -1522,6 +1543,8 @@ static int tw_scsiop_inquiry_complete(TW_Device_Extension *tw_dev, int request_i memcpy(&request_buffer[8], "3ware ", 8); /* Vendor ID */ sprintf(&request_buffer[16], "Logical Disk %-2d ", tw_dev->srb[request_id]->device->id); memcpy(&request_buffer[32], TW_DRIVER_VERSION, 3); + tw_transfer_internal(tw_dev, request_id, request_buffer, + sizeof(request_buffer)); param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; if (param == NULL) { @@ -1612,7 +1635,7 @@ static int tw_scsiop_mode_sense_complete(TW_Device_Extension *tw_dev, int reques { TW_Param *param; unsigned char *flags; - unsigned char *request_buffer; + unsigned char request_buffer[8]; dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_mode_sense_complete()\n"); @@ -1622,8 +1645,7 @@ static int tw_scsiop_mode_sense_complete(TW_Device_Extension *tw_dev, int reques return 1; } flags = (char *)&(param->data[0]); - request_buffer = tw_dev->srb[request_id]->buffer; - memset(request_buffer, 0, tw_dev->srb[request_id]->request_bufflen); + memset(request_buffer, 0, sizeof(request_buffer)); request_buffer[0] = 0xf; /* mode data length */ request_buffer[1] = 0; /* default medium type */ @@ -1635,6 +1657,8 @@ static int tw_scsiop_mode_sense_complete(TW_Device_Extension *tw_dev, int reques request_buffer[6] = 0x4; /* WCE on */ else request_buffer[6] = 0x0; /* WCE off */ + tw_transfer_internal(tw_dev, request_id, request_buffer, + sizeof(request_buffer)); return 0; } /* End tw_scsiop_mode_sense_complete() */ @@ -1701,17 +1725,12 @@ static int tw_scsiop_read_capacity_complete(TW_Device_Extension *tw_dev, int req { unsigned char *param_data; u32 capacity; - char *buff; + char buff[8]; TW_Param *param; dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity_complete()\n"); - buff = tw_dev->srb[request_id]->request_buffer; - if (buff == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Request buffer NULL.\n"); - return 1; - } - memset(buff, 0, tw_dev->srb[request_id]->request_bufflen); + memset(buff, 0, sizeof(buff)); param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; if (param == NULL) { printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Bad alignment virtual address.\n"); @@ -1739,6 +1758,8 @@ static int tw_scsiop_read_capacity_complete(TW_Device_Extension *tw_dev, int req buff[6] = (TW_BLOCK_SIZE >> 8) & 0xff; buff[7] = TW_BLOCK_SIZE & 0xff; + tw_transfer_internal(tw_dev, request_id, buff, sizeof(buff)); + return 0; } /* End tw_scsiop_read_capacity_complete() */ diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 68adc3cc8ad2..b3ae796eb624 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -430,7 +430,7 @@ config SCSI_IN2000 source "drivers/scsi/megaraid/Kconfig.megaraid" config SCSI_SATA - bool "Serial ATA (SATA) support" + tristate "Serial ATA (SATA) support" depends on SCSI help This driver family supports Serial ATA host controllers @@ -1702,7 +1702,7 @@ config TT_DMA_EMUL config MAC_SCSI bool "Macintosh NCR5380 SCSI" - depends on MAC && SCSI + depends on MAC && SCSI=y help This is the NCR 5380 SCSI controller included on most of the 68030 based Macintoshes. If you have one of these say Y and read the @@ -1723,7 +1723,7 @@ config SCSI_MAC_ESP config MVME147_SCSI bool "WD33C93 SCSI driver for MVME147" - depends on MVME147 && SCSI + depends on MVME147 && SCSI=y help Support for the on-board SCSI controller on the Motorola MVME147 single-board computer. @@ -1764,7 +1764,7 @@ config SUN3_SCSI config SUN3X_ESP bool "Sun3x ESP SCSI" - depends on SUN3X && SCSI + depends on SUN3X && SCSI=y help The ESP was an on-board SCSI controller used on Sun 3/80 machines. Say Y here to compile in support for it. diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index bc91e7ce5e59..e40528185d48 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -15,11 +15,7 @@ #define AAC_MAX_LUN (8) #define AAC_MAX_HOSTPHYSMEMPAGES (0xfffff) -/* - * max_sectors is an unsigned short, otherwise limit is 0x100000000 / 512 - * Linux has starvation problems if we permit larger than 4MB I/O ... - */ -#define AAC_MAX_32BIT_SGBCOUNT ((unsigned short)8192) +#define AAC_MAX_32BIT_SGBCOUNT ((unsigned short)512) /* * These macros convert from physical channels to virtual channels diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 2bd594267881..4ff29d7f5825 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -391,7 +391,8 @@ static int aac_slave_configure(struct scsi_device *sdev) else scsi_adjust_queue_depth(sdev, 0, 1); - if (host->max_sectors < AAC_MAX_32BIT_SGBCOUNT) + if (!(((struct aac_dev *)host->hostdata)->adapter_info.options + & AAC_OPT_NEW_COMM)) blk_queue_max_segment_size(sdev->request_queue, 65536); return 0; diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index c5623694d10f..e3b9692b9688 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -1105,6 +1105,7 @@ MODULE_AUTHOR("Jeff Garzik"); MODULE_DESCRIPTION("AHCI SATA low-level driver"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, ahci_pci_tbl); +MODULE_VERSION(DRV_VERSION); module_init(ahci_init); module_exit(ahci_exit); diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 4096d523d08d..c932b3b94490 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -1339,14 +1339,12 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, } switch ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED))) { case AHC_DEV_Q_BASIC: - scsi_adjust_queue_depth(sdev, - MSG_SIMPLE_TASK, - dev->openings + dev->active); + scsi_set_tag_type(sdev, MSG_SIMPLE_TAG); + scsi_activate_tcq(sdev, dev->openings + dev->active); break; case AHC_DEV_Q_TAGGED: - scsi_adjust_queue_depth(sdev, - MSG_ORDERED_TASK, - dev->openings + dev->active); + scsi_set_tag_type(sdev, MSG_ORDERED_TAG); + scsi_activate_tcq(sdev, dev->openings + dev->active); break; default: /* @@ -1355,9 +1353,7 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, * serially on the controller/device. This should * remove some latency. */ - scsi_adjust_queue_depth(sdev, - /*NON-TAGGED*/0, - /*queue depth*/2); + scsi_deactivate_tcq(sdev, 2); break; } } @@ -1710,9 +1706,9 @@ ahc_send_async(struct ahc_softc *ahc, char channel, spi_period(starget) = tinfo->curr.period; spi_width(starget) = tinfo->curr.width; spi_offset(starget) = tinfo->curr.offset; - spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ; - spi_qas(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ; - spi_iu(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ; + spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ ? 1 : 0; + spi_qas(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ ? 1 : 0; + spi_iu(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ ? 1 : 0; spi_display_xfer_agreement(starget); break; } @@ -2502,12 +2498,14 @@ static void ahc_linux_set_dt(struct scsi_target *starget, int dt) unsigned int ppr_options = tinfo->goal.ppr_options & ~MSG_EXT_PPR_DT_REQ; unsigned int period = tinfo->goal.period; + unsigned int width = tinfo->goal.width; unsigned long flags; struct ahc_syncrate *syncrate; if (dt) { - period = 9; /* 12.5ns is the only period valid for DT */ ppr_options |= MSG_EXT_PPR_DT_REQ; + if (!width) + ahc_linux_set_width(starget, 1); } else if (period == 9) period = 10; /* if resetting DT, period must be >= 25ns */ diff --git a/drivers/scsi/arm/Kconfig b/drivers/scsi/arm/Kconfig index 54b32868aaf7..13f23043c8a3 100644 --- a/drivers/scsi/arm/Kconfig +++ b/drivers/scsi/arm/Kconfig @@ -3,7 +3,7 @@ # config SCSI_ACORNSCSI_3 tristate "Acorn SCSI card (aka30) support" - depends on ARCH_ACORN && SCSI + depends on ARCH_ACORN && SCSI && BROKEN help This enables support for the Acorn SCSI card (aka30). If you have an Acorn system with one of these, say Y. If unsure, say N. diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index a2cfade2c1c6..d96ebf9d2228 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -32,7 +32,7 @@ #include <linux/libata.h> #define DRV_NAME "ata_piix" -#define DRV_VERSION "1.03" +#define DRV_VERSION "1.04" enum { PIIX_IOCFG = 0x54, /* IDE I/O configuration register */ diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c index 53b395534313..bd0e1b6be1ea 100644 --- a/drivers/scsi/ch.c +++ b/drivers/scsi/ch.c @@ -30,7 +30,7 @@ #include <scsi/scsi_ioctl.h> #include <scsi/scsi_host.h> #include <scsi/scsi_device.h> -#include <scsi/scsi_request.h> +#include <scsi/scsi_eh.h> #include <scsi/scsi_dbg.h> #define CH_DT_MAX 16 @@ -180,17 +180,17 @@ static struct { /* ------------------------------------------------------------------- */ -static int ch_find_errno(unsigned char *sense_buffer) +static int ch_find_errno(struct scsi_sense_hdr *sshdr) { int i,errno = 0; /* Check to see if additional sense information is available */ - if (sense_buffer[7] > 5 && - sense_buffer[12] != 0) { + if (scsi_sense_valid(sshdr) && + sshdr->asc != 0) { for (i = 0; err[i].errno != 0; i++) { - if (err[i].sense == sense_buffer[ 2] && - err[i].asc == sense_buffer[12] && - err[i].ascq == sense_buffer[13]) { + if (err[i].sense == sshdr->sense_key && + err[i].asc == sshdr->asc && + err[i].ascq == sshdr->ascq) { errno = -err[i].errno; break; } @@ -206,13 +206,9 @@ ch_do_scsi(scsi_changer *ch, unsigned char *cmd, void *buffer, unsigned buflength, enum dma_data_direction direction) { - int errno, retries = 0, timeout; - struct scsi_request *sr; + int errno, retries = 0, timeout, result; + struct scsi_sense_hdr sshdr; - sr = scsi_allocate_request(ch->device, GFP_KERNEL); - if (NULL == sr) - return -ENOMEM; - timeout = (cmd[0] == INITIALIZE_ELEMENT_STATUS) ? timeout_init : timeout_move; @@ -223,16 +219,17 @@ ch_do_scsi(scsi_changer *ch, unsigned char *cmd, __scsi_print_command(cmd); } - scsi_wait_req(sr, cmd, buffer, buflength, - timeout * HZ, MAX_RETRIES); + result = scsi_execute_req(ch->device, cmd, direction, buffer, + buflength, &sshdr, timeout * HZ, + MAX_RETRIES); - dprintk("result: 0x%x\n",sr->sr_result); - if (driver_byte(sr->sr_result) & DRIVER_SENSE) { + dprintk("result: 0x%x\n",result); + if (driver_byte(result) & DRIVER_SENSE) { if (debug) - scsi_print_req_sense(ch->name, sr); - errno = ch_find_errno(sr->sr_sense_buffer); + scsi_print_sense_hdr(ch->name, &sshdr); + errno = ch_find_errno(&sshdr); - switch(sr->sr_sense_buffer[2] & 0xf) { + switch(sshdr.sense_key) { case UNIT_ATTENTION: ch->unit_attention = 1; if (retries++ < 3) @@ -240,7 +237,6 @@ ch_do_scsi(scsi_changer *ch, unsigned char *cmd, break; } } - scsi_release_request(sr); return errno; } diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index 0d58d3538bdf..f6be2c1c3942 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -1156,6 +1156,31 @@ scsi_show_extd_sense(unsigned char asc, unsigned char ascq) } } +void +scsi_print_sense_hdr(const char *name, struct scsi_sense_hdr *sshdr) +{ + const char *sense_txt; + /* An example of deferred is when an earlier write to disk cache + * succeeded, but now the disk discovers that it cannot write the + * data to the magnetic media. + */ + const char *error = scsi_sense_is_deferred(sshdr) ? + "<<DEFERRED>>" : "Current"; + printk(KERN_INFO "%s: %s", name, error); + if (sshdr->response_code >= 0x72) + printk(" [descriptor]"); + + sense_txt = scsi_sense_key_string(sshdr->sense_key); + if (sense_txt) + printk(": sense key: %s\n", sense_txt); + else + printk(": sense key=0x%x\n", sshdr->sense_key); + printk(KERN_INFO " "); + scsi_show_extd_sense(sshdr->asc, sshdr->ascq); + printk("\n"); +} +EXPORT_SYMBOL(scsi_print_sense_hdr); + /* Print sense information */ void __scsi_print_sense(const char *name, const unsigned char *sense_buffer, @@ -1163,8 +1188,6 @@ __scsi_print_sense(const char *name, const unsigned char *sense_buffer, { int k, num, res; unsigned int info; - const char *error; - const char *sense_txt; struct scsi_sense_hdr ssh; res = scsi_normalize_sense(sense_buffer, sense_len, &ssh); @@ -1182,26 +1205,7 @@ __scsi_print_sense(const char *name, const unsigned char *sense_buffer, printk("\n"); return; } - - /* An example of deferred is when an earlier write to disk cache - * succeeded, but now the disk discovers that it cannot write the - * data to the magnetic media. - */ - error = scsi_sense_is_deferred(&ssh) ? - "<<DEFERRED>>" : "Current"; - printk(KERN_INFO "%s: %s", name, error); - if (ssh.response_code >= 0x72) - printk(" [descriptor]"); - - sense_txt = scsi_sense_key_string(ssh.sense_key); - if (sense_txt) - printk(": sense key: %s\n", sense_txt); - else - printk(": sense key=0x%x\n", ssh.sense_key); - printk(KERN_INFO " "); - scsi_show_extd_sense(ssh.asc, ssh.ascq); - printk("\n"); - + scsi_print_sense_hdr(name, &ssh); if (ssh.response_code < 0x72) { /* only decode extras for "fixed" format now */ char buff[80]; 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 @@ * cross a page boundy. */ #define SEGMENTX_LEN (sizeof(struct SGentry)*DC395x_MAX_SG_LISTENTRY) -#define VIRTX_LEN (sizeof(void *) * DC395x_MAX_SG_LISTENTRY) + struct SGentry { u32 address; /* bus! address */ @@ -235,7 +235,6 @@ struct ScsiReqBlk { u8 sg_count; /* No of HW sg entries for this request */ u8 sg_index; /* Index of HW sg entry for this request */ u32 total_xfer_length; /* Total number of bytes remaining to be transfered */ - void **virt_map; unsigned char *virt_addr; /* Virtual address of current transfer position */ /* @@ -1022,14 +1021,14 @@ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb, reqlen, cmd->request_buffer, cmd->use_sg, srb->sg_count); + srb->virt_addr = page_address(sl->page); for (i = 0; i < srb->sg_count; i++) { - u32 seglen = (u32)sg_dma_len(sl + i); - sgp[i].address = (u32)sg_dma_address(sl + i); + u32 busaddr = (u32)sg_dma_address(&sl[i]); + u32 seglen = (u32)sl[i].length; + sgp[i].address = busaddr; sgp[i].length = seglen; srb->total_xfer_length += seglen; - srb->virt_map[i] = kmap(sl[i].page); } - srb->virt_addr = srb->virt_map[0]; sgp += srb->sg_count - 1; /* @@ -1976,7 +1975,6 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left) int segment = cmd->use_sg; u32 xferred = srb->total_xfer_length - left; /* bytes transfered */ struct SGentry *psge = srb->segment_x + srb->sg_index; - void **virt = srb->virt_map; dprintkdbg(DBG_0, "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) /* We have to walk the scatterlist to find it */ sg = (struct scatterlist *)cmd->request_buffer; - idx = 0; while (segment--) { unsigned long mask = ~((unsigned long)sg->length - 1) & PAGE_MASK; if ((sg_dma_address(sg) & mask) == (psge->address & mask)) { - srb->virt_addr = virt[idx] + (psge->address & ~PAGE_MASK); + srb->virt_addr = (page_address(sg->page) + + psge->address - + (psge->address & PAGE_MASK)); return; } ++sg; - ++idx; } 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, DC395x_read32(acb, TRM_S1040_DMA_CXCNT)); } /* - * calculate all the residue data that not yet transfered + * calculate all the residue data that not yet tranfered * SCSI transfer counter + left in SCSI FIFO data * * .....TRM_S1040_SCSI_COUNTER (24bits) @@ -3269,7 +3267,6 @@ static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) struct scsi_cmnd *cmd = srb->cmd; enum dma_data_direction dir = cmd->sc_data_direction; if (cmd->use_sg && dir != PCI_DMA_NONE) { - int i; /* unmap DC395x SG list */ dprintkdbg(DBG_SG, "pci_unmap_srb: list=%08x(%05x)\n", srb->sg_bus_addr, SEGMENTX_LEN); @@ -3279,8 +3276,6 @@ static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) dprintkdbg(DBG_SG, "pci_unmap_srb: segs=%i buffer=%p\n", cmd->use_sg, cmd->request_buffer); /* unmap the sg segments */ - for (i = 0; i < srb->sg_count; i++) - kunmap(virt_to_page(srb->virt_map[i])); pci_unmap_sg(acb->dev, (struct scatterlist *)cmd->request_buffer, cmd->use_sg, dir); @@ -3327,7 +3322,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, if (cmd->use_sg) { struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer; - ptr = (struct ScsiInqData *)(srb->virt_map[0] + sg->offset); + ptr = (struct ScsiInqData *)(page_address(sg->page) + sg->offset); } else { ptr = (struct ScsiInqData *)(cmd->request_buffer); } @@ -4262,9 +4257,8 @@ static void adapter_sg_tables_free(struct AdapterCtlBlk *acb) const unsigned srbs_per_page = PAGE_SIZE/SEGMENTX_LEN; for (i = 0; i < DC395x_MAX_SRB_CNT; i += srbs_per_page) - kfree(acb->srb_array[i].segment_x); - - vfree(acb->srb_array[0].virt_map); + if (acb->srb_array[i].segment_x) + kfree(acb->srb_array[i].segment_x); } @@ -4280,12 +4274,9 @@ static int __devinit adapter_sg_tables_alloc(struct AdapterCtlBlk *acb) int srb_idx = 0; unsigned i = 0; struct SGentry *ptr; - void **virt_array; - for (i = 0; i < DC395x_MAX_SRB_CNT; i++) { + for (i = 0; i < DC395x_MAX_SRB_CNT; i++) acb->srb_array[i].segment_x = NULL; - acb->srb_array[i].virt_map = NULL; - } dprintkdbg(DBG_1, "Allocate %i pages for SG tables\n", pages); while (pages--) { @@ -4306,19 +4297,6 @@ static int __devinit adapter_sg_tables_alloc(struct AdapterCtlBlk *acb) ptr + (i * DC395x_MAX_SG_LISTENTRY); else dprintkl(KERN_DEBUG, "No space for tmsrb SG table reserved?!\n"); - - virt_array = vmalloc((DC395x_MAX_SRB_CNT + 1) * DC395x_MAX_SG_LISTENTRY * sizeof(void*)); - - if (!virt_array) { - adapter_sg_tables_free(acb); - return 1; - } - - for (i = 0; i < DC395x_MAX_SRB_CNT + 1; i++) { - acb->srb_array[i].virt_map = virt_array; - virt_array += DC395x_MAX_SG_LISTENTRY; - } - return 0; } 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 raptorFlag = TRUE; } - + if (pci_request_regions(pDev, "dpt_i2o")) { + PERROR("dpti: adpt_config_hba: pci request region failed\n"); + return -EINVAL; + } base_addr_virt = ioremap(base_addr0_phys,hba_map0_area_size); if (!base_addr_virt) { + pci_release_regions(pDev); PERROR("dpti: adpt_config_hba: io remap failed\n"); return -EINVAL; } @@ -919,6 +923,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev if (!msg_addr_virt) { PERROR("dpti: adpt_config_hba: io remap failed on BAR1\n"); iounmap(base_addr_virt); + pci_release_regions(pDev); return -EINVAL; } } else { @@ -932,6 +937,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev iounmap(msg_addr_virt); } iounmap(base_addr_virt); + pci_release_regions(pDev); return -ENOMEM; } memset(pHba, 0, sizeof(adpt_hba)); @@ -1027,6 +1033,7 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba) up(&adpt_configuration_lock); iounmap(pHba->base_addr_virt); + pci_release_regions(pHba->pDev); if(pHba->msg_addr_virt != pHba->base_addr_virt){ iounmap(pHba->msg_addr_virt); } 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 @@ enum srp_types { SRP_LOGIN_REQ_TYPE = 0x00, SRP_LOGIN_RSP_TYPE = 0xC0, - SRP_LOGIN_REJ_TYPE = 0x80, + SRP_LOGIN_REJ_TYPE = 0xC2, SRP_I_LOGOUT_TYPE = 0x03, SRP_T_LOGOUT_TYPE = 0x80, 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 @@ /* 6.10.00 - Remove 1G Addressing Limitations */ /* 6.11.xx - Get VersionInfo buffer off the stack ! DDTS 60401 */ /* 6.11.xx - Make Logical Drive Info structure safe for DMA DDTS 60639 */ -/* 7.10.xx - Add highmem_io flag in SCSI Templete for 2.4 kernels */ +/* 7.10.18 - Add highmem_io flag in SCSI Templete for 2.4 kernels */ /* - Fix path/name for scsi_hosts.h include for 2.6 kernels */ /* - Fix sort order of 7k */ /* - Remove 3 unused "inline" functions */ +/* 7.12.xx - Use STATIC functions whereever possible */ +/* - Clean up deprecated MODULE_PARM calls */ /*****************************************************************************/ /* @@ -207,8 +209,8 @@ module_param(ips, charp, 0); /* * DRIVER_VER */ -#define IPS_VERSION_HIGH "7.10" -#define IPS_VERSION_LOW ".18 " +#define IPS_VERSION_HIGH "7.12" +#define IPS_VERSION_LOW ".02 " #if !defined(__i386__) && !defined(__ia64__) && !defined(__x86_64__) #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 @@ #define scsi_set_pci_device(sh,dev) (0) #endif - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - - #ifndef irqreturn_t - typedef void irqreturn_t; - #endif - + #ifndef IRQ_NONE + typedef void irqreturn_t; #define IRQ_NONE #define IRQ_HANDLED #define IRQ_RETVAL(x) + #endif + + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #define IPS_REGISTER_HOSTS(SHT) scsi_register_module(MODULE_SCSI_HA,SHT) #define IPS_UNREGISTER_HOSTS(SHT) scsi_unregister_module(MODULE_SCSI_HA,SHT) #define IPS_ADD_HOST(shost,device) @@ -123,6 +122,10 @@ #ifndef min #define min(x,y) ((x) < (y) ? x : y) #endif + + #ifndef __iomem /* For clean compiles in earlier kernels without __iomem annotations */ + #define __iomem + #endif #define pci_dma_hi32(a) ((a >> 16) >> 16) #define pci_dma_lo32(a) (a & 0xffffffff) @@ -1206,13 +1209,13 @@ typedef struct { #define IPS_VER_MAJOR 7 #define IPS_VER_MAJOR_STRING "7" -#define IPS_VER_MINOR 10 -#define IPS_VER_MINOR_STRING "10" -#define IPS_VER_BUILD 18 -#define IPS_VER_BUILD_STRING "18" -#define IPS_VER_STRING "7.10.18" +#define IPS_VER_MINOR 12 +#define IPS_VER_MINOR_STRING "12" +#define IPS_VER_BUILD 02 +#define IPS_VER_BUILD_STRING "02" +#define IPS_VER_STRING "7.12.02" #define IPS_RELEASE_ID 0x00020000 -#define IPS_BUILD_IDENT 731 +#define IPS_BUILD_IDENT 761 #define IPS_LEGALCOPYRIGHT_STRING "(C) Copyright IBM Corp. 1994, 2002. All Rights Reserved." #define IPS_ADAPTECCOPYRIGHT_STRING "(c) Copyright Adaptec, Inc. 2002 to 2004. All Rights Reserved." #define IPS_DELLCOPYRIGHT_STRING "(c) Copyright Dell 2004. All Rights Reserved." @@ -1223,12 +1226,12 @@ typedef struct { #define IPS_VER_SERVERAID2 "2.88.13" #define IPS_VER_NAVAJO "2.88.13" #define IPS_VER_SERVERAID3 "6.10.24" -#define IPS_VER_SERVERAID4H "7.10.11" -#define IPS_VER_SERVERAID4MLx "7.10.18" -#define IPS_VER_SARASOTA "7.10.18" -#define IPS_VER_MARCO "7.10.18" -#define IPS_VER_SEBRING "7.10.18" -#define IPS_VER_KEYWEST "7.10.18" +#define IPS_VER_SERVERAID4H "7.12.02" +#define IPS_VER_SERVERAID4MLx "7.12.02" +#define IPS_VER_SARASOTA "7.12.02" +#define IPS_VER_MARCO "7.12.02" +#define IPS_VER_SEBRING "7.12.02" +#define IPS_VER_KEYWEST "7.12.02" /* Compatability IDs for various adapters */ #define IPS_COMPAT_UNKNOWN "" diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 73b1f72b7e43..f4e7dcb6492b 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2268,19 +2268,6 @@ void ata_qc_prep(struct ata_queued_cmd *qc) * spin_lock_irqsave(host_set lock) */ - - -/** - * ata_sg_init_one - Prepare a one-entry scatter-gather list. - * @qc: Queued command - * @buf: transfer buffer - * @buflen: length of buf - * - * Builds a single-entry scatter-gather list to initiate a - * transfer utilizing the specified buffer. - * - * LOCKING: - */ void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen) { struct scatterlist *sg; @@ -2312,18 +2299,6 @@ void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen) * spin_lock_irqsave(host_set lock) */ - -/** - * ata_sg_init - Assign a scatter gather list to a queued command - * @qc: Queued command - * @sg: Scatter-gather list - * @n_elem: length of sg list - * - * Attaches a scatter-gather list to a queued command. - * - * LOCKING: - */ - void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, unsigned int n_elem) { 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) * appropriate place */ host->host_failed--; + INIT_LIST_HEAD(&host->eh_cmd_q); DPRINTK("EXIT\n"); return 0; diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index d90430bbb0de..3e7f4843020f 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -26,7 +26,7 @@ #define __LIBATA_H__ #define DRV_NAME "libata" -#define DRV_VERSION "1.11" /* must be exactly four chars */ +#define DRV_VERSION "1.12" /* must be exactly four chars */ struct ata_scsi_args { u16 *id; diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index 5c1d4411457a..919fb314ad10 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -40,7 +40,7 @@ #include "sata_promise.h" #define DRV_NAME "sata_promise" -#define DRV_VERSION "1.01" +#define DRV_VERSION "1.02" enum { 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) for (i = 0; i < last; i++) { buf[idx++] = cpu_to_le32(sg_dma_address(&sg[i])); buf[idx++] = cpu_to_le32(sg_dma_len(&sg[i])); - total_len += sg[i].length; + total_len += sg_dma_len(&sg[i]); } buf[idx - 1] |= cpu_to_le32(ATA_PRD_EOT); sgt_len = idx * 4; diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index ae28bcb79242..895c9452be4c 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1822,12 +1822,16 @@ EXPORT_SYMBOL(scsi_reset_provider); int scsi_normalize_sense(const u8 *sense_buffer, int sb_len, struct scsi_sense_hdr *sshdr) { - if (!sense_buffer || !sb_len || (sense_buffer[0] & 0x70) != 0x70) + if (!sense_buffer || !sb_len) return 0; memset(sshdr, 0, sizeof(struct scsi_sense_hdr)); sshdr->response_code = (sense_buffer[0] & 0x7f); + + if (!scsi_sense_valid(sshdr)) + return 0; + if (sshdr->response_code >= 0x72) { /* * descriptor format diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index 946c31fa6466..b7fddac81347 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -88,25 +88,18 @@ static int ioctl_probe(struct Scsi_Host *host, void __user *buffer) static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, int timeout, int retries) { - struct scsi_request *sreq; int result; struct scsi_sense_hdr sshdr; SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", *cmd)); - sreq = scsi_allocate_request(sdev, GFP_KERNEL); - if (!sreq) { - printk(KERN_WARNING "SCSI internal ioctl failed, no memory\n"); - return -ENOMEM; - } - - sreq->sr_data_direction = DMA_NONE; - scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries); + result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, + &sshdr, timeout, retries); - SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", sreq->sr_result)); + SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", result)); - if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) && - (scsi_request_normalize_sense(sreq, &sshdr))) { + if ((driver_byte(result) & DRIVER_SENSE) && + (scsi_sense_valid(&sshdr))) { switch (sshdr.sense_key) { case ILLEGAL_REQUEST: if (cmd[0] == ALLOW_MEDIUM_REMOVAL) @@ -125,7 +118,7 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, case UNIT_ATTENTION: if (sdev->removable) { sdev->changed = 1; - sreq->sr_result = 0; /* This is no longer considered an error */ + result = 0; /* This is no longer considered an error */ break; } default: /* Fall through for non-removable media */ @@ -135,15 +128,13 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, sdev->channel, sdev->id, sdev->lun, - sreq->sr_result); - scsi_print_req_sense(" ", sreq); + result); + scsi_print_sense_hdr(" ", &sshdr); break; } } - result = sreq->sr_result; SCSI_LOG_IOCTL(2, printk("IOCTL Releasing command\n")); - scsi_release_request(sreq); return result; } @@ -208,8 +199,8 @@ int scsi_ioctl_send_command(struct scsi_device *sdev, { char *buf; unsigned char cmd[MAX_COMMAND_SIZE]; + unsigned char sense[SCSI_SENSE_BUFFERSIZE]; char __user *cmd_in; - struct scsi_request *sreq; unsigned char opcode; unsigned int inlen, outlen, cmdlen; unsigned int needed, buf_needed; @@ -321,31 +312,23 @@ int scsi_ioctl_send_command(struct scsi_device *sdev, break; } - sreq = scsi_allocate_request(sdev, GFP_KERNEL); - if (!sreq) { - result = -EINTR; - goto error; - } - - sreq->sr_data_direction = data_direction; - scsi_wait_req(sreq, cmd, buf, needed, timeout, retries); + result = scsi_execute(sdev, cmd, data_direction, buf, needed, + sense, timeout, retries, 0); /* * If there was an error condition, pass the info back to the user. */ - result = sreq->sr_result; if (result) { - int sb_len = sizeof(sreq->sr_sense_buffer); + int sb_len = sizeof(*sense); sb_len = (sb_len > OMAX_SB_LEN) ? OMAX_SB_LEN : sb_len; - if (copy_to_user(cmd_in, sreq->sr_sense_buffer, sb_len)) + if (copy_to_user(cmd_in, sense, sb_len)) result = -EFAULT; } else { if (copy_to_user(cmd_in, buf, outlen)) result = -EFAULT; } - scsi_release_request(sreq); error: kfree(buf); return result; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 060010bccabc..77f2d444f7e0 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -232,23 +232,6 @@ void scsi_do_req(struct scsi_request *sreq, const void *cmnd, } EXPORT_SYMBOL(scsi_do_req); -static void scsi_wait_done(struct scsi_cmnd *cmd) -{ - struct request *req = cmd->request; - struct request_queue *q = cmd->device->request_queue; - unsigned long flags; - - req->rq_status = RQ_SCSI_DONE; /* Busy, but indicate request done */ - - spin_lock_irqsave(q->queue_lock, flags); - if (blk_rq_tagged(req)) - blk_queue_end_tag(q, req); - spin_unlock_irqrestore(q->queue_lock, flags); - - if (req->waiting) - complete(req->waiting); -} - /* This is the end routine we get to if a command was never attached * to the request. Simply complete the request without changing * rq_status; this will cause a DRIVER_ERROR. */ @@ -263,21 +246,114 @@ void scsi_wait_req(struct scsi_request *sreq, const void *cmnd, void *buffer, unsigned bufflen, int timeout, int retries) { DECLARE_COMPLETION(wait); - - sreq->sr_request->waiting = &wait; - sreq->sr_request->rq_status = RQ_SCSI_BUSY; - sreq->sr_request->end_io = scsi_wait_req_end_io; - scsi_do_req(sreq, cmnd, buffer, bufflen, scsi_wait_done, - timeout, retries); + int write = (sreq->sr_data_direction == DMA_TO_DEVICE); + struct request *req; + + req = blk_get_request(sreq->sr_device->request_queue, write, + __GFP_WAIT); + if (bufflen && blk_rq_map_kern(sreq->sr_device->request_queue, req, + buffer, bufflen, __GFP_WAIT)) { + sreq->sr_result = DRIVER_ERROR << 24; + blk_put_request(req); + return; + } + + req->flags |= REQ_NOMERGE; + req->waiting = &wait; + req->end_io = scsi_wait_req_end_io; + req->cmd_len = COMMAND_SIZE(((u8 *)cmnd)[0]); + req->sense = sreq->sr_sense_buffer; + req->sense_len = 0; + memcpy(req->cmd, cmnd, req->cmd_len); + req->timeout = timeout; + req->flags |= REQ_BLOCK_PC; + req->rq_disk = NULL; + blk_insert_request(sreq->sr_device->request_queue, req, + sreq->sr_data_direction == DMA_TO_DEVICE, NULL); wait_for_completion(&wait); sreq->sr_request->waiting = NULL; - if (sreq->sr_request->rq_status != RQ_SCSI_DONE) + sreq->sr_result = req->errors; + if (req->errors) sreq->sr_result |= (DRIVER_ERROR << 24); - __scsi_release_request(sreq); + blk_put_request(req); } + EXPORT_SYMBOL(scsi_wait_req); +/** + * scsi_execute - insert request and wait for the result + * @sdev: scsi device + * @cmd: scsi command + * @data_direction: data direction + * @buffer: data buffer + * @bufflen: len of buffer + * @sense: optional sense buffer + * @timeout: request timeout in seconds + * @retries: number of times to retry request + * @flags: or into request flags; + * + * returns the req->errors value which is the the scsi_cmnd result + * field. + **/ +int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, + int data_direction, void *buffer, unsigned bufflen, + unsigned char *sense, int timeout, int retries, int flags) +{ + struct request *req; + int write = (data_direction == DMA_TO_DEVICE); + int ret = DRIVER_ERROR << 24; + + req = blk_get_request(sdev->request_queue, write, __GFP_WAIT); + + if (bufflen && blk_rq_map_kern(sdev->request_queue, req, + buffer, bufflen, __GFP_WAIT)) + goto out; + + req->cmd_len = COMMAND_SIZE(cmd[0]); + memcpy(req->cmd, cmd, req->cmd_len); + req->sense = sense; + req->sense_len = 0; + req->timeout = timeout; + req->flags |= flags | REQ_BLOCK_PC | REQ_SPECIAL | REQ_QUIET; + + /* + * head injection *required* here otherwise quiesce won't work + */ + blk_execute_rq(req->q, NULL, req, 1); + + ret = req->errors; + out: + blk_put_request(req); + + return ret; +} +EXPORT_SYMBOL(scsi_execute); + + +int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, + int data_direction, void *buffer, unsigned bufflen, + struct scsi_sense_hdr *sshdr, int timeout, int retries) +{ + char *sense = NULL; + int result; + + if (sshdr) { + sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL); + if (!sense) + return DRIVER_ERROR << 24; + memset(sense, 0, SCSI_SENSE_BUFFERSIZE); + } + result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen, + sense, timeout, retries, 0); + if (sshdr) + scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, sshdr); + + kfree(sense); + return result; +} +EXPORT_SYMBOL(scsi_execute_req); + /* * Function: scsi_init_cmd_errh() * @@ -851,17 +927,20 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, scsi_requeue_command(q, cmd); return; } - printk(KERN_INFO "Device %s not ready.\n", - req->rq_disk ? req->rq_disk->disk_name : ""); + if (!(req->flags & REQ_QUIET)) + dev_printk(KERN_INFO, + &cmd->device->sdev_gendev, + "Device not ready.\n"); cmd = scsi_end_request(cmd, 0, this_count, 1); return; case VOLUME_OVERFLOW: - printk(KERN_INFO "Volume overflow <%d %d %d %d> CDB: ", - cmd->device->host->host_no, - (int)cmd->device->channel, - (int)cmd->device->id, (int)cmd->device->lun); - __scsi_print_command(cmd->data_cmnd); - scsi_print_sense("", cmd); + if (!(req->flags & REQ_QUIET)) { + dev_printk(KERN_INFO, + &cmd->device->sdev_gendev, + "Volume overflow, CDB: "); + __scsi_print_command(cmd->data_cmnd); + scsi_print_sense("", cmd); + } cmd = scsi_end_request(cmd, 0, block_bytes, 1); return; default: @@ -878,14 +957,13 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, return; } if (result) { - printk(KERN_INFO "SCSI error : <%d %d %d %d> return code " - "= 0x%x\n", cmd->device->host->host_no, - cmd->device->channel, - cmd->device->id, - cmd->device->lun, result); - - if (driver_byte(result) & DRIVER_SENSE) - scsi_print_sense("", cmd); + if (!(req->flags & REQ_QUIET)) { + dev_printk(KERN_INFO, &cmd->device->sdev_gendev, + "SCSI error: return code = 0x%x\n", result); + + if (driver_byte(result) & DRIVER_SENSE) + scsi_print_sense("", cmd); + } /* * Mark a single buffer as not uptodate. Queue the remainder. * We sometimes get this cruft in the event that a medium error @@ -1020,6 +1098,12 @@ static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk, return -EOPNOTSUPP; } +static void scsi_generic_done(struct scsi_cmnd *cmd) +{ + BUG_ON(!blk_pc_request(cmd->request)); + scsi_io_completion(cmd, cmd->result == 0 ? cmd->bufflen : 0, 0); +} + static int scsi_prep_fn(struct request_queue *q, struct request *req) { struct scsi_device *sdev = q->queuedata; @@ -1061,7 +1145,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) * these two cases differently. We differentiate by looking * at request->cmd, as this tells us the real story. */ - if (req->flags & REQ_SPECIAL) { + if (req->flags & REQ_SPECIAL && req->special) { struct scsi_request *sreq = req->special; if (sreq->sr_magic == SCSI_REQ_MAGIC) { @@ -1073,7 +1157,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) cmd = req->special; } else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) { - if(unlikely(specials_only)) { + if(unlikely(specials_only) && !(req->flags & REQ_SPECIAL)) { if(specials_only == SDEV_QUIESCE || specials_only == SDEV_BLOCK) return BLKPREP_DEFER; @@ -1142,11 +1226,26 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) /* * Initialize the actual SCSI command for this request. */ - drv = *(struct scsi_driver **)req->rq_disk->private_data; - if (unlikely(!drv->init_command(cmd))) { - scsi_release_buffers(cmd); - scsi_put_command(cmd); - return BLKPREP_KILL; + if (req->rq_disk) { + drv = *(struct scsi_driver **)req->rq_disk->private_data; + if (unlikely(!drv->init_command(cmd))) { + scsi_release_buffers(cmd); + scsi_put_command(cmd); + return BLKPREP_KILL; + } + } else { + memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd)); + if (rq_data_dir(req) == WRITE) + cmd->sc_data_direction = DMA_TO_DEVICE; + else if (req->data_len) + cmd->sc_data_direction = DMA_FROM_DEVICE; + else + cmd->sc_data_direction = DMA_NONE; + + cmd->transfersize = req->data_len; + cmd->allowed = 3; + cmd->timeout_per_command = req->timeout; + cmd->done = scsi_generic_done; } } @@ -1539,9 +1638,9 @@ void scsi_exit_queue(void) } } /** - * __scsi_mode_sense - issue a mode sense, falling back from 10 to + * scsi_mode_sense - issue a mode sense, falling back from 10 to * six bytes if necessary. - * @sreq: SCSI request to fill in with the MODE_SENSE + * @sdev: SCSI device to be queried * @dbd: set if mode sense will allow block descriptors to be returned * @modepage: mode page being requested * @buffer: request buffer (may not be smaller than eight bytes) @@ -1549,26 +1648,34 @@ void scsi_exit_queue(void) * @timeout: command timeout * @retries: number of retries before failing * @data: returns a structure abstracting the mode header data + * @sense: place to put sense data (or NULL if no sense to be collected). + * must be SCSI_SENSE_BUFFERSIZE big. * * Returns zero if unsuccessful, or the header offset (either 4 * or 8 depending on whether a six or ten byte command was * issued) if successful. **/ int -__scsi_mode_sense(struct scsi_request *sreq, int dbd, int modepage, +scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, unsigned char *buffer, int len, int timeout, int retries, - struct scsi_mode_data *data) { + struct scsi_mode_data *data, struct scsi_sense_hdr *sshdr) { unsigned char cmd[12]; int use_10_for_ms; int header_length; + int result; + struct scsi_sense_hdr my_sshdr; memset(data, 0, sizeof(*data)); memset(&cmd[0], 0, 12); cmd[1] = dbd & 0x18; /* allows DBD and LLBA bits */ cmd[2] = modepage; + /* caller might not be interested in sense, but we need it */ + if (!sshdr) + sshdr = &my_sshdr; + retry: - use_10_for_ms = sreq->sr_device->use_10_for_ms; + use_10_for_ms = sdev->use_10_for_ms; if (use_10_for_ms) { if (len < 8) @@ -1586,36 +1693,31 @@ __scsi_mode_sense(struct scsi_request *sreq, int dbd, int modepage, header_length = 4; } - sreq->sr_cmd_len = 0; - memset(sreq->sr_sense_buffer, 0, sizeof(sreq->sr_sense_buffer)); - sreq->sr_data_direction = DMA_FROM_DEVICE; - memset(buffer, 0, len); - scsi_wait_req(sreq, cmd, buffer, len, timeout, retries); + result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len, + sshdr, timeout, retries); /* This code looks awful: what it's doing is making sure an * ILLEGAL REQUEST sense return identifies the actual command * byte as the problem. MODE_SENSE commands can return * ILLEGAL REQUEST if the code page isn't supported */ - if (use_10_for_ms && !scsi_status_is_good(sreq->sr_result) && - (driver_byte(sreq->sr_result) & DRIVER_SENSE)) { - struct scsi_sense_hdr sshdr; - - if (scsi_request_normalize_sense(sreq, &sshdr)) { - if ((sshdr.sense_key == ILLEGAL_REQUEST) && - (sshdr.asc == 0x20) && (sshdr.ascq == 0)) { + if (use_10_for_ms && !scsi_status_is_good(result) && + (driver_byte(result) & DRIVER_SENSE)) { + if (scsi_sense_valid(sshdr)) { + if ((sshdr->sense_key == ILLEGAL_REQUEST) && + (sshdr->asc == 0x20) && (sshdr->ascq == 0)) { /* * Invalid command operation code */ - sreq->sr_device->use_10_for_ms = 0; + sdev->use_10_for_ms = 0; goto retry; } } } - if(scsi_status_is_good(sreq->sr_result)) { + if(scsi_status_is_good(result)) { data->header_length = header_length; if(use_10_for_ms) { data->length = buffer[0]*256 + buffer[1] + 2; @@ -1632,73 +1734,31 @@ __scsi_mode_sense(struct scsi_request *sreq, int dbd, int modepage, } } - return sreq->sr_result; -} -EXPORT_SYMBOL(__scsi_mode_sense); - -/** - * scsi_mode_sense - issue a mode sense, falling back from 10 to - * six bytes if necessary. - * @sdev: scsi device to send command to. - * @dbd: set if mode sense will disable block descriptors in the return - * @modepage: mode page being requested - * @buffer: request buffer (may not be smaller than eight bytes) - * @len: length of request buffer. - * @timeout: command timeout - * @retries: number of retries before failing - * - * Returns zero if unsuccessful, or the header offset (either 4 - * or 8 depending on whether a six or ten byte command was - * issued) if successful. - **/ -int -scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, - unsigned char *buffer, int len, int timeout, int retries, - struct scsi_mode_data *data) -{ - struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL); - int ret; - - if (!sreq) - return -1; - - ret = __scsi_mode_sense(sreq, dbd, modepage, buffer, len, - timeout, retries, data); - - scsi_release_request(sreq); - - return ret; + return result; } EXPORT_SYMBOL(scsi_mode_sense); int scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries) { - struct scsi_request *sreq; char cmd[] = { TEST_UNIT_READY, 0, 0, 0, 0, 0, }; + struct scsi_sense_hdr sshdr; int result; - sreq = scsi_allocate_request(sdev, GFP_KERNEL); - if (!sreq) - return -ENOMEM; - - sreq->sr_data_direction = DMA_NONE; - scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries); + result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, &sshdr, + timeout, retries); - if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) && sdev->removable) { - struct scsi_sense_hdr sshdr; + if ((driver_byte(result) & DRIVER_SENSE) && sdev->removable) { - if ((scsi_request_normalize_sense(sreq, &sshdr)) && + if ((scsi_sense_valid(&sshdr)) && ((sshdr.sense_key == UNIT_ATTENTION) || (sshdr.sense_key == NOT_READY))) { sdev->changed = 1; - sreq->sr_result = 0; + result = 0; } } - result = sreq->sr_result; - scsi_release_request(sreq); return result; } EXPORT_SYMBOL(scsi_test_unit_ready); diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 076cbe3b5a05..19c9a232a754 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -111,15 +111,14 @@ MODULE_PARM_DESC(inq_timeout, /** * scsi_unlock_floptical - unlock device via a special MODE SENSE command - * @sreq: used to send the command + * @sdev: scsi device to send command to * @result: area to store the result of the MODE SENSE * * Description: - * Send a vendor specific MODE SENSE (not a MODE SELECT) command using - * @sreq to unlock a device, storing the (unused) results into result. + * Send a vendor specific MODE SENSE (not a MODE SELECT) command. * Called for BLIST_KEY devices. **/ -static void scsi_unlock_floptical(struct scsi_request *sreq, +static void scsi_unlock_floptical(struct scsi_device *sdev, unsigned char *result) { unsigned char scsi_cmd[MAX_COMMAND_SIZE]; @@ -129,11 +128,10 @@ static void scsi_unlock_floptical(struct scsi_request *sreq, scsi_cmd[1] = 0; scsi_cmd[2] = 0x2e; scsi_cmd[3] = 0; - scsi_cmd[4] = 0x2a; /* size */ + scsi_cmd[4] = 0x2a; /* size */ scsi_cmd[5] = 0; - sreq->sr_cmd_len = 0; - sreq->sr_data_direction = DMA_FROM_DEVICE; - scsi_wait_req(sreq, scsi_cmd, result, 0x2a /* size */, SCSI_TIMEOUT, 3); + scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, result, 0x2a, NULL, + SCSI_TIMEOUT, 3); } /** @@ -336,9 +334,23 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, unsigned long flags; const int size = sizeof(struct scsi_target) + shost->transportt->target_size; - struct scsi_target *starget = kmalloc(size, GFP_ATOMIC); + struct scsi_target *starget; struct scsi_target *found_target; + /* + * Obtain the real parent from the transport. The transport + * is allowed to fail (no error) if there is nothing at that + * target id. + */ + if (shost->transportt->target_parent) { + spin_lock_irqsave(shost->host_lock, flags); + parent = shost->transportt->target_parent(shost, channel, id); + spin_unlock_irqrestore(shost->host_lock, flags); + if (!parent) + return NULL; + } + + starget = kmalloc(size, GFP_KERNEL); if (!starget) { printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__); return NULL; @@ -419,26 +431,25 @@ void scsi_target_reap(struct scsi_target *starget) /** * scsi_probe_lun - probe a single LUN using a SCSI INQUIRY - * @sreq: used to send the INQUIRY + * @sdev: scsi_device to probe * @inq_result: area to store the INQUIRY result + * @result_len: len of inq_result * @bflags: store any bflags found here * * Description: - * Probe the lun associated with @sreq using a standard SCSI INQUIRY; + * Probe the lun associated with @req using a standard SCSI INQUIRY; * - * If the INQUIRY is successful, sreq->sr_result is zero and: the + * If the INQUIRY is successful, zero is returned and the * INQUIRY data is in @inq_result; the scsi_level and INQUIRY length - * are copied to the Scsi_Device at @sreq->sr_device (sdev); - * any flags value is stored in *@bflags. + * are copied to the Scsi_Device any flags value is stored in *@bflags. **/ -static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, - int *bflags) +static int scsi_probe_lun(struct scsi_device *sdev, char *inq_result, + int result_len, int *bflags) { - struct scsi_device *sdev = sreq->sr_device; /* a bit ugly */ unsigned char scsi_cmd[MAX_COMMAND_SIZE]; int first_inquiry_len, try_inquiry_len, next_inquiry_len; int response_len = 0; - int pass, count; + int pass, count, result; struct scsi_sense_hdr sshdr; *bflags = 0; @@ -461,28 +472,26 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, memset(scsi_cmd, 0, 6); scsi_cmd[0] = INQUIRY; scsi_cmd[4] = (unsigned char) try_inquiry_len; - sreq->sr_cmd_len = 0; - sreq->sr_data_direction = DMA_FROM_DEVICE; memset(inq_result, 0, try_inquiry_len); - scsi_wait_req(sreq, (void *) scsi_cmd, (void *) inq_result, - try_inquiry_len, - HZ/2 + HZ*scsi_inq_timeout, 3); + + result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, + inq_result, try_inquiry_len, &sshdr, + HZ / 2 + HZ * scsi_inq_timeout, 3); SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: INQUIRY %s " "with code 0x%x\n", - sreq->sr_result ? "failed" : "successful", - sreq->sr_result)); + result ? "failed" : "successful", result)); - if (sreq->sr_result) { + if (result) { /* * not-ready to ready transition [asc/ascq=0x28/0x0] * or power-on, reset [asc/ascq=0x29/0x0], continue. * INQUIRY should not yield UNIT_ATTENTION * but many buggy devices do so anyway. */ - if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) && - scsi_request_normalize_sense(sreq, &sshdr)) { + if ((driver_byte(result) & DRIVER_SENSE) && + scsi_sense_valid(&sshdr)) { if ((sshdr.sense_key == UNIT_ATTENTION) && ((sshdr.asc == 0x28) || (sshdr.asc == 0x29)) && @@ -493,7 +502,7 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, break; } - if (sreq->sr_result == 0) { + if (result == 0) { response_len = (unsigned char) inq_result[4] + 5; if (response_len > 255) response_len = first_inquiry_len; /* sanity */ @@ -542,8 +551,8 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, /* If the last transfer attempt got an error, assume the * peripheral doesn't exist or is dead. */ - if (sreq->sr_result) - return; + if (result) + return -EIO; /* Don't report any more data than the device says is valid */ sdev->inquiry_len = min(try_inquiry_len, response_len); @@ -579,7 +588,7 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, (sdev->scsi_level == 1 && (inq_result[3] & 0x0f) == 1)) sdev->scsi_level++; - return; + return 0; } /** @@ -786,9 +795,8 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, void *hostdata) { struct scsi_device *sdev; - struct scsi_request *sreq; unsigned char *result; - int bflags, res = SCSI_SCAN_NO_RESPONSE; + int bflags, res = SCSI_SCAN_NO_RESPONSE, result_len = 256; struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); /* @@ -817,16 +825,13 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, sdev = scsi_alloc_sdev(starget, lun, hostdata); if (!sdev) goto out; - sreq = scsi_allocate_request(sdev, GFP_ATOMIC); - if (!sreq) - goto out_free_sdev; - result = kmalloc(256, GFP_ATOMIC | + + result = kmalloc(result_len, GFP_ATOMIC | ((shost->unchecked_isa_dma) ? __GFP_DMA : 0)); if (!result) - goto out_free_sreq; + goto out_free_sdev; - scsi_probe_lun(sreq, result, &bflags); - if (sreq->sr_result) + if (scsi_probe_lun(sdev, result, result_len, &bflags)) goto out_free_result; /* @@ -854,7 +859,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, if (res == SCSI_SCAN_LUN_PRESENT) { if (bflags & BLIST_KEY) { sdev->lockable = 0; - scsi_unlock_floptical(sreq, result); + scsi_unlock_floptical(sdev, result); } if (bflagsp) *bflagsp = bflags; @@ -862,8 +867,6 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, out_free_result: kfree(result); - out_free_sreq: - scsi_release_request(sreq); out_free_sdev: if (res == SCSI_SCAN_LUN_PRESENT) { if (sdevp) { @@ -1056,8 +1059,8 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, unsigned int lun; unsigned int num_luns; unsigned int retries; + int result; struct scsi_lun *lunp, *lun_data; - struct scsi_request *sreq; u8 *data; struct scsi_sense_hdr sshdr; struct scsi_target *starget = scsi_target(sdev); @@ -1075,10 +1078,6 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, if (bflags & BLIST_NOLUN) return 0; - sreq = scsi_allocate_request(sdev, GFP_ATOMIC); - if (!sreq) - goto out; - sprintf(devname, "host %d channel %d id %d", sdev->host->host_no, sdev->channel, sdev->id); @@ -1096,7 +1095,7 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, lun_data = kmalloc(length, GFP_ATOMIC | (sdev->host->unchecked_isa_dma ? __GFP_DMA : 0)); if (!lun_data) - goto out_release_request; + goto out; scsi_cmd[0] = REPORT_LUNS; @@ -1115,8 +1114,6 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, scsi_cmd[10] = 0; /* reserved */ scsi_cmd[11] = 0; /* control */ - sreq->sr_cmd_len = 0; - sreq->sr_data_direction = DMA_FROM_DEVICE; /* * We can get a UNIT ATTENTION, for example a power on/reset, so @@ -1132,29 +1129,29 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: Sending" " REPORT LUNS to %s (try %d)\n", devname, retries)); - scsi_wait_req(sreq, scsi_cmd, lun_data, length, - SCSI_TIMEOUT + 4*HZ, 3); + + result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, + lun_data, length, &sshdr, + SCSI_TIMEOUT + 4 * HZ, 3); + SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: REPORT LUNS" - " %s (try %d) result 0x%x\n", sreq->sr_result - ? "failed" : "successful", retries, - sreq->sr_result)); - if (sreq->sr_result == 0) + " %s (try %d) result 0x%x\n", result + ? "failed" : "successful", retries, result)); + if (result == 0) break; - else if (scsi_request_normalize_sense(sreq, &sshdr)) { + else if (scsi_sense_valid(&sshdr)) { if (sshdr.sense_key != UNIT_ATTENTION) break; } } - if (sreq->sr_result) { + if (result) { /* * The device probably does not support a REPORT LUN command */ kfree(lun_data); - scsi_release_request(sreq); return 1; } - scsi_release_request(sreq); /* * Get the length from the first four bytes of lun_data. @@ -1228,8 +1225,6 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, kfree(lun_data); return 0; - out_release_request: - scsi_release_request(sreq); out: /* * We are out of memory, don't try scanning any further. diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 96243c7fe110..2cab556b6e82 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -1024,6 +1024,23 @@ static int fc_rport_match(struct attribute_container *cont, return &i->rport_attr_cont.ac == cont; } + +/* + * Must be called with shost->host_lock held + */ +static struct device *fc_target_parent(struct Scsi_Host *shost, + int channel, uint id) +{ + struct fc_rport *rport; + + list_for_each_entry(rport, &fc_host_rports(shost), peers) + if ((rport->channel == channel) && + (rport->scsi_target_id == id)) + return &rport->dev; + + return NULL; +} + struct scsi_transport_template * fc_attach_transport(struct fc_function_template *ft) { @@ -1059,6 +1076,8 @@ fc_attach_transport(struct fc_function_template *ft) /* Transport uses the shost workq for scsi scanning */ i->t.create_work_queue = 1; + + i->t.target_parent = fc_target_parent; /* * Setup SCSI Target Attributes. diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 89f6b7feb9c2..ef577c8c2182 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -28,7 +28,7 @@ #include "scsi_priv.h" #include <scsi/scsi_device.h> #include <scsi/scsi_host.h> -#include <scsi/scsi_request.h> +#include <scsi/scsi_cmnd.h> #include <scsi/scsi_eh.h> #include <scsi/scsi_transport.h> #include <scsi/scsi_transport_spi.h> @@ -106,27 +106,31 @@ static int sprint_frac(char *dest, int value, int denom) return result; } -/* Modification of scsi_wait_req that will clear UNIT ATTENTION conditions - * resulting from (likely) bus and device resets */ -static void spi_wait_req(struct scsi_request *sreq, const void *cmd, - void *buffer, unsigned bufflen) +static int spi_execute(struct scsi_device *sdev, const void *cmd, + enum dma_data_direction dir, + void *buffer, unsigned bufflen, + struct scsi_sense_hdr *sshdr) { - int i; + int i, result; + unsigned char sense[SCSI_SENSE_BUFFERSIZE]; for(i = 0; i < DV_RETRIES; i++) { - sreq->sr_request->flags |= REQ_FAILFAST; - - scsi_wait_req(sreq, cmd, buffer, bufflen, - DV_TIMEOUT, /* retries */ 1); - if (sreq->sr_result & DRIVER_SENSE) { - struct scsi_sense_hdr sshdr; - - if (scsi_request_normalize_sense(sreq, &sshdr) - && sshdr.sense_key == UNIT_ATTENTION) + result = scsi_execute(sdev, cmd, dir, buffer, bufflen, + sense, DV_TIMEOUT, /* retries */ 1, + REQ_FAILFAST); + if (result & DRIVER_SENSE) { + struct scsi_sense_hdr sshdr_tmp; + if (!sshdr) + sshdr = &sshdr_tmp; + + if (scsi_normalize_sense(sense, sizeof(*sense), + sshdr) + && sshdr->sense_key == UNIT_ATTENTION) continue; } break; } + return result; } static struct { @@ -546,13 +550,13 @@ enum spi_compare_returns { /* This is for read/write Domain Validation: If the device supports * an echo buffer, we do read/write tests to it */ static enum spi_compare_returns -spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer, +spi_dv_device_echo_buffer(struct scsi_device *sdev, u8 *buffer, u8 *ptr, const int retries) { - struct scsi_device *sdev = sreq->sr_device; int len = ptr - buffer; - int j, k, r; + int j, k, r, result; unsigned int pattern = 0x0000ffff; + struct scsi_sense_hdr sshdr; const char spi_write_buffer[] = { WRITE_BUFFER, 0x0a, 0, 0, 0, 0, 0, len >> 8, len & 0xff, 0 @@ -597,14 +601,12 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer, } for (r = 0; r < retries; r++) { - sreq->sr_cmd_len = 0; /* wait_req to fill in */ - sreq->sr_data_direction = DMA_TO_DEVICE; - spi_wait_req(sreq, spi_write_buffer, buffer, len); - if(sreq->sr_result || !scsi_device_online(sdev)) { - struct scsi_sense_hdr sshdr; + result = spi_execute(sdev, spi_write_buffer, DMA_TO_DEVICE, + buffer, len, &sshdr); + if(result || !scsi_device_online(sdev)) { scsi_device_set_state(sdev, SDEV_QUIESCE); - if (scsi_request_normalize_sense(sreq, &sshdr) + if (scsi_sense_valid(&sshdr) && sshdr.sense_key == ILLEGAL_REQUEST /* INVALID FIELD IN CDB */ && sshdr.asc == 0x24 && sshdr.ascq == 0x00) @@ -616,14 +618,13 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer, return SPI_COMPARE_SKIP_TEST; - SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Write Buffer failure %x\n", sreq->sr_result); + SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Write Buffer failure %x\n", result); return SPI_COMPARE_FAILURE; } memset(ptr, 0, len); - sreq->sr_cmd_len = 0; /* wait_req to fill in */ - sreq->sr_data_direction = DMA_FROM_DEVICE; - spi_wait_req(sreq, spi_read_buffer, ptr, len); + spi_execute(sdev, spi_read_buffer, DMA_FROM_DEVICE, + ptr, len, NULL); scsi_device_set_state(sdev, SDEV_QUIESCE); if (memcmp(buffer, ptr, len) != 0) @@ -635,25 +636,22 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer, /* This is for the simplest form of Domain Validation: a read test * on the inquiry data from the device */ static enum spi_compare_returns -spi_dv_device_compare_inquiry(struct scsi_request *sreq, u8 *buffer, +spi_dv_device_compare_inquiry(struct scsi_device *sdev, u8 *buffer, u8 *ptr, const int retries) { - int r; - const int len = sreq->sr_device->inquiry_len; - struct scsi_device *sdev = sreq->sr_device; + int r, result; + const int len = sdev->inquiry_len; const char spi_inquiry[] = { INQUIRY, 0, 0, 0, len, 0 }; for (r = 0; r < retries; r++) { - sreq->sr_cmd_len = 0; /* wait_req to fill in */ - sreq->sr_data_direction = DMA_FROM_DEVICE; - memset(ptr, 0, len); - spi_wait_req(sreq, spi_inquiry, ptr, len); + result = spi_execute(sdev, spi_inquiry, DMA_FROM_DEVICE, + ptr, len, NULL); - if(sreq->sr_result || !scsi_device_online(sdev)) { + if(result || !scsi_device_online(sdev)) { scsi_device_set_state(sdev, SDEV_QUIESCE); return SPI_COMPARE_FAILURE; } @@ -674,12 +672,11 @@ spi_dv_device_compare_inquiry(struct scsi_request *sreq, u8 *buffer, } static enum spi_compare_returns -spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr, +spi_dv_retrain(struct scsi_device *sdev, u8 *buffer, u8 *ptr, enum spi_compare_returns - (*compare_fn)(struct scsi_request *, u8 *, u8 *, int)) + (*compare_fn)(struct scsi_device *, u8 *, u8 *, int)) { - struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt); - struct scsi_device *sdev = sreq->sr_device; + struct spi_internal *i = to_spi_internal(sdev->host->transportt); struct scsi_target *starget = sdev->sdev_target; int period = 0, prevperiod = 0; enum spi_compare_returns retval; @@ -687,7 +684,7 @@ spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr, for (;;) { int newperiod; - retval = compare_fn(sreq, buffer, ptr, DV_LOOPS); + retval = compare_fn(sdev, buffer, ptr, DV_LOOPS); if (retval == SPI_COMPARE_SUCCESS || retval == SPI_COMPARE_SKIP_TEST) @@ -733,9 +730,9 @@ spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr, } static int -spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer) +spi_dv_device_get_echo_buffer(struct scsi_device *sdev, u8 *buffer) { - int l; + int l, result; /* first off do a test unit ready. This can error out * because of reservations or some other reason. If it @@ -751,18 +748,16 @@ spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer) }; - sreq->sr_cmd_len = 0; - sreq->sr_data_direction = DMA_NONE; - /* We send a set of three TURs to clear any outstanding * unit attention conditions if they exist (Otherwise the * buffer tests won't be happy). If the TUR still fails * (reservation conflict, device not ready, etc) just * skip the write tests */ for (l = 0; ; l++) { - spi_wait_req(sreq, spi_test_unit_ready, NULL, 0); + result = spi_execute(sdev, spi_test_unit_ready, DMA_NONE, + NULL, 0, NULL); - if(sreq->sr_result) { + if(result) { if(l >= 3) return 0; } else { @@ -771,12 +766,10 @@ spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer) } } - sreq->sr_cmd_len = 0; - sreq->sr_data_direction = DMA_FROM_DEVICE; - - spi_wait_req(sreq, spi_read_buffer_descriptor, buffer, 4); + result = spi_execute(sdev, spi_read_buffer_descriptor, + DMA_FROM_DEVICE, buffer, 4, NULL); - if (sreq->sr_result) + if (result) /* Device has no echo buffer */ return 0; @@ -784,17 +777,16 @@ spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer) } static void -spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) +spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) { - struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt); - struct scsi_device *sdev = sreq->sr_device; + struct spi_internal *i = to_spi_internal(sdev->host->transportt); struct scsi_target *starget = sdev->sdev_target; int len = sdev->inquiry_len; /* first set us up for narrow async */ DV_SET(offset, 0); DV_SET(width, 0); - if (spi_dv_device_compare_inquiry(sreq, buffer, buffer, DV_LOOPS) + if (spi_dv_device_compare_inquiry(sdev, buffer, buffer, DV_LOOPS) != SPI_COMPARE_SUCCESS) { SPI_PRINTK(starget, KERN_ERR, "Domain Validation Initial Inquiry Failed\n"); /* FIXME: should probably offline the device here? */ @@ -806,7 +798,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) scsi_device_wide(sdev)) { i->f->set_width(starget, 1); - if (spi_dv_device_compare_inquiry(sreq, buffer, + if (spi_dv_device_compare_inquiry(sdev, buffer, buffer + len, DV_LOOPS) != SPI_COMPARE_SUCCESS) { @@ -827,7 +819,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) len = 0; if (scsi_device_dt(sdev)) - len = spi_dv_device_get_echo_buffer(sreq, buffer); + len = spi_dv_device_get_echo_buffer(sdev, buffer); retry: @@ -853,7 +845,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) if (len == 0) { SPI_PRINTK(starget, KERN_INFO, "Domain Validation skipping write tests\n"); - spi_dv_retrain(sreq, buffer, buffer + len, + spi_dv_retrain(sdev, buffer, buffer + len, spi_dv_device_compare_inquiry); return; } @@ -863,7 +855,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) len = SPI_MAX_ECHO_BUFFER_SIZE; } - if (spi_dv_retrain(sreq, buffer, buffer + len, + if (spi_dv_retrain(sdev, buffer, buffer + len, spi_dv_device_echo_buffer) == SPI_COMPARE_SKIP_TEST) { /* OK, the stupid drive can't do a write echo buffer @@ -886,16 +878,12 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) void spi_dv_device(struct scsi_device *sdev) { - struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL); struct scsi_target *starget = sdev->sdev_target; u8 *buffer; const int len = SPI_MAX_ECHO_BUFFER_SIZE*2; - if (unlikely(!sreq)) - return; - if (unlikely(scsi_device_get(sdev))) - goto out_free_req; + return; buffer = kmalloc(len, GFP_KERNEL); @@ -916,7 +904,7 @@ spi_dv_device(struct scsi_device *sdev) SPI_PRINTK(starget, KERN_INFO, "Beginning Domain Validation\n"); - spi_dv_device_internal(sreq, buffer); + spi_dv_device_internal(sdev, buffer); SPI_PRINTK(starget, KERN_INFO, "Ending Domain Validation\n"); @@ -931,8 +919,6 @@ spi_dv_device(struct scsi_device *sdev) kfree(buffer); out_put: scsi_device_put(sdev); - out_free_req: - scsi_release_request(sreq); } EXPORT_SYMBOL(spi_dv_device); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 41ba0809f791..de564b386052 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -59,7 +59,6 @@ #include <scsi/scsi_eh.h> #include <scsi/scsi_host.h> #include <scsi/scsi_ioctl.h> -#include <scsi/scsi_request.h> #include <scsi/scsicam.h> #include "scsi_logging.h" @@ -125,7 +124,7 @@ static int sd_issue_flush(struct device *, sector_t *); static void sd_end_flush(request_queue_t *, struct request *); static int sd_prepare_flush(request_queue_t *, struct request *); static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname, - struct scsi_request *SRpnt, unsigned char *buffer); + unsigned char *buffer); static struct scsi_driver sd_template = { .owner = THIS_MODULE, @@ -682,19 +681,13 @@ not_present: static int sd_sync_cache(struct scsi_device *sdp) { - struct scsi_request *sreq; int retries, res; + struct scsi_sense_hdr sshdr; if (!scsi_device_online(sdp)) return -ENODEV; - sreq = scsi_allocate_request(sdp, GFP_KERNEL); - if (!sreq) { - printk("FAILED\n No memory for request\n"); - return -ENOMEM; - } - sreq->sr_data_direction = DMA_NONE; for (retries = 3; retries > 0; --retries) { unsigned char cmd[10] = { 0 }; @@ -703,22 +696,20 @@ static int sd_sync_cache(struct scsi_device *sdp) * Leave the rest of the command zero to indicate * flush everything. */ - scsi_wait_req(sreq, cmd, NULL, 0, SD_TIMEOUT, SD_MAX_RETRIES); - if (sreq->sr_result == 0) + res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr, + SD_TIMEOUT, SD_MAX_RETRIES); + if (res == 0) break; } - res = sreq->sr_result; - if (res) { - printk(KERN_WARNING "FAILED\n status = %x, message = %02x, " + if (res) { printk(KERN_WARNING "FAILED\n status = %x, message = %02x, " "host = %d, driver = %02x\n ", status_byte(res), msg_byte(res), host_byte(res), driver_byte(res)); if (driver_byte(res) & DRIVER_SENSE) - scsi_print_req_sense("sd", sreq); + scsi_print_sense_hdr("sd", &sshdr); } - scsi_release_request(sreq); return res; } @@ -957,22 +948,19 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt) scsi_io_completion(SCpnt, good_bytes, block_sectors << 9); } -static int media_not_present(struct scsi_disk *sdkp, struct scsi_request *srp) +static int media_not_present(struct scsi_disk *sdkp, + struct scsi_sense_hdr *sshdr) { - struct scsi_sense_hdr sshdr; - if (!srp->sr_result) - return 0; - if (!(driver_byte(srp->sr_result) & DRIVER_SENSE)) + if (!scsi_sense_valid(sshdr)) return 0; /* not invoked for commands that could return deferred errors */ - if (scsi_request_normalize_sense(srp, &sshdr)) { - if (sshdr.sense_key != NOT_READY && - sshdr.sense_key != UNIT_ATTENTION) - return 0; - if (sshdr.asc != 0x3A) /* medium not present */ - return 0; - } + if (sshdr->sense_key != NOT_READY && + sshdr->sense_key != UNIT_ATTENTION) + return 0; + if (sshdr->asc != 0x3A) /* medium not present */ + return 0; + set_media_not_present(sdkp); return 1; } @@ -981,8 +969,8 @@ static int media_not_present(struct scsi_disk *sdkp, struct scsi_request *srp) * spinup disk - called only in sd_revalidate_disk() */ static void -sd_spinup_disk(struct scsi_disk *sdkp, char *diskname, - struct scsi_request *SRpnt, unsigned char *buffer) { +sd_spinup_disk(struct scsi_disk *sdkp, char *diskname) +{ unsigned char cmd[10]; unsigned long spintime_expire = 0; int retries, spintime; @@ -1001,18 +989,13 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname, cmd[0] = TEST_UNIT_READY; memset((void *) &cmd[1], 0, 9); - SRpnt->sr_cmd_len = 0; - memset(SRpnt->sr_sense_buffer, 0, - SCSI_SENSE_BUFFERSIZE); - SRpnt->sr_data_direction = DMA_NONE; + the_result = scsi_execute_req(sdkp->device, cmd, + DMA_NONE, NULL, 0, + &sshdr, SD_TIMEOUT, + SD_MAX_RETRIES); - scsi_wait_req (SRpnt, (void *) cmd, (void *) buffer, - 0/*512*/, SD_TIMEOUT, SD_MAX_RETRIES); - - the_result = SRpnt->sr_result; if (the_result) - sense_valid = scsi_request_normalize_sense( - SRpnt, &sshdr); + sense_valid = scsi_sense_valid(&sshdr); retries++; } while (retries < 3 && (!scsi_status_is_good(the_result) || @@ -1024,7 +1007,7 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname, * any media in it, don't bother with any of the rest of * this crap. */ - if (media_not_present(sdkp, SRpnt)) + if (media_not_present(sdkp, &sshdr)) return; if ((driver_byte(the_result) & DRIVER_SENSE) == 0) { @@ -1063,14 +1046,9 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname, cmd[1] = 1; /* Return immediately */ memset((void *) &cmd[2], 0, 8); cmd[4] = 1; /* Start spin cycle */ - SRpnt->sr_cmd_len = 0; - memset(SRpnt->sr_sense_buffer, 0, - SCSI_SENSE_BUFFERSIZE); - - SRpnt->sr_data_direction = DMA_NONE; - scsi_wait_req(SRpnt, (void *)cmd, - (void *) buffer, 0/*512*/, - SD_TIMEOUT, SD_MAX_RETRIES); + scsi_execute_req(sdkp->device, cmd, DMA_NONE, + NULL, 0, &sshdr, + SD_TIMEOUT, SD_MAX_RETRIES); spintime_expire = jiffies + 100 * HZ; spintime = 1; } @@ -1098,7 +1076,7 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname, if(!spintime) { printk(KERN_NOTICE "%s: Unit Not Ready, " "sense:\n", diskname); - scsi_print_req_sense("", SRpnt); + scsi_print_sense_hdr("", &sshdr); } break; } @@ -1118,14 +1096,15 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname, */ static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname, - struct scsi_request *SRpnt, unsigned char *buffer) { + unsigned char *buffer) +{ unsigned char cmd[16]; - struct scsi_device *sdp = sdkp->device; int the_result, retries; int sector_size = 0; int longrc = 0; struct scsi_sense_hdr sshdr; int sense_valid = 0; + struct scsi_device *sdp = sdkp->device; repeat: retries = 3; @@ -1142,20 +1121,15 @@ repeat: memset((void *) buffer, 0, 8); } - SRpnt->sr_cmd_len = 0; - memset(SRpnt->sr_sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); - SRpnt->sr_data_direction = DMA_FROM_DEVICE; - - scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer, - longrc ? 12 : 8, SD_TIMEOUT, SD_MAX_RETRIES); + the_result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE, + buffer, longrc ? 12 : 8, &sshdr, + SD_TIMEOUT, SD_MAX_RETRIES); - if (media_not_present(sdkp, SRpnt)) + if (media_not_present(sdkp, &sshdr)) return; - the_result = SRpnt->sr_result; if (the_result) - sense_valid = scsi_request_normalize_sense(SRpnt, - &sshdr); + sense_valid = scsi_sense_valid(&sshdr); retries--; } while (the_result && retries); @@ -1170,7 +1144,7 @@ repeat: driver_byte(the_result)); if (driver_byte(the_result) & DRIVER_SENSE) - scsi_print_req_sense("sd", SRpnt); + scsi_print_sense_hdr("sd", &sshdr); else printk("%s : sense not available. \n", diskname); @@ -1310,11 +1284,13 @@ got_data: /* called with buffer of length 512 */ static inline int -sd_do_mode_sense(struct scsi_request *SRpnt, int dbd, int modepage, - unsigned char *buffer, int len, struct scsi_mode_data *data) +sd_do_mode_sense(struct scsi_device *sdp, int dbd, int modepage, + unsigned char *buffer, int len, struct scsi_mode_data *data, + struct scsi_sense_hdr *sshdr) { - return __scsi_mode_sense(SRpnt, dbd, modepage, buffer, len, - SD_TIMEOUT, SD_MAX_RETRIES, data); + return scsi_mode_sense(sdp, dbd, modepage, buffer, len, + SD_TIMEOUT, SD_MAX_RETRIES, data, + sshdr); } /* @@ -1323,25 +1299,27 @@ sd_do_mode_sense(struct scsi_request *SRpnt, int dbd, int modepage, */ static void sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname, - struct scsi_request *SRpnt, unsigned char *buffer) { + unsigned char *buffer) +{ int res; + struct scsi_device *sdp = sdkp->device; struct scsi_mode_data data; set_disk_ro(sdkp->disk, 0); - if (sdkp->device->skip_ms_page_3f) { + if (sdp->skip_ms_page_3f) { printk(KERN_NOTICE "%s: assuming Write Enabled\n", diskname); return; } - if (sdkp->device->use_192_bytes_for_3f) { - res = sd_do_mode_sense(SRpnt, 0, 0x3F, buffer, 192, &data); + if (sdp->use_192_bytes_for_3f) { + res = sd_do_mode_sense(sdp, 0, 0x3F, buffer, 192, &data, NULL); } else { /* * First attempt: ask for all pages (0x3F), but only 4 bytes. * We have to start carefully: some devices hang if we ask * for more than is available. */ - res = sd_do_mode_sense(SRpnt, 0, 0x3F, buffer, 4, &data); + res = sd_do_mode_sense(sdp, 0, 0x3F, buffer, 4, &data, NULL); /* * Second attempt: ask for page 0 When only page 0 is @@ -1350,14 +1328,14 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname, * CDB. */ if (!scsi_status_is_good(res)) - res = sd_do_mode_sense(SRpnt, 0, 0, buffer, 4, &data); + res = sd_do_mode_sense(sdp, 0, 0, buffer, 4, &data, NULL); /* * Third attempt: ask 255 bytes, as we did earlier. */ if (!scsi_status_is_good(res)) - res = sd_do_mode_sense(SRpnt, 0, 0x3F, buffer, 255, - &data); + res = sd_do_mode_sense(sdp, 0, 0x3F, buffer, 255, + &data, NULL); } if (!scsi_status_is_good(res)) { @@ -1379,19 +1357,20 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname, */ static void sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, - struct scsi_request *SRpnt, unsigned char *buffer) + unsigned char *buffer) { int len = 0, res; + struct scsi_device *sdp = sdkp->device; int dbd; int modepage; struct scsi_mode_data data; struct scsi_sense_hdr sshdr; - if (sdkp->device->skip_ms_page_8) + if (sdp->skip_ms_page_8) goto defaults; - if (sdkp->device->type == TYPE_RBC) { + if (sdp->type == TYPE_RBC) { modepage = 6; dbd = 8; } else { @@ -1400,7 +1379,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, } /* cautiously ask */ - res = sd_do_mode_sense(SRpnt, dbd, modepage, buffer, 4, &data); + res = sd_do_mode_sense(sdp, dbd, modepage, buffer, 4, &data, &sshdr); if (!scsi_status_is_good(res)) goto bad_sense; @@ -1421,7 +1400,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, len += data.header_length + data.block_descriptor_length; /* Get the data */ - res = sd_do_mode_sense(SRpnt, dbd, modepage, buffer, len, &data); + res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr); if (scsi_status_is_good(res)) { const char *types[] = { @@ -1453,7 +1432,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, } bad_sense: - if (scsi_request_normalize_sense(SRpnt, &sshdr) && + if (scsi_sense_valid(&sshdr) && sshdr.sense_key == ILLEGAL_REQUEST && sshdr.asc == 0x24 && sshdr.ascq == 0x0) printk(KERN_NOTICE "%s: cache data unavailable\n", @@ -1478,7 +1457,6 @@ static int sd_revalidate_disk(struct gendisk *disk) { struct scsi_disk *sdkp = scsi_disk(disk); struct scsi_device *sdp = sdkp->device; - struct scsi_request *sreq; unsigned char *buffer; SCSI_LOG_HLQUEUE(3, printk("sd_revalidate_disk: disk=%s\n", disk->disk_name)); @@ -1490,18 +1468,11 @@ static int sd_revalidate_disk(struct gendisk *disk) if (!scsi_device_online(sdp)) goto out; - sreq = scsi_allocate_request(sdp, GFP_KERNEL); - if (!sreq) { - printk(KERN_WARNING "(sd_revalidate_disk:) Request allocation " - "failure.\n"); - goto out; - } - buffer = kmalloc(512, GFP_KERNEL | __GFP_DMA); if (!buffer) { printk(KERN_WARNING "(sd_revalidate_disk:) Memory allocation " "failure.\n"); - goto out_release_request; + goto out; } /* defaults, until the device tells us otherwise */ @@ -1512,25 +1483,23 @@ static int sd_revalidate_disk(struct gendisk *disk) sdkp->WCE = 0; sdkp->RCD = 0; - sd_spinup_disk(sdkp, disk->disk_name, sreq, buffer); + sd_spinup_disk(sdkp, disk->disk_name); /* * Without media there is no reason to ask; moreover, some devices * react badly if we do. */ if (sdkp->media_present) { - sd_read_capacity(sdkp, disk->disk_name, sreq, buffer); + sd_read_capacity(sdkp, disk->disk_name, buffer); if (sdp->removable) sd_read_write_protect_flag(sdkp, disk->disk_name, - sreq, buffer); - sd_read_cache_type(sdkp, disk->disk_name, sreq, buffer); + buffer); + sd_read_cache_type(sdkp, disk->disk_name, buffer); } set_capacity(disk, sdkp->capacity); kfree(buffer); - out_release_request: - scsi_release_request(sreq); out: return 0; } diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 616c3f3e62fc..b1b69d738d08 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -2970,23 +2970,22 @@ static void * dev_seq_start(struct seq_file *s, loff_t *pos) { struct sg_proc_deviter * it = kmalloc(sizeof(*it), GFP_KERNEL); + s->private = it; if (! it) return NULL; + if (NULL == sg_dev_arr) - goto err1; + return NULL; it->index = *pos; it->max = sg_last_dev(); if (it->index >= it->max) - goto err1; + return NULL; return it; -err1: - kfree(it); - return NULL; } static void * dev_seq_next(struct seq_file *s, void *v, loff_t *pos) { - struct sg_proc_deviter * it = (struct sg_proc_deviter *) v; + struct sg_proc_deviter * it = s->private; *pos = ++it->index; return (it->index < it->max) ? it : NULL; @@ -2994,7 +2993,7 @@ static void * dev_seq_next(struct seq_file *s, void *v, loff_t *pos) static void dev_seq_stop(struct seq_file *s, void *v) { - kfree (v); + kfree(s->private); } static int sg_proc_open_dev(struct inode *inode, struct file *file) diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index f63d8c6c2a33..ce63fc8312dc 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -50,10 +50,10 @@ #include <scsi/scsi_dbg.h> #include <scsi/scsi_device.h> #include <scsi/scsi_driver.h> +#include <scsi/scsi_cmnd.h> #include <scsi/scsi_eh.h> #include <scsi/scsi_host.h> #include <scsi/scsi_ioctl.h> /* For the door lock/unlock commands */ -#include <scsi/scsi_request.h> #include "scsi_logging.h" #include "sr.h" @@ -642,39 +642,27 @@ static void get_sectorsize(struct scsi_cd *cd) unsigned char *buffer; int the_result, retries = 3; int sector_size; - struct scsi_request *SRpnt = NULL; request_queue_t *queue; buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); if (!buffer) goto Enomem; - SRpnt = scsi_allocate_request(cd->device, GFP_KERNEL); - if (!SRpnt) - goto Enomem; do { cmd[0] = READ_CAPACITY; memset((void *) &cmd[1], 0, 9); - /* Mark as really busy */ - SRpnt->sr_request->rq_status = RQ_SCSI_BUSY; - SRpnt->sr_cmd_len = 0; - memset(buffer, 0, 8); /* Do the command and wait.. */ - SRpnt->sr_data_direction = DMA_FROM_DEVICE; - scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer, - 8, SR_TIMEOUT, MAX_RETRIES); + the_result = scsi_execute_req(cd->device, cmd, DMA_FROM_DEVICE, + buffer, 8, NULL, SR_TIMEOUT, + MAX_RETRIES); - the_result = SRpnt->sr_result; retries--; } while (the_result && retries); - scsi_release_request(SRpnt); - SRpnt = NULL; - if (the_result) { cd->capacity = 0x1fffff; sector_size = 2048; /* A guess, just in case */ @@ -730,8 +718,6 @@ out: Enomem: cd->capacity = 0x1fffff; cd->device->sector_size = 2048; /* A guess, just in case */ - if (SRpnt) - scsi_release_request(SRpnt); goto out; } @@ -739,8 +725,8 @@ static void get_capabilities(struct scsi_cd *cd) { unsigned char *buffer; struct scsi_mode_data data; - struct scsi_request *SRpnt; unsigned char cmd[MAX_COMMAND_SIZE]; + struct scsi_sense_hdr sshdr; unsigned int the_result; int retries, rc, n; @@ -756,19 +742,11 @@ static void get_capabilities(struct scsi_cd *cd) "" }; - /* allocate a request for the TEST_UNIT_READY */ - SRpnt = scsi_allocate_request(cd->device, GFP_KERNEL); - if (!SRpnt) { - printk(KERN_WARNING "(get_capabilities:) Request allocation " - "failure.\n"); - return; - } /* allocate transfer buffer */ buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); if (!buffer) { printk(KERN_ERR "sr: out of memory.\n"); - scsi_release_request(SRpnt); return; } @@ -780,24 +758,19 @@ static void get_capabilities(struct scsi_cd *cd) memset((void *)cmd, 0, MAX_COMMAND_SIZE); cmd[0] = TEST_UNIT_READY; - SRpnt->sr_cmd_len = 0; - SRpnt->sr_sense_buffer[0] = 0; - SRpnt->sr_sense_buffer[2] = 0; - SRpnt->sr_data_direction = DMA_NONE; - - scsi_wait_req (SRpnt, (void *) cmd, buffer, - 0, SR_TIMEOUT, MAX_RETRIES); + the_result = scsi_execute_req (cd->device, cmd, DMA_NONE, NULL, + 0, &sshdr, SR_TIMEOUT, + MAX_RETRIES); - the_result = SRpnt->sr_result; retries++; } while (retries < 5 && (!scsi_status_is_good(the_result) || - ((driver_byte(the_result) & DRIVER_SENSE) && - SRpnt->sr_sense_buffer[2] == UNIT_ATTENTION))); + (scsi_sense_valid(&sshdr) && + sshdr.sense_key == UNIT_ATTENTION))); /* ask for mode page 0x2a */ rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, 128, - SR_TIMEOUT, 3, &data); + SR_TIMEOUT, 3, &data, NULL); if (!scsi_status_is_good(rc)) { /* failed, drive doesn't have capabilities mode page */ @@ -805,7 +778,6 @@ static void get_capabilities(struct scsi_cd *cd) cd->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R | CDC_DVD | CDC_DVD_RAM | CDC_SELECT_DISC | CDC_SELECT_SPEED); - scsi_release_request(SRpnt); kfree(buffer); printk("%s: scsi-1 drive\n", cd->cdi.name); return; @@ -865,7 +837,6 @@ static void get_capabilities(struct scsi_cd *cd) cd->device->writeable = 1; } - scsi_release_request(SRpnt); kfree(buffer); } diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c index 82d68fdb1548..6e45ac3c43c5 100644 --- a/drivers/scsi/sr_ioctl.c +++ b/drivers/scsi/sr_ioctl.c @@ -17,7 +17,7 @@ #include <scsi/scsi_eh.h> #include <scsi/scsi_host.h> #include <scsi/scsi_ioctl.h> -#include <scsi/scsi_request.h> +#include <scsi/scsi_cmnd.h> #include "sr.h" @@ -84,41 +84,37 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc) { - struct scsi_request *SRpnt; struct scsi_device *SDev; - struct request *req; + struct scsi_sense_hdr sshdr; int result, err = 0, retries = 0; + struct request_sense *sense = cgc->sense; SDev = cd->device; - SRpnt = scsi_allocate_request(SDev, GFP_KERNEL); - if (!SRpnt) { - printk(KERN_ERR "Unable to allocate SCSI request in sr_do_ioctl"); - err = -ENOMEM; - goto out; - } - SRpnt->sr_data_direction = cgc->data_direction; + + if (!sense) { + sense = kmalloc(sizeof(*sense), GFP_KERNEL); + if (!sense) { + err = -ENOMEM; + goto out; + } + } retry: if (!scsi_block_when_processing_errors(SDev)) { err = -ENODEV; - goto out_free; + goto out; } - scsi_wait_req(SRpnt, cgc->cmd, cgc->buffer, cgc->buflen, - cgc->timeout, IOCTL_RETRIES); - - req = SRpnt->sr_request; - if (SRpnt->sr_buffer && req->buffer && SRpnt->sr_buffer != req->buffer) { - memcpy(req->buffer, SRpnt->sr_buffer, SRpnt->sr_bufflen); - kfree(SRpnt->sr_buffer); - SRpnt->sr_buffer = req->buffer; - } + memset(sense, 0, sizeof(*sense)); + result = scsi_execute(SDev, cgc->cmd, cgc->data_direction, + cgc->buffer, cgc->buflen, (char *)sense, + cgc->timeout, IOCTL_RETRIES, 0); - result = SRpnt->sr_result; + scsi_normalize_sense((char *)sense, sizeof(*sense), &sshdr); /* Minimal error checking. Ignore cases we know about, and report the rest. */ if (driver_byte(result) != 0) { - switch (SRpnt->sr_sense_buffer[2] & 0xf) { + switch (sshdr.sense_key) { case UNIT_ATTENTION: SDev->changed = 1; if (!cgc->quiet) @@ -128,8 +124,8 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc) err = -ENOMEDIUM; break; case NOT_READY: /* This happens if there is no disc in drive */ - if (SRpnt->sr_sense_buffer[12] == 0x04 && - SRpnt->sr_sense_buffer[13] == 0x01) { + if (sshdr.asc == 0x04 && + sshdr.ascq == 0x01) { /* sense: Logical unit is in process of becoming ready */ if (!cgc->quiet) printk(KERN_INFO "%s: CDROM not ready yet.\n", cd->cdi.name); @@ -146,37 +142,33 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc) if (!cgc->quiet) printk(KERN_INFO "%s: CDROM not ready. Make sure there is a disc in the drive.\n", cd->cdi.name); #ifdef DEBUG - scsi_print_req_sense("sr", SRpnt); + scsi_print_sense_hdr("sr", &sshdr); #endif err = -ENOMEDIUM; break; case ILLEGAL_REQUEST: err = -EIO; - if (SRpnt->sr_sense_buffer[12] == 0x20 && - SRpnt->sr_sense_buffer[13] == 0x00) + if (sshdr.asc == 0x20 && + sshdr.ascq == 0x00) /* sense: Invalid command operation code */ err = -EDRIVE_CANT_DO_THIS; #ifdef DEBUG __scsi_print_command(cgc->cmd); - scsi_print_req_sense("sr", SRpnt); + scsi_print_sense_hdr("sr", &sshdr); #endif break; default: printk(KERN_ERR "%s: CDROM (ioctl) error, command: ", cd->cdi.name); __scsi_print_command(cgc->cmd); - scsi_print_req_sense("sr", SRpnt); + scsi_print_sense_hdr("sr", &sshdr); err = -EIO; } } - if (cgc->sense) - memcpy(cgc->sense, SRpnt->sr_sense_buffer, sizeof(*cgc->sense)); - /* Wake up a process waiting for device */ - out_free: - scsi_release_request(SRpnt); - SRpnt = NULL; out: + if (!cgc->sense) + kfree(sense); cgc->stat = err; return err; } diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 5325cf0ab197..a93308ae9736 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -4241,12 +4241,10 @@ static int __init init_st(void) do_create_driverfs_files(); return 0; } - if (st_sysfs_class) - class_destroy(st_sysfs_class); unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0), - ST_MAX_TAPE_ENTRIES); } + class_destroy(st_sysfs_class); printk(KERN_ERR "Unable to get major %d for SCSI tapes\n", SCSI_TAPE_MAJOR); return 1; @@ -4254,13 +4252,11 @@ static int __init init_st(void) static void __exit exit_st(void) { - if (st_sysfs_class) - class_destroy(st_sysfs_class); - st_sysfs_class = NULL; do_remove_driverfs_files(); scsi_unregister_driver(&st_template.gendrv); unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0), ST_MAX_TAPE_ENTRIES); + class_destroy(st_sysfs_class); kfree(scsi_tapes); printk(KERN_INFO "st: Unloaded.\n"); } diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 97034d3937fd..d5797618a3b9 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -211,7 +211,7 @@ comment "Non-8250 serial port support" config SERIAL_AMBA_PL010 tristate "ARM AMBA PL010 serial port support" - depends on ARM_AMBA + depends on ARM_AMBA && (BROKEN || !ARCH_VERSATILE) select SERIAL_CORE help This selects the ARM(R) AMBA(R) PrimeCell PL010 UART. If you have @@ -819,7 +819,7 @@ config SERIAL_M32R_SIO_CONSOLE config SERIAL_M32R_PLDSIO bool "M32R SIO I/F on a PLD" - depends on SERIAL_M32R_SIO=y + depends on SERIAL_M32R_SIO=y && (PLAT_OPSPUT || PALT_USRV || PLAT_M32700UT) default n help Say Y here if you want to use the M32R serial controller 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 @@ #define TX_NUM_FIFO 4 #define TX_BUF_SIZE 32 +#define SCC_WAIT_CLOSING 100 + struct uart_cpm_port { struct uart_port port; - u16 rx_nrfifos; + u16 rx_nrfifos; u16 rx_fifosize; - u16 tx_nrfifos; + u16 tx_nrfifos; u16 tx_fifosize; - smc_t *smcp; + smc_t *smcp; smc_uart_t *smcup; scc_t *sccp; scc_uart_t *sccup; @@ -67,6 +69,8 @@ struct uart_cpm_port { int bits; /* Keep track of 'odd' SMC2 wirings */ int is_portb; + /* wait on close if needed */ + int wait_closing; }; 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 @@ * * Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2) * Pantelis Antoniou (panto@intracom.gr) (CPM1) - * + * * Copyright (C) 2004 Freescale Semiconductor, Inc. * (C) 2004 Intracom, S.A. + * (C) 2005 MontaVista Software, Inc. by Vitaly Bordug <vbordug@ru.mvista.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -70,8 +71,22 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo); /**************************************************************/ +static inline unsigned long cpu2cpm_addr(void *addr) +{ + if ((unsigned long)addr >= CPM_ADDR) + return (unsigned long)addr; + return virt_to_bus(addr); +} + +static inline void *cpm2cpu_addr(unsigned long addr) +{ + if (addr >= CPM_ADDR) + return (void *)addr; + return bus_to_virt(addr); +} + /* - * Check, if transmit buffers are processed + * Check, if transmit buffers are processed */ static unsigned int cpm_uart_tx_empty(struct uart_port *port) { @@ -143,15 +158,18 @@ static void cpm_uart_start_tx(struct uart_port *port, unsigned int tty_start) } if (cpm_uart_tx_pump(port) != 0) { - if (IS_SMC(pinfo)) + if (IS_SMC(pinfo)) { smcp->smc_smcm |= SMCM_TX; - else + smcp->smc_smcmr |= SMCMR_TEN; + } else { sccp->scc_sccm |= UART_SCCM_TX; + pinfo->sccp->scc_gsmrl |= SCC_GSMRL_ENT; + } } } /* - * Stop receiver + * Stop receiver */ static void cpm_uart_stop_rx(struct uart_port *port) { @@ -176,7 +194,7 @@ static void cpm_uart_enable_ms(struct uart_port *port) } /* - * Generate a break. + * Generate a break. */ static void cpm_uart_break_ctl(struct uart_port *port, int break_state) { @@ -231,7 +249,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs) /* get number of characters, and check spce in flip-buffer */ i = bdp->cbd_datlen; - /* If we have not enough room in tty flip buffer, then we try + /* If we have not enough room in tty flip buffer, then we try * later, which will be the next rx-interrupt or a timeout */ 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) } /* get pointer */ - cp = (unsigned char *)bus_to_virt(bdp->cbd_bufaddr); + cp = cpm2cpu_addr(bdp->cbd_bufaddr); /* loop through the buffer */ while (i-- > 0) { @@ -265,13 +283,14 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs) } /* End while (i--) */ /* This BD is ready to be used again. Clear status. get next */ - bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV); + bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV | BD_SC_ID); bdp->cbd_sc |= BD_SC_EMPTY; if (bdp->cbd_sc & BD_SC_WRAP) bdp = pinfo->rx_bd_base; else bdp++; + } /* End for (;;) */ /* Write back buffer pointer */ @@ -336,22 +355,22 @@ static irqreturn_t cpm_uart_int(int irq, void *data, struct pt_regs *regs) if (IS_SMC(pinfo)) { events = smcp->smc_smce; + smcp->smc_smce = events; if (events & SMCM_BRKE) uart_handle_break(port); if (events & SMCM_RX) cpm_uart_int_rx(port, regs); if (events & SMCM_TX) cpm_uart_int_tx(port, regs); - smcp->smc_smce = events; } else { events = sccp->scc_scce; + sccp->scc_scce = events; if (events & UART_SCCM_BRKE) uart_handle_break(port); if (events & UART_SCCM_RX) cpm_uart_int_rx(port, regs); if (events & UART_SCCM_TX) cpm_uart_int_tx(port, regs); - sccp->scc_scce = events; } return (events) ? IRQ_HANDLED : IRQ_NONE; } @@ -360,6 +379,7 @@ static int cpm_uart_startup(struct uart_port *port) { int retval; struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; + int line = pinfo - cpm_uart_ports; pr_debug("CPM uart[%d]:startup\n", port->line); @@ -376,9 +396,19 @@ static int cpm_uart_startup(struct uart_port *port) pinfo->sccp->scc_sccm |= UART_SCCM_RX; } + if (!(pinfo->flags & FLAG_CONSOLE)) + cpm_line_cr_cmd(line,CPM_CR_INIT_TRX); return 0; } +inline void cpm_uart_wait_until_send(struct uart_cpm_port *pinfo) +{ + unsigned long target_jiffies = jiffies + pinfo->wait_closing; + + while (!time_after(jiffies, target_jiffies)) + schedule(); +} + /* * Shutdown the uart */ @@ -394,6 +424,12 @@ static void cpm_uart_shutdown(struct uart_port *port) /* If the port is not the console, disable Rx and Tx. */ if (!(pinfo->flags & FLAG_CONSOLE)) { + /* Wait for all the BDs marked sent */ + while(!cpm_uart_tx_empty(port)) + schedule_timeout(2); + if(pinfo->wait_closing) + cpm_uart_wait_until_send(pinfo); + /* Stop uarts */ if (IS_SMC(pinfo)) { volatile smc_t *smcp = pinfo->smcp; @@ -502,7 +538,7 @@ static void cpm_uart_set_termios(struct uart_port *port, */ if ((termios->c_cflag & CREAD) == 0) port->read_status_mask &= ~BD_SC_EMPTY; - + spin_lock_irqsave(&port->lock, flags); /* 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) /* Pick next descriptor and fill from buffer */ bdp = pinfo->tx_cur; - p = bus_to_virt(bdp->cbd_bufaddr); + p = cpm2cpu_addr(bdp->cbd_bufaddr); + *p++ = xmit->buf[xmit->tail]; bdp->cbd_datlen = 1; bdp->cbd_sc |= BD_SC_READY; @@ -595,7 +632,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) { count = 0; - p = bus_to_virt(bdp->cbd_bufaddr); + p = cpm2cpu_addr(bdp->cbd_bufaddr); while (count < pinfo->tx_fifosize) { *p++ = xmit->buf[xmit->tail]; xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); @@ -606,6 +643,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) } bdp->cbd_datlen = count; bdp->cbd_sc |= BD_SC_READY; + __asm__("eieio"); /* Get next BD. */ if (bdp->cbd_sc & BD_SC_WRAP) bdp = pinfo->tx_bd_base; @@ -643,12 +681,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo) mem_addr = pinfo->mem_addr; bdp = pinfo->rx_cur = pinfo->rx_bd_base; for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) { - bdp->cbd_bufaddr = virt_to_bus(mem_addr); + bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT; mem_addr += pinfo->rx_fifosize; } - - bdp->cbd_bufaddr = virt_to_bus(mem_addr); + + bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT; /* Set the physical address of the host memory @@ -658,12 +696,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo) mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize); bdp = pinfo->tx_cur = pinfo->tx_bd_base; for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) { - bdp->cbd_bufaddr = virt_to_bus(mem_addr); + bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); bdp->cbd_sc = BD_SC_INTRPT; mem_addr += pinfo->tx_fifosize; } - - bdp->cbd_bufaddr = virt_to_bus(mem_addr); + + bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT; } @@ -763,6 +801,8 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo) /* Using idle charater time requires some additional tuning. */ up->smc_mrblr = pinfo->rx_fifosize; up->smc_maxidl = pinfo->rx_fifosize; + up->smc_brklen = 0; + up->smc_brkec = 0; up->smc_brkcr = 1; cpm_line_cr_cmd(line, CPM_CR_INIT_TRX); @@ -796,7 +836,7 @@ static int cpm_uart_request_port(struct uart_port *port) /* * Setup any port IO, connect any baud rate generators, * etc. This is expected to be handled by board - * dependant code + * dependant code */ if (pinfo->set_lineif) pinfo->set_lineif(pinfo); @@ -815,6 +855,10 @@ static int cpm_uart_request_port(struct uart_port *port) return ret; cpm_uart_initbd(pinfo); + if (IS_SMC(pinfo)) + cpm_uart_init_smc(pinfo); + else + cpm_uart_init_scc(pinfo); return 0; } @@ -869,7 +913,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { .flags = FLAG_SMC, .tx_nrfifos = TX_NUM_FIFO, .tx_fifosize = TX_BUF_SIZE, - .rx_nrfifos = RX_NUM_FIFO, + .rx_nrfifos = RX_NUM_FIFO, .rx_fifosize = RX_BUF_SIZE, .set_lineif = smc1_lineif, }, @@ -883,7 +927,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { .flags = FLAG_SMC, .tx_nrfifos = TX_NUM_FIFO, .tx_fifosize = TX_BUF_SIZE, - .rx_nrfifos = RX_NUM_FIFO, + .rx_nrfifos = RX_NUM_FIFO, .rx_fifosize = RX_BUF_SIZE, .set_lineif = smc2_lineif, #ifdef CONFIG_SERIAL_CPM_ALT_SMC2 @@ -899,9 +943,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { }, .tx_nrfifos = TX_NUM_FIFO, .tx_fifosize = TX_BUF_SIZE, - .rx_nrfifos = RX_NUM_FIFO, + .rx_nrfifos = RX_NUM_FIFO, .rx_fifosize = RX_BUF_SIZE, .set_lineif = scc1_lineif, + .wait_closing = SCC_WAIT_CLOSING, }, [UART_SCC2] = { .port = { @@ -912,9 +957,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { }, .tx_nrfifos = TX_NUM_FIFO, .tx_fifosize = TX_BUF_SIZE, - .rx_nrfifos = RX_NUM_FIFO, + .rx_nrfifos = RX_NUM_FIFO, .rx_fifosize = RX_BUF_SIZE, .set_lineif = scc2_lineif, + .wait_closing = SCC_WAIT_CLOSING, }, [UART_SCC3] = { .port = { @@ -925,9 +971,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { }, .tx_nrfifos = TX_NUM_FIFO, .tx_fifosize = TX_BUF_SIZE, - .rx_nrfifos = RX_NUM_FIFO, + .rx_nrfifos = RX_NUM_FIFO, .rx_fifosize = RX_BUF_SIZE, .set_lineif = scc3_lineif, + .wait_closing = SCC_WAIT_CLOSING, }, [UART_SCC4] = { .port = { @@ -938,9 +985,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { }, .tx_nrfifos = TX_NUM_FIFO, .tx_fifosize = TX_BUF_SIZE, - .rx_nrfifos = RX_NUM_FIFO, + .rx_nrfifos = RX_NUM_FIFO, .rx_fifosize = RX_BUF_SIZE, .set_lineif = scc4_lineif, + .wait_closing = SCC_WAIT_CLOSING, }, }; @@ -983,11 +1031,8 @@ static void cpm_uart_console_write(struct console *co, const char *s, * If the buffer address is in the CPM DPRAM, don't * convert it. */ - if ((uint) (bdp->cbd_bufaddr) > (uint) CPM_ADDR) - cp = (unsigned char *) (bdp->cbd_bufaddr); - else - cp = bus_to_virt(bdp->cbd_bufaddr); - + cp = cpm2cpu_addr(bdp->cbd_bufaddr); + *cp = *s; bdp->cbd_datlen = 1; @@ -1003,10 +1048,7 @@ static void cpm_uart_console_write(struct console *co, const char *s, while ((bdp->cbd_sc & BD_SC_READY) != 0) ; - if ((uint) (bdp->cbd_bufaddr) > (uint) CPM_ADDR) - cp = (unsigned char *) (bdp->cbd_bufaddr); - else - cp = bus_to_virt(bdp->cbd_bufaddr); + cp = cpm2cpu_addr(bdp->cbd_bufaddr); *cp = 13; bdp->cbd_datlen = 1; @@ -1045,7 +1087,7 @@ static int __init cpm_uart_console_setup(struct console *co, char *options) port = (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]]; pinfo = (struct uart_cpm_port *)port; - + pinfo->flags |= FLAG_CONSOLE; if (options) { @@ -1062,7 +1104,7 @@ static int __init cpm_uart_console_setup(struct console *co, char *options) /* * Setup any port IO, connect any baud rate generators, * etc. This is expected to be handled by board - * dependant code + * dependant code */ if (pinfo->set_lineif) pinfo->set_lineif(pinfo); @@ -1092,14 +1134,14 @@ static int __init cpm_uart_console_setup(struct console *co, char *options) return 0; } -extern struct uart_driver cpm_reg; +static struct uart_driver cpm_reg; static struct console cpm_scc_uart_console = { - .name "ttyCPM", - .write cpm_uart_console_write, - .device uart_console_device, - .setup cpm_uart_console_setup, - .flags CON_PRINTBUFFER, - .index -1, + .name = "ttyCPM", + .write = cpm_uart_console_write, + .device = uart_console_device, + .setup = cpm_uart_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, .data = &cpm_reg, }; 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 @@ * * Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2) * Pantelis Antoniou (panto@intracom.gr) (CPM1) - * + * * Copyright (C) 2004 Freescale Semiconductor, Inc. * (C) 2004 Intracom, S.A. * @@ -82,6 +82,17 @@ void cpm_line_cr_cmd(int line, int cmd) void smc1_lineif(struct uart_cpm_port *pinfo) { volatile cpm8xx_t *cp = cpmp; + + (void)cp; /* fix warning */ +#if defined (CONFIG_MPC885ADS) + /* Enable SMC1 transceivers */ + { + cp->cp_pepar |= 0x000000c0; + cp->cp_pedir &= ~0x000000c0; + cp->cp_peso &= ~0x00000040; + cp->cp_peso |= 0x00000080; + } +#elif defined (CONFIG_MPC86XADS) unsigned int iobits = 0x000000c0; if (!pinfo->is_portb) { @@ -93,41 +104,33 @@ void smc1_lineif(struct uart_cpm_port *pinfo) ((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits; ((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits; } - -#ifdef CONFIG_MPC885ADS - /* Enable SMC1 transceivers */ - { - volatile uint __iomem *bcsr1 = ioremap(BCSR1, 4); - uint tmp; - - tmp = in_be32(bcsr1); - tmp &= ~BCSR1_RS232EN_1; - out_be32(bcsr1, tmp); - iounmap(bcsr1); - } #endif - pinfo->brg = 1; } void smc2_lineif(struct uart_cpm_port *pinfo) { -#ifdef CONFIG_MPC885ADS volatile cpm8xx_t *cp = cpmp; - volatile uint __iomem *bcsr1; - uint tmp; + (void)cp; /* fix warning */ +#if defined (CONFIG_MPC885ADS) cp->cp_pepar |= 0x00000c00; cp->cp_pedir &= ~0x00000c00; cp->cp_peso &= ~0x00000400; cp->cp_peso |= 0x00000800; +#elif defined (CONFIG_MPC86XADS) + unsigned int iobits = 0x00000c00; + + if (!pinfo->is_portb) { + cp->cp_pbpar |= iobits; + cp->cp_pbdir &= ~iobits; + cp->cp_pbodr &= ~iobits; + } else { + ((immap_t *)IMAP_ADDR)->im_ioport.iop_papar |= iobits; + ((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits; + ((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits; + } - /* Enable SMC2 transceivers */ - bcsr1 = ioremap(BCSR1, 4); - tmp = in_be32(bcsr1); - tmp &= ~BCSR1_RS232EN_2; - out_be32(bcsr1, tmp); - iounmap(bcsr1); #endif pinfo->brg = 2; @@ -158,7 +161,7 @@ void scc4_lineif(struct uart_cpm_port *pinfo) } /* - * Allocate DP-Ram and memory buffers. We need to allocate a transmit and + * Allocate DP-Ram and memory buffers. We need to allocate a transmit and * receive buffer descriptors from dual port ram, and a character * buffer area from host mem. If we are allocating for the console we need * to do it from bootmem @@ -185,6 +188,8 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) + L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize); if (is_con) { + /* was hostalloc but changed cause it blows away the */ + /* large tlb mapping when pinning the kernel area */ mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8)); dma_addr = 0; } else diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c index 0301feacbde4..9b50560b9d16 100644 --- a/drivers/serial/m32r_sio.c +++ b/drivers/serial/m32r_sio.c @@ -1123,7 +1123,7 @@ static int __init m32r_sio_console_setup(struct console *co, char *options) return uart_set_options(port, co, baud, parity, bits, flow); } -extern struct uart_driver m32r_sio_reg; +static struct uart_driver m32r_sio_reg; static struct console m32r_sio_console = { .name = "ttyS", .write = m32r_sio_console_write, diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c index 840815fde49b..12d1f14e78ce 100644 --- a/drivers/serial/sn_console.c +++ b/drivers/serial/sn_console.c @@ -1093,6 +1093,7 @@ int __init sn_serial_console_early_setup(void) return -1; sal_console_port.sc_ops = &poll_ops; + spin_lock_init(&sal_console_port.sc_port.lock); early_sn_setup(); /* Find SAL entry points */ register_console(&sal_console_early); 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) p.qh->period, le32_to_cpup (&p.qh->hw_info2) /* uframe masks */ - & 0xffff, + & (QH_CMASK | QH_SMASK), p.qh); size -= temp; 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) struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv; /* S-mask in a QH means it's an interrupt urb */ - if ((qh->hw_info2 & __constant_cpu_to_le32 (0x00ff)) != 0) { + if ((qh->hw_info2 & __constant_cpu_to_le32 (QH_SMASK)) != 0) { /* ... update hc-wide periodic stats (for usbfs) */ ehci_to_hcd(ehci)->self.bandwidth_int_reqs--; @@ -428,7 +428,8 @@ halt: /* should be rare for periodic transfers, * except maybe high bandwidth ... */ - if (qh->period) { + if ((__constant_cpu_to_le32 (QH_SMASK) + & qh->hw_info2) != 0) { intr_deschedule (ehci, qh); (void) qh_schedule (ehci, qh); } 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) dev_dbg (&qh->dev->dev, "link qh%d-%04x/%p start %d [%d/%d us]\n", - period, le32_to_cpup (&qh->hw_info2) & 0xffff, + period, le32_to_cpup (&qh->hw_info2) & (QH_CMASK | QH_SMASK), qh, qh->start, qh->usecs, qh->c_usecs); /* high bandwidth, or otherwise every microframe */ @@ -385,7 +385,8 @@ static void qh_unlink_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) dev_dbg (&qh->dev->dev, "unlink qh%d-%04x/%p start %d [%d/%d us]\n", - qh->period, le32_to_cpup (&qh->hw_info2) & 0xffff, + qh->period, + le32_to_cpup (&qh->hw_info2) & (QH_CMASK | QH_SMASK), qh, qh->start, qh->usecs, qh->c_usecs); /* qh->qh_next still "live" to HC */ @@ -411,7 +412,7 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh) * active high speed queues may need bigger delays... */ if (list_empty (&qh->qtd_list) - || (__constant_cpu_to_le32 (0x0ff << 8) + || (__constant_cpu_to_le32 (QH_CMASK) & qh->hw_info2) != 0) wait = 2; else @@ -533,7 +534,7 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh) /* reuse the previous schedule slots, if we can */ if (frame < qh->period) { - uframe = ffs (le32_to_cpup (&qh->hw_info2) & 0x00ff); + uframe = ffs (le32_to_cpup (&qh->hw_info2) & QH_SMASK); status = check_intr_schedule (ehci, frame, --uframe, qh, &c_mask); } else { @@ -569,10 +570,10 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh) qh->start = frame; /* reset S-frame and (maybe) C-frame masks */ - qh->hw_info2 &= __constant_cpu_to_le32 (~0xffff); + qh->hw_info2 &= __constant_cpu_to_le32(~(QH_CMASK | QH_SMASK)); qh->hw_info2 |= qh->period ? cpu_to_le32 (1 << uframe) - : __constant_cpu_to_le32 (0xff); + : __constant_cpu_to_le32 (QH_SMASK); qh->hw_info2 |= c_mask; } else 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 { __le32 hw_info1; /* see EHCI 3.6.2 */ #define QH_HEAD 0x00008000 __le32 hw_info2; /* see EHCI 3.6.2 */ +#define QH_SMASK 0x000000ff +#define QH_CMASK 0x0000ff00 +#define QH_HUBADDR 0x007f0000 +#define QH_HUBPORT 0x3f800000 +#define QH_MULT 0xc0000000 __le32 hw_current; /* qtd list - see EHCI 3.6.4 */ /* 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) struct isp116x_ep *ep; struct urb *urb; struct ptd *ptd; - u16 toggle = 0, dir = PTD_DIR_SETUP, len; + u16 len; for (ep = isp116x->atl_active; ep; ep = ep->active) { + u16 toggle = 0, dir = PTD_DIR_SETUP; + BUG_ON(list_empty(&ep->hep->urb_list)); urb = container_of(ep->hep->urb_list.next, struct urb, urb_list); diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c index 02412e31a46b..3b266af3048a 100644 --- a/drivers/usb/input/wacom.c +++ b/drivers/usb/input/wacom.c @@ -342,9 +342,6 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) goto exit; } - x = le16_to_cpu(*(__le16 *) &data[2]); - y = le16_to_cpu(*(__le16 *) &data[4]); - input_regs(dev, regs); if (data[1] & 0x10) { /* in prox */ @@ -373,15 +370,17 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) } } - if (data[1] & 0x80) { + if (data[1] & 0x90) { + x = le16_to_cpu(*(__le16 *) &data[2]); + y = le16_to_cpu(*(__le16 *) &data[4]); input_report_abs(dev, ABS_X, x); input_report_abs(dev, ABS_Y, y); - } - if (wacom->tool[0] != BTN_TOOL_MOUSE) { - input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6])); - input_report_key(dev, BTN_TOUCH, data[1] & 0x01); - input_report_key(dev, BTN_STYLUS, data[1] & 0x02); - input_report_key(dev, BTN_STYLUS2, data[1] & 0x04); + if (wacom->tool[0] != BTN_TOOL_MOUSE) { + input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6])); + input_report_key(dev, BTN_TOUCH, data[1] & 0x01); + input_report_key(dev, BTN_STYLUS, data[1] & 0x02); + input_report_key(dev, BTN_STYLUS2, data[1] & 0x04); + } } input_report_key(dev, wacom->tool[0], data[1] & 0x10); @@ -568,7 +567,7 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs) /* Cintiq doesn't send data when RDY bit isn't set */ if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40)) - return; + goto exit; if (wacom->features->type >= INTUOS3) { input_report_abs(dev, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1)); 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 help If you say Y here, a component which captures the USB traffic between peripheral-specific drivers and HC drivers will be built. - The USB_MON is similar in spirit and may be compatible with Dave - Harding's USBMon. + For more information, see <file:Documentation/usb/usbmon.txt>. - This is somewhat experimental at this time, but it should be safe, - as long as you aren't using modular USB and try to remove this - module. + This is somewhat experimental at this time, but it should be safe. + + 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 @@ usbmon-objs := mon_main.o mon_stat.o mon_text.o +# This does not use CONFIG_USB_MON because we want this to use a tristate. obj-$(CONFIG_USB) += usbmon.o diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c index aa9d00808e4e..508a21028db4 100644 --- a/drivers/usb/mon/mon_main.c +++ b/drivers/usb/mon/mon_main.c @@ -2,6 +2,8 @@ * The USB Monitor, inspired by Dave Harding's USBMon. * * mon_main.c: Main file, module initiation and exit, registrations, etc. + * + * Copyright (C) 2005 Pete Zaitcev (zaitcev@redhat.com) */ #include <linux/kernel.h> @@ -311,7 +313,7 @@ static int __init mon_init(void) mondir = debugfs_create_dir("usbmon", NULL); if (IS_ERR(mondir)) { - printk(KERN_NOTICE TAG ": debugs is not available\n"); + printk(KERN_NOTICE TAG ": debugfs is not available\n"); return -ENODEV; } if (mondir == NULL) { diff --git a/drivers/usb/mon/usb_mon.h b/drivers/usb/mon/usb_mon.h index ed35c18a5c44..9b06784d2c48 100644 --- a/drivers/usb/mon/usb_mon.h +++ b/drivers/usb/mon/usb_mon.h @@ -1,5 +1,7 @@ /* * The USB Monitor, inspired by Dave Harding's USBMon. + * + * Copyright (C) 2005 Pete Zaitcev (zaitcev@redhat.com) */ #ifndef __USB_MON_H diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c index 576f3b852fce..4528a00c45b0 100644 --- a/drivers/usb/net/usbnet.c +++ b/drivers/usb/net/usbnet.c @@ -1922,7 +1922,7 @@ static int genelink_rx_fixup (struct usbnet *dev, struct sk_buff *skb) // copy the packet data to the new skb memcpy(skb_put(gl_skb, size), packet->packet_data, size); - skb_return (dev, skb); + skb_return (dev, gl_skb); } // advance to the next packet diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c index 29cd801eb958..e32a80b39182 100644 --- a/drivers/usb/net/zd1201.c +++ b/drivers/usb/net/zd1201.c @@ -346,8 +346,7 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs) if (datalen<14) goto resubmit; if ((seq & IEEE802_11_SCTL_FRAG) == 0) { - frag = kmalloc(sizeof(struct zd1201_frag*), - GFP_ATOMIC); + frag = kmalloc(sizeof(*frag), GFP_ATOMIC); if (!frag) goto resubmit; skb = dev_alloc_skb(IEEE802_11_DATA_LEN +14+2); diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index cbff98337aa6..5fe182d6e4ab 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -6,7 +6,7 @@ menu "Console display driver support" config VGA_CONSOLE bool "VGA text console" if EMBEDDED || !X86 - depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC32 && !SPARC64 && !M68K && !PARISC + depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC32 && !SPARC64 && !M68K && !PARISC && !ARCH_VERSATILE default y help Saying Y here will allow you to use Linux in text mode through a diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index d2e19f6dd72c..4ff853fbe0be 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -628,7 +628,7 @@ fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var) int fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) { - int err; + int err, flags = info->flags; if (var->activate & FB_ACTIVATE_INV_MODE) { struct fb_videomode mode1, mode2; @@ -682,7 +682,7 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) !list_empty(&info->modelist)) err = fb_add_videomode(&mode, &info->modelist); - if (!err && info->flags & FBINFO_MISC_USEREVENT) { + if (!err && (flags & FBINFO_MISC_USEREVENT)) { struct fb_event event; info->flags &= ~FBINFO_MISC_USEREVENT; 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) fb_info->var.xoffset); } +static ssize_t show_name(struct class_device *class_device, char *buf) +{ + struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device); + + return snprintf(buf, PAGE_SIZE, "%s\n", fb_info->fix.id); +} + static struct class_device_attribute class_device_attrs[] = { __ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp), __ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank), @@ -424,6 +431,7 @@ static struct class_device_attribute class_device_attrs[] = { __ATTR(modes, S_IRUGO|S_IWUSR, show_modes, store_modes), __ATTR(pan, S_IRUGO|S_IWUSR, show_pan, store_pan), __ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual), + __ATTR(name, S_IRUGO, show_name, NULL), }; int fb_init_class_device(struct fb_info *fb_info) diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c index 298bc9cd99e7..a112a1786855 100644 --- a/drivers/video/intelfb/intelfbdrv.c +++ b/drivers/video/intelfb/intelfbdrv.c @@ -583,23 +583,6 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) return -ENODEV; } - /* Map the fb and MMIO regions */ - dinfo->aperture.virtual = (u8 __iomem *)ioremap_nocache - (dinfo->aperture.physical, dinfo->aperture.size); - if (!dinfo->aperture.virtual) { - ERR_MSG("Cannot remap FB region.\n"); - cleanup(dinfo); - return -ENODEV; - } - dinfo->mmio_base = - (u8 __iomem *)ioremap_nocache(dinfo->mmio_base_phys, - INTEL_REG_SIZE); - if (!dinfo->mmio_base) { - ERR_MSG("Cannot remap MMIO region.\n"); - cleanup(dinfo); - return -ENODEV; - } - /* Get the chipset info. */ dinfo->pci_chipset = pdev->device; @@ -630,9 +613,15 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) dinfo->accel = 0; } + if (MB(voffset) < stolen_size) + offset = (stolen_size >> 12); + else + offset = ROUND_UP_TO_PAGE(MB(voffset))/GTT_PAGE_SIZE; + /* Framebuffer parameters - Use all the stolen memory if >= vram */ - if (ROUND_UP_TO_PAGE(stolen_size) >= MB(vram)) { + if (ROUND_UP_TO_PAGE(stolen_size) >= ((offset << 12) + MB(vram))) { dinfo->fb.size = ROUND_UP_TO_PAGE(stolen_size); + dinfo->fb.offset = 0; dinfo->fbmem_gart = 0; } else { dinfo->fb.size = MB(vram); @@ -663,11 +652,6 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) return -ENODEV; } - if (MB(voffset) < stolen_size) - offset = (stolen_size >> 12); - else - offset = ROUND_UP_TO_PAGE(MB(voffset))/GTT_PAGE_SIZE; - /* set the mem offsets - set them after the already used pages */ if (dinfo->accel) { dinfo->ring.offset = offset + gtt_info.current_memory; @@ -682,6 +666,26 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) + (dinfo->cursor.size >> 12); } + /* Map the fb and MMIO regions */ + /* ioremap only up to the end of used aperture */ + dinfo->aperture.virtual = (u8 __iomem *)ioremap_nocache + (dinfo->aperture.physical, (dinfo->fb.offset << 12) + + dinfo->fb.size); + if (!dinfo->aperture.virtual) { + ERR_MSG("Cannot remap FB region.\n"); + cleanup(dinfo); + return -ENODEV; + } + + dinfo->mmio_base = + (u8 __iomem *)ioremap_nocache(dinfo->mmio_base_phys, + INTEL_REG_SIZE); + if (!dinfo->mmio_base) { + ERR_MSG("Cannot remap MMIO region.\n"); + cleanup(dinfo); + return -ENODEV; + } + /* Allocate memories (which aren't stolen) */ if (dinfo->accel) { if (!(dinfo->gtt_ring_mem = 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[] = { /* 480x300 @ 72 Hz, 48.0 kHz hsync */ NULL, 72, 480, 300, 33386, 40, 24, 11, 19, 80, 3, 0, FB_VMODE_DOUBLE + }, { + /* 1920x1200 @ 60 Hz, 74.5 Khz hsync */ + NULL, 60, 1920, 1200, 5177, 128, 336, 1, 38, 208, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED }, }; 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) fb_videomode_to_var(&nvidiafb_default_var, &modedb); nvidiafb_default_var.bits_per_pixel = 8; + } else if (par->fpWidth && par->fpHeight) { + char buf[16]; + + memset(buf, 0, 16); + snprintf(buf, 15, "%dx%d", par->fpWidth, par->fpHeight); + fb_find_mode(&nvidiafb_default_var, info, buf, specs->modedb, + specs->modedb_len, &modedb, 8); } 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) DPRINTK("reg_lccr2 0x%08x\n", (unsigned int) fbi->reg_lccr2); DPRINTK("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3); + /* enable LCD controller clock */ + pxa_set_cken(CKEN16_LCD, 1); + /* Sequence from 11.7.10 */ LCCR3 = fbi->reg_lccr3; LCCR2 = fbi->reg_lccr2; @@ -750,6 +753,9 @@ static void pxafb_disable_controller(struct pxafb_info *fbi) schedule_timeout(20 * HZ / 1000); remove_wait_queue(&fbi->ctrlr_wait, &wait); + + /* disable LCD controller clock */ + pxa_set_cken(CKEN16_LCD, 0); } /* @@ -1299,8 +1305,6 @@ int __init pxafb_probe(struct device *dev) ret = -ENOMEM; goto failed; } - /* enable LCD controller clock */ - pxa_set_cken(CKEN16_LCD, 1); ret = request_irq(IRQ_LCD, pxafb_handle_irq, SA_INTERRUPT, "LCD", fbi); if (ret) { diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c index c46387024b1d..a78b9bd8f897 100644 --- a/drivers/video/radeonfb.c +++ b/drivers/video/radeonfb.c @@ -80,7 +80,7 @@ #include <video/radeon.h> #include <linux/radeonfb.h> -#define DEBUG 1 +#define DEBUG 0 #if DEBUG #define RTRACE printk 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, * requests for the LCD controller. If we hit this, it means we're * doing nothing but LCD DMA. */ -static unsigned int sa1100fb_display_dma_period(struct fb_var_screeninfo *var) +static inline unsigned int sa1100fb_display_dma_period(struct fb_var_screeninfo *var) { /* * 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 = { static void tridentfb_fillrect(struct fb_info * info, const struct fb_fillrect *fr) { int bpp = info->var.bits_per_pixel; - int col; + int col = 0; switch (bpp) { default: - case 8: col = fr->color; + case 8: col |= fr->color; + col |= col << 8; + col |= col << 16; break; case 16: col = ((u32 *)(info->pseudo_palette))[fr->color]; + break; case 32: col = ((u32 *)(info->pseudo_palette))[fr->color]; break; @@ -882,8 +885,9 @@ static int tridentfb_set_par(struct fb_info *info) write3X4(GraphEngReg, 0x80); //enable GE for text acceleration -// if (info->var.accel_flags & FB_ACCELF_TEXT) -//FIXME acc->init_accel(info->var.xres,bpp); +#ifdef CONFIG_FB_TRIDENT_ACCEL + acc->init_accel(info->var.xres,bpp); +#endif switch (bpp) { case 8: tmp = 0x00; break; @@ -900,7 +904,7 @@ static int tridentfb_set_par(struct fb_info *info) write3X4(DRAMControl, tmp); //both IO,linear enable write3X4(InterfaceSel, read3X4(InterfaceSel) | 0x40); - write3X4(Performance,0x20); + write3X4(Performance,0x92); write3X4(PCIReg,0x07); //MMIO & PCI read and write burst enable /* convert from picoseconds to MHz */ @@ -981,12 +985,14 @@ static int tridentfb_setcolreg(unsigned regno, unsigned red, unsigned green, t_outb(green>>10,0x3C9); t_outb(blue>>10,0x3C9); - } else - if (bpp == 16) /* RGB 565 */ - ((u32*)info->pseudo_palette)[regno] = (red & 0xF800) | - ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11); - else - if (bpp == 32) /* ARGB 8888 */ + } else if (bpp == 16) { /* RGB 565 */ + u32 col; + + col = (red & 0xF800) | ((green & 0xFC00) >> 5) | + ((blue & 0xF800) >> 11); + col |= col << 16; + ((u32 *)(info->pseudo_palette))[regno] = col; + } else if (bpp == 32) /* ARGB 8888 */ ((u32*)info->pseudo_palette)[regno] = ((transp & 0xFF00) <<16) | ((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) * Return 0 - device(s) present, 1 - no devices present. */ if (w1_reset_bus(dev)) { - dev_info(&dev->dev, "No devices present on the wire.\n"); + dev_dbg(&dev->dev, "No devices present on the wire.\n"); break; } |