diff options
Diffstat (limited to 'drivers')
327 files changed, 4660 insertions, 2316 deletions
diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c index d2fc94161848..26038c2a2a71 100644 --- a/drivers/acpi/bay.c +++ b/drivers/acpi/bay.c @@ -301,16 +301,20 @@ static int bay_add(acpi_handle handle, int id) */ pdev->dev.uevent_suppress = 0; - if (acpi_bay_add_fs(new_bay)) { - platform_device_unregister(new_bay->pdev); - goto bay_add_err; - } - /* register for events on this device */ status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, bay_notify, new_bay); if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX "Error installing bay notify handler\n"); + printk(KERN_INFO PREFIX "Error installing bay notify handler\n"); + platform_device_unregister(new_bay->pdev); + goto bay_add_err; + } + + if (acpi_bay_add_fs(new_bay)) { + acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, + bay_notify); + platform_device_unregister(new_bay->pdev); + goto bay_add_err; } /* if we are on a dock station, we should register for dock diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c index c78078315be9..f988a5e7d2b4 100644 --- a/drivers/acpi/dispatcher/dsfield.c +++ b/drivers/acpi/dispatcher/dsfield.c @@ -450,10 +450,6 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, return_ACPI_STATUS(AE_BAD_PARAMETER); } - if (!arg) { - return_ACPI_STATUS(AE_AML_NO_OPERAND); - } - /* Creating new namespace node(s), should not already exist */ flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | @@ -467,6 +463,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, /* * Walk the list of entries in the field_list + * Note: field_list can be of zero length. In this case, Arg will be NULL. */ while (arg) { /* diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index fa44fb96fc34..96c542f7fded 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -834,7 +834,7 @@ static int dock_add(acpi_handle handle) goto dock_add_err; } - printk(KERN_INFO PREFIX "%s \n", ACPI_DOCK_DRIVER_DESCRIPTION); + printk(KERN_INFO PREFIX "%s\n", ACPI_DOCK_DRIVER_DESCRIPTION); return 0; diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 0924992187e8..5622aee996b2 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -194,7 +194,7 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) while (time_before(jiffies, delay)) { if (acpi_ec_check_status(ec, event)) return 0; - udelay(ACPI_EC_UDELAY); + msleep(1); } } pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n", diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index 24da921d13e3..39d742190584 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -375,9 +375,15 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, goto cleanup; } + /* + * Add the table to the namespace. + * + * Note: We load the table objects relative to the root of the namespace. + * This appears to go against the ACPI specification, but we do it for + * compatibility with other ACPI implementations. + */ status = - acpi_ex_add_table(table_index, walk_state->scope_info->scope.node, - &ddb_handle); + acpi_ex_add_table(table_index, acpi_gbl_root_node, &ddb_handle); if (ACPI_FAILURE(status)) { /* On error, table_ptr was deallocated above */ diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 06f8634fe58b..2808dc60fd67 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -272,6 +272,12 @@ static u32 rtc_handler(void *context) static inline void rtc_wake_setup(void) { acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL); + /* + * After the RTC handler is installed, the Fixed_RTC event should + * be disabled. Only when the RTC alarm is set will it be enabled. + */ + acpi_clear_event(ACPI_EVENT_RTC); + acpi_disable_event(ACPI_EVENT_RTC, 0); } static void rtc_wake_on(struct device *dev) diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c index d9937e05ec6a..dba3cfbe8cba 100644 --- a/drivers/acpi/hardware/hwsleep.c +++ b/drivers/acpi/hardware/hwsleep.c @@ -223,15 +223,17 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) break; } - /* Set the system indicators to show the desired sleep state. */ - + /* + * Set the system indicators to show the desired sleep state. + * _SST is an optional method (return no error if not found) + */ status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { ACPI_EXCEPTION((AE_INFO, status, "While executing method _SST")); } - return_ACPI_STATUS(status); + return_ACPI_STATUS(AE_OK); } ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 5d59cb33b1a5..658e5f3abae0 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -140,19 +140,42 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header) } } +/* + * A lot of BIOS fill in 10 (= no distance) everywhere. This messes + * up the NUMA heuristics which wants the local node to have a smaller + * distance than the others. + * Do some quick checks here and only use the SLIT if it passes. + */ +static __init int slit_valid(struct acpi_table_slit *slit) +{ + int i, j; + int d = slit->locality_count; + for (i = 0; i < d; i++) { + for (j = 0; j < d; j++) { + u8 val = slit->entry[d*i + j]; + if (i == j) { + if (val != LOCAL_DISTANCE) + return 0; + } else if (val <= LOCAL_DISTANCE) + return 0; + } + } + return 1; +} + static int __init acpi_parse_slit(struct acpi_table_header *table) { struct acpi_table_slit *slit; - u32 localities; if (!table) return -EINVAL; slit = (struct acpi_table_slit *)table; - /* downcast just for %llu vs %lu for i386/ia64 */ - localities = (u32) slit->locality_count; - + if (!slit_valid(slit)) { + printk(KERN_INFO "ACPI: SLIT table looks invalid. Not used.\n"); + return -EINVAL; + } acpi_numa_slit_init(slit); return 0; diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c index f1e8bf65e24e..e94463778845 100644 --- a/drivers/acpi/parser/psargs.c +++ b/drivers/acpi/parser/psargs.c @@ -268,7 +268,7 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, */ if (ACPI_SUCCESS(status) && possible_method_call && (node->type == ACPI_TYPE_METHOD)) { - if (walk_state->op->common.aml_opcode == AML_UNLOAD_OP) { + if (walk_state->opcode == AML_UNLOAD_OP) { /* * acpi_ps_get_next_namestring has increased the AML pointer, * so we need to restore the saved AML pointer for method call. @@ -691,7 +691,7 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, /* To support super_name arg of Unload */ - if (walk_state->op->common.aml_opcode == AML_UNLOAD_OP) { + if (walk_state->opcode == AML_UNLOAD_OP) { status = acpi_ps_get_next_namepath(walk_state, parser_state, arg, diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 386e5aa48834..9dd0fa93b9e1 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -86,7 +86,6 @@ static int acpi_processor_info_open_fs(struct inode *inode, struct file *file); static void acpi_processor_notify(acpi_handle handle, u32 event, void *data); static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu); static int acpi_processor_handle_eject(struct acpi_processor *pr); -extern int acpi_processor_tstate_has_changed(struct acpi_processor *pr); static const struct acpi_device_id processor_device_ids[] = { diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 2dd2c1f3a01c..556ee1585192 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -1669,6 +1669,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) return -EINVAL; } + dev->cpu = pr->id; for (i = 0; i < CPUIDLE_STATE_MAX; i++) { dev->states[i].name[0] = '\0'; dev->states[i].desc[0] = '\0'; @@ -1738,7 +1739,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) int acpi_processor_cst_has_changed(struct acpi_processor *pr) { - int ret; + int ret = 0; if (boot_option_idle_override) return 0; @@ -1756,8 +1757,10 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) cpuidle_pause_and_lock(); cpuidle_disable_device(&pr->power.dev); acpi_processor_get_power_info(pr); - acpi_processor_setup_cpuidle(pr); - ret = cpuidle_enable_device(&pr->power.dev); + if (pr->flags.power) { + acpi_processor_setup_cpuidle(pr); + ret = cpuidle_enable_device(&pr->power.dev); + } cpuidle_resume_and_unlock(); return ret; @@ -1813,7 +1816,6 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, if (pr->flags.power) { #ifdef CONFIG_CPU_IDLE acpi_processor_setup_cpuidle(pr); - pr->power.dev.cpu = pr->id; if (cpuidle_register_device(&pr->power.dev)) return -EIO; #endif @@ -1850,8 +1852,7 @@ int acpi_processor_power_exit(struct acpi_processor *pr, return 0; #ifdef CONFIG_CPU_IDLE - if (pr->flags.power) - cpuidle_unregister_device(&pr->power.dev); + cpuidle_unregister_device(&pr->power.dev); #endif pr->flags.power_setup_done = 0; diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c index 8a5fe8710513..224c57c03381 100644 --- a/drivers/acpi/sleep/proc.c +++ b/drivers/acpi/sleep/proc.c @@ -495,6 +495,12 @@ static int __init acpi_sleep_proc_init(void) acpi_root_dir, &acpi_system_alarm_fops); acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL); + /* + * Disable the RTC event after installing RTC handler. + * Only when RTC alarm is set will it be enabled. + */ + acpi_clear_event(ACPI_EVENT_RTC); + acpi_disable_event(ACPI_EVENT_RTC, 0); #endif /* HAVE_ACPI_LEGACY_ALARM */ /* 'wakeup device' [R/W] */ diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 769f24855eb6..5bd2dec9a7ac 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -77,7 +77,6 @@ static ssize_t acpi_table_show(struct kobject *kobj, container_of(bin_attr, struct acpi_table_attr, attr); struct acpi_table_header *table_header = NULL; acpi_status status; - ssize_t ret_count = count; status = acpi_get_table(table_attr->name, table_attr->instance, @@ -85,18 +84,8 @@ static ssize_t acpi_table_show(struct kobject *kobj, if (ACPI_FAILURE(status)) return -ENODEV; - if (offset >= table_header->length) { - ret_count = 0; - goto end; - } - - if (offset + ret_count > table_header->length) - ret_count = table_header->length - offset; - - memcpy(buf, ((char *)table_header) + offset, ret_count); - - end: - return ret_count; + return memory_read_from_buffer(buf, count, &offset, + table_header, table_header->length); } static void acpi_table_attr_init(struct acpi_table_attr *table_attr, diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c index 402f93e1ff20..5336ce88f89f 100644 --- a/drivers/acpi/tables/tbinstal.c +++ b/drivers/acpi/tables/tbinstal.c @@ -123,24 +123,13 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, } } - /* The table must be either an SSDT or a PSDT or an OEMx */ - - if (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_PSDT)&& - !ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT)&& - strncmp(table_desc->pointer->signature, "OEM", 3)) { - /* Check for a printable name */ - if (acpi_ut_valid_acpi_name( - *(u32 *) table_desc->pointer->signature)) { - ACPI_ERROR((AE_INFO, "Table has invalid signature " - "[%4.4s], must be SSDT or PSDT", - table_desc->pointer->signature)); - } else { - ACPI_ERROR((AE_INFO, "Table has invalid signature " - "(0x%8.8X), must be SSDT or PSDT", - *(u32 *) table_desc->pointer->signature)); - } - return_ACPI_STATUS(AE_BAD_SIGNATURE); - } + /* + * Originally, we checked the table signature for "SSDT" or "PSDT" here. + * Next, we added support for OEMx tables, signature "OEM". + * Valid tables were encountered with a null signature, so we've just + * given up on validating the signature, since it seems to be a waste + * of code. The original code was removed (05/2008). + */ (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c index fb57b93c2495..0e319604d3e7 100644 --- a/drivers/acpi/tables/tbxface.c +++ b/drivers/acpi/tables/tbxface.c @@ -540,7 +540,7 @@ static acpi_status acpi_tb_load_namespace(void) acpi_tb_print_table_header(0, table); if (no_auto_ssdt == 0) { - printk(KERN_WARNING "ACPI: DSDT override uses original SSDTs unless \"acpi_no_auto_ssdt\""); + printk(KERN_WARNING "ACPI: DSDT override uses original SSDTs unless \"acpi_no_auto_ssdt\"\n"); } } diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 504385b1f211..84c795fb9b1e 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -364,10 +364,17 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) if (flag & ACPI_TRIPS_CRITICAL) { status = acpi_evaluate_integer(tz->device->handle, "_CRT", NULL, &tz->trips.critical.temperature); - if (ACPI_FAILURE(status)) { + /* + * Treat freezing temperatures as invalid as well; some + * BIOSes return really low values and cause reboots at startup. + * Below zero (Celcius) values clearly aren't right for sure.. + * ... so lets discard those as invalid. + */ + if (ACPI_FAILURE(status) || + tz->trips.critical.temperature <= 2732) { tz->trips.critical.flags.valid = 0; ACPI_EXCEPTION((AE_INFO, status, - "No critical threshold")); + "No or invalid critical threshold")); return -ENODEV; } else { tz->trips.critical.flags.valid = 1; diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c index e4ba7192cd15..1f057b71db1a 100644 --- a/drivers/acpi/utilities/utmisc.c +++ b/drivers/acpi/utilities/utmisc.c @@ -1048,6 +1048,7 @@ acpi_ut_exception(char *module_name, va_start(args, format); acpi_os_vprintf(format, args); acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); + va_end(args); } EXPORT_SYMBOL(acpi_ut_exception); @@ -1063,7 +1064,6 @@ acpi_ut_warning(char *module_name, u32 line_number, char *format, ...) acpi_os_vprintf(format, args); acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); va_end(args); - va_end(args); } void ACPI_INTERNAL_VAR_XFACE diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 97f83fb2ee2e..966ab401e523 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -89,6 +89,7 @@ enum { board_ahci_sb600 = 3, board_ahci_mv = 4, board_ahci_sb700 = 5, + board_ahci_mcp65 = 6, /* global controller registers */ HOST_CAP = 0x00, /* host capabilities */ @@ -190,6 +191,7 @@ enum { AHCI_HFLAG_NO_PMP = (1 << 6), /* no PMP */ AHCI_HFLAG_NO_HOTPLUG = (1 << 7), /* ignore PxSERR.DIAG.N */ AHCI_HFLAG_SECT255 = (1 << 8), /* max 255 sectors */ + AHCI_HFLAG_YES_NCQ = (1 << 9), /* force NCQ cap on */ /* ap->flags bits */ @@ -253,6 +255,8 @@ static void ahci_pmp_attach(struct ata_port *ap); static void ahci_pmp_detach(struct ata_port *ap); static int ahci_softreset(struct ata_link *link, unsigned int *class, unsigned long deadline); +static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class, + unsigned long deadline); static int ahci_hardreset(struct ata_link *link, unsigned int *class, unsigned long deadline); static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, @@ -329,6 +333,12 @@ static struct ata_port_operations ahci_p5wdh_ops = { .hardreset = ahci_p5wdh_hardreset, }; +static struct ata_port_operations ahci_sb600_ops = { + .inherits = &ahci_ops, + .softreset = ahci_sb600_softreset, + .pmp_softreset = ahci_sb600_softreset, +}; + #define AHCI_HFLAGS(flags) .private_data = (void *)(flags) static const struct ata_port_info ahci_port_info[] = { @@ -359,11 +369,11 @@ static const struct ata_port_info ahci_port_info[] = { { AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI | - AHCI_HFLAG_SECT255 | AHCI_HFLAG_NO_PMP), + AHCI_HFLAG_SECT255), .flags = AHCI_FLAG_COMMON, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = ATA_UDMA6, - .port_ops = &ahci_ops, + .port_ops = &ahci_sb600_ops, }, /* board_ahci_mv */ { @@ -377,8 +387,15 @@ static const struct ata_port_info ahci_port_info[] = { }, /* board_ahci_sb700 */ { - AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | - AHCI_HFLAG_NO_PMP), + AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL), + .flags = AHCI_FLAG_COMMON, + .pio_mask = 0x1f, /* pio0-4 */ + .udma_mask = ATA_UDMA6, + .port_ops = &ahci_sb600_ops, + }, + /* board_ahci_mcp65 */ + { + AHCI_HFLAGS (AHCI_HFLAG_YES_NCQ), .flags = AHCI_FLAG_COMMON, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = ATA_UDMA6, @@ -438,14 +455,14 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */ /* NVIDIA */ - { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci }, /* MCP65 */ - { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci }, /* MCP65 */ - { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci }, /* MCP65 */ - { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci }, /* MCP65 */ - { PCI_VDEVICE(NVIDIA, 0x045c), board_ahci }, /* MCP65 */ - { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci }, /* MCP65 */ - { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci }, /* MCP65 */ - { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci }, /* MCP65 */ + { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 }, /* MCP65 */ + { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 }, /* MCP65 */ + { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 }, /* MCP65 */ + { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 }, /* MCP65 */ + { PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 }, /* MCP65 */ + { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 }, /* MCP65 */ + { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 }, /* MCP65 */ + { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 }, /* MCP65 */ { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci }, /* MCP67 */ { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci }, /* MCP67 */ { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci }, /* MCP67 */ @@ -502,10 +519,10 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(NVIDIA, 0x0bcd), board_ahci }, /* MCP7B */ { PCI_VDEVICE(NVIDIA, 0x0bce), board_ahci }, /* MCP7B */ { PCI_VDEVICE(NVIDIA, 0x0bcf), board_ahci }, /* MCP7B */ - { PCI_VDEVICE(NVIDIA, 0x0bd0), board_ahci }, /* MCP7B */ - { PCI_VDEVICE(NVIDIA, 0x0bd1), board_ahci }, /* MCP7B */ - { PCI_VDEVICE(NVIDIA, 0x0bd2), board_ahci }, /* MCP7B */ - { PCI_VDEVICE(NVIDIA, 0x0bd3), board_ahci }, /* MCP7B */ + { PCI_VDEVICE(NVIDIA, 0x0bc4), board_ahci }, /* MCP7B */ + { PCI_VDEVICE(NVIDIA, 0x0bc5), board_ahci }, /* MCP7B */ + { PCI_VDEVICE(NVIDIA, 0x0bc6), board_ahci }, /* MCP7B */ + { PCI_VDEVICE(NVIDIA, 0x0bc7), board_ahci }, /* MCP7B */ /* SiS */ { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */ @@ -624,6 +641,12 @@ static void ahci_save_initial_config(struct pci_dev *pdev, cap &= ~HOST_CAP_NCQ; } + if (!(cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_YES_NCQ)) { + dev_printk(KERN_INFO, &pdev->dev, + "controller can do NCQ, turning on CAP_NCQ\n"); + cap |= HOST_CAP_NCQ; + } + if ((cap & HOST_CAP_PMP) && (hpriv->flags & AHCI_HFLAG_NO_PMP)) { dev_printk(KERN_INFO, &pdev->dev, "controller can't do PMP, turning off CAP_PMP\n"); @@ -1262,19 +1285,11 @@ static int ahci_exec_polled_cmd(struct ata_port *ap, int pmp, return 0; } -static int ahci_check_ready(struct ata_link *link) -{ - void __iomem *port_mmio = ahci_port_base(link->ap); - u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF; - - return ata_check_ready(status); -} - -static int ahci_softreset(struct ata_link *link, unsigned int *class, - unsigned long deadline) +static int ahci_do_softreset(struct ata_link *link, unsigned int *class, + int pmp, unsigned long deadline, + int (*check_ready)(struct ata_link *link)) { struct ata_port *ap = link->ap; - int pmp = sata_srst_pmp(link); const char *reason = NULL; unsigned long now, msecs; struct ata_taskfile tf; @@ -1312,7 +1327,7 @@ static int ahci_softreset(struct ata_link *link, unsigned int *class, ahci_exec_polled_cmd(ap, pmp, &tf, 0, 0, 0); /* wait for link to become ready */ - rc = ata_wait_after_reset(link, deadline, ahci_check_ready); + rc = ata_wait_after_reset(link, deadline, check_ready); /* link occupied, -ENODEV too is an error */ if (rc) { reason = "device not ready"; @@ -1328,6 +1343,72 @@ static int ahci_softreset(struct ata_link *link, unsigned int *class, return rc; } +static int ahci_check_ready(struct ata_link *link) +{ + void __iomem *port_mmio = ahci_port_base(link->ap); + u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF; + + return ata_check_ready(status); +} + +static int ahci_softreset(struct ata_link *link, unsigned int *class, + unsigned long deadline) +{ + int pmp = sata_srst_pmp(link); + + DPRINTK("ENTER\n"); + + return ahci_do_softreset(link, class, pmp, deadline, ahci_check_ready); +} + +static int ahci_sb600_check_ready(struct ata_link *link) +{ + void __iomem *port_mmio = ahci_port_base(link->ap); + u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF; + u32 irq_status = readl(port_mmio + PORT_IRQ_STAT); + + /* + * There is no need to check TFDATA if BAD PMP is found due to HW bug, + * which can save timeout delay. + */ + if (irq_status & PORT_IRQ_BAD_PMP) + return -EIO; + + return ata_check_ready(status); +} + +static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class, + unsigned long deadline) +{ + struct ata_port *ap = link->ap; + void __iomem *port_mmio = ahci_port_base(ap); + int pmp = sata_srst_pmp(link); + int rc; + u32 irq_sts; + + DPRINTK("ENTER\n"); + + rc = ahci_do_softreset(link, class, pmp, deadline, + ahci_sb600_check_ready); + + /* + * Soft reset fails on some ATI chips with IPMS set when PMP + * is enabled but SATA HDD/ODD is connected to SATA port, + * do soft reset again to port 0. + */ + if (rc == -EIO) { + irq_sts = readl(port_mmio + PORT_IRQ_STAT); + if (irq_sts & PORT_IRQ_BAD_PMP) { + ata_link_printk(link, KERN_WARNING, + "failed due to HW bug, retry pmp=0\n"); + rc = ahci_do_softreset(link, class, 0, deadline, + ahci_check_ready); + } + } + + return rc; +} + static int ahci_hardreset(struct ata_link *link, unsigned int *class, unsigned long deadline) { @@ -2118,7 +2199,8 @@ static void ahci_p5wdh_workaround(struct ata_host *host) static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; - struct ata_port_info pi = ahci_port_info[ent->driver_data]; + unsigned int board_id = ent->driver_data; + struct ata_port_info pi = ahci_port_info[board_id]; const struct ata_port_info *ppi[] = { &pi, NULL }; struct device *dev = &pdev->dev; struct ahci_host_priv *hpriv; @@ -2167,6 +2249,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) return -ENOMEM; hpriv->flags |= (unsigned long)pi.private_data; + /* MCP65 revision A1 and A2 can't do MSI */ + if (board_id == board_ahci_mcp65 && + (pdev->revision == 0xa1 || pdev->revision == 0xa2)) + hpriv->flags |= AHCI_HFLAG_NO_MSI; + if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev)) pci_intx(pdev, 1); diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index a9027b8fbdd5..81b7ae376951 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -247,10 +247,11 @@ static const struct pci_device_id piix_pci_tbl[] = { { 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, /* SATA Controller 2 IDE (ICH8) */ { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, - /* Mobile SATA Controller IDE (ICH8M) */ - { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, /* Mobile SATA Controller IDE (ICH8M), Apple */ { 0x8086, 0x2828, 0x106b, 0x00a0, 0, 0, ich8m_apple_sata }, + { 0x8086, 0x2828, 0x106b, 0x00a1, 0, 0, ich8m_apple_sata }, + /* Mobile SATA Controller IDE (ICH8M) */ + { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, /* SATA Controller IDE (ICH9) */ { 0x8086, 0x2920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, /* SATA Controller IDE (ICH9) */ @@ -526,7 +527,7 @@ static struct ata_port_info piix_port_info[] = { [ich8m_apple_sata] = { - .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR, + .flags = PIIX_SATA_FLAGS, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = ATA_UDMA6, @@ -573,6 +574,8 @@ static const struct ich_laptop ich_laptop[] = { { 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */ { 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */ { 0x24CA, 0x1025, 0x0061 }, /* ICH4 on ACER Aspire 2023WLMi */ + { 0x24CA, 0x1025, 0x003d }, /* ICH4 on ACER TM290 */ + { 0x266F, 0x1025, 0x0066 }, /* ICH6 on ACER Aspire 1694WLMi */ { 0x2653, 0x1043, 0x82D8 }, /* ICH6M on Asus Eee 701 */ /* end marker */ { 0, } diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index dbf6ca781f66..3ff8b14420d9 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -118,12 +118,62 @@ static void ata_acpi_associate_ide_port(struct ata_port *ap) ap->pflags |= ATA_PFLAG_INIT_GTM_VALID; } -static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device - *dev, u32 event) +static void ata_acpi_eject_device(acpi_handle handle) +{ + struct acpi_object_list arg_list; + union acpi_object arg; + + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = 1; + + if (ACPI_FAILURE(acpi_evaluate_object(handle, "_EJ0", + &arg_list, NULL))) + printk(KERN_ERR "Failed to evaluate _EJ0!\n"); +} + +/* @ap and @dev are the same as ata_acpi_handle_hotplug() */ +static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev) +{ + if (dev) + dev->flags |= ATA_DFLAG_DETACH; + else { + struct ata_link *tlink; + struct ata_device *tdev; + + ata_port_for_each_link(tlink, ap) + ata_link_for_each_dev(tdev, tlink) + tdev->flags |= ATA_DFLAG_DETACH; + } + + ata_port_schedule_eh(ap); +} + +/** + * ata_acpi_handle_hotplug - ACPI event handler backend + * @ap: ATA port ACPI event occurred + * @dev: ATA device ACPI event occurred (can be NULL) + * @event: ACPI event which occurred + * @is_dock_event: boolean indicating whether the event was a dock one + * + * All ACPI bay / device realted events end up in this function. If + * the event is port-wide @dev is NULL. If the event is specific to a + * device, @dev points to it. + * + * Hotplug (as opposed to unplug) notification is always handled as + * port-wide while unplug only kills the target device on device-wide + * event. + * + * LOCKING: + * ACPI notify handler context. May sleep. + */ +static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev, + u32 event, int is_dock_event) { char event_string[12]; char *envp[] = { event_string, NULL }; - struct ata_eh_info *ehi; + struct ata_eh_info *ehi = &ap->link.eh_info; struct kobject *kobj = NULL; int wait = 0; unsigned long flags; @@ -131,87 +181,100 @@ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device unsigned long sta; acpi_status status; - if (!ap) - ap = dev->link->ap; - ehi = &ap->link.eh_info; - - spin_lock_irqsave(ap->lock, flags); - - if (dev) + if (dev) { + if (dev->sdev) + kobj = &dev->sdev->sdev_gendev.kobj; handle = dev->acpi_handle; - else + } else { + kobj = &ap->dev->kobj; handle = ap->acpi_handle; + } status = acpi_get_handle(handle, "_EJ0", &tmphandle); - if (ACPI_FAILURE(status)) { - /* This device is not ejectable */ - spin_unlock_irqrestore(ap->lock, flags); + if (ACPI_FAILURE(status)) + /* This device does not support hotplug */ return; - } - status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); - if (ACPI_FAILURE(status)) { - printk ("Unable to determine bay status\n"); - spin_unlock_irqrestore(ap->lock, flags); - return; - } + spin_lock_irqsave(ap->lock, flags); switch (event) { case ACPI_NOTIFY_BUS_CHECK: case ACPI_NOTIFY_DEVICE_CHECK: ata_ehi_push_desc(ehi, "ACPI event"); - if (!sta) { - /* Device has been unplugged */ - if (dev) - dev->flags |= ATA_DFLAG_DETACH; - else { - struct ata_link *tlink; - struct ata_device *tdev; - - ata_port_for_each_link(tlink, ap) { - ata_link_for_each_dev(tdev, tlink) { - tdev->flags |= - ATA_DFLAG_DETACH; - } - } - } - ata_port_schedule_eh(ap); - wait = 1; - } else { + + status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); + if (ACPI_FAILURE(status)) { + ata_port_printk(ap, KERN_ERR, + "acpi: failed to determine bay status (0x%x)\n", + status); + break; + } + + if (sta) { ata_ehi_hotplugged(ehi); ata_port_freeze(ap); + } else { + /* The device has gone - unplug it */ + ata_acpi_detach_device(ap, dev); + wait = 1; } + break; + case ACPI_NOTIFY_EJECT_REQUEST: + ata_ehi_push_desc(ehi, "ACPI event"); + + if (!is_dock_event) + break; + + /* undock event - immediate unplug */ + ata_acpi_detach_device(ap, dev); + wait = 1; + break; } + /* make sure kobj doesn't go away while ap->lock is released */ + kobject_get(kobj); + spin_unlock_irqrestore(ap->lock, flags); - if (wait) + if (wait) { ata_port_wait_eh(ap); + ata_acpi_eject_device(handle); + } - if (dev) { - if (dev->sdev) - kobj = &dev->sdev->sdev_gendev.kobj; - } else - kobj = &ap->dev->kobj; - - if (kobj) { + if (kobj && !is_dock_event) { sprintf(event_string, "BAY_EVENT=%d", event); kobject_uevent_env(kobj, KOBJ_CHANGE, envp); } + + kobject_put(kobj); +} + +static void ata_acpi_dev_notify_dock(acpi_handle handle, u32 event, void *data) +{ + struct ata_device *dev = data; + + ata_acpi_handle_hotplug(dev->link->ap, dev, event, 1); +} + +static void ata_acpi_ap_notify_dock(acpi_handle handle, u32 event, void *data) +{ + struct ata_port *ap = data; + + ata_acpi_handle_hotplug(ap, NULL, event, 1); } static void ata_acpi_dev_notify(acpi_handle handle, u32 event, void *data) { struct ata_device *dev = data; - ata_acpi_handle_hotplug(NULL, dev, event); + ata_acpi_handle_hotplug(dev->link->ap, dev, event, 0); } static void ata_acpi_ap_notify(acpi_handle handle, u32 event, void *data) { struct ata_port *ap = data; - ata_acpi_handle_hotplug(ap, NULL, event); + ata_acpi_handle_hotplug(ap, NULL, event, 0); } /** @@ -252,7 +315,7 @@ void ata_acpi_associate(struct ata_host *host) ata_acpi_ap_notify, ap); /* we might be on a docking station */ register_hotplug_dock_device(ap->acpi_handle, - ata_acpi_ap_notify, ap); + ata_acpi_ap_notify_dock, ap); } for (j = 0; j < ata_link_max_devices(&ap->link); j++) { @@ -264,7 +327,7 @@ void ata_acpi_associate(struct ata_host *host) ata_acpi_dev_notify, dev); /* we might be on a docking station */ register_hotplug_dock_device(dev->acpi_handle, - ata_acpi_dev_notify, dev); + ata_acpi_dev_notify_dock, dev); } } } diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 3c89f205c83f..cc816ca623d3 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -5403,7 +5403,7 @@ static void ata_host_stop(struct device *gendev, void *res) */ static void ata_finalize_port_ops(struct ata_port_operations *ops) { - static spinlock_t lock = SPIN_LOCK_UNLOCKED; + static DEFINE_SPINLOCK(lock); const struct ata_port_operations *cur; void **begin = (void **)ops; void **end = (void **)&ops->inherits; diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c index 0f9386d4a5a0..7daf4c0f6216 100644 --- a/drivers/ata/libata-pmp.c +++ b/drivers/ata/libata-pmp.c @@ -322,9 +322,12 @@ static void sata_pmp_quirks(struct ata_port *ap) if (vendor == 0x1095 && devid == 0x3726) { /* sil3726 quirks */ ata_port_for_each_link(link, ap) { - /* class code report is unreliable */ + /* Class code report is unreliable and SRST + * times out under certain configurations. + */ if (link->pmp < 5) - link->flags |= ATA_LFLAG_ASSUME_ATA; + link->flags |= ATA_LFLAG_NO_SRST | + ATA_LFLAG_ASSUME_ATA; /* port 5 is for SEMB device and it doesn't like SRST */ if (link->pmp == 5) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index aeb6e01d82ce..2e6e1622dc6d 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1637,6 +1637,7 @@ defer: /** * ata_scsi_rbuf_get - Map response buffer. + * @cmd: SCSI command containing buffer to be mapped. * @flags: unsigned long variable to store irq enable status * @copy_in: copy in from user buffer * @@ -1954,7 +1955,7 @@ static unsigned int ata_msense_ctl_mode(u8 *buf) /** * ata_msense_rw_recovery - Simulate MODE SENSE r/w error recovery page - * @bufp: output buffer + * @buf: output buffer * * Generate a generic MODE SENSE r/w error recovery page. * diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 3c2d2289f85e..215d18672a5a 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -247,7 +247,7 @@ u8 ata_sff_check_status(struct ata_port *ap) * LOCKING: * Inherited from caller. */ -u8 ata_sff_altstatus(struct ata_port *ap) +static u8 ata_sff_altstatus(struct ata_port *ap) { if (ap->ops->sff_check_altstatus) return ap->ops->sff_check_altstatus(ap); @@ -256,6 +256,93 @@ u8 ata_sff_altstatus(struct ata_port *ap) } /** + * ata_sff_irq_status - Check if the device is busy + * @ap: port where the device is + * + * Determine if the port is currently busy. Uses altstatus + * if available in order to avoid clearing shared IRQ status + * when finding an IRQ source. Non ctl capable devices don't + * share interrupt lines fortunately for us. + * + * LOCKING: + * Inherited from caller. + */ +static u8 ata_sff_irq_status(struct ata_port *ap) +{ + u8 status; + + if (ap->ops->sff_check_altstatus || ap->ioaddr.altstatus_addr) { + status = ata_sff_altstatus(ap); + /* Not us: We are busy */ + if (status & ATA_BUSY) + return status; + } + /* Clear INTRQ latch */ + status = ap->ops->sff_check_status(ap); + return status; +} + +/** + * ata_sff_sync - Flush writes + * @ap: Port to wait for. + * + * CAUTION: + * If we have an mmio device with no ctl and no altstatus + * method this will fail. No such devices are known to exist. + * + * LOCKING: + * Inherited from caller. + */ + +static void ata_sff_sync(struct ata_port *ap) +{ + if (ap->ops->sff_check_altstatus) + ap->ops->sff_check_altstatus(ap); + else if (ap->ioaddr.altstatus_addr) + ioread8(ap->ioaddr.altstatus_addr); +} + +/** + * ata_sff_pause - Flush writes and wait 400nS + * @ap: Port to pause for. + * + * CAUTION: + * If we have an mmio device with no ctl and no altstatus + * method this will fail. No such devices are known to exist. + * + * LOCKING: + * Inherited from caller. + */ + +void ata_sff_pause(struct ata_port *ap) +{ + ata_sff_sync(ap); + ndelay(400); +} + +/** + * ata_sff_dma_pause - Pause before commencing DMA + * @ap: Port to pause for. + * + * Perform I/O fencing and ensure sufficient cycle delays occur + * for the HDMA1:0 transition + */ + +void ata_sff_dma_pause(struct ata_port *ap) +{ + if (ap->ops->sff_check_altstatus || ap->ioaddr.altstatus_addr) { + /* An altstatus read will cause the needed delay without + messing up the IRQ status */ + ata_sff_altstatus(ap); + return; + } + /* There are no DMA controllers without ctl. BUG here to ensure + we never violate the HDMA1:0 transition timing and risk + corruption. */ + BUG(); +} + +/** * ata_sff_busy_sleep - sleep until BSY clears, or timeout * @ap: port containing status register to be polled * @tmout_pat: impatience timeout @@ -742,7 +829,7 @@ static void ata_pio_sectors(struct ata_queued_cmd *qc) } else ata_pio_sector(qc); - ata_sff_altstatus(qc->ap); /* flush */ + ata_sff_sync(qc->ap); /* flush */ } /** @@ -763,8 +850,9 @@ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc) WARN_ON(qc->dev->cdb_len < 12); ap->ops->sff_data_xfer(qc->dev, qc->cdb, qc->dev->cdb_len, 1); - ata_sff_altstatus(ap); /* flush */ - + ata_sff_sync(ap); + /* FIXME: If the CDB is for DMA do we need to do the transition delay + or is bmdma_start guaranteed to do it ? */ switch (qc->tf.protocol) { case ATAPI_PROT_PIO: ap->hsm_task_state = HSM_ST; @@ -905,7 +993,7 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc) if (unlikely(__atapi_pio_bytes(qc, bytes))) goto err_out; - ata_sff_altstatus(ap); /* flush */ + ata_sff_sync(ap); /* flush */ return; @@ -1489,14 +1577,10 @@ inline unsigned int ata_sff_host_intr(struct ata_port *ap, goto idle_irq; } - /* check altstatus */ - status = ata_sff_altstatus(ap); - if (status & ATA_BUSY) - goto idle_irq; - /* check main status, clearing INTRQ */ - status = ap->ops->sff_check_status(ap); - if (unlikely(status & ATA_BUSY)) + /* check main status, clearing INTRQ if needed */ + status = ata_sff_irq_status(ap); + if (status & ATA_BUSY) goto idle_irq; /* ack bmdma irq events */ @@ -2030,7 +2114,7 @@ void ata_sff_error_handler(struct ata_port *ap) ap->ops->bmdma_stop(qc); } - ata_sff_altstatus(ap); + ata_sff_sync(ap); /* FIXME: We don't need this */ ap->ops->sff_check_status(ap); ap->ops->sff_irq_clear(ap); @@ -2203,7 +2287,7 @@ void ata_bmdma_stop(struct ata_queued_cmd *qc) mmio + ATA_DMA_CMD); /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ - ata_sff_altstatus(ap); /* dummy read */ + ata_sff_dma_pause(ap); } /** @@ -2722,7 +2806,8 @@ EXPORT_SYMBOL_GPL(ata_sff_qc_prep); EXPORT_SYMBOL_GPL(ata_sff_dumb_qc_prep); EXPORT_SYMBOL_GPL(ata_sff_dev_select); EXPORT_SYMBOL_GPL(ata_sff_check_status); -EXPORT_SYMBOL_GPL(ata_sff_altstatus); +EXPORT_SYMBOL_GPL(ata_sff_dma_pause); +EXPORT_SYMBOL_GPL(ata_sff_pause); EXPORT_SYMBOL_GPL(ata_sff_busy_sleep); EXPORT_SYMBOL_GPL(ata_sff_wait_ready); EXPORT_SYMBOL_GPL(ata_sff_tf_load); diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c index 17138436423d..cf9e9848f8b5 100644 --- a/drivers/ata/pata_icside.c +++ b/drivers/ata/pata_icside.c @@ -270,7 +270,7 @@ static void pata_icside_bmdma_stop(struct ata_queued_cmd *qc) disable_dma(state->dma); /* see ata_bmdma_stop */ - ata_sff_altstatus(ap); + ata_sff_dma_pause(ap); } static u8 pata_icside_bmdma_status(struct ata_port *ap) diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c index a108d259f19d..f8b3ffc8ae9e 100644 --- a/drivers/ata/pata_rb532_cf.c +++ b/drivers/ata/pata_rb532_cf.c @@ -57,7 +57,9 @@ static inline void rb532_pata_finish_io(struct ata_port *ap) struct ata_host *ah = ap->host; struct rb532_cf_info *info = ah->private_data; - ata_sff_altstatus(ap); + /* FIXME: Keep previous delay. If this is merely a fence then + ata_sff_sync might be sufficient. */ + ata_sff_dma_pause(ap); ndelay(RB500_CF_IO_DELAY); set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH); diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c index e965b251ca24..bbf5aa345e68 100644 --- a/drivers/ata/pata_scc.c +++ b/drivers/ata/pata_scc.c @@ -726,7 +726,7 @@ static void scc_bmdma_stop (struct ata_queued_cmd *qc) in_be32(bmid_base + SCC_DMA_CMD) & ~ATA_DMA_START); /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ - ata_sff_altstatus(ap); /* dummy read */ + ata_sff_dma_pause(ap); /* dummy read */ } /** @@ -747,7 +747,8 @@ static u8 scc_bmdma_status (struct ata_port *ap) return host_stat; /* errata A252,A308 workaround: Step4 */ - if ((ata_sff_altstatus(ap) & ATA_ERR) && (int_status & INTSTS_INTRQ)) + if ((scc_check_altstatus(ap) & ATA_ERR) + && (int_status & INTSTS_INTRQ)) return (host_stat | ATA_DMA_INTR); /* errata A308 workaround Step5 */ diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index 853559e32315..3924e7209a44 100644 --- a/drivers/ata/sata_fsl.c +++ b/drivers/ata/sata_fsl.c @@ -34,7 +34,7 @@ enum { SATA_FSL_HOST_FLAGS = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | - ATA_FLAG_NCQ), + ATA_FLAG_PMP | ATA_FLAG_NCQ), SATA_FSL_MAX_CMDS = SATA_FSL_QUEUE_DEPTH, SATA_FSL_CMD_HDR_SIZE = 16, /* 4 DWORDS */ @@ -395,7 +395,7 @@ static void sata_fsl_qc_prep(struct ata_queued_cmd *qc) cd = (struct command_desc *)pp->cmdentry + tag; cd_paddr = pp->cmdentry_paddr + tag * SATA_FSL_CMD_DESC_SIZE; - ata_tf_to_fis(&qc->tf, 0, 1, (u8 *) &cd->cfis); + ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, (u8 *) &cd->cfis); VPRINTK("Dumping cfis : 0x%x, 0x%x, 0x%x\n", cd->cfis[0], cd->cfis[1], cd->cfis[2]); @@ -438,6 +438,8 @@ static unsigned int sata_fsl_qc_issue(struct ata_queued_cmd *qc) ioread32(CA + hcr_base), ioread32(CE + hcr_base), ioread32(CC + hcr_base)); + iowrite32(qc->dev->link->pmp, CQPMP + hcr_base); + /* Simply queue command to the controller/device */ iowrite32(1 << tag, CQ + hcr_base); @@ -558,11 +560,36 @@ static void sata_fsl_thaw(struct ata_port *ap) ioread32(hcr_base + HCONTROL), ioread32(hcr_base + HSTATUS)); } +static void sata_fsl_pmp_attach(struct ata_port *ap) +{ + struct sata_fsl_host_priv *host_priv = ap->host->private_data; + void __iomem *hcr_base = host_priv->hcr_base; + u32 temp; + + temp = ioread32(hcr_base + HCONTROL); + iowrite32((temp | HCONTROL_PMP_ATTACHED), hcr_base + HCONTROL); +} + +static void sata_fsl_pmp_detach(struct ata_port *ap) +{ + struct sata_fsl_host_priv *host_priv = ap->host->private_data; + void __iomem *hcr_base = host_priv->hcr_base; + u32 temp; + + temp = ioread32(hcr_base + HCONTROL); + temp &= ~HCONTROL_PMP_ATTACHED; + iowrite32(temp, hcr_base + HCONTROL); + + /* enable interrupts on the controller/port */ + temp = ioread32(hcr_base + HCONTROL); + iowrite32((temp | DEFAULT_PORT_IRQ_ENABLE_MASK), hcr_base + HCONTROL); + +} + static int sata_fsl_port_start(struct ata_port *ap) { struct device *dev = ap->host->dev; struct sata_fsl_port_priv *pp; - int retval; void *mem; dma_addr_t mem_dma; struct sata_fsl_host_priv *host_priv = ap->host->private_data; @@ -688,12 +715,13 @@ static int sata_fsl_prereset(struct ata_link *link, unsigned long deadline) } static int sata_fsl_softreset(struct ata_link *link, unsigned int *class, - unsigned long deadline) + unsigned long deadline) { struct ata_port *ap = link->ap; struct sata_fsl_port_priv *pp = ap->private_data; struct sata_fsl_host_priv *host_priv = ap->host->private_data; void __iomem *hcr_base = host_priv->hcr_base; + int pmp = sata_srst_pmp(link); u32 temp; struct ata_taskfile tf; u8 *cfis; @@ -703,6 +731,9 @@ static int sata_fsl_softreset(struct ata_link *link, unsigned int *class, DPRINTK("in xx_softreset\n"); + if (pmp != SATA_PMP_CTRL_PORT) + goto issue_srst; + try_offline_again: /* * Force host controller to go off-line, aborting current operations @@ -746,6 +777,7 @@ try_offline_again: temp = ioread32(hcr_base + HCONTROL); temp |= (HCONTROL_ONLINE_PHY_RST | HCONTROL_SNOOP_ENABLE); + temp |= HCONTROL_PMP_ATTACHED; iowrite32(temp, hcr_base + HCONTROL); temp = ata_wait_register(hcr_base + HSTATUS, ONLINE, 0, 1, 500); @@ -771,7 +803,8 @@ try_offline_again: ata_port_printk(ap, KERN_WARNING, "No Device OR PHYRDY change,Hstatus = 0x%x\n", ioread32(hcr_base + HSTATUS)); - goto err; + *class = ATA_DEV_NONE; + goto out; } /* @@ -783,7 +816,8 @@ try_offline_again: if ((temp & 0xFF) != 0x18) { ata_port_printk(ap, KERN_WARNING, "No Signature Update\n"); - goto err; + *class = ATA_DEV_NONE; + goto out; } else { ata_port_printk(ap, KERN_INFO, "Signature Update detected @ %d msecs\n", @@ -798,6 +832,7 @@ try_offline_again: * reached here, we can send a command to the target device */ +issue_srst: DPRINTK("Sending SRST/device reset\n"); ata_tf_init(link->device, &tf); @@ -808,7 +843,7 @@ try_offline_again: SRST_CMD | CMD_DESC_SNOOP_ENABLE, 0, 0, 5); tf.ctl |= ATA_SRST; /* setup SRST bit in taskfile control reg */ - ata_tf_to_fis(&tf, 0, 0, cfis); + ata_tf_to_fis(&tf, pmp, 0, cfis); DPRINTK("Dumping cfis : 0x%x, 0x%x, 0x%x, 0x%x\n", cfis[0], cfis[1], cfis[2], cfis[3]); @@ -854,8 +889,10 @@ try_offline_again: sata_fsl_setup_cmd_hdr_entry(pp, 0, CMD_DESC_SNOOP_ENABLE, 0, 0, 5); tf.ctl &= ~ATA_SRST; /* 2nd H2D Ctl. register FIS */ - ata_tf_to_fis(&tf, 0, 0, cfis); + ata_tf_to_fis(&tf, pmp, 0, cfis); + if (pmp != SATA_PMP_CTRL_PORT) + iowrite32(pmp, CQPMP + hcr_base); iowrite32(1, CQ + hcr_base); msleep(150); /* ?? */ @@ -886,12 +923,21 @@ try_offline_again: VPRINTK("cereg = 0x%x\n", ioread32(hcr_base + CE)); } +out: return 0; err: return -EIO; } +static void sata_fsl_error_handler(struct ata_port *ap) +{ + + DPRINTK("in xx_error_handler\n"); + sata_pmp_error_handler(ap); + +} + static void sata_fsl_post_internal_cmd(struct ata_queued_cmd *qc) { if (qc->flags & ATA_QCFLAG_FAILED) @@ -905,18 +951,21 @@ static void sata_fsl_post_internal_cmd(struct ata_queued_cmd *qc) static void sata_fsl_error_intr(struct ata_port *ap) { - struct ata_link *link = &ap->link; - struct ata_eh_info *ehi = &link->eh_info; struct sata_fsl_host_priv *host_priv = ap->host->private_data; void __iomem *hcr_base = host_priv->hcr_base; - u32 hstatus, dereg, cereg = 0, SError = 0; + u32 hstatus, dereg=0, cereg = 0, SError = 0; unsigned int err_mask = 0, action = 0; - struct ata_queued_cmd *qc; - int freeze = 0; + int freeze = 0, abort=0; + struct ata_link *link = NULL; + struct ata_queued_cmd *qc = NULL; + struct ata_eh_info *ehi; hstatus = ioread32(hcr_base + HSTATUS); cereg = ioread32(hcr_base + CE); + /* first, analyze and record host port events */ + link = &ap->link; + ehi = &link->eh_info; ata_ehi_clear_desc(ehi); /* @@ -926,42 +975,28 @@ static void sata_fsl_error_intr(struct ata_port *ap) sata_fsl_scr_read(ap, SCR_ERROR, &SError); if (unlikely(SError & 0xFFFF0000)) { sata_fsl_scr_write(ap, SCR_ERROR, SError); - err_mask |= AC_ERR_ATA_BUS; } DPRINTK("error_intr,hStat=0x%x,CE=0x%x,DE =0x%x,SErr=0x%x\n", hstatus, cereg, ioread32(hcr_base + DE), SError); - /* handle single device errors */ - if (cereg) { - /* - * clear the command error, also clears queue to the device - * in error, and we can (re)issue commands to this device. - * When a device is in error all commands queued into the - * host controller and at the device are considered aborted - * and the queue for that device is stopped. Now, after - * clearing the device error, we can issue commands to the - * device to interrogate it to find the source of the error. - */ - dereg = ioread32(hcr_base + DE); - iowrite32(dereg, hcr_base + DE); - iowrite32(cereg, hcr_base + CE); + /* handle fatal errors */ + if (hstatus & FATAL_ERROR_DECODE) { + ehi->err_mask |= AC_ERR_ATA_BUS; + ehi->action |= ATA_EH_SOFTRESET; - DPRINTK("single device error, CE=0x%x, DE=0x%x\n", - ioread32(hcr_base + CE), ioread32(hcr_base + DE)); /* - * We should consider this as non fatal error, and TF must - * be updated as done below. + * Ignore serror in case of fatal errors as we always want + * to do a soft-reset of the FSL SATA controller. Analyzing + * serror may cause libata to schedule a hard-reset action, + * and hard-reset currently does not do controller + * offline/online, causing command timeouts and leads to an + * un-recoverable state, hence make libATA ignore + * autopsy in case of fatal errors. */ - err_mask |= AC_ERR_DEV; - } + ehi->flags |= ATA_EHI_NO_AUTOPSY; - /* handle fatal errors */ - if (hstatus & FATAL_ERROR_DECODE) { - err_mask |= AC_ERR_ATA_BUS; - action |= ATA_EH_RESET; - /* how will fatal error interrupts be completed ?? */ freeze = 1; } @@ -971,30 +1006,83 @@ static void sata_fsl_error_intr(struct ata_port *ap) /* Setup a soft-reset EH action */ ata_ehi_hotplugged(ehi); + ata_ehi_push_desc(ehi, "%s", "PHY RDY changed"); freeze = 1; } - /* record error info */ - qc = ata_qc_from_tag(ap, link->active_tag); + /* handle single device errors */ + if (cereg) { + /* + * clear the command error, also clears queue to the device + * in error, and we can (re)issue commands to this device. + * When a device is in error all commands queued into the + * host controller and at the device are considered aborted + * and the queue for that device is stopped. Now, after + * clearing the device error, we can issue commands to the + * device to interrogate it to find the source of the error. + */ + abort = 1; + + DPRINTK("single device error, CE=0x%x, DE=0x%x\n", + ioread32(hcr_base + CE), ioread32(hcr_base + DE)); - if (qc) + /* find out the offending link and qc */ + if (ap->nr_pmp_links) { + dereg = ioread32(hcr_base + DE); + iowrite32(dereg, hcr_base + DE); + iowrite32(cereg, hcr_base + CE); + + if (dereg < ap->nr_pmp_links) { + link = &ap->pmp_link[dereg]; + ehi = &link->eh_info; + qc = ata_qc_from_tag(ap, link->active_tag); + /* + * We should consider this as non fatal error, + * and TF must be updated as done below. + */ + + err_mask |= AC_ERR_DEV; + + } else { + err_mask |= AC_ERR_HSM; + action |= ATA_EH_HARDRESET; + freeze = 1; + } + } else { + dereg = ioread32(hcr_base + DE); + iowrite32(dereg, hcr_base + DE); + iowrite32(cereg, hcr_base + CE); + + qc = ata_qc_from_tag(ap, link->active_tag); + /* + * We should consider this as non fatal error, + * and TF must be updated as done below. + */ + err_mask |= AC_ERR_DEV; + } + } + + /* record error info */ + if (qc) { qc->err_mask |= err_mask; - else + } else ehi->err_mask |= err_mask; ehi->action |= action; - ehi->serror |= SError; /* freeze or abort */ if (freeze) ata_port_freeze(ap); - else - ata_port_abort(ap); + else if (abort) { + if (qc) + ata_link_abort(qc->dev->link); + else + ata_port_abort(ap); + } } static void sata_fsl_host_intr(struct ata_port *ap) { - struct ata_link *link = &ap->link; struct sata_fsl_host_priv *host_priv = ap->host->private_data; void __iomem *hcr_base = host_priv->hcr_base; u32 hstatus, qc_active = 0; @@ -1017,10 +1105,19 @@ static void sata_fsl_host_intr(struct ata_port *ap) return; } - if (link->sactive) { /* only true for NCQ commands */ + /* Read command completed register */ + qc_active = ioread32(hcr_base + CC); + + VPRINTK("Status of all queues :\n"); + VPRINTK("qc_active/CC = 0x%x, CA = 0x%x, CE=0x%x,CQ=0x%x,apqa=0x%x\n", + qc_active, + ioread32(hcr_base + CA), + ioread32(hcr_base + CE), + ioread32(hcr_base + CQ), + ap->qc_active); + + if (qc_active & ap->qc_active) { int i; - /* Read command completed register */ - qc_active = ioread32(hcr_base + CC); /* clear CC bit, this will also complete the interrupt */ iowrite32(qc_active, hcr_base + CC); @@ -1032,8 +1129,9 @@ static void sata_fsl_host_intr(struct ata_port *ap) for (i = 0; i < SATA_FSL_QUEUE_DEPTH; i++) { if (qc_active & (1 << i)) { qc = ata_qc_from_tag(ap, i); - if (qc) + if (qc) { ata_qc_complete(qc); + } DPRINTK ("completing ncq cmd,tag=%d,CC=0x%x,CA=0x%x\n", i, ioread32(hcr_base + CC), @@ -1042,19 +1140,21 @@ static void sata_fsl_host_intr(struct ata_port *ap) } return; - } else if (ap->qc_active) { + } else if ((ap->qc_active & (1 << ATA_TAG_INTERNAL))) { iowrite32(1, hcr_base + CC); - qc = ata_qc_from_tag(ap, link->active_tag); + qc = ata_qc_from_tag(ap, ATA_TAG_INTERNAL); - DPRINTK("completing non-ncq cmd, tag=%d,CC=0x%x\n", - link->active_tag, ioread32(hcr_base + CC)); + DPRINTK("completing non-ncq cmd, CC=0x%x\n", + ioread32(hcr_base + CC)); - if (qc) + if (qc) { ata_qc_complete(qc); + } } else { /* Spurious Interrupt!! */ DPRINTK("spurious interrupt!!, CC = 0x%x\n", ioread32(hcr_base + CC)); + iowrite32(qc_active, hcr_base + CC); return; } } @@ -1130,9 +1230,6 @@ static int sata_fsl_init_controller(struct ata_host *host) iowrite32(0x00000FFFF, hcr_base + CE); iowrite32(0x00000FFFF, hcr_base + DE); - /* initially assuming no Port multiplier, set CQPMP to 0 */ - iowrite32(0x0, hcr_base + CQPMP); - /* * host controller will be brought on-line, during xx_port_start() * callback, that should also initiate the OOB, COMINIT sequence @@ -1154,8 +1251,8 @@ static struct scsi_host_template sata_fsl_sht = { .dma_boundary = ATA_DMA_BOUNDARY, }; -static const struct ata_port_operations sata_fsl_ops = { - .inherits = &sata_port_ops, +static struct ata_port_operations sata_fsl_ops = { + .inherits = &sata_pmp_port_ops, .qc_prep = sata_fsl_qc_prep, .qc_issue = sata_fsl_qc_issue, @@ -1168,10 +1265,15 @@ static const struct ata_port_operations sata_fsl_ops = { .thaw = sata_fsl_thaw, .prereset = sata_fsl_prereset, .softreset = sata_fsl_softreset, + .pmp_softreset = sata_fsl_softreset, + .error_handler = sata_fsl_error_handler, .post_internal_cmd = sata_fsl_post_internal_cmd, .port_start = sata_fsl_port_start, .port_stop = sata_fsl_port_stop, + + .pmp_attach = sata_fsl_pmp_attach, + .pmp_detach = sata_fsl_pmp_detach, }; static const struct ata_port_info sata_fsl_port_info[] = { diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index fb81f0c7a8c2..60391e9a84db 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -72,7 +72,7 @@ #include <linux/libata.h> #define DRV_NAME "sata_mv" -#define DRV_VERSION "1.21" +#define DRV_VERSION "1.24" enum { /* BAR's are enumerated in terms of pci_resource_start() terms */ @@ -122,8 +122,6 @@ enum { /* Host Flags */ MV_FLAG_DUAL_HC = (1 << 30), /* two SATA Host Controllers */ MV_FLAG_IRQ_COALESCE = (1 << 29), /* IRQ coalescing capability */ - /* SoC integrated controllers, no PCI interface */ - MV_FLAG_SOC = (1 << 28), MV_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI | @@ -226,6 +224,11 @@ enum { PHY_MODE3 = 0x310, PHY_MODE4 = 0x314, + PHY_MODE4_CFG_MASK = 0x00000003, /* phy internal config field */ + PHY_MODE4_CFG_VALUE = 0x00000001, /* phy internal config field */ + PHY_MODE4_RSVD_ZEROS = 0x5de3fffa, /* Gen2e always write zeros */ + PHY_MODE4_RSVD_ONES = 0x00000005, /* Gen2e always write ones */ + PHY_MODE2 = 0x330, SATA_IFCTL_OFS = 0x344, SATA_TESTCTL_OFS = 0x348, @@ -356,12 +359,12 @@ enum { MV_HP_ERRATA_50XXB2 = (1 << 2), MV_HP_ERRATA_60X1B2 = (1 << 3), MV_HP_ERRATA_60X1C0 = (1 << 4), - MV_HP_ERRATA_XX42A0 = (1 << 5), MV_HP_GEN_I = (1 << 6), /* Generation I: 50xx */ MV_HP_GEN_II = (1 << 7), /* Generation II: 60xx */ MV_HP_GEN_IIE = (1 << 8), /* Generation IIE: 6042/7042 */ MV_HP_PCIE = (1 << 9), /* PCIe bus/regs: 7042 */ MV_HP_CUT_THROUGH = (1 << 10), /* can use EDMA cut-through */ + MV_HP_FLAG_SOC = (1 << 11), /* SystemOnChip, no PCI */ /* Port private flags (pp_flags) */ MV_PP_FLAG_EDMA_EN = (1 << 0), /* is EDMA engine enabled? */ @@ -374,7 +377,7 @@ enum { #define IS_GEN_II(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_II) #define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE) #define IS_PCIE(hpriv) ((hpriv)->hp_flags & MV_HP_PCIE) -#define HAS_PCI(host) (!((host)->ports[0]->flags & MV_FLAG_SOC)) +#define IS_SOC(hpriv) ((hpriv)->hp_flags & MV_HP_FLAG_SOC) #define WINDOW_CTRL(i) (0x20030 + ((i) << 4)) #define WINDOW_BASE(i) (0x20034 + ((i) << 4)) @@ -652,7 +655,7 @@ static const struct ata_port_info mv_port_info[] = { .port_ops = &mv_iie_ops, }, { /* chip_soc */ - .flags = MV_GENIIE_FLAGS | MV_FLAG_SOC, + .flags = MV_GENIIE_FLAGS, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = ATA_UDMA6, .port_ops = &mv_iie_ops, @@ -812,12 +815,7 @@ static void mv_set_edma_ptrs(void __iomem *port_mmio, writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS); writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | index, port_mmio + EDMA_REQ_Q_IN_PTR_OFS); - - if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0) - writelfl((pp->crqb_dma & 0xffffffff) | index, - port_mmio + EDMA_REQ_Q_OUT_PTR_OFS); - else - writelfl(index, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS); + writelfl(index, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS); /* * initialize response queue @@ -827,13 +825,7 @@ static void mv_set_edma_ptrs(void __iomem *port_mmio, WARN_ON(pp->crpb_dma & 0xff); writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS); - - if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0) - writelfl((pp->crpb_dma & 0xffffffff) | index, - port_mmio + EDMA_RSP_Q_IN_PTR_OFS); - else - writelfl(index, port_mmio + EDMA_RSP_Q_IN_PTR_OFS); - + writelfl(index, port_mmio + EDMA_RSP_Q_IN_PTR_OFS); writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) | index, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); } @@ -1254,7 +1246,7 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq) cfg |= (1 << 23); /* do not mask PM field in rx'd FIS */ cfg |= (1 << 22); /* enab 4-entry host queue cache */ - if (HAS_PCI(ap->host)) + if (!IS_SOC(hpriv)) cfg |= (1 << 18); /* enab early completion */ if (hpriv->hp_flags & MV_HP_CUT_THROUGH) cfg |= (1 << 17); /* enab cut-thru (dis stor&forwrd) */ @@ -2225,7 +2217,7 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance) * a bogus register value which can indicate HW removal or PCI fault. */ if (pending_irqs && main_irq_cause != 0xffffffffU) { - if (unlikely((pending_irqs & PCI_ERR) && HAS_PCI(host))) + if (unlikely((pending_irqs & PCI_ERR) && !IS_SOC(hpriv))) handled = mv_pci_error(host, hpriv->base); else handled = mv_host_intr(host, pending_irqs); @@ -2547,7 +2539,7 @@ static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0); int fix_phy_mode4 = hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0); - u32 m2, tmp; + u32 m2, m3; if (fix_phy_mode2) { m2 = readl(port_mmio + PHY_MODE2); @@ -2564,28 +2556,36 @@ static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, udelay(200); } - /* who knows what this magic does */ - tmp = readl(port_mmio + PHY_MODE3); - tmp &= ~0x7F800000; - tmp |= 0x2A800000; - writel(tmp, port_mmio + PHY_MODE3); - - if (fix_phy_mode4) { - u32 m4; - - m4 = readl(port_mmio + PHY_MODE4); - - if (hp_flags & MV_HP_ERRATA_60X1B2) - tmp = readl(port_mmio + PHY_MODE3); + /* + * Gen-II/IIe PHY_MODE3 errata RM#2: + * Achieves better receiver noise performance than the h/w default: + */ + m3 = readl(port_mmio + PHY_MODE3); + m3 = (m3 & 0x1f) | (0x5555601 << 5); - /* workaround for errata FEr SATA#10 (part 1) */ - m4 = (m4 & ~(1 << 1)) | (1 << 0); + /* Guideline 88F5182 (GL# SATA-S11) */ + if (IS_SOC(hpriv)) + m3 &= ~0x1c; + if (fix_phy_mode4) { + u32 m4 = readl(port_mmio + PHY_MODE4); + /* + * Enforce reserved-bit restrictions on GenIIe devices only. + * For earlier chipsets, force only the internal config field + * (workaround for errata FEr SATA#10 part 1). + */ + if (IS_GEN_IIE(hpriv)) + m4 = (m4 & ~PHY_MODE4_RSVD_ZEROS) | PHY_MODE4_RSVD_ONES; + else + m4 = (m4 & ~PHY_MODE4_CFG_MASK) | PHY_MODE4_CFG_VALUE; writel(m4, port_mmio + PHY_MODE4); - - if (hp_flags & MV_HP_ERRATA_60X1B2) - writel(tmp, port_mmio + PHY_MODE3); } + /* + * Workaround for 60x1-B2 errata SATA#13: + * Any write to PHY_MODE4 (above) may corrupt PHY_MODE3, + * so we must always rewrite PHY_MODE3 after PHY_MODE4. + */ + writel(m3, port_mmio + PHY_MODE3); /* Revert values of pre-emphasis and signal amps to the saved ones */ m2 = readl(port_mmio + PHY_MODE2); @@ -2876,7 +2876,7 @@ static unsigned int mv_in_pcix_mode(struct ata_host *host) void __iomem *mmio = hpriv->base; u32 reg; - if (!HAS_PCI(host) || !IS_PCIE(hpriv)) + if (IS_SOC(hpriv) || !IS_PCIE(hpriv)) return 0; /* not PCI-X capable */ reg = readl(mmio + MV_PCI_MODE_OFS); if ((reg & MV_PCI_MODE_MASK) == 0) @@ -3003,10 +3003,7 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx) hp_flags |= MV_HP_CUT_THROUGH; switch (pdev->revision) { - case 0x0: - hp_flags |= MV_HP_ERRATA_XX42A0; - break; - case 0x1: + case 0x2: /* Rev.B0: the first/only public release */ hp_flags |= MV_HP_ERRATA_60X1C0; break; default: @@ -3018,7 +3015,7 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx) break; case chip_soc: hpriv->ops = &mv_soc_ops; - hp_flags |= MV_HP_ERRATA_60X1C0; + hp_flags |= MV_HP_FLAG_SOC | MV_HP_ERRATA_60X1C0; break; default: @@ -3062,12 +3059,12 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx) if (rc) goto done; - if (HAS_PCI(host)) { - hpriv->main_irq_cause_addr = mmio + PCI_HC_MAIN_IRQ_CAUSE_OFS; - hpriv->main_irq_mask_addr = mmio + PCI_HC_MAIN_IRQ_MASK_OFS; - } else { + if (IS_SOC(hpriv)) { hpriv->main_irq_cause_addr = mmio + SOC_HC_MAIN_IRQ_CAUSE_OFS; hpriv->main_irq_mask_addr = mmio + SOC_HC_MAIN_IRQ_MASK_OFS; + } else { + hpriv->main_irq_cause_addr = mmio + PCI_HC_MAIN_IRQ_CAUSE_OFS; + hpriv->main_irq_mask_addr = mmio + PCI_HC_MAIN_IRQ_MASK_OFS; } /* global interrupt mask: 0 == mask everything */ @@ -3093,7 +3090,7 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx) mv_port_init(&ap->ioaddr, port_mmio); #ifdef CONFIG_PCI - if (HAS_PCI(host)) { + if (!IS_SOC(hpriv)) { unsigned int offset = port_mmio - mmio; ata_port_pbar_desc(ap, MV_PRIMARY_BAR, -1, "mmio"); ata_port_pbar_desc(ap, MV_PRIMARY_BAR, offset, "port"); @@ -3113,7 +3110,7 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx) writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS); } - if (HAS_PCI(host)) { + if (!IS_SOC(hpriv)) { /* Clear any currently outstanding host interrupt conditions */ writelfl(0, mmio + hpriv->irq_cause_ofs); diff --git a/drivers/atm/eni.h b/drivers/atm/eni.h index d04fefb0841f..e4c9525e60b3 100644 --- a/drivers/atm/eni.h +++ b/drivers/atm/eni.h @@ -18,7 +18,6 @@ #include "midway.h" -#define KERNEL_OFFSET 0xC0000000 /* kernel 0x0 is at phys 0xC0000000 */ #define DEV_LABEL "eni" #define UBR_BUFFER (128*1024) /* UBR buffer size */ diff --git a/drivers/base/core.c b/drivers/base/core.c index 72eccae4904b..ee0a51a3a41d 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -760,6 +760,22 @@ static void device_remove_class_symlinks(struct device *dev) } /** + * dev_set_name - set a device name + * @dev: device + * @fmt: format string for the device's name + */ +int dev_set_name(struct device *dev, const char *fmt, ...) +{ + va_list vargs; + + va_start(vargs, fmt); + vsnprintf(dev->bus_id, sizeof(dev->bus_id), fmt, vargs); + va_end(vargs); + return 0; +} +EXPORT_SYMBOL_GPL(dev_set_name); + +/** * device_add - add device to device hierarchy. * @dev: device. * diff --git a/drivers/block/brd.c b/drivers/block/brd.c index 680cdfc00b90..24b97b0bef99 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -397,6 +397,7 @@ module_param(max_part, int, 0); MODULE_PARM_DESC(max_part, "Maximum number of partitions per RAM disk"); MODULE_LICENSE("GPL"); MODULE_ALIAS_BLOCKDEV_MAJOR(RAMDISK_MAJOR); +MODULE_ALIAS("rd"); #ifndef MODULE /* Legacy boot options - nonmodular */ diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index e336b05fe4a7..5f1e1cc6165a 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -53,15 +53,16 @@ #include <linux/scatterlist.h> #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin)) -#define DRIVER_NAME "HP CISS Driver (v 3.6.14)" -#define DRIVER_VERSION CCISS_DRIVER_VERSION(3,6,14) +#define DRIVER_NAME "HP CISS Driver (v 3.6.20)" +#define DRIVER_VERSION CCISS_DRIVER_VERSION(3, 6, 20) /* Embedded module documentation macros - see modules.h */ MODULE_AUTHOR("Hewlett-Packard Company"); -MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 3.6.14"); +MODULE_DESCRIPTION("Driver for HP Smart Array Controllers"); MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400" - " SA6i P600 P800 P400 P400i E200 E200i E500"); -MODULE_VERSION("3.6.14"); + " SA6i P600 P800 P400 P400i E200 E200i E500 P700m" + " Smart Array G2 Series SAS/SATA Controllers"); +MODULE_VERSION("3.6.20"); MODULE_LICENSE("GPL"); #include "cciss_cmd.h" @@ -90,6 +91,11 @@ static const struct pci_device_id cciss_pci_device_id[] = { {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3215}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x3237}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x323D}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3241}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3243}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3245}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3247}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3249}, {PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0}, {0,} @@ -123,6 +129,11 @@ static struct board_type products[] = { {0x3215103C, "Smart Array E200i", &SA5_access, 120}, {0x3237103C, "Smart Array E500", &SA5_access, 512}, {0x323D103C, "Smart Array P700m", &SA5_access, 512}, + {0x3241103C, "Smart Array P212", &SA5_access, 384}, + {0x3243103C, "Smart Array P410", &SA5_access, 384}, + {0x3245103C, "Smart Array P410i", &SA5_access, 384}, + {0x3247103C, "Smart Array P411", &SA5_access, 384}, + {0x3249103C, "Smart Array P812", &SA5_access, 384}, {0xFFFF103C, "Unknown Smart Array", &SA5_access, 120}, }; diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 84e064ffee52..dd7ea203f940 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -260,6 +260,10 @@ static int virtblk_probe(struct virtio_device *vdev) if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER)) blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL); + /* If disk is read-only in the host, the guest should obey */ + if (virtio_has_feature(vdev, VIRTIO_BLK_F_RO)) + set_disk_ro(vblk->disk, 1); + /* Host must always specify the capacity. */ vdev->config->get(vdev, offsetof(struct virtio_blk_config, capacity), &cap, sizeof(cap)); @@ -311,6 +315,7 @@ static void virtblk_remove(struct virtio_device *vdev) /* Stop all the virtqueues. */ vdev->config->reset(vdev); + del_gendisk(vblk->disk); blk_cleanup_queue(vblk->disk->queue); put_disk(vblk->disk); mempool_destroy(vblk->pool); @@ -325,7 +330,7 @@ static struct virtio_device_id id_table[] = { static unsigned int features[] = { VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, - VIRTIO_BLK_F_GEOMETRY, + VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, }; static struct virtio_driver virtio_blk = { diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 595a925c62a9..2d854bb9373e 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -118,8 +118,8 @@ config COMPUTONE order to become a dial-in server. If you have a card like that, say Y here and read <file:Documentation/computone.txt>. - To compile this driver as modules, choose M here: the - modules will be called ip2 and ip2main. + To compile this driver as module, choose M here: the + module will be called ip2. config ROCKETPORT tristate "Comtrol RocketPort support" @@ -749,7 +749,7 @@ config NVRAM if RTC_LIB=n config RTC - tristate "Enhanced Real Time Clock Support" + tristate "Enhanced Real Time Clock Support (legacy PC RTC driver)" depends on !PPC && !PARISC && !IA64 && !M68K && !SPARC && !FRV \ && !ARM && !SUPERH && !S390 && !AVR32 ---help--- @@ -1036,9 +1036,9 @@ config HPET non-periodic and/or periodic. config HPET_RTC_IRQ - bool "HPET Control RTC IRQ" if !HPET_EMULATE_RTC - default n - depends on HPET + bool + default HPET_EMULATE_RTC + depends on RTC && HPET help If you say Y here, you will disable RTC_IRQ in drivers/char/rtc.c. It is assumed the platform called hpet_alloc with the RTC IRQ values for diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index 55c97f623242..07b4d8ff56e5 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c @@ -458,6 +458,10 @@ static struct agp_device_ids ati_agp_device_ids[] __devinitdata = .chipset_name = "IGP9100/M", }, { + .device_id = PCI_DEVICE_ID_ATI_RS350_133, + .chipset_name = "IGP9000/M", + }, + { .device_id = PCI_DEVICE_ID_ATI_RS350_200, .chipset_name = "IGP9100/M", }, diff --git a/drivers/char/generic_nvram.c b/drivers/char/generic_nvram.c index 2398e864c28d..a00869c650d5 100644 --- a/drivers/char/generic_nvram.c +++ b/drivers/char/generic_nvram.c @@ -133,7 +133,7 @@ static struct miscdevice nvram_dev = { int __init nvram_init(void) { - printk(KERN_INFO "Macintosh non-volatile memory driver v%s\n", + printk(KERN_INFO "Generic non-volatile memory driver v%s\n", NVRAM_VERSION); return misc_register(&nvram_dev); } diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 8d6c2089d2a8..efd0b4db7c8e 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -112,3 +112,12 @@ config HW_RANDOM_PASEMI If unsure, say Y. +config HW_RANDOM_VIRTIO + tristate "VirtIO Random Number Generator support" + depends on HW_RANDOM && VIRTIO + ---help--- + This driver provides kernel-side support for the virtual Random Number + Generator hardware. + + To compile this driver as a module, choose M here: the + module will be called virtio-rng. If unsure, say N. diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index c8b7300e2fb1..b4940ddbb35f 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_HW_RANDOM_VIA) += via-rng.o obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o +obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c index 5cc651ef75eb..27fdc0866496 100644 --- a/drivers/char/hw_random/intel-rng.c +++ b/drivers/char/hw_random/intel-rng.c @@ -273,7 +273,7 @@ static int __init intel_rng_hw_init(void *_intel_rng_hw) if (mfc != INTEL_FWH_MANUFACTURER_CODE || (dvc != INTEL_FWH_DEVICE_CODE_8M && dvc != INTEL_FWH_DEVICE_CODE_4M)) { - printk(KERN_ERR PFX "FWH not detected\n"); + printk(KERN_NOTICE PFX "FWH not detected\n"); return -ENODEV; } diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c new file mode 100644 index 000000000000..d0e563e4fc39 --- /dev/null +++ b/drivers/char/hw_random/virtio-rng.c @@ -0,0 +1,155 @@ +/* + * Randomness driver for virtio + * Copyright (C) 2007, 2008 Rusty Russell IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <linux/err.h> +#include <linux/hw_random.h> +#include <linux/scatterlist.h> +#include <linux/spinlock.h> +#include <linux/virtio.h> +#include <linux/virtio_rng.h> + +/* The host will fill any buffer we give it with sweet, sweet randomness. We + * give it 64 bytes at a time, and the hwrng framework takes it 4 bytes at a + * time. */ +#define RANDOM_DATA_SIZE 64 + +static struct virtqueue *vq; +static u32 *random_data; +static unsigned int data_left; +static DECLARE_COMPLETION(have_data); + +static void random_recv_done(struct virtqueue *vq) +{ + int len; + + /* We never get spurious callbacks. */ + if (!vq->vq_ops->get_buf(vq, &len)) + BUG(); + + data_left = len / sizeof(random_data[0]); + complete(&have_data); +} + +static void register_buffer(void) +{ + struct scatterlist sg; + + sg_init_one(&sg, random_data, RANDOM_DATA_SIZE); + /* There should always be room for one buffer. */ + if (vq->vq_ops->add_buf(vq, &sg, 0, 1, random_data) != 0) + BUG(); + vq->vq_ops->kick(vq); +} + +/* At least we don't udelay() in a loop like some other drivers. */ +static int virtio_data_present(struct hwrng *rng, int wait) +{ + if (data_left) + return 1; + + if (!wait) + return 0; + + wait_for_completion(&have_data); + return 1; +} + +/* virtio_data_present() must have succeeded before this is called. */ +static int virtio_data_read(struct hwrng *rng, u32 *data) +{ + BUG_ON(!data_left); + + *data = random_data[--data_left]; + + if (!data_left) { + init_completion(&have_data); + register_buffer(); + } + return sizeof(*data); +} + +static struct hwrng virtio_hwrng = { + .name = "virtio", + .data_present = virtio_data_present, + .data_read = virtio_data_read, +}; + +static int virtrng_probe(struct virtio_device *vdev) +{ + int err; + + /* We expect a single virtqueue. */ + vq = vdev->config->find_vq(vdev, 0, random_recv_done); + if (IS_ERR(vq)) + return PTR_ERR(vq); + + err = hwrng_register(&virtio_hwrng); + if (err) { + vdev->config->del_vq(vq); + return err; + } + + register_buffer(); + return 0; +} + +static void virtrng_remove(struct virtio_device *vdev) +{ + vdev->config->reset(vdev); + hwrng_unregister(&virtio_hwrng); + vdev->config->del_vq(vq); +} + +static struct virtio_device_id id_table[] = { + { VIRTIO_ID_RNG, VIRTIO_DEV_ANY_ID }, + { 0 }, +}; + +static struct virtio_driver virtio_rng = { + .driver.name = KBUILD_MODNAME, + .driver.owner = THIS_MODULE, + .id_table = id_table, + .probe = virtrng_probe, + .remove = __devexit_p(virtrng_remove), +}; + +static int __init init(void) +{ + int err; + + random_data = kmalloc(RANDOM_DATA_SIZE, GFP_KERNEL); + if (!random_data) + return -ENOMEM; + + err = register_virtio_driver(&virtio_rng); + if (err) + kfree(random_data); + return err; +} + +static void __exit fini(void) +{ + kfree(random_data); + unregister_virtio_driver(&virtio_rng); +} +module_init(init); +module_exit(fini); + +MODULE_DEVICE_TABLE(virtio, id_table); +MODULE_DESCRIPTION("Virtio random number driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 7f7e798c1384..d9a0a53c842d 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -677,12 +677,7 @@ static void k_deadunicode(struct vc_data *vc, unsigned int value, char up_flag) static void k_self(struct vc_data *vc, unsigned char value, char up_flag) { - unsigned int uni; - if (kbd->kbdmode == VC_UNICODE) - uni = value; - else - uni = conv_8bit_to_uni(value); - k_unicode(vc, uni, up_flag); + k_unicode(vc, conv_8bit_to_uni(value), up_flag); } static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag) diff --git a/drivers/char/pcmcia/ipwireless/hardware.c b/drivers/char/pcmcia/ipwireless/hardware.c index fa9d3c945f31..ba6340ae98af 100644 --- a/drivers/char/pcmcia/ipwireless/hardware.c +++ b/drivers/char/pcmcia/ipwireless/hardware.c @@ -251,10 +251,11 @@ struct ipw_hardware { int init_loops; struct timer_list setup_timer; + /* Flag if hw is ready to send next packet */ int tx_ready; - struct list_head tx_queue[NL_NUM_OF_PRIORITIES]; - /* True if any packets are queued for transmission */ + /* Count of pending packets to be sent */ int tx_queued; + struct list_head tx_queue[NL_NUM_OF_PRIORITIES]; int rx_bytes_queued; struct list_head rx_queue; @@ -404,6 +405,8 @@ static int do_send_fragment(struct ipw_hardware *hw, const unsigned char *data, spin_lock_irqsave(&hw->spinlock, flags); + hw->tx_ready = 0; + if (hw->hw_version == HW_VERSION_1) { outw((unsigned short) length, hw->base_port + IODWR); @@ -492,6 +495,7 @@ static int do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet) spin_lock_irqsave(&hw->spinlock, flags); list_add(&packet->queue, &hw->tx_queue[0]); + hw->tx_queued++; spin_unlock_irqrestore(&hw->spinlock, flags); } else { if (packet->packet_callback) @@ -949,12 +953,10 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) unsigned long flags; spin_lock_irqsave(&hw->spinlock, flags); - if (hw->tx_queued && hw->tx_ready != 0) { + if (hw->tx_queued && hw->tx_ready) { int priority; struct ipw_tx_packet *packet = NULL; - hw->tx_ready--; - /* Pick a packet */ for (priority = 0; priority < priority_limit; priority++) { if (!list_empty(&hw->tx_queue[priority])) { @@ -963,6 +965,7 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) struct ipw_tx_packet, queue); + hw->tx_queued--; list_del(&packet->queue); break; @@ -973,6 +976,7 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) spin_unlock_irqrestore(&hw->spinlock, flags); return 0; } + spin_unlock_irqrestore(&hw->spinlock, flags); /* Send */ @@ -1063,7 +1067,7 @@ static irqreturn_t ipwireless_handle_v1_interrupt(int irq, if (irqn & IR_TXINTR) { ack |= IR_TXINTR; spin_lock_irqsave(&hw->spinlock, flags); - hw->tx_ready++; + hw->tx_ready = 1; spin_unlock_irqrestore(&hw->spinlock, flags); } /* Received data */ @@ -1170,7 +1174,7 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, if (memrxdone & MEMRX_RX_DONE) { writew(0, &hw->memory_info_regs->memreg_rx_done); spin_lock_irqsave(&hw->spinlock, flags); - hw->tx_ready++; + hw->tx_ready = 1; spin_unlock_irqrestore(&hw->spinlock, flags); tx = 1; } @@ -1234,7 +1238,7 @@ static void send_packet(struct ipw_hardware *hw, int priority, spin_lock_irqsave(&hw->spinlock, flags); list_add_tail(&packet->queue, &hw->tx_queue[priority]); - hw->tx_queued = 1; + hw->tx_queued++; spin_unlock_irqrestore(&hw->spinlock, flags); flush_packets_to_hw(hw); diff --git a/drivers/char/vt.c b/drivers/char/vt.c index fa1ffbf2c621..935f1c207a1f 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -434,7 +434,7 @@ static void update_attr(struct vc_data *vc) vc->vc_blink, vc->vc_underline, vc->vc_reverse ^ vc->vc_decscnm, vc->vc_italic); vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, 1, vc->vc_blink, 0, vc->vc_decscnm, 0) << 8) | ' '; - vc->vc_scrl_erase_char = (build_attr(vc, vc->vc_def_color, 1, false, false, false, false) << 8) | ' '; + vc->vc_scrl_erase_char = (build_attr(vc, vc->vc_def_color, 1, false, false, vc->vc_decscnm, false) << 8) | ' '; } /* Note: inverting the screen twice should revert to the original state */ @@ -909,7 +909,7 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) if (vc->vc_tty) { struct winsize ws, *cws = &vc->vc_tty->winsize; - unsigned long flags; + struct pid *pgrp = NULL; memset(&ws, 0, sizeof(ws)); ws.ws_row = vc->vc_rows; @@ -917,11 +917,14 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) ws.ws_ypixel = vc->vc_scan_lines; mutex_lock(&vc->vc_tty->termios_mutex); - spin_lock_irqsave(&vc->vc_tty->ctrl_lock, flags); - if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col) && - vc->vc_tty->pgrp) + spin_lock_irq(&vc->vc_tty->ctrl_lock); + if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col)) + pgrp = get_pid(vc->vc_tty->pgrp); + spin_unlock_irq(&vc->vc_tty->ctrl_lock); + if (pgrp) { kill_pgrp(vc->vc_tty->pgrp, SIGWINCH, 1); - spin_unlock_irqrestore(&vc->vc_tty->ctrl_lock, flags); + put_pid(pgrp); + } *cws = ws; mutex_unlock(&vc->vc_tty->termios_mutex); } diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 7fce038fa57e..1d41496ed2f8 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -412,7 +412,7 @@ static int cpufreq_parse_governor(char *str_governor, unsigned int *policy, int ret; mutex_unlock(&cpufreq_governor_mutex); - ret = request_module(name); + ret = request_module("%s", name); mutex_lock(&cpufreq_governor_mutex); if (ret == 0) @@ -625,7 +625,7 @@ static ssize_t store_scaling_setspeed(struct cpufreq_policy *policy, unsigned int freq = 0; unsigned int ret; - if (!policy->governor->store_setspeed) + if (!policy->governor || !policy->governor->store_setspeed) return -EINVAL; ret = sscanf(buf, "%u", &freq); @@ -639,7 +639,7 @@ static ssize_t store_scaling_setspeed(struct cpufreq_policy *policy, static ssize_t show_scaling_setspeed(struct cpufreq_policy *policy, char *buf) { - if (!policy->governor->show_setspeed) + if (!policy->governor || !policy->governor->show_setspeed) return sprintf(buf, "<unsupported>\n"); return policy->governor->show_setspeed(policy, buf); @@ -928,13 +928,13 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) policy->user_policy.policy = policy->policy; policy->user_policy.governor = policy->governor; - unlock_policy_rwsem_write(cpu); - if (ret) { dprintk("setting policy failed\n"); goto err_out_unregister; } + unlock_policy_rwsem_write(cpu); + kobject_uevent(&policy->kobj, KOBJ_ADD); module_put(cpufreq_driver->owner); dprintk("initialization complete\n"); diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index fc555a90bb21..23554b676d6e 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -38,6 +38,8 @@ static void cpuidle_kick_cpus(void) static void cpuidle_kick_cpus(void) {} #endif +static int __cpuidle_register_device(struct cpuidle_device *dev); + /** * cpuidle_idle_call - the main idle loop * @@ -138,6 +140,12 @@ int cpuidle_enable_device(struct cpuidle_device *dev) if (!dev->state_count) return -EINVAL; + if (dev->registered == 0) { + ret = __cpuidle_register_device(dev); + if (ret) + return ret; + } + if ((ret = cpuidle_add_state_sysfs(dev))) return ret; @@ -232,10 +240,13 @@ static void poll_idle_init(struct cpuidle_device *dev) {} #endif /* CONFIG_ARCH_HAS_CPU_RELAX */ /** - * cpuidle_register_device - registers a CPU's idle PM feature + * __cpuidle_register_device - internal register function called before register + * and enable routines * @dev: the cpu + * + * cpuidle_lock mutex must be held before this is called */ -int cpuidle_register_device(struct cpuidle_device *dev) +static int __cpuidle_register_device(struct cpuidle_device *dev) { int ret; struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu); @@ -247,18 +258,34 @@ int cpuidle_register_device(struct cpuidle_device *dev) init_completion(&dev->kobj_unregister); - mutex_lock(&cpuidle_lock); - poll_idle_init(dev); per_cpu(cpuidle_devices, dev->cpu) = dev; list_add(&dev->device_list, &cpuidle_detected_devices); if ((ret = cpuidle_add_sysfs(sys_dev))) { - mutex_unlock(&cpuidle_lock); module_put(cpuidle_curr_driver->owner); return ret; } + dev->registered = 1; + return 0; +} + +/** + * cpuidle_register_device - registers a CPU's idle PM feature + * @dev: the cpu + */ +int cpuidle_register_device(struct cpuidle_device *dev) +{ + int ret; + + mutex_lock(&cpuidle_lock); + + if ((ret = __cpuidle_register_device(dev))) { + mutex_unlock(&cpuidle_lock); + return ret; + } + cpuidle_enable_device(dev); cpuidle_install_idle_handler(); @@ -278,6 +305,9 @@ void cpuidle_unregister_device(struct cpuidle_device *dev) { struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu); + if (dev->registered == 0) + return; + cpuidle_pause_and_lock(); cpuidle_disable_device(dev); diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c index 744011989044..9e4f59dc7f1e 100644 --- a/drivers/firmware/edd.c +++ b/drivers/firmware/edd.c @@ -753,7 +753,7 @@ edd_init(void) if (!edd_num_devices()) { printk(KERN_INFO "EDD information not available.\n"); - return 1; + return -ENODEV; } edd_kset = kset_create_and_add("edd", NULL, firmware_kobj); diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c index 88e89653daaf..26df06f840eb 100644 --- a/drivers/hwmon/hdaps.c +++ b/drivers/hwmon/hdaps.c @@ -522,6 +522,7 @@ static struct dmi_system_id __initdata hdaps_whitelist[] = { HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T42"), HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T43"), HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T60"), + HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T61"), HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad X40"), HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad X41"), HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X60"), diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c index 5c006c9a4311..c9416e657487 100644 --- a/drivers/hwmon/ibmaem.c +++ b/drivers/hwmon/ibmaem.c @@ -189,8 +189,8 @@ static struct aem_iana_id system_x_id = { struct aem_find_firmware_req { struct aem_iana_id id; u8 rsvd; - u16 index; - u16 module_type_id; + __be16 index; + __be16 module_type_id; } __packed; struct aem_find_firmware_resp { @@ -202,7 +202,7 @@ struct aem_find_firmware_resp { struct aem_find_instance_req { struct aem_iana_id id; u8 instance_number; - u16 module_type_id; + __be16 module_type_id; } __packed; struct aem_find_instance_resp { @@ -444,17 +444,17 @@ static int aem_read_sensor(struct aem_data *data, u8 elt, u8 reg, } case 2: { u16 *x = buf; - *x = be16_to_cpup((u16 *)rs_resp->bytes); + *x = be16_to_cpup((__be16 *)rs_resp->bytes); break; } case 4: { u32 *x = buf; - *x = be32_to_cpup((u32 *)rs_resp->bytes); + *x = be32_to_cpup((__be32 *)rs_resp->bytes); break; } case 8: { u64 *x = buf; - *x = be64_to_cpup((u64 *)rs_resp->bytes); + *x = be64_to_cpup((__be64 *)rs_resp->bytes); break; } } diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index b4f3aefa12b6..1607536ff5fb 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -1028,6 +1028,7 @@ endif config BLK_DEV_HD_ONLY bool "Old hard disk (MFM/RLL/IDE) driver" + depends on !ARM || ARCH_RPC || ARCH_SHARK || BROKEN help There are two drivers for MFM/RLL/IDE hard disks. Most people use the newer enhanced driver, but this old one is still around for two diff --git a/drivers/ide/arm/bast-ide.c b/drivers/ide/arm/bast-ide.c index 713cef20622e..8e8c28104b45 100644 --- a/drivers/ide/arm/bast-ide.c +++ b/drivers/ide/arm/bast-ide.c @@ -42,6 +42,7 @@ static int __init bastide_register(unsigned int base, unsigned int aux, int irq) hw.io_ports.ctl_addr = aux + (6 * 0x20); hw.irq = irq; + hw.chipset = ide_generic; hwif = ide_find_port(); if (hwif == NULL) diff --git a/drivers/ide/arm/ide_arm.c b/drivers/ide/arm/ide_arm.c index 4263ffd4ab20..2f311da4c963 100644 --- a/drivers/ide/arm/ide_arm.c +++ b/drivers/ide/arm/ide_arm.c @@ -49,6 +49,7 @@ static int __init ide_arm_init(void) memset(&hw, 0, sizeof(hw)); ide_std_init_ports(&hw, base, ctl); hw.irq = IDE_ARM_IRQ; + hw.chipset = ide_generic; hwif = ide_find_port(); if (hwif) { diff --git a/drivers/ide/arm/palm_bk3710.c b/drivers/ide/arm/palm_bk3710.c index 96378ebfb31f..d024ac8fad14 100644 --- a/drivers/ide/arm/palm_bk3710.c +++ b/drivers/ide/arm/palm_bk3710.c @@ -409,9 +409,6 @@ static int __devinit palm_bk3710_probe(struct platform_device *pdev) ide_device_add(idx, &palm_bk3710_port_info); - if (!hwif->present) - goto out; - return 0; out: printk(KERN_WARNING "Palm Chip BK3710 IDE Register Fail\n"); diff --git a/drivers/ide/ide-generic.c b/drivers/ide/ide-generic.c index a6073e248f45..2d92214096ab 100644 --- a/drivers/ide/ide-generic.c +++ b/drivers/ide/ide-generic.c @@ -22,6 +22,10 @@ #define DRV_NAME "ide_generic" +static int probe_mask = 0x03; +module_param(probe_mask, int, 0); +MODULE_PARM_DESC(probe_mask, "probe mask for legacy ISA IDE ports"); + static ssize_t store_add(struct class *cls, const char *buf, size_t n) { ide_hwif_t *hwif; @@ -89,6 +93,9 @@ static int __init ide_generic_init(void) u8 idx[MAX_HWIFS]; int i; + printk(KERN_INFO DRV_NAME ": please use \"probe_mask=0x3f\" module " + "parameter for probing all legacy ISA IDE ports\n"); + for (i = 0; i < MAX_HWIFS; i++) { ide_hwif_t *hwif; unsigned long io_addr = ide_default_io_base(i); @@ -96,7 +103,7 @@ static int __init ide_generic_init(void) idx[i] = 0xff; - if (io_addr) { + if ((probe_mask & (1 << i)) && io_addr) { if (!request_region(io_addr, 8, DRV_NAME)) { printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX " "not free.\n", @@ -125,6 +132,7 @@ static int __init ide_generic_init(void) memset(&hw, 0, sizeof(hw)); ide_std_init_ports(&hw, io_addr, io_addr + 0x206); hw.irq = ide_default_irq(io_addr); + hw.chipset = ide_generic; ide_init_port_hw(hwif, &hw); idx[i] = i; diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c index 6a8953f68e9f..adbd01784162 100644 --- a/drivers/ide/ide-pnp.c +++ b/drivers/ide/ide-pnp.c @@ -55,6 +55,7 @@ static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) memset(&hw, 0, sizeof(hw)); ide_std_init_ports(&hw, base, ctl); hw.irq = pnp_irq(dev, 0); + hw.chipset = ide_generic; hwif = ide_find_port(); if (hwif) { diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 655ec7ef568a..380fa0c8cc84 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1333,8 +1333,7 @@ static void ide_port_init_devices(ide_hwif_t *hwif) static void ide_init_port(ide_hwif_t *hwif, unsigned int port, const struct ide_port_info *d) { - if (d->chipset != ide_etrax100) - hwif->channel = port; + hwif->channel = port; if (d->chipset) hwif->chipset = d->chipset; @@ -1519,7 +1518,7 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d) continue; } - if (d->chipset != ide_etrax100 && (i & 1) && mate) { + if ((i & 1) && mate) { hwif->mate = mate; mate->mate = hwif; } @@ -1665,6 +1664,7 @@ static void ide_legacy_init_one(u8 *idx, hw_regs_t *hw, u8 port_no, ide_std_init_ports(hw, base, ctl); hw->irq = irq; + hw->chipset = d->chipset; hwif = ide_find_port_slot(d); if (hwif) { diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index 8d6ad812a014..55ec7f798772 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -63,7 +63,6 @@ static int proc_ide_read_imodel case ide_pmac: name = "mac-io"; break; case ide_au1xxx: name = "au1xxx"; break; case ide_palm3710: name = "palm3710"; break; - case ide_etrax100: name = "etrax100"; break; case ide_acorn: name = "acorn"; break; default: name = "(unknown)"; break; } diff --git a/drivers/ide/legacy/buddha.c b/drivers/ide/legacy/buddha.c index 5c730e4dd735..9a1d27ef3f8a 100644 --- a/drivers/ide/legacy/buddha.c +++ b/drivers/ide/legacy/buddha.c @@ -138,6 +138,8 @@ static void __init buddha_setup_ports(hw_regs_t *hw, unsigned long base, hw->irq = IRQ_AMIGA_PORTS; hw->ack_intr = ack_intr; + + hw->chipset = ide_generic; } /* diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/legacy/falconide.c index 9e449a0c623f..af11028b4794 100644 --- a/drivers/ide/legacy/falconide.c +++ b/drivers/ide/legacy/falconide.c @@ -81,6 +81,8 @@ static void __init falconide_setup_ports(hw_regs_t *hw) hw->irq = IRQ_MFP_IDE; hw->ack_intr = NULL; + + hw->chipset = ide_generic; } /* diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c index a9c2593a898c..fed7d812761c 100644 --- a/drivers/ide/legacy/gayle.c +++ b/drivers/ide/legacy/gayle.c @@ -16,6 +16,7 @@ #include <linux/ide.h> #include <linux/init.h> #include <linux/zorro.h> +#include <linux/module.h> #include <asm/setup.h> #include <asm/amigahw.h> @@ -62,7 +63,10 @@ GAYLE_NUM_HWIFS-1) #define GAYLE_HAS_CONTROL_REG (!ide_doubler) #define GAYLE_IDEREG_SIZE (ide_doubler ? 0x1000 : 0x2000) + int ide_doubler = 0; /* support IDE doublers? */ +EXPORT_SYMBOL_GPL(ide_doubler); + module_param_named(doubler, ide_doubler, bool, 0); MODULE_PARM_DESC(doubler, "enable support for IDE doublers"); #endif /* CONFIG_BLK_DEV_IDEDOUBLER */ @@ -112,6 +116,8 @@ static void __init gayle_setup_ports(hw_regs_t *hw, unsigned long base, hw->irq = IRQ_AMIGA_PORTS; hw->ack_intr = ack_intr; + + hw->chipset = ide_generic; } /* diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index aa2ea3deac85..f633b6b3c7f3 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c @@ -135,13 +135,17 @@ static void ide_detach(struct pcmcia_device *link) { ide_info_t *info = link->priv; ide_hwif_t *hwif = info->hwif; + unsigned long data_addr, ctl_addr; DEBUG(0, "ide_detach(0x%p)\n", link); + data_addr = hwif->io_ports.data_addr; + ctl_addr = hwif->io_ports.ctl_addr; + ide_release(link); - release_region(hwif->io_ports.ctl_addr, 1); - release_region(hwif->io_ports.data_addr, 8); + release_region(ctl_addr, 1); + release_region(data_addr, 8); kfree(info); } /* ide_detach */ @@ -194,6 +198,16 @@ static ide_hwif_t *idecs_register(unsigned long io, unsigned long ctl, if (hwif->present) return hwif; + /* retry registration in case device is still spinning up */ + for (i = 0; i < 10; i++) { + msleep(100); + ide_port_scan(hwif); + if (hwif->present) + return hwif; + } + + return hwif; + out_release: release_region(ctl, 1); release_region(io, 8); @@ -222,7 +236,7 @@ static int ide_config(struct pcmcia_device *link) cistpl_cftable_entry_t dflt; } *stk = NULL; cistpl_cftable_entry_t *cfg; - int i, pass, last_ret = 0, last_fn = 0, is_kme = 0; + int pass, last_ret = 0, last_fn = 0, is_kme = 0; unsigned long io_base, ctl_base; ide_hwif_t *hwif; @@ -319,30 +333,15 @@ static int ide_config(struct pcmcia_device *link) if (is_kme) outb(0x81, ctl_base+1); - /* retry registration in case device is still spinning up */ - for (i = 0; i < 10; i++) { - hwif = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link); - if (hwif) - break; - if (link->io.NumPorts1 == 0x20) { + hwif = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link); + if (hwif == NULL && link->io.NumPorts1 == 0x20) { outb(0x02, ctl_base + 0x10); hwif = idecs_register(io_base + 0x10, ctl_base + 0x10, link->irq.AssignedIRQ, link); - if (hwif) { - io_base += 0x10; - ctl_base += 0x10; - break; - } - } - msleep(100); } - if (hwif == NULL) { - printk(KERN_NOTICE "ide-cs: ide_register() at 0x%3lx & 0x%3lx" - ", irq %u failed\n", io_base, ctl_base, - link->irq.AssignedIRQ); + if (hwif == NULL) goto failed; - } info->ndev = 1; sprintf(info->node.dev_name, "hd%c", 'a' + hwif->index * 2); diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c index caa2632dd08e..2e84290d0bcc 100644 --- a/drivers/ide/legacy/macide.c +++ b/drivers/ide/legacy/macide.c @@ -78,6 +78,8 @@ static void __init macide_setup_ports(hw_regs_t *hw, unsigned long base, hw->irq = irq; hw->ack_intr = ack_intr; + + hw->chipset = ide_generic; } static const char *mac_ide_name[] = diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c index 6f535d00e638..8ff6e2d20834 100644 --- a/drivers/ide/legacy/q40ide.c +++ b/drivers/ide/legacy/q40ide.c @@ -70,6 +70,8 @@ static void q40_ide_setup_ports(hw_regs_t *hw, unsigned long base, hw->irq = irq; hw->ack_intr = ack_intr; + + hw->chipset = ide_generic; } static void q40ide_input_data(ide_drive_t *drive, struct request *rq, diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c index aaf38109eaec..b38a1980dcd5 100644 --- a/drivers/ide/pci/cmd640.c +++ b/drivers/ide/pci/cmd640.c @@ -747,9 +747,11 @@ static int __init cmd640x_init(void) ide_std_init_ports(&hw[0], 0x1f0, 0x3f6); hw[0].irq = 14; + hw[0].chipset = ide_cmd640; ide_std_init_ports(&hw[1], 0x170, 0x376); hw[1].irq = 15; + hw[1].chipset = ide_cmd640; printk(KERN_INFO "cmd640: buggy cmd640%c interface on %s, config=0x%02x" "\n", 'a' + cmd640_chip_version - 1, bus_type, cfr); diff --git a/drivers/ide/pci/delkin_cb.c b/drivers/ide/pci/delkin_cb.c index b9e457996d0e..af0f30051d5a 100644 --- a/drivers/ide/pci/delkin_cb.c +++ b/drivers/ide/pci/delkin_cb.c @@ -47,13 +47,18 @@ static const struct ide_port_ops delkin_cb_port_ops = { .quirkproc = ide_undecoded_slave, }; +static const struct ide_port_info delkin_cb_port_info = { + .port_ops = &delkin_cb_port_ops, + .host_flags = IDE_HFLAG_IO_32BIT | IDE_HFLAG_UNMASK_IRQS | + IDE_HFLAG_NO_DMA, +}; + static int __devinit delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) { unsigned long base; hw_regs_t hw; ide_hwif_t *hwif = NULL; - ide_drive_t *drive; int i, rc; u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; @@ -79,6 +84,7 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) memset(&hw, 0, sizeof(hw)); ide_std_init_ports(&hw, base + 0x10, base + 0x1e); hw.irq = dev->irq; + hw.dev = &dev->dev; hw.chipset = ide_pci; /* this enables IRQ sharing */ hwif = ide_find_port(); @@ -89,26 +95,16 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) ide_init_port_data(hwif, i); ide_init_port_hw(hwif, &hw); - hwif->port_ops = &delkin_cb_port_ops; idx[0] = i; - ide_device_add(idx, NULL); - - if (!hwif->present) - goto out_disable; + ide_device_add(idx, &delkin_cb_port_info); pci_set_drvdata(dev, hwif); - hwif->dev = &dev->dev; - drive = &hwif->drives[0]; - if (drive->present) { - drive->io_32bit = 1; - drive->unmask = 1; - } + return 0; out_disable: - printk(KERN_ERR "delkin_cb: no IDE devices found\n"); pci_release_regions(dev); pci_disable_device(dev); return -ENODEV; @@ -139,14 +135,12 @@ static struct pci_driver driver = { .remove = delkin_cb_remove, }; -static int -delkin_cb_init (void) +static int __init delkin_cb_init(void) { return pci_register_driver(&driver); } -static void -delkin_cb_exit (void) +static void __exit delkin_cb_exit(void) { pci_unregister_driver(&driver); } diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c index 6e99080497bf..725c80508d90 100644 --- a/drivers/ide/pci/opti621.c +++ b/drivers/ide/pci/opti621.c @@ -81,8 +81,6 @@ * 0.5 doesn't work. */ -#define OPTI621_DEBUG /* define for debug messages */ - #include <linux/types.h> #include <linux/module.h> #include <linux/kernel.h> @@ -92,28 +90,6 @@ #include <asm/io.h> -//#define OPTI621_MAX_PIO 3 -/* In fact, I do not have any PIO 4 drive - * (address: 25 ns, data: 70 ns, recovery: 35 ns), - * but OPTi 82C621 is programmable and it can do (minimal values): - * on 40MHz PCI bus (pulse 25 ns): - * address: 25 ns, data: 25 ns, recovery: 50 ns; - * on 20MHz PCI bus (pulse 50 ns): - * address: 50 ns, data: 50 ns, recovery: 100 ns. - */ - -/* #define READ_PREFETCH 0 */ -/* Uncomment for disable read prefetch. - * There is some readprefetch capatibility in hdparm, - * but when I type hdparm -P 1 /dev/hda, I got errors - * and till reset drive is inaccessible. - * This (hw) read prefetch is safe on my drive. - */ - -#ifndef READ_PREFETCH -#define READ_PREFETCH 0x40 /* read prefetch is enabled */ -#endif /* else read prefetch is disabled */ - #define READ_REG 0 /* index of Read cycle timing register */ #define WRITE_REG 1 /* index of Write cycle timing register */ #define CNTRL_REG 3 /* index of Control register */ @@ -122,51 +98,8 @@ static int reg_base; -#define PIO_NOT_EXIST 254 -#define PIO_DONT_KNOW 255 - static DEFINE_SPINLOCK(opti621_lock); -/* there are stored pio numbers from other calls of opti621_set_pio_mode */ -static void compute_pios(ide_drive_t *drive, const u8 pio) -/* Store values into drive->drive_data - * second_contr - 0 for primary controller, 1 for secondary - * slave_drive - 0 -> pio is for master, 1 -> pio is for slave - * pio - PIO mode for selected drive (for other we don't know) - */ -{ - int d; - ide_hwif_t *hwif = HWIF(drive); - - drive->drive_data = pio; - - for (d = 0; d < 2; ++d) { - drive = &hwif->drives[d]; - if (drive->present) { - if (drive->drive_data == PIO_DONT_KNOW) - drive->drive_data = ide_get_best_pio_mode(drive, 255, 3); -#ifdef OPTI621_DEBUG - printk("%s: Selected PIO mode %d\n", - drive->name, drive->drive_data); -#endif - } else { - drive->drive_data = PIO_NOT_EXIST; - } - } -} - -static int cmpt_clk(int time, int bus_speed) -/* Returns (rounded up) time in clocks for time in ns, - * with bus_speed in MHz. - * Example: bus_speed = 40 MHz, time = 80 ns - * 1000/40 = 25 ns (clk value), - * 80/25 = 3.2, rounded up to 4 (I hope ;-)). - * Use idebus=xx to select right frequency. - */ -{ - return ((time*bus_speed+999)/1000); -} - /* Write value to register reg, base of register * is at reg_base (0x1f0 primary, 0x170 secondary, * if not changed by PCI configuration). @@ -199,83 +132,29 @@ static u8 read_reg(int reg) return ret; } -typedef struct pio_clocks_s { - int address_time; /* Address setup (clocks) */ - int data_time; /* Active/data pulse (clocks) */ - int recovery_time; /* Recovery time (clocks) */ -} pio_clocks_t; - -static void compute_clocks(int pio, pio_clocks_t *clks) -{ - if (pio != PIO_NOT_EXIST) { - int adr_setup, data_pls; - int bus_speed = ide_pci_clk ? ide_pci_clk : system_bus_clock(); - - adr_setup = ide_pio_timings[pio].setup_time; - data_pls = ide_pio_timings[pio].active_time; - clks->address_time = cmpt_clk(adr_setup, bus_speed); - clks->data_time = cmpt_clk(data_pls, bus_speed); - clks->recovery_time = cmpt_clk(ide_pio_timings[pio].cycle_time - - adr_setup-data_pls, bus_speed); - if (clks->address_time < 1) - clks->address_time = 1; - if (clks->address_time > 4) - clks->address_time = 4; - if (clks->data_time < 1) - clks->data_time = 1; - if (clks->data_time > 16) - clks->data_time = 16; - if (clks->recovery_time < 2) - clks->recovery_time = 2; - if (clks->recovery_time > 17) - clks->recovery_time = 17; - } else { - clks->address_time = 1; - clks->data_time = 1; - clks->recovery_time = 2; - /* minimal values */ - } -} - static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio) { - /* primary and secondary drives share some registers, - * so we have to program both drives - */ + ide_hwif_t *hwif = drive->hwif; + ide_drive_t *pair = ide_get_paired_drive(drive); unsigned long flags; - u8 pio1 = 0, pio2 = 0; - pio_clocks_t first, second; - int ax, drdy; - u8 cycle1, cycle2, misc; - ide_hwif_t *hwif = HWIF(drive); - - /* sets drive->drive_data for both drives */ - compute_pios(drive, pio); - pio1 = hwif->drives[0].drive_data; - pio2 = hwif->drives[1].drive_data; - - compute_clocks(pio1, &first); - compute_clocks(pio2, &second); - - /* ax = max(a1,a2) */ - ax = (first.address_time < second.address_time) ? second.address_time : first.address_time; - - drdy = 2; /* DRDY is default 2 (by OPTi Databook) */ - - cycle1 = ((first.data_time-1)<<4) | (first.recovery_time-2); - cycle2 = ((second.data_time-1)<<4) | (second.recovery_time-2); - misc = READ_PREFETCH | ((ax-1)<<4) | ((drdy-2)<<1); - -#ifdef OPTI621_DEBUG - printk("%s: master: address: %d, data: %d, " - "recovery: %d, drdy: %d [clk]\n", - hwif->name, ax, first.data_time, - first.recovery_time, drdy); - printk("%s: slave: address: %d, data: %d, " - "recovery: %d, drdy: %d [clk]\n", - hwif->name, ax, second.data_time, - second.recovery_time, drdy); -#endif + u8 tim, misc, addr_pio = pio, clk; + + /* DRDY is default 2 (by OPTi Databook) */ + static const u8 addr_timings[2][5] = { + { 0x20, 0x10, 0x00, 0x00, 0x00 }, /* 33 MHz */ + { 0x10, 0x10, 0x00, 0x00, 0x00 }, /* 25 MHz */ + }; + static const u8 data_rec_timings[2][5] = { + { 0x5b, 0x45, 0x32, 0x21, 0x20 }, /* 33 MHz */ + { 0x48, 0x34, 0x21, 0x10, 0x10 } /* 25 MHz */ + }; + + drive->drive_data = XFER_PIO_0 + pio; + + if (pair->present) { + if (pair->drive_data && pair->drive_data < drive->drive_data) + addr_pio = pair->drive_data - XFER_PIO_0; + } spin_lock_irqsave(&opti621_lock, flags); @@ -289,24 +168,21 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio) (void)inb(reg_base + CNTRL_REG); /* if reads 0xc0, no interface exist? */ read_reg(CNTRL_REG); - /* read version, probably 0 */ - read_reg(STRAP_REG); - /* program primary drive */ - /* select Index-0 for Register-A */ - write_reg(0, MISC_REG); - /* set read cycle timings */ - write_reg(cycle1, READ_REG); - /* set write cycle timings */ - write_reg(cycle1, WRITE_REG); + /* check CLK speed */ + clk = read_reg(STRAP_REG) & 1; + + printk(KERN_INFO "%s: CLK = %d MHz\n", hwif->name, clk ? 25 : 33); - /* program secondary drive */ - /* select Index-1 for Register-B */ - write_reg(1, MISC_REG); + tim = data_rec_timings[clk][pio]; + misc = addr_timings[clk][addr_pio]; + + /* select Index-0/1 for Register-A/B */ + write_reg(drive->select.b.unit, MISC_REG); /* set read cycle timings */ - write_reg(cycle2, READ_REG); + write_reg(tim, READ_REG); /* set write cycle timings */ - write_reg(cycle2, WRITE_REG); + write_reg(tim, WRITE_REG); /* use Register-A for drive 0 */ /* use Register-B for drive 1 */ @@ -319,45 +195,26 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio) spin_unlock_irqrestore(&opti621_lock, flags); } -static void __devinit opti621_port_init_devs(ide_hwif_t *hwif) -{ - hwif->drives[0].drive_data = PIO_DONT_KNOW; - hwif->drives[1].drive_data = PIO_DONT_KNOW; -} - static const struct ide_port_ops opti621_port_ops = { - .port_init_devs = opti621_port_init_devs, .set_pio_mode = opti621_set_pio_mode, }; -static const struct ide_port_info opti621_chipsets[] __devinitdata = { - { /* 0 */ - .name = "OPTI621", - .enablebits = { {0x45, 0x80, 0x00}, {0x40, 0x08, 0x00} }, - .port_ops = &opti621_port_ops, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA, - .pio_mask = ATA_PIO3, - .swdma_mask = ATA_SWDMA2, - .mwdma_mask = ATA_MWDMA2, - }, { /* 1 */ - .name = "OPTI621X", - .enablebits = { {0x45, 0x80, 0x00}, {0x40, 0x08, 0x00} }, - .port_ops = &opti621_port_ops, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA, - .pio_mask = ATA_PIO3, - .swdma_mask = ATA_SWDMA2, - .mwdma_mask = ATA_MWDMA2, - } +static const struct ide_port_info opti621_chipset __devinitdata = { + .name = "OPTI621/X", + .enablebits = { {0x45, 0x80, 0x00}, {0x40, 0x08, 0x00} }, + .port_ops = &opti621_port_ops, + .host_flags = IDE_HFLAG_NO_DMA, + .pio_mask = ATA_PIO4, }; static int __devinit opti621_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - return ide_setup_pci_device(dev, &opti621_chipsets[id->driver_data]); + return ide_setup_pci_device(dev, &opti621_chipset); } static const struct pci_device_id opti621_pci_tbl[] = { { PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C621), 0 }, - { PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C825), 1 }, + { PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C825), 0 }, { 0, }, }; MODULE_DEVICE_TABLE(pci, opti621_pci_tbl); diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c index 4b0b85d8faf5..e127eb25ab63 100644 --- a/drivers/ide/pci/sis5513.c +++ b/drivers/ide/pci/sis5513.c @@ -569,6 +569,11 @@ static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_devi { struct ide_port_info d = sis5513_chipset; u8 udma_rates[] = { 0x00, 0x00, 0x07, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f }; + int rc; + + rc = pci_enable_device(dev); + if (rc) + return rc; if (sis_find_family(dev) == 0) return -ENOTSUPP; diff --git a/drivers/ide/ppc/mpc8xx.c b/drivers/ide/ppc/mpc8xx.c index f0e638dcc3ab..236f9c38e519 100644 --- a/drivers/ide/ppc/mpc8xx.c +++ b/drivers/ide/ppc/mpc8xx.c @@ -303,6 +303,8 @@ static int __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port) pcmp->pcmc_per = 0x100000 >> (16 * _slot_); #endif /* CONFIG_IDE_8xx_PCCARD */ + hw->chipset = ide_generic; + return 0; } #endif /* CONFIG_IDE_8xx_PCCARD || CONFIG_IDE_8xx_DIRECT */ @@ -377,6 +379,8 @@ static int __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port) ((immap_t *) IMAP_ADDR)->im_siu_conf.sc_siel |= (0x80000000 >> ioport_dsc[data_port].irq); + hw->chipset = ide_generic; + return 0; } #endif /* CONFIG_IDE_8xx_DIRECT */ diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index 48aa019127bc..ba2d58727964 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -59,7 +59,6 @@ typedef struct pmac_ide_hwif { int irq; int kind; int aapl_bus_id; - unsigned cable_80 : 1; unsigned mediabay : 1; unsigned broken_dma : 1; unsigned broken_dma_warn : 1; @@ -918,10 +917,40 @@ pmac_ide_do_resume(ide_hwif_t *hwif) return 0; } +static u8 pmac_ide_cable_detect(ide_hwif_t *hwif) +{ + pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)ide_get_hwifdata(hwif); + struct device_node *np = pmif->node; + const char *cable = of_get_property(np, "cable-type", NULL); + + /* Get cable type from device-tree. */ + if (cable && !strncmp(cable, "80-", 3)) + return ATA_CBL_PATA80; + + /* + * G5's seem to have incorrect cable type in device-tree. + * Let's assume they have a 80 conductor cable, this seem + * to be always the case unless the user mucked around. + */ + if (of_device_is_compatible(np, "K2-UATA") || + of_device_is_compatible(np, "shasta-ata")) + return ATA_CBL_PATA80; + + return ATA_CBL_PATA40; +} + static const struct ide_port_ops pmac_ide_ata6_port_ops = { .set_pio_mode = pmac_ide_set_pio_mode, .set_dma_mode = pmac_ide_set_dma_mode, .selectproc = pmac_ide_kauai_selectproc, + .cable_detect = pmac_ide_cable_detect, +}; + +static const struct ide_port_ops pmac_ide_ata4_port_ops = { + .set_pio_mode = pmac_ide_set_pio_mode, + .set_dma_mode = pmac_ide_set_dma_mode, + .selectproc = pmac_ide_selectproc, + .cable_detect = pmac_ide_cable_detect, }; static const struct ide_port_ops pmac_ide_port_ops = { @@ -949,10 +978,7 @@ static const struct ide_port_info pmac_port_info = { /* * Setup, register & probe an IDE channel driven by this driver, this is - * called by one of the 2 probe functions (macio or PCI). Note that a channel - * that ends up beeing free of any device is not kept around by this driver - * (it is kept in 2.4). This introduce an interface numbering change on some - * rare machines unfortunately, but it's better this way. + * called by one of the 2 probe functions (macio or PCI). */ static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw) @@ -962,7 +988,6 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw) u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; struct ide_port_info d = pmac_port_info; - pmif->cable_80 = 0; pmif->broken_dma = pmif->broken_dma_warn = 0; if (of_device_is_compatible(np, "shasta-ata")) { pmif->kind = controller_sh_ata6; @@ -979,6 +1004,7 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw) } else if (of_device_is_compatible(np, "keylargo-ata")) { if (strcmp(np->name, "ata-4") == 0) { pmif->kind = controller_kl_ata4; + d.port_ops = &pmac_ide_ata4_port_ops; d.udma_mask = ATA_UDMA4; } else pmif->kind = controller_kl_ata3; @@ -992,22 +1018,6 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw) bidp = of_get_property(np, "AAPL,bus-id", NULL); pmif->aapl_bus_id = bidp ? *bidp : 0; - /* Get cable type from device-tree */ - if (pmif->kind == controller_kl_ata4 || pmif->kind == controller_un_ata6 - || pmif->kind == controller_k2_ata6 - || pmif->kind == controller_sh_ata6) { - const char* cable = of_get_property(np, "cable-type", NULL); - if (cable && !strncmp(cable, "80-", 3)) - pmif->cable_80 = 1; - } - /* G5's seem to have incorrect cable type in device-tree. Let's assume - * they have a 80 conductor cable, this seem to be always the case unless - * the user mucked around - */ - if (of_device_is_compatible(np, "K2-UATA") || - of_device_is_compatible(np, "shasta-ata")) - pmif->cable_80 = 1; - /* On Kauai-type controllers, we make sure the FCR is correct */ if (pmif->kauai_fcr) writel(KAUAI_FCR_UATA_MAGIC | @@ -1053,7 +1063,6 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw) hwif->hwif_data = pmif; ide_init_port_hw(hwif, hw); - hwif->cbl = pmif->cable_80 ? ATA_CBL_PATA80 : ATA_CBL_PATA40; printk(KERN_INFO "ide%d: Found Apple %s controller, bus ID %d%s, irq %d\n", hwif->index, model_name[pmif->kind], pmif->aapl_bus_id, @@ -1070,11 +1079,6 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw) } } -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - if (pmif->cable_80 == 0) - d.udma_mask &= ATA_UDMA2; -#endif - idx[0] = hwif->index; ide_device_add(idx, &d); diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c index fe78f7d25099..a1768dbb0720 100644 --- a/drivers/infiniband/core/umem.c +++ b/drivers/infiniband/core/umem.c @@ -150,7 +150,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr, ret = 0; while (npages) { ret = get_user_pages(current, current->mm, cur_base, - min_t(int, npages, + min_t(unsigned long, npages, PAGE_SIZE / sizeof (struct page *)), 1, !umem->writable, page_list, vma_list); diff --git a/drivers/infiniband/hw/amso1100/c2_rnic.c b/drivers/infiniband/hw/amso1100/c2_rnic.c index 9a054c6941a4..b1441aeb60c2 100644 --- a/drivers/infiniband/hw/amso1100/c2_rnic.c +++ b/drivers/infiniband/hw/amso1100/c2_rnic.c @@ -455,8 +455,7 @@ int __devinit c2_rnic_init(struct c2_dev *c2dev) IB_DEVICE_CURR_QP_STATE_MOD | IB_DEVICE_SYS_IMAGE_GUID | IB_DEVICE_ZERO_STAG | - IB_DEVICE_MEM_WINDOW | - IB_DEVICE_SEND_W_INV); + IB_DEVICE_MEM_WINDOW); /* Allocate the qptr_array */ c2dev->qptr_array = vmalloc(C2_MAX_CQS * sizeof(void *)); diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c index bbe0436f4f75..f093b0033daf 100644 --- a/drivers/infiniband/hw/ehca/ehca_reqs.c +++ b/drivers/infiniband/hw/ehca/ehca_reqs.c @@ -421,8 +421,10 @@ int ehca_post_send(struct ib_qp *qp, int ret = 0; unsigned long flags; - if (unlikely(my_qp->state != IB_QPS_RTS)) { - ehca_err(qp->device, "QP not in RTS state qpn=%x", qp->qp_num); + /* Reject WR if QP is in RESET, INIT or RTR state */ + if (unlikely(my_qp->state < IB_QPS_RTS)) { + ehca_err(qp->device, "Invalid QP state qp_state=%d qpn=%x", + my_qp->state, qp->qp_num); return -EINVAL; } diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h index 59a8b254b97f..0bd8bcb184a1 100644 --- a/drivers/infiniband/hw/ipath/ipath_kernel.h +++ b/drivers/infiniband/hw/ipath/ipath_kernel.h @@ -232,6 +232,11 @@ struct ipath_sdma_desc { #define IPATH_SDMA_TXREQ_S_ABORTED 2 #define IPATH_SDMA_TXREQ_S_SHUTDOWN 3 +#define IPATH_SDMA_STATUS_SCORE_BOARD_DRAIN_IN_PROG (1ull << 63) +#define IPATH_SDMA_STATUS_ABORT_IN_PROG (1ull << 62) +#define IPATH_SDMA_STATUS_INTERNAL_SDMA_ENABLE (1ull << 61) +#define IPATH_SDMA_STATUS_SCB_EMPTY (1ull << 30) + /* max dwords in small buffer packet */ #define IPATH_SMALLBUF_DWORDS (dd->ipath_piosize2k >> 2) diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c index 1ff46ae7dd99..5f9315d77a43 100644 --- a/drivers/infiniband/hw/ipath/ipath_mad.c +++ b/drivers/infiniband/hw/ipath/ipath_mad.c @@ -1492,6 +1492,10 @@ static int process_subn(struct ib_device *ibdev, int mad_flags, goto bail; } + case IB_MGMT_METHOD_TRAP: + case IB_MGMT_METHOD_REPORT: + case IB_MGMT_METHOD_REPORT_RESP: + case IB_MGMT_METHOD_TRAP_REPRESS: case IB_MGMT_METHOD_GET_RESP: /* * The ib_mad module will call us to process responses diff --git a/drivers/infiniband/hw/ipath/ipath_sdma.c b/drivers/infiniband/hw/ipath/ipath_sdma.c index 0a8c1b8091a2..eaba03273e4f 100644 --- a/drivers/infiniband/hw/ipath/ipath_sdma.c +++ b/drivers/infiniband/hw/ipath/ipath_sdma.c @@ -263,14 +263,10 @@ static void sdma_abort_task(unsigned long opaque) hwstatus = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmastatus); - if (/* ScoreBoardDrainInProg */ - test_bit(63, &hwstatus) || - /* AbortInProg */ - test_bit(62, &hwstatus) || - /* InternalSDmaEnable */ - test_bit(61, &hwstatus) || - /* ScbEmpty */ - !test_bit(30, &hwstatus)) { + if ((hwstatus & (IPATH_SDMA_STATUS_SCORE_BOARD_DRAIN_IN_PROG | + IPATH_SDMA_STATUS_ABORT_IN_PROG | + IPATH_SDMA_STATUS_INTERNAL_SDMA_ENABLE)) || + !(hwstatus & IPATH_SDMA_STATUS_SCB_EMPTY)) { if (dd->ipath_sdma_reset_wait > 0) { /* not done shutting down sdma */ --dd->ipath_sdma_reset_wait; diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c index e0ec540042bf..7779165b2c2c 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.c +++ b/drivers/infiniband/hw/ipath/ipath_verbs.c @@ -1494,7 +1494,8 @@ static int ipath_query_device(struct ib_device *ibdev, props->device_cap_flags = IB_DEVICE_BAD_PKEY_CNTR | IB_DEVICE_BAD_QKEY_CNTR | IB_DEVICE_SHUTDOWN_PORT | - IB_DEVICE_SYS_IMAGE_GUID; + IB_DEVICE_SYS_IMAGE_GUID | IB_DEVICE_RC_RNR_NAK_GEN | + IB_DEVICE_PORT_ACTIVE_EVENT | IB_DEVICE_SRQ_RESIZE; props->page_size_cap = PAGE_SIZE; props->vendor_id = dev->dd->ipath_vendorid; props->vendor_part_id = dev->dd->ipath_deviceid; diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 4a95adc4cc78..af58a6f1e898 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -807,6 +807,8 @@ static int atkbd_activate(struct atkbd *atkbd) static void atkbd_cleanup(struct serio *serio) { struct atkbd *atkbd = serio_get_drvdata(serio); + + atkbd_disable(atkbd); ps2_command(&atkbd->ps2dev, NULL, ATKBD_CMD_RESET_BAT); } diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index 3dea0c5077a9..45767e73f071 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c @@ -136,6 +136,9 @@ static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad) set_bit(code, input_dev->keybit); } + for (i = 0; i < pdata->direct_key_num; i++) + set_bit(pdata->direct_key_map[i], input_dev->keybit); + keypad->rotary_up_key[0] = pdata->rotary0_up_key; keypad->rotary_up_key[1] = pdata->rotary1_up_key; keypad->rotary_down_key[0] = pdata->rotary0_down_key; @@ -143,17 +146,21 @@ static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad) keypad->rotary_rel_code[0] = pdata->rotary0_rel_code; keypad->rotary_rel_code[1] = pdata->rotary1_rel_code; - if (pdata->rotary0_up_key && pdata->rotary0_down_key) { - set_bit(pdata->rotary0_up_key, input_dev->keybit); - set_bit(pdata->rotary0_down_key, input_dev->keybit); - } else - set_bit(pdata->rotary0_rel_code, input_dev->relbit); - - if (pdata->rotary1_up_key && pdata->rotary1_down_key) { - set_bit(pdata->rotary1_up_key, input_dev->keybit); - set_bit(pdata->rotary1_down_key, input_dev->keybit); - } else - set_bit(pdata->rotary1_rel_code, input_dev->relbit); + if (pdata->enable_rotary0) { + if (pdata->rotary0_up_key && pdata->rotary0_down_key) { + set_bit(pdata->rotary0_up_key, input_dev->keybit); + set_bit(pdata->rotary0_down_key, input_dev->keybit); + } else + set_bit(pdata->rotary0_rel_code, input_dev->relbit); + } + + if (pdata->enable_rotary1) { + if (pdata->rotary1_up_key && pdata->rotary1_down_key) { + set_bit(pdata->rotary1_up_key, input_dev->keybit); + set_bit(pdata->rotary1_down_key, input_dev->keybit); + } else + set_bit(pdata->rotary1_rel_code, input_dev->relbit); + } } static inline unsigned int lookup_matrix_keycode( @@ -484,8 +491,13 @@ static int __devinit pxa27x_keypad_probe(struct platform_device *pdev) keypad->input_dev = input_dev; input_set_drvdata(input_dev, keypad); - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | - BIT_MASK(EV_REL); + input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); + if ((keypad->pdata->enable_rotary0 && + keypad->pdata->rotary0_rel_code) || + (keypad->pdata->enable_rotary1 && + keypad->pdata->rotary1_rel_code)) { + input_dev->evbit[0] |= BIT_MASK(EV_REL); + } pxa27x_keypad_build_keycode(keypad); platform_set_drvdata(pdev, keypad); diff --git a/drivers/input/misc/apanel.c b/drivers/input/misc/apanel.c index 9531d8c7444f..d82f7f727f7a 100644 --- a/drivers/input/misc/apanel.c +++ b/drivers/input/misc/apanel.c @@ -20,7 +20,6 @@ #include <linux/module.h> #include <linux/ioport.h> #include <linux/io.h> -#include <linux/module.h> #include <linux/input-polldev.h> #include <linux/i2c.h> #include <linux/workqueue.h> diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 5ece9f56babc..9aafa96cb746 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -331,6 +331,13 @@ static struct dmi_system_id __initdata i8042_dmi_dritek_table[] = { }, }, { + .ident = "Acer TravelMate 660", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 660"), + }, + }, + { .ident = "Acer TravelMate 2490", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 65a74cfc187b..592ff55b62d0 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -885,6 +885,20 @@ static long i8042_panic_blink(long count) #undef DELAY +#ifdef CONFIG_X86 +static void i8042_dritek_enable(void) +{ + char param = 0x90; + int error; + + error = i8042_command(¶m, 0x1059); + if (error) + printk(KERN_WARNING + "Failed to enable DRITEK extension: %d\n", + error); +} +#endif + #ifdef CONFIG_PM /* * Here we try to restore the original BIOS settings. We only want to @@ -942,6 +956,12 @@ static int i8042_resume(struct platform_device *dev) return -EIO; } + +#ifdef CONFIG_X86 + if (i8042_dritek) + i8042_dritek_enable(); +#endif + if (i8042_mux_present) { if (i8042_set_mux_mode(1, NULL) || i8042_enable_mux_ports()) printk(KERN_WARNING @@ -1160,6 +1180,11 @@ static int __devinit i8042_probe(struct platform_device *dev) if (error) return error; +#ifdef CONFIG_X86 + if (i8042_dritek) + i8042_dritek_enable(); +#endif + if (!i8042_noaux) { error = i8042_setup_aux(); if (error && error != -ENODEV && error != -EBUSY) @@ -1171,14 +1196,6 @@ static int __devinit i8042_probe(struct platform_device *dev) if (error) goto out_fail; } -#ifdef CONFIG_X86 - if (i8042_dritek) { - char param = 0x90; - error = i8042_command(¶m, 0x1059); - if (error) - goto out_fail; - } -#endif /* * Ok, everything is ready, let's register all serio ports */ diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c index c5a8661a1baa..1e748e46d12e 100644 --- a/drivers/input/tablet/gtco.c +++ b/drivers/input/tablet/gtco.c @@ -830,7 +830,7 @@ static int gtco_probe(struct usb_interface *usbinterface, struct gtco *gtco; struct input_dev *input_dev; struct hid_descriptor *hid_desc; - char *report = NULL; + char *report; int result = 0, retry; int error; struct usb_endpoint_descriptor *endpoint; @@ -916,12 +916,16 @@ static int gtco_probe(struct usb_interface *usbinterface, le16_to_cpu(hid_desc->wDescriptorLength), 5000); /* 5 secs */ - if (result == le16_to_cpu(hid_desc->wDescriptorLength)) + dbg("usb_control_msg result: %d", result); + if (result == le16_to_cpu(hid_desc->wDescriptorLength)) { + parse_hid_report_descriptor(gtco, report, result); break; + } } + kfree(report); + /* If we didn't get the report, fail */ - dbg("usb_control_msg result: :%d", result); if (result != le16_to_cpu(hid_desc->wDescriptorLength)) { err("Failed to get HID Report Descriptor of size: %d", hid_desc->wDescriptorLength); @@ -929,12 +933,6 @@ static int gtco_probe(struct usb_interface *usbinterface, goto err_free_urb; } - /* Now we parse the report */ - parse_hid_report_descriptor(gtco, report, result); - - /* Now we delete it */ - kfree(report); - /* Create a device file node */ usb_make_path(gtco->usbdev, gtco->usbpath, sizeof(gtco->usbpath)); strlcat(gtco->usbpath, "/input0", sizeof(gtco->usbpath)); @@ -988,7 +986,6 @@ static int gtco_probe(struct usb_interface *usbinterface, usb_buffer_free(gtco->usbdev, REPORT_MAX_SIZE, gtco->buffer, gtco->buf_dma); err_free_devs: - kfree(report); input_free_device(input_dev); kfree(gtco); return error; diff --git a/drivers/input/touchscreen/wm9713.c b/drivers/input/touchscreen/wm9713.c index 01278bd7e65c..838458792ea0 100644 --- a/drivers/input/touchscreen/wm9713.c +++ b/drivers/input/touchscreen/wm9713.c @@ -85,6 +85,15 @@ module_param(delay, int, 0); MODULE_PARM_DESC(delay, "Set adc sample delay."); /* + * Set five_wire = 1 to use a 5 wire touchscreen. + * + * NOTE: Five wire mode does not allow for readback of pressure. + */ +static int five_wire; +module_param(five_wire, int, 0); +MODULE_PARM_DESC(five_wire, "Set to '1' to use 5-wire touchscreen."); + +/* * Set adc mask function. * * Sources of glitch noise, such as signals driving an LCD display, may feed @@ -162,6 +171,19 @@ static void wm9713_phy_init(struct wm97xx *wm) 64000 / rpu); } + /* Five wire panel? */ + if (five_wire) { + dig3 |= WM9713_45W; + dev_info(wm->dev, "setting 5-wire touchscreen mode."); + + if (pil) { + dev_warn(wm->dev, + "Pressure measurement not supported in 5 " + "wire mode, disabling\n"); + pil = 0; + } + } + /* touchpanel pressure */ if (pil == 2) { dig3 |= WM9712_PIL; diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c index e9c7ea46b6e3..cdc24ad314e0 100644 --- a/drivers/input/touchscreen/wm97xx-core.c +++ b/drivers/input/touchscreen/wm97xx-core.c @@ -608,6 +608,17 @@ static int wm97xx_probe(struct device *dev) goto alloc_err; } + /* set up physical characteristics */ + wm->codec->phy_init(wm); + + /* load gpio cache */ + wm->gpio[0] = wm97xx_reg_read(wm, AC97_GPIO_CFG); + wm->gpio[1] = wm97xx_reg_read(wm, AC97_GPIO_POLARITY); + wm->gpio[2] = wm97xx_reg_read(wm, AC97_GPIO_STICKY); + wm->gpio[3] = wm97xx_reg_read(wm, AC97_GPIO_WAKEUP); + wm->gpio[4] = wm97xx_reg_read(wm, AC97_GPIO_STATUS); + wm->gpio[5] = wm97xx_reg_read(wm, AC97_MISC_AFE); + wm->input_dev = input_allocate_device(); if (wm->input_dev == NULL) { ret = -ENOMEM; @@ -616,6 +627,7 @@ static int wm97xx_probe(struct device *dev) /* set up touch configuration */ wm->input_dev->name = "wm97xx touchscreen"; + wm->input_dev->phys = "wm97xx"; wm->input_dev->open = wm97xx_ts_input_open; wm->input_dev->close = wm97xx_ts_input_close; set_bit(EV_ABS, wm->input_dev->evbit); @@ -634,17 +646,6 @@ static int wm97xx_probe(struct device *dev) if (ret < 0) goto dev_alloc_err; - /* set up physical characteristics */ - wm->codec->phy_init(wm); - - /* load gpio cache */ - wm->gpio[0] = wm97xx_reg_read(wm, AC97_GPIO_CFG); - wm->gpio[1] = wm97xx_reg_read(wm, AC97_GPIO_POLARITY); - wm->gpio[2] = wm97xx_reg_read(wm, AC97_GPIO_STICKY); - wm->gpio[3] = wm97xx_reg_read(wm, AC97_GPIO_WAKEUP); - wm->gpio[4] = wm97xx_reg_read(wm, AC97_GPIO_STATUS); - wm->gpio[5] = wm97xx_reg_read(wm, AC97_MISC_AFE); - /* register our battery device */ wm->battery_dev = platform_device_alloc("wm97xx-battery", -1); if (!wm->battery_dev) { @@ -801,7 +802,7 @@ void wm97xx_unregister_mach_ops(struct wm97xx *wm) EXPORT_SYMBOL_GPL(wm97xx_unregister_mach_ops); static struct device_driver wm97xx_driver = { - .name = "ac97", + .name = "wm97xx-ts", .bus = &ac97_bus_type, .owner = THIS_MODULE, .probe = wm97xx_probe, diff --git a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c index 5fcbdccd7a53..16a874bb1561 100644 --- a/drivers/isdn/hardware/eicon/divasmain.c +++ b/drivers/isdn/hardware/eicon/divasmain.c @@ -806,7 +806,6 @@ static int DIVA_INIT_FUNCTION divas_init(void) if (!create_divas_proc()) { #ifdef MODULE - remove_divas_proc(); divas_unregister_chrdev(); divasfunc_exit(); #endif diff --git a/drivers/isdn/hardware/eicon/divasproc.c b/drivers/isdn/hardware/eicon/divasproc.c index fae895828a17..040827288ec9 100644 --- a/drivers/isdn/hardware/eicon/divasproc.c +++ b/drivers/isdn/hardware/eicon/divasproc.c @@ -125,8 +125,8 @@ static const struct file_operations divas_fops = { int create_divas_proc(void) { - proc_create(divas_proc_name, S_IFREG | S_IRUGO, proc_net_eicon, - &divas_fops); + divas_proc_entry = proc_create(divas_proc_name, S_IFREG | S_IRUGO, + proc_net_eicon, &divas_fops); if (!divas_proc_entry) return (0); diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c index 15906d005b05..484299b031f8 100644 --- a/drivers/isdn/hysdn/hysdn_procconf.c +++ b/drivers/isdn/hysdn/hysdn_procconf.c @@ -207,30 +207,17 @@ hysdn_conf_write(struct file *file, const char __user *buf, size_t count, loff_t /* read conf file -> output card info data */ /*******************************************/ static ssize_t -hysdn_conf_read(struct file *file, char __user *buf, size_t count, loff_t * off) +hysdn_conf_read(struct file *file, char __user *buf, size_t count, loff_t *off) { char *cp; - int i; - if (file->f_mode & FMODE_READ) { - if (!(cp = file->private_data)) - return (-EFAULT); /* should never happen */ - i = strlen(cp); /* get total string length */ - if (*off < i) { - /* still bytes to transfer */ - cp += *off; /* point to desired data offset */ - i -= *off; /* remaining length */ - if (i > count) - i = count; /* limit length to transfer */ - if (copy_to_user(buf, cp, i)) - return (-EFAULT); /* copy error */ - *off += i; /* adjust offset */ - } else - return (0); - } else - return (-EPERM); /* no permission to read */ - - return (i); + if (!(file->f_mode & FMODE_READ)) + return -EPERM; /* no permission to read */ + + if (!(cp = file->private_data)) + return -EFAULT; /* should never happen */ + + return simple_read_from_buffer(buf, count, off, cp, strlen(cp)); } /* hysdn_conf_read */ /******************/ diff --git a/drivers/isdn/sc/ioctl.c b/drivers/isdn/sc/ioctl.c index 7817d2244921..1081091bbfaf 100644 --- a/drivers/isdn/sc/ioctl.c +++ b/drivers/isdn/sc/ioctl.c @@ -226,6 +226,7 @@ int sc_ioctl(int card, scs_ioctl *data) */ if (copy_from_user(spid, data->dataptr, SCIOC_SPIDSIZE)) { kfree(rcvmsg); + kfree(spid); return -EFAULT; } diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c index 8080249957af..1a8de57289eb 100644 --- a/drivers/lguest/lguest_device.c +++ b/drivers/lguest/lguest_device.c @@ -20,14 +20,11 @@ /* The pointer to our (page) of device descriptions. */ static void *lguest_devices; -/* Unique numbering for lguest devices. */ -static unsigned int dev_index; - /* For Guests, device memory can be used as normal memory, so we cast away the * __iomem to quieten sparse. */ static inline void *lguest_map(unsigned long phys_addr, unsigned long pages) { - return (__force void *)ioremap(phys_addr, PAGE_SIZE*pages); + return (__force void *)ioremap_cache(phys_addr, PAGE_SIZE*pages); } static inline void lguest_unmap(void *addr) @@ -325,8 +322,10 @@ static struct device lguest_root = { * As Andrew Tridgell says, "Untested code is buggy code". * * It's worth reading this carefully: we start with a pointer to the new device - * descriptor in the "lguest_devices" page. */ -static void add_lguest_device(struct lguest_device_desc *d) + * descriptor in the "lguest_devices" page, and the offset into the device + * descriptor page so we can uniquely identify it if things go badly wrong. */ +static void add_lguest_device(struct lguest_device_desc *d, + unsigned int offset) { struct lguest_device *ldev; @@ -334,18 +333,14 @@ static void add_lguest_device(struct lguest_device_desc *d) * it. */ ldev = kzalloc(sizeof(*ldev), GFP_KERNEL); if (!ldev) { - printk(KERN_EMERG "Cannot allocate lguest dev %u\n", - dev_index++); + printk(KERN_EMERG "Cannot allocate lguest dev %u type %u\n", + offset, d->type); return; } /* This devices' parent is the lguest/ dir. */ ldev->vdev.dev.parent = &lguest_root; /* We have a unique device index thanks to the dev_index counter. */ - ldev->vdev.index = dev_index++; - /* The device type comes straight from the descriptor. There's also a - * device vendor field in the virtio_device struct, which we leave as - * 0. */ ldev->vdev.id.device = d->type; /* We have a simple set of routines for querying the device's * configuration information and setting its status. */ @@ -357,8 +352,8 @@ static void add_lguest_device(struct lguest_device_desc *d) * virtio_device and calls device_register(). This makes the bus * infrastructure look for a matching driver. */ if (register_virtio_device(&ldev->vdev) != 0) { - printk(KERN_ERR "Failed to register lguest device %u\n", - ldev->vdev.index); + printk(KERN_ERR "Failed to register lguest dev %u type %u\n", + offset, d->type); kfree(ldev); } } @@ -379,7 +374,7 @@ static void scan_devices(void) break; printk("Device at %i has size %u\n", i, desc_size(d)); - add_lguest_device(d); + add_lguest_device(d, i); } } diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c index 82add26cc665..c34bdf852e32 100644 --- a/drivers/macintosh/mediabay.c +++ b/drivers/macintosh/mediabay.c @@ -556,7 +556,8 @@ static void media_bay_step(int i) printk("mediabay %d, registering IDE...\n", i); pmu_suspend(); ide_port_scan(bay->cd_port); - bay->cd_index = bay->cd_port->index; + if (bay->cd_port->present) + bay->cd_index = bay->cd_port->index; pmu_resume(); } if (bay->cd_index == -1) { diff --git a/drivers/md/md.c b/drivers/md/md.c index 51c19f86ff99..7cf512a34ccf 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -276,6 +276,7 @@ static mddev_t * mddev_find(dev_t unit) atomic_set(&new->active, 1); spin_lock_init(&new->write_lock); init_waitqueue_head(&new->sb_wait); + init_waitqueue_head(&new->recovery_wait); new->reshape_position = MaxSector; new->resync_max = MaxSector; new->level = LEVEL_NONE; @@ -5665,7 +5666,6 @@ void md_do_sync(mddev_t *mddev) window/2,(unsigned long long) max_sectors/2); atomic_set(&mddev->recovery_active, 0); - init_waitqueue_head(&mddev->recovery_wait); last_check = 0; if (j>2) { diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 425958a76b84..c37e256b1176 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -2002,6 +2002,7 @@ static int __handle_issuing_new_read_requests5(struct stripe_head *sh, * have quiesced. */ if ((s->uptodate == disks - 1) && + (s->failed && disk_idx == s->failed_num) && !test_bit(STRIPE_OP_CHECK, &sh->ops.pending)) { set_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending); set_bit(R5_Wantcompute, &dev->flags); @@ -2087,7 +2088,9 @@ static void handle_issuing_new_read_requests6(struct stripe_head *sh, /* we would like to get this block, possibly * by computing it, but we might not be able to */ - if (s->uptodate == disks-1) { + if ((s->uptodate == disks - 1) && + (s->failed && (i == r6s->failed_num[0] || + i == r6s->failed_num[1]))) { pr_debug("Computing stripe %llu block %d\n", (unsigned long long)sh->sector, i); compute_block_1(sh, i, 0); @@ -2645,6 +2648,7 @@ static void handle_stripe5(struct stripe_head *sh) struct r5dev *dev; unsigned long pending = 0; mdk_rdev_t *blocked_rdev = NULL; + int prexor; memset(&s, 0, sizeof(s)); pr_debug("handling stripe %llu, state=%#lx cnt=%d, pd_idx=%d " @@ -2774,9 +2778,11 @@ static void handle_stripe5(struct stripe_head *sh) /* leave prexor set until postxor is done, allows us to distinguish * a rmw from a rcw during biodrain */ + prexor = 0; if (test_bit(STRIPE_OP_PREXOR, &sh->ops.complete) && test_bit(STRIPE_OP_POSTXOR, &sh->ops.complete)) { + prexor = 1; clear_bit(STRIPE_OP_PREXOR, &sh->ops.complete); clear_bit(STRIPE_OP_PREXOR, &sh->ops.ack); clear_bit(STRIPE_OP_PREXOR, &sh->ops.pending); @@ -2810,6 +2816,8 @@ static void handle_stripe5(struct stripe_head *sh) if (!test_and_set_bit( STRIPE_OP_IO, &sh->ops.pending)) sh->ops.count++; + if (prexor) + continue; if (!test_bit(R5_Insync, &dev->flags) || (i == sh->pd_idx && s.failed == 0)) set_bit(STRIPE_INSYNC, &sh->state); diff --git a/drivers/media/Makefile b/drivers/media/Makefile index cc11c4c0e7e7..09a829d8a7e7 100644 --- a/drivers/media/Makefile +++ b/drivers/media/Makefile @@ -2,12 +2,7 @@ # Makefile for the kernel multimedia device drivers. # -obj-y := common/ - -obj-$(CONFIG_VIDEO_MEDIA) += common/ - -# Since hybrid devices are here, should be compiled if DVB and/or V4L -obj-$(CONFIG_VIDEO_MEDIA) += video/ +obj-y += common/ video/ obj-$(CONFIG_VIDEO_DEV) += radio/ obj-$(CONFIG_DVB_CORE) += dvb/ diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig index d6206540476b..85482960d012 100644 --- a/drivers/media/common/tuners/Kconfig +++ b/drivers/media/common/tuners/Kconfig @@ -21,6 +21,7 @@ config MEDIA_TUNER tristate default VIDEO_MEDIA && I2C depends on VIDEO_MEDIA && I2C + select FW_LOADER if !MEDIA_TUNER_CUSTOMIZE && HOTPLUG select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE && HOTPLUG select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE && HOTPLUG select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMIZE diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c index 5d05b5390f66..0dc2bef9f6a3 100644 --- a/drivers/media/common/tuners/mxl5005s.c +++ b/drivers/media/common/tuners/mxl5005s.c @@ -101,7 +101,7 @@ enum { MXL_QAM, MXL_ANALOG_CABLE, MXL_ANALOG_OTA -} tuner_modu_type; +}; /* MXL5005 Tuner Register Struct */ struct TunerReg { @@ -194,7 +194,7 @@ enum { RFSYN_DIVM, /* 88 */ DN_BYPASS_AGC_I2C /* 89 */ #endif -} MXL5005_ControlName; +}; /* * The following context is source code provided by MaxLinear. diff --git a/drivers/media/common/tuners/tda18271-common.c b/drivers/media/common/tuners/tda18271-common.c index 42b5f5d4bfe6..f1894fec32b9 100644 --- a/drivers/media/common/tuners/tda18271-common.c +++ b/drivers/media/common/tuners/tda18271-common.c @@ -648,11 +648,11 @@ int tda18271_calc_rf_cal(struct dvb_frontend *fe, u32 *freq) unsigned char *regs = priv->tda18271_regs; u8 val; - tda18271_lookup_map(fe, RF_CAL, freq, &val); + int ret = tda18271_lookup_map(fe, RF_CAL, freq, &val); regs[R_EB14] = val; - return 0; + return ret; } /* diff --git a/drivers/media/common/tuners/tda827x.c b/drivers/media/common/tuners/tda827x.c index d30d2c9094d9..8555d9cf9051 100644 --- a/drivers/media/common/tuners/tda827x.c +++ b/drivers/media/common/tuners/tda827x.c @@ -418,13 +418,13 @@ static void tda827xa_lna_gain(struct dvb_frontend *fe, int high, unsigned char buf[] = {0x22, 0x01}; int arg; int gp_func; - struct i2c_msg msg = { .addr = priv->cfg->switch_addr, .flags = 0, - .buf = buf, .len = sizeof(buf) }; + struct i2c_msg msg = { .flags = 0, .buf = buf, .len = sizeof(buf) }; if (NULL == priv->cfg) { dprintk("tda827x_config not defined, cannot set LNA gain!\n"); return; } + msg.addr = priv->cfg->switch_addr; if (priv->cfg->config) { if (high) dprintk("setting LNA to high gain\n"); diff --git a/drivers/media/common/tuners/tea5761.c b/drivers/media/common/tuners/tea5761.c index b93cdef9ac73..b23dadeecd05 100644 --- a/drivers/media/common/tuners/tea5761.c +++ b/drivers/media/common/tuners/tea5761.c @@ -295,7 +295,7 @@ struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe, { struct tea5761_priv *priv = NULL; - if (tea5761_autodetection(i2c_adap, i2c_addr) == EINVAL) + if (tea5761_autodetection(i2c_adap, i2c_addr) != 0) return NULL; priv = kzalloc(sizeof(struct tea5761_priv), GFP_KERNEL); diff --git a/drivers/media/common/tuners/tuner-i2c.h b/drivers/media/common/tuners/tuner-i2c.h index 3ad6c8e0b04c..cb1c7141f0c6 100644 --- a/drivers/media/common/tuners/tuner-i2c.h +++ b/drivers/media/common/tuners/tuner-i2c.h @@ -170,4 +170,12 @@ __fail: \ __ret; \ }) +#define hybrid_tuner_report_instance_count(state) \ +({ \ + int __ret = 0; \ + if (state) \ + __ret = state->i2c_props.count; \ + __ret; \ +}) + #endif /* __TUNER_I2C_H__ */ diff --git a/drivers/media/common/tuners/tuner-simple.c b/drivers/media/common/tuners/tuner-simple.c index be8d903171b7..266c255cf0d8 100644 --- a/drivers/media/common/tuners/tuner-simple.c +++ b/drivers/media/common/tuners/tuner-simple.c @@ -1018,8 +1018,10 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, fe->ops.i2c_gate_ctrl(fe, 1); if (1 != i2c_transfer(i2c_adap, &msg, 1)) - tuner_warn("unable to probe %s, proceeding anyway.", - tuners[type].name); + printk(KERN_WARNING "tuner-simple %d-%04x: " + "unable to probe %s, proceeding anyway.", + i2c_adapter_id(i2c_adap), i2c_addr, + tuners[type].name); if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c index 9e9003cffc7f..0cbde17bfbb7 100644 --- a/drivers/media/common/tuners/tuner-xc2028.c +++ b/drivers/media/common/tuners/tuner-xc2028.c @@ -46,7 +46,7 @@ module_param_string(firmware_name, firmware_name, sizeof(firmware_name), 0); MODULE_PARM_DESC(firmware_name, "Firmware file name. Allows overriding the " "default firmware name\n"); -static LIST_HEAD(xc2028_list); +static LIST_HEAD(hybrid_tuner_instance_list); static DEFINE_MUTEX(xc2028_list_mutex); /* struct for storing firmware table */ @@ -68,12 +68,11 @@ struct firmware_properties { }; struct xc2028_data { - struct list_head xc2028_list; + struct list_head hybrid_tuner_instance_list; struct tuner_i2c_props i2c_props; int (*tuner_callback) (void *dev, int command, int arg); void *video_dev; - int count; __u32 frequency; struct firmware_description *firm; @@ -1072,20 +1071,19 @@ static int xc2028_dvb_release(struct dvb_frontend *fe) mutex_lock(&xc2028_list_mutex); - priv->count--; - - if (!priv->count) { - list_del(&priv->xc2028_list); - + /* only perform final cleanup if this is the last instance */ + if (hybrid_tuner_report_instance_count(priv) == 1) { kfree(priv->ctrl.fname); - free_firmware(priv); - kfree(priv); - fe->tuner_priv = NULL; } + if (priv) + hybrid_tuner_release_state(priv); + mutex_unlock(&xc2028_list_mutex); + fe->tuner_priv = NULL; + return 0; } @@ -1150,7 +1148,7 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe, struct xc2028_config *cfg) { struct xc2028_data *priv; - void *video_dev; + int instance; if (debug) printk(KERN_DEBUG "xc2028: Xcv2028/3028 init called!\n"); @@ -1163,48 +1161,40 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe, return NULL; } - video_dev = cfg->i2c_adap->algo_data; - - if (debug) - printk(KERN_DEBUG "xc2028: video_dev =%p\n", video_dev); - mutex_lock(&xc2028_list_mutex); - list_for_each_entry(priv, &xc2028_list, xc2028_list) { - if (&priv->i2c_props.adap->dev == &cfg->i2c_adap->dev) { - video_dev = NULL; - if (debug) - printk(KERN_DEBUG "xc2028: reusing device\n"); - - break; - } - } - - if (video_dev) { - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (priv == NULL) { - mutex_unlock(&xc2028_list_mutex); - return NULL; - } - - priv->i2c_props.addr = cfg->i2c_addr; - priv->i2c_props.adap = cfg->i2c_adap; - priv->i2c_props.name = "xc2028"; - - priv->video_dev = video_dev; + instance = hybrid_tuner_request_state(struct xc2028_data, priv, + hybrid_tuner_instance_list, + cfg->i2c_adap, cfg->i2c_addr, + "xc2028"); + switch (instance) { + case 0: + /* memory allocation failure */ + goto fail; + break; + case 1: + /* new tuner instance */ priv->tuner_callback = cfg->callback; priv->ctrl.max_len = 13; mutex_init(&priv->lock); - list_add_tail(&priv->xc2028_list, &xc2028_list); - } - - fe->tuner_priv = priv; - priv->count++; + /* analog side (tuner-core) uses i2c_adap->algo_data. + * digital side is not guaranteed to have algo_data defined. + * + * digital side will always have fe->dvb defined. + * analog side (tuner-core) doesn't (yet) define fe->dvb. + */ + priv->video_dev = ((fe->dvb) && (fe->dvb->priv)) ? + fe->dvb->priv : cfg->i2c_adap->algo_data; - if (debug) - printk(KERN_DEBUG "xc2028: usage count is %i\n", priv->count); + fe->tuner_priv = priv; + break; + case 2: + /* existing tuner instance */ + fe->tuner_priv = priv; + break; + } memcpy(&fe->ops.tuner_ops, &xc2028_dvb_tuner_ops, sizeof(xc2028_dvb_tuner_ops)); @@ -1217,6 +1207,11 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe, mutex_unlock(&xc2028_list_mutex); return fe; +fail: + mutex_unlock(&xc2028_list_mutex); + + xc2028_dvb_release(fe); + return NULL; } EXPORT_SYMBOL(xc2028_attach); diff --git a/drivers/media/dvb/b2c2/flexcop-usb.c b/drivers/media/dvb/b2c2/flexcop-usb.c index 449fb5c3d0b1..ae0d76a5d51d 100644 --- a/drivers/media/dvb/b2c2/flexcop-usb.c +++ b/drivers/media/dvb/b2c2/flexcop-usb.c @@ -379,7 +379,7 @@ static void flexcop_usb_transfer_exit(struct flexcop_usb *fc_usb) static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb) { - u16 frame_size = fc_usb->uintf->cur_altsetting->endpoint[0].desc.wMaxPacketSize; + u16 frame_size = le16_to_cpu(fc_usb->uintf->cur_altsetting->endpoint[0].desc.wMaxPacketSize); int bufsize = B2C2_USB_NUM_ISO_URB * B2C2_USB_FRAMES_PER_ISO * frame_size,i,j,ret; int buffer_offset = 0; diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index f5010e8671b8..a824f3719f81 100644 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/drivers/media/dvb/cinergyT2/cinergyT2.c @@ -82,22 +82,22 @@ enum cinergyt2_ep1_cmd { struct dvbt_set_parameters_msg { uint8_t cmd; - uint32_t freq; + __le32 freq; uint8_t bandwidth; - uint16_t tps; + __le16 tps; uint8_t flags; } __attribute__((packed)); struct dvbt_get_status_msg { - uint32_t freq; + __le32 freq; uint8_t bandwidth; - uint16_t tps; + __le16 tps; uint8_t flags; - uint16_t gain; + __le16 gain; uint8_t snr; - uint32_t viterbi_error_rate; - uint32_t rs_error_rate; - uint32_t uncorrected_block_count; + __le32 viterbi_error_rate; + __le32 rs_error_rate; + __le32 uncorrected_block_count; uint8_t lock_bits; uint8_t prev_lock_bits; } __attribute__((packed)); @@ -136,6 +136,7 @@ struct cinergyt2 { wait_queue_head_t poll_wq; int pending_fe_events; int disconnect_pending; + unsigned int uncorrected_block_count; atomic_t inuse; void *streambuf; @@ -147,7 +148,7 @@ struct cinergyt2 { char phys[64]; struct delayed_work rc_query_work; int rc_input_event; - u32 rc_last_code; + __le32 rc_last_code; unsigned long last_event_jiffies; #endif }; @@ -160,7 +161,7 @@ enum { struct cinergyt2_rc_event { char type; - uint32_t value; + __le32 value; } __attribute__((packed)); static const uint32_t rc_keys[] = { @@ -619,8 +620,11 @@ static int cinergyt2_ioctl (struct inode *inode, struct file *file, { uint32_t unc_count; - unc_count = stat->uncorrected_block_count; - stat->uncorrected_block_count = 0; + if (mutex_lock_interruptible(&cinergyt2->sem)) + return -ERESTARTSYS; + unc_count = cinergyt2->uncorrected_block_count; + cinergyt2->uncorrected_block_count = 0; + mutex_unlock(&cinergyt2->sem); /* UNC are already converted to host byte order... */ return put_user(unc_count,(__u32 __user *) arg); @@ -769,7 +773,7 @@ static void cinergyt2_query_rc (struct work_struct *work) input_sync(cinergyt2->rc_input_dev); cinergyt2->rc_input_event = KEY_MAX; } - cinergyt2->rc_last_code = ~0; + cinergyt2->rc_last_code = cpu_to_le32(~0); } goto out; } @@ -780,7 +784,7 @@ static void cinergyt2_query_rc (struct work_struct *work) n, le32_to_cpu(rc_events[n].value), rc_events[n].type); if (rc_events[n].type == CINERGYT2_RC_EVENT_TYPE_NEC && - rc_events[n].value == ~0) { + rc_events[n].value == cpu_to_le32(~0)) { /* keyrepeat bit -> just repeat last rc_input_event */ } else { cinergyt2->rc_input_event = KEY_MAX; @@ -795,7 +799,7 @@ static void cinergyt2_query_rc (struct work_struct *work) if (cinergyt2->rc_input_event != KEY_MAX) { if (rc_events[n].value == cinergyt2->rc_last_code && - cinergyt2->rc_last_code != ~0) { + cinergyt2->rc_last_code != cpu_to_le32(~0)) { /* emit a key-up so the double event is recognized */ dprintk(1, "rc_input_event=%d UP\n", cinergyt2->rc_input_event); input_report_key(cinergyt2->rc_input_dev, @@ -829,7 +833,7 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) usb_make_path(cinergyt2->udev, cinergyt2->phys, sizeof(cinergyt2->phys)); strlcat(cinergyt2->phys, "/input0", sizeof(cinergyt2->phys)); cinergyt2->rc_input_event = KEY_MAX; - cinergyt2->rc_last_code = ~0; + cinergyt2->rc_last_code = cpu_to_le32(~0); INIT_DELAYED_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc); input_dev->name = DRIVER_NAME " remote control"; @@ -840,8 +844,8 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) input_dev->keycodesize = 0; input_dev->keycodemax = 0; input_dev->id.bustype = BUS_USB; - input_dev->id.vendor = cinergyt2->udev->descriptor.idVendor; - input_dev->id.product = cinergyt2->udev->descriptor.idProduct; + input_dev->id.vendor = le16_to_cpu(cinergyt2->udev->descriptor.idVendor); + input_dev->id.product = le16_to_cpu(cinergyt2->udev->descriptor.idProduct); input_dev->id.version = 1; input_dev->dev.parent = &cinergyt2->udev->dev; @@ -889,18 +893,16 @@ static void cinergyt2_query (struct work_struct *work) char cmd [] = { CINERGYT2_EP1_GET_TUNER_STATUS }; struct dvbt_get_status_msg *s = &cinergyt2->status; uint8_t lock_bits; - uint32_t unc; if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) return; - unc = s->uncorrected_block_count; lock_bits = s->lock_bits; cinergyt2_command(cinergyt2, cmd, sizeof(cmd), (char *) s, sizeof(*s)); - unc += le32_to_cpu(s->uncorrected_block_count); - s->uncorrected_block_count = unc; + cinergyt2->uncorrected_block_count += + le32_to_cpu(s->uncorrected_block_count); if (lock_bits != s->lock_bits) { wake_up_interruptible(&cinergyt2->poll_wq); diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c index 56d871cfd7fc..c2334aef4143 100644 --- a/drivers/media/dvb/dvb-core/dvb_net.c +++ b/drivers/media/dvb/dvb-core/dvb_net.c @@ -168,7 +168,7 @@ struct dvb_net_priv { * stolen from eth.c out of the linux kernel, hacked for dvb-device * by Michael Holzt <kju@debian.org> */ -static unsigned short dvb_net_eth_type_trans(struct sk_buff *skb, +static __be16 dvb_net_eth_type_trans(struct sk_buff *skb, struct net_device *dev) { struct ethhdr *eth; @@ -277,10 +277,10 @@ static int handle_one_ule_extension( struct dvb_net_priv *p ) if(ext_len >= 0) { p->ule_next_hdr += ext_len; if (!p->ule_bridged) { - p->ule_sndu_type = ntohs(*(unsigned short *)p->ule_next_hdr); + p->ule_sndu_type = ntohs(*(__be16 *)p->ule_next_hdr); p->ule_next_hdr += 2; } else { - p->ule_sndu_type = ntohs(*(unsigned short *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN))); + p->ule_sndu_type = ntohs(*(__be16 *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN))); /* This assures the extension handling loop will terminate. */ } } @@ -294,7 +294,7 @@ static int handle_one_ule_extension( struct dvb_net_priv *p ) if (ule_optional_ext_handlers[htype]) (void)ule_optional_ext_handlers[htype]( p ); p->ule_next_hdr += ext_len; - p->ule_sndu_type = ntohs( *(unsigned short *)(p->ule_next_hdr-2) ); + p->ule_sndu_type = ntohs( *(__be16 *)(p->ule_next_hdr-2) ); /* * note: the length of the next header type is included in the * length of THIS optional extension header @@ -594,8 +594,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) /* Check for complete payload. */ if (priv->ule_sndu_remain <= 0) { /* Check CRC32, we've got it in our skb already. */ - unsigned short ulen = htons(priv->ule_sndu_len); - unsigned short utype = htons(priv->ule_sndu_type); + __be16 ulen = htons(priv->ule_sndu_len); + __be16 utype = htons(priv->ule_sndu_type); const u8 *tail; struct kvec iov[3] = { { &ulen, sizeof ulen }, diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index cf4584e48b6d..f00a0eb40420 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -1,6 +1,6 @@ config DVB_USB tristate "Support for various USB DVB devices" - depends on DVB_CORE && USB && I2C + depends on DVB_CORE && USB && I2C && INPUT depends on HOTPLUG # due to FW_LOADER select FW_LOADER help diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 346223856f59..c4d40fe01d57 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -111,8 +111,8 @@ static int bristol_tuner_attach(struct dvb_usb_adapter *adap) struct i2c_adapter *tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe, 1); s8 a; int if1=1220; - if (adap->dev->udev->descriptor.idVendor == USB_VID_HAUPPAUGE && - adap->dev->udev->descriptor.idProduct == USB_PID_HAUPPAUGE_NOVA_T_500_2) { + if (adap->dev->udev->descriptor.idVendor == cpu_to_le16(USB_VID_HAUPPAUGE) && + adap->dev->udev->descriptor.idProduct == cpu_to_le16(USB_PID_HAUPPAUGE_NOVA_T_500_2)) { if (!eeprom_read(prim_i2c,0x59 + adap->id,&a)) if1=1220+a; } return dvb_attach(mt2060_attach,adap->fe, tun_i2c,&bristol_mt2060_config[adap->id], @@ -402,8 +402,8 @@ static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap) { struct usb_device_descriptor *desc = &adap->dev->udev->descriptor; - if (desc->idVendor == USB_VID_PINNACLE && - desc->idProduct == USB_PID_PINNACLE_EXPRESSCARD_320CX) + if (desc->idVendor == cpu_to_le16(USB_VID_PINNACLE) && + desc->idProduct == cpu_to_le16(USB_PID_PINNACLE_EXPRESSCARD_320CX)) dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); else dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); @@ -845,8 +845,8 @@ static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap) struct i2c_adapter *tun_i2c; s8 a; int if1=1220; - if (adap->dev->udev->descriptor.idVendor == USB_VID_HAUPPAUGE && - adap->dev->udev->descriptor.idProduct == USB_PID_HAUPPAUGE_NOVA_T_STICK) { + if (adap->dev->udev->descriptor.idVendor == cpu_to_le16(USB_VID_HAUPPAUGE) && + adap->dev->udev->descriptor.idProduct == cpu_to_le16(USB_PID_HAUPPAUGE_NOVA_T_STICK)) { if (!eeprom_read(prim_i2c,0x58,&a)) if1=1220+a; } if (st->is_dib7000pc) @@ -990,11 +990,12 @@ static struct dib7000p_config dib7070p_dib7000p_config = { /* STK7070P */ static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap) { - if (adap->dev->udev->descriptor.idVendor == USB_VID_PINNACLE && - adap->dev->udev->descriptor.idProduct == USB_PID_PINNACLE_PCTV72E) - dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); + struct usb_device_descriptor *p = &adap->dev->udev->descriptor; + if (p->idVendor == cpu_to_le16(USB_VID_PINNACLE) && + p->idProduct == cpu_to_le16(USB_PID_PINNACLE_PCTV72E)) + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); else - dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); msleep(10); dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c index e1112e39fb63..733a7ff7b207 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c @@ -127,7 +127,7 @@ int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, if ((*pos + hx->len + 4) >= fw->size) return -EINVAL; - hx->addr = le16_to_cpu( *((u16 *) &b[1]) ); + hx->addr = b[1] | (b[2] << 8); hx->type = b[3]; if (hx->type == 0x04) { diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c index 9a942afaf0af..2653120673b7 100644 --- a/drivers/media/dvb/dvb-usb/gp8psk.c +++ b/drivers/media/dvb/dvb-usb/gp8psk.c @@ -146,24 +146,24 @@ static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff) if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM) if (! (status & bm8pskFW_Loaded)) /* BCM4500 firmware loaded */ if(gp8psk_load_bcm4500fw(d)) - return EINVAL; + return -EINVAL; if (! (status & bmIntersilOn)) /* LNB Power */ if (gp8psk_usb_in_op(d, START_INTERSIL, 1, 0, &buf, 1)) - return EINVAL; + return -EINVAL; /* Set DVB mode to 1 */ if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM) if (gp8psk_usb_out_op(d, SET_DVB_MODE, 1, 0, NULL, 0)) - return EINVAL; + return -EINVAL; /* Abort possible TS (if previous tune crashed) */ if (gp8psk_usb_out_op(d, ARM_TRANSFER, 0, 0, NULL, 0)) - return EINVAL; + return -EINVAL; } else { /* Turn off LNB power */ if (gp8psk_usb_in_op(d, START_INTERSIL, 0, 0, &buf, 1)) - return EINVAL; + return -EINVAL; /* Turn off 8psk power */ if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1)) return -EINVAL; diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c index a12e6f784fda..54626a0dbf68 100644 --- a/drivers/media/dvb/dvb-usb/m920x.c +++ b/drivers/media/dvb/dvb-usb/m920x.c @@ -16,6 +16,7 @@ #include "qt1010.h" #include "tda1004x.h" #include "tda827x.h" +#include <asm/unaligned.h> /* debug */ static int dvb_usb_m920x_debug; @@ -347,13 +348,13 @@ static int m920x_firmware_download(struct usb_device *udev, const struct firmwar for (pass = 0; pass < 2; pass++) { for (i = 0; i + (sizeof(u16) * 3) < fw->size;) { - value = le16_to_cpu(*(u16 *)(fw->data + i)); + value = get_unaligned_le16(fw->data + i); i += sizeof(u16); - index = le16_to_cpu(*(u16 *)(fw->data + i)); + index = get_unaligned_le16(fw->data + i); i += sizeof(u16); - size = le16_to_cpu(*(u16 *)(fw->data + i)); + size = get_unaligned_le16(fw->data + i); i += sizeof(u16); if (pass == 1) { diff --git a/drivers/media/dvb/frontends/dib0070.h b/drivers/media/dvb/frontends/dib0070.h index 786e37d33889..3eedfdf505bc 100644 --- a/drivers/media/dvb/frontends/dib0070.h +++ b/drivers/media/dvb/frontends/dib0070.h @@ -37,7 +37,20 @@ struct dib0070_config { u8 flip_chip; }; -extern struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg); +#if defined(CONFIG_DVB_TUNER_DIB0070) || (defined(CONFIG_DVB_TUNER_DIB0070_MODULE) && defined(MODULE)) +extern struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, + struct dib0070_config *cfg); +#else +static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, + struct dib0070_config *cfg) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif + extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, uint8_t open); extern u16 dib0070_wbd_offset(struct dvb_frontend *); diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h index 081bd81f3da2..07c4d12ed5b7 100644 --- a/drivers/media/dvb/frontends/dib7000p.h +++ b/drivers/media/dvb/frontends/dib7000p.h @@ -37,7 +37,20 @@ struct dib7000p_config { #define DEFAULT_DIB7000P_I2C_ADDRESS 18 -extern struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg); +#if defined(CONFIG_DVB_DIB7000P) || (defined(CONFIG_DVB_DIB7000P_MODULE) && defined(MODULE)) +extern struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, + u8 i2c_addr, + struct dib7000p_config *cfg); +#else +static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, + u8 i2c_addr, + struct dib7000p_config *cfg) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif + extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]); extern struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int); diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c index c7b5785f81f2..5ed32544de39 100644 --- a/drivers/media/dvb/frontends/or51132.c +++ b/drivers/media/dvb/frontends/or51132.c @@ -126,7 +126,7 @@ static int or51132_readreg(struct or51132_state *state, u8 reg) reg, err); return -EREMOTEIO; } - return le16_to_cpup((u16*)buf); + return buf[0] | (buf[1] << 8); } static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware *fw) @@ -140,9 +140,9 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware dprintk("Firmware is %Zd bytes\n",fw->size); /* Get size of firmware A and B */ - firmwareAsize = le32_to_cpu(*((u32*)fw->data)); + firmwareAsize = le32_to_cpu(*((__le32*)fw->data)); dprintk("FirmwareA is %i bytes\n",firmwareAsize); - firmwareBsize = le32_to_cpu(*((u32*)(fw->data+4))); + firmwareBsize = le32_to_cpu(*((__le32*)(fw->data+4))); dprintk("FirmwareB is %i bytes\n",firmwareBsize); /* Upload firmware */ diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 747e7f1a6267..f05d43d8b5cf 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -51,6 +51,7 @@ #include <linux/crc32.h> #include <linux/i2c.h> #include <linux/kthread.h> +#include <asm/unaligned.h> #include <asm/system.h> @@ -1461,9 +1462,9 @@ static int check_firmware(struct av7110* av7110) ptr += 4; /* check dpram file */ - crc = ntohl(*(u32*) ptr); + crc = get_unaligned_be32(ptr); ptr += 4; - len = ntohl(*(u32*) ptr); + len = get_unaligned_be32(ptr); ptr += 4; if (len >= 512) { printk("dvb-ttpci: dpram file is way too big.\n"); @@ -1478,9 +1479,9 @@ static int check_firmware(struct av7110* av7110) ptr += len; /* check root file */ - crc = ntohl(*(u32*) ptr); + crc = get_unaligned_be32(ptr); ptr += 4; - len = ntohl(*(u32*) ptr); + len = get_unaligned_be32(ptr); ptr += 4; if (len <= 200000 || len >= 300000 || diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c index 3e6b650fbb81..ec55a968f204 100644 --- a/drivers/media/dvb/ttpci/av7110_av.c +++ b/drivers/media/dvb/ttpci/av7110_av.c @@ -965,8 +965,9 @@ static u8 iframe_header[] = { 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x static int play_iframe(struct av7110 *av7110, char __user *buf, unsigned int len, int nonblock) { - int i, n; + unsigned i, n; int progressive = 0; + int match = 0; dprintk(2, "av7110:%p, \n", av7110); @@ -975,12 +976,31 @@ static int play_iframe(struct av7110 *av7110, char __user *buf, unsigned int len return -EBUSY; } - for (i = 0; i < len - 5; i++) { - /* get progressive flag from picture extension */ - if (buf[i] == 0x00 && buf[i+1] == 0x00 && - buf[i+2] == 0x01 && (unsigned char)buf[i+3] == 0xb5 && - (buf[i+4] & 0xf0) == 0x10) - progressive = buf[i+5] & 0x08; + /* search in buf for instances of 00 00 01 b5 1? */ + for (i = 0; i < len; i++) { + unsigned char c; + if (get_user(c, buf + i)) + return -EFAULT; + if (match == 5) { + progressive = c & 0x08; + match = 0; + } + if (c == 0x00) { + match = (match == 1 || match == 2) ? 2 : 1; + continue; + } + switch (match++) { + case 2: if (c == 0x01) + continue; + break; + case 3: if (c == 0xb5) + continue; + break; + case 4: if ((c & 0xf0) == 0x10) + continue; + break; + } + match = 0; } /* setting n always > 1, fixes problems when playing stillframes diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index 732ce4de512e..5d2d81ab2371 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -552,7 +552,7 @@ static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack, u16 csum = 0, cc; int i; for (i = 0; i < len; i += 2) - csum ^= le16_to_cpup((u16 *) (muxpack + i)); + csum ^= le16_to_cpup((__le16 *) (muxpack + i)); if (csum) { printk("%s: muxpack with incorrect checksum, ignoring\n", __func__); diff --git a/drivers/media/dvb/ttusb-dec/Kconfig b/drivers/media/dvb/ttusb-dec/Kconfig index 0712899e39a4..a23cc0aa17d3 100644 --- a/drivers/media/dvb/ttusb-dec/Kconfig +++ b/drivers/media/dvb/ttusb-dec/Kconfig @@ -1,6 +1,6 @@ config DVB_TTUSB_DEC tristate "Technotrend/Hauppauge USB DEC devices" - depends on DVB_CORE && USB + depends on DVB_CORE && USB && INPUT depends on HOTPLUG # due to FW_LOADER select FW_LOADER select CRC32 diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index 42eee04daa5d..fefdc05e84ac 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -343,7 +343,7 @@ static int ttusb_dec_get_stb_state (struct ttusb_dec *dec, unsigned int *mode, u8 c[COMMAND_PACKET_SIZE]; int c_length; int result; - unsigned int tmp; + __be32 tmp; dprintk("%s\n", __func__); @@ -398,9 +398,9 @@ static void ttusb_dec_set_pids(struct ttusb_dec *dec) 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - u16 pcr = htons(dec->pid[DMX_PES_PCR]); - u16 audio = htons(dec->pid[DMX_PES_AUDIO]); - u16 video = htons(dec->pid[DMX_PES_VIDEO]); + __be16 pcr = htons(dec->pid[DMX_PES_PCR]); + __be16 audio = htons(dec->pid[DMX_PES_AUDIO]); + __be16 video = htons(dec->pid[DMX_PES_VIDEO]); dprintk("%s\n", __func__); @@ -435,7 +435,7 @@ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length) case 0x01: { /* VideoStream */ int prebytes = pva[5] & 0x03; int postbytes = (pva[5] & 0x0c) >> 2; - u16 v_pes_payload_length; + __be16 v_pes_payload_length; if (output_pva) { dec->video_filter->feed->cb.ts(pva, length, NULL, 0, @@ -1006,7 +1006,7 @@ static int ttusb_dec_start_sec_feed(struct dvb_demux_feed *dvbdmxfeed) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - u16 pid; + __be16 pid; u8 c[COMMAND_PACKET_SIZE]; int c_length; int result; @@ -1278,9 +1278,10 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec) u8 *firmware = NULL; size_t firmware_size = 0; u16 firmware_csum = 0; - u16 firmware_csum_ns; - u32 firmware_size_nl; - u32 crc32_csum, crc32_check, tmp; + __be16 firmware_csum_ns; + __be32 firmware_size_nl; + u32 crc32_csum, crc32_check; + __be32 tmp; const struct firmware *fw_entry = NULL; dprintk("%s\n", __func__); @@ -1306,7 +1307,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec) valid. */ crc32_csum = crc32(~0L, firmware, 56) ^ ~0L; memcpy(&tmp, &firmware[56], 4); - crc32_check = htonl(tmp); + crc32_check = ntohl(tmp); if (crc32_csum != crc32_check) { printk("%s: crc32 check of DSP code failed (calculated " "0x%08x != 0x%08x in file), file invalid.\n", @@ -1627,7 +1628,7 @@ static int ttusb_dec_probe(struct usb_interface *intf, usb_set_intfdata(intf, (void *)dec); - switch (le16_to_cpu(id->idProduct)) { + switch (id->idProduct) { case 0x1006: ttusb_dec_set_model(dec, TTUSB_DEC3000S); break; @@ -1652,7 +1653,7 @@ static int ttusb_dec_probe(struct usb_interface *intf, ttusb_dec_init_dvb(dec); dec->adapter.priv = dec; - switch (le16_to_cpu(id->idProduct)) { + switch (id->idProduct) { case 0x1006: dec->fe = ttusbdecfe_dvbs_attach(&fe_config); break; diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c index eb5eaeccd7c4..443af24097f3 100644 --- a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c +++ b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c @@ -86,7 +86,7 @@ static int ttusbdecfe_dvbt_set_frontend(struct dvb_frontend* fe, struct dvb_fron 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff }; - u32 freq = htonl(p->frequency / 1000); + __be32 freq = htonl(p->frequency / 1000); memcpy(&b[4], &freq, sizeof (u32)); state->config->send_command(fe, 0x71, sizeof(b), b, NULL, NULL); @@ -117,10 +117,10 @@ static int ttusbdecfe_dvbs_set_frontend(struct dvb_frontend* fe, struct dvb_fron 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - u32 freq; - u32 sym_rate; - u32 band; - u32 lnb_voltage; + __be32 freq; + __be32 sym_rate; + __be32 band; + __be32 lnb_voltage; freq = htonl(p->frequency + (state->hi_band ? LOF_HI : LOF_LO)); diff --git a/drivers/media/video/au0828/Kconfig b/drivers/media/video/au0828/Kconfig index def10d086373..52b2491581a8 100644 --- a/drivers/media/video/au0828/Kconfig +++ b/drivers/media/video/au0828/Kconfig @@ -1,7 +1,7 @@ config VIDEO_AU0828 tristate "Auvitek AU0828 support" - depends on VIDEO_DEV && I2C && INPUT && DVB_CORE && USB + depends on I2C && INPUT && DVB_CORE && USB select I2C_ALGOBIT select VIDEO_TVEEPROM select DVB_AU8522 if !DVB_FE_CUSTOMIZE diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c index c86a5f17eca8..c6d470590380 100644 --- a/drivers/media/video/au0828/au0828-dvb.c +++ b/drivers/media/video/au0828/au0828-dvb.c @@ -353,12 +353,6 @@ int au0828_dvb_register(struct au0828_dev *dev) return -1; } - /* Put the analog decoder in standby to keep it quiet */ - au0828_call_i2c_clients(dev, TUNER_SET_STANDBY, NULL); - - if (dvb->frontend->ops.analog_ops.standby) - dvb->frontend->ops.analog_ops.standby(dvb->frontend); - /* register everything */ ret = dvb_register(dev); if (ret < 0) { diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index f20a01cfc73e..8ef0424c26c4 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -34,6 +34,7 @@ #include <linux/firmware.h> #include <net/checksum.h> +#include <asm/unaligned.h> #include <asm/io.h> #include "bttvp.h" @@ -3858,7 +3859,7 @@ static void __devinit osprey_eeprom(struct bttv *btv, const u8 ee[256]) ee += i; /* found a valid descriptor */ - type = be16_to_cpup((u16*)(ee+4)); + type = get_unaligned_be16((__be16 *)(ee+4)); switch(type) { /* 848 based */ @@ -3918,7 +3919,7 @@ static void __devinit osprey_eeprom(struct bttv *btv, const u8 ee[256]) btv->c.nr, type); break; } - serial = be32_to_cpup((u32*)(ee+6)); + serial = get_unaligned_be32((__be32 *)(ee+6)); } printk(KERN_INFO "bttv%d: osprey eeprom: card=%d '%s' serial=%u\n", diff --git a/drivers/media/video/bt8xx/bttv-risc.c b/drivers/media/video/bt8xx/bttv-risc.c index e5979f77504c..0af586876e72 100644 --- a/drivers/media/video/bt8xx/bttv-risc.c +++ b/drivers/media/video/bt8xx/bttv-risc.c @@ -48,7 +48,7 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, { u32 instructions,line,todo; struct scatterlist *sg; - u32 *rp; + __le32 *rp; int rc; /* estimate risc mem: worst case is one write per page border + @@ -128,7 +128,8 @@ bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc, unsigned int cpadding) { unsigned int instructions,line,todo,ylen,chroma; - u32 *rp,ri; + __le32 *rp; + u32 ri; struct scatterlist *ysg; struct scatterlist *usg; struct scatterlist *vsg; @@ -244,7 +245,8 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc, { int dwords,rc,line,maxy,start,end,skip,nskips; struct btcx_skiplist *skips; - u32 *rp,ri,ra; + __le32 *rp; + u32 ri,ra; u32 addr; /* skip list for window clipping */ diff --git a/drivers/media/video/btcx-risc.c b/drivers/media/video/btcx-risc.c index ce0840ccd594..f42701f82e7f 100644 --- a/drivers/media/video/btcx-risc.c +++ b/drivers/media/video/btcx-risc.c @@ -63,7 +63,7 @@ int btcx_riscmem_alloc(struct pci_dev *pci, struct btcx_riscmem *risc, unsigned int size) { - u32 *cpu; + __le32 *cpu; dma_addr_t dma; if (NULL != risc->cpu && risc->size < size) diff --git a/drivers/media/video/btcx-risc.h b/drivers/media/video/btcx-risc.h index 503e6c6d7b69..861bc8112824 100644 --- a/drivers/media/video/btcx-risc.h +++ b/drivers/media/video/btcx-risc.h @@ -2,8 +2,8 @@ */ struct btcx_riscmem { unsigned int size; - u32 *cpu; - u32 *jmp; + __le32 *cpu; + __le32 *jmp; dma_addr_t dma; }; diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index 66864904c99b..9a26751615c6 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c @@ -182,14 +182,16 @@ static void input_change(struct cx18 *cx) if (std == V4L2_STD_NTSC_M_JP) { /* Japan uses EIAJ audio standard */ cx18_av_write(cx, 0x808, 0xf7); + cx18_av_write(cx, 0x80b, 0x02); } else if (std == V4L2_STD_NTSC_M_KR) { /* South Korea uses A2 audio standard */ cx18_av_write(cx, 0x808, 0xf8); + cx18_av_write(cx, 0x80b, 0x03); } else { /* Others use the BTSC audio standard */ cx18_av_write(cx, 0x808, 0xf6); + cx18_av_write(cx, 0x80b, 0x01); } - cx18_av_write(cx, 0x80b, 0x00); } else if (std & V4L2_STD_PAL) { /* Follow tuner change procedure for PAL */ cx18_av_write(cx, 0x808, 0xff); @@ -741,8 +743,8 @@ static void log_audio_status(struct cx18 *cx) { struct cx18_av_state *state = &cx->av_state; u8 download_ctl = cx18_av_read(cx, 0x803); - u8 mod_det_stat0 = cx18_av_read(cx, 0x805); - u8 mod_det_stat1 = cx18_av_read(cx, 0x804); + u8 mod_det_stat0 = cx18_av_read(cx, 0x804); + u8 mod_det_stat1 = cx18_av_read(cx, 0x805); u8 audio_config = cx18_av_read(cx, 0x808); u8 pref_mode = cx18_av_read(cx, 0x809); u8 afc0 = cx18_av_read(cx, 0x80b); @@ -760,12 +762,12 @@ static void log_audio_status(struct cx18 *cx) case 0x12: p = "dual with SAP"; break; case 0x14: p = "tri with SAP"; break; case 0xfe: p = "forced mode"; break; - default: p = "not defined"; + default: p = "not defined"; break; } CX18_INFO("Detected audio mode: %s\n", p); switch (mod_det_stat1) { - case 0x00: p = "BTSC"; break; + case 0x00: p = "not defined"; break; case 0x01: p = "EIAJ"; break; case 0x02: p = "A2-M"; break; case 0x03: p = "A2-BG"; break; @@ -779,8 +781,13 @@ static void log_audio_status(struct cx18 *cx) case 0x0b: p = "NICAM-I"; break; case 0x0c: p = "NICAM-L"; break; case 0x0d: p = "BTSC/EIAJ/A2-M Mono (4.5 MHz FMMono)"; break; + case 0x0e: p = "IF FM Radio"; break; + case 0x0f: p = "BTSC"; break; + case 0x10: p = "detected chrominance"; break; + case 0xfd: p = "unknown audio standard"; break; + case 0xfe: p = "forced audio standard"; break; case 0xff: p = "no detected audio standard"; break; - default: p = "not defined"; + default: p = "not defined"; break; } CX18_INFO("Detected audio standard: %s\n", p); CX18_INFO("Audio muted: %s\n", @@ -789,22 +796,23 @@ static void log_audio_status(struct cx18 *cx) (download_ctl & 0x10) ? "running" : "stopped"); switch (audio_config >> 4) { - case 0x00: p = "BTSC"; break; - case 0x01: p = "EIAJ"; break; - case 0x02: p = "A2-M"; break; - case 0x03: p = "A2-BG"; break; - case 0x04: p = "A2-DK1"; break; - case 0x05: p = "A2-DK2"; break; - case 0x06: p = "A2-DK3"; break; - case 0x07: p = "A1 (6.0 MHz FM Mono)"; break; - case 0x08: p = "AM-L"; break; - case 0x09: p = "NICAM-BG"; break; - case 0x0a: p = "NICAM-DK"; break; - case 0x0b: p = "NICAM-I"; break; - case 0x0c: p = "NICAM-L"; break; - case 0x0d: p = "FM radio"; break; + case 0x00: p = "undefined"; break; + case 0x01: p = "BTSC"; break; + case 0x02: p = "EIAJ"; break; + case 0x03: p = "A2-M"; break; + case 0x04: p = "A2-BG"; break; + case 0x05: p = "A2-DK1"; break; + case 0x06: p = "A2-DK2"; break; + case 0x07: p = "A2-DK3"; break; + case 0x08: p = "A1 (6.0 MHz FM Mono)"; break; + case 0x09: p = "AM-L"; break; + case 0x0a: p = "NICAM-BG"; break; + case 0x0b: p = "NICAM-DK"; break; + case 0x0c: p = "NICAM-I"; break; + case 0x0d: p = "NICAM-L"; break; + case 0x0e: p = "FM radio"; break; case 0x0f: p = "automatic detection"; break; - default: p = "undefined"; + default: p = "undefined"; break; } CX18_INFO("Configured audio standard: %s\n", p); @@ -815,12 +823,9 @@ static void log_audio_status(struct cx18 *cx) case 0x02: p = "MONO3 (STEREO forced MONO)"; break; case 0x03: p = "MONO4 (NICAM ANALOG-Language C/Analog Fallback)"; break; case 0x04: p = "STEREO"; break; - case 0x05: p = "DUAL1 (AB)"; break; - case 0x06: p = "DUAL2 (AC) (FM)"; break; - case 0x07: p = "DUAL3 (BC) (FM)"; break; - case 0x08: p = "DUAL4 (AC) (AM)"; break; - case 0x09: p = "DUAL5 (BC) (AM)"; break; - case 0x0a: p = "SAP"; break; + case 0x05: p = "DUAL1 (AC)"; break; + case 0x06: p = "DUAL2 (BC)"; break; + case 0x07: p = "DUAL3 (AB)"; break; default: p = "undefined"; } CX18_INFO("Configured audio mode: %s\n", p); @@ -835,9 +840,11 @@ static void log_audio_status(struct cx18 *cx) case 0x06: p = "BTSC"; break; case 0x07: p = "EIAJ"; break; case 0x08: p = "A2-M"; break; - case 0x09: p = "FM Radio"; break; + case 0x09: p = "FM Radio (4.5 MHz)"; break; + case 0x0a: p = "FM Radio (5.5 MHz)"; break; + case 0x0b: p = "S-Video"; break; case 0x0f: p = "automatic standard and mode detection"; break; - default: p = "undefined"; + default: p = "undefined"; break; } CX18_INFO("Configured audio system: %s\n", p); } @@ -857,22 +864,24 @@ static void log_audio_status(struct cx18 *cx) case 5: p = "language AC"; break; case 6: p = "language BC"; break; case 7: p = "language AB"; break; - default: p = "undefined"; + default: p = "undefined"; break; } CX18_INFO("Preferred audio mode: %s\n", p); if ((audio_config & 0xf) == 0xf) { - switch ((afc0 >> 2) & 0x1) { + switch ((afc0 >> 3) & 0x1) { case 0: p = "system DK"; break; case 1: p = "system L"; break; } CX18_INFO("Selected 65 MHz format: %s\n", p); - switch (afc0 & 0x3) { - case 0: p = "BTSC"; break; - case 1: p = "EIAJ"; break; - case 2: p = "A2-M"; break; - default: p = "undefined"; + switch (afc0 & 0x7) { + case 0: p = "Chroma"; break; + case 1: p = "BTSC"; break; + case 2: p = "EIAJ"; break; + case 3: p = "A2-M"; break; + case 4: p = "autodetect"; break; + default: p = "undefined"; break; } CX18_INFO("Selected 45 MHz format: %s\n", p); } diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index 553adbf2cd44..baccd079243d 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c @@ -126,7 +126,7 @@ static const struct cx18_card cx18_card_hvr1600_samsung = { /* ------------------------------------------------------------------------- */ -/* Compro VideoMate H900: not working at the moment! */ +/* Compro VideoMate H900: note that this card is analog only! */ static const struct cx18_card_pci_info cx18_pci_h900[] = { { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_COMPRO, 0xe100 }, @@ -136,7 +136,7 @@ static const struct cx18_card_pci_info cx18_pci_h900[] = { static const struct cx18_card cx18_card_h900 = { .type = CX18_CARD_COMPRO_H900, .name = "Compro VideoMate H900", - .comment = "DVB & VBI are not yet supported\n", + .comment = "VBI is not yet supported\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_CX23418, .hw_all = CX18_HW_TUNER, diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c index 2bdac5ebbb0d..87cf41021665 100644 --- a/drivers/media/video/cx18/cx18-controls.c +++ b/drivers/media/video/cx18/cx18-controls.c @@ -159,7 +159,7 @@ static int cx18_setup_vbi_fmt(struct cx18 *cx, enum v4l2_mpeg_stream_vbi_fmt fmt { if (!(cx->v4l2_cap & V4L2_CAP_SLICED_VBI_CAPTURE)) return -EINVAL; - if (atomic_read(&cx->capturing) > 0) + if (atomic_read(&cx->ana_capturing) > 0) return -EBUSY; /* First try to allocate sliced VBI buffers if needed. */ @@ -235,7 +235,7 @@ int cx18_control_ioctls(struct cx18 *cx, unsigned int cmd, void *arg) CX18_DEBUG_IOCTL("VIDIOC_S_EXT_CTRLS\n"); if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) { struct cx2341x_mpeg_params p = cx->params; - int err = cx2341x_ext_ctrls(&p, atomic_read(&cx->capturing), arg, cmd); + int err = cx2341x_ext_ctrls(&p, atomic_read(&cx->ana_capturing), arg, cmd); if (err) return err; @@ -295,7 +295,7 @@ int cx18_control_ioctls(struct cx18 *cx, unsigned int cmd, void *arg) CX18_DEBUG_IOCTL("VIDIOC_TRY_EXT_CTRLS\n"); if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) return cx2341x_ext_ctrls(&cx->params, - atomic_read(&cx->capturing), arg, cmd); + atomic_read(&cx->ana_capturing), arg, cmd); return -EINVAL; } diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 0dd4e0529970..2b810bb2a4c7 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -670,7 +670,7 @@ static int __devinit cx18_probe(struct pci_dev *dev, cx18_init_power(cx, 1); cx18_init_memory(cx); - cx->scb = (struct cx18_scb *)(cx->enc_mem + SCB_OFFSET); + cx->scb = (struct cx18_scb __iomem *)(cx->enc_mem + SCB_OFFSET); cx18_init_scb(cx); cx18_gpio_init(cx); @@ -751,17 +751,6 @@ static int __devinit cx18_probe(struct pci_dev *dev, if (cx->options.radio > 0) cx->v4l2_cap |= V4L2_CAP_RADIO; - retval = cx18_streams_setup(cx); - if (retval) { - CX18_ERR("Error %d setting up streams\n", retval); - goto free_irq; - } - retval = cx18_streams_register(cx); - if (retval) { - CX18_ERR("Error %d registering devices\n", retval); - goto free_streams; - } - if (cx->options.tuner > -1) { struct tuner_setup setup; @@ -788,7 +777,16 @@ static int __devinit cx18_probe(struct pci_dev *dev, are not. */ cx->tuner_std = cx->std; - cx18_init_on_first_open(cx); + retval = cx18_streams_setup(cx); + if (retval) { + CX18_ERR("Error %d setting up streams\n", retval); + goto free_irq; + } + retval = cx18_streams_register(cx); + if (retval) { + CX18_ERR("Error %d registering devices\n", retval); + goto free_streams; + } CX18_INFO("Initialized card #%d: %s\n", cx->num, cx->card_name); @@ -889,7 +887,7 @@ static void cx18_remove(struct pci_dev *pci_dev) /* Stop all captures */ CX18_DEBUG_INFO("Stopping all streams\n"); - if (atomic_read(&cx->capturing) > 0) + if (atomic_read(&cx->tot_capturing) > 0) cx18_stop_all_captures(cx); /* Interrupts */ diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index a2a6c58d12fe..de14ab59a206 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -358,7 +358,7 @@ struct cx18 { u32 v4l2_cap; /* V4L2 capabilities of card */ u32 hw_flags; /* Hardware description of the board */ unsigned mdl_offset; - struct cx18_scb *scb; /* pointer to SCB */ + struct cx18_scb __iomem *scb; /* pointer to SCB */ struct cx18_av_state av_state; @@ -380,7 +380,8 @@ struct cx18 { int stream_buf_size[CX18_MAX_STREAMS]; /* Stream buffer size */ struct cx18_stream streams[CX18_MAX_STREAMS]; /* Stream data */ unsigned long i_flags; /* global cx18 flags */ - atomic_t capturing; /* count number of active capture streams */ + atomic_t ana_capturing; /* count number of active analog capture streams */ + atomic_t tot_capturing; /* total count number of active capture streams */ spinlock_t lock; /* lock access to this struct */ int search_pack_header; @@ -423,6 +424,10 @@ struct cx18 { struct mutex i2c_bus_lock[2]; struct i2c_client *i2c_clients[I2C_CLIENTS_MAX]; + /* gpio */ + u32 gpio_dir; + u32 gpio_val; + /* v4l2 and User settings */ /* codec settings */ diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index 0b3141db174b..1e537fe04a23 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c @@ -318,7 +318,7 @@ static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf, size_t tot_written = 0; int single_frame = 0; - if (atomic_read(&cx->capturing) == 0 && s->id == -1) { + if (atomic_read(&cx->ana_capturing) == 0 && s->id == -1) { /* shouldn't happen */ CX18_DEBUG_WARN("Stream %s not initialized before read\n", s->name); @@ -361,7 +361,8 @@ static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf, cx18_enqueue(s, buf, &s->q_free); cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, - (void *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, + (void __iomem *)&cx->scb->cpu_mdl[buf->id] - + cx->enc_mem, 1, buf->id, s->buf_size); } else cx18_enqueue(s, buf, &s->q_io); @@ -581,7 +582,7 @@ int cx18_v4l2_close(struct inode *inode, struct file *filp) cx18_call_i2c_clients(cx, VIDIOC_S_STD, &cx->std); /* Select correct audio input (i.e. TV tuner or Line in) */ cx18_audio_set_io(cx); - if (atomic_read(&cx->capturing) > 0) { + if (atomic_read(&cx->ana_capturing) > 0) { /* Undo video mute */ cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle, cx->params.video_mute | @@ -627,7 +628,7 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp) } if (!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) { - if (atomic_read(&cx->capturing) > 0) { + if (atomic_read(&cx->ana_capturing) > 0) { /* switching to radio while capture is in progress is not polite */ cx18_release_stream(s); @@ -694,7 +695,7 @@ int cx18_v4l2_open(struct inode *inode, struct file *filp) void cx18_mute(struct cx18 *cx) { - if (atomic_read(&cx->capturing)) + if (atomic_read(&cx->ana_capturing)) cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, cx18_find_handle(cx), 1); CX18_DEBUG_INFO("Mute\n"); @@ -702,7 +703,7 @@ void cx18_mute(struct cx18 *cx) void cx18_unmute(struct cx18 *cx) { - if (atomic_read(&cx->capturing)) { + if (atomic_read(&cx->ana_capturing)) { cx18_msleep_timeout(100, 0); cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, cx18_find_handle(cx), 12); diff --git a/drivers/media/video/cx18/cx18-gpio.c b/drivers/media/video/cx18/cx18-gpio.c index bb8bc86086d0..ceb63653c926 100644 --- a/drivers/media/video/cx18/cx18-gpio.c +++ b/drivers/media/video/cx18/cx18-gpio.c @@ -35,9 +35,6 @@ #define CX18_REG_GPIO_OUT2 0xc78104 #define CX18_REG_GPIO_DIR2 0xc7810c -static u32 gpio_dir; -static u32 gpio_val; - /* * HVR-1600 GPIO pins, courtesy of Hauppauge: * @@ -49,24 +46,29 @@ static u32 gpio_val; static void gpio_write(struct cx18 *cx) { - write_reg((gpio_dir & 0xffff) << 16, CX18_REG_GPIO_DIR1); - write_reg(((gpio_dir & 0xffff) << 16) | (gpio_val & 0xffff), + u32 dir = cx->gpio_dir; + u32 val = cx->gpio_val; + + write_reg((dir & 0xffff) << 16, CX18_REG_GPIO_DIR1); + write_reg(((dir & 0xffff) << 16) | (val & 0xffff), CX18_REG_GPIO_OUT1); - write_reg(gpio_dir & 0xffff0000, CX18_REG_GPIO_DIR2); - write_reg((gpio_dir & 0xffff0000) | ((gpio_val & 0xffff0000) >> 16), + write_reg(dir & 0xffff0000, CX18_REG_GPIO_DIR2); + write_reg((dir & 0xffff0000) | ((val & 0xffff0000) >> 16), CX18_REG_GPIO_OUT2); } void cx18_gpio_init(struct cx18 *cx) { - gpio_dir = cx->card->gpio_init.direction; - gpio_val = cx->card->gpio_init.initial_value; + cx->gpio_dir = cx->card->gpio_init.direction; + cx->gpio_val = cx->card->gpio_init.initial_value; - if (gpio_dir == 0) - return; + if (cx->card->tuners[0].tuner == TUNER_XC2028) { + cx->gpio_dir |= 1 << cx->card->xceive_pin; + cx->gpio_val |= 1 << cx->card->xceive_pin; + } - gpio_dir |= 1 << cx->card->xceive_pin; - gpio_val |= 1 << cx->card->xceive_pin; + if (cx->gpio_dir == 0) + return; CX18_DEBUG_INFO("GPIO initial dir: %08x/%08x out: %08x/%08x\n", read_reg(CX18_REG_GPIO_DIR1), read_reg(CX18_REG_GPIO_DIR2), @@ -86,13 +88,12 @@ int cx18_reset_tuner_gpio(void *dev, int cmd, int value) return 0; CX18_DEBUG_INFO("Resetting tuner\n"); - gpio_dir |= 1 << cx->card->xceive_pin; - gpio_val &= ~(1 << cx->card->xceive_pin); + cx->gpio_val &= ~(1 << cx->card->xceive_pin); gpio_write(cx); schedule_timeout_interruptible(msecs_to_jiffies(1)); - gpio_val |= 1 << cx->card->xceive_pin; + cx->gpio_val |= 1 << cx->card->xceive_pin; gpio_write(cx); schedule_timeout_interruptible(msecs_to_jiffies(1)); return 0; diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index dbdcb86ec5aa..4151f1e5493f 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c @@ -247,7 +247,7 @@ static int cx18_try_or_set_fmt(struct cx18 *cx, int streamtype, if (!set_fmt || (cx->params.width == w && cx->params.height == h)) return 0; - if (atomic_read(&cx->capturing) > 0) + if (atomic_read(&cx->ana_capturing) > 0) return -EBUSY; cx->params.width = w; @@ -264,7 +264,7 @@ static int cx18_try_or_set_fmt(struct cx18 *cx, int streamtype, if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { if (set_fmt && streamtype == CX18_ENC_STREAM_TYPE_VBI && cx->vbi.sliced_in->service_set && - atomic_read(&cx->capturing) > 0) + atomic_read(&cx->ana_capturing) > 0) return -EBUSY; if (set_fmt) { cx->vbi.sliced_in->service_set = 0; @@ -293,7 +293,7 @@ static int cx18_try_or_set_fmt(struct cx18 *cx, int streamtype, return 0; if (set == 0) return -EINVAL; - if (atomic_read(&cx->capturing) > 0 && cx->vbi.sliced_in->service_set == 0) + if (atomic_read(&cx->ana_capturing) > 0 && cx->vbi.sliced_in->service_set == 0) return -EBUSY; cx18_av_cmd(cx, VIDIOC_S_FMT, fmt); memcpy(cx->vbi.sliced_in, vbifmt, sizeof(*cx->vbi.sliced_in)); @@ -581,7 +581,7 @@ int cx18_v4l2_ioctls(struct cx18 *cx, struct file *filp, unsigned cmd, void *arg break; if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) || - atomic_read(&cx->capturing) > 0) { + atomic_read(&cx->ana_capturing) > 0) { /* Switching standard would turn off the radio or mess with already running streams, prevent that by returning EBUSY. */ @@ -677,7 +677,7 @@ int cx18_v4l2_ioctls(struct cx18 *cx, struct file *filp, unsigned cmd, void *arg enc->flags = 0; if (try) return 0; - if (!atomic_read(&cx->capturing)) + if (!atomic_read(&cx->ana_capturing)) return -EPERM; if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags)) return 0; @@ -689,7 +689,7 @@ int cx18_v4l2_ioctls(struct cx18 *cx, struct file *filp, unsigned cmd, void *arg enc->flags = 0; if (try) return 0; - if (!atomic_read(&cx->capturing)) + if (!atomic_read(&cx->ana_capturing)) return -EPERM; if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags)) return 0; diff --git a/drivers/media/video/cx18/cx18-irq.c b/drivers/media/video/cx18/cx18-irq.c index 6e14f8bda559..25114a5cbd57 100644 --- a/drivers/media/video/cx18/cx18-irq.c +++ b/drivers/media/video/cx18/cx18-irq.c @@ -75,7 +75,7 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb) cx18_buf_sync_for_device(s, buf); cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, - (void *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, + (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, 1, buf->id, s->buf_size); } else set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags); @@ -161,13 +161,15 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id) */ if (sw2) { - if (sw2 & (cx->scb->cpu2hpu_irq_ack | cx->scb->cpu2epu_irq_ack)) + if (sw2 & (readl(&cx->scb->cpu2hpu_irq_ack) | + readl(&cx->scb->cpu2epu_irq_ack))) wake_up(&cx->mb_cpu_waitq); - if (sw2 & (cx->scb->apu2hpu_irq_ack | cx->scb->apu2epu_irq_ack)) + if (sw2 & (readl(&cx->scb->apu2hpu_irq_ack) | + readl(&cx->scb->apu2epu_irq_ack))) wake_up(&cx->mb_apu_waitq); - if (sw2 & cx->scb->epu2hpu_irq_ack) + if (sw2 & readl(&cx->scb->epu2hpu_irq_ack)) wake_up(&cx->mb_epu_waitq); - if (sw2 & cx->scb->hpu2epu_irq_ack) + if (sw2 & readl(&cx->scb->hpu2epu_irq_ack)) wake_up(&cx->mb_hpu_waitq); } diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index 0c5f328bca54..2a5ccef9185b 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c @@ -94,10 +94,10 @@ static const struct cx18_api_info *find_api_info(u32 cmd) return NULL; } -static struct cx18_mailbox *cx18_mb_is_complete(struct cx18 *cx, int rpu, +static struct cx18_mailbox __iomem *cx18_mb_is_complete(struct cx18 *cx, int rpu, u32 *state, u32 *irq, u32 *req) { - struct cx18_mailbox *mb = NULL; + struct cx18_mailbox __iomem *mb = NULL; int wait_count = 0; u32 ack; @@ -142,7 +142,7 @@ static struct cx18_mailbox *cx18_mb_is_complete(struct cx18 *cx, int rpu, long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb) { const struct cx18_api_info *info = find_api_info(mb->cmd); - struct cx18_mailbox *ack_mb; + struct cx18_mailbox __iomem *ack_mb; u32 ack_irq; u8 rpu = CPU; @@ -182,7 +182,7 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) { const struct cx18_api_info *info = find_api_info(cmd); u32 state = 0, irq = 0, req, oldreq, err; - struct cx18_mailbox *mb; + struct cx18_mailbox __iomem *mb; wait_queue_head_t *waitq; int timeout = 100; int cnt = 0; diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 4ca9d847f1b1..1b921a336092 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -36,12 +36,13 @@ #define CX18_DSP0_INTERRUPT_MASK 0xd0004C static struct file_operations cx18_v4l2_enc_fops = { - .owner = THIS_MODULE, - .read = cx18_v4l2_read, - .open = cx18_v4l2_open, - .ioctl = cx18_v4l2_ioctl, - .release = cx18_v4l2_close, - .poll = cx18_v4l2_enc_poll, + .owner = THIS_MODULE, + .read = cx18_v4l2_read, + .open = cx18_v4l2_open, + .ioctl = cx18_v4l2_ioctl, + .compat_ioctl = v4l_compat_ioctl32, + .release = cx18_v4l2_close, + .poll = cx18_v4l2_enc_poll, }; /* offset from 0 to register ts v4l2 minors on */ @@ -443,7 +444,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) s->handle = data[0]; cx18_vapi(cx, CX18_CPU_SET_CHANNEL_TYPE, 2, s->handle, captype); - if (atomic_read(&cx->capturing) == 0 && !ts) { + if (atomic_read(&cx->ana_capturing) == 0 && !ts) { /* Stuff from Windows, we don't know what it is */ cx18_vapi(cx, CX18_CPU_SET_VER_CROP_LINE, 2, s->handle, 0); cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 3, 1); @@ -466,14 +467,14 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) cx2341x_update(cx, cx18_api_func, NULL, &cx->params); } - if (atomic_read(&cx->capturing) == 0) { + if (atomic_read(&cx->tot_capturing) == 0) { clear_bit(CX18_F_I_EOS, &cx->i_flags); write_reg(7, CX18_DSP0_INTERRUPT_MASK); } cx18_vapi(cx, CX18_CPU_DE_SET_MDL_ACK, 3, s->handle, - (void *)&cx->scb->cpu_mdl_ack[s->type][0] - cx->enc_mem, - (void *)&cx->scb->cpu_mdl_ack[s->type][1] - cx->enc_mem); + (void __iomem *)&cx->scb->cpu_mdl_ack[s->type][0] - cx->enc_mem, + (void __iomem *)&cx->scb->cpu_mdl_ack[s->type][1] - cx->enc_mem); list_for_each(p, &s->q_free.list) { struct cx18_buffer *buf = list_entry(p, struct cx18_buffer, list); @@ -481,8 +482,8 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) writel(buf->dma_handle, &cx->scb->cpu_mdl[buf->id].paddr); writel(s->buf_size, &cx->scb->cpu_mdl[buf->id].length); cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, - (void *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, 1, - buf->id, s->buf_size); + (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, + 1, buf->id, s->buf_size); } /* begin_capture */ if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) { @@ -492,7 +493,9 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) } /* you're live! sit back and await interrupts :) */ - atomic_inc(&cx->capturing); + if (!ts) + atomic_inc(&cx->ana_capturing); + atomic_inc(&cx->tot_capturing); return 0; } @@ -523,7 +526,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end) CX18_DEBUG_INFO("Stop Capture\n"); - if (atomic_read(&cx->capturing) == 0) + if (atomic_read(&cx->tot_capturing) == 0) return 0; if (s->type == CX18_ENC_STREAM_TYPE_MPG) @@ -537,7 +540,9 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end) CX18_INFO("ignoring gop_end: not (yet?) supported by the firmware\n"); } - atomic_dec(&cx->capturing); + if (s->type != CX18_ENC_STREAM_TYPE_TS) + atomic_dec(&cx->ana_capturing); + atomic_dec(&cx->tot_capturing); /* Clear capture and no-read bits */ clear_bit(CX18_F_S_STREAMING, &s->s_flags); @@ -545,7 +550,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end) cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle); s->handle = 0xffffffff; - if (atomic_read(&cx->capturing) > 0) + if (atomic_read(&cx->tot_capturing) > 0) return 0; write_reg(5, CX18_DSP0_INTERRUPT_MASK); diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index f24abcd06dea..c4cc2f3b8876 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c @@ -823,7 +823,7 @@ static void cx23885_dev_unregister(struct cx23885_dev *dev) iounmap(dev->lmmio); } -static u32* cx23885_risc_field(u32 *rp, struct scatterlist *sglist, +static __le32* cx23885_risc_field(__le32 *rp, struct scatterlist *sglist, unsigned int offset, u32 sync_line, unsigned int bpl, unsigned int padding, unsigned int lines) @@ -883,7 +883,7 @@ int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, unsigned int padding, unsigned int lines) { u32 instructions, fields; - u32 *rp; + __le32 *rp; int rc; fields = 0; @@ -924,7 +924,7 @@ static int cx23885_risc_databuffer(struct pci_dev *pci, unsigned int lines) { u32 instructions; - u32 *rp; + __le32 *rp; int rc; /* estimate risc mem: worst case is one write per page border + @@ -951,7 +951,7 @@ static int cx23885_risc_databuffer(struct pci_dev *pci, int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, u32 reg, u32 mask, u32 value) { - u32 *rp; + __le32 *rp; int rc; if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0) diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index aeba26dc0a37..fa6d398e97b9 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1493,10 +1493,16 @@ static const struct cx88_board cx88_boards[] = { }, }, [CX88_BOARD_POWERCOLOR_REAL_ANGEL] = { - .name = "PowerColor Real Angel 330", + .name = "PowerColor RA330", /* Long names may confuse LIRC. */ .tuner_type = TUNER_XC2028, .tuner_addr = 0x61, .input = { { + .type = CX88_VMUX_DEBUG, + .vmux = 3, /* Due to the way the cx88 driver is written, */ + .gpio0 = 0x00ff, /* there is no way to deactivate audio pass- */ + .gpio1 = 0xf39d, /* through without this entry. Furthermore, if */ + .gpio3 = 0x0000, /* the TV mux entry is first, you get audio */ + }, { /* from the tuner on boot for a little while. */ .type = CX88_VMUX_TELEVISION, .vmux = 0, .gpio0 = 0x00ff, @@ -2424,8 +2430,9 @@ void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl) switch (core->boardnr) { case CX88_BOARD_POWERCOLOR_REAL_ANGEL: - /* Doesn't work with firmware version 2.7 */ - ctl->fname = "xc3028-v25.fw"; + /* Now works with firmware version 2.7 */ + if (core->i2c_algo.udelay < 16) + core->i2c_algo.udelay = 16; break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: ctl->scode_table = XC3028_FE_ZARLINK456; diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index c4d1aff1fdb4..60eeda3057e9 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -70,7 +70,7 @@ static DEFINE_MUTEX(devlist); /* @lpi: lines per IRQ, or 0 to not generate irqs. Note: IRQ to be generated _after_ lpi lines are transferred. */ -static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist, +static __le32* cx88_risc_field(__le32 *rp, struct scatterlist *sglist, unsigned int offset, u32 sync_line, unsigned int bpl, unsigned int padding, unsigned int lines, unsigned int lpi) @@ -130,7 +130,7 @@ int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, unsigned int bpl, unsigned int padding, unsigned int lines) { u32 instructions,fields; - u32 *rp; + __le32 *rp; int rc; fields = 0; @@ -168,7 +168,7 @@ int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc, unsigned int lines, unsigned int lpi) { u32 instructions; - u32 *rp; + __le32 *rp; int rc; /* estimate risc mem: worst case is one write per page border + @@ -193,7 +193,7 @@ int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc, int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, u32 reg, u32 mask, u32 value) { - u32 *rp; + __le32 *rp; int rc; if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 8996175cc950..fb163ecd9216 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1166,13 +1166,13 @@ static int vidioc_g_register(struct file *file, void *priv, reg->val = ret; } else { - u64 val = 0; + __le64 val = 0; ret = em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS, reg->reg, (char *)&val, 2); if (ret < 0) return ret; - reg->val = cpu_to_le64((__u64)val); + reg->val = le64_to_cpu(val); } return 0; @@ -1183,9 +1183,9 @@ static int vidioc_s_register(struct file *file, void *priv, { struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; - u64 buf; + __le64 buf; - buf = le64_to_cpu((__u64)reg->val); + buf = cpu_to_le64(reg->val); return em28xx_write_regs(dev, reg->reg, (char *)&buf, em28xx_reg_len(reg->reg)); diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index ba06e813c58c..9d23b1efd36d 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h @@ -259,6 +259,12 @@ struct ivtv_mailbox_data { /* Scatter-Gather array element, used in DMA transfers */ struct ivtv_sg_element { + __le32 src; + __le32 dst; + __le32 size; +}; + +struct ivtv_sg_host_element { u32 src; u32 dst; u32 size; @@ -349,8 +355,8 @@ struct ivtv_stream { u16 dma_xfer_cnt; /* Base Dev SG Array for cx23415/6 */ - struct ivtv_sg_element *sg_pending; - struct ivtv_sg_element *sg_processing; + struct ivtv_sg_host_element *sg_pending; + struct ivtv_sg_host_element *sg_processing; struct ivtv_sg_element *sg_dma; dma_addr_t sg_handle; int sg_pending_size; diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index f2fa434b677b..db813e071ce6 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c @@ -587,7 +587,7 @@ retry: since we may get here before the stream has been fully set-up */ if (mode == OUT_YUV && s->q_full.length == 0 && itv->dma_data_req_size) { while (count >= itv->dma_data_req_size) { - if (!ivtv_yuv_udma_stream_frame (itv, (void *)user_buf)) { + if (!ivtv_yuv_udma_stream_frame (itv, (void __user *)user_buf)) { bytes_written += itv->dma_data_req_size; user_buf += itv->dma_data_req_size; count -= itv->dma_data_req_size; diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c index d8ba3a4a8761..fba150a6cd23 100644 --- a/drivers/media/video/ivtv/ivtv-irq.c +++ b/drivers/media/video/ivtv/ivtv-irq.c @@ -231,14 +231,14 @@ static void dma_post(struct ivtv_stream *s) struct ivtv_buffer *buf = NULL; struct list_head *p; u32 offset; - u32 *u32buf; + __le32 *u32buf; int x = 0; IVTV_DEBUG_HI_DMA("%s %s completed (%x)\n", ivtv_use_pio(s) ? "PIO" : "DMA", s->name, s->dma_offset); list_for_each(p, &s->q_dma.list) { buf = list_entry(p, struct ivtv_buffer, list); - u32buf = (u32 *)buf->buf; + u32buf = (__le32 *)buf->buf; /* Sync Buffer */ ivtv_buf_sync_for_cpu(s, buf); @@ -444,7 +444,7 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s) } s->dma_xfer_cnt++; - memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_element) * s->sg_pending_size); + memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_host_element) * s->sg_pending_size); s->sg_processing_size = s->sg_pending_size; s->sg_pending_size = 0; s->sg_processed = 0; @@ -473,7 +473,7 @@ static void ivtv_dma_dec_start(struct ivtv_stream *s) if (s->q_predma.bytesused) ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused); s->dma_xfer_cnt++; - memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_element) * s->sg_pending_size); + memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_host_element) * s->sg_pending_size); s->sg_processing_size = s->sg_pending_size; s->sg_pending_size = 0; s->sg_processed = 0; diff --git a/drivers/media/video/ivtv/ivtv-queue.c b/drivers/media/video/ivtv/ivtv-queue.c index fc8b1eaa333b..71bd13e22e2e 100644 --- a/drivers/media/video/ivtv/ivtv-queue.c +++ b/drivers/media/video/ivtv/ivtv-queue.c @@ -193,7 +193,7 @@ void ivtv_flush_queues(struct ivtv_stream *s) int ivtv_stream_alloc(struct ivtv_stream *s) { struct ivtv *itv = s->itv; - int SGsize = sizeof(struct ivtv_sg_element) * s->buffers; + int SGsize = sizeof(struct ivtv_sg_host_element) * s->buffers; int i; if (s->buffers == 0) diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index c47c2b945147..c854285a4371 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c @@ -44,23 +44,25 @@ #include "ivtv-streams.h" static const struct file_operations ivtv_v4l2_enc_fops = { - .owner = THIS_MODULE, - .read = ivtv_v4l2_read, - .write = ivtv_v4l2_write, - .open = ivtv_v4l2_open, - .ioctl = ivtv_v4l2_ioctl, - .release = ivtv_v4l2_close, - .poll = ivtv_v4l2_enc_poll, + .owner = THIS_MODULE, + .read = ivtv_v4l2_read, + .write = ivtv_v4l2_write, + .open = ivtv_v4l2_open, + .ioctl = ivtv_v4l2_ioctl, + .compat_ioctl = v4l_compat_ioctl32, + .release = ivtv_v4l2_close, + .poll = ivtv_v4l2_enc_poll, }; static const struct file_operations ivtv_v4l2_dec_fops = { - .owner = THIS_MODULE, - .read = ivtv_v4l2_read, - .write = ivtv_v4l2_write, - .open = ivtv_v4l2_open, - .ioctl = ivtv_v4l2_ioctl, - .release = ivtv_v4l2_close, - .poll = ivtv_v4l2_dec_poll, + .owner = THIS_MODULE, + .read = ivtv_v4l2_read, + .write = ivtv_v4l2_write, + .open = ivtv_v4l2_open, + .ioctl = ivtv_v4l2_ioctl, + .compat_ioctl = v4l_compat_ioctl32, + .release = ivtv_v4l2_close, + .poll = ivtv_v4l2_dec_poll, }; #define IVTV_V4L2_DEC_MPG_OFFSET 16 /* offset from 0 to register decoder mpg v4l2 minors on */ diff --git a/drivers/media/video/ivtv/ivtv-version.h b/drivers/media/video/ivtv/ivtv-version.h index 02c5ab071d1b..442f43f11b73 100644 --- a/drivers/media/video/ivtv/ivtv-version.h +++ b/drivers/media/video/ivtv/ivtv-version.h @@ -22,8 +22,8 @@ #define IVTV_DRIVER_NAME "ivtv" #define IVTV_DRIVER_VERSION_MAJOR 1 -#define IVTV_DRIVER_VERSION_MINOR 2 -#define IVTV_DRIVER_VERSION_PATCHLEVEL 1 +#define IVTV_DRIVER_VERSION_MINOR 3 +#define IVTV_DRIVER_VERSION_PATCHLEVEL 0 #define IVTV_VERSION __stringify(IVTV_DRIVER_VERSION_MAJOR) "." __stringify(IVTV_DRIVER_VERSION_MINOR) "." __stringify(IVTV_DRIVER_VERSION_PATCHLEVEL) #define IVTV_DRIVER_VERSION KERNEL_VERSION(IVTV_DRIVER_VERSION_MAJOR,IVTV_DRIVER_VERSION_MINOR,IVTV_DRIVER_VERSION_PATCHLEVEL) diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c index a9417f6e4087..3092ff1d00a0 100644 --- a/drivers/media/video/ivtv/ivtv-yuv.c +++ b/drivers/media/video/ivtv/ivtv-yuv.c @@ -1116,7 +1116,7 @@ void ivtv_yuv_setup_stream_frame(struct ivtv *itv) } /* Attempt to dma a frame from a user buffer */ -int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void *src) +int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src) { struct yuv_playback_info *yi = &itv->yuv_info; struct ivtv_dma_frame dma_args; diff --git a/drivers/media/video/ivtv/ivtv-yuv.h b/drivers/media/video/ivtv/ivtv-yuv.h index 2fe5f1250762..ca5173fbf006 100644 --- a/drivers/media/video/ivtv/ivtv-yuv.h +++ b/drivers/media/video/ivtv/ivtv-yuv.h @@ -35,7 +35,7 @@ extern const u32 yuv_offset[IVTV_YUV_BUFFERS]; int ivtv_yuv_filter_check(struct ivtv *itv); void ivtv_yuv_setup_stream_frame(struct ivtv *itv); -int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void *src); +int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src); void ivtv_yuv_frame_complete(struct ivtv *itv); int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args); void ivtv_yuv_close(struct ivtv *itv); diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index 1314522a8130..81431ee41842 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -163,8 +163,7 @@ ts_mmap(struct file *file, struct vm_area_struct * vma) static int empress_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct saa7134_fh *fh = priv; - struct saa7134_dev *dev = fh->dev; + struct saa7134_dev *dev = file->private_data; strcpy(cap->driver, "saa7134"); strlcpy(cap->card, saa7134_boards[dev->board].name, diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index a0f7bc1edaa2..0d12ace61665 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -536,7 +536,7 @@ static void set_addr(struct i2c_client *c, struct tuner_setup *tun_setup) static inline int check_mode(struct tuner *t, char *cmd) { if ((1 << t->mode & t->mode_mask) == 0) { - return EINVAL; + return -EINVAL; } switch (t->mode) { @@ -730,11 +730,11 @@ static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, t->mode = mode; - if (check_mode(t, cmd) == EINVAL) { + if (check_mode(t, cmd) == -EINVAL) { t->mode = T_STANDBY; if (analog_ops->standby) analog_ops->standby(&t->fe); - return EINVAL; + return -EINVAL; } return 0; } @@ -776,13 +776,13 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) break; case AUDC_SET_RADIO: if (set_mode(client, t, V4L2_TUNER_RADIO, "AUDC_SET_RADIO") - == EINVAL) + == -EINVAL) return 0; if (t->radio_freq) set_freq(client, t->radio_freq); break; case TUNER_SET_STANDBY: - if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL) + if (check_mode(t, "TUNER_SET_STANDBY") == -EINVAL) return 0; t->mode = T_STANDBY; if (analog_ops->standby) @@ -790,9 +790,9 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) break; #ifdef CONFIG_VIDEO_ALLOW_V4L1 case VIDIOCSAUDIO: - if (check_mode(t, "VIDIOCSAUDIO") == EINVAL) + if (check_mode(t, "VIDIOCSAUDIO") == -EINVAL) return 0; - if (check_v4l2(t) == EINVAL) + if (check_v4l2(t) == -EINVAL) return 0; /* Should be implemented, since bttv calls it */ @@ -810,10 +810,10 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) }; struct video_channel *vc = arg; - if (check_v4l2(t) == EINVAL) + if (check_v4l2(t) == -EINVAL) return 0; - if (set_mode(client,t,V4L2_TUNER_ANALOG_TV, "VIDIOCSCHAN")==EINVAL) + if (set_mode(client,t,V4L2_TUNER_ANALOG_TV, "VIDIOCSCHAN")==-EINVAL) return 0; if (vc->norm < ARRAY_SIZE(map)) @@ -827,9 +827,9 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) { unsigned long *v = arg; - if (check_mode(t, "VIDIOCSFREQ") == EINVAL) + if (check_mode(t, "VIDIOCSFREQ") == -EINVAL) return 0; - if (check_v4l2(t) == EINVAL) + if (check_v4l2(t) == -EINVAL) return 0; set_freq(client, *v); @@ -839,9 +839,9 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct video_tuner *vt = arg; - if (check_mode(t, "VIDIOCGTUNER") == EINVAL) + if (check_mode(t, "VIDIOCGTUNER") == -EINVAL) return 0; - if (check_v4l2(t) == EINVAL) + if (check_v4l2(t) == -EINVAL) return 0; if (V4L2_TUNER_RADIO == t->mode) { @@ -883,9 +883,9 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct video_audio *va = arg; - if (check_mode(t, "VIDIOCGAUDIO") == EINVAL) + if (check_mode(t, "VIDIOCGAUDIO") == -EINVAL) return 0; - if (check_v4l2(t) == EINVAL) + if (check_v4l2(t) == -EINVAL) return 0; if (V4L2_TUNER_RADIO == t->mode) { @@ -925,7 +925,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) v4l2_std_id *id = arg; if (set_mode (client, t, V4L2_TUNER_ANALOG_TV, "VIDIOC_S_STD") - == EINVAL) + == -EINVAL) return 0; switch_v4l2(); @@ -941,7 +941,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) struct v4l2_frequency *f = arg; if (set_mode (client, t, f->type, "VIDIOC_S_FREQUENCY") - == EINVAL) + == -EINVAL) return 0; switch_v4l2(); set_freq(client,f->frequency); @@ -952,7 +952,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct v4l2_frequency *f = arg; - if (check_mode(t, "VIDIOC_G_FREQUENCY") == EINVAL) + if (check_mode(t, "VIDIOC_G_FREQUENCY") == -EINVAL) return 0; switch_v4l2(); f->type = t->mode; @@ -973,7 +973,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct v4l2_tuner *tuner = arg; - if (check_mode(t, "VIDIOC_G_TUNER") == EINVAL) + if (check_mode(t, "VIDIOC_G_TUNER") == -EINVAL) return 0; switch_v4l2(); @@ -1020,7 +1020,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct v4l2_tuner *tuner = arg; - if (check_mode(t, "VIDIOC_S_TUNER") == EINVAL) + if (check_mode(t, "VIDIOC_S_TUNER") == -EINVAL) return 0; switch_v4l2(); diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c index 32e536edf09d..3d26a30abe1e 100644 --- a/drivers/media/video/usbvideo/quickcam_messenger.c +++ b/drivers/media/video/usbvideo/quickcam_messenger.c @@ -210,7 +210,7 @@ static int qcm_stv_setb(struct usb_device *dev, u16 reg, u8 val) return ret; } -static int qcm_stv_setw(struct usb_device *dev, u16 reg, u16 val) +static int qcm_stv_setw(struct usb_device *dev, u16 reg, __le16 val) { int ret; diff --git a/drivers/media/video/zoran.h b/drivers/media/video/zoran.h index 81cc3b00a079..46b7ad477ceb 100644 --- a/drivers/media/video/zoran.h +++ b/drivers/media/video/zoran.h @@ -285,7 +285,7 @@ struct zoran_mapping { struct zoran_jpg_buffer { struct zoran_mapping *map; - u32 *frag_tab; /* addresses of frag table */ + __le32 *frag_tab; /* addresses of frag table */ u32 frag_tab_bus; /* same value cached to save time in ISR */ enum zoran_buffer_state state; /* non-zero if corresponding buffer is in use in grab queue */ struct zoran_sync bs; /* DONE: info to return to application */ @@ -450,7 +450,7 @@ struct zoran { unsigned long jpg_queued_num; /* count of frames queued since grab/play started */ /* zr36057's code buffer table */ - u32 *stat_com; /* stat_com[i] is indexed by dma_head/tail & BUZ_MASK_STAT_COM */ + __le32 *stat_com; /* stat_com[i] is indexed by dma_head/tail & BUZ_MASK_STAT_COM */ /* (value & BUZ_MASK_FRAME) corresponds to index in pend[] queue */ int jpg_pend[BUZ_MAX_FRAME]; diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c index 37629ffd34c3..88d369708e4c 100644 --- a/drivers/media/video/zoran_device.c +++ b/drivers/media/video/zoran_device.c @@ -1320,7 +1320,7 @@ error_handler (struct zoran *zr, if (i) { /* Rotate stat_comm entries to make current entry first */ int j; - u32 bus_addr[BUZ_NUM_STAT_COM]; + __le32 bus_addr[BUZ_NUM_STAT_COM]; /* Here we are copying the stat_com array, which * is already in little endian format, so diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index 345c77e46837..5394d7a5cfee 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c @@ -495,7 +495,7 @@ jpg_fbuffer_alloc (struct file *file) jpg_fbuffer_free(file); return -ENOBUFS; } - fh->jpg_buffers.buffer[i].frag_tab = (u32 *) mem; + fh->jpg_buffers.buffer[i].frag_tab = (__le32 *) mem; fh->jpg_buffers.buffer[i].frag_tab_bus = virt_to_bus((void *) mem); @@ -1167,7 +1167,7 @@ zoran_close_end_session (struct file *file) /* v4l capture */ if (fh->v4l_buffers.active != ZORAN_FREE) { - long flags; + unsigned long flags; spin_lock_irqsave(&zr->spinlock, flags); zr36057_set_memgrab(zr, 0); @@ -3436,7 +3436,7 @@ zoran_do_ioctl (struct inode *inode, /* unload capture */ if (zr->v4l_memgrab_active) { - long flags; + unsigned long flags; spin_lock_irqsave(&zr->spinlock, flags); zr36057_set_memgrab(zr, 0); @@ -4375,7 +4375,7 @@ zoran_vm_close (struct vm_area_struct *vma) mutex_lock(&zr->resource_lock); if (fh->v4l_buffers.active != ZORAN_FREE) { - long flags; + unsigned long flags; spin_lock_irqsave(&zr->spinlock, flags); zr36057_set_memgrab(zr, 0); @@ -4506,7 +4506,7 @@ zoran_mmap (struct file *file, if (todo > fraglen) todo = fraglen; pos = - le32_to_cpu((unsigned long) fh->jpg_buffers. + le32_to_cpu(fh->jpg_buffers. buffer[i].frag_tab[2 * j]); /* should just be pos on i386 */ page = virt_to_phys(bus_to_virt(pos)) diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index 3cdd4e962115..1e24ab4ac38c 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -1238,8 +1238,6 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) sh->max_id = ioc->pfacts->MaxDevices; sh->max_lun = max_lun; - sh->this_id = ioc->pfacts[0].PortSCSIID; - /* Required entry. */ sh->unique_id = ioc->id; diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 468480771f13..4d492ba232b0 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -3193,8 +3193,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) sh->transportt = mptsas_transport_template; - sh->this_id = ioc->pfacts[0].PortSCSIID; - /* Required entry. */ sh->unique_id = ioc->id; diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index b109bd8a4d19..c68ef00c2f92 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -2451,12 +2451,6 @@ mptscsih_slave_configure(struct scsi_device *sdev) ioc->name, sdev->sdtr, sdev->wdtr, sdev->ppr, sdev->inquiry_len)); - if (sdev->id > sh->max_id) { - /* error case, should never happen */ - scsi_adjust_queue_depth(sdev, 0, 1); - goto slave_configure_exit; - } - vdevice->configured_lun = 1; mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH); @@ -2470,8 +2464,6 @@ mptscsih_slave_configure(struct scsi_device *sdev) ioc->name, vtarget->negoFlags, vtarget->maxOffset, vtarget->minSyncFactor)); -slave_configure_exit: - dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "tagged %d, simple %d, ordered %d\n", ioc->name,sdev->tagged_supported, sdev->simple_tags, diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c index e2e7c05a147b..6d14e8fe1537 100644 --- a/drivers/misc/fujitsu-laptop.c +++ b/drivers/misc/fujitsu-laptop.c @@ -352,3 +352,9 @@ MODULE_AUTHOR("Jonathan Woithe"); MODULE_DESCRIPTION("Fujitsu laptop extras support"); MODULE_VERSION(FUJITSU_DRIVER_VERSION); MODULE_LICENSE("GPL"); + +static struct pnp_device_id pnp_ids[] = { + { .id = "FUJ02bf" }, + { .id = "" } +}; +MODULE_DEVICE_TABLE(pnp, pnp_ids); diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c index fa394104339c..e4ff50b95a5e 100644 --- a/drivers/misc/kgdbts.c +++ b/drivers/misc/kgdbts.c @@ -102,7 +102,6 @@ #include <linux/nmi.h> #include <linux/delay.h> #include <linux/kthread.h> -#include <linux/delay.h> #define v1printk(a...) do { \ if (verbose) \ @@ -119,7 +118,6 @@ } while (0) #define MAX_CONFIG_LEN 40 -static const char hexchars[] = "0123456789abcdef"; static struct kgdb_io kgdbts_io_ops; static char get_buf[BUFMAX]; static int get_buf_cnt; @@ -131,6 +129,8 @@ static int repeat_test; static int test_complete; static int send_ack; static int final_ack; +static int force_hwbrks; +static int hwbreaks_ok; static int hw_break_val; static int hw_break_val2; #if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || defined(CONFIG_SPARC) @@ -234,12 +234,12 @@ static void break_helper(char *bp_type, char *arg, unsigned long vaddr) static void sw_break(char *arg) { - break_helper("Z0", arg, 0); + break_helper(force_hwbrks ? "Z1" : "Z0", arg, 0); } static void sw_rem_break(char *arg) { - break_helper("z0", arg, 0); + break_helper(force_hwbrks ? "z1" : "z0", arg, 0); } static void hw_break(char *arg) @@ -619,8 +619,8 @@ static void fill_get_buf(char *buf) count++; } strcat(get_buf, "#"); - get_buf[count + 2] = hexchars[checksum >> 4]; - get_buf[count + 3] = hexchars[checksum & 0xf]; + get_buf[count + 2] = hex_asc_hi(checksum); + get_buf[count + 3] = hex_asc_lo(checksum); get_buf[count + 4] = '\0'; v2printk("get%i: %s\n", ts.idx, get_buf); } @@ -781,6 +781,8 @@ static void run_breakpoint_test(int is_hw_breakpoint) return; eprintk("kgdbts: ERROR %s test failed\n", ts.name); + if (is_hw_breakpoint) + hwbreaks_ok = 0; } static void run_hw_break_test(int is_write_test) @@ -798,9 +800,11 @@ static void run_hw_break_test(int is_write_test) kgdb_breakpoint(); hw_break_val_access(); if (is_write_test) { - if (test_complete == 2) + if (test_complete == 2) { eprintk("kgdbts: ERROR %s broke on access\n", ts.name); + hwbreaks_ok = 0; + } hw_break_val_write(); } kgdb_breakpoint(); @@ -809,6 +813,7 @@ static void run_hw_break_test(int is_write_test) return; eprintk("kgdbts: ERROR %s test failed\n", ts.name); + hwbreaks_ok = 0; } static void run_nmi_sleep_test(int nmi_sleep) @@ -912,6 +917,7 @@ static void kgdbts_run_tests(void) /* All HW break point tests */ if (arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT) { + hwbreaks_ok = 1; v1printk("kgdbts:RUN hw breakpoint test\n"); run_breakpoint_test(1); v1printk("kgdbts:RUN hw write breakpoint test\n"); @@ -925,6 +931,19 @@ static void kgdbts_run_tests(void) run_nmi_sleep_test(nmi_sleep); } +#ifdef CONFIG_DEBUG_RODATA + /* Until there is an api to write to read-only text segments, use + * HW breakpoints for the remainder of any tests, else print a + * failure message if hw breakpoints do not work. + */ + if (!(arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT && hwbreaks_ok)) { + eprintk("kgdbts: HW breakpoints do not work," + "skipping remaining tests\n"); + return; + } + force_hwbrks = 1; +#endif /* CONFIG_DEBUG_RODATA */ + /* If the do_fork test is run it will be the last test that is * executed because a kernel thread will be spawned at the very * end to unregister the debug hooks. diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 3f28f6eabdbf..b5969298f3d3 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -1293,7 +1293,7 @@ static void tpacpi_input_send_radiosw(void) mutex_lock(&tpacpi_inputdev_send_mutex); input_report_switch(tpacpi_inputdev, - SW_RADIO, !!wlsw); + SW_RFKILL_ALL, !!wlsw); input_sync(tpacpi_inputdev); mutex_unlock(&tpacpi_inputdev_send_mutex); @@ -1921,6 +1921,29 @@ static struct attribute *hotkey_mask_attributes[] __initdata = { &dev_attr_hotkey_wakeup_hotunplug_complete.attr, }; +static void hotkey_exit(void) +{ +#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL + hotkey_poll_stop_sync(); +#endif + + if (hotkey_dev_attributes) + delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj); + + kfree(hotkey_keycode_map); + + if (tp_features.hotkey) { + dbg_printk(TPACPI_DBG_EXIT, + "restoring original hot key mask\n"); + /* no short-circuit boolean operator below! */ + if ((hotkey_mask_set(hotkey_orig_mask) | + hotkey_status_set(hotkey_orig_status)) != 0) + printk(TPACPI_ERR + "failed to restore hot key mask " + "to BIOS defaults\n"); + } +} + static int __init hotkey_init(struct ibm_init_struct *iibm) { /* Requirements for changing the default keymaps: @@ -2060,226 +2083,220 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) vdbg_printk(TPACPI_DBG_INIT, "hotkeys are %s\n", str_supported(tp_features.hotkey)); - if (tp_features.hotkey) { - hotkey_dev_attributes = create_attr_set(13, NULL); - if (!hotkey_dev_attributes) - return -ENOMEM; - res = add_many_to_attr_set(hotkey_dev_attributes, - hotkey_attributes, - ARRAY_SIZE(hotkey_attributes)); - if (res) - return res; + if (!tp_features.hotkey) + return 1; - /* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p, - A30, R30, R31, T20-22, X20-21, X22-24. Detected by checking - for HKEY interface version 0x100 */ - if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) { - if ((hkeyv >> 8) != 1) { - printk(TPACPI_ERR "unknown version of the " - "HKEY interface: 0x%x\n", hkeyv); - printk(TPACPI_ERR "please report this to %s\n", - TPACPI_MAIL); - } else { - /* - * MHKV 0x100 in A31, R40, R40e, - * T4x, X31, and later - */ - tp_features.hotkey_mask = 1; - } + hotkey_dev_attributes = create_attr_set(13, NULL); + if (!hotkey_dev_attributes) + return -ENOMEM; + res = add_many_to_attr_set(hotkey_dev_attributes, + hotkey_attributes, + ARRAY_SIZE(hotkey_attributes)); + if (res) + goto err_exit; + + /* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p, + A30, R30, R31, T20-22, X20-21, X22-24. Detected by checking + for HKEY interface version 0x100 */ + if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) { + if ((hkeyv >> 8) != 1) { + printk(TPACPI_ERR "unknown version of the " + "HKEY interface: 0x%x\n", hkeyv); + printk(TPACPI_ERR "please report this to %s\n", + TPACPI_MAIL); + } else { + /* + * MHKV 0x100 in A31, R40, R40e, + * T4x, X31, and later + */ + tp_features.hotkey_mask = 1; } + } - vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n", - str_supported(tp_features.hotkey_mask)); + vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n", + str_supported(tp_features.hotkey_mask)); - if (tp_features.hotkey_mask) { - if (!acpi_evalf(hkey_handle, &hotkey_all_mask, - "MHKA", "qd")) { - printk(TPACPI_ERR - "missing MHKA handler, " - "please report this to %s\n", - TPACPI_MAIL); - /* FN+F12, FN+F4, FN+F3 */ - hotkey_all_mask = 0x080cU; - } + if (tp_features.hotkey_mask) { + if (!acpi_evalf(hkey_handle, &hotkey_all_mask, + "MHKA", "qd")) { + printk(TPACPI_ERR + "missing MHKA handler, " + "please report this to %s\n", + TPACPI_MAIL); + /* FN+F12, FN+F4, FN+F3 */ + hotkey_all_mask = 0x080cU; } + } - /* hotkey_source_mask *must* be zero for - * the first hotkey_mask_get */ - res = hotkey_status_get(&hotkey_orig_status); - if (!res && tp_features.hotkey_mask) { - res = hotkey_mask_get(); - hotkey_orig_mask = hotkey_mask; - if (!res) { - res = add_many_to_attr_set( - hotkey_dev_attributes, - hotkey_mask_attributes, - ARRAY_SIZE(hotkey_mask_attributes)); - } - } + /* hotkey_source_mask *must* be zero for + * the first hotkey_mask_get */ + res = hotkey_status_get(&hotkey_orig_status); + if (res) + goto err_exit; + + if (tp_features.hotkey_mask) { + res = hotkey_mask_get(); + if (res) + goto err_exit; + + hotkey_orig_mask = hotkey_mask; + res = add_many_to_attr_set( + hotkey_dev_attributes, + hotkey_mask_attributes, + ARRAY_SIZE(hotkey_mask_attributes)); + if (res) + goto err_exit; + } #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL - if (tp_features.hotkey_mask) { - hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK - & ~hotkey_all_mask; - } else { - hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK; - } + if (tp_features.hotkey_mask) { + hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK + & ~hotkey_all_mask; + } else { + hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK; + } - vdbg_printk(TPACPI_DBG_INIT, - "hotkey source mask 0x%08x, polling freq %d\n", - hotkey_source_mask, hotkey_poll_freq); + vdbg_printk(TPACPI_DBG_INIT, + "hotkey source mask 0x%08x, polling freq %d\n", + hotkey_source_mask, hotkey_poll_freq); #endif - /* Not all thinkpads have a hardware radio switch */ - if (!res && acpi_evalf(hkey_handle, &status, "WLSW", "qd")) { - tp_features.hotkey_wlsw = 1; - printk(TPACPI_INFO - "radio switch found; radios are %s\n", - enabled(status, 0)); - res = add_to_attr_set(hotkey_dev_attributes, - &dev_attr_hotkey_radio_sw.attr); - } + /* Not all thinkpads have a hardware radio switch */ + if (acpi_evalf(hkey_handle, &status, "WLSW", "qd")) { + tp_features.hotkey_wlsw = 1; + printk(TPACPI_INFO + "radio switch found; radios are %s\n", + enabled(status, 0)); + res = add_to_attr_set(hotkey_dev_attributes, + &dev_attr_hotkey_radio_sw.attr); + } - /* For X41t, X60t, X61t Tablets... */ - if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) { - tp_features.hotkey_tablet = 1; - printk(TPACPI_INFO - "possible tablet mode switch found; " - "ThinkPad in %s mode\n", - (status & TP_HOTKEY_TABLET_MASK)? - "tablet" : "laptop"); - res = add_to_attr_set(hotkey_dev_attributes, - &dev_attr_hotkey_tablet_mode.attr); - } + /* For X41t, X60t, X61t Tablets... */ + if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) { + tp_features.hotkey_tablet = 1; + printk(TPACPI_INFO + "possible tablet mode switch found; " + "ThinkPad in %s mode\n", + (status & TP_HOTKEY_TABLET_MASK)? + "tablet" : "laptop"); + res = add_to_attr_set(hotkey_dev_attributes, + &dev_attr_hotkey_tablet_mode.attr); + } - if (!res) - res = register_attr_set_with_sysfs( - hotkey_dev_attributes, - &tpacpi_pdev->dev.kobj); - if (res) - return res; + if (!res) + res = register_attr_set_with_sysfs( + hotkey_dev_attributes, + &tpacpi_pdev->dev.kobj); + if (res) + goto err_exit; - /* Set up key map */ + /* Set up key map */ - hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE, - GFP_KERNEL); - if (!hotkey_keycode_map) { - printk(TPACPI_ERR - "failed to allocate memory for key map\n"); - return -ENOMEM; - } + hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE, + GFP_KERNEL); + if (!hotkey_keycode_map) { + printk(TPACPI_ERR + "failed to allocate memory for key map\n"); + res = -ENOMEM; + goto err_exit; + } - if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) { - dbg_printk(TPACPI_DBG_INIT, - "using Lenovo default hot key map\n"); - memcpy(hotkey_keycode_map, &lenovo_keycode_map, - TPACPI_HOTKEY_MAP_SIZE); + if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) { + dbg_printk(TPACPI_DBG_INIT, + "using Lenovo default hot key map\n"); + memcpy(hotkey_keycode_map, &lenovo_keycode_map, + TPACPI_HOTKEY_MAP_SIZE); + } else { + dbg_printk(TPACPI_DBG_INIT, + "using IBM default hot key map\n"); + memcpy(hotkey_keycode_map, &ibm_keycode_map, + TPACPI_HOTKEY_MAP_SIZE); + } + + set_bit(EV_KEY, tpacpi_inputdev->evbit); + set_bit(EV_MSC, tpacpi_inputdev->evbit); + set_bit(MSC_SCAN, tpacpi_inputdev->mscbit); + tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE; + tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN; + tpacpi_inputdev->keycode = hotkey_keycode_map; + for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) { + if (hotkey_keycode_map[i] != KEY_RESERVED) { + set_bit(hotkey_keycode_map[i], + tpacpi_inputdev->keybit); } else { - dbg_printk(TPACPI_DBG_INIT, - "using IBM default hot key map\n"); - memcpy(hotkey_keycode_map, &ibm_keycode_map, - TPACPI_HOTKEY_MAP_SIZE); - } - - set_bit(EV_KEY, tpacpi_inputdev->evbit); - set_bit(EV_MSC, tpacpi_inputdev->evbit); - set_bit(MSC_SCAN, tpacpi_inputdev->mscbit); - tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE; - tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN; - tpacpi_inputdev->keycode = hotkey_keycode_map; - for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) { - if (hotkey_keycode_map[i] != KEY_RESERVED) { - set_bit(hotkey_keycode_map[i], - tpacpi_inputdev->keybit); - } else { - if (i < sizeof(hotkey_reserved_mask)*8) - hotkey_reserved_mask |= 1 << i; - } - } - - if (tp_features.hotkey_wlsw) { - set_bit(EV_SW, tpacpi_inputdev->evbit); - set_bit(SW_RADIO, tpacpi_inputdev->swbit); - } - if (tp_features.hotkey_tablet) { - set_bit(EV_SW, tpacpi_inputdev->evbit); - set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit); + if (i < sizeof(hotkey_reserved_mask)*8) + hotkey_reserved_mask |= 1 << i; } + } - /* Do not issue duplicate brightness change events to - * userspace */ - if (!tp_features.bright_acpimode) - /* update bright_acpimode... */ - tpacpi_check_std_acpi_brightness_support(); - - if (tp_features.bright_acpimode) { - printk(TPACPI_INFO - "This ThinkPad has standard ACPI backlight " - "brightness control, supported by the ACPI " - "video driver\n"); - printk(TPACPI_NOTICE - "Disabling thinkpad-acpi brightness events " - "by default...\n"); - - /* The hotkey_reserved_mask change below is not - * necessary while the keys are at KEY_RESERVED in the - * default map, but better safe than sorry, leave it - * here as a marker of what we have to do, especially - * when we finally become able to set this at runtime - * on response to X.org requests */ - hotkey_reserved_mask |= - (1 << TP_ACPI_HOTKEYSCAN_FNHOME) - | (1 << TP_ACPI_HOTKEYSCAN_FNEND); - } + if (tp_features.hotkey_wlsw) { + set_bit(EV_SW, tpacpi_inputdev->evbit); + set_bit(SW_RFKILL_ALL, tpacpi_inputdev->swbit); + } + if (tp_features.hotkey_tablet) { + set_bit(EV_SW, tpacpi_inputdev->evbit); + set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit); + } - dbg_printk(TPACPI_DBG_INIT, - "enabling hot key handling\n"); - res = hotkey_status_set(1); - if (res) - return res; - res = hotkey_mask_set(((hotkey_all_mask | hotkey_source_mask) - & ~hotkey_reserved_mask) - | hotkey_orig_mask); - if (res < 0 && res != -ENXIO) - return res; + /* Do not issue duplicate brightness change events to + * userspace */ + if (!tp_features.bright_acpimode) + /* update bright_acpimode... */ + tpacpi_check_std_acpi_brightness_support(); - dbg_printk(TPACPI_DBG_INIT, - "legacy hot key reporting over procfs %s\n", - (hotkey_report_mode < 2) ? - "enabled" : "disabled"); + if (tp_features.bright_acpimode) { + printk(TPACPI_INFO + "This ThinkPad has standard ACPI backlight " + "brightness control, supported by the ACPI " + "video driver\n"); + printk(TPACPI_NOTICE + "Disabling thinkpad-acpi brightness events " + "by default...\n"); + + /* The hotkey_reserved_mask change below is not + * necessary while the keys are at KEY_RESERVED in the + * default map, but better safe than sorry, leave it + * here as a marker of what we have to do, especially + * when we finally become able to set this at runtime + * on response to X.org requests */ + hotkey_reserved_mask |= + (1 << TP_ACPI_HOTKEYSCAN_FNHOME) + | (1 << TP_ACPI_HOTKEYSCAN_FNEND); + } + + dbg_printk(TPACPI_DBG_INIT, "enabling hot key handling\n"); + res = hotkey_status_set(1); + if (res) { + hotkey_exit(); + return res; + } + res = hotkey_mask_set(((hotkey_all_mask | hotkey_source_mask) + & ~hotkey_reserved_mask) + | hotkey_orig_mask); + if (res < 0 && res != -ENXIO) { + hotkey_exit(); + return res; + } - tpacpi_inputdev->open = &hotkey_inputdev_open; - tpacpi_inputdev->close = &hotkey_inputdev_close; + dbg_printk(TPACPI_DBG_INIT, + "legacy hot key reporting over procfs %s\n", + (hotkey_report_mode < 2) ? + "enabled" : "disabled"); - hotkey_poll_setup_safe(1); - tpacpi_input_send_radiosw(); - tpacpi_input_send_tabletsw(); - } + tpacpi_inputdev->open = &hotkey_inputdev_open; + tpacpi_inputdev->close = &hotkey_inputdev_close; - return (tp_features.hotkey)? 0 : 1; -} + hotkey_poll_setup_safe(1); + tpacpi_input_send_radiosw(); + tpacpi_input_send_tabletsw(); -static void hotkey_exit(void) -{ -#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL - hotkey_poll_stop_sync(); -#endif + return 0; - if (tp_features.hotkey) { - dbg_printk(TPACPI_DBG_EXIT, - "restoring original hot key mask\n"); - /* no short-circuit boolean operator below! */ - if ((hotkey_mask_set(hotkey_orig_mask) | - hotkey_status_set(hotkey_orig_status)) != 0) - printk(TPACPI_ERR - "failed to restore hot key mask " - "to BIOS defaults\n"); - } +err_exit: + delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj); + hotkey_dev_attributes = NULL; - if (hotkey_dev_attributes) { - delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj); - hotkey_dev_attributes = NULL; - } + return (res < 0)? res : 1; } static void hotkey_notify(struct ibm_struct *ibm, u32 event) @@ -3319,7 +3336,7 @@ static struct tpacpi_led_classdev tpacpi_led_thinklight = { static int __init light_init(struct ibm_init_struct *iibm) { - int rc = 0; + int rc; vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n"); @@ -3337,20 +3354,23 @@ static int __init light_init(struct ibm_init_struct *iibm) tp_features.light_status = acpi_evalf(ec_handle, NULL, "KBLT", "qv"); - vdbg_printk(TPACPI_DBG_INIT, "light is %s\n", - str_supported(tp_features.light)); + vdbg_printk(TPACPI_DBG_INIT, "light is %s, light status is %s\n", + str_supported(tp_features.light), + str_supported(tp_features.light_status)); - if (tp_features.light) { - rc = led_classdev_register(&tpacpi_pdev->dev, - &tpacpi_led_thinklight.led_classdev); - } + if (!tp_features.light) + return 1; + + rc = led_classdev_register(&tpacpi_pdev->dev, + &tpacpi_led_thinklight.led_classdev); if (rc < 0) { tp_features.light = 0; tp_features.light_status = 0; - } else { - rc = (tp_features.light)? 0 : 1; + } else { + rc = 0; } + return rc; } @@ -3821,7 +3841,7 @@ TPACPI_HANDLE(led, ec, "SLED", /* 570 */ #define TPACPI_LED_NUMLEDS 8 static struct tpacpi_led_classdev *tpacpi_leds; static enum led_status_t tpacpi_led_state_cache[TPACPI_LED_NUMLEDS]; -static const char const *tpacpi_led_names[TPACPI_LED_NUMLEDS] = { +static const char * const tpacpi_led_names[TPACPI_LED_NUMLEDS] = { /* there's a limit of 19 chars + NULL before 2.6.26 */ "tpacpi::power", "tpacpi:orange:batt", @@ -3833,7 +3853,7 @@ static const char const *tpacpi_led_names[TPACPI_LED_NUMLEDS] = { "tpacpi::standby", }; -static int led_get_status(unsigned int led) +static int led_get_status(const unsigned int led) { int status; enum led_status_t led_s; @@ -3857,41 +3877,42 @@ static int led_get_status(unsigned int led) /* not reached */ } -static int led_set_status(unsigned int led, enum led_status_t ledstatus) +static int led_set_status(const unsigned int led, + const enum led_status_t ledstatus) { /* off, on, blink. Index is led_status_t */ - static const int const led_sled_arg1[] = { 0, 1, 3 }; - static const int const led_exp_hlbl[] = { 0, 0, 1 }; /* led# * */ - static const int const led_exp_hlcl[] = { 0, 1, 1 }; /* led# * */ - static const int const led_led_arg1[] = { 0, 0x80, 0xc0 }; + static const unsigned int led_sled_arg1[] = { 0, 1, 3 }; + static const unsigned int led_led_arg1[] = { 0, 0x80, 0xc0 }; int rc = 0; switch (led_supported) { case TPACPI_LED_570: - /* 570 */ - led = 1 << led; - if (!acpi_evalf(led_handle, NULL, NULL, "vdd", - led, led_sled_arg1[ledstatus])) - rc = -EIO; - break; + /* 570 */ + if (led > 7) + return -EINVAL; + if (!acpi_evalf(led_handle, NULL, NULL, "vdd", + (1 << led), led_sled_arg1[ledstatus])) + rc = -EIO; + break; case TPACPI_LED_OLD: - /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */ - led = 1 << led; - rc = ec_write(TPACPI_LED_EC_HLMS, led); - if (rc >= 0) - rc = ec_write(TPACPI_LED_EC_HLBL, - led * led_exp_hlbl[ledstatus]); - if (rc >= 0) - rc = ec_write(TPACPI_LED_EC_HLCL, - led * led_exp_hlcl[ledstatus]); - break; + /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */ + if (led > 7) + return -EINVAL; + rc = ec_write(TPACPI_LED_EC_HLMS, (1 << led)); + if (rc >= 0) + rc = ec_write(TPACPI_LED_EC_HLBL, + (ledstatus == TPACPI_LED_BLINK) << led); + if (rc >= 0) + rc = ec_write(TPACPI_LED_EC_HLCL, + (ledstatus != TPACPI_LED_OFF) << led); + break; case TPACPI_LED_NEW: - /* all others */ - if (!acpi_evalf(led_handle, NULL, NULL, "vdd", - led, led_led_arg1[ledstatus])) - rc = -EIO; - break; + /* all others */ + if (!acpi_evalf(led_handle, NULL, NULL, "vdd", + led, led_led_arg1[ledstatus])) + rc = -EIO; + break; default: rc = -ENXIO; } @@ -3978,7 +3999,6 @@ static void led_exit(void) } kfree(tpacpi_leds); - tpacpi_leds = NULL; } static int __init led_init(struct ibm_init_struct *iibm) @@ -4802,7 +4822,6 @@ static void brightness_exit(void) vdbg_printk(TPACPI_DBG_EXIT, "calling backlight_device_unregister()\n"); backlight_device_unregister(ibm_backlight_device); - ibm_backlight_device = NULL; } } @@ -5764,11 +5783,16 @@ static int __init fan_init(struct ibm_init_struct *iibm) fan_control_access_mode != TPACPI_FAN_WR_NONE) { rc = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj, &fan_attr_group); - if (!(rc < 0)) - rc = driver_create_file(&tpacpi_hwmon_pdriver.driver, - &driver_attr_fan_watchdog); if (rc < 0) return rc; + + rc = driver_create_file(&tpacpi_hwmon_pdriver.driver, + &driver_attr_fan_watchdog); + if (rc < 0) { + sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj, + &fan_attr_group); + return rc; + } return 0; } else return 1; diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 91ded3e82401..f9ad960d7c1a 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -46,7 +46,7 @@ #define MMC_SHIFT 3 #define MMC_NUM_MINORS (256 >> MMC_SHIFT) -static unsigned long dev_use[MMC_NUM_MINORS/(8*sizeof(unsigned long))]; +static DECLARE_BITMAP(dev_use, MMC_NUM_MINORS); /* * There is one mmc_blk_data per slot. diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c index be624a049c67..c303e7f57ab4 100644 --- a/drivers/mmc/host/wbsd.c +++ b/drivers/mmc/host/wbsd.c @@ -1457,17 +1457,7 @@ static int __devinit wbsd_request_irq(struct wbsd_host *host, int irq) int ret; /* - * Allocate interrupt. - */ - - ret = request_irq(irq, wbsd_irq, IRQF_SHARED, DRIVER_NAME, host); - if (ret) - return ret; - - host->irq = irq; - - /* - * Set up tasklets. + * Set up tasklets. Must be done before requesting interrupt. */ tasklet_init(&host->card_tasklet, wbsd_tasklet_card, (unsigned long)host); @@ -1480,6 +1470,15 @@ static int __devinit wbsd_request_irq(struct wbsd_host *host, int irq) tasklet_init(&host->finish_tasklet, wbsd_tasklet_finish, (unsigned long)host); + /* + * Allocate interrupt. + */ + ret = request_irq(irq, wbsd_irq, IRQF_SHARED, DRIVER_NAME, host); + if (ret) + return ret; + + host->irq = irq; + return 0; } diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 25efd331ef28..b402269301f6 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -346,8 +346,10 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, mutex_lock(&flash->lock); /* Wait until finished previous write command. */ - if (wait_till_ready(flash)) + if (wait_till_ready(flash)) { + mutex_unlock(&flash->lock); return 1; + } write_enable(flash); diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c index 59d8fb49270a..effaf7cdefab 100644 --- a/drivers/mtd/maps/ck804xrom.c +++ b/drivers/mtd/maps/ck804xrom.c @@ -331,15 +331,15 @@ static void __devexit ck804xrom_remove_one (struct pci_dev *pdev) } static struct pci_device_id ck804xrom_pci_tbl[] = { - { PCI_VENDOR_ID_NVIDIA, 0x0051, PCI_ANY_ID, PCI_ANY_ID, DEV_CK804 }, - { PCI_VENDOR_ID_NVIDIA, 0x0360, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 }, - { PCI_VENDOR_ID_NVIDIA, 0x0361, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 }, - { PCI_VENDOR_ID_NVIDIA, 0x0362, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 }, - { PCI_VENDOR_ID_NVIDIA, 0x0363, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 }, - { PCI_VENDOR_ID_NVIDIA, 0x0364, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 }, - { PCI_VENDOR_ID_NVIDIA, 0x0365, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 }, - { PCI_VENDOR_ID_NVIDIA, 0x0366, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 }, - { PCI_VENDOR_ID_NVIDIA, 0x0367, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 }, + { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0051), .driver_data = DEV_CK804 }, + { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0360), .driver_data = DEV_MCP55 }, + { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0361), .driver_data = DEV_MCP55 }, + { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0362), .driver_data = DEV_MCP55 }, + { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0363), .driver_data = DEV_MCP55 }, + { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0364), .driver_data = DEV_MCP55 }, + { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0365), .driver_data = DEV_MCP55 }, + { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0366), .driver_data = DEV_MCP55 }, + { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0367), .driver_data = DEV_MCP55 }, { 0, } }; diff --git a/drivers/mtd/maps/omap_nor.c b/drivers/mtd/maps/omap_nor.c index 240b0e2d095d..c12d8056bebd 100644 --- a/drivers/mtd/maps/omap_nor.c +++ b/drivers/mtd/maps/omap_nor.c @@ -110,7 +110,7 @@ static int __init omapflash_probe(struct platform_device *pdev) err = parse_mtd_partitions(info->mtd, part_probes, &info->parts, 0); if (err > 0) add_mtd_partitions(info->mtd, info->parts, err); - else if (err < 0 && pdata->parts) + else if (err <= 0 && pdata->parts) add_mtd_partitions(info->mtd, pdata->parts, pdata->nr_parts); else #endif diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index fceb468ccdec..fe2bc7e42119 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -1216,7 +1216,7 @@ static int pxa3xx_nand_resume(struct platform_device *pdev) clk_enable(info->clk); - return pxa3xx_nand_config_flash(info); + return pxa3xx_nand_config_flash(info, info->flash_info); } #else #define pxa3xx_nand_suspend NULL diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c index 3d44d040a47d..ad81ab8e95e2 100644 --- a/drivers/mtd/onenand/generic.c +++ b/drivers/mtd/onenand/generic.c @@ -76,7 +76,7 @@ static int __devinit generic_onenand_probe(struct device *dev) err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0); if (err > 0) add_mtd_partitions(&info->mtd, info->parts, err); - else if (err < 0 && pdata->parts) + else if (err <= 0 && pdata->parts) add_mtd_partitions(&info->mtd, pdata->parts, pdata->nr_parts); else #endif diff --git a/drivers/mtd/redboot.c b/drivers/mtd/redboot.c index 47474903263c..c5030f94f04e 100644 --- a/drivers/mtd/redboot.c +++ b/drivers/mtd/redboot.c @@ -295,5 +295,5 @@ module_init(redboot_parser_init); module_exit(redboot_parser_exit); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Red Hat, Inc. - David Woodhouse <dwmw2@cambridge.redhat.com>"); +MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); MODULE_DESCRIPTION("Parsing code for RedBoot Flash Image System (FIS) tables"); diff --git a/drivers/net/7990.c b/drivers/net/7990.c index 750a46f4bc58..ad6b8a5b6574 100644 --- a/drivers/net/7990.c +++ b/drivers/net/7990.c @@ -506,6 +506,7 @@ int lance_open (struct net_device *dev) return res; } +EXPORT_SYMBOL_GPL(lance_open); int lance_close (struct net_device *dev) { @@ -521,6 +522,7 @@ int lance_close (struct net_device *dev) return 0; } +EXPORT_SYMBOL_GPL(lance_close); void lance_tx_timeout(struct net_device *dev) { @@ -529,7 +531,7 @@ void lance_tx_timeout(struct net_device *dev) dev->trans_start = jiffies; netif_wake_queue (dev); } - +EXPORT_SYMBOL_GPL(lance_tx_timeout); int lance_start_xmit (struct sk_buff *skb, struct net_device *dev) { @@ -586,6 +588,7 @@ int lance_start_xmit (struct sk_buff *skb, struct net_device *dev) return 0; } +EXPORT_SYMBOL_GPL(lance_start_xmit); /* taken from the depca driver via a2065.c */ static void lance_load_multicast (struct net_device *dev) @@ -654,6 +657,7 @@ void lance_set_multicast (struct net_device *dev) if (!stopped) netif_start_queue (dev); } +EXPORT_SYMBOL_GPL(lance_set_multicast); #ifdef CONFIG_NET_POLL_CONTROLLER void lance_poll(struct net_device *dev) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index dd0ec9ebc939..f4182cfffe9d 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2426,7 +2426,7 @@ config CHELSIO_T3 config EHEA tristate "eHEA Ethernet support" - depends on IBMEBUS && INET && SPARSEMEM && MEMORY_HOTPLUG + depends on IBMEBUS && INET && SPARSEMEM select INET_LRO ---help--- This driver supports the IBM pSeries eHEA ethernet adapter. diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 6e4c80d41b08..99e0b4cdc56f 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -637,22 +637,6 @@ static s32 atl1_phy_leave_power_saving(struct atl1_hw *hw) } /* - * Force the PHY into power saving mode using vendor magic. - */ -#ifdef CONFIG_PM -static void atl1_phy_enter_power_saving(struct atl1_hw *hw) -{ - atl1_write_phy_reg(hw, MII_DBG_ADDR, 0); - atl1_write_phy_reg(hw, MII_DBG_DATA, 0x124E); - atl1_write_phy_reg(hw, MII_DBG_ADDR, 2); - atl1_write_phy_reg(hw, MII_DBG_DATA, 0x3000); - atl1_write_phy_reg(hw, MII_DBG_ADDR, 3); - atl1_write_phy_reg(hw, MII_DBG_DATA, 0); - -} -#endif - -/* * Resets the PHY and make all config validate * hw - Struct containing variables accessed by shared code * @@ -2023,6 +2007,7 @@ rrd_ok: /* Good Receive */ pci_unmap_page(adapter->pdev, buffer_info->dma, buffer_info->length, PCI_DMA_FROMDEVICE); + buffer_info->dma = 0; skb = buffer_info->skb; length = le16_to_cpu(rrd->xsz.xsum_sz.pkt_size); @@ -2859,7 +2844,6 @@ disable_wol: ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; iowrite32(ctrl, hw->hw_addr + REG_PCIE_PHYMISC); ioread32(hw->hw_addr + REG_PCIE_PHYMISC); - atl1_phy_enter_power_saving(hw); hw->phy_configured = false; pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); exit: diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 4b46e68183e0..367b6d462708 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -5724,14 +5724,12 @@ bnx2_reset_task(struct work_struct *work) if (!netif_running(bp->dev)) return; - bp->in_reset_task = 1; bnx2_netif_stop(bp); bnx2_init_nic(bp); atomic_set(&bp->intr_sem, 1); bnx2_netif_start(bp); - bp->in_reset_task = 0; } static void @@ -5907,12 +5905,7 @@ bnx2_close(struct net_device *dev) struct bnx2 *bp = netdev_priv(dev); u32 reset_code; - /* Calling flush_scheduled_work() may deadlock because - * linkwatch_event() may be on the workqueue and it will try to get - * the rtnl_lock which we are holding. - */ - while (bp->in_reset_task) - msleep(1); + cancel_work_sync(&bp->reset_task); bnx2_disable_int_sync(bp); bnx2_napi_disable(bp); diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 1eaf5bb3d9c2..2377cc13bf61 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -6656,7 +6656,6 @@ struct bnx2 { int current_interval; struct timer_list timer; struct work_struct reset_task; - int in_reset_task; /* Used to synchronize phy accesses. */ spinlock_t phy_lock; diff --git a/drivers/net/bnx2x.c b/drivers/net/bnx2x.c index 7bdb5af35951..70cba64732ca 100644 --- a/drivers/net/bnx2x.c +++ b/drivers/net/bnx2x.c @@ -6,7 +6,8 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * - * Written by: Eliezer Tamir <eliezert@broadcom.com> + * Maintained by: Eilon Greenstein <eilong@broadcom.com> + * Written by: Eliezer Tamir * Based on code from Michael Chan's bnx2 driver * UDP CSUM errata workaround by Arik Gendelman * Slowpath rework by Vladislav Zolotarov @@ -74,7 +75,7 @@ static char version[] __devinitdata = "Broadcom NetXtreme II 5771X 10Gigabit Ethernet Driver " DRV_MODULE_NAME " " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; -MODULE_AUTHOR("Eliezer Tamir <eliezert@broadcom.com>"); +MODULE_AUTHOR("Eliezer Tamir"); MODULE_DESCRIPTION("Broadcom NetXtreme II BCM57710 Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_MODULE_VERSION); diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index 4f0c0d31e7c1..8e68d06510a6 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -6,7 +6,8 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * - * Written by: Eliezer Tamir <eliezert@broadcom.com> + * Maintained by: Eilon Greenstein <eilong@broadcom.com> + * Written by: Eliezer Tamir * Based on code from Michael Chan's bnx2 driver */ diff --git a/drivers/net/bnx2x_init.h b/drivers/net/bnx2x_init.h index dcaecc53bdb1..370686eef97c 100644 --- a/drivers/net/bnx2x_init.h +++ b/drivers/net/bnx2x_init.h @@ -6,7 +6,8 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * - * Written by: Eliezer Tamir <eliezert@broadcom.com> + * Maintained by: Eilon Greenstein <eilong@broadcom.com> + * Written by: Eliezer Tamir */ #ifndef BNX2X_INIT_H diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index 348371fda597..fba87abe78ee 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c @@ -1394,7 +1394,11 @@ net_open(struct net_device *dev) #endif if (!result) { printk(KERN_ERR "%s: EEPROM is configured for unavailable media\n", dev->name); - release_irq: +release_dma: +#if ALLOW_DMA + free_dma(dev->dma); +#endif +release_irq: #if ALLOW_DMA release_dma_buff(lp); #endif @@ -1442,12 +1446,12 @@ net_open(struct net_device *dev) if ((result = detect_bnc(dev)) != DETECTED_NONE) break; printk(KERN_ERR "%s: no media detected\n", dev->name); - goto release_irq; + goto release_dma; } switch(result) { case DETECTED_NONE: printk(KERN_ERR "%s: no network cable attached to configured media\n", dev->name); - goto release_irq; + goto release_dma; case DETECTED_RJ45H: printk(KERN_INFO "%s: using half-duplex 10Base-T (RJ-45)\n", dev->name); break; diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 287a61918739..075fd547421e 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -1766,16 +1766,20 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa) mutex_lock(&ehea_bcmc_regs.lock); /* Deregister old MAC in pHYP */ - ret = ehea_broadcast_reg_helper(port, H_DEREG_BCMC); - if (ret) - goto out_upregs; + if (port->state == EHEA_PORT_UP) { + ret = ehea_broadcast_reg_helper(port, H_DEREG_BCMC); + if (ret) + goto out_upregs; + } port->mac_addr = cb0->port_mac_addr << 16; /* Register new MAC in pHYP */ - ret = ehea_broadcast_reg_helper(port, H_REG_BCMC); - if (ret) - goto out_upregs; + if (port->state == EHEA_PORT_UP) { + ret = ehea_broadcast_reg_helper(port, H_REG_BCMC); + if (ret) + goto out_upregs; + } ret = 0; @@ -2601,7 +2605,8 @@ static int ehea_stop(struct net_device *dev) if (netif_msg_ifdown(port)) ehea_info("disabling port %s", dev->name); - flush_scheduled_work(); + cancel_work_sync(&port->reset_task); + mutex_lock(&port->port_lock); netif_stop_queue(dev); port_napi_disable(port); diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c index 5f9c42e7a7f1..329edd9c08fc 100644 --- a/drivers/net/fec_mpc52xx.c +++ b/drivers/net/fec_mpc52xx.c @@ -78,7 +78,7 @@ module_param_array_named(mac, mpc52xx_fec_mac_addr, byte, NULL, 0); MODULE_PARM_DESC(mac, "six hex digits, ie. 0x1,0x2,0xc0,0x01,0xba,0xbe"); #define MPC52xx_MESSAGES_DEFAULT ( NETIF_MSG_DRV | NETIF_MSG_PROBE | \ - NETIF_MSG_LINK | NETIF_MSG_IFDOWN | NETIF_MSG_IFDOWN ) + NETIF_MSG_LINK | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP) static int debug = -1; /* the above default */ module_param(debug, int, 0); MODULE_PARM_DESC(debug, "debugging messages level"); diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 9eca97fb0a54..2cb244763292 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -3273,6 +3273,20 @@ static void nv_link_irq(struct net_device *dev) dprintk(KERN_DEBUG "%s: link change notification done.\n", dev->name); } +static void nv_msi_workaround(struct fe_priv *np) +{ + + /* Need to toggle the msi irq mask within the ethernet device, + * otherwise, future interrupts will not be detected. + */ + if (np->msi_flags & NV_MSI_ENABLED) { + u8 __iomem *base = np->base; + + writel(0, base + NvRegMSIIrqMask); + writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask); + } +} + static irqreturn_t nv_nic_irq(int foo, void *data) { struct net_device *dev = (struct net_device *) data; @@ -3295,6 +3309,8 @@ static irqreturn_t nv_nic_irq(int foo, void *data) if (!(events & np->irqmask)) break; + nv_msi_workaround(np); + spin_lock(&np->lock); nv_tx_done(dev); spin_unlock(&np->lock); @@ -3410,6 +3426,8 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) if (!(events & np->irqmask)) break; + nv_msi_workaround(np); + spin_lock(&np->lock); nv_tx_done_optimized(dev, TX_WORK_PER_LOOP); spin_unlock(&np->lock); @@ -3750,6 +3768,8 @@ static irqreturn_t nv_nic_irq_test(int foo, void *data) if (!(events & NVREG_IRQ_TIMER)) return IRQ_RETVAL(0); + nv_msi_workaround(np); + spin_lock(&np->lock); np->intr_test = 1; spin_unlock(&np->lock); diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c index dde9c7e6408a..00bc7fbb6b37 100644 --- a/drivers/net/hamradio/baycom_epp.c +++ b/drivers/net/hamradio/baycom_epp.c @@ -959,7 +959,7 @@ static int epp_close(struct net_device *dev) unsigned char tmp[1]; bc->work_running = 0; - flush_scheduled_work(); + cancel_delayed_work_sync(&bc->run_work); bc->stat = EPP_DCDBIT; tmp[0] = 0; pp->ops->epp_write_addr(pp, tmp, 1, 0); diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c index 9b358f61ed7f..679a0826780e 100644 --- a/drivers/net/ipg.c +++ b/drivers/net/ipg.c @@ -577,12 +577,12 @@ static void ipg_nic_set_multicast_list(struct net_device *dev) /* NIC to be configured in promiscuous mode. */ receivemode = IPG_RM_RECEIVEALLFRAMES; } else if ((dev->flags & IFF_ALLMULTI) || - (dev->flags & IFF_MULTICAST & + ((dev->flags & IFF_MULTICAST) && (dev->mc_count > IPG_MULTICAST_HASHTABLE_SIZE))) { /* NIC to be configured to receive all multicast * frames. */ receivemode |= IPG_RM_RECEIVEMULTICAST; - } else if (dev->flags & IFF_MULTICAST & (dev->mc_count > 0)) { + } else if ((dev->flags & IFF_MULTICAST) && (dev->mc_count > 0)) { /* NIC to be configured to receive selected * multicast addresses. */ receivemode |= IPG_RM_RECEIVEMULTICASTHASH; diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig index ce816ba9c40d..e6317557a531 100644 --- a/drivers/net/irda/Kconfig +++ b/drivers/net/irda/Kconfig @@ -329,6 +329,7 @@ config PXA_FICP config MCS_FIR tristate "MosChip MCS7780 IrDA-USB dongle" depends on IRDA && USB && EXPERIMENTAL + select CRC32 help Say Y or M here if you want to build support for the MosChip MCS7780 IrDA-USB bridge device driver. diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index 6321b059ce13..2f38e847e2cd 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -58,8 +58,8 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw); static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw) { - hw->mac.num_rx_queues = IXGBE_82598_MAX_TX_QUEUES; - hw->mac.num_tx_queues = IXGBE_82598_MAX_RX_QUEUES; + hw->mac.num_rx_queues = IXGBE_82598_MAX_RX_QUEUES; + hw->mac.num_tx_queues = IXGBE_82598_MAX_TX_QUEUES; hw->mac.num_rx_addrs = IXGBE_82598_RAR_ENTRIES; /* PHY ops are filled in by default properly for Fiber only */ diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 36be6efc6398..e0d76c75aea0 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -75,7 +75,7 @@ #include "myri10ge_mcp.h" #include "myri10ge_mcp_gen_header.h" -#define MYRI10GE_VERSION_STR "1.3.2-1.287" +#define MYRI10GE_VERSION_STR "1.3.99-1.347" MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); MODULE_AUTHOR("Maintainer: help@myri.com"); diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 58a26a47af29..bafb69b6f7cb 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -341,12 +341,6 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb) struct pppox_sock *relay_po; if (sk->sk_state & PPPOX_BOUND) { - struct pppoe_hdr *ph = pppoe_hdr(skb); - int len = ntohs(ph->length); - skb_pull_rcsum(skb, sizeof(struct pppoe_hdr)); - if (pskb_trim_rcsum(skb, len)) - goto abort_kfree; - ppp_input(&po->chan, skb); } else if (sk->sk_state & PPPOX_RELAY) { relay_po = get_item_by_addr(&po->pppoe_relay); @@ -357,7 +351,6 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb) if ((sk_pppox(relay_po)->sk_state & PPPOX_CONNECTED) == 0) goto abort_put; - skb_pull(skb, sizeof(struct pppoe_hdr)); if (!__pppoe_xmit(sk_pppox(relay_po), skb)) goto abort_put; } else { @@ -388,6 +381,7 @@ static int pppoe_rcv(struct sk_buff *skb, { struct pppoe_hdr *ph; struct pppox_sock *po; + int len; if (!(skb = skb_share_check(skb, GFP_ATOMIC))) goto out; @@ -399,10 +393,21 @@ static int pppoe_rcv(struct sk_buff *skb, goto drop; ph = pppoe_hdr(skb); + len = ntohs(ph->length); + + skb_pull_rcsum(skb, sizeof(*ph)); + if (skb->len < len) + goto drop; po = get_item(ph->sid, eth_hdr(skb)->h_source, dev->ifindex); - if (po != NULL) - return sk_receive_skb(sk_pppox(po), skb, 0); + if (!po) + goto drop; + + if (pskb_trim_rcsum(skb, len)) + goto drop; + + return sk_receive_skb(sk_pppox(po), skb, 0); + drop: kfree_skb(skb); out: @@ -427,12 +432,12 @@ static int pppoe_disc_rcv(struct sk_buff *skb, if (dev_net(dev) != &init_net) goto abort; - if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr))) - goto abort; - if (!(skb = skb_share_check(skb, GFP_ATOMIC))) goto out; + if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr))) + goto abort; + ph = pppoe_hdr(skb); if (ph->code != PADT_CODE) goto abort; @@ -937,12 +942,10 @@ static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock, m->msg_namelen = 0; if (skb) { - struct pppoe_hdr *ph = pppoe_hdr(skb); - const int len = ntohs(ph->length); - - error = memcpy_toiovec(m->msg_iov, (unsigned char *) &ph->tag[0], len); + total_len = min(total_len, skb->len); + error = skb_copy_datagram_iovec(skb, 0, m->msg_iov, total_len); if (error == 0) - error = len; + error = total_len; } kfree_skb(skb); diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c index 8db342f2fdc9..f9298827a76c 100644 --- a/drivers/net/pppol2tp.c +++ b/drivers/net/pppol2tp.c @@ -240,12 +240,15 @@ static inline struct pppol2tp_session *pppol2tp_sock_to_session(struct sock *sk) if (sk == NULL) return NULL; + sock_hold(sk); session = (struct pppol2tp_session *)(sk->sk_user_data); - if (session == NULL) - return NULL; + if (session == NULL) { + sock_put(sk); + goto out; + } BUG_ON(session->magic != L2TP_SESSION_MAGIC); - +out: return session; } @@ -256,12 +259,15 @@ static inline struct pppol2tp_tunnel *pppol2tp_sock_to_tunnel(struct sock *sk) if (sk == NULL) return NULL; + sock_hold(sk); tunnel = (struct pppol2tp_tunnel *)(sk->sk_user_data); - if (tunnel == NULL) - return NULL; + if (tunnel == NULL) { + sock_put(sk); + goto out; + } BUG_ON(tunnel->magic != L2TP_TUNNEL_MAGIC); - +out: return tunnel; } @@ -716,12 +722,14 @@ discard: session->stats.rx_errors++; kfree_skb(skb); sock_put(session->sock); + sock_put(sock); return 0; error: /* Put UDP header back */ __skb_push(skb, sizeof(struct udphdr)); + sock_put(sock); no_tunnel: return 1; @@ -745,10 +753,13 @@ static int pppol2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb) "%s: received %d bytes\n", tunnel->name, skb->len); if (pppol2tp_recv_core(sk, skb)) - goto pass_up; + goto pass_up_put; + sock_put(sk); return 0; +pass_up_put: + sock_put(sk); pass_up: return 1; } @@ -772,14 +783,18 @@ static int pppol2tp_recvmsg(struct kiocb *iocb, struct socket *sock, err = 0; skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, flags & MSG_DONTWAIT, &err); - if (skb) { - err = memcpy_toiovec(msg->msg_iov, (unsigned char *) skb->data, - skb->len); - if (err < 0) - goto do_skb_free; - err = skb->len; - } -do_skb_free: + if (!skb) + goto end; + + if (len > skb->len) + len = skb->len; + else if (len < skb->len) + msg->msg_flags |= MSG_TRUNC; + + err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, len); + if (likely(err == 0)) + err = len; + kfree_skb(skb); end: return err; @@ -858,7 +873,7 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock); if (tunnel == NULL) - goto error; + goto error_put_sess; /* What header length is configured for this session? */ hdr_len = pppol2tp_l2tp_header_len(session); @@ -870,7 +885,7 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh sizeof(ppph) + total_len, 0, GFP_KERNEL); if (!skb) - goto error; + goto error_put_sess_tun; /* Reserve space for headers. */ skb_reserve(skb, NET_SKB_PAD); @@ -900,7 +915,7 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh error = memcpy_fromiovec(skb->data, m->msg_iov, total_len); if (error < 0) { kfree_skb(skb); - goto error; + goto error_put_sess_tun; } skb_put(skb, total_len); @@ -947,10 +962,33 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh session->stats.tx_errors++; } + return error; + +error_put_sess_tun: + sock_put(session->tunnel_sock); +error_put_sess: + sock_put(sk); error: return error; } +/* Automatically called when the skb is freed. + */ +static void pppol2tp_sock_wfree(struct sk_buff *skb) +{ + sock_put(skb->sk); +} + +/* For data skbs that we transmit, we associate with the tunnel socket + * but don't do accounting. + */ +static inline void pppol2tp_skb_set_owner_w(struct sk_buff *skb, struct sock *sk) +{ + sock_hold(sk); + skb->sk = sk; + skb->destructor = pppol2tp_sock_wfree; +} + /* Transmit function called by generic PPP driver. Sends PPP frame * over PPPoL2TP socket. * @@ -993,10 +1031,10 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) sk_tun = session->tunnel_sock; if (sk_tun == NULL) - goto abort; + goto abort_put_sess; tunnel = pppol2tp_sock_to_tunnel(sk_tun); if (tunnel == NULL) - goto abort; + goto abort_put_sess; /* What header length is configured for this session? */ hdr_len = pppol2tp_l2tp_header_len(session); @@ -1009,7 +1047,7 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) sizeof(struct udphdr) + hdr_len + sizeof(ppph); old_headroom = skb_headroom(skb); if (skb_cow_head(skb, headroom)) - goto abort; + goto abort_put_sess_tun; new_headroom = skb_headroom(skb); skb_orphan(skb); @@ -1069,7 +1107,7 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) /* Get routing info from the tunnel socket */ dst_release(skb->dst); skb->dst = dst_clone(__sk_dst_get(sk_tun)); - skb->sk = sk_tun; + pppol2tp_skb_set_owner_w(skb, sk_tun); /* Queue the packet to IP for output */ len = skb->len; @@ -1086,8 +1124,14 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) session->stats.tx_errors++; } + sock_put(sk_tun); + sock_put(sk); return 1; +abort_put_sess_tun: + sock_put(sk_tun); +abort_put_sess: + sock_put(sk); abort: /* Free the original skb */ kfree_skb(skb); @@ -1191,7 +1235,7 @@ static void pppol2tp_tunnel_destruct(struct sock *sk) { struct pppol2tp_tunnel *tunnel; - tunnel = pppol2tp_sock_to_tunnel(sk); + tunnel = sk->sk_user_data; if (tunnel == NULL) goto end; @@ -1230,10 +1274,12 @@ static void pppol2tp_session_destruct(struct sock *sk) if (sk->sk_user_data != NULL) { struct pppol2tp_tunnel *tunnel; - session = pppol2tp_sock_to_session(sk); + session = sk->sk_user_data; if (session == NULL) goto out; + BUG_ON(session->magic != L2TP_SESSION_MAGIC); + /* Don't use pppol2tp_sock_to_tunnel() here to * get the tunnel context because the tunnel * socket might have already been closed (its @@ -1279,6 +1325,7 @@ out: static int pppol2tp_release(struct socket *sock) { struct sock *sk = sock->sk; + struct pppol2tp_session *session; int error; if (!sk) @@ -1296,9 +1343,18 @@ static int pppol2tp_release(struct socket *sock) sock_orphan(sk); sock->sk = NULL; + session = pppol2tp_sock_to_session(sk); + /* Purge any queued data */ skb_queue_purge(&sk->sk_receive_queue); skb_queue_purge(&sk->sk_write_queue); + if (session != NULL) { + struct sk_buff *skb; + while ((skb = skb_dequeue(&session->reorder_q))) { + kfree_skb(skb); + sock_put(sk); + } + } release_sock(sk); @@ -1601,7 +1657,7 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, error = ppp_register_channel(&po->chan); if (error) - goto end; + goto end_put_tun; /* This is how we get the session context from the socket. */ sk->sk_user_data = session; @@ -1621,6 +1677,8 @@ out_no_ppp: PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, "%s: created\n", session->name); +end_put_tun: + sock_put(tunnel_sock); end: release_sock(sk); @@ -1668,6 +1726,7 @@ static int pppol2tp_getname(struct socket *sock, struct sockaddr *uaddr, *usockaddr_len = len; error = 0; + sock_put(sock->sk); end: return error; @@ -1906,14 +1965,17 @@ static int pppol2tp_ioctl(struct socket *sock, unsigned int cmd, err = -EBADF; tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock); if (tunnel == NULL) - goto end; + goto end_put_sess; err = pppol2tp_tunnel_ioctl(tunnel, cmd, arg); - goto end; + sock_put(session->tunnel_sock); + goto end_put_sess; } err = pppol2tp_session_ioctl(session, cmd, arg); +end_put_sess: + sock_put(sk); end: return err; } @@ -2059,14 +2121,17 @@ static int pppol2tp_setsockopt(struct socket *sock, int level, int optname, err = -EBADF; tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock); if (tunnel == NULL) - goto end; + goto end_put_sess; err = pppol2tp_tunnel_setsockopt(sk, tunnel, optname, val); + sock_put(session->tunnel_sock); } else err = pppol2tp_session_setsockopt(sk, session, optname, val); err = 0; +end_put_sess: + sock_put(sk); end: return err; } @@ -2181,20 +2246,24 @@ static int pppol2tp_getsockopt(struct socket *sock, int level, err = -EBADF; tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock); if (tunnel == NULL) - goto end; + goto end_put_sess; err = pppol2tp_tunnel_getsockopt(sk, tunnel, optname, &val); + sock_put(session->tunnel_sock); } else err = pppol2tp_session_getsockopt(sk, session, optname, &val); err = -EFAULT; if (put_user(len, (int __user *) optlen)) - goto end; + goto end_put_sess; if (copy_to_user((void __user *) optval, &val, len)) - goto end; + goto end_put_sess; err = 0; + +end_put_sess: + sock_put(sk); end: return err; } diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 169edc154928..858b191517b3 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -733,7 +733,7 @@ static void r6040_timer(unsigned long data) } /* Timer active again */ - mod_timer(&lp->timer, jiffies + round_jiffies(HZ)); + mod_timer(&lp->timer, round_jiffies(jiffies + HZ)); } /* Read/set MAC address routines */ diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index a20693e09ae8..b5c1e663417d 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -2861,7 +2861,8 @@ static int s2io_poll_msix(struct napi_struct *napi, int budget) struct config_param *config; struct mac_info *mac_control; int pkts_processed = 0; - u8 *addr = NULL, val8 = 0; + u8 __iomem *addr = NULL; + u8 val8 = 0; struct s2io_nic *nic = dev->priv; struct XENA_dev_config __iomem *bar0 = nic->bar0; int budget_org = budget; @@ -2878,7 +2879,7 @@ static int s2io_poll_msix(struct napi_struct *napi, int budget) if (pkts_processed < budget_org) { netif_rx_complete(dev, napi); /*Re Enable MSI-Rx Vector*/ - addr = (u8 *)&bar0->xmsi_mask_reg; + addr = (u8 __iomem *)&bar0->xmsi_mask_reg; addr += 7 - ring->ring_no; val8 = (ring->ring_no == 0) ? 0x3f : 0xbf; writeb(val8, addr); @@ -4364,9 +4365,10 @@ static irqreturn_t s2io_msix_ring_handle(int irq, void *dev_id) return IRQ_HANDLED; if (sp->config.napi) { - u8 *addr = NULL, val8 = 0; + u8 __iomem *addr = NULL; + u8 val8 = 0; - addr = (u8 *)&bar0->xmsi_mask_reg; + addr = (u8 __iomem *)&bar0->xmsi_mask_reg; addr += (7 - ring->ring_no); val8 = (ring->ring_no == 0) ? 0x7f : 0xff; writeb(val8, addr); diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c index b4b63805ee8f..61955f8d8011 100644 --- a/drivers/net/sc92031.c +++ b/drivers/net/sc92031.c @@ -972,7 +972,7 @@ static int sc92031_start_xmit(struct sk_buff *skb, struct net_device *dev) skb_copy_and_csum_dev(skb, priv->tx_bufs + entry * TX_BUF_SIZE); len = skb->len; - if (unlikely(len < ETH_ZLEN)) { + if (len < ETH_ZLEN) { memset(priv->tx_bufs + entry * TX_BUF_SIZE + len, 0, ETH_ZLEN - len); len = ETH_ZLEN; diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index d3f749c72d41..790db89db345 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -733,8 +733,10 @@ void falcon_fini_rx(struct efx_rx_queue *rx_queue) continue; break; } - if (rc) + if (rc) { EFX_ERR(efx, "failed to flush rx queue %d\n", rx_queue->queue); + efx_schedule_reset(efx, RESET_TYPE_INVISIBLE); + } /* Remove RX descriptor ring from card */ EFX_ZERO_OWORD(rx_desc_ptr); diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c index dbdcee4b0f8d..55c0d9760be8 100644 --- a/drivers/net/sfc/falcon_xmac.c +++ b/drivers/net/sfc/falcon_xmac.c @@ -459,7 +459,7 @@ static int falcon_check_xaui_link_up(struct efx_nic *efx) tries--; } - EFX_ERR(efx, "Failed to bring XAUI link back up in %d tries!\n", + EFX_LOG(efx, "Failed to bring XAUI link back up in %d tries!\n", max_tries); return 0; } diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 3bb60530d4d7..62436b3a18c6 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -4404,7 +4404,9 @@ static int sky2_resume(struct pci_dev *pdev) if (err) { printk(KERN_ERR PFX "%s: could not up: %d\n", dev->name, err); + rtnl_lock(); dev_close(dev); + rtnl_unlock(); goto out; } } diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 4e2800205189..e2ee91a6ae7e 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -136,7 +136,6 @@ struct smc911x_local { /* work queue */ struct work_struct phy_configure; - int work_pending; int tx_throttle; spinlock_t lock; @@ -960,11 +959,11 @@ static void smc911x_phy_configure(struct work_struct *work) * We should not be called if phy_type is zero. */ if (lp->phy_type == 0) - goto smc911x_phy_configure_exit_nolock; + return; if (smc911x_phy_reset(dev, phyaddr)) { printk("%s: PHY reset timed out\n", dev->name); - goto smc911x_phy_configure_exit_nolock; + return; } spin_lock_irqsave(&lp->lock, flags); @@ -1033,8 +1032,6 @@ static void smc911x_phy_configure(struct work_struct *work) smc911x_phy_configure_exit: spin_unlock_irqrestore(&lp->lock, flags); -smc911x_phy_configure_exit_nolock: - lp->work_pending = 0; } /* @@ -1356,11 +1353,8 @@ static void smc911x_timeout(struct net_device *dev) * smc911x_phy_configure() calls msleep() which calls schedule_timeout() * which calls schedule(). Hence we use a work queue. */ - if (lp->phy_type != 0) { - if (schedule_work(&lp->phy_configure)) { - lp->work_pending = 1; - } - } + if (lp->phy_type != 0) + schedule_work(&lp->phy_configure); /* We can accept TX packets again */ dev->trans_start = jiffies; @@ -1531,16 +1525,8 @@ static int smc911x_close(struct net_device *dev) if (lp->phy_type != 0) { /* We need to ensure that no calls to * smc911x_phy_configure are pending. - - * flush_scheduled_work() cannot be called because we - * are running with the netlink semaphore held (from - * devinet_ioctl()) and the pending work queue - * contains linkwatch_event() (scheduled by - * netif_carrier_off() above). linkwatch_event() also - * wants the netlink semaphore. */ - while (lp->work_pending) - schedule(); + cancel_work_sync(&lp->phy_configure); smc911x_phy_powerdown(dev, lp->mii.phy_id); } diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index a188e33484e6..f2051b209da2 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -1016,15 +1016,8 @@ static void smc_phy_powerdown(struct net_device *dev) /* We need to ensure that no calls to smc_phy_configure are pending. - - flush_scheduled_work() cannot be called because we are - running with the netlink semaphore held (from - devinet_ioctl()) and the pending work queue contains - linkwatch_event() (scheduled by netif_carrier_off() - above). linkwatch_event() also wants the netlink semaphore. */ - while(lp->work_pending) - yield(); + cancel_work_sync(&lp->phy_configure); bmcr = smc_phy_read(dev, phy, MII_BMCR); smc_phy_write(dev, phy, MII_BMCR, bmcr | BMCR_PDOWN); @@ -1161,7 +1154,6 @@ static void smc_phy_configure(struct work_struct *work) smc_phy_configure_exit: SMC_SELECT_BANK(lp, 2); spin_unlock_irq(&lp->lock); - lp->work_pending = 0; } /* @@ -1389,11 +1381,8 @@ static void smc_timeout(struct net_device *dev) * smc_phy_configure() calls msleep() which calls schedule_timeout() * which calls schedule(). Hence we use a work queue. */ - if (lp->phy_type != 0) { - if (schedule_work(&lp->phy_configure)) { - lp->work_pending = 1; - } - } + if (lp->phy_type != 0) + schedule_work(&lp->phy_configure); /* We can accept TX packets again */ dev->trans_start = jiffies; diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index 69e97a1cb1c4..8606818653f8 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -93,14 +93,14 @@ #define SMC_insw(a, r, p, l) insw ((unsigned long *)((a) + (r)), p, l) # endif /* check if the mac in reg is valid */ -#define SMC_GET_MAC_ADDR(addr) \ +#define SMC_GET_MAC_ADDR(lp, addr) \ do { \ unsigned int __v; \ - __v = SMC_inw(ioaddr, ADDR0_REG); \ + __v = SMC_inw(ioaddr, ADDR0_REG(lp)); \ addr[0] = __v; addr[1] = __v >> 8; \ - __v = SMC_inw(ioaddr, ADDR1_REG); \ + __v = SMC_inw(ioaddr, ADDR1_REG(lp)); \ addr[2] = __v; addr[3] = __v >> 8; \ - __v = SMC_inw(ioaddr, ADDR2_REG); \ + __v = SMC_inw(ioaddr, ADDR2_REG(lp)); \ addr[4] = __v; addr[5] = __v >> 8; \ if (*(u32 *)(&addr[0]) == 0xFFFFFFFF) { \ random_ether_addr(addr); \ diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index b4e7f30ea4e8..1aa425be3067 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -111,7 +111,7 @@ static __inline__ void tx_add_log(struct happy_meal *hp, unsigned int a, unsigne struct hme_tx_logent *tlp; unsigned long flags; - save_and_cli(flags); + local_irq_save(flags); tlp = &tx_log[txlog_cur_entry]; tlp->tstamp = (unsigned int)jiffies; tlp->tx_new = hp->tx_new; @@ -119,7 +119,7 @@ static __inline__ void tx_add_log(struct happy_meal *hp, unsigned int a, unsigne tlp->action = a; tlp->status = s; txlog_cur_entry = (txlog_cur_entry + 1) & (TX_LOG_LEN - 1); - restore_flags(flags); + local_irq_restore(flags); } static __inline__ void tx_dump_log(void) { diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 07b3f77e7626..cc4bde852542 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.92" -#define DRV_MODULE_RELDATE "May 2, 2008" +#define DRV_MODULE_VERSION "3.92.1" +#define DRV_MODULE_RELDATE "June 9, 2008" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -1295,6 +1295,21 @@ static void tg3_frob_aux_power(struct tg3 *tp) GRC_LCLCTRL_GPIO_OUTPUT0 | GRC_LCLCTRL_GPIO_OUTPUT1), 100); + } else if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761) { + /* The 5761 non-e device swaps GPIO 0 and GPIO 2. */ + u32 grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 | + GRC_LCLCTRL_GPIO_OE1 | + GRC_LCLCTRL_GPIO_OE2 | + GRC_LCLCTRL_GPIO_OUTPUT0 | + GRC_LCLCTRL_GPIO_OUTPUT1 | + tp->grc_local_ctrl; + tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl, 100); + + grc_local_ctrl |= GRC_LCLCTRL_GPIO_OUTPUT2; + tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl, 100); + + grc_local_ctrl &= ~GRC_LCLCTRL_GPIO_OUTPUT0; + tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl, 100); } else { u32 no_gpio2; u32 grc_local_ctrl = 0; @@ -3168,8 +3183,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) err |= tg3_readphy(tp, MII_BMCR, &bmcr); if ((tp->link_config.autoneg == AUTONEG_ENABLE) && !force_reset && - (tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT) && - tp->link_config.flowctrl == tp->link_config.active_flowctrl) { + (tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT)) { /* do nothing, just check for link up at the end */ } else if (tp->link_config.autoneg == AUTONEG_ENABLE) { u32 adv, new_adv; @@ -8599,7 +8613,7 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) (cmd->speed == SPEED_1000)) return -EINVAL; else if ((cmd->speed == SPEED_1000) && - (tp->tg3_flags2 & TG3_FLAG_10_100_ONLY)) + (tp->tg3_flags & TG3_FLAG_10_100_ONLY)) return -EINVAL; tg3_full_lock(tp, 0); @@ -11768,6 +11782,15 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL; + if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761) { + /* Turn off the debug UART. */ + tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL; + if (tp->tg3_flags2 & TG3_FLG2_IS_NIC) + /* Keep VMain power. */ + tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE0 | + GRC_LCLCTRL_GPIO_OUTPUT0; + } + /* Force the chip into D0. */ err = tg3_set_power_state(tp, PCI_D0); if (err) { diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index f9d13fa05d64..af8d2c436efd 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -731,7 +731,7 @@ static void tulip_down (struct net_device *dev) void __iomem *ioaddr = tp->base_addr; unsigned long flags; - flush_scheduled_work(); + cancel_work_sync(&tp->media_work); #ifdef CONFIG_TULIP_NAPI napi_disable(&tp->napi); @@ -1729,12 +1729,15 @@ static int tulip_suspend (struct pci_dev *pdev, pm_message_t state) if (!dev) return -EINVAL; - if (netif_running(dev)) - tulip_down(dev); + if (!netif_running(dev)) + goto save_state; + + tulip_down(dev); netif_device_detach(dev); free_irq(dev->irq, dev); +save_state: pci_save_state(pdev); pci_disable_device(pdev); pci_set_power_state(pdev, pci_choose_state(pdev, state)); @@ -1754,6 +1757,9 @@ static int tulip_resume(struct pci_dev *pdev) pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); + if (!netif_running(dev)) + return 0; + if ((retval = pci_enable_device(pdev))) { printk (KERN_ERR "tulip: pci_enable_device failed in resume\n"); return retval; diff --git a/drivers/net/ucc_geth_ethtool.c b/drivers/net/ucc_geth_ethtool.c index 299b7f176950..f5839c4a5cbd 100644 --- a/drivers/net/ucc_geth_ethtool.c +++ b/drivers/net/ucc_geth_ethtool.c @@ -73,6 +73,7 @@ static char tx_fw_stat_gstrings[][ETH_GSTRING_LEN] = { "tx-frames-ok", "tx-excessive-differ-frames", "tx-256-511-frames", + "tx-512-1023-frames", "tx-1024-1518-frames", "tx-jumbo-frames", }; @@ -308,7 +309,7 @@ static void uec_get_strings(struct net_device *netdev, u32 stringset, u8 *buf) buf += UEC_TX_FW_STATS_LEN * ETH_GSTRING_LEN; } if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) - memcpy(buf, tx_fw_stat_gstrings, UEC_RX_FW_STATS_LEN * + memcpy(buf, rx_fw_stat_gstrings, UEC_RX_FW_STATS_LEN * ETH_GSTRING_LEN); } diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index 0dcfc0310264..7c66b052f55a 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c @@ -706,7 +706,7 @@ static void kaweth_kill_urbs(struct kaweth_device *kaweth) usb_kill_urb(kaweth->rx_urb); usb_kill_urb(kaweth->tx_urb); - flush_scheduled_work(); + cancel_delayed_work_sync(&kaweth->lowmem_work); /* a scheduled work may have resubmitted, we hit them again */ diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index fe7cdf2a2a23..4452306d5328 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -44,9 +44,16 @@ struct virtnet_info /* The skb we couldn't send because buffers were full. */ struct sk_buff *last_xmit_skb; + /* If we need to free in a timer, this is it. */ + struct timer_list xmit_free_timer; + /* Number of input buffers, and max we've ever had. */ unsigned int num, max; + /* For cleaning up after transmission. */ + struct tasklet_struct tasklet; + bool free_in_tasklet; + /* Receive & send queues. */ struct sk_buff_head recv; struct sk_buff_head send; @@ -68,8 +75,13 @@ static void skb_xmit_done(struct virtqueue *svq) /* Suppress further interrupts. */ svq->vq_ops->disable_cb(svq); - /* We were waiting for more output buffers. */ + + /* We were probably waiting for more output buffers. */ netif_wake_queue(vi->dev); + + /* Make sure we re-xmit last_xmit_skb: if there are no more packets + * queued, start_xmit won't be called. */ + tasklet_schedule(&vi->tasklet); } static void receive_skb(struct net_device *dev, struct sk_buff *skb, @@ -86,9 +98,7 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb, BUG_ON(len > MAX_PACKET_LEN); skb_trim(skb, len); - skb->protocol = eth_type_trans(skb, dev); - pr_debug("Receiving skb proto 0x%04x len %i type %i\n", - ntohs(skb->protocol), skb->len, skb->pkt_type); + dev->stats.rx_bytes += skb->len; dev->stats.rx_packets++; @@ -98,6 +108,10 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb, goto frame_err; } + skb->protocol = eth_type_trans(skb, dev); + pr_debug("Receiving skb proto 0x%04x len %i type %i\n", + ntohs(skb->protocol), skb->len, skb->pkt_type); + if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { pr_debug("GSO!\n"); switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { @@ -230,9 +244,25 @@ static void free_old_xmit_skbs(struct virtnet_info *vi) } } +/* If the virtio transport doesn't always notify us when all in-flight packets + * are consumed, we fall back to using this function on a timer to free them. */ +static void xmit_free(unsigned long data) +{ + struct virtnet_info *vi = (void *)data; + + netif_tx_lock(vi->dev); + + free_old_xmit_skbs(vi); + + if (!skb_queue_empty(&vi->send)) + mod_timer(&vi->xmit_free_timer, jiffies + (HZ/10)); + + netif_tx_unlock(vi->dev); +} + static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb) { - int num; + int num, err; struct scatterlist sg[2+MAX_SKB_FRAGS]; struct virtio_net_hdr *hdr; const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; @@ -275,7 +305,25 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb) vnet_hdr_to_sg(sg, skb); num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1; - return vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb); + err = vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb); + if (!err && !vi->free_in_tasklet) + mod_timer(&vi->xmit_free_timer, jiffies + (HZ/10)); + + return err; +} + +static void xmit_tasklet(unsigned long data) +{ + struct virtnet_info *vi = (void *)data; + + netif_tx_lock_bh(vi->dev); + if (vi->last_xmit_skb && xmit_skb(vi, vi->last_xmit_skb) == 0) { + vi->svq->vq_ops->kick(vi->svq); + vi->last_xmit_skb = NULL; + } + if (vi->free_in_tasklet) + free_old_xmit_skbs(vi); + netif_tx_unlock_bh(vi->dev); } static int start_xmit(struct sk_buff *skb, struct net_device *dev) @@ -287,21 +335,25 @@ again: free_old_xmit_skbs(vi); /* If we has a buffer left over from last time, send it now. */ - if (vi->last_xmit_skb) { + if (unlikely(vi->last_xmit_skb)) { if (xmit_skb(vi, vi->last_xmit_skb) != 0) { /* Drop this skb: we only queue one. */ vi->dev->stats.tx_dropped++; kfree_skb(skb); + skb = NULL; goto stop_queue; } vi->last_xmit_skb = NULL; } /* Put new one in send queue and do transmit */ - __skb_queue_head(&vi->send, skb); - if (xmit_skb(vi, skb) != 0) { - vi->last_xmit_skb = skb; - goto stop_queue; + if (likely(skb)) { + __skb_queue_head(&vi->send, skb); + if (xmit_skb(vi, skb) != 0) { + vi->last_xmit_skb = skb; + skb = NULL; + goto stop_queue; + } } done: vi->svq->vq_ops->kick(vi->svq); @@ -411,6 +463,10 @@ static int virtnet_probe(struct virtio_device *vdev) vi->vdev = vdev; vdev->priv = vi; + /* If they give us a callback when all buffers are done, we don't need + * the timer. */ + vi->free_in_tasklet = virtio_has_feature(vdev,VIRTIO_F_NOTIFY_ON_EMPTY); + /* We expect two virtqueues, receive then send. */ vi->rvq = vdev->config->find_vq(vdev, 0, skb_recv_done); if (IS_ERR(vi->rvq)) { @@ -428,6 +484,11 @@ static int virtnet_probe(struct virtio_device *vdev) skb_queue_head_init(&vi->recv); skb_queue_head_init(&vi->send); + tasklet_init(&vi->tasklet, xmit_tasklet, (unsigned long)vi); + + if (!vi->free_in_tasklet) + setup_timer(&vi->xmit_free_timer, xmit_free, (unsigned long)vi); + err = register_netdev(dev); if (err) { pr_debug("virtio_net: registering device failed\n"); @@ -465,6 +526,9 @@ static void virtnet_remove(struct virtio_device *vdev) /* Stop all the virtqueues. */ vdev->config->reset(vdev); + if (!vi->free_in_tasklet) + del_timer_sync(&vi->xmit_free_timer); + /* Free our skbs in send and recv queues, if any. */ while ((skb = __skb_dequeue(&vi->recv)) != NULL) { kfree_skb(skb); @@ -488,7 +552,7 @@ static struct virtio_device_id id_table[] = { static unsigned int features[] = { VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GSO, VIRTIO_NET_F_MAC, VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6, - VIRTIO_NET_F_HOST_ECN, + VIRTIO_NET_F_HOST_ECN, VIRTIO_F_NOTIFY_ON_EMPTY, }; static struct virtio_driver virtio_net = { diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 4e1c690ff45f..32019fb878d8 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -2905,7 +2905,7 @@ EXPORT_SYMBOL(init_airo_card); static int waitbusy (struct airo_info *ai) { int delay = 0; - while ((IN4500 (ai, COMMAND) & COMMAND_BUSY) && (delay < 10000)) { + while ((IN4500(ai, COMMAND) & COMMAND_BUSY) && (delay < 10000)) { udelay (10); if ((++delay % 20) == 0) OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY); diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 37783cdd301a..dfa4bdd5597c 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -737,6 +737,7 @@ struct b43_wl { struct ieee80211_tx_control beacon_txctl; bool beacon0_uploaded; bool beacon1_uploaded; + bool beacon_templates_virgin; /* Never wrote the templates? */ struct work_struct beacon_update_trigger; /* The current QOS parameters for the 4 queues. diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 8fdba9415c04..6c3d9ea0a9f8 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1544,6 +1544,30 @@ static void b43_write_probe_resp_template(struct b43_wldev *dev, kfree(probe_resp_data); } +static void b43_upload_beacon0(struct b43_wldev *dev) +{ + struct b43_wl *wl = dev->wl; + + if (wl->beacon0_uploaded) + return; + b43_write_beacon_template(dev, 0x68, 0x18); + /* FIXME: Probe resp upload doesn't really belong here, + * but we don't use that feature anyway. */ + b43_write_probe_resp_template(dev, 0x268, 0x4A, + &__b43_ratetable[3]); + wl->beacon0_uploaded = 1; +} + +static void b43_upload_beacon1(struct b43_wldev *dev) +{ + struct b43_wl *wl = dev->wl; + + if (wl->beacon1_uploaded) + return; + b43_write_beacon_template(dev, 0x468, 0x1A); + wl->beacon1_uploaded = 1; +} + static void handle_irq_beacon(struct b43_wldev *dev) { struct b43_wl *wl = dev->wl; @@ -1568,24 +1592,27 @@ static void handle_irq_beacon(struct b43_wldev *dev) return; } - if (!beacon0_valid) { - if (!wl->beacon0_uploaded) { - b43_write_beacon_template(dev, 0x68, 0x18); - b43_write_probe_resp_template(dev, 0x268, 0x4A, - &__b43_ratetable[3]); - wl->beacon0_uploaded = 1; - } + if (unlikely(wl->beacon_templates_virgin)) { + /* We never uploaded a beacon before. + * Upload both templates now, but only mark one valid. */ + wl->beacon_templates_virgin = 0; + b43_upload_beacon0(dev); + b43_upload_beacon1(dev); cmd = b43_read32(dev, B43_MMIO_MACCMD); cmd |= B43_MACCMD_BEACON0_VALID; b43_write32(dev, B43_MMIO_MACCMD, cmd); - } else if (!beacon1_valid) { - if (!wl->beacon1_uploaded) { - b43_write_beacon_template(dev, 0x468, 0x1A); - wl->beacon1_uploaded = 1; + } else { + if (!beacon0_valid) { + b43_upload_beacon0(dev); + cmd = b43_read32(dev, B43_MMIO_MACCMD); + cmd |= B43_MACCMD_BEACON0_VALID; + b43_write32(dev, B43_MMIO_MACCMD, cmd); + } else if (!beacon1_valid) { + b43_upload_beacon1(dev); + cmd = b43_read32(dev, B43_MMIO_MACCMD); + cmd |= B43_MACCMD_BEACON1_VALID; + b43_write32(dev, B43_MMIO_MACCMD, cmd); } - cmd = b43_read32(dev, B43_MMIO_MACCMD); - cmd |= B43_MACCMD_BEACON1_VALID; - b43_write32(dev, B43_MMIO_MACCMD, cmd); } } @@ -4073,6 +4100,9 @@ static int b43_op_start(struct ieee80211_hw *hw) wl->filter_flags = 0; wl->radiotap_enabled = 0; b43_qos_clear(wl); + wl->beacon0_uploaded = 0; + wl->beacon1_uploaded = 0; + wl->beacon_templates_virgin = 1; /* First register RFkill. * LEDs that are registered later depend on it. */ @@ -4241,7 +4271,9 @@ static void b43_chip_reset(struct work_struct *work) goto out; } } - out: +out: + if (err) + wl->current_dev = NULL; /* Failed to init the dev. */ mutex_unlock(&wl->mutex); if (err) b43err(wl, "Controller restart FAILED\n"); @@ -4382,9 +4414,11 @@ static void b43_one_core_detach(struct ssb_device *dev) struct b43_wldev *wldev; struct b43_wl *wl; + /* Do not cancel ieee80211-workqueue based work here. + * See comment in b43_remove(). */ + wldev = ssb_get_drvdata(dev); wl = wldev->wl; - cancel_work_sync(&wldev->restart_work); b43_debugfs_remove_device(wldev); b43_wireless_core_detach(wldev); list_del(&wldev->list); @@ -4569,6 +4603,10 @@ static void b43_remove(struct ssb_device *dev) struct b43_wl *wl = ssb_get_devtypedata(dev); struct b43_wldev *wldev = ssb_get_drvdata(dev); + /* We must cancel any work here before unregistering from ieee80211, + * as the ieee80211 unreg will destroy the workqueue. */ + cancel_work_sync(&wldev->restart_work); + B43_WARN_ON(!wl); if (wl->current_dev == wldev) ieee80211_unregister_hw(wl->hw); diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 14a5eea2573e..204077c13870 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -3039,7 +3039,6 @@ static void b43legacy_set_pretbtt(struct b43legacy_wldev *dev) /* Locking: wl->mutex */ static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev) { - struct b43legacy_wl *wl = dev->wl; struct b43legacy_phy *phy = &dev->phy; u32 macctl; @@ -3054,12 +3053,6 @@ static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev) macctl |= B43legacy_MACCTL_PSM_JMP0; b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl); - mutex_unlock(&wl->mutex); - /* Must unlock as it would otherwise deadlock. No races here. - * Cancel possibly pending workqueues. */ - cancel_work_sync(&dev->restart_work); - mutex_lock(&wl->mutex); - b43legacy_leds_exit(dev); b43legacy_rng_exit(dev->wl); b43legacy_pio_free(dev); @@ -3486,6 +3479,8 @@ static void b43legacy_chip_reset(struct work_struct *work) } } out: + if (err) + wl->current_dev = NULL; /* Failed to init the dev. */ mutex_unlock(&wl->mutex); if (err) b43legacyerr(wl, "Controller restart FAILED\n"); @@ -3618,9 +3613,11 @@ static void b43legacy_one_core_detach(struct ssb_device *dev) struct b43legacy_wldev *wldev; struct b43legacy_wl *wl; + /* Do not cancel ieee80211-workqueue based work here. + * See comment in b43legacy_remove(). */ + wldev = ssb_get_drvdata(dev); wl = wldev->wl; - cancel_work_sync(&wldev->restart_work); b43legacy_debugfs_remove_device(wldev); b43legacy_wireless_core_detach(wldev); list_del(&wldev->list); @@ -3789,6 +3786,10 @@ static void b43legacy_remove(struct ssb_device *dev) struct b43legacy_wl *wl = ssb_get_devtypedata(dev); struct b43legacy_wldev *wldev = ssb_get_drvdata(dev); + /* We must cancel any work here before unregistering from ieee80211, + * as the ieee80211 unreg will destroy the workqueue. */ + cancel_work_sync(&wldev->restart_work); + B43legacy_WARN_ON(!wl); if (wl->current_dev == wldev) ieee80211_unregister_hw(wl->hw); diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c index 20d387f6658c..f7aec9309d04 100644 --- a/drivers/net/wireless/hostap/hostap_main.c +++ b/drivers/net/wireless/hostap/hostap_main.c @@ -682,7 +682,13 @@ static int prism2_close(struct net_device *dev) netif_device_detach(dev); } - flush_scheduled_work(); + cancel_work_sync(&local->reset_queue); + cancel_work_sync(&local->set_multicast_list_queue); + cancel_work_sync(&local->set_tim_queue); +#ifndef PRISM2_NO_STATION_MODES + cancel_work_sync(&local->info_queue); +#endif + cancel_work_sync(&local->comms_qual_update); module_put(local->hw_module); diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index d74c061994ae..6e704608947c 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -1753,6 +1753,8 @@ static int ipw_radio_kill_sw(struct ipw_priv *priv, int disable_radio) if (priv->workqueue) { cancel_delayed_work(&priv->request_scan); + cancel_delayed_work(&priv->request_direct_scan); + cancel_delayed_work(&priv->request_passive_scan); cancel_delayed_work(&priv->scan_event); } queue_work(priv->workqueue, &priv->down); @@ -2005,6 +2007,8 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) wake_up_interruptible(&priv->wait_command_queue); priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING); cancel_delayed_work(&priv->request_scan); + cancel_delayed_work(&priv->request_direct_scan); + cancel_delayed_work(&priv->request_passive_scan); cancel_delayed_work(&priv->scan_event); schedule_work(&priv->link_down); queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ); @@ -4712,6 +4716,12 @@ static void ipw_rx_notification(struct ipw_priv *priv, priv->status &= ~STATUS_SCAN_FORCED; #endif /* CONFIG_IPW2200_MONITOR */ + /* Do queued direct scans first */ + if (priv->status & STATUS_DIRECT_SCAN_PENDING) { + queue_delayed_work(priv->workqueue, + &priv->request_direct_scan, 0); + } + if (!(priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING | STATUS_ROAMING | @@ -6267,7 +6277,7 @@ static void ipw_add_scan_channels(struct ipw_priv *priv, } } -static int ipw_request_scan_helper(struct ipw_priv *priv, int type) +static int ipw_request_scan_helper(struct ipw_priv *priv, int type, int direct) { struct ipw_scan_request_ext scan; int err = 0, scan_type; @@ -6278,22 +6288,31 @@ static int ipw_request_scan_helper(struct ipw_priv *priv, int type) mutex_lock(&priv->mutex); + if (direct && (priv->direct_scan_ssid_len == 0)) { + IPW_DEBUG_HC("Direct scan requested but no SSID to scan for\n"); + priv->status &= ~STATUS_DIRECT_SCAN_PENDING; + goto done; + } + if (priv->status & STATUS_SCANNING) { - IPW_DEBUG_HC("Concurrent scan requested. Ignoring.\n"); - priv->status |= STATUS_SCAN_PENDING; + IPW_DEBUG_HC("Concurrent scan requested. Queuing.\n"); + priv->status |= direct ? STATUS_DIRECT_SCAN_PENDING : + STATUS_SCAN_PENDING; goto done; } if (!(priv->status & STATUS_SCAN_FORCED) && priv->status & STATUS_SCAN_ABORTING) { IPW_DEBUG_HC("Scan request while abort pending. Queuing.\n"); - priv->status |= STATUS_SCAN_PENDING; + priv->status |= direct ? STATUS_DIRECT_SCAN_PENDING : + STATUS_SCAN_PENDING; goto done; } if (priv->status & STATUS_RF_KILL_MASK) { - IPW_DEBUG_HC("Aborting scan due to RF Kill activation\n"); - priv->status |= STATUS_SCAN_PENDING; + IPW_DEBUG_HC("Queuing scan due to RF Kill activation\n"); + priv->status |= direct ? STATUS_DIRECT_SCAN_PENDING : + STATUS_SCAN_PENDING; goto done; } @@ -6321,6 +6340,7 @@ static int ipw_request_scan_helper(struct ipw_priv *priv, int type) cpu_to_le16(20); scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(120); + scan.dwell_time[IPW_SCAN_ACTIVE_DIRECT_SCAN] = cpu_to_le16(20); #ifdef CONFIG_IPW2200_MONITOR if (priv->ieee->iw_mode == IW_MODE_MONITOR) { @@ -6360,13 +6380,23 @@ static int ipw_request_scan_helper(struct ipw_priv *priv, int type) cpu_to_le16(2000); } else { #endif /* CONFIG_IPW2200_MONITOR */ - /* If we are roaming, then make this a directed scan for the - * current network. Otherwise, ensure that every other scan - * is a fast channel hop scan */ - if ((priv->status & STATUS_ROAMING) - || (!(priv->status & STATUS_ASSOCIATED) - && (priv->config & CFG_STATIC_ESSID) - && (le32_to_cpu(scan.full_scan_index) % 2))) { + /* Honor direct scans first, otherwise if we are roaming make + * this a direct scan for the current network. Finally, + * ensure that every other scan is a fast channel hop scan */ + if (direct) { + err = ipw_send_ssid(priv, priv->direct_scan_ssid, + priv->direct_scan_ssid_len); + if (err) { + IPW_DEBUG_HC("Attempt to send SSID command " + "failed\n"); + goto done; + } + + scan_type = IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN; + } else if ((priv->status & STATUS_ROAMING) + || (!(priv->status & STATUS_ASSOCIATED) + && (priv->config & CFG_STATIC_ESSID) + && (le32_to_cpu(scan.full_scan_index) % 2))) { err = ipw_send_ssid(priv, priv->essid, priv->essid_len); if (err) { IPW_DEBUG_HC("Attempt to send SSID command " @@ -6391,7 +6421,12 @@ send_request: } priv->status |= STATUS_SCANNING; - priv->status &= ~STATUS_SCAN_PENDING; + if (direct) { + priv->status &= ~STATUS_DIRECT_SCAN_PENDING; + priv->direct_scan_ssid_len = 0; + } else + priv->status &= ~STATUS_SCAN_PENDING; + queue_delayed_work(priv->workqueue, &priv->scan_check, IPW_SCAN_CHECK_WATCHDOG); done: @@ -6402,15 +6437,22 @@ done: static void ipw_request_passive_scan(struct work_struct *work) { struct ipw_priv *priv = - container_of(work, struct ipw_priv, request_passive_scan); - ipw_request_scan_helper(priv, IW_SCAN_TYPE_PASSIVE); + container_of(work, struct ipw_priv, request_passive_scan.work); + ipw_request_scan_helper(priv, IW_SCAN_TYPE_PASSIVE, 0); } static void ipw_request_scan(struct work_struct *work) { struct ipw_priv *priv = container_of(work, struct ipw_priv, request_scan.work); - ipw_request_scan_helper(priv, IW_SCAN_TYPE_ACTIVE); + ipw_request_scan_helper(priv, IW_SCAN_TYPE_ACTIVE, 0); +} + +static void ipw_request_direct_scan(struct work_struct *work) +{ + struct ipw_priv *priv = + container_of(work, struct ipw_priv, request_direct_scan.work); + ipw_request_scan_helper(priv, IW_SCAN_TYPE_ACTIVE, 1); } static void ipw_bg_abort_scan(struct work_struct *work) @@ -7558,8 +7600,31 @@ static int ipw_associate(void *data) priv->ieee->iw_mode == IW_MODE_ADHOC && priv->config & CFG_ADHOC_CREATE && priv->config & CFG_STATIC_ESSID && - priv->config & CFG_STATIC_CHANNEL && - !list_empty(&priv->ieee->network_free_list)) { + priv->config & CFG_STATIC_CHANNEL) { + /* Use oldest network if the free list is empty */ + if (list_empty(&priv->ieee->network_free_list)) { + struct ieee80211_network *oldest = NULL; + struct ieee80211_network *target; + DECLARE_MAC_BUF(mac); + + list_for_each_entry(target, &priv->ieee->network_list, list) { + if ((oldest == NULL) || + (target->last_scanned < oldest->last_scanned)) + oldest = target; + } + + /* If there are no more slots, expire the oldest */ + list_del(&oldest->list); + target = oldest; + IPW_DEBUG_ASSOC("Expired '%s' (%s) from " + "network list.\n", + escape_essid(target->ssid, + target->ssid_len), + print_mac(mac, target->bssid)); + list_add_tail(&target->list, + &priv->ieee->network_free_list); + } + element = priv->ieee->network_free_list.next; network = list_entry(element, struct ieee80211_network, list); ipw_adhoc_create(priv, network); @@ -9454,99 +9519,38 @@ static int ipw_wx_get_retry(struct net_device *dev, return 0; } -static int ipw_request_direct_scan(struct ipw_priv *priv, char *essid, - int essid_len) -{ - struct ipw_scan_request_ext scan; - int err = 0, scan_type; - - if (!(priv->status & STATUS_INIT) || - (priv->status & STATUS_EXIT_PENDING)) - return 0; - - mutex_lock(&priv->mutex); - - if (priv->status & STATUS_RF_KILL_MASK) { - IPW_DEBUG_HC("Aborting scan due to RF kill activation\n"); - priv->status |= STATUS_SCAN_PENDING; - goto done; - } - - IPW_DEBUG_HC("starting request direct scan!\n"); - - if (priv->status & (STATUS_SCANNING | STATUS_SCAN_ABORTING)) { - /* We should not sleep here; otherwise we will block most - * of the system (for instance, we hold rtnl_lock when we - * get here). - */ - err = -EAGAIN; - goto done; - } - memset(&scan, 0, sizeof(scan)); - - if (priv->config & CFG_SPEED_SCAN) - scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] = - cpu_to_le16(30); - else - scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] = - cpu_to_le16(20); - - scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] = - cpu_to_le16(20); - scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(120); - scan.dwell_time[IPW_SCAN_ACTIVE_DIRECT_SCAN] = cpu_to_le16(20); - - scan.full_scan_index = cpu_to_le32(ieee80211_get_scans(priv->ieee)); - - err = ipw_send_ssid(priv, essid, essid_len); - if (err) { - IPW_DEBUG_HC("Attempt to send SSID command failed\n"); - goto done; - } - scan_type = IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN; - - ipw_add_scan_channels(priv, &scan, scan_type); - - err = ipw_send_scan_request_ext(priv, &scan); - if (err) { - IPW_DEBUG_HC("Sending scan command failed: %08X\n", err); - goto done; - } - - priv->status |= STATUS_SCANNING; - - done: - mutex_unlock(&priv->mutex); - return err; -} - static int ipw_wx_set_scan(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); struct iw_scan_req *req = (struct iw_scan_req *)extra; + struct delayed_work *work = NULL; mutex_lock(&priv->mutex); + priv->user_requested_scan = 1; - mutex_unlock(&priv->mutex); if (wrqu->data.length == sizeof(struct iw_scan_req)) { if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { - ipw_request_direct_scan(priv, req->essid, - req->essid_len); - return 0; - } - if (req->scan_type == IW_SCAN_TYPE_PASSIVE) { - queue_work(priv->workqueue, - &priv->request_passive_scan); - return 0; + int len = min((int)req->essid_len, + (int)sizeof(priv->direct_scan_ssid)); + memcpy(priv->direct_scan_ssid, req->essid, len); + priv->direct_scan_ssid_len = len; + work = &priv->request_direct_scan; + } else if (req->scan_type == IW_SCAN_TYPE_PASSIVE) { + work = &priv->request_passive_scan; } + } else { + /* Normal active broadcast scan */ + work = &priv->request_scan; } + mutex_unlock(&priv->mutex); + IPW_DEBUG_WX("Start scan\n"); - queue_delayed_work(priv->workqueue, &priv->request_scan, 0); + queue_delayed_work(priv->workqueue, work, 0); return 0; } @@ -10708,6 +10712,8 @@ static void ipw_link_up(struct ipw_priv *priv) } cancel_delayed_work(&priv->request_scan); + cancel_delayed_work(&priv->request_direct_scan); + cancel_delayed_work(&priv->request_passive_scan); cancel_delayed_work(&priv->scan_event); ipw_reset_stats(priv); /* Ensure the rate is updated immediately */ @@ -10738,6 +10744,8 @@ static void ipw_link_down(struct ipw_priv *priv) /* Cancel any queued work ... */ cancel_delayed_work(&priv->request_scan); + cancel_delayed_work(&priv->request_direct_scan); + cancel_delayed_work(&priv->request_passive_scan); cancel_delayed_work(&priv->adhoc_check); cancel_delayed_work(&priv->gather_stats); @@ -10777,8 +10785,9 @@ static int __devinit ipw_setup_deferred_work(struct ipw_priv *priv) INIT_WORK(&priv->up, ipw_bg_up); INIT_WORK(&priv->down, ipw_bg_down); INIT_DELAYED_WORK(&priv->request_scan, ipw_request_scan); + INIT_DELAYED_WORK(&priv->request_direct_scan, ipw_request_direct_scan); + INIT_DELAYED_WORK(&priv->request_passive_scan, ipw_request_passive_scan); INIT_DELAYED_WORK(&priv->scan_event, ipw_scan_event); - INIT_WORK(&priv->request_passive_scan, ipw_request_passive_scan); INIT_DELAYED_WORK(&priv->gather_stats, ipw_bg_gather_stats); INIT_WORK(&priv->abort_scan, ipw_bg_abort_scan); INIT_WORK(&priv->roam, ipw_bg_roam); @@ -11812,6 +11821,8 @@ static void __devexit ipw_pci_remove(struct pci_dev *pdev) cancel_delayed_work(&priv->adhoc_check); cancel_delayed_work(&priv->gather_stats); cancel_delayed_work(&priv->request_scan); + cancel_delayed_work(&priv->request_direct_scan); + cancel_delayed_work(&priv->request_passive_scan); cancel_delayed_work(&priv->scan_event); cancel_delayed_work(&priv->rf_kill); cancel_delayed_work(&priv->scan_check); diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index cd3295b66dd6..d4ab28b73b32 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -1037,6 +1037,7 @@ struct ipw_cmd { /* XXX */ #define STATUS_DISASSOC_PENDING (1<<12) #define STATUS_STATE_PENDING (1<<13) +#define STATUS_DIRECT_SCAN_PENDING (1<<19) #define STATUS_SCAN_PENDING (1<<20) #define STATUS_SCANNING (1<<21) #define STATUS_SCAN_ABORTING (1<<22) @@ -1292,6 +1293,8 @@ struct ipw_priv { struct iw_public_data wireless_data; int user_requested_scan; + u8 direct_scan_ssid[IW_ESSID_MAX_SIZE]; + u8 direct_scan_ssid_len; struct workqueue_struct *workqueue; @@ -1301,8 +1304,9 @@ struct ipw_priv { struct work_struct system_config; struct work_struct rx_replenish; struct delayed_work request_scan; + struct delayed_work request_direct_scan; + struct delayed_work request_passive_scan; struct delayed_work scan_event; - struct work_struct request_passive_scan; struct work_struct adapter_restart; struct delayed_work rf_kill; struct work_struct up; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index d200d08fb086..8b1528e52d43 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c @@ -229,14 +229,15 @@ static int iwl3945_led_register_led(struct iwl3945_priv *priv, led->led_dev.brightness_set = iwl3945_led_brightness_set; led->led_dev.default_trigger = trigger; + led->priv = priv; + led->type = type; + ret = led_classdev_register(device, &led->led_dev); if (ret) { IWL_ERROR("Error: failed to register led handler.\n"); return ret; } - led->priv = priv; - led->type = type; led->registered = 1; if (set_led && led->led_on) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index c9847b1a67f7..3a7f0cb710ec 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c @@ -1162,7 +1162,6 @@ static s32 rs_get_best_rate(struct iwl_priv *priv, /* Higher rate not available, use the original */ } else { - new_rate = rate; break; } } @@ -2009,7 +2008,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, * 2) Not just finishing up a search * 3) Allowing a new search */ - if (!update_lq && !done_search && !lq_sta->stay_in_tbl) { + if (!update_lq && !done_search && !lq_sta->stay_in_tbl && window->counter) { /* Save current throughput to compare with "search" throughput*/ lq_sta->last_tpt = current_tpt; diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 6328b9593877..8124fd9b1353 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -1842,6 +1842,9 @@ static void lbs_send_confirmsleep(struct lbs_private *priv) spin_lock_irqsave(&priv->driver_lock, flags); + /* We don't get a response on the sleep-confirmation */ + priv->dnld_sent = DNLD_RES_RECEIVED; + /* If nothing to do, go back to sleep (?) */ if (!__kfifo_len(priv->event_fifo) && !priv->resp_len[priv->resp_idx]) priv->psstate = PS_STATE_SLEEP; @@ -1904,12 +1907,12 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv) lbs_deb_enter(LBS_DEB_HOST); + spin_lock_irqsave(&priv->driver_lock, flags); if (priv->dnld_sent) { allowed = 0; lbs_deb_host("dnld_sent was set\n"); } - spin_lock_irqsave(&priv->driver_lock, flags); /* In-progress command? */ if (priv->cur_cmd) { allowed = 0; diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index ad2fabca9116..0aa0ce3b2c42 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c @@ -312,8 +312,8 @@ static ssize_t lbs_threshold_write(uint16_t tlv_type, uint16_t event_mask, if (tlv_type != TLV_TYPE_BCNMISS) tlv->freq = freq; - /* The command header, the event mask, and the one TLV */ - events->hdr.size = cpu_to_le16(sizeof(events->hdr) + 2 + sizeof(*tlv)); + /* The command header, the action, the event mask, and one TLV */ + events->hdr.size = cpu_to_le16(sizeof(events->hdr) + 4 + sizeof(*tlv)); ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, events); diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index e1f066068590..acfc4bfcc262 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -732,8 +732,8 @@ static int lbs_thread(void *data) lbs_deb_thread("4: currenttxskb %p, dnld_sent %d\n", priv->currenttxskb, priv->dnld_sent); - spin_lock_irq(&priv->driver_lock); /* Process any pending command response */ + spin_lock_irq(&priv->driver_lock); resp_idx = priv->resp_idx; if (priv->resp_len[resp_idx]) { spin_unlock_irq(&priv->driver_lock); diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 98ddbb3b3273..1610a7308c1d 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -49,6 +49,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x5041, 0x2235)}, /* Linksys WUSB54G Portable */ /* Version 2 devices (3887) */ + {USB_DEVICE(0x0471, 0x1230)}, /* Philips CPWUA054/00 */ {USB_DEVICE(0x050d, 0x7050)}, /* Belkin F5D7050 ver 1000 */ {USB_DEVICE(0x0572, 0x2000)}, /* Cohiba Proto board */ {USB_DEVICE(0x0572, 0x2002)}, /* Cohiba Proto board */ diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index d0b1fb15c709..18c9931e3267 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -116,6 +116,7 @@ MODULE_PARM_DESC(workaround_interval, #define OID_802_11_ENCRYPTION_STATUS ccpu2(0x0d01011b) #define OID_802_11_ADD_KEY ccpu2(0x0d01011d) #define OID_802_11_REMOVE_KEY ccpu2(0x0d01011e) +#define OID_802_11_ASSOCIATION_INFORMATION ccpu2(0x0d01011f) #define OID_802_11_PMKID ccpu2(0x0d010123) #define OID_802_11_NETWORK_TYPES_SUPPORTED ccpu2(0x0d010203) #define OID_802_11_NETWORK_TYPE_IN_USE ccpu2(0x0d010204) @@ -271,6 +272,26 @@ struct ndis_config_param { __le32 value_length; } __attribute__((packed)); +struct ndis_80211_assoc_info { + __le32 length; + __le16 req_ies; + struct req_ie { + __le16 capa; + __le16 listen_interval; + u8 cur_ap_address[6]; + } req_ie; + __le32 req_ie_length; + __le32 offset_req_ies; + __le16 resp_ies; + struct resp_ie { + __le16 capa; + __le16 status_code; + __le16 assoc_id; + } resp_ie; + __le32 resp_ie_length; + __le32 offset_resp_ies; +} __attribute__((packed)); + /* these have to match what is in wpa_supplicant */ enum wpa_alg { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP }; enum wpa_cipher { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP, @@ -674,6 +695,12 @@ static int get_bssid(struct usbnet *usbdev, u8 bssid[ETH_ALEN]) return ret; } +static int get_association_info(struct usbnet *usbdev, + struct ndis_80211_assoc_info *info, int len) +{ + return rndis_query_oid(usbdev, OID_802_11_ASSOCIATION_INFORMATION, + info, &len); +} static int is_associated(struct usbnet *usbdev) { @@ -2182,11 +2209,40 @@ static void rndis_wext_worker(struct work_struct *work) struct usbnet *usbdev = priv->usbdev; union iwreq_data evt; unsigned char bssid[ETH_ALEN]; - int ret; + struct ndis_80211_assoc_info *info; + int assoc_size = sizeof(*info) + IW_CUSTOM_MAX + 32; + int ret, offset; if (test_and_clear_bit(WORK_CONNECTION_EVENT, &priv->work_pending)) { - ret = get_bssid(usbdev, bssid); + info = kzalloc(assoc_size, GFP_KERNEL); + if (!info) + goto get_bssid; + + /* Get association info IEs from device and send them back to + * userspace. */ + ret = get_association_info(usbdev, info, assoc_size); + if (!ret) { + evt.data.length = le32_to_cpu(info->req_ie_length); + if (evt.data.length > 0) { + offset = le32_to_cpu(info->offset_req_ies); + wireless_send_event(usbdev->net, + IWEVASSOCREQIE, &evt, + (char *)info + offset); + } + + evt.data.length = le32_to_cpu(info->resp_ie_length); + if (evt.data.length > 0) { + offset = le32_to_cpu(info->offset_resp_ies); + wireless_send_event(usbdev->net, + IWEVASSOCRESPIE, &evt, + (char *)info + offset); + } + } + + kfree(info); +get_bssid: + ret = get_bssid(usbdev, bssid); if (!ret) { evt.data.flags = 0; evt.data.length = 0; @@ -2414,6 +2470,11 @@ static int bcm4320_early_init(struct usbnet *dev) else if (priv->param_power_save > 2) priv->param_power_save = 2; + if (priv->param_power_output < 0) + priv->param_power_output = 0; + else if (priv->param_power_output > 3) + priv->param_power_output = 3; + if (priv->param_roamtrigger < -80) priv->param_roamtrigger = -80; else if (priv->param_roamtrigger > -60) diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 57bdc153952f..611d98320593 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -328,6 +328,11 @@ static inline int rt2x00_get_link_ant_rssi(struct link *link) return DEFAULT_RSSI; } +static inline void rt2x00_reset_link_ant_rssi(struct link *link) +{ + link->ant.rssi_ant = 0; +} + static inline int rt2x00_get_link_ant_rssi_history(struct link *link, enum antenna ant) { diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index a9930a03f450..48608e8cc8b4 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -129,6 +129,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, */ rt2x00dev->ops->lib->config(rt2x00dev, &libconf, CONFIG_UPDATE_ANTENNA); rt2x00lib_reset_link_tuner(rt2x00dev); + rt2x00_reset_link_ant_rssi(&rt2x00dev->link); rt2x00dev->link.ant.active.rx = libconf.ant.rx; rt2x00dev->link.ant.active.tx = libconf.ant.tx; diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index b22c02737185..2673d568bcac 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -483,9 +483,9 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) return; - ieee80211_iterate_active_interfaces(rt2x00dev->hw, - rt2x00lib_beacondone_iter, - rt2x00dev); + ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw, + rt2x00lib_beacondone_iter, + rt2x00dev); queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work); } @@ -507,7 +507,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, * Update TX statistics. */ rt2x00dev->link.qual.tx_success += success; - rt2x00dev->link.qual.tx_failed += txdesc->retry + fail; + rt2x00dev->link.qual.tx_failed += fail; /* * Initialize TX status diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index c206b5092070..87e280a21971 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -93,6 +93,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, */ if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags)) { ieee80211_stop_queues(hw); + dev_kfree_skb_any(skb); return NETDEV_TX_OK; } diff --git a/drivers/net/wireless/rtl8180_grf5101.c b/drivers/net/wireless/rtl8180_grf5101.c index 5d47935dbac3..947ee55f18b2 100644 --- a/drivers/net/wireless/rtl8180_grf5101.c +++ b/drivers/net/wireless/rtl8180_grf5101.c @@ -88,7 +88,7 @@ static void grf5101_rf_set_channel(struct ieee80211_hw *dev, write_grf5101(dev, 0x0B, chan); write_grf5101(dev, 0x07, 0x1000); - grf5101_write_phy_antenna(dev, chan); + grf5101_write_phy_antenna(dev, channel); } static void grf5101_rf_stop(struct ieee80211_hw *dev) diff --git a/drivers/net/wireless/rtl8180_max2820.c b/drivers/net/wireless/rtl8180_max2820.c index a34dfd382b6d..6c825fd7f3b6 100644 --- a/drivers/net/wireless/rtl8180_max2820.c +++ b/drivers/net/wireless/rtl8180_max2820.c @@ -78,7 +78,8 @@ static void max2820_rf_set_channel(struct ieee80211_hw *dev, struct ieee80211_conf *conf) { struct rtl8180_priv *priv = dev->priv; - int channel = ieee80211_frequency_to_channel(conf->channel->center_freq); + int channel = conf ? + ieee80211_frequency_to_channel(conf->channel->center_freq) : 1; unsigned int chan_idx = channel - 1; u32 txpw = priv->channels[chan_idx].hw_value & 0xFF; u32 chan = max2820_chan[chan_idx]; @@ -87,7 +88,7 @@ static void max2820_rf_set_channel(struct ieee80211_hw *dev, * sa2400, for MAXIM we do this directly from BB */ rtl8180_write_phy(dev, 3, txpw); - max2820_write_phy_antenna(dev, chan); + max2820_write_phy_antenna(dev, channel); write_max2820(dev, 3, chan); } diff --git a/drivers/net/wireless/rtl8180_sa2400.c b/drivers/net/wireless/rtl8180_sa2400.c index 0311b4ea124c..cea4e0ccb92d 100644 --- a/drivers/net/wireless/rtl8180_sa2400.c +++ b/drivers/net/wireless/rtl8180_sa2400.c @@ -86,7 +86,7 @@ static void sa2400_rf_set_channel(struct ieee80211_hw *dev, write_sa2400(dev, 7, txpw); - sa2400_write_phy_antenna(dev, chan); + sa2400_write_phy_antenna(dev, channel); write_sa2400(dev, 0, chan); write_sa2400(dev, 1, 0xbb50); diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 6424e5a2c83d..418606ac1c3b 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -719,7 +719,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) fc = le16_to_cpu(*((__le16 *) buffer)); is_qos = ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) && - ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_QOS_DATA); + (fc & IEEE80211_STYPE_QOS_DATA); is_4addr = (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS); need_padding = is_qos ^ is_4addr; diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c index 715a44471617..b2ccdcbeb896 100644 --- a/drivers/of/of_i2c.c +++ b/drivers/of/of_i2c.c @@ -21,7 +21,6 @@ struct i2c_driver_device { }; static struct i2c_driver_device i2c_devices[] = { - { "dallas,ds1374", "rtc-ds1374" }, }; static int of_find_i2c_driver(struct device_node *node, diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index 925ba16355ce..a11021e8ce37 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c @@ -619,6 +619,7 @@ static struct hotplug_slot *get_slot_from_name (const char *name) int pci_hp_register (struct hotplug_slot *slot) { int result; + struct hotplug_slot *tmp; if (slot == NULL) return -ENODEV; @@ -630,7 +631,11 @@ int pci_hp_register (struct hotplug_slot *slot) return -EINVAL; } - /* this can fail if we have already registered a slot with the same name */ + /* Check if we have already registered a slot with the same name. */ + tmp = get_slot_from_name(slot->name); + if (tmp) + return -EEXIST; + slot->kobj.kset = pci_hotplug_slots_kset; result = kobject_init_and_add(&slot->kobj, &hotplug_slot_ktype, NULL, "%s", slot->name); diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 8264a7680435..79c9ddaad3fb 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -97,6 +97,7 @@ struct controller { u8 cap_base; struct timer_list poll_timer; volatile int cmd_busy; + unsigned int no_cmd_complete:1; }; #define INT_BUTTON_IGNORE 0 @@ -135,6 +136,7 @@ struct controller { #define PWR_LED_PRSN 0x00000010 #define HP_SUPR_RM_SUP 0x00000020 #define EMI_PRSN 0x00020000 +#define NO_CMD_CMPL_SUP 0x00040000 #define ATTN_BUTTN(ctrl) ((ctrl)->slot_cap & ATTN_BUTTN_PRSN) #define POWER_CTRL(ctrl) ((ctrl)->slot_cap & PWR_CTRL_PRSN) @@ -143,13 +145,14 @@ struct controller { #define PWR_LED(ctrl) ((ctrl)->slot_cap & PWR_LED_PRSN) #define HP_SUPR_RM(ctrl) ((ctrl)->slot_cap & HP_SUPR_RM_SUP) #define EMI(ctrl) ((ctrl)->slot_cap & EMI_PRSN) +#define NO_CMD_CMPL(ctrl) ((ctrl)->slot_cap & NO_CMD_CMPL_SUP) extern int pciehp_sysfs_enable_slot(struct slot *slot); extern int pciehp_sysfs_disable_slot(struct slot *slot); -extern u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl); -extern u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl); -extern u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl); -extern u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl); +extern u8 pciehp_handle_attention_button(struct slot *p_slot); + extern u8 pciehp_handle_switch_change(struct slot *p_slot); +extern u8 pciehp_handle_presence_change(struct slot *p_slot); +extern u8 pciehp_handle_power_fault(struct slot *p_slot); extern int pciehp_configure_device(struct slot *p_slot); extern int pciehp_unconfigure_device(struct slot *p_slot); extern void pciehp_queue_pushbutton_work(struct work_struct *work); diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 43d8ddb2d679..48a2ed378914 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -254,7 +254,11 @@ static int init_slots(struct controller *ctrl) slot->hp_slot, slot->number, ctrl->slot_device_offset); retval = pci_hp_register(hotplug_slot); if (retval) { - err ("pci_hp_register failed with error %d\n", retval); + err("pci_hp_register failed with error %d\n", retval); + if (retval == -EEXIST) + err("Failed to register slot because of name " + "collision. Try \'pciehp_slot_with_bus\' " + "module option.\n"); goto error_info; } /* create additional sysfs entries */ diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 0a7aa628e955..96a5d55a4983 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -55,16 +55,13 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type) return 0; } -u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl) +u8 pciehp_handle_attention_button(struct slot *p_slot) { - struct slot *p_slot; u32 event_type; /* Attention Button Change */ dbg("pciehp: Attention button interrupt received.\n"); - p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); - /* * Button pressed - See if need to TAKE ACTION!!! */ @@ -76,18 +73,15 @@ u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl) return 0; } -u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl) +u8 pciehp_handle_switch_change(struct slot *p_slot) { - struct slot *p_slot; u8 getstatus; u32 event_type; /* Switch Change */ dbg("pciehp: Switch interrupt received.\n"); - p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); - if (getstatus) { /* * Switch opened @@ -107,17 +101,14 @@ u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl) return 1; } -u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl) +u8 pciehp_handle_presence_change(struct slot *p_slot) { - struct slot *p_slot; u32 event_type; u8 presence_save; /* Presence Change */ dbg("pciehp: Presence/Notify input change.\n"); - p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); - /* Switch is open, assume a presence change * Save the presence state */ @@ -141,16 +132,13 @@ u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl) return 1; } -u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl) +u8 pciehp_handle_power_fault(struct slot *p_slot) { - struct slot *p_slot; u32 event_type; /* power fault */ dbg("pciehp: Power fault interrupt received.\n"); - p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); - if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) { /* * power fault Cleared @@ -163,7 +151,7 @@ u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl) */ info("Power fault on Slot(%s)\n", p_slot->name); event_type = INT_POWER_FAULT; - info("power fault bit %x set\n", hp_slot); + info("power fault bit %x set\n", 0); } queue_interrupt_event(p_slot, event_type); @@ -186,6 +174,13 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) } } + /* + * After turning power off, we must wait for at least 1 second + * before taking any action that relies on power having been + * removed from the slot/adapter. + */ + msleep(1000); + if (PWR_LED(ctrl)) pslot->hpc_ops->green_led_off(pslot); @@ -289,6 +284,13 @@ static int remove_board(struct slot *p_slot) } } + /* + * After turning power off, we must wait for at least 1 second + * before taking any action that relies on power having been + * removed from the slot/adapter. + */ + msleep(1000); + if (PWR_LED(ctrl)) /* turn off Green LED */ p_slot->hpc_ops->green_led_off(p_slot); diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 891f81a0400c..79f104963166 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -247,14 +247,38 @@ static inline void pciehp_free_irq(struct controller *ctrl) free_irq(ctrl->pci_dev->irq, ctrl); } -static inline int pcie_wait_cmd(struct controller *ctrl) +static inline int pcie_poll_cmd(struct controller *ctrl) +{ + u16 slot_status; + int timeout = 1000; + + if (!pciehp_readw(ctrl, SLOTSTATUS, &slot_status)) + if (slot_status & CMD_COMPLETED) + goto completed; + for (timeout = 1000; timeout > 0; timeout -= 100) { + msleep(100); + if (!pciehp_readw(ctrl, SLOTSTATUS, &slot_status)) + if (slot_status & CMD_COMPLETED) + goto completed; + } + return 0; /* timeout */ + +completed: + pciehp_writew(ctrl, SLOTSTATUS, CMD_COMPLETED); + return timeout; +} + +static inline int pcie_wait_cmd(struct controller *ctrl, int poll) { int retval = 0; unsigned int msecs = pciehp_poll_mode ? 2500 : 1000; unsigned long timeout = msecs_to_jiffies(msecs); int rc; - rc = wait_event_interruptible_timeout(ctrl->queue, + if (poll) + rc = pcie_poll_cmd(ctrl); + else + rc = wait_event_interruptible_timeout(ctrl->queue, !ctrl->cmd_busy, timeout); if (!rc) dbg("Command not completed in 1000 msec\n"); @@ -286,12 +310,28 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) goto out; } - if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) { - /* After 1 sec and CMD_COMPLETED still not set, just - proceed forward to issue the next command according - to spec. Just print out the error message */ - dbg("%s: CMD_COMPLETED not clear after 1 sec.\n", - __func__); + if (slot_status & CMD_COMPLETED) { + if (!ctrl->no_cmd_complete) { + /* + * After 1 sec and CMD_COMPLETED still not set, just + * proceed forward to issue the next command according + * to spec. Just print out the error message. + */ + dbg("%s: CMD_COMPLETED not clear after 1 sec.\n", + __func__); + } else if (!NO_CMD_CMPL(ctrl)) { + /* + * This controller semms to notify of command completed + * event even though it supports none of power + * controller, attention led, power led and EMI. + */ + dbg("%s: Unexpected CMD_COMPLETED. Need to wait for " + "command completed event.\n", __func__); + ctrl->no_cmd_complete = 0; + } else { + dbg("%s: Unexpected CMD_COMPLETED. Maybe the " + "controller is broken.\n", __func__); + } } retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); @@ -315,8 +355,18 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) /* * Wait for command completion. */ - if (!retval) - retval = pcie_wait_cmd(ctrl); + if (!retval && !ctrl->no_cmd_complete) { + int poll = 0; + /* + * if hotplug interrupt is not enabled or command + * completed interrupt is not enabled, we need to poll + * command completed event. + */ + if (!(slot_ctrl & HP_INTR_ENABLE) || + !(slot_ctrl & CMD_CMPL_INTR_ENABLE)) + poll = 1; + retval = pcie_wait_cmd(ctrl, poll); + } out: mutex_unlock(&ctrl->ctrl_lock); return retval; @@ -704,13 +754,6 @@ static int hpc_power_off_slot(struct slot * slot) } dbg("%s: SLOTCTRL %x write cmd %x\n", __func__, ctrl->cap_base + SLOTCTRL, slot_cmd); - - /* - * After turning power off, we must wait for at least 1 second - * before taking any action that relies on power having been - * removed from the slot/adapter. - */ - msleep(1000); out: if (changed) pcie_unmask_bad_dllp(ctrl); @@ -722,6 +765,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) { struct controller *ctrl = (struct controller *)dev_id; u16 detected, intr_loc; + struct slot *p_slot; /* * In order to guarantee that all interrupt events are @@ -756,21 +800,38 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) wake_up_interruptible(&ctrl->queue); } + if (!(intr_loc & ~CMD_COMPLETED)) + return IRQ_HANDLED; + + /* + * Return without handling events if this handler routine is + * called before controller initialization is done. This may + * happen if hotplug event or another interrupt that shares + * the IRQ with pciehp arrives before slot initialization is + * done after interrupt handler is registered. + * + * FIXME - Need more structural fixes. We need to be ready to + * handle the event before installing interrupt handler. + */ + p_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); + if (!p_slot || !p_slot->hpc_ops) + return IRQ_HANDLED; + /* Check MRL Sensor Changed */ if (intr_loc & MRL_SENS_CHANGED) - pciehp_handle_switch_change(0, ctrl); + pciehp_handle_switch_change(p_slot); /* Check Attention Button Pressed */ if (intr_loc & ATTN_BUTTN_PRESSED) - pciehp_handle_attention_button(0, ctrl); + pciehp_handle_attention_button(p_slot); /* Check Presence Detect Changed */ if (intr_loc & PRSN_DETECT_CHANGED) - pciehp_handle_presence_change(0, ctrl); + pciehp_handle_presence_change(p_slot); /* Check Power Fault Detected */ if (intr_loc & PWR_FAULT_DETECTED) - pciehp_handle_power_fault(0, ctrl); + pciehp_handle_power_fault(p_slot); return IRQ_HANDLED; } @@ -1028,6 +1089,12 @@ static int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev) static int pcie_init_hardware_part1(struct controller *ctrl, struct pcie_device *dev) { + /* Clear all remaining event bits in Slot Status register */ + if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f)) { + err("%s: Cannot write to SLOTSTATUS register\n", __func__); + return -1; + } + /* Mask Hot-plug Interrupt Enable */ if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE)) { err("%s: Cannot mask hotplug interrupt enable\n", __func__); @@ -1040,16 +1107,6 @@ int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev) { u16 cmd, mask; - /* - * We need to clear all events before enabling hotplug interrupt - * notification mechanism in order for hotplug controler to - * generate interrupts. - */ - if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f)) { - err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__); - return -1; - } - cmd = PRSN_DETECT_ENABLE; if (ATTN_BUTTN(ctrl)) cmd |= ATTN_BUTTN_ENABLE; @@ -1116,6 +1173,7 @@ static inline void dbg_ctrl(struct controller *ctrl) dbg(" Power Indicator : %3s\n", PWR_LED(ctrl) ? "yes" : "no"); dbg(" Hot-Plug Surprise : %3s\n", HP_SUPR_RM(ctrl) ? "yes" : "no"); dbg(" EMI Present : %3s\n", EMI(ctrl) ? "yes" : "no"); + dbg(" Comamnd Completed : %3s\n", NO_CMD_CMPL(ctrl)? "no" : "yes"); pciehp_readw(ctrl, SLOTSTATUS, ®16); dbg("Slot Status : 0x%04x\n", reg16); pciehp_readw(ctrl, SLOTSTATUS, ®16); @@ -1147,6 +1205,15 @@ int pcie_init(struct controller *ctrl, struct pcie_device *dev) mutex_init(&ctrl->ctrl_lock); init_waitqueue_head(&ctrl->queue); dbg_ctrl(ctrl); + /* + * Controller doesn't notify of command completion if the "No + * Command Completed Support" bit is set in Slot Capability + * register or the controller supports none of power + * controller, attention led, power led and EMI. + */ + if (NO_CMD_CMPL(ctrl) || + !(POWER_CTRL(ctrl) | ATTN_LED(ctrl) | PWR_LED(ctrl) | EMI(ctrl))) + ctrl->no_cmd_complete = 1; info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, diff --git a/drivers/pci/hotplug/rpadlpar_sysfs.c b/drivers/pci/hotplug/rpadlpar_sysfs.c index e32148a8fa12..779c5db71be4 100644 --- a/drivers/pci/hotplug/rpadlpar_sysfs.c +++ b/drivers/pci/hotplug/rpadlpar_sysfs.c @@ -18,8 +18,12 @@ #include "rpadlpar.h" #define DLPAR_KOBJ_NAME "control" -#define ADD_SLOT_ATTR_NAME "add_slot" -#define REMOVE_SLOT_ATTR_NAME "remove_slot" + +/* Those two have no quotes because they are passed to __ATTR() which + * stringifies the argument (yuck !) + */ +#define ADD_SLOT_ATTR_NAME add_slot +#define REMOVE_SLOT_ATTR_NAME remove_slot #define MAX_DRC_NAME_LEN 64 diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 1648076600fc..97848654652a 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -162,6 +162,10 @@ static int init_slots(struct controller *ctrl) retval = pci_hp_register(slot->hotplug_slot); if (retval) { err("pci_hp_register failed with error %d\n", retval); + if (retval == -EEXIST) + err("Failed to register slot because of name " + "collision. Try \'shpchp_slot_with_bus\' " + "module option.\n"); goto error_info; } diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 72cf61ed8f96..e1637bd82b8e 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -181,7 +181,7 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev, any need to change it. */ struct mempolicy *oldpol; cpumask_t oldmask = current->cpus_allowed; - int node = pcibus_to_node(dev->bus); + int node = dev_to_node(&dev->dev); if (node >= 0) { node_to_cpumask_ptr(nodecpumask, node); diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 271d41cc05ab..6f3c7446c329 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -489,13 +489,13 @@ pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr, * @kobj: kobject for mapping * @attr: struct bin_attribute for the file being mapped * @vma: struct vm_area_struct passed into the mmap + * @write_combine: 1 for write_combine mapping * * Use the regular PCI mapping routines to map a PCI resource into userspace. - * FIXME: write combining? maybe automatic for prefetchable regions? */ static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, - struct vm_area_struct *vma) + struct vm_area_struct *vma, int write_combine) { struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj)); @@ -518,7 +518,21 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, vma->vm_pgoff += start >> PAGE_SHIFT; mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io; - return pci_mmap_page_range(pdev, vma, mmap_type, 0); + return pci_mmap_page_range(pdev, vma, mmap_type, write_combine); +} + +static int +pci_mmap_resource_uc(struct kobject *kobj, struct bin_attribute *attr, + struct vm_area_struct *vma) +{ + return pci_mmap_resource(kobj, attr, vma, 0); +} + +static int +pci_mmap_resource_wc(struct kobject *kobj, struct bin_attribute *attr, + struct vm_area_struct *vma) +{ + return pci_mmap_resource(kobj, attr, vma, 1); } /** @@ -541,9 +555,46 @@ pci_remove_resource_files(struct pci_dev *pdev) sysfs_remove_bin_file(&pdev->dev.kobj, res_attr); kfree(res_attr); } + + res_attr = pdev->res_attr_wc[i]; + if (res_attr) { + sysfs_remove_bin_file(&pdev->dev.kobj, res_attr); + kfree(res_attr); + } } } +static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine) +{ + /* allocate attribute structure, piggyback attribute name */ + int name_len = write_combine ? 13 : 10; + struct bin_attribute *res_attr; + int retval; + + res_attr = kzalloc(sizeof(*res_attr) + name_len, GFP_ATOMIC); + if (res_attr) { + char *res_attr_name = (char *)(res_attr + 1); + + if (write_combine) { + pdev->res_attr_wc[num] = res_attr; + sprintf(res_attr_name, "resource%d_wc", num); + res_attr->mmap = pci_mmap_resource_wc; + } else { + pdev->res_attr[num] = res_attr; + sprintf(res_attr_name, "resource%d", num); + res_attr->mmap = pci_mmap_resource_uc; + } + res_attr->attr.name = res_attr_name; + res_attr->attr.mode = S_IRUSR | S_IWUSR; + res_attr->size = pci_resource_len(pdev, num); + res_attr->private = &pdev->resource[num]; + retval = sysfs_create_bin_file(&pdev->dev.kobj, res_attr); + } else + retval = -ENOMEM; + + return retval; +} + /** * pci_create_resource_files - create resource files in sysfs for @dev * @dev: dev in question @@ -557,31 +608,19 @@ static int pci_create_resource_files(struct pci_dev *pdev) /* Expose the PCI resources from this device as files */ for (i = 0; i < PCI_ROM_RESOURCE; i++) { - struct bin_attribute *res_attr; /* skip empty resources */ if (!pci_resource_len(pdev, i)) continue; - /* allocate attribute structure, piggyback attribute name */ - res_attr = kzalloc(sizeof(*res_attr) + 10, GFP_ATOMIC); - if (res_attr) { - char *res_attr_name = (char *)(res_attr + 1); - - pdev->res_attr[i] = res_attr; - sprintf(res_attr_name, "resource%d", i); - res_attr->attr.name = res_attr_name; - res_attr->attr.mode = S_IRUSR | S_IWUSR; - res_attr->size = pci_resource_len(pdev, i); - res_attr->mmap = pci_mmap_resource; - res_attr->private = &pdev->resource[i]; - retval = sysfs_create_bin_file(&pdev->dev.kobj, res_attr); - if (retval) { - pci_remove_resource_files(pdev); - return retval; - } - } else { - return -ENOMEM; + retval = pci_create_attr(pdev, i, 0); + /* for prefetchable resources, create a WC mappable file */ + if (!retval && pdev->resource[i].flags & IORESOURCE_PREFETCH) + retval = pci_create_attr(pdev, i, 1); + + if (retval) { + pci_remove_resource_files(pdev); + return retval; } } return 0; diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 61fedb2448b6..f82495583e63 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -506,6 +506,23 @@ static void free_link_state(struct pci_dev *pdev) pdev->link_state = NULL; } +static int pcie_aspm_sanity_check(struct pci_dev *pdev) +{ + struct pci_dev *child_dev; + int child_pos; + + /* + * Some functions in a slot might not all be PCIE functions, very + * strange. Disable ASPM for the whole slot + */ + list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) { + child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP); + if (!child_pos) + return -EINVAL; + } + return 0; +} + /* * pcie_aspm_init_link_state: Initiate PCI express link state. * It is called after the pcie and its children devices are scaned. @@ -526,6 +543,9 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) if (list_empty(&pdev->subordinate->devices)) goto out; + if (pcie_aspm_sanity_check(pdev)) + goto out; + mutex_lock(&aspm_lock); link_state = kzalloc(sizeof(*link_state), GFP_KERNEL); diff --git a/drivers/pcmcia/electra_cf.c b/drivers/pcmcia/electra_cf.c index 0a6cea1316b4..52d0aa8c2e7a 100644 --- a/drivers/pcmcia/electra_cf.c +++ b/drivers/pcmcia/electra_cf.c @@ -352,6 +352,7 @@ static struct of_device_id electra_cf_match[] = { }, {}, }; +MODULE_DEVICE_TABLE(of, electra_cf_match); static struct of_platform_driver electra_cf_driver = { .name = (char *)driver_name, diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 0201c8adfda7..46c791adb894 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -50,15 +50,17 @@ static int irq_flags(int triggering, int polarity, int shareable) flags = IORESOURCE_IRQ_HIGHEDGE; } - if (shareable) + if (shareable == ACPI_SHARED) flags |= IORESOURCE_IRQ_SHAREABLE; return flags; } -static void decode_irq_flags(int flag, int *triggering, int *polarity) +static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering, + int *polarity, int *shareable) { - switch (flag) { + switch (flags & (IORESOURCE_IRQ_LOWLEVEL | IORESOURCE_IRQ_HIGHLEVEL | + IORESOURCE_IRQ_LOWEDGE | IORESOURCE_IRQ_HIGHEDGE)) { case IORESOURCE_IRQ_LOWLEVEL: *triggering = ACPI_LEVEL_SENSITIVE; *polarity = ACPI_ACTIVE_LOW; @@ -75,7 +77,18 @@ static void decode_irq_flags(int flag, int *triggering, int *polarity) *triggering = ACPI_EDGE_SENSITIVE; *polarity = ACPI_ACTIVE_HIGH; break; + default: + dev_err(&dev->dev, "can't encode invalid IRQ mode %#x\n", + flags); + *triggering = ACPI_EDGE_SENSITIVE; + *polarity = ACPI_ACTIVE_HIGH; + break; } + + if (flags & IORESOURCE_IRQ_SHAREABLE) + *shareable = ACPI_SHARED; + else + *shareable = ACPI_EXCLUSIVE; } static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev, @@ -742,6 +755,9 @@ static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data) if (pnpacpi_supported_resource(res)) { (*resource)->type = res->type; (*resource)->length = sizeof(struct acpi_resource); + if (res->type == ACPI_RESOURCE_TYPE_IRQ) + (*resource)->data.irq.descriptor_length = + res->data.irq.descriptor_length; (*resource)++; } @@ -788,22 +804,21 @@ static void pnpacpi_encode_irq(struct pnp_dev *dev, struct resource *p) { struct acpi_resource_irq *irq = &resource->data.irq; - int triggering, polarity; + int triggering, polarity, shareable; - decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity); + decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable); irq->triggering = triggering; irq->polarity = polarity; - if (triggering == ACPI_EDGE_SENSITIVE) - irq->sharable = ACPI_EXCLUSIVE; - else - irq->sharable = ACPI_SHARED; + irq->sharable = shareable; irq->interrupt_count = 1; irq->interrupts[0] = p->start; - dev_dbg(&dev->dev, " encode irq %d %s %s %s\n", (int) p->start, + dev_dbg(&dev->dev, " encode irq %d %s %s %s (%d-byte descriptor)\n", + (int) p->start, triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge", polarity == ACPI_ACTIVE_LOW ? "low" : "high", - irq->sharable == ACPI_SHARED ? "shared" : "exclusive"); + irq->sharable == ACPI_SHARED ? "shared" : "exclusive", + irq->descriptor_length); } static void pnpacpi_encode_ext_irq(struct pnp_dev *dev, @@ -811,16 +826,13 @@ static void pnpacpi_encode_ext_irq(struct pnp_dev *dev, struct resource *p) { struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq; - int triggering, polarity; + int triggering, polarity, shareable; - decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity); + decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable); extended_irq->producer_consumer = ACPI_CONSUMER; extended_irq->triggering = triggering; extended_irq->polarity = polarity; - if (triggering == ACPI_EDGE_SENSITIVE) - extended_irq->sharable = ACPI_EXCLUSIVE; - else - extended_irq->sharable = ACPI_SHARED; + extended_irq->sharable = shareable; extended_irq->interrupt_count = 1; extended_irq->interrupts[0] = p->start; diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c index e2b7de4cb05e..1ff3bb585ab2 100644 --- a/drivers/pnp/quirks.c +++ b/drivers/pnp/quirks.c @@ -286,7 +286,7 @@ static void quirk_system_pci_resources(struct pnp_dev *dev) pci_name(pdev), i, (unsigned long long) pci_start, (unsigned long long) pci_end); - res->flags = 0; + res->flags |= IORESOURCE_DISABLED; } } } diff --git a/drivers/pnp/system.c b/drivers/pnp/system.c index 9c2496dbeee4..cf4e07b01d48 100644 --- a/drivers/pnp/system.c +++ b/drivers/pnp/system.c @@ -81,7 +81,7 @@ static void reserve_resources_of_dev(struct pnp_dev *dev) } for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) { - if (res->flags & IORESOURCE_UNSET) + if (res->flags & (IORESOURCE_UNSET | IORESOURCE_DISABLED)) continue; reserve_range(dev, res->start, res->end, 0); diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index c444d6b10c58..49215da5249b 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c @@ -201,7 +201,7 @@ int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env) dev_dbg(dev, "uevent\n"); - if (!psy) { + if (!psy || !psy->dev) { dev_dbg(dev, "No power supply yet\n"); return ret; } diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 6cc2c0330230..4949dc4859be 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -256,6 +256,17 @@ config RTC_DRV_S35390A This driver can also be built as a module. If so the module will be called rtc-s35390a. +config RTC_DRV_FM3130 + tristate "Ramtron FM3130" + help + If you say Y here you will get support for the + Ramtron FM3130 RTC chips. + Ramtron FM3130 is a chip with two separate devices inside, + RTC clock and FRAM. This driver provides only RTC functionality. + + This driver can also be built as a module. If so the module + will be called rtc-fm3130. + endif # I2C comment "SPI RTC drivers" @@ -534,4 +545,12 @@ config RTC_DRV_RS5C313 help If you say yes here you get support for the Ricoh RS5C313 RTC chips. +config RTC_DRV_PPC + tristate "PowerPC machine dependent RTC support" + depends on PPC_MERGE + help + The PowerPC kernel has machine-specific functions for accessing + the RTC. This exposes that functionality through the generic RTC + class. + endif # RTC_CLASS diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 872f1218ff9f..b6e14d51670b 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o +obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o @@ -41,6 +42,7 @@ obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o +obj-$(CONFIG_RTC_DRV_PPC) += rtc-ppc.o obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o diff --git a/drivers/rtc/rtc-at32ap700x.c b/drivers/rtc/rtc-at32ap700x.c index 42244f14b41c..2ef8cdfda4a7 100644 --- a/drivers/rtc/rtc-at32ap700x.c +++ b/drivers/rtc/rtc-at32ap700x.c @@ -94,8 +94,11 @@ static int at32_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) { struct rtc_at32ap700x *rtc = dev_get_drvdata(dev); + spin_lock_irq(&rtc->lock); rtc_time_to_tm(rtc->alarm_time, &alrm->time); - alrm->pending = rtc_readl(rtc, IMR) & RTC_BIT(IMR_TOPI) ? 1 : 0; + alrm->enabled = rtc_readl(rtc, IMR) & RTC_BIT(IMR_TOPI) ? 1 : 0; + alrm->pending = rtc_readl(rtc, ISR) & RTC_BIT(ISR_TOPI) ? 1 : 0; + spin_unlock_irq(&rtc->lock); return 0; } @@ -119,7 +122,7 @@ static int at32_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) spin_lock_irq(&rtc->lock); rtc->alarm_time = alarm_unix_time; rtc_writel(rtc, TOP, rtc->alarm_time); - if (alrm->pending) + if (alrm->enabled) rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL) | RTC_BIT(CTRL_TOPEN)); else diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index d060a06ce05b..d7bb9bac71df 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -905,19 +905,7 @@ static struct pnp_driver cmos_pnp_driver = { .resume = cmos_pnp_resume, }; -static int __init cmos_init(void) -{ - return pnp_register_driver(&cmos_pnp_driver); -} -module_init(cmos_init); - -static void __exit cmos_exit(void) -{ - pnp_unregister_driver(&cmos_pnp_driver); -} -module_exit(cmos_exit); - -#else /* no PNP */ +#endif /* CONFIG_PNP */ /*----------------------------------------------------------------*/ @@ -958,20 +946,33 @@ static struct platform_driver cmos_platform_driver = { static int __init cmos_init(void) { +#ifdef CONFIG_PNP + if (pnp_platform_devices) + return pnp_register_driver(&cmos_pnp_driver); + else + return platform_driver_probe(&cmos_platform_driver, + cmos_platform_probe); +#else return platform_driver_probe(&cmos_platform_driver, cmos_platform_probe); +#endif /* CONFIG_PNP */ } module_init(cmos_init); static void __exit cmos_exit(void) { +#ifdef CONFIG_PNP + if (pnp_platform_devices) + pnp_unregister_driver(&cmos_pnp_driver); + else + platform_driver_unregister(&cmos_platform_driver); +#else platform_driver_unregister(&cmos_platform_driver); +#endif /* CONFIG_PNP */ } module_exit(cmos_exit); -#endif /* !PNP */ - MODULE_AUTHOR("David Brownell"); MODULE_DESCRIPTION("Driver for PC-style 'CMOS' RTCs"); MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index fa2d2f8b3f4d..640acd20fdde 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c @@ -42,7 +42,7 @@ #define DS1374_REG_TCR 0x09 /* Trickle Charge */ static const struct i2c_device_id ds1374_id[] = { - { "rtc-ds1374", 0 }, + { "ds1374", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, ds1374_id); diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c new file mode 100644 index 000000000000..11644c8fca82 --- /dev/null +++ b/drivers/rtc/rtc-fm3130.c @@ -0,0 +1,501 @@ +/* + * rtc-fm3130.c - RTC driver for Ramtron FM3130 I2C chip. + * + * Copyright (C) 2008 Sergey Lapin + * Based on ds1307 driver by James Chapman and David Brownell + * + * 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. + */ + +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/rtc.h> +#include <linux/bcd.h> + +#define FM3130_RTC_CONTROL (0x0) +#define FM3130_CAL_CONTROL (0x1) +#define FM3130_RTC_SECONDS (0x2) +#define FM3130_RTC_MINUTES (0x3) +#define FM3130_RTC_HOURS (0x4) +#define FM3130_RTC_DAY (0x5) +#define FM3130_RTC_DATE (0x6) +#define FM3130_RTC_MONTHS (0x7) +#define FM3130_RTC_YEARS (0x8) + +#define FM3130_ALARM_SECONDS (0x9) +#define FM3130_ALARM_MINUTES (0xa) +#define FM3130_ALARM_HOURS (0xb) +#define FM3130_ALARM_DATE (0xc) +#define FM3130_ALARM_MONTHS (0xd) +#define FM3130_ALARM_WP_CONTROL (0xe) + +#define FM3130_CAL_CONTROL_BIT_nOSCEN (1 << 7) /* Osciallator enabled */ +#define FM3130_RTC_CONTROL_BIT_LB (1 << 7) /* Low battery */ +#define FM3130_RTC_CONTROL_BIT_AF (1 << 6) /* Alarm flag */ +#define FM3130_RTC_CONTROL_BIT_CF (1 << 5) /* Century overflow */ +#define FM3130_RTC_CONTROL_BIT_POR (1 << 4) /* Power on reset */ +#define FM3130_RTC_CONTROL_BIT_AEN (1 << 3) /* Alarm enable */ +#define FM3130_RTC_CONTROL_BIT_CAL (1 << 2) /* Calibration mode */ +#define FM3130_RTC_CONTROL_BIT_WRITE (1 << 1) /* W=1 -> write mode W=0 normal */ +#define FM3130_RTC_CONTROL_BIT_READ (1 << 0) /* R=1 -> read mode R=0 normal */ + +#define FM3130_CLOCK_REGS 7 +#define FM3130_ALARM_REGS 5 + +struct fm3130 { + u8 reg_addr_time; + u8 reg_addr_alarm; + u8 regs[15]; + struct i2c_msg msg[4]; + struct i2c_client *client; + struct rtc_device *rtc; + int data_valid; + int alarm; +}; +static const struct i2c_device_id fm3130_id[] = { + { "fm3130-rtc", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, fm3130_id); + +#define FM3130_MODE_NORMAL 0 +#define FM3130_MODE_WRITE 1 +#define FM3130_MODE_READ 2 + +static void fm3130_rtc_mode(struct device *dev, int mode) +{ + struct fm3130 *fm3130 = dev_get_drvdata(dev); + + fm3130->regs[FM3130_RTC_CONTROL] = + i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL); + switch (mode) { + case FM3130_MODE_NORMAL: + fm3130->regs[FM3130_RTC_CONTROL] &= + ~(FM3130_RTC_CONTROL_BIT_WRITE | + FM3130_RTC_CONTROL_BIT_READ); + break; + case FM3130_MODE_WRITE: + fm3130->regs[FM3130_RTC_CONTROL] |= FM3130_RTC_CONTROL_BIT_WRITE; + break; + case FM3130_MODE_READ: + fm3130->regs[FM3130_RTC_CONTROL] |= FM3130_RTC_CONTROL_BIT_READ; + break; + default: + dev_dbg(dev, "invalid mode %d\n", mode); + break; + } + /* Checking for alarm */ + if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AF) { + fm3130->alarm = 1; + fm3130->regs[FM3130_RTC_CONTROL] &= ~FM3130_RTC_CONTROL_BIT_AF; + } + i2c_smbus_write_byte_data(fm3130->client, + FM3130_RTC_CONTROL, fm3130->regs[FM3130_RTC_CONTROL]); +} + +static int fm3130_get_time(struct device *dev, struct rtc_time *t) +{ + struct fm3130 *fm3130 = dev_get_drvdata(dev); + int tmp; + + if (!fm3130->data_valid) { + /* We have invalid data in RTC, probably due + to battery faults or other problems. Return EIO + for now, it will allow us to set data later insted + of error during probing which disables device */ + return -EIO; + } + fm3130_rtc_mode(dev, FM3130_MODE_READ); + + /* read the RTC date and time registers all at once */ + tmp = i2c_transfer(to_i2c_adapter(fm3130->client->dev.parent), + fm3130->msg, 2); + if (tmp != 2) { + dev_err(dev, "%s error %d\n", "read", tmp); + return -EIO; + } + + fm3130_rtc_mode(dev, FM3130_MODE_NORMAL); + + dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x %02x" + "%02x %02x %02x %02x %02x %02x %02x\n", + "read", + fm3130->regs[0], fm3130->regs[1], + fm3130->regs[2], fm3130->regs[3], + fm3130->regs[4], fm3130->regs[5], + fm3130->regs[6], fm3130->regs[7], + fm3130->regs[8], fm3130->regs[9], + fm3130->regs[0xa], fm3130->regs[0xb], + fm3130->regs[0xc], fm3130->regs[0xd], + fm3130->regs[0xe]); + + t->tm_sec = BCD2BIN(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f); + t->tm_min = BCD2BIN(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f); + tmp = fm3130->regs[FM3130_RTC_HOURS] & 0x3f; + t->tm_hour = BCD2BIN(tmp); + t->tm_wday = BCD2BIN(fm3130->regs[FM3130_RTC_DAY] & 0x07) - 1; + t->tm_mday = BCD2BIN(fm3130->regs[FM3130_RTC_DATE] & 0x3f); + tmp = fm3130->regs[FM3130_RTC_MONTHS] & 0x1f; + t->tm_mon = BCD2BIN(tmp) - 1; + + /* assume 20YY not 19YY, and ignore CF bit */ + t->tm_year = BCD2BIN(fm3130->regs[FM3130_RTC_YEARS]) + 100; + + dev_dbg(dev, "%s secs=%d, mins=%d, " + "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", + "read", t->tm_sec, t->tm_min, + t->tm_hour, t->tm_mday, + t->tm_mon, t->tm_year, t->tm_wday); + + /* initial clock setting can be undefined */ + return rtc_valid_tm(t); +} + + +static int fm3130_set_time(struct device *dev, struct rtc_time *t) +{ + struct fm3130 *fm3130 = dev_get_drvdata(dev); + int tmp, i; + u8 *buf = fm3130->regs; + + dev_dbg(dev, "%s secs=%d, mins=%d, " + "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", + "write", t->tm_sec, t->tm_min, + t->tm_hour, t->tm_mday, + t->tm_mon, t->tm_year, t->tm_wday); + + /* first register addr */ + buf[FM3130_RTC_SECONDS] = BIN2BCD(t->tm_sec); + buf[FM3130_RTC_MINUTES] = BIN2BCD(t->tm_min); + buf[FM3130_RTC_HOURS] = BIN2BCD(t->tm_hour); + buf[FM3130_RTC_DAY] = BIN2BCD(t->tm_wday + 1); + buf[FM3130_RTC_DATE] = BIN2BCD(t->tm_mday); + buf[FM3130_RTC_MONTHS] = BIN2BCD(t->tm_mon + 1); + + /* assume 20YY not 19YY */ + tmp = t->tm_year - 100; + buf[FM3130_RTC_YEARS] = BIN2BCD(tmp); + + dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x" + "%02x %02x %02x %02x %02x %02x %02x %02x\n", + "write", buf[0], buf[1], buf[2], buf[3], + buf[4], buf[5], buf[6], buf[7], + buf[8], buf[9], buf[0xa], buf[0xb], + buf[0xc], buf[0xd], buf[0xe]); + + fm3130_rtc_mode(dev, FM3130_MODE_WRITE); + + /* Writing time registers, we don't support multibyte transfers */ + for (i = 0; i < FM3130_CLOCK_REGS; i++) { + i2c_smbus_write_byte_data(fm3130->client, + FM3130_RTC_SECONDS + i, + fm3130->regs[FM3130_RTC_SECONDS + i]); + } + + fm3130_rtc_mode(dev, FM3130_MODE_NORMAL); + + /* We assume here that data are valid once written */ + if (!fm3130->data_valid) + fm3130->data_valid = 1; + return 0; +} + +static int fm3130_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct fm3130 *fm3130 = dev_get_drvdata(dev); + int tmp; + struct rtc_time *tm = &alrm->time; + /* read the RTC alarm registers all at once */ + tmp = i2c_transfer(to_i2c_adapter(fm3130->client->dev.parent), + &fm3130->msg[2], 2); + if (tmp != 2) { + dev_err(dev, "%s error %d\n", "read", tmp); + return -EIO; + } + dev_dbg(dev, "alarm read %02x %02x %02x %02x %02x\n", + fm3130->regs[FM3130_ALARM_SECONDS], + fm3130->regs[FM3130_ALARM_MINUTES], + fm3130->regs[FM3130_ALARM_HOURS], + fm3130->regs[FM3130_ALARM_DATE], + fm3130->regs[FM3130_ALARM_MONTHS]); + + + tm->tm_sec = BCD2BIN(fm3130->regs[FM3130_ALARM_SECONDS] & 0x7F); + tm->tm_min = BCD2BIN(fm3130->regs[FM3130_ALARM_MINUTES] & 0x7F); + tm->tm_hour = BCD2BIN(fm3130->regs[FM3130_ALARM_HOURS] & 0x3F); + tm->tm_mday = BCD2BIN(fm3130->regs[FM3130_ALARM_DATE] & 0x3F); + tm->tm_mon = BCD2BIN(fm3130->regs[FM3130_ALARM_MONTHS] & 0x1F); + if (tm->tm_mon > 0) + tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */ + dev_dbg(dev, "%s secs=%d, mins=%d, " + "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", + "read alarm", tm->tm_sec, tm->tm_min, + tm->tm_hour, tm->tm_mday, + tm->tm_mon, tm->tm_year, tm->tm_wday); + + return 0; +} + +static int fm3130_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct fm3130 *fm3130 = dev_get_drvdata(dev); + struct rtc_time *tm = &alrm->time; + int i; + + dev_dbg(dev, "%s secs=%d, mins=%d, " + "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", + "write alarm", tm->tm_sec, tm->tm_min, + tm->tm_hour, tm->tm_mday, + tm->tm_mon, tm->tm_year, tm->tm_wday); + + if (tm->tm_sec != -1) + fm3130->regs[FM3130_ALARM_SECONDS] = + BIN2BCD(tm->tm_sec) | 0x80; + + if (tm->tm_min != -1) + fm3130->regs[FM3130_ALARM_MINUTES] = + BIN2BCD(tm->tm_min) | 0x80; + + if (tm->tm_hour != -1) + fm3130->regs[FM3130_ALARM_HOURS] = + BIN2BCD(tm->tm_hour) | 0x80; + + if (tm->tm_mday != -1) + fm3130->regs[FM3130_ALARM_DATE] = + BIN2BCD(tm->tm_mday) | 0x80; + + if (tm->tm_mon != -1) + fm3130->regs[FM3130_ALARM_MONTHS] = + BIN2BCD(tm->tm_mon + 1) | 0x80; + + dev_dbg(dev, "alarm write %02x %02x %02x %02x %02x\n", + fm3130->regs[FM3130_ALARM_SECONDS], + fm3130->regs[FM3130_ALARM_MINUTES], + fm3130->regs[FM3130_ALARM_HOURS], + fm3130->regs[FM3130_ALARM_DATE], + fm3130->regs[FM3130_ALARM_MONTHS]); + /* Writing time registers, we don't support multibyte transfers */ + for (i = 0; i < FM3130_ALARM_REGS; i++) { + i2c_smbus_write_byte_data(fm3130->client, + FM3130_ALARM_SECONDS + i, + fm3130->regs[FM3130_ALARM_SECONDS + i]); + } + fm3130->regs[FM3130_RTC_CONTROL] = + i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL); + /* Checking for alarm */ + if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AF) { + fm3130->alarm = 1; + fm3130->regs[FM3130_RTC_CONTROL] &= ~FM3130_RTC_CONTROL_BIT_AF; + } + if (alrm->enabled) { + i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL, + (fm3130->regs[FM3130_RTC_CONTROL] & + ~(FM3130_RTC_CONTROL_BIT_CAL)) | + FM3130_RTC_CONTROL_BIT_AEN); + } else { + i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL, + fm3130->regs[FM3130_RTC_CONTROL] & + ~(FM3130_RTC_CONTROL_BIT_AEN)); + } + return 0; +} + +static const struct rtc_class_ops fm3130_rtc_ops = { + .read_time = fm3130_get_time, + .set_time = fm3130_set_time, + .read_alarm = fm3130_read_alarm, + .set_alarm = fm3130_set_alarm, +}; + +static struct i2c_driver fm3130_driver; + +static int __devinit fm3130_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct fm3130 *fm3130; + int err = -ENODEV; + int tmp; + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + + if (!i2c_check_functionality(adapter, + I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) + return -EIO; + + fm3130 = kzalloc(sizeof(struct fm3130), GFP_KERNEL); + + if (!fm3130) + return -ENOMEM; + + fm3130->client = client; + i2c_set_clientdata(client, fm3130); + fm3130->reg_addr_time = FM3130_RTC_SECONDS; + fm3130->reg_addr_alarm = FM3130_ALARM_SECONDS; + + /* Messages to read time */ + fm3130->msg[0].addr = client->addr; + fm3130->msg[0].flags = 0; + fm3130->msg[0].len = 1; + fm3130->msg[0].buf = &fm3130->reg_addr_time; + + fm3130->msg[1].addr = client->addr; + fm3130->msg[1].flags = I2C_M_RD; + fm3130->msg[1].len = FM3130_CLOCK_REGS; + fm3130->msg[1].buf = &fm3130->regs[FM3130_RTC_SECONDS]; + + /* Messages to read alarm */ + fm3130->msg[2].addr = client->addr; + fm3130->msg[2].flags = 0; + fm3130->msg[2].len = 1; + fm3130->msg[2].buf = &fm3130->reg_addr_alarm; + + fm3130->msg[3].addr = client->addr; + fm3130->msg[3].flags = I2C_M_RD; + fm3130->msg[3].len = FM3130_ALARM_REGS; + fm3130->msg[3].buf = &fm3130->regs[FM3130_ALARM_SECONDS]; + + fm3130->data_valid = 0; + + tmp = i2c_transfer(adapter, fm3130->msg, 4); + if (tmp != 4) { + pr_debug("read error %d\n", tmp); + err = -EIO; + goto exit_free; + } + + fm3130->regs[FM3130_RTC_CONTROL] = + i2c_smbus_read_byte_data(client, FM3130_RTC_CONTROL); + fm3130->regs[FM3130_CAL_CONTROL] = + i2c_smbus_read_byte_data(client, FM3130_CAL_CONTROL); + + /* Checking for alarm */ + if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AF) { + fm3130->alarm = 1; + fm3130->regs[FM3130_RTC_CONTROL] &= ~FM3130_RTC_CONTROL_BIT_AF; + } + + /* Disabling calibration mode */ + if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL) + i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, + fm3130->regs[FM3130_RTC_CONTROL] & + ~(FM3130_RTC_CONTROL_BIT_CAL)); + dev_warn(&client->dev, "Disabling calibration mode!\n"); + + /* Disabling read and write modes */ + if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_WRITE || + fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_READ) + i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, + fm3130->regs[FM3130_RTC_CONTROL] & + ~(FM3130_RTC_CONTROL_BIT_READ | + FM3130_RTC_CONTROL_BIT_WRITE)); + dev_warn(&client->dev, "Disabling READ or WRITE mode!\n"); + + /* oscillator off? turn it on, so clock can tick. */ + if (fm3130->regs[FM3130_CAL_CONTROL] & FM3130_CAL_CONTROL_BIT_nOSCEN) + i2c_smbus_write_byte_data(client, FM3130_CAL_CONTROL, + fm3130->regs[FM3130_CAL_CONTROL] & + ~(FM3130_CAL_CONTROL_BIT_nOSCEN)); + + /* oscillator fault? clear flag, and warn */ + if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_LB) + dev_warn(&client->dev, "Low battery!\n"); + + /* oscillator fault? clear flag, and warn */ + if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_POR) { + i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, + fm3130->regs[FM3130_RTC_CONTROL] & + ~FM3130_RTC_CONTROL_BIT_POR); + dev_warn(&client->dev, "SET TIME!\n"); + } + /* ACS is controlled by alarm */ + i2c_smbus_write_byte_data(client, FM3130_ALARM_WP_CONTROL, 0x80); + + /* TODO */ + /* TODO need to sanity check alarm */ + tmp = fm3130->regs[FM3130_RTC_SECONDS]; + tmp = BCD2BIN(tmp & 0x7f); + if (tmp > 60) + goto exit_bad; + tmp = BCD2BIN(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f); + if (tmp > 60) + goto exit_bad; + + tmp = BCD2BIN(fm3130->regs[FM3130_RTC_DATE] & 0x3f); + if (tmp == 0 || tmp > 31) + goto exit_bad; + + tmp = BCD2BIN(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f); + if (tmp == 0 || tmp > 12) + goto exit_bad; + + tmp = fm3130->regs[FM3130_RTC_HOURS]; + + fm3130->data_valid = 1; + +exit_bad: + if (!fm3130->data_valid) + dev_dbg(&client->dev, + "%s: %02x %02x %02x %02x %02x %02x %02x %02x" + "%02x %02x %02x %02x %02x %02x %02x\n", + "bogus registers", + fm3130->regs[0], fm3130->regs[1], + fm3130->regs[2], fm3130->regs[3], + fm3130->regs[4], fm3130->regs[5], + fm3130->regs[6], fm3130->regs[7], + fm3130->regs[8], fm3130->regs[9], + fm3130->regs[0xa], fm3130->regs[0xb], + fm3130->regs[0xc], fm3130->regs[0xd], + fm3130->regs[0xe]); + + /* We won't bail out here because we just got invalid data. + Time setting from u-boot doesn't work anyway */ + fm3130->rtc = rtc_device_register(client->name, &client->dev, + &fm3130_rtc_ops, THIS_MODULE); + if (IS_ERR(fm3130->rtc)) { + err = PTR_ERR(fm3130->rtc); + dev_err(&client->dev, + "unable to register the class device\n"); + goto exit_free; + } + return 0; +exit_free: + kfree(fm3130); + return err; +} + +static int __devexit fm3130_remove(struct i2c_client *client) +{ + struct fm3130 *fm3130 = i2c_get_clientdata(client); + + rtc_device_unregister(fm3130->rtc); + kfree(fm3130); + return 0; +} + +static struct i2c_driver fm3130_driver = { + .driver = { + .name = "rtc-fm3130", + .owner = THIS_MODULE, + }, + .probe = fm3130_probe, + .remove = __devexit_p(fm3130_remove), + .id_table = fm3130_id, +}; + +static int __init fm3130_init(void) +{ + return i2c_add_driver(&fm3130_driver); +} +module_init(fm3130_init); + +static void __exit fm3130_exit(void) +{ + i2c_del_driver(&fm3130_driver); +} +module_exit(fm3130_exit); + +MODULE_DESCRIPTION("RTC driver for FM3130"); +MODULE_AUTHOR("Sergey Lapin <slapin@ossfans.org>"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/rtc/rtc-ppc.c b/drivers/rtc/rtc-ppc.c new file mode 100644 index 000000000000..c8e97e25ef7e --- /dev/null +++ b/drivers/rtc/rtc-ppc.c @@ -0,0 +1,69 @@ +/* + * RTC driver for ppc_md RTC functions + * + * © 2007 Red Hat, Inc. + * + * Author: David Woodhouse <dwmw2@infradead.org> + * + * 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. + */ + + +#include <linux/module.h> +#include <linux/err.h> +#include <linux/rtc.h> +#include <linux/platform_device.h> +#include <asm/machdep.h> + +static int ppc_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + ppc_md.get_rtc_time(tm); + return 0; +} + +static int ppc_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + return ppc_md.set_rtc_time(tm); +} + +static const struct rtc_class_ops ppc_rtc_ops = { + .set_time = ppc_rtc_set_time, + .read_time = ppc_rtc_read_time, +}; + +static struct rtc_device *rtc; +static struct platform_device *ppc_rtc_pdev; + +static int __init ppc_rtc_init(void) +{ + if (!ppc_md.get_rtc_time || !ppc_md.set_rtc_time) + return -ENODEV; + + ppc_rtc_pdev = platform_device_register_simple("ppc-rtc", 0, NULL, 0); + if (IS_ERR(ppc_rtc_pdev)) + return PTR_ERR(ppc_rtc_pdev); + + rtc = rtc_device_register("ppc_md", &ppc_rtc_pdev->dev, + &ppc_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc)) { + platform_device_unregister(ppc_rtc_pdev); + return PTR_ERR(rtc); + } + + return 0; +} + +static void __exit ppc_rtc_exit(void) +{ + rtc_device_unregister(rtc); + platform_device_unregister(ppc_rtc_pdev); +} + +module_init(ppc_rtc_init); +module_exit(ppc_rtc_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); +MODULE_DESCRIPTION("Generic RTC class driver for PowerPC"); diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 8ba3f135da22..1a4025683362 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -63,6 +63,7 @@ static void dasd_return_cqr_cb(struct dasd_ccw_req *, void *); */ static wait_queue_head_t dasd_init_waitq; static wait_queue_head_t dasd_flush_wq; +static wait_queue_head_t generic_waitq; /* * Allocate memory for a new device structure. @@ -1151,11 +1152,15 @@ static void __dasd_device_process_final_queue(struct dasd_device *device, struct list_head *l, *n; struct dasd_ccw_req *cqr; struct dasd_block *block; + void (*callback)(struct dasd_ccw_req *, void *data); + void *callback_data; list_for_each_safe(l, n, final_queue) { cqr = list_entry(l, struct dasd_ccw_req, devlist); list_del_init(&cqr->devlist); block = cqr->block; + callback = cqr->callback; + callback_data = cqr->callback_data; if (block) spin_lock_bh(&block->queue_lock); switch (cqr->status) { @@ -1176,7 +1181,7 @@ static void __dasd_device_process_final_queue(struct dasd_device *device, BUG(); } if (cqr->callback != NULL) - (cqr->callback)(cqr, cqr->callback_data); + (callback)(cqr, callback_data); if (block) spin_unlock_bh(&block->queue_lock); } @@ -1406,17 +1411,15 @@ static inline int _wait_for_wakeup(struct dasd_ccw_req *cqr) */ int dasd_sleep_on(struct dasd_ccw_req *cqr) { - wait_queue_head_t wait_q; struct dasd_device *device; int rc; device = cqr->startdev; - init_waitqueue_head (&wait_q); cqr->callback = dasd_wakeup_cb; - cqr->callback_data = (void *) &wait_q; + cqr->callback_data = (void *) &generic_waitq; dasd_add_request_tail(cqr); - wait_event(wait_q, _wait_for_wakeup(cqr)); + wait_event(generic_waitq, _wait_for_wakeup(cqr)); /* Request status is either done or failed. */ rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO; @@ -1429,20 +1432,18 @@ int dasd_sleep_on(struct dasd_ccw_req *cqr) */ int dasd_sleep_on_interruptible(struct dasd_ccw_req *cqr) { - wait_queue_head_t wait_q; struct dasd_device *device; int rc; device = cqr->startdev; - init_waitqueue_head (&wait_q); cqr->callback = dasd_wakeup_cb; - cqr->callback_data = (void *) &wait_q; + cqr->callback_data = (void *) &generic_waitq; dasd_add_request_tail(cqr); - rc = wait_event_interruptible(wait_q, _wait_for_wakeup(cqr)); + rc = wait_event_interruptible(generic_waitq, _wait_for_wakeup(cqr)); if (rc == -ERESTARTSYS) { dasd_cancel_req(cqr); /* wait (non-interruptible) for final status */ - wait_event(wait_q, _wait_for_wakeup(cqr)); + wait_event(generic_waitq, _wait_for_wakeup(cqr)); } rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO; return rc; @@ -1466,7 +1467,6 @@ static inline int _dasd_term_running_cqr(struct dasd_device *device) int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr) { - wait_queue_head_t wait_q; struct dasd_device *device; int rc; @@ -1478,9 +1478,8 @@ int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr) return rc; } - init_waitqueue_head (&wait_q); cqr->callback = dasd_wakeup_cb; - cqr->callback_data = (void *) &wait_q; + cqr->callback_data = (void *) &generic_waitq; cqr->status = DASD_CQR_QUEUED; list_add(&cqr->devlist, &device->ccw_queue); @@ -1489,7 +1488,7 @@ int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr) spin_unlock_irq(get_ccwdev_lock(device->cdev)); - wait_event(wait_q, _wait_for_wakeup(cqr)); + wait_event(generic_waitq, _wait_for_wakeup(cqr)); /* Request status is either done or failed. */ rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO; @@ -2430,6 +2429,7 @@ static int __init dasd_init(void) init_waitqueue_head(&dasd_init_waitq); init_waitqueue_head(&dasd_flush_wq); + init_waitqueue_head(&generic_waitq); /* register 'common' DASD debug area, used for all DBF_XXX calls */ dasd_debug_area = debug_register("dasd", 1, 1, 8 * sizeof(long)); diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index 0d98f1ff2edd..848ef7e8523f 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c @@ -549,7 +549,6 @@ raw3270_start_init(struct raw3270 *rp, struct raw3270_view *view, struct raw3270_request *rq) { unsigned long flags; - wait_queue_head_t wq; int rc; #ifdef CONFIG_TN3270_CONSOLE @@ -566,20 +565,20 @@ raw3270_start_init(struct raw3270 *rp, struct raw3270_view *view, return rq->rc; } #endif - init_waitqueue_head(&wq); rq->callback = raw3270_wake_init; - rq->callback_data = &wq; + rq->callback_data = &raw3270_wait_queue; spin_lock_irqsave(get_ccwdev_lock(view->dev->cdev), flags); rc = __raw3270_start(rp, view, rq); spin_unlock_irqrestore(get_ccwdev_lock(view->dev->cdev), flags); if (rc) return rc; /* Now wait for the completion. */ - rc = wait_event_interruptible(wq, raw3270_request_final(rq)); + rc = wait_event_interruptible(raw3270_wait_queue, + raw3270_request_final(rq)); if (rc == -ERESTARTSYS) { /* Interrupted by a signal. */ raw3270_halt_io(view->dev, rq); /* No wait for the halt to complete. */ - wait_event(wq, raw3270_request_final(rq)); + wait_event(raw3270_wait_queue, raw3270_request_final(rq)); return -ERESTARTSYS; } return rq->rc; diff --git a/drivers/s390/char/sclp_config.c b/drivers/s390/char/sclp_config.c index 9e784d5f7f57..ad05a87bc480 100644 --- a/drivers/s390/char/sclp_config.c +++ b/drivers/s390/char/sclp_config.c @@ -40,7 +40,7 @@ static void sclp_cpu_capability_notify(struct work_struct *work) put_online_cpus(); } -static void sclp_cpu_change_notify(struct work_struct *work) +static void __ref sclp_cpu_change_notify(struct work_struct *work) { smp_rescan_cpus(); } diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c index 35707c04e613..3e577f655b18 100644 --- a/drivers/s390/char/sclp_vt220.c +++ b/drivers/s390/char/sclp_vt220.c @@ -71,9 +71,6 @@ static struct list_head sclp_vt220_outqueue; /* Number of requests in outqueue */ static int sclp_vt220_outqueue_count; -/* Wait queue used to delay write requests while we've run out of buffers */ -static wait_queue_head_t sclp_vt220_waitq; - /* Timer used for delaying write requests to merge subsequent messages into * a single buffer */ static struct timer_list sclp_vt220_timer; @@ -133,7 +130,6 @@ sclp_vt220_process_queue(struct sclp_vt220_request *request) } while (request && __sclp_vt220_emit(request)); if (request == NULL && sclp_vt220_flush_later) sclp_vt220_emit_current(); - wake_up(&sclp_vt220_waitq); /* Check if the tty needs a wake up call */ if (sclp_vt220_tty != NULL) { tty_wakeup(sclp_vt220_tty); @@ -383,7 +379,7 @@ sclp_vt220_timeout(unsigned long data) */ static int __sclp_vt220_write(const unsigned char *buf, int count, int do_schedule, - int convertlf, int may_schedule) + int convertlf, int may_fail) { unsigned long flags; void *page; @@ -395,15 +391,14 @@ __sclp_vt220_write(const unsigned char *buf, int count, int do_schedule, overall_written = 0; spin_lock_irqsave(&sclp_vt220_lock, flags); do { - /* Create a sclp output buffer if none exists yet */ + /* Create an sclp output buffer if none exists yet */ if (sclp_vt220_current_request == NULL) { while (list_empty(&sclp_vt220_empty)) { spin_unlock_irqrestore(&sclp_vt220_lock, flags); - if (in_interrupt() || !may_schedule) - sclp_sync_wait(); + if (may_fail) + goto out; else - wait_event(sclp_vt220_waitq, - !list_empty(&sclp_vt220_empty)); + sclp_sync_wait(); spin_lock_irqsave(&sclp_vt220_lock, flags); } page = (void *) sclp_vt220_empty.next; @@ -437,6 +432,7 @@ __sclp_vt220_write(const unsigned char *buf, int count, int do_schedule, add_timer(&sclp_vt220_timer); } spin_unlock_irqrestore(&sclp_vt220_lock, flags); +out: return overall_written; } @@ -520,19 +516,11 @@ sclp_vt220_close(struct tty_struct *tty, struct file *filp) * character to the tty device. If the kernel uses this routine, * it must call the flush_chars() routine (if defined) when it is * done stuffing characters into the driver. - * - * NOTE: include/linux/tty_driver.h specifies that a character should be - * ignored if there is no room in the queue. This driver implements a different - * semantic in that it will block when there is no more room left. - * - * FIXME: putchar can currently be called from BH and other non blocking - * handlers so this semantic isn't a good idea. */ static int sclp_vt220_put_char(struct tty_struct *tty, unsigned char ch) { - __sclp_vt220_write(&ch, 1, 0, 0, 1); - return 1; + return __sclp_vt220_write(&ch, 1, 0, 0, 1); } /* @@ -653,7 +641,6 @@ static int __init __sclp_vt220_init(void) spin_lock_init(&sclp_vt220_lock); INIT_LIST_HEAD(&sclp_vt220_empty); INIT_LIST_HEAD(&sclp_vt220_outqueue); - init_waitqueue_head(&sclp_vt220_waitq); init_timer(&sclp_vt220_timer); sclp_vt220_current_request = NULL; sclp_vt220_buffered_chars = 0; @@ -786,6 +773,7 @@ sclp_vt220_con_init(void) { int rc; + INIT_LIST_HEAD(&sclp_vt220_register.list); if (!CONSOLE_IS_SCLP) return 0; rc = __sclp_vt220_init(); diff --git a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h index dddf8d62c153..d0d565a05dfe 100644 --- a/drivers/s390/char/tape.h +++ b/drivers/s390/char/tape.h @@ -231,6 +231,9 @@ struct tape_device { /* Request queue. */ struct list_head req_queue; + /* Request wait queue. */ + wait_queue_head_t wait_queue; + /* Each tape device has (currently) two minor numbers. */ int first_minor; diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index 8246ef3ab095..42ce7915fc5d 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c @@ -1598,7 +1598,7 @@ tape_3590_setup_device(struct tape_device *device) rc = tape_3590_read_dev_chars(device, rdc_data); if (rc) { DBF_LH(3, "Read device characteristics failed!\n"); - goto fail_kmalloc; + goto fail_rdc_data; } rc = tape_std_assign(device); if (rc) diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c index ddc4a114e7f4..95da72bc17e8 100644 --- a/drivers/s390/char/tape_block.c +++ b/drivers/s390/char/tape_block.c @@ -179,11 +179,11 @@ tapeblock_requeue(struct work_struct *work) { tapeblock_end_request(req, -EIO); continue; } + blkdev_dequeue_request(req); + nr_queued++; spin_unlock_irq(&device->blk_data.request_queue_lock); rc = tapeblock_start_request(device, req); spin_lock_irq(&device->blk_data.request_queue_lock); - blkdev_dequeue_request(req); - nr_queued++; } spin_unlock_irq(&device->blk_data.request_queue_lock); atomic_set(&device->blk_data.requeue_scheduled, 0); diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index 76e44eb7c47f..c20e3c548343 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c @@ -449,6 +449,7 @@ tape_alloc_device(void) INIT_LIST_HEAD(&device->req_queue); INIT_LIST_HEAD(&device->node); init_waitqueue_head(&device->state_change_wq); + init_waitqueue_head(&device->wait_queue); device->tape_state = TS_INIT; device->medium_state = MS_UNKNOWN; *device->modeset_byte = 0; @@ -954,21 +955,19 @@ __tape_wake_up(struct tape_request *request, void *data) int tape_do_io(struct tape_device *device, struct tape_request *request) { - wait_queue_head_t wq; int rc; - init_waitqueue_head(&wq); spin_lock_irq(get_ccwdev_lock(device->cdev)); /* Setup callback */ request->callback = __tape_wake_up; - request->callback_data = &wq; + request->callback_data = &device->wait_queue; /* Add request to request queue and try to start it. */ rc = __tape_start_request(device, request); spin_unlock_irq(get_ccwdev_lock(device->cdev)); if (rc) return rc; /* Request added to the queue. Wait for its completion. */ - wait_event(wq, (request->callback == NULL)); + wait_event(device->wait_queue, (request->callback == NULL)); /* Get rc from request */ return request->rc; } @@ -989,20 +988,19 @@ int tape_do_io_interruptible(struct tape_device *device, struct tape_request *request) { - wait_queue_head_t wq; int rc; - init_waitqueue_head(&wq); spin_lock_irq(get_ccwdev_lock(device->cdev)); /* Setup callback */ request->callback = __tape_wake_up_interruptible; - request->callback_data = &wq; + request->callback_data = &device->wait_queue; rc = __tape_start_request(device, request); spin_unlock_irq(get_ccwdev_lock(device->cdev)); if (rc) return rc; /* Request added to the queue. Wait for its completion. */ - rc = wait_event_interruptible(wq, (request->callback == NULL)); + rc = wait_event_interruptible(device->wait_queue, + (request->callback == NULL)); if (rc != -ERESTARTSYS) /* Request finished normally. */ return request->rc; @@ -1015,7 +1013,7 @@ tape_do_io_interruptible(struct tape_device *device, /* Wait for the interrupt that acknowledges the halt. */ do { rc = wait_event_interruptible( - wq, + device->wait_queue, (request->callback == NULL) ); } while (rc == -ERESTARTSYS); diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c index a4a5f2efea48..0bfcbbe375c4 100644 --- a/drivers/s390/cio/blacklist.c +++ b/drivers/s390/cio/blacklist.c @@ -97,8 +97,8 @@ static int pure_hex(char **cp, unsigned int *val, int min_digit, return 0; } -static int parse_busid(char *str, int *cssid, int *ssid, int *devno, - int msgtrigger) +static int parse_busid(char *str, unsigned int *cssid, unsigned int *ssid, + unsigned int *devno, int msgtrigger) { char *str_work; int val, rc, ret; @@ -148,7 +148,7 @@ out: static int blacklist_parse_parameters(char *str, range_action action, int msgtrigger) { - int from_cssid, to_cssid, from_ssid, to_ssid, from, to; + unsigned int from_cssid, to_cssid, from_ssid, to_ssid, from, to; int rc, totalrc; char *parm; range_action ra; diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 82c6a2d45128..b32d7eb3d81a 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -576,12 +576,14 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) err = -ENODEV; goto out; } - if (cio_is_console(sch->schid)) + if (cio_is_console(sch->schid)) { sch->opm = 0xff; - else + sch->isc = 1; + } else { sch->opm = chp_get_sch_opm(sch); + sch->isc = 3; + } sch->lpm = sch->schib.pmcw.pam & sch->opm; - sch->isc = 3; CIO_MSG_EVENT(6, "Detected device %04x on subchannel 0.%x.%04X " "- PIM = %02X, PAM = %02X, POM = %02X\n", @@ -704,9 +706,9 @@ void wait_cons_dev(void) if (!console_subchannel_in_use) return; - /* disable all but isc 7 (console device) */ + /* disable all but isc 1 (console device) */ __ctl_store (save_cr6, 6, 6); - cr6 = 0x01000000; + cr6 = 0x40000000; __ctl_load (cr6, 6, 6); do { @@ -788,11 +790,11 @@ cio_probe_console(void) } /* - * enable console I/O-interrupt subclass 7 + * enable console I/O-interrupt subclass 1 */ - ctl_set_bit(6, 24); - console_subchannel.isc = 7; - console_subchannel.schib.pmcw.isc = 7; + ctl_set_bit(6, 30); + console_subchannel.isc = 1; + console_subchannel.schib.pmcw.isc = 1; console_subchannel.schib.pmcw.intparm = (u32)(addr_t)&console_subchannel; ret = cio_modify(&console_subchannel); diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c index 9f55ce6f3c78..5ab34340919b 100644 --- a/drivers/s390/kvm/kvm_virtio.c +++ b/drivers/s390/kvm/kvm_virtio.c @@ -31,11 +31,6 @@ */ static void *kvm_devices; -/* - * Unique numbering for kvm devices. - */ -static unsigned int dev_index; - struct kvm_device { struct virtio_device vdev; struct kvm_device_desc *desc; @@ -250,26 +245,25 @@ static struct device kvm_root = { * adds a new device and register it with virtio * appropriate drivers are loaded by the device model */ -static void add_kvm_device(struct kvm_device_desc *d) +static void add_kvm_device(struct kvm_device_desc *d, unsigned int offset) { struct kvm_device *kdev; kdev = kzalloc(sizeof(*kdev), GFP_KERNEL); if (!kdev) { - printk(KERN_EMERG "Cannot allocate kvm dev %u\n", - dev_index++); + printk(KERN_EMERG "Cannot allocate kvm dev %u type %u\n", + offset, d->type); return; } kdev->vdev.dev.parent = &kvm_root; - kdev->vdev.index = dev_index++; kdev->vdev.id.device = d->type; kdev->vdev.config = &kvm_vq_configspace_ops; kdev->desc = d; if (register_virtio_device(&kdev->vdev) != 0) { - printk(KERN_ERR "Failed to register kvm device %u\n", - kdev->vdev.index); + printk(KERN_ERR "Failed to register kvm device %u type %u\n", + offset, d->type); kfree(kdev); } } @@ -289,7 +283,7 @@ static void scan_devices(void) if (d->type == 0) break; - add_kvm_device(d); + add_kvm_device(d, i); } } diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 436bf1f6d4a6..9a71dae223e8 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -290,9 +290,6 @@ int qeth_set_large_send(struct qeth_card *card, card->dev->features |= NETIF_F_TSO | NETIF_F_SG | NETIF_F_HW_CSUM; } else { - PRINT_WARN("TSO not supported on %s. " - "large_send set to 'no'.\n", - card->dev->name); card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | NETIF_F_HW_CSUM); card->options.large_send = QETH_LARGE_SEND_NO; @@ -1407,12 +1404,6 @@ static void qeth_init_func_level(struct qeth_card *card) } } -static inline __u16 qeth_raw_devno_from_bus_id(char *id) -{ - id += (strlen(id) - 4); - return (__u16) simple_strtoul(id, &id, 16); -} - static int qeth_idx_activate_get_answer(struct qeth_channel *channel, void (*idx_reply_cb)(struct qeth_channel *, struct qeth_cmd_buffer *)) @@ -1439,7 +1430,7 @@ static int qeth_idx_activate_get_answer(struct qeth_channel *channel, spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); if (rc) { - PRINT_ERR("Error2 in activating channel rc=%d\n", rc); + QETH_DBF_MESSAGE(2, "Error2 in activating channel rc=%d\n", rc); QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc); atomic_set(&channel->irq_pending, 0); wake_up(&card->wait_q); @@ -1468,6 +1459,7 @@ static int qeth_idx_activate_channel(struct qeth_channel *channel, __u16 temp; __u8 tmp; int rc; + struct ccw_dev_id temp_devid; card = CARD_FROM_CDEV(channel->ccwdev); @@ -1494,8 +1486,8 @@ static int qeth_idx_activate_channel(struct qeth_channel *channel, &card->token.issuer_rm_w, QETH_MPC_TOKEN_LENGTH); memcpy(QETH_IDX_ACT_FUNC_LEVEL(iob->data), &card->info.func_level, sizeof(__u16)); - temp = qeth_raw_devno_from_bus_id(CARD_DDEV_ID(card)); - memcpy(QETH_IDX_ACT_QDIO_DEV_CUA(iob->data), &temp, 2); + ccw_device_get_id(CARD_DDEV(card), &temp_devid); + memcpy(QETH_IDX_ACT_QDIO_DEV_CUA(iob->data), &temp_devid.devno, 2); temp = (card->info.cula << 8) + card->info.unit_addr2; memcpy(QETH_IDX_ACT_QDIO_DEV_REALADDR(iob->data), &temp, 2); @@ -1508,7 +1500,8 @@ static int qeth_idx_activate_channel(struct qeth_channel *channel, spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); if (rc) { - PRINT_ERR("Error1 in activating channel. rc=%d\n", rc); + QETH_DBF_MESSAGE(2, "Error1 in activating channel. rc=%d\n", + rc); QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc); atomic_set(&channel->irq_pending, 0); wake_up(&card->wait_q); @@ -1658,7 +1651,6 @@ int qeth_send_control_data(struct qeth_card *card, int len, reply = qeth_alloc_reply(card); if (!reply) { - PRINT_WARN("Could not alloc qeth_reply!\n"); return -ENOMEM; } reply->callback = reply_cb; @@ -2612,15 +2604,9 @@ void qeth_queue_input_buffer(struct qeth_card *card, int index) if (newcount < count) { /* we are in memory shortage so we switch back to traditional skb allocation and drop packages */ - if (!atomic_read(&card->force_alloc_skb) && - net_ratelimit()) - PRINT_WARN("Switch to alloc skb\n"); atomic_set(&card->force_alloc_skb, 3); count = newcount; } else { - if ((atomic_read(&card->force_alloc_skb) == 1) && - net_ratelimit()) - PRINT_WARN("Switch to sg\n"); atomic_add_unless(&card->force_alloc_skb, -1, 0); } @@ -3034,7 +3020,7 @@ int qeth_get_elements_no(struct qeth_card *card, void *hdr, elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE) + skb->len) >> PAGE_SHIFT); if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)) { - PRINT_ERR("Invalid size of IP packet " + QETH_DBF_MESSAGE(2, "Invalid size of IP packet " "(Number=%d / Length=%d). Discarded.\n", (elements_needed+elems), skb->len); return 0; @@ -3247,8 +3233,6 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, * free buffers) to handle eddp context */ if (qeth_eddp_check_buffers_for_context(queue, ctx) < 0) { - if (net_ratelimit()) - PRINT_WARN("eddp tx_dropped 1\n"); rc = -EBUSY; goto out; } @@ -3260,7 +3244,6 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, tmp = qeth_eddp_fill_buffer(queue, ctx, queue->next_buf_to_fill); if (tmp < 0) { - PRINT_ERR("eddp tx_dropped 2\n"); rc = -EBUSY; goto out; } @@ -3602,8 +3585,6 @@ int qeth_snmp_command(struct qeth_card *card, char __user *udata) if ((!qeth_adp_supported(card, IPA_SETADP_SET_SNMP_CONTROL)) && (!card->options.layer2)) { - PRINT_WARN("SNMP Query MIBS not supported " - "on %s!\n", QETH_CARD_IFNAME(card)); return -EOPNOTSUPP; } /* skip 4 bytes (data_len struct member) to get req_len */ @@ -3634,7 +3615,7 @@ int qeth_snmp_command(struct qeth_card *card, char __user *udata) rc = qeth_send_ipa_snmp_cmd(card, iob, QETH_SETADP_BASE_LEN + req_len, qeth_snmp_command_cb, (void *)&qinfo); if (rc) - PRINT_WARN("SNMP command failed on %s: (0x%x)\n", + QETH_DBF_MESSAGE(2, "SNMP command failed on %s: (0x%x)\n", QETH_CARD_IFNAME(card), rc); else { if (copy_to_user(udata, qinfo.udata, qinfo.udata_len)) @@ -3807,8 +3788,8 @@ retry: if (mpno) mpno = min(mpno - 1, QETH_MAX_PORTNO); if (card->info.portno > mpno) { - PRINT_ERR("Device %s does not offer port number %d \n.", - CARD_BUS_ID(card), card->info.portno); + QETH_DBF_MESSAGE(2, "Device %s does not offer port number %d" + "\n.", CARD_BUS_ID(card), card->info.portno); rc = -ENODEV; goto out; } @@ -3985,8 +3966,6 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card, return skb; no_mem: if (net_ratelimit()) { - PRINT_WARN("No memory for packet received on %s.\n", - QETH_CARD_IFNAME(card)); QETH_DBF_TEXT(TRACE, 2, "noskbmem"); QETH_DBF_TEXT_(TRACE, 2, "%s", CARD_BUS_ID(card)); } @@ -4004,15 +3983,17 @@ static void qeth_unregister_dbf_views(void) } } -void qeth_dbf_longtext(enum qeth_dbf_names dbf_nix, int level, char *text, ...) +void qeth_dbf_longtext(enum qeth_dbf_names dbf_nix, int level, char *fmt, ...) { char dbf_txt_buf[32]; + va_list args; if (level > (qeth_dbf[dbf_nix].id)->level) return; - snprintf(dbf_txt_buf, sizeof(dbf_txt_buf), text); + va_start(args, fmt); + vsnprintf(dbf_txt_buf, sizeof(dbf_txt_buf), fmt, args); + va_end(args); debug_text_event(qeth_dbf[dbf_nix].id, level, dbf_txt_buf); - } EXPORT_SYMBOL_GPL(qeth_dbf_longtext); diff --git a/drivers/s390/net/qeth_core_offl.c b/drivers/s390/net/qeth_core_offl.c index 822df8362856..452874e89740 100644 --- a/drivers/s390/net/qeth_core_offl.c +++ b/drivers/s390/net/qeth_core_offl.c @@ -122,8 +122,8 @@ int qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue, if (element == 0) return -EBUSY; else { - PRINT_WARN("could only partially fill eddp " - "buffer!\n"); + QETH_DBF_MESSAGE(2, "could only partially fill" + "eddp buffer!\n"); goto out; } } @@ -143,8 +143,6 @@ int qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue, if (must_refcnt) { must_refcnt = 0; if (qeth_eddp_buf_ref_context(buf, ctx)) { - PRINT_WARN("no memory to create eddp context " - "reference\n"); goto out_check; } } diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index 08a50f057284..c26e842ad905 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c @@ -129,7 +129,6 @@ static ssize_t qeth_dev_portno_store(struct device *dev, portno = simple_strtoul(buf, &tmp, 16); if (portno > QETH_MAX_PORTNO) { - PRINT_WARN("portno 0x%X is out of range\n", portno); return -EINVAL; } @@ -223,8 +222,6 @@ static ssize_t qeth_dev_prioqing_store(struct device *dev, * if though we have to permit priority queueing */ if (card->qdio.no_out_queues == 1) { - PRINT_WARN("Priority queueing disabled due " - "to hardware limitations!\n"); card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT; return -EPERM; } @@ -250,7 +247,6 @@ static ssize_t qeth_dev_prioqing_store(struct device *dev, card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING; card->qdio.default_out_queue = QETH_DEFAULT_QUEUE; } else { - PRINT_WARN("Unknown queueing type '%s'\n", tmp); return -EINVAL; } return count; @@ -291,9 +287,6 @@ static ssize_t qeth_dev_bufcnt_store(struct device *dev, ((cnt > QETH_IN_BUF_COUNT_MAX) ? QETH_IN_BUF_COUNT_MAX : cnt); if (old_cnt != cnt) { rc = qeth_realloc_buffer_pool(card, cnt); - if (rc) - PRINT_WARN("Error (%d) while setting " - "buffer count.\n", rc); } return count; } @@ -355,7 +348,6 @@ static ssize_t qeth_dev_performance_stats_store(struct device *dev, card->perf_stats.initial_rx_packets = card->stats.rx_packets; card->perf_stats.initial_tx_packets = card->stats.tx_packets; } else { - PRINT_WARN("performance_stats: write 0 or 1 to this file!\n"); return -EINVAL; } return count; @@ -399,7 +391,6 @@ static ssize_t qeth_dev_layer2_store(struct device *dev, newdis = QETH_DISCIPLINE_LAYER2; break; default: - PRINT_WARN("layer2: write 0 or 1 to this file!\n"); return -EINVAL; } @@ -463,7 +454,6 @@ static ssize_t qeth_dev_large_send_store(struct device *dev, } else if (!strcmp(tmp, "TSO")) { type = QETH_LARGE_SEND_TSO; } else { - PRINT_WARN("large_send: invalid mode %s!\n", tmp); return -EINVAL; } if (card->options.large_send == type) @@ -503,8 +493,6 @@ static ssize_t qeth_dev_blkt_store(struct qeth_card *card, if (i <= max_value) { *value = i; } else { - PRINT_WARN("blkt total time: write values between" - " 0 and %d to this file!\n", max_value); return -EINVAL; } return count; diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 86ec50ddae13..f682f7b14480 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -101,19 +101,16 @@ static struct net_device *qeth_l2_netdev_by_devno(unsigned char *read_dev_no) { struct qeth_card *card; struct net_device *ndev; - unsigned char *readno; - __u16 temp_dev_no, card_dev_no; - char *endp; + __u16 temp_dev_no; unsigned long flags; + struct ccw_dev_id read_devid; ndev = NULL; memcpy(&temp_dev_no, read_dev_no, 2); read_lock_irqsave(&qeth_core_card_list.rwlock, flags); list_for_each_entry(card, &qeth_core_card_list.list, list) { - readno = CARD_RDEV_ID(card); - readno += (strlen(readno) - 4); - card_dev_no = simple_strtoul(readno, &endp, 16); - if (card_dev_no == temp_dev_no) { + ccw_device_get_id(CARD_RDEV(card), &read_devid); + if (read_devid.devno == temp_dev_no) { ndev = card->dev; break; } @@ -134,14 +131,14 @@ static int qeth_l2_send_setgroupmac_cb(struct qeth_card *card, mac = &cmd->data.setdelmac.mac[0]; /* MAC already registered, needed in couple/uncouple case */ if (cmd->hdr.return_code == 0x2005) { - PRINT_WARN("Group MAC %02x:%02x:%02x:%02x:%02x:%02x " \ + QETH_DBF_MESSAGE(2, "Group MAC %02x:%02x:%02x:%02x:%02x:%02x " "already existing on %s \n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], QETH_CARD_IFNAME(card)); cmd->hdr.return_code = 0; } if (cmd->hdr.return_code) - PRINT_ERR("Could not set group MAC " \ + QETH_DBF_MESSAGE(2, "Could not set group MAC " "%02x:%02x:%02x:%02x:%02x:%02x on %s: %x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], QETH_CARD_IFNAME(card), cmd->hdr.return_code); @@ -166,7 +163,7 @@ static int qeth_l2_send_delgroupmac_cb(struct qeth_card *card, cmd = (struct qeth_ipa_cmd *) data; mac = &cmd->data.setdelmac.mac[0]; if (cmd->hdr.return_code) - PRINT_ERR("Could not delete group MAC " \ + QETH_DBF_MESSAGE(2, "Could not delete group MAC " "%02x:%02x:%02x:%02x:%02x:%02x on %s: %x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], QETH_CARD_IFNAME(card), cmd->hdr.return_code); @@ -186,10 +183,8 @@ static void qeth_l2_add_mc(struct qeth_card *card, __u8 *mac) mc = kmalloc(sizeof(struct qeth_mc_mac), GFP_ATOMIC); - if (!mc) { - PRINT_ERR("no mem vor mc mac address\n"); + if (!mc) return; - } memcpy(mc->mc_addr, mac, OSA_ADDR_LEN); mc->mc_addrlen = OSA_ADDR_LEN; @@ -280,7 +275,7 @@ static int qeth_l2_send_setdelvlan_cb(struct qeth_card *card, QETH_DBF_TEXT(TRACE, 2, "L2sdvcb"); cmd = (struct qeth_ipa_cmd *) data; if (cmd->hdr.return_code) { - PRINT_ERR("Error in processing VLAN %i on %s: 0x%x. " + QETH_DBF_MESSAGE(2, "Error in processing VLAN %i on %s: 0x%x. " "Continuing\n", cmd->data.setdelvlan.vlan_id, QETH_CARD_IFNAME(card), cmd->hdr.return_code); QETH_DBF_TEXT_(TRACE, 2, "L2VL%4x", cmd->hdr.command); @@ -333,8 +328,6 @@ static void qeth_l2_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) spin_lock_bh(&card->vlanlock); list_add_tail(&id->list, &card->vid_list); spin_unlock_bh(&card->vlanlock); - } else { - PRINT_ERR("no memory for vid\n"); } } @@ -550,16 +543,15 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card) rc = qeth_query_setadapterparms(card); if (rc) { - PRINT_WARN("could not query adapter parameters on device %s: " - "x%x\n", CARD_BUS_ID(card), rc); + QETH_DBF_MESSAGE(2, "could not query adapter parameters on " + "device %s: x%x\n", CARD_BUS_ID(card), rc); } if (card->info.guestlan) { rc = qeth_setadpparms_change_macaddr(card); if (rc) { - PRINT_WARN("couldn't get MAC address on " - "device %s: x%x\n", - CARD_BUS_ID(card), rc); + QETH_DBF_MESSAGE(2, "couldn't get MAC address on " + "device %s: x%x\n", CARD_BUS_ID(card), rc); QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc); return rc; } @@ -585,8 +577,6 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p) } if (card->info.type == QETH_CARD_TYPE_OSN) { - PRINT_WARN("Setting MAC address on %s is not supported.\n", - dev->name); QETH_DBF_TEXT(TRACE, 3, "setmcOSN"); return -EOPNOTSUPP; } @@ -666,7 +656,7 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) ctx = qeth_eddp_create_context(card, new_skb, hdr, skb->sk->sk_protocol); if (ctx == NULL) { - PRINT_WARN("could not create eddp context\n"); + QETH_DBF_MESSAGE(2, "could not create eddp context\n"); goto tx_drop; } } else { @@ -731,6 +721,7 @@ tx_drop: if ((new_skb != skb) && new_skb) dev_kfree_skb_any(new_skb); dev_kfree_skb_any(skb); + netif_wake_queue(dev); return NETDEV_TX_OK; } @@ -1155,7 +1146,7 @@ static int qeth_osn_send_control_data(struct qeth_card *card, int len, (addr_t) iob, 0, 0); spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags); if (rc) { - PRINT_WARN("qeth_osn_send_control_data: " + QETH_DBF_MESSAGE(2, "qeth_osn_send_control_data: " "ccw_device_start rc = %i\n", rc); QETH_DBF_TEXT_(TRACE, 2, " err%d", rc); qeth_release_buffer(iob->channel, iob); diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 94a8ead64ed4..999552c83bbe 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -311,7 +311,6 @@ static struct qeth_ipaddr *qeth_l3_get_addr_buffer( addr = kzalloc(sizeof(struct qeth_ipaddr), GFP_ATOMIC); if (addr == NULL) { - PRINT_WARN("Not enough memory to add address\n"); return NULL; } addr->type = QETH_IP_TYPE_NORMAL; @@ -649,15 +648,6 @@ static void qeth_l3_correct_routing_type(struct qeth_card *card, } } out_inval: - PRINT_WARN("Routing type '%s' not supported for interface %s.\n" - "Router status set to 'no router'.\n", - ((*type == PRIMARY_ROUTER)? "primary router" : - (*type == SECONDARY_ROUTER)? "secondary router" : - (*type == PRIMARY_CONNECTOR)? "primary connector" : - (*type == SECONDARY_CONNECTOR)? "secondary connector" : - (*type == MULTICAST_ROUTER)? "multicast router" : - "unknown"), - card->dev->name); *type = NO_ROUTER; } @@ -674,9 +664,9 @@ int qeth_l3_setrouting_v4(struct qeth_card *card) QETH_PROT_IPV4); if (rc) { card->options.route4.type = NO_ROUTER; - PRINT_WARN("Error (0x%04x) while setting routing type on %s. " - "Type set to 'no router'.\n", - rc, QETH_CARD_IFNAME(card)); + QETH_DBF_MESSAGE(2, "Error (0x%04x) while setting routing type" + " on %s. Type set to 'no router'.\n", rc, + QETH_CARD_IFNAME(card)); } return rc; } @@ -697,9 +687,9 @@ int qeth_l3_setrouting_v6(struct qeth_card *card) QETH_PROT_IPV6); if (rc) { card->options.route6.type = NO_ROUTER; - PRINT_WARN("Error (0x%04x) while setting routing type on %s. " - "Type set to 'no router'.\n", - rc, QETH_CARD_IFNAME(card)); + QETH_DBF_MESSAGE(2, "Error (0x%04x) while setting routing type" + " on %s. Type set to 'no router'.\n", rc, + QETH_CARD_IFNAME(card)); } #endif return rc; @@ -737,7 +727,6 @@ int qeth_l3_add_ipato_entry(struct qeth_card *card, if (!memcmp(ipatoe->addr, new->addr, (ipatoe->proto == QETH_PROT_IPV4)? 4:16) && (ipatoe->mask_bits == new->mask_bits)) { - PRINT_WARN("ipato entry already exists!\n"); rc = -EEXIST; break; } @@ -802,7 +791,6 @@ int qeth_l3_add_vipa(struct qeth_card *card, enum qeth_prot_versions proto, rc = -EEXIST; spin_unlock_irqrestore(&card->ip_lock, flags); if (rc) { - PRINT_WARN("Cannot add VIPA. Address already exists!\n"); return rc; } if (!qeth_l3_add_ip(card, ipaddr)) @@ -867,7 +855,6 @@ int qeth_l3_add_rxip(struct qeth_card *card, enum qeth_prot_versions proto, rc = -EEXIST; spin_unlock_irqrestore(&card->ip_lock, flags); if (rc) { - PRINT_WARN("Cannot add RXIP. Address already exists!\n"); return rc; } if (!qeth_l3_add_ip(card, ipaddr)) @@ -1020,23 +1007,23 @@ static int qeth_l3_setadapter_hstr(struct qeth_card *card) IPA_SETADP_SET_BROADCAST_MODE, card->options.broadcast_mode); if (rc) - PRINT_WARN("couldn't set broadcast mode on " + QETH_DBF_MESSAGE(2, "couldn't set broadcast mode on " "device %s: x%x\n", CARD_BUS_ID(card), rc); rc = qeth_l3_send_setadp_mode(card, IPA_SETADP_ALTER_MAC_ADDRESS, card->options.macaddr_mode); if (rc) - PRINT_WARN("couldn't set macaddr mode on " + QETH_DBF_MESSAGE(2, "couldn't set macaddr mode on " "device %s: x%x\n", CARD_BUS_ID(card), rc); return rc; } if (card->options.broadcast_mode == QETH_TR_BROADCAST_LOCAL) - PRINT_WARN("set adapter parameters not available " + QETH_DBF_MESSAGE(2, "set adapter parameters not available " "to set broadcast mode, using ALLRINGS " "on device %s:\n", CARD_BUS_ID(card)); if (card->options.macaddr_mode == QETH_TR_MACADDR_CANONICAL) - PRINT_WARN("set adapter parameters not available " + QETH_DBF_MESSAGE(2, "set adapter parameters not available " "to set macaddr mode, using NONCANONICAL " "on device %s:\n", CARD_BUS_ID(card)); return 0; @@ -2070,7 +2057,7 @@ static struct qeth_card *qeth_l3_get_card_from_dev(struct net_device *dev) card = netdev_priv(dev); else if (rc == QETH_VLAN_CARD) card = netdev_priv(vlan_dev_info(dev)->real_dev); - if (card->options.layer2) + if (card && card->options.layer2) card = NULL; QETH_DBF_TEXT_(TRACE, 4, "%d", rc); return card ; @@ -2182,8 +2169,6 @@ static int qeth_l3_arp_set_no_entries(struct qeth_card *card, int no_entries) if (card->info.guestlan) return -EOPNOTSUPP; if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) { - PRINT_WARN("ARP processing not supported " - "on %s!\n", QETH_CARD_IFNAME(card)); return -EOPNOTSUPP; } rc = qeth_l3_send_simple_setassparms(card, IPA_ARP_PROCESSING, @@ -2191,8 +2176,8 @@ static int qeth_l3_arp_set_no_entries(struct qeth_card *card, int no_entries) no_entries); if (rc) { tmp = rc; - PRINT_WARN("Could not set number of ARP entries on %s: " - "%s (0x%x/%d)\n", QETH_CARD_IFNAME(card), + QETH_DBF_MESSAGE(2, "Could not set number of ARP entries on " + "%s: %s (0x%x/%d)\n", QETH_CARD_IFNAME(card), qeth_l3_arp_get_error_cause(&rc), tmp, tmp); } return rc; @@ -2260,9 +2245,6 @@ static int qeth_l3_arp_query_cb(struct qeth_card *card, qdata->no_entries * uentry_size){ QETH_DBF_TEXT_(TRACE, 4, "qaer3%i", -ENOMEM); cmd->hdr.return_code = -ENOMEM; - PRINT_WARN("query ARP user space buffer is too small for " - "the returned number of ARP entries. " - "Aborting query!\n"); goto out_error; } QETH_DBF_TEXT_(TRACE, 4, "anore%i", @@ -2324,8 +2306,6 @@ static int qeth_l3_arp_query(struct qeth_card *card, char __user *udata) if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/ IPA_ARP_PROCESSING)) { - PRINT_WARN("ARP processing not supported " - "on %s!\n", QETH_CARD_IFNAME(card)); return -EOPNOTSUPP; } /* get size of userspace buffer and mask_bits -> 6 bytes */ @@ -2344,7 +2324,7 @@ static int qeth_l3_arp_query(struct qeth_card *card, char __user *udata) qeth_l3_arp_query_cb, (void *)&qinfo); if (rc) { tmp = rc; - PRINT_WARN("Error while querying ARP cache on %s: %s " + QETH_DBF_MESSAGE(2, "Error while querying ARP cache on %s: %s " "(0x%x/%d)\n", QETH_CARD_IFNAME(card), qeth_l3_arp_get_error_cause(&rc), tmp, tmp); if (copy_to_user(udata, qinfo.udata, 4)) @@ -2375,8 +2355,6 @@ static int qeth_l3_arp_add_entry(struct qeth_card *card, if (card->info.guestlan) return -EOPNOTSUPP; if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) { - PRINT_WARN("ARP processing not supported " - "on %s!\n", QETH_CARD_IFNAME(card)); return -EOPNOTSUPP; } @@ -2391,10 +2369,9 @@ static int qeth_l3_arp_add_entry(struct qeth_card *card, if (rc) { tmp = rc; qeth_l3_ipaddr4_to_string((u8 *)entry->ipaddr, buf); - PRINT_WARN("Could not add ARP entry for address %s on %s: " - "%s (0x%x/%d)\n", - buf, QETH_CARD_IFNAME(card), - qeth_l3_arp_get_error_cause(&rc), tmp, tmp); + QETH_DBF_MESSAGE(2, "Could not add ARP entry for address %s " + "on %s: %s (0x%x/%d)\n", buf, QETH_CARD_IFNAME(card), + qeth_l3_arp_get_error_cause(&rc), tmp, tmp); } return rc; } @@ -2417,8 +2394,6 @@ static int qeth_l3_arp_remove_entry(struct qeth_card *card, if (card->info.guestlan) return -EOPNOTSUPP; if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) { - PRINT_WARN("ARP processing not supported " - "on %s!\n", QETH_CARD_IFNAME(card)); return -EOPNOTSUPP; } memcpy(buf, entry, 12); @@ -2433,10 +2408,9 @@ static int qeth_l3_arp_remove_entry(struct qeth_card *card, tmp = rc; memset(buf, 0, 16); qeth_l3_ipaddr4_to_string((u8 *)entry->ipaddr, buf); - PRINT_WARN("Could not delete ARP entry for address %s on %s: " - "%s (0x%x/%d)\n", - buf, QETH_CARD_IFNAME(card), - qeth_l3_arp_get_error_cause(&rc), tmp, tmp); + QETH_DBF_MESSAGE(2, "Could not delete ARP entry for address %s" + " on %s: %s (0x%x/%d)\n", buf, QETH_CARD_IFNAME(card), + qeth_l3_arp_get_error_cause(&rc), tmp, tmp); } return rc; } @@ -2456,16 +2430,14 @@ static int qeth_l3_arp_flush_cache(struct qeth_card *card) if (card->info.guestlan || (card->info.type == QETH_CARD_TYPE_IQD)) return -EOPNOTSUPP; if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) { - PRINT_WARN("ARP processing not supported " - "on %s!\n", QETH_CARD_IFNAME(card)); return -EOPNOTSUPP; } rc = qeth_l3_send_simple_setassparms(card, IPA_ARP_PROCESSING, IPA_CMD_ASS_ARP_FLUSH_CACHE, 0); if (rc) { tmp = rc; - PRINT_WARN("Could not flush ARP cache on %s: %s (0x%x/%d)\n", - QETH_CARD_IFNAME(card), + QETH_DBF_MESSAGE(2, "Could not flush ARP cache on %s: %s " + "(0x%x/%d)\n", QETH_CARD_IFNAME(card), qeth_l3_arp_get_error_cause(&rc), tmp, tmp); } return rc; @@ -2724,7 +2696,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) ctx = qeth_eddp_create_context(card, new_skb, hdr, skb->sk->sk_protocol); if (ctx == NULL) { - PRINT_WARN("could not create eddp context\n"); + QETH_DBF_MESSAGE(2, "could not create eddp context\n"); goto tx_drop; } } else { @@ -2792,6 +2764,7 @@ tx_drop: if ((new_skb != skb) && new_skb) dev_kfree_skb_any(new_skb); dev_kfree_skb_any(skb); + netif_wake_queue(dev); return NETDEV_TX_OK; } diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c index 08f51fd902c4..ac1993708ae9 100644 --- a/drivers/s390/net/qeth_l3_sys.c +++ b/drivers/s390/net/qeth_l3_sys.c @@ -85,7 +85,6 @@ static ssize_t qeth_l3_dev_route_store(struct qeth_card *card, } else if (!strcmp(tmp, "multicast_router")) { route->type = MULTICAST_ROUTER; } else { - PRINT_WARN("Invalid routing type '%s'.\n", tmp); return -EINVAL; } if (((card->state == CARD_STATE_SOFTSETUP) || @@ -137,9 +136,6 @@ static ssize_t qeth_l3_dev_route6_store(struct device *dev, return -EINVAL; if (!qeth_is_supported(card, IPA_IPV6)) { - PRINT_WARN("IPv6 not supported for interface %s.\n" - "Routing status no changed.\n", - QETH_CARD_IFNAME(card)); return -ENOTSUPP; } @@ -179,7 +175,6 @@ static ssize_t qeth_l3_dev_fake_broadcast_store(struct device *dev, if ((i == 0) || (i == 1)) card->options.fake_broadcast = i; else { - PRINT_WARN("fake_broadcast: write 0 or 1 to this file!\n"); return -EINVAL; } return count; @@ -220,7 +215,6 @@ static ssize_t qeth_l3_dev_broadcast_mode_store(struct device *dev, if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) || (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) { - PRINT_WARN("Device is not a tokenring device!\n"); return -EINVAL; } @@ -233,8 +227,6 @@ static ssize_t qeth_l3_dev_broadcast_mode_store(struct device *dev, card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS; return count; } else { - PRINT_WARN("broadcast_mode: invalid mode %s!\n", - tmp); return -EINVAL; } return count; @@ -275,7 +267,6 @@ static ssize_t qeth_l3_dev_canonical_macaddr_store(struct device *dev, if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) || (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) { - PRINT_WARN("Device is not a tokenring device!\n"); return -EINVAL; } @@ -285,7 +276,6 @@ static ssize_t qeth_l3_dev_canonical_macaddr_store(struct device *dev, QETH_TR_MACADDR_CANONICAL : QETH_TR_MACADDR_NONCANONICAL; else { - PRINT_WARN("canonical_macaddr: write 0 or 1 to this file!\n"); return -EINVAL; } return count; @@ -327,7 +317,6 @@ static ssize_t qeth_l3_dev_checksum_store(struct device *dev, else if (!strcmp(tmp, "no_checksumming")) card->options.checksum_type = NO_CHECKSUMMING; else { - PRINT_WARN("Unknown checksumming type '%s'\n", tmp); return -EINVAL; } return count; @@ -382,8 +371,6 @@ static ssize_t qeth_l3_dev_ipato_enable_store(struct device *dev, } else if (!strcmp(tmp, "0")) { card->ipato.enabled = 0; } else { - PRINT_WARN("ipato_enable: write 0, 1 or 'toggle' to " - "this file\n"); return -EINVAL; } return count; @@ -422,8 +409,6 @@ static ssize_t qeth_l3_dev_ipato_invert4_store(struct device *dev, } else if (!strcmp(tmp, "0")) { card->ipato.invert4 = 0; } else { - PRINT_WARN("ipato_invert4: write 0, 1 or 'toggle' to " - "this file\n"); return -EINVAL; } return count; @@ -486,13 +471,10 @@ static int qeth_l3_parse_ipatoe(const char *buf, enum qeth_prot_versions proto, /* get address string */ end = strchr(start, '/'); if (!end || (end - start >= 40)) { - PRINT_WARN("Invalid format for ipato_addx/delx. " - "Use <ip addr>/<mask bits>\n"); return -EINVAL; } strncpy(buffer, start, end - start); if (qeth_l3_string_to_ipaddr(buffer, proto, addr)) { - PRINT_WARN("Invalid IP address format!\n"); return -EINVAL; } start = end + 1; @@ -500,7 +482,6 @@ static int qeth_l3_parse_ipatoe(const char *buf, enum qeth_prot_versions proto, if (!strlen(start) || (tmp == start) || (*mask_bits > ((proto == QETH_PROT_IPV4) ? 32 : 128))) { - PRINT_WARN("Invalid mask bits for ipato_addx/delx !\n"); return -EINVAL; } return 0; @@ -520,7 +501,6 @@ static ssize_t qeth_l3_dev_ipato_add_store(const char *buf, size_t count, ipatoe = kzalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL); if (!ipatoe) { - PRINT_WARN("No memory to allocate ipato entry\n"); return -ENOMEM; } ipatoe->proto = proto; @@ -609,8 +589,6 @@ static ssize_t qeth_l3_dev_ipato_invert6_store(struct device *dev, } else if (!strcmp(tmp, "0")) { card->ipato.invert6 = 0; } else { - PRINT_WARN("ipato_invert6: write 0, 1 or 'toggle' to " - "this file\n"); return -EINVAL; } return count; @@ -724,7 +702,6 @@ static int qeth_l3_parse_vipae(const char *buf, enum qeth_prot_versions proto, u8 *addr) { if (qeth_l3_string_to_ipaddr(buf, proto, addr)) { - PRINT_WARN("Invalid IP address format!\n"); return -EINVAL; } return 0; @@ -891,7 +868,6 @@ static int qeth_l3_parse_rxipe(const char *buf, enum qeth_prot_versions proto, u8 *addr) { if (qeth_l3_string_to_ipaddr(buf, proto, addr)) { - PRINT_WARN("Invalid IP address format!\n"); return -EINVAL; } return 0; diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c index 5080f343ad74..5bfbe7659830 100644 --- a/drivers/s390/s390mach.c +++ b/drivers/s390/s390mach.c @@ -207,6 +207,7 @@ s390_handle_mcck(void) do_exit(SIGSEGV); } } +EXPORT_SYMBOL_GPL(s390_handle_mcck); /* * returns 0 if all registers could be validated diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index ccfd8aca3765..5d23368a1bce 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -1348,7 +1348,7 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq, del_timer(&evt_struct->timer); - if (crq->status != VIOSRP_OK && evt_struct->cmnd) + if ((crq->status != VIOSRP_OK && crq->status != VIOSRP_OK2) && evt_struct->cmnd) evt_struct->cmnd->result = DID_ERROR << 16; if (evt_struct->done) evt_struct->done(evt_struct); diff --git a/drivers/scsi/ibmvscsi/viosrp.h b/drivers/scsi/ibmvscsi/viosrp.h index 4c4aadb3e405..204604501ad8 100644 --- a/drivers/scsi/ibmvscsi/viosrp.h +++ b/drivers/scsi/ibmvscsi/viosrp.h @@ -65,7 +65,8 @@ enum viosrp_crq_status { VIOSRP_VIOLATES_MAX_XFER = 0x2, VIOSRP_PARTNER_PANIC = 0x3, VIOSRP_DEVICE_BUSY = 0x8, - VIOSRP_ADAPTER_FAIL = 0x10 + VIOSRP_ADAPTER_FAIL = 0x10, + VIOSRP_OK2 = 0x99, }; struct viosrp_crq { diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 287690853caf..8dd88fc1244a 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -70,6 +70,9 @@ qla2x00_sysfs_write_fw_dump(struct kobject *kobj, case 2: qla2x00_alloc_fw_dump(ha); break; + case 3: + qla2x00_system_error(ha); + break; } return (count); } @@ -886,9 +889,13 @@ qla2x00_get_host_speed(struct Scsi_Host *shost) static void qla2x00_get_host_port_type(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = to_qla_parent(shost_priv(shost)); + scsi_qla_host_t *ha = shost_priv(shost); uint32_t port_type = FC_PORTTYPE_UNKNOWN; + if (ha->parent) { + fc_host_port_type(shost) = FC_PORTTYPE_NPIV; + return; + } switch (ha->current_topology) { case ISP_CFG_NL: port_type = FC_PORTTYPE_LPORT; @@ -1172,10 +1179,10 @@ qla24xx_vport_delete(struct fc_vport *fc_vport) qla24xx_disable_vp(vha); qla24xx_deallocate_vp_id(vha); - down(&ha->vport_sem); + mutex_lock(&ha->vport_lock); ha->cur_vport_count--; clear_bit(vha->vp_idx, ha->vp_idx_map); - up(&ha->vport_sem); + mutex_unlock(&ha->vport_lock); kfree(vha->node_name); kfree(vha->port_name); diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 299eccf6cabd..8dd600013bd1 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2457,7 +2457,7 @@ typedef struct scsi_qla_host { #define MBX_INTR_WAIT 2 #define MBX_UPDATE_FLASH_ACTIVE 3 - struct semaphore vport_sem; /* Virtual port synchronization */ + struct mutex vport_lock; /* Virtual port synchronization */ struct completion mbx_cmd_comp; /* Serialize mbx access */ struct completion mbx_intr_comp; /* Used for completion notification */ diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index f8827068d30f..9b4bebee6879 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -228,6 +228,9 @@ extern int qla24xx_abort_target(struct fc_port *, unsigned int); extern int qla24xx_lun_reset(struct fc_port *, unsigned int); extern int +qla2x00_system_error(scsi_qla_host_t *); + +extern int qla2x00_set_serdes_params(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t); extern int diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index e9bae27737d1..92fafbdbbaab 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h @@ -34,7 +34,11 @@ qla2x00_debounce_register(volatile uint16_t __iomem *addr) static inline void qla2x00_poll(scsi_qla_host_t *ha) { + unsigned long flags; + + local_irq_save(flags); ha->isp_ops->intr_handler(0, ha); + local_irq_restore(flags); } static __inline__ scsi_qla_host_t * diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 5d9a64a7879b..ec63b79f900a 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -272,8 +272,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) uint32_t rscn_entry, host_pid; uint8_t rscn_queue_index; unsigned long flags; - scsi_qla_host_t *vha; - int i; /* Setup to process RIO completion. */ handle_cnt = 0; @@ -544,18 +542,10 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) break; case MBA_PORT_UPDATE: /* Port database update */ - if ((ha->flags.npiv_supported) && (ha->num_vhosts)) { - for_each_mapped_vp_idx(ha, i) { - list_for_each_entry(vha, &ha->vp_list, - vp_list) { - if ((mb[3] & 0xff) - == vha->vp_idx) { - ha = vha; - break; - } - } - } - } + /* Only handle SCNs for our Vport index. */ + if (ha->parent && ha->vp_idx != (mb[3] & 0xff)) + break; + /* * If PORT UPDATE is global (recieved LIP_OCCURED/LIP_RESET * event etc. earlier indicating loop is down) then process @@ -590,18 +580,12 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) break; case MBA_RSCN_UPDATE: /* State Change Registration */ - if ((ha->flags.npiv_supported) && (ha->num_vhosts)) { - for_each_mapped_vp_idx(ha, i) { - list_for_each_entry(vha, &ha->vp_list, - vp_list) { - if ((mb[3] & 0xff) - == vha->vp_idx) { - ha = vha; - break; - } - } - } - } + /* Check if the Vport has issued a SCR */ + if (ha->parent && test_bit(VP_SCR_NEEDED, &ha->vp_flags)) + break; + /* Only handle SCNs for our Vport index. */ + if (ha->parent && ha->vp_idx != (mb[3] & 0xff)) + break; DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n", ha->host_no)); @@ -1132,25 +1116,6 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) break; qla2x00_handle_sense(sp, sense_data, sense_len); - - /* - * In case of a Underrun condition, set both the lscsi - * status and the completion status to appropriate - * values. - */ - if (resid && - ((unsigned)(scsi_bufflen(cp) - resid) < - cp->underflow)) { - DEBUG2(qla_printk(KERN_INFO, ha, - "scsi(%ld:%d:%d:%d): Mid-layer underflow " - "detected (%x of %x bytes)...returning " - "error status.\n", ha->host_no, - cp->device->channel, cp->device->id, - cp->device->lun, resid, - scsi_bufflen(cp))); - - cp->result = DID_ERROR << 16 | lscsi_status; - } } else { /* * If RISC reports underrun and target does not report @@ -1639,12 +1604,12 @@ qla24xx_msix_rsp_q(int irq, void *dev_id) ha = dev_id; reg = &ha->iobase->isp24; - spin_lock(&ha->hardware_lock); + spin_lock_irq(&ha->hardware_lock); qla24xx_process_response_queue(ha); WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); - spin_unlock(&ha->hardware_lock); + spin_unlock_irq(&ha->hardware_lock); return IRQ_HANDLED; } @@ -1663,7 +1628,7 @@ qla24xx_msix_default(int irq, void *dev_id) reg = &ha->iobase->isp24; status = 0; - spin_lock(&ha->hardware_lock); + spin_lock_irq(&ha->hardware_lock); do { stat = RD_REG_DWORD(®->host_status); if (stat & HSRX_RISC_PAUSED) { @@ -1716,7 +1681,7 @@ qla24xx_msix_default(int irq, void *dev_id) } WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); } while (0); - spin_unlock(&ha->hardware_lock); + spin_unlock_irq(&ha->hardware_lock); if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && (status & MBX_INTERRUPT) && ha->flags.mbox_int) { diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 210060420809..250d2f604397 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -2303,8 +2303,6 @@ qla24xx_lun_reset(struct fc_port *fcport, unsigned int l) return __qla24xx_issue_tmf("Lun", TCF_LUN_RESET, fcport, l); } -#if 0 - int qla2x00_system_error(scsi_qla_host_t *ha) { @@ -2312,7 +2310,7 @@ qla2x00_system_error(scsi_qla_host_t *ha) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - if (!IS_FWI2_CAPABLE(ha)) + if (!IS_QLA23XX(ha) && !IS_FWI2_CAPABLE(ha)) return QLA_FUNCTION_FAILED; DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); @@ -2334,8 +2332,6 @@ qla2x00_system_error(scsi_qla_host_t *ha) return rval; } -#endif /* 0 */ - /** * qla2x00_set_serdes_params() - * @ha: HA context @@ -2508,7 +2504,7 @@ qla2x00_enable_fce_trace(scsi_qla_host_t *ha, dma_addr_t fce_dma, if (mb) memcpy(mb, mcp->mb, 8 * sizeof(*mb)); if (dwords) - *dwords = mcp->mb[6]; + *dwords = buffers; } return rval; @@ -2807,9 +2803,9 @@ qla24xx_control_vp(scsi_qla_host_t *vha, int cmd) */ map = (vp_index - 1) / 8; pos = (vp_index - 1) & 7; - down(&ha->vport_sem); + mutex_lock(&ha->vport_lock); vce->vp_idx_map[map] |= 1 << pos; - up(&ha->vport_sem); + mutex_unlock(&ha->vport_lock); rval = qla2x00_issue_iocb(ha, vce, vce_dma, 0); if (rval != QLA_SUCCESS) { diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index f2b04979e5f0..62a3ad6e8ecb 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -32,12 +32,12 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha) scsi_qla_host_t *ha = vha->parent; /* Find an empty slot and assign an vp_id */ - down(&ha->vport_sem); + mutex_lock(&ha->vport_lock); vp_id = find_first_zero_bit(ha->vp_idx_map, ha->max_npiv_vports + 1); if (vp_id > ha->max_npiv_vports) { DEBUG15(printk ("vp_id %d is bigger than max-supported %d.\n", vp_id, ha->max_npiv_vports)); - up(&ha->vport_sem); + mutex_unlock(&ha->vport_lock); return vp_id; } @@ -45,7 +45,7 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha) ha->num_vhosts++; vha->vp_idx = vp_id; list_add_tail(&vha->vp_list, &ha->vp_list); - up(&ha->vport_sem); + mutex_unlock(&ha->vport_lock); return vp_id; } @@ -55,12 +55,12 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha) uint16_t vp_id; scsi_qla_host_t *ha = vha->parent; - down(&ha->vport_sem); + mutex_lock(&ha->vport_lock); vp_id = vha->vp_idx; ha->num_vhosts--; clear_bit(vp_id, ha->vp_idx_map); list_del(&vha->vp_list); - up(&ha->vport_sem); + mutex_unlock(&ha->vport_lock); } static scsi_qla_host_t * @@ -145,9 +145,9 @@ qla24xx_enable_vp(scsi_qla_host_t *vha) } /* Initialize the new vport unless it is a persistent port */ - down(&ha->vport_sem); + mutex_lock(&ha->vport_lock); ret = qla24xx_modify_vp_config(vha); - up(&ha->vport_sem); + mutex_unlock(&ha->vport_lock); if (ret != QLA_SUCCESS) { fc_vport_set_state(vha->fc_vport, FC_VPORT_FAILED); @@ -406,6 +406,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport) INIT_LIST_HEAD(&vha->list); INIT_LIST_HEAD(&vha->fcports); INIT_LIST_HEAD(&vha->vp_fcports); + INIT_LIST_HEAD(&vha->work_list); vha->dpc_flags = 0L; set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags); @@ -437,10 +438,10 @@ qla24xx_create_vhost(struct fc_vport *fc_vport) vha->flags.init_done = 1; num_hosts++; - down(&ha->vport_sem); + mutex_lock(&ha->vport_lock); set_bit(vha->vp_idx, ha->vp_idx_map); ha->cur_vport_count++; - up(&ha->vport_sem); + mutex_unlock(&ha->vport_lock); return vha; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 3223fd16bcfe..48eaa3bb5433 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -10,6 +10,7 @@ #include <linux/vmalloc.h> #include <linux/delay.h> #include <linux/kthread.h> +#include <linux/mutex.h> #include <scsi/scsi_tcq.h> #include <scsi/scsicam.h> @@ -1631,7 +1632,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) /* load the F/W, read paramaters, and init the H/W */ ha->instance = num_hosts; - init_MUTEX(&ha->vport_sem); + mutex_init(&ha->vport_lock); init_completion(&ha->mbx_cmd_comp); complete(&ha->mbx_cmd_comp); init_completion(&ha->mbx_intr_comp); @@ -2156,13 +2157,14 @@ static int qla2x00_post_work(struct scsi_qla_host *ha, struct qla_work_evt *e, int locked) { unsigned long flags; + scsi_qla_host_t *pha = to_qla_parent(ha); if (!locked) - spin_lock_irqsave(&ha->hardware_lock, flags); + spin_lock_irqsave(&pha->hardware_lock, flags); list_add_tail(&e->list, &ha->work_list); qla2xxx_wake_dpc(ha); if (!locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); + spin_unlock_irqrestore(&pha->hardware_lock, flags); return QLA_SUCCESS; } @@ -2202,12 +2204,13 @@ static void qla2x00_do_work(struct scsi_qla_host *ha) { struct qla_work_evt *e; + scsi_qla_host_t *pha = to_qla_parent(ha); - spin_lock_irq(&ha->hardware_lock); + spin_lock_irq(&pha->hardware_lock); while (!list_empty(&ha->work_list)) { e = list_entry(ha->work_list.next, struct qla_work_evt, list); list_del_init(&e->list); - spin_unlock_irq(&ha->hardware_lock); + spin_unlock_irq(&pha->hardware_lock); switch (e->type) { case QLA_EVT_AEN: @@ -2221,9 +2224,9 @@ qla2x00_do_work(struct scsi_qla_host *ha) } if (e->flags & QLA_EVT_FLAG_FREE) kfree(e); - spin_lock_irq(&ha->hardware_lock); + spin_lock_irq(&pha->hardware_lock); } - spin_unlock_irq(&ha->hardware_lock); + spin_unlock_irq(&pha->hardware_lock); } /************************************************************************** @@ -2634,7 +2637,7 @@ qla2x00_timer(scsi_qla_host_t *ha) #define FW_FILE_ISP24XX "ql2400_fw.bin" #define FW_FILE_ISP25XX "ql2500_fw.bin" -static DECLARE_MUTEX(qla_fw_lock); +static DEFINE_MUTEX(qla_fw_lock); static struct fw_blob qla_fw_blobs[FW_BLOBS] = { { .name = FW_FILE_ISP21XX, .segs = { 0x1000, 0 }, }, @@ -2665,7 +2668,7 @@ qla2x00_request_firmware(scsi_qla_host_t *ha) blob = &qla_fw_blobs[FW_ISP25XX]; } - down(&qla_fw_lock); + mutex_lock(&qla_fw_lock); if (blob->fw) goto out; @@ -2678,7 +2681,7 @@ qla2x00_request_firmware(scsi_qla_host_t *ha) } out: - up(&qla_fw_lock); + mutex_unlock(&qla_fw_lock); return blob; } @@ -2687,11 +2690,11 @@ qla2x00_release_firmware(void) { int idx; - down(&qla_fw_lock); + mutex_lock(&qla_fw_lock); for (idx = 0; idx < FW_BLOBS; idx++) if (qla_fw_blobs[idx].fw) release_firmware(qla_fw_blobs[idx].fw); - up(&qla_fw_lock); + mutex_unlock(&qla_fw_lock); } static pci_ers_result_t @@ -2864,7 +2867,8 @@ qla2x00_module_init(void) return -ENODEV; } - printk(KERN_INFO "QLogic Fibre Channel HBA Driver\n"); + printk(KERN_INFO "QLogic Fibre Channel HBA Driver: %s\n", + qla2x00_version_str); ret = pci_register_driver(&qla2xxx_pci_driver); if (ret) { kmem_cache_destroy(srb_cachep); diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index afeae2bfe7eb..d058c8862b35 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.02.01-k2" +#define QLA2XXX_VERSION "8.02.01-k4" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 2 diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 049103f1d16f..93d2b6714453 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -359,7 +359,12 @@ static int scsi_bus_match(struct device *dev, struct device_driver *gendrv) static int scsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env) { - struct scsi_device *sdev = to_scsi_device(dev); + struct scsi_device *sdev; + + if (dev->type != &scsi_dev_type) + return 0; + + sdev = to_scsi_device(dev); add_uevent_var(env, "MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type); return 0; diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 1400ea6a2491..1bc00b721e9d 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -43,7 +43,6 @@ #include <asm/io.h> #include <asm/irq.h> -#include <asm/serial.h> #include "8250.h" @@ -93,6 +92,7 @@ static unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS; */ #define CONFIG_HUB6 1 +#include <asm/serial.h> /* * SERIAL_PORT_DFNS tells us about built-in ports that have no * standard enumeration mechanism. Platforms that can find all @@ -1547,8 +1547,6 @@ static int serial_link_irq_chain(struct uart_8250_port *up) i->head = &up->list; spin_unlock_irq(&i->lock); - irq_flags |= SERIAL_EXTRA_IRQ_FLAGS; - ret = request_irq(up->port.irq, serial8250_interrupt, irq_flags, "serial", i); if (ret < 0) diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h index a10a40cc0d9e..91bd28f2bb47 100644 --- a/drivers/serial/8250.h +++ b/drivers/serial/8250.h @@ -78,8 +78,3 @@ struct serial8250_config { #else #define ALPHA_KLUDGE_MCR 0 #endif - -#ifndef SERIAL_EXTRA_IRQ_FLAGS -#define SERIAL_EXTRA_IRQ_FLAGS 0 -#endif - diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index c065a704a93a..42be8b01a40f 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c @@ -1318,7 +1318,7 @@ static void __init atmel_console_get_options(struct uart_port *port, int *baud, * If the baud rate generator isn't running, the port wasn't * initialized by the boot loader. */ - quot = UART_GET_BRGR(port); + quot = UART_GET_BRGR(port) & ATMEL_US_CD; if (!quot) return; diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c index d6b4ead693b7..f20952c43cb8 100644 --- a/drivers/serial/bfin_5xx.c +++ b/drivers/serial/bfin_5xx.c @@ -530,11 +530,7 @@ static unsigned int bfin_serial_get_mctrl(struct uart_port *port) if (uart->cts_pin < 0) return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; -# ifdef BF54x - if (UART_GET_MSR(uart) & CTS) -# else - if (gpio_get_value(uart->cts_pin)) -# endif + if (UART_GET_CTS(uart)) return TIOCM_DSR | TIOCM_CAR; else #endif @@ -549,17 +545,9 @@ static void bfin_serial_set_mctrl(struct uart_port *port, unsigned int mctrl) return; if (mctrl & TIOCM_RTS) -# ifdef BF54x - UART_PUT_MCR(uart, UART_GET_MCR(uart) & ~MRTS); -# else - gpio_set_value(uart->rts_pin, 0); -# endif + UART_CLEAR_RTS(uart); else -# ifdef BF54x - UART_PUT_MCR(uart, UART_GET_MCR(uart) | MRTS); -# else - gpio_set_value(uart->rts_pin, 1); -# endif + UART_SET_RTS(uart); #endif } @@ -752,11 +740,7 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios, /* Disable UART */ ier = UART_GET_IER(uart); -#ifdef CONFIG_BF54x - UART_CLEAR_IER(uart, 0xF); -#else - UART_PUT_IER(uart, 0); -#endif + UART_DISABLE_INTS(uart); /* Set DLAB in LCR to Access DLL and DLH */ UART_SET_DLAB(uart); @@ -771,11 +755,7 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios, UART_PUT_LCR(uart, lcr); /* Enable UART */ -#ifdef CONFIG_BF54x - UART_SET_IER(uart, ier); -#else - UART_PUT_IER(uart, ier); -#endif + UART_ENABLE_INTS(uart, ier); val = UART_GET_GCTL(uart); val |= UCEN; @@ -833,15 +813,15 @@ bfin_serial_verify_port(struct uart_port *port, struct serial_struct *ser) * Enable the IrDA function if tty->ldisc.num is N_IRDA. * In other cases, disable IrDA function. */ -static void bfin_set_ldisc(struct tty_struct *tty) +static void bfin_serial_set_ldisc(struct uart_port *port) { - int line = tty->index; + int line = port->line; unsigned short val; - if (line >= tty->driver->num) + if (line >= port->info->tty->driver->num) return; - switch (tty->ldisc.num) { + switch (port->info->tty->ldisc.num) { case N_IRDA: val = UART_GET_GCTL(&bfin_serial_ports[line]); val |= (IREN | RPOLC); @@ -866,6 +846,7 @@ static struct uart_ops bfin_serial_pops = { .startup = bfin_serial_startup, .shutdown = bfin_serial_shutdown, .set_termios = bfin_serial_set_termios, + .set_ldisc = bfin_serial_set_ldisc, .type = bfin_serial_type, .release_port = bfin_serial_release_port, .request_port = bfin_serial_request_port, @@ -1206,7 +1187,6 @@ static int __init bfin_serial_init(void) ret = uart_register_driver(&bfin_serial_reg); if (ret == 0) { - bfin_serial_reg.tty_driver->set_ldisc = bfin_set_ldisc; ret = platform_driver_register(&bfin_serial_driver); if (ret) { pr_debug("uart register failed\n"); diff --git a/drivers/serial/sb1250-duart.c b/drivers/serial/sb1250-duart.c index 2d6c08b3dbcf..f8e1447a022a 100644 --- a/drivers/serial/sb1250-duart.c +++ b/drivers/serial/sb1250-duart.c @@ -924,7 +924,7 @@ console_initcall(sbd_serial_console_init); static struct uart_driver sbd_reg = { .owner = THIS_MODULE, - .driver_name = "serial", + .driver_name = "sb1250_duart", .dev_name = "duart", .major = TTY_MAJOR, .minor = SB1250_DUART_MINOR_BASE, diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 53b03c629aff..c9b64e73c987 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1165,6 +1165,15 @@ out: return ret; } +static void uart_set_ldisc(struct tty_struct *tty) +{ + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; + + if (port->ops->set_ldisc) + port->ops->set_ldisc(port); +} + static void uart_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { @@ -2288,6 +2297,7 @@ static const struct tty_operations uart_ops = { .unthrottle = uart_unthrottle, .send_xchar = uart_send_xchar, .set_termios = uart_set_termios, + .set_ldisc = uart_set_ldisc, .stop = uart_stop, .start = uart_start, .hangup = uart_hangup, diff --git a/drivers/serial/ucc_uart.c b/drivers/serial/ucc_uart.c index 01917c433f17..566a8b42e05a 100644 --- a/drivers/serial/ucc_uart.c +++ b/drivers/serial/ucc_uart.c @@ -195,7 +195,7 @@ struct uart_qe_port { static struct uart_driver ucc_uart_driver = { .owner = THIS_MODULE, - .driver_name = "serial", + .driver_name = "ucc_uart", .dev_name = "ttyQE", .major = SERIAL_QE_MAJOR, .minor = SERIAL_QE_MINOR, diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 41620c0fb046..799337f7fde1 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -25,6 +25,7 @@ #include <linux/ioctl.h> #include <linux/fs.h> #include <linux/device.h> +#include <linux/err.h> #include <linux/list.h> #include <linux/errno.h> #include <linux/mutex.h> @@ -67,11 +68,12 @@ static unsigned long minors[N_SPI_MINORS / BITS_PER_LONG]; | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP) struct spidev_data { - struct device dev; + dev_t devt; spinlock_t spi_lock; struct spi_device *spi; struct list_head device_entry; + /* buffer is NULL unless this device is open (users > 0) */ struct mutex buf_lock; unsigned users; u8 *buffer; @@ -467,7 +469,7 @@ static int spidev_open(struct inode *inode, struct file *filp) mutex_lock(&device_list_lock); list_for_each_entry(spidev, &device_list, device_entry) { - if (spidev->dev.devt == inode->i_rdev) { + if (spidev->devt == inode->i_rdev) { status = 0; break; } @@ -500,10 +502,22 @@ static int spidev_release(struct inode *inode, struct file *filp) mutex_lock(&device_list_lock); spidev = filp->private_data; filp->private_data = NULL; + + /* last close? */ spidev->users--; if (!spidev->users) { + int dofree; + kfree(spidev->buffer); spidev->buffer = NULL; + + /* ... after we unbound from the underlying device? */ + spin_lock_irq(&spidev->spi_lock); + dofree = (spidev->spi == NULL); + spin_unlock_irq(&spidev->spi_lock); + + if (dofree) + kfree(spidev); } mutex_unlock(&device_list_lock); @@ -530,19 +544,7 @@ static struct file_operations spidev_fops = { * It also simplifies memory management. */ -static void spidev_classdev_release(struct device *dev) -{ - struct spidev_data *spidev; - - spidev = container_of(dev, struct spidev_data, dev); - kfree(spidev); -} - -static struct class spidev_class = { - .name = "spidev", - .owner = THIS_MODULE, - .dev_release = spidev_classdev_release, -}; +static struct class *spidev_class; /*-------------------------------------------------------------------------*/ @@ -570,20 +572,20 @@ static int spidev_probe(struct spi_device *spi) mutex_lock(&device_list_lock); minor = find_first_zero_bit(minors, N_SPI_MINORS); if (minor < N_SPI_MINORS) { - spidev->dev.parent = &spi->dev; - spidev->dev.class = &spidev_class; - spidev->dev.devt = MKDEV(SPIDEV_MAJOR, minor); - snprintf(spidev->dev.bus_id, sizeof spidev->dev.bus_id, + struct device *dev; + + spidev->devt = MKDEV(SPIDEV_MAJOR, minor); + dev = device_create(spidev_class, &spi->dev, spidev->devt, "spidev%d.%d", spi->master->bus_num, spi->chip_select); - status = device_register(&spidev->dev); + status = IS_ERR(dev) ? PTR_ERR(dev) : 0; } else { dev_dbg(&spi->dev, "no minor number available!\n"); status = -ENODEV; } if (status == 0) { set_bit(minor, minors); - dev_set_drvdata(&spi->dev, spidev); + spi_set_drvdata(spi, spidev); list_add(&spidev->device_entry, &device_list); } mutex_unlock(&device_list_lock); @@ -596,19 +598,21 @@ static int spidev_probe(struct spi_device *spi) static int spidev_remove(struct spi_device *spi) { - struct spidev_data *spidev = dev_get_drvdata(&spi->dev); + struct spidev_data *spidev = spi_get_drvdata(spi); /* make sure ops on existing fds can abort cleanly */ spin_lock_irq(&spidev->spi_lock); spidev->spi = NULL; + spi_set_drvdata(spi, NULL); spin_unlock_irq(&spidev->spi_lock); /* prevent new opens */ mutex_lock(&device_list_lock); list_del(&spidev->device_entry); - dev_set_drvdata(&spi->dev, NULL); - clear_bit(MINOR(spidev->dev.devt), minors); - device_unregister(&spidev->dev); + device_destroy(spidev_class, spidev->devt); + clear_bit(MINOR(spidev->devt), minors); + if (spidev->users == 0) + kfree(spidev); mutex_unlock(&device_list_lock); return 0; @@ -644,15 +648,15 @@ static int __init spidev_init(void) if (status < 0) return status; - status = class_register(&spidev_class); - if (status < 0) { + spidev_class = class_create(THIS_MODULE, "spidev"); + if (IS_ERR(spidev_class)) { unregister_chrdev(SPIDEV_MAJOR, spidev_spi.driver.name); - return status; + return PTR_ERR(spidev_class); } status = spi_register_driver(&spidev_spi); if (status < 0) { - class_unregister(&spidev_class); + class_destroy(spidev_class); unregister_chrdev(SPIDEV_MAJOR, spidev_spi.driver.name); } return status; @@ -662,7 +666,7 @@ module_init(spidev_init); static void __exit spidev_exit(void) { spi_unregister_driver(&spidev_spi); - class_unregister(&spidev_class); + class_destroy(spidev_class); unregister_chrdev(SPIDEV_MAJOR, spidev_spi.driver.name); } module_exit(spidev_exit); diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index 75def13e797d..d28c53868093 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c @@ -537,12 +537,12 @@ int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc, int err = 0; u32 tmp; - might_sleep(); - if (!pdev) goto out; bus = pdev->bus; + might_sleep_if(pdev->id.coreid != SSB_DEV_PCI); + /* Enable interrupts for this device. */ if (bus->host_pci && ((pdev->id.revision >= 6) || (pdev->id.coreid == SSB_DEV_PCIE))) { diff --git a/drivers/usb/c67x00/c67x00-ll-hpi.c b/drivers/usb/c67x00/c67x00-ll-hpi.c index 5100fbbf6cb0..a9636f43bca2 100644 --- a/drivers/usb/c67x00/c67x00-ll-hpi.c +++ b/drivers/usb/c67x00/c67x00-ll-hpi.c @@ -120,7 +120,7 @@ static void hpi_write_word(struct c67x00_device *dev, u16 reg, u16 value) * Only data is little endian, addr has cpu endianess */ static void hpi_write_words_le16(struct c67x00_device *dev, u16 addr, - u16 *data, u16 count) + __le16 *data, u16 count) { unsigned long flags; int i; @@ -129,7 +129,7 @@ static void hpi_write_words_le16(struct c67x00_device *dev, u16 addr, hpi_write_reg(dev, HPI_ADDR, addr); for (i = 0; i < count; i++) - hpi_write_reg(dev, HPI_DATA, cpu_to_le16(*data++)); + hpi_write_reg(dev, HPI_DATA, le16_to_cpu(*data++)); spin_unlock_irqrestore(&dev->hpi.lock, flags); } @@ -138,7 +138,7 @@ static void hpi_write_words_le16(struct c67x00_device *dev, u16 addr, * Only data is little endian, addr has cpu endianess */ static void hpi_read_words_le16(struct c67x00_device *dev, u16 addr, - u16 *data, u16 count) + __le16 *data, u16 count) { unsigned long flags; int i; @@ -146,7 +146,7 @@ static void hpi_read_words_le16(struct c67x00_device *dev, u16 addr, spin_lock_irqsave(&dev->hpi.lock, flags); hpi_write_reg(dev, HPI_ADDR, addr); for (i = 0; i < count; i++) - *data++ = le16_to_cpu(hpi_read_reg(dev, HPI_DATA)); + *data++ = cpu_to_le16(hpi_read_reg(dev, HPI_DATA)); spin_unlock_irqrestore(&dev->hpi.lock, flags); } @@ -425,7 +425,7 @@ void c67x00_ll_write_mem_le16(struct c67x00_device *dev, u16 addr, len--; } - hpi_write_words_le16(dev, addr, (u16 *)buf, len / 2); + hpi_write_words_le16(dev, addr, (__le16 *)buf, len / 2); buf += len & ~0x01; addr += len & ~0x01; len &= 0x01; @@ -456,7 +456,7 @@ void c67x00_ll_read_mem_le16(struct c67x00_device *dev, u16 addr, len--; } - hpi_read_words_le16(dev, addr, (u16 *)buf, len / 2); + hpi_read_words_le16(dev, addr, (__le16 *)buf, len / 2); buf += len & ~0x01; addr += len & ~0x01; len &= 0x01; diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 107666d4e2ec..731db051070a 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -611,8 +611,8 @@ next_desc: goto err; } - desc->wMaxPacketSize = ep->wMaxPacketSize; - desc->bMaxPacketSize0 = cpu_to_le16(udev->descriptor.bMaxPacketSize0); + desc->wMaxPacketSize = le16_to_cpu(ep->wMaxPacketSize); + desc->bMaxPacketSize0 = udev->descriptor.bMaxPacketSize0; desc->orq = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); if (!desc->orq) diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index c1cb94e9f242..7e912f21fd36 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c @@ -155,9 +155,6 @@ static int generic_probe(struct usb_device *udev) { int err, c; - /* put device-specific files into sysfs */ - usb_create_sysfs_dev_files(udev); - /* Choose and set the configuration. This registers the interfaces * with the driver core and lets interface drivers bind to them. */ @@ -189,8 +186,6 @@ static void generic_disconnect(struct usb_device *udev) * unconfigure the device */ if (udev->actconfig) usb_set_configuration(udev, -1); - - usb_remove_sysfs_dev_files(udev); } #ifdef CONFIG_PM diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 1e4b81e9eb50..a0bf5df6cb6f 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -213,6 +213,8 @@ struct hc_driver { /* force handover of high-speed port to full-speed companion */ void (*relinquish_port)(struct usb_hcd *, int); + /* has a port been handed over to a companion? */ + int (*port_handed_over)(struct usb_hcd *, int); }; extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index eb57fcc701d7..94789be54ca3 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -644,6 +644,48 @@ static void hub_stop(struct usb_hub *hub) #ifdef CONFIG_PM +/* Try to identify which devices need USB-PERSIST handling */ +static int persistent_device(struct usb_device *udev) +{ + int i; + int retval; + struct usb_host_config *actconfig; + + /* Explicitly not marked persistent? */ + if (!udev->persist_enabled) + return 0; + + /* No active config? */ + actconfig = udev->actconfig; + if (!actconfig) + return 0; + + /* FIXME! We should check whether it's open here or not! */ + + /* + * Check that all the interface drivers have a + * 'reset_resume' entrypoint + */ + retval = 0; + for (i = 0; i < actconfig->desc.bNumInterfaces; i++) { + struct usb_interface *intf; + struct usb_driver *driver; + + intf = actconfig->interface[i]; + if (!intf->dev.driver) + continue; + driver = to_usb_driver(intf->dev.driver); + if (!driver->reset_resume) + return 0; + /* + * We have at least one driver, and that one + * has a reset_resume method. + */ + retval = 1; + } + return retval; +} + static void hub_restart(struct usb_hub *hub, int type) { struct usb_device *hdev = hub->hdev; @@ -689,8 +731,8 @@ static void hub_restart(struct usb_hub *hub, int type) * turn off the various status changes to prevent * khubd from disconnecting it later. */ - if (udev->persist_enabled && status == 0 && - !(portstatus & USB_PORT_STAT_ENABLE)) { + if (status == 0 && !(portstatus & USB_PORT_STAT_ENABLE) && + persistent_device(udev)) { if (portchange & USB_PORT_STAT_C_ENABLE) clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_ENABLE); @@ -1326,6 +1368,12 @@ void usb_disconnect(struct usb_device **pdev) usb_unlock_device(udev); + /* Remove the device-specific files from sysfs. This must be + * done with udev unlocked, because some of the attribute + * routines try to acquire the device lock. + */ + usb_remove_sysfs_dev_files(udev); + /* Unregister the device. The device driver is responsible * for removing the device files from usbfs and sysfs and for * de-configuring the device. @@ -1541,6 +1589,9 @@ int usb_new_device(struct usb_device *udev) goto fail; } + /* put device-specific files into sysfs */ + usb_create_sysfs_dev_files(udev); + /* Tell the world! */ announce_device(udev); return err; @@ -2744,7 +2795,11 @@ loop: if ((status == -ENOTCONN) || (status == -ENOTSUPP)) break; } - dev_err(hub_dev, "unable to enumerate USB device on port %d\n", port1); + if (hub->hdev->parent || + !hcd->driver->port_handed_over || + !(hcd->driver->port_handed_over)(hcd, port1)) + dev_err(hub_dev, "unable to enumerate USB device on port %d\n", + port1); done: hub_port_disable(hub, port1, 1); diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 2e2019390290..3da1ab4b389d 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -47,6 +47,10 @@ static const struct usb_device_id usb_quirk_list[] = { /* Edirol SD-20 */ { USB_DEVICE(0x0582, 0x0027), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Avision AV600U */ + { USB_DEVICE(0x0638, 0x0a13), .driver_info = + USB_QUIRK_STRING_FETCH_255 }, + /* M-Systems Flash Disk Pioneers */ { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index c783cb111847..5e1f5d55bf04 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -588,35 +588,33 @@ read_descriptors(struct kobject *kobj, struct bin_attribute *attr, container_of(kobj, struct device, kobj)); size_t nleft = count; size_t srclen, n; + int cfgno; + void *src; - usb_lock_device(udev); - - /* The binary attribute begins with the device descriptor */ - srclen = sizeof(struct usb_device_descriptor); - if (off < srclen) { - n = min_t(size_t, nleft, srclen - off); - memcpy(buf, off + (char *) &udev->descriptor, n); - nleft -= n; - buf += n; - off = 0; - } else { - off -= srclen; - } - - /* Then follows the raw descriptor entry for the current - * configuration (config plus subsidiary descriptors). + /* The binary attribute begins with the device descriptor. + * Following that are the raw descriptor entries for all the + * configurations (config plus subsidiary descriptors). */ - if (udev->actconfig) { - int cfgno = udev->actconfig - udev->config; - - srclen = __le16_to_cpu(udev->actconfig->desc.wTotalLength); + for (cfgno = -1; cfgno < udev->descriptor.bNumConfigurations && + nleft > 0; ++cfgno) { + if (cfgno < 0) { + src = &udev->descriptor; + srclen = sizeof(struct usb_device_descriptor); + } else { + src = udev->rawdescriptors[cfgno]; + srclen = __le16_to_cpu(udev->config[cfgno].desc. + wTotalLength); + } if (off < srclen) { - n = min_t(size_t, nleft, srclen - off); - memcpy(buf, off + udev->rawdescriptors[cfgno], n); + n = min(nleft, srclen - (size_t) off); + memcpy(buf, src + off, n); nleft -= n; + buf += n; + off = 0; + } else { + off -= srclen; } } - usb_unlock_device(udev); return count - nleft; } diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c index 651b82701394..18687543d7fa 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.c +++ b/drivers/usb/gadget/fsl_usb2_udc.c @@ -1627,7 +1627,9 @@ static int reset_queues(struct fsl_udc *udc) udc_reset_ep_queue(udc, pipe); /* report disconnect; the driver is already quiesced */ + spin_unlock(&udc->lock); udc->driver->disconnect(&udc->gadget); + spin_lock(&udc->lock); return 0; } diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 1ef6df395e0c..228797e54f9c 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -300,8 +300,8 @@ config USB_R8A66597_HCD module will be called r8a66597-hcd. config SUPERH_ON_CHIP_R8A66597 - boolean "Enable SuperH on-chip USB like the R8A66597" - depends on USB_R8A66597_HCD && CPU_SUBTYPE_SH7366 + boolean "Enable SuperH on-chip R8A66597 USB" + depends on USB_R8A66597_HCD && (CPU_SUBTYPE_SH7366 || CPU_SUBTYPE_SH7723) help - Renesas SuperH processor has USB like the R8A66597. - This driver supported processor is SH7366. + This driver enables support for the on-chip R8A66597 in the + SH7366 and SH7723 processors. diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c index 8b5f991e949c..08a4335401a9 100644 --- a/drivers/usb/host/ehci-au1xxx.c +++ b/drivers/usb/host/ehci-au1xxx.c @@ -223,6 +223,7 @@ static const struct hc_driver ehci_au1xxx_hc_driver = { .bus_suspend = ehci_bus_suspend, .bus_resume = ehci_bus_resume, .relinquish_port = ehci_relinquish_port, + .port_handed_over = ehci_port_handed_over, }; /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 6d9bed6c1f48..7370d6187c64 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -269,7 +269,7 @@ static int ehci_fsl_setup(struct usb_hcd *hcd) if (retval) return retval; - ehci->is_tdi_rh_tt = 1; + hcd->has_tt = 1; ehci->sbrn = 0x20; @@ -295,10 +295,6 @@ static const struct hc_driver ehci_fsl_hc_driver = { */ .reset = ehci_fsl_setup, .start = ehci_run, -#ifdef CONFIG_PM - .suspend = ehci_bus_suspend, - .resume = ehci_bus_resume, -#endif .stop = ehci_stop, .shutdown = ehci_shutdown, @@ -322,6 +318,7 @@ static const struct hc_driver ehci_fsl_hc_driver = { .bus_suspend = ehci_bus_suspend, .bus_resume = ehci_bus_resume, .relinquish_port = ehci_relinquish_port, + .port_handed_over = ehci_port_handed_over, }; static int ehci_fsl_drv_probe(struct platform_device *pdev) diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 382587c4457c..740835bb8575 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -609,7 +609,7 @@ static int ehci_hub_control ( } break; case USB_PORT_FEAT_C_SUSPEND: - /* we auto-clear this feature */ + clear_bit(wIndex, &ehci->port_c_suspend); break; case USB_PORT_FEAT_POWER: if (HCS_PPC (ehci->hcs_params)) @@ -688,7 +688,7 @@ static int ehci_hub_control ( /* resume completed? */ else if (time_after_eq(jiffies, ehci->reset_done[wIndex])) { - status |= 1 << USB_PORT_FEAT_C_SUSPEND; + set_bit(wIndex, &ehci->port_c_suspend); ehci->reset_done[wIndex] = 0; /* stop resume signaling */ @@ -765,6 +765,8 @@ static int ehci_hub_control ( status |= 1 << USB_PORT_FEAT_RESET; if (temp & PORT_POWER) status |= 1 << USB_PORT_FEAT_POWER; + if (test_bit(wIndex, &ehci->port_c_suspend)) + status |= 1 << USB_PORT_FEAT_C_SUSPEND; #ifndef VERBOSE_DEBUG if (status & ~0xffff) /* only if wPortChange is interesting */ @@ -875,3 +877,13 @@ static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum) set_owner(ehci, --portnum, PORT_OWNER); } +static int ehci_port_handed_over(struct usb_hcd *hcd, int portnum) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + u32 __iomem *reg; + + if (ehci_is_TDI(ehci)) + return 0; + reg = &ehci->regs->port_status[portnum - 1]; + return ehci_readl(ehci, reg) & PORT_OWNER; +} diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c index 601c8795a854..9d042f220097 100644 --- a/drivers/usb/host/ehci-ixp4xx.c +++ b/drivers/usb/host/ehci-ixp4xx.c @@ -26,7 +26,7 @@ static int ixp4xx_ehci_init(struct usb_hcd *hcd) + HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - ehci->is_tdi_rh_tt = 1; + hcd->has_tt = 1; ehci_reset(ehci); retval = ehci_init(hcd); @@ -58,6 +58,8 @@ static const struct hc_driver ixp4xx_ehci_hc_driver = { .bus_suspend = ehci_bus_suspend, .bus_resume = ehci_bus_resume, #endif + .relinquish_port = ehci_relinquish_port, + .port_handed_over = ehci_port_handed_over, }; static int ixp4xx_ehci_probe(struct platform_device *pdev) diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index 3adfda813a7b..ab625f0ba1d9 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c @@ -139,10 +139,6 @@ static const struct hc_driver ehci_orion_hc_driver = { */ .reset = ehci_orion_setup, .start = ehci_run, -#ifdef CONFIG_PM - .suspend = ehci_bus_suspend, - .resume = ehci_bus_resume, -#endif .stop = ehci_stop, .shutdown = ehci_shutdown, @@ -165,6 +161,8 @@ static const struct hc_driver ehci_orion_hc_driver = { .hub_control = ehci_hub_control, .bus_suspend = ehci_bus_suspend, .bus_resume = ehci_bus_resume, + .relinquish_port = ehci_relinquish_port, + .port_handed_over = ehci_port_handed_over, }; static void __init @@ -250,7 +248,7 @@ static int __init ehci_orion_drv_probe(struct platform_device *pdev) ehci->regs = hcd->regs + 0x100 + HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - ehci->is_tdi_rh_tt = 1; + hcd->has_tt = 1; ehci->sbrn = 0x20; /* diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 5bb7f6bb13f3..c46a58f9181d 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -129,7 +129,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) switch (pdev->vendor) { case PCI_VENDOR_ID_TDI: if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { - ehci->is_tdi_rh_tt = 1; hcd->has_tt = 1; tdi_reset(ehci); } @@ -379,7 +378,8 @@ static const struct hc_driver ehci_pci_hc_driver = { .hub_control = ehci_hub_control, .bus_suspend = ehci_bus_suspend, .bus_resume = ehci_bus_resume, - .relinquish_port = ehci_relinquish_port, + .relinquish_port = ehci_relinquish_port, + .port_handed_over = ehci_port_handed_over, }; /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c index ee305b1f99ff..b018deed2e8f 100644 --- a/drivers/usb/host/ehci-ppc-of.c +++ b/drivers/usb/host/ehci-ppc-of.c @@ -76,6 +76,8 @@ static const struct hc_driver ehci_ppc_of_hc_driver = { .bus_suspend = ehci_bus_suspend, .bus_resume = ehci_bus_resume, #endif + .relinquish_port = ehci_relinquish_port, + .port_handed_over = ehci_port_handed_over, }; diff --git a/drivers/usb/host/ehci-ppc-soc.c b/drivers/usb/host/ehci-ppc-soc.c index 6c76036783a1..529590eb4037 100644 --- a/drivers/usb/host/ehci-ppc-soc.c +++ b/drivers/usb/host/ehci-ppc-soc.c @@ -163,6 +163,7 @@ static const struct hc_driver ehci_ppc_soc_hc_driver = { .bus_suspend = ehci_bus_suspend, .bus_resume = ehci_bus_resume, .relinquish_port = ehci_relinquish_port, + .port_handed_over = ehci_port_handed_over, }; static int ehci_hcd_ppc_soc_drv_probe(struct platform_device *pdev) diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c index 69782221bcf3..37e6abeb794c 100644 --- a/drivers/usb/host/ehci-ps3.c +++ b/drivers/usb/host/ehci-ps3.c @@ -73,6 +73,7 @@ static const struct hc_driver ps3_ehci_hc_driver = { .bus_resume = ehci_bus_resume, #endif .relinquish_port = ehci_relinquish_port, + .port_handed_over = ehci_port_handed_over, }; static int ps3_ehci_probe(struct ps3_system_bus_device *dev) diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index be575e46eac3..b7853c8bac0f 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1349,18 +1349,27 @@ iso_stream_schedule ( /* when's the last uframe this urb could start? */ max = now + mod; - /* typical case: reuse current schedule. stream is still active, - * and no gaps from host falling behind (irq delays etc) + /* Typical case: reuse current schedule, stream is still active. + * Hopefully there are no gaps from the host falling behind + * (irq delays etc), but if there are we'll take the next + * slot in the schedule, implicitly assuming URB_ISO_ASAP. */ if (likely (!list_empty (&stream->td_list))) { start = stream->next_uframe; if (start < now) start += mod; - if (likely ((start + sched->span) < max)) - goto ready; - /* else fell behind; someday, try to reschedule */ - status = -EL2NSYNC; - goto fail; + + /* Fell behind (by up to twice the slop amount)? */ + if (start >= max - 2 * 8 * SCHEDULE_SLOP) + start += stream->interval * DIV_ROUND_UP( + max - start, stream->interval) - mod; + + /* Tried to schedule too far into the future? */ + if (unlikely((start + sched->span) >= max)) { + status = -EFBIG; + goto fail; + } + goto ready; } /* need to schedule; when's the next (u)frame we could start? @@ -1613,6 +1622,9 @@ itd_complete ( } else if (likely ((t & EHCI_ISOC_ACTIVE) == 0)) { desc->status = 0; desc->actual_length = EHCI_ITD_LENGTH (t); + } else { + /* URB was too late */ + desc->status = -EXDEV; } } @@ -2095,7 +2107,7 @@ done: static void scan_periodic (struct ehci_hcd *ehci) { - unsigned frame, clock, now_uframe, mod; + unsigned now_uframe, frame, clock, clock_frame, mod; unsigned modified; mod = ehci->periodic_size << 3; @@ -2111,6 +2123,7 @@ scan_periodic (struct ehci_hcd *ehci) else clock = now_uframe + mod - 1; clock %= mod; + clock_frame = clock >> 3; for (;;) { union ehci_shadow q, *q_p; @@ -2157,22 +2170,26 @@ restart: case Q_TYPE_ITD: /* If this ITD is still active, leave it for * later processing ... check the next entry. + * No need to check for activity unless the + * frame is current. */ - rmb (); - for (uf = 0; uf < 8 && live; uf++) { - if (0 == (q.itd->hw_transaction [uf] - & ITD_ACTIVE(ehci))) - continue; - incomplete = true; - q_p = &q.itd->itd_next; - hw_p = &q.itd->hw_next; - type = Q_NEXT_TYPE(ehci, + if (frame == clock_frame && live) { + rmb(); + for (uf = 0; uf < 8; uf++) { + if (q.itd->hw_transaction[uf] & + ITD_ACTIVE(ehci)) + break; + } + if (uf < 8) { + incomplete = true; + q_p = &q.itd->itd_next; + hw_p = &q.itd->hw_next; + type = Q_NEXT_TYPE(ehci, q.itd->hw_next); - q = *q_p; - break; + q = *q_p; + break; + } } - if (uf < 8 && live) - break; /* Take finished ITDs out of the schedule * and process them: recycle, maybe report @@ -2189,9 +2206,12 @@ restart: case Q_TYPE_SITD: /* If this SITD is still active, leave it for * later processing ... check the next entry. + * No need to check for activity unless the + * frame is current. */ - if ((q.sitd->hw_results & SITD_ACTIVE(ehci)) - && live) { + if (frame == clock_frame && live && + (q.sitd->hw_results & + SITD_ACTIVE(ehci))) { incomplete = true; q_p = &q.sitd->sitd_next; hw_p = &q.sitd->hw_next; @@ -2260,6 +2280,7 @@ restart: /* rescan the rest of this frame, then ... */ clock = now; + clock_frame = clock >> 3; } else { now_uframe++; now_uframe %= mod; diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index bf92d209a1a9..35a03095757e 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -97,6 +97,8 @@ struct ehci_hcd { /* one per controller */ dedicated to the companion controller */ unsigned long owned_ports; /* which ports are owned by the companion during a bus suspend */ + unsigned long port_c_suspend; /* which ports have + the change-suspend feature turned on */ /* per-HC memory pools (could be per-bus, but ...) */ struct dma_pool *qh_pool; /* qh per active urb */ @@ -112,7 +114,6 @@ struct ehci_hcd { /* one per controller */ u32 command; /* SILICON QUIRKS */ - unsigned is_tdi_rh_tt:1; /* TDI roothub with TT */ unsigned no_selective_suspend:1; unsigned has_fsl_port_bug:1; /* FreeScale */ unsigned big_endian_mmio:1; @@ -678,7 +679,7 @@ struct ehci_fstn { * needed (mostly in root hub code). */ -#define ehci_is_TDI(e) ((e)->is_tdi_rh_tt) +#define ehci_is_TDI(e) (ehci_to_hcd(e)->has_tt) /* Returns the speed of a device attached to a port on the root hub. */ static inline unsigned int diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index c9cec8738261..65aa5ecf569a 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -2207,14 +2207,14 @@ struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq, goto err_put; } - ret = usb_add_hcd(hcd, irq, irqflags); - if (ret) - goto err_unmap; - hcd->irq = irq; hcd->rsrc_start = res_start; hcd->rsrc_len = res_len; + ret = usb_add_hcd(hcd, irq, irqflags); + if (ret) + goto err_unmap; + return hcd; err_unmap: diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index 440bf94f0d4c..c9db3fe98726 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -104,8 +104,8 @@ static u32 nxp_pci_io_base; static u32 iolength; static u32 pci_mem_phy0; static u32 length; -static u8 *chip_addr; -static u8 *iobase; +static u8 __iomem *chip_addr; +static u8 __iomem *iobase; static int __devinit isp1761_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index a53db1d4e07a..001789c9a11a 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -269,3 +269,15 @@ config USB_TEST See <http://www.linux-usb.org/usbtest/> for more information, including sample test device firmware and "how to use it". +config USB_ISIGHTFW + tristate "iSight firmware loading support" + depends on USB + select FW_LOADER + help + This driver loads firmware for USB Apple iSight cameras, allowing + them to be driven by the USB video class driver available at + http://linux-uvc.berlios.de + + The firmware for this driver must be extracted from the MacOS + driver beforehand. Tools for doing so are available at + http://bersace03.free.fr diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index b68e6b774f1a..aba091cb5ec0 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_USB_EMI62) += emi62.o obj-$(CONFIG_USB_FTDI_ELAN) += ftdi-elan.o obj-$(CONFIG_USB_IDMOUSE) += idmouse.o obj-$(CONFIG_USB_IOWARRIOR) += iowarrior.o +obj-$(CONFIG_USB_ISIGHTFW) += isight_firmware.o obj-$(CONFIG_USB_LCD) += usblcd.o obj-$(CONFIG_USB_LD) += ldusb.o obj-$(CONFIG_USB_LED) += usbled.o diff --git a/drivers/usb/misc/isight_firmware.c b/drivers/usb/misc/isight_firmware.c new file mode 100644 index 000000000000..9f30aa1f8a5d --- /dev/null +++ b/drivers/usb/misc/isight_firmware.c @@ -0,0 +1,140 @@ +/* + * Driver for loading USB isight firmware + * + * Copyright (C) 2008 Matthew Garrett <mjg@redhat.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 2. + * + * The USB isight cameras in recent Apples are roughly compatible with the USB + * video class specification, and can be driven by uvcvideo. However, they + * need firmware to be loaded beforehand. After firmware loading, the device + * detaches from the USB bus and reattaches with a new device ID. It can then + * be claimed by the uvc driver. + * + * The firmware is non-free and must be extracted by the user. Tools to do this + * are available at http://bersace03.free.fr/ift/ + * + * The isight firmware loading was reverse engineered by Johannes Berg + * <johannes@sipsolutions.de>, and this driver is based on code by Ronald + * Bultje <rbultje@ronald.bitfreak.net> + */ + +#include <linux/usb.h> +#include <linux/firmware.h> +#include <linux/errno.h> +#include <linux/module.h> + +static struct usb_device_id id_table[] = { + {USB_DEVICE(0x05ac, 0x8300)}, + {}, +}; + +MODULE_DEVICE_TABLE(usb, id_table); + +static int isight_firmware_load(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *dev = interface_to_usbdev(intf); + int llen, len, req, ret = 0; + const struct firmware *firmware; + unsigned char *buf = kmalloc(50, GFP_KERNEL); + unsigned char data[4]; + u8 *ptr; + + if (!buf) + return -ENOMEM; + + if (request_firmware(&firmware, "isight.fw", &dev->dev) != 0) { + printk(KERN_ERR "Unable to load isight firmware\n"); + return -ENODEV; + } + + ptr = firmware->data; + + if (usb_control_msg + (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\1", 1, + 300) != 1) { + printk(KERN_ERR + "Failed to initialise isight firmware loader\n"); + ret = -ENODEV; + goto out; + } + + while (ptr+4 <= firmware->data+firmware->size) { + memcpy(data, ptr, 4); + len = (data[0] << 8 | data[1]); + req = (data[2] << 8 | data[3]); + ptr += 4; + + if (len == 0x8001) + break; /* success */ + else if (len == 0) + continue; + + for (; len > 0; req += 50) { + llen = min(len, 50); + len -= llen; + if (ptr+llen > firmware->data+firmware->size) { + printk(KERN_ERR + "Malformed isight firmware"); + ret = -ENODEV; + goto out; + } + memcpy(buf, ptr, llen); + + ptr += llen; + + if (usb_control_msg + (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, req, 0, + buf, llen, 300) != llen) { + printk(KERN_ERR + "Failed to load isight firmware\n"); + kfree(buf); + ret = -ENODEV; + goto out; + } + + } + } + + if (usb_control_msg + (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\0", 1, + 300) != 1) { + printk(KERN_ERR "isight firmware loading completion failed\n"); + ret = -ENODEV; + } + +out: + kfree(buf); + release_firmware(firmware); + return ret; +} + +static void isight_firmware_disconnect(struct usb_interface *intf) +{ +} + +static struct usb_driver isight_firmware_driver = { + .name = "isight_firmware", + .probe = isight_firmware_load, + .disconnect = isight_firmware_disconnect, + .id_table = id_table, +}; + +static int __init isight_firmware_init(void) +{ + return usb_register(&isight_firmware_driver); +} + +static void __exit isight_firmware_exit(void) +{ + usb_deregister(&isight_firmware_driver); +} + +module_init(isight_firmware_init); +module_exit(isight_firmware_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>"); diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 3cee6feac174..5234e7a3bd2c 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -174,8 +174,270 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_MTXORB_4_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) }, - { USB_DEVICE(MTXORB_VK_VID, MTXORB_VK_PID), + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0100_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0101_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0102_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0103_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0104_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0105_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0106_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0107_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0108_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0109_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010A_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010B_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010C_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010D_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010E_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010F_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0110_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0111_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0112_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0113_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0114_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0115_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0116_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0117_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0118_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0119_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011A_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011B_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011C_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011D_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011E_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011F_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0120_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0121_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0122_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0123_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0124_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0125_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0126_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0127_PID), .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0128_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0129_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012A_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012B_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012C_PID), + .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012D_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012E_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012F_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0130_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0131_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0132_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0133_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0134_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0135_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0136_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0137_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0138_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0139_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013A_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013B_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013C_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013D_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013E_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013F_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0140_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0141_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0142_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0143_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0144_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0145_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0146_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0147_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0148_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0149_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014A_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014B_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014C_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014D_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014E_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014F_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0150_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0151_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0152_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0153_PID), + .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0154_PID), + .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0155_PID), + .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0156_PID), + .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0157_PID), + .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0158_PID), + .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0159_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015A_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015B_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015C_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015D_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015E_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015F_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0160_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0161_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0162_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0163_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0164_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0165_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0166_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0167_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0168_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0169_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016A_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016B_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016C_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016D_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016E_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016F_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0170_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0171_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0172_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0173_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0174_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0175_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0176_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0177_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0178_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0179_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017A_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017B_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017C_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017D_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017E_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017F_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0180_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0181_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0182_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0183_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0184_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0185_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0186_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0187_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0188_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0189_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018A_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018B_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018C_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018D_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018E_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018F_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0190_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0191_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0192_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0193_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0194_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0195_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0196_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0197_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0198_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0199_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019A_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019B_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019C_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019D_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019E_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019F_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A0_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A1_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A2_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A3_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A4_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A5_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A6_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A7_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A8_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A9_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AA_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AB_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AC_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AD_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AE_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AF_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B0_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B1_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B2_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B3_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B4_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B5_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B6_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B7_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B8_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B9_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BA_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BB_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BC_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BD_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BE_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BF_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C0_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C1_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C2_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C3_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C4_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C5_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C6_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C7_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C8_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C9_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CA_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CB_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CC_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CD_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CE_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CF_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D0_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D1_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D2_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D3_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D4_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D5_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D6_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D7_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D8_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D9_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DA_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DB_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DC_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DD_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DE_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DF_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E0_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E1_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E2_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E3_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E4_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E5_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E6_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E7_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E8_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E9_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EA_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EB_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EC_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01ED_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EE_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EF_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F0_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F1_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F2_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F3_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F4_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F5_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F6_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F7_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F8_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F9_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FA_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FB_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FC_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FD_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FE_PID) }, + { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FF_PID) }, { USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) }, { USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) }, { USB_DEVICE(FTDI_VID, FTDI_TNC_X_PID) }, diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index a72f2c81d664..06e0ecabb3eb 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -114,11 +114,268 @@ #define FTDI_OOCDLINK_PID 0xbaf8 /* Amontec JTAGkey */ /* - * The following are the values for the Matrix Orbital VK204-25-USB - * display, which use the FT232RL. - */ -#define MTXORB_VK_VID 0x1b3d -#define MTXORB_VK_PID 0x0158 + * The following are the values for the Matrix Orbital FTDI Range + * Anything in this range will use an FT232RL. + */ +#define MTXORB_VID 0x1B3D +#define MTXORB_FTDI_RANGE_0100_PID 0x0100 +#define MTXORB_FTDI_RANGE_0101_PID 0x0101 +#define MTXORB_FTDI_RANGE_0102_PID 0x0102 +#define MTXORB_FTDI_RANGE_0103_PID 0x0103 +#define MTXORB_FTDI_RANGE_0104_PID 0x0104 +#define MTXORB_FTDI_RANGE_0105_PID 0x0105 +#define MTXORB_FTDI_RANGE_0106_PID 0x0106 +#define MTXORB_FTDI_RANGE_0107_PID 0x0107 +#define MTXORB_FTDI_RANGE_0108_PID 0x0108 +#define MTXORB_FTDI_RANGE_0109_PID 0x0109 +#define MTXORB_FTDI_RANGE_010A_PID 0x010A +#define MTXORB_FTDI_RANGE_010B_PID 0x010B +#define MTXORB_FTDI_RANGE_010C_PID 0x010C +#define MTXORB_FTDI_RANGE_010D_PID 0x010D +#define MTXORB_FTDI_RANGE_010E_PID 0x010E +#define MTXORB_FTDI_RANGE_010F_PID 0x010F +#define MTXORB_FTDI_RANGE_0110_PID 0x0110 +#define MTXORB_FTDI_RANGE_0111_PID 0x0111 +#define MTXORB_FTDI_RANGE_0112_PID 0x0112 +#define MTXORB_FTDI_RANGE_0113_PID 0x0113 +#define MTXORB_FTDI_RANGE_0114_PID 0x0114 +#define MTXORB_FTDI_RANGE_0115_PID 0x0115 +#define MTXORB_FTDI_RANGE_0116_PID 0x0116 +#define MTXORB_FTDI_RANGE_0117_PID 0x0117 +#define MTXORB_FTDI_RANGE_0118_PID 0x0118 +#define MTXORB_FTDI_RANGE_0119_PID 0x0119 +#define MTXORB_FTDI_RANGE_011A_PID 0x011A +#define MTXORB_FTDI_RANGE_011B_PID 0x011B +#define MTXORB_FTDI_RANGE_011C_PID 0x011C +#define MTXORB_FTDI_RANGE_011D_PID 0x011D +#define MTXORB_FTDI_RANGE_011E_PID 0x011E +#define MTXORB_FTDI_RANGE_011F_PID 0x011F +#define MTXORB_FTDI_RANGE_0120_PID 0x0120 +#define MTXORB_FTDI_RANGE_0121_PID 0x0121 +#define MTXORB_FTDI_RANGE_0122_PID 0x0122 +#define MTXORB_FTDI_RANGE_0123_PID 0x0123 +#define MTXORB_FTDI_RANGE_0124_PID 0x0124 +#define MTXORB_FTDI_RANGE_0125_PID 0x0125 +#define MTXORB_FTDI_RANGE_0126_PID 0x0126 +#define MTXORB_FTDI_RANGE_0127_PID 0x0127 +#define MTXORB_FTDI_RANGE_0128_PID 0x0128 +#define MTXORB_FTDI_RANGE_0129_PID 0x0129 +#define MTXORB_FTDI_RANGE_012A_PID 0x012A +#define MTXORB_FTDI_RANGE_012B_PID 0x012B +#define MTXORB_FTDI_RANGE_012C_PID 0x012C +#define MTXORB_FTDI_RANGE_012D_PID 0x012D +#define MTXORB_FTDI_RANGE_012E_PID 0x012E +#define MTXORB_FTDI_RANGE_012F_PID 0x012F +#define MTXORB_FTDI_RANGE_0130_PID 0x0130 +#define MTXORB_FTDI_RANGE_0131_PID 0x0131 +#define MTXORB_FTDI_RANGE_0132_PID 0x0132 +#define MTXORB_FTDI_RANGE_0133_PID 0x0133 +#define MTXORB_FTDI_RANGE_0134_PID 0x0134 +#define MTXORB_FTDI_RANGE_0135_PID 0x0135 +#define MTXORB_FTDI_RANGE_0136_PID 0x0136 +#define MTXORB_FTDI_RANGE_0137_PID 0x0137 +#define MTXORB_FTDI_RANGE_0138_PID 0x0138 +#define MTXORB_FTDI_RANGE_0139_PID 0x0139 +#define MTXORB_FTDI_RANGE_013A_PID 0x013A +#define MTXORB_FTDI_RANGE_013B_PID 0x013B +#define MTXORB_FTDI_RANGE_013C_PID 0x013C +#define MTXORB_FTDI_RANGE_013D_PID 0x013D +#define MTXORB_FTDI_RANGE_013E_PID 0x013E +#define MTXORB_FTDI_RANGE_013F_PID 0x013F +#define MTXORB_FTDI_RANGE_0140_PID 0x0140 +#define MTXORB_FTDI_RANGE_0141_PID 0x0141 +#define MTXORB_FTDI_RANGE_0142_PID 0x0142 +#define MTXORB_FTDI_RANGE_0143_PID 0x0143 +#define MTXORB_FTDI_RANGE_0144_PID 0x0144 +#define MTXORB_FTDI_RANGE_0145_PID 0x0145 +#define MTXORB_FTDI_RANGE_0146_PID 0x0146 +#define MTXORB_FTDI_RANGE_0147_PID 0x0147 +#define MTXORB_FTDI_RANGE_0148_PID 0x0148 +#define MTXORB_FTDI_RANGE_0149_PID 0x0149 +#define MTXORB_FTDI_RANGE_014A_PID 0x014A +#define MTXORB_FTDI_RANGE_014B_PID 0x014B +#define MTXORB_FTDI_RANGE_014C_PID 0x014C +#define MTXORB_FTDI_RANGE_014D_PID 0x014D +#define MTXORB_FTDI_RANGE_014E_PID 0x014E +#define MTXORB_FTDI_RANGE_014F_PID 0x014F +#define MTXORB_FTDI_RANGE_0150_PID 0x0150 +#define MTXORB_FTDI_RANGE_0151_PID 0x0151 +#define MTXORB_FTDI_RANGE_0152_PID 0x0152 +#define MTXORB_FTDI_RANGE_0153_PID 0x0153 +#define MTXORB_FTDI_RANGE_0154_PID 0x0154 +#define MTXORB_FTDI_RANGE_0155_PID 0x0155 +#define MTXORB_FTDI_RANGE_0156_PID 0x0156 +#define MTXORB_FTDI_RANGE_0157_PID 0x0157 +#define MTXORB_FTDI_RANGE_0158_PID 0x0158 +#define MTXORB_FTDI_RANGE_0159_PID 0x0159 +#define MTXORB_FTDI_RANGE_015A_PID 0x015A +#define MTXORB_FTDI_RANGE_015B_PID 0x015B +#define MTXORB_FTDI_RANGE_015C_PID 0x015C +#define MTXORB_FTDI_RANGE_015D_PID 0x015D +#define MTXORB_FTDI_RANGE_015E_PID 0x015E +#define MTXORB_FTDI_RANGE_015F_PID 0x015F +#define MTXORB_FTDI_RANGE_0160_PID 0x0160 +#define MTXORB_FTDI_RANGE_0161_PID 0x0161 +#define MTXORB_FTDI_RANGE_0162_PID 0x0162 +#define MTXORB_FTDI_RANGE_0163_PID 0x0163 +#define MTXORB_FTDI_RANGE_0164_PID 0x0164 +#define MTXORB_FTDI_RANGE_0165_PID 0x0165 +#define MTXORB_FTDI_RANGE_0166_PID 0x0166 +#define MTXORB_FTDI_RANGE_0167_PID 0x0167 +#define MTXORB_FTDI_RANGE_0168_PID 0x0168 +#define MTXORB_FTDI_RANGE_0169_PID 0x0169 +#define MTXORB_FTDI_RANGE_016A_PID 0x016A +#define MTXORB_FTDI_RANGE_016B_PID 0x016B +#define MTXORB_FTDI_RANGE_016C_PID 0x016C +#define MTXORB_FTDI_RANGE_016D_PID 0x016D +#define MTXORB_FTDI_RANGE_016E_PID 0x016E +#define MTXORB_FTDI_RANGE_016F_PID 0x016F +#define MTXORB_FTDI_RANGE_0170_PID 0x0170 +#define MTXORB_FTDI_RANGE_0171_PID 0x0171 +#define MTXORB_FTDI_RANGE_0172_PID 0x0172 +#define MTXORB_FTDI_RANGE_0173_PID 0x0173 +#define MTXORB_FTDI_RANGE_0174_PID 0x0174 +#define MTXORB_FTDI_RANGE_0175_PID 0x0175 +#define MTXORB_FTDI_RANGE_0176_PID 0x0176 +#define MTXORB_FTDI_RANGE_0177_PID 0x0177 +#define MTXORB_FTDI_RANGE_0178_PID 0x0178 +#define MTXORB_FTDI_RANGE_0179_PID 0x0179 +#define MTXORB_FTDI_RANGE_017A_PID 0x017A +#define MTXORB_FTDI_RANGE_017B_PID 0x017B +#define MTXORB_FTDI_RANGE_017C_PID 0x017C +#define MTXORB_FTDI_RANGE_017D_PID 0x017D +#define MTXORB_FTDI_RANGE_017E_PID 0x017E +#define MTXORB_FTDI_RANGE_017F_PID 0x017F +#define MTXORB_FTDI_RANGE_0180_PID 0x0180 +#define MTXORB_FTDI_RANGE_0181_PID 0x0181 +#define MTXORB_FTDI_RANGE_0182_PID 0x0182 +#define MTXORB_FTDI_RANGE_0183_PID 0x0183 +#define MTXORB_FTDI_RANGE_0184_PID 0x0184 +#define MTXORB_FTDI_RANGE_0185_PID 0x0185 +#define MTXORB_FTDI_RANGE_0186_PID 0x0186 +#define MTXORB_FTDI_RANGE_0187_PID 0x0187 +#define MTXORB_FTDI_RANGE_0188_PID 0x0188 +#define MTXORB_FTDI_RANGE_0189_PID 0x0189 +#define MTXORB_FTDI_RANGE_018A_PID 0x018A +#define MTXORB_FTDI_RANGE_018B_PID 0x018B +#define MTXORB_FTDI_RANGE_018C_PID 0x018C +#define MTXORB_FTDI_RANGE_018D_PID 0x018D +#define MTXORB_FTDI_RANGE_018E_PID 0x018E +#define MTXORB_FTDI_RANGE_018F_PID 0x018F +#define MTXORB_FTDI_RANGE_0190_PID 0x0190 +#define MTXORB_FTDI_RANGE_0191_PID 0x0191 +#define MTXORB_FTDI_RANGE_0192_PID 0x0192 +#define MTXORB_FTDI_RANGE_0193_PID 0x0193 +#define MTXORB_FTDI_RANGE_0194_PID 0x0194 +#define MTXORB_FTDI_RANGE_0195_PID 0x0195 +#define MTXORB_FTDI_RANGE_0196_PID 0x0196 +#define MTXORB_FTDI_RANGE_0197_PID 0x0197 +#define MTXORB_FTDI_RANGE_0198_PID 0x0198 +#define MTXORB_FTDI_RANGE_0199_PID 0x0199 +#define MTXORB_FTDI_RANGE_019A_PID 0x019A +#define MTXORB_FTDI_RANGE_019B_PID 0x019B +#define MTXORB_FTDI_RANGE_019C_PID 0x019C +#define MTXORB_FTDI_RANGE_019D_PID 0x019D +#define MTXORB_FTDI_RANGE_019E_PID 0x019E +#define MTXORB_FTDI_RANGE_019F_PID 0x019F +#define MTXORB_FTDI_RANGE_01A0_PID 0x01A0 +#define MTXORB_FTDI_RANGE_01A1_PID 0x01A1 +#define MTXORB_FTDI_RANGE_01A2_PID 0x01A2 +#define MTXORB_FTDI_RANGE_01A3_PID 0x01A3 +#define MTXORB_FTDI_RANGE_01A4_PID 0x01A4 +#define MTXORB_FTDI_RANGE_01A5_PID 0x01A5 +#define MTXORB_FTDI_RANGE_01A6_PID 0x01A6 +#define MTXORB_FTDI_RANGE_01A7_PID 0x01A7 +#define MTXORB_FTDI_RANGE_01A8_PID 0x01A8 +#define MTXORB_FTDI_RANGE_01A9_PID 0x01A9 +#define MTXORB_FTDI_RANGE_01AA_PID 0x01AA +#define MTXORB_FTDI_RANGE_01AB_PID 0x01AB +#define MTXORB_FTDI_RANGE_01AC_PID 0x01AC +#define MTXORB_FTDI_RANGE_01AD_PID 0x01AD +#define MTXORB_FTDI_RANGE_01AE_PID 0x01AE +#define MTXORB_FTDI_RANGE_01AF_PID 0x01AF +#define MTXORB_FTDI_RANGE_01B0_PID 0x01B0 +#define MTXORB_FTDI_RANGE_01B1_PID 0x01B1 +#define MTXORB_FTDI_RANGE_01B2_PID 0x01B2 +#define MTXORB_FTDI_RANGE_01B3_PID 0x01B3 +#define MTXORB_FTDI_RANGE_01B4_PID 0x01B4 +#define MTXORB_FTDI_RANGE_01B5_PID 0x01B5 +#define MTXORB_FTDI_RANGE_01B6_PID 0x01B6 +#define MTXORB_FTDI_RANGE_01B7_PID 0x01B7 +#define MTXORB_FTDI_RANGE_01B8_PID 0x01B8 +#define MTXORB_FTDI_RANGE_01B9_PID 0x01B9 +#define MTXORB_FTDI_RANGE_01BA_PID 0x01BA +#define MTXORB_FTDI_RANGE_01BB_PID 0x01BB +#define MTXORB_FTDI_RANGE_01BC_PID 0x01BC +#define MTXORB_FTDI_RANGE_01BD_PID 0x01BD +#define MTXORB_FTDI_RANGE_01BE_PID 0x01BE +#define MTXORB_FTDI_RANGE_01BF_PID 0x01BF +#define MTXORB_FTDI_RANGE_01C0_PID 0x01C0 +#define MTXORB_FTDI_RANGE_01C1_PID 0x01C1 +#define MTXORB_FTDI_RANGE_01C2_PID 0x01C2 +#define MTXORB_FTDI_RANGE_01C3_PID 0x01C3 +#define MTXORB_FTDI_RANGE_01C4_PID 0x01C4 +#define MTXORB_FTDI_RANGE_01C5_PID 0x01C5 +#define MTXORB_FTDI_RANGE_01C6_PID 0x01C6 +#define MTXORB_FTDI_RANGE_01C7_PID 0x01C7 +#define MTXORB_FTDI_RANGE_01C8_PID 0x01C8 +#define MTXORB_FTDI_RANGE_01C9_PID 0x01C9 +#define MTXORB_FTDI_RANGE_01CA_PID 0x01CA +#define MTXORB_FTDI_RANGE_01CB_PID 0x01CB +#define MTXORB_FTDI_RANGE_01CC_PID 0x01CC +#define MTXORB_FTDI_RANGE_01CD_PID 0x01CD +#define MTXORB_FTDI_RANGE_01CE_PID 0x01CE +#define MTXORB_FTDI_RANGE_01CF_PID 0x01CF +#define MTXORB_FTDI_RANGE_01D0_PID 0x01D0 +#define MTXORB_FTDI_RANGE_01D1_PID 0x01D1 +#define MTXORB_FTDI_RANGE_01D2_PID 0x01D2 +#define MTXORB_FTDI_RANGE_01D3_PID 0x01D3 +#define MTXORB_FTDI_RANGE_01D4_PID 0x01D4 +#define MTXORB_FTDI_RANGE_01D5_PID 0x01D5 +#define MTXORB_FTDI_RANGE_01D6_PID 0x01D6 +#define MTXORB_FTDI_RANGE_01D7_PID 0x01D7 +#define MTXORB_FTDI_RANGE_01D8_PID 0x01D8 +#define MTXORB_FTDI_RANGE_01D9_PID 0x01D9 +#define MTXORB_FTDI_RANGE_01DA_PID 0x01DA +#define MTXORB_FTDI_RANGE_01DB_PID 0x01DB +#define MTXORB_FTDI_RANGE_01DC_PID 0x01DC +#define MTXORB_FTDI_RANGE_01DD_PID 0x01DD +#define MTXORB_FTDI_RANGE_01DE_PID 0x01DE +#define MTXORB_FTDI_RANGE_01DF_PID 0x01DF +#define MTXORB_FTDI_RANGE_01E0_PID 0x01E0 +#define MTXORB_FTDI_RANGE_01E1_PID 0x01E1 +#define MTXORB_FTDI_RANGE_01E2_PID 0x01E2 +#define MTXORB_FTDI_RANGE_01E3_PID 0x01E3 +#define MTXORB_FTDI_RANGE_01E4_PID 0x01E4 +#define MTXORB_FTDI_RANGE_01E5_PID 0x01E5 +#define MTXORB_FTDI_RANGE_01E6_PID 0x01E6 +#define MTXORB_FTDI_RANGE_01E7_PID 0x01E7 +#define MTXORB_FTDI_RANGE_01E8_PID 0x01E8 +#define MTXORB_FTDI_RANGE_01E9_PID 0x01E9 +#define MTXORB_FTDI_RANGE_01EA_PID 0x01EA +#define MTXORB_FTDI_RANGE_01EB_PID 0x01EB +#define MTXORB_FTDI_RANGE_01EC_PID 0x01EC +#define MTXORB_FTDI_RANGE_01ED_PID 0x01ED +#define MTXORB_FTDI_RANGE_01EE_PID 0x01EE +#define MTXORB_FTDI_RANGE_01EF_PID 0x01EF +#define MTXORB_FTDI_RANGE_01F0_PID 0x01F0 +#define MTXORB_FTDI_RANGE_01F1_PID 0x01F1 +#define MTXORB_FTDI_RANGE_01F2_PID 0x01F2 +#define MTXORB_FTDI_RANGE_01F3_PID 0x01F3 +#define MTXORB_FTDI_RANGE_01F4_PID 0x01F4 +#define MTXORB_FTDI_RANGE_01F5_PID 0x01F5 +#define MTXORB_FTDI_RANGE_01F6_PID 0x01F6 +#define MTXORB_FTDI_RANGE_01F7_PID 0x01F7 +#define MTXORB_FTDI_RANGE_01F8_PID 0x01F8 +#define MTXORB_FTDI_RANGE_01F9_PID 0x01F9 +#define MTXORB_FTDI_RANGE_01FA_PID 0x01FA +#define MTXORB_FTDI_RANGE_01FB_PID 0x01FB +#define MTXORB_FTDI_RANGE_01FC_PID 0x01FC +#define MTXORB_FTDI_RANGE_01FD_PID 0x01FD +#define MTXORB_FTDI_RANGE_01FE_PID 0x01FE +#define MTXORB_FTDI_RANGE_01FF_PID 0x01FF + + /* Interbiometrics USB I/O Board */ /* Developed for Interbiometrics by Rudolf Gugler */ diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 6cecd2c12b1d..43cfde83a93b 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -236,25 +236,25 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK_EX) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_MODEM) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_NETWORK) }, - { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) }, - { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1401) }, - { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1403) }, - { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1405) }, - { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1406) }, - { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1408) }, - { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1409) }, - { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1410) }, - { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1411) }, - { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1412) }, - { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1413) }, - { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1414) }, - { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1415) }, - { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1416) }, - { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1417) }, - { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1418) }, - { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1419) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1401, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1403, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1405, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1406, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1408, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1409, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1410, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1411, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1412, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1413, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1414, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1415, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1416, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1417, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1418, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1419, 0xff, 0xff, 0xff) }, { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_9508) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, /* Novatel Merlin V620/S620 */ diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 234c5eea95a2..103195abd417 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -56,6 +56,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ALDIGA) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MMX) }, { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) }, { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) }, { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) }, diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index 3bdefe020501..cff160abb130 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -14,6 +14,7 @@ #define PL2303_PRODUCT_ID_PHAROS 0xaaa0 #define PL2303_PRODUCT_ID_RSAQ3 0xaaa2 #define PL2303_PRODUCT_ID_ALDIGA 0x0611 +#define PL2303_PRODUCT_ID_MMX 0x0612 #define ATEN_VENDOR_ID 0x0557 #define ATEN_VENDOR_ID2 0x0547 diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 1b09578cbb10..45fe3663fa7f 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -405,7 +405,7 @@ UNUSUAL_DEV( 0x04a5, 0x3010, 0x0100, 0x0100, UNUSUAL_DEV( 0x04b4, 0x6830, 0x0000, 0x9999, "Cypress", "Cypress AT2LP", - US_SC_CYP_ATACB, US_PR_BULK, NULL, + US_SC_CYP_ATACB, US_PR_DEVICE, NULL, 0), #endif @@ -1522,7 +1522,7 @@ UNUSUAL_DEV( 0x0fce, 0xe031, 0x0000, 0x0000, "Sony Ericsson", "M600i", US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_FIX_CAPACITY ), + US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ), /* Reported by Kevin Cernekee <kpc-usbdev@gelato.uiuc.edu> * Tested on hardware version 1.10. @@ -1716,10 +1716,12 @@ UNUSUAL_DEV( 0x22b8, 0x3010, 0x0001, 0x0001, /* * Patch by Pete Zaitcev <zaitcev@redhat.com> * Report by Mark Patton. Red Hat bz#208928. + * Added support for rev 0x0002 (Motorola ROKR W5) + * by Javier Smaldone <javier@smaldone.com.ar> */ -UNUSUAL_DEV( 0x22b8, 0x4810, 0x0001, 0x0001, +UNUSUAL_DEV( 0x22b8, 0x4810, 0x0001, 0x0002, "Motorola", - "RAZR V3i", + "RAZR V3i/ROKR W5", US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 35ac9d956b3d..c14b2435d23e 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -2432,9 +2432,9 @@ static int cirrusfb_pci_register(struct pci_dev *pdev, info->screen_size = board_size; cinfo->unmap = cirrusfb_pci_unmap; - printk(KERN_INFO " RAM (%lu kB) at 0xx%lx, ", - info->screen_size >> 10, board_addr); - printk(KERN_INFO "Cirrus Logic chipset on PCI bus\n"); + printk(KERN_INFO "RAM (%lu kB) at 0x%lx, Cirrus " + "Logic chipset on PCI bus\n", + info->screen_size >> 10, board_addr); pci_set_drvdata(pdev, info); ret = cirrusfb_register(info); diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 5fa8b76673cb..97aff8db10bf 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -2275,9 +2275,7 @@ static int fbcon_switch(struct vc_data *vc) * in fb_set_var() */ info->var.activate = var.activate; - var.yoffset = info->var.yoffset; - var.xoffset = info->var.xoffset; - var.vmode = info->var.vmode; + var.vmode |= info->var.vmode & ~FB_VMODE_MASK; fb_set_var(info, &var); ops->var = info->var; diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index b50bb03cb5ab..0a2785361ca3 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c @@ -1320,7 +1320,7 @@ static void free_irq_local(int irq) * Power management hooks. Note that we won't be called from IRQ context, * unlike the blank functions above, so we may sleep. */ -static int fsl_diu_suspend(struct of_device *dev, pm_message_t state) +static int fsl_diu_suspend(struct of_device *ofdev, pm_message_t state) { struct fsl_diu_data *machine_data; @@ -1330,7 +1330,7 @@ static int fsl_diu_suspend(struct of_device *dev, pm_message_t state) return 0; } -static int fsl_diu_resume(struct of_device *dev) +static int fsl_diu_resume(struct of_device *ofdev) { struct fsl_diu_data *machine_data; diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c index fb9e67228543..c18880d9db1f 100644 --- a/drivers/video/hgafb.c +++ b/drivers/video/hgafb.c @@ -279,7 +279,7 @@ static void hga_blank(int blank_mode) static int __init hga_card_detect(void) { - int count=0; + int count = 0; void __iomem *p, *q; unsigned short p_save, q_save; @@ -303,20 +303,18 @@ static int __init hga_card_detect(void) writew(0x55aa, p); if (readw(p) == 0x55aa) count++; writew(p_save, p); - if (count != 2) { - return 0; - } + if (count != 2) + goto error; /* Ok, there is definitely a card registering at the correct * memory location, so now we do an I/O port test. */ - if (!test_hga_b(0x66, 0x0f)) { /* cursor low register */ - return 0; - } - if (!test_hga_b(0x99, 0x0f)) { /* cursor low register */ - return 0; - } + if (!test_hga_b(0x66, 0x0f)) /* cursor low register */ + goto error; + + if (!test_hga_b(0x99, 0x0f)) /* cursor low register */ + goto error; /* See if the card is a Hercules, by checking whether the vsync * bit of the status register is changing. This test lasts for @@ -331,7 +329,7 @@ static int __init hga_card_detect(void) } if (p_save == q_save) - return 0; + goto error; switch (inb_p(HGA_STATUS_PORT) & 0x70) { case 0x10: @@ -348,6 +346,12 @@ static int __init hga_card_detect(void) break; } return 1; +error: + if (release_io_ports) + release_region(0x3b0, 12); + if (release_io_port) + release_region(0x3bf, 1); + return 0; } /** diff --git a/drivers/video/leo.c b/drivers/video/leo.c index 8bc46e930340..13fea61d6ae4 100644 --- a/drivers/video/leo.c +++ b/drivers/video/leo.c @@ -17,8 +17,8 @@ #include <linux/fb.h> #include <linux/mm.h> #include <linux/of_device.h> +#include <linux/io.h> -#include <asm/io.h> #include <asm/fbio.h> #include "sbuslib.h" @@ -33,7 +33,6 @@ static int leo_blank(int, struct fb_info *); static int leo_mmap(struct fb_info *, struct vm_area_struct *); static int leo_ioctl(struct fb_info *, unsigned int, unsigned long); -static int leo_pan_display(struct fb_var_screeninfo *, struct fb_info *); /* * Frame buffer operations @@ -43,7 +42,6 @@ static struct fb_ops leo_ops = { .owner = THIS_MODULE, .fb_setcolreg = leo_setcolreg, .fb_blank = leo_blank, - .fb_pan_display = leo_pan_display, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, @@ -78,7 +76,7 @@ static struct fb_ops leo_ops = { #define LEO_CUR_TYPE_CMAP 0x00000050 struct leo_cursor { - u8 xxx0[16]; + u8 xxx0[16]; u32 cur_type; u32 cur_misc; u32 cur_cursxy; @@ -105,7 +103,7 @@ struct leo_lx_krn { struct leo_lc_ss0_krn { u32 misc; - u8 xxx0[0x800-4]; + u8 xxx0[0x800-4]; u32 rev; }; @@ -116,7 +114,7 @@ struct leo_lc_ss0_usr { u32 fontt; u32 extent; u32 src; - u32 dst; + u32 dst; u32 copy; u32 fill; }; @@ -129,8 +127,8 @@ struct leo_lc_ss1_usr { u8 unknown; }; -struct leo_ld { - u8 xxx0[0xe00]; +struct leo_ld_ss0 { + u8 xxx0[0xe00]; u32 csr; u32 wid; u32 wmask; @@ -144,13 +142,13 @@ struct leo_ld { u32 src; /* Copy/Scroll (SS0 only) */ u32 dst; /* Copy/Scroll/Fill (SS0 only) */ u32 extent; /* Copy/Scroll/Fill size (SS0 only) */ - u32 xxx1[3]; + u32 xxx1[3]; u32 setsem; /* SS1 only */ u32 clrsem; /* SS1 only */ u32 clrpick; /* SS1 only */ u32 clrdat; /* SS1 only */ u32 alpha; /* SS1 only */ - u8 xxx2[0x2c]; + u8 xxx2[0x2c]; u32 winbg; u32 planemask; u32 rop; @@ -199,11 +197,12 @@ struct leo_par { static void leo_wait(struct leo_lx_krn __iomem *lx_krn) { int i; - + for (i = 0; - (sbus_readl(&lx_krn->krn_csr) & LEO_KRN_CSR_PROGRESS) && i < 300000; + (sbus_readl(&lx_krn->krn_csr) & LEO_KRN_CSR_PROGRESS) && + i < 300000; i++) - udelay (1); /* Busy wait at most 0.3 sec */ + udelay(1); /* Busy wait at most 0.3 sec */ return; } @@ -221,7 +220,7 @@ static int leo_setcolreg(unsigned regno, unsigned transp, struct fb_info *info) { struct leo_par *par = (struct leo_par *) info->par; - struct leo_lx_krn __iomem *lx_krn = par->lx_krn; + struct leo_lx_krn __iomem *lx_krn = par->lx_krn; unsigned long flags; u32 val; int i; @@ -408,7 +407,7 @@ static void leo_wid_put(struct fb_info *info, struct fb_wid_list *wl) leo_wait(lx_krn); for (i = 0, wi = wl->wl_list; i < wl->wl_count; i++, wi++) { - switch(wi->wi_type) { + switch (wi->wi_type) { case FB_WID_DBL_8: j = (wi->wi_index & 0xf) + 0x40; break; @@ -453,13 +452,12 @@ static void leo_init_wids(struct fb_info *info) wi.wi_index = 1; wi.wi_values [0] = 0x30; leo_wid_put(info, &wl); - } static void leo_switch_from_graph(struct fb_info *info) { struct leo_par *par = (struct leo_par *) info->par; - struct leo_ld __iomem *ss = (struct leo_ld __iomem *) par->ld_ss0; + struct leo_ld_ss0 __iomem *ss = par->ld_ss0; unsigned long flags; u32 val; @@ -485,19 +483,13 @@ static void leo_switch_from_graph(struct fb_info *info) val = sbus_readl(&par->lc_ss0_usr->csr); } while (val & 0x20000000); - spin_unlock_irqrestore(&par->lock, flags); -} - -static int leo_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) -{ - /* We just use this to catch switches out of - * graphics mode. - */ - leo_switch_from_graph(info); + /* setup screen buffer for cfb_* functions */ + sbus_writel(1, &ss->wid); + sbus_writel(0x00ffffff, &ss->planemask); + sbus_writel(0x310b90, &ss->rop); + sbus_writel(0, &par->lc_ss0_usr->addrspace); - if (var->xoffset || var->yoffset || var->vmode) - return -EINVAL; - return 0; + spin_unlock_irqrestore(&par->lock, flags); } static void leo_init_hw(struct fb_info *info) @@ -542,7 +534,8 @@ static void leo_unmap_regs(struct of_device *op, struct fb_info *info, of_iounmap(&op->resource[0], info->screen_base, 0x800000); } -static int __devinit leo_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit leo_probe(struct of_device *op, + const struct of_device_id *match) { struct device_node *dp = op->node; struct fb_info *info; @@ -594,8 +587,9 @@ static int __devinit leo_probe(struct of_device *op, const struct of_device_id * !info->screen_base) goto out_unmap_regs; - info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; + info->flags = FBINFO_DEFAULT; info->fbops = &leo_ops; + info->pseudo_palette = par->clut_data; leo_init_wids(info); leo_init_hw(info); @@ -649,7 +643,7 @@ static int __devexit leo_remove(struct of_device *op) static struct of_device_id leo_match[] = { { - .name = "leo", + .name = "SUNW,leo", }, {}, }; diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c index 473562191586..d3c3af53a290 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c @@ -28,6 +28,7 @@ #endif const char *fb_mode_option; +EXPORT_SYMBOL_GPL(fb_mode_option); /* * Standard video mode definitions (taken from XFree86) @@ -590,6 +591,7 @@ done: "", (margins) ? " with margins" : "", (interlace) ? " interlaced" : ""); + memset(&cvt_mode, 0, sizeof(cvt_mode)); cvt_mode.xres = xres; cvt_mode.yres = yres; cvt_mode.refresh = (refresh) ? refresh : 60; diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 274bc93ab7d8..7dcda187d9ba 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -573,8 +573,8 @@ static int setup_frame_dma(struct pxafb_info *fbi, int dma, int pal, dma_desc->fdadr = fbi->dma_buff_phys + dma_desc_off; fbi->fdadr[dma] = fbi->dma_buff_phys + dma_desc_off; } else { - pal_desc = &fbi->dma_buff->pal_desc[dma]; - pal_desc_off = offsetof(struct pxafb_dma_buff, dma_desc[pal]); + pal_desc = &fbi->dma_buff->pal_desc[pal]; + pal_desc_off = offsetof(struct pxafb_dma_buff, pal_desc[pal]); pal_desc->fsadr = fbi->dma_buff_phys + pal * PALETTE_SIZE; pal_desc->fidr = 0; @@ -1276,6 +1276,8 @@ static int __init pxafb_map_video_memory(struct pxafb_info *fbi) fbi->dma_buff_phys = fbi->map_dma; fbi->palette_cpu = (u16 *) fbi->dma_buff->palette; + pr_debug("pxafb: palette_mem_size = 0x%08lx\n", fbi->palette_size*sizeof(u16)); + #ifdef CONFIG_FB_PXA_SMARTPANEL fbi->smart_cmds = (uint16_t *) fbi->dma_buff->cmd_buff; fbi->n_smart_cmds = 0; diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 13866789b356..7084e7e146c0 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c @@ -2,6 +2,9 @@ #include <linux/spinlock.h> #include <linux/virtio_config.h> +/* Unique numbering for virtio devices. */ +static unsigned int dev_index; + static ssize_t device_show(struct device *_d, struct device_attribute *attr, char *buf) { @@ -121,9 +124,9 @@ static int virtio_dev_probe(struct device *_d) if (err) add_status(dev, VIRTIO_CONFIG_S_FAILED); else { - add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); /* They should never have set feature bits beyond 32 */ dev->config->set_features(dev, dev->features[0]); + add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); } return err; } @@ -166,7 +169,10 @@ int register_virtio_device(struct virtio_device *dev) int err; dev->dev.bus = &virtio_bus; - sprintf(dev->dev.bus_id, "%u", dev->index); + + /* Assign a unique device index and hence name. */ + dev->index = dev_index++; + sprintf(dev->dev.bus_id, "virtio%u", dev->index); /* We always start by resetting the device, in case a previous * driver messed it up. This also tests that code path a little. */ diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index 27e9fc9117cd..eae7236310e4 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c @@ -78,9 +78,6 @@ static struct device virtio_pci_root = { .bus_id = "virtio-pci", }; -/* Unique numbering for devices under the kvm root */ -static unsigned int dev_index; - /* Convert a generic virtio device to our structure */ static struct virtio_pci_device *to_vp_device(struct virtio_device *vdev) { @@ -325,10 +322,6 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev, if (vp_dev == NULL) return -ENOMEM; - snprintf(vp_dev->vdev.dev.bus_id, BUS_ID_SIZE, "virtio%d", dev_index); - vp_dev->vdev.index = dev_index; - dev_index++; - vp_dev->vdev.dev.parent = &virtio_pci_root; vp_dev->vdev.config = &virtio_pci_config_ops; vp_dev->pci_dev = pci_dev; diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 937a49d6772c..72bf8bc09014 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -227,7 +227,6 @@ static bool vring_enable_cb(struct virtqueue *_vq) struct vring_virtqueue *vq = to_vvq(_vq); START_USE(vq); - BUG_ON(!(vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT)); /* We optimistically turn back on interrupts, then check if there was * more to do. */ @@ -254,13 +253,6 @@ irqreturn_t vring_interrupt(int irq, void *_vq) if (unlikely(vq->broken)) return IRQ_HANDLED; - /* Other side may have missed us turning off the interrupt, - * but we should preserve disable semantic for virtio users. */ - if (unlikely(vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT)) { - pr_debug("virtqueue interrupt after disable for %p\n", vq); - return IRQ_HANDLED; - } - pr_debug("virtqueue callback for %p (%p)\n", vq, vq->vq.callback); if (vq->vq.callback) vq->vq.callback(&vq->vq); diff --git a/drivers/watchdog/geodewdt.c b/drivers/watchdog/geodewdt.c index f85b19625f97..30d09cbbad94 100644 --- a/drivers/watchdog/geodewdt.c +++ b/drivers/watchdog/geodewdt.c @@ -221,8 +221,7 @@ geodewdt_probe(struct platform_device *dev) { int ret, timer; - timer = geode_mfgpt_alloc_timer(MFGPT_TIMER_ANY, - MFGPT_DOMAIN_WORKING, THIS_MODULE); + timer = geode_mfgpt_alloc_timer(MFGPT_TIMER_ANY, MFGPT_DOMAIN_WORKING); if (timer == -1) { printk(KERN_ERR "geodewdt: No timers were available\n"); |