diff options
Diffstat (limited to 'drivers')
286 files changed, 3467 insertions, 3495 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 7c49e103cf8..e2ce4a9c1c9 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -7,6 +7,7 @@ menu "ACPI (Advanced Configuration and Power Interface) Support" depends on !X86_VISWS depends on !IA64_HP_SIM depends on IA64 || X86 + depends on PM config ACPI bool "ACPI Support" @@ -243,6 +244,17 @@ config ACPI_IBM_DOCK If you are not sure, say N here. +config ACPI_IBM_BAY + bool "Legacy Removable Bay Support" + depends on ACPI_IBM + default y + ---help--- + Allows the ibm_acpi driver to handle removable bays. It will allow + disabling the device in the bay, and also generate notifications when + the bay lever is ejected or inserted. + + If you are not sure, say Y here. + config ACPI_TOSHIBA tristate "Toshiba Laptop Extras" depends on X86 diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index f289fd41e77..3ec110ce00c 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -79,11 +79,17 @@ static int __init blacklist_by_year(void) { int year = dmi_get_year(DMI_BIOS_DATE); /* Doesn't exist? Likely an old system */ - if (year == -1) + if (year == -1) { + printk(KERN_ERR PREFIX "no DMI BIOS year, " + "acpi=force is required to enable ACPI\n" ); return 1; + } /* 0? Likely a buggy new BIOS */ - if (year == 0) + if (year == 0) { + printk(KERN_ERR PREFIX "DMI BIOS year==0, " + "assuming ACPI-capable machine\n" ); return 0; + } if (year < CONFIG_ACPI_BLACKLIST_YEAR) { printk(KERN_ERR PREFIX "BIOS age (%d) fails cutoff (%d), " "acpi=force is required to enable ACPI\n", diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index ab688837379..a802962ff2b 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -100,6 +100,7 @@ static struct acpi_ec { unsigned long global_lock; struct mutex lock; atomic_t query_pending; + atomic_t event_count; atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */ wait_queue_head_t wait; } *ec_ecdt; @@ -131,10 +132,12 @@ static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) outb(data, ec->data_addr); } -static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event) +static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event, + unsigned old_count) { u8 status = acpi_ec_read_status(ec); - + if (old_count == atomic_read(&ec->event_count)) + return 0; if (event == ACPI_EC_EVENT_OBF_1) { if (status & ACPI_EC_FLAG_OBF) return 1; @@ -146,19 +149,19 @@ static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event) return 0; } -static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event) +static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, unsigned count) { if (acpi_ec_mode == EC_POLL) { unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); while (time_before(jiffies, delay)) { - if (acpi_ec_check_status(ec, event)) + if (acpi_ec_check_status(ec, event, 0)) return 0; } } else { if (wait_event_timeout(ec->wait, - acpi_ec_check_status(ec, event), + acpi_ec_check_status(ec, event, count), msecs_to_jiffies(ACPI_EC_DELAY)) || - acpi_ec_check_status(ec, event)) { + acpi_ec_check_status(ec, event, 0)) { return 0; } else { printk(KERN_ERR PREFIX "acpi_ec_wait timeout," @@ -225,21 +228,22 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, u8 * rdata, unsigned rdata_len) { int result = 0; - + unsigned count = atomic_read(&ec->event_count); acpi_ec_write_cmd(ec, command); for (; wdata_len > 0; --wdata_len) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count); if (result) { printk(KERN_ERR PREFIX "write_cmd timeout, command = %d\n", command); goto end; } + count = atomic_read(&ec->event_count); acpi_ec_write_data(ec, *(wdata++)); } if (!rdata_len) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count); if (result) { printk(KERN_ERR PREFIX "finish-write timeout, command = %d\n", command); @@ -250,13 +254,13 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, } for (; rdata_len > 0; --rdata_len) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, count); if (result) { printk(KERN_ERR PREFIX "read timeout, command = %d\n", command); goto end; } - + count = atomic_read(&ec->event_count); *(rdata++) = acpi_ec_read_data(ec); } end: @@ -288,7 +292,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, /* Make sure GPE is enabled before doing transaction */ acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); - status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); + status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0); if (status) { printk(KERN_DEBUG PREFIX "input buffer is not empty, aborting transaction\n"); @@ -369,8 +373,8 @@ int ec_write(u8 addr, u8 val) EXPORT_SYMBOL(ec_write); int ec_transaction(u8 command, - const u8 * wdata, unsigned wdata_len, - u8 * rdata, unsigned rdata_len) + const u8 * wdata, unsigned wdata_len, + u8 * rdata, unsigned rdata_len) { struct acpi_ec *ec; @@ -435,7 +439,7 @@ static u32 acpi_ec_gpe_handler(void *data) acpi_status status = AE_OK; u8 value; struct acpi_ec *ec = (struct acpi_ec *)data; - + atomic_inc(&ec->event_count); if (acpi_ec_mode == EC_INTR) { wake_up(&ec->wait); } @@ -633,6 +637,7 @@ static int acpi_ec_add(struct acpi_device *device) ec->uid = -1; mutex_init(&ec->lock); atomic_set(&ec->query_pending, 0); + atomic_set(&ec->event_count, 1); if (acpi_ec_mode == EC_INTR) { atomic_set(&ec->leaving_burst, 1); init_waitqueue_head(&ec->wait); @@ -807,6 +812,7 @@ acpi_fake_ecdt_callback(acpi_handle handle, acpi_status status; mutex_init(&ec_ecdt->lock); + atomic_set(&ec_ecdt->event_count, 1); if (acpi_ec_mode == EC_INTR) { init_waitqueue_head(&ec_ecdt->wait); } @@ -888,6 +894,7 @@ static int __init acpi_ec_get_real_ecdt(void) return -ENOMEM; mutex_init(&ec_ecdt->lock); + atomic_set(&ec_ecdt->event_count, 1); if (acpi_ec_mode == EC_INTR) { init_waitqueue_head(&ec_ecdt->wait); } @@ -1016,8 +1023,7 @@ static int __init acpi_ec_set_intr_mode(char *str) acpi_ec_mode = EC_POLL; } acpi_ec_driver.ops.add = acpi_ec_add; - printk(KERN_NOTICE PREFIX "%s mode.\n", - intr ? "interrupt" : "polling"); + printk(KERN_NOTICE PREFIX "%s mode.\n", intr ? "interrupt" : "polling"); return 1; } diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c index d572700197f..cae786ca860 100644 --- a/drivers/acpi/events/evmisc.c +++ b/drivers/acpi/events/evmisc.c @@ -196,11 +196,15 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, notify_info->notify.value = (u16) notify_value; notify_info->notify.handler_obj = handler_obj; - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); acpi_ev_notify_dispatch(notify_info); - acpi_ex_reacquire_interpreter(); + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } if (!handler_obj) { @@ -423,6 +427,8 @@ static acpi_status acpi_ev_remove_global_lock_handler(void) * the global lock appear as a standard mutex on the OS side. * *****************************************************************************/ +static acpi_thread_id acpi_ev_global_lock_thread_id; +static int acpi_ev_global_lock_acquired; acpi_status acpi_ev_acquire_global_lock(u16 timeout) { @@ -435,11 +441,24 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout) * Only one thread can acquire the GL at a time, the global_lock_mutex * enforces this. This interface releases the interpreter if we must wait. */ - status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, timeout); + status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, 0); + if (status == AE_TIME) { + if (acpi_ev_global_lock_thread_id == acpi_os_get_thread_id()) { + acpi_ev_global_lock_acquired++; + return AE_OK; + } + } + + if (ACPI_FAILURE(status)) { + status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, timeout); + } if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } + acpi_ev_global_lock_thread_id = acpi_os_get_thread_id(); + acpi_ev_global_lock_acquired++; + /* * Make sure that a global lock actually exists. If not, just treat * the lock as a standard mutex. @@ -506,6 +525,11 @@ acpi_status acpi_ev_release_global_lock(void) return_ACPI_STATUS(AE_NOT_ACQUIRED); } + acpi_ev_global_lock_acquired--; + if (acpi_ev_global_lock_acquired > 0) { + return AE_OK; + } + if (acpi_gbl_global_lock_present) { /* Allow any thread to release the lock */ @@ -529,7 +553,8 @@ acpi_status acpi_ev_release_global_lock(void) acpi_gbl_global_lock_acquired = FALSE; /* Release the local GL mutex */ - + acpi_ev_global_lock_thread_id = NULL; + acpi_ev_global_lock_acquired = 0; acpi_os_release_mutex(acpi_gbl_global_lock_mutex); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c index e99f0c435a4..96b0e843174 100644 --- a/drivers/acpi/events/evregion.c +++ b/drivers/acpi/events/evregion.c @@ -291,6 +291,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, u32 bit_width, acpi_integer * value) { acpi_status status; + acpi_status status2; acpi_adr_space_handler handler; acpi_adr_space_setup region_setup; union acpi_operand_object *handler_desc; @@ -344,7 +345,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, * setup will potentially execute control methods * (e.g., _REG method for this region) */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); status = region_setup(region_obj, ACPI_REGION_ACTIVATE, handler_desc->address_space.context, @@ -352,7 +353,10 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, /* Re-enter the interpreter */ - acpi_ex_reacquire_interpreter(); + status2 = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } /* Check for failure of the Region Setup */ @@ -405,7 +409,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, * exit the interpreter because the handler *might* block -- we don't * know what it will do, so we can't hold the lock on the intepreter. */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); } /* Call the handler */ @@ -426,7 +430,10 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, * We just returned from a non-default handler, we must re-enter the * interpreter */ - acpi_ex_reacquire_interpreter(); + status2 = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } } return_ACPI_STATUS(status); diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c index 685a103a358..a3379bafa67 100644 --- a/drivers/acpi/events/evxface.c +++ b/drivers/acpi/events/evxface.c @@ -768,9 +768,11 @@ acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle) return (AE_BAD_PARAMETER); } - /* Must lock interpreter to prevent race conditions */ + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + return (status); + } - acpi_ex_enter_interpreter(); status = acpi_ev_acquire_global_lock(timeout); acpi_ex_exit_interpreter(); diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c index 7c38528a7e8..ae97812681a 100644 --- a/drivers/acpi/executer/excreate.c +++ b/drivers/acpi/executer/excreate.c @@ -583,7 +583,10 @@ acpi_ex_create_method(u8 * aml_start, * Get the sync_level. If method is serialized, a mutex will be * created for this method when it is parsed. */ - if (method_flags & AML_METHOD_SERIALIZED) { + if (acpi_gbl_all_methods_serialized) { + obj_desc->method.sync_level = 0; + obj_desc->method.method_flags |= AML_METHOD_SERIALIZED; + } else if (method_flags & AML_METHOD_SERIALIZED) { /* * ACPI 1.0: sync_level = 0 * ACPI 2.0: sync_level = sync_level in method declaration diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c index 9460baff303..b2edf620ba8 100644 --- a/drivers/acpi/executer/exsystem.c +++ b/drivers/acpi/executer/exsystem.c @@ -66,6 +66,7 @@ ACPI_MODULE_NAME("exsystem") acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) { acpi_status status; + acpi_status status2; ACPI_FUNCTION_TRACE(ex_system_wait_semaphore); @@ -78,7 +79,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) /* We must wait, so unlock the interpreter */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); status = acpi_os_wait_semaphore(semaphore, 1, timeout); @@ -88,7 +89,13 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) /* Reacquire the interpreter */ - acpi_ex_reacquire_interpreter(); + status2 = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status2)) { + + /* Report fatal error, could not acquire interpreter */ + + return_ACPI_STATUS(status2); + } } return_ACPI_STATUS(status); @@ -112,6 +119,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) { acpi_status status; + acpi_status status2; ACPI_FUNCTION_TRACE(ex_system_wait_mutex); @@ -124,7 +132,7 @@ acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) /* We must wait, so unlock the interpreter */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); status = acpi_os_acquire_mutex(mutex, timeout); @@ -134,7 +142,13 @@ acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) /* Reacquire the interpreter */ - acpi_ex_reacquire_interpreter(); + status2 = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status2)) { + + /* Report fatal error, could not acquire interpreter */ + + return_ACPI_STATUS(status2); + } } return_ACPI_STATUS(status); @@ -195,18 +209,20 @@ acpi_status acpi_ex_system_do_stall(u32 how_long) acpi_status acpi_ex_system_do_suspend(acpi_integer how_long) { + acpi_status status; + ACPI_FUNCTION_ENTRY(); /* Since this thread will sleep, we must release the interpreter */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); acpi_os_sleep(how_long); /* And now we must get the interpreter again */ - acpi_ex_reacquire_interpreter(); - return (AE_OK); + status = acpi_ex_enter_interpreter(); + return (status); } /******************************************************************************* diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c index 6b0aeccbb69..aea461f3a48 100644 --- a/drivers/acpi/executer/exutils.c +++ b/drivers/acpi/executer/exutils.c @@ -76,15 +76,14 @@ static u32 acpi_ex_digits_needed(acpi_integer value, u32 base); * * PARAMETERS: None * - * RETURN: None + * RETURN: Status * - * DESCRIPTION: Enter the interpreter execution region. Failure to enter - * the interpreter region is a fatal system error. Used in - * conjunction with exit_interpreter. + * DESCRIPTION: Enter the interpreter execution region. Failure to enter + * the interpreter region is a fatal system error * ******************************************************************************/ -void acpi_ex_enter_interpreter(void) +acpi_status acpi_ex_enter_interpreter(void) { acpi_status status; @@ -92,42 +91,10 @@ void acpi_ex_enter_interpreter(void) status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not acquire AML Interpreter mutex")); + ACPI_ERROR((AE_INFO, "Could not acquire interpreter mutex")); } - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_reacquire_interpreter - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Reacquire the interpreter execution region from within the - * interpreter code. Failure to enter the interpreter region is a - * fatal system error. Used in conjuction with - * relinquish_interpreter - * - ******************************************************************************/ - -void acpi_ex_reacquire_interpreter(void) -{ - ACPI_FUNCTION_TRACE(ex_reacquire_interpreter); - - /* - * If the global serialized flag is set, do not release the interpreter, - * since it was not actually released by acpi_ex_relinquish_interpreter. - * This forces the interpreter to be single threaded. - */ - if (!acpi_gbl_all_methods_serialized) { - acpi_ex_enter_interpreter(); - } - - return_VOID; + return_ACPI_STATUS(status); } /******************************************************************************* @@ -138,9 +105,17 @@ void acpi_ex_reacquire_interpreter(void) * * RETURN: None * - * DESCRIPTION: Exit the interpreter execution region. This is the top level - * routine used to exit the interpreter when all processing has - * been completed. + * DESCRIPTION: Exit the interpreter execution region + * + * Cases where the interpreter is unlocked: + * 1) Completion of the execution of a control method + * 2) Method blocked on a Sleep() AML opcode + * 3) Method blocked on an Acquire() AML opcode + * 4) Method blocked on a Wait() AML opcode + * 5) Method blocked to acquire the global lock + * 6) Method blocked to execute a serialized control method that is + * already executing + * 7) About to invoke a user-installed opregion handler * ******************************************************************************/ @@ -152,46 +127,7 @@ void acpi_ex_exit_interpreter(void) status = acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not release AML Interpreter mutex")); - } - - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_relinquish_interpreter - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Exit the interpreter execution region, from within the - * interpreter - before attempting an operation that will possibly - * block the running thread. - * - * Cases where the interpreter is unlocked internally - * 1) Method to be blocked on a Sleep() AML opcode - * 2) Method to be blocked on an Acquire() AML opcode - * 3) Method to be blocked on a Wait() AML opcode - * 4) Method to be blocked to acquire the global lock - * 5) Method to be blocked waiting to execute a serialized control method - * that is currently executing - * 6) About to invoke a user-installed opregion handler - * - ******************************************************************************/ - -void acpi_ex_relinquish_interpreter(void) -{ - ACPI_FUNCTION_TRACE(ex_relinquish_interpreter); - - /* - * If the global serialized flag is set, do not release the interpreter. - * This forces the interpreter to be single threaded. - */ - if (!acpi_gbl_all_methods_serialized) { - acpi_ex_exit_interpreter(); + ACPI_ERROR((AE_INFO, "Could not release interpreter mutex")); } return_VOID; @@ -205,8 +141,8 @@ void acpi_ex_relinquish_interpreter(void) * * RETURN: none * - * DESCRIPTION: Truncate an ACPI Integer to 32 bits if the execution mode is - * 32-bit, as determined by the revision of the DSDT. + * DESCRIPTION: Truncate a number to 32-bits if the currently executing method + * belongs to a 32-bit ACPI table. * ******************************************************************************/ diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c index 8fa93125fd4..c84b1faba28 100644 --- a/drivers/acpi/hardware/hwsleep.c +++ b/drivers/acpi/hardware/hwsleep.c @@ -300,6 +300,11 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) /* * 2) Enable all wakeup GPEs */ + status = acpi_hw_disable_all_gpes(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + acpi_gbl_system_awake_and_running = FALSE; status = acpi_hw_enable_all_wakeup_gpes(); diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 4cc534e36e8..dc1096608f4 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -86,6 +86,7 @@ #include <linux/proc_fs.h> #include <linux/backlight.h> +#include <linux/fb.h> #include <asm/uaccess.h> #include <linux/dmi.h> @@ -157,6 +158,7 @@ IBM_HANDLE(dock, root, "\\_SB.GDCK", /* X30, X31, X40 */ "\\_SB.PCI.ISA.SLCE", /* 570 */ ); /* A21e,G4x,R30,R31,R32,R40,R40e,R50e */ #endif +#ifdef CONFIG_ACPI_IBM_BAY IBM_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST", /* 570 */ "\\_SB.PCI0.IDE0.IDES.IDSM", /* 600e/x, 770e, 770x */ "\\_SB.PCI0.SATA.SCND.MSTR", /* T60, X60, Z60 */ @@ -174,6 +176,7 @@ IBM_HANDLE(bay2, root, "\\_SB.PCI0.IDE0.PRIM.SLAV", /* A3x, R32 */ IBM_HANDLE(bay2_ej, bay2, "_EJ3", /* 600e/x, 770e, A3x */ "_EJ0", /* 770x */ ); /* all others */ +#endif /* CONFIG_ACPI_IBM_BAY */ /* don't list other alternatives as we install a notify handler on the 570 */ IBM_HANDLE(pci, root, "\\_SB.PCI"); /* 570 */ @@ -1044,6 +1047,7 @@ static int light_write(char *buf) return 0; } +#if defined(CONFIG_ACPI_IBM_DOCK) || defined(CONFIG_ACPI_IBM_BAY) static int _sta(acpi_handle handle) { int status; @@ -1053,6 +1057,7 @@ static int _sta(acpi_handle handle) return status; } +#endif #ifdef CONFIG_ACPI_IBM_DOCK #define dock_docked() (_sta(dock_handle) & 1) @@ -1119,6 +1124,7 @@ static void dock_notify(struct ibm_struct *ibm, u32 event) } #endif +#ifdef CONFIG_ACPI_IBM_BAY static int bay_status_supported; static int bay_status2_supported; static int bay_eject_supported; @@ -1194,6 +1200,7 @@ static void bay_notify(struct ibm_struct *ibm, u32 event) { acpi_bus_generate_event(ibm->device, event, 0); } +#endif /* CONFIG_ACPI_IBM_BAY */ static int cmos_read(char *p) { @@ -1701,7 +1708,10 @@ static int brightness_write(char *buf) static int brightness_update_status(struct backlight_device *bd) { - return brightness_set(bd->props.brightness); + return brightness_set( + (bd->props.fb_blank == FB_BLANK_UNBLANK && + bd->props.power == FB_BLANK_UNBLANK) ? + bd->props.brightness : 0); } static struct backlight_ops ibm_backlight_data = { @@ -1711,6 +1721,12 @@ static struct backlight_ops ibm_backlight_data = { static int brightness_init(void) { + int b; + + b = brightness_get(NULL); + if (b < 0) + return b; + ibm_backlight_device = backlight_device_register("ibm", NULL, NULL, &ibm_backlight_data); if (IS_ERR(ibm_backlight_device)) { @@ -1718,7 +1734,9 @@ static int brightness_init(void) return PTR_ERR(ibm_backlight_device); } - ibm_backlight_device->props.max_brightness = 7; + ibm_backlight_device->props.max_brightness = 7; + ibm_backlight_device->props.brightness = b; + backlight_update_status(ibm_backlight_device); return 0; } @@ -2353,6 +2371,7 @@ static struct ibm_struct ibms[] = { .type = ACPI_SYSTEM_NOTIFY, }, #endif +#ifdef CONFIG_ACPI_IBM_BAY { .name = "bay", .init = bay_init, @@ -2362,6 +2381,7 @@ static struct ibm_struct ibms[] = { .handle = &bay_handle, .type = ACPI_SYSTEM_NOTIFY, }, +#endif /* CONFIG_ACPI_IBM_BAY */ { .name = "cmos", .read = cmos_read, @@ -2487,7 +2507,7 @@ static int __init setup_notify(struct ibm_struct *ibm) ret = acpi_bus_get_device(*ibm->handle, &ibm->device); if (ret < 0) { printk(IBM_ERR "%s device not present\n", ibm->name); - return 0; + return -ENODEV; } acpi_driver_data(ibm->device) = ibm; @@ -2496,8 +2516,13 @@ static int __init setup_notify(struct ibm_struct *ibm) status = acpi_install_notify_handler(*ibm->handle, ibm->type, dispatch_notify, ibm); if (ACPI_FAILURE(status)) { - printk(IBM_ERR "acpi_install_notify_handler(%s) failed: %d\n", - ibm->name, status); + if (status == AE_ALREADY_EXISTS) { + printk(IBM_NOTICE "another device driver is already handling %s events\n", + ibm->name); + } else { + printk(IBM_ERR "acpi_install_notify_handler(%s) failed: %d\n", + ibm->name, status); + } return -ENODEV; } ibm->notify_installed = 1; @@ -2533,6 +2558,8 @@ static int __init register_driver(struct ibm_struct *ibm) return ret; } +static void ibm_exit(struct ibm_struct *ibm); + static int __init ibm_init(struct ibm_struct *ibm) { int ret; @@ -2574,6 +2601,12 @@ static int __init ibm_init(struct ibm_struct *ibm) if (ibm->notify) { ret = setup_notify(ibm); + if (ret == -ENODEV) { + printk(IBM_NOTICE "disabling subdriver %s\n", + ibm->name); + ibm_exit(ibm); + return 0; + } if (ret < 0) return ret; } @@ -2647,7 +2680,9 @@ IBM_PARAM(light); #ifdef CONFIG_ACPI_IBM_DOCK IBM_PARAM(dock); #endif +#ifdef CONFIG_ACPI_IBM_BAY IBM_PARAM(bay); +#endif /* CONFIG_ACPI_IBM_BAY */ IBM_PARAM(cmos); IBM_PARAM(led); IBM_PARAM(beep); @@ -2723,12 +2758,14 @@ static int __init acpi_ibm_init(void) IBM_HANDLE_INIT(dock); #endif IBM_HANDLE_INIT(pci); +#ifdef CONFIG_ACPI_IBM_BAY IBM_HANDLE_INIT(bay); if (bay_handle) IBM_HANDLE_INIT(bay_ej); IBM_HANDLE_INIT(bay2); if (bay2_handle) IBM_HANDLE_INIT(bay2_ej); +#endif /* CONFIG_ACPI_IBM_BAY */ IBM_HANDLE_INIT(beep); IBM_HANDLE_INIT(ecrd); IBM_HANDLE_INIT(ecwr); diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c index aa6370c67ec..26fd0dd6953 100644 --- a/drivers/acpi/namespace/nseval.c +++ b/drivers/acpi/namespace/nseval.c @@ -154,7 +154,11 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info) * Execute the method via the interpreter. The interpreter is locked * here before calling into the AML parser */ - acpi_ex_enter_interpreter(); + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + status = acpi_ps_execute_method(info); acpi_ex_exit_interpreter(); } else { @@ -178,7 +182,10 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info) * resolution, we must lock it because we could access an opregion. * The opregion access code assumes that the interpreter is locked. */ - acpi_ex_enter_interpreter(); + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } /* Function has a strange interface */ diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c index 33db2241044..c4ab615f77f 100644 --- a/drivers/acpi/namespace/nsinit.c +++ b/drivers/acpi/namespace/nsinit.c @@ -214,7 +214,7 @@ acpi_ns_init_one_object(acpi_handle obj_handle, u32 level, void *context, void **return_value) { acpi_object_type type; - acpi_status status = AE_OK; + acpi_status status; struct acpi_init_walk_info *info = (struct acpi_init_walk_info *)context; struct acpi_namespace_node *node = @@ -268,7 +268,10 @@ acpi_ns_init_one_object(acpi_handle obj_handle, /* * Must lock the interpreter before executing AML code */ - acpi_ex_enter_interpreter(); + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + return (status); + } /* * Each of these types can contain executable AML code within the diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c index 7ac6ace5005..8904d0fae6a 100644 --- a/drivers/acpi/namespace/nsxfeval.c +++ b/drivers/acpi/namespace/nsxfeval.c @@ -170,6 +170,7 @@ acpi_evaluate_object(acpi_handle handle, struct acpi_buffer *return_buffer) { acpi_status status; + acpi_status status2; struct acpi_evaluate_info *info; acpi_size buffer_space_needed; u32 i; @@ -328,12 +329,14 @@ acpi_evaluate_object(acpi_handle handle, * Delete the internal return object. NOTE: Interpreter must be * locked to avoid race condition. */ - acpi_ex_enter_interpreter(); + status2 = acpi_ex_enter_interpreter(); + if (ACPI_SUCCESS(status2)) { - /* Remove one reference on the return object (should delete it) */ + /* Remove one reference on the return object (should delete it) */ - acpi_ut_remove_reference(info->return_object); - acpi_ex_exit_interpreter(); + acpi_ut_remove_reference(info->return_object); + acpi_ex_exit_interpreter(); + } } cleanup: diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 1ef338545df..4ffecd17970 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -436,8 +436,6 @@ int acpi_power_transition(struct acpi_device *device, int state) cl = &device->power.states[device->power.state].resources; tl = &device->power.states[state].resources; - device->power.state = ACPI_STATE_UNKNOWN; - if (!cl->count && !tl->count) { result = -ENODEV; goto end; @@ -468,12 +466,15 @@ int acpi_power_transition(struct acpi_device *device, int state) goto end; } - /* We shouldn't change the state till all above operations succeed */ - device->power.state = state; - end: - if (result) + end: + if (result) { + device->power.state = ACPI_STATE_UNKNOWN; printk(KERN_WARNING PREFIX "Transitioning device [%s] to D%d\n", device->pnp.bus_id, state); + } else { + /* We shouldn't change the state till all above operations succeed */ + device->power.state = state; + } return result; } @@ -687,13 +688,6 @@ static int acpi_power_resume(struct acpi_device *device) return result; mutex_lock(&resource->resource_lock); - if ((resource->state == ACPI_POWER_RESOURCE_STATE_ON) && - list_empty(&resource->reference)) { - mutex_unlock(&resource->resource_lock); - result = acpi_power_off_device(device->handle, NULL); - return result; - } - if ((resource->state == ACPI_POWER_RESOURCE_STATE_OFF) && !list_empty(&resource->reference)) { ref = container_of(resource->reference.next, struct acpi_power_reference, node); diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 60773005b8a..cdf78943af4 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -268,6 +268,7 @@ static void acpi_timer_check_state(int state, struct acpi_processor *pr, struct acpi_processor_cx *cx) { struct acpi_processor_power *pwr = &pr->power; + u8 type = local_apic_timer_c2_ok ? ACPI_STATE_C3 : ACPI_STATE_C2; /* * Check, if one of the previous states already marked the lapic @@ -276,7 +277,7 @@ static void acpi_timer_check_state(int state, struct acpi_processor *pr, if (pwr->timer_broadcast_on_state < state) return; - if (cx->type >= ACPI_STATE_C2) + if (cx->type >= type) pr->power.timer_broadcast_on_state = state; } diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c index 1358c06a969..cc48ab05676 100644 --- a/drivers/acpi/resources/rscreate.c +++ b/drivers/acpi/resources/rscreate.c @@ -191,6 +191,9 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer); for (index = 0; index < number_of_elements; index++) { + int source_name_index = 2; + int source_index_index = 3; + /* * Point user_prt past this current structure * @@ -261,10 +264,28 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, } /* + * If BIOS erroneously reversed the _PRT source_name and source_index, + * then reverse them back. + */ + if (ACPI_GET_OBJECT_TYPE (sub_object_list[3]) != ACPI_TYPE_INTEGER) { + if (acpi_gbl_enable_interpreter_slack) { + source_name_index = 3; + source_index_index = 2; + printk(KERN_WARNING "ACPI: Handling Garbled _PRT entry\n"); + } else { + ACPI_ERROR((AE_INFO, + "(PRT[%X].source_index) Need Integer, found %s", + index, + acpi_ut_get_object_type_name(sub_object_list[3]))); + return_ACPI_STATUS(AE_BAD_DATA); + } + } + + /* * 3) Third subobject: Dereference the PRT.source_name * The name may be unresolved (slack mode), so allow a null object */ - obj_desc = sub_object_list[2]; + obj_desc = sub_object_list[source_name_index]; if (obj_desc) { switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { case ACPI_TYPE_LOCAL_REFERENCE: @@ -339,7 +360,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, /* 4) Fourth subobject: Dereference the PRT.source_index */ - obj_desc = sub_object_list[3]; + obj_desc = sub_object_list[source_index_index]; if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { user_prt->source_index = (u32) obj_desc->integer.value; } else { diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 849e2c36180..c3419182c9a 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -42,7 +42,9 @@ static char *mps_inti_flags_trigger[] = { "dfl", "edge", "res", "level" }; static struct acpi_table_desc initial_tables[ACPI_MAX_TABLES] __initdata; -void acpi_table_print_madt_entry(struct acpi_subtable_header * header) +static int acpi_apic_instance __initdata; + +void acpi_table_print_madt_entry(struct acpi_subtable_header *header) { if (!header) return; @@ -183,8 +185,10 @@ acpi_table_parse_entries(char *id, if (!handler) return -EINVAL; - /* Locate the table (if exists). There should only be one. */ - acpi_get_table(id, 0, &table_header); + if (strncmp(id, ACPI_SIG_MADT, 4) == 0) + acpi_get_table(id, acpi_apic_instance, &table_header); + else + acpi_get_table(id, 0, &table_header); if (!table_header) { printk(KERN_WARNING PREFIX "%4.4s not present\n", id); @@ -237,10 +241,15 @@ acpi_table_parse_madt(enum acpi_madt_type id, int __init acpi_table_parse(char *id, acpi_table_handler handler) { struct acpi_table_header *table = NULL; + if (!handler) return -EINVAL; - acpi_get_table(id, 0, &table); + if (strncmp(id, ACPI_SIG_MADT, 4) == 0) + acpi_get_table(id, acpi_apic_instance, &table); + else + acpi_get_table(id, 0, &table); + if (table) { handler(table); return 0; @@ -248,6 +257,31 @@ int __init acpi_table_parse(char *id, acpi_table_handler handler) return 1; } +/* + * The BIOS is supposed to supply a single APIC/MADT, + * but some report two. Provide a knob to use either. + * (don't you wish instance 0 and 1 were not the same?) + */ +static void __init check_multiple_madt(void) +{ + struct acpi_table_header *table = NULL; + + acpi_get_table(ACPI_SIG_MADT, 2, &table); + if (table) { + printk(KERN_WARNING PREFIX + "BIOS bug: multiple APIC/MADT found," + " using %d\n", acpi_apic_instance); + printk(KERN_WARNING PREFIX + "If \"acpi_apic_instance=%d\" works better, " + "notify linux-acpi@vger.kernel.org\n", + acpi_apic_instance ? 0 : 2); + + } else + acpi_apic_instance = 0; + + return; +} + /* * acpi_table_init() * @@ -257,9 +291,22 @@ int __init acpi_table_parse(char *id, acpi_table_handler handler) * result: sdt_entry[] is initialized */ - int __init acpi_table_init(void) { acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0); + check_multiple_madt(); + return 0; +} + +static int __init acpi_parse_apic_instance(char *str) +{ + + acpi_apic_instance = simple_strtoul(str, NULL, 0); + + printk(KERN_NOTICE PREFIX "Shall use APIC/MADT table %d\n", + acpi_apic_instance); + return 0; } + +early_param("acpi_apic_instance", acpi_parse_apic_instance); diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 0771b434feb..00d25b34725 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -102,9 +102,9 @@ struct acpi_video_bus_cap { struct acpi_video_device_attrib { u32 display_index:4; /* A zero-based instance of the Display */ - u32 display_port_attachment:4; /*This field differenates displays type */ + u32 display_port_attachment:4; /*This field differentiates the display type */ u32 display_type:4; /*Describe the specific type in use */ - u32 vendor_specific:4; /*Chipset Vendor Specifi */ + u32 vendor_specific:4; /*Chipset Vendor Specific */ u32 bios_can_detect:1; /*BIOS can detect the device */ u32 depend_on_vga:1; /*Non-VGA output device whose power is related to the VGA device. */ @@ -484,16 +484,16 @@ acpi_video_bus_POST_options(struct acpi_video_bus *video, * 0. The system BIOS should NOT automatically switch(toggle) * the active display output. * 1. The system BIOS should automatically switch (toggle) the - * active display output. No swich event. + * active display output. No switch event. * 2. The _DGS value should be locked. * 3. The system BIOS should not automatically switch (toggle) the * active display output, but instead generate the display switch * event notify code. * lcd_flag : * 0. The system BIOS should automatically control the brightness level - * of the LCD, when the power changes from AC to DC + * of the LCD when the power changes from AC to DC * 1. The system BIOS should NOT automatically control the brightness - * level of the LCD, when the power changes from AC to DC. + * level of the LCD when the power changes from AC to DC. * Return Value: * -1 wrong arg. */ @@ -525,7 +525,7 @@ acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag) * Return Value: * None * - * Find out all required AML method defined under the output + * Find out all required AML methods defined under the output * device. */ @@ -636,7 +636,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) * Return Value: * None * - * Find out all required AML method defined under the video bus device. + * Find out all required AML methods defined under the video bus device. */ static void acpi_video_bus_find_cap(struct acpi_video_bus *video) @@ -681,19 +681,19 @@ static int acpi_video_bus_check(struct acpi_video_bus *video) * to check well known required nodes. */ - /* Does this device able to support video switching ? */ + /* Does this device support video switching? */ if (video->cap._DOS) { video->flags.multihead = 1; status = 0; } - /* Does this device able to retrieve a retrieve a video ROM ? */ + /* Does this device support retrieving a video ROM? */ if (video->cap._ROM) { video->flags.rom = 1; status = 0; } - /* Does this device able to configure which video device to POST ? */ + /* Does this device support configuring which video device to POST? */ if (video->cap._GPD && video->cap._SPD && video->cap._VPO) { video->flags.post = 1; status = 0; @@ -860,7 +860,7 @@ acpi_video_device_write_brightness(struct file *file, if (level > 100) return -EFAULT; - /* validate though the list of available levels */ + /* validate through the list of available levels */ for (i = 0; i < dev->brightness->count; i++) if (level == dev->brightness->levels[i]) { if (ACPI_SUCCESS @@ -1065,10 +1065,10 @@ static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset) printk(KERN_WARNING PREFIX "The motherboard VGA device is not listed as a possible POST device.\n"); printk(KERN_WARNING PREFIX - "This indicate a BIOS bug. Please contact the manufacturer.\n"); + "This indicates a BIOS bug. Please contact the manufacturer.\n"); } printk("%lx\n", options); - seq_printf(seq, "can POST: <intgrated video>"); + seq_printf(seq, "can POST: <integrated video>"); if (options & 2) seq_printf(seq, " <PCI video>"); if (options & 4) @@ -1102,7 +1102,7 @@ static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset) seq_printf(seq, "<not supported>\n"); goto end; } - seq_printf(seq, "device posted is <%s>\n", device_decode[id & 3]); + seq_printf(seq, "device POSTed is <%s>\n", device_decode[id & 3]); end: return 0; @@ -1156,7 +1156,7 @@ acpi_video_bus_write_POST(struct file *file, if (opt > 3) return -EFAULT; - /* just in case an OEM 'forget' the motherboard... */ + /* just in case an OEM 'forgot' the motherboard... */ options |= 1; if (options & (1ul << opt)) { @@ -1527,13 +1527,13 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) /* * Arg: * video : video bus device - * event : Nontify Event + * event : notify event * * Return: * < 0 : error * * 1. Find out the current active output device. - * 2. Identify the next output device to switch + * 2. Identify the next output device to switch to. * 3. call _DSS to do actual switch. */ @@ -1723,12 +1723,12 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data) device = video->device; switch (event) { - case ACPI_VIDEO_NOTIFY_SWITCH: /* User request that a switch occur, + case ACPI_VIDEO_NOTIFY_SWITCH: /* User requested a switch, * most likely via hotkey. */ acpi_bus_generate_event(device, event, 0); break; - case ACPI_VIDEO_NOTIFY_PROBE: /* User plug or remove a video + case ACPI_VIDEO_NOTIFY_PROBE: /* User plugged in or removed a video * connector. */ acpi_video_device_enumerate(video); acpi_video_device_rebind(video); diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index d16b5b0c8b7..7bdbe5a914d 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -564,7 +564,7 @@ config PATA_IXP4XX_CF config PATA_SCC tristate "Toshiba's Cell Reference Set IDE support" - depends on PCI && PPC_IBM_CELL_BLADE + depends on PCI && PPC_CELLEB help This option enables support for the built-in IDE controller on Toshiba Cell Reference Board. diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index dc7b5622592..fd27227771b 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -80,6 +80,7 @@ enum { board_ahci_pi = 1, board_ahci_vt8251 = 2, board_ahci_ign_iferr = 3, + board_ahci_sb600 = 4, /* global controller registers */ HOST_CAP = 0x00, /* host capabilities */ @@ -168,6 +169,7 @@ enum { AHCI_FLAG_NO_NCQ = (1 << 24), AHCI_FLAG_IGN_IRQ_IF_ERR = (1 << 25), /* ignore IRQ_IF_ERR */ AHCI_FLAG_HONOR_PI = (1 << 26), /* honor PORTS_IMPL */ + AHCI_FLAG_IGN_SERR_INTERNAL = (1 << 27), /* ignore SERR_INTERNAL */ }; struct ahci_cmd_hdr { @@ -362,6 +364,18 @@ static const struct ata_port_info ahci_port_info[] = { .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &ahci_ops, }, + /* board_ahci_sb600 */ + { + .sht = &ahci_sht, + .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | + ATA_FLAG_SKIP_D2H_BSY | + AHCI_FLAG_IGN_SERR_INTERNAL, + .pio_mask = 0x1f, /* pio0-4 */ + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ + .port_ops = &ahci_ops, + }, + }; static const struct pci_device_id ahci_pci_tbl[] = { @@ -399,7 +413,7 @@ static const struct pci_device_id ahci_pci_tbl[] = { PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr }, /* ATI */ - { PCI_VDEVICE(ATI, 0x4380), board_ahci }, /* ATI SB600 non-raid */ + { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 non-raid */ { PCI_VDEVICE(ATI, 0x4381), board_ahci }, /* ATI SB600 raid */ /* VIA */ @@ -1067,8 +1081,11 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) if (ap->flags & AHCI_FLAG_IGN_IRQ_IF_ERR) irq_stat &= ~PORT_IRQ_IF_ERR; - if (irq_stat & PORT_IRQ_TF_ERR) + if (irq_stat & PORT_IRQ_TF_ERR) { err_mask |= AC_ERR_DEV; + if (ap->flags & AHCI_FLAG_IGN_SERR_INTERNAL) + serror &= ~SERR_INTERNAL; + } if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) { err_mask |= AC_ERR_HOST_BUS; diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index dc42ba1b46f..b952c584338 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -93,7 +93,7 @@ #include <linux/libata.h> #define DRV_NAME "ata_piix" -#define DRV_VERSION "2.10" +#define DRV_VERSION "2.10ac1" enum { PIIX_IOCFG = 0x54, /* IDE I/O configuration register */ @@ -667,14 +667,9 @@ static int ich_pata_prereset(struct ata_port *ap) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); - if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no])) { - ata_port_printk(ap, KERN_INFO, "port disabled. ignoring.\n"); - ap->eh_context.i.action &= ~ATA_EH_RESET_MASK; - return 0; - } - + if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no])) + return -ENOENT; ich_pata_cbl_detect(ap); - return ata_std_prereset(ap); } diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index d14a48e75f1..03a0acff6cf 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -34,6 +34,13 @@ struct taskfile_array { u8 tfa[REGS_PER_GTF]; /* regs. 0x1f1 - 0x1f7 */ }; +/* + * Helper - belongs in the PCI layer somewhere eventually + */ +static int is_pci_dev(struct device *dev) +{ + return (dev->bus == &pci_bus_type); +} /** * sata_get_dev_handle - finds acpi_handle and PCI device.function @@ -53,6 +60,9 @@ static int sata_get_dev_handle(struct device *dev, acpi_handle *handle, struct pci_dev *pci_dev; acpi_integer addr; + if (!is_pci_dev(dev)) + return -ENODEV; + pci_dev = to_pci_dev(dev); /* NOTE: PCI-specific */ /* Please refer to the ACPI spec for the syntax of _ADR. */ addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn); @@ -84,7 +94,12 @@ static int pata_get_dev_handle(struct device *dev, acpi_handle *handle, acpi_status status; struct acpi_device_info *dinfo = NULL; int ret = -ENODEV; - struct pci_dev *pdev = to_pci_dev(dev); + struct pci_dev *pdev; + + if (!is_pci_dev(dev)) + return -ENODEV; + + pdev = to_pci_dev(dev); bus = pdev->bus->number; devnum = PCI_SLOT(pdev->devfn); @@ -290,7 +305,7 @@ static int do_drive_get_GTF(struct ata_port *ap, int ix, *gtf_address = 0UL; *obj_loc = 0UL; - if (noacpi) + if (libata_noacpi) return 0; if (ata_msg_probe(ap)) @@ -516,7 +531,7 @@ static int do_drive_set_taskfiles(struct ata_port *ap, ata_dev_printk(atadev, KERN_DEBUG, "%s: ENTER: port#: %d\n", __FUNCTION__, ap->port_no); - if (noacpi || !(ap->cbl == ATA_CBL_SATA)) + if (libata_noacpi || !(ap->cbl == ATA_CBL_SATA)) return 0; if (!ata_dev_enabled(atadev) || (ap->flags & ATA_FLAG_DISABLED)) @@ -559,7 +574,14 @@ int ata_acpi_exec_tfs(struct ata_port *ap) unsigned long gtf_address; unsigned long obj_loc; - if (noacpi) + if (libata_noacpi) + return 0; + /* + * TBD - implement PATA support. For now, + * we should not run GTF on PATA devices since some + * PATA require execution of GTM/STM before GTF. + */ + if (!(ap->cbl == ATA_CBL_SATA)) return 0; for (ix = 0; ix < ATA_MAX_DEVICES; ix++) { @@ -614,7 +636,7 @@ int ata_acpi_push_id(struct ata_port *ap, unsigned int ix) struct acpi_object_list input; union acpi_object in_params[1]; - if (noacpi) + if (libata_noacpi) return 0; if (ata_msg_probe(ap)) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index dc362fa01ca..0abd72d0dec 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -93,8 +93,8 @@ static int ata_probe_timeout = ATA_TMOUT_INTERNAL / HZ; module_param(ata_probe_timeout, int, 0444); MODULE_PARM_DESC(ata_probe_timeout, "Set ATA probing timeout (seconds)"); -int noacpi; -module_param(noacpi, int, 0444); +int libata_noacpi = 1; +module_param_named(noacpi, libata_noacpi, int, 0444); MODULE_PARM_DESC(noacpi, "Disables the use of ACPI in suspend/resume when set"); MODULE_AUTHOR("Jeff Garzik"); @@ -826,7 +826,7 @@ static u64 ata_id_n_sectors(const u16 *id) /** * ata_id_to_dma_mode - Identify DMA mode from id block * @dev: device to identify - * @mode: mode to assume if we cannot tell + * @unknown: mode to assume if we cannot tell * * Set up the timing values for the device based upon the identify * reported values for the DMA mode. This function is used by drivers @@ -1784,6 +1784,13 @@ int ata_dev_configure(struct ata_device *dev) dev->max_sectors = ATA_MAX_SECTORS; } + if (ata_device_blacklisted(dev) & ATA_HORKAGE_MAX_SEC_128) + dev->max_sectors = min(ATA_MAX_SECTORS_128, dev->max_sectors); + + /* limit ATAPI DMA to R/W commands only */ + if (ata_device_blacklisted(dev) & ATA_HORKAGE_DMA_RW_ONLY) + dev->horkage |= ATA_HORKAGE_DMA_RW_ONLY; + if (ap->ops->dev_config) ap->ops->dev_config(ap, dev); @@ -3352,6 +3359,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "_NEC DV5800A", NULL, ATA_HORKAGE_NODMA }, { "SAMSUNG CD-ROM SN-124","N001", ATA_HORKAGE_NODMA }, + /* Weird ATAPI devices */ + { "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 | + ATA_HORKAGE_DMA_RW_ONLY }, + /* Devices we expect to fail diagnostics */ /* Devices where NCQ should be avoided */ @@ -3359,6 +3370,15 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "WDC WD740ADFD-00", NULL, ATA_HORKAGE_NONCQ }, /* http://thread.gmane.org/gmane.linux.ide/14907 */ { "FUJITSU MHT2060BH", NULL, ATA_HORKAGE_NONCQ }, + /* NCQ is broken */ + { "Maxtor 6L250S0", "BANC1G10", ATA_HORKAGE_NONCQ }, + /* NCQ hard hangs device under heavier load, needs hard power cycle */ + { "Maxtor 6B250S0", "BANC1B70", ATA_HORKAGE_NONCQ }, + /* Blacklist entries taken from Silicon Image 3124/3132 + Windows driver .inf file - also several Linux problem reports */ + { "HTS541060G9SA00", "MB3OC60D", ATA_HORKAGE_NONCQ, }, + { "HTS541080G9SA00", "MB4OC60D", ATA_HORKAGE_NONCQ, }, + { "HTS541010G9SA00", "MBZOC60D", ATA_HORKAGE_NONCQ, }, /* Devices with NCQ limits */ @@ -3455,7 +3475,8 @@ static void ata_dev_xfermask(struct ata_device *dev) "device is on DMA blacklist, disabling DMA\n"); } - if ((host->flags & ATA_HOST_SIMPLEX) && host->simplex_claimed != ap) { + if ((host->flags & ATA_HOST_SIMPLEX) && + host->simplex_claimed && host->simplex_claimed != ap) { xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); ata_dev_printk(dev, KERN_WARNING, "simplex DMA is claimed by " "other device, disabling DMA\n"); @@ -3669,6 +3690,26 @@ int ata_check_atapi_dma(struct ata_queued_cmd *qc) struct ata_port *ap = qc->ap; int rc = 0; /* Assume ATAPI DMA is OK by default */ + /* some drives can only do ATAPI DMA on read/write */ + if (unlikely(qc->dev->horkage & ATA_HORKAGE_DMA_RW_ONLY)) { + struct scsi_cmnd *cmd = qc->scsicmd; + u8 *scsicmd = cmd->cmnd; + + switch (scsicmd[0]) { + case READ_10: + case WRITE_10: + case READ_12: + case WRITE_12: + case READ_6: + case WRITE_6: + /* atapi dma maybe ok */ + break; + default: + /* turn off atapi dma */ + return 1; + } + } + if (ap->ops->check_atapi_dma) rc = ap->ops->check_atapi_dma(qc); @@ -4712,8 +4753,8 @@ static void fill_result_tf(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - ap->ops->tf_read(ap, &qc->result_tf); qc->result_tf.flags = qc->tf.flags; + ap->ops->tf_read(ap, &qc->result_tf); } /** @@ -5684,18 +5725,22 @@ static void ata_host_release(struct device *gendev, void *res) for (i = 0; i < host->n_ports; i++) { struct ata_port *ap = host->ports[i]; - if (!ap) - continue; - - if (ap->ops->port_stop) + if (ap && ap->ops->port_stop) ap->ops->port_stop(ap); - - scsi_host_put(ap->scsi_host); } if (host->ops->host_stop) host->ops->host_stop(host); + for (i = 0; i < host->n_ports; i++) { + struct ata_port *ap = host->ports[i]; + + if (ap) + scsi_host_put(ap->scsi_host); + + host->ports[i] = NULL; + } + dev_set_drvdata(gendev, NULL); } diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 7349c3dbf77..39f556c0299 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -982,26 +982,27 @@ static int ata_eh_read_log_10h(struct ata_device *dev, * RETURNS: * 0 on success, AC_ERR_* mask on failure */ -static unsigned int atapi_eh_request_sense(struct ata_device *dev, - unsigned char *sense_buf) +static unsigned int atapi_eh_request_sense(struct ata_queued_cmd *qc) { + struct ata_device *dev = qc->dev; + unsigned char *sense_buf = qc->scsicmd->sense_buffer; struct ata_port *ap = dev->ap; struct ata_taskfile tf; u8 cdb[ATAPI_CDB_LEN]; DPRINTK("ATAPI request sense\n"); - ata_tf_init(dev, &tf); - /* FIXME: is this needed? */ memset(sense_buf, 0, SCSI_SENSE_BUFFERSIZE); - /* XXX: why tf_read here? */ - ap->ops->tf_read(ap, &tf); - - /* fill these in, for the case where they are -not- overwritten */ + /* initialize sense_buf with the error register, + * for the case where they are -not- overwritten + */ sense_buf[0] = 0x70; - sense_buf[2] = tf.feature >> 4; + sense_buf[2] = qc->result_tf.feature >> 4; + + /* some devices time out if garbage left in tf */ + ata_tf_init(dev, &tf); memset(cdb, 0, ATAPI_CDB_LEN); cdb[0] = REQUEST_SENSE; @@ -1165,8 +1166,7 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc, case ATA_DEV_ATAPI: if (!(qc->ap->pflags & ATA_PFLAG_FROZEN)) { - tmp = atapi_eh_request_sense(qc->dev, - qc->scsicmd->sense_buffer); + tmp = atapi_eh_request_sense(qc); if (!tmp) { /* ATA_QCFLAG_SENSE_VALID is used to * tell atapi_qc_complete() that sense @@ -1625,8 +1625,14 @@ static int ata_eh_reset(struct ata_port *ap, int classify, rc = prereset(ap); if (rc) { if (rc == -ENOENT) { - ata_port_printk(ap, KERN_DEBUG, "port disabled. ignoring.\n"); + ata_port_printk(ap, KERN_DEBUG, + "port disabled. ignoring.\n"); ap->eh_context.i.action &= ~ATA_EH_RESET_MASK; + + for (i = 0; i < ATA_MAX_DEVICES; i++) + classes[i] = ATA_DEV_NONE; + + rc = 0; } else ata_port_printk(ap, KERN_ERR, "prereset failed (errno=%d)\n", rc); @@ -1737,12 +1743,17 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, { struct ata_eh_context *ehc = &ap->eh_context; struct ata_device *dev; + unsigned int new_mask = 0; unsigned long flags; int i, rc = 0; DPRINTK("ENTER\n"); - for (i = 0; i < ATA_MAX_DEVICES; i++) { + /* For PATA drive side cable detection to work, IDENTIFY must + * be done backwards such that PDIAG- is released by the slave + * device before the master device is identified. + */ + for (i = ATA_MAX_DEVICES - 1; i >= 0; i--) { unsigned int action, readid_flags = 0; dev = &ap->device[i]; @@ -1754,13 +1765,13 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, if (action & ATA_EH_REVALIDATE && ata_dev_ready(dev)) { if (ata_port_offline(ap)) { rc = -EIO; - break; + goto err; } ata_eh_about_to_do(ap, dev, ATA_EH_REVALIDATE); rc = ata_dev_revalidate(dev, readid_flags); if (rc) - break; + goto err; ata_eh_done(ap, dev, ATA_EH_REVALIDATE); @@ -1778,40 +1789,53 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, rc = ata_dev_read_id(dev, &dev->class, readid_flags, dev->id); - if (rc == 0) { - ehc->i.flags |= ATA_EHI_PRINTINFO; - rc = ata_dev_configure(dev); - ehc->i.flags &= ~ATA_EHI_PRINTINFO; - } else if (rc == -ENOENT) { + switch (rc) { + case 0: + new_mask |= 1 << i; + break; + case -ENOENT: /* IDENTIFY was issued to non-existent * device. No need to reset. Just * thaw and kill the device. */ ata_eh_thaw_port(ap); dev->class = ATA_DEV_UNKNOWN; - rc = 0; - } - - if (rc) { - dev->class = ATA_DEV_UNKNOWN; break; + default: + dev->class = ATA_DEV_UNKNOWN; + goto err; } + } + } - if (ata_dev_enabled(dev)) { - spin_lock_irqsave(ap->lock, flags); - ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG; - spin_unlock_irqrestore(ap->lock, flags); + /* Configure new devices forward such that user doesn't see + * device detection messages backwards. + */ + for (i = 0; i < ATA_MAX_DEVICES; i++) { + dev = &ap->device[i]; - /* new device discovered, configure xfermode */ - ehc->i.flags |= ATA_EHI_SETMODE; - } - } + if (!(new_mask & (1 << i))) + continue; + + ehc->i.flags |= ATA_EHI_PRINTINFO; + rc = ata_dev_configure(dev); + ehc->i.flags &= ~ATA_EHI_PRINTINFO; + if (rc) + goto err; + + spin_lock_irqsave(ap->lock, flags); + ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG; + spin_unlock_irqrestore(ap->lock, flags); + + /* new device discovered, configure xfermode */ + ehc->i.flags |= ATA_EHI_SETMODE; } - if (rc) - *r_failed_dev = dev; + return 0; - DPRINTK("EXIT\n"); + err: + *r_failed_dev = dev; + DPRINTK("EXIT rc=%d\n", rc); return rc; } diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 6cc817a1020..e9364434182 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -333,7 +333,7 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg) scsi_cmd[8] = args[3]; scsi_cmd[10] = args[4]; scsi_cmd[12] = args[5]; - scsi_cmd[13] = args[6] & 0x0f; + scsi_cmd[13] = args[6] & 0x4f; scsi_cmd[14] = args[0]; /* Good values for timeout and retries? Values below diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index c42671493e8..1f1e3a51f85 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -56,7 +56,7 @@ extern struct workqueue_struct *ata_aux_wq; extern int atapi_enabled; extern int atapi_dmadir; extern int libata_fua; -extern int noacpi; +extern int libata_noacpi; extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev); extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, u64 block, u32 n_block, unsigned int tf_flags, diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c index 7ef834250a4..55cc293e748 100644 --- a/drivers/ata/pata_cs5520.c +++ b/drivers/ata/pata_cs5520.c @@ -208,7 +208,7 @@ static struct ata_port_operations cs5520_port_ops = { static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id) { u8 pcicfg; - void *iomap[5]; + void __iomem *iomap[5]; static struct ata_probe_ent probe[2]; int ports = 0; diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c index 9a0523b5c94..c6f0e192755 100644 --- a/drivers/ata/pata_ixp4xx_cf.c +++ b/drivers/ata/pata_ixp4xx_cf.c @@ -193,7 +193,7 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq) - set_irq_type(irq, IRQT_HIGH); + set_irq_type(irq, IRQT_RISING); /* Setup expansion bus chip selects */ *data->cs0_cfg = data->cs0_bits; @@ -232,7 +232,6 @@ static __devexit int ixp4xx_pata_remove(struct platform_device *dev) struct ata_host *host = platform_get_drvdata(dev); ata_host_detach(host); - platform_set_drvdata(dev, NULL); return 0; } diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c index f5d88729ca7..882c36eaf29 100644 --- a/drivers/ata/pata_mpc52xx.c +++ b/drivers/ata/pata_mpc52xx.c @@ -329,7 +329,7 @@ mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv) ae->dev = dev; ae->irq = priv->ata_irq; - aio->cmd_addr = 0; /* Don't have a classic reg block */ + aio->cmd_addr = NULL; /* Don't have a classic reg block */ aio->altstatus_addr = &priv->ata_regs->tf_control; aio->ctl_addr = &priv->ata_regs->tf_control; aio->data_addr = &priv->ata_regs->tf_data; diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c index acdc52cbe38..0a149339891 100644 --- a/drivers/ata/pata_pdc202xx_old.c +++ b/drivers/ata/pata_pdc202xx_old.c @@ -195,7 +195,7 @@ static void pdc2026x_bmdma_start(struct ata_queued_cmd *qc) /* Cases the state machine will not complete correctly without help */ if ((tf->flags & ATA_TFLAG_LBA48) || tf->protocol == ATA_PROT_ATAPI_DMA) { - len = qc->nbytes; + len = qc->nbytes / 2; if (tf->flags & ATA_TFLAG_WRITE) len |= 0x06000000; diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c index 3193a603d1a..1e21688bfcf 100644 --- a/drivers/ata/sata_inic162x.c +++ b/drivers/ata/sata_inic162x.c @@ -672,10 +672,6 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) return rc; - rc = pci_request_regions(pdev, DRV_NAME); - if (rc) - return rc; - rc = pcim_iomap_regions(pdev, 0x3f, DRV_NAME); if (rc) return rc; diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 388d07fab5f..9d9670a9b11 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -874,8 +874,14 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) if (status & (NV_ADMA_STAT_DONE | NV_ADMA_STAT_CPBERR)) { - u32 check_commands = notifier | notifier_error; + u32 check_commands; int pos, error = 0; + + if(ata_tag_valid(ap->active_tag)) + check_commands = 1 << ap->active_tag; + else + check_commands = ap->sactive; + /** Check CPBs for completed commands */ while ((pos = ffs(check_commands)) && !error) { pos--; diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 75d96159965..5614df8c1ce 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -346,6 +346,7 @@ static const struct pci_device_id sil24_pci_tbl[] = { { PCI_VDEVICE(CMD, 0x3124), BID_SIL3124 }, { PCI_VDEVICE(INTEL, 0x3124), BID_SIL3124 }, { PCI_VDEVICE(CMD, 0x3132), BID_SIL3132 }, + { PCI_VDEVICE(CMD, 0x0242), BID_SIL3132 }, { PCI_VDEVICE(CMD, 0x3131), BID_SIL3131 }, { PCI_VDEVICE(CMD, 0x3531), BID_SIL3131 }, diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c index 1879e0cd56a..a787f0d4a5b 100644 --- a/drivers/ata/sata_sis.c +++ b/drivers/ata/sata_sis.c @@ -354,7 +354,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) return -ENOMEM; if (!(probe_ent->port_flags & SIS_FLAG_CFGSCR)) { - void *mmio; + void __iomem *mmio; mmio = pcim_iomap(pdev, SIS_SCR_PCI_BAR, 0); if (!mmio) diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c index 0d7091e2077..2ad2527cf5b 100644 --- a/drivers/atm/zatm.c +++ b/drivers/atm/zatm.c @@ -1177,7 +1177,7 @@ static void __devinit eprom_get_esi(struct atm_dev *dev) /*--------------------------------- entries ---------------------------------*/ -static int __init zatm_init(struct atm_dev *dev) +static int __devinit zatm_init(struct atm_dev *dev) { struct zatm_dev *zatm_dev; struct pci_dev *pci_dev; @@ -1256,7 +1256,7 @@ static int __init zatm_init(struct atm_dev *dev) } -static int __init zatm_start(struct atm_dev *dev) +static int __devinit zatm_start(struct atm_dev *dev) { struct zatm_dev *zatm_dev = ZATM_DEV(dev); struct pci_dev *pdev = zatm_dev->pci_dev; diff --git a/drivers/base/core.c b/drivers/base/core.c index cf2a398aaaa..d7fcf823a42 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -28,20 +28,6 @@ int (*platform_notify)(struct device * dev) = NULL; int (*platform_notify_remove)(struct device * dev) = NULL; /* - * Detect the LANANA-assigned LOCAL/EXPERIMENTAL majors - */ -bool is_lanana_major(unsigned int major) -{ - if (major >= 60 && major <= 63) - return 1; - if (major >= 120 && major <= 127) - return 1; - if (major >= 240 && major <= 254) - return 1; - return 0; -} - -/* * sysfs bindings for devices. */ @@ -407,6 +393,35 @@ void device_remove_bin_file(struct device *dev, struct bin_attribute *attr) } EXPORT_SYMBOL_GPL(device_remove_bin_file); +/** + * device_schedule_callback - helper to schedule a callback for a device + * @dev: device. + * @func: callback function to invoke later. + * + * Attribute methods must not unregister themselves or their parent device + * (which would amount to the same thing). Attempts to do so will deadlock, + * since unregistration is mutually exclusive with driver callbacks. + * + * Instead methods can call this routine, which will attempt to allocate + * and schedule a workqueue request to call back @func with @dev as its + * argument in the workqueue's process context. @dev will be pinned until + * @func returns. + * + * Returns 0 if the request was submitted, -ENOMEM if storage could not + * be allocated. + * + * NOTE: This routine won't work if CONFIG_SYSFS isn't set! It uses an + * underlying sysfs routine (since it is intended for use by attribute + * methods), and if sysfs isn't available you'll get nothing but -ENOSYS. + */ +int device_schedule_callback(struct device *dev, + void (*func)(struct device *)) +{ + return sysfs_schedule_callback(&dev->kobj, + (void (*)(void *)) func, dev); +} +EXPORT_SYMBOL_GPL(device_schedule_callback); + static void klist_children_get(struct klist_node *n) { struct device *dev = container_of(n, struct device, knode_parent); @@ -584,17 +599,17 @@ int device_add(struct device *dev) if (dev->kobj.parent != &dev->class->subsys.kset.kobj) sysfs_create_link(&dev->class->subsys.kset.kobj, &dev->kobj, dev->bus_id); -#ifdef CONFIG_SYSFS_DEPRECATED if (parent) { sysfs_create_link(&dev->kobj, &dev->parent->kobj, "device"); +#ifdef CONFIG_SYSFS_DEPRECATED class_name = make_class_name(dev->class->name, &dev->kobj); if (class_name) sysfs_create_link(&dev->parent->kobj, &dev->kobj, class_name); - } #endif + } } if ((error = device_add_attrs(dev))) @@ -651,17 +666,17 @@ int device_add(struct device *dev) if (dev->kobj.parent != &dev->class->subsys.kset.kobj) sysfs_remove_link(&dev->class->subsys.kset.kobj, dev->bus_id); -#ifdef CONFIG_SYSFS_DEPRECATED if (parent) { +#ifdef CONFIG_SYSFS_DEPRECATED char *class_name = make_class_name(dev->class->name, &dev->kobj); if (class_name) sysfs_remove_link(&dev->parent->kobj, class_name); kfree(class_name); +#endif sysfs_remove_link(&dev->kobj, "device"); } -#endif down(&dev->class->sem); /* notify any interfaces that the device is now gone */ @@ -761,17 +776,17 @@ void device_del(struct device * dev) if (dev->kobj.parent != &dev->class->subsys.kset.kobj) sysfs_remove_link(&dev->class->subsys.kset.kobj, dev->bus_id); -#ifdef CONFIG_SYSFS_DEPRECATED if (parent) { +#ifdef CONFIG_SYSFS_DEPRECATED char *class_name = make_class_name(dev->class->name, &dev->kobj); if (class_name) sysfs_remove_link(&dev->parent->kobj, class_name); kfree(class_name); +#endif sysfs_remove_link(&dev->kobj, "device"); } -#endif down(&dev->class->sem); /* notify any interfaces that the device is now gone */ @@ -787,6 +802,13 @@ void device_del(struct device * dev) device_remove_attrs(dev); bus_remove_device(dev); + /* + * Some platform devices are driven without driver attached + * and managed resources may have been acquired. Make sure + * all resources are released. + */ + devres_release_all(dev); + /* Notify the platform of the removal, in case they * need to do anything... */ @@ -1058,14 +1080,14 @@ int device_rename(struct device *dev, char *new_name) return error; } - +EXPORT_SYMBOL_GPL(device_rename); static int device_move_class_links(struct device *dev, struct device *old_parent, struct device *new_parent) { + int error = 0; #ifdef CONFIG_SYSFS_DEPRECATED - int error; char *class_name; class_name = make_class_name(dev->class->name, &dev->kobj); @@ -1093,7 +1115,12 @@ out: kfree(class_name); return error; #else - return 0; + if (old_parent) + sysfs_remove_link(&dev->kobj, "device"); + if (new_parent) + error = sysfs_create_link(&dev->kobj, &new_parent->kobj, + "device"); + return error; #endif } diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 1214cbd17d8..082bfded385 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -183,7 +183,14 @@ int driver_register(struct device_driver * drv) void driver_unregister(struct device_driver * drv) { bus_remove_driver(drv); - wait_for_completion(&drv->unloaded); + /* + * If the driver is a module, we are probably in + * the module unload path, and we want to wait + * for everything to unload before we can actually + * finish the unload. + */ + if (drv->owner) + wait_for_completion(&drv->unloaded); } /** diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index fdfa3d0cf6a..bbbb973a9d3 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -54,7 +54,8 @@ int device_pm_add(struct device * dev) int error; pr_debug("PM: Adding info for %s:%s\n", - dev->bus ? dev->bus->name : "No Bus", dev->kobj.name); + dev->bus ? dev->bus->name : "No Bus", + kobject_name(&dev->kobj)); down(&dpm_list_sem); list_add_tail(&dev->power.entry, &dpm_active); device_pm_set_parent(dev, dev->parent); @@ -67,7 +68,8 @@ int device_pm_add(struct device * dev) void device_pm_remove(struct device * dev) { pr_debug("PM: Removing info for %s:%s\n", - dev->bus ? dev->bus->name : "No Bus", dev->kobj.name); + dev->bus ? dev->bus->name : "No Bus", + kobject_name(&dev->kobj)); down(&dpm_list_sem); dpm_sysfs_remove(dev); put_device(dev->power.pm_parent); diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 0c716ee905d..14d780666c0 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -1439,7 +1439,7 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk) if (return_code == IO_OK) { listlength = - be32_to_cpu(*(__u32 *) ld_buff->LUNListLength); + be32_to_cpu(*(__be32 *) ld_buff->LUNListLength); } else { /* reading number of logical volumes failed */ printk(KERN_WARNING "cciss: report logical volume" " command failed\n"); @@ -1915,6 +1915,7 @@ static void cciss_geometry_inquiry(int ctlr, int logvol, "does not support reading geometry\n"); drv->heads = 255; drv->sectors = 32; // Sectors per track + drv->cylinders = total_size + 1; drv->raid_level = RAID_UNKNOWN; } else { drv->heads = inq_buff->data_byte[6]; @@ -1961,8 +1962,8 @@ cciss_read_capacity(int ctlr, int logvol, int withirq, sector_t *total_size, ctlr, buf, sizeof(ReadCapdata_struct), 1, logvol, 0, NULL, TYPE_CMD); if (return_code == IO_OK) { - *total_size = be32_to_cpu(*(__u32 *) buf->total_size); - *block_size = be32_to_cpu(*(__u32 *) buf->block_size); + *total_size = be32_to_cpu(*(__be32 *) buf->total_size); + *block_size = be32_to_cpu(*(__be32 *) buf->block_size); } else { /* read capacity command failed */ printk(KERN_WARNING "cciss: read capacity failed\n"); *total_size = 0; @@ -1997,8 +1998,8 @@ cciss_read_capacity_16(int ctlr, int logvol, int withirq, sector_t *total_size, 1, logvol, 0, NULL, TYPE_CMD); } if (return_code == IO_OK) { - *total_size = be64_to_cpu(*(__u64 *) buf->total_size); - *block_size = be32_to_cpu(*(__u32 *) buf->block_size); + *total_size = be64_to_cpu(*(__be64 *) buf->total_size); + *block_size = be32_to_cpu(*(__be32 *) buf->block_size); } else { /* read capacity command failed */ printk(KERN_WARNING "cciss: read capacity failed\n"); *total_size = 0; diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index 99e2c8ce1cc..31e01488eb5 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c @@ -663,11 +663,11 @@ static enum action pd_identify(struct pd_unit *disk) return Fail; pi_read_block(disk->pi, pd_scratch, 512); disk->can_lba = pd_scratch[99] & 2; - disk->sectors = le16_to_cpu(*(u16 *) (pd_scratch + 12)); - disk->heads = le16_to_cpu(*(u16 *) (pd_scratch + 6)); - disk->cylinders = le16_to_cpu(*(u16 *) (pd_scratch + 2)); + disk->sectors = le16_to_cpu(*(__le16 *) (pd_scratch + 12)); + disk->heads = le16_to_cpu(*(__le16 *) (pd_scratch + 6)); + disk->cylinders = le16_to_cpu(*(__le16 *) (pd_scratch + 2)); if (disk->can_lba) - disk->capacity = le32_to_cpu(*(u32 *) (pd_scratch + 120)); + disk->capacity = le32_to_cpu(*(__le32 *) (pd_scratch + 120)); else disk->capacity = disk->sectors * disk->heads * disk->cylinders; diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 3429ece4ef9..d0c978fbc20 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -386,6 +386,39 @@ config AU1000_SERIAL_CONSOLE If you have an Alchemy AU1000 processor (MIPS based) and you want to use a console on a serial port, say Y. Otherwise, say N. +config SERIAL_DEC + bool "DECstation serial support" + depends on MACH_DECSTATION + default y + help + This selects whether you want to be asked about drivers for + DECstation serial ports. + + Note that the answer to this question won't directly affect the + kernel: saying N will just cause the configurator to skip all + the questions about DECstation serial ports. + +config SERIAL_DEC_CONSOLE + bool "Support for console on a DECstation serial port" + depends on SERIAL_DEC + default y + help + If you say Y here, it will be possible to use a serial port as the + system console (the system console is the device which receives all + kernel messages and warnings and which allows logins in single user + mode). Note that the firmware uses ttyS0 as the serial console on + the Maxine and ttyS2 on the others. + + If unsure, say Y. + +config ZS + bool "Z85C30 Serial Support" + depends on SERIAL_DEC + default y + help + Documentation on the Zilog 85C350 serial communications controller + is downloadable at <http://www.zilog.com/pdfs/serial/z85c30.pdf> + config A2232 tristate "Commodore A2232 serial support (EXPERIMENTAL)" depends on EXPERIMENTAL && ZORRO && BROKEN_ON_SMP diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index e542a628f1c..55392a45a14 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -18,11 +18,14 @@ #define PCI_DEVICE_ID_INTEL_82965Q_IG 0x2992 #define PCI_DEVICE_ID_INTEL_82965G_HB 0x29A0 #define PCI_DEVICE_ID_INTEL_82965G_IG 0x29A2 +#define PCI_DEVICE_ID_INTEL_82965GM_HB 0x2A00 +#define PCI_DEVICE_ID_INTEL_82965GM_IG 0x2A02 #define IS_I965 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82946GZ_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_1_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965Q_HB || \ - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB) + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB || \ + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB) extern int agp_memory_reserved; @@ -428,9 +431,8 @@ static void intel_i830_init_gtt_entries(void) if (IS_I965) { u32 pgetbl_ctl; + pgetbl_ctl = readl(intel_i830_private.registers+I810_PGETBL_CTL); - pci_read_config_dword(agp_bridge->dev, I810_PGETBL_CTL, - &pgetbl_ctl); /* The 965 has a field telling us the size of the GTT, * which may be larger than what is necessary to map the * aperture. @@ -1921,7 +1923,13 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, bridge->driver = &intel_845_driver; name = "965G"; break; - + case PCI_DEVICE_ID_INTEL_82965GM_HB: + if (find_i830(PCI_DEVICE_ID_INTEL_82965GM_IG)) + bridge->driver = &intel_i965_driver; + else + bridge->driver = &intel_845_driver; + name = "965GM"; + break; case PCI_DEVICE_ID_INTEL_7505_0: bridge->driver = &intel_7505_driver; name = "E7505"; @@ -2080,6 +2088,7 @@ static struct pci_device_id agp_intel_pci_table[] = { ID(PCI_DEVICE_ID_INTEL_82965G_1_HB), ID(PCI_DEVICE_ID_INTEL_82965Q_HB), ID(PCI_DEVICE_ID_INTEL_82965G_HB), + ID(PCI_DEVICE_ID_INTEL_82965GM_HB), { } }; diff --git a/drivers/char/drm/Makefile b/drivers/char/drm/Makefile index 3ad0f648c6b..6915a0599df 100644 --- a/drivers/char/drm/Makefile +++ b/drivers/char/drm/Makefile @@ -15,7 +15,6 @@ i810-objs := i810_drv.o i810_dma.o i830-objs := i830_drv.o i830_dma.o i830_irq.o i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o -ffb-objs := ffb_drv.o ffb_context.o sis-objs := sis_drv.o sis_mm.o savage-objs := savage_drv.o savage_bci.o savage_state.o via-objs := via_irq.o via_drv.o via_map.o via_mm.o via_dma.o via_verifier.o via_video.o via_dmablit.o @@ -36,7 +35,6 @@ obj-$(CONFIG_DRM_MGA) += mga.o obj-$(CONFIG_DRM_I810) += i810.o obj-$(CONFIG_DRM_I830) += i830.o obj-$(CONFIG_DRM_I915) += i915.o -obj-$(CONFIG_DRM_FFB) += ffb.o obj-$(CONFIG_DRM_SIS) += sis.o obj-$(CONFIG_DRM_SAVAGE)+= savage.o obj-$(CONFIG_DRM_VIA) +=via.o diff --git a/drivers/char/drm/ffb_context.c b/drivers/char/drm/ffb_context.c deleted file mode 100644 index ac9ab40d57a..00000000000 --- a/drivers/char/drm/ffb_context.c +++ /dev/null @@ -1,544 +0,0 @@ -/* $Id: ffb_context.c,v 1.5 2001/08/09 17:47:51 davem Exp $ - * ffb_context.c: Creator/Creator3D DRI/DRM context switching. - * - * Copyright (C) 2000 David S. Miller (davem@redhat.com) - * - * Almost entirely stolen from tdfx_context.c, see there - * for authors. - */ - -#include <asm/upa.h> - -#include "ffb.h" -#include "drmP.h" - -#include "ffb_drv.h" - -static int DRM(alloc_queue) (drm_device_t * dev, int is_2d_only) { - ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private; - int i; - - for (i = 0; i < FFB_MAX_CTXS; i++) { - if (fpriv->hw_state[i] == NULL) - break; - } - if (i == FFB_MAX_CTXS) - return -1; - - fpriv->hw_state[i] = kmalloc(sizeof(struct ffb_hw_context), GFP_KERNEL); - if (fpriv->hw_state[i] == NULL) - return -1; - - fpriv->hw_state[i]->is_2d_only = is_2d_only; - - /* Plus one because 0 is the special DRM_KERNEL_CONTEXT. */ - return i + 1; -} - -static void ffb_save_context(ffb_dev_priv_t * fpriv, int idx) -{ - ffb_fbcPtr ffb = fpriv->regs; - struct ffb_hw_context *ctx; - int i; - - ctx = fpriv->hw_state[idx - 1]; - if (idx == 0 || ctx == NULL) - return; - - if (ctx->is_2d_only) { - /* 2D applications only care about certain pieces - * of state. - */ - ctx->drawop = upa_readl(&ffb->drawop); - ctx->ppc = upa_readl(&ffb->ppc); - ctx->wid = upa_readl(&ffb->wid); - ctx->fg = upa_readl(&ffb->fg); - ctx->bg = upa_readl(&ffb->bg); - ctx->xclip = upa_readl(&ffb->xclip); - ctx->fbc = upa_readl(&ffb->fbc); - ctx->rop = upa_readl(&ffb->rop); - ctx->cmp = upa_readl(&ffb->cmp); - ctx->matchab = upa_readl(&ffb->matchab); - ctx->magnab = upa_readl(&ffb->magnab); - ctx->pmask = upa_readl(&ffb->pmask); - ctx->xpmask = upa_readl(&ffb->xpmask); - ctx->lpat = upa_readl(&ffb->lpat); - ctx->fontxy = upa_readl(&ffb->fontxy); - ctx->fontw = upa_readl(&ffb->fontw); - ctx->fontinc = upa_readl(&ffb->fontinc); - - /* stencil/stencilctl only exists on FFB2+ and later - * due to the introduction of 3DRAM-III. - */ - if (fpriv->ffb_type == ffb2_vertical_plus || - fpriv->ffb_type == ffb2_horizontal_plus) { - ctx->stencil = upa_readl(&ffb->stencil); - ctx->stencilctl = upa_readl(&ffb->stencilctl); - } - - for (i = 0; i < 32; i++) - ctx->area_pattern[i] = upa_readl(&ffb->pattern[i]); - ctx->ucsr = upa_readl(&ffb->ucsr); - return; - } - - /* Fetch drawop. */ - ctx->drawop = upa_readl(&ffb->drawop); - - /* If we were saving the vertex registers, this is where - * we would do it. We would save 32 32-bit words starting - * at ffb->suvtx. - */ - - /* Capture rendering attributes. */ - - ctx->ppc = upa_readl(&ffb->ppc); /* Pixel Processor Control */ - ctx->wid = upa_readl(&ffb->wid); /* Current WID */ - ctx->fg = upa_readl(&ffb->fg); /* Constant FG color */ - ctx->bg = upa_readl(&ffb->bg); /* Constant BG color */ - ctx->consty = upa_readl(&ffb->consty); /* Constant Y */ - ctx->constz = upa_readl(&ffb->constz); /* Constant Z */ - ctx->xclip = upa_readl(&ffb->xclip); /* X plane clip */ - ctx->dcss = upa_readl(&ffb->dcss); /* Depth Cue Scale Slope */ - ctx->vclipmin = upa_readl(&ffb->vclipmin); /* Primary XY clip, minimum */ - ctx->vclipmax = upa_readl(&ffb->vclipmax); /* Primary XY clip, maximum */ - ctx->vclipzmin = upa_readl(&ffb->vclipzmin); /* Primary Z clip, minimum */ - ctx->vclipzmax = upa_readl(&ffb->vclipzmax); /* Primary Z clip, maximum */ - ctx->dcsf = upa_readl(&ffb->dcsf); /* Depth Cue Scale Front Bound */ - ctx->dcsb = upa_readl(&ffb->dcsb); /* Depth Cue Scale Back Bound */ - ctx->dczf = upa_readl(&ffb->dczf); /* Depth Cue Scale Z Front */ - ctx->dczb = upa_readl(&ffb->dczb); /* Depth Cue Scale Z Back */ - ctx->blendc = upa_readl(&ffb->blendc); /* Alpha Blend Control */ - ctx->blendc1 = upa_readl(&ffb->blendc1); /* Alpha Blend Color 1 */ - ctx->blendc2 = upa_readl(&ffb->blendc2); /* Alpha Blend Color 2 */ - ctx->fbc = upa_readl(&ffb->fbc); /* Frame Buffer Control */ - ctx->rop = upa_readl(&ffb->rop); /* Raster Operation */ - ctx->cmp = upa_readl(&ffb->cmp); /* Compare Controls */ - ctx->matchab = upa_readl(&ffb->matchab); /* Buffer A/B Match Ops */ - ctx->matchc = upa_readl(&ffb->matchc); /* Buffer C Match Ops */ - ctx->magnab = upa_readl(&ffb->magnab); /* Buffer A/B Magnitude Ops */ - ctx->magnc = upa_readl(&ffb->magnc); /* Buffer C Magnitude Ops */ - ctx->pmask = upa_readl(&ffb->pmask); /* RGB Plane Mask */ - ctx->xpmask = upa_readl(&ffb->xpmask); /* X Plane Mask */ - ctx->ypmask = upa_readl(&ffb->ypmask); /* Y Plane Mask */ - ctx->zpmask = upa_readl(&ffb->zpmask); /* Z Plane Mask */ - - /* Auxiliary Clips. */ - ctx->auxclip0min = upa_readl(&ffb->auxclip[0].min); - ctx->auxclip0max = upa_readl(&ffb->auxclip[0].max); - ctx->auxclip1min = upa_readl(&ffb->auxclip[1].min); - ctx->auxclip1max = upa_readl(&ffb->auxclip[1].max); - ctx->auxclip2min = upa_readl(&ffb->auxclip[2].min); - ctx->auxclip2max = upa_readl(&ffb->auxclip[2].max); - ctx->auxclip3min = upa_readl(&ffb->auxclip[3].min); - ctx->auxclip3max = upa_readl(&ffb->auxclip[3].max); - - ctx->lpat = upa_readl(&ffb->lpat); /* Line Pattern */ - ctx->fontxy = upa_readl(&ffb->fontxy); /* XY Font Coordinate */ - ctx->fontw = upa_readl(&ffb->fontw); /* Font Width */ - ctx->fontinc = upa_readl(&ffb->fontinc); /* Font X/Y Increment */ - - /* These registers/features only exist on FFB2 and later chips. */ - if (fpriv->ffb_type >= ffb2_prototype) { - ctx->dcss1 = upa_readl(&ffb->dcss1); /* Depth Cue Scale Slope 1 */ - ctx->dcss2 = upa_readl(&ffb->dcss2); /* Depth Cue Scale Slope 2 */ - ctx->dcss2 = upa_readl(&ffb->dcss3); /* Depth Cue Scale Slope 3 */ - ctx->dcs2 = upa_readl(&ffb->dcs2); /* Depth Cue Scale 2 */ - ctx->dcs3 = upa_readl(&ffb->dcs3); /* Depth Cue Scale 3 */ - ctx->dcs4 = upa_readl(&ffb->dcs4); /* Depth Cue Scale 4 */ - ctx->dcd2 = upa_readl(&ffb->dcd2); /* Depth Cue Depth 2 */ - ctx->dcd3 = upa_readl(&ffb->dcd3); /* Depth Cue Depth 3 */ - ctx->dcd4 = upa_readl(&ffb->dcd4); /* Depth Cue Depth 4 */ - - /* And stencil/stencilctl only exists on FFB2+ and later - * due to the introduction of 3DRAM-III. - */ - if (fpriv->ffb_type == ffb2_vertical_plus || - fpriv->ffb_type == ffb2_horizontal_plus) { - ctx->stencil = upa_readl(&ffb->stencil); - ctx->stencilctl = upa_readl(&ffb->stencilctl); - } - } - - /* Save the 32x32 area pattern. */ - for (i = 0; i < 32; i++) - ctx->area_pattern[i] = upa_readl(&ffb->pattern[i]); - - /* Finally, stash away the User Constol/Status Register. */ - ctx->ucsr = upa_readl(&ffb->ucsr); -} - -static void ffb_restore_context(ffb_dev_priv_t * fpriv, int old, int idx) -{ - ffb_fbcPtr ffb = fpriv->regs; - struct ffb_hw_context *ctx; - int i; - - ctx = fpriv->hw_state[idx - 1]; - if (idx == 0 || ctx == NULL) - return; - - if (ctx->is_2d_only) { - /* 2D applications only care about certain pieces - * of state. - */ - upa_writel(ctx->drawop, &ffb->drawop); - - /* If we were restoring the vertex registers, this is where - * we would do it. We would restore 32 32-bit words starting - * at ffb->suvtx. - */ - - upa_writel(ctx->ppc, &ffb->ppc); - upa_writel(ctx->wid, &ffb->wid); - upa_writel(ctx->fg, &ffb->fg); - upa_writel(ctx->bg, &ffb->bg); - upa_writel(ctx->xclip, &ffb->xclip); - upa_writel(ctx->fbc, &ffb->fbc); - upa_writel(ctx->rop, &ffb->rop); - upa_writel(ctx->cmp, &ffb->cmp); - upa_writel(ctx->matchab, &ffb->matchab); - upa_writel(ctx->magnab, &ffb->magnab); - upa_writel(ctx->pmask, &ffb->pmask); - upa_writel(ctx->xpmask, &ffb->xpmask); - upa_writel(ctx->lpat, &ffb->lpat); - upa_writel(ctx->fontxy, &ffb->fontxy); - upa_writel(ctx->fontw, &ffb->fontw); - upa_writel(ctx->fontinc, &ffb->fontinc); - - /* stencil/stencilctl only exists on FFB2+ and later - * due to the introduction of 3DRAM-III. - */ - if (fpriv->ffb_type == ffb2_vertical_plus || - fpriv->ffb_type == ffb2_horizontal_plus) { - upa_writel(ctx->stencil, &ffb->stencil); - upa_writel(ctx->stencilctl, &ffb->stencilctl); - upa_writel(0x80000000, &ffb->fbc); - upa_writel((ctx->stencilctl | 0x80000), - &ffb->rawstencilctl); - upa_writel(ctx->fbc, &ffb->fbc); - } - - for (i = 0; i < 32; i++) - upa_writel(ctx->area_pattern[i], &ffb->pattern[i]); - upa_writel((ctx->ucsr & 0xf0000), &ffb->ucsr); - return; - } - - /* Restore drawop. */ - upa_writel(ctx->drawop, &ffb->drawop); - - /* If we were restoring the vertex registers, this is where - * we would do it. We would restore 32 32-bit words starting - * at ffb->suvtx. - */ - - /* Restore rendering attributes. */ - - upa_writel(ctx->ppc, &ffb->ppc); /* Pixel Processor Control */ - upa_writel(ctx->wid, &ffb->wid); /* Current WID */ - upa_writel(ctx->fg, &ffb->fg); /* Constant FG color */ - upa_writel(ctx->bg, &ffb->bg); /* Constant BG color */ - upa_writel(ctx->consty, &ffb->consty); /* Constant Y */ - upa_writel(ctx->constz, &ffb->constz); /* Constant Z */ - upa_writel(ctx->xclip, &ffb->xclip); /* X plane clip */ - upa_writel(ctx->dcss, &ffb->dcss); /* Depth Cue Scale Slope */ - upa_writel(ctx->vclipmin, &ffb->vclipmin); /* Primary XY clip, minimum */ - upa_writel(ctx->vclipmax, &ffb->vclipmax); /* Primary XY clip, maximum */ - upa_writel(ctx->vclipzmin, &ffb->vclipzmin); /* Primary Z clip, minimum */ - upa_writel(ctx->vclipzmax, &ffb->vclipzmax); /* Primary Z clip, maximum */ - upa_writel(ctx->dcsf, &ffb->dcsf); /* Depth Cue Scale Front Bound */ - upa_writel(ctx->dcsb, &ffb->dcsb); /* Depth Cue Scale Back Bound */ - upa_writel(ctx->dczf, &ffb->dczf); /* Depth Cue Scale Z Front */ - upa_writel(ctx->dczb, &ffb->dczb); /* Depth Cue Scale Z Back */ - upa_writel(ctx->blendc, &ffb->blendc); /* Alpha Blend Control */ - upa_writel(ctx->blendc1, &ffb->blendc1); /* Alpha Blend Color 1 */ - upa_writel(ctx->blendc2, &ffb->blendc2); /* Alpha Blend Color 2 */ - upa_writel(ctx->fbc, &ffb->fbc); /* Frame Buffer Control */ - upa_writel(ctx->rop, &ffb->rop); /* Raster Operation */ - upa_writel(ctx->cmp, &ffb->cmp); /* Compare Controls */ - upa_writel(ctx->matchab, &ffb->matchab); /* Buffer A/B Match Ops */ - upa_writel(ctx->matchc, &ffb->matchc); /* Buffer C Match Ops */ - upa_writel(ctx->magnab, &ffb->magnab); /* Buffer A/B Magnitude Ops */ - upa_writel(ctx->magnc, &ffb->magnc); /* Buffer C Magnitude Ops */ - upa_writel(ctx->pmask, &ffb->pmask); /* RGB Plane Mask */ - upa_writel(ctx->xpmask, &ffb->xpmask); /* X Plane Mask */ - upa_writel(ctx->ypmask, &ffb->ypmask); /* Y Plane Mask */ - upa_writel(ctx->zpmask, &ffb->zpmask); /* Z Plane Mask */ - - /* Auxiliary Clips. */ - upa_writel(ctx->auxclip0min, &ffb->auxclip[0].min); - upa_writel(ctx->auxclip0max, &ffb->auxclip[0].max); - upa_writel(ctx->auxclip1min, &ffb->auxclip[1].min); - upa_writel(ctx->auxclip1max, &ffb->auxclip[1].max); - upa_writel(ctx->auxclip2min, &ffb->auxclip[2].min); - upa_writel(ctx->auxclip2max, &ffb->auxclip[2].max); - upa_writel(ctx->auxclip3min, &ffb->auxclip[3].min); - upa_writel(ctx->auxclip3max, &ffb->auxclip[3].max); - - upa_writel(ctx->lpat, &ffb->lpat); /* Line Pattern */ - upa_writel(ctx->fontxy, &ffb->fontxy); /* XY Font Coordinate */ - upa_writel(ctx->fontw, &ffb->fontw); /* Font Width */ - upa_writel(ctx->fontinc, &ffb->fontinc); /* Font X/Y Increment */ - - /* These registers/features only exist on FFB2 and later chips. */ - if (fpriv->ffb_type >= ffb2_prototype) { - upa_writel(ctx->dcss1, &ffb->dcss1); /* Depth Cue Scale Slope 1 */ - upa_writel(ctx->dcss2, &ffb->dcss2); /* Depth Cue Scale Slope 2 */ - upa_writel(ctx->dcss3, &ffb->dcss2); /* Depth Cue Scale Slope 3 */ - upa_writel(ctx->dcs2, &ffb->dcs2); /* Depth Cue Scale 2 */ - upa_writel(ctx->dcs3, &ffb->dcs3); /* Depth Cue Scale 3 */ - upa_writel(ctx->dcs4, &ffb->dcs4); /* Depth Cue Scale 4 */ - upa_writel(ctx->dcd2, &ffb->dcd2); /* Depth Cue Depth 2 */ - upa_writel(ctx->dcd3, &ffb->dcd3); /* Depth Cue Depth 3 */ - upa_writel(ctx->dcd4, &ffb->dcd4); /* Depth Cue Depth 4 */ - - /* And stencil/stencilctl only exists on FFB2+ and later - * due to the introduction of 3DRAM-III. - */ - if (fpriv->ffb_type == ffb2_vertical_plus || - fpriv->ffb_type == ffb2_horizontal_plus) { - /* Unfortunately, there is a hardware bug on - * the FFB2+ chips which prevents a normal write - * to the stencil control register from working - * as it should. - * - * The state controlled by the FFB stencilctl register - * really gets transferred to the per-buffer instances - * of the stencilctl register in the 3DRAM chips. - * - * The bug is that FFB does not update buffer C correctly, - * so we have to do it by hand for them. - */ - - /* This will update buffers A and B. */ - upa_writel(ctx->stencil, &ffb->stencil); - upa_writel(ctx->stencilctl, &ffb->stencilctl); - - /* Force FFB to use buffer C 3dram regs. */ - upa_writel(0x80000000, &ffb->fbc); - upa_writel((ctx->stencilctl | 0x80000), - &ffb->rawstencilctl); - - /* Now restore the correct FBC controls. */ - upa_writel(ctx->fbc, &ffb->fbc); - } - } - - /* Restore the 32x32 area pattern. */ - for (i = 0; i < 32; i++) - upa_writel(ctx->area_pattern[i], &ffb->pattern[i]); - - /* Finally, stash away the User Constol/Status Register. - * The only state we really preserve here is the picking - * control. - */ - upa_writel((ctx->ucsr & 0xf0000), &ffb->ucsr); -} - -#define FFB_UCSR_FB_BUSY 0x01000000 -#define FFB_UCSR_RP_BUSY 0x02000000 -#define FFB_UCSR_ALL_BUSY (FFB_UCSR_RP_BUSY|FFB_UCSR_FB_BUSY) - -static void FFBWait(ffb_fbcPtr ffb) -{ - int limit = 100000; - - do { - u32 regval = upa_readl(&ffb->ucsr); - - if ((regval & FFB_UCSR_ALL_BUSY) == 0) - break; - } while (--limit); -} - -int ffb_driver_context_switch(drm_device_t * dev, int old, int new) -{ - ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private; - -#ifdef DRM_DMA_HISTOGRAM - dev->ctx_start = get_cycles(); -#endif - - DRM_DEBUG("Context switch from %d to %d\n", old, new); - - if (new == dev->last_context || dev->last_context == 0) { - dev->last_context = new; - return 0; - } - - FFBWait(fpriv->regs); - ffb_save_context(fpriv, old); - ffb_restore_context(fpriv, old, new); - FFBWait(fpriv->regs); - - dev->last_context = new; - - return 0; -} - -int ffb_driver_resctx(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) -{ - drm_ctx_res_t res; - drm_ctx_t ctx; - int i; - - DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS); - if (copy_from_user(&res, (drm_ctx_res_t __user *) arg, sizeof(res))) - return -EFAULT; - if (res.count >= DRM_RESERVED_CONTEXTS) { - memset(&ctx, 0, sizeof(ctx)); - for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { - ctx.handle = i; - if (copy_to_user(&res.contexts[i], &i, sizeof(i))) - return -EFAULT; - } - } - res.count = DRM_RESERVED_CONTEXTS; - if (copy_to_user((drm_ctx_res_t __user *) arg, &res, sizeof(res))) - return -EFAULT; - return 0; -} - -int ffb_driver_addctx(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - drm_ctx_t ctx; - int idx; - - if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx))) - return -EFAULT; - idx = DRM(alloc_queue) (dev, (ctx.flags & _DRM_CONTEXT_2DONLY)); - if (idx < 0) - return -ENFILE; - - DRM_DEBUG("%d\n", ctx.handle); - ctx.handle = idx; - if (copy_to_user((drm_ctx_t __user *) arg, &ctx, sizeof(ctx))) - return -EFAULT; - return 0; -} - -int ffb_driver_modctx(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private; - struct ffb_hw_context *hwctx; - drm_ctx_t ctx; - int idx; - - if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx))) - return -EFAULT; - - idx = ctx.handle; - if (idx <= 0 || idx >= FFB_MAX_CTXS) - return -EINVAL; - - hwctx = fpriv->hw_state[idx - 1]; - if (hwctx == NULL) - return -EINVAL; - - if ((ctx.flags & _DRM_CONTEXT_2DONLY) == 0) - hwctx->is_2d_only = 0; - else - hwctx->is_2d_only = 1; - - return 0; -} - -int ffb_driver_getctx(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private; - struct ffb_hw_context *hwctx; - drm_ctx_t ctx; - int idx; - - if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx))) - return -EFAULT; - - idx = ctx.handle; - if (idx <= 0 || idx >= FFB_MAX_CTXS) - return -EINVAL; - - hwctx = fpriv->hw_state[idx - 1]; - if (hwctx == NULL) - return -EINVAL; - - if (hwctx->is_2d_only != 0) - ctx.flags = _DRM_CONTEXT_2DONLY; - else - ctx.flags = 0; - - if (copy_to_user((drm_ctx_t __user *) arg, &ctx, sizeof(ctx))) - return -EFAULT; - - return 0; -} - -int ffb_driver_switchctx(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - drm_ctx_t ctx; - - if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx))) - return -EFAULT; - DRM_DEBUG("%d\n", ctx.handle); - return ffb_driver_context_switch(dev, dev->last_context, ctx.handle); -} - -int ffb_driver_newctx(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) -{ - drm_ctx_t ctx; - - if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx))) - return -EFAULT; - DRM_DEBUG("%d\n", ctx.handle); - - return 0; -} - -int ffb_driver_rmctx(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) -{ - drm_ctx_t ctx; - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private; - int idx; - - if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx))) - return -EFAULT; - DRM_DEBUG("%d\n", ctx.handle); - - idx = ctx.handle - 1; - if (idx < 0 || idx >= FFB_MAX_CTXS) - return -EINVAL; - - kfree(fpriv->hw_state[idx]); - fpriv->hw_state[idx] = NULL; - return 0; -} - -void ffb_set_context_ioctls(void) -{ - DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)].func = ffb_driver_addctx; - DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)].func = ffb_driver_rmctx; - DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)].func = ffb_driver_modctx; - DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)].func = ffb_driver_getctx; - DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)].func = - ffb_driver_switchctx; - DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)].func = ffb_driver_newctx; - DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)].func = ffb_driver_resctx; - -} diff --git a/drivers/char/drm/ffb_drv.c b/drivers/char/drm/ffb_drv.c deleted file mode 100644 index 9a19879e3b6..00000000000 --- a/drivers/char/drm/ffb_drv.c +++ /dev/null @@ -1,355 +0,0 @@ -/* $Id: ffb_drv.c,v 1.16 2001/10/18 16:00:24 davem Exp $ - * ffb_drv.c: Creator/Creator3D direct rendering driver. - * - * Copyright (C) 2000 David S. Miller (davem@redhat.com) - */ - -#include "ffb.h" -#include "drmP.h" - -#include "ffb_drv.h" - -#include <linux/smp_lock.h> -#include <asm/shmparam.h> -#include <asm/oplib.h> -#include <asm/upa.h> - -#define DRIVER_AUTHOR "David S. Miller" - -#define DRIVER_NAME "ffb" -#define DRIVER_DESC "Creator/Creator3D" -#define DRIVER_DATE "20000517" - -#define DRIVER_MAJOR 0 -#define DRIVER_MINOR 0 -#define DRIVER_PATCHLEVEL 1 - -typedef struct _ffb_position_t { - int node; - int root; -} ffb_position_t; - -static ffb_position_t *ffb_position; - -static void get_ffb_type(ffb_dev_priv_t * ffb_priv, int instance) -{ - volatile unsigned char *strap_bits; - unsigned char val; - - strap_bits = (volatile unsigned char *) - (ffb_priv->card_phys_base + 0x00200000UL); - - /* Don't ask, you have to read the value twice for whatever - * reason to get correct contents. - */ - val = upa_readb(strap_bits); - val = upa_readb(strap_bits); - switch (val & 0x78) { - case (0x0 << 5) | (0x0 << 3): - ffb_priv->ffb_type = ffb1_prototype; - printk("ffb%d: Detected FFB1 pre-FCS prototype\n", instance); - break; - case (0x0 << 5) | (0x1 << 3): - ffb_priv->ffb_type = ffb1_standard; - printk("ffb%d: Detected FFB1\n", instance); - break; - case (0x0 << 5) | (0x3 << 3): - ffb_priv->ffb_type = ffb1_speedsort; - printk("ffb%d: Detected FFB1-SpeedSort\n", instance); - break; - case (0x1 << 5) | (0x0 << 3): - ffb_priv->ffb_type = ffb2_prototype; - printk("ffb%d: Detected FFB2/vertical pre-FCS prototype\n", - instance); - break; - case (0x1 << 5) | (0x1 << 3): - ffb_priv->ffb_type = ffb2_vertical; - printk("ffb%d: Detected FFB2/vertical\n", instance); - break; - case (0x1 << 5) | (0x2 << 3): - ffb_priv->ffb_type = ffb2_vertical_plus; - printk("ffb%d: Detected FFB2+/vertical\n", instance); - break; - case (0x2 << 5) | (0x0 << 3): - ffb_priv->ffb_type = ffb2_horizontal; - printk("ffb%d: Detected FFB2/horizontal\n", instance); - break; - case (0x2 << 5) | (0x2 << 3): - ffb_priv->ffb_type = ffb2_horizontal; - printk("ffb%d: Detected FFB2+/horizontal\n", instance); - break; - default: - ffb_priv->ffb_type = ffb2_vertical; - printk("ffb%d: Unknown boardID[%08x], assuming FFB2\n", - instance, val); - break; - }; -} - -static void ffb_apply_upa_parent_ranges(int parent, - struct linux_prom64_registers *regs) -{ - struct linux_prom64_ranges ranges[PROMREG_MAX]; - char name[128]; - int len, i; - - prom_getproperty(parent, "name", name, sizeof(name)); - if (strcmp(name, "upa") != 0) - return; - - len = - prom_getproperty(parent, "ranges", (void *)ranges, sizeof(ranges)); - if (len <= 0) - return; - - len /= sizeof(struct linux_prom64_ranges); - for (i = 0; i < len; i++) { - struct linux_prom64_ranges *rng = &ranges[i]; - u64 phys_addr = regs->phys_addr; - - if (phys_addr >= rng->ot_child_base && - phys_addr < (rng->ot_child_base + rng->or_size)) { - regs->phys_addr -= rng->ot_child_base; - regs->phys_addr += rng->ot_parent_base; - return; - } - } - - return; -} - -static int ffb_init_one(drm_device_t * dev, int prom_node, int parent_node, - int instance) -{ - struct linux_prom64_registers regs[2 * PROMREG_MAX]; - ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *) dev->dev_private; - int i; - - ffb_priv->prom_node = prom_node; - if (prom_getproperty(ffb_priv->prom_node, "reg", - (void *)regs, sizeof(regs)) <= 0) { - return -EINVAL; - } - ffb_apply_upa_parent_ranges(parent_node, ®s[0]); - ffb_priv->card_phys_base = regs[0].phys_addr; - ffb_priv->regs = (ffb_fbcPtr) - (regs[0].phys_addr + 0x00600000UL); - get_ffb_type(ffb_priv, instance); - for (i = 0; i < FFB_MAX_CTXS; i++) - ffb_priv->hw_state[i] = NULL; - - return 0; -} - -static drm_map_t *ffb_find_map(struct file *filp, unsigned long off) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev; - drm_map_list_t *r_list; - struct list_head *list; - drm_map_t *map; - - if (!priv || (dev = priv->dev) == NULL) - return NULL; - - list_for_each(list, &dev->maplist->head) { - r_list = (drm_map_list_t *) list; - map = r_list->map; - if (!map) - continue; - if (r_list->user_token == off) - return map; - } - - return NULL; -} - -unsigned long ffb_get_unmapped_area(struct file *filp, - unsigned long hint, - unsigned long len, - unsigned long pgoff, unsigned long flags) -{ - drm_map_t *map = ffb_find_map(filp, pgoff << PAGE_SHIFT); - unsigned long addr = -ENOMEM; - - if (!map) - return get_unmapped_area(NULL, hint, len, pgoff, flags); - - if (map->type == _DRM_FRAME_BUFFER || map->type == _DRM_REGISTERS) { -#ifdef HAVE_ARCH_FB_UNMAPPED_AREA - addr = get_fb_unmapped_area(filp, hint, len, pgoff, flags); -#else - addr = get_unmapped_area(NULL, hint, len, pgoff, flags); -#endif - } else if (map->type == _DRM_SHM && SHMLBA > PAGE_SIZE) { - unsigned long slack = SHMLBA - PAGE_SIZE; - - addr = get_unmapped_area(NULL, hint, len + slack, pgoff, flags); - if (!(addr & ~PAGE_MASK)) { - unsigned long kvirt = (unsigned long)map->handle; - - if ((kvirt & (SHMLBA - 1)) != (addr & (SHMLBA - 1))) { - unsigned long koff, aoff; - - koff = kvirt & (SHMLBA - 1); - aoff = addr & (SHMLBA - 1); - if (koff < aoff) - koff += SHMLBA; - - addr += (koff - aoff); - } - } - } else { - addr = get_unmapped_area(NULL, hint, len, pgoff, flags); - } - - return addr; -} - -static int ffb_presetup(drm_device_t * dev) -{ - ffb_dev_priv_t *ffb_priv; - int ret = 0; - int i = 0; - - /* Check for the case where no device was found. */ - if (ffb_position == NULL) - return -ENODEV; - - /* code used to use numdevs no numdevs anymore */ - ffb_priv = kmalloc(sizeof(ffb_dev_priv_t), GFP_KERNEL); - if (!ffb_priv) - return -ENOMEM; - memset(ffb_priv, 0, sizeof(*ffb_priv)); - dev->dev_private = ffb_priv; - - ret = ffb_init_one(dev, ffb_position[i].node, ffb_position[i].root, i); - return ret; -} - -static void ffb_driver_release(drm_device_t * dev, struct file *filp) -{ - ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private; - int context = _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock); - int idx; - - idx = context - 1; - if (fpriv && - context != DRM_KERNEL_CONTEXT && fpriv->hw_state[idx] != NULL) { - kfree(fpriv->hw_state[idx]); - fpriv->hw_state[idx] = NULL; - } -} - -static void ffb_driver_pretakedown(drm_device_t * dev) -{ - kfree(dev->dev_private); -} - -static int ffb_driver_postcleanup(drm_device_t * dev) -{ - kfree(ffb_position); - return 0; -} - -static void ffb_driver_kernel_context_switch_unlock(struct drm_device *dev, - drm_lock_t * lock) -{ - dev->lock.filp = 0; - { - __volatile__ unsigned int *plock = &dev->lock.hw_lock->lock; - unsigned int old, new, prev, ctx; - - ctx = lock->context; - do { - old = *plock; - new = ctx; - prev = cmpxchg(plock, old, new); - } while (prev != old); - } - wake_up_interruptible(&dev->lock.lock_queue); -} - -static unsigned long ffb_driver_get_map_ofs(drm_map_t * map) -{ - return (map->offset & 0xffffffff); -} - -static unsigned long ffb_driver_get_reg_ofs(drm_device_t * dev) -{ - ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *) dev->dev_private; - - if (ffb_priv) - return ffb_priv->card_phys_base; - - return 0; -} - -static int postinit(struct drm_device *dev, unsigned long flags) -{ - DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", - DRIVER_NAME, - DRIVER_MAJOR, - DRIVER_MINOR, DRIVER_PATCHLEVEL, DRIVER_DATE, dev->minor); - return 0; -} - -static int version(drm_version_t * version) -{ - int len; - - version->version_major = DRIVER_MAJOR; - version->version_minor = DRIVER_MINOR; - version->version_patchlevel = DRIVER_PATCHLEVEL; - DRM_COPY(version->name, DRIVER_NAME); - DRM_COPY(version->date, DRIVER_DATE); - DRM_COPY(version->desc, DRIVER_DESC); - return 0; -} - -static drm_ioctl_desc_t ioctls[] = { - -}; - -static struct drm_driver driver = { - .driver_features = 0, - .dev_priv_size = sizeof(u32), - .release = ffb_driver_release, - .presetup = ffb_presetup, - .pretakedown = ffb_driver_pretakedown, - .postcleanup = ffb_driver_postcleanup, - .kernel_context_switch = ffb_driver_context_switch, - .kernel_context_switch_unlock = ffb_driver_kernel_context_switch_unlock, - .get_map_ofs = ffb_driver_get_map_ofs, - .get_reg_ofs = ffb_driver_get_reg_ofs, - .postinit = postinit, - .version = version, - .ioctls = ioctls, - .num_ioctls = DRM_ARRAY_SIZE(ioctls), - .fops = { - .owner = THIS_MODULE, - .open = drm_open, - .release = drm_release, - .ioctl = drm_ioctl, - .mmap = drm_mmap, - .poll = drm_poll, - .fasync = drm_fasync, - } - , -}; - -static int __init ffb_init(void) -{ - return -ENODEV; -} - -static void __exit ffb_exit(void) -{ -} - -module_init(ffb_init); -module_exit(ffb_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/char/drm/ffb_drv.h b/drivers/char/drm/ffb_drv.h deleted file mode 100644 index 582afa6dd2b..00000000000 --- a/drivers/char/drm/ffb_drv.h +++ /dev/null @@ -1,379 +0,0 @@ -/* $Id: ffb_drv.h,v 1.1 2000/06/01 04:24:39 davem Exp $ - * ffb_drv.h: Creator/Creator3D direct rendering driver. - * - * Copyright (C) 2000 David S. Miller (davem@redhat.com) - */ - -/* Auxilliary clips. */ -typedef struct { - volatile unsigned int min; - volatile unsigned int max; -} ffb_auxclip, *ffb_auxclipPtr; - -/* FFB register set. */ -typedef struct _ffb_fbc { - /* Next vertex registers, on the right we list which drawops - * use said register and the logical name the register has in - * that context. - *//* DESCRIPTION DRAWOP(NAME) */ - /*0x00*/ unsigned int pad1[3]; - /* Reserved */ - /*0x0c*/ volatile unsigned int alpha; - /* ALPHA Transparency */ - /*0x10*/ volatile unsigned int red; - /* RED */ - /*0x14*/ volatile unsigned int green; - /* GREEN */ - /*0x18*/ volatile unsigned int blue; - /* BLUE */ - /*0x1c*/ volatile unsigned int z; - /* DEPTH */ - /*0x20*/ volatile unsigned int y; - /* Y triangle(DOYF) */ - /* aadot(DYF) */ - /* ddline(DYF) */ - /* aaline(DYF) */ - /*0x24*/ volatile unsigned int x; - /* X triangle(DOXF) */ - /* aadot(DXF) */ - /* ddline(DXF) */ - /* aaline(DXF) */ - /*0x28*/ unsigned int pad2[2]; - /* Reserved */ - /*0x30*/ volatile unsigned int ryf; - /* Y (alias to DOYF) ddline(RYF) */ - /* aaline(RYF) */ - /* triangle(RYF) */ - /*0x34*/ volatile unsigned int rxf; - /* X ddline(RXF) */ - /* aaline(RXF) */ - /* triangle(RXF) */ - /*0x38*/ unsigned int pad3[2]; - /* Reserved */ - /*0x40*/ volatile unsigned int dmyf; - /* Y (alias to DOYF) triangle(DMYF) */ - /*0x44*/ volatile unsigned int dmxf; - /* X triangle(DMXF) */ - /*0x48*/ unsigned int pad4[2]; - /* Reserved */ - /*0x50*/ volatile unsigned int ebyi; - /* Y (alias to RYI) polygon(EBYI) */ - /*0x54*/ volatile unsigned int ebxi; - /* X polygon(EBXI) */ - /*0x58*/ unsigned int pad5[2]; - /* Reserved */ - /*0x60*/ volatile unsigned int by; - /* Y brline(RYI) */ - /* fastfill(OP) */ - /* polygon(YI) */ - /* rectangle(YI) */ - /* bcopy(SRCY) */ - /* vscroll(SRCY) */ - /*0x64*/ volatile unsigned int bx; - /* X brline(RXI) */ - /* polygon(XI) */ - /* rectangle(XI) */ - /* bcopy(SRCX) */ - /* vscroll(SRCX) */ - /* fastfill(GO) */ - /*0x68*/ volatile unsigned int dy; - /* destination Y fastfill(DSTY) */ - /* bcopy(DSRY) */ - /* vscroll(DSRY) */ - /*0x6c*/ volatile unsigned int dx; - /* destination X fastfill(DSTX) */ - /* bcopy(DSTX) */ - /* vscroll(DSTX) */ - /*0x70*/ volatile unsigned int bh; - /* Y (alias to RYI) brline(DYI) */ - /* dot(DYI) */ - /* polygon(ETYI) */ - /* Height fastfill(H) */ - /* bcopy(H) */ - /* vscroll(H) */ - /* Y count fastfill(NY) */ - /*0x74*/ volatile unsigned int bw; - /* X dot(DXI) */ - /* brline(DXI) */ - /* polygon(ETXI) */ - /* fastfill(W) */ - /* bcopy(W) */ - /* vscroll(W) */ - /* fastfill(NX) */ - /*0x78*/ unsigned int pad6[2]; - /* Reserved */ - /*0x80*/ unsigned int pad7[32]; - /* Reserved */ - - /* Setup Unit's vertex state register */ -/*100*/ volatile unsigned int suvtx; - /*104*/ unsigned int pad8[63]; - /* Reserved */ - - /* Frame Buffer Control Registers */ - /*200*/ volatile unsigned int ppc; - /* Pixel Processor Control */ - /*204*/ volatile unsigned int wid; - /* Current WID */ - /*208*/ volatile unsigned int fg; - /* FG data */ - /*20c*/ volatile unsigned int bg; - /* BG data */ - /*210*/ volatile unsigned int consty; - /* Constant Y */ - /*214*/ volatile unsigned int constz; - /* Constant Z */ - /*218*/ volatile unsigned int xclip; - /* X Clip */ - /*21c*/ volatile unsigned int dcss; - /* Depth Cue Scale Slope */ - /*220*/ volatile unsigned int vclipmin; - /* Viewclip XY Min Bounds */ - /*224*/ volatile unsigned int vclipmax; - /* Viewclip XY Max Bounds */ - /*228*/ volatile unsigned int vclipzmin; - /* Viewclip Z Min Bounds */ - /*22c*/ volatile unsigned int vclipzmax; - /* Viewclip Z Max Bounds */ - /*230*/ volatile unsigned int dcsf; - /* Depth Cue Scale Front Bound */ - /*234*/ volatile unsigned int dcsb; - /* Depth Cue Scale Back Bound */ - /*238*/ volatile unsigned int dczf; - /* Depth Cue Z Front */ - /*23c*/ volatile unsigned int dczb; - /* Depth Cue Z Back */ - /*240*/ unsigned int pad9; - /* Reserved */ - /*244*/ volatile unsigned int blendc; - /* Alpha Blend Control */ - /*248*/ volatile unsigned int blendc1; - /* Alpha Blend Color 1 */ - /*24c*/ volatile unsigned int blendc2; - /* Alpha Blend Color 2 */ - /*250*/ volatile unsigned int fbramitc; - /* FB RAM Interleave Test Control */ - /*254*/ volatile unsigned int fbc; - /* Frame Buffer Control */ - /*258*/ volatile unsigned int rop; - /* Raster OPeration */ - /*25c*/ volatile unsigned int cmp; - /* Frame Buffer Compare */ - /*260*/ volatile unsigned int matchab; - /* Buffer AB Match Mask */ - /*264*/ volatile unsigned int matchc; - /* Buffer C(YZ) Match Mask */ - /*268*/ volatile unsigned int magnab; - /* Buffer AB Magnitude Mask */ - /*26c*/ volatile unsigned int magnc; - /* Buffer C(YZ) Magnitude Mask */ - /*270*/ volatile unsigned int fbcfg0; - /* Frame Buffer Config 0 */ - /*274*/ volatile unsigned int fbcfg1; - /* Frame Buffer Config 1 */ - /*278*/ volatile unsigned int fbcfg2; - /* Frame Buffer Config 2 */ - /*27c*/ volatile unsigned int fbcfg3; - /* Frame Buffer Config 3 */ - /*280*/ volatile unsigned int ppcfg; - /* Pixel Processor Config */ - /*284*/ volatile unsigned int pick; - /* Picking Control */ - /*288*/ volatile unsigned int fillmode; - /* FillMode */ - /*28c*/ volatile unsigned int fbramwac; - /* FB RAM Write Address Control */ - /*290*/ volatile unsigned int pmask; - /* RGB PlaneMask */ - /*294*/ volatile unsigned int xpmask; - /* X PlaneMask */ - /*298*/ volatile unsigned int ypmask; - /* Y PlaneMask */ - /*29c*/ volatile unsigned int zpmask; - /* Z PlaneMask */ - /*2a0*/ ffb_auxclip auxclip[4]; - /* Auxilliary Viewport Clip */ - - /* New 3dRAM III support regs */ -/*2c0*/ volatile unsigned int rawblend2; -/*2c4*/ volatile unsigned int rawpreblend; -/*2c8*/ volatile unsigned int rawstencil; -/*2cc*/ volatile unsigned int rawstencilctl; -/*2d0*/ volatile unsigned int threedram1; -/*2d4*/ volatile unsigned int threedram2; -/*2d8*/ volatile unsigned int passin; -/*2dc*/ volatile unsigned int rawclrdepth; -/*2e0*/ volatile unsigned int rawpmask; -/*2e4*/ volatile unsigned int rawcsrc; -/*2e8*/ volatile unsigned int rawmatch; -/*2ec*/ volatile unsigned int rawmagn; -/*2f0*/ volatile unsigned int rawropblend; -/*2f4*/ volatile unsigned int rawcmp; -/*2f8*/ volatile unsigned int rawwac; -/*2fc*/ volatile unsigned int fbramid; - - /*300*/ volatile unsigned int drawop; - /* Draw OPeration */ - /*304*/ unsigned int pad10[2]; - /* Reserved */ - /*30c*/ volatile unsigned int lpat; - /* Line Pattern control */ - /*310*/ unsigned int pad11; - /* Reserved */ - /*314*/ volatile unsigned int fontxy; - /* XY Font coordinate */ - /*318*/ volatile unsigned int fontw; - /* Font Width */ - /*31c*/ volatile unsigned int fontinc; - /* Font Increment */ - /*320*/ volatile unsigned int font; - /* Font bits */ - /*324*/ unsigned int pad12[3]; - /* Reserved */ -/*330*/ volatile unsigned int blend2; -/*334*/ volatile unsigned int preblend; -/*338*/ volatile unsigned int stencil; -/*33c*/ volatile unsigned int stencilctl; - - /*340*/ unsigned int pad13[4]; - /* Reserved */ - /*350*/ volatile unsigned int dcss1; - /* Depth Cue Scale Slope 1 */ - /*354*/ volatile unsigned int dcss2; - /* Depth Cue Scale Slope 2 */ - /*358*/ volatile unsigned int dcss3; - /* Depth Cue Scale Slope 3 */ -/*35c*/ volatile unsigned int widpmask; -/*360*/ volatile unsigned int dcs2; -/*364*/ volatile unsigned int dcs3; -/*368*/ volatile unsigned int dcs4; - /*36c*/ unsigned int pad14; - /* Reserved */ -/*370*/ volatile unsigned int dcd2; -/*374*/ volatile unsigned int dcd3; -/*378*/ volatile unsigned int dcd4; - /*37c*/ unsigned int pad15; - /* Reserved */ - /*380*/ volatile unsigned int pattern[32]; - /* area Pattern */ - /*400*/ unsigned int pad16[8]; - /* Reserved */ - /*420*/ volatile unsigned int reset; - /* chip RESET */ - /*424*/ unsigned int pad17[247]; - /* Reserved */ - /*800*/ volatile unsigned int devid; - /* Device ID */ - /*804*/ unsigned int pad18[63]; - /* Reserved */ - /*900*/ volatile unsigned int ucsr; - /* User Control & Status Register */ - /*904*/ unsigned int pad19[31]; - /* Reserved */ - /*980*/ volatile unsigned int mer; - /* Mode Enable Register */ - /*984*/ unsigned int pad20[1439]; - /* Reserved */ -} ffb_fbc, *ffb_fbcPtr; - -struct ffb_hw_context { - int is_2d_only; - - unsigned int ppc; - unsigned int wid; - unsigned int fg; - unsigned int bg; - unsigned int consty; - unsigned int constz; - unsigned int xclip; - unsigned int dcss; - unsigned int vclipmin; - unsigned int vclipmax; - unsigned int vclipzmin; - unsigned int vclipzmax; - unsigned int dcsf; - unsigned int dcsb; - unsigned int dczf; - unsigned int dczb; - unsigned int blendc; - unsigned int blendc1; - unsigned int blendc2; - unsigned int fbc; - unsigned int rop; - unsigned int cmp; - unsigned int matchab; - unsigned int matchc; - unsigned int magnab; - unsigned int magnc; - unsigned int pmask; - unsigned int xpmask; - unsigned int ypmask; - unsigned int zpmask; - unsigned int auxclip0min; - unsigned int auxclip0max; - unsigned int auxclip1min; - unsigned int auxclip1max; - unsigned int auxclip2min; - unsigned int auxclip2max; - unsigned int auxclip3min; - unsigned int auxclip3max; - unsigned int drawop; - unsigned int lpat; - unsigned int fontxy; - unsigned int fontw; - unsigned int fontinc; - unsigned int area_pattern[32]; - unsigned int ucsr; - unsigned int stencil; - unsigned int stencilctl; - unsigned int dcss1; - unsigned int dcss2; - unsigned int dcss3; - unsigned int dcs2; - unsigned int dcs3; - unsigned int dcs4; - unsigned int dcd2; - unsigned int dcd3; - unsigned int dcd4; - unsigned int mer; -}; - -#define FFB_MAX_CTXS 32 - -enum ffb_chip_type { - ffb1_prototype = 0, /* Early pre-FCS FFB */ - ffb1_standard, /* First FCS FFB, 100Mhz UPA, 66MHz gclk */ - ffb1_speedsort, /* Second FCS FFB, 100Mhz UPA, 75MHz gclk */ - ffb2_prototype, /* Early pre-FCS vertical FFB2 */ - ffb2_vertical, /* First FCS FFB2/vertical, 100Mhz UPA, 100MHZ gclk, - 75(SingleBuffer)/83(DoubleBuffer) MHz fclk */ - ffb2_vertical_plus, /* Second FCS FFB2/vertical, same timings */ - ffb2_horizontal, /* First FCS FFB2/horizontal, same timings as FFB2/vert */ - ffb2_horizontal_plus, /* Second FCS FFB2/horizontal, same timings */ - afb_m3, /* FCS Elite3D, 3 float chips */ - afb_m6 /* FCS Elite3D, 6 float chips */ -}; - -typedef struct ffb_dev_priv { - /* Misc software state. */ - int prom_node; - enum ffb_chip_type ffb_type; - u64 card_phys_base; - struct miscdevice miscdev; - - /* Controller registers. */ - ffb_fbcPtr regs; - - /* Context table. */ - struct ffb_hw_context *hw_state[FFB_MAX_CTXS]; -} ffb_dev_priv_t; - -extern unsigned long ffb_get_unmapped_area(struct file *filp, - unsigned long hint, - unsigned long len, - unsigned long pgoff, - unsigned long flags); -extern void ffb_set_context_ioctls(void); -extern drm_ioctl_desc_t DRM(ioctls)[]; - -extern int ffb_driver_context_switch(drm_device_t * dev, int old, int new); diff --git a/drivers/char/ds1286.c b/drivers/char/ds1286.c index 6d58b037080..59146e3365b 100644 --- a/drivers/char/ds1286.c +++ b/drivers/char/ds1286.c @@ -197,6 +197,7 @@ static int ds1286_ioctl(struct inode *inode, struct file *file, hrs = alm_tm.tm_hour; min = alm_tm.tm_min; + sec = alm_tm.tm_sec; if (hrs >= 24) hrs = 0xff; @@ -204,9 +205,11 @@ static int ds1286_ioctl(struct inode *inode, struct file *file, if (min >= 60) min = 0xff; - BIN_TO_BCD(sec); - BIN_TO_BCD(min); - BIN_TO_BCD(hrs); + if (sec != 0) + return -EINVAL; + + min = BIN2BCD(min); + min = BIN2BCD(hrs); spin_lock(&ds1286_lock); rtc_write(hrs, RTC_HOURS_ALARM); diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c index 337bbcdcf13..8ea02755b1c 100644 --- a/drivers/char/generic_serial.c +++ b/drivers/char/generic_serial.c @@ -710,12 +710,6 @@ void gs_close(struct tty_struct * tty, struct file * filp) } -static unsigned int gs_baudrates[] = { - 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, - 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600 -}; - - void gs_set_termios (struct tty_struct * tty, struct ktermios * old_termios) { @@ -771,7 +765,6 @@ void gs_set_termios (struct tty_struct * tty, baudrate = tty_get_baud_rate(tty); - baudrate = gs_baudrates[baudrate]; if ((tiosp->c_cflag & CBAUD) == B38400) { if ( (port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) baudrate = 57600; diff --git a/drivers/char/lcd.c b/drivers/char/lcd.c index 5f4fdcf7c96..1f0962616ee 100644 --- a/drivers/char/lcd.c +++ b/drivers/char/lcd.c @@ -11,9 +11,6 @@ * March 2001: Ported from 2.0.34 by Liam Davies * */ - -#define RTC_IO_EXTENT 0x10 /*Only really two ports, but... */ - #include <linux/types.h> #include <linux/errno.h> #include <linux/miscdevice.h> @@ -32,8 +29,6 @@ #include "lcd.h" -static DEFINE_SPINLOCK(lcd_lock); - static int lcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index e4532685668..7a32df59490 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1376,6 +1376,8 @@ static void do_tty_hangup(struct work_struct *work) read_unlock(&tasklist_lock); tty->flags = 0; + put_pid(tty->session); + put_pid(tty->pgrp); tty->session = NULL; tty->pgrp = NULL; tty->ctrl_status = 0; @@ -3841,6 +3843,9 @@ static struct pid *__proc_set_tty(struct task_struct *tsk, struct tty_struct *tt { struct pid *old_pgrp; if (tty) { + /* We should not have a session or pgrp to here but.... */ + put_pid(tty->session); + put_pid(tty->pgrp); tty->session = get_pid(task_session(tsk)); tty->pgrp = get_pid(task_pgrp(tsk)); } diff --git a/drivers/char/vt.c b/drivers/char/vt.c index c3f8e383933..1bbb45b937f 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -724,6 +724,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ return -ENOMEM; memset(vc, 0, sizeof(*vc)); vc_cons[currcons].d = vc; + INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); visual_init(vc, currcons, 1); if (!*vc->vc_uni_pagedir_loc) con_set_default_unimap(vc); @@ -2185,10 +2186,28 @@ static void console_callback(struct work_struct *ignored) release_console_sem(); } -void set_console(int nr) +int set_console(int nr) { + struct vc_data *vc = vc_cons[fg_console].d; + + if (!vc_cons_allocated(nr) || vt_dont_switch || + (vc->vt_mode.mode == VT_AUTO && vc->vc_mode == KD_GRAPHICS)) { + + /* + * Console switch will fail in console_callback() or + * change_console() so there is no point scheduling + * the callback + * + * Existing set_console() users don't check the return + * value so this shouldn't break anything + */ + return -EINVAL; + } + want_console = nr; schedule_console_callback(); + + return 0; } struct tty_driver *console_driver; diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index 3a5d301e783..c9f2dd620e8 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c @@ -34,7 +34,7 @@ #include <linux/kbd_diacr.h> #include <linux/selection.h> -static char vt_dont_switch; +char vt_dont_switch; extern struct tty_driver *console_driver; #define VT_IS_IN_USE(i) (console_driver->ttys[i] && console_driver->ttys[i]->count) @@ -1039,10 +1039,22 @@ int vt_waitactive(int vt) add_wait_queue(&vt_activate_queue, &wait); for (;;) { - set_current_state(TASK_INTERRUPTIBLE); retval = 0; - if (vt == fg_console) + + /* + * Synchronize with redraw_screen(). By acquiring the console + * semaphore we make sure that the console switch is completed + * before we return. If we didn't wait for the semaphore, we + * could return at a point where fg_console has already been + * updated, but the console switch hasn't been completed. + */ + acquire_console_sem(); + set_current_state(TASK_INTERRUPTIBLE); + if (vt == fg_console) { + release_console_sem(); break; + } + release_console_sem(); retval = -EINTR; if (signal_pending(current)) break; diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index ea09d0c974e..e812aa129e2 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig @@ -301,6 +301,7 @@ config I6300ESB_WDT config I8XX_TCO tristate "Intel i8xx TCO Timer/Watchdog" depends on WATCHDOG && (X86 || IA64) && PCI + default n ---help--- Hardware driver for the TCO timer built into the Intel 82801 I/O Controller Hub family. The TCO (Total Cost of Ownership) diff --git a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c index 4a328ba0d26..76c7fa37fa6 100644 --- a/drivers/char/watchdog/machzwd.c +++ b/drivers/char/watchdog/machzwd.c @@ -314,21 +314,21 @@ static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, { void __user *argp = (void __user *)arg; int __user *p = argp; - switch(cmd){ - case WDIOC_GETSUPPORT: - if (copy_to_user(argp, &zf_info, sizeof(zf_info))) - return -EFAULT; - break; + switch (cmd) { + case WDIOC_GETSUPPORT: + if (copy_to_user(argp, &zf_info, sizeof(zf_info))) + return -EFAULT; + break; - case WDIOC_GETSTATUS: - return put_user(0, p); + case WDIOC_GETSTATUS: + return put_user(0, p); - case WDIOC_KEEPALIVE: - zf_ping(0); - break; + case WDIOC_KEEPALIVE: + zf_ping(0); + break; - default: - return -ENOTTY; + default: + return -ENOTTY; } return 0; diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c index d42060ede93..5ac309ee7f0 100644 --- a/drivers/clocksource/acpi_pm.c +++ b/drivers/clocksource/acpi_pm.c @@ -90,7 +90,7 @@ __setup("acpi_pm_good", acpi_pm_good_setup); static inline void acpi_pm_need_workaround(void) { clocksource_acpi_pm.read = acpi_pm_read_slow; - clocksource_acpi_pm.rating = 110; + clocksource_acpi_pm.rating = 120; } /* diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index a44db75bc25..a905f782033 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -128,7 +128,7 @@ EXPORT_SYMBOL_GPL(cn_netlink_send); */ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), void *data) { - struct cn_callback_entry *__cbq; + struct cn_callback_entry *__cbq, *__new_cbq; struct cn_dev *dev = &cdev; int err = -ENODEV; @@ -148,27 +148,27 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v } else { struct cn_callback_data *d; - __cbq = kzalloc(sizeof(*__cbq), GFP_ATOMIC); - if (__cbq) { - d = &__cbq->data; + err = -ENOMEM; + __new_cbq = kzalloc(sizeof(struct cn_callback_entry), GFP_ATOMIC); + if (__new_cbq) { + d = &__new_cbq->data; d->callback_priv = msg; d->callback = __cbq->data.callback; d->ddata = data; d->destruct_data = destruct_data; - d->free = __cbq; + d->free = __new_cbq; - INIT_WORK(&__cbq->work, + INIT_WORK(&__new_cbq->work, &cn_queue_wrapper); - + if (queue_work(dev->cbdev->cn_queue, - &__cbq->work)) + &__new_cbq->work)) err = 0; else { - kfree(__cbq); + kfree(__new_cbq); err = -EINVAL; } - } else - err = -ENOMEM; + } } break; } diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index f52facc570f..3162010900c 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1015,6 +1015,10 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) { unsigned int cpu = sys_dev->id; int retval; + + if (cpu_is_offline(cpu)) + return 0; + if (unlikely(lock_policy_rwsem_write(cpu))) BUG(); diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 15278044295..322ee2984e3 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -176,6 +176,7 @@ void dma_chan_cleanup(struct kref *kref) chan->client = NULL; kref_put(&chan->device->refcount, dma_async_device_cleanup); } +EXPORT_SYMBOL(dma_chan_cleanup); static void dma_chan_free_rcu(struct rcu_head *rcu) { @@ -261,6 +262,7 @@ struct dma_client *dma_async_client_register(dma_event_callback event_callback) return client; } +EXPORT_SYMBOL(dma_async_client_register); /** * dma_async_client_unregister - unregister a client and free the &dma_client @@ -287,6 +289,7 @@ void dma_async_client_unregister(struct dma_client *client) kfree(client); dma_chans_rebalance(); } +EXPORT_SYMBOL(dma_async_client_unregister); /** * dma_async_client_chan_request - request DMA channels @@ -304,6 +307,7 @@ void dma_async_client_chan_request(struct dma_client *client, client->chans_desired = number; dma_chans_rebalance(); } +EXPORT_SYMBOL(dma_async_client_chan_request); /** * dma_async_device_register - registers DMA devices found @@ -346,6 +350,7 @@ int dma_async_device_register(struct dma_device *device) return 0; } +EXPORT_SYMBOL(dma_async_device_register); /** * dma_async_device_cleanup - function called when all references are released @@ -390,23 +395,12 @@ void dma_async_device_unregister(struct dma_device *device) kref_put(&device->refcount, dma_async_device_cleanup); wait_for_completion(&device->done); } +EXPORT_SYMBOL(dma_async_device_unregister); static int __init dma_bus_init(void) { mutex_init(&dma_list_mutex); return class_register(&dma_devclass); } - subsys_initcall(dma_bus_init); -EXPORT_SYMBOL(dma_async_client_register); -EXPORT_SYMBOL(dma_async_client_unregister); -EXPORT_SYMBOL(dma_async_client_chan_request); -EXPORT_SYMBOL(dma_async_memcpy_buf_to_buf); -EXPORT_SYMBOL(dma_async_memcpy_buf_to_pg); -EXPORT_SYMBOL(dma_async_memcpy_pg_to_pg); -EXPORT_SYMBOL(dma_async_memcpy_complete); -EXPORT_SYMBOL(dma_async_memcpy_issue_pending); -EXPORT_SYMBOL(dma_async_device_register); -EXPORT_SYMBOL(dma_async_device_unregister); -EXPORT_SYMBOL(dma_chan_cleanup); diff --git a/drivers/eisa/pci_eisa.c b/drivers/eisa/pci_eisa.c index 9e913629ef3..74edb1d0110 100644 --- a/drivers/eisa/pci_eisa.c +++ b/drivers/eisa/pci_eisa.c @@ -19,8 +19,8 @@ /* There is only *one* pci_eisa device per machine, right ? */ static struct eisa_root_device pci_eisa_root; -static int __devinit pci_eisa_init (struct pci_dev *pdev, - const struct pci_device_id *ent) +static int __init pci_eisa_init(struct pci_dev *pdev, + const struct pci_device_id *ent) { int rc; diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index f4ee1afe488..1cca32f4694 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -26,6 +26,7 @@ #include <asm/byteorder.h> #include <linux/input.h> #include <linux/wait.h> +#include <linux/vmalloc.h> #include <linux/hid.h> #include <linux/hiddev.h> @@ -654,12 +655,13 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size) memcpy(device->rdesc, start, size); device->rsize = size; - if (!(parser = kzalloc(sizeof(struct hid_parser), GFP_KERNEL))) { + if (!(parser = vmalloc(sizeof(struct hid_parser)))) { kfree(device->rdesc); kfree(device->collection); kfree(device); return NULL; } + memset(parser, 0, sizeof(struct hid_parser)); parser->device = device; end = start + size; @@ -668,7 +670,7 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size) if (item.format != HID_ITEM_FORMAT_SHORT) { dbg("unexpected long global item"); hid_free_device(device); - kfree(parser); + vfree(parser); return NULL; } @@ -676,7 +678,7 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size) dbg("item %u %u %u %u parsing failed\n", item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag); hid_free_device(device); - kfree(parser); + vfree(parser); return NULL; } @@ -684,23 +686,23 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size) if (parser->collection_stack_ptr) { dbg("unbalanced collection at end of report description"); hid_free_device(device); - kfree(parser); + vfree(parser); return NULL; } if (parser->local.delimiter_depth) { dbg("unbalanced delimiter at end of report description"); hid_free_device(device); - kfree(parser); + vfree(parser); return NULL; } - kfree(parser); + vfree(parser); return device; } } dbg("item fetching failed at offset %d\n", (int)(end - start)); hid_free_device(device); - kfree(parser); + vfree(parser); return NULL; } EXPORT_SYMBOL_GPL(hid_parse_report); @@ -753,8 +755,7 @@ static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n) report += offset >> 3; /* adjust byte index */ offset &= 7; /* now only need bit offset into one byte */ - x = get_unaligned((u64 *) report); - x = le64_to_cpu(x); + x = le64_to_cpu(get_unaligned((__le64 *) report)); x = (x >> offset) & ((1ULL << n) - 1); /* extract bit field */ return (u32) x; } @@ -769,7 +770,7 @@ static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n) */ static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value) { - u64 x; + __le64 x; u64 m = (1ULL << n) - 1; WARN_ON(n > 32); @@ -780,10 +781,10 @@ static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u3 report += offset >> 3; offset &= 7; - x = get_unaligned((u64 *)report); + x = get_unaligned((__le64 *)report); x &= cpu_to_le64(~(m << offset)); x |= cpu_to_le64(((u64) value) << offset); - put_unaligned(x, (u64 *) report); + put_unaligned(x, (__le64 *) report); } /* @@ -873,10 +874,6 @@ static void hid_output_field(struct hid_field *field, __u8 *data) unsigned size = field->report_size; unsigned n; - /* make sure the unused bits in the last byte are zeros */ - if (count > 0 && size > 0) - data[(offset+count*size-1)/8] = 0; - for (n = 0; n < count; n++) { if (field->logical_minimum < 0) /* signed values */ implement(data, offset + n * size, size, s32ton(field->value[n], size)); @@ -972,7 +969,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i if (size < rsize) { dbg("report %d is too short, (%d < %d)", report->id, size, rsize); - return -1; + memset(data + size, 0, rsize - size); } if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event) diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index c3d4856fb61..6d105a1d41b 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -527,6 +527,7 @@ config SENSORS_W83792D config SENSORS_W83793 tristate "Winbond W83793" depends on HWMON && I2C && EXPERIMENTAL + select HWMON_VID help If you say yes here you get support for the Winbond W83793 hardware monitoring chip. diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c index e15f9e37716..0c70f829334 100644 --- a/drivers/i2c/busses/i2c-amd8111.c +++ b/drivers/i2c/busses/i2c-amd8111.c @@ -254,7 +254,8 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, break; case I2C_SMBUS_BLOCK_PROC_CALL: - len = min_t(u8, data->block[0], 31); + len = min_t(u8, data->block[0], + I2C_SMBUS_BLOCK_MAX - 1); amd_ec_write(smbus, AMD_SMB_CMD, command); amd_ec_write(smbus, AMD_SMB_BCNT, len); for (i = 0; i < len; i++) diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 6569a36985b..a320e7d82c1 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -97,6 +97,7 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, int command, int hwpec); static unsigned long i801_smba; +static unsigned char i801_original_hstcfg; static struct pci_driver i801_driver; static struct pci_dev *I801_dev; static int isich4; @@ -510,6 +511,7 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id } pci_read_config_byte(I801_dev, SMBHSTCFG, &temp); + i801_original_hstcfg = temp; temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */ if (!(temp & SMBHSTCFG_HST_EN)) { dev_info(&dev->dev, "Enabling SMBus device\n"); @@ -543,6 +545,7 @@ exit: static void __devexit i801_remove(struct pci_dev *dev) { i2c_del_adapter(&i801_adapter); + pci_write_config_byte(I801_dev, SMBHSTCFG, i801_original_hstcfg); pci_release_region(dev, SMBBAR); /* * do not call pci_disable_device(dev) since it can cause hard hangs on @@ -550,11 +553,33 @@ static void __devexit i801_remove(struct pci_dev *dev) */ } +#ifdef CONFIG_PM +static int i801_suspend(struct pci_dev *dev, pm_message_t mesg) +{ + pci_save_state(dev); + pci_write_config_byte(dev, SMBHSTCFG, i801_original_hstcfg); + pci_set_power_state(dev, pci_choose_state(dev, mesg)); + return 0; +} + +static int i801_resume(struct pci_dev *dev) +{ + pci_set_power_state(dev, PCI_D0); + pci_restore_state(dev); + return pci_enable_device(dev); +} +#else +#define i801_suspend NULL +#define i801_resume NULL +#endif + static struct pci_driver i801_driver = { .name = "i801_smbus", .id_table = i801_ids, .probe = i801_probe, .remove = __devexit_p(i801_remove), + .suspend = i801_suspend, + .resume = i801_resume, }; static int __init i2c_i801_init(void) diff --git a/drivers/i2c/chips/ds1374.c b/drivers/i2c/chips/ds1374.c index 15edf40828b..8a2ff0c114d 100644 --- a/drivers/i2c/chips/ds1374.c +++ b/drivers/i2c/chips/ds1374.c @@ -207,6 +207,10 @@ static int ds1374_probe(struct i2c_adapter *adap, int addr, int kind) client->driver = &ds1374_driver; ds1374_workqueue = create_singlethread_workqueue("ds1374"); + if (!ds1374_workqueue) { + kfree(client); + return -ENOMEM; /* most expected reason */ + } if ((rc = i2c_attach_client(client)) != 0) { kfree(client); diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 5d134bb75ba..ca2e4f830c3 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -103,8 +103,10 @@ config BLK_DEV_IDE_SATA ---help--- There are two drivers for Serial ATA controllers. - The main driver, "libata", exists inside the SCSI subsystem - and supports most modern SATA controllers. + The main driver, "libata", uses the SCSI subsystem + and supports most modern SATA controllers. In order to use it + you may take a look at "Serial ATA (prod) and Parallel ATA + (experimental) drivers". The IDE driver (which you are currently configuring) supports a few first-generation SATA controllers. @@ -434,24 +436,8 @@ config BLK_DEV_IDEDMA_FORCED Generally say N here. -config IDEDMA_PCI_AUTO - bool "Use PCI DMA by default when available" - ---help--- - Prior to kernel version 2.1.112, Linux used to automatically use - DMA for IDE drives and chipsets which support it. Due to concerns - about a couple of cases where buggy hardware may have caused damage, - the default is now to NOT use DMA automatically. To revert to the - previous behaviour, say Y to this question. - - If you suspect your hardware is at all flakey, say N here. - Do NOT email the IDE kernel people regarding this issue! - - It is normally safe to answer Y to this question unless your - motherboard uses a VIA VP2 chipset, in which case you should say N. - config IDEDMA_ONLYDISK bool "Enable DMA only for disks " - depends on IDEDMA_PCI_AUTO help This is used if you know your ATAPI Devices are going to fail DMA Transfers. @@ -769,6 +755,14 @@ config BLK_DEV_TC86C001 help This driver adds support for Toshiba TC86C001 GOKU-S chip. +config BLK_DEV_CELLEB + tristate "Toshiba's Cell Reference Set IDE support" + depends on PPC_CELLEB + help + This driver provides support for the built-in IDE controller on + Toshiba Cell Reference Board. + If unsure, say Y. + endif config BLK_DEV_IDE_PMAC @@ -800,14 +794,6 @@ config BLK_DEV_IDEDMA_PMAC to transfer data to and from memory. Saying Y is safe and improves performance. -config BLK_DEV_IDE_CELLEB - bool "Toshiba's Cell Reference Set IDE support" - depends on PPC_CELLEB - help - This driver provides support for the built-in IDE controller on - Toshiba Cell Reference Board. - If unsure, say Y. - config BLK_DEV_IDE_SWARM tristate "IDE for Sibyte evaluation boards" depends on SIBYTE_SB1xxx_SOC @@ -851,19 +837,6 @@ config BLK_DEV_IDEDMA_ICS Say Y here if you want to add DMA (Direct Memory Access) support to the ICS IDE driver. -config IDEDMA_ICS_AUTO - bool "Use ICS DMA by default" - depends on BLK_DEV_IDEDMA_ICS - help - Prior to kernel version 2.1.112, Linux used to automatically use - DMA for IDE drives and chipsets which support it. Due to concerns - about a couple of cases where buggy hardware may have caused damage, - the default is now to NOT use DMA automatically. To revert to the - previous behaviour, say Y to this question. - - If you suspect your hardware is at all flakey, say N here. - Do NOT email the IDE kernel people regarding this issue! - config BLK_DEV_IDE_RAPIDE tristate "RapIDE interface support" depends on ARM && ARCH_ACORN @@ -1086,9 +1059,6 @@ config IDEDMA_IVB It is normally safe to answer Y; however, the default is N. -config IDEDMA_AUTO - def_bool IDEDMA_PCI_AUTO || IDEDMA_ICS_AUTO - endif config BLK_DEV_HD_ONLY diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index 28feedfbd21..d9f029e8ff7 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -37,7 +37,6 @@ ide-core-$(CONFIG_BLK_DEV_Q40IDE) += legacy/q40ide.o # built-in only drivers from ppc/ ide-core-$(CONFIG_BLK_DEV_MPC8xx_IDE) += ppc/mpc8xx.o ide-core-$(CONFIG_BLK_DEV_IDE_PMAC) += ppc/pmac.o -ide-core-$(CONFIG_BLK_DEV_IDE_CELLEB) += ppc/scc_pata.o # built-in only drivers from h8300/ ide-core-$(CONFIG_H8300) += h8300/ide-h8300.o diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c index 40e5c66b81c..e2953fc1faf 100644 --- a/drivers/ide/arm/icside.c +++ b/drivers/ide/arm/icside.c @@ -196,11 +196,6 @@ static void icside_maskproc(ide_drive_t *drive, int mask) } #ifdef CONFIG_BLK_DEV_IDEDMA_ICS - -#ifndef CONFIG_IDEDMA_ICS_AUTO -#warning CONFIG_IDEDMA_ICS_AUTO=n support is obsolete, and will be removed soon. -#endif - /* * SG-DMA support. * @@ -474,12 +469,6 @@ static int icside_dma_lostirq(ide_drive_t *drive) static void icside_dma_init(ide_hwif_t *hwif) { - int autodma = 0; - -#ifdef CONFIG_IDEDMA_ICS_AUTO - autodma = 1; -#endif - printk(" %s: SG-DMA", hwif->name); hwif->atapi_dma = 1; @@ -489,7 +478,7 @@ static void icside_dma_init(ide_hwif_t *hwif) hwif->dmatable_cpu = NULL; hwif->dmatable_dma = 0; hwif->speedproc = icside_set_speed; - hwif->autodma = autodma; + hwif->autodma = 1; hwif->ide_dma_check = icside_dma_check; hwif->dma_host_off = icside_dma_host_off; diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 45a928c058c..638becda81c 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -735,6 +735,15 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) cdrom_saw_media_change (drive); /*printk("%s: media changed\n",drive->name);*/ return 0; + } else if ((sense_key == ILLEGAL_REQUEST) && + (rq->cmd[0] == GPCMD_START_STOP_UNIT)) { + /* + * Don't print error message for this condition-- + * SFF8090i indicates that 5/24/00 is the correct + * response to a request to close the tray if the + * drive doesn't have that capability. + * cdrom_log_sense() knows this! + */ } else if (!(rq->cmd_flags & REQ_QUIET)) { /* Otherwise, print an error. */ ide_dump_status(drive, "packet command error", stat); diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 08e7cd043bc..fd213088b06 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -767,7 +767,7 @@ int ide_set_dma(ide_drive_t *drive) switch(rc) { case -1: /* DMA needs to be disabled */ hwif->dma_off_quietly(drive); - return 0; + return -1; case 0: /* DMA needs to be enabled */ return hwif->ide_dma_on(drive); case 1: /* DMA setting cannot be changed */ diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index c193553f6fe..8670112f1d3 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -519,21 +519,24 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8 if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ && hwif->err_stops_fifo == 0) try_to_flush_leftover_data(drive); + if (rq->errors >= ERROR_MAX || blk_noretry_request(rq)) { + ide_kill_rq(drive, rq); + return ide_stopped; + } + if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT)) - /* force an abort */ - hwif->OUTB(WIN_IDLEIMMEDIATE, IDE_COMMAND_REG); + rq->errors |= ERROR_RESET; - if (rq->errors >= ERROR_MAX || blk_noretry_request(rq)) - ide_kill_rq(drive, rq); - else { - if ((rq->errors & ERROR_RESET) == ERROR_RESET) { - ++rq->errors; - return ide_do_reset(drive); - } - if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) - drive->special.b.recalibrate = 1; + if ((rq->errors & ERROR_RESET) == ERROR_RESET) { ++rq->errors; + return ide_do_reset(drive); } + + if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) + drive->special.b.recalibrate = 1; + + ++rq->errors; + return ide_stopped; } @@ -1025,6 +1028,13 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) if (!drive->special.all) { ide_driver_t *drv; + /* + * We reset the drive so we need to issue a SETFEATURES. + * Do it _after_ do_special() restored device parameters. + */ + if (drive->current_speed == 0xff) + ide_config_drive_speed(drive, drive->desired_speed); + if (rq->cmd_type == REQ_TYPE_ATA_CMD || rq->cmd_type == REQ_TYPE_ATA_TASK || rq->cmd_type == REQ_TYPE_ATA_TASKFILE) @@ -1216,6 +1226,7 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) #endif /* so that ide_timer_expiry knows what to do */ hwgroup->sleeping = 1; + hwgroup->req_gen_timer = hwgroup->req_gen; mod_timer(&hwgroup->timer, sleep); /* we purposely leave hwgroup->busy==1 * while sleeping */ @@ -1401,7 +1412,8 @@ void ide_timer_expiry (unsigned long data) spin_lock_irqsave(&ide_lock, flags); - if ((handler = hwgroup->handler) == NULL) { + if (((handler = hwgroup->handler) == NULL) || + (hwgroup->req_gen != hwgroup->req_gen_timer)) { /* * Either a marginal timeout occurred * (got the interrupt just as timer expired), @@ -1429,6 +1441,7 @@ void ide_timer_expiry (unsigned long data) if ((wait = expiry(drive)) > 0) { /* reset timer */ hwgroup->timer.expires = jiffies + wait; + hwgroup->req_gen_timer = hwgroup->req_gen; add_timer(&hwgroup->timer); spin_unlock_irqrestore(&ide_lock, flags); return; @@ -1643,6 +1656,7 @@ irqreturn_t ide_intr (int irq, void *dev_id) printk(KERN_ERR "%s: ide_intr: hwgroup->busy was 0 ??\n", drive->name); } hwgroup->handler = NULL; + hwgroup->req_gen++; del_timer(&hwgroup->timer); spin_unlock(&ide_lock); diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index bd513f5a232..3caa176b315 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -583,8 +583,12 @@ u8 eighty_ninty_three (ide_drive_t *drive) if(!(drive->id->hw_config & 0x4000)) return 0; #endif /* CONFIG_IDEDMA_IVB */ - if (!(drive->id->hw_config & 0x2000)) - return 0; + /* + * FIXME: + * - change master/slave IDENTIFY order + * - force bit13 (80c cable present) check + * (unless the slave device is pre-ATA3) + */ return 1; } @@ -885,6 +889,7 @@ static void __ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, hwgroup->handler = handler; hwgroup->expiry = expiry; hwgroup->timer.expires = jiffies + timeout; + hwgroup->req_gen_timer = hwgroup->req_gen; add_timer(&hwgroup->timer); } @@ -925,6 +930,7 @@ void ide_execute_command(ide_drive_t *drive, task_ioreg_t cmd, ide_handler_t *ha hwgroup->handler = handler; hwgroup->expiry = expiry; hwgroup->timer.expires = jiffies + timeout; + hwgroup->req_gen_timer = hwgroup->req_gen; add_timer(&hwgroup->timer); hwif->OUTBSYNC(drive, cmd, IDE_COMMAND_REG); /* Drive takes 400nS to respond, we must avoid the IRQ being @@ -1090,6 +1096,9 @@ static void pre_reset(ide_drive_t *drive) if (HWIF(drive)->pre_reset != NULL) HWIF(drive)->pre_reset(drive); + if (drive->current_speed != 0xff) + drive->desired_speed = drive->current_speed; + drive->current_speed = 0xff; } /* diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index dfbd7445852..ae5bf2be6f5 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -177,11 +177,7 @@ DECLARE_MUTEX(ide_cfg_sem); static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */ #endif -#ifdef CONFIG_IDEDMA_AUTO int noautodma = 0; -#else -int noautodma = 1; -#endif EXPORT_SYMBOL(noautodma); @@ -1128,17 +1124,40 @@ static int set_io_32bit(ide_drive_t *drive, int arg) static int set_using_dma (ide_drive_t *drive, int arg) { #ifdef CONFIG_BLK_DEV_IDEDMA + ide_hwif_t *hwif = drive->hwif; + int err = -EPERM; + if (!drive->id || !(drive->id->capability & 1)) - return -EPERM; - if (HWIF(drive)->ide_dma_check == NULL) - return -EPERM; + goto out; + + if (hwif->ide_dma_check == NULL) + goto out; + + err = -EBUSY; + if (ide_spin_wait_hwgroup(drive)) + goto out; + /* + * set ->busy flag, unlock and let it ride + */ + hwif->hwgroup->busy = 1; + spin_unlock_irq(&ide_lock); + + err = 0; + if (arg) { - if (ide_set_dma(drive)) - return -EIO; - if (HWIF(drive)->ide_dma_on(drive)) return -EIO; + if (ide_set_dma(drive) || hwif->ide_dma_on(drive)) + err = -EIO; } else ide_dma_off(drive); - return 0; + + /* + * lock, clear ->busy flag and unlock before leaving + */ + spin_lock_irq(&ide_lock); + hwif->hwgroup->busy = 0; + spin_unlock_irq(&ide_lock); +out: + return err; #else return -EPERM; #endif @@ -1943,6 +1962,8 @@ static char *media_string(ide_drive_t *drive) return "tape"; case ide_floppy: return "floppy"; + case ide_optical: + return "optical"; default: return "UNKNOWN"; } diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c index b2dc028dc8c..d54d9fe92a7 100644 --- a/drivers/ide/mips/au1xxx-ide.c +++ b/drivers/ide/mips/au1xxx-ide.c @@ -639,6 +639,7 @@ static int au_ide_probe(struct device *dev) _auide_hwif *ahwif = &auide_hwif; ide_hwif_t *hwif; struct resource *res; + hw_regs_t *hw; int ret = 0; #if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA) @@ -681,7 +682,7 @@ static int au_ide_probe(struct device *dev) /* FIXME: This might possibly break PCMCIA IDE devices */ hwif = &ide_hwifs[pdev->id]; - hw_regs_t *hw = &hwif->hw; + hw = &hwif->hw; hwif->irq = hw->irq = ahwif->irq; hwif->chipset = ide_au1xxx; diff --git a/drivers/ide/pci/Makefile b/drivers/ide/pci/Makefile index 6591ff4753c..95d1ea8f1f1 100644 --- a/drivers/ide/pci/Makefile +++ b/drivers/ide/pci/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_BLK_DEV_AEC62XX) += aec62xx.o obj-$(CONFIG_BLK_DEV_ALI15X3) += alim15x3.o obj-$(CONFIG_BLK_DEV_AMD74XX) += amd74xx.o obj-$(CONFIG_BLK_DEV_ATIIXP) += atiixp.o +obj-$(CONFIG_BLK_DEV_CELLEB) += scc_pata.o obj-$(CONFIG_BLK_DEV_CMD64X) += cmd64x.o obj-$(CONFIG_BLK_DEV_CS5520) += cs5520.o obj-$(CONFIG_BLK_DEV_CS5530) += cs5530.o diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c index b0d4825c56a..561197f7b5b 100644 --- a/drivers/ide/pci/cmd64x.c +++ b/drivers/ide/pci/cmd64x.c @@ -1,6 +1,6 @@ /* $Id: cmd64x.c,v 1.21 2000/01/30 23:23:16 * - * linux/drivers/ide/pci/cmd64x.c Version 1.41 Feb 3, 2007 + * linux/drivers/ide/pci/cmd64x.c Version 1.42 Feb 8, 2007 * * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines. * Note, this driver is not used at all on other systems because @@ -189,6 +189,11 @@ static int cmd64x_get_info (char *buffer, char **addr, off_t offset, int count) #endif /* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) */ +static u8 quantize_timing(int timing, int quant) +{ + return (timing + quant - 1) / quant; +} + /* * This routine writes the prepared setup/active/recovery counts * for a drive into the cmd646 chipset registers to active them. @@ -268,47 +273,37 @@ static void program_drive_counts (ide_drive_t *drive, int setup_count, int activ */ static u8 cmd64x_tune_pio (ide_drive_t *drive, u8 mode_wanted) { - int setup_time, active_time, recovery_time; - int clock_time, pio_mode, cycle_time; - u8 recovery_count2, cycle_count; - int setup_count, active_count, recovery_count; - int bus_speed = system_bus_clock(); - ide_pio_data_t d; + int setup_time, active_time, cycle_time; + u8 cycle_count, setup_count, active_count, recovery_count; + u8 pio_mode; + int clock_time = 1000 / system_bus_clock(); + ide_pio_data_t pio; - pio_mode = ide_get_best_pio_mode(drive, mode_wanted, 5, &d); - cycle_time = d.cycle_time; + pio_mode = ide_get_best_pio_mode(drive, mode_wanted, 5, &pio); + cycle_time = pio.cycle_time; - /* - * I copied all this complicated stuff from cmd640.c and made a few - * minor changes. For now I am just going to pray that it is correct. - */ setup_time = ide_pio_timings[pio_mode].setup_time; active_time = ide_pio_timings[pio_mode].active_time; - recovery_time = cycle_time - (setup_time + active_time); - clock_time = 1000 / bus_speed; - cycle_count = (cycle_time + clock_time - 1) / clock_time; - - setup_count = (setup_time + clock_time - 1) / clock_time; - active_count = (active_time + clock_time - 1) / clock_time; + setup_count = quantize_timing( setup_time, clock_time); + cycle_count = quantize_timing( cycle_time, clock_time); + active_count = quantize_timing(active_time, clock_time); - recovery_count = (recovery_time + clock_time - 1) / clock_time; - recovery_count2 = cycle_count - (setup_count + active_count); - if (recovery_count2 > recovery_count) - recovery_count = recovery_count2; + recovery_count = cycle_count - active_count; + /* program_drive_counts() takes care of zero recovery cycles */ if (recovery_count > 16) { active_count += recovery_count - 16; recovery_count = 16; } if (active_count > 16) - active_count = 16; /* maximum allowed by cmd646 */ + active_count = 16; /* maximum allowed by cmd64x */ program_drive_counts (drive, setup_count, active_count, recovery_count); cmdprintk("%s: PIO mode wanted %d, selected %d (%dns)%s, " "clocks=%d/%d/%d\n", drive->name, mode_wanted, pio_mode, cycle_time, - d.overridden ? " (overriding vendor mode)" : "", + pio.overridden ? " (overriding vendor mode)" : "", setup_count, active_count, recovery_count); return pio_mode; diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c index 53f25500c22..be4fc96c29e 100644 --- a/drivers/ide/pci/jmicron.c +++ b/drivers/ide/pci/jmicron.c @@ -240,12 +240,31 @@ static int __devinit jmicron_init_one(struct pci_dev *dev, const struct pci_devi return 0; } +/* If libata is configured, jmicron PCI quirk will configure it such + * that the SATA ports are in AHCI function while the PATA ports are + * in a separate IDE function. In such cases, match device class and + * attach only to IDE. If libata isn't configured, keep the old + * behavior for backward compatibility. + */ +#if defined(CONFIG_ATA) || defined(CONFIG_ATA_MODULE) +#define JMB_CLASS PCI_CLASS_STORAGE_IDE << 8 +#define JMB_CLASS_MASK 0xffff00 +#else +#define JMB_CLASS 0 +#define JMB_CLASS_MASK 0 +#endif + static struct pci_device_id jmicron_pci_tbl[] = { - { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, - { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, - { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, - { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, + { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, + PCI_ANY_ID, PCI_ANY_ID, JMB_CLASS, JMB_CLASS_MASK, 0}, + { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, + PCI_ANY_ID, PCI_ANY_ID, JMB_CLASS, JMB_CLASS_MASK, 1}, + { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, + PCI_ANY_ID, PCI_ANY_ID, JMB_CLASS, JMB_CLASS_MASK, 2}, + { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, + PCI_ANY_ID, PCI_ANY_ID, JMB_CLASS, JMB_CLASS_MASK, 3}, + { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, + PCI_ANY_ID, PCI_ANY_ID, JMB_CLASS, JMB_CLASS_MASK, 4}, { 0, }, }; diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c index 6ceb25bc5a7..ace98929cc3 100644 --- a/drivers/ide/pci/pdc202xx_new.c +++ b/drivers/ide/pci/pdc202xx_new.c @@ -255,7 +255,7 @@ static int config_chipset_for_dma(ide_drive_t *drive) printk(KERN_WARNING "%s reduced to Ultra33 mode.\n", drive->name); } - if (drive->media != ide_disk) + if (drive->media != ide_disk && drive->media != ide_cdrom) return 0; if (id->capability & 4) { @@ -545,6 +545,7 @@ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif) hwif->drives[0].autotune = hwif->drives[1].autotune = 1; + hwif->atapi_dma = 1; hwif->ultra_mask = 0x7f; hwif->mwdma_mask = 0x07; diff --git a/drivers/ide/ppc/scc_pata.c b/drivers/ide/pci/scc_pata.c index f84bf791f72..f84bf791f72 100644 --- a/drivers/ide/ppc/scc_pata.c +++ b/drivers/ide/pci/scc_pata.c diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index a52c80fe7d3..118fb3205ca 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -505,11 +505,6 @@ static void ide_hwif_setup_dma(struct pci_dev *dev, ide_pci_device_t *d, ide_hwi } } } - -#ifndef CONFIG_IDEDMA_PCI_AUTO -#warning CONFIG_IDEDMA_PCI_AUTO=n support is obsolete, and will be removed soon. -#endif - #endif /* CONFIG_BLK_DEV_IDEDMA_PCI*/ /** diff --git a/drivers/ieee1394/Kconfig b/drivers/ieee1394/Kconfig index b8a47342cd2..cd84a55ecf2 100644 --- a/drivers/ieee1394/Kconfig +++ b/drivers/ieee1394/Kconfig @@ -138,9 +138,9 @@ config IEEE1394_DV1394 tristate "OHCI-DV I/O support (deprecated)" depends on IEEE1394 && IEEE1394_OHCI1394 help - The dv1394 driver will be removed from Linux in a future release. - Its functionality is now provided by raw1394 together with libraries - such as libiec61883. + The dv1394 driver is unsupported and may be removed from Linux in a + future release. Its functionality is now provided by raw1394 together + with libraries such as libiec61883. config IEEE1394_RAWIO tristate "Raw IEEE1394 I/O support" diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index dee9529aa8e..026e38face5 100644 --- a/drivers/ieee1394/dv1394.c +++ b/drivers/ieee1394/dv1394.c @@ -2564,8 +2564,8 @@ static int __init dv1394_init_module(void) int ret; printk(KERN_WARNING - "WARNING: The dv1394 driver is unsupported and will be removed " - "from Linux soon. Use raw1394 instead.\n"); + "NOTE: The dv1394 driver is unsupported and may be removed in a " + "future Linux release. Use raw1394 instead.\n"); cdev_init(&dv1394_cdev, &dv1394_fops); dv1394_cdev.owner = THIS_MODULE; diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index a9531352198..03e44b337eb 100644 --- a/drivers/ieee1394/eth1394.c +++ b/drivers/ieee1394/eth1394.c @@ -584,7 +584,10 @@ static void ether1394_add_host (struct hpsb_host *host) } SET_MODULE_OWNER(dev); +#if 0 + /* FIXME - Is this the correct parent device anyway? */ SET_NETDEV_DEV(dev, &host->device); +#endif priv = netdev_priv(dev); diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index d441815a3e0..fde92ce4515 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -1821,7 +1821,7 @@ static int cma_alloc_port(struct idr *ps, struct rdma_id_private *id_priv, struct rdma_bind_list *bind_list; int port, ret; - bind_list = kmalloc(sizeof *bind_list, GFP_KERNEL); + bind_list = kzalloc(sizeof *bind_list, GFP_KERNEL); if (!bind_list) return -ENOMEM; diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index b516b93b855..c859134c1da 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c @@ -266,7 +266,7 @@ static int ucma_event_handler(struct rdma_cm_id *cm_id, mutex_lock(&ctx->file->mut); if (event->event == RDMA_CM_EVENT_CONNECT_REQUEST) { if (!ctx->backlog) { - ret = -EDQUOT; + ret = -ENOMEM; kfree(uevent); goto out; } diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.c b/drivers/infiniband/hw/cxgb3/cxio_hal.c index d737c738d87..f5e9aeec6f6 100644 --- a/drivers/infiniband/hw/cxgb3/cxio_hal.c +++ b/drivers/infiniband/hw/cxgb3/cxio_hal.c @@ -36,6 +36,7 @@ #include <linux/sched.h> #include <linux/spinlock.h> #include <linux/pci.h> +#include <linux/dma-mapping.h> #include "cxio_resource.h" #include "cxio_hal.h" @@ -497,9 +498,9 @@ static int cxio_hal_init_ctrl_qp(struct cxio_rdev *rdev_p) u64 sge_cmd, ctx0, ctx1; u64 base_addr; struct t3_modify_qp_wr *wqe; - struct sk_buff *skb = alloc_skb(sizeof(*wqe), GFP_KERNEL); - + struct sk_buff *skb; + skb = alloc_skb(sizeof(*wqe), GFP_KERNEL); if (!skb) { PDBG("%s alloc_skb failed\n", __FUNCTION__); return -ENOMEM; @@ -507,7 +508,7 @@ static int cxio_hal_init_ctrl_qp(struct cxio_rdev *rdev_p) err = cxio_hal_init_ctrl_cq(rdev_p); if (err) { PDBG("%s err %d initializing ctrl_cq\n", __FUNCTION__, err); - return err; + goto err; } rdev_p->ctrl_qp.workq = dma_alloc_coherent( &(rdev_p->rnic_info.pdev->dev), @@ -517,7 +518,8 @@ static int cxio_hal_init_ctrl_qp(struct cxio_rdev *rdev_p) GFP_KERNEL); if (!rdev_p->ctrl_qp.workq) { PDBG("%s dma_alloc_coherent failed\n", __FUNCTION__); - return -ENOMEM; + err = -ENOMEM; + goto err; } pci_unmap_addr_set(&rdev_p->ctrl_qp, mapping, rdev_p->ctrl_qp.dma_addr); @@ -555,6 +557,9 @@ static int cxio_hal_init_ctrl_qp(struct cxio_rdev *rdev_p) rdev_p->ctrl_qp.workq, 1 << T3_CTRL_QP_SIZE_LOG2); skb->priority = CPL_PRIORITY_CONTROL; return (cxgb3_ofld_send(rdev_p->t3cdev_p, skb)); +err: + kfree_skb(skb); + return err; } static int cxio_hal_destroy_ctrl_qp(struct cxio_rdev *rdev_p) diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c index b21fde8b659..d0ed1d35ca3 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_cm.c +++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c @@ -305,8 +305,7 @@ static int status2errno(int status) */ static struct sk_buff *get_skb(struct sk_buff *skb, int len, gfp_t gfp) { - if (skb) { - BUG_ON(skb_cloned(skb)); + if (skb && !skb_is_nonlinear(skb) && !skb_cloned(skb)) { skb_trim(skb, 0); skb_get(skb); } else { @@ -1415,6 +1414,7 @@ static int peer_close(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) wake_up(&ep->com.waitq); break; case FPDU_MODE: + start_ep_timer(ep); __state_set(&ep->com, CLOSING); attrs.next_state = IWCH_QP_STATE_CLOSING; iwch_modify_qp(ep->com.qp->rhp, ep->com.qp, @@ -1425,7 +1425,6 @@ static int peer_close(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) disconnect = 0; break; case CLOSING: - start_ep_timer(ep); __state_set(&ep->com, MORIBUND); disconnect = 0; break; @@ -1487,8 +1486,10 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) case CONNECTING: break; case MPA_REQ_WAIT: + stop_ep_timer(ep); break; case MPA_REQ_SENT: + stop_ep_timer(ep); connect_reply_upcall(ep, -ECONNRESET); break; case MPA_REP_SENT: @@ -1507,9 +1508,10 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) get_ep(&ep->com); break; case MORIBUND: + case CLOSING: stop_ep_timer(ep); + /*FALLTHROUGH*/ case FPDU_MODE: - case CLOSING: if (ep->com.cm_id && ep->com.qp) { attrs.next_state = IWCH_QP_STATE_ERROR; ret = iwch_modify_qp(ep->com.qp->rhp, @@ -1570,7 +1572,6 @@ static int close_con_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) spin_lock_irqsave(&ep->com.lock, flags); switch (ep->com.state) { case CLOSING: - start_ep_timer(ep); __state_set(&ep->com, MORIBUND); break; case MORIBUND: @@ -1586,6 +1587,8 @@ static int close_con_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) __state_set(&ep->com, DEAD); release = 1; break; + case ABORTING: + break; case DEAD: default: BUG_ON(1); @@ -1659,6 +1662,7 @@ static void ep_timeout(unsigned long arg) break; case MPA_REQ_WAIT: break; + case CLOSING: case MORIBUND: if (ep->com.cm_id && ep->com.qp) { attrs.next_state = IWCH_QP_STATE_ERROR; @@ -1687,12 +1691,11 @@ int iwch_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len) return -ECONNRESET; } BUG_ON(state_read(&ep->com) != MPA_REQ_RCVD); - state_set(&ep->com, CLOSING); if (mpa_rev == 0) abort_connection(ep, NULL, GFP_KERNEL); else { err = send_mpa_reject(ep, pdata, pdata_len); - err = send_halfclose(ep, GFP_KERNEL); + err = iwch_ep_disconnect(ep, 0, GFP_KERNEL); } return 0; } @@ -1957,11 +1960,11 @@ int iwch_ep_disconnect(struct iwch_ep *ep, int abrupt, gfp_t gfp) case MPA_REQ_RCVD: case MPA_REP_SENT: case FPDU_MODE: + start_ep_timer(ep); ep->com.state = CLOSING; close = 1; break; case CLOSING: - start_ep_timer(ep); ep->com.state = MORIBUND; close = 1; break; diff --git a/drivers/infiniband/hw/cxgb3/iwch_ev.c b/drivers/infiniband/hw/cxgb3/iwch_ev.c index 54362afbf72..b40676662a8 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_ev.c +++ b/drivers/infiniband/hw/cxgb3/iwch_ev.c @@ -47,12 +47,6 @@ static void post_qp_event(struct iwch_dev *rnicp, struct iwch_cq *chp, struct iwch_qp_attributes attrs; struct iwch_qp *qhp; - printk(KERN_ERR "%s - AE qpid 0x%x opcode %d status 0x%x " - "type %d wrid.hi 0x%x wrid.lo 0x%x \n", __FUNCTION__, - CQE_QPID(rsp_msg->cqe), CQE_OPCODE(rsp_msg->cqe), - CQE_STATUS(rsp_msg->cqe), CQE_TYPE(rsp_msg->cqe), - CQE_WRID_HI(rsp_msg->cqe), CQE_WRID_LOW(rsp_msg->cqe)); - spin_lock(&rnicp->lock); qhp = get_qhp(rnicp, CQE_QPID(rsp_msg->cqe)); @@ -73,6 +67,12 @@ static void post_qp_event(struct iwch_dev *rnicp, struct iwch_cq *chp, return; } + printk(KERN_ERR "%s - AE qpid 0x%x opcode %d status 0x%x " + "type %d wrid.hi 0x%x wrid.lo 0x%x \n", __FUNCTION__, + CQE_QPID(rsp_msg->cqe), CQE_OPCODE(rsp_msg->cqe), + CQE_STATUS(rsp_msg->cqe), CQE_TYPE(rsp_msg->cqe), + CQE_WRID_HI(rsp_msg->cqe), CQE_WRID_LOW(rsp_msg->cqe)); + atomic_inc(&qhp->refcnt); spin_unlock(&rnicp->lock); diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c index 9947a144a92..24e0df04f7d 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_provider.c +++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c @@ -331,6 +331,7 @@ static int iwch_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) int ret = 0; struct iwch_mm_entry *mm; struct iwch_ucontext *ucontext; + u64 addr; PDBG("%s pgoff 0x%lx key 0x%x len %d\n", __FUNCTION__, vma->vm_pgoff, key, len); @@ -345,10 +346,11 @@ static int iwch_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) mm = remove_mmap(ucontext, key, len); if (!mm) return -EINVAL; + addr = mm->addr; kfree(mm); - if ((mm->addr >= rdev_p->rnic_info.udbell_physbase) && - (mm->addr < (rdev_p->rnic_info.udbell_physbase + + if ((addr >= rdev_p->rnic_info.udbell_physbase) && + (addr < (rdev_p->rnic_info.udbell_physbase + rdev_p->rnic_info.udbell_len))) { /* @@ -362,7 +364,7 @@ static int iwch_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND; vma->vm_flags &= ~VM_MAYREAD; ret = io_remap_pfn_range(vma, vma->vm_start, - mm->addr >> PAGE_SHIFT, + addr >> PAGE_SHIFT, len, vma->vm_page_prot); } else { @@ -370,7 +372,7 @@ static int iwch_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) * Map WQ or CQ contig dma memory... */ ret = remap_pfn_range(vma, vma->vm_start, - mm->addr >> PAGE_SHIFT, + addr >> PAGE_SHIFT, len, vma->vm_page_prot); } @@ -463,9 +465,6 @@ static struct ib_mr *iwch_register_phys_mem(struct ib_pd *pd, php = to_iwch_pd(pd); rhp = php->rhp; - acc = iwch_convert_access(acc); - - mhp = kzalloc(sizeof(*mhp), GFP_KERNEL); if (!mhp) return ERR_PTR(-ENOMEM); @@ -491,12 +490,7 @@ static struct ib_mr *iwch_register_phys_mem(struct ib_pd *pd, mhp->attr.pdid = php->pdid; mhp->attr.zbva = 0; - /* NOTE: TPT perms are backwards from BIND WR perms! */ - mhp->attr.perms = (acc & 0x1) << 3; - mhp->attr.perms |= (acc & 0x2) << 1; - mhp->attr.perms |= (acc & 0x4) >> 1; - mhp->attr.perms |= (acc & 0x8) >> 3; - + mhp->attr.perms = iwch_ib_to_tpt_access(acc); mhp->attr.va_fbo = *iova_start; mhp->attr.page_size = shift - 12; @@ -525,7 +519,6 @@ static int iwch_reregister_phys_mem(struct ib_mr *mr, struct iwch_mr mh, *mhp; struct iwch_pd *php; struct iwch_dev *rhp; - int new_acc; __be64 *page_list = NULL; int shift = 0; u64 total_size; @@ -546,19 +539,20 @@ static int iwch_reregister_phys_mem(struct ib_mr *mr, if (rhp != php->rhp) return -EINVAL; - new_acc = mhp->attr.perms; - memcpy(&mh, mhp, sizeof *mhp); if (mr_rereg_mask & IB_MR_REREG_PD) php = to_iwch_pd(pd); if (mr_rereg_mask & IB_MR_REREG_ACCESS) - mh.attr.perms = iwch_convert_access(acc); - if (mr_rereg_mask & IB_MR_REREG_TRANS) + mh.attr.perms = iwch_ib_to_tpt_access(acc); + if (mr_rereg_mask & IB_MR_REREG_TRANS) { ret = build_phys_page_list(buffer_list, num_phys_buf, iova_start, &total_size, &npages, &shift, &page_list); + if (ret) + return ret; + } ret = iwch_reregister_mem(rhp, php, &mh, shift, page_list, npages); kfree(page_list); @@ -568,7 +562,7 @@ static int iwch_reregister_phys_mem(struct ib_mr *mr, if (mr_rereg_mask & IB_MR_REREG_PD) mhp->attr.pdid = php->pdid; if (mr_rereg_mask & IB_MR_REREG_ACCESS) - mhp->attr.perms = acc; + mhp->attr.perms = iwch_ib_to_tpt_access(acc); if (mr_rereg_mask & IB_MR_REREG_TRANS) { mhp->attr.zbva = 0; mhp->attr.va_fbo = *iova_start; @@ -613,8 +607,6 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, struct ib_umem *region, goto err; } - acc = iwch_convert_access(acc); - i = n = 0; list_for_each_entry(chunk, ®ion->chunk_list, list) @@ -630,10 +622,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, struct ib_umem *region, mhp->rhp = rhp; mhp->attr.pdid = php->pdid; mhp->attr.zbva = 0; - mhp->attr.perms = (acc & 0x1) << 3; - mhp->attr.perms |= (acc & 0x2) << 1; - mhp->attr.perms |= (acc & 0x4) >> 1; - mhp->attr.perms |= (acc & 0x8) >> 3; + mhp->attr.perms = iwch_ib_to_tpt_access(acc); mhp->attr.va_fbo = region->virt_base; mhp->attr.page_size = shift - 12; mhp->attr.len = (u32) region->length; @@ -736,10 +725,8 @@ static int iwch_destroy_qp(struct ib_qp *ib_qp) qhp = to_iwch_qp(ib_qp); rhp = qhp->rhp; - if (qhp->attr.state == IWCH_QP_STATE_RTS) { - attrs.next_state = IWCH_QP_STATE_ERROR; - iwch_modify_qp(rhp, qhp, IWCH_QP_ATTR_NEXT_STATE, &attrs, 0); - } + attrs.next_state = IWCH_QP_STATE_ERROR; + iwch_modify_qp(rhp, qhp, IWCH_QP_ATTR_NEXT_STATE, &attrs, 0); wait_event(qhp->wait, !qhp->ep); remove_handle(rhp, &rhp->qpidr, qhp->wq.qpid); diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.h b/drivers/infiniband/hw/cxgb3/iwch_provider.h index de0fe1b93a0..93bcc56756b 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_provider.h +++ b/drivers/infiniband/hw/cxgb3/iwch_provider.h @@ -286,27 +286,20 @@ static inline int iwch_convert_state(enum ib_qp_state ib_state) } } -enum iwch_mem_perms { - IWCH_MEM_ACCESS_LOCAL_READ = 1 << 0, - IWCH_MEM_ACCESS_LOCAL_WRITE = 1 << 1, - IWCH_MEM_ACCESS_REMOTE_READ = 1 << 2, - IWCH_MEM_ACCESS_REMOTE_WRITE = 1 << 3, - IWCH_MEM_ACCESS_ATOMICS = 1 << 4, - IWCH_MEM_ACCESS_BINDING = 1 << 5, - IWCH_MEM_ACCESS_LOCAL = - (IWCH_MEM_ACCESS_LOCAL_READ | IWCH_MEM_ACCESS_LOCAL_WRITE), - IWCH_MEM_ACCESS_REMOTE = - (IWCH_MEM_ACCESS_REMOTE_WRITE | IWCH_MEM_ACCESS_REMOTE_READ) - /* cannot go beyond 1 << 31 */ -} __attribute__ ((packed)); - -static inline u32 iwch_convert_access(int acc) +static inline u32 iwch_ib_to_tpt_access(int acc) { - return (acc & IB_ACCESS_REMOTE_WRITE ? IWCH_MEM_ACCESS_REMOTE_WRITE : 0) - | (acc & IB_ACCESS_REMOTE_READ ? IWCH_MEM_ACCESS_REMOTE_READ : 0) | - (acc & IB_ACCESS_LOCAL_WRITE ? IWCH_MEM_ACCESS_LOCAL_WRITE : 0) | - (acc & IB_ACCESS_MW_BIND ? IWCH_MEM_ACCESS_BINDING : 0) | - IWCH_MEM_ACCESS_LOCAL_READ; + return (acc & IB_ACCESS_REMOTE_WRITE ? TPT_REMOTE_WRITE : 0) | + (acc & IB_ACCESS_REMOTE_READ ? TPT_REMOTE_READ : 0) | + (acc & IB_ACCESS_LOCAL_WRITE ? TPT_LOCAL_WRITE : 0) | + TPT_LOCAL_READ; +} + +static inline u32 iwch_ib_to_mwbind_access(int acc) +{ + return (acc & IB_ACCESS_REMOTE_WRITE ? T3_MEM_ACCESS_REM_WRITE : 0) | + (acc & IB_ACCESS_REMOTE_READ ? T3_MEM_ACCESS_REM_READ : 0) | + (acc & IB_ACCESS_LOCAL_WRITE ? T3_MEM_ACCESS_LOCAL_WRITE : 0) | + T3_MEM_ACCESS_LOCAL_READ; } enum iwch_mmid_state { diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c index 9ea00cc4a5f..0a472c9b44d 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_qp.c +++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c @@ -439,7 +439,7 @@ int iwch_bind_mw(struct ib_qp *qp, wqe->bind.type = T3_VA_BASED_TO; /* TBD: check perms */ - wqe->bind.perms = iwch_convert_access(mw_bind->mw_access_flags); + wqe->bind.perms = iwch_ib_to_mwbind_access(mw_bind->mw_access_flags); wqe->bind.mr_stag = cpu_to_be32(mw_bind->mr->lkey); wqe->bind.mw_stag = cpu_to_be32(mw->rkey); wqe->bind.mw_len = cpu_to_be32(mw_bind->length); diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h index 40404c9e281..82ded44c6ce 100644 --- a/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/drivers/infiniband/hw/ehca/ehca_classes.h @@ -52,6 +52,8 @@ struct ehca_mw; struct ehca_pd; struct ehca_av; +#include <linux/wait.h> + #include <rdma/ib_verbs.h> #include <rdma/ib_user_verbs.h> @@ -153,7 +155,9 @@ struct ehca_cq { spinlock_t cb_lock; struct hlist_head qp_hashtab[QP_HASHTAB_LEN]; struct list_head entry; - u32 nr_callbacks; + u32 nr_callbacks; /* #events assigned to cpu by scaling code */ + u32 nr_events; /* #events seen */ + wait_queue_head_t wait_completion; spinlock_t task_lock; u32 ownpid; /* mmap counter for resources mapped into user space */ diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c index 6ebfa27e4e1..e2cdc1a16fe 100644 --- a/drivers/infiniband/hw/ehca/ehca_cq.c +++ b/drivers/infiniband/hw/ehca/ehca_cq.c @@ -146,6 +146,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, spin_lock_init(&my_cq->spinlock); spin_lock_init(&my_cq->cb_lock); spin_lock_init(&my_cq->task_lock); + init_waitqueue_head(&my_cq->wait_completion); my_cq->ownpid = current->tgid; cq = &my_cq->ib_cq; @@ -302,6 +303,16 @@ create_cq_exit1: return cq; } +static int get_cq_nr_events(struct ehca_cq *my_cq) +{ + int ret; + unsigned long flags; + spin_lock_irqsave(&ehca_cq_idr_lock, flags); + ret = my_cq->nr_events; + spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); + return ret; +} + int ehca_destroy_cq(struct ib_cq *cq) { u64 h_ret; @@ -329,10 +340,11 @@ int ehca_destroy_cq(struct ib_cq *cq) } spin_lock_irqsave(&ehca_cq_idr_lock, flags); - while (my_cq->nr_callbacks) { + while (my_cq->nr_events) { spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); - yield(); + wait_event(my_cq->wait_completion, !get_cq_nr_events(my_cq)); spin_lock_irqsave(&ehca_cq_idr_lock, flags); + /* recheck nr_events to assure no cqe has just arrived */ } idr_remove(&ehca_cq_idr, my_cq->token); diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c index 3ec53c687d0..f284be1c916 100644 --- a/drivers/infiniband/hw/ehca/ehca_irq.c +++ b/drivers/infiniband/hw/ehca/ehca_irq.c @@ -66,7 +66,9 @@ static void queue_comp_task(struct ehca_cq *__cq); static struct ehca_comp_pool* pool; +#ifdef CONFIG_HOTPLUG_CPU static struct notifier_block comp_pool_callback_nb; +#endif static inline void comp_event_callback(struct ehca_cq *cq) { @@ -404,10 +406,11 @@ static inline void process_eqe(struct ehca_shca *shca, struct ehca_eqe *eqe) u32 token; unsigned long flags; struct ehca_cq *cq; + eqe_value = eqe->entry; ehca_dbg(&shca->ib_device, "eqe_value=%lx", eqe_value); if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, eqe_value)) { - ehca_dbg(&shca->ib_device, "... completion event"); + ehca_dbg(&shca->ib_device, "Got completion event"); token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value); spin_lock_irqsave(&ehca_cq_idr_lock, flags); cq = idr_find(&ehca_cq_idr, token); @@ -419,16 +422,20 @@ static inline void process_eqe(struct ehca_shca *shca, struct ehca_eqe *eqe) return; } reset_eq_pending(cq); - if (ehca_scaling_code) { + cq->nr_events++; + spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); + if (ehca_scaling_code) queue_comp_task(cq); - spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); - } else { - spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); + else { comp_event_callback(cq); + spin_lock_irqsave(&ehca_cq_idr_lock, flags); + cq->nr_events--; + if (!cq->nr_events) + wake_up(&cq->wait_completion); + spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); } } else { - ehca_dbg(&shca->ib_device, - "Got non completion event"); + ehca_dbg(&shca->ib_device, "Got non completion event"); parse_identifier(shca, eqe_value); } } @@ -478,6 +485,7 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq) "token=%x", token); continue; } + eqe_cache[eqe_cnt].cq->nr_events++; spin_unlock(&ehca_cq_idr_lock); } else eqe_cache[eqe_cnt].cq = NULL; @@ -504,12 +512,18 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq) /* call completion handler for cached eqes */ for (i = 0; i < eqe_cnt; i++) if (eq->eqe_cache[i].cq) { - if (ehca_scaling_code) { - spin_lock(&ehca_cq_idr_lock); + if (ehca_scaling_code) queue_comp_task(eq->eqe_cache[i].cq); - spin_unlock(&ehca_cq_idr_lock); - } else - comp_event_callback(eq->eqe_cache[i].cq); + else { + struct ehca_cq *cq = eq->eqe_cache[i].cq; + comp_event_callback(cq); + spin_lock_irqsave(&ehca_cq_idr_lock, flags); + cq->nr_events--; + if (!cq->nr_events) + wake_up(&cq->wait_completion); + spin_unlock_irqrestore(&ehca_cq_idr_lock, + flags); + } } else { ehca_dbg(&shca->ib_device, "Got non completion event"); parse_identifier(shca, eq->eqe_cache[i].eqe->entry); @@ -523,7 +537,6 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq) if (!eqe) break; process_eqe(shca, eqe); - eqe_cnt++; } while (1); unlock_irq_spinlock: @@ -567,8 +580,7 @@ static void __queue_comp_task(struct ehca_cq *__cq, list_add_tail(&__cq->entry, &cct->cq_list); cct->cq_jobs++; wake_up(&cct->wait_queue); - } - else + } else __cq->nr_callbacks++; spin_unlock(&__cq->task_lock); @@ -577,18 +589,21 @@ static void __queue_comp_task(struct ehca_cq *__cq, static void queue_comp_task(struct ehca_cq *__cq) { - int cpu; int cpu_id; struct ehca_cpu_comp_task *cct; + int cq_jobs; + unsigned long flags; - cpu = get_cpu(); cpu_id = find_next_online_cpu(pool); BUG_ON(!cpu_online(cpu_id)); cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id); BUG_ON(!cct); - if (cct->cq_jobs > 0) { + spin_lock_irqsave(&cct->task_lock, flags); + cq_jobs = cct->cq_jobs; + spin_unlock_irqrestore(&cct->task_lock, flags); + if (cq_jobs > 0) { cpu_id = find_next_online_cpu(pool); cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id); BUG_ON(!cct); @@ -608,11 +623,17 @@ static void run_comp_task(struct ehca_cpu_comp_task* cct) cq = list_entry(cct->cq_list.next, struct ehca_cq, entry); spin_unlock_irqrestore(&cct->task_lock, flags); comp_event_callback(cq); - spin_lock_irqsave(&cct->task_lock, flags); + spin_lock_irqsave(&ehca_cq_idr_lock, flags); + cq->nr_events--; + if (!cq->nr_events) + wake_up(&cq->wait_completion); + spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); + + spin_lock_irqsave(&cct->task_lock, flags); spin_lock(&cq->task_lock); cq->nr_callbacks--; - if (cq->nr_callbacks == 0) { + if (!cq->nr_callbacks) { list_del_init(cct->cq_list.next); cct->cq_jobs--; } @@ -714,6 +735,7 @@ static void take_over_work(struct ehca_comp_pool *pool, } +#ifdef CONFIG_HOTPLUG_CPU static int comp_pool_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) @@ -756,6 +778,7 @@ static int comp_pool_callback(struct notifier_block *nfb, return NOTIFY_OK; } +#endif int ehca_create_comp_pool(void) { @@ -786,9 +809,11 @@ int ehca_create_comp_pool(void) } } +#ifdef CONFIG_HOTPLUG_CPU comp_pool_callback_nb.notifier_call = comp_pool_callback; comp_pool_callback_nb.priority =0; register_cpu_notifier(&comp_pool_callback_nb); +#endif printk(KERN_INFO "eHCA scaling code enabled\n"); @@ -802,7 +827,9 @@ void ehca_destroy_comp_pool(void) if (!ehca_scaling_code) return; +#ifdef CONFIG_HOTPLUG_CPU unregister_cpu_notifier(&comp_pool_callback_nb); +#endif for (i = 0; i < NR_CPUS; i++) { if (cpu_online(i)) diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c index c1835121a82..059da9628bb 100644 --- a/drivers/infiniband/hw/ehca/ehca_main.c +++ b/drivers/infiniband/hw/ehca/ehca_main.c @@ -52,7 +52,7 @@ MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>"); MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver"); -MODULE_VERSION("SVNEHCA_0021"); +MODULE_VERSION("SVNEHCA_0022"); int ehca_open_aqp1 = 0; int ehca_debug_level = 0; @@ -810,7 +810,7 @@ int __init ehca_module_init(void) int ret; printk(KERN_INFO "eHCA Infiniband Device Driver " - "(Rel.: SVNEHCA_0021)\n"); + "(Rel.: SVNEHCA_0022)\n"); idr_init(&ehca_qp_idr); idr_init(&ehca_cq_idr); spin_lock_init(&ehca_qp_idr_lock); diff --git a/drivers/infiniband/hw/ipath/ipath_dma.c b/drivers/infiniband/hw/ipath/ipath_dma.c index f6f94904082..f87f003e3ef 100644 --- a/drivers/infiniband/hw/ipath/ipath_dma.c +++ b/drivers/infiniband/hw/ipath/ipath_dma.c @@ -167,7 +167,7 @@ static void *ipath_dma_alloc_coherent(struct ib_device *dev, size_t size, } static void ipath_dma_free_coherent(struct ib_device *dev, size_t size, - void *cpu_addr, dma_addr_t dma_handle) + void *cpu_addr, u64 dma_handle) { free_pages((unsigned long) cpu_addr, get_order(size)); } diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c index 5b40a846ff9..ed55979bfd3 100644 --- a/drivers/infiniband/hw/ipath/ipath_fs.c +++ b/drivers/infiniband/hw/ipath/ipath_fs.c @@ -451,12 +451,18 @@ bail: return ret; } -static void remove_file(struct dentry *parent, char *name) +static int remove_file(struct dentry *parent, char *name) { struct dentry *tmp; + int ret; tmp = lookup_one_len(name, parent, strlen(name)); + if (IS_ERR(tmp)) { + ret = PTR_ERR(tmp); + goto bail; + } + spin_lock(&dcache_lock); spin_lock(&tmp->d_lock); if (!(d_unhashed(tmp) && tmp->d_inode)) { @@ -469,6 +475,14 @@ static void remove_file(struct dentry *parent, char *name) spin_unlock(&tmp->d_lock); spin_unlock(&dcache_lock); } + + ret = 0; +bail: + /* + * We don't expect clients to care about the return value, but + * it's there if they need it. + */ + return ret; } static int remove_device_files(struct super_block *sb, diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c index 8e4846b5c64..fdb576dcfaa 100644 --- a/drivers/infiniband/hw/mthca/mthca_mr.c +++ b/drivers/infiniband/hw/mthca/mthca_mr.c @@ -881,8 +881,8 @@ int mthca_init_mr_table(struct mthca_dev *dev) } mpts = mtts = 1 << i; } else { - mpts = dev->limits.num_mtt_segs; - mtts = dev->limits.num_mpts; + mtts = dev->limits.num_mtt_segs; + mpts = dev->limits.num_mpts; } if (!mthca_is_memfree(dev) && diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 71dc84bd425..1c6b63aca26 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -1088,21 +1088,21 @@ static void mthca_unmap_memfree(struct mthca_dev *dev, static int mthca_alloc_memfree(struct mthca_dev *dev, struct mthca_qp *qp) { - int ret = 0; - if (mthca_is_memfree(dev)) { qp->rq.db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_RQ, qp->qpn, &qp->rq.db); if (qp->rq.db_index < 0) - return ret; + return -ENOMEM; qp->sq.db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_SQ, qp->qpn, &qp->sq.db); - if (qp->sq.db_index < 0) + if (qp->sq.db_index < 0) { mthca_free_db(dev, MTHCA_DB_TYPE_RQ, qp->rq.db_index); + return -ENOMEM; + } } - return ret; + return 0; } static void mthca_free_memfree(struct mthca_dev *dev, diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 3484e8ba24a..2b242a4823f 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c @@ -131,7 +131,7 @@ static struct sk_buff *ipoib_cm_alloc_rx_skb(struct net_device *dev, int id, int skb_fill_page_desc(skb, i, page, 0, PAGE_SIZE); mapping[i + 1] = ib_dma_map_page(priv->ca, skb_shinfo(skb)->frags[i].page, - 0, PAGE_SIZE, DMA_TO_DEVICE); + 0, PAGE_SIZE, DMA_FROM_DEVICE); if (unlikely(ib_dma_mapping_error(priv->ca, mapping[i + 1]))) goto partial_error; } @@ -452,7 +452,7 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_ skb->len, tx->mtu); ++priv->stats.tx_dropped; ++priv->stats.tx_errors; - ipoib_cm_skb_too_long(dev, skb, tx->mtu - INFINIBAND_ALEN); + ipoib_cm_skb_too_long(dev, skb, tx->mtu - IPOIB_ENCAP_LEN); return; } @@ -1095,7 +1095,7 @@ static void ipoib_cm_stale_task(struct work_struct *work) /* List if sorted by LRU, start from tail, * stop when we see a recently used entry */ p = list_entry(priv->cm.passive_ids.prev, typeof(*p), list); - if (time_after_eq(jiffies, p->jiffies + IPOIB_CM_RX_TIMEOUT)) + if (time_before_eq(jiffies, p->jiffies + IPOIB_CM_RX_TIMEOUT)) break; list_del_init(&p->list); spin_unlock_irqrestore(&priv->lock, flags); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index f2aa923ddbe..ba0ee5cf2ad 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -328,9 +328,9 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_tx_buf *tx_req; u64 addr; - if (unlikely(skb->len > priv->mcast_mtu + INFINIBAND_ALEN)) { + if (unlikely(skb->len > priv->mcast_mtu + IPOIB_ENCAP_LEN)) { ipoib_warn(priv, "packet len %d (> %d) too long to send, dropping\n", - skb->len, priv->mcast_mtu + INFINIBAND_ALEN); + skb->len, priv->mcast_mtu + IPOIB_ENCAP_LEN); ++priv->stats.tx_dropped; ++priv->stats.tx_errors; ipoib_cm_skb_too_long(dev, skb, priv->mcast_mtu); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index f9dbc6f6814..f2a40ae8e7d 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -380,7 +380,7 @@ static void path_rec_completion(int status, struct net_device *dev = path->dev; struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_ah *ah = NULL; - struct ipoib_neigh *neigh; + struct ipoib_neigh *neigh, *tn; struct sk_buff_head skqueue; struct sk_buff *skb; unsigned long flags; @@ -418,7 +418,7 @@ static void path_rec_completion(int status, while ((skb = __skb_dequeue(&path->queue))) __skb_queue_tail(&skqueue, skb); - list_for_each_entry(neigh, &path->neigh_list, list) { + list_for_each_entry_safe(neigh, tn, &path->neigh_list, list) { kref_get(&path->ah->ref); neigh->ah = path->ah; memcpy(&neigh->dgid.raw, &path->pathrec.dgid.raw, @@ -814,7 +814,7 @@ static void ipoib_set_mcast_list(struct net_device *dev) queue_work(ipoib_workqueue, &priv->restart_task); } -static void ipoib_neigh_destructor(struct neighbour *n) +static void ipoib_neigh_cleanup(struct neighbour *n) { struct ipoib_neigh *neigh; struct ipoib_dev_priv *priv = netdev_priv(n->dev); @@ -822,7 +822,7 @@ static void ipoib_neigh_destructor(struct neighbour *n) struct ipoib_ah *ah = NULL; ipoib_dbg(priv, - "neigh_destructor for %06x " IPOIB_GID_FMT "\n", + "neigh_cleanup for %06x " IPOIB_GID_FMT "\n", IPOIB_QPN(n->ha), IPOIB_GID_RAW_ARG(n->ha + 4)); @@ -874,7 +874,7 @@ void ipoib_neigh_free(struct net_device *dev, struct ipoib_neigh *neigh) static int ipoib_neigh_setup_dev(struct net_device *dev, struct neigh_parms *parms) { - parms->neigh_destructor = ipoib_neigh_destructor; + parms->neigh_cleanup = ipoib_neigh_cleanup; return 0; } diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index bb2e3d5eee2..54fbead4de0 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -407,6 +407,10 @@ static int ipoib_mcast_join_complete(int status, queue_delayed_work(ipoib_workqueue, &priv->mcast_task, 0); mutex_unlock(&mcast_mutex); + + if (mcast == priv->broadcast) + netif_carrier_on(dev); + return 0; } @@ -594,7 +598,6 @@ void ipoib_mcast_join_task(struct work_struct *work) ipoib_dbg_mcast(priv, "successfully joined all multicast groups\n"); clear_bit(IPOIB_MCAST_RUN, &priv->flags); - netif_carrier_on(dev); } int ipoib_mcast_start_thread(struct net_device *dev) @@ -641,6 +644,9 @@ static int ipoib_mcast_leave(struct net_device *dev, struct ipoib_mcast *mcast) struct ipoib_dev_priv *priv = netdev_priv(dev); int ret = 0; + if (test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags)) + ib_sa_free_multicast(mcast->mc); + if (test_and_clear_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags)) { ipoib_dbg_mcast(priv, "leaving MGID " IPOIB_GID_FMT "\n", IPOIB_GID_ARG(mcast->mcmember.mgid)); @@ -652,9 +658,6 @@ static int ipoib_mcast_leave(struct net_device *dev, struct ipoib_mcast *mcast) ipoib_warn(priv, "ipoib_mcast_detach failed (result = %d)\n", ret); } - if (test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags)) - ib_sa_free_multicast(mcast->mc); - return 0; } diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c index 3cb551b8875..7f3ec205e35 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c @@ -259,12 +259,13 @@ void ipoib_event(struct ib_event_handler *handler, struct ipoib_dev_priv *priv = container_of(handler, struct ipoib_dev_priv, event_handler); - if (record->event == IB_EVENT_PORT_ERR || - record->event == IB_EVENT_PKEY_CHANGE || - record->event == IB_EVENT_PORT_ACTIVE || - record->event == IB_EVENT_LID_CHANGE || - record->event == IB_EVENT_SM_CHANGE || - record->event == IB_EVENT_CLIENT_REREGISTER) { + if ((record->event == IB_EVENT_PORT_ERR || + record->event == IB_EVENT_PKEY_CHANGE || + record->event == IB_EVENT_PORT_ACTIVE || + record->event == IB_EVENT_LID_CHANGE || + record->event == IB_EVENT_SM_CHANGE || + record->event == IB_EVENT_CLIENT_REREGISTER) && + record->element.port_num == priv->port) { ipoib_dbg(priv, "Port state change event\n"); queue_work(ipoib_workqueue, &priv->flush_task); } diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h index cae8c96a55f..8960196ffb0 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.h +++ b/drivers/infiniband/ulp/iser/iscsi_iser.h @@ -245,7 +245,6 @@ struct iser_conn { wait_queue_head_t wait; /* waitq for conn/disconn */ atomic_t post_recv_buf_count; /* posted rx count */ atomic_t post_send_buf_count; /* posted tx count */ - struct work_struct comperror_work; /* conn term sleepable ctx*/ char name[ISER_OBJECT_NAME_SIZE]; struct iser_page_vec *page_vec; /* represents SG to fmr maps* * maps serialized as tx is*/ diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c index 89e37283c83..278fcbccc2d 100644 --- a/drivers/infiniband/ulp/iser/iser_initiator.c +++ b/drivers/infiniband/ulp/iser/iser_initiator.c @@ -658,6 +658,7 @@ void iser_ctask_rdma_finalize(struct iscsi_iser_cmd_task *iser_ctask) { int deferred; int is_rdma_aligned = 1; + struct iser_regd_buf *regd; /* if we were reading, copy back to unaligned sglist, * anyway dma_unmap and free the copy @@ -672,20 +673,20 @@ void iser_ctask_rdma_finalize(struct iscsi_iser_cmd_task *iser_ctask) } if (iser_ctask->dir[ISER_DIR_IN]) { - deferred = iser_regd_buff_release - (&iser_ctask->rdma_regd[ISER_DIR_IN]); + regd = &iser_ctask->rdma_regd[ISER_DIR_IN]; + deferred = iser_regd_buff_release(regd); if (deferred) { - iser_err("References remain for BUF-IN rdma reg\n"); - BUG(); + iser_err("%d references remain for BUF-IN rdma reg\n", + atomic_read(®d->ref_count)); } } if (iser_ctask->dir[ISER_DIR_OUT]) { - deferred = iser_regd_buff_release - (&iser_ctask->rdma_regd[ISER_DIR_OUT]); + regd = &iser_ctask->rdma_regd[ISER_DIR_OUT]; + deferred = iser_regd_buff_release(regd); if (deferred) { - iser_err("References remain for BUF-OUT rdma reg\n"); - BUG(); + iser_err("%d references remain for BUF-OUT rdma reg\n", + atomic_read(®d->ref_count)); } } diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c index 693b7700289..1fc967464a2 100644 --- a/drivers/infiniband/ulp/iser/iser_verbs.c +++ b/drivers/infiniband/ulp/iser/iser_verbs.c @@ -48,7 +48,6 @@ static void iser_cq_tasklet_fn(unsigned long data); static void iser_cq_callback(struct ib_cq *cq, void *cq_context); -static void iser_comp_error_worker(struct work_struct *work); static void iser_cq_event_callback(struct ib_event *cause, void *context) { @@ -480,7 +479,6 @@ int iser_conn_init(struct iser_conn **ibconn) init_waitqueue_head(&ib_conn->wait); atomic_set(&ib_conn->post_recv_buf_count, 0); atomic_set(&ib_conn->post_send_buf_count, 0); - INIT_WORK(&ib_conn->comperror_work, iser_comp_error_worker); INIT_LIST_HEAD(&ib_conn->conn_list); spin_lock_init(&ib_conn->lock); @@ -753,26 +751,6 @@ int iser_post_send(struct iser_desc *tx_desc) return ret_val; } -static void iser_comp_error_worker(struct work_struct *work) -{ - struct iser_conn *ib_conn = - container_of(work, struct iser_conn, comperror_work); - - /* getting here when the state is UP means that the conn is being * - * terminated asynchronously from the iSCSI layer's perspective. */ - if (iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP, - ISER_CONN_TERMINATING)) - iscsi_conn_failure(ib_conn->iser_conn->iscsi_conn, - ISCSI_ERR_CONN_FAILED); - - /* complete the termination process if disconnect event was delivered * - * note there are no more non completed posts to the QP */ - if (ib_conn->disc_evt_flag) { - ib_conn->state = ISER_CONN_DOWN; - wake_up_interruptible(&ib_conn->wait); - } -} - static void iser_handle_comp_error(struct iser_desc *desc) { struct iser_dto *dto = &desc->dto; @@ -791,8 +769,22 @@ static void iser_handle_comp_error(struct iser_desc *desc) } if (atomic_read(&ib_conn->post_recv_buf_count) == 0 && - atomic_read(&ib_conn->post_send_buf_count) == 0) - schedule_work(&ib_conn->comperror_work); + atomic_read(&ib_conn->post_send_buf_count) == 0) { + /* getting here when the state is UP means that the conn is * + * being terminated asynchronously from the iSCSI layer's * + * perspective. */ + if (iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP, + ISER_CONN_TERMINATING)) + iscsi_conn_failure(ib_conn->iser_conn->iscsi_conn, + ISCSI_ERR_CONN_FAILED); + + /* complete the termination process if disconnect event was delivered * + * note there are no more non completed posts to the QP */ + if (ib_conn->disc_evt_flag) { + ib_conn->state = ISER_CONN_DOWN; + wake_up_interruptible(&ib_conn->wait); + } + } } static void iser_cq_tasklet_fn(unsigned long data) diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index ec195a36e8f..db9cca3b65e 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -553,7 +553,8 @@ static int __devinit i8042_check_aux(void) */ param = 0x5a; - if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != 0x5a) { + retval = i8042_command(¶m, I8042_CMD_AUX_LOOP); + if (retval || param != 0x5a) { /* * External connection test - filters out AT-soldered PS/2 i8042's @@ -567,7 +568,12 @@ static int __devinit i8042_check_aux(void) (param && param != 0xfa && param != 0xff)) return -1; - aux_loop_broken = 1; +/* + * If AUX_LOOP completed without error but returned unexpected data + * mark it as broken + */ + if (!retval) + aux_loop_broken = 1; } /* diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index c7db4032ef0..e8606c48c9c 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c @@ -553,6 +553,7 @@ static int ucb1400_ts_remove(struct device *dev) } static struct device_driver ucb1400_ts_driver = { + .name = "ucb1400_ts", .owner = THIS_MODULE, .bus = &ac97_bus_type, .probe = ucb1400_ts_probe, diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 63e51dd6deb..00e31609a23 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -54,7 +54,7 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode"); #define USB_SX353_PRODUCT_ID 0x0022 /* table of devices that work with this driver */ -static struct usb_device_id gigaset_table [] = { +static const struct usb_device_id gigaset_table [] = { { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3070_PRODUCT_ID) }, { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3075_PRODUCT_ID) }, { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX303_PRODUCT_ID) }, @@ -2305,7 +2305,7 @@ static void gigaset_disconnect(struct usb_interface *interface) gigaset_unassign(cs); } -static struct gigaset_ops gigops = { +static const struct gigaset_ops gigops = { gigaset_write_cmd, gigaset_write_room, gigaset_chars_in_buffer, diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index b460a73a7c8..6df336bdd57 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -944,8 +944,8 @@ static DEFINE_SPINLOCK(driver_lock); struct cardstate *gigaset_get_cs_by_id(int id) { unsigned long flags; - static struct cardstate *ret = NULL; - static struct cardstate *cs; + struct cardstate *ret = NULL; + struct cardstate *cs; struct gigaset_driver *drv; unsigned i; @@ -999,7 +999,7 @@ void gigaset_debugdrivers(void) static struct cardstate *gigaset_get_cs_by_minor(unsigned minor) { unsigned long flags; - static struct cardstate *ret = NULL; + struct cardstate *ret = NULL; struct gigaset_driver *drv; unsigned index; diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index 4661e2c722b..cec1ef342fc 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c @@ -409,7 +409,7 @@ static struct reply_t tab_cid[] = /* no dle mode */ //FIXME }; #endif -static struct resp_type_t resp_type[]= +static const struct resp_type_t resp_type[] = { /*{"", RSP_EMPTY, RT_NOTHING},*/ {"OK", RSP_OK, RT_NOTHING}, @@ -511,7 +511,7 @@ void gigaset_handle_modem_response(struct cardstate *cs) unsigned char *argv[MAX_REC_PARAMS + 1]; int params; int i, j; - struct resp_type_t *rt; + const struct resp_type_t *rt; int curarg; unsigned long flags; unsigned next, tail, head; diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index 8c0eb522dab..e0505f23880 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c @@ -274,7 +274,7 @@ static inline void dump_bytes(enum debuglevel level, const char *tag, * bit 12..10 = number of trailing '1' bits in result * bit 14..13 = number of bits added by stuffing */ -static u16 stufftab[5 * 256] = { +static const u16 stufftab[5 * 256] = { // previous 1s = 0: 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x201f, @@ -629,7 +629,7 @@ static inline void hdlc_frag(struct bc_state *bcs, unsigned inbits) * (replacing 8 by 7 to make it fit; the algorithm won't care) * bit 7 set if there are 5 or more "interior" consecutive '1' bits */ -static unsigned char bitcounts[256] = { +static const unsigned char bitcounts[256] = { 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c index c8b7db65e48..ea44302e6e7 100644 --- a/drivers/isdn/gigaset/ser-gigaset.c +++ b/drivers/isdn/gigaset/ser-gigaset.c @@ -459,7 +459,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) return -EINVAL; } -static struct gigaset_ops ops = { +static const struct gigaset_ops ops = { gigaset_write_cmd, gigaset_write_room, gigaset_chars_in_buffer, diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index 04f2ad7ba8b..2baef349c12 100644 --- a/drivers/isdn/gigaset/usb-gigaset.c +++ b/drivers/isdn/gigaset/usb-gigaset.c @@ -50,7 +50,7 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode"); #define USB_M105_PRODUCT_ID 0x0009 /* table of devices that work with this driver */ -static struct usb_device_id gigaset_table [] = { +static const struct usb_device_id gigaset_table [] = { { USB_DEVICE(USB_M105_VENDOR_ID, USB_M105_PRODUCT_ID) }, { } /* Terminating entry */ }; @@ -860,7 +860,7 @@ static void gigaset_disconnect(struct usb_interface *interface) gigaset_unassign(cs); } -static struct gigaset_ops ops = { +static const struct gigaset_ops ops = { gigaset_write_cmd, gigaset_write_room, gigaset_chars_in_buffer, diff --git a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c index 9df9e3548cf..c547a666505 100644 --- a/drivers/isdn/hisax/isar.c +++ b/drivers/isdn/hisax/isar.c @@ -440,7 +440,7 @@ isar_bh(struct work_struct *work) { struct BCState *bcs = container_of(work, struct BCState, tqueue); - BChannel_bh(bcs); + BChannel_bh(work); if (test_and_clear_bit(B_LL_NOCARRIER, &bcs->event)) ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_NOCARR); if (test_and_clear_bit(B_LL_CONNECT, &bcs->event)) diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index a163bca3897..dc7a8c78cbf 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c @@ -2464,7 +2464,7 @@ int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module) r = kvm_arch_ops->hardware_setup(); if (r < 0) - return r; + goto out; on_each_cpu(kvm_arch_ops->hardware_enable, NULL, 0, 1); r = register_cpu_notifier(&kvm_cpu_notifier); @@ -2500,6 +2500,8 @@ out_free_2: out_free_1: on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1); kvm_arch_ops->hardware_unsetup(); +out: + kvm_arch_ops = NULL; return r; } diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c index a1a93368f31..e85b4c7c36f 100644 --- a/drivers/kvm/mmu.c +++ b/drivers/kvm/mmu.c @@ -131,7 +131,7 @@ static int dbg = 1; (((address) >> PT32_LEVEL_SHIFT(level)) & ((1 << PT32_LEVEL_BITS) - 1)) -#define PT64_BASE_ADDR_MASK (((1ULL << 52) - 1) & PAGE_MASK) +#define PT64_BASE_ADDR_MASK (((1ULL << 52) - 1) & ~(u64)(PAGE_SIZE-1)) #define PT64_DIR_BASE_ADDR_MASK \ (PT64_BASE_ADDR_MASK & ~((1ULL << (PAGE_SHIFT + PT64_LEVEL_BITS)) - 1)) @@ -406,8 +406,8 @@ static void rmap_write_protect(struct kvm_vcpu *vcpu, u64 gfn) spte = desc->shadow_ptes[0]; } BUG_ON(!spte); - BUG_ON((*spte & PT64_BASE_ADDR_MASK) != - page_to_pfn(page) << PAGE_SHIFT); + BUG_ON((*spte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT + != page_to_pfn(page)); BUG_ON(!(*spte & PT_PRESENT_MASK)); BUG_ON(!(*spte & PT_WRITABLE_MASK)); rmap_printk("rmap_write_protect: spte %p %llx\n", spte, *spte); @@ -1093,22 +1093,40 @@ out: return r; } +static void mmu_pre_write_zap_pte(struct kvm_vcpu *vcpu, + struct kvm_mmu_page *page, + u64 *spte) +{ + u64 pte; + struct kvm_mmu_page *child; + + pte = *spte; + if (is_present_pte(pte)) { + if (page->role.level == PT_PAGE_TABLE_LEVEL) + rmap_remove(vcpu, spte); + else { + child = page_header(pte & PT64_BASE_ADDR_MASK); + mmu_page_remove_parent_pte(vcpu, child, spte); + } + } + *spte = 0; +} + void kvm_mmu_pre_write(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes) { gfn_t gfn = gpa >> PAGE_SHIFT; struct kvm_mmu_page *page; - struct kvm_mmu_page *child; struct hlist_node *node, *n; struct hlist_head *bucket; unsigned index; u64 *spte; - u64 pte; unsigned offset = offset_in_page(gpa); unsigned pte_size; unsigned page_offset; unsigned misaligned; int level; int flooded = 0; + int npte; pgprintk("%s: gpa %llx bytes %d\n", __FUNCTION__, gpa, bytes); if (gfn == vcpu->last_pt_write_gfn) { @@ -1144,22 +1162,26 @@ void kvm_mmu_pre_write(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes) } page_offset = offset; level = page->role.level; + npte = 1; if (page->role.glevels == PT32_ROOT_LEVEL) { - page_offset <<= 1; /* 32->64 */ + page_offset <<= 1; /* 32->64 */ + /* + * A 32-bit pde maps 4MB while the shadow pdes map + * only 2MB. So we need to double the offset again + * and zap two pdes instead of one. + */ + if (level == PT32_ROOT_LEVEL) { + page_offset <<= 1; + npte = 2; + } page_offset &= ~PAGE_MASK; } spte = __va(page->page_hpa); spte += page_offset / sizeof(*spte); - pte = *spte; - if (is_present_pte(pte)) { - if (level == PT_PAGE_TABLE_LEVEL) - rmap_remove(vcpu, spte); - else { - child = page_header(pte & PT64_BASE_ADDR_MASK); - mmu_page_remove_parent_pte(vcpu, child, spte); - } + while (npte--) { + mmu_pre_write_zap_pte(vcpu, page, spte); + ++spte; } - *spte = 0; } } diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c index c07178e6112..fbbf9d6b299 100644 --- a/drivers/kvm/vmx.c +++ b/drivers/kvm/vmx.c @@ -371,10 +371,10 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata) data = vmcs_read32(GUEST_SYSENTER_CS); break; case MSR_IA32_SYSENTER_EIP: - data = vmcs_read32(GUEST_SYSENTER_EIP); + data = vmcs_readl(GUEST_SYSENTER_EIP); break; case MSR_IA32_SYSENTER_ESP: - data = vmcs_read32(GUEST_SYSENTER_ESP); + data = vmcs_readl(GUEST_SYSENTER_ESP); break; default: msr = find_msr_entry(vcpu, msr_index); @@ -412,10 +412,10 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data) vmcs_write32(GUEST_SYSENTER_CS, data); break; case MSR_IA32_SYSENTER_EIP: - vmcs_write32(GUEST_SYSENTER_EIP, data); + vmcs_writel(GUEST_SYSENTER_EIP, data); break; case MSR_IA32_SYSENTER_ESP: - vmcs_write32(GUEST_SYSENTER_ESP, data); + vmcs_writel(GUEST_SYSENTER_ESP, data); break; case MSR_IA32_TIME_STAMP_COUNTER: guest_write_tsc(data); @@ -618,7 +618,7 @@ static void fix_pmode_dataseg(int seg, struct kvm_save_segment *save) { struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg]; - if (vmcs_readl(sf->base) == save->base) { + if (vmcs_readl(sf->base) == save->base && (save->base & AR_S_MASK)) { vmcs_write16(sf->selector, save->selector); vmcs_writel(sf->base, save->base); vmcs_write32(sf->limit, save->limit); @@ -1888,6 +1888,27 @@ again: [cr2]"i"(offsetof(struct kvm_vcpu, cr2)) : "cc", "memory" ); + /* + * Reload segment selectors ASAP. (it's needed for a functional + * kernel: x86 relies on having __KERNEL_PDA in %fs and x86_64 + * relies on having 0 in %gs for the CPU PDA to work.) + */ + if (fs_gs_ldt_reload_needed) { + load_ldt(ldt_sel); + load_fs(fs_sel); + /* + * If we have to reload gs, we must take care to + * preserve our gs base. + */ + local_irq_disable(); + load_gs(gs_sel); +#ifdef CONFIG_X86_64 + wrmsrl(MSR_GS_BASE, vmcs_readl(HOST_GS_BASE)); +#endif + local_irq_enable(); + + reload_tss(); + } ++kvm_stat.exits; save_msrs(vcpu->guest_msrs, NR_BAD_MSRS); @@ -1905,22 +1926,6 @@ again: kvm_run->exit_reason = vmcs_read32(VM_INSTRUCTION_ERROR); r = 0; } else { - if (fs_gs_ldt_reload_needed) { - load_ldt(ldt_sel); - load_fs(fs_sel); - /* - * If we have to reload gs, we must take care to - * preserve our gs base. - */ - local_irq_disable(); - load_gs(gs_sel); -#ifdef CONFIG_X86_64 - wrmsrl(MSR_GS_BASE, vmcs_readl(HOST_GS_BASE)); -#endif - local_irq_enable(); - - reload_tss(); - } /* * Profile KVM exit RIPs: */ diff --git a/drivers/md/linear.c b/drivers/md/linear.c index c625ddb8833..d5ecd2d5304 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -188,7 +188,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) for (i=0; i < cnt-1 ; i++) { sector_t sz = 0; int j; - for (j=i; i<cnt-1 && sz < min_spacing ; j++) + for (j = i; j < cnt - 1 && sz < min_spacing; j++) sz += conf->disks[j].size; if (sz >= min_spacing && sz < conf->hash_spacing) conf->hash_spacing = sz; diff --git a/drivers/md/md.c b/drivers/md/md.c index 6c06e825cff..509171ca7fa 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1318,6 +1318,7 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) char b[BDEVNAME_SIZE]; struct kobject *ko; char *s; + int err; if (rdev->mddev) { MD_BUG(); @@ -1352,20 +1353,35 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) while ( (s=strchr(rdev->kobj.k_name, '/')) != NULL) *s = '!'; - list_add(&rdev->same_set, &mddev->disks); rdev->mddev = mddev; printk(KERN_INFO "md: bind<%s>\n", b); rdev->kobj.parent = &mddev->kobj; - kobject_add(&rdev->kobj); + if ((err = kobject_add(&rdev->kobj))) + goto fail; if (rdev->bdev->bd_part) ko = &rdev->bdev->bd_part->kobj; else ko = &rdev->bdev->bd_disk->kobj; - sysfs_create_link(&rdev->kobj, ko, "block"); + if ((err = sysfs_create_link(&rdev->kobj, ko, "block"))) { + kobject_del(&rdev->kobj); + goto fail; + } + list_add(&rdev->same_set, &mddev->disks); bd_claim_by_disk(rdev->bdev, rdev, mddev->gendisk); return 0; + + fail: + printk(KERN_WARNING "md: failed to register dev-%s for %s\n", + b, mdname(mddev)); + return err; +} + +static void delayed_delete(struct work_struct *ws) +{ + mdk_rdev_t *rdev = container_of(ws, mdk_rdev_t, del_work); + kobject_del(&rdev->kobj); } static void unbind_rdev_from_array(mdk_rdev_t * rdev) @@ -1380,7 +1396,12 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev) printk(KERN_INFO "md: unbind<%s>\n", bdevname(rdev->bdev,b)); rdev->mddev = NULL; sysfs_remove_link(&rdev->kobj, "block"); - kobject_del(&rdev->kobj); + + /* We need to delay this, otherwise we can deadlock when + * writing to 'remove' to "dev/state" + */ + INIT_WORK(&rdev->del_work, delayed_delete); + schedule_work(&rdev->del_work); } /* @@ -2966,7 +2987,9 @@ static struct kobject *md_probe(dev_t dev, int *part, void *data) mddev->kobj.k_name = NULL; snprintf(mddev->kobj.name, KOBJ_NAME_LEN, "%s", "md"); mddev->kobj.ktype = &md_ktype; - kobject_register(&mddev->kobj); + if (kobject_register(&mddev->kobj)) + printk(KERN_WARNING "md: cannot register %s/md - name in use\n", + disk->disk_name); return NULL; } @@ -3144,9 +3167,12 @@ static int do_md_run(mddev_t * mddev) bitmap_destroy(mddev); return err; } - if (mddev->pers->sync_request) - sysfs_create_group(&mddev->kobj, &md_redundancy_group); - else if (mddev->ro == 2) /* auto-readonly not meaningful */ + if (mddev->pers->sync_request) { + if (sysfs_create_group(&mddev->kobj, &md_redundancy_group)) + printk(KERN_WARNING + "md: cannot register extra attributes for %s\n", + mdname(mddev)); + } else if (mddev->ro == 2) /* auto-readonly not meaningful */ mddev->ro = 0; atomic_set(&mddev->writes_pending,0); @@ -3160,7 +3186,9 @@ static int do_md_run(mddev_t * mddev) if (rdev->raid_disk >= 0) { char nm[20]; sprintf(nm, "rd%d", rdev->raid_disk); - sysfs_create_link(&mddev->kobj, &rdev->kobj, nm); + if (sysfs_create_link(&mddev->kobj, &rdev->kobj, nm)) + printk("md: cannot register %s for %s\n", + nm, mdname(mddev)); } set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); @@ -3325,6 +3353,7 @@ static int do_md_stop(mddev_t * mddev, int mode) mddev->queue->merge_bvec_fn = NULL; mddev->queue->unplug_fn = NULL; mddev->queue->issue_flush_fn = NULL; + mddev->queue->backing_dev_info.congested_fn = NULL; if (mddev->pers->sync_request) sysfs_remove_group(&mddev->kobj, &md_redundancy_group); @@ -3371,6 +3400,9 @@ static int do_md_stop(mddev_t * mddev, int mode) sysfs_remove_link(&mddev->kobj, nm); } + /* make sure all delayed_delete calls have finished */ + flush_scheduled_work(); + export_array(mddev); mddev->array_size = 0; @@ -5385,8 +5417,12 @@ static int remove_and_add_spares(mddev_t *mddev) if (mddev->pers->hot_add_disk(mddev,rdev)) { char nm[20]; sprintf(nm, "rd%d", rdev->raid_disk); - sysfs_create_link(&mddev->kobj, - &rdev->kobj, nm); + if (sysfs_create_link(&mddev->kobj, + &rdev->kobj, nm)) + printk(KERN_WARNING + "md: cannot register " + "%s for %s\n", + nm, mdname(mddev)); spares++; md_new_event(mddev); } else diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 54a1ad5eef4..8d59914f205 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -3642,12 +3642,15 @@ static int run(mddev_t *mddev) } /* Ok, everything is just fine now */ - sysfs_create_group(&mddev->kobj, &raid5_attrs_group); + if (sysfs_create_group(&mddev->kobj, &raid5_attrs_group)) + printk(KERN_WARNING + "raid5: failed to create sysfs attributes for %s\n", + mdname(mddev)); mddev->queue->unplug_fn = raid5_unplug_device; mddev->queue->issue_flush_fn = raid5_issue_flush; - mddev->queue->backing_dev_info.congested_fn = raid5_congested; mddev->queue->backing_dev_info.congested_data = mddev; + mddev->queue->backing_dev_info.congested_fn = raid5_congested; mddev->array_size = mddev->size * (conf->previous_raid_disks - conf->max_degraded); @@ -3678,6 +3681,7 @@ static int stop(mddev_t *mddev) mddev->thread = NULL; shrink_stripes(conf); kfree(conf->stripe_hashtbl); + mddev->queue->backing_dev_info.congested_fn = NULL; blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ sysfs_remove_group(&mddev->kobj, &raid5_attrs_group); kfree(conf->disks); @@ -3950,7 +3954,12 @@ static int raid5_start_reshape(mddev_t *mddev) added_devices++; rdev->recovery_offset = 0; sprintf(nm, "rd%d", rdev->raid_disk); - sysfs_create_link(&mddev->kobj, &rdev->kobj, nm); + if (sysfs_create_link(&mddev->kobj, + &rdev->kobj, nm)) + printk(KERN_WARNING + "raid5: failed to create " + " link %s for %s\n", + nm, mdname(mddev)); } else break; } @@ -4104,6 +4113,10 @@ static struct mdk_personality raid4_personality = .spare_active = raid5_spare_active, .sync_request = sync_request, .resize = raid5_resize, +#ifdef CONFIG_MD_RAID5_RESHAPE + .check_reshape = raid5_check_reshape, + .start_reshape = raid5_start_reshape, +#endif .quiesce = raid5_quiesce, }; diff --git a/drivers/media/common/ir-functions.c b/drivers/media/common/ir-functions.c index cbf7c056488..fcb19413562 100644 --- a/drivers/media/common/ir-functions.c +++ b/drivers/media/common/ir-functions.c @@ -310,13 +310,15 @@ void ir_rc5_timer_end(unsigned long data) tv.tv_usec - ir->base_time.tv_usec; } - /* Allow some timmer jitter (RC5 is ~24ms anyway so this is ok) */ + /* signal we're ready to start a new code */ + ir->active = 0; + + /* Allow some timer jitter (RC5 is ~24ms anyway so this is ok) */ if (gap < 28000) { dprintk(1, "ir-common: spurious timer_end\n"); return; } - ir->active = 0; if (ir->last_bit < 20) { /* ignore spurious codes (caused by light/other remotes) */ dprintk(1, "ir-common: short code: %x\n", ir->code); diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c index fc77de45ca4..a5c0e1a3e6d 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ b/drivers/media/dvb/dvb-core/dmxdev.c @@ -180,8 +180,7 @@ static int dvb_dvr_release(struct inode *inode, struct file *file) struct dvb_device *dvbdev = file->private_data; struct dmxdev *dmxdev = dvbdev->priv; - if (mutex_lock_interruptible(&dmxdev->mutex)) - return -ERESTARTSYS; + mutex_lock(&dmxdev->mutex); if ((file->f_flags & O_ACCMODE) == O_WRONLY) { dmxdev->demux->disconnect_frontend(dmxdev->demux); @@ -673,13 +672,8 @@ static int dvb_demux_open(struct inode *inode, struct file *file) static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev, struct dmxdev_filter *dmxdevfilter) { - if (mutex_lock_interruptible(&dmxdev->mutex)) - return -ERESTARTSYS; - - if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { - mutex_unlock(&dmxdev->mutex); - return -ERESTARTSYS; - } + mutex_lock(&dmxdev->mutex); + mutex_lock(&dmxdevfilter->mutex); dvb_dmxdev_filter_stop(dmxdevfilter); dvb_dmxdev_filter_reset(dmxdevfilter); diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c index fcff5eab21a..6d8d1c3df86 100644 --- a/drivers/media/dvb/dvb-core/dvb_demux.c +++ b/drivers/media/dvb/dvb-core/dvb_demux.c @@ -673,8 +673,7 @@ static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed *ts_feed) struct dvb_demux *demux = feed->demux; int ret; - if (mutex_lock_interruptible(&demux->mutex)) - return -ERESTARTSYS; + mutex_lock(&demux->mutex); if (feed->state < DMX_STATE_GO) { mutex_unlock(&demux->mutex); @@ -748,8 +747,7 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, struct dvb_demux *demux = (struct dvb_demux *)dmx; struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed; - if (mutex_lock_interruptible(&demux->mutex)) - return -ERESTARTSYS; + mutex_lock(&demux->mutex); if (feed->state == DMX_STATE_FREE) { mutex_unlock(&demux->mutex); @@ -916,8 +914,7 @@ static int dmx_section_feed_stop_filtering(struct dmx_section_feed *feed) struct dvb_demux *dvbdmx = dvbdmxfeed->demux; int ret; - if (mutex_lock_interruptible(&dvbdmx->mutex)) - return -ERESTARTSYS; + mutex_lock(&dvbdmx->mutex); if (!dvbdmx->stop_feed) { mutex_unlock(&dvbdmx->mutex); @@ -942,8 +939,7 @@ static int dmx_section_feed_release_filter(struct dmx_section_feed *feed, struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; struct dvb_demux *dvbdmx = dvbdmxfeed->demux; - if (mutex_lock_interruptible(&dvbdmx->mutex)) - return -ERESTARTSYS; + mutex_lock(&dvbdmx->mutex); if (dvbdmxfilter->feed != dvbdmxfeed) { mutex_unlock(&dvbdmx->mutex); @@ -1016,8 +1012,7 @@ static int dvbdmx_release_section_feed(struct dmx_demux *demux, struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; struct dvb_demux *dvbdmx = (struct dvb_demux *)demux; - if (mutex_lock_interruptible(&dvbdmx->mutex)) - return -ERESTARTSYS; + mutex_lock(&dvbdmx->mutex); if (dvbdmxfeed->state == DMX_STATE_FREE) { mutex_unlock(&dvbdmx->mutex); @@ -1126,8 +1121,7 @@ static int dvbdmx_connect_frontend(struct dmx_demux *demux, if (demux->frontend) return -EINVAL; - if (mutex_lock_interruptible(&dvbdemux->mutex)) - return -ERESTARTSYS; + mutex_lock(&dvbdemux->mutex); demux->frontend = frontend; mutex_unlock(&dvbdemux->mutex); @@ -1138,8 +1132,7 @@ static int dvbdmx_disconnect_frontend(struct dmx_demux *demux) { struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; - if (mutex_lock_interruptible(&dvbdemux->mutex)) - return -ERESTARTSYS; + mutex_lock(&dvbdemux->mutex); demux->frontend = NULL; mutex_unlock(&dvbdemux->mutex); diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c index 490337b5ee3..14a372a0fe8 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ b/drivers/media/dvb/dvb-core/dvbdev.c @@ -203,8 +203,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, int id; - if (mutex_lock_interruptible(&dvbdev_register_lock)) - return -ERESTARTSYS; + mutex_lock(&dvbdev_register_lock); if ((id = dvbdev_get_free_id (adap, type)) < 0){ mutex_unlock(&dvbdev_register_lock); @@ -294,8 +293,7 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct modu { int num; - if (mutex_lock_interruptible(&dvbdev_register_lock)) - return -ERESTARTSYS; + mutex_lock(&dvbdev_register_lock); if ((num = dvbdev_get_free_adapter_num ()) < 0) { mutex_unlock(&dvbdev_register_lock); @@ -323,8 +321,7 @@ EXPORT_SYMBOL(dvb_register_adapter); int dvb_unregister_adapter(struct dvb_adapter *adap) { - if (mutex_lock_interruptible(&dvbdev_register_lock)) - return -ERESTARTSYS; + mutex_lock(&dvbdev_register_lock); list_del (&adap->list_head); mutex_unlock(&dvbdev_register_lock); return 0; diff --git a/drivers/media/dvb/frontends/isl6421.c b/drivers/media/dvb/frontends/isl6421.c index ef319369ec2..c967148a594 100644 --- a/drivers/media/dvb/frontends/isl6421.c +++ b/drivers/media/dvb/frontends/isl6421.c @@ -122,6 +122,7 @@ struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter /* detect if it is present or not */ if (isl6421_set_voltage(fe, SEC_VOLTAGE_OFF)) { kfree(isl6421); + fe->sec_priv = NULL; return NULL; } diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c index 87c286ee6a0..b809f83d956 100644 --- a/drivers/media/dvb/frontends/nxt200x.c +++ b/drivers/media/dvb/frontends/nxt200x.c @@ -562,7 +562,7 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe, /* set input */ if (state->config->set_pll_input) - state->config->set_pll_input(buf, 1); + state->config->set_pll_input(buf+1, 1); break; case VSB_8: /* Set non-punctured clock for VSB */ @@ -571,7 +571,7 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe, /* set input */ if (state->config->set_pll_input) - state->config->set_pll_input(buf, 0); + state->config->set_pll_input(buf+1, 0); break; default: return -EINVAL; diff --git a/drivers/media/dvb/frontends/tda10086.c b/drivers/media/dvb/frontends/tda10086.c index 4c27a2d90a3..ccc429cbbad 100644 --- a/drivers/media/dvb/frontends/tda10086.c +++ b/drivers/media/dvb/frontends/tda10086.c @@ -212,7 +212,7 @@ static int tda10086_send_master_cmd (struct dvb_frontend* fe, for(i=0; i< cmd->msg_len; i++) { tda10086_write_byte(state, 0x48+i, cmd->msg[i]); } - tda10086_write_byte(state, 0x36, 0x08 | ((cmd->msg_len + 1) << 4)); + tda10086_write_byte(state, 0x36, 0x08 | ((cmd->msg_len - 1) << 4)); tda10086_diseqc_wait(state); diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c index ffda71dfdd6..058df5c1003 100644 --- a/drivers/media/dvb/pluto2/pluto2.c +++ b/drivers/media/dvb/pluto2/pluto2.c @@ -149,6 +149,15 @@ static inline void pluto_rw(struct pluto *pluto, u32 reg, u32 mask, u32 bits) writel(val, &pluto->io_mem[reg]); } +static void pluto_write_tscr(struct pluto *pluto, u32 val) +{ + /* set the number of packets */ + val &= ~TSCR_ADEF; + val |= TS_DMA_PACKETS / 2; + + pluto_writereg(pluto, REG_TSCR, val); +} + static void pluto_setsda(void *data, int state) { struct pluto *pluto = data; @@ -213,11 +222,11 @@ static void pluto_reset_ts(struct pluto *pluto, int reenable) if (val & TSCR_RSTN) { val &= ~TSCR_RSTN; - pluto_writereg(pluto, REG_TSCR, val); + pluto_write_tscr(pluto, val); } if (reenable) { val |= TSCR_RSTN; - pluto_writereg(pluto, REG_TSCR, val); + pluto_write_tscr(pluto, val); } } @@ -339,7 +348,7 @@ static irqreturn_t pluto_irq(int irq, void *dev_id) } /* ACK the interrupt */ - pluto_writereg(pluto, REG_TSCR, tscr | TSCR_IACK); + pluto_write_tscr(pluto, tscr | TSCR_IACK); return IRQ_HANDLED; } @@ -348,9 +357,6 @@ static void __devinit pluto_enable_irqs(struct pluto *pluto) { u32 val = pluto_readreg(pluto, REG_TSCR); - /* set the number of packets */ - val &= ~TSCR_ADEF; - val |= TS_DMA_PACKETS / 2; /* disable AFUL and LOCK interrupts */ val |= (TSCR_MSKA | TSCR_MSKL); /* enable DMA and OVERFLOW interrupts */ @@ -358,7 +364,7 @@ static void __devinit pluto_enable_irqs(struct pluto *pluto) /* clear pending interrupts */ val |= TSCR_IACK; - pluto_writereg(pluto, REG_TSCR, val); + pluto_write_tscr(pluto, val); } static void pluto_disable_irqs(struct pluto *pluto) @@ -370,7 +376,7 @@ static void pluto_disable_irqs(struct pluto *pluto) /* clear pending interrupts */ val |= TSCR_IACK; - pluto_writereg(pluto, REG_TSCR, val); + pluto_write_tscr(pluto, val); } static int __devinit pluto_hw_init(struct pluto *pluto) diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index 920b63f8cf0..af66a5d5ecd 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -3,7 +3,7 @@ # menu "Radio Adapters" - depends on VIDEO_DEV!=n + depends on VIDEO_DEV config RADIO_CADET tristate "ADS Cadet AM/FM Tuner" diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index 2fb9fe6a1ae..ba1af3c8525 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c @@ -780,18 +780,16 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) return 0; } -static int msp_suspend(struct device * dev, pm_message_t state) +static int msp_suspend(struct i2c_client *client, pm_message_t state) { - struct i2c_client *client = container_of(dev, struct i2c_client, dev); v4l_dbg(1, msp_debug, client, "suspend\n"); msp_reset(client); return 0; } -static int msp_resume(struct device * dev) +static int msp_resume(struct i2c_client *client) { - struct i2c_client *client = container_of(dev, struct i2c_client, dev); v4l_dbg(1, msp_debug, client, "resume\n"); msp_wake_thread(client); @@ -825,7 +823,7 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) if (msp_reset(client) == -1) { v4l_dbg(1, msp_debug, client, "msp3400 not found\n"); kfree(client); - return -1; + return 0; } state = kmalloc(sizeof(*state), GFP_KERNEL); @@ -859,7 +857,7 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) v4l_dbg(1, msp_debug, client, "not an msp3400 (cannot read chip version)\n"); kfree(state); kfree(client); - return -1; + return 0; } msp_set_audio(client); @@ -996,11 +994,11 @@ static struct i2c_driver i2c_driver = { .id = I2C_DRIVERID_MSP3400, .attach_adapter = msp_probe, .detach_client = msp_detach, + .suspend = msp_suspend, + .resume = msp_resume, .command = msp_command, .driver = { .name = "msp3400", - .suspend = msp_suspend, - .resume = msp_resume, }, }; diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 1ff5138e4bb..9916cf32494 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1248,10 +1248,10 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) ret |= pvr2_write_register(hdw, 0xaa18, 0x00840000); /*unknown*/ LOCK_TAKE(hdw->ctl_lock); do { hdw->cmd_buffer[0] = FX2CMD_FWPOST1; - ret |= pvr2_send_request(hdw,hdw->cmd_buffer,1,0,0); + ret |= pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0); hdw->cmd_buffer[0] = FX2CMD_MEMSEL; hdw->cmd_buffer[1] = 0; - ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,0,0); + ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,NULL,0); } while (0); LOCK_GIVE(hdw->ctl_lock); if (ret) { @@ -1320,7 +1320,7 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) LOCK_TAKE(hdw->ctl_lock); do { hdw->cmd_buffer[0] = FX2CMD_MEMSEL; hdw->cmd_buffer[1] = 0; - ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,0,0); + ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,NULL,0); } while (0); LOCK_GIVE(hdw->ctl_lock); if (ret) { diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 5313d342666..25d3830b482 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -808,11 +808,11 @@ static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp) { if (vp->dev_video) { pvr2_v4l2_dev_destroy(vp->dev_video); - vp->dev_video = 0; + vp->dev_video = NULL; } if (vp->dev_radio) { pvr2_v4l2_dev_destroy(vp->dev_radio); - vp->dev_radio = 0; + vp->dev_radio = NULL; } pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp); @@ -1138,7 +1138,7 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, { int mindevnum; int unit_number; - int *nr_ptr = 0; + int *nr_ptr = NULL; dip->v4lp = vp; diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 7735b675892..4d5bbd859de 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -961,7 +961,7 @@ static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std) reg |= 0x10; } else if (std == V4L2_STD_NTSC_M_JP) { reg |= 0x40; - } else if (std == V4L2_STD_SECAM) { + } else if (std & V4L2_STD_SECAM) { reg |= 0x50; } saa711x_write(client, R_0E_CHROMA_CNTL_1, reg); diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 7be73e3763d..15dbc6bf42a 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -804,9 +804,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) return 0; } -static int tuner_suspend(struct device *dev, pm_message_t state) +static int tuner_suspend(struct i2c_client *c, pm_message_t state) { - struct i2c_client *c = container_of (dev, struct i2c_client, dev); struct tuner *t = i2c_get_clientdata (c); tuner_dbg ("suspend\n"); @@ -814,9 +813,8 @@ static int tuner_suspend(struct device *dev, pm_message_t state) return 0; } -static int tuner_resume(struct device *dev) +static int tuner_resume(struct i2c_client *c) { - struct i2c_client *c = container_of (dev, struct i2c_client, dev); struct tuner *t = i2c_get_clientdata (c); tuner_dbg ("resume\n"); @@ -837,10 +835,10 @@ static struct i2c_driver driver = { .attach_adapter = tuner_probe, .detach_client = tuner_detach, .command = tuner_command, + .suspend = tuner_suspend, + .resume = tuner_resume, .driver = { .name = "tuner", - .suspend = tuner_suspend, - .resume = tuner_resume, }, }; static struct i2c_client client_template = { diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 404c014db1b..1d2d03f7789 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -815,7 +815,7 @@ mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) static int mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) { - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; + MPT_SCSI_HOST *hd; struct mptsas_target_reset_event *target_reset_list, *n; int rc; @@ -827,7 +827,10 @@ mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) if (reset_phase != MPT_IOC_POST_RESET) goto out; - if (!hd || !hd->ioc) + if (!ioc->sh || !ioc->sh->hostdata) + goto out; + hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; + if (!hd->ioc) goto out; if (list_empty(&hd->target_reset_list)) diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index da9859f2caf..b17c4b2bc9e 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -390,13 +390,6 @@ static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req) return BLKPREP_KILL; } - /* request is already processed by us, so return */ - if (blk_special_request(req)) { - osm_debug("REQ_SPECIAL already set!\n"); - req->cmd_flags |= REQ_DONTPREP; - return BLKPREP_OK; - } - /* connect the i2o_block_request to the request */ if (!req->special) { ireq = i2o_block_request_alloc(); @@ -408,11 +401,8 @@ static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req) ireq->i2o_blk_dev = i2o_blk_dev; req->special = ireq; ireq->req = req; - } else - ireq = req->special; - + } /* do not come back here */ - req->cmd_type = REQ_TYPE_SPECIAL; req->cmd_flags |= REQ_DONTPREP; return BLKPREP_OK; diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index c707c8ebc1a..b0b4458ae90 100644 --- a/drivers/mfd/sm501.c +++ b/drivers/mfd/sm501.c @@ -319,7 +319,7 @@ int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to) mode &= 3; /* get current power mode */ - if (unit > ARRAY_SIZE(sm->unit_power)) { + if (unit >= ARRAY_SIZE(sm->unit_power)) { dev_err(dev, "%s: bad unit %d\n", __FUNCTION__, unit); goto already; } diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c index 295e931c0df..4b232124a1a 100644 --- a/drivers/misc/asus-laptop.c +++ b/drivers/misc/asus-laptop.c @@ -211,7 +211,7 @@ static struct workqueue_struct *led_workqueue; enum led_brightness value); \ static void object##_led_update(struct work_struct *ignored); \ static int object##_led_wk; \ - DECLARE_WORK(object##_led_work, object##_led_update); \ + static DECLARE_WORK(object##_led_work, object##_led_update); \ static struct led_classdev object##_led = { \ .name = "asus:" ledname, \ .brightness_set = object##_led_set, \ diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c index 2ebe240dd53..ac708bc2f9f 100644 --- a/drivers/misc/sony-laptop.c +++ b/drivers/misc/sony-laptop.c @@ -453,7 +453,7 @@ static int sony_acpi_resume(struct acpi_device *device) static int sony_acpi_add(struct acpi_device *device) { acpi_status status; - int result; + int result = 0; acpi_handle handle; sony_acpi_acpi_device = device; diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c index b060d4bfba2..0de5c9e94e7 100644 --- a/drivers/mmc/imxmmc.c +++ b/drivers/mmc/imxmmc.c @@ -569,10 +569,12 @@ static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat) if(host->dma_dir == DMA_FROM_DEVICE) { imxmci_busy_wait_for_status(host, &stat, - STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE, + STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE | + STATUS_TIME_OUT_READ, 50, "imxmci_cpu_driven_data read"); while((stat & (STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE)) && + !(stat & STATUS_TIME_OUT_READ) && (host->data_cnt < 512)) { udelay(20); /* required for clocks < 8MHz*/ @@ -602,6 +604,12 @@ static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat) if(host->dma_size & 0x1ff) stat &= ~STATUS_CRC_READ_ERR; + if(stat & STATUS_TIME_OUT_READ) { + dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data read timeout STATUS = 0x%x\n", + stat); + trans_done = -1; + } + } else { imxmci_busy_wait_for_status(host, &stat, STATUS_APPL_BUFF_FE, @@ -709,6 +717,9 @@ static void imxmci_tasklet_fnc(unsigned long data) */ stat |= host->status_reg; + if(test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events)) + stat &= ~STATUS_CRC_READ_ERR; + if(test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) { imxmci_busy_wait_for_status(host, &stat, STATUS_END_CMD_RESP | STATUS_ERR_MASK, diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index e3acd398fb3..1f644584046 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -359,6 +359,8 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp; cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp; cfi->chips[i].erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp; + cfi->chips[i].ref_point_counter = 0; + init_waitqueue_head(&(cfi->chips[i].wq)); } map->fldrv = &cfi_amdstd_chipdrv; diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c index 69d49e0250a..b344ff858b2 100644 --- a/drivers/mtd/chips/cfi_cmdset_0020.c +++ b/drivers/mtd/chips/cfi_cmdset_0020.c @@ -158,6 +158,8 @@ struct mtd_info *cfi_cmdset_0020(struct map_info *map, int primary) cfi->chips[i].word_write_time = 128; cfi->chips[i].buffer_write_time = 128; cfi->chips[i].erase_time = 1024; + cfi->chips[i].ref_point_counter = 0; + init_waitqueue_head(&(cfi->chips[i].wq)); } return cfi_staa_setup(map); diff --git a/drivers/mtd/maps/dilnetpc.c b/drivers/mtd/maps/dilnetpc.c index b1104fe1f20..1c3b34ad732 100644 --- a/drivers/mtd/maps/dilnetpc.c +++ b/drivers/mtd/maps/dilnetpc.c @@ -402,8 +402,8 @@ static int __init init_dnpc(void) ++higlvl_partition_info[i].name; } - printk(KERN_NOTICE "DIL/Net %s flash: 0x%lx at 0x%lx\n", - is_dnp ? "DNPC" : "ADNP", dnpc_map.size, dnpc_map.phys); + printk(KERN_NOTICE "DIL/Net %s flash: 0x%lx at 0x%llx\n", + is_dnp ? "DNPC" : "ADNP", dnpc_map.size, (unsigned long long)dnpc_map.phys); dnpc_map.virt = ioremap_nocache(dnpc_map.phys, dnpc_map.size); diff --git a/drivers/mtd/maps/esb2rom.c b/drivers/mtd/maps/esb2rom.c index 0bc013fd66a..aa64a475278 100644 --- a/drivers/mtd/maps/esb2rom.c +++ b/drivers/mtd/maps/esb2rom.c @@ -30,7 +30,7 @@ #define ROM_PROBE_STEP_SIZE (64*1024) /* 64KiB */ -#define BIOS_CNTL 0xDC +#define BIOS_CNTL 0xDC #define BIOS_LOCK_ENABLE 0x02 #define BIOS_WRITE_ENABLE 0x01 @@ -145,7 +145,7 @@ static void esb2rom_cleanup(struct esb2rom_window *window) } static int __devinit esb2rom_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) + const struct pci_device_id *ent) { static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; struct esb2rom_window *window = &esb2rom_window; @@ -185,7 +185,7 @@ static int __devinit esb2rom_init_one(struct pci_dev *pdev, /* Find a region continuous to the end of the ROM window */ window->phys = 0; pci_read_config_word(pdev, FWH_DEC_EN1, &word); - printk(KERN_DEBUG "pci_read_config_byte : %x\n", word); + printk(KERN_DEBUG "pci_read_config_word : %x\n", word); if ((word & FWH_8MiB) == FWH_8MiB) window->phys = 0xff400000; @@ -212,6 +212,11 @@ static int __devinit esb2rom_init_one(struct pci_dev *pdev, else if ((word & FWH_0_5MiB) == FWH_0_5MiB) window->phys = 0xfff80000; + if (window->phys == 0) { + printk(KERN_ERR MOD_NAME ": Rom window is closed\n"); + goto out; + } + /* reserved 0x0020 and 0x0010 */ window->phys -= 0x400000UL; window->size = (0xffffffffUL - window->phys) + 1UL; diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c index 880580c44e0..41844ea0246 100644 --- a/drivers/mtd/mtdconcat.c +++ b/drivers/mtd/mtdconcat.c @@ -727,6 +727,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c concat->mtd.erasesize = subdev[0]->erasesize; concat->mtd.writesize = subdev[0]->writesize; concat->mtd.oobsize = subdev[0]->oobsize; + concat->mtd.oobavail = subdev[0]->oobavail; if (subdev[0]->writev) concat->mtd.writev = concat_writev; if (subdev[0]->read_oob) diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 633def3fb08..1af989023c6 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -200,6 +200,11 @@ static int part_erase (struct mtd_info *mtd, struct erase_info *instr) return -EINVAL; instr->addr += part->offset; ret = part->master->erase(part->master, instr); + if (ret) { + if (instr->fail_addr != 0xffffffff) + instr->fail_addr -= part->offset; + instr->addr -= part->offset; + } return ret; } @@ -338,6 +343,7 @@ int add_mtd_partitions(struct mtd_info *master, slave->mtd.size = parts[i].size; slave->mtd.writesize = master->writesize; slave->mtd.oobsize = master->oobsize; + slave->mtd.oobavail = master->oobavail; slave->mtd.subpage_sft = master->subpage_sft; slave->mtd.name = parts[i].name; @@ -559,4 +565,3 @@ EXPORT_SYMBOL_GPL(deregister_mtd_parser); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Nicolas Pitre <nico@cam.org>"); MODULE_DESCRIPTION("Generic support for partitioning of MTD devices"); - diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index 12608c13cce..595208f965a 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -114,7 +114,7 @@ module_param(no_autopart, int, 0); static int show_firmware_partition = 0; module_param(show_firmware_partition, int, 0); -#ifdef MTD_NAND_DISKONCHIP_BBTWRITE +#ifdef CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE static int inftl_bbt_write = 1; #else static int inftl_bbt_write = 0; diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index acaf97bc80d..6af37b8cff6 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2524,6 +2524,7 @@ int nand_scan_tail(struct mtd_info *mtd) for (i = 0; chip->ecc.layout->oobfree[i].length; i++) chip->ecc.layout->oobavail += chip->ecc.layout->oobfree[i].length; + mtd->oobavail = chip->ecc.layout->oobavail; /* * Set the number of read / write steps for one page depending on ECC diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 7f1cb6e5dcc..9e14a26ca4e 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -4,6 +4,11 @@ * Copyright (C) 2005-2007 Samsung Electronics * Kyungmin Park <kyungmin.park@samsung.com> * + * Credits: + * Adrian Hunter <ext-adrian.hunter@nokia.com>: + * auto-placement support, read-while load support, various fixes + * Copyright (C) Nokia Corporation, 2007 + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. @@ -831,7 +836,7 @@ static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf, int col int readcol = column; int readend = column + thislen; int lastgap = 0; - uint8_t *oob_buf = this->page_buf + mtd->writesize; + uint8_t *oob_buf = this->oob_buf; for (free = this->ecclayout->oobfree; free->length; ++free) { if (readcol >= lastgap) @@ -849,7 +854,8 @@ static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf, int col int n = ed - st; memcpy(buf, oob_buf + st, n); buf += n; - } + } else + break; } return 0; } @@ -947,9 +953,9 @@ static int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len, /** * onenand_read_oob - [MTD Interface] NAND write data and/or out-of-band - * @mtd: MTD device structure - * @from: offset to read from - * @ops: oob operation description structure + * @param mtd: MTD device structure + * @param from: offset to read from + * @param ops: oob operation description structure */ static int onenand_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) @@ -1017,7 +1023,7 @@ static int onenand_bbt_wait(struct mtd_info *mtd, int state) * onenand_bbt_read_oob - [MTD Interface] OneNAND read out-of-band for bbt scan * @param mtd MTD device structure * @param from offset to read from - * @param @ops oob operation description structure + * @param ops oob operation description structure * * OneNAND read out-of-band data from the spare area for bbt scan */ @@ -1093,7 +1099,7 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from, static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to) { struct onenand_chip *this = mtd->priv; - char *readp = this->page_buf + mtd->writesize; + char oobbuf[64]; int status, i; this->command(mtd, ONENAND_CMD_READOOB, to, mtd->oobsize); @@ -1102,9 +1108,9 @@ static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to if (status) return status; - this->read_bufferram(mtd, ONENAND_SPARERAM, readp, 0, mtd->oobsize); - for(i = 0; i < mtd->oobsize; i++) - if (buf[i] != 0xFF && buf[i] != readp[i]) + this->read_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize); + for (i = 0; i < mtd->oobsize; i++) + if (buf[i] != 0xFF && buf[i] != oobbuf[i]) return -EBADMSG; return 0; @@ -1290,7 +1296,8 @@ static int onenand_fill_auto_oob(struct mtd_info *mtd, u_char *oob_buf, int n = ed - st; memcpy(oob_buf + st, buf, n); buf += n; - } + } else + break; } return 0; } @@ -1312,6 +1319,7 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len, struct onenand_chip *this = mtd->priv; int column, ret = 0, oobsize; int written = 0; + u_char *oobbuf; DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); @@ -1331,7 +1339,7 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len, } /* For compatibility with NAND: Do not allow write past end of page */ - if (column + len > oobsize) { + if (unlikely(column + len > oobsize)) { printk(KERN_ERR "onenand_write_oob: " "Attempt to write past end of page\n"); return -EINVAL; @@ -1348,6 +1356,8 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len, /* Grab the lock and see if the device is available */ onenand_get_device(mtd, FL_WRITING); + oobbuf = this->oob_buf; + /* Loop until all data write */ while (written < len) { int thislen = min_t(int, oobsize, len - written); @@ -1358,12 +1368,12 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len, /* We send data to spare ram with oobsize * to prevent byte access */ - memset(this->page_buf, 0xff, mtd->oobsize); + memset(oobbuf, 0xff, mtd->oobsize); if (mode == MTD_OOB_AUTO) - onenand_fill_auto_oob(mtd, this->page_buf, buf, column, thislen); + onenand_fill_auto_oob(mtd, oobbuf, buf, column, thislen); else - memcpy(this->page_buf + column, buf, thislen); - this->write_bufferram(mtd, ONENAND_SPARERAM, this->page_buf, 0, mtd->oobsize); + memcpy(oobbuf + column, buf, thislen); + this->write_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize); this->command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize); @@ -1375,7 +1385,7 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len, break; } - ret = onenand_verify_oob(mtd, this->page_buf, to); + ret = onenand_verify_oob(mtd, oobbuf, to); if (ret) { printk(KERN_ERR "onenand_write_oob: verify failed %d\n", ret); break; @@ -1400,9 +1410,9 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len, /** * onenand_write_oob - [MTD Interface] NAND write data and/or out-of-band - * @mtd: MTD device structure - * @from: offset to read from - * @ops: oob operation description structure + * @param mtd: MTD device structure + * @param to: offset to write + * @param ops: oob operation description structure */ static int onenand_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops) @@ -1616,6 +1626,7 @@ static int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs) * @param mtd MTD device structure * @param ofs offset relative to mtd start * @param len number of bytes to lock or unlock + * @param cmd lock or unlock command * * Lock or unlock one or more blocks */ @@ -2117,10 +2128,11 @@ static void onenand_check_features(struct mtd_info *mtd) } /** - * onenand_print_device_info - Print device ID + * onenand_print_device_info - Print device & version ID * @param device device ID + * @param version version ID * - * Print device ID + * Print device & version ID */ static void onenand_print_device_info(int device, int version) { @@ -2320,15 +2332,25 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) /* Allocate buffers, if necessary */ if (!this->page_buf) { - size_t len; - len = mtd->writesize + mtd->oobsize; - this->page_buf = kmalloc(len, GFP_KERNEL); + this->page_buf = kzalloc(mtd->writesize, GFP_KERNEL); if (!this->page_buf) { printk(KERN_ERR "onenand_scan(): Can't allocate page_buf\n"); return -ENOMEM; } this->options |= ONENAND_PAGEBUF_ALLOC; } + if (!this->oob_buf) { + this->oob_buf = kzalloc(mtd->oobsize, GFP_KERNEL); + if (!this->oob_buf) { + printk(KERN_ERR "onenand_scan(): Can't allocate oob_buf\n"); + if (this->options & ONENAND_PAGEBUF_ALLOC) { + this->options &= ~ONENAND_PAGEBUF_ALLOC; + kfree(this->page_buf); + } + return -ENOMEM; + } + this->options |= ONENAND_OOBBUF_ALLOC; + } this->state = FL_READY; init_waitqueue_head(&this->wq); @@ -2367,6 +2389,7 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) for (i = 0; this->ecclayout->oobfree[i].length; i++) this->ecclayout->oobavail += this->ecclayout->oobfree[i].length; + mtd->oobavail = this->ecclayout->oobavail; mtd->ecclayout = this->ecclayout; @@ -2424,9 +2447,11 @@ void onenand_release(struct mtd_info *mtd) kfree(bbm->bbt); kfree(this->bbm); } - /* Buffer allocated by onenand_scan */ + /* Buffers allocated by onenand_scan */ if (this->options & ONENAND_PAGEBUF_ALLOC) kfree(this->page_buf); + if (this->options & ONENAND_OOBBUF_ALLOC) + kfree(this->oob_buf); } EXPORT_SYMBOL_GPL(onenand_scan); diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 72995777f80..b406ecfa726 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -858,19 +858,7 @@ static struct eisa_device_id vortex_eisa_ids[] = { }; MODULE_DEVICE_TABLE(eisa, vortex_eisa_ids); -static int vortex_eisa_probe(struct device *device); -static int vortex_eisa_remove(struct device *device); - -static struct eisa_driver vortex_eisa_driver = { - .id_table = vortex_eisa_ids, - .driver = { - .name = "3c59x", - .probe = vortex_eisa_probe, - .remove = vortex_eisa_remove - } -}; - -static int vortex_eisa_probe(struct device *device) +static int __init vortex_eisa_probe(struct device *device) { void __iomem *ioaddr; struct eisa_device *edev; @@ -893,7 +881,7 @@ static int vortex_eisa_probe(struct device *device) return 0; } -static int vortex_eisa_remove(struct device *device) +static int __devexit vortex_eisa_remove(struct device *device) { struct eisa_device *edev; struct net_device *dev; @@ -918,7 +906,17 @@ static int vortex_eisa_remove(struct device *device) free_netdev(dev); return 0; } -#endif + +static struct eisa_driver vortex_eisa_driver = { + .id_table = vortex_eisa_ids, + .driver = { + .name = "3c59x", + .probe = vortex_eisa_probe, + .remove = __devexit_p(vortex_eisa_remove) + } +}; + +#endif /* CONFIG_EISA */ /* returns count found (>= 0), or negative on error */ static int __init vortex_eisa_init(void) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index dae0aa408bc..753695b624b 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2373,22 +2373,23 @@ config CHELSIO_T1_NAPI when the driver is receiving lots of packets from the card. config CHELSIO_T3 - tristate "Chelsio Communications T3 10Gb Ethernet support" - depends on PCI - help - This driver supports Chelsio T3-based gigabit and 10Gb Ethernet - adapters. + tristate "Chelsio Communications T3 10Gb Ethernet support" + depends on PCI + select FW_LOADER + help + This driver supports Chelsio T3-based gigabit and 10Gb Ethernet + adapters. - For general information about Chelsio and our products, visit - our website at <http://www.chelsio.com>. + For general information about Chelsio and our products, visit + our website at <http://www.chelsio.com>. - For customer support, please visit our customer support page at - <http://www.chelsio.com/support.htm>. + For customer support, please visit our customer support page at + <http://www.chelsio.com/support.htm>. - Please send feedback to <linux-bugs@chelsio.com>. + Please send feedback to <linux-bugs@chelsio.com>. - To compile this driver as a module, choose M here: the module - will be called cxgb3. + To compile this driver as a module, choose M here: the module + will be called cxgb3. config EHEA tristate "eHEA Ethernet support" diff --git a/drivers/net/atl1/atl1_hw.c b/drivers/net/atl1/atl1_hw.c index 314dbaabb64..69482e0d849 100644 --- a/drivers/net/atl1/atl1_hw.c +++ b/drivers/net/atl1/atl1_hw.c @@ -334,7 +334,6 @@ u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr) int i; crc32 = ether_crc_le(6, mc_addr); - crc32 = ~crc32; for (i = 0; i < 32; i++) value |= (((crc32 >> i) & 1) << (31 - i)); diff --git a/drivers/net/atl1/atl1_main.c b/drivers/net/atl1/atl1_main.c index 88d4f70035b..8606eac5bec 100644 --- a/drivers/net/atl1/atl1_main.c +++ b/drivers/net/atl1/atl1_main.c @@ -1328,7 +1328,7 @@ static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb, if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { cso = skb->h.raw - skb->data; - css = (skb->h.raw + skb->csum) - skb->data; + css = (skb->h.raw + skb->csum_offset) - skb->data; if (unlikely(cso & 0x1)) { printk(KERN_DEBUG "%s: payload offset != even number\n", atl1_driver_name); @@ -1562,7 +1562,7 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev) /* mss will be nonzero if we're doing segment offload (TSO/GSO) */ mss = skb_shinfo(skb)->gso_size; if (mss) { - if (skb->protocol == ntohs(ETH_P_IP)) { + if (skb->protocol == htons(ETH_P_IP)) { proto_hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2)); if (unlikely(proto_hdr_len > len)) { @@ -2320,6 +2320,16 @@ static void __devexit atl1_remove(struct pci_dev *pdev) return; adapter = netdev_priv(netdev); + + /* Some atl1 boards lack persistent storage for their MAC, and get it + * from the BIOS during POST. If we've been messing with the MAC + * address, we need to save the permanent one. + */ + if (memcmp(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, ETH_ALEN)) { + memcpy(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, ETH_ALEN); + atl1_set_mac_addr(&adapter->hw); + } + iowrite16(0, adapter->hw.hw_addr + REG_GPHY_ENABLE); unregister_netdev(netdev); pci_iounmap(pdev, adapter->hw.hw_addr); diff --git a/drivers/net/b44.c b/drivers/net/b44.c index aaada572732..d742bfe2447 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -1709,7 +1709,7 @@ static void __b44_set_rx_mode(struct net_device *dev) bw32(bp, B44_RXCONFIG, val); } else { unsigned char zero[6] = {0, 0, 0, 0, 0, 0}; - int i = 0; + int i = 1; __b44_set_mac_addr(bp); diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index c12e5ea6181..0b7aded8dcf 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -54,8 +54,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.5.5" -#define DRV_MODULE_RELDATE "February 1, 2007" +#define DRV_MODULE_VERSION "1.5.7" +#define DRV_MODULE_RELDATE "March 29, 2007" #define RUN_AT(x) (jiffies + (x)) @@ -2033,8 +2033,8 @@ bnx2_has_work(struct bnx2 *bp) (sblk->status_tx_quick_consumer_index0 != bp->hw_tx_cons)) return 1; - if (((sblk->status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) != 0) != - bp->link_up) + if ((sblk->status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) != + (sblk->status_attn_bits_ack & STATUS_ATTN_BITS_LINK_STATE)) return 1; return 0; @@ -3099,20 +3099,18 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf, if ((align_start = (offset32 & 3))) { offset32 &= ~3; - len32 += (4 - align_start); + len32 += align_start; + if (len32 < 4) + len32 = 4; if ((rc = bnx2_nvram_read(bp, offset32, start, 4))) return rc; } if (len32 & 3) { - if ((len32 > 4) || !align_start) { - align_end = 4 - (len32 & 3); - len32 += align_end; - if ((rc = bnx2_nvram_read(bp, offset32 + len32 - 4, - end, 4))) { - return rc; - } - } + align_end = 4 - (len32 & 3); + len32 += align_end; + if ((rc = bnx2_nvram_read(bp, offset32 + len32 - 4, end, 4))) + return rc; } if (align_start || align_end) { @@ -3187,17 +3185,17 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf, if ((rc = bnx2_enable_nvram_write(bp)) != 0) goto nvram_write_end; - /* Erase the page */ - if ((rc = bnx2_nvram_erase_page(bp, page_start)) != 0) - goto nvram_write_end; - - /* Re-enable the write again for the actual write */ - bnx2_enable_nvram_write(bp); - /* Loop to write back the buffer data from page_start to * data_start */ i = 0; if (bp->flash_info->buffered == 0) { + /* Erase the page */ + if ((rc = bnx2_nvram_erase_page(bp, page_start)) != 0) + goto nvram_write_end; + + /* Re-enable the write again for the actual write */ + bnx2_enable_nvram_write(bp); + for (addr = page_start; addr < data_start; addr += 4, i += 4) { diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h index e23deeb7d06..8d137963369 100644 --- a/drivers/net/cxgb3/common.h +++ b/drivers/net/cxgb3/common.h @@ -112,8 +112,7 @@ enum { }; enum { - SUPPORTED_OFFLOAD = 1 << 24, - SUPPORTED_IRQ = 1 << 25 + SUPPORTED_IRQ = 1 << 24 }; enum { /* adapter interrupt-maintained statistics */ @@ -260,6 +259,10 @@ struct mac_stats { unsigned long serdes_signal_loss; unsigned long xaui_pcs_ctc_err; unsigned long xaui_pcs_align_change; + + unsigned long num_toggled; /* # times toggled TxEn due to stuck TX */ + unsigned long num_resets; /* # times reset due to stuck TX */ + }; struct tp_mib_stats { @@ -354,6 +357,9 @@ enum { MC5_MODE_72_BIT = 2 }; +/* MC5 min active region size */ +enum { MC5_MIN_TIDS = 16 }; + struct vpd_params { unsigned int cclk; unsigned int mclk; @@ -398,6 +404,13 @@ struct adapter_params { unsigned int stats_update_period; /* MAC stats accumulation period */ unsigned int linkpoll_period; /* link poll period in 0.1s */ unsigned int rev; /* chip revision */ + unsigned int offload; +}; + +enum { /* chip revisions */ + T3_REV_A = 0, + T3_REV_B = 2, + T3_REV_B2 = 3, }; struct trace_params { @@ -465,6 +478,13 @@ struct cmac { struct adapter *adapter; unsigned int offset; unsigned int nucast; /* # of address filters for unicast MACs */ + unsigned int tx_tcnt; + unsigned int tx_xcnt; + u64 tx_mcnt; + unsigned int rx_xcnt; + u64 rx_mcnt; + unsigned int toggle_cnt; + unsigned int txen; struct mac_stats stats; }; @@ -588,7 +608,7 @@ static inline int is_10G(const struct adapter *adap) static inline int is_offload(const struct adapter *adap) { - return adapter_info(adap)->caps & SUPPORTED_OFFLOAD; + return adap->params.offload; } static inline unsigned int core_ticks_per_usec(const struct adapter *adap) @@ -666,6 +686,7 @@ int t3_mac_set_address(struct cmac *mac, unsigned int idx, u8 addr[6]); int t3_mac_set_num_ucast(struct cmac *mac, int n); const struct mac_stats *t3_mac_update_stats(struct cmac *mac); int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc); +int t3b2_mac_watchdog_task(struct cmac *mac); void t3_mc5_prep(struct adapter *adapter, struct mc5 *mc5, int mode); int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters, diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 7ff834e45d6..67b4b219d92 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -42,6 +42,7 @@ #include <linux/workqueue.h> #include <linux/proc_fs.h> #include <linux/rtnetlink.h> +#include <linux/firmware.h> #include <asm/uaccess.h> #include "common.h" @@ -184,16 +185,24 @@ void t3_os_link_changed(struct adapter *adapter, int port_id, int link_stat, int speed, int duplex, int pause) { struct net_device *dev = adapter->port[port_id]; + struct port_info *pi = netdev_priv(dev); + struct cmac *mac = &pi->mac; /* Skip changes from disabled ports. */ if (!netif_running(dev)) return; if (link_stat != netif_carrier_ok(dev)) { - if (link_stat) + if (link_stat) { + t3_mac_enable(mac, MAC_DIRECTION_RX); netif_carrier_on(dev); - else + } else { netif_carrier_off(dev); + pi->phy.ops->power_down(&pi->phy, 1); + t3_mac_disable(mac, MAC_DIRECTION_RX); + t3_link_start(&pi->phy, mac, &pi->link_config); + } + link_report(dev); } } @@ -406,7 +415,7 @@ static void quiesce_rx(struct adapter *adap) static int setup_sge_qsets(struct adapter *adap) { int i, j, err, irq_idx = 0, qset_idx = 0, dummy_dev_idx = 0; - unsigned int ntxq = is_offload(adap) ? SGE_TXQ_PER_SET : 1; + unsigned int ntxq = SGE_TXQ_PER_SET; if (adap->params.rev > 0 && !(adap->flags & USING_MSI)) irq_idx = -1; @@ -484,12 +493,14 @@ static ssize_t show_##name(struct device *d, struct device_attribute *attr, \ static ssize_t set_nfilters(struct net_device *dev, unsigned int val) { struct adapter *adap = dev->priv; + int min_tids = is_offload(adap) ? MC5_MIN_TIDS : 0; if (adap->flags & FULL_INIT_DONE) return -EBUSY; if (val && adap->params.rev == 0) return -EINVAL; - if (val > t3_mc5_size(&adap->mc5) - adap->params.mc5.nservers) + if (val > t3_mc5_size(&adap->mc5) - adap->params.mc5.nservers - + min_tids) return -EINVAL; adap->params.mc5.nfilters = val; return 0; @@ -507,7 +518,8 @@ static ssize_t set_nservers(struct net_device *dev, unsigned int val) if (adap->flags & FULL_INIT_DONE) return -EBUSY; - if (val > t3_mc5_size(&adap->mc5) - adap->params.mc5.nfilters) + if (val > t3_mc5_size(&adap->mc5) - adap->params.mc5.nfilters - + MC5_MIN_TIDS) return -EINVAL; adap->params.mc5.nservers = val; return 0; @@ -707,6 +719,28 @@ static void bind_qsets(struct adapter *adap) } } +#define FW_FNAME "t3fw-%d.%d.%d.bin" + +static int upgrade_fw(struct adapter *adap) +{ + int ret; + char buf[64]; + const struct firmware *fw; + struct device *dev = &adap->pdev->dev; + + snprintf(buf, sizeof(buf), FW_FNAME, FW_VERSION_MAJOR, + FW_VERSION_MINOR, FW_VERSION_MICRO); + ret = request_firmware(&fw, buf, dev); + if (ret < 0) { + dev_err(dev, "could not upgrade firmware: unable to load %s\n", + buf); + return ret; + } + ret = t3_load_fw(adap, fw->data, fw->size); + release_firmware(fw); + return ret; +} + /** * cxgb_up - enable the adapter * @adapter: adapter being enabled @@ -723,6 +757,8 @@ static int cxgb_up(struct adapter *adap) if (!(adap->flags & FULL_INIT_DONE)) { err = t3_check_fw_version(adap); + if (err == -EINVAL) + err = upgrade_fw(adap); if (err) goto out; @@ -734,6 +770,8 @@ static int cxgb_up(struct adapter *adap) if (err) goto out; + t3_write_reg(adap, A_ULPRX_TDDP_PSZ, V_HPZ0(PAGE_SHIFT - 12)); + err = setup_sge_qsets(adap); if (err) goto out; @@ -894,7 +932,7 @@ static int cxgb_open(struct net_device *dev) return err; set_bit(pi->port_id, &adapter->open_device_map); - if (!ofld_disable) { + if (is_offload(adapter) && !ofld_disable) { err = offload_open(dev); if (err) printk(KERN_WARNING @@ -1031,7 +1069,11 @@ static char stats_strings[][ETH_GSTRING_LEN] = { "VLANinsertions ", "TxCsumOffload ", "RxCsumGood ", - "RxDrops " + "RxDrops ", + + "CheckTXEnToggled ", + "CheckResets ", + }; static int get_stats_count(struct net_device *dev) @@ -1145,6 +1187,9 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats, *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_TX_CSUM); *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_RX_CSUM_GOOD); *data++ = s->rx_cong_drops; + + *data++ = s->num_toggled; + *data++ = s->num_resets; } static inline void reg_block_dump(struct adapter *ap, void *buf, @@ -1362,23 +1407,27 @@ static int set_rx_csum(struct net_device *dev, u32 data) static void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e) { - struct adapter *adapter = dev->priv; + const struct adapter *adapter = dev->priv; + const struct port_info *pi = netdev_priv(dev); + const struct qset_params *q = &adapter->params.sge.qset[pi->first_qset]; e->rx_max_pending = MAX_RX_BUFFERS; e->rx_mini_max_pending = 0; e->rx_jumbo_max_pending = MAX_RX_JUMBO_BUFFERS; e->tx_max_pending = MAX_TXQ_ENTRIES; - e->rx_pending = adapter->params.sge.qset[0].fl_size; - e->rx_mini_pending = adapter->params.sge.qset[0].rspq_size; - e->rx_jumbo_pending = adapter->params.sge.qset[0].jumbo_size; - e->tx_pending = adapter->params.sge.qset[0].txq_size[0]; + e->rx_pending = q->fl_size; + e->rx_mini_pending = q->rspq_size; + e->rx_jumbo_pending = q->jumbo_size; + e->tx_pending = q->txq_size[0]; } static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e) { int i; + struct qset_params *q; struct adapter *adapter = dev->priv; + const struct port_info *pi = netdev_priv(dev); if (e->rx_pending > MAX_RX_BUFFERS || e->rx_jumbo_pending > MAX_RX_JUMBO_BUFFERS || @@ -1393,9 +1442,8 @@ static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e) if (adapter->flags & FULL_INIT_DONE) return -EBUSY; - for (i = 0; i < SGE_QSETS; ++i) { - struct qset_params *q = &adapter->params.sge.qset[i]; - + q = &adapter->params.sge.qset[pi->first_qset]; + for (i = 0; i < pi->nqsets; ++i, ++q) { q->rspq_size = e->rx_mini_pending; q->fl_size = e->rx_pending; q->jumbo_size = e->rx_jumbo_pending; @@ -2067,6 +2115,42 @@ static void check_link_status(struct adapter *adapter) } } +static void check_t3b2_mac(struct adapter *adapter) +{ + int i; + + if (!rtnl_trylock()) /* synchronize with ifdown */ + return; + + for_each_port(adapter, i) { + struct net_device *dev = adapter->port[i]; + struct port_info *p = netdev_priv(dev); + int status; + + if (!netif_running(dev)) + continue; + + status = 0; + if (netif_running(dev) && netif_carrier_ok(dev)) + status = t3b2_mac_watchdog_task(&p->mac); + if (status == 1) + p->mac.stats.num_toggled++; + else if (status == 2) { + struct cmac *mac = &p->mac; + + t3_mac_set_mtu(mac, dev->mtu); + t3_mac_set_address(mac, 0, dev->dev_addr); + cxgb_set_rxmode(dev); + t3_link_start(&p->phy, mac, &p->link_config); + t3_mac_enable(mac, MAC_DIRECTION_RX | MAC_DIRECTION_TX); + t3_port_intr_enable(adapter, p->port_id); + p->mac.stats.num_resets++; + } + } + rtnl_unlock(); +} + + static void t3_adap_check_task(struct work_struct *work) { struct adapter *adapter = container_of(work, struct adapter, @@ -2087,6 +2171,9 @@ static void t3_adap_check_task(struct work_struct *work) adapter->check_task_cnt = 0; } + if (p->rev == T3_REV_B2) + check_t3b2_mac(adapter); + /* Schedule the next check update if any port is active. */ spin_lock(&adapter->work_lock); if (adapter->open_device_map & PORT_MASK) @@ -2195,9 +2282,9 @@ static void __devinit print_port_info(struct adapter *adap, if (!test_bit(i, &adap->registered_device_map)) continue; - printk(KERN_INFO "%s: %s %s RNIC (rev %d) %s%s\n", + printk(KERN_INFO "%s: %s %s %sNIC (rev %d) %s%s\n", dev->name, ai->desc, pi->port_type->desc, - adap->params.rev, buf, + is_offload(adap) ? "R" : "", adap->params.rev, buf, (adap->flags & USING_MSIX) ? " MSI-X" : (adap->flags & USING_MSI) ? " MSI" : ""); if (adap->name == dev->name && adap->params.vpd.mclk) diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c index f6ed033efb5..48649244673 100644 --- a/drivers/net/cxgb3/cxgb3_offload.c +++ b/drivers/net/cxgb3/cxgb3_offload.c @@ -553,7 +553,9 @@ int cxgb3_alloc_atid(struct t3cdev *tdev, struct cxgb3_client *client, struct tid_info *t = &(T3C_DATA(tdev))->tid_maps; spin_lock_bh(&t->atid_lock); - if (t->afree) { + if (t->afree && + t->atids_in_use + atomic_read(&t->tids_in_use) + MC5_MIN_TIDS <= + t->ntids) { union active_open_entry *p = t->afree; atid = (p - t->atid_tab) + t->atid_base; @@ -741,17 +743,6 @@ static int do_act_establish(struct t3cdev *dev, struct sk_buff *skb) } } -static int do_set_tcb_rpl(struct t3cdev *dev, struct sk_buff *skb) -{ - struct cpl_set_tcb_rpl *rpl = cplhdr(skb); - - if (rpl->status != CPL_ERR_NONE) - printk(KERN_ERR - "Unexpected SET_TCB_RPL status %u for tid %u\n", - rpl->status, GET_TID(rpl)); - return CPL_RET_BUF_DONE; -} - static int do_trace(struct t3cdev *dev, struct sk_buff *skb) { struct cpl_trace_pkt *p = cplhdr(skb); @@ -1213,7 +1204,8 @@ void __init cxgb3_offload_init(void) t3_register_cpl_handler(CPL_CLOSE_CON_RPL, do_hwtid_rpl); t3_register_cpl_handler(CPL_ABORT_REQ_RSS, do_abort_req_rss); t3_register_cpl_handler(CPL_ACT_ESTABLISH, do_act_establish); - t3_register_cpl_handler(CPL_SET_TCB_RPL, do_set_tcb_rpl); + t3_register_cpl_handler(CPL_SET_TCB_RPL, do_hwtid_rpl); + t3_register_cpl_handler(CPL_GET_TCB_RPL, do_hwtid_rpl); t3_register_cpl_handler(CPL_RDMA_TERMINATE, do_term); t3_register_cpl_handler(CPL_RDMA_EC_STATUS, do_hwtid_rpl); t3_register_cpl_handler(CPL_TRACE_PKT, do_trace); diff --git a/drivers/net/cxgb3/mc5.c b/drivers/net/cxgb3/mc5.c index 644d62ea86a..84c1ffa8e2d 100644 --- a/drivers/net/cxgb3/mc5.c +++ b/drivers/net/cxgb3/mc5.c @@ -328,6 +328,9 @@ int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters, unsigned int tcam_size = mc5->tcam_size; struct adapter *adap = mc5->adapter; + if (!tcam_size) + return 0; + if (nroutes > MAX_ROUTES || nroutes + nservers + nfilters > tcam_size) return -EINVAL; diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/cxgb3/regs.h index b56c5f52bcd..e5a553410e2 100644 --- a/drivers/net/cxgb3/regs.h +++ b/drivers/net/cxgb3/regs.h @@ -1206,6 +1206,14 @@ #define A_TP_RX_TRC_KEY0 0x120 +#define A_TP_TX_DROP_CNT_CH0 0x12d + +#define S_TXDROPCNTCH0RCVD 0 +#define M_TXDROPCNTCH0RCVD 0xffff +#define V_TXDROPCNTCH0RCVD(x) ((x) << S_TXDROPCNTCH0RCVD) +#define G_TXDROPCNTCH0RCVD(x) (((x) >> S_TXDROPCNTCH0RCVD) & \ + M_TXDROPCNTCH0RCVD) + #define A_ULPRX_CTL 0x500 #define S_ROUND_ROBIN 4 @@ -1226,9 +1234,15 @@ #define A_ULPRX_ISCSI_TAGMASK 0x514 +#define S_HPZ0 0 +#define M_HPZ0 0xf +#define V_HPZ0(x) ((x) << S_HPZ0) +#define G_HPZ0(x) (((x) >> S_HPZ0) & M_HPZ0) + #define A_ULPRX_TDDP_LLIMIT 0x51c #define A_ULPRX_TDDP_ULIMIT 0x520 +#define A_ULPRX_TDDP_PSZ 0x528 #define A_ULPRX_STAG_LLIMIT 0x52c @@ -1834,6 +1848,8 @@ #define V_TXPAUSEEN(x) ((x) << S_TXPAUSEEN) #define F_TXPAUSEEN V_TXPAUSEEN(1U) +#define A_XGM_TX_PAUSE_QUANTA 0x808 + #define A_XGM_RX_CTRL 0x80c #define S_RXEN 0 @@ -1920,11 +1936,20 @@ #define A_XGM_TXFIFO_CFG 0x888 +#define S_TXIPG 13 +#define M_TXIPG 0xff +#define V_TXIPG(x) ((x) << S_TXIPG) +#define G_TXIPG(x) (((x) >> S_TXIPG) & M_TXIPG) + #define S_TXFIFOTHRESH 4 #define M_TXFIFOTHRESH 0x1ff #define V_TXFIFOTHRESH(x) ((x) << S_TXFIFOTHRESH) +#define S_ENDROPPKT 21 +#define V_ENDROPPKT(x) ((x) << S_ENDROPPKT) +#define F_ENDROPPKT V_ENDROPPKT(1U) + #define A_XGM_SERDES_CTRL 0x890 #define A_XGM_SERDES_CTRL0 0x8e0 @@ -2190,6 +2215,13 @@ #define A_XGM_RX_MAX_PKT_SIZE_ERR_CNT 0x9a4 +#define A_XGM_TX_SPI4_SOP_EOP_CNT 0x9a8 + +#define S_TXSPI4SOPCNT 16 +#define M_TXSPI4SOPCNT 0xffff +#define V_TXSPI4SOPCNT(x) ((x) << S_TXSPI4SOPCNT) +#define G_TXSPI4SOPCNT(x) (((x) >> S_TXSPI4SOPCNT) & M_TXSPI4SOPCNT) + #define A_XGM_RX_SPI4_SOP_EOP_CNT 0x9ac #define XGMAC0_1_BASE_ADDR 0xa00 diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index c23783432e5..027ab2c3825 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -2631,7 +2631,7 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, q->txq[TXQ_ETH].stop_thres = nports * flits_to_desc(sgl_len(MAX_SKB_FRAGS + 1) + 3); - if (ntxq == 1) { + if (!is_offload(adapter)) { #ifdef USE_RX_PAGE q->fl[0].buf_size = RX_PAGE_SIZE; #else diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c index eaa7a2e89a3..d83f075ef2d 100644 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c @@ -438,23 +438,23 @@ static const struct adapter_info t3_adap_info[] = { {2, 0, 0, 0, F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, F_GPIO3 | F_GPIO5, - SUPPORTED_OFFLOAD, + 0, &mi1_mdio_ops, "Chelsio PE9000"}, {2, 0, 0, 0, F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, F_GPIO3 | F_GPIO5, - SUPPORTED_OFFLOAD, + 0, &mi1_mdio_ops, "Chelsio T302"}, {1, 0, 0, 0, F_GPIO1_OEN | F_GPIO6_OEN | F_GPIO7_OEN | F_GPIO10_OEN | F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, 0, - SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_OFFLOAD, + SUPPORTED_10000baseT_Full | SUPPORTED_AUI, &mi1_mdio_ext_ops, "Chelsio T310"}, {2, 0, 0, 0, F_GPIO1_OEN | F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO5_OEN | F_GPIO6_OEN | F_GPIO7_OEN | F_GPIO10_OEN | F_GPIO11_OEN | F_GPIO1_OUT_VAL | F_GPIO5_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, 0, - SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_OFFLOAD, + SUPPORTED_10000baseT_Full | SUPPORTED_AUI, &mi1_mdio_ext_ops, "Chelsio T320"}, }; @@ -681,7 +681,8 @@ enum { SF_ERASE_SECTOR = 0xd8, /* erase sector */ FW_FLASH_BOOT_ADDR = 0x70000, /* start address of FW in flash */ - FW_VERS_ADDR = 0x77ffc /* flash address holding FW version */ + FW_VERS_ADDR = 0x77ffc, /* flash address holding FW version */ + FW_MIN_SIZE = 8 /* at least version and csum */ }; /** @@ -935,7 +936,7 @@ int t3_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size) const u32 *p = (const u32 *)fw_data; int ret, addr, fw_sector = FW_FLASH_BOOT_ADDR >> 16; - if (size & 3) + if ((size & 3) || size < FW_MIN_SIZE) return -EINVAL; if (size > FW_VERS_ADDR + 8 - FW_FLASH_BOOT_ADDR) return -EFBIG; @@ -2899,6 +2900,9 @@ static int mc7_init(struct mc7 *mc7, unsigned int mc7_clock, int mem_type) struct adapter *adapter = mc7->adapter; const struct mc7_timing_params *p = &mc7_timings[mem_type]; + if (!mc7->size) + return 0; + val = t3_read_reg(adapter, mc7->offset + A_MC7_CFG); slow = val & F_SLOW; width = G_WIDTH(val); @@ -3099,8 +3103,10 @@ int t3_init_hw(struct adapter *adapter, u32 fw_params) do { /* wait for uP to initialize */ msleep(20); } while (t3_read_reg(adapter, A_CIM_HOST_ACC_DATA) && --attempts); - if (!attempts) + if (!attempts) { + CH_ERR(adapter, "uP initialization timed out\n"); goto out_err; + } err = 0; out_err: @@ -3200,7 +3206,7 @@ static void __devinit mc7_prep(struct adapter *adapter, struct mc7 *mc7, mc7->name = name; mc7->offset = base_addr - MC7_PMRX_BASE_ADDR; cfg = t3_read_reg(adapter, mc7->offset + A_MC7_CFG); - mc7->size = mc7_calc_size(cfg); + mc7->size = mc7->size = G_DEN(cfg) == M_DEN ? 0 : mc7_calc_size(cfg); mc7->width = G_WIDTH(cfg); } @@ -3227,6 +3233,7 @@ void early_hw_init(struct adapter *adapter, const struct adapter_info *ai) V_I2C_CLKDIV(adapter->params.vpd.cclk / 80 - 1)); t3_write_reg(adapter, A_T3DBG_GPIO_EN, ai->gpio_out | F_GPIO0_OEN | F_GPIO0_OUT_VAL); + t3_write_reg(adapter, A_MC5_DB_SERVER_INDEX, 0); if (adapter->params.rev == 0 || !uses_xaui(adapter)) val |= F_ENRGMII; @@ -3243,15 +3250,17 @@ void early_hw_init(struct adapter *adapter, const struct adapter_info *ai) } /* - * Reset the adapter. PCIe cards lose their config space during reset, PCI-X + * Reset the adapter. + * Older PCIe cards lose their config space during reset, PCI-X * ones don't. */ int t3_reset_adapter(struct adapter *adapter) { - int i; + int i, save_and_restore_pcie = + adapter->params.rev < T3_REV_B2 && is_pcie(adapter); uint16_t devid = 0; - if (is_pcie(adapter)) + if (save_and_restore_pcie) pci_save_state(adapter->pdev); t3_write_reg(adapter, A_PL_RST, F_CRSTWRM | F_CRSTWRMMODE); @@ -3269,7 +3278,7 @@ int t3_reset_adapter(struct adapter *adapter) if (devid != 0x1425) return -1; - if (is_pcie(adapter)) + if (save_and_restore_pcie) pci_restore_state(adapter->pdev); return 0; } @@ -3323,7 +3332,13 @@ int __devinit t3_prep_adapter(struct adapter *adapter, p->tx_num_pgs = pm_num_pages(p->chan_tx_size, p->tx_pg_size); p->ntimer_qs = p->cm_size >= (128 << 20) || adapter->params.rev > 0 ? 12 : 6; + } + + adapter->params.offload = t3_mc7_size(&adapter->pmrx) && + t3_mc7_size(&adapter->pmtx) && + t3_mc7_size(&adapter->cm); + if (is_offload(adapter)) { adapter->params.mc5.nservers = DEFAULT_NSERVERS; adapter->params.mc5.nfilters = adapter->params.rev > 0 ? DEFAULT_NFILTERS : 0; diff --git a/drivers/net/cxgb3/version.h b/drivers/net/cxgb3/version.h index 82278f85025..042e27e291c 100644 --- a/drivers/net/cxgb3/version.h +++ b/drivers/net/cxgb3/version.h @@ -36,6 +36,9 @@ #define DRV_NAME "cxgb3" /* Driver version */ #define DRV_VERSION "1.0-ko" + +/* Firmware version */ #define FW_VERSION_MAJOR 3 -#define FW_VERSION_MINOR 2 +#define FW_VERSION_MINOR 3 +#define FW_VERSION_MICRO 0 #endif /* __CHELSIO_VERSION_H */ diff --git a/drivers/net/cxgb3/xgmac.c b/drivers/net/cxgb3/xgmac.c index 907a272ae32..a506792f957 100644 --- a/drivers/net/cxgb3/xgmac.c +++ b/drivers/net/cxgb3/xgmac.c @@ -124,9 +124,6 @@ int t3_mac_reset(struct cmac *mac) xaui_serdes_reset(mac); } - if (adap->params.rev > 0) - t3_write_reg(adap, A_XGM_PAUSE_TIMER + oft, 0xf000); - val = F_MAC_RESET_; if (is_10G(adap)) val |= F_PCS_RESET_; @@ -145,6 +142,58 @@ int t3_mac_reset(struct cmac *mac) return 0; } +int t3b2_mac_reset(struct cmac *mac) +{ + struct adapter *adap = mac->adapter; + unsigned int oft = mac->offset; + u32 val; + + if (!macidx(mac)) + t3_set_reg_field(adap, A_MPS_CFG, F_PORT0ACTIVE, 0); + else + t3_set_reg_field(adap, A_MPS_CFG, F_PORT1ACTIVE, 0); + + t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_); + t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ + + msleep(10); + + /* Check for xgm Rx fifo empty */ + if (t3_wait_op_done(adap, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT + oft, + 0x80000000, 1, 5, 2)) { + CH_ERR(adap, "MAC %d Rx fifo drain failed\n", + macidx(mac)); + return -1; + } + + t3_write_reg(adap, A_XGM_RESET_CTRL + oft, 0); + t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ + + val = F_MAC_RESET_; + if (is_10G(adap)) + val |= F_PCS_RESET_; + else if (uses_xaui(adap)) + val |= F_PCS_RESET_ | F_XG2G_RESET_; + else + val |= F_RGMII_RESET_ | F_XG2G_RESET_; + t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val); + t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ + if ((val & F_PCS_RESET_) && adap->params.rev) { + msleep(1); + t3b_pcs_reset(mac); + } + t3_write_reg(adap, A_XGM_RX_CFG + oft, + F_DISPAUSEFRAMES | F_EN1536BFRAMES | + F_RMFCS | F_ENJUMBO | F_ENHASHMCAST); + + if (!macidx(mac)) + t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT0ACTIVE); + else + t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT1ACTIVE); + + return 0; +} + /* * Set the exact match register 'idx' to recognize the given Ethernet address. */ @@ -251,9 +300,11 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu) * Adjust the PAUSE frame watermarks. We always set the LWM, and the * HWM only if flow-control is enabled. */ - hwm = max(MAC_RXFIFO_SIZE - 3 * mtu, MAC_RXFIFO_SIZE / 2U); - hwm = min(hwm, 3 * MAC_RXFIFO_SIZE / 4 + 1024); - lwm = hwm - 1024; + hwm = max_t(unsigned int, MAC_RXFIFO_SIZE - 3 * mtu, + MAC_RXFIFO_SIZE * 38 / 100); + hwm = min(hwm, MAC_RXFIFO_SIZE - 8192); + lwm = min(3 * (int)mtu, MAC_RXFIFO_SIZE / 4); + v = t3_read_reg(adap, A_XGM_RXFIFO_CFG + mac->offset); v &= ~V_RXFIFOPAUSELWM(M_RXFIFOPAUSELWM); v |= V_RXFIFOPAUSELWM(lwm / 8); @@ -270,7 +321,15 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu) thres = mtu > thres ? (mtu - thres + 7) / 8 : 0; thres = max(thres, 8U); /* need at least 8 */ t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + mac->offset, - V_TXFIFOTHRESH(M_TXFIFOTHRESH), V_TXFIFOTHRESH(thres)); + V_TXFIFOTHRESH(M_TXFIFOTHRESH) | V_TXIPG(M_TXIPG), + V_TXFIFOTHRESH(thres) | V_TXIPG(1)); + + if (adap->params.rev > 0) + t3_write_reg(adap, A_XGM_PAUSE_TIMER + mac->offset, + (hwm - lwm) * 4 / 8); + t3_write_reg(adap, A_XGM_TX_PAUSE_QUANTA + mac->offset, + MAC_RXFIFO_SIZE * 4 * 8 / 512); + return 0; } @@ -298,12 +357,6 @@ int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc) V_PORTSPEED(M_PORTSPEED), val); } - val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft); - val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM); - if (fc & PAUSE_TX) - val |= V_RXFIFOPAUSEHWM(G_RXFIFOPAUSELWM(val) + 128); /* +1KB */ - t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val); - t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN, (fc & PAUSE_RX) ? F_TXPAUSEEN : 0); return 0; @@ -314,13 +367,28 @@ int t3_mac_enable(struct cmac *mac, int which) int idx = macidx(mac); struct adapter *adap = mac->adapter; unsigned int oft = mac->offset; - + struct mac_stats *s = &mac->stats; + if (which & MAC_DIRECTION_TX) { t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN); t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); - t3_write_reg(adap, A_TP_PIO_DATA, 0xbf000001); + t3_write_reg(adap, A_TP_PIO_DATA, 0xc0ede401); t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_MODE); t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 1 << idx); + + t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CNT_CH0 + idx); + mac->tx_mcnt = s->tx_frames; + mac->tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap, + A_TP_PIO_DATA))); + mac->tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, + A_XGM_TX_SPI4_SOP_EOP_CNT + + oft))); + mac->rx_mcnt = s->rx_frames; + mac->rx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, + A_XGM_RX_SPI4_SOP_EOP_CNT + + oft))); + mac->txen = F_TXEN; + mac->toggle_cnt = 0; } if (which & MAC_DIRECTION_RX) t3_write_reg(adap, A_XGM_RX_CTRL + oft, F_RXEN); @@ -331,19 +399,102 @@ int t3_mac_disable(struct cmac *mac, int which) { int idx = macidx(mac); struct adapter *adap = mac->adapter; + int val; if (which & MAC_DIRECTION_TX) { t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0); t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); t3_write_reg(adap, A_TP_PIO_DATA, 0xc000001f); t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_MODE); - t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 0); + t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 1 << idx); + mac->txen = 0; } - if (which & MAC_DIRECTION_RX) + if (which & MAC_DIRECTION_RX) { + t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset, + F_PCS_RESET_, 0); + msleep(100); t3_write_reg(adap, A_XGM_RX_CTRL + mac->offset, 0); + val = F_MAC_RESET_; + if (is_10G(adap)) + val |= F_PCS_RESET_; + else if (uses_xaui(adap)) + val |= F_PCS_RESET_ | F_XG2G_RESET_; + else + val |= F_RGMII_RESET_ | F_XG2G_RESET_; + t3_write_reg(mac->adapter, A_XGM_RESET_CTRL + mac->offset, val); + } return 0; } +int t3b2_mac_watchdog_task(struct cmac *mac) +{ + struct adapter *adap = mac->adapter; + struct mac_stats *s = &mac->stats; + unsigned int tx_tcnt, tx_xcnt; + unsigned int tx_mcnt = s->tx_frames; + unsigned int rx_mcnt = s->rx_frames; + unsigned int rx_xcnt; + int status; + + if (tx_mcnt == mac->tx_mcnt) { + tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, + A_XGM_TX_SPI4_SOP_EOP_CNT + + mac->offset))); + if (tx_xcnt == 0) { + t3_write_reg(adap, A_TP_PIO_ADDR, + A_TP_TX_DROP_CNT_CH0 + macidx(mac)); + tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap, + A_TP_PIO_DATA))); + } else { + mac->toggle_cnt = 0; + return 0; + } + } else { + mac->toggle_cnt = 0; + return 0; + } + + if (((tx_tcnt != mac->tx_tcnt) && + (tx_xcnt == 0) && (mac->tx_xcnt == 0)) || + ((mac->tx_mcnt == tx_mcnt) && + (tx_xcnt != 0) && (mac->tx_xcnt != 0))) { + if (mac->toggle_cnt > 4) + status = 2; + else + status = 1; + } else { + mac->toggle_cnt = 0; + return 0; + } + + if (rx_mcnt != mac->rx_mcnt) + rx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, + A_XGM_RX_SPI4_SOP_EOP_CNT + + mac->offset))); + else + return 0; + + if (mac->rx_mcnt != s->rx_frames && rx_xcnt == 0 && mac->rx_xcnt == 0) + status = 2; + + mac->tx_tcnt = tx_tcnt; + mac->tx_xcnt = tx_xcnt; + mac->tx_mcnt = s->tx_frames; + mac->rx_xcnt = rx_xcnt; + mac->rx_mcnt = s->rx_frames; + if (status == 1) { + t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0); + t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); /* flush */ + t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, mac->txen); + t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); /* flush */ + mac->toggle_cnt++; + } else if (status == 2) { + t3b2_mac_reset(mac); + mac->toggle_cnt = 0; + } + return status; +} + /* * This function is called periodically to accumulate the current values of the * RMON counters into the port statistics. Since the packet counters are only @@ -373,7 +524,11 @@ const struct mac_stats *t3_mac_update_stats(struct cmac *mac) RMON_UPDATE(mac, rx_symbol_errs, RX_SYM_CODE_ERR_FRAMES); RMON_UPDATE(mac, rx_too_long, RX_OVERSIZE_FRAMES); - mac->stats.rx_too_long += RMON_READ(mac, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT); + + v = RMON_READ(mac, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT); + if (mac->adapter->params.rev == T3_REV_B2) + v &= 0x7fffffff; + mac->stats.rx_too_long += v; RMON_UPDATE(mac, rx_frames_64, RX_64B_FRAMES); RMON_UPDATE(mac, rx_frames_65_127, RX_65_127B_FRAMES); diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c index c8c41f0a47d..714ea1176ec 100644 --- a/drivers/net/ewrk3.c +++ b/drivers/net/ewrk3.c @@ -414,10 +414,9 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase) icr &= 0x70; outb(icr, EWRK3_ICR); /* Disable all the IRQs */ - if (nicsr == (CSR_TXD | CSR_RXD)) + if (nicsr != (CSR_TXD | CSR_RXD)) return -ENXIO; - /* Check that the EEPROM is alive and well and not living on Pluto... */ for (chksum = 0, i = 0; i < EEPROM_MAX; i += 2) { union { diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 46e1697d9cf..d04214e4e58 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -2050,9 +2050,10 @@ static void nv_tx_timeout(struct net_device *dev) nv_drain_tx(dev); nv_init_tx(dev); setup_hw_rings(dev, NV_SETUP_TX_RING); - netif_wake_queue(dev); } + netif_wake_queue(dev); + /* 4) restart tx engine */ nv_start_tx(dev); spin_unlock_irq(&np->lock); @@ -3536,7 +3537,10 @@ static void nv_do_nic_poll(unsigned long data) pci_push(base); if (!using_multi_irqs(dev)) { - nv_nic_irq(0, dev); + if (np->desc_ver == DESC_VER_3) + nv_nic_irq_optimized(0, dev); + else + nv_nic_irq(0, dev); if (np->msi_flags & NV_MSI_X_ENABLED) enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); else diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c index ca2b21f9d44..07b4c0d7a75 100644 --- a/drivers/net/ifb.c +++ b/drivers/net/ifb.c @@ -96,17 +96,24 @@ static void ri_tasklet(unsigned long dev) skb->tc_verd = SET_TC_NCLS(skb->tc_verd); stats->tx_packets++; stats->tx_bytes +=skb->len; + + skb->dev = __dev_get_by_index(skb->iif); + if (!skb->dev) { + dev_kfree_skb(skb); + stats->tx_dropped++; + break; + } + skb->iif = _dev->ifindex; + if (from & AT_EGRESS) { dp->st_rx_frm_egr++; dev_queue_xmit(skb); } else if (from & AT_INGRESS) { - dp->st_rx_frm_ing++; + skb_pull(skb, skb->dev->hard_header_len); netif_rx(skb); - } else { - dev_kfree_skb(skb); - stats->tx_dropped++; - } + } else + BUG(); } if (netif_tx_trylock(_dev)) { @@ -157,26 +164,10 @@ static int ifb_xmit(struct sk_buff *skb, struct net_device *dev) stats->rx_packets++; stats->rx_bytes+=skb->len; - if (!from || !skb->input_dev) { -dropped: + if (!(from & (AT_INGRESS|AT_EGRESS)) || !skb->iif) { dev_kfree_skb(skb); stats->rx_dropped++; return ret; - } else { - /* - * note we could be going - * ingress -> egress or - * egress -> ingress - */ - skb->dev = skb->input_dev; - skb->input_dev = dev; - if (from & AT_INGRESS) { - skb_pull(skb, skb->dev->hard_header_len); - } else { - if (!(from & AT_EGRESS)) { - goto dropped; - } - } } if (skb_queue_len(&dp->rq) >= dev->tx_queue_len) { diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index 340ee99652e..1d510bdc9b8 100644 --- a/drivers/net/irda/irda-usb.c +++ b/drivers/net/irda/irda-usb.c @@ -1057,6 +1057,8 @@ static int stir421x_fw_upload(struct irda_usb_cb *self, if (ret < 0) break; + + mdelay(10); } kfree(patch_block); diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c index 9137e239fac..2272156af31 100644 --- a/drivers/net/irda/pxaficp_ir.c +++ b/drivers/net/irda/pxaficp_ir.c @@ -321,15 +321,22 @@ static void pxa_irda_fir_dma_tx_irq(int channel, void *data) pxa_irda_set_speed(si, si->newspeed); si->newspeed = 0; } else { + int i = 64; + ICCR0 = 0; pxa_irda_fir_dma_rx_start(si); + while ((ICSR1 & ICSR1_RNE) && i--) + (void)ICDR; ICCR0 = ICCR0_ITR | ICCR0_RXE; + + if (i < 0) + printk(KERN_ERR "pxa_ir: cannot clear Rx FIFO!\n"); } netif_wake_queue(dev); } /* EIF(Error in FIFO/End in Frame) handler for FIR */ -static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev) +static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev, int icsr0) { unsigned int len, stat, data; @@ -350,7 +357,7 @@ static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev) } if (stat & ICSR1_ROR) { printk(KERN_DEBUG "pxa_ir: fir receive overrun\n"); - si->stats.rx_frame_errors++; + si->stats.rx_over_errors++; } } else { si->dma_rx_buff[len++] = data; @@ -362,7 +369,15 @@ static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev) if (stat & ICSR1_EOF) { /* end of frame. */ - struct sk_buff *skb = alloc_skb(len+1,GFP_ATOMIC); + struct sk_buff *skb; + + if (icsr0 & ICSR0_FRE) { + printk(KERN_ERR "pxa_ir: dropping erroneous frame\n"); + si->stats.rx_dropped++; + return; + } + + skb = alloc_skb(len+1,GFP_ATOMIC); if (!skb) { printk(KERN_ERR "pxa_ir: fir out of memory for receive skb\n"); si->stats.rx_dropped++; @@ -392,7 +407,7 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id) { struct net_device *dev = dev_id; struct pxa_irda *si = netdev_priv(dev); - int icsr0; + int icsr0, i = 64; /* stop RX DMA */ DCSR(si->rxdma) &= ~DCSR_RUN; @@ -412,13 +427,18 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id) if (icsr0 & ICSR0_EIF) { /* An error in FIFO occured, or there is a end of frame */ - pxa_irda_fir_irq_eif(si, dev); + pxa_irda_fir_irq_eif(si, dev, icsr0); } ICCR0 = 0; pxa_irda_fir_dma_rx_start(si); + while ((ICSR1 & ICSR1_RNE) && i--) + (void)ICDR; ICCR0 = ICCR0_ITR | ICCR0_RXE; + if (i < 0) + printk(KERN_ERR "pxa_ir: cannot clear Rx FIFO!\n"); + return IRQ_HANDLED; } diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 9ba21e0f27c..8015a7c5b0c 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -787,6 +787,12 @@ static int mv643xx_eth_open(struct net_device *dev) unsigned int size; int err; + /* Clear any pending ethernet port interrupts */ + mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0); + mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0); + /* wait for previous write to complete */ + mv_read (MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num)); + err = request_irq(dev->irq, mv643xx_eth_int_handler, IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, dev); if (err) { @@ -875,10 +881,6 @@ static int mv643xx_eth_open(struct net_device *dev) mv643xx_eth_rx_refill_descs(dev); /* Fill RX ring with skb's */ - /* Clear any pending ethernet port interrupts */ - mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0); - mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0); - eth_port_start(dev); /* Interrupt Coalescing */ @@ -1377,7 +1379,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev) spin_lock_init(&mp->lock); - port_num = pd->port_number; + port_num = mp->port_num = pd->port_number; /* set default config values */ eth_port_uc_addr_get(dev, dev->dev_addr); @@ -1409,8 +1411,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev) duplex = pd->duplex; speed = pd->speed; - mp->port_num = port_num; - /* Hook up MII support for ethtool */ mp->mii.dev = dev; mp->mii.mdio_read = mv643xx_mdio_read; @@ -1514,9 +1514,23 @@ static int mv643xx_eth_shared_remove(struct platform_device *pdev) return 0; } +static void mv643xx_eth_shutdown(struct platform_device *pdev) +{ + struct net_device *dev = platform_get_drvdata(pdev); + struct mv643xx_private *mp = netdev_priv(dev); + unsigned int port_num = mp->port_num; + + /* Mask all interrupts on ethernet port */ + mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), 0); + mv_read (MV643XX_ETH_INTERRUPT_MASK_REG(port_num)); + + eth_port_reset(port_num); +} + static struct platform_driver mv643xx_eth_driver = { .probe = mv643xx_eth_probe, .remove = mv643xx_eth_remove, + .shutdown = mv643xx_eth_shutdown, .driver = { .name = MV643XX_ETH_NAME, }, diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index b05dc6ed7fb..f8efe0e70a6 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -71,7 +71,7 @@ #include "myri10ge_mcp.h" #include "myri10ge_mcp_gen_header.h" -#define MYRI10GE_VERSION_STR "1.2.0" +#define MYRI10GE_VERSION_STR "1.3.0-1.233" MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); MODULE_AUTHOR("Maintainer: help@myri.com"); @@ -181,6 +181,7 @@ struct myri10ge_priv { int intr_coal_delay; __be32 __iomem *intr_coal_delay_ptr; int mtrr; + int wc_enabled; int wake_queue; int stop_queue; int down_cnt; @@ -233,7 +234,7 @@ static int myri10ge_msi = 1; /* enable msi by default */ module_param(myri10ge_msi, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(myri10ge_msi, "Enable Message Signalled Interrupts\n"); -static int myri10ge_intr_coal_delay = 25; +static int myri10ge_intr_coal_delay = 75; module_param(myri10ge_intr_coal_delay, int, S_IRUGO); MODULE_PARM_DESC(myri10ge_intr_coal_delay, "Interrupt coalescing delay\n"); @@ -278,7 +279,7 @@ static int myri10ge_fill_thresh = 256; module_param(myri10ge_fill_thresh, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(myri10ge_fill_thresh, "Number of empty rx slots allowed\n"); -static int myri10ge_wcfifo = 1; +static int myri10ge_wcfifo = 0; module_param(myri10ge_wcfifo, int, S_IRUGO); MODULE_PARM_DESC(myri10ge_wcfifo, "Enable WC Fifo when WC is enabled\n"); @@ -717,6 +718,8 @@ static int myri10ge_reset(struct myri10ge_priv *mgp) int status; size_t bytes; u32 len; + struct page *dmatest_page; + dma_addr_t dmatest_bus; /* try to send a reset command to the card to see if it * is alive */ @@ -726,6 +729,11 @@ static int myri10ge_reset(struct myri10ge_priv *mgp) dev_err(&mgp->pdev->dev, "failed reset\n"); return -ENXIO; } + dmatest_page = alloc_page(GFP_KERNEL); + if (!dmatest_page) + return -ENOMEM; + dmatest_bus = pci_map_page(mgp->pdev, dmatest_page, 0, PAGE_SIZE, + DMA_BIDIRECTIONAL); /* Now exchange information about interrupts */ @@ -764,8 +772,8 @@ static int myri10ge_reset(struct myri10ge_priv *mgp) len = mgp->tx.boundary; - cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus); - cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus); + cmd.data0 = MYRI10GE_LOWPART_TO_U32(dmatest_bus); + cmd.data1 = MYRI10GE_HIGHPART_TO_U32(dmatest_bus); cmd.data2 = len * 0x10000; status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0); if (status == 0) @@ -774,8 +782,8 @@ static int myri10ge_reset(struct myri10ge_priv *mgp) else dev_warn(&mgp->pdev->dev, "DMA read benchmark failed: %d\n", status); - cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus); - cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus); + cmd.data0 = MYRI10GE_LOWPART_TO_U32(dmatest_bus); + cmd.data1 = MYRI10GE_HIGHPART_TO_U32(dmatest_bus); cmd.data2 = len * 0x1; status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0); if (status == 0) @@ -785,8 +793,8 @@ static int myri10ge_reset(struct myri10ge_priv *mgp) dev_warn(&mgp->pdev->dev, "DMA write benchmark failed: %d\n", status); - cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus); - cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus); + cmd.data0 = MYRI10GE_LOWPART_TO_U32(dmatest_bus); + cmd.data1 = MYRI10GE_HIGHPART_TO_U32(dmatest_bus); cmd.data2 = len * 0x10001; status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0); if (status == 0) @@ -796,6 +804,9 @@ static int myri10ge_reset(struct myri10ge_priv *mgp) dev_warn(&mgp->pdev->dev, "DMA read/write benchmark failed: %d\n", status); + pci_unmap_page(mgp->pdev, dmatest_bus, PAGE_SIZE, DMA_BIDIRECTIONAL); + put_page(dmatest_page); + memset(mgp->rx_done.entry, 0, bytes); /* reset mcp/driver shared state back to 0 */ @@ -889,9 +900,7 @@ myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, /* try to refill entire ring */ while (rx->fill_cnt != (rx->cnt + rx->mask + 1)) { idx = rx->fill_cnt & rx->mask; - - if ((bytes < MYRI10GE_ALLOC_SIZE / 2) && - (rx->page_offset + bytes <= MYRI10GE_ALLOC_SIZE)) { + if (rx->page_offset + bytes <= MYRI10GE_ALLOC_SIZE) { /* we can use part of previous page */ get_page(rx->page); } else { @@ -922,6 +931,13 @@ myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, /* start next packet on a cacheline boundary */ rx->page_offset += SKB_DATA_ALIGN(bytes); + +#if MYRI10GE_ALLOC_SIZE > 4096 + /* don't cross a 4KB boundary */ + if ((rx->page_offset >> 12) != + ((rx->page_offset + bytes - 1) >> 12)) + rx->page_offset = (rx->page_offset + 4096) & ~4095; +#endif rx->fill_cnt++; /* copy 8 descriptors to the firmware at a time */ @@ -1375,7 +1391,7 @@ myri10ge_get_ethtool_stats(struct net_device *netdev, data[i] = ((unsigned long *)&mgp->stats)[i]; data[i++] = (unsigned int)mgp->tx.boundary; - data[i++] = (unsigned int)(mgp->mtrr >= 0); + data[i++] = (unsigned int)mgp->wc_enabled; data[i++] = (unsigned int)mgp->pdev->irq; data[i++] = (unsigned int)mgp->msi_enabled; data[i++] = (unsigned int)mgp->read_dma; @@ -1456,6 +1472,8 @@ static int myri10ge_allocate_rings(struct net_device *dev) status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_RING_SIZE, &cmd, 0); tx_ring_size = cmd.data0; status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_RX_RING_SIZE, &cmd, 0); + if (status != 0) + return status; rx_ring_size = cmd.data0; tx_ring_entries = tx_ring_size / sizeof(struct mcp_kreq_ether_send); @@ -1463,6 +1481,8 @@ static int myri10ge_allocate_rings(struct net_device *dev) mgp->tx.mask = tx_ring_entries - 1; mgp->rx_small.mask = mgp->rx_big.mask = rx_ring_entries - 1; + status = -ENOMEM; + /* allocate the host shadow rings */ bytes = 8 + (MYRI10GE_MAX_SEND_DESC_TSO + 4) @@ -1735,7 +1755,7 @@ static int myri10ge_open(struct net_device *dev) goto abort_with_irq; } - if (myri10ge_wcfifo && mgp->mtrr >= 0) { + if (myri10ge_wcfifo && mgp->wc_enabled) { mgp->tx.wc_fifo = (u8 __iomem *) mgp->sram + MXGEFW_ETH_SEND_4; mgp->rx_small.wc_fifo = (u8 __iomem *) mgp->sram + MXGEFW_ETH_RECV_SMALL; @@ -1992,10 +2012,9 @@ again: mss = 0; max_segments = MXGEFW_MAX_SEND_DESC; - if (skb->len > (dev->mtu + ETH_HLEN)) { + if (skb_is_gso(skb)) { mss = skb_shinfo(skb)->gso_size; - if (mss != 0) - max_segments = MYRI10GE_MAX_SEND_DESC_TSO; + max_segments = MYRI10GE_MAX_SEND_DESC_TSO; } if ((unlikely(avail < max_segments))) { @@ -2468,6 +2487,12 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp) #define PCI_DEVICE_ID_INTEL_E5000_PCIE23 0x25f7 #define PCI_DEVICE_ID_INTEL_E5000_PCIE47 0x25fa +#define PCI_DEVICE_ID_INTEL_6300ESB_PCIEE1 0x3510 +#define PCI_DEVICE_ID_INTEL_6300ESB_PCIEE4 0x351b +#define PCI_DEVICE_ID_INTEL_E3000_PCIE 0x2779 +#define PCI_DEVICE_ID_INTEL_E3010_PCIE 0x277a +#define PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_FIRST 0x140 +#define PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_LAST 0x142 static void myri10ge_select_firmware(struct myri10ge_priv *mgp) { @@ -2499,6 +2524,24 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp) ((bridge->vendor == PCI_VENDOR_ID_SERVERWORKS && bridge->device == PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE) + /* ServerWorks HT2100 */ + || (bridge->vendor == PCI_VENDOR_ID_SERVERWORKS + && bridge->device >= + PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_FIRST + && bridge->device <= + PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_LAST) + /* All Intel E3000/E3010 PCIE ports */ + || (bridge->vendor == PCI_VENDOR_ID_INTEL + && (bridge->device == + PCI_DEVICE_ID_INTEL_E3000_PCIE + || bridge->device == + PCI_DEVICE_ID_INTEL_E3010_PCIE)) + /* All Intel 6310/6311/6321ESB PCIE ports */ + || (bridge->vendor == PCI_VENDOR_ID_INTEL + && bridge->device >= + PCI_DEVICE_ID_INTEL_6300ESB_PCIEE1 + && bridge->device <= + PCI_DEVICE_ID_INTEL_6300ESB_PCIEE4) /* All Intel E5000 PCIE ports */ || (bridge->vendor == PCI_VENDOR_ID_INTEL && bridge->device >= @@ -2510,6 +2553,12 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp) bridge->vendor, bridge->device); mgp->tx.boundary = 4096; mgp->fw_name = myri10ge_fw_aligned; + } else if (bridge && + bridge->vendor == PCI_VENDOR_ID_SGI && + bridge->device == 0x4002 /* TIOCE pcie-port */ ) { + /* this pcie bridge does not support 4K rdma request */ + mgp->tx.boundary = 2048; + mgp->fw_name = myri10ge_fw_aligned; } } else { if (myri10ge_force_firmware == 1) { @@ -2830,9 +2879,12 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) mgp->board_span = pci_resource_len(pdev, 0); mgp->iomem_base = pci_resource_start(pdev, 0); mgp->mtrr = -1; + mgp->wc_enabled = 0; #ifdef CONFIG_MTRR mgp->mtrr = mtrr_add(mgp->iomem_base, mgp->board_span, MTRR_TYPE_WRCOMB, 1); + if (mgp->mtrr >= 0) + mgp->wc_enabled = 1; #endif /* Hack. need to get rid of these magic numbers */ mgp->sram_size = @@ -2927,7 +2979,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dev_info(dev, "%s IRQ %d, tx bndry %d, fw %s, WC %s\n", (mgp->msi_enabled ? "MSI" : "xPIC"), netdev->irq, mgp->tx.boundary, mgp->fw_name, - (mgp->mtrr >= 0 ? "Enabled" : "Disabled")); + (mgp->wc_enabled ? "Enabled" : "Disabled")); return 0; diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index c6172a77a6d..349b96a3ec4 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -1712,7 +1712,7 @@ static void init_registers(struct net_device *dev) /* Enable interrupts by setting the interrupt mask. */ writel(DEFAULT_INTR, ioaddr + IntrMask); - writel(1, ioaddr + IntrEnable); + natsemi_irq_enable(dev); writel(RxOn | TxOn, ioaddr + ChipCmd); writel(StatsClear, ioaddr + StatsCtrl); /* Clear Stats */ @@ -2119,28 +2119,35 @@ static irqreturn_t intr_handler(int irq, void *dev_instance) struct netdev_private *np = netdev_priv(dev); void __iomem * ioaddr = ns_ioaddr(dev); - if (np->hands_off) + /* Reading IntrStatus automatically acknowledges so don't do + * that while interrupts are disabled, (for example, while a + * poll is scheduled). */ + if (np->hands_off || !readl(ioaddr + IntrEnable)) return IRQ_NONE; - /* Reading automatically acknowledges. */ np->intr_status = readl(ioaddr + IntrStatus); + if (!np->intr_status) + return IRQ_NONE; + if (netif_msg_intr(np)) printk(KERN_DEBUG "%s: Interrupt, status %#08x, mask %#08x.\n", dev->name, np->intr_status, readl(ioaddr + IntrMask)); - if (!np->intr_status) - return IRQ_NONE; - prefetch(&np->rx_skbuff[np->cur_rx % RX_RING_SIZE]); if (netif_rx_schedule_prep(dev)) { /* Disable interrupts and register for poll */ natsemi_irq_disable(dev); __netif_rx_schedule(dev); - } + } else + printk(KERN_WARNING + "%s: Ignoring interrupt, status %#08x, mask %#08x.\n", + dev->name, np->intr_status, + readl(ioaddr + IntrMask)); + return IRQ_HANDLED; } @@ -2156,6 +2163,20 @@ static int natsemi_poll(struct net_device *dev, int *budget) int work_done = 0; do { + if (netif_msg_intr(np)) + printk(KERN_DEBUG + "%s: Poll, status %#08x, mask %#08x.\n", + dev->name, np->intr_status, + readl(ioaddr + IntrMask)); + + /* netdev_rx() may read IntrStatus again if the RX state + * machine falls over so do it first. */ + if (np->intr_status & + (IntrRxDone | IntrRxIntr | RxStatusFIFOOver | + IntrRxErr | IntrRxOverrun)) { + netdev_rx(dev, &work_done, work_to_do); + } + if (np->intr_status & (IntrTxDone | IntrTxIntr | IntrTxIdle | IntrTxErr)) { spin_lock(&np->lock); @@ -2167,12 +2188,6 @@ static int natsemi_poll(struct net_device *dev, int *budget) if (np->intr_status & IntrAbnormalSummary) netdev_error(dev, np->intr_status); - if (np->intr_status & - (IntrRxDone | IntrRxIntr | RxStatusFIFOOver | - IntrRxErr | IntrRxOverrun)) { - netdev_rx(dev, &work_done, work_to_do); - } - *budget -= work_done; dev->quota -= work_done; @@ -2399,19 +2414,8 @@ static struct net_device_stats *get_stats(struct net_device *dev) #ifdef CONFIG_NET_POLL_CONTROLLER static void natsemi_poll_controller(struct net_device *dev) { - struct netdev_private *np = netdev_priv(dev); - disable_irq(dev->irq); - - /* - * A real interrupt might have already reached us at this point - * but NAPI might still haven't called us back. As the interrupt - * status register is cleared by reading, we should prevent an - * interrupt loss in this case... - */ - if (!np->intr_status) - intr_handler(dev->irq, dev); - + intr_handler(dev->irq, dev); enable_irq(dev->irq); } #endif @@ -3071,7 +3075,7 @@ static void enable_wol_mode(struct net_device *dev, int enable_intr) * Could be used to send a netlink message. */ writel(WOLPkt | LinkChange, ioaddr + IntrMask); - writel(1, ioaddr + IntrEnable); + natsemi_irq_enable(dev); } } @@ -3202,7 +3206,7 @@ static int natsemi_suspend (struct pci_dev *pdev, pm_message_t state) disable_irq(dev->irq); spin_lock_irq(&np->lock); - writel(0, ioaddr + IntrEnable); + natsemi_irq_disable(dev); np->hands_off = 1; natsemi_stop_rxtx(dev); netif_stop_queue(dev); diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 81742e4e561..dd8ce35332f 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -232,6 +232,7 @@ enum { #define MPORT_SINGLE_FUNCTION_MODE 0x1111 extern unsigned long long netxen_dma_mask; +extern unsigned long last_schedule_time; /* * NetXen host-peg signal message structure diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index 986ef98db22..ee1b5a24cbe 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -462,6 +462,7 @@ netxen_nic_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, } printk(KERN_INFO "%s: flash unlocked. \n", netxen_nic_driver_name); + last_schedule_time = jiffies; ret = netxen_flash_erase_secondary(adapter); if (ret != FLASH_SUCCESS) { printk(KERN_ERR "%s: Flash erase failed.\n", diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index a2877f33fa8..6537574a9cd 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -228,7 +228,7 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter) &adapter->ctx_desc_pdev); printk("ctx_desc_phys_addr: 0x%llx\n", - (u64) adapter->ctx_desc_phys_addr); + (unsigned long long) adapter->ctx_desc_phys_addr); if (addr == NULL) { DPRINTK(ERR, "bad return from pci_alloc_consistent\n"); err = -ENOMEM; @@ -247,7 +247,8 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter) adapter->max_tx_desc_count, (dma_addr_t *) & hw->cmd_desc_phys_addr, &adapter->ahw.cmd_desc_pdev); - printk("cmd_desc_phys_addr: 0x%llx\n", (u64) hw->cmd_desc_phys_addr); + printk("cmd_desc_phys_addr: 0x%llx\n", + (unsigned long long) hw->cmd_desc_phys_addr); if (addr == NULL) { DPRINTK(ERR, "bad return from pci_alloc_consistent\n"); @@ -821,7 +822,10 @@ int netxen_nic_set_mtu_xgb(struct netxen_port *port, int new_mtu) { struct netxen_adapter *adapter = port->adapter; new_mtu += NETXEN_NIU_HDRSIZE + NETXEN_NIU_TLRSIZE; - netxen_nic_write_w0(adapter, NETXEN_NIU_XGE_MAX_FRAME_SIZE, new_mtu); + if (port->portnum == 0) + netxen_nic_write_w0(adapter, NETXEN_NIU_XGE_MAX_FRAME_SIZE, new_mtu); + else if (port->portnum == 1) + netxen_nic_write_w0(adapter, NETXEN_NIU_XG1_MAX_FRAME_SIZE, new_mtu); return 0; } diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 586d32b676a..eff965dc5ff 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -42,6 +42,8 @@ struct crb_addr_pair { u32 data; }; +unsigned long last_schedule_time; + #define NETXEN_MAX_CRB_XFORM 60 static unsigned int crb_addr_xform[NETXEN_MAX_CRB_XFORM]; #define NETXEN_ADDR_ERROR (0xffffffff) @@ -404,9 +406,14 @@ static inline int do_rom_fast_write(struct netxen_adapter *adapter, int addr, static inline int do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) { + if (jiffies > (last_schedule_time + (8 * HZ))) { + last_schedule_time = jiffies; + schedule(); + } + netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr); netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3); - udelay(70); /* prevent bursting on CRB */ + udelay(100); /* prevent bursting on CRB */ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0xb); if (netxen_wait_rom_done(adapter)) { @@ -415,7 +422,7 @@ do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) } /* reset abyte_cnt and dummy_byte_cnt */ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0); - udelay(70); /* prevent bursting on CRB */ + udelay(100); /* prevent bursting on CRB */ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); *valp = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_ROM_RDATA); @@ -431,6 +438,7 @@ do_rom_fast_read_words(struct netxen_adapter *adapter, int addr, for (addridx = addr; addridx < (addr + size); addridx += 4) { ret = do_rom_fast_read(adapter, addridx, (int *)bytes); + *(int *)bytes = cpu_to_le32(*(int *)bytes); if (ret != 0) break; bytes += 4; @@ -490,7 +498,7 @@ static inline int do_rom_fast_write_words(struct netxen_adapter *adapter, int timeout = 0; int data; - data = *(u32*)bytes; + data = le32_to_cpu((*(u32*)bytes)); ret = do_rom_fast_write(adapter, addridx, data); if (ret < 0) diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c index 00ca0fdb837..6ca4e4fa6b8 100644 --- a/drivers/net/pci-skeleton.c +++ b/drivers/net/pci-skeleton.c @@ -710,8 +710,8 @@ match: tp->chipset, rtl_chip_info[tp->chipset].name); - i = register_netdev (dev); - if (i) + rc = register_netdev (dev); + if (rc) goto err_out_unmap; DPRINTK ("EXIT, returning 0\n"); diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index a956a51d284..1060154ae75 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c @@ -138,7 +138,7 @@ static const struct ethtool_ops netdev_ethtool_ops = { ======================================================================*/ -static int ibmtr_attach(struct pcmcia_device *link) +static int __devinit ibmtr_attach(struct pcmcia_device *link) { ibmtr_dev_t *info; struct net_device *dev; @@ -217,7 +217,7 @@ static void ibmtr_detach(struct pcmcia_device *link) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static int ibmtr_config(struct pcmcia_device *link) +static int __devinit ibmtr_config(struct pcmcia_device *link) { ibmtr_dev_t *info = link->priv; struct net_device *dev = info->dev; diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 11b575f8985..ef58e412878 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -2544,6 +2544,9 @@ static void ppp_destroy_interface(struct ppp *ppp) ppp->active_filter = NULL; #endif /* CONFIG_PPP_FILTER */ + if (ppp->xmit_pending) + kfree_skb(ppp->xmit_pending); + kfree(ppp); } diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index d3f65dab306..a8246eb2f8d 100755 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c @@ -1691,6 +1691,27 @@ static int ql_populate_free_queue(struct ql3_adapter *qdev) /* * Caller holds hw_lock. */ +static void ql_update_small_bufq_prod_index(struct ql3_adapter *qdev) +{ + struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; + if (qdev->small_buf_release_cnt >= 16) { + while (qdev->small_buf_release_cnt >= 16) { + qdev->small_buf_q_producer_index++; + + if (qdev->small_buf_q_producer_index == + NUM_SBUFQ_ENTRIES) + qdev->small_buf_q_producer_index = 0; + qdev->small_buf_release_cnt -= 8; + } + wmb(); + writel(qdev->small_buf_q_producer_index, + &port_regs->CommonRegs.rxSmallQProducerIndex); + } +} + +/* + * Caller holds hw_lock. + */ static void ql_update_lrg_bufq_prod_index(struct ql3_adapter *qdev) { struct bufq_addr_element *lrg_buf_q_ele; @@ -1732,13 +1753,10 @@ static void ql_update_lrg_bufq_prod_index(struct ql3_adapter *qdev) lrg_buf_q_ele = qdev->lrg_buf_q_virt_addr; } } - + wmb(); qdev->lrg_buf_next_free = lrg_buf_q_ele; - - ql_write_common_reg(qdev, - &port_regs->CommonRegs. - rxLargeQProducerIndex, - qdev->lrg_buf_q_producer_index); + writel(qdev->lrg_buf_q_producer_index, + &port_regs->CommonRegs.rxLargeQProducerIndex); } } @@ -1915,17 +1933,18 @@ static void ql_process_macip_rx_intr(struct ql3_adapter *qdev, u16 checksum = le16_to_cpu(ib_ip_rsp_ptr->checksum); if (checksum & (IB_IP_IOCB_RSP_3032_ICE | - IB_IP_IOCB_RSP_3032_CE | - IB_IP_IOCB_RSP_3032_NUC)) { + IB_IP_IOCB_RSP_3032_CE)) { printk(KERN_ERR "%s: Bad checksum for this %s packet, checksum = %x.\n", __func__, ((checksum & IB_IP_IOCB_RSP_3032_TCP) ? "TCP" : "UDP"),checksum); - } else if (checksum & IB_IP_IOCB_RSP_3032_TCP) { + } else if ((checksum & IB_IP_IOCB_RSP_3032_TCP) || + (checksum & IB_IP_IOCB_RSP_3032_UDP && + !(checksum & IB_IP_IOCB_RSP_3032_NUC))) { skb2->ip_summed = CHECKSUM_UNNECESSARY; - } + } } skb2->dev = qdev->ndev; skb2->protocol = eth_type_trans(skb2, qdev->ndev); @@ -1944,16 +1963,12 @@ static void ql_process_macip_rx_intr(struct ql3_adapter *qdev, static int ql_tx_rx_clean(struct ql3_adapter *qdev, int *tx_cleaned, int *rx_cleaned, int work_to_do) { - struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; struct net_rsp_iocb *net_rsp; struct net_device *ndev = qdev->ndev; - unsigned long hw_flags; int work_done = 0; - u32 rsp_producer_index = le32_to_cpu(*(qdev->prsp_producer_index)); - /* While there are entries in the completion queue. */ - while ((rsp_producer_index != + while ((le32_to_cpu(*(qdev->prsp_producer_index)) != qdev->rsp_consumer_index) && (work_done < work_to_do)) { net_rsp = qdev->rsp_current; @@ -2009,33 +2024,7 @@ static int ql_tx_rx_clean(struct ql3_adapter *qdev, work_done = *tx_cleaned + *rx_cleaned; } - if(work_done) { - spin_lock_irqsave(&qdev->hw_lock, hw_flags); - - ql_update_lrg_bufq_prod_index(qdev); - - if (qdev->small_buf_release_cnt >= 16) { - while (qdev->small_buf_release_cnt >= 16) { - qdev->small_buf_q_producer_index++; - - if (qdev->small_buf_q_producer_index == - NUM_SBUFQ_ENTRIES) - qdev->small_buf_q_producer_index = 0; - qdev->small_buf_release_cnt -= 8; - } - - wmb(); - ql_write_common_reg(qdev, - &port_regs->CommonRegs. - rxSmallQProducerIndex, - qdev->small_buf_q_producer_index); - - } - - spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); - } - - return *tx_cleaned + *rx_cleaned; + return work_done; } static int ql_poll(struct net_device *ndev, int *budget) @@ -2059,9 +2048,10 @@ quit_polling: netif_rx_complete(ndev); spin_lock_irqsave(&qdev->hw_lock, hw_flags); - ql_write_common_reg(qdev, - &port_regs->CommonRegs.rspQConsumerIndex, - qdev->rsp_consumer_index); + ql_update_small_bufq_prod_index(qdev); + ql_update_lrg_bufq_prod_index(qdev); + writel(qdev->rsp_consumer_index, + &port_regs->CommonRegs.rspQConsumerIndex); spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); ql_enable_interrupts(qdev); @@ -2217,12 +2207,7 @@ static int ql_send_map(struct ql3_adapter *qdev, int seg_cnt, seg = 0; int frag_cnt = (int)skb_shinfo(skb)->nr_frags; - seg_cnt = tx_cb->seg_count = ql_get_seg_count(qdev, - (skb_shinfo(skb)->nr_frags)); - if(seg_cnt == -1) { - printk(KERN_ERR PFX"%s: invalid segment count!\n",__func__); - return NETDEV_TX_BUSY; - } + seg_cnt = tx_cb->seg_count; /* * Map the skb buffer first. */ @@ -2278,7 +2263,7 @@ static int ql_send_map(struct ql3_adapter *qdev, pci_unmap_addr_set(&tx_cb->map[seg], mapaddr, map); pci_unmap_len_set(&tx_cb->map[seg], maplen, - len); + sizeof(struct oal)); oal_entry = (struct oal_entry *)oal; oal++; seg++; @@ -2380,6 +2365,7 @@ static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev) } mac_iocb_ptr = tx_cb->queue_entry; + memset((void *)mac_iocb_ptr, 0, sizeof(struct ob_mac_iocb_req)); mac_iocb_ptr->opcode = qdev->mac_ob_opcode; mac_iocb_ptr->flags = OB_MAC_IOCB_REQ_X; mac_iocb_ptr->flags |= qdev->mb_bit_mask; @@ -3054,15 +3040,6 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev) goto out; } - if (qdev->mac_index) - ql_write_page0_reg(qdev, - &port_regs->mac1MaxFrameLengthReg, - qdev->max_frame_size); - else - ql_write_page0_reg(qdev, - &port_regs->mac0MaxFrameLengthReg, - qdev->max_frame_size); - value = qdev->nvram_data.tcpMaxWindowSize; ql_write_page0_reg(qdev, &port_regs->tcpMaxWindow, value); @@ -3082,6 +3059,14 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev) ql_sem_unlock(qdev, QL_FLASH_SEM_MASK); } + if (qdev->mac_index) + ql_write_page0_reg(qdev, + &port_regs->mac1MaxFrameLengthReg, + qdev->max_frame_size); + else + ql_write_page0_reg(qdev, + &port_regs->mac0MaxFrameLengthReg, + qdev->max_frame_size); if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK, (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) * @@ -3152,7 +3137,8 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev) if (qdev->device_id == QL3032_DEVICE_ID) { value = (QL3032_PORT_CONTROL_EF | QL3032_PORT_CONTROL_KIE | - QL3032_PORT_CONTROL_EIv6 | QL3032_PORT_CONTROL_EIv4); + QL3032_PORT_CONTROL_EIv6 | QL3032_PORT_CONTROL_EIv4 | + QL3032_PORT_CONTROL_ET); ql_write_page0_reg(qdev, &port_regs->functionControl, ((value << 16) | value)); } else { diff --git a/drivers/net/qla3xxx.h b/drivers/net/qla3xxx.h index 34cd6580fd0..0203f88f054 100755 --- a/drivers/net/qla3xxx.h +++ b/drivers/net/qla3xxx.h @@ -1014,8 +1014,7 @@ struct eeprom_data { /* Transmit and Receive Buffers */ #define NUM_LBUFQ_ENTRIES 128 -#define JUMBO_NUM_LBUFQ_ENTRIES \ -(NUM_LBUFQ_ENTRIES/(JUMBO_MTU_SIZE/NORMAL_MTU_SIZE)) +#define JUMBO_NUM_LBUFQ_ENTRIES 32 #define NUM_SBUFQ_ENTRIES 64 #define QL_SMALL_BUFFER_SIZE 32 #define QL_ADDR_ELE_PER_BUFQ_ENTRY \ diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 15d954e50ca..6a77b8a9224 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -66,6 +66,7 @@ VERSION 2.2LK <2005/01/25> #include <linux/init.h> #include <linux/dma-mapping.h> +#include <asm/system.h> #include <asm/io.h> #include <asm/irq.h> @@ -486,6 +487,7 @@ static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, void __iomem *); static int rtl8169_change_mtu(struct net_device *dev, int new_mtu); static void rtl8169_down(struct net_device *dev); +static void rtl8169_rx_clear(struct rtl8169_private *tp); #ifdef CONFIG_R8169_NAPI static int rtl8169_poll(struct net_device *dev, int *budget); @@ -572,8 +574,8 @@ static void rtl8169_xmii_reset_enable(void __iomem *ioaddr) { unsigned int val; - mdio_write(ioaddr, MII_BMCR, BMCR_RESET); - val = mdio_read(ioaddr, MII_BMCR); + val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET; + mdio_write(ioaddr, MII_BMCR, val & 0xffff); } static void rtl8169_check_link_status(struct net_device *dev, @@ -1368,11 +1370,7 @@ static inline void rtl8169_request_timer(struct net_device *dev) (tp->phy_version >= RTL_GIGA_PHY_VER_H)) return; - init_timer(timer); - timer->expires = jiffies + RTL8169_PHY_TIMEOUT; - timer->data = (unsigned long)(dev); - timer->function = rtl8169_phy_timer; - add_timer(timer); + mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); } #ifdef CONFIG_NET_POLL_CONTROLLER @@ -1685,6 +1683,10 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->mmio_addr = ioaddr; tp->align = rtl_cfg_info[ent->driver_data].align; + init_timer(&tp->timer); + tp->timer.data = (unsigned long) dev; + tp->timer.function = rtl8169_phy_timer; + spin_lock_init(&tp->lock); rc = register_netdev(dev); @@ -1751,16 +1753,10 @@ static int rtl8169_open(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); struct pci_dev *pdev = tp->pci_dev; - int retval; - - rtl8169_set_rxbufsize(tp, dev); + int retval = -ENOMEM; - retval = - request_irq(dev->irq, rtl8169_interrupt, IRQF_SHARED, dev->name, dev); - if (retval < 0) - goto out; - retval = -ENOMEM; + rtl8169_set_rxbufsize(tp, dev); /* * Rx and Tx desscriptors needs 256 bytes alignment. @@ -1769,19 +1765,26 @@ static int rtl8169_open(struct net_device *dev) tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES, &tp->TxPhyAddr); if (!tp->TxDescArray) - goto err_free_irq; + goto out; tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES, &tp->RxPhyAddr); if (!tp->RxDescArray) - goto err_free_tx; + goto err_free_tx_0; retval = rtl8169_init_ring(dev); if (retval < 0) - goto err_free_rx; + goto err_free_rx_1; INIT_DELAYED_WORK(&tp->task, NULL); + smp_mb(); + + retval = request_irq(dev->irq, rtl8169_interrupt, IRQF_SHARED, + dev->name, dev); + if (retval < 0) + goto err_release_ring_2; + rtl8169_hw_start(dev); rtl8169_request_timer(dev); @@ -1790,14 +1793,14 @@ static int rtl8169_open(struct net_device *dev) out: return retval; -err_free_rx: +err_release_ring_2: + rtl8169_rx_clear(tp); +err_free_rx_1: pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, tp->RxPhyAddr); -err_free_tx: +err_free_tx_0: pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, tp->TxPhyAddr); -err_free_irq: - free_irq(dev->irq, dev); goto out; } @@ -2887,7 +2890,7 @@ static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state) void __iomem *ioaddr = tp->mmio_addr; if (!netif_running(dev)) - goto out; + goto out_pci_suspend; netif_device_detach(dev); netif_stop_queue(dev); @@ -2901,10 +2904,11 @@ static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state) spin_unlock_irq(&tp->lock); +out_pci_suspend: pci_save_state(pdev); pci_enable_wake(pdev, pci_choose_state(pdev, state), tp->wol_enabled); pci_set_power_state(pdev, pci_choose_state(pdev, state)); -out: + return 0; } @@ -2912,15 +2916,15 @@ static int rtl8169_resume(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + pci_enable_wake(pdev, PCI_D0, 0); + if (!netif_running(dev)) goto out; netif_device_attach(dev); - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - pci_enable_wake(pdev, PCI_D0, 0); - rtl8169_schedule_work(dev, rtl8169_reset_task); out: return 0; diff --git a/drivers/net/saa9730.c b/drivers/net/saa9730.c index b269513cde4..143958f1ef0 100644 --- a/drivers/net/saa9730.c +++ b/drivers/net/saa9730.c @@ -64,37 +64,37 @@ static unsigned int pci_irq_line; static void evm_saa9730_enable_lan_int(struct lan_saa9730_private *lp) { - outl(readl(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT, - &lp->evm_saa9730_regs->InterruptBlock1); - outl(readl(&lp->evm_saa9730_regs->InterruptStatus1) | EVM_LAN_INT, - &lp->evm_saa9730_regs->InterruptStatus1); - outl(readl(&lp->evm_saa9730_regs->InterruptEnable1) | EVM_LAN_INT | - EVM_MASTER_EN, &lp->evm_saa9730_regs->InterruptEnable1); + writel(readl(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT, + &lp->evm_saa9730_regs->InterruptBlock1); + writel(readl(&lp->evm_saa9730_regs->InterruptStatus1) | EVM_LAN_INT, + &lp->evm_saa9730_regs->InterruptStatus1); + writel(readl(&lp->evm_saa9730_regs->InterruptEnable1) | EVM_LAN_INT | + EVM_MASTER_EN, &lp->evm_saa9730_regs->InterruptEnable1); } static void evm_saa9730_disable_lan_int(struct lan_saa9730_private *lp) { - outl(readl(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT, - &lp->evm_saa9730_regs->InterruptBlock1); - outl(readl(&lp->evm_saa9730_regs->InterruptEnable1) & ~EVM_LAN_INT, - &lp->evm_saa9730_regs->InterruptEnable1); + writel(readl(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT, + &lp->evm_saa9730_regs->InterruptBlock1); + writel(readl(&lp->evm_saa9730_regs->InterruptEnable1) & ~EVM_LAN_INT, + &lp->evm_saa9730_regs->InterruptEnable1); } static void evm_saa9730_clear_lan_int(struct lan_saa9730_private *lp) { - outl(EVM_LAN_INT, &lp->evm_saa9730_regs->InterruptStatus1); + writel(EVM_LAN_INT, &lp->evm_saa9730_regs->InterruptStatus1); } static void evm_saa9730_block_lan_int(struct lan_saa9730_private *lp) { - outl(readl(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT, - &lp->evm_saa9730_regs->InterruptBlock1); + writel(readl(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT, + &lp->evm_saa9730_regs->InterruptBlock1); } static void evm_saa9730_unblock_lan_int(struct lan_saa9730_private *lp) { - outl(readl(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT, - &lp->evm_saa9730_regs->InterruptBlock1); + writel(readl(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT, + &lp->evm_saa9730_regs->InterruptBlock1); } static void __attribute_used__ show_saa9730_regs(struct lan_saa9730_private *lp) @@ -147,7 +147,7 @@ static void __attribute_used__ show_saa9730_regs(struct lan_saa9730_private *lp) printk("lp->lan_saa9730_regs->RxStatus = %x\n", readl(&lp->lan_saa9730_regs->RxStatus)); for (i = 0; i < LAN_SAA9730_CAM_DWORDS; i++) { - outl(i, &lp->lan_saa9730_regs->CamAddress); + writel(i, &lp->lan_saa9730_regs->CamAddress); printk("lp->lan_saa9730_regs->CamData = %x\n", readl(&lp->lan_saa9730_regs->CamData)); } @@ -288,28 +288,27 @@ static int lan_saa9730_allocate_buffers(struct pci_dev *pdev, * Set rx buffer A and rx buffer B to point to the first two buffer * spaces. */ - outl(lp->dma_addr + rxoffset, - &lp->lan_saa9730_regs->RxBuffA); - outl(lp->dma_addr + rxoffset + - LAN_SAA9730_PACKET_SIZE * LAN_SAA9730_RCV_Q_SIZE, - &lp->lan_saa9730_regs->RxBuffB); + writel(lp->dma_addr + rxoffset, &lp->lan_saa9730_regs->RxBuffA); + writel(lp->dma_addr + rxoffset + + LAN_SAA9730_PACKET_SIZE * LAN_SAA9730_RCV_Q_SIZE, + &lp->lan_saa9730_regs->RxBuffB); /* * Set txm_buf_a and txm_buf_b to point to the first two buffer * space */ - outl(lp->dma_addr + txoffset, - &lp->lan_saa9730_regs->TxBuffA); - outl(lp->dma_addr + txoffset + - LAN_SAA9730_PACKET_SIZE * LAN_SAA9730_TXM_Q_SIZE, - &lp->lan_saa9730_regs->TxBuffB); + writel(lp->dma_addr + txoffset, + &lp->lan_saa9730_regs->TxBuffA); + writel(lp->dma_addr + txoffset + + LAN_SAA9730_PACKET_SIZE * LAN_SAA9730_TXM_Q_SIZE, + &lp->lan_saa9730_regs->TxBuffB); /* Set packet number */ - outl((lp->DmaRcvPackets << PK_COUNT_RX_A_SHF) | - (lp->DmaRcvPackets << PK_COUNT_RX_B_SHF) | - (lp->DmaTxmPackets << PK_COUNT_TX_A_SHF) | - (lp->DmaTxmPackets << PK_COUNT_TX_B_SHF), - &lp->lan_saa9730_regs->PacketCount); + writel((lp->DmaRcvPackets << PK_COUNT_RX_A_SHF) | + (lp->DmaRcvPackets << PK_COUNT_RX_B_SHF) | + (lp->DmaTxmPackets << PK_COUNT_TX_A_SHF) | + (lp->DmaTxmPackets << PK_COUNT_TX_B_SHF), + &lp->lan_saa9730_regs->PacketCount); return 0; @@ -326,10 +325,10 @@ static int lan_saa9730_cam_load(struct lan_saa9730_private *lp) for (i = 0; i < LAN_SAA9730_CAM_DWORDS; i++) { /* First set address to where data is written */ - outl(i, &lp->lan_saa9730_regs->CamAddress); - outl((NetworkAddress[0] << 24) | (NetworkAddress[1] << 16) - | (NetworkAddress[2] << 8) | NetworkAddress[3], - &lp->lan_saa9730_regs->CamData); + writel(i, &lp->lan_saa9730_regs->CamAddress); + writel((NetworkAddress[0] << 24) | (NetworkAddress[1] << 16) | + (NetworkAddress[2] << 8) | NetworkAddress[3], + &lp->lan_saa9730_regs->CamData); NetworkAddress += 4; } return 0; @@ -365,8 +364,8 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp) } /* Now set the control and address register. */ - outl(MD_CA_BUSY | PHY_STATUS | PHY_ADDRESS << MD_CA_PHY_SHF, - &lp->lan_saa9730_regs->StationMgmtCtl); + writel(MD_CA_BUSY | PHY_STATUS | PHY_ADDRESS << MD_CA_PHY_SHF, + &lp->lan_saa9730_regs->StationMgmtCtl); /* check link status, spin here till station is not busy */ i = 0; @@ -391,23 +390,23 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp) /* Link is down, reset the PHY first. */ /* set PHY address = 'CONTROL' */ - outl(PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR | PHY_CONTROL, - &lp->lan_saa9730_regs->StationMgmtCtl); + writel(PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR | PHY_CONTROL, + &lp->lan_saa9730_regs->StationMgmtCtl); /* Wait for 1 ms. */ mdelay(1); /* set 'CONTROL' = force reset and renegotiate */ - outl(PHY_CONTROL_RESET | PHY_CONTROL_AUTO_NEG | - PHY_CONTROL_RESTART_AUTO_NEG, - &lp->lan_saa9730_regs->StationMgmtData); + writel(PHY_CONTROL_RESET | PHY_CONTROL_AUTO_NEG | + PHY_CONTROL_RESTART_AUTO_NEG, + &lp->lan_saa9730_regs->StationMgmtData); /* Wait for 50 ms. */ mdelay(50); /* set 'BUSY' to start operation */ - outl(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR | - PHY_CONTROL, &lp->lan_saa9730_regs->StationMgmtCtl); + writel(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR | + PHY_CONTROL, &lp->lan_saa9730_regs->StationMgmtCtl); /* await completion */ i = 0; @@ -427,9 +426,9 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp) for (l = 0; l < 2; l++) { /* set PHY address = 'STATUS' */ - outl(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF | - PHY_STATUS, - &lp->lan_saa9730_regs->StationMgmtCtl); + writel(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF | + PHY_STATUS, + &lp->lan_saa9730_regs->StationMgmtCtl); /* await completion */ i = 0; @@ -462,35 +461,35 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp) static int lan_saa9730_control_init(struct lan_saa9730_private *lp) { /* Initialize DMA control register. */ - outl((LANMB_ANY << DMA_CTL_MAX_XFER_SHF) | - (LANEND_LITTLE << DMA_CTL_ENDIAN_SHF) | - (LAN_SAA9730_RCV_Q_INT_THRESHOLD << DMA_CTL_RX_INT_COUNT_SHF) - | DMA_CTL_RX_INT_TO_EN | DMA_CTL_RX_INT_EN | - DMA_CTL_MAC_RX_INT_EN | DMA_CTL_MAC_TX_INT_EN, - &lp->lan_saa9730_regs->LanDmaCtl); + writel((LANMB_ANY << DMA_CTL_MAX_XFER_SHF) | + (LANEND_LITTLE << DMA_CTL_ENDIAN_SHF) | + (LAN_SAA9730_RCV_Q_INT_THRESHOLD << DMA_CTL_RX_INT_COUNT_SHF) + | DMA_CTL_RX_INT_TO_EN | DMA_CTL_RX_INT_EN | + DMA_CTL_MAC_RX_INT_EN | DMA_CTL_MAC_TX_INT_EN, + &lp->lan_saa9730_regs->LanDmaCtl); /* Initial MAC control register. */ - outl((MACCM_MII << MAC_CONTROL_CONN_SHF) | MAC_CONTROL_FULL_DUP, - &lp->lan_saa9730_regs->MacCtl); + writel((MACCM_MII << MAC_CONTROL_CONN_SHF) | MAC_CONTROL_FULL_DUP, + &lp->lan_saa9730_regs->MacCtl); /* Initialize CAM control register. */ - outl(CAM_CONTROL_COMP_EN | CAM_CONTROL_BROAD_ACC, - &lp->lan_saa9730_regs->CamCtl); + writel(CAM_CONTROL_COMP_EN | CAM_CONTROL_BROAD_ACC, + &lp->lan_saa9730_regs->CamCtl); /* * Initialize CAM enable register, only turn on first entry, should * contain own addr. */ - outl(0x0001, &lp->lan_saa9730_regs->CamEnable); + writel(0x0001, &lp->lan_saa9730_regs->CamEnable); /* Initialize Tx control register */ - outl(TX_CTL_EN_COMP, &lp->lan_saa9730_regs->TxCtl); + writel(TX_CTL_EN_COMP, &lp->lan_saa9730_regs->TxCtl); /* Initialize Rcv control register */ - outl(RX_CTL_STRIP_CRC, &lp->lan_saa9730_regs->RxCtl); + writel(RX_CTL_STRIP_CRC, &lp->lan_saa9730_regs->RxCtl); /* Reset DMA engine */ - outl(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest); + writel(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest); return 0; } @@ -500,14 +499,14 @@ static int lan_saa9730_stop(struct lan_saa9730_private *lp) int i; /* Stop DMA first */ - outl(readl(&lp->lan_saa9730_regs->LanDmaCtl) & - ~(DMA_CTL_EN_TX_DMA | DMA_CTL_EN_RX_DMA), - &lp->lan_saa9730_regs->LanDmaCtl); + writel(readl(&lp->lan_saa9730_regs->LanDmaCtl) & + ~(DMA_CTL_EN_TX_DMA | DMA_CTL_EN_RX_DMA), + &lp->lan_saa9730_regs->LanDmaCtl); /* Set the SW Reset bits in DMA and MAC control registers */ - outl(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest); - outl(readl(&lp->lan_saa9730_regs->MacCtl) | MAC_CONTROL_RESET, - &lp->lan_saa9730_regs->MacCtl); + writel(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest); + writel(readl(&lp->lan_saa9730_regs->MacCtl) | MAC_CONTROL_RESET, + &lp->lan_saa9730_regs->MacCtl); /* * Wait for MAC reset to have finished. The reset bit is auto cleared @@ -532,8 +531,8 @@ static int lan_saa9730_dma_init(struct lan_saa9730_private *lp) /* Stop lan controller. */ lan_saa9730_stop(lp); - outl(LAN_SAA9730_DEFAULT_TIME_OUT_CNT, - &lp->lan_saa9730_regs->Timeout); + writel(LAN_SAA9730_DEFAULT_TIME_OUT_CNT, + &lp->lan_saa9730_regs->Timeout); return 0; } @@ -552,19 +551,19 @@ static int lan_saa9730_start(struct lan_saa9730_private *lp) lp->PendingTxmPacketIndex = 0; lp->PendingTxmBufferIndex = 0; - outl(readl(&lp->lan_saa9730_regs->LanDmaCtl) | DMA_CTL_EN_TX_DMA | - DMA_CTL_EN_RX_DMA, &lp->lan_saa9730_regs->LanDmaCtl); + writel(readl(&lp->lan_saa9730_regs->LanDmaCtl) | DMA_CTL_EN_TX_DMA | + DMA_CTL_EN_RX_DMA, &lp->lan_saa9730_regs->LanDmaCtl); /* For Tx, turn on MAC then DMA */ - outl(readl(&lp->lan_saa9730_regs->TxCtl) | TX_CTL_TX_EN, - &lp->lan_saa9730_regs->TxCtl); + writel(readl(&lp->lan_saa9730_regs->TxCtl) | TX_CTL_TX_EN, + &lp->lan_saa9730_regs->TxCtl); /* For Rx, turn on DMA then MAC */ - outl(readl(&lp->lan_saa9730_regs->RxCtl) | RX_CTL_RX_EN, - &lp->lan_saa9730_regs->RxCtl); + writel(readl(&lp->lan_saa9730_regs->RxCtl) | RX_CTL_RX_EN, + &lp->lan_saa9730_regs->RxCtl); /* Set Ok2Use to let hardware own the buffers. */ - outl(OK2USE_RX_A | OK2USE_RX_B, &lp->lan_saa9730_regs->Ok2Use); + writel(OK2USE_RX_A | OK2USE_RX_B, &lp->lan_saa9730_regs->Ok2Use); return 0; } @@ -587,7 +586,7 @@ static int lan_saa9730_tx(struct net_device *dev) printk("lan_saa9730_tx interrupt\n"); /* Clear interrupt. */ - outl(DMA_STATUS_MAC_TX_INT, &lp->lan_saa9730_regs->DmaStatus); + writel(DMA_STATUS_MAC_TX_INT, &lp->lan_saa9730_regs->DmaStatus); while (1) { pPacket = lp->TxmBuffer[lp->PendingTxmBufferIndex] @@ -660,8 +659,8 @@ static int lan_saa9730_rx(struct net_device *dev) printk("lan_saa9730_rx interrupt\n"); /* Clear receive interrupts. */ - outl(DMA_STATUS_MAC_RX_INT | DMA_STATUS_RX_INT | - DMA_STATUS_RX_TO_INT, &lp->lan_saa9730_regs->DmaStatus); + writel(DMA_STATUS_MAC_RX_INT | DMA_STATUS_RX_INT | + DMA_STATUS_RX_TO_INT, &lp->lan_saa9730_regs->DmaStatus); /* Address next packet */ BufferIndex = lp->NextRcvBufferIndex; @@ -725,8 +724,8 @@ static int lan_saa9730_rx(struct net_device *dev) *pPacket = cpu_to_le32(RXSF_READY << RX_STAT_CTL_OWNER_SHF); /* Make sure A or B is available to hardware as appropriate. */ - outl(BufferIndex ? OK2USE_RX_B : OK2USE_RX_A, - &lp->lan_saa9730_regs->Ok2Use); + writel(BufferIndex ? OK2USE_RX_B : OK2USE_RX_A, + &lp->lan_saa9730_regs->Ok2Use); /* Go to next packet in sequence. */ lp->NextRcvPacketIndex++; @@ -844,8 +843,8 @@ static int lan_saa9730_write(struct lan_saa9730_private *lp, (len << TX_STAT_CTL_LENGTH_SHF)); /* Make sure A or B is available to hardware as appropriate. */ - outl(BufferIndex ? OK2USE_TX_B : OK2USE_TX_A, - &lp->lan_saa9730_regs->Ok2Use); + writel(BufferIndex ? OK2USE_TX_B : OK2USE_TX_A, + &lp->lan_saa9730_regs->Ok2Use); return 0; } @@ -938,15 +937,15 @@ static void lan_saa9730_set_multicast(struct net_device *dev) if (dev->flags & IFF_PROMISC) { /* accept all packets */ - outl(CAM_CONTROL_COMP_EN | CAM_CONTROL_STATION_ACC | - CAM_CONTROL_GROUP_ACC | CAM_CONTROL_BROAD_ACC, - &lp->lan_saa9730_regs->CamCtl); + writel(CAM_CONTROL_COMP_EN | CAM_CONTROL_STATION_ACC | + CAM_CONTROL_GROUP_ACC | CAM_CONTROL_BROAD_ACC, + &lp->lan_saa9730_regs->CamCtl); } else { if (dev->flags & IFF_ALLMULTI) { /* accept all multicast packets */ - outl(CAM_CONTROL_COMP_EN | CAM_CONTROL_GROUP_ACC | - CAM_CONTROL_BROAD_ACC, - &lp->lan_saa9730_regs->CamCtl); + writel(CAM_CONTROL_COMP_EN | CAM_CONTROL_GROUP_ACC | + CAM_CONTROL_BROAD_ACC, + &lp->lan_saa9730_regs->CamCtl); } else { /* * Will handle the multicast stuff later. -carstenl diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index 1eae16b72b4..103c3174ab5 100644 --- a/drivers/net/sb1250-mac.c +++ b/drivers/net/sb1250-mac.c @@ -243,7 +243,7 @@ struct sbmac_softc { * Controller-specific things */ - volatile void __iomem *sbm_base; /* MAC's base address */ + void __iomem *sbm_base; /* MAC's base address */ sbmac_state_t sbm_state; /* current state */ volatile void __iomem *sbm_macenable; /* MAC Enable Register */ diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c index 4a926f20b6e..c32c21af3fd 100644 --- a/drivers/net/sc92031.c +++ b/drivers/net/sc92031.c @@ -964,7 +964,7 @@ static int sc92031_start_xmit(struct sk_buff *skb, struct net_device *dev) goto out; } - spin_lock_bh(&priv->lock); + spin_lock(&priv->lock); if (unlikely(!netif_carrier_ok(dev))) { err = -ENOLINK; @@ -1005,7 +1005,7 @@ static int sc92031_start_xmit(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); out_unlock: - spin_unlock_bh(&priv->lock); + spin_unlock(&priv->lock); out: dev_kfree_skb(skb); @@ -1042,12 +1042,12 @@ static int sc92031_open(struct net_device *dev) priv->pm_config = 0; /* Interrupts already disabled by sc92031_stop or sc92031_probe */ - spin_lock(&priv->lock); + spin_lock_bh(&priv->lock); _sc92031_reset(dev); mmiowb(); - spin_unlock(&priv->lock); + spin_unlock_bh(&priv->lock); sc92031_enable_interrupts(dev); if (netif_carrier_ok(dev)) @@ -1077,13 +1077,13 @@ static int sc92031_stop(struct net_device *dev) /* Disable interrupts, stop Tx and Rx. */ sc92031_disable_interrupts(dev); - spin_lock(&priv->lock); + spin_lock_bh(&priv->lock); _sc92031_disable_tx_rx(dev); _sc92031_tx_clear(dev); mmiowb(); - spin_unlock(&priv->lock); + spin_unlock_bh(&priv->lock); free_irq(pdev->irq, dev); pci_free_consistent(pdev, TX_BUF_TOT_LEN, priv->tx_bufs, @@ -1539,13 +1539,13 @@ static int sc92031_suspend(struct pci_dev *pdev, pm_message_t state) /* Disable interrupts, stop Tx and Rx. */ sc92031_disable_interrupts(dev); - spin_lock(&priv->lock); + spin_lock_bh(&priv->lock); _sc92031_disable_tx_rx(dev); _sc92031_tx_clear(dev); mmiowb(); - spin_unlock(&priv->lock); + spin_unlock_bh(&priv->lock); out: pci_set_power_state(pdev, pci_choose_state(pdev, state)); @@ -1565,12 +1565,12 @@ static int sc92031_resume(struct pci_dev *pdev) goto out; /* Interrupts already disabled by sc92031_suspend */ - spin_lock(&priv->lock); + spin_lock_bh(&priv->lock); _sc92031_reset(dev); mmiowb(); - spin_unlock(&priv->lock); + spin_unlock_bh(&priv->lock); sc92031_enable_interrupts(dev); netif_device_attach(dev); diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index b08508b3583..34463ce6f13 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -324,6 +324,7 @@ static struct mii_chip_info { u32 feature; } mii_chip_table[] = { { "Broadcom PHY BCM5461", { 0x0020, 0x60c0 }, LAN, F_PHY_BCM5461 }, + { "Broadcom PHY AC131", { 0x0143, 0xbc70 }, LAN, 0 }, { "Agere PHY ET1101B", { 0x0282, 0xf010 }, LAN, 0 }, { "Marvell PHY 88E1111", { 0x0141, 0x0cc0 }, LAN, F_PHY_88E1111 }, { "Realtek PHY RTL8201", { 0x0000, 0x8200 }, LAN, 0 }, diff --git a/drivers/net/skge.c b/drivers/net/skge.c index eea75a401b0..d476a3cc2e9 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -105,7 +105,8 @@ static const int txqaddr[] = { Q_XA1, Q_XA2 }; static const int rxqaddr[] = { Q_R1, Q_R2 }; static const u32 rxirqmask[] = { IS_R1_F, IS_R2_F }; static const u32 txirqmask[] = { IS_XA1_F, IS_XA2_F }; -static const u32 irqmask[] = { IS_R1_F|IS_XA1_F, IS_R2_F|IS_XA2_F }; +static const u32 napimask[] = { IS_R1_F|IS_XA1_F, IS_R2_F|IS_XA2_F }; +static const u32 portmask[] = { IS_PORT_1, IS_PORT_2 }; static int skge_get_regs_len(struct net_device *dev) { @@ -162,27 +163,46 @@ static void skge_wol_init(struct skge_port *skge) { struct skge_hw *hw = skge->hw; int port = skge->port; - enum pause_control save_mode; - u32 ctrl; + u16 ctrl; - /* Bring hardware out of reset */ skge_write16(hw, B0_CTST, CS_RST_CLR); skge_write16(hw, SK_REG(port, GMAC_LINK_CTRL), GMLC_RST_CLR); - skge_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR); - skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR); + /* Turn on Vaux */ + skge_write8(hw, B0_POWER_CTRL, + PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_ON | PC_VCC_OFF); - /* Force to 10/100 skge_reset will re-enable on resume */ - save_mode = skge->flow_control; - skge->flow_control = FLOW_MODE_SYMMETRIC; + /* WA code for COMA mode -- clear PHY reset */ + if (hw->chip_id == CHIP_ID_YUKON_LITE && + hw->chip_rev >= CHIP_REV_YU_LITE_A3) { + u32 reg = skge_read32(hw, B2_GP_IO); + reg |= GP_DIR_9; + reg &= ~GP_IO_9; + skge_write32(hw, B2_GP_IO, reg); + } - ctrl = skge->advertising; - skge->advertising &= ~(ADVERTISED_1000baseT_Half|ADVERTISED_1000baseT_Full); + skge_write32(hw, SK_REG(port, GPHY_CTRL), + GPC_DIS_SLEEP | + GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0 | + GPC_ANEG_1 | GPC_RST_SET); - skge_phy_reset(skge); + skge_write32(hw, SK_REG(port, GPHY_CTRL), + GPC_DIS_SLEEP | + GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0 | + GPC_ANEG_1 | GPC_RST_CLR); + + skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR); + + /* Force to 10/100 skge_reset will re-enable on resume */ + gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, + PHY_AN_100FULL | PHY_AN_100HALF | + PHY_AN_10FULL | PHY_AN_10HALF| PHY_AN_CSMA); + /* no 1000 HD/FD */ + gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, 0); + gm_phy_write(hw, port, PHY_MARV_CTRL, + PHY_CT_RESET | PHY_CT_SPS_LSB | PHY_CT_ANE | + PHY_CT_RE_CFG | PHY_CT_DUP_MD); - skge->flow_control = save_mode; - skge->advertising = ctrl; /* Set GMAC to no flow control and auto update for speed/duplex */ gma_write16(hw, port, GM_GP_CTRL, @@ -226,12 +246,10 @@ static int skge_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) struct skge_port *skge = netdev_priv(dev); struct skge_hw *hw = skge->hw; - if (wol->wolopts & wol_supported(hw)) + if (wol->wolopts & ~wol_supported(hw)) return -EOPNOTSUPP; skge->wol = wol->wolopts; - if (!netif_running(dev)) - skge_wol_init(skge); return 0; } @@ -671,7 +689,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode) struct skge_hw *hw = skge->hw; int port = skge->port; - mutex_lock(&hw->phy_mutex); + spin_lock_bh(&hw->phy_lock); if (hw->chip_id == CHIP_ID_GENESIS) { switch (mode) { case LED_MODE_OFF: @@ -742,7 +760,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode) PHY_M_LED_MO_RX(MO_LED_ON)); } } - mutex_unlock(&hw->phy_mutex); + spin_unlock_bh(&hw->phy_lock); } /* blink LED's for finding board */ @@ -1316,7 +1334,7 @@ static void xm_phy_init(struct skge_port *skge) xm_phy_write(hw, port, PHY_XMAC_CTRL, ctrl); /* Poll PHY for status changes */ - schedule_delayed_work(&skge->link_thread, LINK_HZ); + mod_timer(&skge->link_timer, jiffies + LINK_HZ); } static void xm_check_link(struct net_device *dev) @@ -1391,10 +1409,9 @@ static void xm_check_link(struct net_device *dev) * Since internal PHY is wired to a level triggered pin, can't * get an interrupt when carrier is detected. */ -static void xm_link_timer(struct work_struct *work) +static void xm_link_timer(unsigned long arg) { - struct skge_port *skge = - container_of(work, struct skge_port, link_thread.work); + struct skge_port *skge = (struct skge_port *) arg; struct net_device *dev = skge->netdev; struct skge_hw *hw = skge->hw; int port = skge->port; @@ -1414,13 +1431,13 @@ static void xm_link_timer(struct work_struct *work) goto nochange; } - mutex_lock(&hw->phy_mutex); + spin_lock(&hw->phy_lock); xm_check_link(dev); - mutex_unlock(&hw->phy_mutex); + spin_unlock(&hw->phy_lock); nochange: if (netif_running(dev)) - schedule_delayed_work(&skge->link_thread, LINK_HZ); + mod_timer(&skge->link_timer, jiffies + LINK_HZ); } static void genesis_mac_init(struct skge_hw *hw, int port) @@ -2323,7 +2340,7 @@ static void skge_phy_reset(struct skge_port *skge) netif_stop_queue(skge->netdev); netif_carrier_off(skge->netdev); - mutex_lock(&hw->phy_mutex); + spin_lock_bh(&hw->phy_lock); if (hw->chip_id == CHIP_ID_GENESIS) { genesis_reset(hw, port); genesis_mac_init(hw, port); @@ -2331,7 +2348,7 @@ static void skge_phy_reset(struct skge_port *skge) yukon_reset(hw, port); yukon_init(hw, port); } - mutex_unlock(&hw->phy_mutex); + spin_unlock_bh(&hw->phy_lock); dev->set_multicast_list(dev); } @@ -2354,12 +2371,12 @@ static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /* fallthru */ case SIOCGMIIREG: { u16 val = 0; - mutex_lock(&hw->phy_mutex); + spin_lock_bh(&hw->phy_lock); if (hw->chip_id == CHIP_ID_GENESIS) err = __xm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val); else err = __gm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val); - mutex_unlock(&hw->phy_mutex); + spin_unlock_bh(&hw->phy_lock); data->val_out = val; break; } @@ -2368,14 +2385,14 @@ static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) if (!capable(CAP_NET_ADMIN)) return -EPERM; - mutex_lock(&hw->phy_mutex); + spin_lock_bh(&hw->phy_lock); if (hw->chip_id == CHIP_ID_GENESIS) err = xm_phy_write(hw, skge->port, data->reg_num & 0x1f, data->val_in); else err = gm_phy_write(hw, skge->port, data->reg_num & 0x1f, data->val_in); - mutex_unlock(&hw->phy_mutex); + spin_unlock_bh(&hw->phy_lock); break; } return err; @@ -2481,12 +2498,12 @@ static int skge_up(struct net_device *dev) goto free_rx_ring; /* Initialize MAC */ - mutex_lock(&hw->phy_mutex); + spin_lock_bh(&hw->phy_lock); if (hw->chip_id == CHIP_ID_GENESIS) genesis_mac_init(hw, port); else yukon_mac_init(hw, port); - mutex_unlock(&hw->phy_mutex); + spin_unlock_bh(&hw->phy_lock); /* Configure RAMbuffers */ chunk = hw->ram_size / ((hw->ports + 1)*2); @@ -2504,6 +2521,11 @@ static int skge_up(struct net_device *dev) skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F); skge_led(skge, LED_MODE_ON); + spin_lock_irq(&hw->hw_lock); + hw->intr_mask |= portmask[port]; + skge_write32(hw, B0_IMSK, hw->intr_mask); + spin_unlock_irq(&hw->hw_lock); + netif_poll_enable(dev); return 0; @@ -2530,8 +2552,17 @@ static int skge_down(struct net_device *dev) printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); netif_stop_queue(dev); + if (hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC) - cancel_delayed_work(&skge->link_thread); + del_timer_sync(&skge->link_timer); + + netif_poll_disable(dev); + netif_carrier_off(dev); + + spin_lock_irq(&hw->hw_lock); + hw->intr_mask &= ~portmask[port]; + skge_write32(hw, B0_IMSK, hw->intr_mask); + spin_unlock_irq(&hw->hw_lock); skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF); if (hw->chip_id == CHIP_ID_GENESIS) @@ -2575,8 +2606,10 @@ static int skge_down(struct net_device *dev) skge_led(skge, LED_MODE_OFF); - netif_poll_disable(dev); + netif_tx_lock_bh(dev); skge_tx_clean(dev); + netif_tx_unlock_bh(dev); + skge_rx_clean(skge); kfree(skge->rx_ring.start); @@ -2721,7 +2754,6 @@ static void skge_tx_clean(struct net_device *dev) struct skge_port *skge = netdev_priv(dev); struct skge_element *e; - netif_tx_lock_bh(dev); for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) { struct skge_tx_desc *td = e->desc; skge_tx_free(skge, e, td->control); @@ -2730,7 +2762,6 @@ static void skge_tx_clean(struct net_device *dev) skge->tx_ring.to_clean = e; netif_wake_queue(dev); - netif_tx_unlock_bh(dev); } static void skge_tx_timeout(struct net_device *dev) @@ -3049,7 +3080,7 @@ static int skge_poll(struct net_device *dev, int *budget) spin_lock_irqsave(&hw->hw_lock, flags); __netif_rx_complete(dev); - hw->intr_mask |= irqmask[skge->port]; + hw->intr_mask |= napimask[skge->port]; skge_write32(hw, B0_IMSK, hw->intr_mask); skge_read32(hw, B0_IMSK); spin_unlock_irqrestore(&hw->hw_lock, flags); @@ -3160,28 +3191,29 @@ static void skge_error_irq(struct skge_hw *hw) } /* - * Interrupt from PHY are handled in work queue + * Interrupt from PHY are handled in tasklet (softirq) * because accessing phy registers requires spin wait which might * cause excess interrupt latency. */ -static void skge_extirq(struct work_struct *work) +static void skge_extirq(unsigned long arg) { - struct skge_hw *hw = container_of(work, struct skge_hw, phy_work); + struct skge_hw *hw = (struct skge_hw *) arg; int port; - mutex_lock(&hw->phy_mutex); for (port = 0; port < hw->ports; port++) { struct net_device *dev = hw->dev[port]; - struct skge_port *skge = netdev_priv(dev); if (netif_running(dev)) { + struct skge_port *skge = netdev_priv(dev); + + spin_lock(&hw->phy_lock); if (hw->chip_id != CHIP_ID_GENESIS) yukon_phy_intr(skge); else if (hw->phy_type == SK_PHY_BCOM) bcom_phy_intr(skge); + spin_unlock(&hw->phy_lock); } } - mutex_unlock(&hw->phy_mutex); spin_lock_irq(&hw->hw_lock); hw->intr_mask |= IS_EXT_REG; @@ -3206,7 +3238,7 @@ static irqreturn_t skge_intr(int irq, void *dev_id) status &= hw->intr_mask; if (status & IS_EXT_REG) { hw->intr_mask &= ~IS_EXT_REG; - schedule_work(&hw->phy_work); + tasklet_schedule(&hw->phy_task); } if (status & (IS_XA1_F|IS_R1_F)) { @@ -3275,24 +3307,35 @@ static int skge_set_mac_address(struct net_device *dev, void *p) struct skge_hw *hw = skge->hw; unsigned port = skge->port; const struct sockaddr *addr = p; + u16 ctrl; if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; - mutex_lock(&hw->phy_mutex); memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); - memcpy_toio(hw->regs + B2_MAC_1 + port*8, - dev->dev_addr, ETH_ALEN); - memcpy_toio(hw->regs + B2_MAC_2 + port*8, - dev->dev_addr, ETH_ALEN); - if (hw->chip_id == CHIP_ID_GENESIS) - xm_outaddr(hw, port, XM_SA, dev->dev_addr); - else { - gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr); - gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr); + if (!netif_running(dev)) { + memcpy_toio(hw->regs + B2_MAC_1 + port*8, dev->dev_addr, ETH_ALEN); + memcpy_toio(hw->regs + B2_MAC_2 + port*8, dev->dev_addr, ETH_ALEN); + } else { + /* disable Rx */ + spin_lock_bh(&hw->phy_lock); + ctrl = gma_read16(hw, port, GM_GP_CTRL); + gma_write16(hw, port, GM_GP_CTRL, ctrl & ~GM_GPCR_RX_ENA); + + memcpy_toio(hw->regs + B2_MAC_1 + port*8, dev->dev_addr, ETH_ALEN); + memcpy_toio(hw->regs + B2_MAC_2 + port*8, dev->dev_addr, ETH_ALEN); + + if (hw->chip_id == CHIP_ID_GENESIS) + xm_outaddr(hw, port, XM_SA, dev->dev_addr); + else { + gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr); + gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr); + } + + gma_write16(hw, port, GM_GP_CTRL, ctrl); + spin_unlock_bh(&hw->phy_lock); } - mutex_unlock(&hw->phy_mutex); return 0; } @@ -3407,10 +3450,9 @@ static int skge_reset(struct skge_hw *hw) else hw->ram_size = t8 * 4096; - hw->intr_mask = IS_HW_ERR | IS_PORT_1; - if (hw->ports > 1) - hw->intr_mask |= IS_PORT_2; + hw->intr_mask = IS_HW_ERR; + /* Use PHY IRQ for all but fiber based Genesis board */ if (!(hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC)) hw->intr_mask |= IS_EXT_REG; @@ -3478,14 +3520,12 @@ static int skge_reset(struct skge_hw *hw) skge_write32(hw, B0_IMSK, hw->intr_mask); - mutex_lock(&hw->phy_mutex); for (i = 0; i < hw->ports; i++) { if (hw->chip_id == CHIP_ID_GENESIS) genesis_reset(hw, i); else yukon_reset(hw, i); } - mutex_unlock(&hw->phy_mutex); return 0; } @@ -3533,6 +3573,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, skge->netdev = dev; skge->hw = hw; skge->msg_enable = netif_msg_init(debug, default_msg); + skge->tx_ring.count = DEFAULT_TX_RING_SIZE; skge->rx_ring.count = DEFAULT_RX_RING_SIZE; @@ -3549,7 +3590,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, skge->port = port; /* Only used for Genesis XMAC */ - INIT_DELAYED_WORK(&skge->link_thread, xm_link_timer); + setup_timer(&skge->link_timer, xm_link_timer, (unsigned long) skge); if (hw->chip_id != CHIP_ID_GENESIS) { dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; @@ -3631,9 +3672,9 @@ static int __devinit skge_probe(struct pci_dev *pdev, } hw->pdev = pdev; - mutex_init(&hw->phy_mutex); - INIT_WORK(&hw->phy_work, skge_extirq); spin_lock_init(&hw->hw_lock); + spin_lock_init(&hw->phy_lock); + tasklet_init(&hw->phy_task, &skge_extirq, (unsigned long) hw); hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000); if (!hw->regs) { @@ -3719,6 +3760,8 @@ static void __devexit skge_remove(struct pci_dev *pdev) dev0 = hw->dev[0]; unregister_netdev(dev0); + tasklet_disable(&hw->phy_task); + spin_lock_irq(&hw->hw_lock); hw->intr_mask = 0; skge_write32(hw, B0_IMSK, 0); @@ -3741,21 +3784,6 @@ static void __devexit skge_remove(struct pci_dev *pdev) } #ifdef CONFIG_PM -static int vaux_avail(struct pci_dev *pdev) -{ - int pm_cap; - - pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); - if (pm_cap) { - u16 ctl; - pci_read_config_word(pdev, pm_cap + PCI_PM_PMC, &ctl); - if (ctl & PCI_PM_CAP_AUX_POWER) - return 1; - } - return 0; -} - - static int skge_suspend(struct pci_dev *pdev, pm_message_t state) { struct skge_hw *hw = pci_get_drvdata(pdev); @@ -3777,10 +3805,6 @@ static int skge_suspend(struct pci_dev *pdev, pm_message_t state) wol |= skge->wol; } - if (wol && vaux_avail(pdev)) - skge_write8(hw, B0_POWER_CTRL, - PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_ON | PC_VCC_OFF); - skge_write32(hw, B0_IMSK, 0); pci_enable_wake(pdev, pci_choose_state(pdev, state), wol); pci_set_power_state(pdev, pci_choose_state(pdev, state)); @@ -3826,6 +3850,28 @@ out: } #endif +static void skge_shutdown(struct pci_dev *pdev) +{ + struct skge_hw *hw = pci_get_drvdata(pdev); + int i, wol = 0; + + for (i = 0; i < hw->ports; i++) { + struct net_device *dev = hw->dev[i]; + struct skge_port *skge = netdev_priv(dev); + + if (skge->wol) + skge_wol_init(skge); + wol |= skge->wol; + } + + pci_enable_wake(pdev, PCI_D3hot, wol); + pci_enable_wake(pdev, PCI_D3cold, wol); + + pci_disable_device(pdev); + pci_set_power_state(pdev, PCI_D3hot); + +} + static struct pci_driver skge_driver = { .name = DRV_NAME, .id_table = skge_id_table, @@ -3835,6 +3881,7 @@ static struct pci_driver skge_driver = { .suspend = skge_suspend, .resume = skge_resume, #endif + .shutdown = skge_shutdown, }; static int __init skge_init_module(void) diff --git a/drivers/net/skge.h b/drivers/net/skge.h index e9354dfa7e9..86467ae74d4 100644 --- a/drivers/net/skge.h +++ b/drivers/net/skge.h @@ -2424,8 +2424,8 @@ struct skge_hw { u32 ram_size; u32 ram_offset; u16 phy_addr; - struct work_struct phy_work; - struct mutex phy_mutex; + spinlock_t phy_lock; + struct tasklet_struct phy_task; }; enum pause_control { @@ -2457,7 +2457,7 @@ struct skge_port { struct net_device_stats net_stats; - struct delayed_work link_thread; + struct timer_list link_timer; enum pause_control flow_control; enum pause_status flow_status; u8 rx_csum; diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 53839979cfb..4a009b7b177 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -510,9 +510,9 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) ledover &= ~PHY_M_LED_MO_RX; } - if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev == CHIP_REV_YU_EC_A1) { + if (hw->chip_id == CHIP_ID_YUKON_EC_U && + hw->chip_rev == CHIP_REV_YU_EC_U_A1) { /* apply fixes in PHY AFE */ - pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 255); /* increase differential signal amplitude in 10BASE-T */ @@ -524,7 +524,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) gm_phy_write(hw, port, 0x17, 0x2002); /* set page register to 0 */ - gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0); } else if (hw->chip_id != CHIP_ID_YUKON_EX) { gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); @@ -1561,6 +1561,7 @@ static int sky2_down(struct net_device *dev) /* Stop more packets from being queued */ netif_stop_queue(dev); + netif_carrier_off(dev); /* Disable port IRQ */ imask = sky2_read32(hw, B0_IMSK); @@ -2165,9 +2166,27 @@ force_update: /* fall through */ #endif case OP_RXCHKS: - skb = sky2->rx_ring[sky2->rx_next].skb; - skb->ip_summed = CHECKSUM_COMPLETE; - skb->csum = status & 0xffff; + if (!sky2->rx_csum) + break; + + /* Both checksum counters are programmed to start at + * the same offset, so unless there is a problem they + * should match. This failure is an early indication that + * hardware receive checksumming won't work. + */ + if (likely(status >> 16 == (status & 0xffff))) { + skb = sky2->rx_ring[sky2->rx_next].skb; + skb->ip_summed = CHECKSUM_COMPLETE; + skb->csum = status & 0xffff; + } else { + printk(KERN_NOTICE PFX "%s: hardware receive " + "checksum problem (status = %#x)\n", + dev->name, status); + sky2->rx_csum = 0; + sky2_write32(sky2->hw, + Q_ADDR(rxqaddr[le->link], Q_CSR), + BMU_DIS_RX_CHKSUM); + } break; case OP_TXINDEXLE: @@ -3751,6 +3770,11 @@ static int sky2_resume(struct pci_dev *pdev) goto out; pci_enable_wake(pdev, PCI_D0, 0); + + /* Re-enable all clocks */ + if (hw->chip_id == CHIP_ID_YUKON_EX || hw->chip_id == CHIP_ID_YUKON_EC_U) + sky2_pci_write32(hw, PCI_DEV_REG3, 0); + sky2_reset(hw); sky2_write32(hw, B0_IMSK, Y2_IS_BASE); diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c index c62e85d89f4..7bee45b42a2 100644 --- a/drivers/net/sun3lance.c +++ b/drivers/net/sun3lance.c @@ -336,13 +336,27 @@ static int __init lance_probe( struct net_device *dev) /* XXX - leak? */ MEM = dvma_malloc_align(sizeof(struct lance_memory), 0x10000); + if (MEM == NULL) { +#ifdef CONFIG_SUN3 + iounmap((void __iomem *)ioaddr); +#endif + printk(KERN_WARNING "SUN3 Lance couldn't allocate DVMA memory\n"); + return 0; + } lp->iobase = (volatile unsigned short *)ioaddr; dev->base_addr = (unsigned long)ioaddr; /* informational only */ REGA(CSR0) = CSR0_STOP; - request_irq(LANCE_IRQ, lance_interrupt, IRQF_DISABLED, "SUN3 Lance", dev); + if (request_irq(LANCE_IRQ, lance_interrupt, IRQF_DISABLED, "SUN3 Lance", dev) < 0) { +#ifdef CONFIG_SUN3 + iounmap((void __iomem *)ioaddr); +#endif + dvma_free((void *)MEM); + printk(KERN_WARNING "SUN3 Lance unable to allocate IRQ\n"); + return 0; + } dev->irq = (unsigned short)LANCE_IRQ; diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 616be8d0fa8..08ea61db46f 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -2530,6 +2530,35 @@ static struct net_device_stats *gem_get_stats(struct net_device *dev) return &gp->net_stats; } +static int gem_set_mac_address(struct net_device *dev, void *addr) +{ + struct sockaddr *macaddr = (struct sockaddr *) addr; + struct gem *gp = dev->priv; + unsigned char *e = &dev->dev_addr[0]; + + if (!is_valid_ether_addr(macaddr->sa_data)) + return -EADDRNOTAVAIL; + + if (!netif_running(dev) || !netif_device_present(dev)) { + /* We'll just catch it later when the + * device is up'd or resumed. + */ + memcpy(dev->dev_addr, macaddr->sa_data, dev->addr_len); + return 0; + } + + mutex_lock(&gp->pm_mutex); + memcpy(dev->dev_addr, macaddr->sa_data, dev->addr_len); + if (gp->running) { + writel((e[4] << 8) | e[5], gp->regs + MAC_ADDR0); + writel((e[2] << 8) | e[3], gp->regs + MAC_ADDR1); + writel((e[0] << 8) | e[1], gp->regs + MAC_ADDR2); + } + mutex_unlock(&gp->pm_mutex); + + return 0; +} + static void gem_set_multicast(struct net_device *dev) { struct gem *gp = dev->priv; @@ -3122,6 +3151,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev, dev->change_mtu = gem_change_mtu; dev->irq = pdev->irq; dev->dma = 0; + dev->set_mac_address = gem_set_mac_address; #ifdef CONFIG_NET_POLL_CONTROLLER dev->poll_controller = gem_poll_controller; #endif diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 8c8f9f4d47a..256969e1300 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -64,8 +64,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.74" -#define DRV_MODULE_RELDATE "February 20, 2007" +#define DRV_MODULE_VERSION "3.75" +#define DRV_MODULE_RELDATE "March 23, 2007" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -3568,32 +3568,34 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id) * Reading the PCI State register will confirm whether the * interrupt is ours and will flush the status block. */ - if ((sblk->status & SD_STATUS_UPDATED) || - !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { - /* - * Writing any value to intr-mbox-0 clears PCI INTA# and - * chip-internal interrupt pending events. - * Writing non-zero to intr-mbox-0 additional tells the - * NIC to stop sending us irqs, engaging "in-intr-handler" - * event coalescing. - */ - tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, - 0x00000001); - if (tg3_irq_sync(tp)) + if (unlikely(!(sblk->status & SD_STATUS_UPDATED))) { + if ((tp->tg3_flags & TG3_FLAG_CHIP_RESETTING) || + (tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { + handled = 0; goto out; - sblk->status &= ~SD_STATUS_UPDATED; - if (likely(tg3_has_work(tp))) { - prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); - netif_rx_schedule(dev); /* schedule NAPI poll */ - } else { - /* No work, shared interrupt perhaps? re-enable - * interrupts, and flush that PCI write - */ - tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, - 0x00000000); } - } else { /* shared interrupt */ - handled = 0; + } + + /* + * Writing any value to intr-mbox-0 clears PCI INTA# and + * chip-internal interrupt pending events. + * Writing non-zero to intr-mbox-0 additional tells the + * NIC to stop sending us irqs, engaging "in-intr-handler" + * event coalescing. + */ + tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); + if (tg3_irq_sync(tp)) + goto out; + sblk->status &= ~SD_STATUS_UPDATED; + if (likely(tg3_has_work(tp))) { + prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); + netif_rx_schedule(dev); /* schedule NAPI poll */ + } else { + /* No work, shared interrupt perhaps? re-enable + * interrupts, and flush that PCI write + */ + tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, + 0x00000000); } out: return IRQ_RETVAL(handled); @@ -3611,31 +3613,33 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id) * Reading the PCI State register will confirm whether the * interrupt is ours and will flush the status block. */ - if ((sblk->status_tag != tp->last_tag) || - !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { - /* - * writing any value to intr-mbox-0 clears PCI INTA# and - * chip-internal interrupt pending events. - * writing non-zero to intr-mbox-0 additional tells the - * NIC to stop sending us irqs, engaging "in-intr-handler" - * event coalescing. - */ - tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, - 0x00000001); - if (tg3_irq_sync(tp)) + if (unlikely(sblk->status_tag == tp->last_tag)) { + if ((tp->tg3_flags & TG3_FLAG_CHIP_RESETTING) || + (tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { + handled = 0; goto out; - if (netif_rx_schedule_prep(dev)) { - prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); - /* Update last_tag to mark that this status has been - * seen. Because interrupt may be shared, we may be - * racing with tg3_poll(), so only update last_tag - * if tg3_poll() is not scheduled. - */ - tp->last_tag = sblk->status_tag; - __netif_rx_schedule(dev); } - } else { /* shared interrupt */ - handled = 0; + } + + /* + * writing any value to intr-mbox-0 clears PCI INTA# and + * chip-internal interrupt pending events. + * writing non-zero to intr-mbox-0 additional tells the + * NIC to stop sending us irqs, engaging "in-intr-handler" + * event coalescing. + */ + tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); + if (tg3_irq_sync(tp)) + goto out; + if (netif_rx_schedule_prep(dev)) { + prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); + /* Update last_tag to mark that this status has been + * seen. Because interrupt may be shared, we may be + * racing with tg3_poll(), so only update last_tag + * if tg3_poll() is not scheduled. + */ + tp->last_tag = sblk->status_tag; + __netif_rx_schedule(dev); } out: return IRQ_RETVAL(handled); @@ -4823,6 +4827,21 @@ static int tg3_chip_reset(struct tg3 *tp) if (write_op == tg3_write_flush_reg32) tp->write32 = tg3_write32; + /* Prevent the irq handler from reading or writing PCI registers + * during chip reset when the memory enable bit in the PCI command + * register may be cleared. The chip does not generate interrupt + * at this time, but the irq handler may still be called due to irq + * sharing or irqpoll. + */ + tp->tg3_flags |= TG3_FLAG_CHIP_RESETTING; + if (tp->hw_status) { + tp->hw_status->status = 0; + tp->hw_status->status_tag = 0; + } + tp->last_tag = 0; + smp_mb(); + synchronize_irq(tp->pdev->irq); + /* do the reset */ val = GRC_MISC_CFG_CORECLK_RESET; @@ -4904,6 +4923,8 @@ static int tg3_chip_reset(struct tg3 *tp) pci_restore_state(tp->pdev); + tp->tg3_flags &= ~TG3_FLAG_CHIP_RESETTING; + /* Make sure PCI-X relaxed ordering bit is clear. */ pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val); val &= ~PCIX_CAPS_RELAXED_ORDERING; @@ -6321,8 +6342,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) RDMAC_MODE_ADDROFLOW_ENAB | RDMAC_MODE_FIFOOFLOW_ENAB | RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB | RDMAC_MODE_LNGREAD_ENAB); - if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE) - rdmac_mode |= RDMAC_MODE_SPLIT_ENABLE; /* If statement applies to 5705 and 5750 PCI devices only */ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 && @@ -6495,9 +6514,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { val &= ~(PCIX_CAPS_SPLIT_MASK | PCIX_CAPS_BURST_MASK); val |= (PCIX_CAPS_MAX_BURST_CPIOB << PCIX_CAPS_BURST_SHIFT); - if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE) - val |= (tp->split_mode_max_reqs << - PCIX_CAPS_SPLIT_SHIFT); } tw32(TG3PCI_X_CAPS, val); } @@ -10863,14 +10879,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) grc_misc_cfg = tr32(GRC_MISC_CFG); grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK; - /* Broadcom's driver says that CIOBE multisplit has a bug */ -#if 0 - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 && - grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5704CIOBE) { - tp->tg3_flags |= TG3_FLAG_SPLIT_MODE; - tp->split_mode_max_reqs = SPLIT_MODE_5704_MAX_REQ; - } -#endif if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 && (grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788 || grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M)) @@ -11968,14 +11976,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, i == 5 ? '\n' : ':'); printk(KERN_INFO "%s: RXcsums[%d] LinkChgREG[%d] " - "MIirq[%d] ASF[%d] Split[%d] WireSpeed[%d] " - "TSOcap[%d] \n", + "MIirq[%d] ASF[%d] WireSpeed[%d] TSOcap[%d]\n", dev->name, (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0, (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) != 0, (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) != 0, (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0, - (tp->tg3_flags & TG3_FLAG_SPLIT_MODE) != 0, (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0, (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0); printk(KERN_INFO "%s: dma_rwctrl[%08x] dma_mask[%d-bit]\n", diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 086892d8c1f..d515ed23841 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2223,7 +2223,7 @@ struct tg3 { #define TG3_FLAG_40BIT_DMA_BUG 0x08000000 #define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000 #define TG3_FLAG_GOT_SERDES_FLOWCTL 0x20000000 -#define TG3_FLAG_SPLIT_MODE 0x40000000 +#define TG3_FLAG_CHIP_RESETTING 0x40000000 #define TG3_FLAG_INIT_COMPLETE 0x80000000 u32 tg3_flags2; #define TG3_FLG2_RESTART_TIMER 0x00000001 @@ -2262,9 +2262,6 @@ struct tg3 { #define TG3_FLG2_NO_FWARE_REPORTED 0x40000000 #define TG3_FLG2_PHY_ADJUST_TRIM 0x80000000 - u32 split_mode_max_reqs; -#define SPLIT_MODE_5704_MAX_REQ 3 - struct timer_list timer; u16 timer_counter; u16 timer_multiplier; diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c index 0d97e10ccac..01d55315ee8 100644 --- a/drivers/net/tokenring/ibmtr.c +++ b/drivers/net/tokenring/ibmtr.c @@ -186,7 +186,6 @@ static char __devinit *adapter_def(char type) #define TRC_INITV 0x02 /* verbose init trace points */ static unsigned char ibmtr_debug_trace = 0; -static int ibmtr_probe(struct net_device *dev); static int ibmtr_probe1(struct net_device *dev, int ioaddr); static unsigned char get_sram_size(struct tok_info *adapt_info); static int trdev_init(struct net_device *dev); @@ -335,17 +334,6 @@ static void ibmtr_cleanup_card(struct net_device *dev) #endif } -int ibmtr_probe_card(struct net_device *dev) -{ - int err = ibmtr_probe(dev); - if (!err) { - err = register_netdev(dev); - if (err) - ibmtr_cleanup_card(dev); - } - return err; -} - /**************************************************************************** * ibmtr_probe(): Routine specified in the network device structure * to probe for an IBM Token Ring Adapter. Routine outline: @@ -358,7 +346,7 @@ int ibmtr_probe_card(struct net_device *dev) * which references it. ****************************************************************************/ -static int ibmtr_probe(struct net_device *dev) +static int __devinit ibmtr_probe(struct net_device *dev) { int i; int base_addr = dev->base_addr; @@ -378,6 +366,17 @@ static int ibmtr_probe(struct net_device *dev) return -ENODEV; } +int __devinit ibmtr_probe_card(struct net_device *dev) +{ + int err = ibmtr_probe(dev); + if (!err) { + err = register_netdev(dev); + if (err) + ibmtr_cleanup_card(dev); + } + return err; +} + /*****************************************************************************/ static int __devinit ibmtr_probe1(struct net_device *dev, int PIOaddr) diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c index 24a29c99ba9..9aeac76184f 100644 --- a/drivers/net/tulip/dmfe.c +++ b/drivers/net/tulip/dmfe.c @@ -190,13 +190,13 @@ /* Structure/enum declaration ------------------------------- */ struct tx_desc { - u32 tdes0, tdes1, tdes2, tdes3; /* Data for the card */ + __le32 tdes0, tdes1, tdes2, tdes3; /* Data for the card */ char *tx_buf_ptr; /* Data for us */ struct tx_desc *next_tx_desc; } __attribute__(( aligned(32) )); struct rx_desc { - u32 rdes0, rdes1, rdes2, rdes3; /* Data for the card */ + __le32 rdes0, rdes1, rdes2, rdes3; /* Data for the card */ struct sk_buff *rx_skb_ptr; /* Data for us */ struct rx_desc *next_rx_desc; } __attribute__(( aligned(32) )); @@ -458,7 +458,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, /* read 64 word srom data */ for (i = 0; i < 64; i++) - ((u16 *) db->srom)[i] = + ((__le16 *) db->srom)[i] = cpu_to_le16(read_srom_word(db->ioaddr, i)); /* Set Node address */ diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index dab88b958d6..639e1e6913b 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -3607,7 +3607,6 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev) if (bd == ugeth->confBd[txQ]) { if (!netif_queue_stopped(dev)) netif_stop_queue(dev); - return NETDEV_TX_BUSY; } ugeth->txBd[txQ] = bd; @@ -3623,7 +3622,7 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev) spin_unlock_irq(&ugeth->lock); - return NETDEV_TX_OK; + return 0; } static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit) diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index ebbda1d8f54..f3a972e74e9 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -30,8 +30,8 @@ */ #define DRV_NAME "via-rhine" -#define DRV_VERSION "1.4.2" -#define DRV_RELDATE "Sept-11-2006" +#define DRV_VERSION "1.4.3" +#define DRV_RELDATE "2007-03-06" /* A few user-configurable values. @@ -105,6 +105,7 @@ static const int multicast_filter_limit = 32; #include <asm/io.h> #include <asm/irq.h> #include <asm/uaccess.h> +#include <linux/dmi.h> /* These identify the driver base version and may not be removed. */ static char version[] __devinitdata = @@ -1995,6 +1996,23 @@ static struct pci_driver rhine_driver = { .shutdown = rhine_shutdown, }; +static struct dmi_system_id __initdata rhine_dmi_table[] = { + { + .ident = "EPIA-M", + .matches = { + DMI_MATCH(DMI_BIOS_VENDOR, "Award Software International, Inc."), + DMI_MATCH(DMI_BIOS_VERSION, "6.00 PG"), + }, + }, + { + .ident = "KV7", + .matches = { + DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies, LTD"), + DMI_MATCH(DMI_BIOS_VERSION, "6.00 PG"), + }, + }, + { NULL } +}; static int __init rhine_init(void) { @@ -2002,6 +2020,16 @@ static int __init rhine_init(void) #ifdef MODULE printk(version); #endif + if (dmi_check_system(rhine_dmi_table)) { + /* these BIOSes fail at PXE boot if chip is in D3 */ + avoid_D3 = 1; + printk(KERN_WARNING "%s: Broken BIOS detected, avoid_D3 " + "enabled.\n", + DRV_NAME); + } + else if (avoid_D3) + printk(KERN_INFO "%s: avoid_D3 set.\n", DRV_NAME); + return pci_register_driver(&rhine_driver); } diff --git a/drivers/net/wan/lmc/lmc_media.h b/drivers/net/wan/lmc/lmc_media.h deleted file mode 100644 index ddcc0040356..00000000000 --- a/drivers/net/wan/lmc/lmc_media.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef _LMC_MEDIA_H_ -#define _LMC_MEDIA_H_ - -lmc_media_t lmc_ds3_media = { - lmc_ds3_init, /* special media init stuff */ - lmc_ds3_default, /* reset to default state */ - lmc_ds3_set_status, /* reset status to state provided */ - lmc_dummy_set_1, /* set clock source */ - lmc_dummy_set2_1, /* set line speed */ - lmc_ds3_set_100ft, /* set cable length */ - lmc_ds3_set_scram, /* set scrambler */ - lmc_ds3_get_link_status, /* get link status */ - lmc_dummy_set_1, /* set link status */ - lmc_ds3_set_crc_length, /* set CRC length */ - lmc_dummy_set_1, /* set T1 or E1 circuit type */ - lmc_ds3_watchdog -}; - -lmc_media_t lmc_hssi_media = { - lmc_hssi_init, /* special media init stuff */ - lmc_hssi_default, /* reset to default state */ - lmc_hssi_set_status, /* reset status to state provided */ - lmc_hssi_set_clock, /* set clock source */ - lmc_dummy_set2_1, /* set line speed */ - lmc_dummy_set_1, /* set cable length */ - lmc_dummy_set_1, /* set scrambler */ - lmc_hssi_get_link_status, /* get link status */ - lmc_hssi_set_link_status, /* set link status */ - lmc_hssi_set_crc_length, /* set CRC length */ - lmc_dummy_set_1, /* set T1 or E1 circuit type */ - lmc_hssi_watchdog -}; - -lmc_media_t lmc_ssi_media = { lmc_ssi_init, /* special media init stuff */ - lmc_ssi_default, /* reset to default state */ - lmc_ssi_set_status, /* reset status to state provided */ - lmc_ssi_set_clock, /* set clock source */ - lmc_ssi_set_speed, /* set line speed */ - lmc_dummy_set_1, /* set cable length */ - lmc_dummy_set_1, /* set scrambler */ - lmc_ssi_get_link_status, /* get link status */ - lmc_ssi_set_link_status, /* set link status */ - lmc_ssi_set_crc_length, /* set CRC length */ - lmc_dummy_set_1, /* set T1 or E1 circuit type */ - lmc_ssi_watchdog -}; - -lmc_media_t lmc_t1_media = { - lmc_t1_init, /* special media init stuff */ - lmc_t1_default, /* reset to default state */ - lmc_t1_set_status, /* reset status to state provided */ - lmc_t1_set_clock, /* set clock source */ - lmc_dummy_set2_1, /* set line speed */ - lmc_dummy_set_1, /* set cable length */ - lmc_dummy_set_1, /* set scrambler */ - lmc_t1_get_link_status, /* get link status */ - lmc_dummy_set_1, /* set link status */ - lmc_t1_set_crc_length, /* set CRC length */ - lmc_t1_set_circuit_type, /* set T1 or E1 circuit type */ - lmc_t1_watchdog -}; - - -#endif - diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c index 8dbcf83bb5f..8b4540bfc1b 100644 --- a/drivers/net/wan/z85230.c +++ b/drivers/net/wan/z85230.c @@ -407,7 +407,7 @@ static void z8530_tx(struct z8530_channel *c) while(c->txcount) { /* FIFO full ? */ if(!(read_zsreg(c, R0)&4)) - break; + return; c->txcount--; /* * Shovel out the byte diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index a8c2bfe26c2..2ada76a93cb 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -2852,7 +2852,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, if (rc) { airo_print_err(dev->name, "register interrupt %d failed, rc %d", irq, rc); - goto err_out_unlink; + goto err_out_nets; } if (!is_pcmcia) { if (!request_region( dev->base_addr, 64, dev->name )) { @@ -2935,6 +2935,8 @@ err_out_res: release_region( dev->base_addr, 64 ); err_out_irq: free_irq(dev->irq, dev); +err_out_nets: + airo_networks_free(ai); err_out_unlink: del_airo_dev(dev); err_out_thr: diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index e594af46ff0..a38e7eec0e6 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -946,6 +946,7 @@ static int bcm43xx_geo_init(struct bcm43xx_private *bcm) u8 channel; struct bcm43xx_phyinfo *phy; const char *iso_country; + u8 max_bg_channel; geo = kzalloc(sizeof(*geo), GFP_KERNEL); if (!geo) @@ -967,6 +968,23 @@ static int bcm43xx_geo_init(struct bcm43xx_private *bcm) } iso_country = bcm43xx_locale_iso(bcm->sprom.locale); +/* set the maximum channel based on locale set in sprom or witle locale option */ + switch (bcm->sprom.locale) { + case BCM43xx_LOCALE_THAILAND: + case BCM43xx_LOCALE_ISRAEL: + case BCM43xx_LOCALE_JORDAN: + case BCM43xx_LOCALE_USA_CANADA_ANZ: + case BCM43xx_LOCALE_USA_LOW: + max_bg_channel = 11; + break; + case BCM43xx_LOCALE_JAPAN: + case BCM43xx_LOCALE_JAPAN_HIGH: + max_bg_channel = 14; + break; + default: + max_bg_channel = 13; + } + if (have_a) { for (i = 0, channel = IEEE80211_52GHZ_MIN_CHANNEL; channel <= IEEE80211_52GHZ_MAX_CHANNEL; channel++) { @@ -978,7 +996,7 @@ static int bcm43xx_geo_init(struct bcm43xx_private *bcm) } if (have_bg) { for (i = 0, channel = IEEE80211_24GHZ_MIN_CHANNEL; - channel <= IEEE80211_24GHZ_MAX_CHANNEL; channel++) { + channel <= max_bg_channel; channel++) { chan = &geo->bg[i++]; chan->freq = bcm43xx_channel_to_freq_bg(channel); chan->channel = channel; @@ -1858,9 +1876,6 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id) spin_lock(&bcm->irq_lock); - assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); - assert(bcm->current_core->id == BCM43xx_COREID_80211); - reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); if (reason == 0xffffffff) { /* irq not for us (shared irq) */ @@ -1871,6 +1886,9 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id) if (!reason) goto out; + assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); + assert(bcm->current_core->id == BCM43xx_COREID_80211); + bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA0_REASON) & 0x0001DC00; bcm->dma_reason[1] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index 3a5c9c2b215..72529a440f1 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -757,7 +757,7 @@ static void bcm43xx_phy_initb5(struct bcm43xx_private *bcm) if (radio->version == 0x2050) bcm43xx_phy_write(bcm, 0x0038, 0x0667); - if (phy->type == BCM43xx_PHYTYPE_G) { + if (phy->connected) { if (radio->version == 0x2050) { bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) @@ -859,6 +859,11 @@ static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm) bcm43xx_radio_write16(bcm, 0x005D, 0x0088); bcm43xx_radio_write16(bcm, 0x005E, 0x0088); bcm43xx_radio_write16(bcm, 0x007D, 0x0088); + bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET, + (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET) + | 0x00000200)); } if (radio->revision == 8) { bcm43xx_radio_write16(bcm, 0x0051, 0x0000); @@ -941,7 +946,8 @@ static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x0038, 0x0668); bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF); if (radio->revision <= 5) - bcm43xx_phy_write(bcm, 0x005D, bcm43xx_phy_read(bcm, 0x005D) | 0x0003); + bcm43xx_phy_write(bcm, 0x005D, (bcm43xx_phy_read(bcm, 0x005D) + & 0xFF80) | 0x0003); if (radio->revision <= 2) bcm43xx_radio_write16(bcm, 0x005D, 0x000D); @@ -958,7 +964,7 @@ static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x0016, 0x0410); bcm43xx_phy_write(bcm, 0x0017, 0x0820); bcm43xx_phy_write(bcm, 0x0062, 0x0007); - (void) bcm43xx_radio_calibrationvalue(bcm); + bcm43xx_radio_init2050(bcm); bcm43xx_phy_lo_g_measure(bcm); if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) { bcm43xx_calc_nrssi_slope(bcm); @@ -972,7 +978,7 @@ static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm) { struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 backup_phy[15]; + u16 backup_phy[15] = {0}; u16 backup_radio[3]; u16 backup_bband; u16 i; @@ -983,8 +989,10 @@ static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm) backup_phy[1] = bcm43xx_phy_read(bcm, 0x0001); backup_phy[2] = bcm43xx_phy_read(bcm, 0x0811); backup_phy[3] = bcm43xx_phy_read(bcm, 0x0812); - backup_phy[4] = bcm43xx_phy_read(bcm, 0x0814); - backup_phy[5] = bcm43xx_phy_read(bcm, 0x0815); + if (phy->rev != 1) { + backup_phy[4] = bcm43xx_phy_read(bcm, 0x0814); + backup_phy[5] = bcm43xx_phy_read(bcm, 0x0815); + } backup_phy[6] = bcm43xx_phy_read(bcm, 0x005A); backup_phy[7] = bcm43xx_phy_read(bcm, 0x0059); backup_phy[8] = bcm43xx_phy_read(bcm, 0x0058); @@ -1012,14 +1020,16 @@ static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm) bcm43xx_phy_read(bcm, 0x0811) | 0x0001); bcm43xx_phy_write(bcm, 0x0812, bcm43xx_phy_read(bcm, 0x0812) & 0xFFFE); - bcm43xx_phy_write(bcm, 0x0814, - bcm43xx_phy_read(bcm, 0x0814) | 0x0001); - bcm43xx_phy_write(bcm, 0x0815, - bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE); - bcm43xx_phy_write(bcm, 0x0814, - bcm43xx_phy_read(bcm, 0x0814) | 0x0002); - bcm43xx_phy_write(bcm, 0x0815, - bcm43xx_phy_read(bcm, 0x0815) & 0xFFFD); + if (phy->rev != 1) { + bcm43xx_phy_write(bcm, 0x0814, + bcm43xx_phy_read(bcm, 0x0814) | 0x0001); + bcm43xx_phy_write(bcm, 0x0815, + bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE); + bcm43xx_phy_write(bcm, 0x0814, + bcm43xx_phy_read(bcm, 0x0814) | 0x0002); + bcm43xx_phy_write(bcm, 0x0815, + bcm43xx_phy_read(bcm, 0x0815) & 0xFFFD); + } bcm43xx_phy_write(bcm, 0x0811, bcm43xx_phy_read(bcm, 0x0811) | 0x000C); bcm43xx_phy_write(bcm, 0x0812, @@ -1042,10 +1052,12 @@ static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm) bcm43xx_phy_read(bcm, 0x000A) | 0x2000); } - bcm43xx_phy_write(bcm, 0x0814, - bcm43xx_phy_read(bcm, 0x0814) | 0x0004); - bcm43xx_phy_write(bcm, 0x0815, - bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB); + if (phy->rev != 1) { + bcm43xx_phy_write(bcm, 0x0814, + bcm43xx_phy_read(bcm, 0x0814) | 0x0004); + bcm43xx_phy_write(bcm, 0x0815, + bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB); + } bcm43xx_phy_write(bcm, 0x0003, (bcm43xx_phy_read(bcm, 0x0003) & 0xFF9F) | 0x0040); @@ -1132,8 +1144,10 @@ static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm) } } - bcm43xx_phy_write(bcm, 0x0814, backup_phy[4]); - bcm43xx_phy_write(bcm, 0x0815, backup_phy[5]); + if (phy->rev != 1) { + bcm43xx_phy_write(bcm, 0x0814, backup_phy[4]); + bcm43xx_phy_write(bcm, 0x0815, backup_phy[5]); + } bcm43xx_phy_write(bcm, 0x005A, backup_phy[6]); bcm43xx_phy_write(bcm, 0x0059, backup_phy[7]); bcm43xx_phy_write(bcm, 0x0058, backup_phy[8]); @@ -1182,24 +1196,23 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x0811, 0x0000); bcm43xx_phy_write(bcm, 0x0015, 0x00C0); } - if (phy->rev >= 3) { + if (phy->rev > 5) { bcm43xx_phy_write(bcm, 0x0811, 0x0400); bcm43xx_phy_write(bcm, 0x0015, 0x00C0); } - if (phy->connected) { + if (phy->rev >= 2 && phy->connected) { tmp = bcm43xx_phy_read(bcm, 0x0400) & 0xFF; - if (tmp < 6) { + if (tmp ==3 || tmp == 5) { bcm43xx_phy_write(bcm, 0x04C2, 0x1816); bcm43xx_phy_write(bcm, 0x04C3, 0x8006); - if (tmp != 3) { + if (tmp == 5) { bcm43xx_phy_write(bcm, 0x04CC, (bcm43xx_phy_read(bcm, 0x04CC) & 0x00FF) | 0x1F00); } } - } - if (phy->rev < 3 && phy->connected) bcm43xx_phy_write(bcm, 0x047E, 0x0078); + } if (radio->revision == 8) { bcm43xx_phy_write(bcm, 0x0801, bcm43xx_phy_read(bcm, 0x0801) | 0x0080); bcm43xx_phy_write(bcm, 0x043E, bcm43xx_phy_read(bcm, 0x043E) | 0x0004); @@ -1226,7 +1239,7 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) if (phy->rev >= 6) { bcm43xx_phy_write(bcm, 0x0036, (bcm43xx_phy_read(bcm, 0x0036) - & 0xF000) | (radio->txctl2 << 12)); + & 0x0FFF) | (radio->txctl2 << 12)); } if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) bcm43xx_phy_write(bcm, 0x002E, 0x8075); @@ -1237,7 +1250,7 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) else bcm43xx_phy_write(bcm, 0x002F, 0x0202); } - if (phy->connected) { + if (phy->connected || phy->rev >= 2) { bcm43xx_phy_lo_adjust(bcm, 0); bcm43xx_phy_write(bcm, 0x080F, 0x8078); } @@ -1251,7 +1264,7 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) */ bcm43xx_nrssi_hw_update(bcm, 0xFFFF); bcm43xx_calc_nrssi_threshold(bcm); - } else if (phy->connected) { + } else if (phy->connected || phy->rev >= 2) { if (radio->nrssi[0] == -1000) { assert(radio->nrssi[1] == -1000); bcm43xx_calc_nrssi_slope(bcm); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c index 32beb91b716..4025dd0089d 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c @@ -458,7 +458,7 @@ static void bcm43xx_calc_nrssi_offset(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x005A, 0x0480); bcm43xx_phy_write(bcm, 0x0059, 0x0810); bcm43xx_phy_write(bcm, 0x0058, 0x000D); - if (phy->rev == 0) { + if (phy->analog == 0) { bcm43xx_phy_write(bcm, 0x0003, 0x0122); } else { bcm43xx_phy_write(bcm, 0x000A, @@ -570,9 +570,9 @@ void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm) nrssi0 = (s16)bcm43xx_phy_read(bcm, 0x0027); bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) & 0x007F); - if (phy->rev >= 2) { + if (phy->analog >= 2) { bcm43xx_write16(bcm, 0x03E6, 0x0040); - } else if (phy->rev == 0) { + } else if (phy->analog == 0) { bcm43xx_write16(bcm, 0x03E6, 0x0122); } else { bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, @@ -596,7 +596,7 @@ void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x0015, backup[5]); bcm43xx_phy_write(bcm, 0x002A, backup[6]); bcm43xx_synth_pu_workaround(bcm, radio->channel); - if (phy->rev != 0) + if (phy->analog != 0) bcm43xx_write16(bcm, 0x03F4, backup[13]); bcm43xx_phy_write(bcm, 0x0020, backup[7]); @@ -692,7 +692,7 @@ void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm) bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) & 0x007F); - if (phy->rev >= 2) { + if (phy->analog >= 2) { bcm43xx_phy_write(bcm, 0x0003, (bcm43xx_phy_read(bcm, 0x0003) & 0xFF9F) | 0x0040); @@ -882,10 +882,10 @@ static void _stack_save(u32 *_stackptr, size_t *stackidx, { u32 *stackptr = &(_stackptr[*stackidx]); - assert((offset & 0xF000) == 0x0000); - assert((id & 0xF0) == 0x00); + assert((offset & 0xE000) == 0x0000); + assert((id & 0xF8) == 0x00); *stackptr = offset; - *stackptr |= ((u32)id) << 12; + *stackptr |= ((u32)id) << 13; *stackptr |= ((u32)value) << 16; (*stackidx)++; assert(*stackidx < BCM43xx_INTERFSTACK_SIZE); @@ -896,12 +896,12 @@ static u16 _stack_restore(u32 *stackptr, { size_t i; - assert((offset & 0xF000) == 0x0000); - assert((id & 0xF0) == 0x00); + assert((offset & 0xE000) == 0x0000); + assert((id & 0xF8) == 0x00); for (i = 0; i < BCM43xx_INTERFSTACK_SIZE; i++, stackptr++) { - if ((*stackptr & 0x00000FFF) != offset) + if ((*stackptr & 0x00001FFF) != offset) continue; - if (((*stackptr & 0x0000F000) >> 12) != id) + if (((*stackptr & 0x00007000) >> 13) != id) continue; return ((*stackptr & 0xFFFF0000) >> 16); } @@ -1579,7 +1579,7 @@ void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm) for (i = 0; i < 5; i++) { for (j = 0; j < 5; j++) { - if (tmp == (data_high[i] << 4 | data_low[j])) { + if (tmp == (data_high[i] | data_low[j])) { bcm43xx_phy_write(bcm, 0x0069, (i - j) << 8 | 0x00C0); return; } diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index 7b665e2386a..d6d9413d7f2 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -105,18 +105,24 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; u8 channel; + s8 expon; int freq; int err = -EINVAL; mutex_lock(&bcm->mutex); spin_lock_irqsave(&bcm->irq_lock, flags); - if ((data->freq.m >= 0) && (data->freq.m <= 1000)) { + if ((data->freq.e == 0) && + (data->freq.m >= 0) && (data->freq.m <= 1000)) { channel = data->freq.m; freq = bcm43xx_channel_to_freq(bcm, channel); } else { - channel = bcm43xx_freq_to_channel(bcm, data->freq.m); freq = data->freq.m; + expon = 6 - data->freq.e; + while (--expon >= 0) /* scale down the frequency to MHz */ + freq /= 10; + assert(freq > 1000); + channel = bcm43xx_freq_to_channel(bcm, freq); } if (!ieee80211_is_valid_channel(bcm->ieee, channel)) goto out_unlock; diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index 9c64f894b71..87ee3ee020f 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c @@ -337,6 +337,7 @@ static int read_pod(struct zd_chip *chip, u8 *rf_type) chip->patch_cr157 = (value >> 13) & 0x1; chip->patch_6m_band_edge = (value >> 21) & 0x1; chip->new_phy_layout = (value >> 31) & 0x1; + chip->al2230s_bit = (value >> 7) & 0x1; chip->link_led = ((value >> 4) & 1) ? LED1 : LED2; chip->supports_tx_led = 1; if (value & (1 << 24)) { /* LED scenario */ @@ -591,16 +592,16 @@ int zd_chip_unlock_phy_regs(struct zd_chip *chip) return r; } -/* CR157 can be optionally patched by the EEPROM */ +/* CR157 can be optionally patched by the EEPROM for original ZD1211 */ static int patch_cr157(struct zd_chip *chip) { int r; - u32 value; + u16 value; if (!chip->patch_cr157) return 0; - r = zd_ioread32_locked(chip, &value, E2P_PHY_REG); + r = zd_ioread16_locked(chip, &value, E2P_PHY_REG); if (r) return r; @@ -790,11 +791,6 @@ static int zd1211b_hw_reset_phy(struct zd_chip *chip) goto out; r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); - if (r) - goto unlock; - - r = patch_cr157(chip); -unlock: t = zd_chip_unlock_phy_regs(chip); if (t && !r) r = t; diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h index b07569e391e..e57ed75d942 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/drivers/net/wireless/zd1211rw/zd_chip.h @@ -641,8 +641,8 @@ enum { * also only 11 channels. */ #define E2P_ALLOWED_CHANNEL E2P_DATA(0x18) -#define E2P_PHY_REG E2P_DATA(0x1a) #define E2P_DEVICE_VER E2P_DATA(0x20) +#define E2P_PHY_REG E2P_DATA(0x25) #define E2P_36M_CAL_VALUE1 E2P_DATA(0x28) #define E2P_36M_CAL_VALUE2 E2P_DATA(0x2a) #define E2P_36M_CAL_VALUE3 E2P_DATA(0x2c) @@ -711,7 +711,7 @@ struct zd_chip { u16 link_led; unsigned int pa_type:4, patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1, - new_phy_layout:1, + new_phy_layout:1, al2230s_bit:1, is_zd1211b:1, supports_tx_led:1; }; diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c index 25323a13a3d..5235a7827ac 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c +++ b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c @@ -358,6 +358,12 @@ int zd_rf_init_al2230(struct zd_rf *rf) { struct zd_chip *chip = zd_rf_to_chip(rf); + if (chip->al2230s_bit) { + dev_err(zd_chip_dev(chip), "AL2230S devices are not yet " + "supported by this driver.\n"); + return -ENODEV; + } + rf->switch_radio_off = al2230_switch_radio_off; if (chip->is_zd1211b) { rf->init_hw = zd1211b_al2230_init_hw; diff --git a/drivers/oprofile/event_buffer.c b/drivers/oprofile/event_buffer.c index 00e937e9240..e7fbac52993 100644 --- a/drivers/oprofile/event_buffer.c +++ b/drivers/oprofile/event_buffer.c @@ -70,11 +70,12 @@ void wake_up_buffer_waiter(void) int alloc_event_buffer(void) { int err = -ENOMEM; + unsigned long flags; - spin_lock(&oprofilefs_lock); + spin_lock_irqsave(&oprofilefs_lock, flags); buffer_size = fs_buffer_size; buffer_watershed = fs_buffer_watershed; - spin_unlock(&oprofilefs_lock); + spin_unlock_irqrestore(&oprofilefs_lock, flags); if (buffer_watershed >= buffer_size) return -EINVAL; diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c index 6e67b42ca46..8543cb26cf3 100644 --- a/drivers/oprofile/oprofilefs.c +++ b/drivers/oprofile/oprofilefs.c @@ -65,6 +65,7 @@ ssize_t oprofilefs_ulong_to_user(unsigned long val, char __user * buf, size_t co int oprofilefs_ulong_from_user(unsigned long * val, char const __user * buf, size_t count) { char tmpbuf[TMPBUFSIZE]; + unsigned long flags; if (!count) return 0; @@ -77,9 +78,9 @@ int oprofilefs_ulong_from_user(unsigned long * val, char const __user * buf, siz if (copy_from_user(tmpbuf, buf, count)) return -EFAULT; - spin_lock(&oprofilefs_lock); + spin_lock_irqsave(&oprofilefs_lock, flags); *val = simple_strtoul(tmpbuf, NULL, 0); - spin_unlock(&oprofilefs_lock); + spin_unlock_irqrestore(&oprofilefs_lock, flags); return 0; } diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 01869b1782e..435c1958a7b 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -94,12 +94,14 @@ static void msi_set_mask_bit(unsigned int irq, int flag) int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET; writel(flag, entry->mask_base + offset); + readl(entry->mask_base + offset); break; } default: BUG(); break; } + entry->msi_attrib.masked = !!flag; } void read_msi_msg(unsigned int irq, struct msi_msg *msg) @@ -179,6 +181,7 @@ void write_msi_msg(unsigned int irq, struct msi_msg *msg) default: BUG(); } + entry->msg = *msg; } void mask_msi_irq(unsigned int irq) @@ -225,164 +228,60 @@ static struct msi_desc* alloc_msi_entry(void) } #ifdef CONFIG_PM -static int __pci_save_msi_state(struct pci_dev *dev) -{ - int pos, i = 0; - u16 control; - struct pci_cap_saved_state *save_state; - u32 *cap; - - if (!dev->msi_enabled) - return 0; - - pos = pci_find_capability(dev, PCI_CAP_ID_MSI); - if (pos <= 0) - return 0; - - save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u32) * 5, - GFP_KERNEL); - if (!save_state) { - printk(KERN_ERR "Out of memory in pci_save_msi_state\n"); - return -ENOMEM; - } - cap = &save_state->data[0]; - - pci_read_config_dword(dev, pos, &cap[i++]); - control = cap[0] >> 16; - pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, &cap[i++]); - if (control & PCI_MSI_FLAGS_64BIT) { - pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, &cap[i++]); - pci_read_config_dword(dev, pos + PCI_MSI_DATA_64, &cap[i++]); - } else - pci_read_config_dword(dev, pos + PCI_MSI_DATA_32, &cap[i++]); - if (control & PCI_MSI_FLAGS_MASKBIT) - pci_read_config_dword(dev, pos + PCI_MSI_MASK_BIT, &cap[i++]); - save_state->cap_nr = PCI_CAP_ID_MSI; - pci_add_saved_cap(dev, save_state); - return 0; -} - static void __pci_restore_msi_state(struct pci_dev *dev) { - int i = 0, pos; + int pos; u16 control; - struct pci_cap_saved_state *save_state; - u32 *cap; + struct msi_desc *entry; if (!dev->msi_enabled) return; - save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSI); - pos = pci_find_capability(dev, PCI_CAP_ID_MSI); - if (!save_state || pos <= 0) - return; - cap = &save_state->data[0]; + entry = get_irq_msi(dev->irq); + pos = entry->msi_attrib.pos; pci_intx(dev, 0); /* disable intx */ - control = cap[i++] >> 16; msi_set_enable(dev, 0); - pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, cap[i++]); - if (control & PCI_MSI_FLAGS_64BIT) { - pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, cap[i++]); - pci_write_config_dword(dev, pos + PCI_MSI_DATA_64, cap[i++]); - } else - pci_write_config_dword(dev, pos + PCI_MSI_DATA_32, cap[i++]); - if (control & PCI_MSI_FLAGS_MASKBIT) - pci_write_config_dword(dev, pos + PCI_MSI_MASK_BIT, cap[i++]); + write_msi_msg(dev->irq, &entry->msg); + if (entry->msi_attrib.maskbit) + msi_set_mask_bit(dev->irq, entry->msi_attrib.masked); + + pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control); + control &= ~(PCI_MSI_FLAGS_QSIZE | PCI_MSI_FLAGS_ENABLE); + if (entry->msi_attrib.maskbit || !entry->msi_attrib.masked) + control |= PCI_MSI_FLAGS_ENABLE; pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); - pci_remove_saved_cap(save_state); - kfree(save_state); -} - -static int __pci_save_msix_state(struct pci_dev *dev) -{ - int pos; - int irq, head, tail = 0; - u16 control; - struct pci_cap_saved_state *save_state; - - if (!dev->msix_enabled) - return 0; - - pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); - if (pos <= 0) - return 0; - - /* save the capability */ - pci_read_config_word(dev, msi_control_reg(pos), &control); - save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u16), - GFP_KERNEL); - if (!save_state) { - printk(KERN_ERR "Out of memory in pci_save_msix_state\n"); - return -ENOMEM; - } - *((u16 *)&save_state->data[0]) = control; - - /* save the table */ - irq = head = dev->first_msi_irq; - while (head != tail) { - struct msi_desc *entry; - - entry = get_irq_msi(irq); - read_msi_msg(irq, &entry->msg_save); - - tail = entry->link.tail; - irq = tail; - } - - save_state->cap_nr = PCI_CAP_ID_MSIX; - pci_add_saved_cap(dev, save_state); - return 0; -} - -int pci_save_msi_state(struct pci_dev *dev) -{ - int rc; - - rc = __pci_save_msi_state(dev); - if (rc) - return rc; - - rc = __pci_save_msix_state(dev); - - return rc; } static void __pci_restore_msix_state(struct pci_dev *dev) { - u16 save; int pos; int irq, head, tail = 0; struct msi_desc *entry; - struct pci_cap_saved_state *save_state; + u16 control; if (!dev->msix_enabled) return; - save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSIX); - if (!save_state) - return; - save = *((u16 *)&save_state->data[0]); - pci_remove_saved_cap(save_state); - kfree(save_state); - - pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); - if (pos <= 0) - return; - /* route the table */ pci_intx(dev, 0); /* disable intx */ msix_set_enable(dev, 0); irq = head = dev->first_msi_irq; + entry = get_irq_msi(irq); + pos = entry->msi_attrib.pos; while (head != tail) { entry = get_irq_msi(irq); - write_msi_msg(irq, &entry->msg_save); + write_msi_msg(irq, &entry->msg); + msi_set_mask_bit(irq, entry->msi_attrib.masked); tail = entry->link.tail; irq = tail; } - pci_write_config_word(dev, msi_control_reg(pos), save); + pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control); + control &= ~PCI_MSIX_FLAGS_MASKALL; + control |= PCI_MSIX_FLAGS_ENABLE; + pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control); } void pci_restore_msi_state(struct pci_dev *dev) @@ -420,6 +319,7 @@ static int msi_capability_init(struct pci_dev *dev) entry->msi_attrib.is_64 = is_64bit_address(control); entry->msi_attrib.entry_nr = 0; entry->msi_attrib.maskbit = is_mask_bit_support(control); + entry->msi_attrib.masked = 1; entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */ entry->msi_attrib.pos = pos; if (is_mask_bit_support(control)) { @@ -507,6 +407,7 @@ static int msix_capability_init(struct pci_dev *dev, entry->msi_attrib.is_64 = 1; entry->msi_attrib.entry_nr = j; entry->msi_attrib.maskbit = 1; + entry->msi_attrib.masked = 1; entry->msi_attrib.default_irq = dev->irq; entry->msi_attrib.pos = pos; entry->dev = dev; diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index df495300ce3..d3eab057b2d 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -551,7 +551,9 @@ static int pci_save_pcie_state(struct pci_dev *dev) if (pos <= 0) return 0; - save_state = kzalloc(sizeof(*save_state) + sizeof(u16) * 4, GFP_KERNEL); + save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP); + if (!save_state) + save_state = kzalloc(sizeof(*save_state) + sizeof(u16) * 4, GFP_KERNEL); if (!save_state) { dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n"); return -ENOMEM; @@ -582,8 +584,6 @@ static void pci_restore_pcie_state(struct pci_dev *dev) pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, cap[i++]); pci_write_config_word(dev, pos + PCI_EXP_SLTCTL, cap[i++]); pci_write_config_word(dev, pos + PCI_EXP_RTCTL, cap[i++]); - pci_remove_saved_cap(save_state); - kfree(save_state); } @@ -597,7 +597,9 @@ static int pci_save_pcix_state(struct pci_dev *dev) if (pos <= 0) return 0; - save_state = kzalloc(sizeof(*save_state) + sizeof(u16), GFP_KERNEL); + save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP); + if (!save_state) + save_state = kzalloc(sizeof(*save_state) + sizeof(u16), GFP_KERNEL); if (!save_state) { dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n"); return -ENOMEM; @@ -622,8 +624,6 @@ static void pci_restore_pcix_state(struct pci_dev *dev) cap = (u16 *)&save_state->data[0]; pci_write_config_word(dev, pos + PCI_X_CMD, cap[i++]); - pci_remove_saved_cap(save_state); - kfree(save_state); } @@ -638,8 +638,6 @@ pci_save_state(struct pci_dev *dev) /* XXX: 100% dword access ok here? */ for (i = 0; i < 16; i++) pci_read_config_dword(dev, i * 4,&dev->saved_config_space[i]); - if ((i = pci_save_msi_state(dev)) != 0) - return i; if ((i = pci_save_pcie_state(dev)) != 0) return i; if ((i = pci_save_pcix_state(dev)) != 0) @@ -757,7 +755,8 @@ int pci_enable_device(struct pci_dev *dev) * when a device is enabled using managed PCI device enable interface. */ struct pci_devres { - unsigned int disable:1; + unsigned int enabled:1; + unsigned int pinned:1; unsigned int orig_intx:1; unsigned int restore_intx:1; u32 region_mask; @@ -781,7 +780,7 @@ static void pcim_release(struct device *gendev, void *res) if (this->restore_intx) pci_intx(dev, this->orig_intx); - if (this->disable) + if (this->enabled && !this->pinned) pci_disable_device(dev); } @@ -820,12 +819,12 @@ int pcim_enable_device(struct pci_dev *pdev) dr = get_pci_dr(pdev); if (unlikely(!dr)) return -ENOMEM; - WARN_ON(!!dr->disable); + WARN_ON(!!dr->enabled); rc = pci_enable_device(pdev); if (!rc) { pdev->is_managed = 1; - dr->disable = 1; + dr->enabled = 1; } return rc; } @@ -843,9 +842,9 @@ void pcim_pin_device(struct pci_dev *pdev) struct pci_devres *dr; dr = find_pci_dr(pdev); - WARN_ON(!dr || !dr->disable); + WARN_ON(!dr || !dr->enabled); if (dr) - dr->disable = 0; + dr->pinned = 1; } /** @@ -876,7 +875,7 @@ pci_disable_device(struct pci_dev *dev) dr = find_pci_dr(dev); if (dr) - dr->disable = 0; + dr->enabled = 0; if (atomic_sub_return(1, &dev->enable_cnt) != 0) return; diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index ae7a975995a..62ea04c8af6 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -52,10 +52,8 @@ static inline void pci_no_msi(void) { } #endif #if defined(CONFIG_PCI_MSI) && defined(CONFIG_PM) -int pci_save_msi_state(struct pci_dev *dev); void pci_restore_msi_state(struct pci_dev *dev); #else -static inline int pci_save_msi_state(struct pci_dev *dev) { return 0; } static inline void pci_restore_msi_state(struct pci_dev *dev) {} #endif diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c index b164de050d4..db6ad8e763a 100644 --- a/drivers/pci/pcie/aer/aerdrv.c +++ b/drivers/pci/pcie/aer/aerdrv.c @@ -66,7 +66,7 @@ static struct pci_error_handlers aer_error_handlers = { .resume = aer_error_resume, }; -static struct pcie_port_service_driver aerdrv = { +static struct pcie_port_service_driver aerdriver = { .name = "aer", .id_table = &aer_id[0], @@ -328,7 +328,7 @@ static void aer_error_resume(struct pci_dev *dev) **/ static int __init aer_service_init(void) { - return pcie_port_service_register(&aerdrv); + return pcie_port_service_register(&aerdriver); } /** @@ -338,7 +338,7 @@ static int __init aer_service_init(void) **/ static void __exit aer_service_exit(void) { - pcie_port_service_unregister(&aerdrv); + pcie_port_service_unregister(&aerdriver); } module_init(aer_service_init); diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index f17e7ed2b2a..df383645e36 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -93,7 +93,7 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev, if (!dev->irq && dev->pin) { printk(KERN_WARNING "%s->Dev[%04x:%04x] has invalid IRQ. Check vendor BIOS\n", - __FUNCTION__, dev->device, dev->vendor); + __FUNCTION__, dev->vendor, dev->device); } if (pcie_port_device_register(dev)) { pci_disable_device(dev); @@ -276,7 +276,7 @@ static struct pci_error_handlers pcie_portdrv_err_handler = { .resume = pcie_portdrv_err_resume, }; -static struct pci_driver pcie_portdrv = { +static struct pci_driver pcie_portdriver = { .name = (char *)device_name, .id_table = &port_pci_ids[0], @@ -298,7 +298,7 @@ static int __init pcie_portdrv_init(void) printk(KERN_WARNING "PCIE: bus_register error: %d\n", retval); goto out; } - retval = pci_register_driver(&pcie_portdrv); + retval = pci_register_driver(&pcie_portdriver); if (retval) pcie_port_bus_unregister(); out: @@ -307,7 +307,7 @@ static int __init pcie_portdrv_init(void) static void __exit pcie_portdrv_exit(void) { - pci_unregister_driver(&pcie_portdrv); + pci_unregister_driver(&pcie_portdriver); pcie_port_bus_unregister(); } diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 7f94fc098cd..65d6f23ead4 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -963,6 +963,13 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, k8t_sound_ho * bridge. Unfortunately, this device has no subvendor/subdevice ID. So it * becomes necessary to do this tweak in two steps -- I've chosen the Host * bridge as trigger. + * + * Note that we used to unhide the SMBus that way on Toshiba laptops + * (Satellite A40 and Tecra M2) but then found that the thermal management + * was done by SMM code, which could cause unsynchronized concurrent + * accesses to the SMBus registers, with potentially bad effects. Thus you + * should be very careful when adding new entries: if SMM is accessing the + * Intel SMBus, this is a very good reason to leave it hidden. */ static int asus_hides_smbus; @@ -1040,17 +1047,6 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev) case 0x099c: /* HP Compaq nx6110 */ asus_hides_smbus = 1; } - } else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_TOSHIBA)) { - if (dev->device == PCI_DEVICE_ID_INTEL_82855GM_HB) - switch(dev->subsystem_device) { - case 0x0001: /* Toshiba Satellite A40 */ - asus_hides_smbus = 1; - } - else if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB) - switch(dev->subsystem_device) { - case 0x0001: /* Toshiba Tecra M2 */ - asus_hides_smbus = 1; - } } else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG)) { if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB) switch(dev->subsystem_device) { diff --git a/drivers/pci/search.c b/drivers/pci/search.c index ff98eaddaa7..2dd8681d6b3 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -15,7 +15,7 @@ DECLARE_RWSEM(pci_bus_sem); -static struct pci_bus * __devinit +static struct pci_bus * pci_do_find_bus(struct pci_bus* bus, unsigned char busnr) { struct pci_bus* child; diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c index 551bde5d943..b693367d38c 100644 --- a/drivers/pcmcia/au1000_generic.c +++ b/drivers/pcmcia/au1000_generic.c @@ -372,7 +372,7 @@ int au1x00_pcmcia_socket_probe(struct device *dev, struct pcmcia_low_level *ops, skt->socket.resource_ops = &pccard_static_ops; skt->socket.ops = &au1x00_pcmcia_operations; skt->socket.owner = ops->owner; - skt->socket.dev.dev = dev; + skt->socket.dev.parent = dev; init_timer(&skt->poll_timer); skt->poll_timer.function = au1x00_pcmcia_poll_event; diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c index d77f75129f8..2df216b0081 100644 --- a/drivers/pcmcia/omap_cf.c +++ b/drivers/pcmcia/omap_cf.c @@ -202,15 +202,14 @@ static struct pccard_operations omap_cf_ops = { * "what chipselect is used". Boards could want more. */ -static int __devinit omap_cf_probe(struct device *dev) +static int __init omap_cf_probe(struct platform_device *pdev) { unsigned seg; struct omap_cf_socket *cf; - struct platform_device *pdev = to_platform_device(dev); int irq; int status; - seg = (int) dev->platform_data; + seg = (int) pdev->dev.platform_data; if (seg == 0 || seg > 3) return -ENODEV; @@ -227,7 +226,7 @@ static int __devinit omap_cf_probe(struct device *dev) cf->timer.data = (unsigned long) cf; cf->pdev = pdev; - dev_set_drvdata(dev, cf); + platform_set_drvdata(pdev, cf); /* this primarily just shuts up irq handling noise */ status = request_irq(irq, omap_cf_irq, IRQF_SHARED, @@ -291,7 +290,7 @@ static int __devinit omap_cf_probe(struct device *dev) omap_cf_present() ? "present" : "(not present)"); cf->socket.owner = THIS_MODULE; - cf->socket.dev.parent = dev; + cf->socket.dev.parent = &pdev->dev; cf->socket.ops = &omap_cf_ops; cf->socket.resource_ops = &pccard_static_ops; cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP @@ -318,9 +317,9 @@ fail0: return status; } -static int __devexit omap_cf_remove(struct device *dev) +static int __exit omap_cf_remove(struct platform_device *pdev) { - struct omap_cf_socket *cf = dev_get_drvdata(dev); + struct omap_cf_socket *cf = platform_get_drvdata(pdev); cf->active = 0; pcmcia_unregister_socket(&cf->socket); @@ -332,26 +331,36 @@ static int __devexit omap_cf_remove(struct device *dev) return 0; } -static struct device_driver omap_cf_driver = { - .name = (char *) driver_name, - .bus = &platform_bus_type, - .probe = omap_cf_probe, - .remove = __devexit_p(omap_cf_remove), - .suspend = pcmcia_socket_dev_suspend, - .resume = pcmcia_socket_dev_resume, +static int omap_cf_suspend(struct platform_device *pdev, pm_message_t mesg) +{ + return pcmcia_socket_dev_suspend(&pdev->dev, mesg); +} + +static int omap_cf_resume(struct platform_device *pdev) +{ + return pcmcia_socket_dev_resume(&pdev->dev); +} + +static struct platform_driver omap_cf_driver = { + .driver = { + .name = (char *) driver_name, + }, + .remove = __exit_p(omap_cf_remove), + .suspend = omap_cf_suspend, + .resume = omap_cf_resume, }; static int __init omap_cf_init(void) { if (cpu_is_omap16xx()) - return driver_register(&omap_cf_driver); + return platform_driver_probe(&omap_cf_driver, omap_cf_probe); return -ENODEV; } static void __exit omap_cf_exit(void) { if (cpu_is_omap16xx()) - driver_unregister(&omap_cf_driver); + platform_driver_unregister(&omap_cf_driver); } module_init(omap_cf_init); diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index 5026b345cb3..57e6ab1004d 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c @@ -451,7 +451,7 @@ int pnp_auto_config_dev(struct pnp_dev *dev) return -EINVAL; if(!pnp_can_configure(dev)) { - pnp_info("Device %s does not support resource configuration.", dev->dev.bus_id); + pnp_dbg("Device %s does not support resource configuration.", dev->dev.bus_id); return -ENODEV; } @@ -482,7 +482,7 @@ int pnp_auto_config_dev(struct pnp_dev *dev) int pnp_start_dev(struct pnp_dev *dev) { if (!pnp_can_write(dev)) { - pnp_info("Device %s does not support activation.", dev->dev.bus_id); + pnp_dbg("Device %s does not support activation.", dev->dev.bus_id); return -EINVAL; } @@ -506,7 +506,7 @@ int pnp_start_dev(struct pnp_dev *dev) int pnp_stop_dev(struct pnp_dev *dev) { if (!pnp_can_disable(dev)) { - pnp_info("Device %s does not support disabling.", dev->dev.bus_id); + pnp_dbg("Device %s does not support disabling.", dev->dev.bus_id); return -EINVAL; } if (dev->protocol->disable(dev)<0) { diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 7a535542fe9..118ac9779b3 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -89,6 +89,7 @@ pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, u32 gsi, return; res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag + res->irq_resource[i].flags |= irq_flags(triggering, polarity); irq = acpi_register_gsi(gsi, triggering, polarity); if (irq < 0) { res->irq_resource[i].flags |= IORESOURCE_DISABLED; @@ -103,8 +104,52 @@ pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, u32 gsi, pcibios_penalize_isa_irq(irq, 1); } +static int dma_flags(int type, int bus_master, int transfer) +{ + int flags = 0; + + if (bus_master) + flags |= IORESOURCE_DMA_MASTER; + switch (type) { + case ACPI_COMPATIBILITY: + flags |= IORESOURCE_DMA_COMPATIBLE; + break; + case ACPI_TYPE_A: + flags |= IORESOURCE_DMA_TYPEA; + break; + case ACPI_TYPE_B: + flags |= IORESOURCE_DMA_TYPEB; + break; + case ACPI_TYPE_F: + flags |= IORESOURCE_DMA_TYPEF; + break; + default: + /* Set a default value ? */ + flags |= IORESOURCE_DMA_COMPATIBLE; + pnp_err("Invalid DMA type"); + } + switch (transfer) { + case ACPI_TRANSFER_8: + flags |= IORESOURCE_DMA_8BIT; + break; + case ACPI_TRANSFER_8_16: + flags |= IORESOURCE_DMA_8AND16BIT; + break; + case ACPI_TRANSFER_16: + flags |= IORESOURCE_DMA_16BIT; + break; + default: + /* Set a default value ? */ + flags |= IORESOURCE_DMA_8AND16BIT; + pnp_err("Invalid DMA transfer type"); + } + + return flags; +} + static void -pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, u32 dma) +pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, u32 dma, + int type, int bus_master, int transfer) { int i = 0; while (i < PNP_MAX_DMA && @@ -112,6 +157,7 @@ pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, u32 dma) i++; if (i < PNP_MAX_DMA) { res->dma_resource[i].flags = IORESOURCE_DMA; // Also clears _UNSET flag + res->dma_resource[i].flags |= dma_flags(type, bus_master, transfer); if (dma == -1) { res->dma_resource[i].flags |= IORESOURCE_DISABLED; return; @@ -123,7 +169,7 @@ pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, u32 dma) static void pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res, - u64 io, u64 len) + u64 io, u64 len, int io_decode) { int i = 0; while (!(res->port_resource[i].flags & IORESOURCE_UNSET) && @@ -131,6 +177,8 @@ pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res, i++; if (i < PNP_MAX_PORT) { res->port_resource[i].flags = IORESOURCE_IO; // Also clears _UNSET flag + if (io_decode == ACPI_DECODE_16) + res->port_resource[i].flags |= PNP_PORT_FLAG_16BITADDR; if (len <= 0 || (io + len -1) >= 0x10003) { res->port_resource[i].flags |= IORESOURCE_DISABLED; return; @@ -142,7 +190,7 @@ pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res, static void pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res, - u64 mem, u64 len) + u64 mem, u64 len, int write_protect) { int i = 0; while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) && @@ -154,6 +202,9 @@ pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res, res->mem_resource[i].flags |= IORESOURCE_DISABLED; return; } + if(write_protect == ACPI_READ_WRITE_MEMORY) + res->mem_resource[i].flags |= IORESOURCE_MEM_WRITEABLE; + res->mem_resource[i].start = mem; res->mem_resource[i].end = mem + len - 1; } @@ -178,10 +229,11 @@ pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res_table, if (p->resource_type == ACPI_MEMORY_RANGE) pnpacpi_parse_allocated_memresource(res_table, - p->minimum, p->address_length); + p->minimum, p->address_length, p->info.mem.write_protect); else if (p->resource_type == ACPI_IO_RANGE) pnpacpi_parse_allocated_ioresource(res_table, - p->minimum, p->address_length); + p->minimum, p->address_length, + p->granularity == 0xfff ? ACPI_DECODE_10 : ACPI_DECODE_16); } static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, @@ -208,13 +260,17 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, case ACPI_RESOURCE_TYPE_DMA: if (res->data.dma.channel_count > 0) pnpacpi_parse_allocated_dmaresource(res_table, - res->data.dma.channels[0]); + res->data.dma.channels[0], + res->data.dma.type, + res->data.dma.bus_master, + res->data.dma.transfer); break; case ACPI_RESOURCE_TYPE_IO: pnpacpi_parse_allocated_ioresource(res_table, res->data.io.minimum, - res->data.io.address_length); + res->data.io.address_length, + res->data.io.io_decode); break; case ACPI_RESOURCE_TYPE_START_DEPENDENT: @@ -224,7 +280,8 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, case ACPI_RESOURCE_TYPE_FIXED_IO: pnpacpi_parse_allocated_ioresource(res_table, res->data.fixed_io.address, - res->data.fixed_io.address_length); + res->data.fixed_io.address_length, + ACPI_DECODE_10); break; case ACPI_RESOURCE_TYPE_VENDOR: @@ -236,17 +293,20 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, case ACPI_RESOURCE_TYPE_MEMORY24: pnpacpi_parse_allocated_memresource(res_table, res->data.memory24.minimum, - res->data.memory24.address_length); + res->data.memory24.address_length, + res->data.memory24.write_protect); break; case ACPI_RESOURCE_TYPE_MEMORY32: pnpacpi_parse_allocated_memresource(res_table, res->data.memory32.minimum, - res->data.memory32.address_length); + res->data.memory32.address_length, + res->data.memory32.write_protect); break; case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: pnpacpi_parse_allocated_memresource(res_table, res->data.fixed_memory32.address, - res->data.fixed_memory32.address_length); + res->data.fixed_memory32.address_length, + res->data.fixed_memory32.write_protect); break; case ACPI_RESOURCE_TYPE_ADDRESS16: case ACPI_RESOURCE_TYPE_ADDRESS32: @@ -304,42 +364,8 @@ static void pnpacpi_parse_dma_option(struct pnp_option *option, struct acpi_reso for(i = 0; i < p->channel_count; i++) dma->map |= 1 << p->channels[i]; - dma->flags = 0; - if (p->bus_master) - dma->flags |= IORESOURCE_DMA_MASTER; - switch (p->type) { - case ACPI_COMPATIBILITY: - dma->flags |= IORESOURCE_DMA_COMPATIBLE; - break; - case ACPI_TYPE_A: - dma->flags |= IORESOURCE_DMA_TYPEA; - break; - case ACPI_TYPE_B: - dma->flags |= IORESOURCE_DMA_TYPEB; - break; - case ACPI_TYPE_F: - dma->flags |= IORESOURCE_DMA_TYPEF; - break; - default: - /* Set a default value ? */ - dma->flags |= IORESOURCE_DMA_COMPATIBLE; - pnp_err("Invalid DMA type"); - } - switch (p->transfer) { - case ACPI_TRANSFER_8: - dma->flags |= IORESOURCE_DMA_8BIT; - break; - case ACPI_TRANSFER_8_16: - dma->flags |= IORESOURCE_DMA_8AND16BIT; - break; - case ACPI_TRANSFER_16: - dma->flags |= IORESOURCE_DMA_16BIT; - break; - default: - /* Set a default value ? */ - dma->flags |= IORESOURCE_DMA_8AND16BIT; - pnp_err("Invalid DMA transfer type"); - } + + dma->flags = dma_flags(p->type, p->bus_master, p->transfer); pnp_register_dma_resource(option, dma); return; diff --git a/drivers/pnp/system.c b/drivers/pnp/system.c index 2065e74bb63..a8a95540b1e 100644 --- a/drivers/pnp/system.c +++ b/drivers/pnp/system.c @@ -22,7 +22,7 @@ static const struct pnp_device_id pnp_dev_table[] = { { "", 0 } }; -static void reserve_range(char *pnpid, int start, int end, int port) +static void reserve_range(const char *pnpid, resource_size_t start, resource_size_t end, int port) { struct resource *res; char *regionid; @@ -32,9 +32,9 @@ static void reserve_range(char *pnpid, int start, int end, int port) return; snprintf(regionid, 16, "pnp %s", pnpid); if (port) - res = request_region(start,end-start+1,regionid); + res = request_region(start, end-start+1, regionid); else - res = request_mem_region(start,end-start+1,regionid); + res = request_mem_region(start, end-start+1, regionid); if (res == NULL) kfree(regionid); else @@ -45,12 +45,13 @@ static void reserve_range(char *pnpid, int start, int end, int port) * have double reservations. */ printk(KERN_INFO - "pnp: %s: %s range 0x%x-0x%x %s reserved\n", - pnpid, port ? "ioport" : "iomem", start, end, + "pnp: %s: %s range 0x%llx-0x%llx %s reserved\n", + pnpid, port ? "ioport" : "iomem", + (unsigned long long)start, (unsigned long long)end, NULL != res ? "has been" : "could not be"); } -static void reserve_resources_of_dev(struct pnp_dev *dev) +static void reserve_resources_of_dev(const struct pnp_dev *dev) { int i; diff --git a/drivers/ps3/ps3av_cmd.c b/drivers/ps3/ps3av_cmd.c index 21c97c80aa2..bc70e81f8cb 100644 --- a/drivers/ps3/ps3av_cmd.c +++ b/drivers/ps3/ps3av_cmd.c @@ -485,12 +485,12 @@ static u8 ps3av_cnv_mclk(u32 fs) static const u32 ps3av_ns_table[][5] = { /* D1, D2, D3, D4, D5 */ - [PS3AV_CMD_AUDIO_FS_44K-BASE] { 6272, 6272, 17836, 17836, 8918 }, - [PS3AV_CMD_AUDIO_FS_48K-BASE] { 6144, 6144, 11648, 11648, 5824 }, - [PS3AV_CMD_AUDIO_FS_88K-BASE] { 12544, 12544, 35672, 35672, 17836 }, - [PS3AV_CMD_AUDIO_FS_96K-BASE] { 12288, 12288, 23296, 23296, 11648 }, - [PS3AV_CMD_AUDIO_FS_176K-BASE] { 25088, 25088, 71344, 71344, 35672 }, - [PS3AV_CMD_AUDIO_FS_192K-BASE] { 24576, 24576, 46592, 46592, 23296 } + [PS3AV_CMD_AUDIO_FS_44K-BASE] = { 6272, 6272, 17836, 17836, 8918 }, + [PS3AV_CMD_AUDIO_FS_48K-BASE] = { 6144, 6144, 11648, 11648, 5824 }, + [PS3AV_CMD_AUDIO_FS_88K-BASE] = { 12544, 12544, 35672, 35672, 17836 }, + [PS3AV_CMD_AUDIO_FS_96K-BASE] = { 12288, 12288, 23296, 23296, 11648 }, + [PS3AV_CMD_AUDIO_FS_176K-BASE] = { 25088, 25088, 71344, 71344, 35672 }, + [PS3AV_CMD_AUDIO_FS_192K-BASE] = { 24576, 24576, 46592, 46592, 23296 } }; static void ps3av_cnv_ns(u8 *ns, u32 fs, u32 video_vid) @@ -543,9 +543,10 @@ static void ps3av_cnv_ns(u8 *ns, u32 fs, u32 video_vid) #undef BASE -static u8 ps3av_cnv_enable(u32 source, u8 *enable) +static u8 ps3av_cnv_enable(u32 source, const u8 *enable) { - u8 *p, ret = 0; + const u8 *p; + u8 ret = 0; if (source == PS3AV_CMD_AUDIO_SOURCE_SPDIF) { ret = 0x03; @@ -559,9 +560,10 @@ static u8 ps3av_cnv_enable(u32 source, u8 *enable) return ret; } -static u8 ps3av_cnv_fifomap(u8 *map) +static u8 ps3av_cnv_fifomap(const u8 *map) { - u8 *p, ret = 0; + const u8 *p; + u8 ret = 0; p = map; ret = p[0] + (p[1] << 2) + (p[2] << 4) + (p[3] << 6); @@ -615,7 +617,7 @@ static void ps3av_cnv_info(struct ps3av_audio_info_frame *info, info->pb5.lsv = mode->audio_downmix_level; } -static void ps3av_cnv_chstat(u8 *chstat, u8 *cs_info) +static void ps3av_cnv_chstat(u8 *chstat, const u8 *cs_info) { memcpy(chstat, cs_info, 5); } diff --git a/drivers/ps3/vuart.c b/drivers/ps3/vuart.c index 1adf186bfaf..6c12744eeb9 100644 --- a/drivers/ps3/vuart.c +++ b/drivers/ps3/vuart.c @@ -952,7 +952,7 @@ fail_alloc_irq: kfree(dev->priv); dev->priv = NULL; fail_alloc: - vuart_bus_priv.devices[port_number] = 0; + vuart_bus_priv.devices[port_number] = NULL; fail_match: up(&vuart_bus_priv.probe_mutex); dev_dbg(&dev->core, "%s:%d failed\n", __func__, __LINE__); @@ -978,7 +978,7 @@ static int ps3_vuart_remove(struct device *_dev) dev_dbg(&dev->core, "%s:%d: %s no remove method\n", __func__, __LINE__, dev->core.bus_id); - vuart_bus_priv.devices[dev->priv->port_number] = 0; + vuart_bus_priv.devices[dev->priv->port_number] = NULL; if (--vuart_bus_priv.use_count == 0) { BUG(); diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 85bf795abdc..7c0d6091007 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -59,6 +59,19 @@ struct cmos_rtc { static const char driver_name[] = "rtc_cmos"; +/* The RTC_INTR register may have e.g. RTC_PF set even if RTC_PIE is clear; + * always mask it against the irq enable bits in RTC_CONTROL. Bit values + * are the same: PF==PIE, AF=AIE, UF=UIE; so RTC_IRQMASK works with both. + */ +#define RTC_IRQMASK (RTC_PF | RTC_AF | RTC_UF) + +static inline int is_intr(u8 rtc_intr) +{ + if (!(rtc_intr & RTC_IRQF)) + return 0; + return rtc_intr & RTC_IRQMASK; +} + /*----------------------------------------------------------------*/ static int cmos_read_time(struct device *dev, struct rtc_time *t) @@ -188,7 +201,8 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) rtc_control &= ~RTC_AIE; CMOS_WRITE(rtc_control, RTC_CONTROL); rtc_intr = CMOS_READ(RTC_INTR_FLAGS); - if (rtc_intr) + rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; + if (is_intr(rtc_intr)) rtc_update_irq(&cmos->rtc->class_dev, 1, rtc_intr); /* update alarm */ @@ -207,7 +221,8 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) rtc_control |= RTC_AIE; CMOS_WRITE(rtc_control, RTC_CONTROL); rtc_intr = CMOS_READ(RTC_INTR_FLAGS); - if (rtc_intr) + rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; + if (is_intr(rtc_intr)) rtc_update_irq(&cmos->rtc->class_dev, 1, rtc_intr); } @@ -287,7 +302,8 @@ cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) } CMOS_WRITE(rtc_control, RTC_CONTROL); rtc_intr = CMOS_READ(RTC_INTR_FLAGS); - if (rtc_intr) + rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; + if (is_intr(rtc_intr)) rtc_update_irq(&cmos->rtc->class_dev, 1, rtc_intr); spin_unlock_irqrestore(&rtc_lock, flags); return 0; @@ -353,12 +369,10 @@ static irqreturn_t cmos_interrupt(int irq, void *p) spin_lock(&rtc_lock); irqstat = CMOS_READ(RTC_INTR_FLAGS); + irqstat &= (CMOS_READ(RTC_CONTROL) & RTC_IRQMASK) | RTC_IRQF; spin_unlock(&rtc_lock); - if (irqstat) { - /* NOTE: irqstat may have e.g. RTC_PF set - * even when RTC_PIE is clear... - */ + if (is_intr(irqstat)) { rtc_update_irq(p, 1, irqstat); return IRQ_HANDLED; } else @@ -525,25 +539,26 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg) { struct cmos_rtc *cmos = dev_get_drvdata(dev); int do_wake = device_may_wakeup(dev); - unsigned char tmp, irqstat; + unsigned char tmp; /* only the alarm might be a wakeup event source */ spin_lock_irq(&rtc_lock); cmos->suspend_ctrl = tmp = CMOS_READ(RTC_CONTROL); if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) { + unsigned char irqstat; + if (do_wake) tmp &= ~(RTC_PIE|RTC_UIE); else tmp &= ~(RTC_PIE|RTC_AIE|RTC_UIE); CMOS_WRITE(tmp, RTC_CONTROL); irqstat = CMOS_READ(RTC_INTR_FLAGS); - } else - irqstat = 0; + irqstat &= (tmp & RTC_IRQMASK) | RTC_IRQF; + if (is_intr(irqstat)) + rtc_update_irq(&cmos->rtc->class_dev, 1, irqstat); + } spin_unlock_irq(&rtc_lock); - if (irqstat) - rtc_update_irq(&cmos->rtc->class_dev, 1, irqstat); - /* ACPI HOOK: enable ACPI_EVENT_RTC when (tmp & RTC_AIE) * ... it'd be best if we could do that under rtc_lock. */ @@ -573,9 +588,10 @@ static int cmos_resume(struct device *dev) spin_lock_irq(&rtc_lock); CMOS_WRITE(tmp, RTC_CONTROL); tmp = CMOS_READ(RTC_INTR_FLAGS); - spin_unlock_irq(&rtc_lock); - if (tmp) + tmp &= (cmos->suspend_ctrl & RTC_IRQMASK) | RTC_IRQF; + if (is_intr(tmp)) rtc_update_irq(&cmos->rtc->class_dev, 1, tmp); + spin_unlock_irq(&rtc_lock); } pr_debug("%s: resume, ctrl %02x\n", @@ -594,7 +610,7 @@ static int cmos_resume(struct device *dev) /*----------------------------------------------------------------*/ /* The "CMOS" RTC normally lives on the platform_bus. On ACPI systems, - * the device node may alternatively be created as a PNP device. + * the device node will always be created as a PNPACPI device. */ #ifdef CONFIG_PNPACPI @@ -673,7 +689,7 @@ module_exit(cmos_exit); /*----------------------------------------------------------------*/ /* Platform setup should have set up an RTC device, when PNPACPI is - * unavailable ... this is the normal case, common even on PCs. + * unavailable ... this could happen even on (older) PCs. */ static int __init cmos_platform_probe(struct platform_device *pdev) diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index ab782bb46ac..e810e4a44ed 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c @@ -65,7 +65,7 @@ static const u8 DASD_DIAG_CMS1[] = { 0xc3, 0xd4, 0xe2, 0xf1 };/* EBCDIC CMS1 */ * resulting condition code and DIAG return code. */ static inline int dia250(void *iob, int cmd) { - register unsigned long reg0 asm ("0") = (unsigned long) iob; + register unsigned long reg2 asm ("2") = (unsigned long) iob; typedef union { struct dasd_diag_init_io init_io; struct dasd_diag_rw_io rw_io; @@ -74,15 +74,15 @@ static inline int dia250(void *iob, int cmd) rc = 3; asm volatile( - " diag 0,%2,0x250\n" + " diag 2,%2,0x250\n" "0: ipm %0\n" " srl %0,28\n" - " or %0,1\n" + " or %0,3\n" "1:\n" EX_TABLE(0b,1b) : "+d" (rc), "=m" (*(addr_type *) iob) - : "d" (cmd), "d" (reg0), "m" (*(addr_type *) iob) - : "1", "cc"); + : "d" (cmd), "d" (reg2), "m" (*(addr_type *) iob) + : "3", "cc"); return rc; } diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index d48e3ca4752..5aeb68e732b 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -71,19 +71,31 @@ __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev) * Provide an 'ungroup' attribute so the user can remove group devices no * longer needed or accidentially created. Saves memory :) */ +static void ccwgroup_ungroup_callback(struct device *dev) +{ + struct ccwgroup_device *gdev = to_ccwgroupdev(dev); + + __ccwgroup_remove_symlinks(gdev); + device_unregister(dev); +} + static ssize_t ccwgroup_ungroup_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct ccwgroup_device *gdev; + int rc; gdev = to_ccwgroupdev(dev); if (gdev->state != CCWGROUP_OFFLINE) return -EINVAL; - __ccwgroup_remove_symlinks(gdev); - device_unregister(dev); - + /* Note that we cannot unregister the device from one of its + * attribute methods, so we have to use this roundabout approach. + */ + rc = device_schedule_callback(dev, ccwgroup_ungroup_callback); + if (rc) + count = rc; return count; } diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c index 6b1caea622e..aa96e675259 100644 --- a/drivers/s390/cio/device_status.c +++ b/drivers/s390/cio/device_status.c @@ -221,6 +221,14 @@ ccw_device_accumulate_irb(struct ccw_device *cdev, struct irb *irb) cdev_irb = &cdev->private->irb; + /* + * If the clear function had been performed, all formerly pending + * status at the subchannel has been cleared and we must not pass + * intermediate accumulated status to the device driver. + */ + if (irb->scsw.fctl & SCSW_FCTL_CLEAR_FUNC) + memset(&cdev->private->irb, 0, sizeof(struct irb)); + /* Copy bits which are valid only for the start function. */ if (irb->scsw.fctl & SCSW_FCTL_START_FUNC) { /* Copy key. */ @@ -263,7 +271,11 @@ ccw_device_accumulate_irb(struct ccw_device *cdev, struct irb *irb) cdev_irb->scsw.cpa = irb->scsw.cpa; /* Accumulate device status, but not the device busy flag. */ cdev_irb->scsw.dstat &= ~DEV_STAT_BUSY; - cdev_irb->scsw.dstat |= irb->scsw.dstat; + /* dstat is not always valid. */ + if (irb->scsw.stctl & + (SCSW_STCTL_PRIM_STATUS | SCSW_STCTL_SEC_STATUS + | SCSW_STCTL_INTER_STATUS | SCSW_STCTL_ALERT_STATUS)) + cdev_irb->scsw.dstat |= irb->scsw.dstat; /* Accumulate subchannel status. */ cdev_irb->scsw.cstat |= irb->scsw.cstat; /* Copy residual count if it is valid. */ diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index 5b1e3ff26c0..05fac0733f3 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c @@ -210,9 +210,11 @@ again: goto again; } if (rc < 0) { - QDIO_DBF_TEXT3(1,trace,"sqberr"); - sprintf(dbf_text,"%2x,%2x,%d,%d",tmp_cnt,*cnt,ccq,q_no); - QDIO_DBF_TEXT3(1,trace,dbf_text); + QDIO_DBF_TEXT3(1,trace,"sqberr"); + sprintf(dbf_text,"%2x,%2x",tmp_cnt,*cnt); + QDIO_DBF_TEXT3(1,trace,dbf_text); + sprintf(dbf_text,"%d,%d",ccq,q_no); + QDIO_DBF_TEXT3(1,trace,dbf_text); q->handler(q->cdev,QDIO_STATUS_ACTIVATE_CHECK_CONDITION| QDIO_STATUS_LOOK_FOR_ERROR, 0, 0, 0, -1, -1, q->int_parm); @@ -1250,7 +1252,6 @@ qdio_is_inbound_q_done(struct qdio_q *q) if (!no_used) { QDIO_DBF_TEXT4(0,trace,"inqisdnA"); QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); - QDIO_DBF_TEXT4(0,trace,dbf_text); return 1; } if (irq->is_qebsm) { @@ -3371,10 +3372,15 @@ qdio_do_qdio_fill_input(struct qdio_q *q, unsigned int qidx, unsigned int count, struct qdio_buffer *buffers) { struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr; + int tmp = 0; + qidx &= (QDIO_MAX_BUFFERS_PER_Q - 1); if (irq->is_qebsm) { - while (count) - set_slsb(q, &qidx, SLSB_CU_INPUT_EMPTY, &count); + while (count) { + tmp = set_slsb(q, &qidx, SLSB_CU_INPUT_EMPTY, &count); + if (!tmp) + return; + } return; } for (;;) { @@ -3390,11 +3396,15 @@ qdio_do_qdio_fill_output(struct qdio_q *q, unsigned int qidx, unsigned int count, struct qdio_buffer *buffers) { struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr; + int tmp = 0; qidx &= (QDIO_MAX_BUFFERS_PER_Q - 1); if (irq->is_qebsm) { - while (count) - set_slsb(q, &qidx, SLSB_CU_OUTPUT_PRIMED, &count); + while (count) { + tmp = set_slsb(q, &qidx, SLSB_CU_OUTPUT_PRIMED, &count); + if (!tmp) + return; + } return; } diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index c7d1355237b..bf37cdf43fa 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -65,6 +65,8 @@ module_param_named(poll_thread, ap_thread_flag, int, 0000); MODULE_PARM_DESC(poll_thread, "Turn on/off poll thread, default is 1 (on)."); static struct device *ap_root_device = NULL; +static DEFINE_SPINLOCK(ap_device_lock); +static LIST_HEAD(ap_device_list); /** * Workqueue & timer for bus rescan. @@ -457,6 +459,9 @@ static int ap_device_probe(struct device *dev) int rc; ap_dev->drv = ap_drv; + spin_lock_bh(&ap_device_lock); + list_add(&ap_dev->list, &ap_device_list); + spin_unlock_bh(&ap_device_lock); rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV; return rc; } @@ -497,6 +502,12 @@ static int ap_device_remove(struct device *dev) ap_flush_queue(ap_dev); if (ap_drv->remove) ap_drv->remove(ap_dev); + spin_lock_bh(&ap_device_lock); + list_del_init(&ap_dev->list); + spin_unlock_bh(&ap_device_lock); + spin_lock_bh(&ap_dev->lock); + atomic_sub(ap_dev->queue_count, &ap_poll_requests); + spin_unlock_bh(&ap_dev->lock); return 0; } @@ -749,10 +760,16 @@ static void ap_scan_bus(struct work_struct *unused) (void *)(unsigned long)qid, __ap_scan_bus); rc = ap_query_queue(qid, &queue_depth, &device_type); - if (dev && rc) { - put_device(dev); - device_unregister(dev); - continue; + if (dev) { + ap_dev = to_ap_dev(dev); + spin_lock_bh(&ap_dev->lock); + if (rc || ap_dev->unregistered) { + spin_unlock_bh(&ap_dev->lock); + put_device(dev); + device_unregister(dev); + continue; + } else + spin_unlock_bh(&ap_dev->lock); } if (dev) { put_device(dev); @@ -772,6 +789,7 @@ static void ap_scan_bus(struct work_struct *unused) spin_lock_init(&ap_dev->lock); INIT_LIST_HEAD(&ap_dev->pendingq); INIT_LIST_HEAD(&ap_dev->requestq); + INIT_LIST_HEAD(&ap_dev->list); if (device_type == 0) ap_probe_device_type(ap_dev); else @@ -852,6 +870,7 @@ static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags) case AP_RESPONSE_NO_PENDING_REPLY: if (status.queue_empty) { /* The card shouldn't forget requests but who knows. */ + atomic_sub(ap_dev->queue_count, &ap_poll_requests); ap_dev->queue_count = 0; list_splice_init(&ap_dev->pendingq, &ap_dev->requestq); ap_dev->requestq_count += ap_dev->pendingq_count; @@ -985,7 +1004,7 @@ void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg) ap_dev->unregistered = 1; } else { ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV)); - rc = 0; + rc = -ENODEV; } spin_unlock_bh(&ap_dev->lock); if (rc == -ENODEV) @@ -1033,31 +1052,29 @@ static void ap_poll_timeout(unsigned long unused) * polling until bit 2^0 of the control flags is not set. If bit 2^1 * of the control flags has been set arm the poll timer. */ -static int __ap_poll_all(struct device *dev, void *data) +static int __ap_poll_all(struct ap_device *ap_dev, unsigned long *flags) { - struct ap_device *ap_dev = to_ap_dev(dev); - int rc; - spin_lock(&ap_dev->lock); if (!ap_dev->unregistered) { - rc = ap_poll_queue(to_ap_dev(dev), (unsigned long *) data); - if (rc) + if (ap_poll_queue(ap_dev, flags)) ap_dev->unregistered = 1; - } else - rc = 0; + } spin_unlock(&ap_dev->lock); - if (rc) - device_unregister(&ap_dev->device); return 0; } static void ap_poll_all(unsigned long dummy) { unsigned long flags; + struct ap_device *ap_dev; do { flags = 0; - bus_for_each_dev(&ap_bus_type, NULL, &flags, __ap_poll_all); + spin_lock(&ap_device_lock); + list_for_each_entry(ap_dev, &ap_device_list, list) { + __ap_poll_all(ap_dev, &flags); + } + spin_unlock(&ap_device_lock); } while (flags & 1); if (flags & 2) ap_schedule_poll_timer(); @@ -1075,6 +1092,7 @@ static int ap_poll_thread(void *data) DECLARE_WAITQUEUE(wait, current); unsigned long flags; int requests; + struct ap_device *ap_dev; set_user_nice(current, 19); while (1) { @@ -1092,10 +1110,12 @@ static int ap_poll_thread(void *data) set_current_state(TASK_RUNNING); remove_wait_queue(&ap_poll_wait, &wait); - local_bh_disable(); flags = 0; - bus_for_each_dev(&ap_bus_type, NULL, &flags, __ap_poll_all); - local_bh_enable(); + spin_lock_bh(&ap_device_lock); + list_for_each_entry(ap_dev, &ap_device_list, list) { + __ap_poll_all(ap_dev, &flags); + } + spin_unlock_bh(&ap_device_lock); } set_current_state(TASK_RUNNING); remove_wait_queue(&ap_poll_wait, &wait); diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h index 83b69c01cd6..008559ea742 100644 --- a/drivers/s390/crypto/ap_bus.h +++ b/drivers/s390/crypto/ap_bus.h @@ -106,6 +106,7 @@ struct ap_device { struct device device; struct ap_driver *drv; /* Pointer to AP device driver. */ spinlock_t lock; /* Per device lock. */ + struct list_head list; /* private list of all AP devices. */ ap_qid_t qid; /* AP queue id. */ int queue_depth; /* AP queue depth.*/ diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 99761391f34..e3625a47a59 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -298,14 +298,14 @@ static long zcrypt_rsa_modexpo(struct ica_rsa_modexpo *mex) get_device(&zdev->ap_dev->device); zdev->request_count++; __zcrypt_decrease_preference(zdev); - spin_unlock_bh(&zcrypt_device_lock); if (try_module_get(zdev->ap_dev->drv->driver.owner)) { + spin_unlock_bh(&zcrypt_device_lock); rc = zdev->ops->rsa_modexpo(zdev, mex); + spin_lock_bh(&zcrypt_device_lock); module_put(zdev->ap_dev->drv->driver.owner); } else rc = -EAGAIN; - spin_lock_bh(&zcrypt_device_lock); zdev->request_count--; __zcrypt_increase_preference(zdev); put_device(&zdev->ap_dev->device); @@ -373,14 +373,14 @@ static long zcrypt_rsa_crt(struct ica_rsa_modexpo_crt *crt) get_device(&zdev->ap_dev->device); zdev->request_count++; __zcrypt_decrease_preference(zdev); - spin_unlock_bh(&zcrypt_device_lock); if (try_module_get(zdev->ap_dev->drv->driver.owner)) { + spin_unlock_bh(&zcrypt_device_lock); rc = zdev->ops->rsa_modexpo_crt(zdev, crt); + spin_lock_bh(&zcrypt_device_lock); module_put(zdev->ap_dev->drv->driver.owner); } else rc = -EAGAIN; - spin_lock_bh(&zcrypt_device_lock); zdev->request_count--; __zcrypt_increase_preference(zdev); put_device(&zdev->ap_dev->device); @@ -408,14 +408,14 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB) get_device(&zdev->ap_dev->device); zdev->request_count++; __zcrypt_decrease_preference(zdev); - spin_unlock_bh(&zcrypt_device_lock); if (try_module_get(zdev->ap_dev->drv->driver.owner)) { + spin_unlock_bh(&zcrypt_device_lock); rc = zdev->ops->send_cprb(zdev, xcRB); + spin_lock_bh(&zcrypt_device_lock); module_put(zdev->ap_dev->drv->driver.owner); } else rc = -EAGAIN; - spin_lock_bh(&zcrypt_device_lock); zdev->request_count--; __zcrypt_increase_preference(zdev); put_device(&zdev->ap_dev->device); diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index e95c281f1e3..84b108d7c7f 100644 --- a/drivers/s390/net/qeth.h +++ b/drivers/s390/net/qeth.h @@ -873,7 +873,7 @@ qeth_realloc_headroom(struct qeth_card *card, struct sk_buff *skb, int size) } static inline struct sk_buff * -qeth_pskb_unshare(struct sk_buff *skb, int pri) +qeth_pskb_unshare(struct sk_buff *skb, gfp_t pri) { struct sk_buff *nskb; if (!skb_cloned(skb)) diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index 8c81cec8529..60446b88f72 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -3091,6 +3091,7 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b) cmdp->u.raw64.direction = gdth_direction_tab[scp->cmnd[0]]==DOU ? GDTH_DATA_OUT:GDTH_DATA_IN; memcpy(cmdp->u.raw64.cmd,scp->cmnd,16); + cmdp->u.raw64.sg_ranz = 0; } else { cmdp->u.raw.reserved = 0; cmdp->u.raw.mdisc_time = 0; @@ -3107,6 +3108,7 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b) cmdp->u.raw.direction = gdth_direction_tab[scp->cmnd[0]]==DOU ? GDTH_DATA_OUT:GDTH_DATA_IN; memcpy(cmdp->u.raw.cmd,scp->cmnd,12); + cmdp->u.raw.sg_ranz = 0; } if (scp->use_sg) { diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 9d014e5a81c..057fd7e0e37 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -1817,10 +1817,9 @@ static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev, struct lpfc_sli *psli = &phba->sli; struct lpfc_sli_ring *pring; - if (state == pci_channel_io_perm_failure) { - lpfc_pci_remove_one(pdev); + if (state == pci_channel_io_perm_failure) return PCI_ERS_RESULT_DISCONNECT; - } + pci_disable_device(pdev); /* * There may be I/Os dropped by the firmware. diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index b8edcf5b545..918bb601954 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -716,7 +716,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, */ if (copy_sense) { if (!SCSI_SENSE_VALID(scmd)) { - memcpy(scmd->sense_buffer, scmd->request_buffer, + memcpy(scmd->sense_buffer, page_address(sgl.page), sizeof(scmd->sense_buffer)); } __free_page(sgl.page); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index c275dcac3f1..939de0de18b 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -452,10 +452,22 @@ store_rescan_field (struct device *dev, struct device_attribute *attr, const cha } static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field); +static void sdev_store_delete_callback(struct device *dev) +{ + scsi_remove_device(to_scsi_device(dev)); +} + static ssize_t sdev_store_delete(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - scsi_remove_device(to_scsi_device(dev)); + int rc; + + /* An attribute cannot be unregistered by one of its own methods, + * so we have to use this roundabout approach. + */ + rc = device_schedule_callback(dev, sdev_store_delete_callback); + if (rc) + count = rc; return count; }; static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete); diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c index cde5db44abf..301c8c0be9d 100644 --- a/drivers/serial/8250_pnp.c +++ b/drivers/serial/8250_pnp.c @@ -340,6 +340,9 @@ static const struct pnp_device_id pnp_dev_table[] = { { "FUJ02B8", 0 }, { "FUJ02B9", 0 }, { "FUJ02BC", 0 }, + /* Fujitsu Wacom Tablet PC devices */ + { "FUJ02E5", 0 }, + { "FUJ02E6", 0 }, /* Rockwell's (PORALiNK) 33600 INT PNP */ { "WCI0003", 0 }, /* Unkown PnP modems */ diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index c53b69610a5..46c40bbc4bc 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -17,6 +17,9 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. */ +#if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif #undef DEBUG @@ -49,11 +52,6 @@ #endif #include <asm/sci.h> - -#if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include "sh-sci.h" struct sci_port { @@ -645,6 +643,9 @@ static inline int sci_handle_breaks(struct uart_port *port) struct tty_struct *tty = port->info->tty; struct sci_port *s = &sci_ports[port->line]; + if (uart_handle_break(port)) + return 0; + if (!s->break_flag && status & SCxSR_BRK(port)) { #if defined(CONFIG_CPU_SH3) /* Debounce break */ diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c index 253ceb895ca..a27e9e92cb5 100644 --- a/drivers/serial/sn_console.c +++ b/drivers/serial/sn_console.c @@ -636,25 +636,6 @@ static irqreturn_t sn_sal_interrupt(int irq, void *dev_id) } /** - * sn_sal_connect_interrupt - Request interrupt, handled by sn_sal_interrupt - * @port: Our sn_cons_port (which contains the uart port) - * - * returns the console irq if interrupt is successfully registered, else 0 - * - */ -static int sn_sal_connect_interrupt(struct sn_cons_port *port) -{ - if (request_irq(SGI_UART_VECTOR, sn_sal_interrupt, - IRQF_DISABLED | IRQF_SHARED, - "SAL console driver", port) >= 0) { - return SGI_UART_VECTOR; - } - - printk(KERN_INFO "sn_console: console proceeding in polled mode\n"); - return 0; -} - -/** * sn_sal_timer_poll - this function handles polled console mode * @data: A pointer to our sn_cons_port (which contains the uart port) * @@ -746,30 +727,31 @@ static void __init sn_sal_switch_to_asynch(struct sn_cons_port *port) * mode. We were previously in asynch/polling mode (using init_timer). * * We attempt to switch to interrupt mode here by calling - * sn_sal_connect_interrupt. If that works out, we enable receive interrupts. + * request_irq. If that works out, we enable receive interrupts. */ static void __init sn_sal_switch_to_interrupts(struct sn_cons_port *port) { - int irq; unsigned long flags; - if (!port) - return; - - DPRINTF("sn_console: switching to interrupt driven console\n"); - - spin_lock_irqsave(&port->sc_port.lock, flags); + if (port) { + DPRINTF("sn_console: switching to interrupt driven console\n"); - irq = sn_sal_connect_interrupt(port); + if (request_irq(SGI_UART_VECTOR, sn_sal_interrupt, + IRQF_DISABLED | IRQF_SHARED, + "SAL console driver", port) >= 0) { + spin_lock_irqsave(&port->sc_port.lock, flags); + port->sc_port.irq = SGI_UART_VECTOR; + port->sc_ops = &intr_ops; - if (irq) { - port->sc_port.irq = irq; - port->sc_ops = &intr_ops; - - /* turn on receive interrupts */ - ia64_sn_console_intr_enable(SAL_CONSOLE_INTR_RECV); + /* turn on receive interrupts */ + ia64_sn_console_intr_enable(SAL_CONSOLE_INTR_RECV); + spin_unlock_irqrestore(&port->sc_port.lock, flags); + } + else { + printk(KERN_INFO + "sn_console: console proceeding in polled mode\n"); + } } - spin_unlock_irqrestore(&port->sc_port.lock, flags); } /* diff --git a/drivers/spi/at25.c b/drivers/spi/at25.c index 48e4f48e779..8efa07e8b8c 100644 --- a/drivers/spi/at25.c +++ b/drivers/spi/at25.c @@ -291,7 +291,7 @@ static int at25_probe(struct spi_device *spi) */ sr = spi_w8r8(spi, AT25_RDSR); if (sr < 0 || sr & AT25_SR_nRDY) { - dev_dbg(&at25->spi->dev, "rdsr --> %d (%02x)\n", sr, sr); + dev_dbg(&spi->dev, "rdsr --> %d (%02x)\n", sr, sr); err = -ENXIO; goto fail; } diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c index 6fa260d1a9b..66e7bc98579 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c @@ -425,7 +425,7 @@ static int atmel_spi_setup(struct spi_device *spi) if (ret) return ret; spi->controller_state = (void *)npcs_pin; - gpio_direction_output(npcs_pin); + gpio_direction_output(npcs_pin, !(spi->mode & SPI_CS_HIGH)); } dev_dbg(&spi->dev, diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 2328128728b..6657331eed9 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -189,8 +189,8 @@ static DECLARE_MUTEX(board_lock); * this is exported so that for example a USB or parport based adapter * driver could add devices (which it would learn about out-of-band). */ -struct spi_device *__init_or_module -spi_new_device(struct spi_master *master, struct spi_board_info *chip) +struct spi_device *spi_new_device(struct spi_master *master, + struct spi_board_info *chip) { struct spi_device *proxy; struct device *dev = master->cdev.dev; @@ -352,8 +352,7 @@ static struct class spi_master_class = { * the master's methods before calling spi_register_master(); and (after errors * adding the device) calling spi_master_put() to prevent a memory leak. */ -struct spi_master * __init_or_module -spi_alloc_master(struct device *dev, unsigned size) +struct spi_master *spi_alloc_master(struct device *dev, unsigned size) { struct spi_master *master; @@ -392,8 +391,7 @@ EXPORT_SYMBOL_GPL(spi_alloc_master); * After a successful return, the caller is responsible for calling * spi_unregister_master(). */ -int __init_or_module -spi_register_master(struct spi_master *master) +int spi_register_master(struct spi_master *master) { static atomic_t dyn_bus_id = ATOMIC_INIT((1<<16) - 1); struct device *dev = master->cdev.dev; diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c index 24a330d8239..88425e1af4d 100644 --- a/drivers/spi/spi_bitbang.c +++ b/drivers/spi/spi_bitbang.c @@ -302,10 +302,6 @@ static void bitbang_work(struct work_struct *work) setup_transfer = NULL; list_for_each_entry (t, &m->transfers, transfer_list) { - if (bitbang->shutdown) { - status = -ESHUTDOWN; - break; - } /* override or restore speed and wordsize */ if (t->speed_hz || t->bits_per_word) { @@ -410,8 +406,6 @@ int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m) m->status = -EINPROGRESS; bitbang = spi_master_get_devdata(spi->master); - if (bitbang->shutdown) - return -ESHUTDOWN; spin_lock_irqsave(&bitbang->lock, flags); if (!spi->max_speed_hz) @@ -507,28 +501,12 @@ EXPORT_SYMBOL_GPL(spi_bitbang_start); */ int spi_bitbang_stop(struct spi_bitbang *bitbang) { - unsigned limit = 500; - - spin_lock_irq(&bitbang->lock); - bitbang->shutdown = 0; - while (!list_empty(&bitbang->queue) && limit--) { - spin_unlock_irq(&bitbang->lock); + spi_unregister_master(bitbang->master); - dev_dbg(bitbang->master->cdev.dev, "wait for queue\n"); - msleep(10); - - spin_lock_irq(&bitbang->lock); - } - spin_unlock_irq(&bitbang->lock); - if (!list_empty(&bitbang->queue)) { - dev_err(bitbang->master->cdev.dev, "queue didn't empty\n"); - return -EBUSY; - } + WARN_ON(!list_empty(&bitbang->queue)); destroy_workqueue(bitbang->workqueue); - spi_unregister_master(bitbang->master); - return 0; } EXPORT_SYMBOL_GPL(spi_bitbang_stop); diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c index 651379c51ae..220abce63e4 100644 --- a/drivers/spi/spi_s3c24xx.c +++ b/drivers/spi/spi_s3c24xx.c @@ -41,7 +41,7 @@ struct s3c24xx_spi { int len; int count; - int (*set_cs)(struct s3c2410_spi_info *spi, + void (*set_cs)(struct s3c2410_spi_info *spi, int cs, int pol); /* data buffers */ diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c index 3d72aa5cfc7..3524e3fc08b 100644 --- a/drivers/tc/zs.c +++ b/drivers/tc/zs.c @@ -70,7 +70,6 @@ #include <asm/dec/machtype.h> #include <asm/dec/serial.h> #include <asm/dec/system.h> -#include <asm/dec/tc.h> #ifdef CONFIG_KGDB #include <asm/kgdb.h> diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index d38a25f36ea..31ae661e586 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -332,9 +332,9 @@ static void acm_rx_tasklet(unsigned long _acm) if (!ACM_READY(acm)) return; - spin_lock(&acm->throttle_lock); + spin_lock_irqsave(&acm->throttle_lock, flags); throttled = acm->throttle; - spin_unlock(&acm->throttle_lock); + spin_unlock_irqrestore(&acm->throttle_lock, flags); if (throttled) return; @@ -352,9 +352,9 @@ next_buffer: dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size); tty_buffer_request_room(tty, buf->size); - spin_lock(&acm->throttle_lock); + spin_lock_irqsave(&acm->throttle_lock, flags); throttled = acm->throttle; - spin_unlock(&acm->throttle_lock); + spin_unlock_irqrestore(&acm->throttle_lock, flags); if (!throttled) tty_insert_flip_string(tty, buf->base, buf->size); tty_flip_buffer_push(tty); diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 63e50a1f139..6584cf00f7f 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -202,6 +202,7 @@ struct quirk_printer_struct { #define USBLP_QUIRK_BIDIR 0x1 /* reports bidir but requires unidirectional mode (no INs/reads) */ #define USBLP_QUIRK_USB_INIT 0x2 /* needs vendor USB init string */ +#define USBLP_QUIRK_BAD_CLASS 0x4 /* descriptor uses vendor-specific Class or SubClass */ static const struct quirk_printer_struct quirk_printers[] = { { 0x03f0, 0x0004, USBLP_QUIRK_BIDIR }, /* HP DeskJet 895C */ @@ -218,6 +219,7 @@ static const struct quirk_printer_struct quirk_printers[] = { { 0x0409, 0xf0be, USBLP_QUIRK_BIDIR }, /* NEC Picty920 (HP OEM) */ { 0x0409, 0xf1be, USBLP_QUIRK_BIDIR }, /* NEC Picty800 (HP OEM) */ { 0x0482, 0x0010, USBLP_QUIRK_BIDIR }, /* Kyocera Mita FS 820, by zut <kernel@zut.de> */ + { 0x04b8, 0x0202, USBLP_QUIRK_BAD_CLASS }, /* Seiko Epson Receipt Printer M129C */ { 0, 0 } }; @@ -1048,7 +1050,8 @@ static int usblp_select_alts(struct usblp *usblp) ifd = &if_alt->altsetting[i]; if (ifd->desc.bInterfaceClass != 7 || ifd->desc.bInterfaceSubClass != 1) - continue; + if (!(usblp->quirks & USBLP_QUIRK_BAD_CLASS)) + continue; if (ifd->desc.bInterfaceProtocol < USBLP_FIRST_PROTOCOL || ifd->desc.bInterfaceProtocol > USBLP_LAST_PROTOCOL) @@ -1232,6 +1235,7 @@ static struct usb_device_id usblp_ids [] = { { USB_INTERFACE_INFO(7, 1, 1) }, { USB_INTERFACE_INFO(7, 1, 2) }, { USB_INTERFACE_INFO(7, 1, 3) }, + { USB_DEVICE(0x04b8, 0x0202) }, /* Seiko Epson Receipt Printer M129C */ { } /* Terminating entry */ }; diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 274f14f1633..36e7a843bf9 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -912,7 +912,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, struct async *as; struct usb_ctrlrequest *dr = NULL; unsigned int u, totlen, isofrmlen; - int ret, interval = 0, ifnum = -1; + int ret, ifnum = -1; if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_SHORT_NOT_OK| URB_NO_FSBR|URB_ZERO_PACKET)) @@ -992,7 +992,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC) return -EINVAL; - interval = 1 << min (15, ep->desc.bInterval - 1); isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb->number_of_packets; if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL))) return -ENOMEM; @@ -1021,10 +1020,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) return -EINVAL; - if (ps->dev->speed == USB_SPEED_HIGH) - interval = 1 << min (15, ep->desc.bInterval - 1); - else - interval = ep->desc.bInterval; if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) return -EINVAL; if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length)) @@ -1053,7 +1048,11 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, as->urb->setup_packet = (unsigned char*)dr; as->urb->start_frame = uurb->start_frame; as->urb->number_of_packets = uurb->number_of_packets; - as->urb->interval = interval; + if (uurb->type == USBDEVFS_URB_TYPE_ISO || + ps->dev->speed == USB_SPEED_HIGH) + as->urb->interval = 1 << min(15, ep->desc.bInterval - 1); + else + as->urb->interval = ep->desc.bInterval; as->urb->context = as; as->urb->complete = async_completed; for (totlen = u = 0; u < uurb->number_of_packets; u++) { diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 41400743ce2..b89a98e6132 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1281,12 +1281,6 @@ int usb_new_device(struct usb_device *udev) { int err; - /* Lock ourself into memory in order to keep a probe sequence - * sleeping in a new thread from allowing us to be unloaded. - */ - if (!try_module_get(THIS_MODULE)) - return -EINVAL; - /* Determine quirks */ usb_detect_quirks(udev); @@ -1390,7 +1384,6 @@ int usb_new_device(struct usb_device *udev) usb_autoresume_device(udev->parent); exit: - module_put(THIS_MODULE); return err; fail: @@ -2443,7 +2436,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, if (portchange & USB_PORT_STAT_C_CONNECTION) { status = hub_port_debounce(hub, port1); - if (status < 0) { + if (status < 0 && printk_ratelimit()) { dev_err (hub_dev, "connect-debounce failed, port %d disabled\n", port1); diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 2f17468b5c1..217a3d6d0a0 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -221,10 +221,15 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) { + int interval; + + if (usb_dev->speed == USB_SPEED_HIGH) + interval = 1 << min(15, ep->desc.bInterval - 1); + else + interval = ep->desc.bInterval; pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30); usb_fill_int_urb(urb, usb_dev, pipe, data, len, - usb_api_blocking_completion, NULL, - ep->desc.bInterval); + usb_api_blocking_completion, NULL, interval); } else usb_fill_bulk_urb(urb, usb_dev, pipe, data, len, usb_api_blocking_completion, NULL); diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 0e5c646cb4f..f08ec85a6d6 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -30,7 +30,8 @@ static const struct usb_device_id usb_quirk_list[] = { /* HP 5300/5370C scanner */ { USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 }, - + /* Seiko Epson Corp - Perfection 1670 */ + { USB_DEVICE(0x04b8, 0x011f), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, /* Elsa MicroLink 56k (V.250) */ { USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index a4677802fb2..2a6e3163d94 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -1835,7 +1835,7 @@ static int at91udc_resume(struct platform_device *pdev) #define at91udc_resume NULL #endif -static struct platform_driver at91_udc = { +static struct platform_driver at91_udc_driver = { .remove = __exit_p(at91udc_remove), .shutdown = at91udc_shutdown, .suspend = at91udc_suspend, @@ -1848,13 +1848,13 @@ static struct platform_driver at91_udc = { static int __init udc_init_module(void) { - return platform_driver_probe(&at91_udc, at91udc_probe); + return platform_driver_probe(&at91_udc_driver, at91udc_probe); } module_init(udc_init_module); static void __exit udc_exit_module(void) { - platform_driver_unregister(&at91_udc); + platform_driver_unregister(&at91_udc_driver); } module_exit(udc_exit_module); diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 7b3a326b57a..65c91d3735d 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -297,27 +297,6 @@ goku_free_request(struct usb_ep *_ep, struct usb_request *_req) /*-------------------------------------------------------------------------*/ -#undef USE_KMALLOC - -/* many common platforms have dma-coherent caches, which means that it's - * safe to use kmalloc() memory for all i/o buffers without using any - * cache flushing calls. (unless you're trying to share cache lines - * between dma and non-dma activities, which is a slow idea in any case.) - * - * other platforms need more care, with 2.6 having a moderately general - * solution except for the common "buffer is smaller than a page" case. - */ -#if defined(CONFIG_X86) -#define USE_KMALLOC - -#elif defined(CONFIG_MIPS) && !defined(CONFIG_DMA_NONCOHERENT) -#define USE_KMALLOC - -#elif defined(CONFIG_PPC) && !defined(CONFIG_NOT_COHERENT_CACHE) -#define USE_KMALLOC - -#endif - /* allocating buffers this way eliminates dma mapping overhead, which * on some platforms will mean eliminating a per-io buffer copy. with * some kinds of system caches, further tweaks may still be needed. @@ -334,11 +313,6 @@ goku_alloc_buffer(struct usb_ep *_ep, unsigned bytes, return NULL; *dma = DMA_ADDR_INVALID; -#if defined(USE_KMALLOC) - retval = kmalloc(bytes, gfp_flags); - if (retval) - *dma = virt_to_phys(retval); -#else if (ep->dma) { /* the main problem with this call is that it wastes memory * on typical 1/N page allocations: it allocates 1-N pages. @@ -348,7 +322,6 @@ goku_alloc_buffer(struct usb_ep *_ep, unsigned bytes, bytes, dma, gfp_flags); } else retval = kmalloc(bytes, gfp_flags); -#endif return retval; } @@ -356,7 +329,6 @@ static void goku_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma, unsigned bytes) { /* free memory into the right allocator */ -#ifndef USE_KMALLOC if (dma != DMA_ADDR_INVALID) { struct goku_ep *ep; @@ -365,7 +337,6 @@ goku_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma, unsigned bytes) return; dma_free_coherent(&ep->dev->pdev->dev, bytes, buf, dma); } else -#endif kfree (buf); } diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 8f9a2b61542..b394e63894d 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -296,6 +296,15 @@ omap_free_request(struct usb_ep *ep, struct usb_request *_req) /*-------------------------------------------------------------------------*/ +/* + * dma-coherent memory allocation (for dma-capable endpoints) + * + * NOTE: the dma_*_coherent() API calls suck. Most implementations are + * (a) page-oriented, so small buffers lose big; and (b) asymmetric with + * respect to calls with irqs disabled: alloc is safe, free is not. + * We currently work around (b), but not (a). + */ + static void * omap_alloc_buffer( struct usb_ep *_ep, @@ -307,6 +316,9 @@ omap_alloc_buffer( void *retval; struct omap_ep *ep; + if (!_ep) + return NULL; + ep = container_of(_ep, struct omap_ep, ep); if (use_dma && ep->has_dma) { static int warned; @@ -326,6 +338,35 @@ omap_alloc_buffer( return retval; } +static DEFINE_SPINLOCK(buflock); +static LIST_HEAD(buffers); + +struct free_record { + struct list_head list; + struct device *dev; + unsigned bytes; + dma_addr_t dma; +}; + +static void do_free(unsigned long ignored) +{ + spin_lock_irq(&buflock); + while (!list_empty(&buffers)) { + struct free_record *buf; + + buf = list_entry(buffers.next, struct free_record, list); + list_del(&buf->list); + spin_unlock_irq(&buflock); + + dma_free_coherent(buf->dev, buf->bytes, buf, buf->dma); + + spin_lock_irq(&buflock); + } + spin_unlock_irq(&buflock); +} + +static DECLARE_TASKLET(deferred_free, do_free, 0); + static void omap_free_buffer( struct usb_ep *_ep, void *buf, @@ -333,13 +374,29 @@ static void omap_free_buffer( unsigned bytes ) { - struct omap_ep *ep; + if (!_ep) { + WARN_ON(1); + return; + } - ep = container_of(_ep, struct omap_ep, ep); - if (use_dma && _ep && ep->has_dma) - dma_free_coherent(ep->udc->gadget.dev.parent, bytes, buf, dma); - else - kfree (buf); + /* free memory into the right allocator */ + if (dma != DMA_ADDR_INVALID) { + struct omap_ep *ep; + struct free_record *rec = buf; + unsigned long flags; + + ep = container_of(_ep, struct omap_ep, ep); + + rec->dev = ep->udc->gadget.dev.parent; + rec->bytes = bytes; + rec->dma = dma; + + spin_lock_irqsave(&buflock, flags); + list_add_tail(&rec->list, &buffers); + tasklet_schedule(&deferred_free); + spin_unlock_irqrestore(&buflock, flags); + } else + kfree(buf); } /*-------------------------------------------------------------------------*/ @@ -1691,12 +1748,38 @@ ep0out_status_stage: udc->ep0_pending = 0; break; case USB_REQ_GET_STATUS: + /* USB_ENDPOINT_HALT status? */ + if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT)) + goto intf_status; + + /* ep0 never stalls */ + if (!(w_index & 0xf)) + goto zero_status; + + /* only active endpoints count */ + ep = &udc->ep[w_index & 0xf]; + if (w_index & USB_DIR_IN) + ep += 16; + if (!ep->desc) + goto do_stall; + + /* iso never stalls */ + if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) + goto zero_status; + + /* FIXME don't assume non-halted endpoints!! */ + ERR("%s status, can't report\n", ep->ep.name); + goto do_stall; + +intf_status: /* return interface status. if we were pedantic, * we'd detect non-existent interfaces, and stall. */ if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)) goto delegate; + +zero_status: /* return two zero bytes */ UDC_EP_NUM_REG = UDC_EP_SEL|UDC_EP_DIR; UDC_DATA_REG = 0; @@ -2068,7 +2151,7 @@ static irqreturn_t omap_udc_iso_irq(int irq, void *_dev) /*-------------------------------------------------------------------------*/ -static inline int machine_needs_vbus_session(void) +static inline int machine_without_vbus_sense(void) { return (machine_is_omap_innovator() || machine_is_omap_osk() @@ -2156,7 +2239,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) /* boards that don't have VBUS sensing can't autogate 48MHz; * can't enter deep sleep while a gadget driver is active. */ - if (machine_needs_vbus_session()) + if (machine_without_vbus_sense()) omap_vbus_session(&udc->gadget, 1); done: @@ -2179,7 +2262,7 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) if (udc->dc_clk != NULL) omap_udc_enable_clock(1); - if (machine_needs_vbus_session()) + if (machine_without_vbus_sense()) omap_vbus_session(&udc->gadget, 0); if (udc->transceiver) @@ -2822,7 +2905,7 @@ static int __init omap_udc_probe(struct platform_device *pdev) hmc = HMC_1510; type = "(unknown)"; - if (machine_is_omap_innovator() || machine_is_sx1()) { + if (machine_without_vbus_sense()) { /* just set up software VBUS detect, and then * later rig it so we always report VBUS. * FIXME without really sensing VBUS, we can't diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index a7405648823..c7458f7e56c 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -669,6 +669,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) */ ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); + mod_timer(&hcd->rh_timer, ehci->reset_done[i]); } } diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 9af529d22b3..1813b7cac29 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -653,8 +653,7 @@ static int ehci_hub_control ( if (status & ~0xffff) /* only if wPortChange is interesting */ #endif dbg_port (ehci, "GetStatus", wIndex + 1, temp); - // we "know" this alignment is good, caller used kmalloc()... - *((__le32 *) buf) = cpu_to_le32 (status); + put_unaligned(cpu_to_le32 (status), (__le32 *) buf); break; case SetHubFeature: switch (wValue) { diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index 8d24d3dc0a6..1497371583b 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c @@ -145,7 +145,8 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space) return out - buf; } -static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) +static int uhci_show_qh(struct uhci_hcd *uhci, + struct uhci_qh *qh, char *buf, int len, int space) { char *out = buf; int i, nurbs; @@ -190,6 +191,9 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) if (list_empty(&qh->queue)) { out += sprintf(out, "%*s queue is empty\n", space, ""); + if (qh == uhci->skel_async_qh) + out += uhci_show_td(uhci->term_td, out, + len - (out - buf), 0); } else { struct urb_priv *urbp = list_entry(qh->queue.next, struct urb_priv, node); @@ -343,6 +347,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) struct list_head *tmp, *head; int nframes, nerrs; __le32 link; + __le32 fsbr_link; static const char * const qh_names[] = { "unlink", "iso", "int128", "int64", "int32", "int16", @@ -424,21 +429,22 @@ check_link: out += sprintf(out, "Skeleton QHs\n"); + fsbr_link = 0; for (i = 0; i < UHCI_NUM_SKELQH; ++i) { int cnt = 0; - __le32 fsbr_link = 0; qh = uhci->skelqh[i]; out += sprintf(out, "- skel_%s_qh\n", qh_names[i]); \ - out += uhci_show_qh(qh, out, len - (out - buf), 4); + out += uhci_show_qh(uhci, qh, out, len - (out - buf), 4); /* Last QH is the Terminating QH, it's different */ if (i == SKEL_TERM) { if (qh_element(qh) != LINK_TO_TD(uhci->term_td)) out += sprintf(out, " skel_term_qh element is not set to term_td!\n"); - if (link == LINK_TO_QH(uhci->skel_term_qh)) - goto check_qh_link; - continue; + link = fsbr_link; + if (!link) + link = LINK_TO_QH(uhci->skel_term_qh); + goto check_qh_link; } head = &qh->node; @@ -448,7 +454,7 @@ check_link: qh = list_entry(tmp, struct uhci_qh, node); tmp = tmp->next; if (++cnt <= 10) - out += uhci_show_qh(qh, out, + out += uhci_show_qh(uhci, qh, out, len - (out - buf), 4); if (!fsbr_link && qh->skel >= SKEL_FSBR) fsbr_link = LINK_TO_QH(qh); @@ -463,8 +469,6 @@ check_link: link = LINK_TO_QH(uhci->skel_async_qh); else if (!uhci->fsbr_is_on) ; - else if (fsbr_link) - link = fsbr_link; else link = LINK_TO_QH(uhci->skel_term_qh); check_qh_link: @@ -573,8 +577,8 @@ static const struct file_operations uhci_debug_operations = { static inline void lprintk(char *buf) {} -static inline int uhci_show_qh(struct uhci_qh *qh, char *buf, - int len, int space) +static inline int uhci_show_qh(struct uhci_hcd *uhci, + struct uhci_qh *qh, char *buf, int len, int space) { return 0; } diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 44da4334f1d..d22da26ff16 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -632,7 +632,8 @@ static int uhci_start(struct usb_hcd *hcd) */ for (i = SKEL_ISO + 1; i < SKEL_ASYNC; ++i) uhci->skelqh[i]->link = LINK_TO_QH(uhci->skel_async_qh); - uhci->skel_async_qh->link = uhci->skel_term_qh->link = UHCI_PTR_TERM; + uhci->skel_async_qh->link = UHCI_PTR_TERM; + uhci->skel_term_qh->link = LINK_TO_QH(uhci->skel_term_qh); /* This dummy TD is to work around a bug in Intel PIIX controllers */ uhci_fill_td(uhci->term_td, 0, uhci_explen(0) | diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index bacc25c53ba..8e4427aebb1 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c @@ -33,6 +33,9 @@ static __u8 root_hub_hub_des[] = /* status change bits: nonzero writes will clear */ #define RWC_BITS (USBPORTSC_OCC | USBPORTSC_PEC | USBPORTSC_CSC) +/* suspend/resume bits: port suspended or port resuming */ +#define SUSPEND_BITS (USBPORTSC_SUSP | USBPORTSC_RD) + /* A port that either is connected or has a changed-bit set will prevent * us from AUTO_STOPPING. */ @@ -96,8 +99,8 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port, int status; int i; - if (inw(port_addr) & (USBPORTSC_SUSP | USBPORTSC_RD)) { - CLR_RH_PORTSTAT(USBPORTSC_SUSP | USBPORTSC_RD); + if (inw(port_addr) & SUSPEND_BITS) { + CLR_RH_PORTSTAT(SUSPEND_BITS); if (test_bit(port, &uhci->resuming_ports)) set_bit(port, &uhci->port_c_suspend); @@ -107,7 +110,7 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port, * Experiments show that some controllers take longer, so * we'll poll for completion. */ for (i = 0; i < 10; ++i) { - if (!(inw(port_addr) & USBPORTSC_RD)) + if (!(inw(port_addr) & SUSPEND_BITS)) break; udelay(1); } @@ -289,7 +292,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, wPortStatus |= USB_PORT_STAT_CONNECTION; if (status & USBPORTSC_PE) { wPortStatus |= USB_PORT_STAT_ENABLE; - if (status & (USBPORTSC_SUSP | USBPORTSC_RD)) + if (status & SUSPEND_BITS) wPortStatus |= USB_PORT_STAT_SUSPEND; } if (status & USBPORTSC_OC) diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index f4ebdb3e488..19a0cc02b9a 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -45,43 +45,27 @@ static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci) */ static void uhci_fsbr_on(struct uhci_hcd *uhci) { - struct uhci_qh *fsbr_qh, *lqh, *tqh; + struct uhci_qh *lqh; + /* The terminating skeleton QH always points back to the first + * FSBR QH. Make the last async QH point to the terminating + * skeleton QH. */ uhci->fsbr_is_on = 1; lqh = list_entry(uhci->skel_async_qh->node.prev, struct uhci_qh, node); - - /* Find the first FSBR QH. Linear search through the list is - * acceptable because normally FSBR gets turned on as soon as - * one QH needs it. */ - fsbr_qh = NULL; - list_for_each_entry_reverse(tqh, &uhci->skel_async_qh->node, node) { - if (tqh->skel < SKEL_FSBR) - break; - fsbr_qh = tqh; - } - - /* No FSBR QH means we must insert the terminating skeleton QH */ - if (!fsbr_qh) { - uhci->skel_term_qh->link = LINK_TO_QH(uhci->skel_term_qh); - wmb(); - lqh->link = uhci->skel_term_qh->link; - - /* Otherwise loop the last QH to the first FSBR QH */ - } else - lqh->link = LINK_TO_QH(fsbr_qh); + lqh->link = LINK_TO_QH(uhci->skel_term_qh); } static void uhci_fsbr_off(struct uhci_hcd *uhci) { struct uhci_qh *lqh; + /* Remove the link from the last async QH to the terminating + * skeleton QH. */ uhci->fsbr_is_on = 0; lqh = list_entry(uhci->skel_async_qh->node.prev, struct uhci_qh, node); - - /* End the async list normally and unlink the terminating QH */ - lqh->link = uhci->skel_term_qh->link = UHCI_PTR_TERM; + lqh->link = UHCI_PTR_TERM; } static void uhci_add_fsbr(struct uhci_hcd *uhci, struct urb *urb) @@ -464,9 +448,8 @@ static void link_interrupt(struct uhci_hcd *uhci, struct uhci_qh *qh) */ static void link_async(struct uhci_hcd *uhci, struct uhci_qh *qh) { - struct uhci_qh *pqh, *lqh; + struct uhci_qh *pqh; __le32 link_to_new_qh; - __le32 *extra_link = &link_to_new_qh; /* Find the predecessor QH for our new one and insert it in the list. * The list of QHs is expected to be short, so linear search won't @@ -476,31 +459,17 @@ static void link_async(struct uhci_hcd *uhci, struct uhci_qh *qh) break; } list_add(&qh->node, &pqh->node); - qh->link = pqh->link; - - link_to_new_qh = LINK_TO_QH(qh); - - /* If this is now the first FSBR QH, take special action */ - if (uhci->fsbr_is_on && pqh->skel < SKEL_FSBR && - qh->skel >= SKEL_FSBR) { - lqh = list_entry(uhci->skel_async_qh->node.prev, - struct uhci_qh, node); - - /* If the new QH is also the last one, we must unlink - * the terminating skeleton QH and make the new QH point - * back to itself. */ - if (qh == lqh) { - qh->link = link_to_new_qh; - extra_link = &uhci->skel_term_qh->link; - - /* Otherwise the last QH must point to the new QH */ - } else - extra_link = &lqh->link; - } /* Link it into the schedule */ + qh->link = pqh->link; wmb(); - *extra_link = pqh->link = link_to_new_qh; + link_to_new_qh = LINK_TO_QH(qh); + pqh->link = link_to_new_qh; + + /* If this is now the first FSBR QH, link the terminating skeleton + * QH to it. */ + if (pqh->skel < SKEL_FSBR && qh->skel >= SKEL_FSBR) + uhci->skel_term_qh->link = link_to_new_qh; } /* @@ -561,31 +530,16 @@ static void unlink_interrupt(struct uhci_hcd *uhci, struct uhci_qh *qh) */ static void unlink_async(struct uhci_hcd *uhci, struct uhci_qh *qh) { - struct uhci_qh *pqh, *lqh; + struct uhci_qh *pqh; __le32 link_to_next_qh = qh->link; pqh = list_entry(qh->node.prev, struct uhci_qh, node); - - /* If this is the first FSBQ QH, take special action */ - if (uhci->fsbr_is_on && pqh->skel < SKEL_FSBR && - qh->skel >= SKEL_FSBR) { - lqh = list_entry(uhci->skel_async_qh->node.prev, - struct uhci_qh, node); - - /* If this QH is also the last one, we must link in - * the terminating skeleton QH. */ - if (qh == lqh) { - link_to_next_qh = LINK_TO_QH(uhci->skel_term_qh); - uhci->skel_term_qh->link = link_to_next_qh; - wmb(); - qh->link = link_to_next_qh; - - /* Otherwise the last QH must point to the new first FSBR QH */ - } else - lqh->link = link_to_next_qh; - } - pqh->link = link_to_next_qh; + + /* If this was the old first FSBR QH, link the terminating skeleton + * QH to the next (new first FSBR) QH. */ + if (pqh->skel < SKEL_FSBR && qh->skel >= SKEL_FSBR) + uhci->skel_term_qh->link = link_to_next_qh; mb(); } @@ -1217,7 +1171,7 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) if (debug > 1 && errbuf) { /* Print the chain for debugging */ - uhci_show_qh(urbp->qh, errbuf, + uhci_show_qh(uhci, urbp->qh, errbuf, ERRBUF_LEN, 0); lprintk(errbuf); } diff --git a/drivers/usb/misc/berry_charge.c b/drivers/usb/misc/berry_charge.c index 60893c6c822..b15f2fd8dab 100644 --- a/drivers/usb/misc/berry_charge.c +++ b/drivers/usb/misc/berry_charge.c @@ -69,7 +69,7 @@ static int magic_charge(struct usb_device *udev) return retval; } - dbg(&udev->dev, "Sending first magic command\n"); + dbg(&udev->dev, "Sending second magic command\n"); retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0xa2, 0x40, 0, 1, dummy_buffer, 0, 100); if (retval != 0) { diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 0c1d66ddb81..bc3327e3dd7 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -2905,17 +2905,31 @@ static int __init ftdi_elan_init(void) { int result; printk(KERN_INFO "driver %s built at %s on %s\n", ftdi_elan_driver.name, - __TIME__, __DATE__); + __TIME__, __DATE__); init_MUTEX(&ftdi_module_lock); INIT_LIST_HEAD(&ftdi_static_list); status_queue = create_singlethread_workqueue("ftdi-status-control"); + if (!status_queue) + goto err1; command_queue = create_singlethread_workqueue("ftdi-command-engine"); + if (!command_queue) + goto err2; respond_queue = create_singlethread_workqueue("ftdi-respond-engine"); + if (!respond_queue) + goto err3; result = usb_register(&ftdi_elan_driver); if (result) printk(KERN_ERR "usb_register failed. Error number %d\n", - result); + result); return result; + + err3: + destroy_workqueue(command_queue); + err2: + destroy_workqueue(status_queue); + err1: + printk(KERN_ERR "%s couldn't create workqueue\n", ftdi_elan_driver.name); + return -ENOMEM; } static void __exit ftdi_elan_exit(void) diff --git a/drivers/usb/net/dm9601.c b/drivers/usb/net/dm9601.c index 4a932e1cd93..5130cc7eb31 100644 --- a/drivers/usb/net/dm9601.c +++ b/drivers/usb/net/dm9601.c @@ -571,9 +571,21 @@ static const struct driver_info dm9601_info = { static const struct usb_device_id products[] = { { + USB_DEVICE(0x07aa, 0x9601), /* Corega FEther USB-TXC */ + .driver_info = (unsigned long)&dm9601_info, + }, + { USB_DEVICE(0x0a46, 0x9601), /* Davicom USB-100 */ .driver_info = (unsigned long)&dm9601_info, }, + { + USB_DEVICE(0x0a46, 0x6688), /* ZT6688 USB NIC */ + .driver_info = (unsigned long)&dm9601_info, + }, + { + USB_DEVICE(0x0a46, 0x0268), /* ShanTou ST268 USB NIC */ + .driver_info = (unsigned long)&dm9601_info, + }, {}, // END }; diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c index 18816bf96a4..39a49836259 100644 --- a/drivers/usb/serial/airprime.c +++ b/drivers/usb/serial/airprime.c @@ -18,11 +18,6 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */ - { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */ - { USB_DEVICE(0x1410, 0x1130) }, /* Novatel Wireless S720 CDMA/EV-DO */ - { USB_DEVICE(0x1410, 0x2110) }, /* Novatel Wireless U720 CDMA/EV-DO */ - { USB_DEVICE(0x1410, 0x1430) }, /* Novatel Merlin XU870 HSDPA/3G */ - { USB_DEVICE(0x1410, 0x1100) }, /* ExpressCard34 Qualcomm 3G CDMA */ { USB_DEVICE(0x413c, 0x8115) }, /* Dell Wireless HSDPA 5500 */ { }, }; @@ -44,8 +39,43 @@ struct airprime_private { int outstanding_urbs; int throttled; struct urb *read_urbp[NUM_READ_URBS]; + + /* Settings for the port */ + int rts_state; /* Handshaking pins (outputs) */ + int dtr_state; + int cts_state; /* Handshaking pins (inputs) */ + int dsr_state; + int dcd_state; + int ri_state; }; +static int airprime_send_setup(struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; + struct airprime_private *priv; + + dbg("%s", __FUNCTION__); + + if (port->number != 0) + return 0; + + priv = usb_get_serial_port_data(port); + + if (port->tty) { + int val = 0; + if (priv->dtr_state) + val |= 0x01; + if (priv->rts_state) + val |= 0x02; + + return usb_control_msg(serial->dev, + usb_rcvctrlpipe(serial->dev, 0), + 0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT); + } + + return 0; +} + static void airprime_read_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; @@ -118,6 +148,10 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp) usb_set_serial_port_data(port, priv); } + /* Set some sane defaults */ + priv->rts_state = 1; + priv->dtr_state = 1; + for (i = 0; i < NUM_READ_URBS; ++i) { buffer = kmalloc(buffer_size, GFP_KERNEL); if (!buffer) { @@ -151,6 +185,9 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp) /* remember this urb so we can kill it when the port is closed */ priv->read_urbp[i] = urb; } + + airprime_send_setup(port); + goto out; errout: @@ -176,6 +213,11 @@ static void airprime_close(struct usb_serial_port *port, struct file * filp) dbg("%s - port %d", __FUNCTION__, port->number); + priv->rts_state = 0; + priv->dtr_state = 0; + + airprime_send_setup(port); + for (i = 0; i < NUM_READ_URBS; ++i) { usb_kill_urb (priv->read_urbp[i]); kfree (priv->read_urbp[i]->transfer_buffer); diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index db623e75489..d7d0ba986a8 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -63,6 +63,8 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ { USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */ + { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */ + { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */ { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */ { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */ diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index c525b42dadd..8ff9d54b21e 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -315,6 +315,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_SIO_PID) }, { USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) }, { USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_232RL_PID) }, { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) }, { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) }, @@ -420,6 +421,14 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_ELV_ALC8500_PID) }, { USB_DEVICE(FTDI_VID, FTDI_PYRAMID_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1000PC_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_IBS_US485_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_IBS_PICPRO_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_IBS_PCMCIA_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_IBS_PK1_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_IBS_RS232MON_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_IBS_APP70_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) }, /* * These will probably use user-space drivers. Uncomment them if * you need them or use the user-specified vendor/product module @@ -459,6 +468,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FALCOM_VID, FALCOM_TWIST_PID) }, { USB_DEVICE(FALCOM_VID, FALCOM_SAMBA_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SUUNTO_SPORTS_PID) }, + { USB_DEVICE(TTI_VID, TTI_QL355P_PID) }, { USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) }, { USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) }, { USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) }, @@ -533,6 +543,7 @@ static const char *ftdi_chip_name[] = { [FT8U232AM] = "FT8U232AM", [FT232BM] = "FT232BM", [FT2232C] = "FT2232C", + [FT232RL] = "FT232RL", }; @@ -588,6 +599,8 @@ struct ftdi_private { static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id); static int ftdi_sio_attach (struct usb_serial *serial); static void ftdi_shutdown (struct usb_serial *serial); +static int ftdi_sio_port_probe (struct usb_serial_port *port); +static int ftdi_sio_port_remove (struct usb_serial_port *port); static int ftdi_open (struct usb_serial_port *port, struct file *filp); static void ftdi_close (struct usb_serial_port *port, struct file *filp); static int ftdi_write (struct usb_serial_port *port, const unsigned char *buf, int count); @@ -622,6 +635,8 @@ static struct usb_serial_driver ftdi_sio_device = { .num_bulk_out = 1, .num_ports = 1, .probe = ftdi_sio_probe, + .port_probe = ftdi_sio_port_probe, + .port_remove = ftdi_sio_port_remove, .open = ftdi_open, .close = ftdi_close, .throttle = ftdi_throttle, @@ -864,6 +879,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port) break; case FT232BM: /* FT232BM chip */ case FT2232C: /* FT2232C chip */ + case FT232RL: if (baud <= 3000000) { div_value = ftdi_232bm_baud_to_divisor(baud); } else { @@ -1006,9 +1022,12 @@ static void ftdi_determine_type(struct usb_serial_port *port) /* (It might be a BM because of the iSerialNumber bug, * but it will still work as an AM device.) */ priv->chip_type = FT8U232AM; - } else { + } else if (version < 0x600) { /* Assume its an FT232BM (or FT245BM) */ priv->chip_type = FT232BM; + } else { + /* Assume its an FT232R */ + priv->chip_type = FT232RL; } info("Detected %s", ftdi_chip_name[priv->chip_type]); } @@ -1024,11 +1043,10 @@ static ssize_t show_latency_timer(struct device *dev, struct device_attribute *a { struct usb_serial_port *port = to_usb_serial_port(dev); struct ftdi_private *priv = usb_get_serial_port_data(port); - struct usb_device *udev; + struct usb_device *udev = port->serial->dev; unsigned short latency = 0; int rv = 0; - udev = to_usb_device(dev); dbg("%s",__FUNCTION__); @@ -1052,13 +1070,11 @@ static ssize_t store_latency_timer(struct device *dev, struct device_attribute * { struct usb_serial_port *port = to_usb_serial_port(dev); struct ftdi_private *priv = usb_get_serial_port_data(port); - struct usb_device *udev; + struct usb_device *udev = port->serial->dev; char buf[1]; int v = simple_strtoul(valbuf, NULL, 10); int rv = 0; - udev = to_usb_device(dev); - dbg("%s: setting latency timer = %i", __FUNCTION__, v); rv = usb_control_msg(udev, @@ -1083,13 +1099,11 @@ static ssize_t store_event_char(struct device *dev, struct device_attribute *att { struct usb_serial_port *port = to_usb_serial_port(dev); struct ftdi_private *priv = usb_get_serial_port_data(port); - struct usb_device *udev; + struct usb_device *udev = port->serial->dev; char buf[1]; int v = simple_strtoul(valbuf, NULL, 10); int rv = 0; - udev = to_usb_device(dev); - dbg("%s: setting event char = %i", __FUNCTION__, v); rv = usb_control_msg(udev, @@ -1110,46 +1124,38 @@ static ssize_t store_event_char(struct device *dev, struct device_attribute *att static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, store_latency_timer); static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char); -static int create_sysfs_attrs(struct usb_serial *serial) +static int create_sysfs_attrs(struct usb_serial_port *port) { - struct ftdi_private *priv; - struct usb_device *udev; + struct ftdi_private *priv = usb_get_serial_port_data(port); int retval = 0; dbg("%s",__FUNCTION__); - priv = usb_get_serial_port_data(serial->port[0]); - udev = serial->dev; - /* XXX I've no idea if the original SIO supports the event_char * sysfs parameter, so I'm playing it safe. */ if (priv->chip_type != SIO) { dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]); - retval = device_create_file(&udev->dev, &dev_attr_event_char); + retval = device_create_file(&port->dev, &dev_attr_event_char); if ((!retval) && (priv->chip_type == FT232BM || priv->chip_type == FT2232C)) { - retval = device_create_file(&udev->dev, + retval = device_create_file(&port->dev, &dev_attr_latency_timer); } } return retval; } -static void remove_sysfs_attrs(struct usb_serial *serial) +static void remove_sysfs_attrs(struct usb_serial_port *port) { - struct ftdi_private *priv; - struct usb_device *udev; + struct ftdi_private *priv = usb_get_serial_port_data(port); dbg("%s",__FUNCTION__); - priv = usb_get_serial_port_data(serial->port[0]); - udev = serial->dev; - /* XXX see create_sysfs_attrs */ if (priv->chip_type != SIO) { - device_remove_file(&udev->dev, &dev_attr_event_char); + device_remove_file(&port->dev, &dev_attr_event_char); if (priv->chip_type == FT232BM || priv->chip_type == FT2232C) { - device_remove_file(&udev->dev, &dev_attr_latency_timer); + device_remove_file(&port->dev, &dev_attr_latency_timer); } } @@ -1169,13 +1175,9 @@ static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id return (0); } -/* attach subroutine */ -static int ftdi_sio_attach (struct usb_serial *serial) +static int ftdi_sio_port_probe(struct usb_serial_port *port) { - struct usb_serial_port *port = serial->port[0]; struct ftdi_private *priv; - struct ftdi_sio_quirk *quirk; - int retval; dbg("%s",__FUNCTION__); @@ -1215,19 +1217,21 @@ static int ftdi_sio_attach (struct usb_serial *serial) kfree(port->bulk_out_buffer); port->bulk_out_buffer = NULL; - usb_set_serial_port_data(serial->port[0], priv); + usb_set_serial_port_data(port, priv); - ftdi_determine_type (serial->port[0]); - retval = create_sysfs_attrs(serial); - if (retval) - dev_err(&serial->dev->dev, "Error creating sysfs files, " - "continuing\n"); + ftdi_determine_type (port); + create_sysfs_attrs(port); + return 0; +} +/* attach subroutine */ +static int ftdi_sio_attach (struct usb_serial *serial) +{ /* Check for device requiring special set up. */ - quirk = (struct ftdi_sio_quirk *)usb_get_serial_data(serial); - if (quirk && quirk->setup) { + struct ftdi_sio_quirk *quirk = usb_get_serial_data(serial); + + if (quirk && quirk->setup) quirk->setup(serial); - } return 0; } /* ftdi_sio_attach */ @@ -1271,17 +1275,18 @@ static void ftdi_HE_TIRA1_setup (struct usb_serial *serial) * calls __serial_close for each open of the port * shutdown is called then (ie ftdi_shutdown) */ - - static void ftdi_shutdown (struct usb_serial *serial) -{ /* ftdi_shutdown */ +{ + dbg("%s", __FUNCTION__); +} - struct usb_serial_port *port = serial->port[0]; +static int ftdi_sio_port_remove(struct usb_serial_port *port) +{ struct ftdi_private *priv = usb_get_serial_port_data(port); dbg("%s", __FUNCTION__); - remove_sysfs_attrs(serial); + remove_sysfs_attrs(port); /* all open ports are closed at this point * (by usbserial.c:__serial_close, which calls ftdi_close) @@ -1291,8 +1296,9 @@ static void ftdi_shutdown (struct usb_serial *serial) usb_set_serial_port_data(port, NULL); kfree(priv); } -} /* ftdi_shutdown */ + return 0; +} static int ftdi_open (struct usb_serial_port *port, struct file *filp) { /* ftdi_open */ diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 1bdda935f7d..513cfe1b768 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -27,6 +27,7 @@ #define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */ #define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */ #define FTDI_8U2232C_PID 0x6010 /* Dual channel device */ +#define FTDI_232RL_PID 0xFBFA /* Product ID for FT232RL */ #define FTDI_RELAIS_PID 0xFA10 /* Relais device from Rudolf Gugler */ #define FTDI_NF_RIC_VID 0x0DCD /* Vendor Id */ #define FTDI_NF_RIC_PID 0x0001 /* Product Id */ @@ -339,6 +340,12 @@ #define FTDI_SUUNTO_SPORTS_PID 0xF680 /* Suunto Sports instrument */ /* + * TTi (Thurlby Thandar Instruments) + */ +#define TTI_VID 0x103E /* Vendor Id */ +#define TTI_QL355P_PID 0x03E8 /* TTi QL355P power supply */ + +/* * Definitions for B&B Electronics products. */ #define BANDB_VID 0x0856 /* B&B Electronics Vendor ID */ @@ -497,6 +504,19 @@ #define TELLDUS_VID 0x1781 /* Vendor ID */ #define TELLDUS_TELLSTICK_PID 0x0C30 /* RF control dongle 433 MHz using FT232RL */ +/* + * IBS elektronik product ids + * Submitted by Thomas Schleusener + */ +#define FTDI_IBS_US485_PID 0xff38 /* IBS US485 (USB<-->RS422/485 interface) */ +#define FTDI_IBS_PICPRO_PID 0xff39 /* IBS PIC-Programmer */ +#define FTDI_IBS_PCMCIA_PID 0xff3a /* IBS Card reader for PCMCIA SRAM-cards */ +#define FTDI_IBS_PK1_PID 0xff3b /* IBS PK1 - Particel counter */ +#define FTDI_IBS_RS232MON_PID 0xff3c /* IBS RS232 - Monitor */ +#define FTDI_IBS_APP70_PID 0xff3d /* APP 70 (dust monitoring system) */ +#define FTDI_IBS_PEDO_PID 0xff3e /* IBS PEDO-Modem (RF modem 868.35 MHz) */ +#define FTDI_IBS_PROD_PID 0xff3f /* future device */ + /* Commands */ #define FTDI_SIO_RESET 0 /* Reset the port */ #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ @@ -620,6 +640,7 @@ typedef enum { FT8U232AM = 2, FT232BM = 3, FT2232C = 4, + FT232RL = 5, } ftdi_chip_type_t; typedef enum { diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 53baeec8f26..4f8282ad772 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -20,13 +20,14 @@ #include <linux/usb/serial.h> #include <asm/uaccess.h> -static int generic_probe(struct usb_interface *interface, - const struct usb_device_id *id); - static int debug; #ifdef CONFIG_USB_SERIAL_GENERIC + +static int generic_probe(struct usb_interface *interface, + const struct usb_device_id *id); + static __u16 vendor = 0x05f9; static __u16 product = 0xffff; diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index a408184334e..d16e2e1764a 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c @@ -247,6 +247,8 @@ static struct usb_device_id ipaq_id_table [] = { { USB_DEVICE(0x04AD, 0x0301) }, /* USB Sync 0301 */ { USB_DEVICE(0x04AD, 0x0302) }, /* USB Sync 0302 */ { USB_DEVICE(0x04AD, 0x0303) }, /* USB Sync 0303 */ + { USB_DEVICE(0x04AD, 0x0306) }, /* GPS Pocket PC USB Sync */ + { USB_DEVICE(0x04B7, 0x0531) }, /* MyGuide 7000 XL USB Sync */ { USB_DEVICE(0x04C5, 0x1058) }, /* FUJITSU USB Sync */ { USB_DEVICE(0x04C5, 0x1079) }, /* FUJITSU USB Sync */ { USB_DEVICE(0x04DA, 0x2500) }, /* Panasonic USB Sync */ diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 2d588fb8257..19bf403f9db 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -1628,6 +1628,7 @@ static struct usb_serial_driver moschip7720_2port_driver = { .chars_in_buffer = mos7720_chars_in_buffer, .break_ctl = mos7720_break, .read_bulk_callback = mos7720_bulk_in_callback, + .read_int_callback = mos7720_interrupt_callback, }; static int __init moschip7720_init(void) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index db92a7fb1f7..e178e6f4031 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -109,7 +109,6 @@ static int option_send_setup(struct usb_serial_port *port); #define HUAWEI_PRODUCT_E220 0x1003 #define NOVATELWIRELESS_VENDOR_ID 0x1410 -#define NOVATELWIRELESS_PRODUCT_U740 0x1400 #define ANYDATA_VENDOR_ID 0x16d5 #define ANYDATA_PRODUCT_ID 0x6501 @@ -152,7 +151,19 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_NETWORK) }, { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) }, - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1100) }, /* Novatel Merlin XS620/S640 */ + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1110) }, /* Novatel Merlin S620 */ + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1120) }, /* Novatel Merlin EX720 */ + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1130) }, /* Novatel Merlin S720 */ + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1400) }, /* Novatel U730 */ + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1410) }, /* Novatel U740 */ + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1420) }, /* Novatel EU870 */ + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1430) }, /* Novatel Merlin XU870 HSDPA/3G */ + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1430) }, /* Novatel XU870 */ + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2100) }, /* Novatel EV620 CDMA/EV-DO */ + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2110) }, /* Novatel Merlin ES620 / Merlin ES720 / Ovation U720 */ + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2130) }, /* Novatel Merlin ES620 SM Bus */ + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2410) }, /* Novatel EU740 */ { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 6bf22a28adb..7639022cdf8 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -99,9 +99,12 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po continue; *minor = i; + j = 0; dbg("%s - minor base = %d", __FUNCTION__, *minor); - for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) + for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) { serial_table[i] = serial; + serial->port[j++]->number = i; + } spin_unlock(&table_lock); return serial; } @@ -826,7 +829,6 @@ int usb_serial_probe(struct usb_interface *interface, num_ports = type->num_ports; } - serial->minor = minor; serial->num_ports = num_ports; serial->num_bulk_in = num_bulk_in; serial->num_bulk_out = num_bulk_out; @@ -847,7 +849,6 @@ int usb_serial_probe(struct usb_interface *interface, port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL); if (!port) goto probe_error; - port->number = i + serial->minor; port->serial = serial; spin_lock_init(&port->lock); mutex_init(&port->mutex); @@ -980,6 +981,7 @@ int usb_serial_probe(struct usb_interface *interface, dev_err(&interface->dev, "No more free serial devices\n"); goto probe_error; } + serial->minor = minor; /* register all of the individual ports with the driver core */ for (i = 0; i < num_ports; ++i) { @@ -1034,9 +1036,6 @@ probe_error: kfree(port->interrupt_out_buffer); } - /* return the minor range that this device had */ - return_serial (serial); - /* free up any memory that we allocated */ for (i = 0; i < serial->num_port_pointers; ++i) kfree(serial->port[i]); diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 9644a8ea4aa..4a9d0d5c728 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -146,6 +146,13 @@ UNUSUAL_DEV( 0x0420, 0x0001, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), +/* Reported by Andrew Nayenko <relan@bk.ru> */ +UNUSUAL_DEV( 0x0421, 0x0019, 0x0592, 0x0592, + "Nokia", + "Nokia 6288", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_MAX_SECTORS_64 ), + /* Reported by Mario Rettig <mariorettig@web.de> */ UNUSUAL_DEV( 0x0421, 0x042e, 0x0100, 0x0100, "Nokia", @@ -320,6 +327,13 @@ UNUSUAL_DEV( 0x04b0, 0x040d, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), +/* Reported by Emil Larsson <emil@swip.net> */ +UNUSUAL_DEV( 0x04b0, 0x0411, 0x0100, 0x0100, + "NIKON", + "NIKON DSC D80", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY), + /* BENQ DC5330 * Reported by Manuel Fombuena <mfombuena@ya.com> and * Frank Copeland <fjc@thingy.apana.org.au> */ @@ -1395,16 +1409,6 @@ UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), -/* Reported by Thomas Baechler <thomas@archlinux.org> - * Fixes I/O errors with Teac HD-35PU devices - */ - -UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201, - "Super Top", - "USB 2.0 IDE DEVICE", - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_IGNORE_RESIDUE), - /* patch submitted by Davide Perini <perini.davide@dpsoftware.org> * and Renato Perini <rperini@email.it> */ @@ -1414,6 +1418,16 @@ UNUSUAL_DEV( 0x22b8, 0x3010, 0x0001, 0x0001, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ), +/* + * Patch by Pete Zaitcev <zaitcev@redhat.com> + * Report by Mark Patton. Red Hat bz#208928. + */ +UNUSUAL_DEV( 0x22b8, 0x4810, 0x0001, 0x0001, + "Motorola", + "RAZR V3i", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY), + /* Reported by Radovan Garabik <garabik@kassiopeia.juls.savba.sk> */ UNUSUAL_DEV( 0x2735, 0x100b, 0x0000, 0x9999, "MPIO", diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 35d2abd1ed5..5af684b4049 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -1320,7 +1320,7 @@ config FB_AU1100 config FB_AU1200 bool "Au1200 LCD Driver" - depends on FB && MIPS && SOC_AU1200 + depends on (FB = y) && MIPS && SOC_AU1200 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -1470,7 +1470,7 @@ config FB_G364 config FB_68328 bool "Motorola 68328 native frame buffer support" - depends on FB && (M68328 || M68EZ328 || M68VZ328) + depends on (FB = y) && (M68328 || M68EZ328 || M68VZ328) select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -1616,7 +1616,7 @@ config FB_IBM_GXT4500 config FB_PS3 bool "PS3 GPU framebuffer driver" - depends on FB && PS3_PS3AV + depends on (FB = y) && PS3_PS3AV select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c index d1312477813..6b488b8a7ee 100644 --- a/drivers/video/backlight/locomolcd.c +++ b/drivers/video/backlight/locomolcd.c @@ -199,8 +199,8 @@ static int locomolcd_remove(struct locomo_dev *dev) { unsigned long flags; - locomobl_data.brightness = 0; - locomobl_data.power = 0; + locomolcd_bl_device->props.brightness = 0; + locomolcd_bl_device->props.power = 0; locomolcd_set_intensity(locomolcd_bl_device); backlight_device_unregister(locomolcd_bl_device); diff --git a/drivers/video/backlight/progear_bl.c b/drivers/video/backlight/progear_bl.c index 70226935786..836ab4df0ef 100644 --- a/drivers/video/backlight/progear_bl.c +++ b/drivers/video/backlight/progear_bl.c @@ -65,13 +65,13 @@ static int progearbl_probe(struct platform_device *pdev) u8 temp; struct backlight_device *progear_backlight_device; - pmu_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, 0); + pmu_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, NULL); if (!pmu_dev) { printk("ALI M7101 PMU not found.\n"); return -ENODEV; } - sb_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, 0); + sb_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); if (!sb_dev) { printk("ALI 1533 SB not found.\n"); pci_dev_put(pmu_dev); diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c index 9bb6257d691..b0b2e40bbd9 100644 --- a/drivers/video/bw2.c +++ b/drivers/video/bw2.c @@ -186,8 +186,7 @@ static int bw2_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) * Initialisation */ -static void -bw2_init_fix(struct fb_info *info, int linebytes) +static void __devinit bw2_init_fix(struct fb_info *info, int linebytes) { strlcpy(info->fix.id, "bwtwo", sizeof(info->fix.id)); @@ -199,43 +198,44 @@ bw2_init_fix(struct fb_info *info, int linebytes) info->fix.accel = FB_ACCEL_SUN_BWTWO; } -static u8 bw2regs_1600[] __initdata = { +static u8 bw2regs_1600[] __devinitdata = { 0x14, 0x8b, 0x15, 0x28, 0x16, 0x03, 0x17, 0x13, 0x18, 0x7b, 0x19, 0x05, 0x1a, 0x34, 0x1b, 0x2e, 0x1c, 0x00, 0x1d, 0x0a, 0x1e, 0xff, 0x1f, 0x01, 0x10, 0x21, 0 }; -static u8 bw2regs_ecl[] __initdata = { +static u8 bw2regs_ecl[] __devinitdata = { 0x14, 0x65, 0x15, 0x1e, 0x16, 0x04, 0x17, 0x0c, 0x18, 0x5e, 0x19, 0x03, 0x1a, 0xa7, 0x1b, 0x23, 0x1c, 0x00, 0x1d, 0x08, 0x1e, 0xff, 0x1f, 0x01, 0x10, 0x20, 0 }; -static u8 bw2regs_analog[] __initdata = { +static u8 bw2regs_analog[] __devinitdata = { 0x14, 0xbb, 0x15, 0x2b, 0x16, 0x03, 0x17, 0x13, 0x18, 0xb0, 0x19, 0x03, 0x1a, 0xa6, 0x1b, 0x22, 0x1c, 0x01, 0x1d, 0x05, 0x1e, 0xff, 0x1f, 0x01, 0x10, 0x20, 0 }; -static u8 bw2regs_76hz[] __initdata = { +static u8 bw2regs_76hz[] __devinitdata = { 0x14, 0xb7, 0x15, 0x27, 0x16, 0x03, 0x17, 0x0f, 0x18, 0xae, 0x19, 0x03, 0x1a, 0xae, 0x1b, 0x2a, 0x1c, 0x01, 0x1d, 0x09, 0x1e, 0xff, 0x1f, 0x01, 0x10, 0x24, 0 }; -static u8 bw2regs_66hz[] __initdata = { +static u8 bw2regs_66hz[] __devinitdata = { 0x14, 0xbb, 0x15, 0x2b, 0x16, 0x04, 0x17, 0x14, 0x18, 0xae, 0x19, 0x03, 0x1a, 0xa8, 0x1b, 0x24, 0x1c, 0x01, 0x1d, 0x05, 0x1e, 0xff, 0x1f, 0x01, 0x10, 0x20, 0 }; -static void bw2_do_default_mode(struct bw2_par *par, struct fb_info *info, - int *linebytes) +static void __devinit bw2_do_default_mode(struct bw2_par *par, + struct fb_info *info, + int *linebytes) { u8 status, mon; u8 *p; diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c index ec6a51a5822..b071bb632b9 100644 --- a/drivers/video/cg14.c +++ b/drivers/video/cg14.c @@ -354,7 +354,8 @@ static int cg14_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) * Initialisation */ -static void cg14_init_fix(struct fb_info *info, int linebytes, struct device_node *dp) +static void __devinit cg14_init_fix(struct fb_info *info, int linebytes, + struct device_node *dp) { const char *name = dp->name; @@ -368,7 +369,7 @@ static void cg14_init_fix(struct fb_info *info, int linebytes, struct device_nod info->fix.accel = FB_ACCEL_SUN_CG14; } -static struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] __initdata = { +static struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] __devinitdata = { { .voff = CG14_REGS, .poff = 0x80000000, diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c index ada6f7e3a89..767c850f8eb 100644 --- a/drivers/video/cg3.c +++ b/drivers/video/cg3.c @@ -186,8 +186,7 @@ static int cg3_setcolreg(unsigned regno, * @blank_mode: the blank mode we want. * @info: frame buffer structure that represents a single frame buffer */ -static int -cg3_blank(int blank, struct fb_info *info) +static int cg3_blank(int blank, struct fb_info *info) { struct cg3_par *par = (struct cg3_par *) info->par; struct cg3_regs __iomem *regs = par->regs; @@ -251,8 +250,8 @@ static int cg3_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) * Initialisation */ -static void -cg3_init_fix(struct fb_info *info, int linebytes, struct device_node *dp) +static void __devinit cg3_init_fix(struct fb_info *info, int linebytes, + struct device_node *dp) { strlcpy(info->fix.id, dp->name, sizeof(info->fix.id)); @@ -264,8 +263,8 @@ cg3_init_fix(struct fb_info *info, int linebytes, struct device_node *dp) info->fix.accel = FB_ACCEL_SUN_CGTHREE; } -static void cg3_rdi_maybe_fixup_var(struct fb_var_screeninfo *var, - struct device_node *dp) +static void __devinit cg3_rdi_maybe_fixup_var(struct fb_var_screeninfo *var, + struct device_node *dp) { char *params; char *p; @@ -287,36 +286,36 @@ static void cg3_rdi_maybe_fixup_var(struct fb_var_screeninfo *var, } } -static u8 cg3regvals_66hz[] __initdata = { /* 1152 x 900, 66 Hz */ +static u8 cg3regvals_66hz[] __devinitdata = { /* 1152 x 900, 66 Hz */ 0x14, 0xbb, 0x15, 0x2b, 0x16, 0x04, 0x17, 0x14, 0x18, 0xae, 0x19, 0x03, 0x1a, 0xa8, 0x1b, 0x24, 0x1c, 0x01, 0x1d, 0x05, 0x1e, 0xff, 0x1f, 0x01, 0x10, 0x20, 0 }; -static u8 cg3regvals_76hz[] __initdata = { /* 1152 x 900, 76 Hz */ +static u8 cg3regvals_76hz[] __devinitdata = { /* 1152 x 900, 76 Hz */ 0x14, 0xb7, 0x15, 0x27, 0x16, 0x03, 0x17, 0x0f, 0x18, 0xae, 0x19, 0x03, 0x1a, 0xae, 0x1b, 0x2a, 0x1c, 0x01, 0x1d, 0x09, 0x1e, 0xff, 0x1f, 0x01, 0x10, 0x24, 0 }; -static u8 cg3regvals_rdi[] __initdata = { /* 640 x 480, cgRDI */ +static u8 cg3regvals_rdi[] __devinitdata = { /* 640 x 480, cgRDI */ 0x14, 0x70, 0x15, 0x20, 0x16, 0x08, 0x17, 0x10, 0x18, 0x06, 0x19, 0x02, 0x1a, 0x31, 0x1b, 0x51, 0x1c, 0x06, 0x1d, 0x0c, 0x1e, 0xff, 0x1f, 0x01, 0x10, 0x22, 0 }; -static u8 *cg3_regvals[] __initdata = { +static u8 *cg3_regvals[] __devinitdata = { cg3regvals_66hz, cg3regvals_76hz, cg3regvals_rdi }; -static u_char cg3_dacvals[] __initdata = { +static u_char cg3_dacvals[] __devinitdata = { 4, 0xff, 5, 0x00, 6, 0x70, 7, 0x00, 0 }; -static void cg3_do_default_mode(struct cg3_par *par) +static void __devinit cg3_do_default_mode(struct cg3_par *par) { enum cg3_type type; u8 *p; @@ -433,7 +432,8 @@ static int __devinit cg3_init_one(struct of_device *op) return 0; } -static int __devinit cg3_probe(struct of_device *dev, const struct of_device_id *match) +static int __devinit cg3_probe(struct of_device *dev, + const struct of_device_id *match) { struct of_device *op = to_of_device(&dev->dev); diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c index 15854aec318..1d4e8354b56 100644 --- a/drivers/video/ffb.c +++ b/drivers/video/ffb.c @@ -336,14 +336,30 @@ struct ffb_dac { u32 value2; }; +#define FFB_DAC_UCTRL 0x1001 /* User Control */ +#define FFB_DAC_UCTRL_MANREV 0x00000f00 /* 4-bit Manufacturing Revision */ +#define FFB_DAC_UCTRL_MANREV_SHIFT 8 +#define FFB_DAC_TGEN 0x6000 /* Timing Generator */ +#define FFB_DAC_TGEN_VIDE 0x00000001 /* Video Enable */ +#define FFB_DAC_DID 0x8000 /* Device Identification */ +#define FFB_DAC_DID_PNUM 0x0ffff000 /* Device Part Number */ +#define FFB_DAC_DID_PNUM_SHIFT 12 +#define FFB_DAC_DID_REV 0xf0000000 /* Device Revision */ +#define FFB_DAC_DID_REV_SHIFT 28 + +#define FFB_DAC_CUR_CTRL 0x100 +#define FFB_DAC_CUR_CTRL_P0 0x00000001 +#define FFB_DAC_CUR_CTRL_P1 0x00000002 + struct ffb_par { spinlock_t lock; struct ffb_fbc __iomem *fbc; struct ffb_dac __iomem *dac; u32 flags; -#define FFB_FLAG_AFB 0x00000001 -#define FFB_FLAG_BLANKED 0x00000002 +#define FFB_FLAG_AFB 0x00000001 /* AFB m3 or m6 */ +#define FFB_FLAG_BLANKED 0x00000002 /* screen is blanked */ +#define FFB_FLAG_INVCURSOR 0x00000004 /* DAC has inverted cursor logic */ u32 fg_cache __attribute__((aligned (8))); u32 bg_cache; @@ -354,7 +370,6 @@ struct ffb_par { unsigned long physbase; unsigned long fbsize; - int dac_rev; int board_type; }; @@ -426,11 +441,12 @@ static void ffb_switch_from_graph(struct ffb_par *par) FFBWait(par); /* Disable cursor. */ - upa_writel(0x100, &dac->type2); - if (par->dac_rev <= 2) + upa_writel(FFB_DAC_CUR_CTRL, &dac->type2); + if (par->flags & FFB_FLAG_INVCURSOR) upa_writel(0, &dac->value2); else - upa_writel(3, &dac->value2); + upa_writel((FFB_DAC_CUR_CTRL_P0 | + FFB_DAC_CUR_CTRL_P1), &dac->value2); spin_unlock_irqrestore(&par->lock, flags); } @@ -664,18 +680,18 @@ ffb_blank(int blank, struct fb_info *info) struct ffb_par *par = (struct ffb_par *) info->par; struct ffb_dac __iomem *dac = par->dac; unsigned long flags; - u32 tmp; + u32 val; + int i; spin_lock_irqsave(&par->lock, flags); FFBWait(par); + upa_writel(FFB_DAC_TGEN, &dac->type); + val = upa_readl(&dac->value); switch (blank) { case FB_BLANK_UNBLANK: /* Unblanking */ - upa_writel(0x6000, &dac->type); - tmp = (upa_readl(&dac->value) | 0x1); - upa_writel(0x6000, &dac->type); - upa_writel(tmp, &dac->value); + val |= FFB_DAC_TGEN_VIDE; par->flags &= ~FFB_FLAG_BLANKED; break; @@ -683,13 +699,16 @@ ffb_blank(int blank, struct fb_info *info) case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */ case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */ case FB_BLANK_POWERDOWN: /* Poweroff */ - upa_writel(0x6000, &dac->type); - tmp = (upa_readl(&dac->value) & ~0x1); - upa_writel(0x6000, &dac->type); - upa_writel(tmp, &dac->value); + val &= ~FFB_DAC_TGEN_VIDE; par->flags |= FFB_FLAG_BLANKED; break; } + upa_writel(FFB_DAC_TGEN, &dac->type); + upa_writel(val, &dac->value); + for (i = 0; i < 10; i++) { + upa_writel(FFB_DAC_TGEN, &dac->type); + upa_readl(&dac->value); + } spin_unlock_irqrestore(&par->lock, flags); @@ -894,6 +913,7 @@ static int ffb_init_one(struct of_device *op) struct ffb_dac __iomem *dac; struct all_info *all; int err; + u32 dac_pnum, dac_rev, dac_mrev; all = kzalloc(sizeof(*all), GFP_KERNEL); if (!all) @@ -948,17 +968,31 @@ static int ffb_init_one(struct of_device *op) if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0) upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr); - ffb_switch_from_graph(&all->par); - dac = all->par.dac; - upa_writel(0x8000, &dac->type); - all->par.dac_rev = upa_readl(&dac->value) >> 0x1c; + upa_writel(FFB_DAC_DID, &dac->type); + dac_pnum = upa_readl(&dac->value); + dac_rev = (dac_pnum & FFB_DAC_DID_REV) >> FFB_DAC_DID_REV_SHIFT; + dac_pnum = (dac_pnum & FFB_DAC_DID_PNUM) >> FFB_DAC_DID_PNUM_SHIFT; + + upa_writel(FFB_DAC_UCTRL, &dac->type); + dac_mrev = upa_readl(&dac->value); + dac_mrev = (dac_mrev & FFB_DAC_UCTRL_MANREV) >> + FFB_DAC_UCTRL_MANREV_SHIFT; /* Elite3D has different DAC revision numbering, and no DAC revisions - * have the reversed meaning of cursor enable. + * have the reversed meaning of cursor enable. Otherwise, Pacifica 1 + * ramdacs with manufacturing revision less than 3 have inverted + * cursor logic. We identify Pacifica 1 as not Pacifica 2, the + * latter having a part number value of 0x236e. */ - if (all->par.flags & FFB_FLAG_AFB) - all->par.dac_rev = 10; + if ((all->par.flags & FFB_FLAG_AFB) || dac_pnum == 0x236e) { + all->par.flags &= ~FFB_FLAG_INVCURSOR; + } else { + if (dac_mrev < 3) + all->par.flags |= FFB_FLAG_INVCURSOR; + } + + ffb_switch_from_graph(&all->par); /* Unblank it just to be sure. When there are multiple * FFB/AFB cards in the system, or it is not the OBP @@ -993,10 +1027,12 @@ static int ffb_init_one(struct of_device *op) dev_set_drvdata(&op->dev, all); - printk("%s: %s at %016lx, type %d, DAC revision %d\n", + printk("%s: %s at %016lx, type %d, " + "DAC pnum[%x] rev[%d] manuf_rev[%d]\n", dp->full_name, ((all->par.flags & FFB_FLAG_AFB) ? "AFB" : "FFB"), - all->par.physbase, all->par.board_type, all->par.dac_rev); + all->par.physbase, all->par.board_type, + dac_pnum, dac_rev, dac_mrev); return 0; } diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c index 1d1c7c624d7..d7ece8d17a2 100644 --- a/drivers/video/riva/fbdev.c +++ b/drivers/video/riva/fbdev.c @@ -285,8 +285,6 @@ static const struct riva_regs reg_template = { #define MAX_LEVEL 0x534 #define LEVEL_STEP ((MAX_LEVEL - MIN_LEVEL) / FB_BACKLIGHT_MAX) -static struct backlight_properties riva_bl_data; - static int riva_bl_get_level_brightness(struct riva_par *par, int level) { @@ -372,7 +370,7 @@ static void riva_bl_init(struct riva_par *par) FB_BACKLIGHT_MAX); bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1; - bd->props.brightness = riva_bl_data.max_brightness; + bd->props.brightness = bd->props.max_brightness; bd->props.power = FB_BLANK_UNBLANK; backlight_update_status(bd); diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c index 98919a6975f..3091b20124b 100644 --- a/drivers/video/s3fb.c +++ b/drivers/video/s3fb.c @@ -1000,11 +1000,12 @@ err_enable_device: static void __devexit s3_pci_remove(struct pci_dev *dev) { struct fb_info *info = pci_get_drvdata(dev); - struct s3fb_info *par = info->par; if (info) { #ifdef CONFIG_MTRR + struct s3fb_info *par = info->par; + if (par->mtrr_reg >= 0) { mtrr_del(par->mtrr_reg, 0, 0); par->mtrr_reg = -1; diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c index 4afa30522fd..0166ec2ccf3 100644 --- a/drivers/video/savage/savagefb_driver.c +++ b/drivers/video/savage/savagefb_driver.c @@ -384,6 +384,19 @@ SavageSetup2DEngine(struct savagefb_par *par) BCI_SEND(0); BCI_SEND(BCI_CMD_SETREG | (1 << 16) | BCI_GBD2); BCI_SEND(GlobalBitmapDescriptor); + + /* + * I don't know why, sending this twice fixes the intial black screen, + * prevents X from crashing at least in Toshiba laptops with SavageIX. + * --Tony + */ + par->bci_ptr = 0; + par->SavageWaitFifo(par, 4); + + BCI_SEND(BCI_CMD_SETREG | (1 << 16) | BCI_GBD1); + BCI_SEND(0); + BCI_SEND(BCI_CMD_SETREG | (1 << 16) | BCI_GBD2); + BCI_SEND(GlobalBitmapDescriptor); } static void savagefb_set_clip(struct fb_info *info) @@ -496,7 +509,7 @@ static int common_calc_clock(long freq, int min_m, int min_n1, int max_n1, #ifdef SAVAGEFB_DEBUG /* This function is used to debug, it prints out the contents of s3 regs */ -static void SavagePrintRegs(void) +static void SavagePrintRegs(struct savagefb_par *par) { unsigned char i; int vgaCRIndex = 0x3d4; @@ -1525,7 +1538,7 @@ static int savagefb_set_par(struct fb_info *info) savagefb_set_fix(info); savagefb_set_clip(info); - SavagePrintRegs(); + SavagePrintRegs(par); return 0; } @@ -2155,7 +2168,6 @@ static int __devinit savagefb_probe(struct pci_dev* dev, int video_len; DBG("savagefb_probe"); - SavagePrintRegs(); info = framebuffer_alloc(sizeof(struct savagefb_par), &dev->dev); if (!info) diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c index 59cd1e750f3..62fa5500361 100644 --- a/drivers/video/sstfb.c +++ b/drivers/video/sstfb.c @@ -257,6 +257,7 @@ static void __sst_dac_write(u8 __iomem *vbase, u8 reg, u8 val) r_dprintk("sst_dac_write(%#x, %#x)\n", reg, val); reg &= 0x07; __sst_write(vbase, DAC_DATA,(((u32)reg << 8)) | (u32)val); + __sst_wait_idle(vbase); } /* indexed access to ti/att dacs */ |