diff options
Diffstat (limited to 'drivers')
323 files changed, 11032 insertions, 8068 deletions
diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c index d2fc9416184..26038c2a2a7 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 c78078315be..f988a5e7d2b 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 fa44fb96fc3..96c542f7fde 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 0924992187e..5622aee996b 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 24da921d13e..39d74219058 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 06f8634fe58..2808dc60fd6 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 d9937e05ec6..dba3cfbe8cb 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 5d59cb33b1a..658e5f3abae 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 f1e8bf65e24..e9446377884 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 386e5aa4883..9dd0fa93b9e 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 2dd2c1f3a01..556ee158519 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 8a5fe871051..224c57c0338 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 769f24855eb..5bd2dec9a7a 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 402f93e1ff2..5336ce88f89 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 fb57b93c249..0e319604d3e 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 504385b1f21..84c795fb9b1 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 e4ba7192cd1..1f057b71db1 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 544b7d6c617..966ab401e52 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 */ @@ -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 3548ee7014c..81b7ae37695 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -574,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 dbf6ca781f6..3ff8b14420d 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-sff.c b/drivers/ata/libata-sff.c index 3c2d2289f85..215d18672a5 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 17138436423..cf9e9848f8b 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 a108d259f19..f8b3ffc8ae9 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 e965b251ca2..bbf5aa345e6 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_mv.c b/drivers/ata/sata_mv.c index acf347f71a2..60391e9a84d 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -224,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, @@ -2563,17 +2568,16 @@ static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, m3 &= ~0x1c; if (fix_phy_mode4) { - u32 m4; - - m4 = readl(port_mmio + PHY_MODE4); - - /* workaround for errata FEr SATA#10 (part 1) */ - m4 = (m4 & ~(1 << 1)) | (1 << 0); - - /* enforce bit restrictions on GenIIe devices */ + 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 & ~0x5DE3FFFC) | (1 << 2); - + 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); } /* diff --git a/drivers/atm/Kconfig b/drivers/atm/Kconfig index b554edac1ce..f197a193633 100644 --- a/drivers/atm/Kconfig +++ b/drivers/atm/Kconfig @@ -294,7 +294,7 @@ config ATM_HORIZON_DEBUG config ATM_IA tristate "Interphase ATM PCI x575/x525/x531" - depends on PCI && !64BIT + depends on PCI ---help--- This is a driver for the Interphase (i)ChipSAR adapter cards which include a variety of variants in term of the size of the @@ -325,81 +325,22 @@ config ATM_IA_DEBUG speed of the driver, and the size of your syslog files! When inactive, they will have only a modest impact on performance. -config ATM_FORE200E_MAYBE +config ATM_FORE200E tristate "FORE Systems 200E-series" - depends on PCI || SBUS + depends on (PCI || SBUS) + select FW_LOADER ---help--- This is a driver for the FORE Systems 200E-series ATM adapter cards. It simultaneously supports PCA-200E and SBA-200E models on PCI and SBUS hosts. Say Y (or M to compile as a module named fore_200e) here if you have one of these ATM adapters. - Note that the driver will actually be compiled only if you - additionally enable the support for PCA-200E and/or SBA-200E - cards. - See the file <file:Documentation/networking/fore200e.txt> for further details. -config ATM_FORE200E_PCA - bool "PCA-200E support" - depends on ATM_FORE200E_MAYBE && PCI - help - Say Y here if you want your PCA-200E cards to be probed. - -config ATM_FORE200E_PCA_DEFAULT_FW - bool "Use default PCA-200E firmware (normally enabled)" - depends on ATM_FORE200E_PCA - help - Use the default PCA-200E firmware data shipped with the driver. - - Normal users do not have to deal with the firmware stuff, so - they should say Y here. - -config ATM_FORE200E_PCA_FW - string "Pathname of user-supplied binary firmware" - depends on ATM_FORE200E_PCA && !ATM_FORE200E_PCA_DEFAULT_FW - default "" - help - This defines the pathname of an alternative PCA-200E binary - firmware image supplied by the user. This pathname may be - absolute or relative to the drivers/atm directory. - - The driver comes with an adequate firmware image, so normal users do - not have to supply an alternative one. They just say Y to "Use - default PCA-200E firmware" instead. - -config ATM_FORE200E_SBA - bool "SBA-200E support" - depends on ATM_FORE200E_MAYBE && SBUS - help - Say Y here if you want your SBA-200E cards to be probed. - -config ATM_FORE200E_SBA_DEFAULT_FW - bool "Use default SBA-200E firmware (normally enabled)" - depends on ATM_FORE200E_SBA - help - Use the default SBA-200E firmware data shipped with the driver. - - Normal users do not have to deal with the firmware stuff, so - they should say Y here. - -config ATM_FORE200E_SBA_FW - string "Pathname of user-supplied binary firmware" - depends on ATM_FORE200E_SBA && !ATM_FORE200E_SBA_DEFAULT_FW - default "" - help - This defines the pathname of an alternative SBA-200E binary - firmware image supplied by the user. This pathname may be - absolute or relative to the drivers/atm directory. - - The driver comes with an adequate firmware image, so normal users do - not have to supply an alternative one. They just say Y to "Use - default SBA-200E firmware", above. - config ATM_FORE200E_USE_TASKLET bool "Defer interrupt work to a tasklet" - depends on (PCI || SBUS) && (ATM_FORE200E_PCA || ATM_FORE200E_SBA) + depends on ATM_FORE200E default n help This defers work to be done by the interrupt handler to a @@ -408,7 +349,7 @@ config ATM_FORE200E_USE_TASKLET config ATM_FORE200E_TX_RETRY int "Maximum number of tx retries" - depends on (PCI || SBUS) && (ATM_FORE200E_PCA || ATM_FORE200E_SBA) + depends on ATM_FORE200E default "16" ---help--- Specifies the number of times the driver attempts to transmit @@ -425,7 +366,7 @@ config ATM_FORE200E_TX_RETRY config ATM_FORE200E_DEBUG int "Debugging level (0-3)" - depends on (PCI || SBUS) && (ATM_FORE200E_PCA || ATM_FORE200E_SBA) + depends on ATM_FORE200E default "0" help Specifies the level of debugging messages issued by the driver. @@ -436,12 +377,6 @@ config ATM_FORE200E_DEBUG the performances of the driver, and the size of your syslog files! Keep the debugging level to 0 during normal operations. -config ATM_FORE200E - tristate - depends on (PCI || SBUS) && (ATM_FORE200E_PCA || ATM_FORE200E_SBA) - default m if ATM_FORE200E_MAYBE!=y - default y if ATM_FORE200E_MAYBE=y - config ATM_HE tristate "ForeRunner HE Series" depends on PCI diff --git a/drivers/atm/Makefile b/drivers/atm/Makefile index e4fa9965869..0bfb31748ec 100644 --- a/drivers/atm/Makefile +++ b/drivers/atm/Makefile @@ -3,14 +3,6 @@ # fore_200e-objs := fore200e.o -hostprogs-y := fore200e_mkfirm - -# Files generated that shall be removed upon make clean -clean-files := atmsar11.bin atmsar11.bin1 atmsar11.bin2 pca200e.bin \ - pca200e.bin1 pca200e.bin2 pca200e_ecd.bin pca200e_ecd.bin1 \ - pca200e_ecd.bin2 sba200e_ecd.bin sba200e_ecd.bin1 sba200e_ecd.bin2 -# Firmware generated that shall be removed upon make clean -clean-files += fore200e_pca_fw.c fore200e_sba_fw.c obj-$(CONFIG_ATM_ZATM) += zatm.o uPD98402.o obj-$(CONFIG_ATM_NICSTAR) += nicstar.o @@ -36,38 +28,7 @@ obj-$(CONFIG_ATM_TCP) += atmtcp.o obj-$(CONFIG_ATM_FIRESTREAM) += firestream.o obj-$(CONFIG_ATM_LANAI) += lanai.o -ifeq ($(CONFIG_ATM_FORE200E_PCA),y) - fore_200e-objs += fore200e_pca_fw.o - # guess the target endianess to choose the right PCA-200E firmware image - ifeq ($(CONFIG_ATM_FORE200E_PCA_DEFAULT_FW),y) - byteorder.h := include$(if $(patsubst $(srctree),,$(objtree)),2)/asm/byteorder.h - CONFIG_ATM_FORE200E_PCA_FW := $(obj)/pca200e$(if $(shell $(CC) $(KBUILD_CPPFLAGS) -E -dM $(byteorder.h) | grep ' __LITTLE_ENDIAN '),.bin,_ecd.bin2) - endif -endif - -ifeq ($(CONFIG_ATM_FORE200E_SBA),y) - fore_200e-objs += fore200e_sba_fw.o - ifeq ($(CONFIG_ATM_FORE200E_SBA_DEFAULT_FW),y) - CONFIG_ATM_FORE200E_SBA_FW := $(obj)/sba200e_ecd.bin2 - endif -endif obj-$(CONFIG_ATM_HE) += he.o ifeq ($(CONFIG_ATM_HE_USE_SUNI),y) obj-$(CONFIG_ATM_HE) += suni.o endif - -# FORE Systems 200E-series firmware magic -$(obj)/fore200e_pca_fw.c: $(patsubst "%", %, $(CONFIG_ATM_FORE200E_PCA_FW)) \ - $(obj)/fore200e_mkfirm - $(obj)/fore200e_mkfirm -k -b _fore200e_pca_fw \ - -i $(CONFIG_ATM_FORE200E_PCA_FW) -o $@ - -$(obj)/fore200e_sba_fw.c: $(patsubst "%", %, $(CONFIG_ATM_FORE200E_SBA_FW)) \ - $(obj)/fore200e_mkfirm - $(obj)/fore200e_mkfirm -k -b _fore200e_sba_fw \ - -i $(CONFIG_ATM_FORE200E_SBA_FW) -o $@ - -# deal with the various suffixes of the binary firmware images -$(obj)/%.bin $(obj)/%.bin1 $(obj)/%.bin2: $(src)/%.data - objcopy -Iihex $< -Obinary $@.gz - gzip -n -df $@.gz diff --git a/drivers/atm/eni.h b/drivers/atm/eni.h index d04fefb0841..e4c9525e60b 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/atm/fore200e.c b/drivers/atm/fore200e.c index 432181ed7bb..d5c1bbfbe79 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -36,6 +36,7 @@ #include <linux/atm_suni.h> #include <linux/dma-mapping.h> #include <linux/delay.h> +#include <linux/firmware.h> #include <asm/io.h> #include <asm/string.h> #include <asm/page.h> @@ -45,7 +46,7 @@ #include <asm/uaccess.h> #include <asm/atomic.h> -#ifdef CONFIG_ATM_FORE200E_SBA +#ifdef CONFIG_SBUS #include <asm/idprom.h> #include <asm/sbus.h> #include <asm/openprom.h> @@ -382,9 +383,6 @@ fore200e_shutdown(struct fore200e* fore200e) case FORE200E_STATE_START_FW: /* nothing to do for that state */ - case FORE200E_STATE_LOAD_FW: - /* nothing to do for that state */ - case FORE200E_STATE_RESET: /* nothing to do for that state */ @@ -405,7 +403,7 @@ fore200e_shutdown(struct fore200e* fore200e) } -#ifdef CONFIG_ATM_FORE200E_PCA +#ifdef CONFIG_PCI static u32 fore200e_pca_read(volatile u32 __iomem *addr) { @@ -658,10 +656,10 @@ fore200e_pca_proc_read(struct fore200e* fore200e, char *page) pci_dev->bus->number, PCI_SLOT(pci_dev->devfn), PCI_FUNC(pci_dev->devfn)); } -#endif /* CONFIG_ATM_FORE200E_PCA */ +#endif /* CONFIG_PCI */ -#ifdef CONFIG_ATM_FORE200E_SBA +#ifdef CONFIG_SBUS static u32 fore200e_sba_read(volatile u32 __iomem *addr) @@ -907,7 +905,7 @@ fore200e_sba_proc_read(struct fore200e* fore200e, char *page) return sprintf(page, " SBUS slot/device:\t\t%d/'%s'\n", sbus_dev->slot, sbus_dev->prom_name); } -#endif /* CONFIG_ATM_FORE200E_SBA */ +#endif /* CONFIG_SBUS */ static void @@ -2552,13 +2550,53 @@ fore200e_monitor_puts(struct fore200e* fore200e, char* str) while (fore200e_monitor_getc(fore200e) >= 0); } +#ifdef __LITTLE_ENDIAN +#define FW_EXT ".bin" +#else +#define FW_EXT "_ecd.bin2" +#endif static int __devinit -fore200e_start_fw(struct fore200e* fore200e) -{ - int ok; - char cmd[ 48 ]; - struct fw_header* fw_header = (struct fw_header*) fore200e->bus->fw_data; +fore200e_load_and_start_fw(struct fore200e* fore200e) +{ + const struct firmware *firmware; + struct device *device; + struct fw_header *fw_header; + u32 *fw_data, fw_size; + u32 __iomem *load_addr; + char buf[48]; + int err = -ENODEV; + + if (strcmp(fore200e->bus->model_name, "PCA-200E") == 0) + device = &((struct pci_dev *) fore200e->bus_dev)->dev; +#ifdef CONFIG_SBUS + else if (strcmp(fore200e->bus->model_name, "SBA-200E") == 0) + device = &((struct sbus_dev *) fore200e->bus_dev)->ofdev.dev; +#endif + else + return err; + + sprintf(buf, "%s%s", fore200e->bus->proc_name, FW_EXT); + if (request_firmware(&firmware, buf, device) == 1) { + printk(FORE200E "missing %s firmware image\n", fore200e->bus->model_name); + return err; + } + + fw_data = (u32 *) firmware->data; + fw_size = firmware->size / sizeof(u32); + fw_header = (struct fw_header *) firmware->data; + load_addr = fore200e->virt_base + le32_to_cpu(fw_header->load_offset); + + DPRINTK(2, "device %s firmware being loaded at 0x%p (%d words)\n", + fore200e->name, load_addr, fw_size); + + if (le32_to_cpu(fw_header->magic) != FW_HEADER_MAGIC) { + printk(FORE200E "corrupted %s firmware image\n", fore200e->bus->model_name); + goto release; + } + + for (; fw_size--; fw_data++, load_addr++) + fore200e->bus->write(le32_to_cpu(*fw_data), load_addr); DPRINTK(2, "device %s firmware being started\n", fore200e->name); @@ -2567,46 +2605,22 @@ fore200e_start_fw(struct fore200e* fore200e) fore200e_spin(100); #endif - sprintf(cmd, "\rgo %x\r", le32_to_cpu(fw_header->start_offset)); + sprintf(buf, "\rgo %x\r", le32_to_cpu(fw_header->start_offset)); + fore200e_monitor_puts(fore200e, buf); - fore200e_monitor_puts(fore200e, cmd); - - ok = fore200e_io_poll(fore200e, &fore200e->cp_monitor->bstat, BSTAT_CP_RUNNING, 1000); - if (ok == 0) { + if (fore200e_io_poll(fore200e, &fore200e->cp_monitor->bstat, BSTAT_CP_RUNNING, 1000) == 0) { printk(FORE200E "device %s firmware didn't start\n", fore200e->name); - return -ENODEV; + goto release; } printk(FORE200E "device %s firmware started\n", fore200e->name); fore200e->state = FORE200E_STATE_START_FW; - return 0; -} + err = 0; - -static int __devinit -fore200e_load_fw(struct fore200e* fore200e) -{ - __le32* fw_data = (__le32*) fore200e->bus->fw_data; - u32 fw_size = (u32) *fore200e->bus->fw_size / sizeof(u32); - - struct fw_header* fw_header = (struct fw_header*) fw_data; - - u32 __iomem *load_addr = fore200e->virt_base + le32_to_cpu(fw_header->load_offset); - - DPRINTK(2, "device %s firmware being loaded at 0x%p (%d words)\n", - fore200e->name, load_addr, fw_size); - - if (le32_to_cpu(fw_header->magic) != FW_HEADER_MAGIC) { - printk(FORE200E "corrupted %s firmware image\n", fore200e->bus->model_name); - return -ENODEV; - } - - for (; fw_size--; fw_data++, load_addr++) - fore200e->bus->write(le32_to_cpu(*fw_data), load_addr); - - fore200e->state = FORE200E_STATE_LOAD_FW; - return 0; +release: + release_firmware(firmware); + return err; } @@ -2652,10 +2666,7 @@ fore200e_init(struct fore200e* fore200e) if (fore200e_reset(fore200e, 1) < 0) return -ENODEV; - if (fore200e_load_fw(fore200e) < 0) - return -ENODEV; - - if (fore200e_start_fw(fore200e) < 0) + if (fore200e_load_and_start_fw(fore200e) < 0) return -ENODEV; if (fore200e_initialize(fore200e) < 0) @@ -2689,7 +2700,7 @@ fore200e_init(struct fore200e* fore200e) return 0; } -#ifdef CONFIG_ATM_FORE200E_PCA +#ifdef CONFIG_PCI static int __devinit fore200e_pca_detect(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent) { @@ -2804,7 +2815,7 @@ fore200e_module_init(void) } } -#ifdef CONFIG_ATM_FORE200E_PCA +#ifdef CONFIG_PCI if (!pci_register_driver(&fore200e_pca_driver)) return 0; #endif @@ -2821,7 +2832,7 @@ fore200e_module_cleanup(void) { struct fore200e *fore200e, *next; -#ifdef CONFIG_ATM_FORE200E_PCA +#ifdef CONFIG_PCI pci_unregister_driver(&fore200e_pca_driver); #endif @@ -3140,19 +3151,9 @@ static const struct atmdev_ops fore200e_ops = }; -#ifdef CONFIG_ATM_FORE200E_PCA -extern const unsigned char _fore200e_pca_fw_data[]; -extern const unsigned int _fore200e_pca_fw_size; -#endif -#ifdef CONFIG_ATM_FORE200E_SBA -extern const unsigned char _fore200e_sba_fw_data[]; -extern const unsigned int _fore200e_sba_fw_size; -#endif - static const struct fore200e_bus fore200e_bus[] = { -#ifdef CONFIG_ATM_FORE200E_PCA +#ifdef CONFIG_PCI { "PCA-200E", "pca200e", 32, 4, 32, - _fore200e_pca_fw_data, &_fore200e_pca_fw_size, fore200e_pca_read, fore200e_pca_write, fore200e_pca_dma_map, @@ -3173,9 +3174,8 @@ static const struct fore200e_bus fore200e_bus[] = { fore200e_pca_proc_read, }, #endif -#ifdef CONFIG_ATM_FORE200E_SBA +#ifdef CONFIG_SBUS { "SBA-200E", "sba200e", 32, 64, 32, - _fore200e_sba_fw_data, &_fore200e_sba_fw_size, fore200e_sba_read, fore200e_sba_write, fore200e_sba_dma_map, diff --git a/drivers/atm/fore200e.h b/drivers/atm/fore200e.h index 8dd4aa76c3b..5c6e7adcb19 100644 --- a/drivers/atm/fore200e.h +++ b/drivers/atm/fore200e.h @@ -754,7 +754,6 @@ typedef enum fore200e_state { FORE200E_STATE_CONFIGURE, /* bus interface configured */ FORE200E_STATE_MAP, /* board space mapped in host memory */ FORE200E_STATE_RESET, /* board resetted */ - FORE200E_STATE_LOAD_FW, /* firmware loaded */ FORE200E_STATE_START_FW, /* firmware started */ FORE200E_STATE_INITIALIZE, /* initialize command successful */ FORE200E_STATE_INIT_CMDQ, /* command queue initialized */ @@ -803,8 +802,6 @@ typedef struct fore200e_bus { int descr_alignment; /* tpd/rpd/rbd DMA alignment requirement */ int buffer_alignment; /* rx buffers DMA alignment requirement */ int status_alignment; /* status words DMA alignment requirement */ - const unsigned char* fw_data; /* address of firmware data start */ - const unsigned int* fw_size; /* address of firmware data size */ u32 (*read)(volatile u32 __iomem *); void (*write)(u32, volatile u32 __iomem *); u32 (*dma_map)(struct fore200e*, void*, int, int); diff --git a/drivers/atm/fore200e_firmware_copyright b/drivers/atm/fore200e_firmware_copyright deleted file mode 100644 index d58e6490836..00000000000 --- a/drivers/atm/fore200e_firmware_copyright +++ /dev/null @@ -1,31 +0,0 @@ - -These microcode data are placed under the terms of the GNU General Public License. - -We would prefer you not to distribute modified versions of it and not to ask -for assembly or other microcode source. - -Copyright (c) 1995-2000 FORE Systems, Inc., as an unpublished work. This -notice does not imply unrestricted or public access to these materials which -are a trade secret of FORE Systems, Inc. or its subsidiaries or affiliates -(together referred to as "FORE"), and which may not be reproduced, used, sold -or transferred to any third party without FORE's prior written consent. All -rights reserved. - -U.S. Government Restricted Rights. If you are licensing the Software on -behalf of the U.S. Government ("Government"), the following provisions apply -to you. If the software is supplied to the Department of Defense ("DoD"), it -is classified as "Commercial Computer Software" under paragraph 252.227-7014 -of the DoD Supplement to the Federal Acquisition Regulations ("DFARS") (or any -successor regulations) and the Government is acquiring only the license -rights granted herein (the license rights customarily provided to non-Government -users). If the Software is supplied to any unit or agency of the Government -other than the DoD, it is classified as "Restricted Computer Software" and -the Government's rights in the Software are defined in paragraph 52.227-19 of -the Federal Acquisition Regulations ("FAR") (or any successor regulations) or, -in the cases of NASA, in paragraph 18.52.227-86 of the NASA Supplement to the FAR -(or any successor regulations). - -FORE Systems is a registered trademark, and ForeRunner, ForeRunnerLE, and -ForeThought are trademarks of FORE Systems, Inc. All other brands or product -names are trademarks or registered trademarks of their respective holders. - diff --git a/drivers/atm/fore200e_mkfirm.c b/drivers/atm/fore200e_mkfirm.c deleted file mode 100644 index 520e14b488f..00000000000 --- a/drivers/atm/fore200e_mkfirm.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - mkfirm.c: generates a C readable file from a binary firmware image - - Christophe Lizzi (lizzi@{csti.fr, cnam.fr}), June 1999. - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. -*/ - -#include <stdio.h> -#include <stdlib.h> -#include <sys/types.h> -#include <time.h> - -char* default_basename = "pca200e"; /* was initially written for the PCA-200E firmware */ -char* default_infname = "<stdin>"; -char* default_outfname = "<stdout>"; - -char* progname; -int verbose = 0; -int inkernel = 0; - - -void usage(void) -{ - fprintf(stderr, - "%s: [-v] [-k] [-b basename ] [-i firmware.bin] [-o firmware.c]\n", - progname); - exit(-1); -} - - -int main(int argc, char** argv) -{ - time_t now; - char* infname = NULL; - char* outfname = NULL; - char* basename = NULL; - FILE* infile; - FILE* outfile; - unsigned firmsize; - int c; - - progname = *(argv++); - - while (argc > 1) { - if ((*argv)[0] == '-') { - switch ((*argv)[1]) { - case 'i': - if (argc-- < 3) - usage(); - infname = *(++argv); - break; - case 'o': - if (argc-- < 3) - usage(); - outfname = *(++argv); - break; - case 'b': - if (argc-- < 3) - usage(); - basename = *(++argv); - break; - case 'v': - verbose = 1; - break; - case 'k': - inkernel = 1; - break; - default: - usage(); - } - } - else { - usage(); - } - argc--; - argv++; - } - - if (infname != NULL) { - infile = fopen(infname, "r"); - if (infile == NULL) { - fprintf(stderr, "%s: can't open %s for reading\n", - progname, infname); - exit(-2); - } - } - else { - infile = stdin; - infname = default_infname; - } - - if (outfname) { - outfile = fopen(outfname, "w"); - if (outfile == NULL) { - fprintf(stderr, "%s: can't open %s for writing\n", - progname, outfname); - exit(-3); - } - } - else { - outfile = stdout; - outfname = default_outfname; - } - - if (basename == NULL) - basename = default_basename; - - if (verbose) { - fprintf(stderr, "%s: input file = %s\n", progname, infname ); - fprintf(stderr, "%s: output file = %s\n", progname, outfname ); - fprintf(stderr, "%s: firmware basename = %s\n", progname, basename ); - } - - time(&now); - fprintf(outfile, "/*\n generated by %s from %s on %s" - " DO NOT EDIT!\n*/\n\n", - progname, infname, ctime(&now)); - - if (inkernel) - fprintf(outfile, "#include <linux/init.h>\n\n" ); - - /* XXX force 32 bit alignment? */ - fprintf(outfile, "const unsigned char%s %s_data[] = {\n", - inkernel ? " __initdata" : "", basename ); - - c = getc(infile); - fprintf(outfile,"\t0x%02x", c); - firmsize = 1; - - while ((c = getc(infile)) >= 0) { - - if (firmsize++ % 8) - fprintf(outfile,", 0x%02x", c); - else - fprintf(outfile,",\n\t0x%02x", c); - } - - fprintf(outfile, "\n};\n\n"); - - fprintf(outfile, "const unsigned int%s %s_size = %u;\n", - inkernel ? " __initdata" : "", basename, firmsize ); - - if (infile != stdin) - fclose(infile); - if (outfile != stdout) - fclose(outfile); - - if(verbose) - fprintf(stderr, "%s: firmware size = %u\n", progname, firmsize); - - exit(0); -} diff --git a/drivers/atm/he.c b/drivers/atm/he.c index ffc4a5a4194..bdbad7edf68 100644 --- a/drivers/atm/he.c +++ b/drivers/atm/he.c @@ -75,14 +75,8 @@ #include <linux/atm.h> #include <linux/sonet.h> -#define USE_TASKLET #undef USE_SCATTERGATHER #undef USE_CHECKSUM_HW /* still confused about this */ -#define USE_RBPS -#undef USE_RBPS_POOL /* if memory is tight try this */ -#undef USE_RBPL_POOL /* if memory is tight try this */ -#define USE_TPD_POOL -/* #undef CONFIG_ATM_HE_USE_SUNI */ /* #undef HE_DEBUG */ #include "he.h" @@ -388,9 +382,7 @@ he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent) he_dev->atm_dev->dev_data = he_dev; atm_dev->dev_data = he_dev; he_dev->number = atm_dev->number; -#ifdef USE_TASKLET tasklet_init(&he_dev->tasklet, he_tasklet, (unsigned long) he_dev); -#endif spin_lock_init(&he_dev->global_lock); if (he_start(atm_dev)) { @@ -787,23 +779,13 @@ he_init_group(struct he_dev *he_dev, int group) { int i; -#ifdef USE_RBPS /* small buffer pool */ -#ifdef USE_RBPS_POOL he_dev->rbps_pool = pci_pool_create("rbps", he_dev->pci_dev, CONFIG_RBPS_BUFSIZE, 8, 0); if (he_dev->rbps_pool == NULL) { hprintk("unable to create rbps pages\n"); return -ENOMEM; } -#else /* !USE_RBPS_POOL */ - he_dev->rbps_pages = pci_alloc_consistent(he_dev->pci_dev, - CONFIG_RBPS_SIZE * CONFIG_RBPS_BUFSIZE, &he_dev->rbps_pages_phys); - if (he_dev->rbps_pages == NULL) { - hprintk("unable to create rbps page pool\n"); - return -ENOMEM; - } -#endif /* USE_RBPS_POOL */ he_dev->rbps_base = pci_alloc_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE * sizeof(struct he_rbp), &he_dev->rbps_phys); @@ -818,14 +800,9 @@ he_init_group(struct he_dev *he_dev, int group) dma_addr_t dma_handle; void *cpuaddr; -#ifdef USE_RBPS_POOL cpuaddr = pci_pool_alloc(he_dev->rbps_pool, GFP_KERNEL|GFP_DMA, &dma_handle); if (cpuaddr == NULL) return -ENOMEM; -#else - cpuaddr = he_dev->rbps_pages + (i * CONFIG_RBPS_BUFSIZE); - dma_handle = he_dev->rbps_pages_phys + (i * CONFIG_RBPS_BUFSIZE); -#endif he_dev->rbps_virt[i].virt = cpuaddr; he_dev->rbps_base[i].status = RBP_LOANED | RBP_SMALLBUF | (i << RBP_INDEX_OFF); @@ -844,30 +821,14 @@ he_init_group(struct he_dev *he_dev, int group) RBP_QSIZE(CONFIG_RBPS_SIZE - 1) | RBP_INT_ENB, G0_RBPS_QI + (group * 32)); -#else /* !USE_RBPS */ - he_writel(he_dev, 0x0, G0_RBPS_S + (group * 32)); - he_writel(he_dev, 0x0, G0_RBPS_T + (group * 32)); - he_writel(he_dev, 0x0, G0_RBPS_QI + (group * 32)); - he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0), - G0_RBPS_BS + (group * 32)); -#endif /* USE_RBPS */ /* large buffer pool */ -#ifdef USE_RBPL_POOL he_dev->rbpl_pool = pci_pool_create("rbpl", he_dev->pci_dev, CONFIG_RBPL_BUFSIZE, 8, 0); if (he_dev->rbpl_pool == NULL) { hprintk("unable to create rbpl pool\n"); return -ENOMEM; } -#else /* !USE_RBPL_POOL */ - he_dev->rbpl_pages = (void *) pci_alloc_consistent(he_dev->pci_dev, - CONFIG_RBPL_SIZE * CONFIG_RBPL_BUFSIZE, &he_dev->rbpl_pages_phys); - if (he_dev->rbpl_pages == NULL) { - hprintk("unable to create rbpl pages\n"); - return -ENOMEM; - } -#endif /* USE_RBPL_POOL */ he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE * sizeof(struct he_rbp), &he_dev->rbpl_phys); @@ -882,14 +843,9 @@ he_init_group(struct he_dev *he_dev, int group) dma_addr_t dma_handle; void *cpuaddr; -#ifdef USE_RBPL_POOL cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, GFP_KERNEL|GFP_DMA, &dma_handle); if (cpuaddr == NULL) return -ENOMEM; -#else - cpuaddr = he_dev->rbpl_pages + (i * CONFIG_RBPL_BUFSIZE); - dma_handle = he_dev->rbpl_pages_phys + (i * CONFIG_RBPL_BUFSIZE); -#endif he_dev->rbpl_virt[i].virt = cpuaddr; he_dev->rbpl_base[i].status = RBP_LOANED | (i << RBP_INDEX_OFF); @@ -1475,7 +1431,6 @@ he_start(struct atm_dev *dev) he_init_tpdrq(he_dev); -#ifdef USE_TPD_POOL he_dev->tpd_pool = pci_pool_create("tpd", he_dev->pci_dev, sizeof(struct he_tpd), TPD_ALIGNMENT, 0); if (he_dev->tpd_pool == NULL) { @@ -1484,20 +1439,6 @@ he_start(struct atm_dev *dev) } INIT_LIST_HEAD(&he_dev->outstanding_tpds); -#else - he_dev->tpd_base = (void *) pci_alloc_consistent(he_dev->pci_dev, - CONFIG_NUMTPDS * sizeof(struct he_tpd), &he_dev->tpd_base_phys); - if (!he_dev->tpd_base) - return -ENOMEM; - - for (i = 0; i < CONFIG_NUMTPDS; ++i) { - he_dev->tpd_base[i].status = (i << TPD_ADDR_SHIFT); - he_dev->tpd_base[i].inuse = 0; - } - - he_dev->tpd_head = he_dev->tpd_base; - he_dev->tpd_end = &he_dev->tpd_base[CONFIG_NUMTPDS - 1]; -#endif if (he_init_group(he_dev, 0) != 0) return -ENOMEM; @@ -1542,7 +1483,8 @@ he_start(struct atm_dev *dev) /* initialize framer */ #ifdef CONFIG_ATM_HE_USE_SUNI - suni_init(he_dev->atm_dev); + if (he_isMM(he_dev)) + suni_init(he_dev->atm_dev); if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->start) he_dev->atm_dev->phy->start(he_dev->atm_dev); #endif /* CONFIG_ATM_HE_USE_SUNI */ @@ -1554,6 +1496,7 @@ he_start(struct atm_dev *dev) val = he_phy_get(he_dev->atm_dev, SUNI_TPOP_APM); val = (val & ~SUNI_TPOP_APM_S) | (SUNI_TPOP_S_SDH << SUNI_TPOP_APM_S_SHIFT); he_phy_put(he_dev->atm_dev, val, SUNI_TPOP_APM); + he_phy_put(he_dev->atm_dev, SUNI_TACP_IUCHP_CLP, SUNI_TACP_IUCHP); } /* 5.1.12 enable transmit and receive */ @@ -1604,9 +1547,7 @@ he_stop(struct he_dev *he_dev) gen_cntl_0 &= ~(INT_PROC_ENBL | INIT_ENB); pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0); -#ifdef USE_TASKLET tasklet_disable(&he_dev->tasklet); -#endif /* disable recv and transmit */ @@ -1636,7 +1577,6 @@ he_stop(struct he_dev *he_dev) he_dev->hsp, he_dev->hsp_phys); if (he_dev->rbpl_base) { -#ifdef USE_RBPL_POOL int i; for (i = 0; i < CONFIG_RBPL_SIZE; ++i) { @@ -1645,22 +1585,14 @@ he_stop(struct he_dev *he_dev) pci_pool_free(he_dev->rbpl_pool, cpuaddr, dma_handle); } -#else - pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE - * CONFIG_RBPL_BUFSIZE, he_dev->rbpl_pages, he_dev->rbpl_pages_phys); -#endif pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE * sizeof(struct he_rbp), he_dev->rbpl_base, he_dev->rbpl_phys); } -#ifdef USE_RBPL_POOL if (he_dev->rbpl_pool) pci_pool_destroy(he_dev->rbpl_pool); -#endif -#ifdef USE_RBPS if (he_dev->rbps_base) { -#ifdef USE_RBPS_POOL int i; for (i = 0; i < CONFIG_RBPS_SIZE; ++i) { @@ -1669,20 +1601,12 @@ he_stop(struct he_dev *he_dev) pci_pool_free(he_dev->rbps_pool, cpuaddr, dma_handle); } -#else - pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE - * CONFIG_RBPS_BUFSIZE, he_dev->rbps_pages, he_dev->rbps_pages_phys); -#endif pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE * sizeof(struct he_rbp), he_dev->rbps_base, he_dev->rbps_phys); } -#ifdef USE_RBPS_POOL if (he_dev->rbps_pool) pci_pool_destroy(he_dev->rbps_pool); -#endif - -#endif /* USE_RBPS */ if (he_dev->rbrq_base) pci_free_consistent(he_dev->pci_dev, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), @@ -1696,14 +1620,8 @@ he_stop(struct he_dev *he_dev) pci_free_consistent(he_dev->pci_dev, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), he_dev->tpdrq_base, he_dev->tpdrq_phys); -#ifdef USE_TPD_POOL if (he_dev->tpd_pool) pci_pool_destroy(he_dev->tpd_pool); -#else - if (he_dev->tpd_base) - pci_free_consistent(he_dev->pci_dev, CONFIG_NUMTPDS * sizeof(struct he_tpd), - he_dev->tpd_base, he_dev->tpd_base_phys); -#endif if (he_dev->pci_dev) { pci_read_config_word(he_dev->pci_dev, PCI_COMMAND, &command); @@ -1718,7 +1636,6 @@ he_stop(struct he_dev *he_dev) static struct he_tpd * __alloc_tpd(struct he_dev *he_dev) { -#ifdef USE_TPD_POOL struct he_tpd *tpd; dma_addr_t dma_handle; @@ -1733,27 +1650,6 @@ __alloc_tpd(struct he_dev *he_dev) tpd->iovec[2].addr = 0; tpd->iovec[2].len = 0; return tpd; -#else - int i; - - for (i = 0; i < CONFIG_NUMTPDS; ++i) { - ++he_dev->tpd_head; - if (he_dev->tpd_head > he_dev->tpd_end) { - he_dev->tpd_head = he_dev->tpd_base; - } - - if (!he_dev->tpd_head->inuse) { - he_dev->tpd_head->inuse = 1; - he_dev->tpd_head->status &= TPD_MASK; - he_dev->tpd_head->iovec[0].addr = 0; he_dev->tpd_head->iovec[0].len = 0; - he_dev->tpd_head->iovec[1].addr = 0; he_dev->tpd_head->iovec[1].len = 0; - he_dev->tpd_head->iovec[2].addr = 0; he_dev->tpd_head->iovec[2].len = 0; - return he_dev->tpd_head; - } - } - hprintk("out of tpds -- increase CONFIG_NUMTPDS (%d)\n", CONFIG_NUMTPDS); - return NULL; -#endif } #define AAL5_LEN(buf,len) \ @@ -1802,11 +1698,9 @@ he_service_rbrq(struct he_dev *he_dev, int group) RBRQ_CON_CLOSED(he_dev->rbrq_head) ? " CON_CLOSED" : "", RBRQ_HBUF_ERR(he_dev->rbrq_head) ? " HBUF_ERR" : ""); -#ifdef USE_RBPS if (RBRQ_ADDR(he_dev->rbrq_head) & RBP_SMALLBUF) rbp = &he_dev->rbps_base[RBP_INDEX(RBRQ_ADDR(he_dev->rbrq_head))]; else -#endif rbp = &he_dev->rbpl_base[RBP_INDEX(RBRQ_ADDR(he_dev->rbrq_head))]; buf_len = RBRQ_BUFLEN(he_dev->rbrq_head) * 4; @@ -1885,12 +1779,10 @@ he_service_rbrq(struct he_dev *he_dev, int group) for (iov = he_vcc->iov_head; iov < he_vcc->iov_tail; ++iov) { -#ifdef USE_RBPS if (iov->iov_base & RBP_SMALLBUF) memcpy(skb_put(skb, iov->iov_len), he_dev->rbps_virt[RBP_INDEX(iov->iov_base)].virt, iov->iov_len); else -#endif memcpy(skb_put(skb, iov->iov_len), he_dev->rbpl_virt[RBP_INDEX(iov->iov_base)].virt, iov->iov_len); } @@ -1935,11 +1827,9 @@ return_host_buffers: for (iov = he_vcc->iov_head; iov < he_vcc->iov_tail; ++iov) { -#ifdef USE_RBPS if (iov->iov_base & RBP_SMALLBUF) rbp = &he_dev->rbps_base[RBP_INDEX(iov->iov_base)]; else -#endif rbp = &he_dev->rbpl_base[RBP_INDEX(iov->iov_base)]; rbp->status &= ~RBP_LOANED; @@ -1975,9 +1865,7 @@ he_service_tbrq(struct he_dev *he_dev, int group) he_dev->hsp->group[group].tbrq_tail); struct he_tpd *tpd; int slot, updated = 0; -#ifdef USE_TPD_POOL struct he_tpd *__tpd; -#endif /* 2.1.6 transmit buffer return queue */ @@ -1989,7 +1877,6 @@ he_service_tbrq(struct he_dev *he_dev, int group) TBRQ_TPD(he_dev->tbrq_head), TBRQ_EOS(he_dev->tbrq_head) ? " EOS" : "", TBRQ_MULTIPLE(he_dev->tbrq_head) ? " MULTIPLE" : ""); -#ifdef USE_TPD_POOL tpd = NULL; list_for_each_entry(__tpd, &he_dev->outstanding_tpds, entry) { if (TPD_ADDR(__tpd->status) == TBRQ_TPD(he_dev->tbrq_head)) { @@ -2004,9 +1891,6 @@ he_service_tbrq(struct he_dev *he_dev, int group) TBRQ_TPD(he_dev->tbrq_head)); goto next_tbrq_entry; } -#else - tpd = &he_dev->tpd_base[ TPD_INDEX(TBRQ_TPD(he_dev->tbrq_head)) ]; -#endif if (TBRQ_EOS(he_dev->tbrq_head)) { HPRINTK("wake_up(tx_waitq) cid 0x%x\n", @@ -2036,12 +1920,8 @@ he_service_tbrq(struct he_dev *he_dev, int group) } next_tbrq_entry: -#ifdef USE_TPD_POOL if (tpd) pci_pool_free(he_dev->tpd_pool, tpd, TPD_ADDR(tpd->status)); -#else - tpd->inuse = 0; -#endif he_dev->tbrq_head = (struct he_tbrq *) ((unsigned long) he_dev->tbrq_base | TBRQ_MASK(++he_dev->tbrq_head)); @@ -2084,7 +1964,6 @@ he_service_rbpl(struct he_dev *he_dev, int group) he_writel(he_dev, RBPL_MASK(he_dev->rbpl_tail), G0_RBPL_T); } -#ifdef USE_RBPS static void he_service_rbps(struct he_dev *he_dev, int group) { @@ -2111,7 +1990,6 @@ he_service_rbps(struct he_dev *he_dev, int group) if (moved) he_writel(he_dev, RBPS_MASK(he_dev->rbps_tail), G0_RBPS_T); } -#endif /* USE_RBPS */ static void he_tasklet(unsigned long data) @@ -2122,9 +2000,7 @@ he_tasklet(unsigned long data) int updated = 0; HPRINTK("tasklet (0x%lx)\n", data); -#ifdef USE_TASKLET spin_lock_irqsave(&he_dev->global_lock, flags); -#endif while (he_dev->irq_head != he_dev->irq_tail) { ++updated; @@ -2139,9 +2015,7 @@ he_tasklet(unsigned long data) case ITYPE_RBRQ_TIMER: if (he_service_rbrq(he_dev, group)) { he_service_rbpl(he_dev, group); -#ifdef USE_RBPS he_service_rbps(he_dev, group); -#endif /* USE_RBPS */ } break; case ITYPE_TBRQ_THRESH: @@ -2154,9 +2028,7 @@ he_tasklet(unsigned long data) he_service_rbpl(he_dev, group); break; case ITYPE_RBPS_THRESH: -#ifdef USE_RBPS he_service_rbps(he_dev, group); -#endif /* USE_RBPS */ break; case ITYPE_PHY: HPRINTK("phy interrupt\n"); @@ -2184,9 +2056,7 @@ he_tasklet(unsigned long data) he_service_rbrq(he_dev, 0); he_service_rbpl(he_dev, 0); -#ifdef USE_RBPS he_service_rbps(he_dev, 0); -#endif /* USE_RBPS */ he_service_tbrq(he_dev, 0); break; default: @@ -2208,9 +2078,7 @@ he_tasklet(unsigned long data) IRQ_TAIL(he_dev->irq_tail), IRQ0_HEAD); (void) he_readl(he_dev, INT_FIFO); /* 8.1.2 controller errata; flush posted writes */ } -#ifdef USE_TASKLET spin_unlock_irqrestore(&he_dev->global_lock, flags); -#endif } static irqreturn_t @@ -2242,11 +2110,7 @@ he_irq_handler(int irq, void *dev_id) if (he_dev->irq_head != he_dev->irq_tail) { handled = 1; -#ifdef USE_TASKLET tasklet_schedule(&he_dev->tasklet); -#else - he_tasklet((unsigned long) he_dev); -#endif he_writel(he_dev, INT_CLEAR_A, INT_FIFO); /* clear interrupt */ (void) he_readl(he_dev, INT_FIFO); /* flush posted writes */ } @@ -2303,23 +2167,14 @@ __enqueue_tpd(struct he_dev *he_dev, struct he_tpd *tpd, unsigned cid) dev_kfree_skb_any(tpd->skb); atomic_inc(&tpd->vcc->stats->tx_err); } -#ifdef USE_TPD_POOL pci_pool_free(he_dev->tpd_pool, tpd, TPD_ADDR(tpd->status)); -#else - tpd->inuse = 0; -#endif return; } } /* 2.1.5 transmit packet descriptor ready queue */ -#ifdef USE_TPD_POOL list_add_tail(&tpd->entry, &he_dev->outstanding_tpds); he_dev->tpdrq_tail->tpd = TPD_ADDR(tpd->status); -#else - he_dev->tpdrq_tail->tpd = he_dev->tpd_base_phys + - (TPD_INDEX(tpd->status) * sizeof(struct he_tpd)); -#endif he_dev->tpdrq_tail->cid = cid; wmb(); @@ -2509,13 +2364,8 @@ he_open(struct atm_vcc *vcc) goto open_failed; } -#ifdef USE_RBPS rsr1 = RSR1_GROUP(0); rsr4 = RSR4_GROUP(0); -#else /* !USE_RBPS */ - rsr1 = RSR1_GROUP(0)|RSR1_RBPL_ONLY; - rsr4 = RSR4_GROUP(0)|RSR4_RBPL_ONLY; -#endif /* USE_RBPS */ rsr0 = vcc->qos.rxtp.traffic_class == ATM_UBR ? (RSR0_EPD_ENABLE|RSR0_PPD_ENABLE) : 0; @@ -2844,10 +2694,15 @@ he_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void __user *arg) if (copy_from_user(®, arg, sizeof(struct he_ioctl_reg))) return -EFAULT; - + spin_lock_irqsave(&he_dev->global_lock, flags); switch (reg.type) { case HE_REGTYPE_PCI: + if (reg.addr < 0 || reg.addr >= HE_REGMAP_SIZE) { + err = -EINVAL; + break; + } + reg.val = he_readl(he_dev, reg.addr); break; case HE_REGTYPE_RCM: diff --git a/drivers/atm/he.h b/drivers/atm/he.h index fe6cd15a78a..c2983e0d4ec 100644 --- a/drivers/atm/he.h +++ b/drivers/atm/he.h @@ -51,8 +51,6 @@ #define CONFIG_IRQ_SIZE 128 #define CONFIG_IRQ_THRESH (CONFIG_IRQ_SIZE/2) -#define CONFIG_NUMTPDS 256 - #define CONFIG_TPDRQ_SIZE 512 #define TPDRQ_MASK(x) (((unsigned long)(x))&((CONFIG_TPDRQ_SIZE<<3)-1)) @@ -140,12 +138,7 @@ struct he_tpd { struct sk_buff *skb; struct atm_vcc *vcc; -#ifdef USE_TPD_POOL struct list_head entry; -#else - u32 inuse; - char padding[32 - sizeof(u32) - (2*sizeof(void*))]; -#endif }; #define TPD_ALIGNMENT 64 @@ -267,13 +260,7 @@ struct he_dev { char prod_id[30]; char mac_addr[6]; - int media; /* - * 0x26 = HE155 MM - * 0x27 = HE622 MM - * 0x46 = HE155 SM - * 0x47 = HE622 SM - */ - + int media; unsigned int vcibits, vpibits; unsigned int cells_per_row; @@ -297,16 +284,9 @@ struct he_dev { volatile unsigned *irq_tailoffset; int irq_peak; -#ifdef USE_TASKLET struct tasklet_struct tasklet; -#endif -#ifdef USE_TPD_POOL struct pci_pool *tpd_pool; struct list_head outstanding_tpds; -#else - struct he_tpd *tpd_head, *tpd_base, *tpd_end; - dma_addr_t tpd_base_phys; -#endif dma_addr_t tpdrq_phys; struct he_tpdrq *tpdrq_base, *tpdrq_tail, *tpdrq_head; @@ -317,25 +297,13 @@ struct he_dev { struct he_rbrq *rbrq_base, *rbrq_head; int rbrq_peak; -#ifdef USE_RBPL_POOL struct pci_pool *rbpl_pool; -#else - void *rbpl_pages; - dma_addr_t rbpl_pages_phys; -#endif dma_addr_t rbpl_phys; struct he_rbp *rbpl_base, *rbpl_tail; struct he_virt *rbpl_virt; int rbpl_peak; -#ifdef USE_RBPS -#ifdef USE_RBPS_POOL struct pci_pool *rbps_pool; -#else - void *rbps_pages; - dma_addr_t rbps_pages_phys; -#endif -#endif dma_addr_t rbps_phys; struct he_rbp *rbps_base, *rbps_tail; struct he_virt *rbps_virt; @@ -392,6 +360,7 @@ struct he_vcc #define HE_DEV(dev) ((struct he_dev *) (dev)->dev_data) #define he_is622(dev) ((dev)->media & 0x1) +#define he_isMM(dev) ((dev)->media & 0x20) #define HE_REGMAP_SIZE 0x100000 @@ -876,8 +845,8 @@ struct he_vcc #define M_SN 0x3a /* integer */ #define MEDIA 0x3e /* integer */ #define HE155MM 0x26 -#define HE155SM 0x27 -#define HE622MM 0x46 +#define HE622MM 0x27 +#define HE155SM 0x46 #define HE622SM 0x47 #define MAC_ADDR 0x42 /* char[] */ diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c index 5c28ca7380f..24df73ad326 100644 --- a/drivers/atm/iphase.c +++ b/drivers/atm/iphase.c @@ -65,12 +65,7 @@ #include "iphase.h" #include "suni.h" #define swap(x) (((x & 0xff) << 8) | ((x & 0xff00) >> 8)) -struct suni_priv { - struct k_sonet_stats sonet_stats; /* link diagnostics */ - unsigned char loop_mode; /* loopback mode */ - struct atm_dev *dev; /* device back-pointer */ - struct suni_priv *next; /* next SUNI */ -}; + #define PRIV(dev) ((struct suni_priv *) dev->phy_data) static unsigned char ia_phy_get(struct atm_dev *dev, unsigned long addr); @@ -94,10 +89,6 @@ module_param(IADebugFlag, uint, 0644); MODULE_LICENSE("GPL"); -#if BITS_PER_LONG != 32 -# error FIXME: this driver only works on 32-bit platforms -#endif - /**************************** IA_LIB **********************************/ static void ia_init_rtn_q (IARTN_Q *que) @@ -1411,7 +1402,6 @@ static int rx_init(struct atm_dev *dev) struct abr_vc_table *abr_vc_table; u16 *vc_table; u16 *reass_table; - u16 *ptr16; int i,j, vcsize_sel; u_short freeq_st_adr; u_short *freeq_start; @@ -1426,14 +1416,15 @@ static int rx_init(struct atm_dev *dev) printk(KERN_ERR DEV_LABEL "can't allocate DLEs\n"); goto err_out; } - iadev->rx_dle_q.start = (struct dle*)dle_addr; + iadev->rx_dle_q.start = (struct dle *)dle_addr; iadev->rx_dle_q.read = iadev->rx_dle_q.start; iadev->rx_dle_q.write = iadev->rx_dle_q.start; - iadev->rx_dle_q.end = (struct dle*)((u32)dle_addr+sizeof(struct dle)*DLE_ENTRIES); + iadev->rx_dle_q.end = (struct dle*)((unsigned long)dle_addr+sizeof(struct dle)*DLE_ENTRIES); /* the end of the dle q points to the entry after the last DLE that can be used. */ /* write the upper 20 bits of the start address to rx list address register */ + /* We know this is 32bit bus addressed so the following is safe */ writel(iadev->rx_dle_dma & 0xfffff000, iadev->dma + IPHASE5575_RX_LIST_ADDR); IF_INIT(printk("Tx Dle list addr: 0x%08x value: 0x%0x\n", @@ -1587,11 +1578,12 @@ static int rx_init(struct atm_dev *dev) Set Packet Aging Interval count register to overflow in about 4 us */ writew(0xF6F8, iadev->reass_reg+PKT_TM_CNT ); - ptr16 = (u16*)j; - i = ((u32)ptr16 >> 6) & 0xff; - ptr16 += j - 1; - i |=(((u32)ptr16 << 2) & 0xff00); + + i = (j >> 6) & 0xFF; + j += 2 * (j - 1); + i |= ((j << 2) & 0xFF00); writew(i, iadev->reass_reg+TMOUT_RANGE); + /* initiate the desc_tble */ for(i=0; i<iadev->num_tx_desc;i++) iadev->desc_tbl[i].timestamp = 0; @@ -1914,7 +1906,7 @@ static int tx_init(struct atm_dev *dev) iadev->tx_dle_q.start = (struct dle*)dle_addr; iadev->tx_dle_q.read = iadev->tx_dle_q.start; iadev->tx_dle_q.write = iadev->tx_dle_q.start; - iadev->tx_dle_q.end = (struct dle*)((u32)dle_addr+sizeof(struct dle)*DLE_ENTRIES); + iadev->tx_dle_q.end = (struct dle*)((unsigned long)dle_addr+sizeof(struct dle)*DLE_ENTRIES); /* write the upper 20 bits of the start address to tx list address register */ writel(iadev->tx_dle_dma & 0xfffff000, @@ -2562,17 +2554,11 @@ static int __devinit ia_start(struct atm_dev *dev) error = suni_init(dev); if (error) goto err_free_rx; - /* - * Enable interrupt on loss of signal - * SUNI_RSOP_CIE - 0x10 - * SUNI_RSOP_CIE_LOSE - 0x04 - */ - ia_phy_put(dev, ia_phy_get(dev, 0x10) | 0x04, 0x10); -#ifndef MODULE - error = dev->phy->start(dev); - if (error) - goto err_free_rx; -#endif + if (dev->phy->start) { + error = dev->phy->start(dev); + if (error) + goto err_free_rx; + } /* Get iadev->carrier_detect status */ IaFrontEndIntr(iadev); } @@ -2913,7 +2899,7 @@ static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) { dev_kfree_skb_any(skb); return 0; } - if ((u32)skb->data & 3) { + if ((unsigned long)skb->data & 3) { printk("Misaligned SKB\n"); if (vcc->pop) vcc->pop(vcc, skb); @@ -3198,6 +3184,8 @@ static int __devinit ia_init_one(struct pci_dev *pdev, IF_INIT(printk("dev_id = 0x%x iadev->LineRate = %d \n", (u32)dev, iadev->LineRate);) + pci_set_drvdata(pdev, dev); + ia_dev[iadev_count] = iadev; _ia_dev[iadev_count] = dev; iadev_count++; @@ -3219,8 +3207,6 @@ static int __devinit ia_init_one(struct pci_dev *pdev, iadev->next_board = ia_boards; ia_boards = dev; - pci_set_drvdata(pdev, dev); - return 0; err_out_deregister_dev: @@ -3238,9 +3224,14 @@ static void __devexit ia_remove_one(struct pci_dev *pdev) struct atm_dev *dev = pci_get_drvdata(pdev); IADEV *iadev = INPH_IA_DEV(dev); - ia_phy_put(dev, ia_phy_get(dev,0x10) & ~(0x4), 0x10); + /* Disable phy interrupts */ + ia_phy_put(dev, ia_phy_get(dev, SUNI_RSOP_CIE) & ~(SUNI_RSOP_CIE_LOSE), + SUNI_RSOP_CIE); udelay(1); + if (dev->phy && dev->phy->stop) + dev->phy->stop(dev); + /* De-register device */ free_irq(iadev->irq, dev); iadev_count--; diff --git a/drivers/atm/pca200e.data b/drivers/atm/pca200e.data deleted file mode 100644 index e78e83becd9..00000000000 --- a/drivers/atm/pca200e.data +++ /dev/null @@ -1,850 +0,0 @@ -:150000001F8B0808AB5A10380203706361323030652E62696E4D -:150015007D00E43A0D7014D7796FA5BDE84EC86211A7333020EE -:15002A00AD89C00A23EA83AA589C7E7C38D8152EB887477677D3 -:15003F0095C39C3DB2AB388CA324C4A509352BFBB085BBD0C73F -:150054007210B903C92991CCD1B1C242255BCCD81EA5C34C6826 -:1500690006271AC6D36A3A31B976D4A9A683DB4B07BB38265C56 -:15007E00BFEFBDB7777BA7030B2733994C35737AFBBEF7BDEFE7 -:15009300EF7DDFF7BEF7769FFEEAD79F221221E1ED844C3E4677 -:1500A8007EA3BFF036F827CF8597C3AF0C7E920B16595BCE5AA8 -:1500BD00296B6483D83E9F7DBE8FF50BE74A0B45FB1F274FAA79 -:1500D200D82E2867139DF637FD937EF1D55FB0769FE8678BDAFB -:1500E7007D9BD8885451515172FE27E4138E9FC9949CBFF026BC -:1500FC00741DF83ECE59823FF23BF89346493F6B4F17C1B3A7CE -:15011100B3B79C97D3275B5ABFEC3CF9579457703B3CBFEFD600 -:15012600FC38236CA91B5E347EDBFA67F7ED4397956EA4D3C5F4 -:15013B007CE6A567799EFFF5CFC4FF7BDF938BF83E83EDE59F02 -:15015000FEAC24BF8A3C3F2FF9FDFF933CF51EF2FFEC2FEBFA11 -:150165002341C38CBC5F4EAA265F5EAF04BC51F0059FD1419ED8 -:15017A00063493D465A2384E66A0171C30231F40AB5CB5646FC8 -:15018F005CBFB633DECCC614D2DAF622F15D3189EFEA3EE28B83 -:1501A4007D99F8DABE4D7C2418A438AF3129015D7507F1032EBA -:1501B900E174827F46C82229AE2BC63A9D50E9253960EC005FCA -:1501CE00F2EDFE0AF12A9D5EBD6A35F1B5AC441A49BAD94F22C6 -:1501E300DECB544F180D1A51FACD8C4A7C034B93DAFD6455A8F9 -:1501F8009AAC5AB74C9542EF11E23DB0946A0F1B0DA10BF0CC0C -:15020D00F9A4A8097BCA1D751474A02FEC02593C75C9E870D176 -:15022200B8CF352EC3783C379E1C2893C98017C6A57B3CDD0E4D -:15023700CE32426A9CB99F03FC2E81BF46AD0D06544FD0190B08 -:15024C00C0580B8E897EFDF490DE08FD652E9CFAE911DD5F24FE -:15026100CF832469DAB1116BE0F3C437B686F8D275C437AC9220 -:150276000542BFF6CC0320B22AB7237E1F5B97A4E927A397490C -:15028B0064C43AFF0CD8ACCE8886D37F632A7F4C16005E289CAF -:1502A0003E491DDAFB083513C6B0A6B8E4929626F531E0877479 -:1502B50082E58C9E2503DDD45DC4777E3BF1051F253E09684E42 -:1502CA00C3BAC26825AC39F5225F6598EE23B366227C52ABFC3A -:1502DF00BC2754E61BD1FFEBAE6DCDFE8D49AAEA38EE89A35A1B -:1502F4009DF0DCF4254234681BBB09E98536033F2F3C5F835F24 -:15030900107E147E1AE8AA0406A36989DB63C95ADE9F9272EBA7 -:15031E00C17C6131AC4519193457028723BE118D0433D6F063E5 -:150333005C6E1C77EC2981FD118663B2FA3A455F8D11A2D66BC0 -:15034800AFE9B096E6D4A38454D70D004ECA8235541117C7A5F2 -:15035D002D26F8E4B07D3848BA956402FC7BF8EC956CB6B6D35F -:1503720091EB21B280C218CAB04122B5957583D126189B7D88FF -:15038700FB2BDA46560F52056C867C6CE85FF1135F19E0C948D1 -:15039C0023873342916798F3A6E45FA58C9021887DB9A8DF9307 -:1503B1002EECF7421F693AB054DE6F73F4FDF414E83A6B66B2C0 -:1503C6000B11C3BA0E45D0D1074E3318C92C24FE074FF267E847 -:1503DB00E03AE67193D635C40D9FD66A65B471CABA5AC66D9C17 -:1503F00081B68DE4F5200AEA316B3E3EF5F8D4CAF0C902BFBC6E -:1504050003FD12ED00BE39F8E7C4E765F2A6F8BCC8083DA6B648 -:15041A00335DAAA0AFC4DEA66A6CDC8418EA26910FAD6A0821BE -:15042F0012B4A9C269D1DDAC9DB05A98BD06B91D807702D6021B -:15044400F02CA479BF88CD3D82BE3F92D49137C262E0EB5969BB -:15045900D6AC8DA4F4A3A0EB808FEB8570E6F34897F9F77CE4C2 -:15046E0071E4E07C73F2C0FC256AC3208B2D5C834D43BA3F060F -:15048300F39566B386103FC611E321E23D02F1168A79426C3DFD -:15049800E159DA32AAA34C083FBA62DC2474847A94BF031D86A2 -:1504AD00ACE5EAEB969CDC4FF3F3216F03DE5414FD8ED3DA3050 -:1504C2005F5AC953795A804F2146D05612811C0DB6A0BC0E67DE -:1504D7007C6E471FC3A5CFA04B06639EFA201E11FA182E7D3E53 -:1504EC009556913E89227D129F511FDBA5CF05970CF63CF54199 -:15050100BCE097B83EB64B9F4FA555A4CF60913E839F511F752A -:1505160026AF4FCB4C5E0684CF471FC48B75737DF079C37C69B3 -:15052B0015E973BC489FE32E7DC231AFD997FEF15925301975DC -:150540007CBC5E33F5D918F2E53E82FD69D1B745FF82E8237F22 -:15055500EC4FB07ED2A4626FD8C3F7363321FA29D11F14FD6938 -:15056A00D13F2EFA9D40678FFA1ACBD131181B507F88FBA8451E -:15057F00E179507D8362EC4FC2734A7D8786D5D526CF431356CC -:1505940010E6D51152BB2CE6690F243DED35694FBB17D6017487 -:1505A900B251C766F514A3D3037337AB67189D043C77A9E728AB -:1505BE00CE3FCFE5A0C8B347ED17F9CDB09A812EE4A09AFBC861 -:1505D30005F3ECCE1F76B0B8059C6AD51342D87777BEC16093F7 -:1505E8002ED82B3BDF613094C9813DB7F3A50E87FE6A95AF1F58 -:1505FD00D259C69E53B447F047991EAA1FDDE8D0747091968332 -:15061200EBC88AB2D5095CA4FB07AA87ED030961D37494DB348F -:15062700C27225D77D497EBF32958271CE6F8DA0D12CF612E37F -:15063C00718ED32568206F3FDF874C7B477EAC4DD8310AE35B40 -:15065100C17E683B139EA3EA6178A6D65B4CA65926E72EF555F4 -:150666007A82D977D06A9A610E58F3D80D4F6BFDF4DDFAC37506 -:15067B00E7D67D672AA93DD881720C301B55C6E4D0860EB97506 -:150690007D5DFF3A0A636BD898CDE4AD4C7A42CBDE915B037587 -:1506A50087D7593056DDC1E5477B55429CDCF8B5DCFAAB15AFBD -:1506BA00AE3B0263FFD3EE69AF8C5584FEF3FD0FDA90E6BFADE7 -:1506CF0030DB70FEBF9C186B43DC4BEFBFDE4682BD8C27C86F5A -:1506E400B3BC185CC264063DED086BF730DA2418B655D6F63110 -:1506F900394850B53126EEFCD1AC2EBD1B83F83B6D56056C5662 -:15070E0027F079B3565739DFC3A2AC8D591AB48B37FD4097B6BD -:150723007D4527CA41F38E00D6C48665887A30CEDA5E6BA09CE8 -:15073800EF7568CF8A7EC03FF80DC05F6B56078280AFB25C86D9 -:15074D00F863ACEDB32658DBC26CBEE04780FFEEB7017F9BB98C -:15076200301001FCB0C5E54E5A0DD0BEC8D6618FD53893DFDBC0 -:15077700489D0A781A5B9B27616DFAD4435409C08E179C365B01 -:15078C00B86D2C5EB34E5BCDD0CEC0B98106CBBA25A29A87AEC7 -:1507A100676BD0977601BC4A7DCDC2BA15ED575E1DD7B78610CF -:1507B6008FC715EE954F0A5CB4B78837139F9F079E8AEFA21E32 -:1507CB00DF9814679714AB9163E99F59FEBDE3263A704FFA4DF8 -:1507E0000BFAD400D9FCE1115DF1C541C7772D591DB7BA1C7929 -:1507F500D4BBCC1B9F701EC761BE22E4A1429EB736E6E5C1BDA9 -:15080A00EE92C09D74C933790B79222E79BA401EE8535A429E39 -:15081F00F3ABF2F23C2B785CC43812F24C0A799A5CF2E05E759D -:15083400BFC0457F73E4C1E79BC91376C9B319E4813E4D9690D5 -:15084900A7D925CFE55F711E6D33B8A771799007CA73BC252F86 -:15085E000FEE3567392EE35506B935DE3E625D87B3AC9363DDC5 -:15087300675D387B325FEEC53DCA370CF1D064D2707F1F9E1BAD -:15088800BCCC7732962CFCB60AF76B17AFD80C1694A4D6EBDAB7 -:15089D0047E58DFC1CEB75E1E10563311E21B6794C95704FA00C -:1508B20031EEBF8BC93DD0270326EC0F8A54674771FCCEF0B040 -:1508C7007E67F81CD864D8EA401CC819480FE1811DBC76E5FDFE -:1508DC00733A83FDD508D6AA24406D9DCF3FA75FCC66FD65D592 -:1508F100FDFAEE7BF332F5F0FDC225936D769033AD01550A3A24 -:15090600BCF12CBF86F184F305E007567C68E59EDB3FCCF1498D -:15091B00D79F692B73E8803CC25E4CAEDA152370463A4A2DE42F -:15093000AB34998BC0DE1BD01C0AA7C5715314ED0FC74F4B510E -:150945005ED2BDC9319893001F18B3A2AE734B17D4E2CFA89EB1 -:15095A00D6B7245E6394E2F350520E95A6DD6079943780F65B70 -:15096F00507B1C857AE36D0B6B12491D8133EA88E6D41A72B92A -:15098400A835607E52D421448C255D7548EE0F723FD656E84744 -:15099900CA3D28974DE33C4751AF90CFEB9603D61BE545BA8197 -:1509AE00906D2A44D446CA190BE550DE5F85B273DF637264CCC1 -:1509C300C15E487501388B928C8974B4ED9C4E8FD80F395D9B32 -:1509D800D9A7F6FDFD5482B3B6141B358F92514D3A30CEEA2EE8 -:1509ED003EC7B6108744E478BE6ECB98555F46FA54D0E77A23D8 -:150A0200FDE876AE1FE7932AE0C3EC226CC2EC98E676BC7347DE -:150A1700DC0A446C361675F3A48267306C72595A4C85D9A5D310 -:150A2C006467AB60D0E4761AA00C1E19A6CFDE057584F27DAC4C -:150A4100810A64F09F5845DD6B073896ACC05936324E1D3FC1D0 -:150A56001C843796C7485C2391FD168998CC2EAC0E807119F419 -:150A6B00A52D86899716E555719D1E5CABF77860FDA686D87D2E -:150A8000881FD74839ABCBEADB34C06AE6FC196F49F9DC3367A7 -:150A9500FF9653FCBCE83E774E9DC198FD9433E7203F734E0EF2 -:150AAA00E7CE9BECEC19F9BEE5F8961C30A2634DFCFEA0D0B70D -:150ABF00B82FA14CBDC23E6C6D4249E6574419B2081DA247F1E2 -:150AD400AE02FC0A7D81D9CC00FA74C84ADCC82E72F9336B3524 -:150AE90075186487D8A757CCC5B06FE37D56B5BAAAF912D674D6 -:150AFE0012F13EA3AE0D5D83985C9FF6B7B3DAEE31CEB713DA06 -:150B130045E420F33B90DB12700BE117C47D4058E0468A700568 -:150B2800DC42F87111EF0EFD1E316777D11C01B710DE2BE8F75C -:150B3D000A5CA30857C02D84B709FA2B05FD06818B78F8BCDCC9 -:150B5200956F1A5D63F88C67293C4379C18FCAAB46C037862CF0 -:150B6700B497ACBCA2E37A07D5613B00F6AA091FED901553AFF3 -:150B7C00EDBFA257A9A7AC65C6076D814DFFADCBB131EB44D2FC -:150B9100D3ED8D9966269B5D0C355EAB1CBB62393E5B09B92DA1 -:150BA6007D3DEB73C7C0B7A0CE95599D4AE7C4A388AF5C5E4121 -:150BBB001ACAA1213D513EACA16C353B1A2C279ED9DA634E30EB -:150BD0002027A4DFC63C22E273C22A8E67F405C61362C61D27AE -:150BE5002FDE11D7C365DC0F1591D33E2D4E5E82FD3B17230768 -:150BFA008634CC078AD84F31565642CAC2B3E0D3AC9E17310500 -:150C0F00F1F318F89BA8DF73B0FBC5B9E2E6B1D4226269A8F448 -:150C2400FD8D2B9E7ABEF0DBCFD57473E2296C3D2DEC7EBCF2E1 -:150C3900AE00DF13950DDEA802CFB7FA713CC25A35E0ECA52AC3 -:150C4E00D412F544A96ED2E3655F78CA23E0B4C678CA19C73BC6 -:150C63007A25DCF084ECD008279EA8719E37E5E1B9FD8ADDB182 -:150C78000DC0764CD423AADC4D73B519BFDF7C84EDF7B3589BA5 -:150C8D002978178F2324729206D4F666ACDF181C6C7FFDBEF62F -:150CA2003F04FFB4091D3E8BEDE2C8A08EF7A1481361354A427E -:150CB700BF0075C79CFD52F0EFBA09FFF58CFF80C9F2281DB6EB -:150CCC00918E943ECEE946809780E173BA047D6A637DC3E9E326 -:150CE100FD30D41426ABD5A0BF066353F5B7AD57AB426111E732 -:150CF6002175793BD0A435CA01DD9101E36E51513FF72CF85916 -:150D0B00533FD0D6AB0F846AD4079A03EAAAD056276FA94F71C2 -:150D2000DA82A6E43B3E87AEF48FB786AD4E2F6F75EEA36584E2 -:150D3500837D8F64208743DE10F7CD8B56A7E5565C0F7627CD82 -:150D4A0071E811C84132E2404C200ECA9A85BA8E1AFB35425244 -:150D5F00980BCDECDF9F97C1AF71CF55D02E2C2EA660BF823D2D -:150D74006135190E61FC6476BEDEE1BEA7FD9C787F107F84E908 -:150D89005860EF2C9930495D2A9AA76D08DAB6C1624F81FD644F -:150D9E0072445B638C94A45D2168373E42BCEE7D285F5F65CC2D -:150DB300E4D7B03E3172F5C9FCF381CDF301E856321F28AE3A51 -:150DC80028771E688C4A5BD641CD07B107B58A72379C210E6DFD -:150DDD00D477415EF648712D0AAD1C4846132A3F977C1772DDE5 -:150DF200B1E4C7CDE4EA10BDF6B5FC7B8D3D5FFFDDFEA623C476 -:150E070037F149D60767196DF37D72BB73D787F76764B77176CD -:150E1C0012DFEDED4E9E9D62ED24C612B4E9B319F6CE0FCEC553 -:150E310060A795E28EC5592B49ACD55EA03DFBA77C1F408D2F19 -:150E4600C19925111ED61AB1FD22D431CC768DCC76686BC46913 -:150E5B00025948755C5BFE89B05F4C62F603E3079A805E15C03F -:150E70007F7E9F7C2F5BCFEDA2BE82166B17AC59900EF6BB59E8 -:150E85003D95F781473ED50706C49DFE70491F5072FB7DC6422E -:150E9A009DC136B6B08D2D6C630BDBD8689B72C8E56E9F99AF8B -:150EAF003DF1DD13D451C14A757F10CEF8BE3C6C2DC00E06535C -:150EC40005B03F02D8D1E09803AB42582DC056042711C6EE3D4A -:150ED900B87DDFFB18EC09763DFFF15CBBBEF730F18D7D8C764C -:150EEE006DB877BE7ACD579F7809FF2813FE1105BE17B615CA1F -:150F0300D922135F23C8E20159979490B511E67899AC4DF7DEFF -:150F1800CE1ACC57DEDE12F2960B795F0759976C9BEBCF06FAC8 -:150F2D004B095F8E5DCBFACA408FC8B5B97AC4804EF81AEAE194 -:150F4200BFF7767DE976F4E929A18F2CF4F9F956E2EB84DF675D -:150F5700E1BFF97F4127B5812A6A1365EFE620074AB029B701EC -:150F6C001CFB32E934357C0E6AA60AD659AEEA96A26EFA5B76F9 -:150F8100970E79676B6C88BD2B8E7D53DCF73CC76A5433FD0D60 -:150F9600A89D643847E33B55DC9401EF62EC9455F5C419EBC295 -:150FAB00479C3601BAD9858639057D89F7BD631F15CA33267057 -:150FC000DF83B68B244DBFCAF9118DF3433EC8CFDE5DC86F3932 -:150FD500E0553D71CADA0AFC3441837EC4F9C5043FE87BDDF609 -:150FEA0054843DCD3FE1EFB8AF3E440AC61789F15D62FCBDA29D -:150FFF00F11A31BE558C8F158D2F16E34D623CC1C63366D79E29 -:15101400FC793F0B3A5202FB37ECD5DEE52452707687BF81A5FC -:15102900B646E14C41EA923BF0AC5963EC5F87EFF53591D70ED8 -:15103E002C9DD53AC22F873A5DF7E92F4C3CF113B4D573BB2F35 -:1510530075045DF0CBAFFEF57584B7EEF84987FBFE7DFA8D6F83 -:151068009D40F893FFF0E30EC2BE871834E3FFFC179BFC0163E8 -:15107D0047B297F8269F24BE3972BAEE17827F59B87FCB380E23 -:15109200F9167388548D39197231C24AECC74EAE81B351FBEE40 -:1510A7002DE2DE07700F6C19D52A638F065F811671F66EE7672C -:1510BC003C1C73CE320C5644AF8EDFF7F1EF332E0FE8F683F8F2 -:1510D1001D01FB1640C47E8ADD2918BE51B6571056CB2419BE69 -:1510E6005F39CDEE52768B7B1784A9EA283B4BED71C18202D67F -:1510FB00E7823509D8DE99FCB707866B1CED4B26086954472D8C -:15111000370CBF436C2882554932692E84518A67BFD838550E10 -:151125008DEA2D3826F4C6EF6508BD9BD99D8AF91FDC58F453B2 -:15113A002F9B9FF345D18A7E649C4A07F09C0338ECFD3DE713EE -:15114F005647E93EA827B19EC2F3EE65F0B7441FE9C6F74ED3D0 -:15116400397FE1B66DACE2760DA74FE6E40CA74FD3FE2DE3DA2C -:151179006675DC72D37C79E98086FB33D28C15ECEFA3ECEE6226 -:15118E00AB80ED1132EE113206605F6732E27B2576864DE1DED8 -:1511A300CF6A05B6F78BB51C106B298B6F2998CDA06605DE16C5 -:1511B8007EFF9280338317CFA17866127A7845AB14B5176F64D1 -:1511CD000BEA546EDF93EC5E0EF76903F4C3332E3E3B30F2F086 -:1511E2005C58991BC6EAE794D509272B493C6F56381C6C66A124 -:1511F700DD6A33CCCE0143C8C160013B1AD89812E727389FC223 -:15120C009C5A03D60DD688B591717321D2A3A356297C52029F42 -:15122100E4F0DFE4F605183C5B7B9DCFF944FCBD20F4E4B19C55 -:1512360062758BE4E804CF57A514F3F7A03F3FFEF296FCB8034D -:15124B007BA9044C7E782ECCE386B9623AE7DF22A69C7875C78E -:15126000727F512C633B25C66E36C72831C7196BC4F68BF9B97C -:151275009590BB8DBBC902278FA04D5E747C0E9EEBA7E37AAC39 -:15128A00687CC1E594CE69A4CC1648B68998A71B7CAC06F7016D -:15129F0073733E27A17F605C38637DEE31F6ED1BA7C35A178D76 -:1512B400CE221A8E0DB80F7298510C037A2F38307F1E66948027 -:1512C900555617C250A7FD2E9D1D58BC04ACBCDA0D334CBB4EC1 -:1512DE0026E1D5C23EB08F60CEC0B8F483CF634D85DFE4B17ECD -:1512F3002015AD75BD4B225584BD3342FFF533FF1D311D3FAFDB -:151308003C84DF1BD87400BFB50BF35C568A8672DB34600CF7B2 -:15131D00176514F12C2D1717498AF91CF3E12ECC25D0C77907C1 -:1513320097A634461F7DC54F6829B8E2829B6EFC25A5E10AC018 -:151347007B9DEFDEEA788E75DB6BAB74137BF94BEBBAE0B20DCC -:15135C0067E4D1BE83504BB03C301FBBFD1669A19EB75A03F3CC -:1513710076E4FACCB40AD7D51679DED9AB793E2EB475613E2E11 -:15138600210BCCE1B2A44CD602ED85480F6ABE927628814F729C -:15139B00F885F2ED75F91DC6AF543D37BE49F5DCF82EAB9E1BB7 -:1513B000CBA404EC15DFDCF8F654CF8D65B90886F847DC73F32E -:1513C500EF3C2B79FD8531CEF706B469BD6BEF83D6D825BEDF9F -:1513DA0020AEBD50291A935D63FEA231AF6B6C49D158956B6C58 -:1513EF00B922F611E52D4A1493CAEA307BCFC4BF63A4F41A6BD3 -:1514040007E9F532BEE765581B34A1A82072F5889E30C635FCEE -:151419005676B13CA21F2B1FD78E854735AC55BE639CD3BC1730 -:15142E003FD0192E201F360E68CA5653AF81BC5CE97AFF8BDFE1 -:151443008FCAE638833F17AB0ACDB8D613DFFBFFD37DFC7B9AE7 -:1514580058EEDB1B80CFF0335F65F2D7CDCB92DFC4EF4EC4B7BF -:15146D003313ECBB277E5F3EC1BF8D080E50FEBD0C1538830C25 -:15148200A7D7F57E03DF9F3F2BF84CCEE17347011FFE7DCD0460 -:15149700FB7ECAE1630B3E5D820FC719345551A725A13D119479 -:1514AC00BA2B0E8DE8FEF02AFD353C9FC4EE6E0BC42A425745A7 -:1514C1007C5D8ADD139A85672FD8BF5E8BEBD433DA5719F3B4AB -:1514D600E33A292ABE8B033BBE097935297577A9A72C388AD66C -:1514EB00C8CA5A88EB03B42E7CB0ED30665CA5DFC46F5D37FF53 -:151500003B9CEB22BFB41AD45F5ACEFBE836F58015560F5BFEA9 -:15151500F408FDBFF6BE3E3A8AEBCAF355AB5A6A498DA816ADA6 -:15152A0046C2209588708447715A422648964C43182F78306934 -:15153F00639CAD12C26EDB644C1C26A3DD61E7704E58BB255AC4 -:1515540020E10729D548462638B4B064E30938322B123C47248E -:1515690062E275F02C61B48CC390C4269D19C626332456BC4A65 -:15157E0086CD38F4DEDFABAAEE9210FE9839B367FF58D5D1A9A8 -:15159300EA57EFE3BE7BEFBBEFDEF7EEBB657887B6D5087BF17D -:1515A800081FA63A83A941B22B5F3491CE945E0EDF6E779BEBA1 -:1515BD00BF3ED0EC2E5FA1FD996EDA75A02C9E5157FCDBF00DF9 -:1515D200AF6E8D4C2B5F4CE523EA336693FA8A5DBE77C6F2D17B -:1515E700E31818D5AD80254CEF6AD47623AC7673ACFB9A2CD1D0 -:1515FC00A6A93F37BD12FC228E7293F5B5C9B184594CF2CC8307 -:151611007DE9E8A0E98BF59AFED8A869EDDBB8F9F8A4CDC7F152 -:15162600297C9CE1DFB1214D71F16F51CCDB98E151EC1B61AFE5 -:15163B008478348FE466095BA45B7DABB6FA16196876F3735093 -:15165000ED364231F94E6BBFC1E0F0E51DF97BAC8FC45BA1DF9D -:15166500AF6E60F987CA929AA22E16B459053AC0F5491D31629D -:15167A00EA5123A26EE04A68756B1FE9A75864EF1B7F41737C57 -:15168F00777BEDF1DB6FF95B14BBFD285AA9BF3945A7743575DF -:1516A4008C67CB1C31B9ED0FE7E415FB9AE349AD9878DC5D3E9C -:1516B900AAF61A1BA87D8DE0D0D483F47FD56853AB8CED6A8D70 -:1516CE001157EB8D2EB5C930D45544BB477493FD595B754AEC79 -:1516E3009FB6F553FEA43A6A1C51B9D1F7EC515EC28EE97336A4 -:1516F8003DCB17BC759527367D92772E58CC776DAAE5BB9F6D89 -:15170D00E05D6FADE04F2F38CEB166F2B91FC0892426ECBAFDF3 -:15172200CF9EE2FED387F59EB7F6F262B677A91B2E3205F38BA3 -:15173700D455CD99B46807AF92587EB13B4D74A083F39BA4BF13 -:15174C0071217D43BA16EB3032FB606FDDF89E191DFCFD821912 -:15176100EA235E1B79279D5F953C6C88B1053FE0CB37DAD7F014 -:151776008388129F788B3A85AE7290F2BC1FCCFA9DF8A6FB9DCA -:15178B0010AF1E14B65E3B7C7A4CE13F4D63DF4B32A32F49FA86 -:1517A0006CD3104F596B5EA6DF3A5F31A744D87D9326DEAB6A39 -:1517B500027BA94167BC63FD5E8B55124FE0EC483B8FBBDA56CD -:1517CA0066F0C3F1C5A85D3127C44DEC57F6A9528B323AC0AF33 -:1517DF00D96D627F734A9BF4DE37ADCDE9FB071B5CED3357FB1F -:1517F400EA0CEDCBAEF6E7CFD07ED5C76C1FFE3589863077601A -:15180900010C3BE65830CCA7B6A6B7AF8CBE28DA526303A46BCC -:15181E000CB732A5D384EF8F4CB67188DA9D1F1B309E5EF06B13 -:15183300E1D331E9F6F371EDCFAC7D2AEB3F22E52774A9ECA464 -:15184800BE7EACB3D1B78E0B5D46B92FA995EC18E1511F8B60C6 -:15185D007C96EC18E4317A866F01F21B296F0B337E6D62EF18A4 -:15187200699E6969D4D712C77F24188AB5865929DFD939B88DCC -:15188700190F70F08FFA790234A4B5FACEEDA1F64EF292D096AF -:15189C00D6B93B8EF208B5118C5B3A33F2083F10E3707FF1B807 -:1518B10021F67738C13277473D27B9DDD6B177ADF0F3098696FE -:1518C600B576DCFB29FD3CE1E9B598E74ECFA5FF20CE4084AD8B -:1518DB00730562BF0D739DBD9F2CF6434331A9B94059AFA36E52 -:1518F00094654A3397A5C37AA7381BF0B258170EC2C732BA3C2A -:15190500B35621C717E9589F484C785A426F35F0D08A7B74362A -:15191A003E6286562CB6FD5AC4BA96B557611C3597624F3D3A72 -:15192F0018BF4DDDB4043693D88735068633FFCA603C4875F9B3 -:15194400F32BF52BE974E08DE57AD3E34F7A9A1C5A5DA0BEB02D -:15195900F0761BEEB69BC2EDB954A1CBA79337C21E5E6686ED09 -:15196E00F593E9F04346032FE883D59719FA30FE0D731DFA6039 -:151983003C175F29FA10113028D1B80EF80D35A70577C08F3B83 -:15199800F15EC92CCC25E37BF8E0EFD285428F540EC7C7976FC2 -:1519AD00AA1FA5BEADA2BE39EF77FCCE75D410FE24048BAFE8E2 -:1519C200A8E085B93B4EF00999C598B16838A00CEA993335F4F6 -:1519D7005B8D25E8FD31FE3EDEC37710FB414A3B6C06E386DFF9 -:1519EC006E7FA97D597EF71525048FB3FA041F233316FB9D6202 -:151A0100BF69D883FD6A137BBB57D3E950D6FF89C6CBBFB17C5F -:151A1600625F767D5894CF961DB6FF8DCCFFB4F5E2B6988F27FD -:151A2B0053DF3715E2733535305C1CDA4EF56CE1C154A5312B41 -:151A400095D3B22AB5D80884DA88DE63A2CE10CDC92CFAFBFC5E -:151A55003519FBF21A87AF8EFCFA2384C752BE16FABD021FF809 -:151A6A00A8F0B5EA8DD7697F1EA96DBE47F5349FF75EE1A1C844 -:151A7F002797826E1BD2E9C249C9B193BA8D3CD02D2AEF32DA11 -:151A9400E013B89683D6C85743F9CEDAF9C2A91554EF6A739572 -:151AA900C573C38286F6BD26760FEF16FB8295246F5682A68619 -:151ABE0045C3A9F70E09EB8657787A391C7107881F3FAD4DE607 -:151AD30058F517F101FD41755663B13AABF6A5CA924673E18293 -:151AE800C657F18EE018BC9E2E5CA84A8D024E85F4B072A3D58F -:151AFD00C7FAF9E51FA7F333E7F1C60F5B7B8DE387CD4365D585 -:151B12001AF58C63BFABD7AE9FCA37A32E8DEA72F23AF9B6524A -:151B27009E7D6B06B45D34C6D0875B49E64D6F6BFB8FAD3D8A0C -:151B3C00522AFFAA64C185737B5D180BE37163BE7F500FFE6E98 -:151B5100BF8101BE3AF5A2619DD34A3333F282D647F5CEF3D710 -:151B6600E8A42B97C0D7BC865DE189C837DB70F62E89B1BB66B3 -:151B7B00B16E12AD72D990EE25FEC7DE506364A89129CF59B491 -:151B9000B1F5378C6159F0994A70455A05FCCA73E69B3F4AE70C -:151BA5001FF558FD5C49B46E9A81A6B751DBD3FB34F8A3B4D82E -:151BBA0013443D5BEDF2F36252A3779C6440740FF7F8137A2424 -:151BCF00B59F375D4AE73B6573699CE02CDDA88D779CE714B2F2 -:151BE40080F0E0E4E9A777E2D9788AC77F98B6CE3F529E37DF4D -:151BF9009F8A7BF0E04CB012FE4B4A53ED46FD050BE783D3CA28 -:151C0E008D02FFE07371566D0F77708D3371AB530326C73E7BDE -:151C2300785ABF5957A6DF472F5AFD06ED515F1BD55763D34CAD -:151C3800F0E6A0C59BF04B97D6FCBE1EA5F7B73AFC67D3C2C2FA -:151C4D0063B60EEDA2056B1BF1C4C8BF583C31CF5FAF8706A432 -:151C6200468737B662BC5BE73B6DDE209D3F32A42D64279AC1E8 -:151C770017C18661C10F667CA1E6EB7E519769AE5C68F381E5DB -:151C8C00F73A95EEA493FA42CA61E2F9765E447C116CAFD595EC -:151CA100376C7C3BE3C15506F6D44CF8BE1DE39DF203E737B4A5 -:151CB60043E3E928D5E9F8D3E4BA78631BF186FAA6C51B12E1DB -:151CCB0057B67963EDDF5AF8157B568493CBBFCDD20FF5CD8A7C -:151CE0006ED1B59F7CA99E649C599D5A6356A5569824E74C9214 -:151CF50083C60CFB4DE21C33F4143FD901C2276E063F6FD2937B -:151D0A00785E51B7DE06BF4CD2DFA09749F9033AF6B5BAEC73CC -:151D1F000BF02D7B50F8330D0B5B4AF877E34C34D94F87CA4E3B -:151D34006ACC1812BEDE4AB2D384BDBB2A794AE877F1E410782A -:151D4900728EA2769AABD453A641F712E388FEAA6ABD67954398 -:151D5E00FCF24DF43FD8438150B4750FE66FA58A17939CAF263F -:151D73003BE676F8E23B7633D96915DA55BD27B2BF0DF8F35FD4 -:151D8800C8DACDADEA7DE6DB3F93EE94957BF52A7505AF225DD7 -:151D9D00FE92EA6D0ED2FD5BF04514E36C0F2F3D9FCE7FAD5214 -:151DB2006E249BDC207BD698C78EDD15211B50B6694D76AC01A8 -:151DC70059D9E44A433E25146EA53ACD2ED5DFECF8589692BDD0 -:151DDC009BC72C3D0DBF8F52DDBB95A7DAA08F55CF618580CB48 -:151DF1006D67BA6DCCE80FAD71D029F257F36BC5AC9029EF99AF -:151E0600412A0399E186C9E2BF7A7E3BCD0B800F7004D5970D68 -:151E1B00F4218F781FEBE76C7C31749E6068C5A774F41D7A90B7 -:151E3000F774834E6085AAA82E21038C1E1E559FE1AFCE26DABE -:151E45002BC46754DE6907766090F41F4A33DD6DDE934E8B36D0 -:151E5A00855EA51C364748472B8FD9B22C6AC939D4D9361BEBFD -:151E6F00F6614A3B2CE0F2B2BD7A0FE08AEE3121A71CBA396BC1 -:151E84001ED13740BBF704ED707E5C55498F573A877DEA1DA687 -:151E99007705E940D1BDA26EE8F5D0E9FDEAB366CD75A929AB9C -:151EAE00CF583470F0EDA6C360C0F2BFBCD97B1E60856E7A0042 -:151EC3009EB1BFA139D2A117E495526526D6701D7AD4E49355C5 -:151ED800774DE7D7A87D9E2F9E7AC72C095D6CCD49922D7DFE54 -:151EED000A8D8D2FF00AED4FF425B16FF37D9D27DAC43E90ED91 -:151F0200971EA6BBB087B08608C28CC1C77DD80C8BB3DCDF30DF -:151F1700E684CE50BB3F249952DAEA8B3D493AED72CC2B66C792 -:151F2C00BD0F918E7BBFD171EFBD7A774A024E857E9B87392E76 -:151F41001CB5F5DB2ECB2F8FC66CCCF6B31F16F76ADB0638627B -:151F56008CDC073B2B4265B6087D3A2D7C44525C444EC819E394 -:151F6B00E1582D9F9DCC69093CBB9E074EB7E852F2040F40BFA2 -:151F8000879E7C1F7CD25F163EB87DEC9B1ACABD4FCA53DF677C -:151F9500BF69EDA7517DFBD97734B6ED1847F4903EF66D0DBA40 -:151FAA0018E4771F7B4D832F2DE089920E87FC80E55689059E76 -:151FBF00227915185BA9DF4DFDF12B8FE8B2FA9C81BE3A7E50F6 -:151FD4002C7A9FD931EB5EE1039C4F3031638DD9C70632FE501A -:151FE90028CFA2CF99AF125FFACE8DE86CA4D384FD04FA0FDB39 -:151FFE007BCC68ABE8524AEFCD7941E8F56BB1AE3C72CC1C63DA -:15201300225F1CFA3CFCE2B0B78867D80758AF213917C7BC7364 -:15202800ADE27073B9EA69F49D233DBCFE18A7726DED852B5BE4 -:15203D00A05F930D5A124DBD635468DFD3674BCF0B9DD8E33F85 -:15205200A1236F09FC1BEA87903F7270672FCD457DC236050FD3 -:15206700887764234E923CF49D3BA8CF3BF79CCE2607054C382D -:15207C00EF437C2564FC1FC6D6365978F986E13BFD72960F9219 -:15209100DE0C1F84C007842787F6BEC82ABDABCD63D111F4336D -:1520A600BA4D879E4FB31735879E2CFA0D73103ABACD2B53F1A0 -:1520BB0067E1EDABAFFF9186337253717644E0ACA44DF848DBB0 -:1520D000381B06CE026CFC581CBEDAD79EBC7789A80FB6CCA84C -:1520E5008533165D346CFD77F65B733B1B9E3B7A42E047AC7FA6 -:1520FA0019C7CC02E8C5935FE16F104B127F9414A53CCDC0ED45 -:15210F00E39E2796FE69CA736728E66976F30978C373E91DDDF8 -:1521240027BDA077AB599C04A78C0DCBF6035D2D7EB6C60AF085 -:1521390094E1F5E9769FBDEF6EAAEBEFF49DBBAAC367D9EAA701 -:15214E00C1710644E83FE1301778D9F669AB7FCA401C6BEB2D2E -:15216300EA034BB0FFE1659D7A70C75745FFD8E6E778EFD81756 -:15217800493E7CD174D93BFDC2D6C19E36E18245474CA78E203C -:15218D00D951852E5C8C117F2797AF6FBA7EDDC2C76FCA9FA8EE -:1521A200DD40FA96859FBFD7EBA4273F003FDF27FC3CFFEF82DF -:1521B7009F97809F7577E98E6D9E6661CE267F6EE1836CE6DE14 -:1521CC0038EC050B1F0BD8223DF8FE62818F9C68A95E1E2F6F3A -:1521E100BE45CC71FB782CF5AEB9ED97B0974B5BE9D9807CB1CE -:1521F600EC1FC21BFBE32C0F2A583310FF84BB0117EE5E369D99 -:15220B00F6A6E3AE9770B78D70F77736EE2E12EED07EC8D5FE2D -:15222000B55F586D4F6DF7056D5FFE505666DC5C56CC71C98A24 -:15223500A64C3EEBEC74667C2CC4BAEEBAE7333244D8E7E3545F -:15224A002E3EA44D2EF70AD8204B204722A4E3418E604D0A67B3 -:15225F002050EEE9944B9EE4BCA461FF0FE736F05EBCB3E449EC -:15227400896FDD4BFA016A5BC8946D4362CC627D0A7D2E76F53C -:1522890059A63EBB65CD74FFA551F8E6285C2FBA64E801D20F34 -:15229E00FA9232F547354EDE27F4CA906B8F8C063EE99034B72D -:1522B3000357276DFE4079DF42962F8FEFD495F33BB5A9FEFC1E -:1522C80086B0357697F56B42B7945917703526D65C86E20BB10B -:1522DD00A743632327752C2EA74EC47D7ED27308BF05F1A1C669 -:1522F200E2A841F301E73D29B94556137CAEF217382B182AC2CA -:1523070019BA0C4C5161776CC799BBF2D5ADD0B1587958D821CF -:15231C00D095271EB07C67AFE15EBE8CE6DDDF3F207CF7C2EA17 -:15233100F1D40333FB731B87B07ED12FD62F76931E5C34D629A3 -:15234600D609D8B89C301A8E58B04787E245F06FB4D33DB1A12D -:15235B00B8D2302CFAD7C3F66A384FE85B47F3883104BD08739A -:152370008C41735BA67FC591C146A7ACB58F9B79BE019E6B8741 -:15238500B2EB31BBCB86B5A2B80D8F711378285D215B1AB0B83F -:15239A00DB94ACFD988ECC5A8DBD3F8FBD68567ED2DAF7B4FD65 -:1523AF00110977167EACB5F4A978543A0F4CF12FA27110BF1F74 -:1523C4007D305A31164897E928B77CA2E21D94DE1B4D6ABE22CE -:1523D9004B2F4B114C5772E258F32AC4FBE87ACB96C1DAC1428D -:1523EE00DB8F6AB5E09123F1FBE89D03BB809BF26BEBC51EA3A5 -:15240300D8075C6BE7D35DF956A45EE8A0FF38D28DF558CFF983 -:15241800761CF31EFA82FD4FC0D1BB73480B8ED9F050BAD3EE10 -:15242D0016BBBE9E19DAED77B5BBD5CEF78C2BDF4A6A17F99220 -:15244200AE7C6D76BE8119E05B99FA661C67108E0818BF1BC70A -:152457001ED815824521F89E16BC734CF8CDF47E8F6065D6BA3B -:15246C00E01517ACDBECBA5F9C01D661170CDBED7C2FCF00EB9F -:152481004957BE1D76BE573E0056D0D881F5EA87C07AD5056B9E -:15249600CAAEBBFDFE1B61EDBA3F0BC3653B5FF7FD37A1E7FD24 -:1524AB00597A5EBE093D2FBBDABDE2D0738676FB5DED5E75E845 -:1524C000799376B76CC0F81A050E8C0977BBE8AFBD7E8F74875A -:1524D500E71FA7FCFBD95086E737782D9E7F5FB2783EB621DB46 -:1524EA0076D46BB5FDF0860F681BFBA576BB4E7B93AE7E6EB0F7 -:1524FF00EBF8E2CC751818B38E6FCEB5E9328FE4CBE5C1ACBCF8 -:1525140013E359ACCD22E69421FC099832624057F1F93BF5DD6E -:152529006586A6D0FCA0AC3DA597F213FA3E9A12DC32E809EAA9 -:15253E00D74CB2C729179286B4FDA437825F2CFFC7BD644B24A5 -:152553003BE0EFBD52D4959D1BEAA82E0FCD0B19B94A7A896F04 -:15256800DD9090A9429E3AF3451CF27448C853650DC14F725439 -:15257D00723D4F9D8FB0DFDBAF4965869EC61A18F6DAADB37498 -:15259200F6DC346CB56FD8F234DA678A35D5F121C3EACBA0069B -:1525A7007F17EC0B189897C85E99ABBCA2FB48E7C6DC34E37C24 -:1525BC0032945D0FC73A1CF6944270D7856FBEFD9BE6F339D379 -:1525D100D7C2AD75DCA3864CF348A0419C756301E917FA933497 -:1525E600B72D10BAC911331264D1D7688EF6150D0A9F0E2B1601 -:1525FB0058B5D807DA5DA66AAC7E2F6F13FB0B3D64EF579AE254 -:152610004CDCFFEDFFC3BD1C30B36DEFF238D159C0EE7ABF99F3 -:15262500F4B6E5F4FECBEC1F9722C609FAB0ABEC88735E5915B9 -:15263A007D237D48F44321BBE2E3FE0FF4F29215EFEAD9B4A1AD -:15264F00E175B1F412A7AD0ACDB2D53F4A5BF1E48D7535C6BE43 -:152664002BEA8A7E40F918952B5D33B5DCEDB18796587433CC8C -:15267900D5A09B5D2E4C79FDD3F2D6C52AECBC2A17FB43365DAB -:15268E006591AFC75C3061C77B237CE26C5D5D2CAF51ECBDC060 -:1526A3007F53E44F7092F13109F989A7113746B6E2C319880F2E -:1526B80027CE3F132F89B399E383A67B3FA9F5886B3F087BA603 -:1526CD00DB388F603F272A6C1B71BE5251E0FF613FAB3807990B -:1526E200DD0FEA75955F18931B9D3D21D421AFE17A8F589B1E44 -:1526F7001C9E74EDA33AECEF63A3F96FC977E57CD9F39EF47519 -:15270C00E951E9335250BAC6FE8EFD35FB2E7B990DB1AF319314 -:1527210075B30EB683FD2929DA5F628FB147D9436C23D3D8036A -:152736006C3DFB1CBB97FD015BCDEE66ABD84AB6822D67CDACF0 -:15274B008935B206B68C2D6577B07AB684D5B15A16669F66B73C -:15276000B34FB11ABA7E8FDDC616D355CD3E49D7AD6C115D55E8 -:15277500747D82AE857455D2A5D25521AE72BA16886BBEB86E5A -:15278A0011D73CFB2A1357A97DCDCD5C21FB2AC95C41D735C7EC -:15279F0075154FB902D32EE5866BF60D57D18CD7AC9B5EFE0F7A -:1527B400BC0A3FF42AF8C857FE875E3E26CE181FB7D6B754E111 -:1527C9008B4EBA3DE9F151A61E475A15A519F673353D8FDBCFB4 -:1527DE0035F4AC48F48C35BEF26ACA1FE1065BCDC7C95E5024A0 -:1527F3008D2BEAC2E34A8CFE93F49F5A785C8C2BB11E522DF667 -:15280800DB55D54ECBB7D3244A8BD96905769A87D292765AA167 -:15281D009D964369A88FDA14B02B2C1AB6EB825F60D8AE037E98 -:152832008061BB2CFCFEC254262AC16651F9F04B5828BD8D33C0 -:1528470075E1016F6899A8272AE2EED41AC549A9CE776631CD9E -:15285C006B95077C671A843C887FC0BBE10F78073F38BC2BA2B2 -:1528710077946E225D7EBD41176D8F2F361DDC3938473FC66D43 -:15288600189561411343153E7661037E200CFD1465C2ADC02FED -:15289B0070A878ACFCA96FDBEF99CA9BD485A661D7C35EB1D235 -:1528B000A3942F8A754A65A129FBC8A6BFC93D2A65F38CBB9EA0 -:1528C500154FF6D9B0D345FD63E9D988ED64F947AA7C42ACE7CD -:1528DA00A8563C48B12EAA8A5891B9F6B3F043F310AF617D2323 -:1528EF00BC8C477FE16109CF32332FA4B6CA91067DA2B241C487 -:15290400A998F8AEF70EE004BFE12B3046E5FC6C19CEE49A35C6 -:15291900840B529EB84FAD33F3D86D04FB6DA63714691D9F2168 -:15292E004D91AC34A6BE67C2BEAACE99AE9FA98648037FD3FD64 -:152943004155AA9389664ABCBD4E86FF8C5209F9ED634A2D354B -:15295800B9CCA81171196A4DA6002E55C012F594521B8B0DB4AE -:15296D002F9F29D595F8E27ADC7DF1C575B847D1D7F1B090F94B -:15298200C82BF818F29DF489B81813CB7844F8D946901E4BCFE8 -:152997005E4D79A2464CAC776BF659FC188F88B5932DD699FCEB -:1529AC00709B75469E6DB7E3F076D9677810F764360195205DD9 -:1529C1002461182CA141FFC1EFF796CB77B0F10EC3AFCA752C4C -:1529D600BAD39844BFC655C35A07B2CE2DD7A472EA449D549F2D -:1529EB00386783E768AFD15516D72431FFF59A9973E3D1FFDE24 -:152A00008FFECD579F3664F575D21913464495EF78E9A197A820 -:152A1500FED7FA918EB41A4A3B302DAD94D2764D4BDBB69CE0E0 -:152A2A0052DEEEFFF243EFD49262C6FDEA25633B3BC3E7AF7812 -:152A3F00476FA9F869EDD7965DB17DA5E362BD6D41FC027C739B -:152A5400845EB160C5395D4E0E1A9EF223ADAAFAAD7E664C9A2E -:152A6900BEAE5EA193637EF68DF52D0D618EA47698F10DF3161F -:152A7E00E91D1D7828603FAD1D7EE8974B0906A2E92582EB9C07 -:152A930021F17DFAD736BDCD6F89D05CACEC330967F1EBCB57B1 -:152AA800D5FABAA9BDE8CE617624176BE5C33E1F7483DD077C9B -:152ABD00ABDFA1F4FD07ACDF2FD8BFBF7DE00CCDB7C9EBD3C29B -:152AD20060477FD89FF09C3180B7ED6C8CC7BF935BF7C413B97E -:152AE70075581F3830FE356DDEF9FD5ACEB937F4BBD985DA799A -:152AFC0063A774C41685FE62AD2F8E8BBE96287FAE4F3E7CC918 -:152B11009C27BD46EF2F98BEF8B1A5D88342DD130F9F337CC974 -:152B2600DCBA912773EF10671887451C98E3090FD90CCA090325 -:152B3B007DF9EDA1CEFAD069AA5BF9078EFE28803BFABD611FD5 -:152B5000620529BB8F2B02FEEF1F7F9BC66081BAB70B6BB57987 -:152B65006A67BC27CE3589F49389CA1F1AD05192A4777CD58762 -:152B7A00F83ABC6BA2F2D726E5DDF34BB5E68E28E5DF115B5586 -:152B8F0007BB4A8C2DE59821279F2519E9AD8B8D1DAD63C60920 -:152BA4006302BC47EF317ED653BA9C3C46FCD3297C13ABEDD81E -:152BB9006D62AC197BC53E47B5186706F725F7D2388B73996858 -:152BCE00AB305E8FBB8FF13ADC113FCA97ECA33AC68C36EC2BC0 -:152BE300261386E4231C85C74CFC061F627C9CF92EDE0D923EE6 -:152BF800493A7F3261DE16E7227D8CD2F11BFBC81395DCF0C751 -:152C0D00E4BA00E96B1827139583E63CB22746AF7BEF205C9AE6 -:152C220067DE4FFB1482A789DAB8807115EEE71324839BA85E80 -:152C3700963C68BE91F1E7EE32FC8481300177A193D733E374C9 -:152C4C00BFF0632179D61D39A7FDE51772EBFA59A7D61FEFD3ED -:152C61007E5925DFD14FF6DADC44AFDEB3936B3D0D17C55EB4FD -:152C7600927ABAFFB645E59F11BA5B383E8C9824810509C4C806 -:152C8B0032E627459FAC182F3EE8A37111C3A55AC6DEFBDB8611 -:152CA000B41AF18A5F357BC6B806FF415FF22095DB0D3C8B58F6 -:152CB50057A5A9A7CDF9A9AF9BD5849BF9D4D7642EF634778BAF -:152CCA00F159ADEE16BEF1A20E85236E9FAF54FDAA217CF63673 -:152CDF00714EE50CC806393662D4A7BE437977D358E9A579EE05 -:152CF400A08E3A3D6787442CE5B6BF60AC0CF62FD980885722D7 -:152D0900AFDBA5539F0E78D6EDD3B7E4B1A9E3631CB16EBAF850 -:152D1E0057DE92BFFFB424E82262000553F033EA177E46C029AE -:152D3300E2FE045942AC5F8A78669FB77CBF906E8EF56AA5A9CF -:152D48005DFDE1D4F3496505D77DA403E7ACE5BAAC72D3EF4371 -:152D5D008CB783BC3AD2B714EBBE25EDC43FEA102F8DE3F709B1 -:152D72003364FF464C0D4BEE937D9AF2D7210DEBC2BE8CFF7CCB -:152D8700BF8881E3016EC67B8D2A4107EB8CA2447637CEE55AC6 -:152D9C006713AD3DBD37A92E896000ED413FA9EB981E5AD069C0 -:152DB100EE8F58E7DA104346FA032EF47445D0D1107E6A8AE003 -:152DC600EBE78E5F1636449788B723A748868D4F0A3C07C84604 -:152DDB00F60B1F837E116FC72362565BBE6BCC78CA443C46C088 -:152DF00029A5BEC2AB539FA875CB76C874D04FC8F58C4C27F975 -:152E0500BE25B72598FA8D29E22C1E07FFED32F7FC2E5D520F81 -:152E1A003F3B9B06C07130B5CFF0F05E3DD068C5BCF3906C4040 -:152E2F00DC763FEB5DE2271E99C77A6B41BFAD2EDEDC6AD1C9B0 -:152E4400D88E7BF99556C15B4437FC96C5B982B888E3047A8367 -:152E5900BE22361FC632D1733A2D6551D6A2C387E1F623D3083F -:152E6E003470E3DEA1C7C7A04181A041BF1DE7284B8B0FA58182 -:152E83006B6E75F03FF62DC4A72C0ABB69511CFB64ADB04BA3BE -:152E9800EDC3D79EFCE452259647F368BB01DB13B28A7F25B730 -:152EAD00EEE2BF38F2C79217A544ABE205DC94A84FA01DFA68E6 -:152EC200C53AB2DA407BA83B130F23A31F59F42873D1628780A9 -:152ED700A7CB3AB740EF11574B49ED33253521F808BF35D77979 -:152EEC00E0A0AB7CF0F399F8E022AE783F1B12FB163ED0BC7DCA -:152F010048F3AB5E218B15F007C99EB288257B32E38EFA2C6D48 -:152F1600C1FC4BF735E7040E689C06FB7F6BF53735EDB313D89E -:152F2B00A3290D75B596D1DCAFB2E4F1301B3B1E61A9E3D72E7F -:152F4000A4F3E93E4CBF87297D58B3CBDF2CFF9137A7E6AFB6EC -:152F5500F3631E1FFD8DDBFF14F32C8BBACB8AB8C362CF8D1B4F -:152F6A00D79F94EF6882BF8B3A1AFFEA99535A2E9917B2DADB5D -:152F7F0085B84805EAAB5D38FF68F9838F8933508A3A42764A45 -:152F9400C2F0A716D5C97F93CE071ECE5E4AE74FAFD30D9B3808 -:152FA9003B48659BD4678CC99F71D2890C1173C9E2C33F330520 -:152FBE00EF5AB19D267A483FAC233DE8E3F0E6C4CF7A8D84A7CE -:152FD300CB6047E496899F7133E1E9379BD41EF337D7313EE251 -:152FE800B62DD26E5E86EE13361CBDD48AEB6E1C34A0034B3494 -:152FFD006E003BFD3677FC17D2FBC25113FAAE83B39387B2F8C4 -:153012006EFD7516BFF3110B22544A7A79BB7196E0DECE629CE6 -:15302700A5C2FDD88FF2A7AA8DDCD3B5FAB7E28B6B3B972D9B72 -:15303C00A22BE631F8892E13FA539EF428C98F35869A8AF63372 -:15305100E557A6CF57A9C3D7D4D213172E2D205BC453AE8936F5 -:15306600105F167AB6B7BD562F8AD4D617509B472BEE5C3A3F3C -:15307B00A5D25C576D94A6C286E46FD43B9FADE5DE31B2FBC612 -:153090009799CE1E37621B0A5D5D6927FDB1AA56C65E6AF49146 -:1530A50061663C7CC0D785F301FF49DC53CB3D7764D7834AED9C -:1530BA00B882D5B69C0A939C5AA6414F9FA74A61118F54C869C1 -:1530CF00B241A83FB22B2695357F3E3F5C3676502FB3D7338382 -:1530E400340F63BE65E3AF9801E9B25E5759F419567EA695B16D -:1530F9002B5C61FFB03428BDABEF53BD75D005C32413E74B43AF -:15310E007A49E864AB2FF20F4BE6D3DD73AE4FF8AD601D6FEEF2 -:153123000AC4C23B69FBC7C4F9159AD78BE327F4C07CD24B94E8 -:153138008EE18FFA3F97746FDCFB97E7D517C7F2C82679C5604B -:15314D00A9E78FBF41E3687EEA6903B24AC411A0FE07683EBE55 -:153162005AD6BB2442BA0CE69B07BC86D05F7EFC0CAF75749694 -:15317700ABBF4BDF546719FEDFE99BEA2CCB6EA6B344DFE129A5 -:15318C00E7FC27640CE1CA57F985A505620F0F783BB53478FAFC -:1531A1001754FF29BE9E70B77F99E19CA917780AC54732780A6C -:1531B600A516D5FAAE604FB963587EFD14E473685E6A562DFD13 -:1531CB00368A5325E25E905A20EE06C9F199FA4FF369BD67F568 -:1531E000BBFAE56B691FF080BED6D87D9F78DFEAFBFC19FA8E7C -:1531F50032C3D73E7EFF1710DD4B2147A33DFD6DBF9966BF5070 -:15320A001FC55AAA8B9E6BDD79A27DC63DAC9F6F201D3DF78709 -:15321F00BD4B54F5345920295E2C91DEA55C3083365FCA381F10 -:15323400A4FCC4DCCE2EF280745587DCBB65C5BB7A78EC3BF5FD -:15324900B73458F8BC85BD63F975517BB7C05E095F143805CF3D -:15325E00C1BF133EA2E5296F9D9367EEE94B19BCCFA5B28ADA53 -:15327300DE1F2F4CB420EF56ECE54447FA117B31E7CC29BC3BCF -:15328800E0397B4A37D26427D1FB6AF50B4B71073C93CBF3EE4B -:15329D00D8F6D04F491FFC89E1535F3E50A3FEC85C3669F73195 -:1532B200BA6BD88FF8AAC9F5DC7A86ADB46BF8CA72ABFC49C28D -:1532C7005BD0AEEBDAF2C796DECE5EA813B68E2B2FCAA20E77B1 -:1532DC00B9B394A7E3A90B5A58FD8F4B908EF99154E5CFE1F98C -:1532F10019CC91D15D49E89F285B803D65C225BE1F33BFE7B062 -:15330600C0EB3C957402BBFEA229CF736B3DD6737F813ABB967E -:15331B00EE86A7C8D2CB51BFE7EB7B74A1037C876405E9576696 -:15333000E4794D8924F4529A3B443C16C53A83F361FF34A7745C -:15334500495DEB75F8193265A7987794129A3FEC7947CC41785F -:15335A00F731E61F67EEB1E7A119E71FCC3D9883EAC599FBCC51 -:15336F005CC3D5316BAEB1DA5159A9FA2B730E74099A977C6AF3 -:15338400B7B9E5BDB4AF20C9BB0A08EEFA48A2CEB1FF4A691EE8 -:15339900439ED5EF39F4EE349AEA2CBB716254BC37F03E4CF834 -:1533AE00417996BC6C486557881F39D98D5D3C37998817533BB2 -:1533C3004A72A41F632E27758AA34EF01A78AE5AFDD901F0D4A9 -:1533D800C5F71DFDCC8699607DA3E7591AC3EDC6D65F58F3BB94 -:1533ED005897A5B6467F951D5F8190E5EFE1B3CF1924432C9F18 -:1534020074CFFC2B01EB77DCCBF23748AC707B0ECBC77986F8A2 -:15341700D8D46F3B4DFC2D4D4C1711129DBA46FF6DF46FD0FFC6 -:15342C0030FD8FD3FF04FD2B3FA2F73FB2F28ABD83A0EAC46896 -:15344100E467C7F0E1884A1DB1F06F555B97B0FA5F755EA47C51 -:1534560015FDCF100EAE926CBE6AB2FA761EFB4B7B9DAD7E8045 -:15346B0027E9B947F5B62834AEC7DE465F470DC4BC14E73EEA46 -:15348000BB39DAA977F43BCA1FA7FCB7B2BDCDE299DA539A5FFA -:15349500340CF4433961C0BF36B4E298CE627B39DEA3EC7EF867 -:1534AA0063217634D5592CEA7C45B429621B7D601DC77851E412 -:1534BF005433F2A3CDB9A11BFDA9597082F7B2ECFEADF0DF0892 -:1534D40066CFECBF799A1AA43993D59FE216AEE1DB316CF5B34B -:1534E9007E888B36C73B0DAC81948C1DD3156AB7247E54878F79 -:1534FE009EAC4E4DC31A888FD202E35D7ACF84A7C5FDCE47EF92 -:1535130042CA7FD3FD64878E601FD4D97725F8FCCC155F697AF0 -:153528000CA57FE37B9C131A0922364775EB55BA7B953A1D3188 -:15353D0072FDB14A3397CA5C0BB142F9BFB61B56BC617917D2C3 -:153552000629CD1F1BA03967917E71B9749757E9D0C7290DF1AC -:153567004BBB903F5669E07C8D8A73A29426C706CC61A4D3B355 -:15357C00417C7B9164217CFC6BE63271C68307B23609CE1C5FF6 -:15359100F558F1B2B6219DE007C079471077F45DAE9C7F464330 -:1535A6003F4AE11BA48C709FFF98BE8E6CB339AADC92973A2800 -:1535BB00E2B610FCC5A114F2EFED90BA7B853F27CE18DE966C99 -:1535D0005AA2F82D5F0BC466982DEA1C3AE0A33C3E2B4FB034D1 -:1535E500292F918EDC589645F304DE0C9AF7AAE658DF8082FF11 -:1535FA00BDC3E7E373E0979EC8F887C9EAA4D95A427822B92460 -:15360F00137EA2F4CC66F0E72F25BC5BDF3CF96B737BEA6F0F36 -:15362400C897DAF5CBC553EBC7F744DAECFABDA1B156CA6B50E9 -:15363900DE7ED4B58764E75A196B3AED343E2254FF6AEE53F13D -:15364E001C6D853FB7447A2EE9C2A65FD5CDB504838C33722494 -:15366300A7F17D95F96A3B87DCDC537646C37AECAAD43F13CFF4 -:15367800FEC05C4DF724F1C25ABAAF4E7DA61FB410FEE76AEDB5 -:15368D00011FD5514FF59706587E581DE0169C5FE8079C388F73 -:1536A200BD92F475D8309EF258EB9EB2360DF23E42EDC4A82EF4 -:1536B700CA773C4AF7CDF41FA1FA733167184D7C436AB919A3B7 -:1536CC0076A2A9FDFD38F3B09ADA89AA3D070E521E8DDA3AAA9F -:1536E100D8676C4987403B84C0923D6549AD551D306304D7662A -:1536F600AA7F82F07335C00A7D54E632DD714E9EF8CFBC46CFF7 -:15370B00ABA88E8900CE1924F8167A7E35007E575BDFA4FB6AE1 -:153720004A93296D989EFD418B46D371ECA697F7525CDF4C7926 -:153735008B55B939C745CFB03A48B8867F31F68427699C0F9A63 -:15374A008A4A73DA349A875F9B2AAFE12FA284734806776564EA -:15375F00301C123057DF4DD38107E71CB78D7051CE386594ECF6 -:1537740018B4E4DCB663960C8AEE35E0D33217320A6B58888D3C -:1537890019957765DADD3669CBEF1E9249581B3C684A65713D24 -:15379E00E37F4678A0692F9FE62E23389BE5E3AC06D9408DFDF8 -:1537B30012CB273E32A89F8D7E1AC705EA82CFACCA63F9F3E96C -:1537C80019DF929195DDFA28F169BFC20ABFCCAA1A494008FC7C -:1537DD003E42CF09C5C26B39AB6A8EDA721FB240C04675602E4B -:1537F20088501E12E685CBE8AE282FEA997874341F5FA8686FF7 -:1538070084CFA788BD46F7ABCBBDCD0AE5DB5A7CE31872C60954 -:15381C00F6CC300E2798F50D3C278F9FF860A7FD9DBA72D5DBD0 -:153831005C4DF5E4975F213A1D9A820B85FA73167CA3DC26CE74 -:15384600D0EC8AE13B033DC613915ED1FFFC4FD3FC46F800FFDC -:15385B002D25B4416F7FB508E30EFD7AD1C01CD1C83A455EA932 -:153870002CAC77E663AD63C0AC72FAA5741B32E916D5E0BD40AC -:1538850017740503FE7E0AD581323EF5457AFF2B33BFC82AC7C6 -:15389A0094174DE0783BE5CF75CD5B6AD1D4F59B6B45AC3048CA -:1538AF0079268AC0F35546428C936A314EE0DF0499FBE6F5749D -:1538C4003EFC750AE289466FB45A57D54AE3CA72A97994CAD023 -:1538D900382EF4BAEA2FB6CFD665ED55D598781B01B576EAA8ED -:1538EE005B39FF7B22D6307CB5B09624931C95A9BE2292F7E8B6 -:15390300C7C44303F50FD2337CAD64711EC8D603E0E3F536F634 -:15391800F82CF8E5D810C9A4170D712EDDD255D3C53407E3FBCC -:15392D0055B2FA8C69CB9300BE0D09F926C33FC2FEFEC424D5C1 -:15394200F3E318F1606CC85E334EA7FF6A6CB0D14FBF713687E5 -:1539570045DBF9F642969F5B4934B4EBFE2DF5DDE90BD67050D7 -:15396C008785AB230257F0FB0DB1458D4E7F0AA80F93158B9A3D -:1539810071CE7372162BACB8981D3F326414D96517C986FC2802 -:15399600FDC4FE9B809FF409C0E21D233B3B3A4A750D4057248D -:1539AB003C7467FC45BC946FB480E5DFA30276AB6F778D250892 -:1539C000B735A60337F611FFC7B19F1CC5FA83A82F84B58C55BA -:1539D50007A03FE3BD903D36BEEAA7ED4F59E36515B7F15B828E -:1539EA00FD0F3FE5298EC9CD9B73B26347C9AFC1B7BB047ED1E3 -:1539FF00D6BCB141D2A306B1A79816E71AE9AF3CF242E3453F3E -:153A140070F373DD194F23F6F95EE80781F1A7F4C0F9255AB02E -:153A2900BD419F97929A049F19DD7C07CDEFBE50360E0960AEE7 -:153A3E00639F6A862E3096EFD0CDEAFB6FD177AA0BF97136C947 -:153A53001FB3E28A20CDDBB448C46C9745DC120BA6BF2298E058 -:153A6800DF081AECC7593A9A0333F44D791BA103CAA9534601AC -:153A7D007BA57132ED6D9E97F23607A7F58164880F78925343FB -:153A920037A72BE1183038FCE84F9D30FA52DE9650D3908009B9 -:153AA7007066F4D570B5A08B22F42AC0FD29EC41091CCD8B0F3C -:153ABC00D43B78D94C32D76BD3CD473A5451A5D468F5CDC2C5E5 -:153AD10075C1E30306C64D89DDCE3F52F98FD3DF85D4DFAA4288 -:153AE600F437ABCF839FB723662FF1815F75F529F6B2D117930E -:153AFB00B27D52AD3E59F850459F9CF3D2363D44BF0CD798284B -:153B100076E10E7A01F0E6F4674EE84A2BC9419A7F7F6EE6B539 -:153B2500D3F852F6F0373C969E087C6C60D9710F19B839730EAD -:153B3A00D7D28BC4B96ABBDC412A071E49A28C4B9E857F379504 -:153B4F00FFFDEA51923983FC4F2343B5CA8E11D12F5FB2D374B5 -:153B6400FA0C79017E2F16B1E59F35DDB20973899C7CD6EC230E -:153B79005D5321FB3E4032DF9F841CE3A6D5CFE12C9D934346AA -:153B8E00A8E984C04788FA60AF6F171440BE8AF1C5752BEEFC13 -:153BA30015D1DEC2152FB8C697859FA2D38322FE2F70F7C8C3D1 -:153BB80096BF2BEAFF0EDB4B7C3068049A3A6DFE1FCCF0FF61C9 -:153BCD00E27FC0073B05EB7C820F62E003C3E683D10CDFCFCFB8 -:153BE2009FCAF747057F0E66E9AF8E18A82BCBD3832EFA774D11 -:153BF700A33FE0D96BF537293763ECB8C70C7ECB49C4324A1863 -:153C0C004F936CB360B6FAB98BF8DAE1E110C1574C7CEBC07AA5 -:153C21008D602D2758DB7C37F2ECABBF01BFBAE08D11BC311723 -:153C3600BCAA1B5E4B36BAF502A5A953C0EBC8216B6EE8123030 -:153C4B00CB31CB87CF8824DA8A5C7362EADA541EC4B91256DF0C -:153C60006BE0FB53B01DB5FF952ECCF01FD92E6F2256C061F98F -:153C75004E2566D92FC591A33AA972C52595724BE07CBFE6913D -:153C8A0058600EDE8D8F18CAF9A426930D739CE055C8E6958910 -:153C9F00C7B0AEE5F321561CE721A2A74AB64FFCA9DE960EA415 -:153CB40077FD33E6910EDFD953629FF44AC5DE3BD8F8A8618648 -:153CC900A516D4539ED88B98C1C1B988EF41E9896EEC77ED3513 -:153CDE0065AA0F7B61E237B52B8BB5FABDA62887B68CBD387FDC -:153CF3003CA73C2937B65B653AE26413E16C936F2DD785BF237A -:153D08007C526C9B08B0A2FE9DABB996B36E528FD370E9FD2C8B -:153D1D00D7D06799CA94278E6D02FC98CF010B60036F2E2318BE -:153D32004ACE9FD4E662CE7FFD59BD98719A2F92DAB7302FD91C -:153D470075E2FB086DD4579473FABE8BEAEFDA7742F851827F75 -:153D5C0044DEE84887AFFB9FF51460A33EA12F6CF220CE5EA6C6 -:153D71008107D29D39F0B9142C4BEF1D5C5CCCE0C16A2B830789 -:153D8600ACDF8D5B78087D576EEC5A873DC921DE4EE9BD185FB6 -:153D9B008413A4C13644AC330BDE538483631AEACF59F76B7D0D -:153DB00087C0C3312D40FD030E149C3BC6DA3BF4326A0B310BAB -:153DC500C3D47E39C941271EA1751E24CED93B8CED29EBD2DED5 -:153DDA0023DD754198FD61952ADFE5C45B1FFEBC88472874DE64 -:153DEF00D5C2AE5A7420286268EE16DF804059E2EB7CFA3D8C92 -:153E04007DC0F17F72C5B3251B113184845E087F7AF8A685976F -:153E190071863C4ADD01D249C6E2D5DE16C957A3CB91C5FA20AF -:153E2E00C18AF80B48AFD0FA750573907A6FA34FFDA346457D70 -:153E4300A0598EAA3ADEA54847C77DB3388FF4E722966149836F -:153E58006A5AF51E860E34B68CDE5568861E8E0F36D6501DD54A -:153E6D00544795FA40A35347A9783FB58DCBCB1F10F5FA45BD41 -:153E8200BFEA70F25ABF0F1B89E57D778A33DA0D13565B510BB7 -:153E97007EE0EAACF0EFAF36A3948E39F62A6385D2EAC5BA120B -:153EAC00818E68F793F20D8A7C61BE01E58DC526F28ECD90178A -:153EC1006D6F07ED92569E8337C9B30163D3CEB3FD2679C294B6 -:153ED600C76FE7D9302D4FAE522FBE37847CE095ADCB7F762708 -:153EEB006425FA21533F719F43F2DCA79AE64CEB596166FBCB27 -:153F0000638C2A8363D86F147A0B3DE34CAD88371B8D0BDE2D37 -:153F1500B1CECE67D68424C9E2B74CBD549FEAAC1F093F34B224 -:153F2A004F7F90C3B07E029FEF94A06FB6BC150BEB8881746A9C -:153F3F00D3AA9FDE958C3FA707CF3FA7C1462DA1B1126C1A1181 -:153F54006397F836A0B013F598673FF7560E53E3234B133497BD -:153F6900FBC9362A461F146E5A3E6FC233A400318BFDF1634B40 -:153F7E00A04B237F10F53B700839DE65C11749D48BEFFDD9F533 -:153F9300CE8F0F2EAD99566FC60EA6B941949F617DE61FEDF10C -:153FA800877EC15626788B2F63DC2855D9F2EE785B347E71160F -:153FBD00EB9F662877745A391A9F379C27B4CA1FE23F9FA1FCAC -:153FD200D68F50FEDD19CAD57F28BC87F89519CABDCF3EBCBDF5 -:153FE700D434FD0AFC1274F31FD6D5FFC9F54DBA19DEC7AF7EC8 -:153FFC00F0FB890F7BFFEF5DFFB4F77EF778F8A0F5D6FFFFFE71 -:154011005FF55E71E1BF789A7CFA7F077E9B3FA69D399A78FFE4 -:15402600C6F1F061F5B9F94D2A3BA2F779129B3F2ABF61BCCE52 -:15403B009155FE79711EAABAB553896D5E49C3DA1FF8828EF8BF -:1540500077F80EB8FFEE6E1D631E3A823FB0459FB5AA5B57D5B8 -:154065002FF15977B7EBC1755CF34B957AB0A8524F90CE66CB4D -:15407A00874DD7482F5102D53AEAFBD7D675680DD786E173B5CB -:15408F00AE4A877F33BC776435A7E57192F925FE4ABD605D8D23 -:1540A400FEF5358BB58A758BB5907FB3DE99F37B1AF6A316C828 -:1540B90031C4C70922AF2C7D4217EB40ABDA850C822CAA284A4F -:1540CE0068F08372DE178BF78B756F202EF4DA8A07E3BAF0CFA1 -:1540E3002438CFCED0FE4ABBFD426AFF10B55FE26A1BED9653F3 -:1540F800FBC827EAA5FADD6D5FB3EB9D70D59B4EFF34ED474C7B -:15410D00C55AD6B29E4C18D41DCF8971E022CDACBA6EA7297B4C -:154122002EE1C54F6DE6AF5D4CF8A9D416F86BF4F99F965BBC93 -:15413700AC7D63C51FCB2D87662704FEB12E457378106BA2B712 -:15414C0009DD240BBB881D01FD90C59F147D2398CEDA308DA2A4 -:15416100EFFE0D7AC5BEF5BA54E4C096BEEEC0D648B095FA2B21 -:15417600457A9C14638756F94535BA5FC0D4AD2D284AE83D3BB9 -:15418B00F764F80078FE6D3A6DC3C0443F71F6CEDA779D78128F -:1541A000ED8EDB7048655DF8269C6F36B76008ECABD203D41E5E -:1541B500FAD662FBB8C3394CE0252F8B970AE29BC2B54D7AC9E4 -:1541CA00BA7A01CFEE9C6EAD80F052E84FE8B92CB1718FCD975C -:1541DF000B45DFB3ED5EA1B60C7A17207C11DD8B1D1840FB8A9B -:1541F400D51B34D8DC15EB3668D3E94F83275020CE13B2828A7C -:154209003307C57BE95C8D5EF2604C97D997F45994E780C44203 -:15421E005EFB791F3D17AE23F8884F0A8BEA75FEBD06EDD0EB49 -:154233000D5AE1B9B57A09A7B47DAB74FED97B88DFEFD140FB92 -:1542480012C265C55A0B07724C6A51D9165E4F38F34A0FEBFE75 -:15425D00580E62F807F3B15753BEBA7596F4A8EE9757EAFE153F -:15427200D4D6DD8FEBFE55F7E87B73566A5823975764F3E7852A -:15428700AC3324227FA2D6CAFFDA1775FFAB0DFADE9DB59A97C5 -:15429C00E6ECC0F7366B159FCE69C177627CF1DA8DF9630D1B06 -:1542B1009FC6B78679AD5E71EE615D3ADBA073CA2BF9B2F8DF16 -:1542C60086311D12674E362176B4AF9DCA9D6ED828ECDA65ACCF -:1542DB00253710DE981758B6B1A26BBDB69B6401E982C5BBE8C3 -:1542F000FE879031FFF331DDBFAB41870DA1AA8F72B16F98F838 -:15430500A22EADFD922EDEBDD640EF6BF5BD842FD01C7C0DFB89 -:15431A00ABE09B524BC539C21F6FD74BCE7D512F3CDB2DE8DE86 -:15432F0043749F45F42E88F08D6E39045A835EC25FD7A623F818 -:15434400F06E82A505F0138E11377A1D3D2772B66AB3A81DC03C -:15435900DFB9D37ABEFB7ABA0472C8F98DBC34AF6C3A4869289B -:15436E000B7E36C98C04FE20E7C8BE9CE3F0D276CA237CAB09C3 -:1543830086ADF41CF8DE7CADE26C29E1B3549F896F7EC9B27C78 -:15439800F377CCE21BE0BD80F826E4DF2A70F1759B77C03725B1 -:1543AD009CD2A6F14E77FCBEC70A425B8826B1D66EF6E863B372 -:1543C20042D156C9FFB8EEFC2E8C3CFA186833AB7DFD46F67A95 -:1543D700CB46E75EF1AE477C1FA220BE7E63E158CB46299FE89F -:1543EC00FC894AEE25DC5F277A0367B70BFC7B5A0A7907E1FE98 -:1544010071C2FD1E21B7DDF8CFB1F19FB0BE4B11947C9FA0B6CC -:15441600A39BCE085A8057A29B46A7D102DF6D7BD0A605C9D76D -:15442B00E2F52E5ADCEAA2C57BC287303B8677D2F8ED75D106C1 -:15444000EB55A03BD277D8F4394FB471E8B1659AFFE787D1E3D1 -:15445500828B1E7F65D30363B8C4A6C50D7420DAB86991177966 -:15446A00E4B1DCC8FAC7D876D6E21F7B64E32C65CBC63CF69F69 -:15447F001F2B88FFC946FFD8A3E277C51F8B315AEC67F43BF207 -:15449400258177794725F7908CBD9E17E5050EDE696C16FA775A -:1544A900929CBB5F2F5CFBD414BC17CC84F7AE85A0B90BEF3177 -:1544BE008177A7BF6EFC936C2FBEDBC63FD67C30361CFC17BBB3 -:1544D300F0EF116B37167E7B6DFC164136D13BEC33BBF9DE2957 -:1544E800FF4B21FF2D9AA19C887B69D3C1C279FD14589E408C43 -:1544FD00AAA4D48273D5099237B954C72304C3A17B37EB15EBF0 -:154512009A34256789969773A7061EF693BC61AF376C3CF4031B -:154527007A776EAD569CF3592D3FE70FAC77D2CA8D6CCD3D1BF6 -:15453C0077C73C2D806B2170522ED6B603B9AA47CC8548473C72 -:1545510037C7A641FBD89BCA71E6687B9E403EF80E03AEB7C9AB -:15456600ECA43C99F1FE1A8D77CC5117D26905EB41D003684EA5 -:15457B000BBE6AE7FF163D57BC2BE35E7CD2EA77C1FF01EF9849 -:06459000C0E6B892000035 -:00000001FF diff --git a/drivers/atm/pca200e_ecd.data b/drivers/atm/pca200e_ecd.data deleted file mode 100644 index eca84aa7e0c..00000000000 --- a/drivers/atm/pca200e_ecd.data +++ /dev/null @@ -1,906 +0,0 @@ -:150000001F8B0808AC5A10380203706361323030655F65636428 -:150015002E62696E327D00DC3A0D7054459AFD261333136278A4 -:15002A00192663E02479728060A10E9063213F64F0700F3DE05E -:15003F009E6CDC7B2F3514B35EF0A28B9A5A731E554B91474C5C -:1500540034E11AB6692618B7609D8404A2121CA8648D7551435D -:150069009DA578A56C8AF276A9AB829DF3AC92DD52CC5EB177A0 -:15007E00D4CA32F77DDD6F665E263FA25B775B7753D5E9F7BEA8 -:15009300FEFAFBEBEFFBFAEB7E79F4A91F6C270A21A1870849C1 -:1500A8007C974CFA8536C11F37B9A99FFEAD9C49302569258321 -:1500BD00D8EF4EEE6E14EF59E3B3EDFED3E3C735EC67E50822CC -:1500D200A9FE0FFD29BF7CEA97A26F4EC993D537AF13234A5E2D -:1500E7005EDE94F3BF245F4AFCF1F129E7CF9E866E0ADE2C3919 -:1500FC002BF0237F849F3240F688FEB5EC75792D39E3BCB43E9B -:15011100C9A9F54BDE24FFBC9C3C6987DDCD33F3938CB0674E4E -:1501260078D6F8D7D63FD9DC8CEEABDC4824B2F9DC949E391965 -:15013B00FED7BF11FF975E7267F17D1CFB4BE77E3625BFBC0C26 -:150150003F0FF9BFFF5372CB72671A1F3D3EF99DF51312ECCF0D -:15016500C070095C0E5FF8FFFE4B3A7E246851FDD31C5230FA46 -:15017A00FC0A35E009832F79ADB5E45140A3A4743C8CE3E39F62 -:15018F00C35BB09DEAFF05BD7A95BB3DADE6B56DADE538465425 -:1501A40052C90E11EF08B4773A8857FB013CB7112F090619CEAC -:1501B9005B125380AEB695F80197D874FE9A9022A5D554ADE572 -:1501CE002661CA73EE80B5F5F26AE22D7F9A78FC814838484AB5 -:1501E300E8B36DBD4D843D4C4930CE42B06FCC091861CFB9BDAD -:1501F8002621C3B438D010BE6DD7091AF29090DFEA334930C6AA -:15020D001187E86D9CB09E2EDF18033C8DD220A9BB6D57390DB4 -:1502220011D2D8B26F23C02CEA0FAC0EB76CBADB3C4F48F1BBF2 -:150237001157A5EBD25FC0FCCB804A3412ECA211D133EA167DD2 -:15024C003B8518510311A53A5FDD62226D9C4BD46AEA567ACCA9 -:15026100362DB78EE8A7683E21017F201E4E927EEAB6169944DB -:15027600AFE1ADE3AEBAC0C53534B0EE4194CF8AC2FE47C6065E -:15028B007960DD5253D1FA6834346000BC45C0D909BE0A681025 -:1502A000BDD7BA4BDBBA12ED8A7C09EB8EA79BDA6BF9816681AC -:1502B500F70EF3723259F4518D59F578B3AB0A66E7A3597F0E69 -:1502CA00BA90E04E5BEEC669E5765D2A33DD6762936427C1D5C0 -:1502DF005CDA40CA8A7AA03EA807AC0147BBA02E52A72974180E -:1502F4007B956F461DD851EB3EA14348C8A0EA9689F2332DA72B -:150309000E7B941FFB00D8FFD6801526637B69AB8FCC22A5F03C -:15031E00ACF65863355BCB4740B7F5A05B6A3CEC239954156CC1 -:15033300E7B09E9AA7F084F085DB760DD171378910B6285EA406 -:15034800F64A5F403DE05D8BB4C2F800BD8EE3418BAF06B8AA3D -:15035D00EE81F5E96393DE6D3B92E0385D564748698085091946 -:15037200A79EC256E0D34F49792B1D759310AC032BD6FBCDCEAF -:1503870038D845EFE5456A87F95932097ABB5B050D98BFE30F8A -:15039C009CDF2BE6B767E667E6C6EDC6D24DB7E7A56AA4888777 -:1503B1003626DE3B6D253EE5C5810BE19CD8095A7CFEB241D8BF -:1503C600765A663C6DAE8CBC4EF7B70D35420264F51833C16105 -:1503DB00A6438F32018C232C303A64E29A23DCADBDCAE604CE52 -:1503F000C2DAFC0BE48392B027D20C3E546386122FF0964DDB3D -:15040500C0A7BEC35A366D323B120AE8B357F8531ECA1ED46DF0 -:15041A007F6AE732A6800FFA49302E6321B8C48EB97E560BEFE0 -:15042F00458110CC6910FE9B84D825C10415992A67940623CBF7 -:15044400E9EC584E5DD1912DB4E84C9DA9C486689188ABB8F0F0 -:15045900BD43E494A124DEA49DE43503E75D87B4D6F9E7F81CCD -:15046E00E748EF05F296419A062866F84EF23AC04791363CBF24 -:150483000BCFC31CE5D213EF71C44759162BA4E81F2077148DF9 -:15049800DE677E1BF429501F117ABAB5A3E037FD527EFD21DE68 -:1504AD0072EB2653890C502FC844D803BC937403BD7E2113CE66 -:1504C20027FA51FE0EC4AAE7DCA04906DB38E62BF04FDB0E52E9 -:1504D700EFC24B09339A731CE3886F2C203A191CE0A344E0591A -:1504EC00183F514DC49F88258C471F213EC2FAAC68A8CFB85650 -:15050100D6535DAAB92A3CE7C0EFCB0728CC6BDC33EBBE3AF4E9 -:15051600E76BC964B19EF8949519FF64CE568E091F74150C995D -:15052B00885B1C83D82FEF43FCD0E167A306513B39C4E31CF4C7 -:150540000131A6FE965F4D26FD9E7387CD79E78E9AE46AAF90F1 -:1505550009FC2A0E7E2562E5D1C8C62AB40BFA87E7CCA98C1F9A -:15056A00E07CDB0F02E0079ED07A136DD5DEE892EB27D74DDAA8 -:15057F009075F0D47A1E222F1BA9F524FAABBC1763C2F6998923 -:15059400F69376FBD1FB4F007E4396CDFA85CD8A1BD166C3B678 -:1505A900CDE268B322323660755A03C6B5E64D2B053DCC1D2390 -:1505BE00D266445F1497ADAD0B68E03E15BF6D6448D8278AEB56 -:1505D300C80678BEF73EB0C30FE947E092E01FC585095735DAFE -:1505E800F671D7EE55CF245C958188AB5ADA037C046D01BEE121 -:1505FD00BAF4A9E9518E9B1D5AC626FE09B121732DAEABB48BBB -:150612008C15B459DAD7B3F32CC428FA34D7B6547ACE7D067369 -:15062700345B4F0631B39A266B102748855D9AEE95FAA9DD5677 -:15063C00D4EA35EAB4875792D2583897B499FE5D3F12FA91FA31 -:15065100A3343AFA18E487C7B823BF7489DC027E87B620FA20D5 -:150666004FD1F043DE9AE5B0C528F877AC664BD58D1BD21EFFFA -:15067B0059BA7B79AD423CD23EFF6EAE509A67B0CF7B609F6360 -:15069000FF23F63989F6D9BCD64CED8550E85072F557D21EB076 -:1506A5004745AD6EE339DB1EF3C922D37F7DA9B0478E5E629653 -:1506BA005AA5D57F827B8FBE9F46125FF04F66E1FE5412866761 -:1506CF0086F945D818ED469ECAF8A08A7BB46860BB6E87ED4EC3 -:1506E400F114BF6CDB45C1764D60BB8F6DDB5D00DB21FF8083E0 -:1506F9007F83CD7B22DFE3C67E6F5F26674C9F2BE638724555DF -:15070E001A0F7DDA111F0B20A778361F4BE710B11F8EC13CAB3F -:15072300CFB85A932B64C35C82792494788F611E51E60E9B4A3C -:1507380007E413987728E1C8273927219F0C603EF1E1B81893A8 -:15074D00F9A4D8B3F9A4F963E02D724A539F88D97980873AFBA5 -:150762001C3A37E59359CE5C33A1781D3BC1DC9B7BCDA235ED12 -:15077700A29E2C523E379B4988CE17BAF7F3909FE8EF821F7925 -:15078C000AB11608D25AE1474B445DF7FC5CCD20E5FB68A3A870 -:1507A100170E70A2DF010DFCFD7FBBF54429CA4C9ABEA016F86E -:1507B6008190DD315E0F7E5103E34F925FAF825A94A30ECFCD41 -:1507CB00EDC7BD45FA3FEA06F6167AA890B7BE6EEB8ED2E275F7 -:1507E0005F9819585F7C7324B932C5ABCC90B5C0CDF0B262939A -:1507F500695544DE16B4F419E647605EC90313E7DD13D9B652B6 -:15080A00AE1BE31B70DDEC7941C02DC8C25D1129B371352AEAA4 -:15081F003D7B5DDD02EF009F3F4EEA549887F684FAAA68452469 -:15083400AF42D45290DF570BFC56BA0BF015C4D73BF911F04B90 -:1508490037E243DE03FC62DCA7D1977CA206EDE5CEFA7063BDC6 -:15085E00A3BEDB4CC197290D617DA68BDC791A7B55055EA967AE -:150873000D7A477DD7EA98BF20E2AE48D57848C3FD00350F601C -:150888007C421EC69849CFB37FEA060FC6604F20B001CE496318 -:15089D00F45BB141FAE3B6A126DC2B99A8E7346641AFCCBD0C5D -:1508B200FC9F80B3D24E383761AD1C83FDE1320F41BEF0EFBA70 -:1508C7005F9C89FC501BE39EAAC2D98AE8F5D48775DE582DD4FD -:1508DC0079C130D653FB649EE04837404E899AD0B2CF592B7220 -:1508F10048F13F47DC707EFA7B13EB3699AF0DFBFCA4DB755C24 -:150906003B75477AA046AD605EF541B3E5D6BBCD36A0A978FFF8 -:15091B00C6DC8B750C9CBB3007DDB2E7553337827B40B7D80387 -:150930008A033190A792DF42FECCF4C379E3167106B1EBAEB1A5 -:150945001EEEC7F307D45D9DA1DE74BD05671CBE429CA18E43BC -:15095A00BE5B682CD0CC95E2ACA1F6C4DD381FFA828EE5E21D9F -:15096F00CF4F17DE36CBDB9B95EA476A72D279D11F53A6CF9FA5 -:150984002F7597077ACCF25BD6C49886A7633517D785EC80E7CC -:15099900C4DF12320AAD0BDA4E683AB425D008B40B301E87C6CB -:1509AE00A0E9625E4FDC6EB04FF43059BBFD16CF2CA13DDE56FB -:1509C30043BEDBB50EF83FC2317F3629F20C3409C7410F71268F -:1509D8008F2F88CBF60A4BF1D9381D5E9ADF82B8362D3FA475C3 -:1509ED00BA4BD293F8E3643ABE8067E39C2533D1CBD03A3C13A1 -:150A02009E8DD33425BF89326D9C964E46A68553D2C9D040BBF7 -:150A17007F55C31A995C3D2CF1C7A25CE40D8CB1E29881790360 -:150A2C00623586F12B629A58F412FA289C3F647C34424C9608E5 -:150A41007F9B2E4E5E8138715DFA8579CB9E939363247D66979D -:150A5600B181F1823501C620C60CC64E3A56ACA39958518FC96B -:150A6B00B3FA18D457D69F1A6B2156F09CCE223913E224153FF3 -:150A80001F431E9A8D7990EDA5175CF2ACFE817D7D38027114D6 -:150A950081380A7D8D38DA6CC751C3639938FA009E23DF07232E -:150AAA004223D0128F43850E8D416B8016825602ED1AE0753D49 -:150ABF0036318EC41D03C412CAEFD9DF938E27E09B965B03B992 -:150AD400F7BCFF8A21C70726C557AA05537E9F8DEBE047317E33 -:150AE900DEEF81F157441D23C75BE2B2C13A3649FEF5022F9BEF -:150AFE004E8B23CE5AE21F91E9F8B54C8AB35E320D3D874FEF6F -:150B13009A915E86969EC69B420F382B230E9D92DF4499668A69 -:150B28008D7A32959D60BE4D7FE194E3683F394E74A0F3154D74 -:150B3D00CE4DE17F988EBFD4BA8B38D4FBB846C8AC542C4EA83B -:150B520027713FDF91D98F156FABA86DB78CB65588BD1DFC5798 -:150B67007D286614EF1AA4BA479E078B77F5D28847D6AE88CF94 -:150B7C00B0C665526784B9B260E38E7DBC445B88674CB6E10A5C -:150B910021EE75DDA61F635A2DC718F12B780796AE33FA999E1D -:150BA60043484524B702756A8067E58101519721BC73FE108595 -:150BBB009862B92AE8AF77F3DBB513DC1D6B73DC635914F1AC84 -:150BD00087F12E56D25A75B3B4622F6768017E1CF67CBF1E338F -:150BE50015C85F985FE2F23B9EE0F375F4B11CFA743964B06EE9 -:150BFA00521FC48BD74A7D2C873E5F492B4B9FC12C7D06BFA10A -:150C0F003E71873E671D32C46F521FC44B7C47EA1377E8F3954C -:150C2400B4B2F419CED267F81BEAA35EC9E8B3E44A460684DF02 -:150C39008C3E88A7DAFAE0F3AA9BA595A5CF48963E230E7D4207 -:150C4E00F6FDA61A180DA77CBCCCA066BB897CA58FE0FB4EFBF0 -:150C63003D6EBF37D8EFC81FDF0DF11EA3C29781C7CE1CD1D360 -:150C780041FBBDDF7E1FB6DF2FD8EF23F6FB6AA0B3533BC6C47E -:150C8D007E0B63EDDA49BC1BE40C9EBBB49FE2F99F8FC273BFE6 -:150CA200F6160B698BA97DE6E61ACC2B857D695E24B73A10CB76 -:150CB700ADF62572AB3DB00E78DE451DCBB597059D7A98BB5EAC -:150CCC003B25E844E1B9567B83E1FC77A41C0C79D66B7B98A408 -:150CE1006BF18540B710724F0D394B4F6F3BB916715096422D36 -:150CF600B702613FD9F653011B75C0F66E7B4BC050A614EC99A4 -:150D0B006DCFAD4DD15FACC9F5433AF3C4733FABB7F9A34C0FC4 -:150D2000960DAC49D14CE122AD146E4A5694ADD4C645BAF768FE -:150D3500B9D5381EB56DAA3D216D1ABA22EF6F904789BD3FE19D -:150D4A00B8BEC3392EF9DD65D358286174F44989B3DEA681BC57 -:150D5F00FD4803C6C69FC88C55D9760CC3F846B01FDA8EC2739B -:150D7400583BC0F0DC392264BA2CE4DCA1BDC88E08FB76F1DBED -:150D8900AF0807F47DF7466E65D9853BCDCDA56F2C7F612C6631 -:150D9E007C7B2DCAD12E6C940F67B9556BDD952B4AF72C6730C3 -:150DB3007697188B0B79F363B915F3DE7257064A0F2CE7305641 -:150DC800B856CA8FF6CA8738B9F17B77E5EFE6BFB8FC208CFDBE -:150DDD0047756E753E9C577F7DF1F32AA4F9F17C5A85F3FFF557 -:150DF200C86015E29EBF78026AAD06C113E48F5BA22F113283A0 -:150E07009E715DF43B056D120CC555D1370A39E07C18C798B8BB -:150E1C00EDCC6553F93002F1F71A2D10DF7F625CCEBBCC6B45C5 -:150E31002F6D4482116E403F67DD5153D9F47DA8B3F6D15B712C -:150E4600AF04BB49BE31DE2AFA06DE2EFA2E61CFBC3D80BFEF5E -:150E5B0069C0BF9B16068280AF895C26F2ADE81BF9B0E8570B92 -:150E70009BCF3A03F81FFE10F037D1D9011DF0435CCA1DE37EDB -:150E8500E89F15EBB093975CC9EC6DA454033C43ACCD23B0367D -:150E9A008DDA7EA606C6007681AE96B6E141D15FE0E5D037AD30 -:150EAF00245E1674D52944A3FBAF277DE84B3B005EA01D83BA29 -:150EC400C112F6CB81B3F8ED77209E8C2BDC2B1FB171D1DE7613 -:150ED900BC517CDE0D3C55EF0766EB9A98FD6DB39F22BF48E2BF -:150EEE0067DCBF6B08EB5F529F789DC33BB340367FA8CF54BDFC -:150F0300782FF021776B43FC9315B63CDA1DF4C69792C76198CC -:150F1800AFDAF2305B1EAA65E4C1BDEEBC8D3BEA9067740679E9 -:150F2D0074873CB5200FBC3336853CB50E799EB4797C807164D6 -:150F4200CB336ACB73BD2C230FEE55F7D9B8E86F2979F0793A72 -:150F570079420E79D6833CF0CE6253C8F3CEF28C3C977E277943 -:150F6C002CBB827B9A940779A03C3B1CF2E05E735AE20A5E2E36 -:150F8100C8ADADD57DFC7A32994CE55867F917D10659443B01F6 -:150F960039BA96AA810DE1CE35FD14FF4FA873ECB821758973F1 -:150FAB00DDCE291BAFE0A505F1791CFB6658EB6539856F9A5A59 -:150FC00002CE58E939FD7C839D8F53B806E04521B67D901B9DD8 -:150FD500F3752DCA6A81BF017218DA61689FB1466D21DBA92DFB -:150FEA00039F2967ED5A15ACD57A56663C627272B07149A28F90 -:150FFF0046ADBEC62EC08F6923AC5FA3ACF3C8095A4C06CC398E -:151014005B8FD0F9173FA3AD5BEFA46DF397D2E7B62EA7CF1F57 -:151029005943DB2FAEA387E69FA6783FF357BFC8C198A6F8BFCB -:15103E00542F1C7993169CE9310F5CDC07F5C0BE554EB9CEDE5D -:1510530043BC85DAFAEA344C6FA1E5F712AFCF09130AB4D0C3DD -:15106800D3C06BAF2527C18D480BC37C89F6F12F9E621E6BA1D1 -:15107D00CBD64C01875AE093F9C4BB30D6C3704D312FD45EC9C3 -:15109200D405E99F3AC2884A995B13DF2FD855FCC78E2063D72D -:1510A70044DFC5AEBB64AD33EE92DF494812EAA2C23E336A0D67 -:1510BC0019F87D638EBBCF3C9433641C0A0D189DB0962F586F8B -:1510D100189E0F3E1777C9F825E280D561A81BA9897E90EF9079 -:1510E6000FCFF76E3A24E0CF440A2A3E49FD7B8D9D377E5E23CE -:1510FB00F7C7487A2F8D31947F01EC63F9B1DF97CF8BFD1DEE8E -:1511100023F65E382CEA18B97F0DCB5C073693FB1FB371BA04B5 -:151125004E43669F14F1F0A4CD6774129F5B27F091FBE5B0A8F2 -:15113A0087527CE2369FF5361F89D345651EEE67B171428E04DB -:15114F0095BABCFD7DA63FB4C83C06BAFA2277560560AFBA7A78 -:1511640043EA7B3E726FC56578F680FDCB0C3807E50E34C29EFD -:1511790055AD94F687550DBF8B04E9D8DB9027624A5DADF6326D -:15118E00DED9F9DCEADDB00F75B0D2D0BEAA0324DA48D43DD4DD -:1511A30055DA15762F851A4DFF0D5FA8FD86BB6C5B57691D3C31 -:1511B800A41DE0FE441F63B97D4DCBB46E8E79C51A053D12BD56 -:1511CD004C059A08276A94C281CBE3E4B9E527DDD5CEF965C6B7 -:1511E2004193DB34702E3E232D1D68B94B97844359F37D303FCA -:1511F700A4BDC8A186B0E747A79CAFFE23EE4D4BC2284B10C611 -:15120C0096419D11D43AC45D3427AD8D86F62B9EAB609E3B411A -:1512210039E96C74475AB90FF66017D6BB7A2FF744A2BC2032BB -:1512360022EE9C27FAF1B0EDC7D6043F4EFBEF689FA13AFCB79B -:15124B00106A85B48F821FE0FAA18FE6ED1F308BC92253EAB616 -:1512600044EA16EAAE76FAB35FEB608188BBD28DE768C2A807ED -:15127500D6A3E94EE2C5F7E7E7B61B259B89F7A5B93143D596FA -:15128A008AB5598FEB0073D9FAE876EC73578BFF21CABF23206C -:15129F0069AAAB3C61159E676A128F885E0BA4E4D620EECA880B -:1512B4005AB8CC6C752DDD9E6BC399CFDA9E1AC7FF6352430BCD -:1512C900BFE74ED10845BFE74B3DAFCBC0459C801EF81D11EF02 -:1512DE00CD0E6AEE3A96DE9BE4BDD916BCABB2EFA5314E08DEDD -:1512F300AFE9C75940AB2EC7B51570BD8F5DAFA95E29EEFB990A -:15130800BCE39FA37799F8BD016922CCA746CDB3C9A47F527EA9 -:15131D00B2F9D74EE2DF6EDF9D4B39EE127766BD71A4A3240E38 -:151332004BBA3A7E4790307C4E4C419FC571FF91F4D500F0620B -:1513470094E2BE68D3F4F9347FD50AADA02264E78D0AEDF66A05 -:15135C00A0C97C6A47FAEE1068B3A2ACF7F4B3CD8F8F1D355654 -:1513710068F757F8B4FBCB03DAA28AD47DEB0A6DBBA46DD35490 -:15138600BC8727D155DE9F19B638717B25D610F8EC4638D8F716 -:15139B00207ECF8950FC3E731ABFE72C4EB82B713D104791385F -:1513B000EC20E660C4D1FB38E2A0ACA501AC11A1B67B88903162 -:1513C5000236FE4BE255C5DD690CCF9BEA79D24FF15ED2F20E35 -:1513DA0088EF6B44AC7B4CE0FBD5D7E47730FBDC81304D1BA0C3 -:1513EF00E28CE280056D58A303B6CC8635E0D9B754F0E33B1C7E -:15140400E3E2FF0C865D648936C09D30DC971766C188CB4DCA55 -:1514190027C2583DF46A6488A910CBABB3C712CAF87016AC0146 -:15142E0060235930F7BF29E3A3593002B0771066AFF37F13F3E9 -:1514430084C1511569F6242F3203617CC0644C280C0F0C1AF656 -:15145800229960D0640871E2A297502C37025AEFB141264ADC60 -:15146D00E0A1CC4156D92DEE7CC144126CB07926122DDD9DB8D3 -:1514820099327844070F14B7425DEE8E73BD2D6A2B6559B7D497 -:151497009D52B355DE15578538BAE8B2559C73DFD7DD6FE6CDD5 -:1514AC006450F1F6EA7E4CBD37DDFDBEEFEBAFBFFEBEAFFBFBA7 -:1514C100BA31DE44D82DB80EE738919E4FBE9AF31B37FF6E8C0B -:1514D600D97D8E4A1BC19FE113CC3500EB7D15DAA8986B25E05C -:1514EB0087B471F62449D02133CEFDA473208FA0ED37A19F74B0 -:151500003663C7C458757D99E6E3144ABE9AA12F947C9BF50CD4 -:151515008CEBAB1D34234CD447180B4298111E57823AA4431D81 -:15152A006768C3D7CAB2AD92C6AD92463FE63CA91C16DF3FF7EC -:15153F00E1FF709CDAB90469291BFD5236446E9DE415D833C0CF -:151554000DBEEBAB6C10E61C105FC6F58DEC875B3ED5BCE799CF -:15156900AF3269B70EFEBE8AB2C2569792B0D97682E72DADE6FD -:15157E00717D5146D64D2F2B7296012DDCE704CDE492EFAB5527 -:15159300511E4ABE0134BEC1CA529CCF7E53D2C1CBC0E6F81BA9 -:1515A800C7A4FE495015BE293361DC608CF8337C825E8FF0D8F6 -:1515BD00B855A83D29D09E64DABF2DF80B65F06EEDC9F843208F -:1515D200770BC03B94FDC477DE271FD06EF709DE2FB9C6F8FCD9 -:1515E70009F8B2F5FBDAB2F576D9D305CA9475D3CB4A9C65796F -:1515FC00F1542EDF728EDAF3DFA91B7AF274033EA764DDD5BE7C -:15161100310B7C63D755E3F3FBD96FD1EE4ECD27B36CBD843CC7 -:1516260079CA9639785F78B6D748E4D5CF3A3766081863B4A142 -:15163B001CFCA948C92615F7A301D6853FCFEA38940F9C17769B -:15165000DD94B30E78E19670F8D301632C0F86CD032183A2CC22 -:15166500CC2F03787BED325FB6CC2C5036D39B5B867DEA73F4B0 -:15167A00D92EEB2D5056EC7596993451A9105621F9436214752A -:15168F0006CE4B1FC83CC6CA306EC2FFFBC7DACB1C6B51524A3A -:1516A400F89A13E5D7C7E5374E6D399F7910F72B13AC1DE6BA33 -:1516B9003F2474592118EA35C380BA700CDFB19DA53BD60968C7 -:1516CE001F501F6E475D02FFF1BB0315633A878FB2E223AC503C -:1516E300B9EA28A7CEF6E585CB5528EF92712E94FB7C7E617C84 -:1516F800B820BF7C85FB3AEB5CC21832C7A3072A123AD703DF1D -:15170D00866F7F4258D8CFAF1B037A2D747D6758B9E39A907AAE -:15172200DEB6FD421FE7F23A571F17A005BE11B48C51FE04D841 -:15173700D7233CF06F0AF2A1407B92699F4BDF1E87DCE1FC7519 -:15174C0079A7CF6FE29D3EBF8BBCD3E7322950B6DF337D7E97A8 -:1517610078A7CF6525AF0CDB3FE7FC36BB26E13ABB92CF716123 -:151776001B90A70B1DB60FE3E0DD72AF86386CA19A57A738EAD9 -:15178B007C79756E475D795E5DA9A36E812AED48204577F72309 -:1517A0005D268F1F667D8F380BDA7BE6DCDF88338C69E058640C -:1517B500FD8D98217C8BDCDC45A266737E547F75BBABAD8E9F57 -:1517CA0067C09C7AF516428A0E361AC9CFD31E5843EA53F054F3 -:1517DF00802798FB87FB643F03997A3EF6C77A726984BDD79F79 -:1517F4008DAFB70EFCFFFECEB7104F0DD0CA423DFAEA3B9555D3 -:1518090076EC09E339A4DB7C7312CFA274C7DE9CE2CF495CDB6C -:15181E00C033F9668A9F5101FFF25EB157E2F039A98B8C9F43E4 -:151833007E52807D39C4E339D2CEF6839D1D053B0BCFEF8FEA65 -:151848008277D59C77B6CD8D7D96F6106FAFCE3E93FC8BB8384D -:15185D00FF50FF35013C13CA3FBC53B903F1EDB957CC93DDF0B5 -:15187200447F12734E79CC08FEAFCFF137E36CCD771C7335E3A0 -:15188700FFA62CEC2BF024217992903C49489E249027C5B09E3B -:15189C00BE16FEE15CF26A4B0233B5BEC04BC58257A2EC562824 -:1518B1003B1018CB295B01654381E3765929969541D98D8149CF -:1518C6002CE3FBEE829F7A0AF8077C6C4D4DE7E3A53B89A721F4 -:1518DB00857CACBAE34FDD9FFE02F25024E5610FE03DDF9C4B45 -:1518F0006783423C473F853903B4BEF4E9745A5BE11BFA29D2CB -:151905005AF3AD69B5E391DF86DEED05E82D96F49E015A1B9ABF -:15191A00A7CBAF8939BE0564F7E38B694F11F4E3838BD3FB616C -:15192F00029CD317B11FBE6BEA47E63CEEB7EC4F5781FE28B23F -:151944003F5756114F17FCBE0BFEF73E813E69554CD56A18D73C -:15195900FDA0F35CCB09998472FCAF9056FA21BE0774AA017723 -:15196E00166886A56A2D2F22FE08E899B511DC0F8C51DC35426B -:151983009B98A262AD12DB0FB65831C11EF6F3FD2C0AEDCE4436 -:151998008E58A51DC7ACB512762F3CD3D79B74233C5DE2BFBBA6 -:1519AD00218F9E06D95687E746F0357D9AC04774810FF120BED8 -:1519C200E833B9F81640BBD28E23D65AC0F7E10501C327F17D8A -:1519D7007C41E083FF6E273F55C9CFA34D44D437919CFA39B6C6 -:1519EC00FE93F59756E6D6CF95F5DB65FD0779F5F364FD5A59A5 -:151A01007F9CD7A7A8EFD9ECF9A334F491913E1DF790DC68A32C -:151A1600F3CE1BF5833FC4F0CC47656C7333EE2F997D75959A13 -:151A2B0012D4A53E1BA838AF3787F6055B1DF1DCBD273B7E8D0B -:151A4000BC7ABCFBFDE680A3FCDC0BCF5CC1F2959B7FDDEC8CD9 -:151A5500FF9E7DEBA72F63F983FFF8AB665289B1C761DAFBDB56 -:151A6A00275A7C7E7373EC87C433761FF14CA3D391AF9B7A36C9 -:151A7F00D73E0B5F2365A10E7179C53A8C97A9B97DB3FD236C72 -:151A94003713647D3028721BB0ED40DBB83E33725F607F1BD7AA -:151AA900E5CCB47539D4719D0F3079591E3C5C6F52B02D5D5C15 -:151ABE0086ED35183306CD2A1DF7BDC16FF4F457C4F4BBC89216 -:151AD300A0972CA99BAFB98298233650C1F4756655F0BD0C5F2F -:151AE800C6F83EC46CCE0FB6177D9412F0F546F3EA3D8E7A059E -:151AFD00EA7BB37CED2F5248BF1BEA5DB5307EB2CD7C6ECFC40A -:151B1200B7D741FB8DB2FDF740FFFBB592805DE787BA0622E42F -:151B270009FF2F3C3B6254C3FFF98E360BCFC60D5F1E3DF7C0A8 -:151B3C0038252271CB0DBAB6FECBB4277625EDD9FA557A96EC0C -:151B5100DFAA49D0D3203F397AC527E574B491F079134A3E4B1F -:151B660093256416CA19FAC136EC27619E610C4775D0E5AA8842 -:151B7B0019C723DCFED2808C3FEF01B8D5C0FFDE45C493AA12E9 -:151B9000B27FB20160CB7D72226DF99364980E4E8EEA336F4273 -:151BA5009B1EA0C297D5E43E6D35C576459EB8F1AF8B7E50EF22 -:151BBA006B8CB1062BEB6F45E0BD669090283C1B9E23C484E70C -:151BCF0065F895C3FB65F885E0C79E13FB5D08A7F53FD29ED399 -:151BE400B82693FFDDE7D39EE3F89F8DB079303E181BA8E47B6F -:151BF9000929EBF4FD843C87B6818D58367FED75C669919FC22E -:151C0E0061281AC6285EC77C7A9ABA8F102FEA228C9B711FF33D -:151C230088E56AA306EE2763EC8AE7CAAB23B8B75AD6E4A0E3B9 -:151C3800AC9BCCC2D82AE2C7734FB857B100EAC73CD25E713CCB -:151C4D000798CA7535A326FC5FF05F609F501F89FC8B0C2D99AC -:151C6200B39958F63B570AF0F17D3CC5F18E7B97F63BEE59F2DD -:151C7700B80FFC1F73C4B96C783E76C4405D904A5FCFE71EC6BA -:151C8C004486FEF9282F23A9EB89EFDD51F10E7F701CB36D6341 -:151CA10016C65186268FEA650ADF43B1447C2566613CA5C94103 -:151CB600B7D8BF1CA60F4C3D30B5787234472E67A35C227D20D4 -:151CCB009BBB6F271E1EAF0C1F61E8F7EDD7560510861B73A2DD -:151CE00022A798163941FDFC9CD3179697E700279862EF075FF5 -:151CF50014F916FC5C82DAC3F74C791C397CCC7A5CCEC76BF51C -:151D0A00279B1CFCFA661A246E3CAB84F80BCC81F25560EBE5AC -:151D1F00FC60B8F7AC522E5764B288801D328662CA263C7B40E5 -:151D3400EFE5716FBFBD6E9B43460CD46BC85B2AE9C3EFCFDEF8 -:151D4900463CCAD45386FAFE53BA5347E2792466821EE76BBC5A -:151D5E007E9AFEBBD30AC626152EFBA6581F4D017FCCB87E3379 -:151D7300190DE299C5D496A3CDCE71B94EEA8BEE159C0779F150 -:151D8800175CBFD9704D0E374D4ED2CC99447594611CED7B66CF -:151D9D00BC20EC191276F90A92B38F9B858F79A4FD745FC5B0E0 -:151DB200CECFC7838E45FA63FCEC42DC5C8CEB03C0519C1C3729 -:151DC70095E409D35D1A37704F7026E09B1B66862B42E9A1A492 -:151DDC00B249D17AE90DEA2F8D33E9B4DF1B5382D9757098A279 -:151DF1005FBBDB85BAB015CAAAF9790D9EAE8B3EC3FD620D515C -:151E06008ECFCA06983B77BFC8D75A01ED4D727F017AC13E46AC -:151E1B000EA37D1CE6F6715FC549DD3BD9773BC737A5F4B2C6FC -:151E300031417B386E7AD1DF93E54591B8A9362678FF0E9103BC -:151E4500BA05F2EA5E07F38DC5AD9BC51955E68A8C67FA3737FD -:151E5A00341AB4BF15FA2AF33E8D9EF70E67F371F7817FE13540 -:151E6F00253DEC2AF440B90AFA176971E2748978EADE9C3334E2 -:151E8400A82741C648E549B18F20FD33E09DE08FC82DC8E5A33C -:151E9900DAF762CE7E3DCCBDC806EC036BC7791A4A1EDE5B29A3 -:151EAE00D681E683503E188EE96EAFD86B4B024DE78B4D3CA3AA -:151EC3003E0BEB03EB458E0CDAB0C572EDD8CA6564CCAC833ABB -:151ED8009B764E37B46F58CFFD6C1EC75F2BDB353ADAB5245FE1 -:151EED00DD0B3F13CBA3EB798CC4C43831F605D7AA48C7E05399 -:151F020071DD3729F704A1DCC6DB25E1FD5501BCBB1D78B7CB1C -:151F1700763F71B4BB0BF0623BD3D12E2ADBF514A0EFAEE41B6C -:151F2C0026CEB17E4EE3DF9B685FDC408B0AF43DCF65679CEF03 -:151F4100430FFE13D04AC4397EB783D66E097BA000ADCC41C374 -:151F56006ED9EE50015A871DEDF6C8762F7C0DAD38C636ADA5E6 -:151F6B00DF406BA983D6A484DDB1613AAD5D1BB2347C2CDB6D89 -:151F8000DB7095F1DC901D4FE52AE3A938F09EB7C7B300DEDD56 -:151F95000EBC17ECF1BC0ADED68D38BF2690074C75E2C5FECA8E -:151FAA00FB36B0DC96F935D0FE308967647E638990F92B2E21E2 -:151FBF00F3A18D59DCE11281BB65E3D7E006BC3E89D7C6E77309 -:151FD400F473A384D1561806C3396BEF7597E7EB3CD02FC75F90 -:151FE900CAEA3B3E9FF95D0A4719B767784F8E7A9CA11FE92EF7 -:151FFE00ED33F6815FAA826D53D79E32CAE909E32021739C3A1C -:15201300E86FA05F85748FFD9DDF15D70F9BE33ACA8B88271E8C -:15202800D0613DBC17D7BF77715859DBB01C6015815DC8E8D5B4 -:15203D00D0B8EE5E17E73A95EB53DB5E98A84FE35C9FAA6D40B2 -:152052003FE85197E33DA7BF9598AF31ACBB2A9881E7F178AE2F -:152067008CB0F9D23625047E26F5697848F8946063455F46F90A -:15207C00F9097E3E08ED52641CECD23B863B7682A26D2A684F28 -:152091005ECEAE1F193FC7D46BF8319C8E7B15F2FFA5747A5E1E -:1520A600FE5A52EC77F278BD359C02FDEA81B915AEA12CD41386 -:1520BB00455DEC2E163A59917E7C293CA37F486772FF588AE7B0 -:1520D000E79539F3C6944671EF4CABA31D5EF893DF0E6DC2F3A4 -:1520E5001A9E5B3AC910CE83987F510BFF8167E877BB2A13EDD1 -:1520FA00587F4368D4B821F40ECA8CD5CC7345C618C2C372FF1D -:15210F00E6B895FDFF8EC1CBFE3A8E3E0BF1B38421BE7F076D69 -:15212400BAAFC8DB631CFF324BD3608AFB4D0E9A12B4991C5B1C -:15213900E9D75C011B37DEBDC3F34230FF1ADAFB6FFCC2CABCBE -:15214E00AFFA228327B9F058535126EF07D6AB320F1BE92ABB9B -:15216300310E7EFE10B3F819D31A3A07F87D3BB24315B044DB21 -:152178003186FC07B368A9EAD330D6C7E19B414BD18E5BED0E8D -:15218D00BF12D6DDE411AD64E5844BAE8B0BE05983BE4B41D8DD -:1521A200555689FA16C09EA0840D594AEC94856704C4797E691E -:1521B700BB51BF15CBF98B396DF25C0091759305FD19915B88C8 -:1521CC0072746106D29560ED226798B9257D6E271D682B8B05AC -:1521E1005C7F30415522CF2AA8C72CA443FD6889C56D51868E26 -:1521F60014ED8A65E51BE11CBD4FC0194C09F8026E82F3A7EC3D -:15220B00A33EE68235223F8347C6753C138F3EB0F82661619B93 -:152220009C7900F03F8C65FD1FBBDF083F719FE89FC0339683D4 -:15223500C7DE73C0B69C8F49C1C71B36F75AFE7082D7259C38A8 -:15224A0033E7914354D0D24055CE975679875080BA653E202FCF -:15225F000F8FB28717A1EFFA0ACF4773D2E07B7909738E1DB4DE -:15227400B114F508C6FE992D27E80BE30D65CF935E9DDFD31477 -:15228900A69C2FFCAC05D42BD05FD660525C841797F61AECC022 -:15229E00ADC607FF96F690A911BEBEF7E118A96F1A8A768AF9BB -:1522B30023E24E017B0D535E3C7D1DD5D37624735E3EB39E9A77 -:1522C8003A66DD7EADEBA9F06B962D539847365C22D6BDB93243 -:1522DD002564086919967CE163128C7179E2EB5958C7A33D4393 -:1522F200794219E0BC32C51AFEA5AF44AE52A1F504CF1B0EC06E -:15230700DC6717E83C7FA01DF767BCDA92FAF7D19EC23AFC1118 -:15231C00EDD6E0659893CB93BE55DC36DE2FF37DEEC74B4F0E1C -:1523310070B9E3F960A2DCC2F2F7E4FA3622DB46F3DACA720B9E -:15234600CBEDF3B836FC5EF9CD60DE37B2DCC2F22E09BF5FB607 -:15235B008DE5B595E51696DBEBD4C512FE6AD916DBE1FB028718 -:15237000BE6975D4E13B9E6DC2334D6E90A362B0558A36622134 -:15238500BF1475BF81E31DD046F19EA9B9734343CD0AAC57CB16 -:15239A007A2E18A5DA116BBEF94993BFE55343891CB75E8E95C9 -:1523AF006C72C39A0BECF1BC9991192B95C805CB96D999A0DB1C -:1523C4009257709F2E3B077E0A3652E1E746D8B4F928E757464D -:1523D900AF200CF5E08831583CAA236D73375759F67CE632C014 -:1523EE00CFE58EF3BB8BF8592FA147ACFCF92CF2400127CC19EB -:15240300E73C796A76AF91F8ADD84754A54EFBA679F27480DF1E -:152418008D23E6C8C008CF89518BB3F98F8B31F7007C8D07F85F -:15242D00DE7E36AEB50EE4CD67CBCDFF36BEE9984FAD45FF072C -:152442003A3ACF9F086B23ACC4DBC7F9F912C06BFAD4E10B5CB6 -:15245700CCB3BB400BB611FB20A6C5F7472AC7DA4B0EC68D21C8 -:15246C009015B5294E93220662B9C57E29BF37096D33D66BB0B8 -:152481006E4FA17D97F0307EAB4716B1622FDE75D743272F66C3 -:1524960071AB05FC107704F0F23D0AD3C2F11A02BBAF4E8CD0AA -:1524AB00CB12278E6F0E4EA877E7E1CCED7F75FB4607FE900352 -:1524C000BF5600BFE2C0BFA000FEAA6BC48FFE456F6380DAB4A9 -:1524D500200D139F081A1600AE7CFCEAC4118E4B8B8CC0DA3C30 -:1524EA00D10E6B6F0B7D1F45E377CACC5B101961CF83DF833679 -:1524FF00ED92D3CFC1589F5A65F5B65103EF74BBF46455338FA4 -:152514002756DFB4B4AA6D6B50FB6143E366ED9EBF587FB7B6A6 -:15252900E127BBBA3B1FDDA5ADEFDCDED9B1AB33A8B56CB9679D -:15253E00C7CECE8D5D3B7EFCA3AEEE2DF5CB6E5B16D0AA1FD909 -:15255300D5B56DE7CE1D8F6DE978BC235457D75877DBD23F5BD6 -:15256800AE3DBC6D7BE72E2DD0585BD750DB7807BC04EB03C11A -:15257D00FADBB4AA4CFCCCC6575BBBB533BAA3BBF6A11D8F4646 -:152592006B3BB67644773D51FB68C7B6C76A77ED7CA8B6735700 -:1525A700B4F6E1276A3B3AB6F3B2ED3B764497EDBAA96E857601 -:1525BC00ABD6B9755BB7B6B5F3E18E1F6FEFD61EEAEA78EC478C -:1525D1009D5AF5EEEECEDDDD4B11CBB783BF75E7B6C73B77D624 -:1525E6003E0CDDDAD2D1FDE896AD3B1F5FF6D04D2B1AAE063F10 -:1525FB00039E9F6799E30FB7EFC77D42B58ACEF537B4576BF5C9 -:152610006C199EE5B1F3F423CACA85FA05E350E870B4880CD334 -:15262500F63FA63379FAEDDABDD67FFECEB552517F6054692D59 -:15263A00B40AE6DE39D0253E78BE85BA539ECBEEFA22ED797785 -:15264F009112DCA81D613550379F8C3787B401C6EBC3CAD30165 -:1526640028437DD3E428C3762AD8408069F56BA5AB6C9B500E21 -:15267900BA710611BE04FEBF02B0F7A9CF44D14F1CFE657A16F7 -:15268E00D2E5CC6B77E6B4C72E8B585C1F6F5F4DBBA03D513FA2 -:1526A300B77CF0CD04E68D39F0B328E1676797B9C85CA40FE9F8 -:1526B800F069C718F66106AC53317F8E4C2DC538ACCFDF72AB4E -:1526CD00817DC77B164BFEA1D1C02B54AA0096D8AF3A44C3DAC6 -:1526E2000BB4FE6DC00DFE940FBEB7F1E0391EBCB301CA2C2721 -:1526F700CE35E934C7C9EF6D04FFEA783A3DA732E2127B6AE153 -:15270C00017A1DD80584997C0BF3660350F60AA7AB04ECE521AB -:152721007E6FC47EDC972BB3C7CD3E6311FB038EDDE77CEC30F5 -:152736007EA36930EFD4BE845B5B6195B41C85F13EC061E33C5F -:15274B00C43958AABD6CD57CE56ACAFAAB620C6C7E3BC7C1F730 -:152760004EDAFD75F5574EA66739C703E951811E9F63BCA211D6 -:15277500378D257F65A920875A722431D7BF1BDA76515F7211DD -:15278A009B9D2CDEB43AB914E435DA8E776AE01D89782F0E0997 -:15279F00DF4DDF55709DA453F465947F79D0C07B36D662FC4621 -:1527B400C533BB61EE8B0E9ACBF5D74275ABD66845ABDE2F396E -:1527C9004FFDA15BF83E63EFEBE959975C765ED6009B9133FE04 -:1527DE006B29DE5D89EDDAA1DD19D92E906C01B8ADD66A11DF97 -:1527F30048F03B29E5B326B2860EF0BC9145D485F77F014FC4CC -:152808009D94B9CFBD2E71278EB8E76B047CE95AFD52B180EFB5 -:15281D00A523C603DAECE05C6D76DDEB8BCA82D6E21B83A7B1E3 -:152832000EE3BAE3E9598B355790D3A90E50DC8376C3BC3C0DA3 -:15284700F320137F9B7A45D8E7A957AC9F5754EB7CBF1874E630 -:15285C00A0840FDFF3BDD47E8065B7B5DB6D873607DBF0BEB4B9 -:1528710012DE07DCDFCDC7A57F21E6512B7CCFE358324E77F2F6 -:1528860028C233D982D251C3F7DF87190A4E6B12CF389FE7E720 -:15289B00A9ACD0ABFA10C09D5F5A632C07BEE2D9D81A729EF631 -:1528B00086DE88624C2D896B83B6A5860563751DC84EC99E710C -:1528C5008AB90441DCFF507F21C646CE65F4A915BE2ED380AECD -:1528DA00503BA75FFD85357129ED395A24FA79178C75538131D3 -:1528EF00857575597E9F7A2FA5790E09C2D92EBF9F0F73AE6456 -:15290400CA34F0BEBA2258A784928729FD4DDA637F8B730575F3 -:15291900E284E43BC66F911701E083DD6618EAF83B7B864652D2 -:15292E006911EF8436A54773798F325888569CC7E5C91EE6FB92 -:152943004CF0FC83BFCDFD6E02F98F72CE75C37E6AF37A1078EE -:15295800DD9A1CB1265E933E80B3DFB83724FB4D7F2FFA8D63CC -:15296D008FF0A200AF468E1997CD51219B788ED6D576B71186B2 -:15298200FA9B6DF9936321F89885D1F07B416B1464E2E3D78499 -:152997004CCC2FAD37FC23AEA02D1B78CC3B2AE2B952364EE849 -:1529AC00E8DF2D262756A15CF81A135C1E2C73B1EE1E386228C5 -:1529C100A073174B3910FB02B9E37E12F8EC575F0199EFA15EF8 -:1529D600900B5F4F9D91BA28F96DCF07C737181B2FC4EF6538A7 -:1529EB00DFA13DE7793E1E984F9837649F7FB9CE211BDD201B4B -:152A0000D13342365C781796940DCC8343DEF01C07CCEB782D44 -:152A15003B7E086F76B8CBD0FFFD2FEB41C759D5C936AB2AD9BA -:152A2A0062819EB3400FB202F909FC5E665CEF946A553CC61AE4 -:152A3F002BB00F06FA9BCEF00E1891728C1B8DB5A3DFE6F28C47 -:152A540018B89FA6CB73D6E8833FC0F79712FCAC18DFFF8275A5 -:152A69003B9E0FFB79C54958ABC6F95E981AEBB3300F7275EC6C -:152A7E0014F7FFCC581C65729EAAF559ABB553168367191B3372 -:152A93004E6BA29E2C8AD38FAFE21FBAC984E723A5B9F8B1A2B3 -:152AA800CF5D3F73FD4F7B4F1B1DC575DD9BD5AC342B0D627676 -:152ABD00D95D495848232C12C9519C5DB1C8922CC242A88FEC13 -:152AD20010654B9D744612F63AB603B19D84B634C7E784C42B00 -:152AE7005889058FF03015F65A266695480E6E209539909014D9 -:152AFC0092A5761C9152B2E1381C9AA4F638716C9AB8B6EC6293 -:152B110087A436DB7BEFCCAC56027F25ED39FDD13367CECCFB72 -:152B2600BEEFDEF7EEBBEFBDFBEEBB95BB86F37317D82FD98F5D -:152B3B00D9F7D9636C823DC40CB69D6D619BD917D84676275BBC -:152B5000CF6E6537B33EA6B04FB0B5ECE3EC63ECA3AC9B5DC784 -:152B650056B3556C255BC196C38CB29375B076D6C696B1085B45 -:152B7A00CA5A599885D887D8D5EC83AC059E0FB0AB58333C4D64 -:152B8F00ECFDF0BC8F2D81A7119E2BE1590C4F033C323CF5F4B3 -:152BA400D4C1B3889E5A7AAEA067A1FDD4D0536D3F558527687B -:152BB9003F81C2E32F7A16143DBE598F77CE235DF2CCBFE4A91D -:152BCE00BCEC33EF2D1FF16D9F8A777CCADFF5E379C747C0C3D7 -:152BE300535AF6BB963D6099CEB280EC52D7DE1F63F241F46BAC -:152BF800043FDDFE6F82FF9CFDDF02FF1207FFC863EA9A207EDC -:152C0D0054D359B7968349B2C4299A242F3E28C5E1CDC06B2E5B -:152C22003E487602C97E6C13D9BE9365DBCF63FB71E017B7FD26 -:152C3700CA6D3F17F8656CBF0ADBAF04FC303F2893CE264A2C4B -:152C4C0016B2F342BDE2909D07EA1187ECB4A8371C8234310E91 -:152C6100F768656DE3B751D0BA4A83D9F6A81BE41AF48BD1B952 -:152C7600FFB0EECB70ADC25433F081865161AA83EC1B26DE2674 -:152C8B006CF26DC2C81E0B84554218F81BE8CF9FE850A9EC5CF1 -:152CA000B3E1E0CEC139D62367C3983B4234D1659A8787749C89 -:152CB500F731AC27A509F5237E118792CB8A3F99B5C3813776CE -:152CCA00C98B0DDDC9E7B8E51F837831E49BD262831740067A12 -:152CDF008B6F8C9B89932BFA975C33FFBAED4FF8CFE6E7A36DBF -:152CF40009EB3CB7AC4D93FD5BD9D2E720DD4999743D4AED7F28 -:152D09003A37EB82B686F66043EDC03B5D2CE96A37CA609ECA75 -:152D1E00473BD4E9860E5A9F9BFEBE7B19E204DDB8469A857495 -:152D3300226B471D6CA30570018C5613E456A38C5D05B05F65E1 -:152D4800B883D1FEDC65FC24CEF263F2AB06F2DAA6B96B14217A -:152D5D0059273F6CDFF0BD49E65A79A099941868E571BE2C35E6 -:152D7200A03D4A18CFC35064BBDE42EB5061834908974CB0C425 -:152D87005CD55046B38EE5F353D5AA94688EE0574834B7E23778 -:152D9C008675CD8548A6C6B8D48ED15E6528A425A84FB46B511B -:152DB100D26D8AA27F3C3FBF1BE2C4C88E24CAD0D659D8B8163F -:152DC600A573001BAC33B1A18D961E14BBDBBE272065EB48E02C -:152DDB003AEF7C002A09F397A4AEB3A482FB3DE87E7505BF8CF3 -:152DF000E5B6E8A2CCB7B2D856FD3CD62B27EB96DD5C4B6FAAC7 -:152E0500C52C69A53C213F5A57C2FFD8889EAA49281CD9F31C8E -:152E1A00310A7A20B11FA4B17EB5F2FD3A2F9F30989E84791408 -:152E2F00BFEC9B377F13F27F328DFEE8D7027EA373FCAAC16F26 -:152E4400688EDFA6150097F47CFA7337BF1006815913E5A7F5FB -:152E5900BBD99456BBF205B5B7FE99F043EDE7ECB316093A3FF3 -:152E6E00BC287106EF0EA075B3452B4FA97C665C77C1B828CBA6 -:152E8300DF4A33FDBC21A44668AE836B6D4276775B10E7515087 -:152E98000ED3BF615CC1BDA0221ECAD933E1C99B5F6A031880EB -:152EAD00A64F035CA7744EDBA93EB4EE79ED8AA806ED68A70154 -:152EC200384B5C5CB13A2C6C87F2625B27D9BE52B42D3E2908A7 -:152ED70068EB74DBA8D0FD02F83F306AB9BF6EBBBF3D3A95CFC1 -:152EEC00073217E75CF311FB693AE99AD2116F77B3AC96F85E05 -:152F010069EB97BF5CDA8AFA10A3B9879485A71F504A4E3DA5BB -:152F16005EC7CE8417668FA964672DA4DB76067354D780F4F77E -:152F2B00EAF95B9E3616724F42F81943481C68C3392CE63D7D7E -:152F4000CB295DC894B61EBAA77419CA26C447A4B18349570694 -:152F5500E87C58C7BAFC61EF6024781CF2967EAD617D24843B52 -:152F6A00F6F8A4807B23D2B68312C1FFC383CF431F2C978753B1 -:152F7F0068DBBA4C1E4CEC4A680AD7A3411FFDA98E3657E38FD5 -:152F940031769F80FB095A6ABAE13503E2EE78496E591683F8DE -:152FA9009BE3AB5B518EA1BE251DD0F9CC578047BA5BE3D9FD8E -:152FBE00AD4C3FAC4F63DB8370EC3F6BC19FCF1C80F63348B612 -:152FD300299A6CDB31D4D7F461B20BDF44FD0C64DBCC30F4B3E3 -:152FE80084C6036D25A645F02B30AD15BFB85F266476431E596D -:152FFD00B2C55A9D49EA9C00380A65C9862AB643EC1FFBA6308D -:153012006CDC88A1CC9D491A572534F2CF803FBA512E9C6ED029 -:153027007431CEB77A4176C47E32DD306E2C0C66FA8F5E742F22 -:15303C00035C1A536FE40509E0E98232CE60BF0AA5B52CF0E088 -:153051002EC89765F6184F15CEF7A47411301002E09E1FD42243 -:153066004C3F9EA67929F0B3EDD153CAE9DB4B5BD36C504927FD -:15307B00762B171BF965E9E8B052951C51776DD5945D1D6749C3 -:15309000B694CCFBD39D4BEAAEA13DA3506212D762BD8B92B8B7 -:1530A50027A8D766A84ED69AB680F67513B466DDCEA32CFDBCA3 -:1530BA00CE75A38EE113C6AEACA6E07AA190D903E9B6219E69A5 -:1530CF006FAFDABCDFA8351F369A0037B550D75C298805108ECA -:1530E400FDB349DE46B63C280F49439B4E42B57C9F4E36F7D6B9 -:1530F900691AA4D39137F0F1437AC4FC1EC4DD66A00D4E616AB7 -:15310E008F8A79BA4E4E908E5AEC71C66A70BF3F74846C05F0F8 -:153123003D432AD469D4D5B3534D95B1D9FD23876BFB29ED8BE7 -:15313800FFC6FFF0618EE8427B1E7EF311D203A45B7670CD1FF4 -:15314D00FD5892F4B5B0CED6FE478AF63F8CEC88526D0EA543D0 -:15316200E6231969A5A60AD76B6AC91A4DE565CD1005DCD3DEE3 -:15317700A3354577B7E1B9B1C000B41F98B75627D07DD808DA47 -:15318C006E3CD36EF1FDDD86DF145BD18FEC8D16F643D2B4E610 -:1531A100EF42DCE446F446A28375C69963FB34D4CBB6CE365B69 -:1531B6007720FC02F2E2D6A0CE5E86E8C7A50EA8C14583C60317 -:1531CB0051EB5C2CAE9DBB7A2CDBCB3716D921E03EAA912D62AA -:1531E0000969AB7FED20D93284FAE33A346F022FCB9D277C7B31 -:1531F5004DBE57A4B9439AF6195CA46B6ADDB101F35C03ED4235 -:15320A0021BC9CF945ADC95C102EE6F1C8DB918EC4DF0BBC1DC8 -:15321F00F8FC86D25EBFF9BA4176DBFE11DBE190B1E5CD7CA012 -:15323400E54DECBB162D10D77E73A7EED246546FA7B5D7EF02FD -:153249001E81F7CB886C64A9086D65211B09231DB5A236AA591F -:15325E00F4D2D3A4F375AE9FDA18D00FDD3CB3F45F5336DD9182 -:15327300CE9806DD48D7B934251AD8F478271CBF5B5AFD4FD299 -:15328800A29C6891B6F7796668F28EB4281A6B1D3AE8DF477B45 -:15329D005995A1629AF8E2EF0F93DDEDD8C0E4857BDEDF26C538 -:1532B200CB605C1DD0D1B636F2AECD5F2C6D9DFA2F871F59FCB0 -:1532C700A31A68E65BA4191CF04DA421D6D5DAF3B1CAC0F230DC -:1532DC00EFC2B9A882BC64D1A5A688269B099E94657705C27175 -:1532F1005F5132771A9C9CA4F6846EA5C8BE40A4287DE4930561 -:153306007D5FD2134EB309D2DB6C42DA0F4C28A2EC26DE1C225F -:15331B003D404DAF895ABCA8D00FA1CEDC061C8FE17BFD29C2BE -:1533300001F45B7FEA0F567DCD39D76CA18DFBEA60AABF06645E -:153345000199650E8658F660949907AB7F9BF7C07712DC93E0AA -:15335A003FD96DA77FABF8CAB9D9F1ABEDF838AEEF7FBDA84C2E -:15336F00D4C780F947715AB2CF45771668FAC57BF8655DB87E3E -:153384002E1F4DDC37754C2985E9062F8FA4D04E49B9FC448ADD -:15339900EC86D37E5096CE544AF22198B72475D15CD27AE3FDB6 -:1533AE00790FE2417B30EF999B67316CA4770869BBE407F5F373 -:1533C300CF6A2023E96403C56A877F6750DBB56CAD4CEF0279DE -:1533D800B115E4A2F7D236A79F1DD193AE94CEF6F1BDD3CF6A0E -:1533ED0046D29536BAE45DC6EB17B17F24ECB9C980F11CCA42CA -:15340200407FDC5F95A18C629C5C787A363E717FD796672D5DEB -:15341700687D8F8EB23307FD0BEB086E63F5DF82BC188A914D54 -:15342C0074279FEC8F67F2697C2D2FD4E2D9A16035C8F103FAC1 -:153441004928F36E16D798194AE3BA986836E9A5C7C3EAB7121E -:15345600CDE1C1F6F659B26519C375E276EAF765DCADC067AE49 -:15346B00D765339666D22B862034A8B8D66CC9958BDBCA61EE8B -:15348000E2AA53A80CB4878769DC0361B5321A8E944399FBEB54 -:15349500AF6DAB3565181B9BF46A33A47362A73AF895B0E6CE17 -:1534AA00C23C31D76E387788A0EE07B374D041DE6C0CF3B8563E -:1534BF001DFBD424D36F191552B87FF857F43557B896CDACFF5A -:1534D40057DB7A174D363F0B013F6B5750AEF7C95C88E62A504F -:1534E9000FDEB11D937B64B226BB47ADB1EF6FF0C3388DE3317F -:1534FE00CB7DC7F072CFA9AD0D95D7B0BAA97EC6CE6912FB759A -:153513009B9F7B59DD29BB5B51560C01AFACE526D440F048BF54 -:1535280010FDF5D25AF8BA4EED26BBF4C827AB56A26EC011FBD2 -:15353D00BEA1843605E3BE2F7158F5D682DC52B0CFFCCE6F157A -:15355200C8E6F84DAF288BF8E2653067F98ECECC470E8E83CCE6 -:15356700556BDEAF23EFC276817BD85E18AF9FAA19591A05598C -:15357C0007C7A14FB875926FFEE9412DECC8346FBC997F4B99EA -:1535910026FDFBFC5BCA34ED6F25D3C45ED04CE77C39F21CC0B6 -:1535A60095D0707B5B39E93423DE8EB5F98FFF07E47F4C5B0B28 -:1535BB00B87BA05D776C76109E828943053C05CD2561E11CEEF2 -:1535D000296D99E44F1C437E1D5C68CE0B835BF79901FA969B53 -:1535E5008BE8AB035FBF5CFD619C8DB8BA5F564F5EC80B880779 -:1535FA00AC6B8B5D7766D7BDF63275C734E90BEFBDFE8B80EE1D -:15360F00D5C85763BBD2B1D7E7CC6FA08E747744113D5B8AE3A5 -:15362400C476EB37B0B47623C8F0CF3F35B254968F4F0297D654 -:153639007C1C8CB7D219C36FB74B1EF505A49F1B77B3B39A97FE -:15364E007B91EE4FB862E5CB6A28FBBDC8151D163EAF602F502E -:15366300DBC3FE7A05CE67426709A7D8E6703D17D784EB4C771E -:15367800AB13A7EAF8D305BC57415A491E48272A92BD18F72EE4 -:15368D005CB28D1D4AA32E4AC9D4310C1B759D3CA6EA799847E0 -:1536A2004178937C7B1B7E119EF32BCA966DBAF91990177FAEFD -:1536B7000BF263A32DF2BF1AD5E7ED3AC6862645D437CBACD512 -:1536CC00AC7F9C4B0D4D9E5B61A53F0278F3DB795D58B1BEED6D -:1536E1006AF6F5569A0B15C5C5B49847713AB4F7BEE5DE334AFE -:1536F60048FECBA5E88FE32588D21FC7FF0771CC8C0D65503E7B -:15370B00C5B4E5A8630FB8C4F361B5BBBE4A785D28838C60E796 -:153720005F39EBBF2AECB2FED3E5F2FC307C7557A525B763FE8C -:15373500AE8777A83437FA21F00A90BB8CE8238A144DAAD5302F -:15374A0096D079BD7761A31F5F1863525C6AAD8AFB984CDA4A08 -:15375F00E3901480F1C41E87684CC2B0F7301E3963913D2E5D94 -:15377400763CC2B108C7A408D9F4288C291A3B618D29563932C9 -:15378900AB965F3116A06C01E394206F37BA5FCD0BE5192D5589 -:15379E000E7047A2C956677E580DE31AC6697AD5A1F7A05EDB5A -:1537B3006ACD2B733FA0701DC343801F4CCF32CFE97417484EF5 -:1537C8008379654A2BCD24133E2847CA1C4A639F2B318F699847 -:1537DD0027B6356C734DF2B3A3D8A6CEBEE1C86B36CC00EBA1A5 -:1537F2005D5F813E3CA0D37959B439FA5D6B5CDDF3CA4CFFF2E4 -:1538070006ADF32F82BD5F3659C53C208B7AF62DB0DC719E794D -:15381C0036BB98670A5E4BCE6EB27993A523E2C6BB03FCCE58AA -:1538310098D136039EFCC73BD45520CFBA07C6D491DC98522753 -:15384600BB3B17CA1FFC30AE9D511AA9592D9C178D3540BBE016 -:15385B0086F87883EE96701D8E1B7A716F73849D1FD0CC1378F1 -:15387000B9D15C797276F9AB12CD4BFFA4722ED1BF09F53756D0 -:15388500B10A495AACA2BE2DEE75476A58855BFA06E9475E9528 -:15389A0079B30B75A7825F0AA3AC4B3A51645F00CFE5423CA71A -:1538AF003CF4EF02F78CCD6E9AEB94E3BEF81341B47DD3D4FF48 -:1538C4004610F36D253D9F5C35AB10E363C05797A8EF93B98E87 -:1538D90052482FC61B8C0BE0CF7F6940B7F412F921679DC02DFA -:1538EE006D517F0161685F6F04E340BD704F4F46DD29F0E3E3FC -:1539030063C651F487FF17618E7ED64E877B5BCF813F7EC78161 -:15391800C6783EF0A8CB3A53398234F74FA31D4656B60FEDE209 -:15392D00BDAC49A71F5450AFB51AE737D2214D100FA83D40DB6E -:153942000532DF5B66EE21BB48B5C00B8326C61FDEC26D1FA1AC -:15395700FBE170AE7355A66BA9245A672FD0F6C97CCA736254CD -:15396C0080388215C75F9DE19772FB2E4DCB6265A4EFAA03DE24 -:153981002201EB4C23EAB7A0DD41DCCF37C18F49C9C2FE1A2F08 -:153996009F37EE02BAF1801711FA66BCCABEA3720E7D437141CA -:1539AB008B9B3F3CC83F3DA0BEE177F2AD2DE49BB2F38DDBB65E -:1539C000677700AF385A86B695E47E964B18B4FE2E4534AEAEF2 -:1539D500BD9F379B0CC1443FA095D94EE5579BD306CA4392991B -:1539EA00813CE3FDB82EB9A3668342BCAA6E637FAD8967CCCFD0 -:1539FF00F6F3F2678DA341AB7D34429A263337DA02E923905F61 -:153A1400D702E609417A0BB63F4B236C68A77415CAA076FB725B -:153A2900D545FBA3E6EF8C1D3531254A792AFD317043FC83ABCF -:153A3E00E11B87BC4B614E70A3B9D7889A0FA4BB4D7D34065FA4 -:153A5300DCD38BC17F16C215282BE7B36DF1B20CE1009015D890 -:153A6800519351FACD8C711BE41B07D8FCD85E01572DF015E0BB -:153A7D008B362E6508AF85FFD590871FBE8D3077DB00FFE716D1 -:153A920060DB065C815F37F8F1C06F9E02BF50D0A2477C8E4D94 -:153AA7005FF7D30915DA5D854FE6979714D18B4378E47103D74A -:153ABC00A042F2B826E0FFE5F4E5E83C48448BB958C5D5995BCC -:153AD10022D86F4A3B642D4B3A81CD7A359E6991068C52DA2366 -:153AE600E6869C3C3250667D7A8CCE0570350975C67E4B14E2A1 -:153AFB00453406F90D215EFC4D05DEA69CC231AD5945BBE28BDE -:153B1000E5DEA56CD32B8353CF32E6E4C3360D68999FD8FB05AF -:153B25009BC63413FE51074328C0D3A12FC47105C39EB5F48CEF -:153B3A005B1CFE047ED99FA0AEDEB2E502C00A3207C1EDD09B26 -:153B4F00492097DBE9826CF972B6A983F277F46D310DE45551D0 -:153B6400C9BA280CF32A0B5E8A2FECDF7E6E461F5EC2BB96FCCD -:153B7900FB0A75ECFA31D6F1807A030C0DD29726F4F88F11604E -:153B8E00B44D64ADF7EBE0CEC03B096F16DE1CBC26BCD3787B99 -:153BA300758E0CAD3119DE50CE8ACB360D5A75B574E6C9CD7E81 -:153BB80039DB2DCF7147E7B8E373DC8939EECC1C77768EDB9CD5 -:153BCD00E366BF9A53FEAF8A74FA013FDDDC6CFB0393483BFFD1 -:153BE20064C16E531CEA161838AC56D2D9503B1F9873E3DCFA61 -:153BF70086F8BA48E0D8849ECE219D66F03605EEB3F09E83F799 -:153C0C0002BC02D0A71ADE2678DBE1ED86578177C34FACB8ECF6 -:153C2100D004E12DE3D01FDC8837BDC88D784B14B9116F1B8B77 -:153C3600DC88B778911BF1162B7223DEA2456EC45BA8C88D78AC -:153C4B00938BCBFFD58C5D442A1FDC818E8C816D1BF54BF97BFD -:153C6000D65DEB9C6B279C5DCE3E03E0576445F89D1BE74F0C29 -:153C750047DE7314E417908DF427E6310FEA1AC29CBA33CD31E8 -:153C8A008F00FFC0673A451823CBE545D73C05E3622DFC231DFB -:153C9F0079699B7A971778D67C5671076BEC8CCEB778DA4DF0DC -:153CB4001F996FF1B23AD6B8DCD11B91D1CE2F8CF93AE48138E6 -:153CC9009BAE84F11BD29FAB44D9E1D1193B0A20EF9DA91F80D0 -:153CDE0071793FCA08FAF40AF7F227208EECBDFCF8E48C73B8E8 -:153CF3009789E311A0D1531C4F8472B7DA67BC41DE597E16F2D1 -:153D0800F290FC3E9B8FD502BC9B251C0F51BED8AEEF88E3B99A -:153D1D009E47F52DD1FD547FCF87DCBD92DCAC23CF6F03B4794F -:153D320057EEC6B5306DE33C5CCF1FD399FEA81E80B97B271B90 -:153D4700A4F8839E0985AB6987B175CCC07B8078905BC9B66F83 -:153D5C006C587B6A3E8E637ABFE44D511E47459021218D203F57 -:153D7100AAF330167B2A715D6ECC401B0688E746C9923F10D617 -:153D86009C385BBEDB378F553C01F965E6E138D3A827696C6ACA -:153D9B00A2B109CF137235213A9F7EF662DE539E18E874C79ABA -:153DB00054596ED05F5CC12DBF0BD24CCDB76422070F3E5B5772 -:153DC5006B66FD43D6A7A7914F6D25BB6B98BF74FA030A9ED3D9 -:153DDA0040987DD1B1A53CC82A3CE4390D79F6824C85E7407863 -:153DEF00D265A57138407607A62D9BA17C7CC21065EBFED03C4A -:153E0400E9413FAA0580E7F3F26306C6AF043E4AF7A59780FC2C -:153E19008C770C16DDDF721EF2F8511CDA5E1C6D16587691BFD7 -:153E2E00CBC63A4570E33883B88C9633CFEBD0665F65039D0EF2 -:153E4300EC164EF6116FC23CE8CC045BD2E9C07D1EE046FD401A -:153E5800A04305DAF9C0B6C1A3DED985BCC7B1FB5D5CA7605144 -:153E6D009D9CF106EB45FBBCC0EF102E777618E039AA511DA462 -:153E8200319C7340BDB7CFD89D8D0F68231EE6B9016075D27CEB -:153E9700383AD8897BD4FF7CE0E7FB45B9C50890AEA70A7D760A -:153EAC00B5E1C0CECBFB691E86FF38C64B368ED6D8703A7A6FBD -:153EC100362E03B8BFD60261BE38BFDC5F32D337244FA36ADD4C -:153ED600E39AA6F28CE3E3CB5924827BD6796BEF219FFFF2F1E0 -:153EEB0008F82575BC5BC09BBB57F59EBE56918EAF54EB645735 -:153F000017E9B4E6B6A30E89C7533C6EDA70B6B225342E4F0ACC -:153F1500CCF334D4F167D0F6D8A6AF525E185F405E1F19A77B66 -:153F2A000BE8FC47570B9D7B00395CFF6662AC13CF44207E1FE7 -:153F3F00887374AF9C8D779FCF747756A1BC6E1ED3CFDFFC9DFD -:153F5400E53F0337D69937272EDFDE0047567BB3DA8F681ED6B2 -:153F6900779BEEDE60D7049587FDCCA2A74C3875F835DFB5043E -:153F7E00F729315CAFCB8E459CFAC6B8D9ED12F5122EC6B94E46 -:153F930084DBC1DB4BD971E201621C78825DCECF208F775BA70C -:153FA8003AD3BD3C543EBB2D76BF9EF7AC063A8AF1A2BAC88FA0 -:153FBD00E9A87F56A80BCC61ACFA3715EA8270F05D1FA4BA1001 -:153FD2009EE2636F8927B7D4A8DAEB1E79ACAF707C17E9FAE127 -:153FE700DC688FCBE6138003E0E99E82CDF1DC8076F2BF1C7DE8 -:153FFC00CB16AA13EACF3A696F837448EF34A429E63377BF6960 -:15401100B55751DEAFCBF171ED73D18930968D6D51DA7CD43A54 -:1540260057969B80F9C2A041F6E1A72D5EEEF415DE3C60489E81 -:15403B0009D50B3CF77E985B8926F215CDAEFF9199FA43BBA8E9 -:15405000EA3A46F5AF02BAD9F42D8C21E5C8EFA83F68AA6507E9 -:15406500DCEA0F17D1164AE4D0ACFEF09BEC21B28F82386BBD10 -:15407A00C53AEF8DE53CCC863BA12D5BFDA46BD06AC700EB5097 -:15408F0002CF30EBFDBBC9B6F9B139F4D62D7AD71F5D6E805B09 -:1540A4008C8F17D1F5908E6966E83A6ED72B45F5429EE3ED1A8C -:1540B900A63A2DCCF0CBB1ED3BB42CB45FF0E333686B3FA90FC2 -:1540CE0041FFB3ECEC5BF5F802B44FA72DFAD8D1CE4A281F618E -:1540E300B900B02C84B677A86C76DB3BF99FD0EEE422F8E200AC -:1540F8005FBC083ED981CFE24B84CFAE4182AF982F4C4F5B7B51 -:15410D00C8F8E5E3D69DB37A34B9B1B268CC49FCDE694B85B9DC -:15412200AB8F454608B768CB223D9DAF28B43D906D7E81BADD7A -:154137005FE5AF95E2D6FCDB17DDAF3E0969020D7CAFF7745A0A -:15414C007171CCBB00C3728774E97446E1610E7E10609570CC13 -:1541610081F683EB92828072A7A6058347FA65909112F78EF437 -:154176006E41FFD4EF90876F114E1EA37DF073F5C3CB58EEA8CC -:15418B006E84B85ECCA72E398C36C1FC5578BF10F827613ECE96 -:1541A000A4618387FC708F93DC502E4F7B2AC306A5C3B2F461E7 -:1541B500D4175D5097E13B07AC345B1230A7C77511618DA6D2CC -:1541CA00FDBCA87364CFE91156CC7F6BB7A694F49C5713F9BC33 -:1541DF006FE4239A8275E6214D5DF2C03A841FC74E840561C3C2 -:1541F4003D8476802170FA88521587BA9EF88AEA631AF0F08C51 -:15420900F22D1C17EC3CD1FE3CC8C03E4CE7D47D08F24FED3C5F -:15421E004CF7FE627BA1B8B1435B84EDBF534D840DEA8475C1C0 -:154233007B41912E8807A61FD3109F6DA83600E10E2ECE16F0E9 -:15424800609555C003AEBFE62C3C04BFCF77A67A70AF79421B7B -:15425D0000FF11EC2F8013F4C3B50D1C832D788F010E0E289865 -:154272007F49CF6BEA66C2C301C50BF5431C48782E05F74EF013 -:15428700CE0D280B6DDA86A0FCBAE0B97EC75EAD65DF04E6FFDB -:15429C00AF30B6A326A5BCCACE698B42ECD38D32FF61C79E62DB -:1542B100EE9364AF96ECCE74D31AC19251EB6C608AD245CD6D7D -:1542C6001AB46D0F7C711FCDC8BD36D3CEF13C18AE55611B6D33 -:1542DB00C1B934EA1E86DA35F61AE9B58DC2989B4D34B97B3965 -:1542F00021A2F289B0BA0760AD5726F19E385D977777D1FC14F6 -:15430500E248C03B44F9639D82FCD94E49FEC4723E26E3789DC3 -:15431A007D0EE461FCF6E35C2AF628D9BC0D74C886953FCA8CB7 -:15432F0063D91084B540FA2648DF08E9D1AF56FE44A79307B46F -:15434400A74E11C205087F6EC567293F91E666AF6C71E26CC493 -:154359007200267FC7B495B76EC18D388A60DF00385BE467BB1B -:15436E00F88E901183705C2FE882F934970AAB5202F7D2ACF8F1 -:15438300981FB481000FF9603CD2E77E0DCF015AF769601F6EDA -:1543980067F6FC1ADBBC346E97B3AF1F6D3254D3D97DCB0FE76F -:1543AD004CE8876D2260E9B05F325FE2388B9E057FC8BFD6990B -:1543C200FF901E1F944F7704650CF3B54BE75CD6D9C17D3A8668 -:1543D70021FF015E6B95057102B9AFA9FED35F53505EF5771D0F -:1543EC00B2EEE580303FCEFDD9611CDFB58FBF50C26AB387DBB4 -:1544010036C2B827DAF30C4B67D09273D066BC9038B0B40A64E3 -:154416004F3FE61BDA67C151E0932982CF1F4D46C83E04B8311D -:15442B00CFEAE8785B6D519E85B90BF05C4A6FF3CFDFD8ED19DF -:15444000EB81733B80CDF71CADE934CEA4293E8F48F76DDFA789 -:15445500FDF632E9F6CF4907ED5DBFDC7A52D4DCABFDFB65D2F4 -:15446A00DFF52ED2BF7C997491778477AF76EE32E9DE60EF5C67 -:15447F00DEF49B73F6D3707DA7B8FD01ADA65F9BBDBE31373CC9 -:15449400F1FADB874FBF53F8FF76FE73C2C5E2F6FF76EB03FFC6 -:1544A9001FFE47854B45F8F7CDE54BFF67E0B7DB47ECBDA5C765 -:1544BE00FEB580974916FB24D9B869EA1F94E2B7AD82AE287AF2 -:1544D3006F573508C7BB56C5EBB6AB74D607656EEF0675DEEA92 -:1544E800EDAA2CDFA9CDBB6E40F5F7688AC835A8FECA063509AF -:1544FD00728BDDA7D75D80B159F236A998DF1F9BD7DEEB35652F -:154512001275FF7A70EE12D7502389974B7A3F073C392036A83C -:15452700E53D2DEAC3D7372BF53DCD4A50BC4D1D2CF98082F66E -:15453C002017F17167AEE2C7F83C77A54A6B0FAB078877200F1F -:15455100A9AF4C2AA8DFE584FB28BC59757B1324DFD5DF9450C1 -:15456600697FC9BE2F7C2E0CAB6C182A0086BD0043A0A87C2C1D -:15457B00B70E60C078942FE45F5CF6053BDFE9A27CF3F967F20B -:15459000229E150FB3DEB578473AE49D28896B888F3CB3F2BAA4 -:1545A5009AB10555801B11CAF4AC69061C35288BC416B5F6430B -:1545BA007CAF9B0DF4D57F9EEFDD3B3F4934C0759110C0817BDE -:1545CF00705791DD9019D81126929358E21EAA1BC074D286E933 -:1545E40028D65DBC51ADDFB956E52A1DD8F2171DD83A01B66A62 -:1545F900B181FC1320203AF4F254B6A822C1B45D595499547755 -:15460E006DDD51680B88E73FE4F3360C8CEA893695ACFDE3E983 -:154623007BB0DC9C0D075793C2BBA784F99A05837767A3EA852E -:15463800F2B06EBDB62E3F2ABD115ECA66F0520F6DA7624D974C -:15464D001AE889103CDB4AB62BE580970A31A996B264DF0EBB47 -:154662006D2EA6BACF947B0ECAD221CC0BF802BAFB1C1890F65F -:15467700F5DD372A280BD5F7DCA8CCA53F74226F39ED1BCCF4C2 -:15468C00A7FAA93D148F3BD5A2066E8AAB3CBB539D07711FE630 -:1546A10058D06DFF1BF05FD10370427BA9A88CA8DAE31DCADEFE -:1546B600131D4AC5A9356A4003BF9DAB55ED233740DBBF41C1A6 -:1546CB003610009CD6AFB170C1C7B95E996DA0B60D729ADFCD92 -:1546E000DDA28AF112BCF7C4EFC1BD9ABAEEFE79DCADAAC8AF72 -:1546F50052C59550DE7577A8E2EA1BD4E192554A04D70156CE75 -:15470A00C42F0B5AE766287E326CC57FF233AAF844873ABC35B0 -:15471F00ACB861DCF53E7E9B52FFA1925EB48D2C24C27D9E6CDC -:1547340047DFFD684F4A0BABF5A76E51B9931DAA067139618691 -:15474900169BB08F07E99CCD3AB4A5220C40BAE31D7D34D76B64 -:15475E0067BDA5DE505F99B7BDAF3EB556D906BC4106FF21F8F1 -:154773007E1A79CE4FD6ABE250878A72B52CDF8AB29D20263FAF -:15478800A3726BEE5429ECC90E080FABC38033A43FB6719C93FD -:15479D0094FF03D75B7F0A70A80DA881539F512B4E6EA736B0B1 -:1547B2000BDAC03CA07D7954EB2BE64B4877A41DE928DB34C57B -:1547C70036791DC0D28BF0039EF16EBF1EF84F96DCA5CC837208 -:1547DC0010FEC1ADD6FFAA8BF900F225C78D71616C58B7278FDB -:1547F1006B3856DB36606A85F843BE0773AE054EBBBA1BE290E4 -:154806003E39C070D71CFD4AEFE3B54AFDC96AC06DB57AB97630 -:15481B00F4129B6947BF64563B421A94433B0A8A77115E1EB6C7 -:15483000DB12B6A380067E73DAD2F6C49FAF2F0F6E00FAC4FB9D -:15484500B7B35BD7CF0BC6FA39F10ED57157446F5D8F749A376F -:15485A00B0B68F9DE8ED73BEF52FBBE87E9DF2C4DABE8A6C6F1C -:15486F001FE7019A5FD9A0B9810E1781F688BFAB8916AEDE0ABE -:154884006D0BD0E10EA0C30EE2E9C5B428B16991B4EEF5F17365 -:15489900C29550766CDD14D105DB4D6CDDD13974019AF86EB218 -:1548AE00E9027CD7B7B6882EEF2BA2CBABA43339D3B7B742BF10 -:1548C3001E29A213D987863680FE9B6D5A9D063A39B4D9F01E37 -:1548D800E971A6881E3FB2E9817D3A60D3E2123A006D8A695101 -:1548ED0016FDD4FAD2E8DAF5EC6ED62B663FD5374FDAD057C62A -:15490200FE7A7D79E26FFAC4ECADE4AEFF3CF5579FC8C01DBD70 -:1549170093F0CE6F6ED05CC07B2F96C5B47207EFD04F2BC4AD95 -:15492C00C0FFFE42AD5873EF2CBC975F0EEFA9C548F322BCC7E7 -:1549410009EF4E7D8BF10F3CDF779D8D7F5C13C17EE2E0DF5732 -:15495600847F17AD6D58F81DB1F15B897C0AC2F0DEF0E23EE01F -:15496B00A47F89C6058B66988EECD3DB74B0701E9905CB97015C -:15498000CF6286EB7D12BE49E03DA59007DE9FBCF763B7A9F5A9 -:154995003D5D8A54B254292BB956C1362C02EF61273AFAF6FE68 -:1549AA000B849D5AA3F84A3EA2784A3E6A8571ABFAD8F537F4B0 -:1549BF006D8BBB7A11AEC5F69DF2D046BCA5B28BC648F4477B35 -:1549D40018CE1C05CB47BB9125CED86D8F1F180F75A511AEE79C -:1549E900F3793FC429F4FD27A1EFE3D87506A693B85E82F2017F -:1549FE008C75FE27ECF8DF82FFFA9779FCFA8E505E2975976B5E -:154A1300FC36D4D3629C7597298C2C795F74FC768369A4F38504 -:104A2800FEFE99F5D6F2FF06E2E5D1A4A89C0000A7 -:00000001FF diff --git a/drivers/atm/sba200e_ecd.data b/drivers/atm/sba200e_ecd.data deleted file mode 100644 index d097e743b84..00000000000 --- a/drivers/atm/sba200e_ecd.data +++ /dev/null @@ -1,928 +0,0 @@ -:150000001F8B0808AC5A10380203736261323030655F65636426 -:150015002E62696E327D00DC3A0D6C14D7996FD7B3F5AE71CCD4 -:15002A0078592F3F8DD70F0AA949E8DD022E07F61A1644AA40C3 -:15003F00012D88A433EE52268844E8924B571792229D1B0F8EB1 -:15005400013B7DD0C7608813E1640D5E58529C6C909D101DE4AC -:1500690016357749A4E4BA8A7227541DC9AA17295C4A2F76455E -:15007E00259438EC7DDF9B19EF7831C4A1524F772B8DDF9BF742 -:15009300BEF7FDBFEFFBDE1B3FFCD3BF7F88B808896E2484FED3 -:1500A8008890844A880EFD1CB4BBA00DB710128396439B8076CC -:1500BD0018DA4E68B51FC3036D16DA1DB8364E88026DE92FBA6D -:1500D2001EFE486452BF7C63D90D63AE825E0863FB54E1A984C2 -:1500E700782F999F6AB59F9E3C49B19D522690D8ED9FFB737D9F -:1500FC00FCD38F45DB66F353D2B6AD1433AEF2F2F209D77F491D -:15011100BE34E18787275C3FF52678EDF13693B20B7EE47FE17D -:15012600E71A20BB45FB4AA95D5E29DC72DD983C8589E52B4C68 -:15013B00927E7959B9A987A7DA6E4DCF24842D778E97CC7F63BA -:15015000F90B6D6DE8BEAEEBF97C299D49C95956A43F7A5BF4D5 -:150165005F7C512AA1FBB7D87EF4AFBF99905E79919E97FCDF83 -:15017A00FFB93C759E5BCDF3F48DEFDA29E89C2A8EA109DC0E0B -:15018F005FF8FFFE2B387E24ACB3FC6765A432BB6F911CF4C674 -:1501A400C1977CFA72F2308031121A8EE3BC3E026FE14E96FF67 -:1501B900025AF9AA21793BD46B5B3B1A708EC8A429FF1CF1557A -:1501CE003E4F7C81FDC4977802FA5DC447C2618EEBEA932EC057 -:1501E3004BB79000C012130F873C52EDEA50657DA14AB86BAFA6 -:1501F80014D4B75C5C467C1D4F126F20B8231E269759EF9EFE32 -:15020D009D846F61249CE1FA03844C0B6A716FD52F20EB9C6518 -:1502220035C1447C7AEB6916F59268404FA9249C341086C4F6C2 -:15023700182477ACC79FE300570FFC87E3FBC3A4657AEB6A1692 -:15024C0085F4D4BE7FB34AE4F5AC7D7DB3FA3C213546D2DD045F -:150261007C32C81F7230EF6A9E22B7A8B81EE7116EDFCCCB8A9D -:1502760067E549751FF5B490DC6C5641483010844C26EF66BEA1 -:15028B006067FCC3B9C4E721F3D53DC3EE1669F72655BAB04CF6 -:1502A00095B6AC654B008EF03EFD6EBA6531EA08F113F958A63E -:1502B500F8F4EB015853B966BE7AB950A8FEB04D8DB4FF933BA0 -:1502CA00021254BC2478DA75DB3C456FC2D306E429775C5F2546 -:1502DF0078A202FFB7626115F9D9AB95B5608BFC601B04DD5402 -:1502F4000575C0F90BA1C39DD5640A91FBF4DC8A2D0DE780D715 -:150309001DC0AB3D1FAB26E3C3487898BD07DA0F053964FC6180 -:15031E00B09F6E2C85F4EFDDC054B2B33F93978886ED30B49447 -:15033300768879E085CA723BCEF75CC37918AB1763BB718C8F81 -:15034800E218973A503F887F41CB78FCF545FC0256ACB3E8DA10 -:15035D0034052D8BEE84341DF8D924F1874DFC62BDC065D1B458 -:1503720069396575E2BF52823F5CC47F03AE9BF17F2BFD283F5C -:15038700BE7DFE1BC41863C362AC4325B1FE8C3D3EF66ED31296 -:15039C00F6BE39FF0257281DAF69ED17F8883C2F83386A5A1923 -:1503B1001BB5E418C30B73E3E48AF573539E9BF37F2BFCD76E07 -:1503C600827FCCEEB1FE1E1B7F838D9FA45929AE521C387FCD8B -:1503DB00E143B62C02A73CD433A10CE3F647A7B91FAAFA55D204 -:1503F00030CFB4AD06B685FE0DBED990327DD38903EC5BB9A572 -:15040500685F6F5587E09B3474B0AC44A2105B784D2CAD1ECE76 -:15041A00B85B80BE512D77A9570A85A0D33FD6FD99EB3BC4FAF6 -:15042F00CE09D78FAD053C57715DCCE12B18A2352F4BE4DF3E26 -:15044400A3E73F3562F9670D7FEEAC3AFD034D21B14BAC4EB966 -:15045900475D4C7FC5F6DC3B9020F2BF81EF26793FC4F5605035 -:15046E0089631EE0D00FC49222DEE3788D3E00FDB481E324B744 -:15048300A8470EEE8A93DC7B10B366C4F7CDDCA178E9E3ACFDEA -:15049800FD956A27C4B7F6F7D7837DE688787987152FBF0532CD -:1504AD00C87598AB92BC1BCF26E134E7D056692EE07F3ED0CF67 -:1504C20033CC96D2CAB56AA12CCB24D72A55EADDC8BAC949C5A3 -:1504D700A50DB0EEB2E30AC28C421A3D4C5E56C05E0CAB886E6F -:1504EC00F23A8C67712DF4FF45113C02DE68FE6D03E4309096C9 -:15050100DB45AABB203749D1BBD5BB80A7629CBF17F86C6701DD -:15051600E06D6788F8BC40FB933677C4BBE135950CFEDCC09CF9 -:15052B0087FC728B5FC455F5515EED2E3BA9A05ED65592181934 -:150540001C30B244C0E918E7BB519E705AC4FC2A42FC2496D294 -:1505550047B7F635873457A377C309F0B30106F089DD3F9C0F86 -:15056A00364FF16B85424D9DF26B359AFF9457B94EA8B1FCDB9D -:15057F009C84327177E57915E18379C83D202BD2385A0672CBE6 -:1505940003461053742C63CEC97F32C0F601EF8697D559078ED5 -:1505A900C3BE4D097EC0EE19B0BBD8136BE99A8829F3A21ECFAA -:1505BE00CAE3AAB013E634CB4601878D1EADB5725A02721ADA1A -:1505D30000748276C8A27FA15F800E9016D959D40FEAE5975DB2 -:1505E800DF079D844D9D583CD83A09002E874EAA854E56AC5F7D -:1505FD002CF0900C0BB60AF9C00FF764AC07F676126B984CB013 -:1506120055E82BFA3CD80FD619159837071F671F423DF547CC48 -:150627009D9ABBB94EF94FD5EDFED9920D9ABB2948DDCDE3ED05 -:15063C007B3FE4F1ACE201DD96CA8CF2A1DC1EB2006AA3679877 -:150651000CB2CABD9BD88E3B896FAFB6B1C9BBE105F0796ED6EE -:1506660014E1A5ACB002FD803221E3D52B26CFBC5F7F80DEBF28 -:15067B00988492F15AB2470D8C32C12FE9EF63DDD98560AF85B3 -:1506900006ECCF8CF5F4E05E053D0AD9486CD0C0F501D8C35394 -:1506A5001C72BD05754ABA6D6364519B29DBDD753F5B485DC4FE -:1506BA006BCAFA6BF53A79F216B2E641D6939396B5F5DBC477B6 -:1506CF004CC8FA30C8BAC39435047BBBE1F7A67CB1E3FA532095 -:1506E4005F6DF63BEAD4489390AD2C36430DE9A1E66F635D12CB -:1506F9003B20628096FFDC38EB2553A0E5B81F85AE5007644910 -:15070E00D12FE4BE8CF5801EFA8A7AC8BD6A209D523DF4801E4A -:1507230074D043D0D24325E80169074B68831F4E194FF38472E3 -:15073800C0972AEED189F7E6346B6F46C6E6D1C78027EC8760F4 -:15074D00EF3AF72BEE55C253FAB5151EC10BC417D8AF2761BF9D -:150762007ECADD9543AA6BE659D5D53524F6EC11C79EED297B45 -:15077700C5DEB37E9C3F52DCB335E8FFE8D7CE7D3B0BE05046FB -:15078C00BF4346AD9C4C71EEE7B1FC943BCDFDC1CBF1EA46B191 -:1507A1005788F48AD452BDAC53F4AB5DEB45BC8E06486C8EF056 -:1507B6005F6EE65EC88572F20A93D6ACC59C974940CE2B4C4D3A -:1507CB00B05EFDB8C2662694C06E880F77A4541FFA4FCCB0FC60 -:1507E00087C7671D931ABD55AB61BFC6581BD118FA4ADA05352E -:1507F50041586188A322F20CD3A03568598B1F7CEB04ACF36627 -:15080A008FA9011DF3FFEF0D51CBE01EF84BB6DB3E6764B09B53 -:15081F00E9E04BC89773FE51F0AD1524C1B6E9879693F065A3B1 -:150834001E6581396FB61DCE4A585F7C435A0F9AB4B278CE7380 -:15084900CCAD4A8E3621FE34B9357E5D33D7E74BD637265BC568 -:15085E00FAA513ACA7DA492677758B1C6DCF47110FCCDD958C37 -:1508730034A1FEEDB501FD984A61CE8BF0B1B9803B950925C1C8 -:15088800A6164C8305238BF5A9CC647C22F0A6D48CF11F7DAC82 -:15089D00167D35D76F94D64FEB1E76D43FA2AE642C8AB58F2916 -:1508B200DF196CCD7ACFEA53689DF58F63FD1C0D7D1060A1FEDC -:1508C700411CD21AA61EC43D0BF2E27E1A572BE3F1F93E2FEEED -:1508DC0053C31FCCC6F17C5BA75C51FF86BE06E7DDA19D24F6BF -:1508F10004C39C9E7B40D4893C8BF50E9C875D33CD9A270A7153 -:1509060003EB2B92DB8E7006C2C9C119702E7E5A9C8BA747FA68 -:15091B00C59938181D54B1CEC0F544AE15676212AA8F4F8F3447 -:150930008873309E89CB8066FBFEFBADF3F0BDEAF32EFB3CBC70 -:15094500D43C7BDE10C78B67CF89F2349E3DDFAA29397B62AE9C -:15095A00B6CFC3B992F33087986B3F373B0F7F4D8C7C4CDB1875 -:15096F00F11C3CA3BA601DC6BA3D10C776BF9B56BC55C7314647 -:150984008A5A40C43898C739A0853569CD9CA4A7C98449A13EBA -:15099900A222060A9B891858EDADFA15F8C48098DB4EACF36D2F -:1509AE0091DF1EC423D60B9D9B7024F62763F7BB19657A24259F -:1509C3006C00670103C726F7FCB3217C16EC1BA8492A585360D5 -:1509D8002C47BF7906F9224BD94BA843FB5EE0366C531F98D827 -:1509ED003613DD0B94C796AA28EB3EBC178056DC0B403BFE5E71 -:150A020060693CEEBAF15EE0EB6CD6FE17B0D944FAE413D8D15A -:150A17005B750FD830CA2C7939CAEB6D9D6DE290470CBF43DE6A -:150A2C00042153049FAD7D967D070C8499DC73613C3F729F6190 -:150A4100E39D01786D5BDBF1E9CE478AF1C5E5EB107ADA94DD30 -:150A5600D3689F51E58D49A5A67590C5800FAC0FF04CAA79CD1A -:150A6B003C8DF05CE80DFC0A748363EE92B161475C9A41E7F61F -:150A800060CCB93802B97A659F1AD0D07F1A18C81E708580C77E -:150A950031BED23C564648A3E66944597640DFB5C63C7FE1F838 -:150AAA00E1DA2106B508F7C82F412CEF33EEA4A70D29B9C7210B -:150ABF0097CE104EFF119EB74C5C4B268B2B79AA880BE087AD61 -:150AD40073A08BE8784634F0DDA6F34DE4D11DF2F43878D02783 -:150AE900290FC2651E30E5D11DF27C2DAE1279AE96C873F536FA -:150AFE00E5C938E479C7C1436692F2205CFE7E539E8C439EAFE6 -:150B1300C55522CFB51279AEDDA63CC991A23C67478A3CE0F891 -:150B280064E44138D99207FB4B268BAB449ED11279461DF2440C -:150B3D00ADFB0C19F3B9E5E3750A53EFFB09D2357D04DF975A45 -:150B5200EF19EBBDDE7A47FAF83E43BC2799F065A0B1AB4CB4FF -:150B6700ECAAF59EB6DEAF59EF17ADF751EBFD1DC0B38B9EE038 -:150B7C00D8D760AE93BECCC5BD03F47BE86B5CD403D04FD337E7 -:150B91007994DEC5CC73C5592303EBE05C51334BF33407939EC7 -:150BA600667FDED3EC053B606D8F3236D05302CF7658BB9ABEDF -:150BBB002AF074437F337D83E3FAB74C3E38D2DC4E777313AFA4 -:150BD0006E0C025EBC6B5841DE6167B6BEBC5CDC59004C15F5B9 -:150BE50034E2D80B5B5F136359C7D8335BDF1463C8933DF6E484 -:150BFA00D6BDCB6DFC7751D37E886796E8A7F9768B3EF2B4B65E -:150C0F006E60998DD386455C36ACCD2BF216B26011EF5F514FEF -:150C2400B3B84BB1743AFC88A9D39CF8EE61CA3EC3CE1F304F8C -:150C3900C7CD9BF4EEB6700C9A638CFF9D09F3A1850369071099 -:150C4E0007CC651F2DCE452C3DC6617E1DE80F75C7A01FA7072F -:150C6300399E8FCE099E2E0B3E1FA5CFF15EA1DF1EE3F48870DB -:150C780040FF03D73D4D7B67526543E88D85CFE692CA0F962315 -:150C8D001F9D424715509B2E592E352D0AED5EC861EE6E319754 -:150CA20011FC56243D8DB3DE949A82A1830B0D98AB5A6EF28FE3 -:150CB700FAAA807D72FD2BA9E98BDAE7161E82B93F367B9A2BEB -:150CCC00B4F2C6CF2EFD2182387F57CB22B8FEB7BD831184FDD0 -:150CE100E0D269C8FB3B044DE03FA38B7686E019E4CCC444BBDF -:150CF6004BE026E1682629DA84E0036A8E0CEE89E9172EABAEBD -:150D0B00F735D87FAFB0CA60268EFA31D75D36368BD6D41109F9 -:150D20006B8602EDB495C755D7FA47A0F6D9CFEEC05C097A3363 -:150D3500E9268D0ED1EE303A45DB23F4590EE705D7FEC701FEB1 -:150D4A007BAC2A1806782A6219C20F8A36619C15ED52A1F32969 -:150D5F001700FEFD7F10B5D5D4600CE0A386C977D2E887F6692B -:150D740061875D467AA498DB4808EAADB0226CB30D6C93A007C3 -:150D8900B81CCCC1D845B6B4CCBA2B17ED45A301DA9DDF273E14 -:150D9E001E76B7C0318F1D182DF8D1971E85F14A7A02EA055D0D -:150DB300E8AF0CCE160BBE8370E6BEC25CB9CD82457D5BFB8D79 -:150DC80061FF29A029FBDE533B9625AD6F6D507FC1B896FF8DAF -:150DDD0011681D62E8C0DBF3AF1BF0CE75E02D104DA9B20FCFF3 -:150DF20039EF1B121D323E69B0F8A1B3D9F52F4D1A4761BD6C70 -:150E0700F1C32D7E8ECE29F283B9EE030B36EBE0277B0B7E623A -:150E1C000E7E36033FF0CEF904FC6C76F0F39845E33DDC47160B -:150E31003F598B9F4A073F98AB5659B0E86F363FD8BF193F51AC -:150E4600073FAB811F78E7C909F8796B71919F8FBE30699C1BBB -:150E5B00C19C66F28334909FD6D9457E30D79C3161052D37C413 -:150E7000D68EE694310A676A3BC63A3F0F6874906BF434C4E84F -:150E8500CD4C0EDE173FBC2CCDF0FF560EE74E2AD65D9091B78B -:150E9A0062CA7F8CE0652EF17B1D79334EFB7959D57995E60779 -:150EAF0058714DDAB868C5631B5601B86ED8DB7E888DCEF53124 -:150EC400DACD37037D05F850E85178AEF0049DCB77D105E03353 -:150ED9000DBC9346C056AB799DB24D35C8A1447D3EC5BAF55427 -:150EEE00A207E093F41C4F53C60FF79E663564409DB6A597D514 -:150F03005EBAC23AB67C97EDA99DCFF66E59C8F6F52E639D97C5 -:150F180056B223B56718DED37CFCDB32DCD30CFFB7E7D9DEF32D -:150F2D00ACF2C231F5E0A5FD500FEC5FE2E4EB9D30F155D1D593 -:150F4200CD6363B176D6B090F8FCCE3121403B3B7A93F1CDD75E -:150F57000A378C2B5A3BC77889FA09D44FB08EB7B33B9B26184E -:150F6C00875AE06A1DF179434911ABC046F2DCE4318EF6C5F74D -:150F81004F46AC1A413EC789CCB844C51D2BBF8AFF6810E6FCBA -:150F96009A687BF8A8DBAC7586451B66A4007551554AEDD6878E -:150FAB00946EBD5F9926A5D4236543CA91E88072186CF9ACFEB4 -:150FC00086E27DEF0FAA8005E0837A9722AF632AFA4185833FB6 -:150FD500BC8390D890187F52AB6CFCC4FE770F2B6EFCFB0A33BF -:150FEA003F6A63B934C991E73990C72A925F35CC4A3E8179C4C6 -:150FFF00CA8567451D63E6AFB366AC039D99F98F5B303D026617 -:1510140047314F8AFDF09845277B039D3BC6D131F3E559510FD6 -:15102900D97432169D0F2D3A264C0F33E3709A87AF12D21B76BE -:15103E00B5941F48A981E83CBCDFF3FBB5EF468290ABAE5E372C -:15105300E5FD40FBEBC6CBD0F782FEEB14380779061290B39AFC -:151068005DA1745CA678DF1B66C92CC489A4AB65333D652C022E -:15107D001C92FC3DC8435D3C14DD1F3948BA13788676877AE21E -:15109200D23D50A3C5468CB974C4705BBA8ED02E234A0F1A8197 -:1510A7007C8A734F6AE702DA67605C895D0039F2FD5C069C38D8 -:1510BC000E276206072EAF93E6A617FA9A9DEBEB9443AA61E19E -:1510D100C0B5D8475C147049A1FA78B464BD1FD647E97306D4F3 -:1510E60010D6FAEE09D7E7FE1173537D1C7909C3DC02A833C232 -:1510FB00B48BE1DD96413A120AFD2FC3E3C238779A19E470422A -:15111000D23A0C3FE46037D6BBB17EC3AB751B95DA39718F365C -:15112500DE8FCF5A7EAC8FF3E331FFCDA614D9E1BF55502B8C04 -:15113A00F928F801DA0F7DB4FCC0805A43E6A9A66CF5A66CD11A -:15114F00BE66A73F0768170F6A529384E766C29917ECB1733E0C -:15116400F1E1FBBE999DCAC54DC4F7E2CCA422D3F9C236ABD16A -:151179000EB096AFEE7E085BCF52F13F2D15B383264E79893719 -:15118E002E43FF568F0947444B8336DF14F65D1D91AB16A81DE5 -:1511A300EEF90F79AC71EED71FB2E7F1FF6AE4E8DC07251B479E -:1511B800B4FB41BFDD5F591C17FB04E498438E36617E801A931D -:1511CD004E8BF5604D631CA2520BD51883B37A0061360998CB74 -:1511E200D6779F4EBCA3A0247692076973837DCF82DF034657E0 -:1511F700342F36BFD19B7797884F4E7633C487637EB95B7D077F -:15120C00713AE82F17B829C33B5949FE0CE87719B80EE95BEBFC -:1512210032B80EE89D71F62F3AF158BF83B9E39073F0FBEF1552 -:15123600568DF74FFC285B8BFB92DE1B09D2798DCC8A0F3FA1C4 -:15124B000F35EA629F778AEFE5BBA75C413ADC2F3F67DE75C28B -:1512600018E4AB1A1BBFA4CD6558B309D81F7EDE4272FD7C9ADA -:1512750003B6C2829520374F16EE10F0BA0AE2DD0B5A5D13D6FA -:15128A0008E677FE432A9C9E184473435AF339F8E46CD63B4C08 -:15129F00104FA67AF42893454EE83FF3BB42A11AEF06B789B5BD -:1512B40069B17681B69FD5C84FAB776AE759448333656C9E811D -:1512C900F489DC6F081EB09F4B19923C5745DC52FEA88DDBE4E5 -:1512DE0011F6DA589FA78C2CD058A44D6FACD2A6477EA04D6DF9 -:1512F30044BE376975CDB67C923C5B2D956F3273820F7BACC455 -:151308007E7C18BF7D9F03DB65E24B08A9C63AC6E53BA7BEE98E -:15131D00C2FBC734D64D747A10725E6CC8C0DA424A0E31D7BBE7 -:15133200E7D5FF065E7B5CC48BF6C77BF9465AD358456B227E15 -:151347007A47E366D0D32A5ADBB8CEB237E2A8965F1577D4E057 -:15135C000C34289F51CB80C60298AF86BE1BFA088773F6B90BB5 -:15137100E15DD638AE0F26E78571BD8CB2027D19F8284CA5ECCB -:1513860008E953189C8702AE3EF17DE059F17F5203D67D685A64 -:15139B009CD1719F797D57D4368823337C4755D7CC4EF57052CB -:1513B0006AA9B9705E9D23EE5933868EDF5E760E88EF34384755 -:1513C5008E0DB1CBE2FB0C65B3C8A9E508432C18F17DA56F880C -:1513DA00CDD2BE6A126B89398EDF4DF4248EFFBC89C883064DB6 -:1513EF00A6F03B8821AF1950A330EED79AC5B817DEA980AB6D72 -:1514040092F05E22F6BA7118FC026582FD5F8D7715B3A2A71B27 -:15141900C59D456ED038AC4942EF788FF70CC43C5BC6A0252368 -:15142E00CA11B1F27D7D01CF75FF43CC13064755A4D993BC91CC -:151443001988C3038611280C0F1CD6E045326894648038C168C9 -:151458002556E40688EE7B5CD089266EB450729055768B5B5FCA -:15146D003081041F5CF34C206BE1DE84CD94932B2203071A3D8B -:15148200ACCBDE79BB68A5AE721677C7D5B9DEECD69E4779615E -:151497008D6CDC65AB38E7BEAFBBDFCC9BC9A0E0DED5FD987AC3 -:1514AC006FBEEEF77D5F7FFDF5F77DDDFD7547F5F31B315A88AC -:1514C1001BB88ED10BB618607BCEF31C0253B2E941318E59B05A -:1514D600E751CCF18671A03F4CDCB28FC53814642D3F01387A39 -:1514EB00433155770FB3BC0699D9A328ABEF954FB03595493179 -:151500002F4698A20CB3BD8A291B2C2060E47206562A6057702E -:151515006D46C454576DDF30DD1B292025CAB0698761DCE8CF5F -:15152A00819102899467C3E8203CE5C8192A83AFA9C032D15E21 -:15153F00DC8F21F4769E6B22BEBFF4E59C7F70B1EFE3D4E291CB -:151554003FC5FFF019EAE881BE606BC0316AD10929C3F44592AE -:1515690030FAF4188BBB3F01BB07D1C3168CBB93E9B888CB7601 -:15157E00C1548AC935947C3DCD6728F916EDE819566B6CBC2309 -:151593004EF46F7DA14186B319437E5C0345D9C8C3B42F1C65B4 -:1515A800F07A019F12B1117B029F3EDC2F92193EA6035EFC1FE0 -:1515BD008E1956FFA7447F768BFE64BA60C90D6224A00FF3A197 -:1515D200D7696F826C29B2D96359B4C7259E72CEF3BD2FD3E9DE -:1515E700C559F685CBFB75B6CF555344C27ADD1915C74C0DDB68 -:1515FC0013E730B2613AACC00E2BC6711C376BC1E339C47B8D20 -:15161100CCE1A1E409E0F7049D3FC9E4EED3053F0C0636CD57B4 -:15162600191773BF8421C3372C8708FA8C3DC3678CD9888F0E7C -:15163B009BF9EA933CF549BAFE5B5CD600837773773ADE8E53ED -:151650006931CC3E443BF19DB5C90BBC5B6D82F729479CE97FDA -:15166500C09B29DF579729B7607BF3C0A40DD3614E3B2C67FFB1 -:15167A0091E9BB1863D6F8B58FED8E9CB18D4FE7C7710DCBAE50 -:15168F00F58D9EE71BABEC255B19C674ED8BC82CCBA6A03CAC55 -:1516A400727C5F72A1536BC8299F85B4EF47DA71A3028C776FB2 -:1516B900C4B945C6BD0EC0157E28639F5037702C5865E5F6325F -:1516CE0090834BE0614F1B8EA21C1C56FBB9FE71989E0B037C5D -:1516E3007B2C983703D3F3C0667AB261D8A62E5B9B2D58671E54 -:1516F80058A1C70ED38D4431D8B685423E246AA0FDC0F1E915CD -:15170D00FA1E4FEB3BC0D017D8D63A4811616B1AA8BF5EA6BF42 -:1517220031C3D2F39907713D3C418FC2B8F785B86DCB8743BE31 -:15173700611C5086397BF230D6331B6CF350B4EF681FB7A15DC2 -:15174C00C1B526F8EEC0C2B8CAF0839EC14490E683CB36B861D9 -:15176100AFBF203F5C0678AB43D8DF626E732D99615C500F659D -:1517760079E5E5CDDFD6591F27B43E7DB8EDC0C284CA7310AFE4 -:15178B00436EFF8BB8B09D5FD507C68DF0F58D7165F76B42D8B7 -:1517A0007BCB77737B9C2DEB6C7B9C8717F886F302710A3E0187 -:1517B500F76CC4C7F6C3F3C8214F7D92AE9FCDDF6E9BDEE11865 -:1517CA007678A68F71E2993EC60B3CD3C733C903DBEF9E3EC6AB -:1517DF009D9EE9E359CA8161FD57ECDF66E6BC221EC371CE7D03 -:1517F40003CA7489CDF7C15397785C62129B2F9473CA245B99AC -:1518090037A7CC652B5B905356642B5B2C0B3F129834E23DC8D7 -:15181E00972EF2CBAD582446838A3390893D6294E5EA425F6464 -:15183300628FA8C6E38C9CD853CEE4C8C8BE924647DD2AE853AA -:1518480098670742867C3B2105072B357D32E5763A3AD5367878 -:15185D004A20935E85AFC3FE0874EA70F4F7E5646A805EE941AA -:15187200044EC44576EDFFFFFDD5D610F7D86729370D75A835F8 -:15188700F749EBACBD4DDC2F24EDFA293667688F9E1A67CFD1D9 -:15189C00532CC7AA3D796A929DC989D2C446BE16678B410D07AF -:1518B10019FE18E539713F71ABF7F3BC65EE67BBC1CF0E829F2F -:1518C600051FC9E456C2E466F9EA1AE083783AD5F2CF84EC22A0 -:1518DB000E263BB47D51C0E307F847F749AB91D6D98D7C8C8CD2 -:1518F000C013D71B1D0A8B154DFCBF212BF68CD107BF617F17F3 -:15190500B179E0A4896D045924842C12421609218B04CAA2F079 -:15191A005E57A33D7EB95EF9E158F228CB033395AEC0D1422EFD -:15192F002B0EBB13600702F12CD83D00EB0B9CB66045089B0F62 -:15194400B05B03A30863FB3A5CA6572E810C4196172F4D9765C3 -:15195900C37AE2BE700965E95F7DBDEDBADEF69CCBA30F054261 -:15196E001F3EAA26EEDAEA6C3E2B24E2AE075E9CC0EBDA3CBC7E -:15198300C6A17E29E3B574F58DF4C1F5F27B3C0FBF8582DF525A -:15199800A0DD1F9AAEBFFA35F4B77322E52E8076B44F4C6F471A -:1519AD0012F0344F603BBCAB6F54976EA43DF13CED91447B1A71 -:1519C200818773F7417BBE01FDD6FF8236297E2A2BA594D97E0D -:1519D700B0798EBB0889001CFF4BA4D6D88DEF01D550403A8B99 -:1519EC0015CD9495EA57D91E33D899FA08AE37478DF001EE1352 -:151A010095837CAE32FE32F86249077FD8CDD64B0DA837161922 -:151A1600328B9A4E9A139F72DC7EC09B9AAD1B53F0DFC1FFBBA4 -:151A2B002E7C9ACDCF0551F70A3C1B20DEF42A9C1E51393DA4D7 -:151A400083F4D02BDBE92D867A454D43663DD0DB2D709CFE9440 -:151A5500D3EB14F4E0BFCB2E4F59C8B3086489E5ED5524AB7C94 -:151A6A008E65FFAA7879434EF95C513E26CACB73CAE789F2E328 -:151A7F00A2DCCBCA278D1A9A39CF92823652D2A5E2DE9D0B7DD7 -:151A940074CEF9956E888768D4B905E28CAD55B8AEA977AD2A29 -:151AA90056A4A02AE29A9E8517D5AAD0BE60AD2D5F60CF48D3BE -:151ABE000728ABE7DB3FAC0AD8E01FFFF0E5AB085FB3F5832A70 -:151AD3007B7EC18537BFFF1AC29FF8DB9F559162DCDBEE373A7F -:151AE800FFE5856AAF4FDF4A1E236E974ADCD3F8B4E58F2987E0 -:151AFD00B2FD338F35264DB4210E0F9FC331989CDD362B3EC2C4 -:151B12007A3341D7A7D6F2DC19ACDB5337ACCE8C3C12D85FC732 -:151B2700EC391DB5EC39945967724637E69FEF1B9FA7DCF14B5D -:151B3C002977661E46B55EDDAFE2BE0AC48DEEEE8551753D59D3 -:151B51001EF490E5AB16298EE0799045CF42AA6ED0FDC17369BF -:151B6600B9C4D99AC4CD4C1E740FC6284E88F50673CADDB672FB -:151B7B0009CA3B3372ED2E9048B70BCA1D65D07FA2CE22E6D307 -:151B9000F8B73741FD0651FF0EB0FF3EE1DFB0CC07651584EB9F -:151BA50013FE5F7261402B81FF8B6C75965C8869DE1C7E1E8494 -:151BBA007E4A4462A60B7C6CF96F53EEE8D594BBF9CBD42CD1C5 -:151BCF00BE7511B0D3A03F5976C52BF45442F9839E86927F6EF3 -:151BE400E84E320BF50CE3600B37AE5FE21EA16CE30B73854FA4 -:151BF90047980F360222BFA108F02E00F97B9712B7EEE7BABFE7 -:151C0E00600DE016FB3054F8F31749BFD13B3AA8BEB90CF7E984 -:151C230002068F654B0C561EA830D07717B863DA0F963E5CEE8D -:151C3800AD8CD2D65732F1168577A90F2255788EC2EF1CFC9498 -:151C4D005EB0AFF01B17BFD65EBEFE85F82EFE12D7BF94C6F455 -:151C6200BC4CC0A3FFC1E161012F009F5683EF7480CE837E2B7B -:151C770000FF50CCD618264DE9DB84BC823E830E9896DCADF9D7 -:151C8C000796596D9394037406B3ADD4083C4A48D17FA6DC93CD -:151CA100249BAEEE22B370AD1BF1FF33CC476702DD31A81376E8 -:151CB600733F65E191051EF932E76DF493947B90E7F5883A101A -:151CCB0007D1210DC7EC646A361B23B837D6F7F7C7198C4CCED0 -:151CE00026DE9F0EF277F883F2CED48D9AB89FD6377A5C9D2F99 -:151CF500B1F50E93EFB3454DDC575B6BA3C3D71DFB8DC7C61FD8 -:151D0A001B5F363A98A53F37A3FE209FA043814ADCA386B8203C -:151D1F003C443146DBAFAC0BB01C45CC8D8BBC4B95C819C3C77B -:151D340072E8BF303D7CED9BF68A7557BE8E3BC2F70C020ADF8D -:151D49002F40BA387EC227CDE7593FDC40FC373E8438D2F3B0B3 -:151D5E00AFE741D0065A69FA79F475DB3AF0CB69FB17A5E3B899 -:151D7300D62B1BEC9C14192D20E037D8FA3EE0A0631B591E841D -:151D8800CF9A67CD2103EC0C12CA784CD834FCBEFB5EE296C690 -:151D9D005FD2E40F5F52ED362D6D77D99C6CC448FDD57B923824 -:151DB2003324A32D66F3191AA37790C120E6EA4FFDFB7095BD05 -:151DC7006F6E1263BBA482E45D1FE56B9BBAC03B22F026742EFA -:151DDC003FC0ABC738DE25C7B3F0CE1078C757E7E0457B08F1E8 -:151DF100D5BE85FD2A3BAF0F3610F126393E7D19EEC9CB83B482 -:151E06003039AC4BC933BAAB28C6D6F966029DB961AA3922869F -:151E1B007128296D91944EE316F91D6D2C95F279A25230334FC2 -:151E30000D1B1877EE72A0ADAA6DB4CEDD635E358B4B587EE23F -:151E4500A4A9E2B3B8A291C80FBCCAE64201E554E8D13CED0713 -:151E5A00FF15E847FFD5CFFCD7BE8523AA67B4EB5E466F5CEA4B -:151E6F00A49571CE7B38A67B301E13F082484C972B13AC7D8726 -:151E8400C801D584B1ECDA30C8F6D1BE85361EFAC411194EB76D -:151E99006F6E6830687DCBED46FA7D1A3FFDFD997CEC7DE0FFB5 -:151EAE003DBAE0875E831F80CB601F91173B4D07DF4FDF9375AB -:151EC3002604ED1501BE8B47F83C5FC44F203B2E1F9E4F922D53 -:151ED80047B9EBD5ACFD0B186FC88303FA1AD73F43C9237B8A4E -:151EED00F95C4DFF25C07BC351D5E5116B64C0D3C5421DCF3873 -:151F0200CFC2F2B64D3C470A7DCC3231BFAB653A12D7FF14CA3C -:151F17002CDE19DF507FD7261607B33C8E7A51EF7BB67AD5C94A -:151F2C00D7F7C04F47786213DBD3D0314F00DB82F349E4A3F77A -:151F4100A598EA1DE5FC20DCA2DB2AF09DCC4377C446779BA8EC -:151F5600F7B6ADDE7AA08BF5466DF5DA44BD9FE4E16F7DF2845B -:151F6B008EE3EA1CE3F16F74F403B5789E06F83BCC746798AD4C -:151F800015F7FE1DF04A0619AFB5365EDB05EEF7F3F03A6EE3A1 -:151F95006197A8F78F7978BD60ABB75BD4FBD7AFE035BA39C326 -:151FAA006BFDD7F05A6FE33529700F6C9ECE6B7C7386875F8943 -:151FBF007A439BAFD19F9B33FD59738DFEACB1D1BD68F5671EA7 -:151FD400BA2336BA13567F5E836E77038EAFB328031AB6D3C5F7 -:151FE900F68AFB3F106EE9FC7EA87F84C4D23ADFE0E43A7FD59C -:151FFE00C1755E6FC8D00E3B39ED8E86AFA00D741B045D8B5E7B -:1520130083AD9D0D02474F7E1C14C7ACB516ADE6DA3C3C4FF630 -:152028005AC6DEB1F18CE771E5E394F92FBCB7473E4D31CE73E4 -:15203D00157569FB206E94C197C9F5EF6A0B8C33DA41DCA3B7F4 -:15205200D9A01F40BBF2D91EEB3B9F23A61ED18755D417BEF704 -:15206700774085F9EA1E9C9FAE67B832BEE12EC055007E216DFF -:15207C005743C3AA6B438CD954664F2D7FA1A33D8D317B2AD7C5 -:1520910001FF60471DB6F7ACF61663BE4EBFEA5848B514E65951 -:1520A600E0BAEF659EFBC57D5382D3A7C29E86FB786C07BE8FF4 -:1520BB00B765909DE791C3BA46D12F4586C12FBDADB9A2670C99 -:1520D000F44D79FDC98F32F33B9ECFD0A9F970BB1AD712C4FFBC -:1520E500A9546A5EEE5C8FAF47B2FD70B3640AECAB1BC656B88C -:1520FA00D4A0A18E36B4C5AE426E93252BCEC6F32DBF4BA57368 -:15210F003F9529969F39DF9E372855F27B70545B3DBC8028B73B -:152124001EFA84C30A9EA11AA188E7093C4355E6C0DBD558FC4D -:15213900EB284E3462F92DA141ED96D0DBA8336615D6C19800DF -:15214E00F3A901EEDB1A3333FFDFD618ECCF6218A3101F4D680E -:15216300FCFBB7D1A77B0B3C1DDA7BBFCDF0E49F6271928DA775 -:152178008451454EAEF1298E80451BEF02BA83D18C52ACEFBB81 -:15218D00F50B33FDBEEE8B349DE492936B0BD2795F309F147980 -:1521A200F8C8D7FC5B3127A28F9AEC2C5729CB19BA17C5217371 -:1521B7005CBC6E9CA2FCC12D9AB2BC17FAFA347CD36B4ACA69E7 -:1521CC00B3D1164F5E7C84906714E79AB30E316FCD43E7218C26 -:1521E1005DF2E2F69B4EF94DC07DD620B4CF94A2EF9A986F8196 -:1521F600EB9F69DF8DF38A42317E11EFB7C57D14A20CFFE7B9AD -:15220B00EF83E596A21E4DCC40BE127482E78C5397E0CF65E79A -:1522200003FA1BF945BCBE6082E51BB1BC0FF9A4897CC83F5F73 -:152235008EBC73DD13EBF1150319FD463C138F703CFE298E9FB9 -:15224A00E34D30F9CCFF791775C01C0EEFAFE823C32A9EA3C3D2 -:15225F0098977F9330B14ED63800FCC707ECF7C9F07623FEC926 -:152274004778FB389D78161D6B4D00EB323926B91C6FD9DA6987 -:15228900E23D116C4E63A7993E5F1B32382F1586CCE4526BF06A -:15229E009C8480E112F9A00C1E1EA44F2DC5D8F518CB47B4F334 -:1522B300E07D6D39B5F71DD431257908F7E6A9A5272CC606DB7A -:1522C8007A9874AAECDEA8B0C1E4827C61B904EDA515BA819379 -:1522DD00E4C2A24E8D1EB8533B7F21E526E3036CFEEDC53E92E8 -:1522F2004F6992F22EF545F8F9796BEEB2A070FAFCA9A36E8876 -:15230700CDE7B2E650E327CD7B6F740E15FE4BD3D229CC23ECDB -:15231C0077F2F969B64E711D425E4A845C589F04A33C7F4D1EC1 -:1523310030713E8DFE0CF5097580C94AE773E9A35FA6E6D8F47E -:15234600384B9F59DE7800C63E9D30E6F9028DB87EE2519697DC -:15235B007F88FE14E6E9CF287706AFC098BC2BE965E7B07B1FA4 -:15237000E5F4E38FE2251B0798DE610E97809B083F27E6B551F3 -:152385005137915357C04D841F15E3DDC2FF9EF8E67CCE37023B -:15239A006E22BC55E03F27EA2673EA0AB889F0B502FF3281BF77 -:1523AF0053D4C57AF8BED8666FBA6D65F88E67DBF04C9B0BF426 -:1523C400A8107C95A40C98282F49DEAFA19F092883788676EE70 -:1523D900DC505F9504F3D3F91D135A9132642ED22FADF5557FB6 -:1523EE00A64991D3E66B51E71617CFFB9C373332638D14993002 -:152403002D9D9D09B62D7915D7D13263E0FBE02325766E884EE9 -:152418001B8F627CA5ED0AE2900F0E68BD85832AF23677ABDF7C -:15242D00B4C633D301B409101B3892EFB2FD46FEFD88993B9E8E -:1524420079FE24D08431631F272FDDDCA925FE89AFF3C9C2A6AC -:152457007DDD38D98BB9A2D618E91960392BB2F0A7385696619D -:15246C006E00C41A8FB1B5F7CCDED306C51910E7A9FEF0FD47F0 -:15248100DB78AA2DF83FB0D139F1445819A04E4F17936729E02E -:15249600ABFF2CE377E9E7397E1778C13A44EEC03326265B170D -:1524AB00298E373A0FC6B43ED015796D8CDFCF00B8703D05C6F8 -:1524C000E33C764700F8662CC77BC33087D8F2BFB8BFAA46965F -:1524D500D2420FDEBDD7618CFF3A435BCE1387B8224097AF4988 -:1524EA0098D85F7DE0F7E5B303C6154113FB378B2694BB7268E4 -:1524FF0066B7BFA4B1C1463F6CA3AFE4A12FD9E82FCE43DF7F80 -:1525140083F431BEE8AC0C18162FC8C3D825CEC362A0954B5FF5 -:152529003E3BC46829910103EF4082B9B789B18FA4F03B8F16DC -:15253E004706E861887BD0A74DD9E31C5C7393FD66679DA1E108 -:152553005D60532FFAABD87E5FC96D2BFC75CD41E54F2A2AB7BB -:152568002A0FFEF1A60794CDDFDBD9DEF2EC4E6553CBB696A616 -:15257D009D2D41A5FAF107B7EF686968DDFEDDEFB4B63F5EBE5C -:15259200F2EE9501A5E4999DAD4FEFD8B1FDB9C79B9E6F0AADAF -:1525A7005A55B9EAEE157F7497F2D4D3DB5A762A81CAB255156B -:1525BC006595ABE125581E0896DFADF8D3FB5B16BDB2B2E696EB -:1525D100B6EDED654F6E7FB6ADACA9B9A96DE70B65CF363DFDA7 -:1525E6005CD9CE1D4F96B5EC6C2B7BEA85B2A6A66D0CB66DFB24 -:1525FB00F6B6953B6F5B758F72A7D2D2FC74BBD2DCF254D3775B -:15261000B7B52B4FB6363DF79D16A564577BCBAEF61548E5FA76 -:15262500F037EF78FAF9961D654F41B31E6F6A7FF6F1E61DCF95 -:15263A00AF7CF2B67B2AAE853F8D9E9D679AE30B37EE67F71A4D -:15264F00F88DB9BE8AC612A59CAEC4B35CD6398D88B406EFD1B8 -:1526640038143AD25640FA8DC6DFA7D2E7341A958DE627BF703B -:15267900AC91E48735BF526DF861EC7D0CB6C40BCF37D176E26F -:15268E003E09DD6FB47E9172FF74A9146C50866829942D22C3C6 -:1526A3005521A587B2F2B0B4370030B4376B6D30AC27830F04B5 -:1526B8009C66B752B4CEF2090BC036CE203C96C0FF5701F73E78 -:1526CD00F9E5368C13CFFD756A16F2653FD7603FD310BDC2F71F -:1526E200CABA58FD12A31FEA13F9B2E9856FCE027D3B4FB48D99 -:1526F700B0B3D32B1D642EF2877C78959314DB3003E6A998E3FD -:15270C0046C657E03EA9D7577DA7866DEF02393A7F52A9E1B5D5 -:152721006A7EC0C5D7AB0E1961E58746CD08D08678CA0BDF5BC8 -:1527360074F01C97B77A850630D34EF3A1548AD1EC62FD72CC9E -:15274B003C9D4ACDC1FBC4F8BA738F7113F805C439F916AEE733 -:152760000700768CF1E5047F7908F90AEFC775B9F956BF5967CC -:152775006CA2BFC3BEBBCCFA0EF7571405C69DDC957029F7980F -:15278A00CEEAE3D0DF07186E1C8738068B94D7CCD22F1D6BED4A -:15279F00EBBF28734BDEF67EA87927E5FAAAF2D27752B3ECFD49 -:1527B40081FCC8C08FD7D65F6D1197114DFEEC556C93121D4848 -:1527C900CCC13BE7E8622314ED4890E2B6464F926CF14697828B -:1527DE003F3EC7EEC3F3F96AA1ED0F18787F29CE1DDF9470BE3A -:1527F300A41A18D348EF3FA3E11D51F5B8CF12C6B3DB611693D4 -:15280800F6EA41D50C55AEDBA414ACFBD079D1F0856E67EB8DA0 -:15281D00462235EB23B12F128AF6D09BB2F4A01EF3BFE763BD01 -:1528320066A8773ABDAF1231F07EEE40B49A12F915EA666D83D9 -:15284700793795F63ADCEB35DC4767F617BEDFE3C0F58C8BFC2C -:15285C00CEAAE601889DCB204E78925E29242ECFD880F69872A0 -:152871007370AE72F3AA3796CE0FBEBAECD6E018C091DED4894A -:15288600D4AC658A23C8F8917B0C5C7376C1383C0F7A9FDE0F44 -:15289B001B3FC6FDF1F831F32F1696A86C7D186CE4D142116F97 -:1528B000290EB6761A075C565DAB5E3BD4395837A0E29DA7C812 -:1528C5002FAEE7E6D2C2F18BDFB7C2F7EF39385FB8A679E10D71 -:1528DA001C3F7BE9E2A241CDFBDF47282A4A6D14CFB45F64E72D -:1528EF00E7CCD0EB6A1FE05D5454AADD8577C28E47D55272D174 -:15290400E80C9D68C33D2E05FBA96E8566429FA0AE38770F1B8D -:15291900B8B71FC4F58EF08F791F88B18B31B4C4E6610AF015FA -:15292E006A64FC877F6C8E4DA5DCA70B783BD7439FAECDD37719 -:15294300308F9E9FDBA6DEA914CBE9403CEDE2FB4530C69CE3B3 -:152958003A8C83FD4601CC4B42C923863196725BDFCE80B1811F -:15296D0036F0AC903BEEA7A22CC22007AB4E3F94B1F7F1970D63 -:15298200CCA762FB8F50A7F48D6CD95F0539E6E315C7ED82680B -:1529970007F57FCE653E359CFD1D933FEA33B305FB0D4BD6BDC7 -:1529AC0020EBDAE88079F5B8F0F9F676A34E8A761FFD0D6F378E -:1529C100F63DE2DB05F84A599F458C5D2C6E133AFA2BAEA378CF -:1529D6007EDA51F780867B86DFB2F450F40997670657E8379C5D -:1529EB00E736D00DE083E9C6A2A2B59AEF178EA0A523783CBFC9 -:152A00008DEFB30A1D39A3625CB78C9C5987FAE1AD4C30BD3021 -:152A1500F565AAEBFD214D025BBB4CE8035F0FC8EEFF1190B788 -:152A2A004F3EC6E29DD9A01F5EB0BF577E2DE46E8D0BDB37B8AA -:152A3F00679D4FEE2B717C437D94FD343A30AE7A218EAC17FDA3 -:152A54003EC3A623EDA023AD1F701D71809C25A123E597B99C53 -:152A690059EE01F6FFF14C3F223E4FB84D6BFDB7B672B0676627 -:152A7E0049B4CEF447FFA7BDEF8F8EE2B8F3AC1EF54833D22015 -:152A93005AC3CC20B0905A443892A33833625024598481B05E2D -:152AA8009910769673B2DD92B0C7B1BD109B64B93B6E1FEF85E7 -:152ABD00C42318890137B8E913589615337224AF7C0B398507C9 -:152AD200397C4F24E2C239B021DC2C211C9764F1388FD8BAACE3 -:152AE700CF283E62E3C466EEFBA9EE1E8D846CECDDBDF7EE8F21 -:152AFC009B7EF3BAEBF7B7BEDF6F557DABEA5BDF5A69AC4D3DC0 -:152B110064AC4ED519D4075AF65353DC2E34E6371EB9869F2B10 -:152B26000ACEB2EE45FDB55654BA5B0DDE817DA2914EC869824F -:152B3B007B50C5FAD98475AE1E32F7037C3D69949F0DE4EB5DA3 -:152B5000B09131CED8A10527686E3ACCD7BEA454B701BDC4D514 -:152B6500A9935CDE8BA786C193F324B9DB582D9F34747AFBF5F8 -:152B7A0011F5B46C86B3EA61EDEA07C8832E36E6FE07F17305BB -:152B8F005F77BC253C273C2C7C56F00937D8AFD97F633F64DFE9 -:152BA40063C3EC5966B0DD6C07DBCEFE9A6D618FB38DEC61F62A -:152BB90020EB600AFB125BCFFE8C7D917D81B5B17BD96AB68A61 -:152BCE00AD642BD8729A41B6B066D6C41AD93216664B59030BD8 -:152BE300B120FB0CBB9B7D9AD5D3F3297617ABA3A7967D929E0F -:152BF8003BD9127A6AE8F9043D8BE9A9A647A6A78A3F95F42CC7 -:152C0D00E24F057FEEE0CF42EB59C09F72EB999F7B02D6E3CFE1 -:152C22003DBEBC675EDEE39DF694CD78A45B9EB9B73CA5B33E15 -:152C3700733EF0F17CE85372DBA7F8233FEEDB3E2E6E3B338E52 -:152C4C00F3B1C15A4DE6674B4856A96CEA8C32F928FC6AC84FD6 -:152C6100B7BE6BE93B6D7DD7D3B724D037FA96CA5A8A1FD17442 -:152C7600D6A6A569522C098A26C98B8F4A31FAA7E89F597C1419 -:152C8B00E598B6496BB90D3659B6FCDC969F407E31CBAFD8F202 -:152CA00073905FCAF22BB1FC0AC80FF95199FC2CAAC4A2412BC1 -:152CB5002FE8F906AD3CA0D71BB4D2428F374869A202F66465D7 -:152CCA002D880E49BE4BA3D975BF93E469F845B99D8790EE4D6B -:152CDF00090DAE3375D4FEABFB5D679A558E9F0F091BFD90302C -:152CF4006E7F87C24A298CFC0DF88B679B555E76BACEB07167CF -:152D0900E31CF5485B30EA2F719AE8329F770775CCF318EAC994 -:152D1E00D3043B815FE0507298F1E3A7AC70EA135BE5C5866EE7 -:152D3300E593FA2FA67F94E245D15F4A8B0DD105BBA3B3BFA3AF -:152D4800C2549C74DEB7E498FAD62D7F8EFFF1EC5CE82698E770 -:152D5D00F7656DD2B4C76AEA6D705D4699EB74145ADFFC9CB4E6 -:152D720083788DD11C34D8447DA783251C4D4611ECA1469AD5B9 -:152D8700C9EA66BE1E37F943E732E0046EAC898E533A0F6B8218 -:152D9C004EB4514FB8A08E5673C90D4611BB8B60BFCB700622DC -:152DB1009DE959FC24C1F463F25B06FADADA996B124159E77EE0 -:152DC600E0EF029CCB151A44A29914EF6A10313F96AAF537A019 -:152DDB003B2F85A8C826BD9EAF3BC17E6C33D7C9803BEA28A727 -:152DF00032EA74942F9E2957A5785D186F57BCAE01EF28EA9AFF -:152E05000E72191A71391FC3DE6230A8C5799B68D2225CD728D1 -:152E1A0002FF58766E1BC58972FB879095CD33CF312DC2F5F20E -:152E2F0037F133A82CB8C53C03CDB659F714242D5D08ACEBCEA1 -:152E440025A012345F49E83A4B28D8DF81FBAD15E23296DEA113 -:152E59007B64B1814577C2AE9C8BA565DDB4FF6AEA31D5670A9B -:152E6E001A789E941F5F47C277B4574F2E882B42AA17DF464EDC -:152E8300CF23FA5FFB50BF0AF9A02ECA670DA62768DE242EFB76 -:152E9800EE83DFA5FC5FEE833FFCEAC9AF7F865F39F9F5CCF080 -:152EAD00DBBA82E0925EEBFBFA83AF874860D63CF2157D1B3BFC -:152EC200A355AC7C5D6DAF7A25F46CD3045FB75814BF44F57999 -:152ED7004A5BB4F2BCEABA4FE336CACB2DBBF3934F88CBC4D496 -:152EEC0090EEA0F15196BFDFC7F4EB862B69DAE3E476D4C70FBC -:152F01003406307FA2F298FEB7C61DC2EB2AF051CC5E098D3CFA -:152F1600F86623C142B4BD42F09DD7056D9FFAEC86D7B43B22A6 -:152F2B005486B4CF20DCC56FAE581D72ED46F93B47D94821CDB2 -:152F4000E3BE33EA725DA3F05DFDAEB6D7C9FFE97ED3FD3796FB -:152F5500FB3FF59FC966FD7DF679C0E8CFFB128E333AF0B68DCF -:152F6A008D6BF11F14367CEB5B850DD07FE84F3FAB2CBCF0B4B0 -:152F7F005270FEA2BA865D0A2D1C3FA9422748F8C900F4F5CCDC -:152F94003A120D70EED52FFD07F5FA43578C85C2CB14E792E1D4 -:152FA9008A1F69C4BC15F94F3E745E77A50A1B469F285CC6F5AF -:152FBE00645FE26BDE47138E14D1FAB88E7AFCE1507738708AB3 -:152FD300F2977EA3A12E12608EFE68D485FD1069D75189C3FEC9 -:152FE800E3A3AF513B2C96F726B3244F16C9DDF1FD714D11D6BF -:152FFD0069D44E7FAEC36E288D00EC2917F610B4E464F5EF0D02 -:153012008ABBE74DB97E5994E26F8FAD6EE0EBAF05E6594D31D5 -:15302700F56DEA279D0DB1F1C30D4C3FAE4F82FFB0BE47E1EB7B -:15303C00C95F4C1D211EEAE6F6486A2D7B41BCBDE97BB9DDF0EB -:153051005ADED648AE4DEDA5B616D744A2ABC4B430DE2EA635C4 -:15306600E08D3D3257EA00EC1D733BA2E5A9842EB85EC63C93F4 -:15307B00DB0B052FA28DB8CE216CC88842EE4E258CBBE21AF7B7 -:153090007FEF27541EB921134ED2D4D013131BCA486E445B997A -:1530A500AC1E321606529D63379DCB0897C6E9F7B22E89E06916 -:1530BA00A5322EA16D05FB349DFAE156CA97A5068C8BBC7E4946 -:1530CF009DDAA91424C0DEEED6C24C3F053BDAA3E82F7747CE85 -:1530E4002BBF7EB4B0A18F752B7DF1034AE91271595F64AF3217 -:1530F9003FD1ABEEDFA929FB9B2F73D952CA1CEC5BB3A4F2B3DC -:15310E007C8F28181FC5DA6BD9A204F600F58A14AF8FB986EDC6 -:1531230032EDF5E3BB4D24193AF39A2EB411EFEAA78DFDE39A1A -:1531380082F541576A80D2ED028EF95E5E79E6A0519179CEA8B5 -:15314D0025BC54503D338524165038DA67ADBC8BDB6EE1794811 -:153162009A7191E6A1E5F2533AB7B1B841D3289D8EBE418C1DA2 -:15317700D3C3991F50DC5DD4467A699C1B509167762EF4786000 -:15318C004B80BAFC7327D583F15EC5BBB257756843AA6B7CB87A -:1531A10011E7E87DA78E98F6BC4F33B6003A00D029A39FB8AE2A -:1531B60047A57AF73BD6ED53134579776CA4B1D69FD4BEF10F46 -:1531CB00E28F0F0A9C667C0FC4977981EB03F25B806033057EB2 -:1531E0002CC1F5B78013733F24C9F7438CF15EA53CD3D317CC90 -:1531F500BC9092566ABC0F2958ABA9A2AC191E17F6B807B4DAA8 -:15320A00C881469CF3F277116FD1BCB63C0EF7712360B985B33F -:15321F0003AA392E1C307C194F03FCB0B6EFCAED8FF4F13D009A -:15323400077097EED56B389DCCF3C9021BD1A0476D9E4B1EE5BE -:153249007DE9AF282F612DFAB214A7AF903CA20616751B4F47B0 -:15325E00CC73AC584B17BEA071BBBA12A7B3693B5AE23CFF9D4E -:15327300A35761D392EA8DF56831437D5BFA3AA7435946C4B92C -:15328800E57980A79CDB5F4A76DA773430FD4903F6C100A7902A -:15329D00F986569B9917CAEFFBD1E783BEBCDFCFF5F9D4FF6FB5 -:1532B2002A6CF765DEC638C06DAB48991EE3B1F7B37EDFFBE0EC -:1532C700779306C0B12FB34F7768BD6A598BB9E7EFA07E03F7AF -:1532DC00DE7858EF520FF1D042D61B02FDCE7D798A77CF59B649 -:1532F1007F2F73DDAF894ECE7B4437B845BEDF11E7FB58A037C4 -:15330600E8CB6D5EA19D133D67D292E3DEA2C3ED70FB9169045F -:15331B001AE4E3DEA6C7C7A04131A7419FB5CF33458BDBD220BD -:153330006FECB5F11F1B87BDB4D2603E2DBCB14F86605F8345EF -:15334500BB466F3CF1C946295644E36C972E901FFAB1CDDF28C2 -:15335A006C38F147FB3CA0D99F9413ADBC8B3443A03A8176A8A8 -:15336F00A3B9E7639681F290B77DBE7D4A7E32E9B1208F16DB67 -:15338400393C49D3EE0E85635F51CAEC3304EBBE1BB8953CFDD8 -:15339900E3AD79E9B77E39A7E7CBF583FBD830D7DBDC049A7748 -:1533AE000D2B1ED9C9FBE92D5C0F50D31744CCBE29D7EEA8CE2A -:1533C300C2268CCBF4BEEF3CC701B553DFB63F98F5CDCCB8F661 -:1533D8000BF6DCCB03C9CE052413C82C7534C8C68F4658E668BC -:1533ED00F93F66DDF41E25F728F98F3659E93F28BE32313DBE77 -:15340200CB8A8F717EE0EDBC32B1DF48F391FCB4A80F9F7B51F9 -:153417007D6E92FCD28AF573792CFED499934A2189F6A2DC9BBD -:15342C00849D9A62F97412679ECDFDA0717EE651928FD13C2606 -:15344100A17B324B1A4E1FC8BA81878167B3EE9979E6C3C6F7CB -:1534560031296DABFC8C7EFD558D64259C19485A7CF8EF0DCEEC -:15346B00BB416EB37E723FC98F0D241F7D1CDE9C7CB5574F3836 -:15348000481E1D11DB275FD58C84A3CF6895F71B6FDF44FB88C7 -:153495005B73952EE32A6422A23FF657652A231F2737AE4CC7E0 -:1534AA0027F6772DF9D6D47FD60774C8D202B52FD491DC46F8DA -:1534BF00DF91FC188C72BBDF763E727A2A1FDFEFB3AE0A9CED31 -:1534D4000994C32EB47E91CADC06BBF91968DC46344FA6562FE1 -:1534E9003C15527F10AF0B753735F13EAB88D1DC287D9F562434 -:1534FE003C4C7DCB9A19B2A6639928DFA7CB99681FEC1CBB5C2A -:15351300D514DE66C9998B1B8B694EE3A8547859B08B0879DDE3 -:15352800D915524B23A17031953D54754F634546A631B3562FB7 -:15353D00CF0475C1D3A2767F3BA439C769FE986E326C7BD4D0FD -:1535520001E132BFD445F2674D4874134CD1AF8C32FDA17E5706 -:1535670012FB88FF9ABF332B1CCB6ED5BF29B7F4306AAD7E2D55 -:15357C0048FD5A9302B9DF2B0B413E9709364DD94049BF30BA8B -:15359100607C405D60DD59E0A3711C63314BBF64940957D55FDC -:1535A60057977E96914CCED88426B1DF34FA846B6A69B5B301F8 -:1535BB0072648464F60A6158D593DD4A39E618D46FA29F14DD49 -:1535D000AF73FB344CDA31FA00FBEF212ECBC1760CB91792FC9F -:1535E5008DB7FD5F2817B5E7DC83669A8FF23F9CCD06642ABF7B -:1535FA00D1CA9FDBF69F257FFB1F4F4DE57DA7FCA73C0DEC3F98 -:15360F0049B566F92E8259B6E250BF1E58287F32945F1FF84BF5 -:15362400DC864D11CDA95ED259E685A33E6AE7C998735945E6DD -:15363900A08EFE14BC8A7DF5329219DA16F42E8D903C8631F194 -:15364E004B4E9DCB608DCF68215BEEDAF47EF603E52ECFBBD91D -:153663000F94BB9A6691BB1CE78EA890BD206FD9F2574EEE8AAB -:153678000C37E28CBB6F25CEBABFAE35DD9CDE1FF23E9368DB97 -:15368D0056FD686331D7C99ED03CEC64A3EFD4FF22584E6A8B1D -:1536A200334B7278704D38DB6D3CC006D104E1E9DECC1C93BEB6 -:1536B700382B6386EB62F2B87A37A1A1006E2B0C7E080B4085CD -:1536CC006486DF091AAF3E088F243B841D6DD7D41BEF645DC0D6 -:1536E1002770566FE1B0E63D138715B3E010694EBFF32F8B4708 -:1536F6003FE457C2E3A2C089CECBC063747F5FECF733AE95B49A -:15370B007065F3FFEDDCF2CCF4D103FA1AD6A7DD4FF39DEFFF58 -:15372000AC77A92C9F1AA5514CF30A24A74A970C9FD54E45E8FD -:153735005348BF34B6B1CB5A99F0867AC7CA6BEA216A87341F91 -:15374A006FC01AB85466A898FBB2F401CD357E90DE07B53B5395 -:15375F00628397E6805EF6BAEA3D754515F8BD15A3DCBE14B79D -:15377400AFF4438C1B716D60FC07E13B28DE1D142F30DE13B21D -:153789006D3F4994066D54A638B63F6C3FC11FEDAB32736F4889 -:15379E009A28E434E736A7CE5EE16D0AF76905327786A6EC5777 -:1537B3005DE1FD43F0D5D2507EF9F2AB81696EE9D5CA696EE8E9 -:1537C8005BCDA7B2E673B8BAF3E03A990757771E5C272DB8FEA1 -:1537DD0084E072E6C175320FAE25A19976B582164FE7E0CAF8FC -:1537F200A7C3955934CD0D9EA9A0B1B531833E90DF11C9F8DC00 -:153807004700EF8C111DC61AE711CFCC3F457C263F63283769B9 -:15381C009E9E7E5E0F73FB865D7DF192443BDCDBF85D55C7FA7E -:15383100A00F5570866091BBFA1DE7BECD797284AFDD3CAF0766 -:15384600E5471BCDB897B5EB2B8A96791E7885E629BFD45DF29A -:15385B00F7FAEBE5FF61C47F37939F7A463DD07F4CADD7CC6F34 -:15387000CCF37B46275698F98C52BE3E2BCF1B2B3636DECDFE86 -:15388500A681CFD3F3E2222DF2C84F778EE2EC78F2921294FFC4 -:15389A006229FC21BFD134EECFF0FD0C64B8684F0AF323A42D33 -:1538AF00C6990FE25D9C27ACD8FF3CE763F4AFA2957FE9B4EFA6 -:1538C400F92187F9DD572CCF0DD15B7770BD769DE7EF786E8FEB -:1538D900CA714CF3761FC9FF46E405458A24D472C23F3FDF2953 -:1538EE009936FF6FF72799272924D7ABD85767D24E2E1749FE99 -:15390300B862CB455C4642D8C7908F6CD9C8929366958F201BEC -:1539180041460A731B30391947D3CF99328E598ECCCAE5DF195D -:15392D00F320EB92DCE492771B23D7B2AEE294962C26B8C3914D -:153942004483BD76514E7216E224AF8166DD3AAB15DBB75F33B8 -:15395700E5AEF11FF3701DE141C20FD2B3D4555D583041E3BBD3 -:15396C00466D21A915A612712F9523A58EF5A19F04DF214FCC1D -:15398100DFC17FB5F2ABFDE6BC7E265FF7F2FE653EC9C5DE53D5 -:153996007B492619D3C08315046BEB1FF3E55FAB8E54B7792958 -:1539AB00677BE6CDACBF96E4DD6DBF356556BE1741F09D79D3A5 -:1539C0004C531630CF6FB9ACFDDFD1F9CC4D7329F7C83CD38DB4 -:1539D500F3A3DB1DCC7D86FEE6FCB0D6B28F62EA383953423B4C -:1539EA00F33569F6D962CF4F894F4E35ABAB683EE6EC1A547BD6 -:1539FF00D3834AA5EC6C59287FFA73580BE669A43A35771E3916 -:153A14005A4D7C24F488B16ADD29615D59E879E3505D985DEFCD -:153A2900D2B6FC149750CD9C0F4D2F7F55BC6EE93FAB9C5BF459 -:153A3E00C7829D35F35989242D56A12F0E5D0DD843724A7FCB73 -:153A5300F57BEF4ABDDF0ADDBFC03743E8C3B84E1FB761111D23 -:153A680036D6523CBB3CF8B7927BEACE013E472F96024D9DA766 -:153A7D0003B0AF54DBF95E00F936987A72E5ACC4131BA4B1734E -:153A9200897AA72C34632FD513AB366E90BFF8CD2EDDD4AB1599 -:153AA7007B2E5AF32BA7B443FD1585C13E682FE250BDB0372D1B -:153ABC0043F78FFCC4D8A031067FFA7EA390B92F5BE98AC87D98 -:153AD10095FCF11E221AC35ED698C33CB3DB0B9AFB26614796E4 -:153AE600158DC02EE7354DBAF08C02BDEC729C75938E692ECFE7 -:153AFB0011751DD1769E2CB6176506349CF3A8A07E349041FC40 -:153B1000BD3B30C60996EDC0BB52AD4B258F797608B675E6F2B3 -:153B25003C87FB711F93CB8CE32B4F894B85915BD3B26811D7DC -:153B3A00D7D6096F61BF797616FA59B09B0A3D948C1F77C324AA -:153B4F0072F73188F2756333D14D24BC78A82DC7E89BCDB21F0F -:153B64001B8CB9B458E6C747C52B5DEA7B3E3BDF8A5CBE492BCA -:153B7900DF98653B7B0FF52D63458C9F1966E9B8C1F793A4B0E2 -:153B8E00265436758A995AC395811FD12AD3C4CB2FCF4C92FB54 -:153BA3004CA79449519EB14EACB3EF59B049E17D5BE596CE8A23 -:153BB8000C6C185CEE14E5AF196301933F6A284D6D26DD5F4F2A -:153BCD00E9C3945FEB3CE60E527A13B63FE9036CB0B3BC0A7361 -:153BE20028669F5B8E744632EF187B16449508CF53E98C929B8F -:153BF700E21F5D4DEF18E55D4873DAFB33878C48E6E9BEB68CD8 -:153C0C00DE1FA537F6A8A3F43D4EE10A9595F65AB6C4598AE365 -:153C210000F64B61F3B13393321EA17C63049B0FFC4AB8AAA7B5 -:153C3600B78BDEB0D12B5378057DAFA63C7CF4AEA1F9DA26FA1D -:153C4B009E9807DE265C915F1BF989D4D75C24BF60C0A4476CD9 -:153C6000864D72E795B84A7C57E295C5E50579F412008F3C64E5 -:153C7500604D35280F515F3764CC464FF33C53588B3A58C9DDD8 -:153C8A00A987C2683785CDB216E53AAD757A39BF43A8CB30756C -:153C9F001D841E3B8F149559D537C8CFB5080BE2EA947DA00895 -:153CB400C50B6B8CF2EB015E7CB5B9BE6DE2EF3106D6A9B8178D -:153CC90061B1DCBE946DFD5DB7F21BC6EC7CD8D62E2DF8736B0E -:153CDE00FF6BEBA0B685BE7B6467BB2B074FB3BE10E310C27EAD -:153CF30063EAC9D7DBFD13F9457F0E5DD365CB5D046B8C997058 -:153D0800DBF4E6772A5AE9026CF972B6B599E76FEB8B230DE54F -:153D1D005552CA5A7918F22A0ADC8A2FB46F9F30759E439A7424 -:153D3200501D4772753C7701753CA2AE8149D46F0EEB9317007C -:153D4700306C5F99FB57F2CF281AFD23F48FD23F46FF2DF48FD5 -:153D5C00D35FA77F8AFEA3F41FFF9919976DED36EB6A9EF9E018 -:153D71006E7D867B74863B3DC33D39C32DBD36DD1D9CE18ECEF0 -:153D8600706F99E1D667B8475FCB3B9342F86913A6DBB78880A5 -:153D9B0076BED19C5DB049AA97BFEBB85ACACF365BF9548E74A6 -:153DB000626D684D6C43D87F7258AFBD083A4DE14D21F726FA49 -:153DC5006FA37F92FE7DF41FA1FF09FA9FA1FF65FA4FD0FFC613 -:153DDA0045332E3B36CCF196B2E94F6EE04DCF73036FF13C37CD -:153DEF00F0B625CF0DBCC5F2DCC05B34CF0DBC45F2DCC05B3084 -:153E0400CF0DBCC9F9E5BF36657F93974F6E7F73CA006F433FFD -:153E19005A7C62C33DB67D048EB3D9EC7F107E3D2C0FBF33E3C5 -:153E2E00FC33C3D1F78C91FC42B2947E7A0E734357B658165B92 -:153E4300FA04E676D137F5332D1E1A238BE5459FBD48E36205B5 -:153E58007D838EA2B44BDD5C467DD65C56F218AB6989CC35FBFF -:153E6D00B407E83B3CD7ECCB2A59CD725BFF49869D72DCFB4582 -:153E820079006793A5347E53FA8952C80E2F4ED9E92019F152A8 -:153E970055178DCB872123E8932B9CCB4F531CB96CF6F1C91EC9 -:153EAC00E7B0378FF1689299363AEC781E2A77A7659780E49DE9 -:153EC100E597292F3797F7A7F7631504EF7609E321E48BDDFA81 -:153ED6009E18CEA5BDA8EF881CE6F5777FC6D92EC9753AFA7C2A -:153EEB009C112A5B79006BB9DA9639D89F1AD499FEA2EE178621 -:153F0000D516D6CDE377BB87156141138DAD83460DD54D243929 -:153F150097DB268FEED52ECEC538A6774A65499EC7988764486F -:153F2A004AE3925FD4451A8BDDA558571EA4BEFC450378AE91FA -:153F3F004CF903B0A63DD3E5BB9139ACE434E5979A8371A6469B -:153F54004FF0B1A9968F4D380F2B2C08727B0A976F66DDC5F1B1 -:153F6900AE1667B45695E56AFD8D15C2F2CD94E6CC5C5326B23D -:153F7E00F1E0B5740FA7F477653D4EBC29A57772BB7EC85FBA96 -:153F9300F02905E78C00B33732B854245945A43C2729CF769297 -:153FA800A9708E49E4BAD87C1C862D490379A0BD8BB161C323AE -:153FBD009BF7BA66B91EFF8B9A9FFA7C51FE9E81F8B8FB976419 -:153FD200B00D1305243FE3CEC7BCFBA71294C7DFC588F762B02A -:153FE700B561DA75FFCF6CB0C5436E8C33C065A498B9DF269E84 -:153FFC007D8B75B5D8B09B3819E17D13F2E0677ED892161BEE59 -:15401100EB0437F45D890E25B02303DE100907176F64DDF6BD19 -:1540260005F9750AE4D5C91E6F502FAEB740FD1DE0728ED39C6C -:15403B00233AA6F13A4883FD34F7A07AEF9EB2731CEBD27ADD53 -:15405000CCBD8660B5D37C2ED2DD029D8B9F1CF9E5618F5C6F8D -:15406500F8B9AEB24A6D76B561C32ECA87F9BC0DDF18E3250BE4 -:15407A00476B2D386D3D4E0B977EEC15D7539837262EF7154C5C -:15408F00B50DC95DA39AF7EBF6F1F28C5343CB59380C1D8CAC5D -:1540A400B96796CD7EEB5498FC123AEE46294B3FA9965DB84765 -:1540B900914EAD542B65472BD7C94EEF864E94DB9D3F6E5A70DC -:1540CE0036B0257C5C1E7531F715AAE32F88F7D8D6E7795E88FB -:1540E300EF425F1F1EE2F7AEF0F34BADF5FCDC0EC9E1FA77E3C0 -:1540F800832D38D303FC3E8D7B0B49A6B5F0EEF5669C2DF321EE -:15410D00AF674EEAD71F7C69F92FC88D3A8B99E1D9F98D706485 -:15412200F29BC93F9ECC71FD40C6D91E681DE6E5A19D99F4946F -:15413700394EEDFE5A6C5D82B51884EB95E38361BBBE51613A5F -:15414C005F42CFE6664C6801DC36DEDE1C1FE27D8027467D8299 -:1541610055CE2F288F8F5AA7CA8C7379B0783A2FB6BD9D75AFA9 -:15417600263A7A62797591BFA7439F3257179AC398F5AFCDD556 -:15418B00057088AD9FE675E1788A0D7E209E9C528D6AAD9364C6 -:1541A000515FD7A9FD5C671573A30187D54F100EA84F77E7EEE2 -:1541B5004C487769E7FE68EB0FD7F33A411FDC4EFB08A503BD44 -:1541CA00FB284D7E3FB3ED7D935F3DF2615D8E0D695F8F0C8732 -:1541DF0050367851DA3E669E8B4C0FD37CA11BFB9D567D877409 -:1541F400BBAD88992386E41E56CBA8CF3D48732B4F06FD8A6685 -:15420900D5FFC454FD892FE6B79EE4F59F4F74B3E89B1B438A6B -:15421E00D1DFF1F6A0C1DE7FAE3DDC840D9FF0B169EDE1B7E3CD -:15423300C7B85D1FE0ACE121D35E01CA798EED6D215E36DB49B7 -:154248006BB7C9C7046B4F1C67F0F5CE03B8B3217A7206BD7508 -:15425D0093DE5563CB0D727B624379743DA623CD145D87AC7ADB -:154272002579BDD0E794B5EEE5755A98129783F76D5AE6F89743 -:15428700FCC414EE0A49E83DD4FECC7B42CC7AFC35F1A7CD8B26 -:15429C005E36D6524AE503961B04CB42E2BD6345D379EFDCFF00 -:1542B10026BE93F3E08B117CB13CF8641B3EB35FE2F86CEDE6C9 -:1542C600F0E5F70BF1EBA6CE03DE62CCBC07588F24B694E68D22 -:1542DB0039F1776D5ECACD5DBD2CDCCB710B5B2C7D93D9921C44 -:1542F000EF916CF32B9C55785EBC478A99F36F6FE4B0FA32A58C -:15430500F1578BED6517FA1487C0CAE6212C7D4C972EA414DCF3 -:15431A00F17094609530E610FF6C06AFBA20776A5A2070A253C4 -:15432F00261929FE646FFB0EF827DF411FBEC375EE24D7DB9887 -:15434400A8DABB8CA5C7742328B4239FCAC45ED89CF3CDC7FD16 -:1543590068E49FC07AB5B4D710293FECCD7337952BF23DC1BDA2 -:15436E00064F87B2F4BDD07F9E87BB95BBCC343BE234A7C7BA03 -:15438300886BAD063D0E3FD7A1B3E6F412BF4F604CDFD9A6299D -:1543980005EBAEABF16CD6DBFB794D419D454A539938B201F0C4 -:1543AD0063EC042C80CD4F75692218FC174E28F36354D7B3DF2C -:1543C20056BD4CA33E3CA57C1FE38295A77876402519D88B7446 -:1543D70076DD7B28FFE4BEE3FC1E66F00B8F1B3DB6C3B5FB1DAF -:1543EC003503D8A84EA80BBB3EA0812EC003D34F6AC06723D44E -:154401005C28DCC6C5E51C1ECCB27278C07A6DDAC443E08762E3 -:154416004B721D742486B52EF2EF457B219CC00F6B1B18834D1B -:15442B00784F120E8E28C8BF60DDEFD5ED1C0F479432AA1F70F9 -:1544400020E15C15D5DB853B83A82CD84C0E52F99581894EDBE9 -:154455001EB2699F27AEE9C4837B162495B7D884B628C8FEB2C2 -:15446A0046163F97B3D7F917DC1E32B79BD4C6D70896F49B67EE -:15447F005B933C5D24B30B7756B8E98D7D6023F6EE149FE33C0E -:1544940023D6AAC0A3F5984B439736D8A4E937B89E663F8DB948 -:1544A900E3F15A67BBE00AAB623CA40E10AC55CA28EEB9D475D6 -:1544BE00F9402B9F9F521C89FA0E8FFCC51697FCB51649FED26B -:1544D30072312A63BC1EBF4AF230DE9D984B455FE43695FDCD24 -:1544E800B261E60F9971703C4861F594BE96D2D7507AF855C8F3 -:1544FD005F6AB1F3207E6AF150B88BC2AFAEF81ACFCFC3E766D2 -:15451200BFDB61C7D9827208265FF3A499B76EC20D1C85D136AC -:1545270008CE7AF9D556B1396864281CEB05AD349F1692215583 -:15453C008A630FD88C8FFC8807FC22E58378FC7C020EA4C7CC33 -:15455100FB80D0869B9835BF06CF4B435639239DB02952CE6D45 -:154566004F987E9833C18FEB1B9A67316E992F098249CF9C3FD4 -:15457B00E55F61CF7FB85E2A95CFEF384B195BDEBD75CE659ECD -:154590007D1DD11186FE07772CF8ADFEC69FFE8EEABBF01D0521 -:1545A500F2AAAFF59879AF1085F930F767C731BE6BAFFCB680E3 -:1545BA00558C1F6FDC42E39EC79A67983AB0A69C833B095CF13E -:1545CF00234BE793ECE943BEC111138E5C3F99E4F0F9228930CA -:1545E400B76F426EE4591E196AACC8CB333777A13E97A7B7FA20 -:1545F900CFDF5AFC8C7A606E47B079AFF2359D9AA934F9E76932 -:15460E00F9FDE74F69FF384BBAC333D211BFEBB3AD27453287BE -:15462300B4FF394BFACD1F21FDB559D2856F0BEF216D6296747F -:15463800EFB1DB9737F9FE8CFD27ACEFE4F31FD6FCDF9DBEBE22 -:15464D0031335CFAC38787C76F17FE7F3BFF19E19E7CFEFFB008 -:15466200F581FF1FFE4F0A97F2F0EF9DD92FFD3F03BFC51FD198 -:154677008F971EED6B9E287359ECCBDC46536D67B7147B641541 -:15468C0035454FD9A3AA46E1B82BDA73EF6E15ED14E3A4A76CC6 -:1546A100933A67F56E55961FD7E6DCDBA5FAD6698A47A8567DC5 -:1546B600A5D56A82E416AB4D6FB84163B35456AB22BF7F6A5E9C -:1546CB0087EED314EC110BEB30778969D0A813E582F6AF539F69 -:1546E000ECF754ABC5EBEAD5E7EEAB53AAD6D52901CF236A774F -:1546F500C1A714DCC5B8488CD973151FE28BC22754BEF6B0BABF -:15470A008BF71DE843AA4A130AF413ED702F0FAF539D65712E7A -:15471F00DF553D1057F9FE1264E459605865C15042301C22180D -:15473400FC79E5A3DC4A8201F178BE947F7ED937AC7C27F3F2CE -:15474900CD665FC97A60EB20C4DAD7331640DEF18298067C644E -:15475E009999D7DD8CCD9B4FB8F15099EEB57584A36A6591A745 -:154773005EADF88CD8EE645D1D557F25B61F9A9BE034C0BA4825 -:1547880090E0C01EDC5DDC76DA14EC5EAE07833DB8F813BC6EA9 -:15479D0004D3390BA631D4DD73BF5AB56FBD2A94DAB0656FDA01 -:1547B200B0B5106CE59E6AEE1F2701D1A697BBB45EF5709876A1 -:1547C7002B8B4A13EAFE9D7B72BC003CFF219BB56060BC9EB026 -:1547DC000966EE374F3E8172D3161CB81FEC0C7DCFD54C18CA91 -:1547F100F6D5A865541EEAD66E9D4D81D226C74BD1145EAA8851 -:15480600774AD6B6AAFE75610ECFAE82DD4A31E1A5C493500B35 -:15481B0059A2638FC59B8B79DDA7CA9DA0B2740A2B237C11DDC4 -:15483000BD360CA07D55DBFD0A64A1AA75F72B33E94F8DA8AC8E -:1548450098EF1B4CB5A7AA33033C9E70BE5EF53F105345F6B844 -:15485A003A87E23E27B080D3FA36E8BB641DC149FC52521A56D0 -:15486F00B51F352B87CE362B25E7D7AA7E8DFCF6AD56B5CFAF8A -:1548840021DE5FA38007FC84D3AAB5262EC498D02EB34D9CB7E4 -:15489900494EF3398587544FAC0077EBF8DCD8ABA96CEB9C2374 -:1548AE003CAC7AC455AA67259577EF63AA67F51A756FC12A05F2 -:1548C300FA1EE2CAA9F84501F31C188F9F0899F15FFEAAEA3924 -:1548D800DDACEEDD19529C34EE96FDE811A5EA3305EDB0BDEDB4 -:1548ED008A873ADCE3CD1D07610F4D0BA955E71F528573CDAA2E -:15490200467105D7142DB6A28D07F8B9B10DB005E4EAA274A731 -:154917009A3BF85CAF89B51796053B8ACA9A3AAA92EB955DD473 -:15492C0037C8E4DF43EFBF449FF3F71B554F4FB30AB95A961F63 -:15494100866CE7F224BEAA0A6B1F5779D8CBCD141E52F712CEDB -:15495600407FF038E624C5FF5168AF3A4F38D4BA54FFF9AFAA3B -:15496B0025E776731ED84F3C3087685F1CD13AF2FB25D01DB469 -:15498000E33AF5164DC193F7122CED809FF08CBB49D7D177A2D7 -:1549950060B33287CA01FCDD3BCDEF5537B37EF44BB61B7169FF -:1549AA006CD83090C51A8EC9DB064DAD803FF47B34E79A67F3A6 -:1549BF00D5368AC3CF47100C9B67E80797FDA842A93A574EB8AA -:1549D4002D5767E3A337D9141FFD9A997C041A14131F053C9B2E -:1549E900395E9EB378097CE4D7C86F062FED8EFFF9C6E2C026AC -:1549FE00A24FAC73377B78E39C40B453F03CA6DAEE92C8C31BD2 -:154A130041A7395DEB3BD8D9F60EFB5D75CDC1EF702A8EAFEF25 -:154A280028196FEF10DC44F34F546B4EA2C34DA23DF07737A785 -:154A3D0085A3BD44DB4174788CE8B087F7E9F9B428B0689130FA -:154A5200EF8EF209AE4F50D9D10D67385DC037D10D6333E84242 -:154A670034F13E60D185FA5DEFFA3CBADC994797B7B8CEEF5418 -:154A7C00DBDE49EDBA378F4EDCFE38F100FCB75BB4BA803BFF2F -:154A91002CDA6CFA98F4B894478FBFB3E88136EDB768710B1D40 -:154AA6008836F9B4288A7C65636164FD46B68DB57BC6BFD23197 -:154ABB0047DAD451C4FECDC6E2F8BFEDF08C3FCCDD557FC5DBED -:154AD000ABD7C3C81D799CE35DDC5EAD39A8EFBD5914D58A6DA5 -:154AE500BC533B2DF1ECA4FEEF5FA9256B9F9C86F7E2D9F09E3E -:154AFA005C0C9AE7E13DC6F16ED7371FFFD4E77BEFB5F08F35C1 -:154B0F0011B4131BFFDE3CFC3BF8DA8689DF5E0BBFA5E8A7280A -:154B2400AC92E65AF96DC04EFF261F174C9A211DE8A658743081 -:154B3900711E9E06CBB708CF9E94D0FE32BD13D4F714521EB8D2 -:154B4E00FFFDD0171F51ABD6B52A52C152A5A8E01E053CECA121 -:154B6300BE879D6DEE38F4530A3BBF56F1167C5E71177CC10C75 -:154B7800135675B0FBD674EC8A39DA01D762E084CA261E292BCC -:154B8D00941D7C8C843FECB9D87314940FBBA705F6D86D8D1FA2 -:154BA20088075D7FC0F55A36EBA338B9B6FF32B57D8C5D9768CE -:154BB7003A89F512C80734D6F94E5BF1BF4FDF55D744BCBD27B6 -:154BCC00785E4975BF63E8117EC65230EF62A69125EB8D0C3DF1 -:154BE1006A308DEB88C1DF37B5DE5AFC7F00E871AED038A00037 -:014BF60000BE -:00000001FF diff --git a/drivers/atm/suni.c b/drivers/atm/suni.c index b1d063cc4fb..6dd3f591996 100644 --- a/drivers/atm/suni.c +++ b/drivers/atm/suni.c @@ -1,8 +1,14 @@ -/* drivers/atm/suni.c - PMC PM5346 SUNI (PHY) driver */ +/* + * drivers/atm/suni.c - S/UNI PHY driver + * + * Supports the following: + * PMC PM5346 S/UNI LITE + * PMC PM5350 S/UNI 155 ULTRA + * PMC PM5355 S/UNI 622 + */ /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ - #include <linux/module.h> #include <linux/jiffies.h> #include <linux/kernel.h> @@ -29,15 +35,6 @@ #define DPRINTK(format,args...) #endif - -struct suni_priv { - struct k_sonet_stats sonet_stats; /* link diagnostics */ - int loop_mode; /* loopback mode */ - struct atm_dev *dev; /* device back-pointer */ - struct suni_priv *next; /* next SUNI */ -}; - - #define PRIV(dev) ((struct suni_priv *) dev->phy_data) #define PUT(val,reg) dev->ops->phy_put(dev,val,SUNI_##reg) @@ -155,25 +152,105 @@ static int get_diag(struct atm_dev *dev,void __user *arg) static int set_loopback(struct atm_dev *dev,int mode) { unsigned char control; + int reg, dle, lle; + + if (PRIV(dev)->type == SUNI_MRI_TYPE_PM5355) { + reg = SUNI_MCM; + dle = SUNI_MCM_DLE; + lle = SUNI_MCM_LLE; + } else { + reg = SUNI_MCT; + dle = SUNI_MCT_DLE; + lle = SUNI_MCT_LLE; + } - control = GET(MCT) & ~(SUNI_MCT_DLE | SUNI_MCT_LLE); + control = dev->ops->phy_get(dev, reg) & ~(dle | lle); switch (mode) { case ATM_LM_NONE: break; case ATM_LM_LOC_PHY: - control |= SUNI_MCT_DLE; + control |= dle; break; case ATM_LM_RMT_PHY: - control |= SUNI_MCT_LLE; + control |= lle; break; default: return -EINVAL; } - PUT(control,MCT); + dev->ops->phy_put(dev, control, reg); PRIV(dev)->loop_mode = mode; return 0; } +/* + * SONET vs. SDH Configuration + * + * Z0INS (register 0x06): 0 for SONET, 1 for SDH + * ENSS (register 0x3D): 0 for SONET, 1 for SDH + * LEN16 (register 0x28): 0 for SONET, 1 for SDH (n/a for S/UNI 155 QUAD) + * LEN16 (register 0x50): 0 for SONET, 1 for SDH (n/a for S/UNI 155 QUAD) + * S[1:0] (register 0x46): 00 for SONET, 10 for SDH + */ + +static int set_sonet(struct atm_dev *dev) +{ + if (PRIV(dev)->type == SUNI_MRI_TYPE_PM5355) { + PUT(GET(RPOP_RC) & ~SUNI_RPOP_RC_ENSS, RPOP_RC); + PUT(GET(SSTB_CTRL) & ~SUNI_SSTB_CTRL_LEN16, SSTB_CTRL); + PUT(GET(SPTB_CTRL) & ~SUNI_SPTB_CTRL_LEN16, SPTB_CTRL); + } + + REG_CHANGE(SUNI_TPOP_APM_S, SUNI_TPOP_APM_S_SHIFT, + SUNI_TPOP_S_SONET, TPOP_APM); + + return 0; +} + +static int set_sdh(struct atm_dev *dev) +{ + if (PRIV(dev)->type == SUNI_MRI_TYPE_PM5355) { + PUT(GET(RPOP_RC) | SUNI_RPOP_RC_ENSS, RPOP_RC); + PUT(GET(SSTB_CTRL) | SUNI_SSTB_CTRL_LEN16, SSTB_CTRL); + PUT(GET(SPTB_CTRL) | SUNI_SPTB_CTRL_LEN16, SPTB_CTRL); + } + + REG_CHANGE(SUNI_TPOP_APM_S, SUNI_TPOP_APM_S_SHIFT, + SUNI_TPOP_S_SDH, TPOP_APM); + + return 0; +} + + +static int get_framing(struct atm_dev *dev, void __user *arg) +{ + int framing; + unsigned char s; + + + s = (GET(TPOP_APM) & SUNI_TPOP_APM_S) >> SUNI_TPOP_APM_S_SHIFT; + if (s == SUNI_TPOP_S_SONET) + framing = SONET_FRAME_SONET; + else + framing = SONET_FRAME_SDH; + + return put_user(framing, (int __user *) arg) ? -EFAULT : 0; +} + +static int set_framing(struct atm_dev *dev, void __user *arg) +{ + int mode; + + if (get_user(mode, (int __user *) arg)) + return -EFAULT; + + if (mode == SONET_FRAME_SONET) + return set_sonet(dev); + else if (mode == SONET_FRAME_SDH) + return set_sdh(dev); + + return -EINVAL; +} + static int suni_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg) { @@ -188,14 +265,16 @@ static int suni_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg) case SONET_GETDIAG: return get_diag(dev,arg); case SONET_SETFRAMING: - if ((int)(unsigned long)arg != SONET_FRAME_SONET) return -EINVAL; - return 0; + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + return set_framing(dev, arg); case SONET_GETFRAMING: - return put_user(SONET_FRAME_SONET,(int __user *)arg) ? - -EFAULT : 0; + return get_framing(dev, arg); case SONET_GETFRSENSE: return -EINVAL; case ATM_SETLOOP: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; return set_loopback(dev,(int)(unsigned long)arg); case ATM_GETLOOP: return put_user(PRIV(dev)->loop_mode,(int __user *)arg) ? @@ -229,10 +308,6 @@ static int suni_start(struct atm_dev *dev) unsigned long flags; int first; - if (!(dev->phy_data = kmalloc(sizeof(struct suni_priv),GFP_KERNEL))) - return -ENOMEM; - - PRIV(dev)->dev = dev; spin_lock_irqsave(&sunis_lock,flags); first = !sunis; PRIV(dev)->next = sunis; @@ -293,16 +368,21 @@ int suni_init(struct atm_dev *dev) { unsigned char mri; + if (!(dev->phy_data = kmalloc(sizeof(struct suni_priv),GFP_KERNEL))) + return -ENOMEM; + PRIV(dev)->dev = dev; + mri = GET(MRI); /* reset SUNI */ + PRIV(dev)->type = (mri & SUNI_MRI_TYPE) >> SUNI_MRI_TYPE_SHIFT; PUT(mri | SUNI_MRI_RESET,MRI); PUT(mri,MRI); PUT((GET(MT) & SUNI_MT_DS27_53),MT); /* disable all tests */ - REG_CHANGE(SUNI_TPOP_APM_S,SUNI_TPOP_APM_S_SHIFT,SUNI_TPOP_S_SONET, - TPOP_APM); /* use SONET */ + set_sonet(dev); REG_CHANGE(SUNI_TACP_IUCHP_CLP,0,SUNI_TACP_IUCHP_CLP, TACP_IUCHP); /* idle cells */ PUT(SUNI_IDLE_PATTERN,TACP_IUCPOP); dev->phy = &suni_ops; + return 0; } diff --git a/drivers/atm/suni.h b/drivers/atm/suni.h index d14c835abc9..7e3e656b399 100644 --- a/drivers/atm/suni.h +++ b/drivers/atm/suni.h @@ -1,14 +1,15 @@ -/* drivers/atm/suni.h - PMC PM5346 SUNI (PHY) declarations */ +/* + * drivers/atm/suni.h - S/UNI PHY driver + */ /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ - #ifndef DRIVER_ATM_SUNI_H #define DRIVER_ATM_SUNI_H #include <linux/atmdev.h> #include <linux/atmioc.h> - +#include <linux/sonet.h> /* SUNI registers */ @@ -39,7 +40,8 @@ #define SUNI_RLOP_LFM 0x1F /* RLOP Line FEBE MSB */ #define SUNI_TLOP_CTRL 0x20 /* TLOP Control */ #define SUNI_TLOP_DIAG 0x21 /* TLOP Diagnostic */ - /* 0x22-0x2F reserved */ + /* 0x22-0x27 reserved */ +#define SUNI_SSTB_CTRL 0x28 #define SUNI_RPOP_SC 0x30 /* RPOP Status/Control */ #define SUNI_RPOP_IS 0x31 /* RPOP Interrupt Status */ /* 0x32 reserved */ @@ -52,6 +54,7 @@ #define SUNI_RPOP_PFM 0x3B /* RPOP Path FEBE MSB */ /* 0x3C reserved */ #define SUNI_RPOP_PBC 0x3D /* RPOP Path BIP-8 Configuration */ +#define SUNI_RPOP_RC 0x3D /* RPOP Ring Control (PM5355) */ /* 0x3E-0x3F reserved */ #define SUNI_TPOP_CD 0x40 /* TPOP Control/Diagnostic */ #define SUNI_TPOP_PC 0x41 /* TPOP Pointer Control */ @@ -82,7 +85,8 @@ #define SUNI_TACP_TCC 0x65 /* TACP Transmit Cell Counter */ #define SUNI_TACP_TCCM 0x66 /* TACP Transmit Cell Counter MSB */ #define SUNI_TACP_CFG 0x67 /* TACP Configuration */ - /* 0x68-0x7F reserved */ +#define SUNI_SPTB_CTRL 0x68 /* SPTB Control */ + /* 0x69-0x7F reserved */ #define SUNI_MT 0x80 /* Master Test */ /* 0x81-0xFF reserved */ @@ -94,9 +98,18 @@ #define SUNI_MRI_ID_SHIFT 0 #define SUNI_MRI_TYPE 0x70 /* R, SUNI type (lite is 011) */ #define SUNI_MRI_TYPE_SHIFT 4 +#define SUNI_MRI_TYPE_PM5346 0x3 /* S/UNI 155 LITE */ +#define SUNI_MRI_TYPE_PM5347 0x4 /* S/UNI 155 PLUS */ +#define SUNI_MRI_TYPE_PM5350 0x7 /* S/UNI 155 ULTRA */ +#define SUNI_MRI_TYPE_PM5355 0x1 /* S/UNI 622 */ #define SUNI_MRI_RESET 0x80 /* RW, reset & power down chip 0: normal operation 1: reset & low power */ + +/* MCM is reg 0x4 */ +#define SUNI_MCM_LLE 0x20 /* line loopback (PM5355) */ +#define SUNI_MCM_DLE 0x10 /* diagnostic loopback (PM5355) */ + /* MCT is reg 5 */ #define SUNI_MCT_LOOPT 0x01 /* RW, timing source, 0: from TRCLK+/- */ @@ -144,6 +157,12 @@ /* TLOP_DIAG is reg 0x21 */ #define SUNI_TLOP_DIAG_DBIP 0x01 /* insert line BIP err (continuously) */ +/* SSTB_CTRL is reg 0x28 */ +#define SUNI_SSTB_CTRL_LEN16 0x01 /* path trace message length bit */ + +/* RPOP_RC is reg 0x3D (PM5355) */ +#define SUNI_RPOP_RC_ENSS 0x40 /* enable size bit */ + /* TPOP_DIAG is reg 0x40 */ #define SUNI_TPOP_DIAG_PAIS 0x01 /* insert STS path alarm ind (cont) */ #define SUNI_TPOP_DIAG_DB3 0x02 /* insert path BIP err (continuously) */ @@ -191,6 +210,9 @@ pattern */ #define SUNI_TACP_IUCHP_GFC_SHIFT 4 +/* SPTB_CTRL is reg 0x68 */ +#define SUNI_SPTB_CTRL_LEN16 0x01 /* path trace message length */ + /* MT is reg 0x80 */ #define SUNI_MT_HIZIO 0x01 /* RW, all but data bus & MP interface tri-state */ @@ -205,6 +227,14 @@ #ifdef __KERNEL__ +struct suni_priv { + struct k_sonet_stats sonet_stats; /* link diagnostics */ + int loop_mode; /* loopback mode */ + int type; /* phy type */ + struct atm_dev *dev; /* device back-pointer */ + struct suni_priv *next; /* next SUNI */ +}; + int suni_init(struct atm_dev *dev); #endif diff --git a/drivers/base/core.c b/drivers/base/core.c index 422cfcad486..ee0a51a3a41 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -762,6 +762,7 @@ 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, ...) { diff --git a/drivers/block/brd.c b/drivers/block/brd.c index 680cdfc00b9..24b97b0bef9 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 e336b05fe4a..5f1e1cc6165 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/char/Kconfig b/drivers/char/Kconfig index 595a925c62a..2d854bb9373 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 55c97f62324..07b4d8ff56e 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 2398e864c28..a00869c650d 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/intel-rng.c b/drivers/char/hw_random/intel-rng.c index 5cc651ef75e..27fdc086649 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/keyboard.c b/drivers/char/keyboard.c index 7f7e798c138..d9a0a53c842 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 fa9d3c945f3..ba6340ae98a 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 fa1ffbf2c62..935f1c207a1 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 86f0a243062..1d41496ed2f 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); diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index fc555a90bb2..23554b676d6 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 74401198904..9e4f59dc7f1 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 88e89653daa..26df06f840e 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 5c006c9a431..c9416e65748 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 b4f3aefa12b..1607536ff5f 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 713cef20622..8e8c28104b4 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 4263ffd4ab2..2f311da4c96 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 96378ebfb31..d024ac8fad1 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 a6073e248f4..9134488ac04 100644 --- a/drivers/ide/ide-generic.c +++ b/drivers/ide/ide-generic.c @@ -125,6 +125,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 6a8953f68e9..adbd0178416 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 655ec7ef568..380fa0c8cc8 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 8d6ad812a01..55ec7f79877 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 5c730e4dd73..9a1d27ef3f8 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 9e449a0c623..af11028b479 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 a9c2593a898..fed7d812761 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/macide.c b/drivers/ide/legacy/macide.c index caa2632dd08..2e84290d0bc 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 6f535d00e63..8ff6e2d2083 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 aaf38109eae..b38a1980dcd 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 b9e457996d0..af0f30051d5 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/sis5513.c b/drivers/ide/pci/sis5513.c index 4b0b85d8faf..e127eb25ab6 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 f0e638dcc3a..236f9c38e51 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/infiniband/core/umem.c b/drivers/infiniband/core/umem.c index fe78f7d2509..a1768dbb072 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 9a054c6941a..b1441aeb60c 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 bbe0436f4f7..f093b0033da 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 59a8b254b97..0bd8bcb184a 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 1ff46ae7dd9..5f9315d77a4 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 0a8c1b8091a..eaba03273e4 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 e0ec540042b..7779165b2c2 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/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c index 5fcbdccd7a5..16a874bb156 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 fae895828a1..040827288ec 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 15906d005b0..484299b031f 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 7817d224492..1081091bbfa 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/md/md.c b/drivers/md/md.c index 51c19f86ff9..7cf512a34cc 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 425958a76b8..c37e256b117 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 cc11c4c0e7e..09a829d8a7e 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 d6206540476..85482960d01 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 5d05b5390f6..0dc2bef9f6a 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 42b5f5d4bfe..f1894fec32b 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 d30d2c9094d..8555d9cf905 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 b93cdef9ac7..b23dadeecd0 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 3ad6c8e0b04..cb1c7141f0c 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 be8d903171b..266c255cf0d 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 9e9003cffc7..0cbde17bfbb 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 449fb5c3d0b..ae0d76a5d51 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 f5010e8671b..a824f3719f8 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 56d871cfd7f..c2334aef414 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 cf4584e48b6..f00a0eb4042 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 346223856f5..c4d40fe01d5 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 e1112e39fb6..733a7ff7b20 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 9a942afaf0a..2653120673b 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 a12e6f784fd..54626a0dbf6 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 786e37d3388..3eedfdf505b 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 081bd81f3da..07c4d12ed5b 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 c7b5785f81f..5ed32544de3 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 747e7f1a626..f05d43d8b5c 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 3e6b650fbb8..ec55a968f20 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 732ce4de512..5d2d81ab237 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 0712899e39a..a23cc0aa17d 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 42eee04daa5..fefdc05e84a 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 eb5eaeccd7c..443af24097f 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 def10d08637..52b2491581a 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 c86a5f17eca..c6d47059038 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 f20a01cfc73..8ef0424c26c 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 e5979f77504..0af586876e7 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 ce0840ccd59..f42701f82e7 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 503e6c6d7b6..861bc811282 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 66864904c99..9a26751615c 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 553adbf2cd4..baccd079243 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 2bdac5ebbb0..87cf4102166 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 0dd4e052997..2b810bb2a4c 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 a2a6c58d12f..de14ab59a20 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 0b3141db174..1e537fe04a2 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 bb8bc86086d..ceb63653c92 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 dbdcb86ec5a..4151f1e5493 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 6e14f8bda55..25114a5cbd5 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 0c5f328bca5..2a5ccef9185 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 4ca9d847f1b..1b921a33609 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 f24abcd06de..c4cc2f3b887 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 aeba26dc0a3..fa6d398e97b 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 c4d1aff1fdb..60eeda3057e 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 8996175cc95..fb163ecd921 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 ba06e813c58..9d23b1efd36 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 f2fa434b677..db813e071ce 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 d8ba3a4a876..fba150a6cd2 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 fc8b1eaa333..71bd13e22e2 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 c47c2b94514..c854285a437 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 02c5ab071d1..442f43f11b7 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 a9417f6e408..3092ff1d00a 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 2fe5f125076..ca5173fbf00 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 1314522a813..81431ee4184 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 a0f7bc1edaa..0d12ace6166 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 32e536edf09..3d26a30abe1 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 81cc3b00a07..46b7ad477ce 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 37629ffd34c..88d369708e4 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 345c77e4683..5394d7a5cfe 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 3cdd4e96211..1e24ab4ac38 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 468480771f1..4d492ba232b 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 b109bd8a4d1..c68ef00c2f9 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 e2e7c05a147..6d14e8fe153 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 fa394104339..e4ff50b95a5 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 a0ce0b2fa03..b5969298f3d 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; } @@ -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 led_sled_arg1[] = { 0, 1, 3 }; - static const int led_exp_hlbl[] = { 0, 0, 1 }; /* led# * */ - static const int led_exp_hlcl[] = { 0, 1, 1 }; /* led# * */ - static const int 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 91ded3e8240..f9ad960d7c1 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 be624a049c6..c303e7f57ab 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 25efd331ef2..b402269301f 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/omap_nor.c b/drivers/mtd/maps/omap_nor.c index 240b0e2d095..c12d8056beb 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 fceb468ccde..fe2bc7e4211 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 3d44d040a47..ad81ab8e95e 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 47474903263..c5030f94f04 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 750a46f4bc5..ad6b8a5b657 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 c537f53ffcb..20b5367f7e0 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -524,6 +524,18 @@ config STNIC If unsure, say N. +config SH_ETH + tristate "Renesas SuperH Ethernet support" + depends on SUPERH && \ + (CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712) + select CRC32 + select MII + select MDIO_BITBANG + select PHYLIB + help + Renesas SuperH Ethernet device driver. + This driver support SH7710 and SH7712. + config SUNLANCE tristate "Sun LANCE support" depends on SBUS @@ -955,7 +967,7 @@ config SMC911X tristate "SMSC LAN911[5678] support" select CRC32 select MII - depends on ARCH_PXA || SH_MAGIC_PANEL_R2 + depends on ARCH_PXA || SUPERH help This is a driver for SMSC's LAN911x series of Ethernet chipsets including the new LAN9115, LAN9116, LAN9117, and LAN9118. @@ -2441,7 +2453,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/Makefile b/drivers/net/Makefile index dcbfe842115..c96fe203680 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -80,6 +80,7 @@ obj-$(CONFIG_VIA_RHINE) += via-rhine.o obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o obj-$(CONFIG_RIONET) += rionet.o +obj-$(CONFIG_SH_ETH) += sh_eth.o # # end link order section @@ -236,6 +237,7 @@ obj-$(CONFIG_USB_CATC) += usb/ obj-$(CONFIG_USB_KAWETH) += usb/ obj-$(CONFIG_USB_PEGASUS) += usb/ obj-$(CONFIG_USB_RTL8150) += usb/ +obj-$(CONFIG_USB_HSO) += usb/ obj-$(CONFIG_USB_USBNET) += usb/ obj-$(CONFIG_USB_ZD1201) += usb/ diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index 6c5719ae8cc..9c0837435b6 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c @@ -475,16 +475,12 @@ static irqreturn_t lance_interrupt (int irq, void *dev_id) return IRQ_HANDLED; } -struct net_device *last_dev; - static int lance_open (struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); volatile struct lance_regs *ll = lp->ll; int ret; - last_dev = dev; - /* Stop the Lance */ ll->rap = LE_CSR0; ll->rdp = LE_C0_STOP; diff --git a/drivers/net/atarilance.c b/drivers/net/atarilance.c index 4cceaac8863..0860cc280b0 100644 --- a/drivers/net/atarilance.c +++ b/drivers/net/atarilance.c @@ -243,7 +243,7 @@ struct lance_private { /* Possible memory/IO addresses for probing */ -struct lance_addr { +static struct lance_addr { unsigned long memaddr; unsigned long ioaddr; int slow_flag; diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 32dc391e63c..919ffb9bfa4 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 * @@ -2861,7 +2845,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 b32d22762b9..2c52d2c7c49 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -5664,14 +5664,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, 1); atomic_set(&bp->intr_sem, 1); bnx2_netif_start(bp); - bp->in_reset_task = 0; } static void @@ -5847,12 +5845,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 16020a10bf4..be7ccb5b77d 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 7bdb5af3595..70cba64732c 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 4f0c0d31e7c..8e68d06510a 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 dcaecc53bdb..370686eef97 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/declance.c b/drivers/net/declance.c index 6b1e77cc069..3e3506411ac 100644 --- a/drivers/net/declance.c +++ b/drivers/net/declance.c @@ -773,8 +773,6 @@ static irqreturn_t lance_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -struct net_device *last_dev = 0; - static int lance_open(struct net_device *dev) { volatile u16 *ib = (volatile u16 *)dev->mem_start; @@ -782,8 +780,6 @@ static int lance_open(struct net_device *dev) volatile struct lance_regs *ll = lp->ll; int status = 0; - last_dev = dev; - /* Stop the Lance */ writereg(&ll->rap, LE_CSR0); writereg(&ll->rdp, LE_C0_STOP); diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index cab1835173c..ccb8ca2cbb2 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -4343,6 +4343,11 @@ static int __devinit e1000_probe(struct pci_dev *pdev, netdev->features |= NETIF_F_TSO; netdev->features |= NETIF_F_TSO6; + netdev->vlan_features |= NETIF_F_TSO; + netdev->vlan_features |= NETIF_F_TSO6; + netdev->vlan_features |= NETIF_F_HW_CSUM; + netdev->vlan_features |= NETIF_F_SG; + if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 287a6191873..075fd547421 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 5f9c42e7a7f..329edd9c08f 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 e4d69789436..c980ce9719a 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -3277,6 +3277,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; @@ -3299,6 +3313,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); @@ -3414,6 +3430,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); @@ -3754,6 +3772,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 dde9c7e6408..00bc7fbb6b3 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/hplance.c b/drivers/net/hplance.c index be6e5bc7c88..2e802634d36 100644 --- a/drivers/net/hplance.c +++ b/drivers/net/hplance.c @@ -220,12 +220,12 @@ static int hplance_close(struct net_device *dev) return 0; } -int __init hplance_init_module(void) +static int __init hplance_init_module(void) { return dio_register_driver(&hplance_driver); } -void __exit hplance_cleanup_module(void) +static void __exit hplance_cleanup_module(void) { dio_unregister_driver(&hplance_driver); } diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index ae398f04c7b..7b6b780dc8a 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -967,8 +967,13 @@ static int __devinit igb_probe(struct pci_dev *pdev, NETIF_F_HW_VLAN_FILTER; netdev->features |= NETIF_F_TSO; - netdev->features |= NETIF_F_TSO6; + + netdev->vlan_features |= NETIF_F_TSO; + netdev->vlan_features |= NETIF_F_TSO6; + netdev->vlan_features |= NETIF_F_HW_CSUM; + netdev->vlan_features |= NETIF_F_SG; + if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c index 9b358f61ed7..679a0826780 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/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index 6321b059ce1..2f38e847e2c 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/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 7b859220c25..0d37c9025be 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3518,8 +3518,13 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, NETIF_F_HW_VLAN_FILTER; netdev->features |= NETIF_F_TSO; - netdev->features |= NETIF_F_TSO6; + + netdev->vlan_features |= NETIF_F_TSO; + netdev->vlan_features |= NETIF_F_TSO6; + netdev->vlan_features |= NETIF_F_HW_CSUM; + netdev->vlan_features |= NETIF_F_SG; + if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; diff --git a/drivers/net/lib8390.c b/drivers/net/lib8390.c index ed495275b57..00d59ab2f8a 100644 --- a/drivers/net/lib8390.c +++ b/drivers/net/lib8390.c @@ -553,6 +553,8 @@ static void __ei_poll(struct net_device *dev) static void ei_tx_err(struct net_device *dev) { unsigned long e8390_base = dev->base_addr; + /* ei_local is used on some platforms via the EI_SHIFT macro */ + struct ei_device *ei_local __maybe_unused = netdev_priv(dev); unsigned char txsr = ei_inb_p(e8390_base+EN0_TSR); unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU); @@ -815,6 +817,8 @@ static void ei_rx_overrun(struct net_device *dev) { unsigned long e8390_base = dev->base_addr; unsigned char was_txing, must_resend = 0; + /* ei_local is used on some platforms via the EI_SHIFT macro */ + struct ei_device *ei_local __maybe_unused = netdev_priv(dev); /* * Record whether a Tx was in progress and then issue the diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c index 9e700749bb3..98e3eb2697c 100644 --- a/drivers/net/mac8390.c +++ b/drivers/net/mac8390.c @@ -117,8 +117,6 @@ enum mac8390_access { ACCESS_16, }; -extern enum mac8390_type mac8390_ident(struct nubus_dev * dev); -extern int mac8390_memsize(unsigned long membase); extern int mac8390_memtest(struct net_device * dev); static int mac8390_initdev(struct net_device * dev, struct nubus_dev * ndev, enum mac8390_type type); @@ -163,7 +161,7 @@ static void slow_sane_block_output(struct net_device *dev, int count, static void word_memcpy_tocard(void *tp, const void *fp, int count); static void word_memcpy_fromcard(void *tp, const void *fp, int count); -enum mac8390_type __init mac8390_ident(struct nubus_dev * dev) +static enum mac8390_type __init mac8390_ident(struct nubus_dev *dev) { switch (dev->dr_sw) { case NUBUS_DRSW_3COM: @@ -234,7 +232,7 @@ enum mac8390_type __init mac8390_ident(struct nubus_dev * dev) return MAC8390_NONE; } -enum mac8390_access __init mac8390_testio(volatile unsigned long membase) +static enum mac8390_access __init mac8390_testio(volatile unsigned long membase) { unsigned long outdata = 0xA5A0B5B0; unsigned long indata = 0x00000000; @@ -252,7 +250,7 @@ enum mac8390_access __init mac8390_testio(volatile unsigned long membase) return ACCESS_UNKNOWN; } -int __init mac8390_memsize(unsigned long membase) +static int __init mac8390_memsize(unsigned long membase) { unsigned long flags; int i, j; diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 92dccd43bdc..e34630252ce 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -80,8 +80,12 @@ static void __init macb_get_hwaddr(struct macb *bp) addr[4] = top & 0xff; addr[5] = (top >> 8) & 0xff; - if (is_valid_ether_addr(addr)) + if (is_valid_ether_addr(addr)) { memcpy(bp->dev->dev_addr, addr, sizeof(addr)); + } else { + dev_info(&bp->pdev->dev, "invalid hw address, using random\n"); + random_ether_addr(bp->dev->dev_addr); + } } static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum) diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c index b267161418e..e64c2086d33 100644 --- a/drivers/net/macsonic.c +++ b/drivers/net/macsonic.c @@ -83,9 +83,6 @@ static unsigned int sonic_debug = 1; static int sonic_version_printed; -extern int mac_onboard_sonic_probe(struct net_device* dev); -extern int mac_nubus_sonic_probe(struct net_device* dev); - /* For onboard SONIC */ #define ONBOARD_SONIC_REGISTERS 0x50F0A000 #define ONBOARD_SONIC_PROM_BASE 0x50f08000 @@ -170,7 +167,7 @@ static int macsonic_close(struct net_device* dev) return err; } -int __init macsonic_init(struct net_device* dev) +static int __init macsonic_init(struct net_device *dev) { struct sonic_local* lp = netdev_priv(dev); @@ -218,7 +215,7 @@ int __init macsonic_init(struct net_device* dev) return 0; } -int __init mac_onboard_sonic_ethernet_addr(struct net_device* dev) +static int __init mac_onboard_sonic_ethernet_addr(struct net_device *dev) { struct sonic_local *lp = netdev_priv(dev); const int prom_addr = ONBOARD_SONIC_PROM_BASE; @@ -284,7 +281,7 @@ int __init mac_onboard_sonic_ethernet_addr(struct net_device* dev) } else return 0; } -int __init mac_onboard_sonic_probe(struct net_device* dev) +static int __init mac_onboard_sonic_probe(struct net_device *dev) { /* Bwahahaha */ static int once_is_more_than_enough; @@ -405,9 +402,9 @@ int __init mac_onboard_sonic_probe(struct net_device* dev) return macsonic_init(dev); } -int __init mac_nubus_sonic_ethernet_addr(struct net_device* dev, - unsigned long prom_addr, - int id) +static int __init mac_nubus_sonic_ethernet_addr(struct net_device *dev, + unsigned long prom_addr, + int id) { int i; for(i = 0; i < 6; i++) @@ -420,7 +417,7 @@ int __init mac_nubus_sonic_ethernet_addr(struct net_device* dev, return 0; } -int __init macsonic_ident(struct nubus_dev* ndev) +static int __init macsonic_ident(struct nubus_dev *ndev) { if (ndev->dr_hw == NUBUS_DRHW_ASANTE_LC && ndev->dr_sw == NUBUS_DRSW_SONIC_LC) @@ -445,7 +442,7 @@ int __init macsonic_ident(struct nubus_dev* ndev) return -1; } -int __init mac_nubus_sonic_probe(struct net_device* dev) +static int __init mac_nubus_sonic_probe(struct net_device *dev) { static int slots; struct nubus_dev* ndev = NULL; diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 58a26a47af2..bafb69b6f7c 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 70cfdb46aa2..f9298827a76 100644 --- a/drivers/net/pppol2tp.c +++ b/drivers/net/pppol2tp.c @@ -783,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; diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 169edc15492..858b191517b 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 dcc953e57ab..5694e894fc7 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/sfc/falcon.c b/drivers/net/sfc/falcon.c index 8cb57987905..630406e142e 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -755,8 +755,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/sh_eth.c b/drivers/net/sh_eth.c new file mode 100644 index 00000000000..f64d987140a --- /dev/null +++ b/drivers/net/sh_eth.c @@ -0,0 +1,1174 @@ +/* + * SuperH Ethernet device driver + * + * Copyright (C) 2006,2007 Nobuhiro Iwamatsu + * Copyright (C) 2008 Renesas Solutions Corp. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + */ + +#include <linux/version.h> +#include <linux/init.h> +#include <linux/dma-mapping.h> +#include <linux/etherdevice.h> +#include <linux/delay.h> +#include <linux/platform_device.h> +#include <linux/mdio-bitbang.h> +#include <linux/netdevice.h> +#include <linux/phy.h> +#include <linux/cache.h> +#include <linux/io.h> + +#include "sh_eth.h" + +/* + * Program the hardware MAC address from dev->dev_addr. + */ +static void update_mac_address(struct net_device *ndev) +{ + u32 ioaddr = ndev->base_addr; + + ctrl_outl((ndev->dev_addr[0] << 24) | (ndev->dev_addr[1] << 16) | + (ndev->dev_addr[2] << 8) | (ndev->dev_addr[3]), + ioaddr + MAHR); + ctrl_outl((ndev->dev_addr[4] << 8) | (ndev->dev_addr[5]), + ioaddr + MALR); +} + +/* + * Get MAC address from SuperH MAC address register + * + * SuperH's Ethernet device doesn't have 'ROM' to MAC address. + * This driver get MAC address that use by bootloader(U-boot or sh-ipl+g). + * When you want use this device, you must set MAC address in bootloader. + * + */ +static void read_mac_address(struct net_device *ndev) +{ + u32 ioaddr = ndev->base_addr; + + ndev->dev_addr[0] = (ctrl_inl(ioaddr + MAHR) >> 24); + ndev->dev_addr[1] = (ctrl_inl(ioaddr + MAHR) >> 16) & 0xFF; + ndev->dev_addr[2] = (ctrl_inl(ioaddr + MAHR) >> 8) & 0xFF; + ndev->dev_addr[3] = (ctrl_inl(ioaddr + MAHR) & 0xFF); + ndev->dev_addr[4] = (ctrl_inl(ioaddr + MALR) >> 8) & 0xFF; + ndev->dev_addr[5] = (ctrl_inl(ioaddr + MALR) & 0xFF); +} + +struct bb_info { + struct mdiobb_ctrl ctrl; + u32 addr; + u32 mmd_msk;/* MMD */ + u32 mdo_msk; + u32 mdi_msk; + u32 mdc_msk; +}; + +/* PHY bit set */ +static void bb_set(u32 addr, u32 msk) +{ + ctrl_outl(ctrl_inl(addr) | msk, addr); +} + +/* PHY bit clear */ +static void bb_clr(u32 addr, u32 msk) +{ + ctrl_outl((ctrl_inl(addr) & ~msk), addr); +} + +/* PHY bit read */ +static int bb_read(u32 addr, u32 msk) +{ + return (ctrl_inl(addr) & msk) != 0; +} + +/* Data I/O pin control */ +static void sh_mmd_ctrl(struct mdiobb_ctrl *ctrl, int bit) +{ + struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl); + if (bit) + bb_set(bitbang->addr, bitbang->mmd_msk); + else + bb_clr(bitbang->addr, bitbang->mmd_msk); +} + +/* Set bit data*/ +static void sh_set_mdio(struct mdiobb_ctrl *ctrl, int bit) +{ + struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl); + + if (bit) + bb_set(bitbang->addr, bitbang->mdo_msk); + else + bb_clr(bitbang->addr, bitbang->mdo_msk); +} + +/* Get bit data*/ +static int sh_get_mdio(struct mdiobb_ctrl *ctrl) +{ + struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl); + return bb_read(bitbang->addr, bitbang->mdi_msk); +} + +/* MDC pin control */ +static void sh_mdc_ctrl(struct mdiobb_ctrl *ctrl, int bit) +{ + struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl); + + if (bit) + bb_set(bitbang->addr, bitbang->mdc_msk); + else + bb_clr(bitbang->addr, bitbang->mdc_msk); +} + +/* mdio bus control struct */ +static struct mdiobb_ops bb_ops = { + .owner = THIS_MODULE, + .set_mdc = sh_mdc_ctrl, + .set_mdio_dir = sh_mmd_ctrl, + .set_mdio_data = sh_set_mdio, + .get_mdio_data = sh_get_mdio, +}; + +static void sh_eth_reset(struct net_device *ndev) +{ + u32 ioaddr = ndev->base_addr; + + ctrl_outl(ctrl_inl(ioaddr + EDMR) | EDMR_SRST, ioaddr + EDMR); + mdelay(3); + ctrl_outl(ctrl_inl(ioaddr + EDMR) & ~EDMR_SRST, ioaddr + EDMR); +} + +/* free skb and descriptor buffer */ +static void sh_eth_ring_free(struct net_device *ndev) +{ + struct sh_eth_private *mdp = netdev_priv(ndev); + int i; + + /* Free Rx skb ringbuffer */ + if (mdp->rx_skbuff) { + for (i = 0; i < RX_RING_SIZE; i++) { + if (mdp->rx_skbuff[i]) + dev_kfree_skb(mdp->rx_skbuff[i]); + } + } + kfree(mdp->rx_skbuff); + + /* Free Tx skb ringbuffer */ + if (mdp->tx_skbuff) { + for (i = 0; i < TX_RING_SIZE; i++) { + if (mdp->tx_skbuff[i]) + dev_kfree_skb(mdp->tx_skbuff[i]); + } + } + kfree(mdp->tx_skbuff); +} + +/* format skb and descriptor buffer */ +static void sh_eth_ring_format(struct net_device *ndev) +{ + struct sh_eth_private *mdp = netdev_priv(ndev); + int i; + struct sk_buff *skb; + struct sh_eth_rxdesc *rxdesc = NULL; + struct sh_eth_txdesc *txdesc = NULL; + int rx_ringsize = sizeof(*rxdesc) * RX_RING_SIZE; + int tx_ringsize = sizeof(*txdesc) * TX_RING_SIZE; + + mdp->cur_rx = mdp->cur_tx = 0; + mdp->dirty_rx = mdp->dirty_tx = 0; + + memset(mdp->rx_ring, 0, rx_ringsize); + + /* build Rx ring buffer */ + for (i = 0; i < RX_RING_SIZE; i++) { + /* skb */ + mdp->rx_skbuff[i] = NULL; + skb = dev_alloc_skb(mdp->rx_buf_sz); + mdp->rx_skbuff[i] = skb; + if (skb == NULL) + break; + skb->dev = ndev; /* Mark as being used by this device. */ + skb_reserve(skb, RX_OFFSET); + + /* RX descriptor */ + rxdesc = &mdp->rx_ring[i]; + rxdesc->addr = (u32)skb->data & ~0x3UL; + rxdesc->status = cpu_to_le32(RD_RACT | RD_RFP); + + /* The size of the buffer is 16 byte boundary. */ + rxdesc->buffer_length = (mdp->rx_buf_sz + 16) & ~0x0F; + } + + mdp->dirty_rx = (u32) (i - RX_RING_SIZE); + + /* Mark the last entry as wrapping the ring. */ + rxdesc->status |= cpu_to_le32(RC_RDEL); + + memset(mdp->tx_ring, 0, tx_ringsize); + + /* build Tx ring buffer */ + for (i = 0; i < TX_RING_SIZE; i++) { + mdp->tx_skbuff[i] = NULL; + txdesc = &mdp->tx_ring[i]; + txdesc->status = cpu_to_le32(TD_TFP); + txdesc->buffer_length = 0; + } + + txdesc->status |= cpu_to_le32(TD_TDLE); +} + +/* Get skb and descriptor buffer */ +static int sh_eth_ring_init(struct net_device *ndev) +{ + struct sh_eth_private *mdp = netdev_priv(ndev); + int rx_ringsize, tx_ringsize, ret = 0; + + /* + * +26 gets the maximum ethernet encapsulation, +7 & ~7 because the + * card needs room to do 8 byte alignment, +2 so we can reserve + * the first 2 bytes, and +16 gets room for the status word from the + * card. + */ + mdp->rx_buf_sz = (ndev->mtu <= 1492 ? PKT_BUF_SZ : + (((ndev->mtu + 26 + 7) & ~7) + 2 + 16)); + + /* Allocate RX and TX skb rings */ + mdp->rx_skbuff = kmalloc(sizeof(*mdp->rx_skbuff) * RX_RING_SIZE, + GFP_KERNEL); + if (!mdp->rx_skbuff) { + printk(KERN_ERR "%s: Cannot allocate Rx skb\n", ndev->name); + ret = -ENOMEM; + return ret; + } + + mdp->tx_skbuff = kmalloc(sizeof(*mdp->tx_skbuff) * TX_RING_SIZE, + GFP_KERNEL); + if (!mdp->tx_skbuff) { + printk(KERN_ERR "%s: Cannot allocate Tx skb\n", ndev->name); + ret = -ENOMEM; + goto skb_ring_free; + } + + /* Allocate all Rx descriptors. */ + rx_ringsize = sizeof(struct sh_eth_rxdesc) * RX_RING_SIZE; + mdp->rx_ring = dma_alloc_coherent(NULL, rx_ringsize, &mdp->rx_desc_dma, + GFP_KERNEL); + + if (!mdp->rx_ring) { + printk(KERN_ERR "%s: Cannot allocate Rx Ring (size %d bytes)\n", + ndev->name, rx_ringsize); + ret = -ENOMEM; + goto desc_ring_free; + } + + mdp->dirty_rx = 0; + + /* Allocate all Tx descriptors. */ + tx_ringsize = sizeof(struct sh_eth_txdesc) * TX_RING_SIZE; + mdp->tx_ring = dma_alloc_coherent(NULL, tx_ringsize, &mdp->tx_desc_dma, + GFP_KERNEL); + if (!mdp->tx_ring) { + printk(KERN_ERR "%s: Cannot allocate Tx Ring (size %d bytes)\n", + ndev->name, tx_ringsize); + ret = -ENOMEM; + goto desc_ring_free; + } + return ret; + +desc_ring_free: + /* free DMA buffer */ + dma_free_coherent(NULL, rx_ringsize, mdp->rx_ring, mdp->rx_desc_dma); + +skb_ring_free: + /* Free Rx and Tx skb ring buffer */ + sh_eth_ring_free(ndev); + + return ret; +} + +static int sh_eth_dev_init(struct net_device *ndev) +{ + int ret = 0; + struct sh_eth_private *mdp = netdev_priv(ndev); + u32 ioaddr = ndev->base_addr; + u_int32_t rx_int_var, tx_int_var; + u32 val; + + /* Soft Reset */ + sh_eth_reset(ndev); + + ctrl_outl(RPADIR_PADS1, ioaddr + RPADIR); /* SH7712-DMA-RX-PAD2 */ + + /* all sh_eth int mask */ + ctrl_outl(0, ioaddr + EESIPR); + + /* FIFO size set */ + ctrl_outl(0, ioaddr + EDMR); /* Endian change */ + + ctrl_outl((FIFO_SIZE_T | FIFO_SIZE_R), ioaddr + FDR); + ctrl_outl(0, ioaddr + TFTR); + + ctrl_outl(RMCR_RST, ioaddr + RMCR); + + rx_int_var = mdp->rx_int_var = DESC_I_RINT8 | DESC_I_RINT5; + tx_int_var = mdp->tx_int_var = DESC_I_TINT2; + ctrl_outl(rx_int_var | tx_int_var, ioaddr + TRSCER); + + ctrl_outl((FIFO_F_D_RFF | FIFO_F_D_RFD), ioaddr + FCFTR); + ctrl_outl(0, ioaddr + TRIMD); + + /* Descriptor format */ + sh_eth_ring_format(ndev); + + ctrl_outl((u32)mdp->rx_ring, ioaddr + RDLAR); + ctrl_outl((u32)mdp->tx_ring, ioaddr + TDLAR); + + ctrl_outl(ctrl_inl(ioaddr + EESR), ioaddr + EESR); + ctrl_outl((DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff), ioaddr + EESIPR); + + /* PAUSE Prohibition */ + val = (ctrl_inl(ioaddr + ECMR) & ECMR_DM) | + ECMR_ZPF | (mdp->duplex ? ECMR_DM : 0) | ECMR_TE | ECMR_RE; + + ctrl_outl(val, ioaddr + ECMR); + ctrl_outl(ECSR_BRCRX | ECSR_PSRTO | ECSR_LCHNG | ECSR_ICD | + ECSIPR_MPDIP, ioaddr + ECSR); + ctrl_outl(ECSIPR_BRCRXIP | ECSIPR_PSRTOIP | ECSIPR_LCHNGIP | + ECSIPR_ICDIP | ECSIPR_MPDIP, ioaddr + ECSIPR); + + /* Set MAC address */ + update_mac_address(ndev); + + /* mask reset */ +#if defined(CONFIG_CPU_SUBTYPE_SH7710) + ctrl_outl(APR_AP, ioaddr + APR); + ctrl_outl(MPR_MP, ioaddr + MPR); + ctrl_outl(TPAUSER_UNLIMITED, ioaddr + TPAUSER); + ctrl_outl(BCFR_UNLIMITED, ioaddr + BCFR); +#endif + /* Setting the Rx mode will start the Rx process. */ + ctrl_outl(EDRRR_R, ioaddr + EDRRR); + + netif_start_queue(ndev); + + return ret; +} + +/* free Tx skb function */ +static int sh_eth_txfree(struct net_device *ndev) +{ + struct sh_eth_private *mdp = netdev_priv(ndev); + struct sh_eth_txdesc *txdesc; + int freeNum = 0; + int entry = 0; + + for (; mdp->cur_tx - mdp->dirty_tx > 0; mdp->dirty_tx++) { + entry = mdp->dirty_tx % TX_RING_SIZE; + txdesc = &mdp->tx_ring[entry]; + if (txdesc->status & cpu_to_le32(TD_TACT)) + break; + /* Free the original skb. */ + if (mdp->tx_skbuff[entry]) { + dev_kfree_skb_irq(mdp->tx_skbuff[entry]); + mdp->tx_skbuff[entry] = NULL; + freeNum++; + } + txdesc->status = cpu_to_le32(TD_TFP); + if (entry >= TX_RING_SIZE - 1) + txdesc->status |= cpu_to_le32(TD_TDLE); + + mdp->stats.tx_packets++; + mdp->stats.tx_bytes += txdesc->buffer_length; + } + return freeNum; +} + +/* Packet receive function */ +static int sh_eth_rx(struct net_device *ndev) +{ + struct sh_eth_private *mdp = netdev_priv(ndev); + struct sh_eth_rxdesc *rxdesc; + + int entry = mdp->cur_rx % RX_RING_SIZE; + int boguscnt = (mdp->dirty_rx + RX_RING_SIZE) - mdp->cur_rx; + struct sk_buff *skb; + u16 pkt_len = 0; + u32 desc_status; + + rxdesc = &mdp->rx_ring[entry]; + while (!(rxdesc->status & cpu_to_le32(RD_RACT))) { + desc_status = le32_to_cpu(rxdesc->status); + pkt_len = rxdesc->frame_length; + + if (--boguscnt < 0) + break; + + if (!(desc_status & RDFEND)) + mdp->stats.rx_length_errors++; + + if (desc_status & (RD_RFS1 | RD_RFS2 | RD_RFS3 | RD_RFS4 | + RD_RFS5 | RD_RFS6 | RD_RFS10)) { + mdp->stats.rx_errors++; + if (desc_status & RD_RFS1) + mdp->stats.rx_crc_errors++; + if (desc_status & RD_RFS2) + mdp->stats.rx_frame_errors++; + if (desc_status & RD_RFS3) + mdp->stats.rx_length_errors++; + if (desc_status & RD_RFS4) + mdp->stats.rx_length_errors++; + if (desc_status & RD_RFS6) + mdp->stats.rx_missed_errors++; + if (desc_status & RD_RFS10) + mdp->stats.rx_over_errors++; + } else { + swaps((char *)(rxdesc->addr & ~0x3), pkt_len + 2); + skb = mdp->rx_skbuff[entry]; + mdp->rx_skbuff[entry] = NULL; + skb_put(skb, pkt_len); + skb->protocol = eth_type_trans(skb, ndev); + netif_rx(skb); + ndev->last_rx = jiffies; + mdp->stats.rx_packets++; + mdp->stats.rx_bytes += pkt_len; + } + rxdesc->status |= cpu_to_le32(RD_RACT); + entry = (++mdp->cur_rx) % RX_RING_SIZE; + } + + /* Refill the Rx ring buffers. */ + for (; mdp->cur_rx - mdp->dirty_rx > 0; mdp->dirty_rx++) { + entry = mdp->dirty_rx % RX_RING_SIZE; + rxdesc = &mdp->rx_ring[entry]; + if (mdp->rx_skbuff[entry] == NULL) { + skb = dev_alloc_skb(mdp->rx_buf_sz); + mdp->rx_skbuff[entry] = skb; + if (skb == NULL) + break; /* Better luck next round. */ + skb->dev = ndev; + skb_reserve(skb, RX_OFFSET); + rxdesc->addr = (u32)skb->data & ~0x3UL; + } + /* The size of the buffer is 16 byte boundary. */ + rxdesc->buffer_length = (mdp->rx_buf_sz + 16) & ~0x0F; + if (entry >= RX_RING_SIZE - 1) + rxdesc->status |= + cpu_to_le32(RD_RACT | RD_RFP | RC_RDEL); + else + rxdesc->status |= + cpu_to_le32(RD_RACT | RD_RFP); + } + + /* Restart Rx engine if stopped. */ + /* If we don't need to check status, don't. -KDU */ + ctrl_outl(EDRRR_R, ndev->base_addr + EDRRR); + + return 0; +} + +/* error control function */ +static void sh_eth_error(struct net_device *ndev, int intr_status) +{ + struct sh_eth_private *mdp = netdev_priv(ndev); + u32 ioaddr = ndev->base_addr; + u32 felic_stat; + + if (intr_status & EESR_ECI) { + felic_stat = ctrl_inl(ioaddr + ECSR); + ctrl_outl(felic_stat, ioaddr + ECSR); /* clear int */ + if (felic_stat & ECSR_ICD) + mdp->stats.tx_carrier_errors++; + if (felic_stat & ECSR_LCHNG) { + /* Link Changed */ + u32 link_stat = (ctrl_inl(ioaddr + PSR)); + if (!(link_stat & PHY_ST_LINK)) { + /* Link Down : disable tx and rx */ + ctrl_outl(ctrl_inl(ioaddr + ECMR) & + ~(ECMR_RE | ECMR_TE), ioaddr + ECMR); + } else { + /* Link Up */ + ctrl_outl(ctrl_inl(ioaddr + EESIPR) & + ~DMAC_M_ECI, ioaddr + EESIPR); + /*clear int */ + ctrl_outl(ctrl_inl(ioaddr + ECSR), + ioaddr + ECSR); + ctrl_outl(ctrl_inl(ioaddr + EESIPR) | + DMAC_M_ECI, ioaddr + EESIPR); + /* enable tx and rx */ + ctrl_outl(ctrl_inl(ioaddr + ECMR) | + (ECMR_RE | ECMR_TE), ioaddr + ECMR); + } + } + } + + if (intr_status & EESR_TWB) { + /* Write buck end. unused write back interrupt */ + if (intr_status & EESR_TABT) /* Transmit Abort int */ + mdp->stats.tx_aborted_errors++; + } + + if (intr_status & EESR_RABT) { + /* Receive Abort int */ + if (intr_status & EESR_RFRMER) { + /* Receive Frame Overflow int */ + mdp->stats.rx_frame_errors++; + printk(KERN_ERR "Receive Frame Overflow\n"); + } + } + + if (intr_status & EESR_ADE) { + if (intr_status & EESR_TDE) { + if (intr_status & EESR_TFE) + mdp->stats.tx_fifo_errors++; + } + } + + if (intr_status & EESR_RDE) { + /* Receive Descriptor Empty int */ + mdp->stats.rx_over_errors++; + + if (ctrl_inl(ioaddr + EDRRR) ^ EDRRR_R) + ctrl_outl(EDRRR_R, ioaddr + EDRRR); + printk(KERN_ERR "Receive Descriptor Empty\n"); + } + if (intr_status & EESR_RFE) { + /* Receive FIFO Overflow int */ + mdp->stats.rx_fifo_errors++; + printk(KERN_ERR "Receive FIFO Overflow\n"); + } + if (intr_status & + (EESR_TWB | EESR_TABT | EESR_ADE | EESR_TDE | EESR_TFE)) { + /* Tx error */ + u32 edtrr = ctrl_inl(ndev->base_addr + EDTRR); + /* dmesg */ + printk(KERN_ERR "%s:TX error. status=%8.8x cur_tx=%8.8x ", + ndev->name, intr_status, mdp->cur_tx); + printk(KERN_ERR "dirty_tx=%8.8x state=%8.8x EDTRR=%8.8x.\n", + mdp->dirty_tx, (u32) ndev->state, edtrr); + /* dirty buffer free */ + sh_eth_txfree(ndev); + + /* SH7712 BUG */ + if (edtrr ^ EDTRR_TRNS) { + /* tx dma start */ + ctrl_outl(EDTRR_TRNS, ndev->base_addr + EDTRR); + } + /* wakeup */ + netif_wake_queue(ndev); + } +} + +static irqreturn_t sh_eth_interrupt(int irq, void *netdev) +{ + struct net_device *ndev = netdev; + struct sh_eth_private *mdp = netdev_priv(ndev); + u32 ioaddr, boguscnt = RX_RING_SIZE; + u32 intr_status = 0; + + ioaddr = ndev->base_addr; + spin_lock(&mdp->lock); + + intr_status = ctrl_inl(ioaddr + EESR); + /* Clear interrupt */ + ctrl_outl(intr_status, ioaddr + EESR); + + if (intr_status & (EESR_FRC | EESR_RINT8 | + EESR_RINT5 | EESR_RINT4 | EESR_RINT3 | EESR_RINT2 | + EESR_RINT1)) + sh_eth_rx(ndev); + if (intr_status & (EESR_FTC | + EESR_TINT4 | EESR_TINT3 | EESR_TINT2 | EESR_TINT1)) { + + sh_eth_txfree(ndev); + netif_wake_queue(ndev); + } + + if (intr_status & EESR_ERR_CHECK) + sh_eth_error(ndev, intr_status); + + if (--boguscnt < 0) { + printk(KERN_WARNING + "%s: Too much work at interrupt, status=0x%4.4x.\n", + ndev->name, intr_status); + } + + spin_unlock(&mdp->lock); + + return IRQ_HANDLED; +} + +static void sh_eth_timer(unsigned long data) +{ + struct net_device *ndev = (struct net_device *)data; + struct sh_eth_private *mdp = netdev_priv(ndev); + + mod_timer(&mdp->timer, jiffies + (10 * HZ)); +} + +/* PHY state control function */ +static void sh_eth_adjust_link(struct net_device *ndev) +{ + struct sh_eth_private *mdp = netdev_priv(ndev); + struct phy_device *phydev = mdp->phydev; + u32 ioaddr = ndev->base_addr; + int new_state = 0; + + if (phydev->link != PHY_DOWN) { + if (phydev->duplex != mdp->duplex) { + new_state = 1; + mdp->duplex = phydev->duplex; + } + + if (phydev->speed != mdp->speed) { + new_state = 1; + mdp->speed = phydev->speed; + } + if (mdp->link == PHY_DOWN) { + ctrl_outl((ctrl_inl(ioaddr + ECMR) & ~ECMR_TXF) + | ECMR_DM, ioaddr + ECMR); + new_state = 1; + mdp->link = phydev->link; + netif_schedule(ndev); + netif_carrier_on(ndev); + netif_start_queue(ndev); + } + } else if (mdp->link) { + new_state = 1; + mdp->link = PHY_DOWN; + mdp->speed = 0; + mdp->duplex = -1; + netif_stop_queue(ndev); + netif_carrier_off(ndev); + } + + if (new_state) + phy_print_status(phydev); +} + +/* PHY init function */ +static int sh_eth_phy_init(struct net_device *ndev) +{ + struct sh_eth_private *mdp = netdev_priv(ndev); + char phy_id[BUS_ID_SIZE]; + struct phy_device *phydev = NULL; + + snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, + mdp->mii_bus->id , mdp->phy_id); + + mdp->link = PHY_DOWN; + mdp->speed = 0; + mdp->duplex = -1; + + /* Try connect to PHY */ + phydev = phy_connect(ndev, phy_id, &sh_eth_adjust_link, + 0, PHY_INTERFACE_MODE_MII); + if (IS_ERR(phydev)) { + dev_err(&ndev->dev, "phy_connect failed\n"); + return PTR_ERR(phydev); + } + dev_info(&ndev->dev, "attached phy %i to driver %s\n", + phydev->addr, phydev->drv->name); + + mdp->phydev = phydev; + + return 0; +} + +/* PHY control start function */ +static int sh_eth_phy_start(struct net_device *ndev) +{ + struct sh_eth_private *mdp = netdev_priv(ndev); + int ret; + + ret = sh_eth_phy_init(ndev); + if (ret) + return ret; + + /* reset phy - this also wakes it from PDOWN */ + phy_write(mdp->phydev, MII_BMCR, BMCR_RESET); + phy_start(mdp->phydev); + + return 0; +} + +/* network device open function */ +static int sh_eth_open(struct net_device *ndev) +{ + int ret = 0; + struct sh_eth_private *mdp = netdev_priv(ndev); + + ret = request_irq(ndev->irq, &sh_eth_interrupt, 0, ndev->name, ndev); + if (ret) { + printk(KERN_ERR "Can not assign IRQ number to %s\n", CARDNAME); + return ret; + } + + /* Descriptor set */ + ret = sh_eth_ring_init(ndev); + if (ret) + goto out_free_irq; + + /* device init */ + ret = sh_eth_dev_init(ndev); + if (ret) + goto out_free_irq; + + /* PHY control start*/ + ret = sh_eth_phy_start(ndev); + if (ret) + goto out_free_irq; + + /* Set the timer to check for link beat. */ + init_timer(&mdp->timer); + mdp->timer.expires = (jiffies + (24 * HZ)) / 10;/* 2.4 sec. */ + setup_timer(&mdp->timer, sh_eth_timer, ndev); + + return ret; + +out_free_irq: + free_irq(ndev->irq, ndev); + return ret; +} + +/* Timeout function */ +static void sh_eth_tx_timeout(struct net_device *ndev) +{ + struct sh_eth_private *mdp = netdev_priv(ndev); + u32 ioaddr = ndev->base_addr; + struct sh_eth_rxdesc *rxdesc; + int i; + + netif_stop_queue(ndev); + + /* worning message out. */ + printk(KERN_WARNING "%s: transmit timed out, status %8.8x," + " resetting...\n", ndev->name, (int)ctrl_inl(ioaddr + EESR)); + + /* tx_errors count up */ + mdp->stats.tx_errors++; + + /* timer off */ + del_timer_sync(&mdp->timer); + + /* Free all the skbuffs in the Rx queue. */ + for (i = 0; i < RX_RING_SIZE; i++) { + rxdesc = &mdp->rx_ring[i]; + rxdesc->status = 0; + rxdesc->addr = 0xBADF00D0; + if (mdp->rx_skbuff[i]) + dev_kfree_skb(mdp->rx_skbuff[i]); + mdp->rx_skbuff[i] = NULL; + } + for (i = 0; i < TX_RING_SIZE; i++) { + if (mdp->tx_skbuff[i]) + dev_kfree_skb(mdp->tx_skbuff[i]); + mdp->tx_skbuff[i] = NULL; + } + + /* device init */ + sh_eth_dev_init(ndev); + + /* timer on */ + mdp->timer.expires = (jiffies + (24 * HZ)) / 10;/* 2.4 sec. */ + add_timer(&mdp->timer); +} + +/* Packet transmit function */ +static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev) +{ + struct sh_eth_private *mdp = netdev_priv(ndev); + struct sh_eth_txdesc *txdesc; + u32 entry; + int flags; + + spin_lock_irqsave(&mdp->lock, flags); + if ((mdp->cur_tx - mdp->dirty_tx) >= (TX_RING_SIZE - 4)) { + if (!sh_eth_txfree(ndev)) { + netif_stop_queue(ndev); + spin_unlock_irqrestore(&mdp->lock, flags); + return 1; + } + } + spin_unlock_irqrestore(&mdp->lock, flags); + + entry = mdp->cur_tx % TX_RING_SIZE; + mdp->tx_skbuff[entry] = skb; + txdesc = &mdp->tx_ring[entry]; + txdesc->addr = (u32)(skb->data); + /* soft swap. */ + swaps((char *)(txdesc->addr & ~0x3), skb->len + 2); + /* write back */ + __flush_purge_region(skb->data, skb->len); + if (skb->len < ETHERSMALL) + txdesc->buffer_length = ETHERSMALL; + else + txdesc->buffer_length = skb->len; + + if (entry >= TX_RING_SIZE - 1) + txdesc->status |= cpu_to_le32(TD_TACT | TD_TDLE); + else + txdesc->status |= cpu_to_le32(TD_TACT); + + mdp->cur_tx++; + + ctrl_outl(EDTRR_TRNS, ndev->base_addr + EDTRR); + ndev->trans_start = jiffies; + + return 0; +} + +/* device close function */ +static int sh_eth_close(struct net_device *ndev) +{ + struct sh_eth_private *mdp = netdev_priv(ndev); + u32 ioaddr = ndev->base_addr; + int ringsize; + + netif_stop_queue(ndev); + + /* Disable interrupts by clearing the interrupt mask. */ + ctrl_outl(0x0000, ioaddr + EESIPR); + + /* Stop the chip's Tx and Rx processes. */ + ctrl_outl(0, ioaddr + EDTRR); + ctrl_outl(0, ioaddr + EDRRR); + + /* PHY Disconnect */ + if (mdp->phydev) { + phy_stop(mdp->phydev); + phy_disconnect(mdp->phydev); + } + + free_irq(ndev->irq, ndev); + + del_timer_sync(&mdp->timer); + + /* Free all the skbuffs in the Rx queue. */ + sh_eth_ring_free(ndev); + + /* free DMA buffer */ + ringsize = sizeof(struct sh_eth_rxdesc) * RX_RING_SIZE; + dma_free_coherent(NULL, ringsize, mdp->rx_ring, mdp->rx_desc_dma); + + /* free DMA buffer */ + ringsize = sizeof(struct sh_eth_txdesc) * TX_RING_SIZE; + dma_free_coherent(NULL, ringsize, mdp->tx_ring, mdp->tx_desc_dma); + + return 0; +} + +static struct net_device_stats *sh_eth_get_stats(struct net_device *ndev) +{ + struct sh_eth_private *mdp = netdev_priv(ndev); + u32 ioaddr = ndev->base_addr; + + mdp->stats.tx_dropped += ctrl_inl(ioaddr + TROCR); + ctrl_outl(0, ioaddr + TROCR); /* (write clear) */ + mdp->stats.collisions += ctrl_inl(ioaddr + CDCR); + ctrl_outl(0, ioaddr + CDCR); /* (write clear) */ + mdp->stats.tx_carrier_errors += ctrl_inl(ioaddr + LCCR); + ctrl_outl(0, ioaddr + LCCR); /* (write clear) */ + mdp->stats.tx_carrier_errors += ctrl_inl(ioaddr + CNDCR); + ctrl_outl(0, ioaddr + CNDCR); /* (write clear) */ + + return &mdp->stats; +} + +/* ioctl to device funciotn*/ +static int sh_eth_do_ioctl(struct net_device *ndev, struct ifreq *rq, + int cmd) +{ + struct sh_eth_private *mdp = netdev_priv(ndev); + struct phy_device *phydev = mdp->phydev; + + if (!netif_running(ndev)) + return -EINVAL; + + if (!phydev) + return -ENODEV; + + return phy_mii_ioctl(phydev, if_mii(rq), cmd); +} + + +/* Multicast reception directions set */ +static void sh_eth_set_multicast_list(struct net_device *ndev) +{ + u32 ioaddr = ndev->base_addr; + + if (ndev->flags & IFF_PROMISC) { + /* Set promiscuous. */ + ctrl_outl((ctrl_inl(ioaddr + ECMR) & ~ECMR_MCT) | ECMR_PRM, + ioaddr + ECMR); + } else { + /* Normal, unicast/broadcast-only mode. */ + ctrl_outl((ctrl_inl(ioaddr + ECMR) & ~ECMR_PRM) | ECMR_MCT, + ioaddr + ECMR); + } +} + +/* SuperH's TSU register init function */ +static void sh_eth_tsu_init(u32 ioaddr) +{ + ctrl_outl(0, ioaddr + TSU_FWEN0); /* Disable forward(0->1) */ + ctrl_outl(0, ioaddr + TSU_FWEN1); /* Disable forward(1->0) */ + ctrl_outl(0, ioaddr + TSU_FCM); /* forward fifo 3k-3k */ + ctrl_outl(0xc, ioaddr + TSU_BSYSL0); + ctrl_outl(0xc, ioaddr + TSU_BSYSL1); + ctrl_outl(0, ioaddr + TSU_PRISL0); + ctrl_outl(0, ioaddr + TSU_PRISL1); + ctrl_outl(0, ioaddr + TSU_FWSL0); + ctrl_outl(0, ioaddr + TSU_FWSL1); + ctrl_outl(TSU_FWSLC_POSTENU | TSU_FWSLC_POSTENL, ioaddr + TSU_FWSLC); + ctrl_outl(0, ioaddr + TSU_QTAGM0); /* Disable QTAG(0->1) */ + ctrl_outl(0, ioaddr + TSU_QTAGM1); /* Disable QTAG(1->0) */ + ctrl_outl(0, ioaddr + TSU_FWSR); /* all interrupt status clear */ + ctrl_outl(0, ioaddr + TSU_FWINMK); /* Disable all interrupt */ + ctrl_outl(0, ioaddr + TSU_TEN); /* Disable all CAM entry */ + ctrl_outl(0, ioaddr + TSU_POST1); /* Disable CAM entry [ 0- 7] */ + ctrl_outl(0, ioaddr + TSU_POST2); /* Disable CAM entry [ 8-15] */ + ctrl_outl(0, ioaddr + TSU_POST3); /* Disable CAM entry [16-23] */ + ctrl_outl(0, ioaddr + TSU_POST4); /* Disable CAM entry [24-31] */ +} + +/* MDIO bus release function */ +static int sh_mdio_release(struct net_device *ndev) +{ + struct mii_bus *bus = dev_get_drvdata(&ndev->dev); + + /* unregister mdio bus */ + mdiobus_unregister(bus); + + /* remove mdio bus info from net_device */ + dev_set_drvdata(&ndev->dev, NULL); + + /* free bitbang info */ + free_mdio_bitbang(bus); + + return 0; +} + +/* MDIO bus init function */ +static int sh_mdio_init(struct net_device *ndev, int id) +{ + int ret, i; + struct bb_info *bitbang; + struct sh_eth_private *mdp = netdev_priv(ndev); + + /* create bit control struct for PHY */ + bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL); + if (!bitbang) { + ret = -ENOMEM; + goto out; + } + + /* bitbang init */ + bitbang->addr = ndev->base_addr + PIR; + bitbang->mdi_msk = 0x08; + bitbang->mdo_msk = 0x04; + bitbang->mmd_msk = 0x02;/* MMD */ + bitbang->mdc_msk = 0x01; + bitbang->ctrl.ops = &bb_ops; + + /* MII contorller setting */ + mdp->mii_bus = alloc_mdio_bitbang(&bitbang->ctrl); + if (!mdp->mii_bus) { + ret = -ENOMEM; + goto out_free_bitbang; + } + + /* Hook up MII support for ethtool */ + mdp->mii_bus->name = "sh_mii"; + mdp->mii_bus->dev = &ndev->dev; + mdp->mii_bus->id = id; + + /* PHY IRQ */ + mdp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL); + if (!mdp->mii_bus->irq) { + ret = -ENOMEM; + goto out_free_bus; + } + + for (i = 0; i < PHY_MAX_ADDR; i++) + mdp->mii_bus->irq[i] = PHY_POLL; + + /* regist mdio bus */ + ret = mdiobus_register(mdp->mii_bus); + if (ret) + goto out_free_irq; + + dev_set_drvdata(&ndev->dev, mdp->mii_bus); + + return 0; + +out_free_irq: + kfree(mdp->mii_bus->irq); + +out_free_bus: + kfree(mdp->mii_bus); + +out_free_bitbang: + kfree(bitbang); + +out: + return ret; +} + +static int sh_eth_drv_probe(struct platform_device *pdev) +{ + int ret, i, devno = 0; + struct resource *res; + struct net_device *ndev = NULL; + struct sh_eth_private *mdp; + + /* get base addr */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (unlikely(res == NULL)) { + dev_err(&pdev->dev, "invalid resource\n"); + ret = -EINVAL; + goto out; + } + + ndev = alloc_etherdev(sizeof(struct sh_eth_private)); + if (!ndev) { + printk(KERN_ERR "%s: could not allocate device.\n", CARDNAME); + ret = -ENOMEM; + goto out; + } + + /* The sh Ether-specific entries in the device structure. */ + ndev->base_addr = res->start; + devno = pdev->id; + if (devno < 0) + devno = 0; + + ndev->dma = -1; + ndev->irq = platform_get_irq(pdev, 0); + if (ndev->irq < 0) { + ret = -ENODEV; + goto out_release; + } + + SET_NETDEV_DEV(ndev, &pdev->dev); + + /* Fill in the fields of the device structure with ethernet values. */ + ether_setup(ndev); + + mdp = netdev_priv(ndev); + spin_lock_init(&mdp->lock); + + /* get PHY ID */ + mdp->phy_id = (int)pdev->dev.platform_data; + + /* set function */ + ndev->open = sh_eth_open; + ndev->hard_start_xmit = sh_eth_start_xmit; + ndev->stop = sh_eth_close; + ndev->get_stats = sh_eth_get_stats; + ndev->set_multicast_list = sh_eth_set_multicast_list; + ndev->do_ioctl = sh_eth_do_ioctl; + ndev->tx_timeout = sh_eth_tx_timeout; + ndev->watchdog_timeo = TX_TIMEOUT; + + mdp->post_rx = POST_RX >> (devno << 1); + mdp->post_fw = POST_FW >> (devno << 1); + + /* read and set MAC address */ + read_mac_address(ndev); + + /* First device only init */ + if (!devno) { + /* reset device */ + ctrl_outl(ARSTR_ARSTR, ndev->base_addr + ARSTR); + mdelay(1); + + /* TSU init (Init only)*/ + sh_eth_tsu_init(SH_TSU_ADDR); + } + + /* network device register */ + ret = register_netdev(ndev); + if (ret) + goto out_release; + + /* mdio bus init */ + ret = sh_mdio_init(ndev, pdev->id); + if (ret) + goto out_unregister; + + /* pritnt device infomation */ + printk(KERN_INFO "%s: %s at 0x%x, ", + ndev->name, CARDNAME, (u32) ndev->base_addr); + + for (i = 0; i < 5; i++) + printk(KERN_INFO "%2.2x:", ndev->dev_addr[i]); + printk(KERN_INFO "%2.2x, IRQ %d.\n", ndev->dev_addr[i], ndev->irq); + + platform_set_drvdata(pdev, ndev); + + return ret; + +out_unregister: + unregister_netdev(ndev); + +out_release: + /* net_dev free */ + if (ndev) + free_netdev(ndev); + +out: + return ret; +} + +static int sh_eth_drv_remove(struct platform_device *pdev) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + + sh_mdio_release(ndev); + unregister_netdev(ndev); + flush_scheduled_work(); + + free_netdev(ndev); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver sh_eth_driver = { + .probe = sh_eth_drv_probe, + .remove = sh_eth_drv_remove, + .driver = { + .name = CARDNAME, + }, +}; + +static int __init sh_eth_init(void) +{ + return platform_driver_register(&sh_eth_driver); +} + +static void __exit sh_eth_cleanup(void) +{ + platform_driver_unregister(&sh_eth_driver); +} + +module_init(sh_eth_init); +module_exit(sh_eth_cleanup); + +MODULE_AUTHOR("Nobuhiro Iwamatsu, Yoshihiro Shimoda"); +MODULE_DESCRIPTION("Renesas SuperH Ethernet driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/sh_eth.h b/drivers/net/sh_eth.h new file mode 100644 index 00000000000..ca2db6bb3c6 --- /dev/null +++ b/drivers/net/sh_eth.h @@ -0,0 +1,464 @@ +/* + * SuperH Ethernet device driver + * + * Copyright (C) 2006-2008 Nobuhiro Iwamatsu + * Copyright (C) 2008 Renesas Solutions Corp. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + */ + +#ifndef __SH_ETH_H__ +#define __SH_ETH_H__ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/spinlock.h> +#include <linux/workqueue.h> +#include <linux/netdevice.h> +#include <linux/phy.h> + +#define CARDNAME "sh-eth" +#define TX_TIMEOUT (5*HZ) + +#define TX_RING_SIZE 128 /* Tx ring size */ +#define RX_RING_SIZE 128 /* Rx ring size */ +#define RX_OFFSET 2 /* skb offset */ +#define ETHERSMALL 60 +#define PKT_BUF_SZ 1538 + +/* Chip Base Address */ +#define SH_ETH0_BASE 0xA7000000 +#define SH_ETH1_BASE 0xA7000400 +#define SH_TSU_ADDR 0xA7000804 + +/* Chip Registers */ +/* E-DMAC */ +#define EDMR 0x0000 +#define EDTRR 0x0004 +#define EDRRR 0x0008 +#define TDLAR 0x000C +#define RDLAR 0x0010 +#define EESR 0x0014 +#define EESIPR 0x0018 +#define TRSCER 0x001C +#define RMFCR 0x0020 +#define TFTR 0x0024 +#define FDR 0x0028 +#define RMCR 0x002C +#define EDOCR 0x0030 +#define FCFTR 0x0034 +#define RPADIR 0x0038 +#define TRIMD 0x003C +#define RBWAR 0x0040 +#define RDFAR 0x0044 +#define TBRAR 0x004C +#define TDFAR 0x0050 +/* Ether Register */ +#define ECMR 0x0160 +#define ECSR 0x0164 +#define ECSIPR 0x0168 +#define PIR 0x016C +#define MAHR 0x0170 +#define MALR 0x0174 +#define RFLR 0x0178 +#define PSR 0x017C +#define TROCR 0x0180 +#define CDCR 0x0184 +#define LCCR 0x0188 +#define CNDCR 0x018C +#define CEFCR 0x0194 +#define FRECR 0x0198 +#define TSFRCR 0x019C +#define TLFRCR 0x01A0 +#define RFCR 0x01A4 +#define MAFCR 0x01A8 +#define IPGR 0x01B4 +#if defined(CONFIG_CPU_SUBTYPE_SH7710) +#define APR 0x01B8 +#define MPR 0x01BC +#define TPAUSER 0x1C4 +#define BCFR 0x1CC +#endif /* CONFIG_CPU_SH7710 */ + +#define ARSTR 0x0800 + +/* TSU */ +#define TSU_CTRST 0x004 +#define TSU_FWEN0 0x010 +#define TSU_FWEN1 0x014 +#define TSU_FCM 0x018 +#define TSU_BSYSL0 0x020 +#define TSU_BSYSL1 0x024 +#define TSU_PRISL0 0x028 +#define TSU_PRISL1 0x02C +#define TSU_FWSL0 0x030 +#define TSU_FWSL1 0x034 +#define TSU_FWSLC 0x038 +#define TSU_QTAGM0 0x040 +#define TSU_QTAGM1 0x044 +#define TSU_ADQT0 0x048 +#define TSU_ADQT1 0x04C +#define TSU_FWSR 0x050 +#define TSU_FWINMK 0x054 +#define TSU_ADSBSY 0x060 +#define TSU_TEN 0x064 +#define TSU_POST1 0x070 +#define TSU_POST2 0x074 +#define TSU_POST3 0x078 +#define TSU_POST4 0x07C +#define TXNLCR0 0x080 +#define TXALCR0 0x084 +#define RXNLCR0 0x088 +#define RXALCR0 0x08C +#define FWNLCR0 0x090 +#define FWALCR0 0x094 +#define TXNLCR1 0x0A0 +#define TXALCR1 0x0A4 +#define RXNLCR1 0x0A8 +#define RXALCR1 0x0AC +#define FWNLCR1 0x0B0 +#define FWALCR1 0x0B4 + +#define TSU_ADRH0 0x0100 +#define TSU_ADRL0 0x0104 +#define TSU_ADRL31 0x01FC + +/* Register's bits */ + +/* EDMR */ +enum DMAC_M_BIT { + EDMR_DL1 = 0x20, EDMR_DL0 = 0x10, EDMR_SRST = 0x01, +}; + +/* EDTRR */ +enum DMAC_T_BIT { + EDTRR_TRNS = 0x01, +}; + +/* EDRRR*/ +enum EDRRR_R_BIT { + EDRRR_R = 0x01, +}; + +/* TPAUSER */ +enum TPAUSER_BIT { + TPAUSER_TPAUSE = 0x0000ffff, + TPAUSER_UNLIMITED = 0, +}; + +/* BCFR */ +enum BCFR_BIT { + BCFR_RPAUSE = 0x0000ffff, + BCFR_UNLIMITED = 0, +}; + +/* PIR */ +enum PIR_BIT { + PIR_MDI = 0x08, PIR_MDO = 0x04, PIR_MMD = 0x02, PIR_MDC = 0x01, +}; + +/* PSR */ +enum PHY_STATUS_BIT { PHY_ST_LINK = 0x01, }; + +/* EESR */ +enum EESR_BIT { + EESR_TWB = 0x40000000, EESR_TABT = 0x04000000, + EESR_RABT = 0x02000000, EESR_RFRMER = 0x01000000, + EESR_ADE = 0x00800000, EESR_ECI = 0x00400000, + EESR_FTC = 0x00200000, EESR_TDE = 0x00100000, + EESR_TFE = 0x00080000, EESR_FRC = 0x00040000, + EESR_RDE = 0x00020000, EESR_RFE = 0x00010000, + EESR_TINT4 = 0x00000800, EESR_TINT3 = 0x00000400, + EESR_TINT2 = 0x00000200, EESR_TINT1 = 0x00000100, + EESR_RINT8 = 0x00000080, EESR_RINT5 = 0x00000010, + EESR_RINT4 = 0x00000008, EESR_RINT3 = 0x00000004, + EESR_RINT2 = 0x00000002, EESR_RINT1 = 0x00000001, +}; + +#define EESR_ERR_CHECK (EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE \ + | EESR_RFRMER | EESR_ADE | EESR_TFE | EESR_TDE | EESR_ECI) + +/* EESIPR */ +enum DMAC_IM_BIT { + DMAC_M_TWB = 0x40000000, DMAC_M_TABT = 0x04000000, + DMAC_M_RABT = 0x02000000, + DMAC_M_RFRMER = 0x01000000, DMAC_M_ADF = 0x00800000, + DMAC_M_ECI = 0x00400000, DMAC_M_FTC = 0x00200000, + DMAC_M_TDE = 0x00100000, DMAC_M_TFE = 0x00080000, + DMAC_M_FRC = 0x00040000, DMAC_M_RDE = 0x00020000, + DMAC_M_RFE = 0x00010000, DMAC_M_TINT4 = 0x00000800, + DMAC_M_TINT3 = 0x00000400, DMAC_M_TINT2 = 0x00000200, + DMAC_M_TINT1 = 0x00000100, DMAC_M_RINT8 = 0x00000080, + DMAC_M_RINT5 = 0x00000010, DMAC_M_RINT4 = 0x00000008, + DMAC_M_RINT3 = 0x00000004, DMAC_M_RINT2 = 0x00000002, + DMAC_M_RINT1 = 0x00000001, +}; + +/* Receive descriptor bit */ +enum RD_STS_BIT { + RD_RACT = 0x80000000, RC_RDEL = 0x40000000, + RC_RFP1 = 0x20000000, RC_RFP0 = 0x10000000, + RD_RFE = 0x08000000, RD_RFS10 = 0x00000200, + RD_RFS9 = 0x00000100, RD_RFS8 = 0x00000080, + RD_RFS7 = 0x00000040, RD_RFS6 = 0x00000020, + RD_RFS5 = 0x00000010, RD_RFS4 = 0x00000008, + RD_RFS3 = 0x00000004, RD_RFS2 = 0x00000002, + RD_RFS1 = 0x00000001, +}; +#define RDF1ST RC_RFP1 +#define RDFEND RC_RFP0 +#define RD_RFP (RC_RFP1|RC_RFP0) + +/* FCFTR */ +enum FCFTR_BIT { + FCFTR_RFF2 = 0x00040000, FCFTR_RFF1 = 0x00020000, + FCFTR_RFF0 = 0x00010000, FCFTR_RFD2 = 0x00000004, + FCFTR_RFD1 = 0x00000002, FCFTR_RFD0 = 0x00000001, +}; +#define FIFO_F_D_RFF (FCFTR_RFF2|FCFTR_RFF1|FCFTR_RFF0) +#define FIFO_F_D_RFD (FCFTR_RFD2|FCFTR_RFD1|FCFTR_RFD0) + +/* Transfer descriptor bit */ +enum TD_STS_BIT { + TD_TACT = 0x80000000, TD_TDLE = 0x40000000, TD_TFP1 = 0x20000000, + TD_TFP0 = 0x10000000, +}; +#define TDF1ST TD_TFP1 +#define TDFEND TD_TFP0 +#define TD_TFP (TD_TFP1|TD_TFP0) + +/* RMCR */ +enum RECV_RST_BIT { RMCR_RST = 0x01, }; +/* ECMR */ +enum FELIC_MODE_BIT { + ECMR_ZPF = 0x00080000, ECMR_PFR = 0x00040000, ECMR_RXF = 0x00020000, + ECMR_TXF = 0x00010000, ECMR_MCT = 0x00002000, ECMR_PRCEF = 0x00001000, + ECMR_PMDE = 0x00000200, ECMR_RE = 0x00000040, ECMR_TE = 0x00000020, + ECMR_ILB = 0x00000008, ECMR_ELB = 0x00000004, ECMR_DM = 0x00000002, + ECMR_PRM = 0x00000001, +}; + +/* ECSR */ +enum ECSR_STATUS_BIT { + ECSR_BRCRX = 0x20, ECSR_PSRTO = 0x10, ECSR_LCHNG = 0x04, + ECSR_MPD = 0x02, ECSR_ICD = 0x01, +}; + +/* ECSIPR */ +enum ECSIPR_STATUS_MASK_BIT { + ECSIPR_BRCRXIP = 0x20, ECSIPR_PSRTOIP = 0x10, ECSIPR_LCHNGIP = 0x04, + ECSIPR_MPDIP = 0x02, ECSIPR_ICDIP = 0x01, +}; + +/* APR */ +enum APR_BIT { + APR_AP = 0x00000001, +}; + +/* MPR */ +enum MPR_BIT { + MPR_MP = 0x00000001, +}; + +/* TRSCER */ +enum DESC_I_BIT { + DESC_I_TINT4 = 0x0800, DESC_I_TINT3 = 0x0400, DESC_I_TINT2 = 0x0200, + DESC_I_TINT1 = 0x0100, DESC_I_RINT8 = 0x0080, DESC_I_RINT5 = 0x0010, + DESC_I_RINT4 = 0x0008, DESC_I_RINT3 = 0x0004, DESC_I_RINT2 = 0x0002, + DESC_I_RINT1 = 0x0001, +}; + +/* RPADIR */ +enum RPADIR_BIT { + RPADIR_PADS1 = 0x20000, RPADIR_PADS0 = 0x10000, + RPADIR_PADR = 0x0003f, +}; + +/* FDR */ +enum FIFO_SIZE_BIT { + FIFO_SIZE_T = 0x00000700, FIFO_SIZE_R = 0x00000007, +}; +enum phy_offsets { + PHY_CTRL = 0, PHY_STAT = 1, PHY_IDT1 = 2, PHY_IDT2 = 3, + PHY_ANA = 4, PHY_ANL = 5, PHY_ANE = 6, + PHY_16 = 16, +}; + +/* PHY_CTRL */ +enum PHY_CTRL_BIT { + PHY_C_RESET = 0x8000, PHY_C_LOOPBK = 0x4000, PHY_C_SPEEDSL = 0x2000, + PHY_C_ANEGEN = 0x1000, PHY_C_PWRDN = 0x0800, PHY_C_ISO = 0x0400, + PHY_C_RANEG = 0x0200, PHY_C_DUPLEX = 0x0100, PHY_C_COLT = 0x0080, +}; +#define DM9161_PHY_C_ANEGEN 0 /* auto nego special */ + +/* PHY_STAT */ +enum PHY_STAT_BIT { + PHY_S_100T4 = 0x8000, PHY_S_100X_F = 0x4000, PHY_S_100X_H = 0x2000, + PHY_S_10T_F = 0x1000, PHY_S_10T_H = 0x0800, PHY_S_ANEGC = 0x0020, + PHY_S_RFAULT = 0x0010, PHY_S_ANEGA = 0x0008, PHY_S_LINK = 0x0004, + PHY_S_JAB = 0x0002, PHY_S_EXTD = 0x0001, +}; + +/* PHY_ANA */ +enum PHY_ANA_BIT { + PHY_A_NP = 0x8000, PHY_A_ACK = 0x4000, PHY_A_RF = 0x2000, + PHY_A_FCS = 0x0400, PHY_A_T4 = 0x0200, PHY_A_FDX = 0x0100, + PHY_A_HDX = 0x0080, PHY_A_10FDX = 0x0040, PHY_A_10HDX = 0x0020, + PHY_A_SEL = 0x001f, +}; +/* PHY_ANL */ +enum PHY_ANL_BIT { + PHY_L_NP = 0x8000, PHY_L_ACK = 0x4000, PHY_L_RF = 0x2000, + PHY_L_FCS = 0x0400, PHY_L_T4 = 0x0200, PHY_L_FDX = 0x0100, + PHY_L_HDX = 0x0080, PHY_L_10FDX = 0x0040, PHY_L_10HDX = 0x0020, + PHY_L_SEL = 0x001f, +}; + +/* PHY_ANE */ +enum PHY_ANE_BIT { + PHY_E_PDF = 0x0010, PHY_E_LPNPA = 0x0008, PHY_E_NPA = 0x0004, + PHY_E_PRX = 0x0002, PHY_E_LPANEGA = 0x0001, +}; + +/* DM9161 */ +enum PHY_16_BIT { + PHY_16_BP4B45 = 0x8000, PHY_16_BPSCR = 0x4000, PHY_16_BPALIGN = 0x2000, + PHY_16_BP_ADPOK = 0x1000, PHY_16_Repeatmode = 0x0800, + PHY_16_TXselect = 0x0400, + PHY_16_Rsvd = 0x0200, PHY_16_RMIIEnable = 0x0100, + PHY_16_Force100LNK = 0x0080, + PHY_16_APDLED_CTL = 0x0040, PHY_16_COLLED_CTL = 0x0020, + PHY_16_RPDCTR_EN = 0x0010, + PHY_16_ResetStMch = 0x0008, PHY_16_PreamSupr = 0x0004, + PHY_16_Sleepmode = 0x0002, + PHY_16_RemoteLoopOut = 0x0001, +}; + +#define POST_RX 0x08 +#define POST_FW 0x04 +#define POST0_RX (POST_RX) +#define POST0_FW (POST_FW) +#define POST1_RX (POST_RX >> 2) +#define POST1_FW (POST_FW >> 2) +#define POST_ALL (POST0_RX | POST0_FW | POST1_RX | POST1_FW) + +/* ARSTR */ +enum ARSTR_BIT { ARSTR_ARSTR = 0x00000001, }; + +/* TSU_FWEN0 */ +enum TSU_FWEN0_BIT { + TSU_FWEN0_0 = 0x00000001, +}; + +/* TSU_ADSBSY */ +enum TSU_ADSBSY_BIT { + TSU_ADSBSY_0 = 0x00000001, +}; + +/* TSU_TEN */ +enum TSU_TEN_BIT { + TSU_TEN_0 = 0x80000000, +}; + +/* TSU_FWSL0 */ +enum TSU_FWSL0_BIT { + TSU_FWSL0_FW50 = 0x1000, TSU_FWSL0_FW40 = 0x0800, + TSU_FWSL0_FW30 = 0x0400, TSU_FWSL0_FW20 = 0x0200, + TSU_FWSL0_FW10 = 0x0100, TSU_FWSL0_RMSA0 = 0x0010, +}; + +/* TSU_FWSLC */ +enum TSU_FWSLC_BIT { + TSU_FWSLC_POSTENU = 0x2000, TSU_FWSLC_POSTENL = 0x1000, + TSU_FWSLC_CAMSEL03 = 0x0080, TSU_FWSLC_CAMSEL02 = 0x0040, + TSU_FWSLC_CAMSEL01 = 0x0020, TSU_FWSLC_CAMSEL00 = 0x0010, + TSU_FWSLC_CAMSEL13 = 0x0008, TSU_FWSLC_CAMSEL12 = 0x0004, + TSU_FWSLC_CAMSEL11 = 0x0002, TSU_FWSLC_CAMSEL10 = 0x0001, +}; + +/* + * The sh ether Tx buffer descriptors. + * This structure should be 20 bytes. + */ +struct sh_eth_txdesc { + u32 status; /* TD0 */ +#if defined(CONFIG_CPU_LITTLE_ENDIAN) + u16 pad0; /* TD1 */ + u16 buffer_length; /* TD1 */ +#else + u16 buffer_length; /* TD1 */ + u16 pad0; /* TD1 */ +#endif + u32 addr; /* TD2 */ + u32 pad1; /* padding data */ +}; + +/* + * The sh ether Rx buffer descriptors. + * This structure should be 20 bytes. + */ +struct sh_eth_rxdesc { + u32 status; /* RD0 */ +#if defined(CONFIG_CPU_LITTLE_ENDIAN) + u16 frame_length; /* RD1 */ + u16 buffer_length; /* RD1 */ +#else + u16 buffer_length; /* RD1 */ + u16 frame_length; /* RD1 */ +#endif + u32 addr; /* RD2 */ + u32 pad0; /* padding data */ +}; + +struct sh_eth_private { + dma_addr_t rx_desc_dma; + dma_addr_t tx_desc_dma; + struct sh_eth_rxdesc *rx_ring; + struct sh_eth_txdesc *tx_ring; + struct sk_buff **rx_skbuff; + struct sk_buff **tx_skbuff; + struct net_device_stats stats; + struct timer_list timer; + spinlock_t lock; + u32 cur_rx, dirty_rx; /* Producer/consumer ring indices */ + u32 cur_tx, dirty_tx; + u32 rx_buf_sz; /* Based on MTU+slack. */ + /* MII transceiver section. */ + u32 phy_id; /* PHY ID */ + struct mii_bus *mii_bus; /* MDIO bus control */ + struct phy_device *phydev; /* PHY device control */ + enum phy_state link; + int msg_enable; + int speed; + int duplex; + u32 rx_int_var, tx_int_var; /* interrupt control variables */ + char post_rx; /* POST receive */ + char post_fw; /* POST forward */ + struct net_device_stats tsu_stats; /* TSU forward status */ +}; + +static void swaps(char *src, int len) +{ +#ifdef __LITTLE_ENDIAN__ + u32 *p = (u32 *)src; + u32 *maxp; + maxp = p + ((len + sizeof(u32) - 1) / sizeof(u32)); + + for (; p < maxp; p++) + *p = swab32(*p); +#endif +} diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index c83406f4f2a..7f1cfc48e1b 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -4536,7 +4536,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 4e280020518..c5871624f97 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -106,56 +106,6 @@ MODULE_ALIAS("platform:smc911x"); */ #define POWER_DOWN 1 - -/* store this information for the driver.. */ -struct smc911x_local { - /* - * If I have to wait until the DMA is finished and ready to reload a - * packet, I will store the skbuff here. Then, the DMA will send it - * out and free it. - */ - struct sk_buff *pending_tx_skb; - - /* version/revision of the SMC911x chip */ - u16 version; - u16 revision; - - /* FIFO sizes */ - int tx_fifo_kb; - int tx_fifo_size; - int rx_fifo_size; - int afc_cfg; - - /* Contains the current active receive/phy mode */ - int ctl_rfduplx; - int ctl_rspeed; - - u32 msg_enable; - u32 phy_type; - struct mii_if_info mii; - - /* work queue */ - struct work_struct phy_configure; - int work_pending; - - int tx_throttle; - spinlock_t lock; - - struct net_device *netdev; - -#ifdef SMC_USE_DMA - /* DMA needs the physical address of the chip */ - u_long physaddr; - int rxdma; - int txdma; - int rxdma_active; - int txdma_active; - struct sk_buff *current_rx_skb; - struct sk_buff *current_tx_skb; - struct device *dev; -#endif -}; - #if SMC_DEBUG > 0 #define DBG(n, args...) \ do { \ @@ -203,24 +153,24 @@ static void PRINT_PKT(u_char *buf, int length) /* this enables an interrupt in the interrupt mask register */ -#define SMC_ENABLE_INT(x) do { \ +#define SMC_ENABLE_INT(lp, x) do { \ unsigned int __mask; \ unsigned long __flags; \ spin_lock_irqsave(&lp->lock, __flags); \ - __mask = SMC_GET_INT_EN(); \ + __mask = SMC_GET_INT_EN((lp)); \ __mask |= (x); \ - SMC_SET_INT_EN(__mask); \ + SMC_SET_INT_EN((lp), __mask); \ spin_unlock_irqrestore(&lp->lock, __flags); \ } while (0) /* this disables an interrupt from the interrupt mask register */ -#define SMC_DISABLE_INT(x) do { \ +#define SMC_DISABLE_INT(lp, x) do { \ unsigned int __mask; \ unsigned long __flags; \ spin_lock_irqsave(&lp->lock, __flags); \ - __mask = SMC_GET_INT_EN(); \ + __mask = SMC_GET_INT_EN((lp)); \ __mask &= ~(x); \ - SMC_SET_INT_EN(__mask); \ + SMC_SET_INT_EN((lp), __mask); \ spin_unlock_irqrestore(&lp->lock, __flags); \ } while (0) @@ -229,7 +179,6 @@ static void PRINT_PKT(u_char *buf, int length) */ static void smc911x_reset(struct net_device *dev) { - unsigned long ioaddr = dev->base_addr; struct smc911x_local *lp = netdev_priv(dev); unsigned int reg, timeout=0, resets=1; unsigned long flags; @@ -237,13 +186,13 @@ static void smc911x_reset(struct net_device *dev) DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); /* Take out of PM setting first */ - if ((SMC_GET_PMT_CTRL() & PMT_CTRL_READY_) == 0) { + if ((SMC_GET_PMT_CTRL(lp) & PMT_CTRL_READY_) == 0) { /* Write to the bytetest will take out of powerdown */ - SMC_SET_BYTE_TEST(0); + SMC_SET_BYTE_TEST(lp, 0); timeout=10; do { udelay(10); - reg = SMC_GET_PMT_CTRL() & PMT_CTRL_READY_; + reg = SMC_GET_PMT_CTRL(lp) & PMT_CTRL_READY_; } while (--timeout && !reg); if (timeout == 0) { PRINTK("%s: smc911x_reset timeout waiting for PM restore\n", dev->name); @@ -253,15 +202,15 @@ static void smc911x_reset(struct net_device *dev) /* Disable all interrupts */ spin_lock_irqsave(&lp->lock, flags); - SMC_SET_INT_EN(0); + SMC_SET_INT_EN(lp, 0); spin_unlock_irqrestore(&lp->lock, flags); while (resets--) { - SMC_SET_HW_CFG(HW_CFG_SRST_); + SMC_SET_HW_CFG(lp, HW_CFG_SRST_); timeout=10; do { udelay(10); - reg = SMC_GET_HW_CFG(); + reg = SMC_GET_HW_CFG(lp); /* If chip indicates reset timeout then try again */ if (reg & HW_CFG_SRST_TO_) { PRINTK("%s: chip reset timeout, retrying...\n", dev->name); @@ -277,7 +226,7 @@ static void smc911x_reset(struct net_device *dev) /* make sure EEPROM has finished loading before setting GPIO_CFG */ timeout=1000; - while ( timeout-- && (SMC_GET_E2P_CMD() & E2P_CMD_EPC_BUSY_)) { + while ( timeout-- && (SMC_GET_E2P_CMD(lp) & E2P_CMD_EPC_BUSY_)) { udelay(10); } if (timeout == 0){ @@ -286,24 +235,24 @@ static void smc911x_reset(struct net_device *dev) } /* Initialize interrupts */ - SMC_SET_INT_EN(0); - SMC_ACK_INT(-1); + SMC_SET_INT_EN(lp, 0); + SMC_ACK_INT(lp, -1); /* Reset the FIFO level and flow control settings */ - SMC_SET_HW_CFG((lp->tx_fifo_kb & 0xF) << 16); + SMC_SET_HW_CFG(lp, (lp->tx_fifo_kb & 0xF) << 16); //TODO: Figure out what appropriate pause time is - SMC_SET_FLOW(FLOW_FCPT_ | FLOW_FCEN_); - SMC_SET_AFC_CFG(lp->afc_cfg); + SMC_SET_FLOW(lp, FLOW_FCPT_ | FLOW_FCEN_); + SMC_SET_AFC_CFG(lp, lp->afc_cfg); /* Set to LED outputs */ - SMC_SET_GPIO_CFG(0x70070000); + SMC_SET_GPIO_CFG(lp, 0x70070000); /* * Deassert IRQ for 1*10us for edge type interrupts * and drive IRQ pin push-pull */ - SMC_SET_IRQ_CFG( (1 << 24) | INT_CFG_IRQ_EN_ | INT_CFG_IRQ_TYPE_ ); + SMC_SET_IRQ_CFG(lp, (1 << 24) | INT_CFG_IRQ_EN_ | INT_CFG_IRQ_TYPE_); /* clear anything saved */ if (lp->pending_tx_skb != NULL) { @@ -319,46 +268,45 @@ static void smc911x_reset(struct net_device *dev) */ static void smc911x_enable(struct net_device *dev) { - unsigned long ioaddr = dev->base_addr; struct smc911x_local *lp = netdev_priv(dev); unsigned mask, cfg, cr; unsigned long flags; DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); - SMC_SET_MAC_ADDR(dev->dev_addr); + SMC_SET_MAC_ADDR(lp, dev->dev_addr); /* Enable TX */ - cfg = SMC_GET_HW_CFG(); + cfg = SMC_GET_HW_CFG(lp); cfg &= HW_CFG_TX_FIF_SZ_ | 0xFFF; cfg |= HW_CFG_SF_; - SMC_SET_HW_CFG(cfg); - SMC_SET_FIFO_TDA(0xFF); + SMC_SET_HW_CFG(lp, cfg); + SMC_SET_FIFO_TDA(lp, 0xFF); /* Update TX stats on every 64 packets received or every 1 sec */ - SMC_SET_FIFO_TSL(64); - SMC_SET_GPT_CFG(GPT_CFG_TIMER_EN_ | 10000); + SMC_SET_FIFO_TSL(lp, 64); + SMC_SET_GPT_CFG(lp, GPT_CFG_TIMER_EN_ | 10000); spin_lock_irqsave(&lp->lock, flags); - SMC_GET_MAC_CR(cr); + SMC_GET_MAC_CR(lp, cr); cr |= MAC_CR_TXEN_ | MAC_CR_HBDIS_; - SMC_SET_MAC_CR(cr); - SMC_SET_TX_CFG(TX_CFG_TX_ON_); + SMC_SET_MAC_CR(lp, cr); + SMC_SET_TX_CFG(lp, TX_CFG_TX_ON_); spin_unlock_irqrestore(&lp->lock, flags); /* Add 2 byte padding to start of packets */ - SMC_SET_RX_CFG((2<<8) & RX_CFG_RXDOFF_); + SMC_SET_RX_CFG(lp, (2<<8) & RX_CFG_RXDOFF_); /* Turn on receiver and enable RX */ if (cr & MAC_CR_RXEN_) DBG(SMC_DEBUG_RX, "%s: Receiver already enabled\n", dev->name); spin_lock_irqsave(&lp->lock, flags); - SMC_SET_MAC_CR( cr | MAC_CR_RXEN_ ); + SMC_SET_MAC_CR(lp, cr | MAC_CR_RXEN_); spin_unlock_irqrestore(&lp->lock, flags); /* Interrupt on every received packet */ - SMC_SET_FIFO_RSA(0x01); - SMC_SET_FIFO_RSL(0x00); + SMC_SET_FIFO_RSA(lp, 0x01); + SMC_SET_FIFO_RSL(lp, 0x00); /* now, enable interrupts */ mask = INT_EN_TDFA_EN_ | INT_EN_TSFL_EN_ | INT_EN_RSFL_EN_ | @@ -369,7 +317,7 @@ static void smc911x_enable(struct net_device *dev) else { mask|=INT_EN_RDFO_EN_; } - SMC_ENABLE_INT(mask); + SMC_ENABLE_INT(lp, mask); } /* @@ -377,7 +325,6 @@ static void smc911x_enable(struct net_device *dev) */ static void smc911x_shutdown(struct net_device *dev) { - unsigned long ioaddr = dev->base_addr; struct smc911x_local *lp = netdev_priv(dev); unsigned cr; unsigned long flags; @@ -385,35 +332,35 @@ static void smc911x_shutdown(struct net_device *dev) DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", CARDNAME, __FUNCTION__); /* Disable IRQ's */ - SMC_SET_INT_EN(0); + SMC_SET_INT_EN(lp, 0); /* Turn of Rx and TX */ spin_lock_irqsave(&lp->lock, flags); - SMC_GET_MAC_CR(cr); + SMC_GET_MAC_CR(lp, cr); cr &= ~(MAC_CR_TXEN_ | MAC_CR_RXEN_ | MAC_CR_HBDIS_); - SMC_SET_MAC_CR(cr); - SMC_SET_TX_CFG(TX_CFG_STOP_TX_); + SMC_SET_MAC_CR(lp, cr); + SMC_SET_TX_CFG(lp, TX_CFG_STOP_TX_); spin_unlock_irqrestore(&lp->lock, flags); } static inline void smc911x_drop_pkt(struct net_device *dev) { - unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); unsigned int fifo_count, timeout, reg; DBG(SMC_DEBUG_FUNC | SMC_DEBUG_RX, "%s: --> %s\n", CARDNAME, __FUNCTION__); - fifo_count = SMC_GET_RX_FIFO_INF() & 0xFFFF; + fifo_count = SMC_GET_RX_FIFO_INF(lp) & 0xFFFF; if (fifo_count <= 4) { /* Manually dump the packet data */ while (fifo_count--) - SMC_GET_RX_FIFO(); + SMC_GET_RX_FIFO(lp); } else { /* Fast forward through the bad packet */ - SMC_SET_RX_DP_CTRL(RX_DP_CTRL_FFWD_BUSY_); + SMC_SET_RX_DP_CTRL(lp, RX_DP_CTRL_FFWD_BUSY_); timeout=50; do { udelay(10); - reg = SMC_GET_RX_DP_CTRL() & RX_DP_CTRL_FFWD_BUSY_; + reg = SMC_GET_RX_DP_CTRL(lp) & RX_DP_CTRL_FFWD_BUSY_; } while (--timeout && reg); if (timeout == 0) { PRINTK("%s: timeout waiting for RX fast forward\n", dev->name); @@ -429,14 +376,14 @@ static inline void smc911x_drop_pkt(struct net_device *dev) */ static inline void smc911x_rcv(struct net_device *dev) { - unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); unsigned int pkt_len, status; struct sk_buff *skb; unsigned char *data; DBG(SMC_DEBUG_FUNC | SMC_DEBUG_RX, "%s: --> %s\n", dev->name, __FUNCTION__); - status = SMC_GET_RX_STS_FIFO(); + status = SMC_GET_RX_STS_FIFO(lp); DBG(SMC_DEBUG_RX, "%s: Rx pkt len %d status 0x%08x \n", dev->name, (status & 0x3fff0000) >> 16, status & 0xc000ffff); pkt_len = (status & RX_STS_PKT_LEN_) >> 16; @@ -473,24 +420,23 @@ static inline void smc911x_rcv(struct net_device *dev) skb_put(skb,pkt_len-4); #ifdef SMC_USE_DMA { - struct smc911x_local *lp = netdev_priv(dev); unsigned int fifo; /* Lower the FIFO threshold if possible */ - fifo = SMC_GET_FIFO_INT(); + fifo = SMC_GET_FIFO_INT(lp); if (fifo & 0xFF) fifo--; DBG(SMC_DEBUG_RX, "%s: Setting RX stat FIFO threshold to %d\n", dev->name, fifo & 0xff); - SMC_SET_FIFO_INT(fifo); + SMC_SET_FIFO_INT(lp, fifo); /* Setup RX DMA */ - SMC_SET_RX_CFG(RX_CFG_RX_END_ALGN16_ | ((2<<8) & RX_CFG_RXDOFF_)); + SMC_SET_RX_CFG(lp, RX_CFG_RX_END_ALGN16_ | ((2<<8) & RX_CFG_RXDOFF_)); lp->rxdma_active = 1; lp->current_rx_skb = skb; - SMC_PULL_DATA(data, (pkt_len+2+15) & ~15); + SMC_PULL_DATA(lp, data, (pkt_len+2+15) & ~15); /* Packet processing deferred to DMA RX interrupt */ } #else - SMC_SET_RX_CFG(RX_CFG_RX_END_ALGN4_ | ((2<<8) & RX_CFG_RXDOFF_)); - SMC_PULL_DATA(data, pkt_len+2+3); + SMC_SET_RX_CFG(lp, RX_CFG_RX_END_ALGN4_ | ((2<<8) & RX_CFG_RXDOFF_)); + SMC_PULL_DATA(lp, data, pkt_len+2+3); DBG(SMC_DEBUG_PKTS, "%s: Received packet\n", dev->name); PRINT_PKT(data, ((pkt_len - 4) <= 64) ? pkt_len - 4 : 64); @@ -509,7 +455,6 @@ static inline void smc911x_rcv(struct net_device *dev) static void smc911x_hardware_send_pkt(struct net_device *dev) { struct smc911x_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; struct sk_buff *skb; unsigned int cmdA, cmdB, len; unsigned char *buf; @@ -542,8 +487,8 @@ static void smc911x_hardware_send_pkt(struct net_device *dev) DBG(SMC_DEBUG_TX, "%s: TX PKT LENGTH 0x%04x (%d) BUF 0x%p CMDA 0x%08x CMDB 0x%08x\n", dev->name, len, len, buf, cmdA, cmdB); - SMC_SET_TX_FIFO(cmdA); - SMC_SET_TX_FIFO(cmdB); + SMC_SET_TX_FIFO(lp, cmdA); + SMC_SET_TX_FIFO(lp, cmdB); DBG(SMC_DEBUG_PKTS, "%s: Transmitted packet\n", dev->name); PRINT_PKT(buf, len <= 64 ? len : 64); @@ -551,10 +496,10 @@ static void smc911x_hardware_send_pkt(struct net_device *dev) /* Send pkt via PIO or DMA */ #ifdef SMC_USE_DMA lp->current_tx_skb = skb; - SMC_PUSH_DATA(buf, len); + SMC_PUSH_DATA(lp, buf, len); /* DMA complete IRQ will free buffer and set jiffies */ #else - SMC_PUSH_DATA(buf, len); + SMC_PUSH_DATA(lp, buf, len); dev->trans_start = jiffies; dev_kfree_skb(skb); #endif @@ -563,7 +508,7 @@ static void smc911x_hardware_send_pkt(struct net_device *dev) netif_wake_queue(dev); } spin_unlock_irqrestore(&lp->lock, flags); - SMC_ENABLE_INT(INT_EN_TDFA_EN_ | INT_EN_TSFL_EN_); + SMC_ENABLE_INT(lp, INT_EN_TDFA_EN_ | INT_EN_TSFL_EN_); } /* @@ -575,7 +520,6 @@ static void smc911x_hardware_send_pkt(struct net_device *dev) static int smc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct smc911x_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; unsigned int free; unsigned long flags; @@ -584,7 +528,7 @@ static int smc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) BUG_ON(lp->pending_tx_skb != NULL); - free = SMC_GET_TX_FIFO_INF() & TX_FIFO_INF_TDFREE_; + free = SMC_GET_TX_FIFO_INF(lp) & TX_FIFO_INF_TDFREE_; DBG(SMC_DEBUG_TX, "%s: TX free space %d\n", dev->name, free); /* Turn off the flow when running out of space in FIFO */ @@ -593,7 +537,7 @@ static int smc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) dev->name, free); spin_lock_irqsave(&lp->lock, flags); /* Reenable when at least 1 packet of size MTU present */ - SMC_SET_FIFO_TDA((SMC911X_TX_FIFO_LOW_THRESHOLD)/64); + SMC_SET_FIFO_TDA(lp, (SMC911X_TX_FIFO_LOW_THRESHOLD)/64); lp->tx_throttle = 1; netif_stop_queue(dev); spin_unlock_irqrestore(&lp->lock, flags); @@ -648,7 +592,6 @@ static int smc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) */ static void smc911x_tx(struct net_device *dev) { - unsigned long ioaddr = dev->base_addr; struct smc911x_local *lp = netdev_priv(dev); unsigned int tx_status; @@ -656,11 +599,11 @@ static void smc911x_tx(struct net_device *dev) dev->name, __FUNCTION__); /* Collect the TX status */ - while (((SMC_GET_TX_FIFO_INF() & TX_FIFO_INF_TSUSED_) >> 16) != 0) { + while (((SMC_GET_TX_FIFO_INF(lp) & TX_FIFO_INF_TSUSED_) >> 16) != 0) { DBG(SMC_DEBUG_TX, "%s: Tx stat FIFO used 0x%04x\n", dev->name, - (SMC_GET_TX_FIFO_INF() & TX_FIFO_INF_TSUSED_) >> 16); - tx_status = SMC_GET_TX_STS_FIFO(); + (SMC_GET_TX_FIFO_INF(lp) & TX_FIFO_INF_TSUSED_) >> 16); + tx_status = SMC_GET_TX_STS_FIFO(lp); dev->stats.tx_packets++; dev->stats.tx_bytes+=tx_status>>16; DBG(SMC_DEBUG_TX, "%s: Tx FIFO tag 0x%04x status 0x%04x\n", @@ -698,10 +641,10 @@ static void smc911x_tx(struct net_device *dev) static int smc911x_phy_read(struct net_device *dev, int phyaddr, int phyreg) { - unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); unsigned int phydata; - SMC_GET_MII(phyreg, phyaddr, phydata); + SMC_GET_MII(lp, phyreg, phyaddr, phydata); DBG(SMC_DEBUG_MISC, "%s: phyaddr=0x%x, phyreg=0x%02x, phydata=0x%04x\n", __FUNCTION__, phyaddr, phyreg, phydata); @@ -715,12 +658,12 @@ static int smc911x_phy_read(struct net_device *dev, int phyaddr, int phyreg) static void smc911x_phy_write(struct net_device *dev, int phyaddr, int phyreg, int phydata) { - unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); DBG(SMC_DEBUG_MISC, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n", __FUNCTION__, phyaddr, phyreg, phydata); - SMC_SET_MII(phyreg, phyaddr, phydata); + SMC_SET_MII(lp, phyreg, phyaddr, phydata); } /* @@ -729,7 +672,6 @@ static void smc911x_phy_write(struct net_device *dev, int phyaddr, int phyreg, */ static void smc911x_phy_detect(struct net_device *dev) { - unsigned long ioaddr = dev->base_addr; struct smc911x_local *lp = netdev_priv(dev); int phyaddr; unsigned int cfg, id1, id2; @@ -745,30 +687,30 @@ static void smc911x_phy_detect(struct net_device *dev) switch(lp->version) { case 0x115: case 0x117: - cfg = SMC_GET_HW_CFG(); + cfg = SMC_GET_HW_CFG(lp); if (cfg & HW_CFG_EXT_PHY_DET_) { cfg &= ~HW_CFG_PHY_CLK_SEL_; cfg |= HW_CFG_PHY_CLK_SEL_CLK_DIS_; - SMC_SET_HW_CFG(cfg); + SMC_SET_HW_CFG(lp, cfg); udelay(10); /* Wait for clocks to stop */ cfg |= HW_CFG_EXT_PHY_EN_; - SMC_SET_HW_CFG(cfg); + SMC_SET_HW_CFG(lp, cfg); udelay(10); /* Wait for clocks to stop */ cfg &= ~HW_CFG_PHY_CLK_SEL_; cfg |= HW_CFG_PHY_CLK_SEL_EXT_PHY_; - SMC_SET_HW_CFG(cfg); + SMC_SET_HW_CFG(lp, cfg); udelay(10); /* Wait for clocks to stop */ cfg |= HW_CFG_SMI_SEL_; - SMC_SET_HW_CFG(cfg); + SMC_SET_HW_CFG(lp, cfg); for (phyaddr = 1; phyaddr < 32; ++phyaddr) { /* Read the PHY identifiers */ - SMC_GET_PHY_ID1(phyaddr & 31, id1); - SMC_GET_PHY_ID2(phyaddr & 31, id2); + SMC_GET_PHY_ID1(lp, phyaddr & 31, id1); + SMC_GET_PHY_ID2(lp, phyaddr & 31, id2); /* Make sure it is a valid identifier */ if (id1 != 0x0000 && id1 != 0xffff && @@ -783,8 +725,8 @@ static void smc911x_phy_detect(struct net_device *dev) } default: /* Internal media only */ - SMC_GET_PHY_ID1(1, id1); - SMC_GET_PHY_ID2(1, id2); + SMC_GET_PHY_ID1(lp, 1, id1); + SMC_GET_PHY_ID2(lp, 1, id2); /* Save the PHY's address */ lp->mii.phy_id = 1; lp->phy_type = id1 << 16 | id2; @@ -801,16 +743,15 @@ static void smc911x_phy_detect(struct net_device *dev) static int smc911x_phy_fixed(struct net_device *dev) { struct smc911x_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; int phyaddr = lp->mii.phy_id; int bmcr; DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); /* Enter Link Disable state */ - SMC_GET_PHY_BMCR(phyaddr, bmcr); + SMC_GET_PHY_BMCR(lp, phyaddr, bmcr); bmcr |= BMCR_PDOWN; - SMC_SET_PHY_BMCR(phyaddr, bmcr); + SMC_SET_PHY_BMCR(lp, phyaddr, bmcr); /* * Set our fixed capabilities @@ -824,11 +765,11 @@ static int smc911x_phy_fixed(struct net_device *dev) bmcr |= BMCR_SPEED100; /* Write our capabilities to the phy control register */ - SMC_SET_PHY_BMCR(phyaddr, bmcr); + SMC_SET_PHY_BMCR(lp, phyaddr, bmcr); /* Re-Configure the Receive/Phy Control register */ bmcr &= ~BMCR_PDOWN; - SMC_SET_PHY_BMCR(phyaddr, bmcr); + SMC_SET_PHY_BMCR(lp, phyaddr, bmcr); return 1; } @@ -848,7 +789,6 @@ static int smc911x_phy_fixed(struct net_device *dev) static int smc911x_phy_reset(struct net_device *dev, int phy) { struct smc911x_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; int timeout; unsigned long flags; unsigned int reg; @@ -856,15 +796,15 @@ static int smc911x_phy_reset(struct net_device *dev, int phy) DBG(SMC_DEBUG_FUNC, "%s: --> %s()\n", dev->name, __FUNCTION__); spin_lock_irqsave(&lp->lock, flags); - reg = SMC_GET_PMT_CTRL(); + reg = SMC_GET_PMT_CTRL(lp); reg &= ~0xfffff030; reg |= PMT_CTRL_PHY_RST_; - SMC_SET_PMT_CTRL(reg); + SMC_SET_PMT_CTRL(lp, reg); spin_unlock_irqrestore(&lp->lock, flags); for (timeout = 2; timeout; timeout--) { msleep(50); spin_lock_irqsave(&lp->lock, flags); - reg = SMC_GET_PMT_CTRL(); + reg = SMC_GET_PMT_CTRL(lp); spin_unlock_irqrestore(&lp->lock, flags); if (!(reg & PMT_CTRL_PHY_RST_)) { /* extra delay required because the phy may @@ -889,13 +829,13 @@ static int smc911x_phy_reset(struct net_device *dev, int phy) */ static void smc911x_phy_powerdown(struct net_device *dev, int phy) { - unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); unsigned int bmcr; /* Enter Link Disable state */ - SMC_GET_PHY_BMCR(phy, bmcr); + SMC_GET_PHY_BMCR(lp, phy, bmcr); bmcr |= BMCR_PDOWN; - SMC_SET_PHY_BMCR(phy, bmcr); + SMC_SET_PHY_BMCR(lp, phy, bmcr); } /* @@ -909,7 +849,6 @@ static void smc911x_phy_powerdown(struct net_device *dev, int phy) static void smc911x_phy_check_media(struct net_device *dev, int init) { struct smc911x_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; int phyaddr = lp->mii.phy_id; unsigned int bmcr, cr; @@ -917,8 +856,8 @@ static void smc911x_phy_check_media(struct net_device *dev, int init) if (mii_check_media(&lp->mii, netif_msg_link(lp), init)) { /* duplex state has changed */ - SMC_GET_PHY_BMCR(phyaddr, bmcr); - SMC_GET_MAC_CR(cr); + SMC_GET_PHY_BMCR(lp, phyaddr, bmcr); + SMC_GET_MAC_CR(lp, cr); if (lp->mii.full_duplex) { DBG(SMC_DEBUG_MISC, "%s: Configuring for full-duplex mode\n", dev->name); bmcr |= BMCR_FULLDPLX; @@ -928,8 +867,8 @@ static void smc911x_phy_check_media(struct net_device *dev, int init) bmcr &= ~BMCR_FULLDPLX; cr &= ~MAC_CR_RCVOWN_; } - SMC_SET_PHY_BMCR(phyaddr, bmcr); - SMC_SET_MAC_CR(cr); + SMC_SET_PHY_BMCR(lp, phyaddr, bmcr); + SMC_SET_MAC_CR(lp, cr); } } @@ -947,7 +886,6 @@ static void smc911x_phy_configure(struct work_struct *work) struct smc911x_local *lp = container_of(work, struct smc911x_local, phy_configure); struct net_device *dev = lp->netdev; - unsigned long ioaddr = dev->base_addr; int phyaddr = lp->mii.phy_id; int my_phy_caps; /* My PHY capabilities */ int my_ad_caps; /* My Advertised capabilities */ @@ -960,11 +898,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); @@ -972,7 +910,7 @@ static void smc911x_phy_configure(struct work_struct *work) * Enable PHY Interrupts (for register 18) * Interrupts listed here are enabled */ - SMC_SET_PHY_INT_MASK(phyaddr, PHY_INT_MASK_ENERGY_ON_ | + SMC_SET_PHY_INT_MASK(lp, phyaddr, PHY_INT_MASK_ENERGY_ON_ | PHY_INT_MASK_ANEG_COMP_ | PHY_INT_MASK_REMOTE_FAULT_ | PHY_INT_MASK_LINK_DOWN_); @@ -983,7 +921,7 @@ static void smc911x_phy_configure(struct work_struct *work) } /* Copy our capabilities from MII_BMSR to MII_ADVERTISE */ - SMC_GET_PHY_BMSR(phyaddr, my_phy_caps); + SMC_GET_PHY_BMSR(lp, phyaddr, my_phy_caps); if (!(my_phy_caps & BMSR_ANEGCAPABLE)) { printk(KERN_INFO "Auto negotiation NOT supported\n"); smc911x_phy_fixed(dev); @@ -1012,7 +950,7 @@ static void smc911x_phy_configure(struct work_struct *work) my_ad_caps &= ~(ADVERTISE_100FULL|ADVERTISE_10FULL); /* Update our Auto-Neg Advertisement Register */ - SMC_SET_PHY_MII_ADV(phyaddr, my_ad_caps); + SMC_SET_PHY_MII_ADV(lp, phyaddr, my_ad_caps); lp->mii.advertising = my_ad_caps; /* @@ -1021,20 +959,18 @@ static void smc911x_phy_configure(struct work_struct *work) * the link does not come up. */ udelay(10); - SMC_GET_PHY_MII_ADV(phyaddr, status); + SMC_GET_PHY_MII_ADV(lp, phyaddr, status); DBG(SMC_DEBUG_MISC, "%s: phy caps=0x%04x\n", dev->name, my_phy_caps); DBG(SMC_DEBUG_MISC, "%s: phy advertised caps=0x%04x\n", dev->name, my_ad_caps); /* Restart auto-negotiation process in order to advertise my caps */ - SMC_SET_PHY_BMCR(phyaddr, BMCR_ANENABLE | BMCR_ANRESTART); + SMC_SET_PHY_BMCR(lp, phyaddr, BMCR_ANENABLE | BMCR_ANRESTART); smc911x_phy_check_media(dev, 1); smc911x_phy_configure_exit: spin_unlock_irqrestore(&lp->lock, flags); -smc911x_phy_configure_exit_nolock: - lp->work_pending = 0; } /* @@ -1046,7 +982,6 @@ smc911x_phy_configure_exit_nolock: static void smc911x_phy_interrupt(struct net_device *dev) { struct smc911x_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; int phyaddr = lp->mii.phy_id; int status; @@ -1057,11 +992,11 @@ static void smc911x_phy_interrupt(struct net_device *dev) smc911x_phy_check_media(dev, 0); /* read to clear status bits */ - SMC_GET_PHY_INT_SRC(phyaddr,status); + SMC_GET_PHY_INT_SRC(lp, phyaddr,status); DBG(SMC_DEBUG_MISC, "%s: PHY interrupt status 0x%04x\n", dev->name, status & 0xffff); DBG(SMC_DEBUG_MISC, "%s: AFC_CFG 0x%08x\n", - dev->name, SMC_GET_AFC_CFG()); + dev->name, SMC_GET_AFC_CFG(lp)); } /*--- END PHY CONTROL AND CONFIGURATION-------------------------------------*/ @@ -1073,7 +1008,6 @@ static void smc911x_phy_interrupt(struct net_device *dev) static irqreturn_t smc911x_interrupt(int irq, void *dev_id) { struct net_device *dev = dev_id; - unsigned long ioaddr = dev->base_addr; struct smc911x_local *lp = netdev_priv(dev); unsigned int status, mask, timeout; unsigned int rx_overrun=0, cr, pkts; @@ -1084,21 +1018,21 @@ static irqreturn_t smc911x_interrupt(int irq, void *dev_id) spin_lock_irqsave(&lp->lock, flags); /* Spurious interrupt check */ - if ((SMC_GET_IRQ_CFG() & (INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) != + if ((SMC_GET_IRQ_CFG(lp) & (INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) != (INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) { spin_unlock_irqrestore(&lp->lock, flags); return IRQ_NONE; } - mask = SMC_GET_INT_EN(); - SMC_SET_INT_EN(0); + mask = SMC_GET_INT_EN(lp); + SMC_SET_INT_EN(lp, 0); /* set a timeout value, so I don't stay here forever */ timeout = 8; do { - status = SMC_GET_INT(); + status = SMC_GET_INT(lp); DBG(SMC_DEBUG_MISC, "%s: INT 0x%08x MASK 0x%08x OUTSIDE MASK 0x%08x\n", dev->name, status, mask, status & ~mask); @@ -1109,53 +1043,53 @@ static irqreturn_t smc911x_interrupt(int irq, void *dev_id) /* Handle SW interrupt condition */ if (status & INT_STS_SW_INT_) { - SMC_ACK_INT(INT_STS_SW_INT_); + SMC_ACK_INT(lp, INT_STS_SW_INT_); mask &= ~INT_EN_SW_INT_EN_; } /* Handle various error conditions */ if (status & INT_STS_RXE_) { - SMC_ACK_INT(INT_STS_RXE_); + SMC_ACK_INT(lp, INT_STS_RXE_); dev->stats.rx_errors++; } if (status & INT_STS_RXDFH_INT_) { - SMC_ACK_INT(INT_STS_RXDFH_INT_); - dev->stats.rx_dropped+=SMC_GET_RX_DROP(); + SMC_ACK_INT(lp, INT_STS_RXDFH_INT_); + dev->stats.rx_dropped+=SMC_GET_RX_DROP(lp); } /* Undocumented interrupt-what is the right thing to do here? */ if (status & INT_STS_RXDF_INT_) { - SMC_ACK_INT(INT_STS_RXDF_INT_); + SMC_ACK_INT(lp, INT_STS_RXDF_INT_); } /* Rx Data FIFO exceeds set level */ if (status & INT_STS_RDFL_) { if (IS_REV_A(lp->revision)) { rx_overrun=1; - SMC_GET_MAC_CR(cr); + SMC_GET_MAC_CR(lp, cr); cr &= ~MAC_CR_RXEN_; - SMC_SET_MAC_CR(cr); + SMC_SET_MAC_CR(lp, cr); DBG(SMC_DEBUG_RX, "%s: RX overrun\n", dev->name); dev->stats.rx_errors++; dev->stats.rx_fifo_errors++; } - SMC_ACK_INT(INT_STS_RDFL_); + SMC_ACK_INT(lp, INT_STS_RDFL_); } if (status & INT_STS_RDFO_) { if (!IS_REV_A(lp->revision)) { - SMC_GET_MAC_CR(cr); + SMC_GET_MAC_CR(lp, cr); cr &= ~MAC_CR_RXEN_; - SMC_SET_MAC_CR(cr); + SMC_SET_MAC_CR(lp, cr); rx_overrun=1; DBG(SMC_DEBUG_RX, "%s: RX overrun\n", dev->name); dev->stats.rx_errors++; dev->stats.rx_fifo_errors++; } - SMC_ACK_INT(INT_STS_RDFO_); + SMC_ACK_INT(lp, INT_STS_RDFO_); } /* Handle receive condition */ if ((status & INT_STS_RSFL_) || rx_overrun) { unsigned int fifo; DBG(SMC_DEBUG_RX, "%s: RX irq\n", dev->name); - fifo = SMC_GET_RX_FIFO_INF(); + fifo = SMC_GET_RX_FIFO_INF(lp); pkts = (fifo & RX_FIFO_INF_RXSUSED_) >> 16; DBG(SMC_DEBUG_RX, "%s: Rx FIFO pkts %d, bytes %d\n", dev->name, pkts, fifo & 0xFFFF ); @@ -1166,61 +1100,61 @@ static irqreturn_t smc911x_interrupt(int irq, void *dev_id) DBG(SMC_DEBUG_RX | SMC_DEBUG_DMA, "%s: RX DMA active\n", dev->name); /* The DMA is already running so up the IRQ threshold */ - fifo = SMC_GET_FIFO_INT() & ~0xFF; + fifo = SMC_GET_FIFO_INT(lp) & ~0xFF; fifo |= pkts & 0xFF; DBG(SMC_DEBUG_RX, "%s: Setting RX stat FIFO threshold to %d\n", dev->name, fifo & 0xff); - SMC_SET_FIFO_INT(fifo); + SMC_SET_FIFO_INT(lp, fifo); } else #endif smc911x_rcv(dev); } - SMC_ACK_INT(INT_STS_RSFL_); + SMC_ACK_INT(lp, INT_STS_RSFL_); } /* Handle transmit FIFO available */ if (status & INT_STS_TDFA_) { DBG(SMC_DEBUG_TX, "%s: TX data FIFO space available irq\n", dev->name); - SMC_SET_FIFO_TDA(0xFF); + SMC_SET_FIFO_TDA(lp, 0xFF); lp->tx_throttle = 0; #ifdef SMC_USE_DMA if (!lp->txdma_active) #endif netif_wake_queue(dev); - SMC_ACK_INT(INT_STS_TDFA_); + SMC_ACK_INT(lp, INT_STS_TDFA_); } /* Handle transmit done condition */ #if 1 if (status & (INT_STS_TSFL_ | INT_STS_GPT_INT_)) { DBG(SMC_DEBUG_TX | SMC_DEBUG_MISC, "%s: Tx stat FIFO limit (%d) /GPT irq\n", - dev->name, (SMC_GET_FIFO_INT() & 0x00ff0000) >> 16); + dev->name, (SMC_GET_FIFO_INT(lp) & 0x00ff0000) >> 16); smc911x_tx(dev); - SMC_SET_GPT_CFG(GPT_CFG_TIMER_EN_ | 10000); - SMC_ACK_INT(INT_STS_TSFL_); - SMC_ACK_INT(INT_STS_TSFL_ | INT_STS_GPT_INT_); + SMC_SET_GPT_CFG(lp, GPT_CFG_TIMER_EN_ | 10000); + SMC_ACK_INT(lp, INT_STS_TSFL_); + SMC_ACK_INT(lp, INT_STS_TSFL_ | INT_STS_GPT_INT_); } #else if (status & INT_STS_TSFL_) { DBG(SMC_DEBUG_TX, "%s: TX status FIFO limit (%d) irq \n", dev->name, ); smc911x_tx(dev); - SMC_ACK_INT(INT_STS_TSFL_); + SMC_ACK_INT(lp, INT_STS_TSFL_); } if (status & INT_STS_GPT_INT_) { DBG(SMC_DEBUG_RX, "%s: IRQ_CFG 0x%08x FIFO_INT 0x%08x RX_CFG 0x%08x\n", dev->name, - SMC_GET_IRQ_CFG(), - SMC_GET_FIFO_INT(), - SMC_GET_RX_CFG()); + SMC_GET_IRQ_CFG(lp), + SMC_GET_FIFO_INT(lp), + SMC_GET_RX_CFG(lp)); DBG(SMC_DEBUG_RX, "%s: Rx Stat FIFO Used 0x%02x " "Data FIFO Used 0x%04x Stat FIFO 0x%08x\n", dev->name, - (SMC_GET_RX_FIFO_INF() & 0x00ff0000) >> 16, - SMC_GET_RX_FIFO_INF() & 0xffff, - SMC_GET_RX_STS_FIFO_PEEK()); - SMC_SET_GPT_CFG(GPT_CFG_TIMER_EN_ | 10000); - SMC_ACK_INT(INT_STS_GPT_INT_); + (SMC_GET_RX_FIFO_INF(lp) & 0x00ff0000) >> 16, + SMC_GET_RX_FIFO_INF(lp) & 0xffff, + SMC_GET_RX_STS_FIFO_PEEK(lp)); + SMC_SET_GPT_CFG(lp, GPT_CFG_TIMER_EN_ | 10000); + SMC_ACK_INT(lp, INT_STS_GPT_INT_); } #endif @@ -1228,12 +1162,12 @@ static irqreturn_t smc911x_interrupt(int irq, void *dev_id) if (status & INT_STS_PHY_INT_) { DBG(SMC_DEBUG_MISC, "%s: PHY irq\n", dev->name); smc911x_phy_interrupt(dev); - SMC_ACK_INT(INT_STS_PHY_INT_); + SMC_ACK_INT(lp, INT_STS_PHY_INT_); } } while (--timeout); /* restore mask state */ - SMC_SET_INT_EN(mask); + SMC_SET_INT_EN(lp, mask); DBG(SMC_DEBUG_MISC, "%s: Interrupt done (%d loops)\n", dev->name, 8-timeout); @@ -1335,32 +1269,28 @@ static void smc911x_poll_controller(struct net_device *dev) static void smc911x_timeout(struct net_device *dev) { struct smc911x_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; int status, mask; unsigned long flags; DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); spin_lock_irqsave(&lp->lock, flags); - status = SMC_GET_INT(); - mask = SMC_GET_INT_EN(); + status = SMC_GET_INT(lp); + mask = SMC_GET_INT_EN(lp); spin_unlock_irqrestore(&lp->lock, flags); DBG(SMC_DEBUG_MISC, "%s: INT 0x%02x MASK 0x%02x \n", dev->name, status, mask); /* Dump the current TX FIFO contents and restart */ - mask = SMC_GET_TX_CFG(); - SMC_SET_TX_CFG(mask | TX_CFG_TXS_DUMP_ | TX_CFG_TXD_DUMP_); + mask = SMC_GET_TX_CFG(lp); + SMC_SET_TX_CFG(lp, mask | TX_CFG_TXS_DUMP_ | TX_CFG_TXD_DUMP_); /* * Reconfiguring the PHY doesn't seem like a bad idea here, but * 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; @@ -1376,7 +1306,6 @@ static void smc911x_timeout(struct net_device *dev) static void smc911x_set_multicast_list(struct net_device *dev) { struct smc911x_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; unsigned int multicast_table[2]; unsigned int mcr, update_multicast = 0; unsigned long flags; @@ -1384,7 +1313,7 @@ static void smc911x_set_multicast_list(struct net_device *dev) DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); spin_lock_irqsave(&lp->lock, flags); - SMC_GET_MAC_CR(mcr); + SMC_GET_MAC_CR(lp, mcr); spin_unlock_irqrestore(&lp->lock, flags); if (dev->flags & IFF_PROMISC) { @@ -1461,13 +1390,13 @@ static void smc911x_set_multicast_list(struct net_device *dev) } spin_lock_irqsave(&lp->lock, flags); - SMC_SET_MAC_CR(mcr); + SMC_SET_MAC_CR(lp, mcr); if (update_multicast) { DBG(SMC_DEBUG_MISC, "%s: update mcast hash table 0x%08x 0x%08x\n", dev->name, multicast_table[0], multicast_table[1]); - SMC_SET_HASHL(multicast_table[0]); - SMC_SET_HASHH(multicast_table[1]); + SMC_SET_HASHL(lp, multicast_table[0]); + SMC_SET_HASHH(lp, multicast_table[1]); } spin_unlock_irqrestore(&lp->lock, flags); } @@ -1531,16 +1460,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); } @@ -1559,7 +1480,6 @@ static int smc911x_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd) { struct smc911x_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; int ret, status; unsigned long flags; @@ -1587,7 +1507,7 @@ smc911x_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd) else cmd->transceiver = XCVR_EXTERNAL; cmd->port = 0; - SMC_GET_PHY_SPECIAL(lp->mii.phy_id, status); + SMC_GET_PHY_SPECIAL(lp, lp->mii.phy_id, status); cmd->duplex = (status & (PHY_SPECIAL_SPD_10FULL_ | PHY_SPECIAL_SPD_100FULL_)) ? DUPLEX_FULL : DUPLEX_HALF; @@ -1668,7 +1588,6 @@ static int smc911x_ethtool_getregslen(struct net_device *dev) static void smc911x_ethtool_getregs(struct net_device *dev, struct ethtool_regs* regs, void *buf) { - unsigned long ioaddr = dev->base_addr; struct smc911x_local *lp = netdev_priv(dev); unsigned long flags; u32 reg,i,j=0; @@ -1676,17 +1595,17 @@ static void smc911x_ethtool_getregs(struct net_device *dev, regs->version = lp->version; for(i=ID_REV;i<=E2P_CMD;i+=4) { - data[j++] = SMC_inl(ioaddr,i); + data[j++] = SMC_inl(lp, i); } for(i=MAC_CR;i<=WUCSR;i++) { spin_lock_irqsave(&lp->lock, flags); - SMC_GET_MAC_CSR(i, reg); + SMC_GET_MAC_CSR(lp, i, reg); spin_unlock_irqrestore(&lp->lock, flags); data[j++] = reg; } for(i=0;i<=31;i++) { spin_lock_irqsave(&lp->lock, flags); - SMC_GET_MII(i, lp->mii.phy_id, reg); + SMC_GET_MII(lp, i, lp->mii.phy_id, reg); spin_unlock_irqrestore(&lp->lock, flags); data[j++] = reg & 0xFFFF; } @@ -1694,11 +1613,11 @@ static void smc911x_ethtool_getregs(struct net_device *dev, static int smc911x_ethtool_wait_eeprom_ready(struct net_device *dev) { - unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); unsigned int timeout; int e2p_cmd; - e2p_cmd = SMC_GET_E2P_CMD(); + e2p_cmd = SMC_GET_E2P_CMD(lp); for(timeout=10;(e2p_cmd & E2P_CMD_EPC_BUSY_) && timeout; timeout--) { if (e2p_cmd & E2P_CMD_EPC_TIMEOUT_) { PRINTK("%s: %s timeout waiting for EEPROM to respond\n", @@ -1706,7 +1625,7 @@ static int smc911x_ethtool_wait_eeprom_ready(struct net_device *dev) return -EFAULT; } mdelay(1); - e2p_cmd = SMC_GET_E2P_CMD(); + e2p_cmd = SMC_GET_E2P_CMD(lp); } if (timeout == 0) { PRINTK("%s: %s timeout waiting for EEPROM CMD not busy\n", @@ -1719,12 +1638,12 @@ static int smc911x_ethtool_wait_eeprom_ready(struct net_device *dev) static inline int smc911x_ethtool_write_eeprom_cmd(struct net_device *dev, int cmd, int addr) { - unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); int ret; if ((ret = smc911x_ethtool_wait_eeprom_ready(dev))!=0) return ret; - SMC_SET_E2P_CMD(E2P_CMD_EPC_BUSY_ | + SMC_SET_E2P_CMD(lp, E2P_CMD_EPC_BUSY_ | ((cmd) & (0x7<<28)) | ((addr) & 0xFF)); return 0; @@ -1733,24 +1652,24 @@ static inline int smc911x_ethtool_write_eeprom_cmd(struct net_device *dev, static inline int smc911x_ethtool_read_eeprom_byte(struct net_device *dev, u8 *data) { - unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); int ret; if ((ret = smc911x_ethtool_wait_eeprom_ready(dev))!=0) return ret; - *data = SMC_GET_E2P_DATA(); + *data = SMC_GET_E2P_DATA(lp); return 0; } static inline int smc911x_ethtool_write_eeprom_byte(struct net_device *dev, u8 data) { - unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); int ret; if ((ret = smc911x_ethtool_wait_eeprom_ready(dev))!=0) return ret; - SMC_SET_E2P_DATA(data); + SMC_SET_E2P_DATA(lp, data); return 0; } @@ -1817,8 +1736,9 @@ static const struct ethtool_ops smc911x_ethtool_ops = { * This routine has a simple purpose -- make the SMC chip generate an * interrupt, so an auto-detect routine can detect it, and find the IRQ, */ -static int __init smc911x_findirq(unsigned long ioaddr) +static int __init smc911x_findirq(struct net_device *dev) { + struct smc911x_local *lp = netdev_priv(dev); int timeout = 20; unsigned long cookie; @@ -1830,7 +1750,7 @@ static int __init smc911x_findirq(unsigned long ioaddr) * Force a SW interrupt */ - SMC_SET_INT_EN(INT_EN_SW_INT_EN_); + SMC_SET_INT_EN(lp, INT_EN_SW_INT_EN_); /* * Wait until positive that the interrupt has been generated @@ -1838,7 +1758,7 @@ static int __init smc911x_findirq(unsigned long ioaddr) do { int int_status; udelay(10); - int_status = SMC_GET_INT_EN(); + int_status = SMC_GET_INT_EN(lp); if (int_status & INT_EN_SW_INT_EN_) break; /* got the interrupt */ } while (--timeout); @@ -1851,7 +1771,7 @@ static int __init smc911x_findirq(unsigned long ioaddr) */ /* and disable all interrupts again */ - SMC_SET_INT_EN(0); + SMC_SET_INT_EN(lp, 0); /* and return what I found */ return probe_irq_off(cookie); @@ -1880,17 +1800,18 @@ static int __init smc911x_findirq(unsigned long ioaddr) * o actually GRAB the irq. * o GRAB the region */ -static int __init smc911x_probe(struct net_device *dev, unsigned long ioaddr) +static int __init smc911x_probe(struct net_device *dev) { struct smc911x_local *lp = netdev_priv(dev); int i, retval; unsigned int val, chip_id, revision; const char *version_string; + unsigned long irq_flags; DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); /* First, see if the endian word is recognized */ - val = SMC_GET_BYTE_TEST(); + val = SMC_GET_BYTE_TEST(lp); DBG(SMC_DEBUG_MISC, "%s: endian probe returned 0x%04x\n", CARDNAME, val); if (val != 0x87654321) { printk(KERN_ERR "Invalid chip endian 0x08%x\n",val); @@ -1903,7 +1824,7 @@ static int __init smc911x_probe(struct net_device *dev, unsigned long ioaddr) * recognize. These might need to be added to later, * as future revisions could be added. */ - chip_id = SMC_GET_PN(); + chip_id = SMC_GET_PN(lp); DBG(SMC_DEBUG_MISC, "%s: id probe returned 0x%04x\n", CARDNAME, chip_id); for(i=0;chip_ids[i].id != 0; i++) { if (chip_ids[i].id == chip_id) break; @@ -1915,7 +1836,7 @@ static int __init smc911x_probe(struct net_device *dev, unsigned long ioaddr) } version_string = chip_ids[i].name; - revision = SMC_GET_REV(); + revision = SMC_GET_REV(lp); DBG(SMC_DEBUG_MISC, "%s: revision = 0x%04x\n", CARDNAME, revision); /* At this point I'll assume that the chip is an SMC911x. */ @@ -1929,7 +1850,6 @@ static int __init smc911x_probe(struct net_device *dev, unsigned long ioaddr) } /* fill in some of the fields */ - dev->base_addr = ioaddr; lp->version = chip_ids[i].id; lp->revision = revision; lp->tx_fifo_kb = tx_fifo_kb; @@ -1988,7 +1908,7 @@ static int __init smc911x_probe(struct net_device *dev, unsigned long ioaddr) spin_lock_init(&lp->lock); /* Get the MAC address */ - SMC_GET_MAC_ADDR(dev->dev_addr); + SMC_GET_MAC_ADDR(lp, dev->dev_addr); /* now, reset the chip, and put it into a known state */ smc911x_reset(dev); @@ -2005,7 +1925,7 @@ static int __init smc911x_probe(struct net_device *dev, unsigned long ioaddr) trials = 3; while (trials--) { - dev->irq = smc911x_findirq(ioaddr); + dev->irq = smc911x_findirq(dev); if (dev->irq) break; /* kick the card and try again */ @@ -2053,9 +1973,15 @@ static int __init smc911x_probe(struct net_device *dev, unsigned long ioaddr) lp->ctl_rfduplx = 1; lp->ctl_rspeed = 100; +#ifdef SMC_DYNAMIC_BUS_CONFIG + irq_flags = lp->cfg.irq_flags; +#else + irq_flags = IRQF_SHARED | SMC_IRQ_SENSE; +#endif + /* Grab the IRQ */ retval = request_irq(dev->irq, &smc911x_interrupt, - IRQF_SHARED | SMC_IRQ_SENSE, dev->name, dev); + irq_flags, dev->name, dev); if (retval) goto err_out; @@ -2125,6 +2051,7 @@ err_out: */ static int smc911x_drv_probe(struct platform_device *pdev) { + struct smc91x_platdata *pd = pdev->dev.platform_data; struct net_device *ndev; struct resource *res; struct smc911x_local *lp; @@ -2158,6 +2085,13 @@ static int smc911x_drv_probe(struct platform_device *pdev) ndev->irq = platform_get_irq(pdev, 0); lp = netdev_priv(ndev); lp->netdev = ndev; +#ifdef SMC_DYNAMIC_BUS_CONFIG + if (!pd) { + ret = -EINVAL; + goto release_both; + } + memcpy(&lp->cfg, pd, sizeof(lp->cfg)); +#endif addr = ioremap(res->start, SMC911X_IO_EXTENT); if (!addr) { @@ -2166,7 +2100,9 @@ static int smc911x_drv_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, ndev); - ret = smc911x_probe(ndev, (unsigned long)addr); + lp->base = addr; + ndev->base_addr = res->start; + ret = smc911x_probe(ndev); if (ret != 0) { platform_set_drvdata(pdev, NULL); iounmap(addr); @@ -2190,6 +2126,7 @@ out: static int smc911x_drv_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); + struct smc911x_local *lp = netdev_priv(ndev); struct resource *res; DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__); @@ -2201,7 +2138,6 @@ static int smc911x_drv_remove(struct platform_device *pdev) #ifdef SMC_USE_DMA { - struct smc911x_local *lp = netdev_priv(ndev); if (lp->rxdma != -1) { SMC_DMA_FREE(dev, lp->rxdma); } @@ -2210,7 +2146,7 @@ static int smc911x_drv_remove(struct platform_device *pdev) } } #endif - iounmap((void *)ndev->base_addr); + iounmap(lp->base); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(res->start, SMC911X_IO_EXTENT); @@ -2221,7 +2157,7 @@ static int smc911x_drv_remove(struct platform_device *pdev) static int smc911x_drv_suspend(struct platform_device *dev, pm_message_t state) { struct net_device *ndev = platform_get_drvdata(dev); - unsigned long ioaddr = ndev->base_addr; + struct smc911x_local *lp = netdev_priv(ndev); DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__); if (ndev) { @@ -2230,7 +2166,7 @@ static int smc911x_drv_suspend(struct platform_device *dev, pm_message_t state) smc911x_shutdown(ndev); #if POWER_DOWN /* Set D2 - Energy detect only setting */ - SMC_SET_PMT_CTRL(2<<12); + SMC_SET_PMT_CTRL(lp, 2<<12); #endif } } diff --git a/drivers/net/smc911x.h b/drivers/net/smc911x.h index 7defa63b9c7..76c17c28fab 100644 --- a/drivers/net/smc911x.h +++ b/drivers/net/smc911x.h @@ -29,6 +29,7 @@ #ifndef _SMC911X_H_ #define _SMC911X_H_ +#include <linux/smc911x.h> /* * Use the DMA feature on PXA chips */ @@ -38,42 +39,160 @@ #define SMC_USE_32BIT 1 #define SMC_IRQ_SENSE IRQF_TRIGGER_FALLING #elif defined(CONFIG_SH_MAGIC_PANEL_R2) - #define SMC_USE_SH_DMA 0 #define SMC_USE_16BIT 0 #define SMC_USE_32BIT 1 #define SMC_IRQ_SENSE IRQF_TRIGGER_LOW +#else +/* + * Default configuration + */ + +#define SMC_DYNAMIC_BUS_CONFIG #endif +/* store this information for the driver.. */ +struct smc911x_local { + /* + * If I have to wait until the DMA is finished and ready to reload a + * packet, I will store the skbuff here. Then, the DMA will send it + * out and free it. + */ + struct sk_buff *pending_tx_skb; + + /* version/revision of the SMC911x chip */ + u16 version; + u16 revision; + + /* FIFO sizes */ + int tx_fifo_kb; + int tx_fifo_size; + int rx_fifo_size; + int afc_cfg; + + /* Contains the current active receive/phy mode */ + int ctl_rfduplx; + int ctl_rspeed; + + u32 msg_enable; + u32 phy_type; + struct mii_if_info mii; + + /* work queue */ + struct work_struct phy_configure; + + int tx_throttle; + spinlock_t lock; + + struct net_device *netdev; + +#ifdef SMC_USE_DMA + /* DMA needs the physical address of the chip */ + u_long physaddr; + int rxdma; + int txdma; + int rxdma_active; + int txdma_active; + struct sk_buff *current_rx_skb; + struct sk_buff *current_tx_skb; + struct device *dev; +#endif + void __iomem *base; +#ifdef SMC_DYNAMIC_BUS_CONFIG + struct smc911x_platdata cfg; +#endif +}; /* * Define the bus width specific IO macros */ +#ifdef SMC_DYNAMIC_BUS_CONFIG +static inline unsigned int SMC_inl(struct smc911x_local *lp, int reg) +{ + void __iomem *ioaddr = lp->base + reg; + + if (lp->cfg.flags & SMC911X_USE_32BIT) + return readl(ioaddr); + + if (lp->cfg.flags & SMC911X_USE_16BIT) + return readw(ioaddr) | (readw(ioaddr + 2) << 16); + + BUG(); +} + +static inline void SMC_outl(unsigned int value, struct smc911x_local *lp, + int reg) +{ + void __iomem *ioaddr = lp->base + reg; + + if (lp->cfg.flags & SMC911X_USE_32BIT) { + writel(value, ioaddr); + return; + } + + if (lp->cfg.flags & SMC911X_USE_16BIT) { + writew(value & 0xffff, ioaddr); + writew(value >> 16, ioaddr + 2); + return; + } + + BUG(); +} + +static inline void SMC_insl(struct smc911x_local *lp, int reg, + void *addr, unsigned int count) +{ + void __iomem *ioaddr = lp->base + reg; + + if (lp->cfg.flags & SMC911X_USE_32BIT) { + readsl(ioaddr, addr, count); + return; + } + + if (lp->cfg.flags & SMC911X_USE_16BIT) { + readsw(ioaddr, addr, count * 2); + return; + } + + BUG(); +} + +static inline void SMC_outsl(struct smc911x_local *lp, int reg, + void *addr, unsigned int count) +{ + void __iomem *ioaddr = lp->base + reg; + + if (lp->cfg.flags & SMC911X_USE_32BIT) { + writesl(ioaddr, addr, count); + return; + } + + if (lp->cfg.flags & SMC911X_USE_16BIT) { + writesw(ioaddr, addr, count * 2); + return; + } + + BUG(); +} +#else #if SMC_USE_16BIT -#define SMC_inb(a, r) readb((a) + (r)) -#define SMC_inw(a, r) readw((a) + (r)) -#define SMC_inl(a, r) ((SMC_inw(a, r) & 0xFFFF)+(SMC_inw(a+2, r)<<16)) -#define SMC_outb(v, a, r) writeb(v, (a) + (r)) -#define SMC_outw(v, a, r) writew(v, (a) + (r)) -#define SMC_outl(v, a, r) \ +#define SMC_inl(lp, r) ((readw((lp)->base + (r)) & 0xFFFF) + (readw((lp)->base + (r) + 2) << 16)) +#define SMC_outl(v, lp, r) \ do{ \ - writel(v & 0xFFFF, (a) + (r)); \ - writel(v >> 16, (a) + (r) + 2); \ + writew(v & 0xFFFF, (lp)->base + (r)); \ + writew(v >> 16, (lp)->base + (r) + 2); \ } while (0) -#define SMC_insl(a, r, p, l) readsw((short*)((a) + (r)), p, l*2) -#define SMC_outsl(a, r, p, l) writesw((short*)((a) + (r)), p, l*2) +#define SMC_insl(lp, r, p, l) readsw((short*)((lp)->base + (r)), p, l*2) +#define SMC_outsl(lp, r, p, l) writesw((short*)((lp)->base + (r)), p, l*2) #elif SMC_USE_32BIT -#define SMC_inb(a, r) readb((a) + (r)) -#define SMC_inw(a, r) readw((a) + (r)) -#define SMC_inl(a, r) readl((a) + (r)) -#define SMC_outb(v, a, r) writeb(v, (a) + (r)) -#define SMC_outl(v, a, r) writel(v, (a) + (r)) -#define SMC_insl(a, r, p, l) readsl((int*)((a) + (r)), p, l) -#define SMC_outsl(a, r, p, l) writesl((int*)((a) + (r)), p, l) +#define SMC_inl(lp, r) readl((lp)->base + (r)) +#define SMC_outl(v, lp, r) writel(v, (lp)->base + (r)) +#define SMC_insl(lp, r, p, l) readsl((int*)((lp)->base + (r)), p, l) +#define SMC_outsl(lp, r, p, l) writesl((int*)((lp)->base + (r)), p, l) #endif /* SMC_USE_16BIT */ - +#endif /* SMC_DYNAMIC_BUS_CONFIG */ #ifdef SMC_USE_PXA_DMA @@ -110,22 +229,22 @@ static int rx_dmalen, tx_dmalen; #ifdef SMC_insl #undef SMC_insl -#define SMC_insl(a, r, p, l) \ - smc_pxa_dma_insl(lp->dev, a, lp->physaddr, r, lp->rxdma, p, l) +#define SMC_insl(lp, r, p, l) \ + smc_pxa_dma_insl(lp, lp->physaddr, r, lp->rxdma, p, l) static inline void -smc_pxa_dma_insl(struct device *dev, u_long ioaddr, u_long physaddr, +smc_pxa_dma_insl(struct smc911x_local *lp, u_long physaddr, int reg, int dma, u_char *buf, int len) { /* 64 bit alignment is required for memory to memory DMA */ if ((long)buf & 4) { - *((u32 *)buf) = SMC_inl(ioaddr, reg); + *((u32 *)buf) = SMC_inl(lp, reg); buf += 4; len--; } len *= 4; - rx_dmabuf = dma_map_single(dev, buf, len, DMA_FROM_DEVICE); + rx_dmabuf = dma_map_single(lp->dev, buf, len, DMA_FROM_DEVICE); rx_dmalen = len; DCSR(dma) = DCSR_NODESC; DTADR(dma) = rx_dmabuf; @@ -136,52 +255,24 @@ smc_pxa_dma_insl(struct device *dev, u_long ioaddr, u_long physaddr, } #endif -#ifdef SMC_insw -#undef SMC_insw -#define SMC_insw(a, r, p, l) \ - smc_pxa_dma_insw(lp->dev, a, lp->physaddr, r, lp->rxdma, p, l) - -static inline void -smc_pxa_dma_insw(struct device *dev, u_long ioaddr, u_long physaddr, - int reg, int dma, u_char *buf, int len) -{ - /* 64 bit alignment is required for memory to memory DMA */ - while ((long)buf & 6) { - *((u16 *)buf) = SMC_inw(ioaddr, reg); - buf += 2; - len--; - } - - len *= 2; - rx_dmabuf = dma_map_single(dev, buf, len, DMA_FROM_DEVICE); - rx_dmalen = len; - DCSR(dma) = DCSR_NODESC; - DTADR(dma) = rx_dmabuf; - DSADR(dma) = physaddr + reg; - DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 | - DCMD_WIDTH2 | DCMD_ENDIRQEN | (DCMD_LENGTH & rx_dmalen)); - DCSR(dma) = DCSR_NODESC | DCSR_RUN; -} -#endif - #ifdef SMC_outsl #undef SMC_outsl -#define SMC_outsl(a, r, p, l) \ - smc_pxa_dma_outsl(lp->dev, a, lp->physaddr, r, lp->txdma, p, l) +#define SMC_outsl(lp, r, p, l) \ + smc_pxa_dma_outsl(lp, lp->physaddr, r, lp->txdma, p, l) static inline void -smc_pxa_dma_outsl(struct device *dev, u_long ioaddr, u_long physaddr, +smc_pxa_dma_outsl(struct smc911x_local *lp, u_long physaddr, int reg, int dma, u_char *buf, int len) { /* 64 bit alignment is required for memory to memory DMA */ if ((long)buf & 4) { - SMC_outl(*((u32 *)buf), ioaddr, reg); + SMC_outl(*((u32 *)buf), lp, reg); buf += 4; len--; } len *= 4; - tx_dmabuf = dma_map_single(dev, buf, len, DMA_TO_DEVICE); + tx_dmabuf = dma_map_single(lp->dev, buf, len, DMA_TO_DEVICE); tx_dmalen = len; DCSR(dma) = DCSR_NODESC; DSADR(dma) = tx_dmabuf; @@ -191,35 +282,6 @@ smc_pxa_dma_outsl(struct device *dev, u_long ioaddr, u_long physaddr, DCSR(dma) = DCSR_NODESC | DCSR_RUN; } #endif - -#ifdef SMC_outsw -#undef SMC_outsw -#define SMC_outsw(a, r, p, l) \ - smc_pxa_dma_outsw(lp->dev, a, lp->physaddr, r, lp->txdma, p, l) - -static inline void -smc_pxa_dma_outsw(struct device *dev, u_long ioaddr, u_long physaddr, - int reg, int dma, u_char *buf, int len) -{ - /* 64 bit alignment is required for memory to memory DMA */ - while ((long)buf & 6) { - SMC_outw(*((u16 *)buf), ioaddr, reg); - buf += 2; - len--; - } - - len *= 2; - tx_dmabuf = dma_map_single(dev, buf, len, DMA_TO_DEVICE); - tx_dmalen = len; - DCSR(dma) = DCSR_NODESC; - DSADR(dma) = tx_dmabuf; - DTADR(dma) = physaddr + reg; - DCMD(dma) = (DCMD_INCSRCADDR | DCMD_BURST32 | - DCMD_WIDTH2 | DCMD_ENDIRQEN | (DCMD_LENGTH & tx_dmalen)); - DCSR(dma) = DCSR_NODESC | DCSR_RUN; -} -#endif - #endif /* SMC_USE_PXA_DMA */ @@ -629,213 +691,213 @@ static const struct chip_id chip_ids[] = { * capabilities. Please use those and not the in/out primitives. */ /* FIFO read/write macros */ -#define SMC_PUSH_DATA(p, l) SMC_outsl( ioaddr, TX_DATA_FIFO, p, (l) >> 2 ) -#define SMC_PULL_DATA(p, l) SMC_insl ( ioaddr, RX_DATA_FIFO, p, (l) >> 2 ) -#define SMC_SET_TX_FIFO(x) SMC_outl( x, ioaddr, TX_DATA_FIFO ) -#define SMC_GET_RX_FIFO() SMC_inl( ioaddr, RX_DATA_FIFO ) +#define SMC_PUSH_DATA(lp, p, l) SMC_outsl( lp, TX_DATA_FIFO, p, (l) >> 2 ) +#define SMC_PULL_DATA(lp, p, l) SMC_insl ( lp, RX_DATA_FIFO, p, (l) >> 2 ) +#define SMC_SET_TX_FIFO(lp, x) SMC_outl( x, lp, TX_DATA_FIFO ) +#define SMC_GET_RX_FIFO(lp) SMC_inl( lp, RX_DATA_FIFO ) /* I/O mapped register read/write macros */ -#define SMC_GET_TX_STS_FIFO() SMC_inl( ioaddr, TX_STATUS_FIFO ) -#define SMC_GET_RX_STS_FIFO() SMC_inl( ioaddr, RX_STATUS_FIFO ) -#define SMC_GET_RX_STS_FIFO_PEEK() SMC_inl( ioaddr, RX_STATUS_FIFO_PEEK ) -#define SMC_GET_PN() (SMC_inl( ioaddr, ID_REV ) >> 16) -#define SMC_GET_REV() (SMC_inl( ioaddr, ID_REV ) & 0xFFFF) -#define SMC_GET_IRQ_CFG() SMC_inl( ioaddr, INT_CFG ) -#define SMC_SET_IRQ_CFG(x) SMC_outl( x, ioaddr, INT_CFG ) -#define SMC_GET_INT() SMC_inl( ioaddr, INT_STS ) -#define SMC_ACK_INT(x) SMC_outl( x, ioaddr, INT_STS ) -#define SMC_GET_INT_EN() SMC_inl( ioaddr, INT_EN ) -#define SMC_SET_INT_EN(x) SMC_outl( x, ioaddr, INT_EN ) -#define SMC_GET_BYTE_TEST() SMC_inl( ioaddr, BYTE_TEST ) -#define SMC_SET_BYTE_TEST(x) SMC_outl( x, ioaddr, BYTE_TEST ) -#define SMC_GET_FIFO_INT() SMC_inl( ioaddr, FIFO_INT ) -#define SMC_SET_FIFO_INT(x) SMC_outl( x, ioaddr, FIFO_INT ) -#define SMC_SET_FIFO_TDA(x) \ +#define SMC_GET_TX_STS_FIFO(lp) SMC_inl( lp, TX_STATUS_FIFO ) +#define SMC_GET_RX_STS_FIFO(lp) SMC_inl( lp, RX_STATUS_FIFO ) +#define SMC_GET_RX_STS_FIFO_PEEK(lp) SMC_inl( lp, RX_STATUS_FIFO_PEEK ) +#define SMC_GET_PN(lp) (SMC_inl( lp, ID_REV ) >> 16) +#define SMC_GET_REV(lp) (SMC_inl( lp, ID_REV ) & 0xFFFF) +#define SMC_GET_IRQ_CFG(lp) SMC_inl( lp, INT_CFG ) +#define SMC_SET_IRQ_CFG(lp, x) SMC_outl( x, lp, INT_CFG ) +#define SMC_GET_INT(lp) SMC_inl( lp, INT_STS ) +#define SMC_ACK_INT(lp, x) SMC_outl( x, lp, INT_STS ) +#define SMC_GET_INT_EN(lp) SMC_inl( lp, INT_EN ) +#define SMC_SET_INT_EN(lp, x) SMC_outl( x, lp, INT_EN ) +#define SMC_GET_BYTE_TEST(lp) SMC_inl( lp, BYTE_TEST ) +#define SMC_SET_BYTE_TEST(lp, x) SMC_outl( x, lp, BYTE_TEST ) +#define SMC_GET_FIFO_INT(lp) SMC_inl( lp, FIFO_INT ) +#define SMC_SET_FIFO_INT(lp, x) SMC_outl( x, lp, FIFO_INT ) +#define SMC_SET_FIFO_TDA(lp, x) \ do { \ unsigned long __flags; \ int __mask; \ local_irq_save(__flags); \ - __mask = SMC_GET_FIFO_INT() & ~(0xFF<<24); \ - SMC_SET_FIFO_INT( __mask | (x)<<24 ); \ + __mask = SMC_GET_FIFO_INT((lp)) & ~(0xFF<<24); \ + SMC_SET_FIFO_INT( (lp), __mask | (x)<<24 ); \ local_irq_restore(__flags); \ } while (0) -#define SMC_SET_FIFO_TSL(x) \ +#define SMC_SET_FIFO_TSL(lp, x) \ do { \ unsigned long __flags; \ int __mask; \ local_irq_save(__flags); \ - __mask = SMC_GET_FIFO_INT() & ~(0xFF<<16); \ - SMC_SET_FIFO_INT( __mask | (((x) & 0xFF)<<16)); \ + __mask = SMC_GET_FIFO_INT((lp)) & ~(0xFF<<16); \ + SMC_SET_FIFO_INT( (lp), __mask | (((x) & 0xFF)<<16)); \ local_irq_restore(__flags); \ } while (0) -#define SMC_SET_FIFO_RSA(x) \ +#define SMC_SET_FIFO_RSA(lp, x) \ do { \ unsigned long __flags; \ int __mask; \ local_irq_save(__flags); \ - __mask = SMC_GET_FIFO_INT() & ~(0xFF<<8); \ - SMC_SET_FIFO_INT( __mask | (((x) & 0xFF)<<8)); \ + __mask = SMC_GET_FIFO_INT((lp)) & ~(0xFF<<8); \ + SMC_SET_FIFO_INT( (lp), __mask | (((x) & 0xFF)<<8)); \ local_irq_restore(__flags); \ } while (0) -#define SMC_SET_FIFO_RSL(x) \ +#define SMC_SET_FIFO_RSL(lp, x) \ do { \ unsigned long __flags; \ int __mask; \ local_irq_save(__flags); \ - __mask = SMC_GET_FIFO_INT() & ~0xFF; \ - SMC_SET_FIFO_INT( __mask | ((x) & 0xFF)); \ + __mask = SMC_GET_FIFO_INT((lp)) & ~0xFF; \ + SMC_SET_FIFO_INT( (lp),__mask | ((x) & 0xFF)); \ local_irq_restore(__flags); \ } while (0) -#define SMC_GET_RX_CFG() SMC_inl( ioaddr, RX_CFG ) -#define SMC_SET_RX_CFG(x) SMC_outl( x, ioaddr, RX_CFG ) -#define SMC_GET_TX_CFG() SMC_inl( ioaddr, TX_CFG ) -#define SMC_SET_TX_CFG(x) SMC_outl( x, ioaddr, TX_CFG ) -#define SMC_GET_HW_CFG() SMC_inl( ioaddr, HW_CFG ) -#define SMC_SET_HW_CFG(x) SMC_outl( x, ioaddr, HW_CFG ) -#define SMC_GET_RX_DP_CTRL() SMC_inl( ioaddr, RX_DP_CTRL ) -#define SMC_SET_RX_DP_CTRL(x) SMC_outl( x, ioaddr, RX_DP_CTRL ) -#define SMC_GET_PMT_CTRL() SMC_inl( ioaddr, PMT_CTRL ) -#define SMC_SET_PMT_CTRL(x) SMC_outl( x, ioaddr, PMT_CTRL ) -#define SMC_GET_GPIO_CFG() SMC_inl( ioaddr, GPIO_CFG ) -#define SMC_SET_GPIO_CFG(x) SMC_outl( x, ioaddr, GPIO_CFG ) -#define SMC_GET_RX_FIFO_INF() SMC_inl( ioaddr, RX_FIFO_INF ) -#define SMC_SET_RX_FIFO_INF(x) SMC_outl( x, ioaddr, RX_FIFO_INF ) -#define SMC_GET_TX_FIFO_INF() SMC_inl( ioaddr, TX_FIFO_INF ) -#define SMC_SET_TX_FIFO_INF(x) SMC_outl( x, ioaddr, TX_FIFO_INF ) -#define SMC_GET_GPT_CFG() SMC_inl( ioaddr, GPT_CFG ) -#define SMC_SET_GPT_CFG(x) SMC_outl( x, ioaddr, GPT_CFG ) -#define SMC_GET_RX_DROP() SMC_inl( ioaddr, RX_DROP ) -#define SMC_SET_RX_DROP(x) SMC_outl( x, ioaddr, RX_DROP ) -#define SMC_GET_MAC_CMD() SMC_inl( ioaddr, MAC_CSR_CMD ) -#define SMC_SET_MAC_CMD(x) SMC_outl( x, ioaddr, MAC_CSR_CMD ) -#define SMC_GET_MAC_DATA() SMC_inl( ioaddr, MAC_CSR_DATA ) -#define SMC_SET_MAC_DATA(x) SMC_outl( x, ioaddr, MAC_CSR_DATA ) -#define SMC_GET_AFC_CFG() SMC_inl( ioaddr, AFC_CFG ) -#define SMC_SET_AFC_CFG(x) SMC_outl( x, ioaddr, AFC_CFG ) -#define SMC_GET_E2P_CMD() SMC_inl( ioaddr, E2P_CMD ) -#define SMC_SET_E2P_CMD(x) SMC_outl( x, ioaddr, E2P_CMD ) -#define SMC_GET_E2P_DATA() SMC_inl( ioaddr, E2P_DATA ) -#define SMC_SET_E2P_DATA(x) SMC_outl( x, ioaddr, E2P_DATA ) +#define SMC_GET_RX_CFG(lp) SMC_inl( lp, RX_CFG ) +#define SMC_SET_RX_CFG(lp, x) SMC_outl( x, lp, RX_CFG ) +#define SMC_GET_TX_CFG(lp) SMC_inl( lp, TX_CFG ) +#define SMC_SET_TX_CFG(lp, x) SMC_outl( x, lp, TX_CFG ) +#define SMC_GET_HW_CFG(lp) SMC_inl( lp, HW_CFG ) +#define SMC_SET_HW_CFG(lp, x) SMC_outl( x, lp, HW_CFG ) +#define SMC_GET_RX_DP_CTRL(lp) SMC_inl( lp, RX_DP_CTRL ) +#define SMC_SET_RX_DP_CTRL(lp, x) SMC_outl( x, lp, RX_DP_CTRL ) +#define SMC_GET_PMT_CTRL(lp) SMC_inl( lp, PMT_CTRL ) +#define SMC_SET_PMT_CTRL(lp, x) SMC_outl( x, lp, PMT_CTRL ) +#define SMC_GET_GPIO_CFG(lp) SMC_inl( lp, GPIO_CFG ) +#define SMC_SET_GPIO_CFG(lp, x) SMC_outl( x, lp, GPIO_CFG ) +#define SMC_GET_RX_FIFO_INF(lp) SMC_inl( lp, RX_FIFO_INF ) +#define SMC_SET_RX_FIFO_INF(lp, x) SMC_outl( x, lp, RX_FIFO_INF ) +#define SMC_GET_TX_FIFO_INF(lp) SMC_inl( lp, TX_FIFO_INF ) +#define SMC_SET_TX_FIFO_INF(lp, x) SMC_outl( x, lp, TX_FIFO_INF ) +#define SMC_GET_GPT_CFG(lp) SMC_inl( lp, GPT_CFG ) +#define SMC_SET_GPT_CFG(lp, x) SMC_outl( x, lp, GPT_CFG ) +#define SMC_GET_RX_DROP(lp) SMC_inl( lp, RX_DROP ) +#define SMC_SET_RX_DROP(lp, x) SMC_outl( x, lp, RX_DROP ) +#define SMC_GET_MAC_CMD(lp) SMC_inl( lp, MAC_CSR_CMD ) +#define SMC_SET_MAC_CMD(lp, x) SMC_outl( x, lp, MAC_CSR_CMD ) +#define SMC_GET_MAC_DATA(lp) SMC_inl( lp, MAC_CSR_DATA ) +#define SMC_SET_MAC_DATA(lp, x) SMC_outl( x, lp, MAC_CSR_DATA ) +#define SMC_GET_AFC_CFG(lp) SMC_inl( lp, AFC_CFG ) +#define SMC_SET_AFC_CFG(lp, x) SMC_outl( x, lp, AFC_CFG ) +#define SMC_GET_E2P_CMD(lp) SMC_inl( lp, E2P_CMD ) +#define SMC_SET_E2P_CMD(lp, x) SMC_outl( x, lp, E2P_CMD ) +#define SMC_GET_E2P_DATA(lp) SMC_inl( lp, E2P_DATA ) +#define SMC_SET_E2P_DATA(lp, x) SMC_outl( x, lp, E2P_DATA ) /* MAC register read/write macros */ -#define SMC_GET_MAC_CSR(a,v) \ +#define SMC_GET_MAC_CSR(lp,a,v) \ do { \ - while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_); \ - SMC_SET_MAC_CMD(MAC_CSR_CMD_CSR_BUSY_ | \ + while (SMC_GET_MAC_CMD((lp)) & MAC_CSR_CMD_CSR_BUSY_); \ + SMC_SET_MAC_CMD((lp),MAC_CSR_CMD_CSR_BUSY_ | \ MAC_CSR_CMD_R_NOT_W_ | (a) ); \ - while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_); \ - v = SMC_GET_MAC_DATA(); \ + while (SMC_GET_MAC_CMD((lp)) & MAC_CSR_CMD_CSR_BUSY_); \ + v = SMC_GET_MAC_DATA((lp)); \ } while (0) -#define SMC_SET_MAC_CSR(a,v) \ +#define SMC_SET_MAC_CSR(lp,a,v) \ do { \ - while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_); \ - SMC_SET_MAC_DATA(v); \ - SMC_SET_MAC_CMD(MAC_CSR_CMD_CSR_BUSY_ | (a) ); \ - while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_); \ + while (SMC_GET_MAC_CMD((lp)) & MAC_CSR_CMD_CSR_BUSY_); \ + SMC_SET_MAC_DATA((lp), v); \ + SMC_SET_MAC_CMD((lp), MAC_CSR_CMD_CSR_BUSY_ | (a) ); \ + while (SMC_GET_MAC_CMD((lp)) & MAC_CSR_CMD_CSR_BUSY_); \ } while (0) -#define SMC_GET_MAC_CR(x) SMC_GET_MAC_CSR( MAC_CR, x ) -#define SMC_SET_MAC_CR(x) SMC_SET_MAC_CSR( MAC_CR, x ) -#define SMC_GET_ADDRH(x) SMC_GET_MAC_CSR( ADDRH, x ) -#define SMC_SET_ADDRH(x) SMC_SET_MAC_CSR( ADDRH, x ) -#define SMC_GET_ADDRL(x) SMC_GET_MAC_CSR( ADDRL, x ) -#define SMC_SET_ADDRL(x) SMC_SET_MAC_CSR( ADDRL, x ) -#define SMC_GET_HASHH(x) SMC_GET_MAC_CSR( HASHH, x ) -#define SMC_SET_HASHH(x) SMC_SET_MAC_CSR( HASHH, x ) -#define SMC_GET_HASHL(x) SMC_GET_MAC_CSR( HASHL, x ) -#define SMC_SET_HASHL(x) SMC_SET_MAC_CSR( HASHL, x ) -#define SMC_GET_MII_ACC(x) SMC_GET_MAC_CSR( MII_ACC, x ) -#define SMC_SET_MII_ACC(x) SMC_SET_MAC_CSR( MII_ACC, x ) -#define SMC_GET_MII_DATA(x) SMC_GET_MAC_CSR( MII_DATA, x ) -#define SMC_SET_MII_DATA(x) SMC_SET_MAC_CSR( MII_DATA, x ) -#define SMC_GET_FLOW(x) SMC_GET_MAC_CSR( FLOW, x ) -#define SMC_SET_FLOW(x) SMC_SET_MAC_CSR( FLOW, x ) -#define SMC_GET_VLAN1(x) SMC_GET_MAC_CSR( VLAN1, x ) -#define SMC_SET_VLAN1(x) SMC_SET_MAC_CSR( VLAN1, x ) -#define SMC_GET_VLAN2(x) SMC_GET_MAC_CSR( VLAN2, x ) -#define SMC_SET_VLAN2(x) SMC_SET_MAC_CSR( VLAN2, x ) -#define SMC_SET_WUFF(x) SMC_SET_MAC_CSR( WUFF, x ) -#define SMC_GET_WUCSR(x) SMC_GET_MAC_CSR( WUCSR, x ) -#define SMC_SET_WUCSR(x) SMC_SET_MAC_CSR( WUCSR, x ) +#define SMC_GET_MAC_CR(lp, x) SMC_GET_MAC_CSR( (lp), MAC_CR, x ) +#define SMC_SET_MAC_CR(lp, x) SMC_SET_MAC_CSR( (lp), MAC_CR, x ) +#define SMC_GET_ADDRH(lp, x) SMC_GET_MAC_CSR( (lp), ADDRH, x ) +#define SMC_SET_ADDRH(lp, x) SMC_SET_MAC_CSR( (lp), ADDRH, x ) +#define SMC_GET_ADDRL(lp, x) SMC_GET_MAC_CSR( (lp), ADDRL, x ) +#define SMC_SET_ADDRL(lp, x) SMC_SET_MAC_CSR( (lp), ADDRL, x ) +#define SMC_GET_HASHH(lp, x) SMC_GET_MAC_CSR( (lp), HASHH, x ) +#define SMC_SET_HASHH(lp, x) SMC_SET_MAC_CSR( (lp), HASHH, x ) +#define SMC_GET_HASHL(lp, x) SMC_GET_MAC_CSR( (lp), HASHL, x ) +#define SMC_SET_HASHL(lp, x) SMC_SET_MAC_CSR( (lp), HASHL, x ) +#define SMC_GET_MII_ACC(lp, x) SMC_GET_MAC_CSR( (lp), MII_ACC, x ) +#define SMC_SET_MII_ACC(lp, x) SMC_SET_MAC_CSR( (lp), MII_ACC, x ) +#define SMC_GET_MII_DATA(lp, x) SMC_GET_MAC_CSR( (lp), MII_DATA, x ) +#define SMC_SET_MII_DATA(lp, x) SMC_SET_MAC_CSR( (lp), MII_DATA, x ) +#define SMC_GET_FLOW(lp, x) SMC_GET_MAC_CSR( (lp), FLOW, x ) +#define SMC_SET_FLOW(lp, x) SMC_SET_MAC_CSR( (lp), FLOW, x ) +#define SMC_GET_VLAN1(lp, x) SMC_GET_MAC_CSR( (lp), VLAN1, x ) +#define SMC_SET_VLAN1(lp, x) SMC_SET_MAC_CSR( (lp), VLAN1, x ) +#define SMC_GET_VLAN2(lp, x) SMC_GET_MAC_CSR( (lp), VLAN2, x ) +#define SMC_SET_VLAN2(lp, x) SMC_SET_MAC_CSR( (lp), VLAN2, x ) +#define SMC_SET_WUFF(lp, x) SMC_SET_MAC_CSR( (lp), WUFF, x ) +#define SMC_GET_WUCSR(lp, x) SMC_GET_MAC_CSR( (lp), WUCSR, x ) +#define SMC_SET_WUCSR(lp, x) SMC_SET_MAC_CSR( (lp), WUCSR, x ) /* PHY register read/write macros */ -#define SMC_GET_MII(a,phy,v) \ +#define SMC_GET_MII(lp,a,phy,v) \ do { \ u32 __v; \ do { \ - SMC_GET_MII_ACC(__v); \ + SMC_GET_MII_ACC((lp), __v); \ } while ( __v & MII_ACC_MII_BUSY_ ); \ - SMC_SET_MII_ACC( ((phy)<<11) | ((a)<<6) | \ + SMC_SET_MII_ACC( (lp), ((phy)<<11) | ((a)<<6) | \ MII_ACC_MII_BUSY_); \ do { \ - SMC_GET_MII_ACC(__v); \ + SMC_GET_MII_ACC( (lp), __v); \ } while ( __v & MII_ACC_MII_BUSY_ ); \ - SMC_GET_MII_DATA(v); \ + SMC_GET_MII_DATA((lp), v); \ } while (0) -#define SMC_SET_MII(a,phy,v) \ +#define SMC_SET_MII(lp,a,phy,v) \ do { \ u32 __v; \ do { \ - SMC_GET_MII_ACC(__v); \ + SMC_GET_MII_ACC((lp), __v); \ } while ( __v & MII_ACC_MII_BUSY_ ); \ - SMC_SET_MII_DATA(v); \ - SMC_SET_MII_ACC( ((phy)<<11) | ((a)<<6) | \ + SMC_SET_MII_DATA((lp), v); \ + SMC_SET_MII_ACC( (lp), ((phy)<<11) | ((a)<<6) | \ MII_ACC_MII_BUSY_ | \ MII_ACC_MII_WRITE_ ); \ do { \ - SMC_GET_MII_ACC(__v); \ + SMC_GET_MII_ACC((lp), __v); \ } while ( __v & MII_ACC_MII_BUSY_ ); \ } while (0) -#define SMC_GET_PHY_BMCR(phy,x) SMC_GET_MII( MII_BMCR, phy, x ) -#define SMC_SET_PHY_BMCR(phy,x) SMC_SET_MII( MII_BMCR, phy, x ) -#define SMC_GET_PHY_BMSR(phy,x) SMC_GET_MII( MII_BMSR, phy, x ) -#define SMC_GET_PHY_ID1(phy,x) SMC_GET_MII( MII_PHYSID1, phy, x ) -#define SMC_GET_PHY_ID2(phy,x) SMC_GET_MII( MII_PHYSID2, phy, x ) -#define SMC_GET_PHY_MII_ADV(phy,x) SMC_GET_MII( MII_ADVERTISE, phy, x ) -#define SMC_SET_PHY_MII_ADV(phy,x) SMC_SET_MII( MII_ADVERTISE, phy, x ) -#define SMC_GET_PHY_MII_LPA(phy,x) SMC_GET_MII( MII_LPA, phy, x ) -#define SMC_SET_PHY_MII_LPA(phy,x) SMC_SET_MII( MII_LPA, phy, x ) -#define SMC_GET_PHY_CTRL_STS(phy,x) SMC_GET_MII( PHY_MODE_CTRL_STS, phy, x ) -#define SMC_SET_PHY_CTRL_STS(phy,x) SMC_SET_MII( PHY_MODE_CTRL_STS, phy, x ) -#define SMC_GET_PHY_INT_SRC(phy,x) SMC_GET_MII( PHY_INT_SRC, phy, x ) -#define SMC_SET_PHY_INT_SRC(phy,x) SMC_SET_MII( PHY_INT_SRC, phy, x ) -#define SMC_GET_PHY_INT_MASK(phy,x) SMC_GET_MII( PHY_INT_MASK, phy, x ) -#define SMC_SET_PHY_INT_MASK(phy,x) SMC_SET_MII( PHY_INT_MASK, phy, x ) -#define SMC_GET_PHY_SPECIAL(phy,x) SMC_GET_MII( PHY_SPECIAL, phy, x ) +#define SMC_GET_PHY_BMCR(lp,phy,x) SMC_GET_MII( (lp), MII_BMCR, phy, x ) +#define SMC_SET_PHY_BMCR(lp,phy,x) SMC_SET_MII( (lp), MII_BMCR, phy, x ) +#define SMC_GET_PHY_BMSR(lp,phy,x) SMC_GET_MII( (lp), MII_BMSR, phy, x ) +#define SMC_GET_PHY_ID1(lp,phy,x) SMC_GET_MII( (lp), MII_PHYSID1, phy, x ) +#define SMC_GET_PHY_ID2(lp,phy,x) SMC_GET_MII( (lp), MII_PHYSID2, phy, x ) +#define SMC_GET_PHY_MII_ADV(lp,phy,x) SMC_GET_MII( (lp), MII_ADVERTISE, phy, x ) +#define SMC_SET_PHY_MII_ADV(lp,phy,x) SMC_SET_MII( (lp), MII_ADVERTISE, phy, x ) +#define SMC_GET_PHY_MII_LPA(lp,phy,x) SMC_GET_MII( (lp), MII_LPA, phy, x ) +#define SMC_SET_PHY_MII_LPA(lp,phy,x) SMC_SET_MII( (lp), MII_LPA, phy, x ) +#define SMC_GET_PHY_CTRL_STS(lp,phy,x) SMC_GET_MII( (lp), PHY_MODE_CTRL_STS, phy, x ) +#define SMC_SET_PHY_CTRL_STS(lp,phy,x) SMC_SET_MII( (lp), PHY_MODE_CTRL_STS, phy, x ) +#define SMC_GET_PHY_INT_SRC(lp,phy,x) SMC_GET_MII( (lp), PHY_INT_SRC, phy, x ) +#define SMC_SET_PHY_INT_SRC(lp,phy,x) SMC_SET_MII( (lp), PHY_INT_SRC, phy, x ) +#define SMC_GET_PHY_INT_MASK(lp,phy,x) SMC_GET_MII( (lp), PHY_INT_MASK, phy, x ) +#define SMC_SET_PHY_INT_MASK(lp,phy,x) SMC_SET_MII( (lp), PHY_INT_MASK, phy, x ) +#define SMC_GET_PHY_SPECIAL(lp,phy,x) SMC_GET_MII( (lp), PHY_SPECIAL, phy, x ) /* Misc read/write macros */ #ifndef SMC_GET_MAC_ADDR -#define SMC_GET_MAC_ADDR(addr) \ +#define SMC_GET_MAC_ADDR(lp, addr) \ do { \ unsigned int __v; \ \ - SMC_GET_MAC_CSR(ADDRL, __v); \ + SMC_GET_MAC_CSR((lp), ADDRL, __v); \ addr[0] = __v; addr[1] = __v >> 8; \ addr[2] = __v >> 16; addr[3] = __v >> 24; \ - SMC_GET_MAC_CSR(ADDRH, __v); \ + SMC_GET_MAC_CSR((lp), ADDRH, __v); \ addr[4] = __v; addr[5] = __v >> 8; \ } while (0) #endif -#define SMC_SET_MAC_ADDR(addr) \ +#define SMC_SET_MAC_ADDR(lp, addr) \ do { \ - SMC_SET_MAC_CSR(ADDRL, \ + SMC_SET_MAC_CSR((lp), ADDRL, \ addr[0] | \ (addr[1] << 8) | \ (addr[2] << 16) | \ (addr[3] << 24)); \ - SMC_SET_MAC_CSR(ADDRH, addr[4]|(addr[5] << 8));\ + SMC_SET_MAC_CSR((lp), ADDRH, addr[4]|(addr[5] << 8));\ } while (0) -#define SMC_WRITE_EEPROM_CMD(cmd, addr) \ +#define SMC_WRITE_EEPROM_CMD(lp, cmd, addr) \ do { \ - while (SMC_GET_E2P_CMD() & MAC_CSR_CMD_CSR_BUSY_); \ - SMC_SET_MAC_CMD(MAC_CSR_CMD_R_NOT_W_ | a ); \ - while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_); \ + while (SMC_GET_E2P_CMD((lp)) & MAC_CSR_CMD_CSR_BUSY_); \ + SMC_SET_MAC_CMD((lp), MAC_CSR_CMD_R_NOT_W_ | a ); \ + while (SMC_GET_MAC_CMD((lp)) & MAC_CSR_CMD_CSR_BUSY_); \ } while (0) #endif /* _SMC911X_H_ */ diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index a188e33484e..f2051b209da 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 69e97a1cb1c..8606818653f 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/sunlance.c b/drivers/net/sunlance.c index 26ade68aeab..4e994f87469 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c @@ -915,15 +915,11 @@ static void build_fake_packet(struct lance_private *lp) lp->tx_new = TX_NEXT(entry); } -struct net_device *last_dev; - static int lance_open(struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); int status = 0; - last_dev = dev; - STOP_LANCE(lp); if (request_irq(dev->irq, &lance_interrupt, IRQF_SHARED, diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index 55670b5eb61..af8d2c436ef 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); diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 0604f3faf04..68e198bd538 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -154,6 +154,16 @@ config USB_NET_AX8817X This driver creates an interface named "ethX", where X depends on what other networking devices you have in use. +config USB_HSO + tristate "Option USB High Speed Mobile Devices" + depends on USB && RFKILL + default n + help + Choose this option if you have an Option HSDPA/HSUPA card. + These cards support downlink speeds of 7.2Mbps or greater. + + To compile this driver as a module, choose M here: the + module will be called hso. config USB_NET_CDCETHER tristate "CDC Ethernet support (smart devices such as cable modems)" diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index 595a539f838..24800c157f9 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_USB_CATC) += catc.o obj-$(CONFIG_USB_KAWETH) += kaweth.o obj-$(CONFIG_USB_PEGASUS) += pegasus.o obj-$(CONFIG_USB_RTL8150) += rtl8150.o +obj-$(CONFIG_USB_HSO) += hso.o obj-$(CONFIG_USB_NET_AX8817X) += asix.o obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o obj-$(CONFIG_USB_NET_DM9601) += dm9601.o diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c new file mode 100644 index 00000000000..031d07b105a --- /dev/null +++ b/drivers/net/usb/hso.c @@ -0,0 +1,2836 @@ +/****************************************************************************** + * + * Driver for Option High Speed Mobile Devices. + * + * Copyright (C) 2008 Option International + * Copyright (C) 2007 Andrew Bird (Sphere Systems Ltd) + * <ajb@spheresystems.co.uk> + * Copyright (C) 2008 Greg Kroah-Hartman <gregkh@suse.de> + * Copyright (C) 2008 Novell, Inc. + * + * 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. + * + * 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 Street, Fifth Floor, Boston, MA 02110-1301, + * USA + * + * + *****************************************************************************/ + +/****************************************************************************** + * + * Description of the device: + * + * Interface 0: Contains the IP network interface on the bulk end points. + * The multiplexed serial ports are using the interrupt and + * control endpoints. + * Interrupt contains a bitmap telling which multiplexed + * serialport needs servicing. + * + * Interface 1: Diagnostics port, uses bulk only, do not submit urbs until the + * port is opened, as this have a huge impact on the network port + * throughput. + * + * Interface 2: Standard modem interface - circuit switched interface, should + * not be used. + * + *****************************************************************************/ + +#include <linux/sched.h> +#include <linux/slab.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/netdevice.h> +#include <linux/module.h> +#include <linux/ethtool.h> +#include <linux/usb.h> +#include <linux/timer.h> +#include <linux/tty.h> +#include <linux/tty_driver.h> +#include <linux/tty_flip.h> +#include <linux/kmod.h> +#include <linux/rfkill.h> +#include <linux/ip.h> +#include <linux/uaccess.h> +#include <linux/usb/cdc.h> +#include <net/arp.h> +#include <asm/byteorder.h> + + +#define DRIVER_VERSION "1.2" +#define MOD_AUTHOR "Option Wireless" +#define MOD_DESCRIPTION "USB High Speed Option driver" +#define MOD_LICENSE "GPL" + +#define HSO_MAX_NET_DEVICES 10 +#define HSO__MAX_MTU 2048 +#define DEFAULT_MTU 1500 +#define DEFAULT_MRU 1500 + +#define CTRL_URB_RX_SIZE 1024 +#define CTRL_URB_TX_SIZE 64 + +#define BULK_URB_RX_SIZE 4096 +#define BULK_URB_TX_SIZE 8192 + +#define MUX_BULK_RX_BUF_SIZE HSO__MAX_MTU +#define MUX_BULK_TX_BUF_SIZE HSO__MAX_MTU +#define MUX_BULK_RX_BUF_COUNT 4 +#define USB_TYPE_OPTION_VENDOR 0x20 + +/* These definitions are used with the struct hso_net flags element */ +/* - use *_bit operations on it. (bit indices not values.) */ +#define HSO_NET_RUNNING 0 + +#define HSO_NET_TX_TIMEOUT (HZ*10) + +/* Serial port defines and structs. */ +#define HSO_SERIAL_FLAG_RX_SENT 0 + +#define HSO_SERIAL_MAGIC 0x48534f31 + +/* Number of ttys to handle */ +#define HSO_SERIAL_TTY_MINORS 256 + +#define MAX_RX_URBS 2 + +#define get_serial_by_tty(x) \ + (x ? (struct hso_serial *)x->driver_data : NULL) + +/*****************************************************************************/ +/* Debugging functions */ +/*****************************************************************************/ +#define D__(lvl_, fmt, arg...) \ + do { \ + printk(lvl_ "[%d:%s]: " fmt "\n", \ + __LINE__, __func__, ## arg); \ + } while (0) + +#define D_(lvl, args...) \ + do { \ + if (lvl & debug) \ + D__(KERN_INFO, args); \ + } while (0) + +#define D1(args...) D_(0x01, ##args) +#define D2(args...) D_(0x02, ##args) +#define D3(args...) D_(0x04, ##args) +#define D4(args...) D_(0x08, ##args) +#define D5(args...) D_(0x10, ##args) + +/*****************************************************************************/ +/* Enumerators */ +/*****************************************************************************/ +enum pkt_parse_state { + WAIT_IP, + WAIT_DATA, + WAIT_SYNC +}; + +/*****************************************************************************/ +/* Structs */ +/*****************************************************************************/ + +struct hso_shared_int { + struct usb_endpoint_descriptor *intr_endp; + void *shared_intr_buf; + struct urb *shared_intr_urb; + struct usb_device *usb; + int use_count; + int ref_count; + struct mutex shared_int_lock; +}; + +struct hso_net { + struct hso_device *parent; + struct net_device *net; + struct rfkill *rfkill; + + struct usb_endpoint_descriptor *in_endp; + struct usb_endpoint_descriptor *out_endp; + + struct urb *mux_bulk_rx_urb_pool[MUX_BULK_RX_BUF_COUNT]; + struct urb *mux_bulk_tx_urb; + void *mux_bulk_rx_buf_pool[MUX_BULK_RX_BUF_COUNT]; + void *mux_bulk_tx_buf; + + struct sk_buff *skb_rx_buf; + struct sk_buff *skb_tx_buf; + + enum pkt_parse_state rx_parse_state; + spinlock_t net_lock; + + unsigned short rx_buf_size; + unsigned short rx_buf_missing; + struct iphdr rx_ip_hdr; + + unsigned long flags; +}; + +struct hso_serial { + struct hso_device *parent; + int magic; + u8 minor; + + struct hso_shared_int *shared_int; + + /* rx/tx urb could be either a bulk urb or a control urb depending + on which serial port it is used on. */ + struct urb *rx_urb[MAX_RX_URBS]; + u8 num_rx_urbs; + u8 *rx_data[MAX_RX_URBS]; + u16 rx_data_length; /* should contain allocated length */ + + struct urb *tx_urb; + u8 *tx_data; + u8 *tx_buffer; + u16 tx_data_length; /* should contain allocated length */ + u16 tx_data_count; + u16 tx_buffer_count; + struct usb_ctrlrequest ctrl_req_tx; + struct usb_ctrlrequest ctrl_req_rx; + + struct usb_endpoint_descriptor *in_endp; + struct usb_endpoint_descriptor *out_endp; + + unsigned long flags; + u8 rts_state; + u8 dtr_state; + unsigned tx_urb_used:1; + + /* from usb_serial_port */ + struct tty_struct *tty; + int open_count; + spinlock_t serial_lock; + + int (*write_data) (struct hso_serial *serial); +}; + +struct hso_device { + union { + struct hso_serial *dev_serial; + struct hso_net *dev_net; + } port_data; + + u32 port_spec; + + u8 is_active; + u8 usb_gone; + struct work_struct async_get_intf; + struct work_struct async_put_intf; + + struct usb_device *usb; + struct usb_interface *interface; + + struct device *dev; + struct kref ref; + struct mutex mutex; +}; + +/* Type of interface */ +#define HSO_INTF_MASK 0xFF00 +#define HSO_INTF_MUX 0x0100 +#define HSO_INTF_BULK 0x0200 + +/* Type of port */ +#define HSO_PORT_MASK 0xFF +#define HSO_PORT_NO_PORT 0x0 +#define HSO_PORT_CONTROL 0x1 +#define HSO_PORT_APP 0x2 +#define HSO_PORT_GPS 0x3 +#define HSO_PORT_PCSC 0x4 +#define HSO_PORT_APP2 0x5 +#define HSO_PORT_GPS_CONTROL 0x6 +#define HSO_PORT_MSD 0x7 +#define HSO_PORT_VOICE 0x8 +#define HSO_PORT_DIAG2 0x9 +#define HSO_PORT_DIAG 0x10 +#define HSO_PORT_MODEM 0x11 +#define HSO_PORT_NETWORK 0x12 + +/* Additional device info */ +#define HSO_INFO_MASK 0xFF000000 +#define HSO_INFO_CRC_BUG 0x01000000 + +/*****************************************************************************/ +/* Prototypes */ +/*****************************************************************************/ +/* Serial driver functions */ +static int hso_serial_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear); +static void ctrl_callback(struct urb *urb); +static void put_rxbuf_data(struct urb *urb, struct hso_serial *serial); +static void hso_kick_transmit(struct hso_serial *serial); +/* Helper functions */ +static int hso_mux_submit_intr_urb(struct hso_shared_int *mux_int, + struct usb_device *usb, gfp_t gfp); +static void log_usb_status(int status, const char *function); +static struct usb_endpoint_descriptor *hso_get_ep(struct usb_interface *intf, + int type, int dir); +static int hso_get_mux_ports(struct usb_interface *intf, unsigned char *ports); +static void hso_free_interface(struct usb_interface *intf); +static int hso_start_serial_device(struct hso_device *hso_dev, gfp_t flags); +static int hso_stop_serial_device(struct hso_device *hso_dev); +static int hso_start_net_device(struct hso_device *hso_dev); +static void hso_free_shared_int(struct hso_shared_int *shared_int); +static int hso_stop_net_device(struct hso_device *hso_dev); +static void hso_serial_ref_free(struct kref *ref); +static void async_get_intf(struct work_struct *data); +static void async_put_intf(struct work_struct *data); +static int hso_put_activity(struct hso_device *hso_dev); +static int hso_get_activity(struct hso_device *hso_dev); + +/*****************************************************************************/ +/* Helping functions */ +/*****************************************************************************/ + +/* #define DEBUG */ + +#define dev2net(x) (x->port_data.dev_net) +#define dev2ser(x) (x->port_data.dev_serial) + +/* Debugging functions */ +#ifdef DEBUG +static void dbg_dump(int line_count, const char *func_name, unsigned char *buf, + unsigned int len) +{ + u8 i = 0; + + printk(KERN_DEBUG "[%d:%s]: len %d", line_count, func_name, len); + + for (i = 0; i < len; i++) { + if (!(i % 16)) + printk("\n 0x%03x: ", i); + printk("%02x ", (unsigned char)buf[i]); + } + printk("\n"); +} + +#define DUMP(buf_, len_) \ + dbg_dump(__LINE__, __func__, buf_, len_) + +#define DUMP1(buf_, len_) \ + do { \ + if (0x01 & debug) \ + DUMP(buf_, len_); \ + } while (0) +#else +#define DUMP(buf_, len_) +#define DUMP1(buf_, len_) +#endif + +/* module parameters */ +static int debug; +static int tty_major; +static int disable_net; + +/* driver info */ +static const char driver_name[] = "hso"; +static const char tty_filename[] = "ttyHS"; +static const char *version = __FILE__ ": " DRIVER_VERSION " " MOD_AUTHOR; +/* the usb driver itself (registered in hso_init) */ +static struct usb_driver hso_driver; +/* serial structures */ +static struct tty_driver *tty_drv; +static struct hso_device *serial_table[HSO_SERIAL_TTY_MINORS]; +static struct hso_device *network_table[HSO_MAX_NET_DEVICES]; +static spinlock_t serial_table_lock; +static struct ktermios *hso_serial_termios[HSO_SERIAL_TTY_MINORS]; +static struct ktermios *hso_serial_termios_locked[HSO_SERIAL_TTY_MINORS]; + +static const s32 default_port_spec[] = { + HSO_INTF_MUX | HSO_PORT_NETWORK, + HSO_INTF_BULK | HSO_PORT_DIAG, + HSO_INTF_BULK | HSO_PORT_MODEM, + 0 +}; + +static const s32 icon321_port_spec[] = { + HSO_INTF_MUX | HSO_PORT_NETWORK, + HSO_INTF_BULK | HSO_PORT_DIAG2, + HSO_INTF_BULK | HSO_PORT_MODEM, + HSO_INTF_BULK | HSO_PORT_DIAG, + 0 +}; + +#define default_port_device(vendor, product) \ + USB_DEVICE(vendor, product), \ + .driver_info = (kernel_ulong_t)default_port_spec + +#define icon321_port_device(vendor, product) \ + USB_DEVICE(vendor, product), \ + .driver_info = (kernel_ulong_t)icon321_port_spec + +/* list of devices we support */ +static const struct usb_device_id hso_ids[] = { + {default_port_device(0x0af0, 0x6711)}, + {default_port_device(0x0af0, 0x6731)}, + {default_port_device(0x0af0, 0x6751)}, + {default_port_device(0x0af0, 0x6771)}, + {default_port_device(0x0af0, 0x6791)}, + {default_port_device(0x0af0, 0x6811)}, + {default_port_device(0x0af0, 0x6911)}, + {default_port_device(0x0af0, 0x6951)}, + {default_port_device(0x0af0, 0x6971)}, + {default_port_device(0x0af0, 0x7011)}, + {default_port_device(0x0af0, 0x7031)}, + {default_port_device(0x0af0, 0x7051)}, + {default_port_device(0x0af0, 0x7071)}, + {default_port_device(0x0af0, 0x7111)}, + {default_port_device(0x0af0, 0x7211)}, + {default_port_device(0x0af0, 0x7251)}, + {default_port_device(0x0af0, 0x7271)}, + {default_port_device(0x0af0, 0x7311)}, + {default_port_device(0x0af0, 0xc031)}, /* Icon-Edge */ + {icon321_port_device(0x0af0, 0xd013)}, /* Module HSxPA */ + {icon321_port_device(0x0af0, 0xd031)}, /* Icon-321 */ + {default_port_device(0x0af0, 0xd033)}, /* Icon-322 */ + {USB_DEVICE(0x0af0, 0x7301)}, /* GE40x */ + {USB_DEVICE(0x0af0, 0x7361)}, /* GE40x */ + {USB_DEVICE(0x0af0, 0x7401)}, /* GI 0401 */ + {USB_DEVICE(0x0af0, 0x7501)}, /* GTM 382 */ + {USB_DEVICE(0x0af0, 0x7601)}, /* GE40x */ + {} +}; +MODULE_DEVICE_TABLE(usb, hso_ids); + +/* Sysfs attribute */ +static ssize_t hso_sysfs_show_porttype(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct hso_device *hso_dev = dev->driver_data; + char *port_name; + + if (!hso_dev) + return 0; + + switch (hso_dev->port_spec & HSO_PORT_MASK) { + case HSO_PORT_CONTROL: + port_name = "Control"; + break; + case HSO_PORT_APP: + port_name = "Application"; + break; + case HSO_PORT_APP2: + port_name = "Application2"; + break; + case HSO_PORT_GPS: + port_name = "GPS"; + break; + case HSO_PORT_GPS_CONTROL: + port_name = "GPS Control"; + break; + case HSO_PORT_PCSC: + port_name = "PCSC"; + break; + case HSO_PORT_DIAG: + port_name = "Diagnostic"; + break; + case HSO_PORT_DIAG2: + port_name = "Diagnostic2"; + break; + case HSO_PORT_MODEM: + port_name = "Modem"; + break; + case HSO_PORT_NETWORK: + port_name = "Network"; + break; + default: + port_name = "Unknown"; + break; + } + + return sprintf(buf, "%s\n", port_name); +} +static DEVICE_ATTR(hsotype, S_IRUGO, hso_sysfs_show_porttype, NULL); + +/* converts mux value to a port spec value */ +static u32 hso_mux_to_port(int mux) +{ + u32 result; + + switch (mux) { + case 0x1: + result = HSO_PORT_CONTROL; + break; + case 0x2: + result = HSO_PORT_APP; + break; + case 0x4: + result = HSO_PORT_PCSC; + break; + case 0x8: + result = HSO_PORT_GPS; + break; + case 0x10: + result = HSO_PORT_APP2; + break; + default: + result = HSO_PORT_NO_PORT; + } + return result; +} + +/* converts port spec value to a mux value */ +static u32 hso_port_to_mux(int port) +{ + u32 result; + + switch (port & HSO_PORT_MASK) { + case HSO_PORT_CONTROL: + result = 0x0; + break; + case HSO_PORT_APP: + result = 0x1; + break; + case HSO_PORT_PCSC: + result = 0x2; + break; + case HSO_PORT_GPS: + result = 0x3; + break; + case HSO_PORT_APP2: + result = 0x4; + break; + default: + result = 0x0; + } + return result; +} + +static struct hso_serial *get_serial_by_shared_int_and_type( + struct hso_shared_int *shared_int, + int mux) +{ + int i, port; + + port = hso_mux_to_port(mux); + + for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) { + if (serial_table[i] + && (dev2ser(serial_table[i])->shared_int == shared_int) + && ((serial_table[i]->port_spec & HSO_PORT_MASK) == port)) { + return dev2ser(serial_table[i]); + } + } + + return NULL; +} + +static struct hso_serial *get_serial_by_index(unsigned index) +{ + struct hso_serial *serial; + unsigned long flags; + + if (!serial_table[index]) + return NULL; + spin_lock_irqsave(&serial_table_lock, flags); + serial = dev2ser(serial_table[index]); + spin_unlock_irqrestore(&serial_table_lock, flags); + + return serial; +} + +static int get_free_serial_index(void) +{ + int index; + unsigned long flags; + + spin_lock_irqsave(&serial_table_lock, flags); + for (index = 0; index < HSO_SERIAL_TTY_MINORS; index++) { + if (serial_table[index] == NULL) { + spin_unlock_irqrestore(&serial_table_lock, flags); + return index; + } + } + spin_unlock_irqrestore(&serial_table_lock, flags); + + printk(KERN_ERR "%s: no free serial devices in table\n", __func__); + return -1; +} + +static void set_serial_by_index(unsigned index, struct hso_serial *serial) +{ + unsigned long flags; + spin_lock_irqsave(&serial_table_lock, flags); + if (serial) + serial_table[index] = serial->parent; + else + serial_table[index] = NULL; + spin_unlock_irqrestore(&serial_table_lock, flags); +} + +/* log a meaningfull explanation of an USB status */ +static void log_usb_status(int status, const char *function) +{ + char *explanation; + + switch (status) { + case -ENODEV: + explanation = "no device"; + break; + case -ENOENT: + explanation = "endpoint not enabled"; + break; + case -EPIPE: + explanation = "endpoint stalled"; + break; + case -ENOSPC: + explanation = "not enough bandwidth"; + break; + case -ESHUTDOWN: + explanation = "device disabled"; + break; + case -EHOSTUNREACH: + explanation = "device suspended"; + break; + case -EINVAL: + case -EAGAIN: + case -EFBIG: + case -EMSGSIZE: + explanation = "internal error"; + break; + default: + explanation = "unknown status"; + break; + } + D1("%s: received USB status - %s (%d)", function, explanation, status); +} + +/* Network interface functions */ + +/* called when net interface is brought up by ifconfig */ +static int hso_net_open(struct net_device *net) +{ + struct hso_net *odev = netdev_priv(net); + unsigned long flags = 0; + + if (!odev) { + dev_err(&net->dev, "No net device !\n"); + return -ENODEV; + } + + odev->skb_tx_buf = NULL; + + /* setup environment */ + spin_lock_irqsave(&odev->net_lock, flags); + odev->rx_parse_state = WAIT_IP; + odev->rx_buf_size = 0; + odev->rx_buf_missing = sizeof(struct iphdr); + spin_unlock_irqrestore(&odev->net_lock, flags); + + hso_start_net_device(odev->parent); + + /* We are up and running. */ + set_bit(HSO_NET_RUNNING, &odev->flags); + + /* Tell the kernel we are ready to start receiving from it */ + netif_start_queue(net); + + return 0; +} + +/* called when interface is brought down by ifconfig */ +static int hso_net_close(struct net_device *net) +{ + struct hso_net *odev = netdev_priv(net); + + /* we don't need the queue anymore */ + netif_stop_queue(net); + /* no longer running */ + clear_bit(HSO_NET_RUNNING, &odev->flags); + + hso_stop_net_device(odev->parent); + + /* done */ + return 0; +} + +/* USB tells is xmit done, we should start the netqueue again */ +static void write_bulk_callback(struct urb *urb) +{ + struct hso_net *odev = urb->context; + int status = urb->status; + + /* Sanity check */ + if (!odev || !test_bit(HSO_NET_RUNNING, &odev->flags)) { + dev_err(&urb->dev->dev, "%s: device not running\n", __func__); + return; + } + + /* Do we still have a valid kernel network device? */ + if (!netif_device_present(odev->net)) { + dev_err(&urb->dev->dev, "%s: net device not present\n", + __func__); + return; + } + + /* log status, but don't act on it, we don't need to resubmit anything + * anyhow */ + if (status) + log_usb_status(status, __func__); + + hso_put_activity(odev->parent); + + /* Tell the network interface we are ready for another frame */ + netif_wake_queue(odev->net); +} + +/* called by kernel when we need to transmit a packet */ +static int hso_net_start_xmit(struct sk_buff *skb, struct net_device *net) +{ + struct hso_net *odev = netdev_priv(net); + int result; + + /* Tell the kernel, "No more frames 'til we are done with this one." */ + netif_stop_queue(net); + if (hso_get_activity(odev->parent) == -EAGAIN) { + odev->skb_tx_buf = skb; + return 0; + } + + /* log if asked */ + DUMP1(skb->data, skb->len); + /* Copy it from kernel memory to OUR memory */ + memcpy(odev->mux_bulk_tx_buf, skb->data, skb->len); + D1("len: %d/%d", skb->len, MUX_BULK_TX_BUF_SIZE); + + /* Fill in the URB for shipping it out. */ + usb_fill_bulk_urb(odev->mux_bulk_tx_urb, + odev->parent->usb, + usb_sndbulkpipe(odev->parent->usb, + odev->out_endp-> + bEndpointAddress & 0x7F), + odev->mux_bulk_tx_buf, skb->len, write_bulk_callback, + odev); + + /* Deal with the Zero Length packet problem, I hope */ + odev->mux_bulk_tx_urb->transfer_flags |= URB_ZERO_PACKET; + + /* Send the URB on its merry way. */ + result = usb_submit_urb(odev->mux_bulk_tx_urb, GFP_ATOMIC); + if (result) { + dev_warn(&odev->parent->interface->dev, + "failed mux_bulk_tx_urb %d", result); + net->stats.tx_errors++; + netif_start_queue(net); + } else { + net->stats.tx_packets++; + net->stats.tx_bytes += skb->len; + /* And tell the kernel when the last transmit started. */ + net->trans_start = jiffies; + } + dev_kfree_skb(skb); + /* we're done */ + return result; +} + +static void hso_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info) +{ + struct hso_net *odev = netdev_priv(net); + + strncpy(info->driver, driver_name, ETHTOOL_BUSINFO_LEN); + strncpy(info->version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN); + usb_make_path(odev->parent->usb, info->bus_info, sizeof info->bus_info); +} + +static struct ethtool_ops ops = { + .get_drvinfo = hso_get_drvinfo, + .get_link = ethtool_op_get_link +}; + +/* called when a packet did not ack after watchdogtimeout */ +static void hso_net_tx_timeout(struct net_device *net) +{ + struct hso_net *odev = netdev_priv(net); + + if (!odev) + return; + + /* Tell syslog we are hosed. */ + dev_warn(&net->dev, "Tx timed out.\n"); + + /* Tear the waiting frame off the list */ + if (odev->mux_bulk_tx_urb + && (odev->mux_bulk_tx_urb->status == -EINPROGRESS)) + usb_unlink_urb(odev->mux_bulk_tx_urb); + + /* Update statistics */ + net->stats.tx_errors++; +} + +/* make a real packet from the received USB buffer */ +static void packetizeRx(struct hso_net *odev, unsigned char *ip_pkt, + unsigned int count, unsigned char is_eop) +{ + unsigned short temp_bytes; + unsigned short buffer_offset = 0; + unsigned short frame_len; + unsigned char *tmp_rx_buf; + + /* log if needed */ + D1("Rx %d bytes", count); + DUMP(ip_pkt, min(128, (int)count)); + + while (count) { + switch (odev->rx_parse_state) { + case WAIT_IP: + /* waiting for IP header. */ + /* wanted bytes - size of ip header */ + temp_bytes = + (count < + odev->rx_buf_missing) ? count : odev-> + rx_buf_missing; + + memcpy(((unsigned char *)(&odev->rx_ip_hdr)) + + odev->rx_buf_size, ip_pkt + buffer_offset, + temp_bytes); + + odev->rx_buf_size += temp_bytes; + buffer_offset += temp_bytes; + odev->rx_buf_missing -= temp_bytes; + count -= temp_bytes; + + if (!odev->rx_buf_missing) { + /* header is complete allocate an sk_buffer and + * continue to WAIT_DATA */ + frame_len = ntohs(odev->rx_ip_hdr.tot_len); + + if ((frame_len > DEFAULT_MRU) || + (frame_len < sizeof(struct iphdr))) { + dev_err(&odev->net->dev, + "Invalid frame (%d) length\n", + frame_len); + odev->rx_parse_state = WAIT_SYNC; + continue; + } + /* Allocate an sk_buff */ + odev->skb_rx_buf = dev_alloc_skb(frame_len); + if (!odev->skb_rx_buf) { + /* We got no receive buffer. */ + D1("could not allocate memory"); + odev->rx_parse_state = WAIT_SYNC; + return; + } + /* Here's where it came from */ + odev->skb_rx_buf->dev = odev->net; + + /* Copy what we got so far. make room for iphdr + * after tail. */ + tmp_rx_buf = + skb_put(odev->skb_rx_buf, + sizeof(struct iphdr)); + memcpy(tmp_rx_buf, (char *)&(odev->rx_ip_hdr), + sizeof(struct iphdr)); + + /* ETH_HLEN */ + odev->rx_buf_size = sizeof(struct iphdr); + + /* Filip actually use .tot_len */ + odev->rx_buf_missing = + frame_len - sizeof(struct iphdr); + odev->rx_parse_state = WAIT_DATA; + } + break; + + case WAIT_DATA: + temp_bytes = (count < odev->rx_buf_missing) + ? count : odev->rx_buf_missing; + + /* Copy the rest of the bytes that are left in the + * buffer into the waiting sk_buf. */ + /* Make room for temp_bytes after tail. */ + tmp_rx_buf = skb_put(odev->skb_rx_buf, temp_bytes); + memcpy(tmp_rx_buf, ip_pkt + buffer_offset, temp_bytes); + + odev->rx_buf_missing -= temp_bytes; + count -= temp_bytes; + buffer_offset += temp_bytes; + odev->rx_buf_size += temp_bytes; + if (!odev->rx_buf_missing) { + /* Packet is complete. Inject into stack. */ + /* We have IP packet here */ + odev->skb_rx_buf->protocol = + __constant_htons(ETH_P_IP); + /* don't check it */ + odev->skb_rx_buf->ip_summed = + CHECKSUM_UNNECESSARY; + + skb_reset_mac_header(odev->skb_rx_buf); + + /* Ship it off to the kernel */ + netif_rx(odev->skb_rx_buf); + /* No longer our buffer. */ + odev->skb_rx_buf = NULL; + + /* update out statistics */ + odev->net->stats.rx_packets++; + + odev->net->stats.rx_bytes += odev->rx_buf_size; + + odev->rx_buf_size = 0; + odev->rx_buf_missing = sizeof(struct iphdr); + odev->rx_parse_state = WAIT_IP; + } + break; + + case WAIT_SYNC: + D1(" W_S"); + count = 0; + break; + default: + D1(" "); + count--; + break; + } + } + + /* Recovery mechanism for WAIT_SYNC state. */ + if (is_eop) { + if (odev->rx_parse_state == WAIT_SYNC) { + odev->rx_parse_state = WAIT_IP; + odev->rx_buf_size = 0; + odev->rx_buf_missing = sizeof(struct iphdr); + } + } +} + +/* Moving data from usb to kernel (in interrupt state) */ +static void read_bulk_callback(struct urb *urb) +{ + struct hso_net *odev = urb->context; + struct net_device *net; + int result; + int status = urb->status; + + /* is al ok? (Filip: Who's Al ?) */ + if (status) { + log_usb_status(status, __func__); + return; + } + + /* Sanity check */ + if (!odev || !test_bit(HSO_NET_RUNNING, &odev->flags)) { + D1("BULK IN callback but driver is not active!"); + return; + } + usb_mark_last_busy(urb->dev); + + net = odev->net; + + if (!netif_device_present(net)) { + /* Somebody killed our network interface... */ + return; + } + + if (odev->parent->port_spec & HSO_INFO_CRC_BUG) { + u32 rest; + u8 crc_check[4] = { 0xDE, 0xAD, 0xBE, 0xEF }; + rest = urb->actual_length % odev->in_endp->wMaxPacketSize; + if (((rest == 5) || (rest == 6)) + && !memcmp(((u8 *) urb->transfer_buffer) + + urb->actual_length - 4, crc_check, 4)) { + urb->actual_length -= 4; + } + } + + /* do we even have a packet? */ + if (urb->actual_length) { + /* Handle the IP stream, add header and push it onto network + * stack if the packet is complete. */ + spin_lock(&odev->net_lock); + packetizeRx(odev, urb->transfer_buffer, urb->actual_length, + (urb->transfer_buffer_length > + urb->actual_length) ? 1 : 0); + spin_unlock(&odev->net_lock); + } + + /* We are done with this URB, resubmit it. Prep the USB to wait for + * another frame. Reuse same as received. */ + usb_fill_bulk_urb(urb, + odev->parent->usb, + usb_rcvbulkpipe(odev->parent->usb, + odev->in_endp-> + bEndpointAddress & 0x7F), + urb->transfer_buffer, MUX_BULK_RX_BUF_SIZE, + read_bulk_callback, odev); + + /* Give this to the USB subsystem so it can tell us when more data + * arrives. */ + result = usb_submit_urb(urb, GFP_ATOMIC); + if (result) + dev_warn(&odev->parent->interface->dev, + "%s failed submit mux_bulk_rx_urb %d", __func__, + result); +} + +/* Serial driver functions */ + +static void _hso_serial_set_termios(struct tty_struct *tty, + struct ktermios *old) +{ + struct hso_serial *serial = get_serial_by_tty(tty); + struct ktermios *termios; + + if ((!tty) || (!tty->termios) || (!serial)) { + printk(KERN_ERR "%s: no tty structures", __func__); + return; + } + + D4("port %d", serial->minor); + + /* + * The default requirements for this device are: + */ + termios = tty->termios; + termios->c_iflag &= + ~(IGNBRK /* disable ignore break */ + | BRKINT /* disable break causes interrupt */ + | PARMRK /* disable mark parity errors */ + | ISTRIP /* disable clear high bit of input characters */ + | INLCR /* disable translate NL to CR */ + | IGNCR /* disable ignore CR */ + | ICRNL /* disable translate CR to NL */ + | IXON); /* disable enable XON/XOFF flow control */ + + /* disable postprocess output characters */ + termios->c_oflag &= ~OPOST; + + termios->c_lflag &= + ~(ECHO /* disable echo input characters */ + | ECHONL /* disable echo new line */ + | ICANON /* disable erase, kill, werase, and rprnt + special characters */ + | ISIG /* disable interrupt, quit, and suspend special + characters */ + | IEXTEN); /* disable non-POSIX special characters */ + + termios->c_cflag &= + ~(CSIZE /* no size */ + | PARENB /* disable parity bit */ + | CBAUD /* clear current baud rate */ + | CBAUDEX); /* clear current buad rate */ + + termios->c_cflag |= CS8; /* character size 8 bits */ + + /* baud rate 115200 */ + tty_encode_baud_rate(serial->tty, 115200, 115200); + + /* + * Force low_latency on; otherwise the pushes are scheduled; + * this is bad as it opens up the possibility of dropping bytes + * on the floor. We don't want to drop bytes on the floor. :) + */ + serial->tty->low_latency = 1; + return; +} + +/* open the requested serial port */ +static int hso_serial_open(struct tty_struct *tty, struct file *filp) +{ + struct hso_serial *serial = get_serial_by_index(tty->index); + int result; + + /* sanity check */ + if (serial == NULL || serial->magic != HSO_SERIAL_MAGIC) { + tty->driver_data = NULL; + D1("Failed to open port"); + return -ENODEV; + } + + mutex_lock(&serial->parent->mutex); + result = usb_autopm_get_interface(serial->parent->interface); + if (result < 0) + goto err_out; + + D1("Opening %d", serial->minor); + kref_get(&serial->parent->ref); + + /* setup */ + tty->driver_data = serial; + serial->tty = tty; + + /* check for port allready opened, if not set the termios */ + serial->open_count++; + if (serial->open_count == 1) { + tty->low_latency = 1; + serial->flags = 0; + /* Force default termio settings */ + _hso_serial_set_termios(tty, NULL); + result = hso_start_serial_device(serial->parent, GFP_KERNEL); + if (result) { + hso_stop_serial_device(serial->parent); + serial->open_count--; + kref_put(&serial->parent->ref, hso_serial_ref_free); + } + } else { + D1("Port was already open"); + } + + usb_autopm_put_interface(serial->parent->interface); + + /* done */ + if (result) + hso_serial_tiocmset(tty, NULL, TIOCM_RTS | TIOCM_DTR, 0); +err_out: + mutex_unlock(&serial->parent->mutex); + return result; +} + +/* close the requested serial port */ +static void hso_serial_close(struct tty_struct *tty, struct file *filp) +{ + struct hso_serial *serial = tty->driver_data; + u8 usb_gone; + + D1("Closing serial port"); + + mutex_lock(&serial->parent->mutex); + usb_gone = serial->parent->usb_gone; + + if (!usb_gone) + usb_autopm_get_interface(serial->parent->interface); + + /* reset the rts and dtr */ + /* do the actual close */ + serial->open_count--; + if (serial->open_count <= 0) { + kref_put(&serial->parent->ref, hso_serial_ref_free); + serial->open_count = 0; + if (serial->tty) { + serial->tty->driver_data = NULL; + serial->tty = NULL; + } + if (!usb_gone) + hso_stop_serial_device(serial->parent); + } + if (!usb_gone) + usb_autopm_put_interface(serial->parent->interface); + mutex_unlock(&serial->parent->mutex); +} + +/* close the requested serial port */ +static int hso_serial_write(struct tty_struct *tty, const unsigned char *buf, + int count) +{ + struct hso_serial *serial = get_serial_by_tty(tty); + int space, tx_bytes; + unsigned long flags; + + /* sanity check */ + if (serial == NULL) { + printk(KERN_ERR "%s: serial is NULL\n", __func__); + return -ENODEV; + } + + spin_lock_irqsave(&serial->serial_lock, flags); + + space = serial->tx_data_length - serial->tx_buffer_count; + tx_bytes = (count < space) ? count : space; + + if (!tx_bytes) + goto out; + + memcpy(serial->tx_buffer + serial->tx_buffer_count, buf, tx_bytes); + serial->tx_buffer_count += tx_bytes; + +out: + spin_unlock_irqrestore(&serial->serial_lock, flags); + + hso_kick_transmit(serial); + /* done */ + return tx_bytes; +} + +/* how much room is there for writing */ +static int hso_serial_write_room(struct tty_struct *tty) +{ + struct hso_serial *serial = get_serial_by_tty(tty); + int room; + unsigned long flags; + + spin_lock_irqsave(&serial->serial_lock, flags); + room = serial->tx_data_length - serial->tx_buffer_count; + spin_unlock_irqrestore(&serial->serial_lock, flags); + + /* return free room */ + return room; +} + +/* setup the term */ +static void hso_serial_set_termios(struct tty_struct *tty, struct ktermios *old) +{ + struct hso_serial *serial = get_serial_by_tty(tty); + unsigned long flags; + + if (old) + D5("Termios called with: cflags new[%d] - old[%d]", + tty->termios->c_cflag, old->c_cflag); + + /* the actual setup */ + spin_lock_irqsave(&serial->serial_lock, flags); + if (serial->open_count) + _hso_serial_set_termios(tty, old); + else + tty->termios = old; + spin_unlock_irqrestore(&serial->serial_lock, flags); + + /* done */ + return; +} + +/* how many characters in the buffer */ +static int hso_serial_chars_in_buffer(struct tty_struct *tty) +{ + struct hso_serial *serial = get_serial_by_tty(tty); + int chars; + unsigned long flags; + + /* sanity check */ + if (serial == NULL) + return 0; + + spin_lock_irqsave(&serial->serial_lock, flags); + chars = serial->tx_buffer_count; + spin_unlock_irqrestore(&serial->serial_lock, flags); + + return chars; +} + +static int hso_serial_tiocmget(struct tty_struct *tty, struct file *file) +{ + unsigned int value; + struct hso_serial *serial = get_serial_by_tty(tty); + unsigned long flags; + + /* sanity check */ + if (!serial) { + D1("no tty structures"); + return -EINVAL; + } + + spin_lock_irqsave(&serial->serial_lock, flags); + value = ((serial->rts_state) ? TIOCM_RTS : 0) | + ((serial->dtr_state) ? TIOCM_DTR : 0); + spin_unlock_irqrestore(&serial->serial_lock, flags); + + return value; +} + +static int hso_serial_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) +{ + int val = 0; + unsigned long flags; + int if_num; + struct hso_serial *serial = get_serial_by_tty(tty); + + /* sanity check */ + if (!serial) { + D1("no tty structures"); + return -EINVAL; + } + if_num = serial->parent->interface->altsetting->desc.bInterfaceNumber; + + spin_lock_irqsave(&serial->serial_lock, flags); + if (set & TIOCM_RTS) + serial->rts_state = 1; + if (set & TIOCM_DTR) + serial->dtr_state = 1; + + if (clear & TIOCM_RTS) + serial->rts_state = 0; + if (clear & TIOCM_DTR) + serial->dtr_state = 0; + + if (serial->dtr_state) + val |= 0x01; + if (serial->rts_state) + val |= 0x02; + + spin_unlock_irqrestore(&serial->serial_lock, flags); + + return usb_control_msg(serial->parent->usb, + usb_rcvctrlpipe(serial->parent->usb, 0), 0x22, + 0x21, val, if_num, NULL, 0, + USB_CTRL_SET_TIMEOUT); +} + +/* starts a transmit */ +static void hso_kick_transmit(struct hso_serial *serial) +{ + u8 *temp; + unsigned long flags; + int res; + + spin_lock_irqsave(&serial->serial_lock, flags); + if (!serial->tx_buffer_count) + goto out; + + if (serial->tx_urb_used) + goto out; + + /* Wakeup USB interface if necessary */ + if (hso_get_activity(serial->parent) == -EAGAIN) + goto out; + + /* Switch pointers around to avoid memcpy */ + temp = serial->tx_buffer; + serial->tx_buffer = serial->tx_data; + serial->tx_data = temp; + serial->tx_data_count = serial->tx_buffer_count; + serial->tx_buffer_count = 0; + + /* If temp is set, it means we switched buffers */ + if (temp && serial->write_data) { + res = serial->write_data(serial); + if (res >= 0) + serial->tx_urb_used = 1; + } +out: + spin_unlock_irqrestore(&serial->serial_lock, flags); +} + +/* make a request (for reading and writing data to muxed serial port) */ +static int mux_device_request(struct hso_serial *serial, u8 type, u16 port, + struct urb *ctrl_urb, + struct usb_ctrlrequest *ctrl_req, + u8 *ctrl_urb_data, u32 size) +{ + int result; + int pipe; + + /* Sanity check */ + if (!serial || !ctrl_urb || !ctrl_req) { + printk(KERN_ERR "%s: Wrong arguments\n", __func__); + return -EINVAL; + } + + /* initialize */ + ctrl_req->wValue = 0; + ctrl_req->wIndex = hso_port_to_mux(port); + ctrl_req->wLength = size; + + if (type == USB_CDC_GET_ENCAPSULATED_RESPONSE) { + /* Reading command */ + ctrl_req->bRequestType = USB_DIR_IN | + USB_TYPE_OPTION_VENDOR | + USB_RECIP_INTERFACE; + ctrl_req->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE; + pipe = usb_rcvctrlpipe(serial->parent->usb, 0); + } else { + /* Writing command */ + ctrl_req->bRequestType = USB_DIR_OUT | + USB_TYPE_OPTION_VENDOR | + USB_RECIP_INTERFACE; + ctrl_req->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND; + pipe = usb_sndctrlpipe(serial->parent->usb, 0); + } + /* syslog */ + D2("%s command (%02x) len: %d, port: %d", + type == USB_CDC_GET_ENCAPSULATED_RESPONSE ? "Read" : "Write", + ctrl_req->bRequestType, ctrl_req->wLength, port); + + /* Load ctrl urb */ + ctrl_urb->transfer_flags = 0; + usb_fill_control_urb(ctrl_urb, + serial->parent->usb, + pipe, + (u8 *) ctrl_req, + ctrl_urb_data, size, ctrl_callback, serial); + /* Send it on merry way */ + result = usb_submit_urb(ctrl_urb, GFP_ATOMIC); + if (result) { + dev_err(&ctrl_urb->dev->dev, + "%s failed submit ctrl_urb %d type %d", __func__, + result, type); + return result; + } + + /* done */ + return size; +} + +/* called by intr_callback when read occurs */ +static int hso_mux_serial_read(struct hso_serial *serial) +{ + if (!serial) + return -EINVAL; + + /* clean data */ + memset(serial->rx_data[0], 0, CTRL_URB_RX_SIZE); + /* make the request */ + + if (serial->num_rx_urbs != 1) { + dev_err(&serial->parent->interface->dev, + "ERROR: mux'd reads with multiple buffers " + "not possible\n"); + return 0; + } + return mux_device_request(serial, + USB_CDC_GET_ENCAPSULATED_RESPONSE, + serial->parent->port_spec & HSO_PORT_MASK, + serial->rx_urb[0], + &serial->ctrl_req_rx, + serial->rx_data[0], serial->rx_data_length); +} + +/* used for muxed serial port callback (muxed serial read) */ +static void intr_callback(struct urb *urb) +{ + struct hso_shared_int *shared_int = urb->context; + struct hso_serial *serial; + unsigned char *port_req; + int status = urb->status; + int i; + + usb_mark_last_busy(urb->dev); + + /* sanity check */ + if (!shared_int) + return; + + /* status check */ + if (status) { + log_usb_status(status, __func__); + return; + } + D4("\n--- Got intr callback 0x%02X ---", status); + + /* what request? */ + port_req = urb->transfer_buffer; + D4(" port_req = 0x%.2X\n", *port_req); + /* loop over all muxed ports to find the one sending this */ + for (i = 0; i < 8; i++) { + /* max 8 channels on MUX */ + if (*port_req & (1 << i)) { + serial = get_serial_by_shared_int_and_type(shared_int, + (1 << i)); + if (serial != NULL) { + D1("Pending read interrupt on port %d\n", i); + if (!test_and_set_bit(HSO_SERIAL_FLAG_RX_SENT, + &serial->flags)) { + /* Setup and send a ctrl req read on + * port i */ + hso_mux_serial_read(serial); + } else { + D1("Already pending a read on " + "port %d\n", i); + } + } + } + } + /* Resubmit interrupt urb */ + hso_mux_submit_intr_urb(shared_int, urb->dev, GFP_ATOMIC); +} + +/* called for writing to muxed serial port */ +static int hso_mux_serial_write_data(struct hso_serial *serial) +{ + if (NULL == serial) + return -EINVAL; + + return mux_device_request(serial, + USB_CDC_SEND_ENCAPSULATED_COMMAND, + serial->parent->port_spec & HSO_PORT_MASK, + serial->tx_urb, + &serial->ctrl_req_tx, + serial->tx_data, serial->tx_data_count); +} + +/* write callback for Diag and CS port */ +static void hso_std_serial_write_bulk_callback(struct urb *urb) +{ + struct hso_serial *serial = urb->context; + int status = urb->status; + + /* sanity check */ + if (!serial) { + D1("serial == NULL"); + return; + } + + spin_lock(&serial->serial_lock); + serial->tx_urb_used = 0; + spin_unlock(&serial->serial_lock); + if (status) { + log_usb_status(status, __func__); + return; + } + hso_put_activity(serial->parent); + tty_wakeup(serial->tty); + hso_kick_transmit(serial); + + D1(" "); + return; +} + +/* called for writing diag or CS serial port */ +static int hso_std_serial_write_data(struct hso_serial *serial) +{ + int count = serial->tx_data_count; + int result; + + usb_fill_bulk_urb(serial->tx_urb, + serial->parent->usb, + usb_sndbulkpipe(serial->parent->usb, + serial->out_endp-> + bEndpointAddress & 0x7F), + serial->tx_data, serial->tx_data_count, + hso_std_serial_write_bulk_callback, serial); + + result = usb_submit_urb(serial->tx_urb, GFP_ATOMIC); + if (result) { + dev_warn(&serial->parent->usb->dev, + "Failed to submit urb - res %d\n", result); + return result; + } + + return count; +} + +/* callback after read or write on muxed serial port */ +static void ctrl_callback(struct urb *urb) +{ + struct hso_serial *serial = urb->context; + struct usb_ctrlrequest *req; + int status = urb->status; + + /* sanity check */ + if (!serial) + return; + + spin_lock(&serial->serial_lock); + serial->tx_urb_used = 0; + spin_unlock(&serial->serial_lock); + if (status) { + log_usb_status(status, __func__); + return; + } + + /* what request? */ + req = (struct usb_ctrlrequest *)(urb->setup_packet); + D4("\n--- Got muxed ctrl callback 0x%02X ---", status); + D4("Actual length of urb = %d\n", urb->actual_length); + DUMP1(urb->transfer_buffer, urb->actual_length); + + if (req->bRequestType == + (USB_DIR_IN | USB_TYPE_OPTION_VENDOR | USB_RECIP_INTERFACE)) { + /* response to a read command */ + if (serial->open_count > 0) { + /* handle RX data the normal way */ + put_rxbuf_data(urb, serial); + } + + /* Re issue a read as long as we receive data. */ + if (urb->actual_length != 0) + hso_mux_serial_read(serial); + else + clear_bit(HSO_SERIAL_FLAG_RX_SENT, &serial->flags); + } else { + hso_put_activity(serial->parent); + tty_wakeup(serial->tty); + /* response to a write command */ + hso_kick_transmit(serial); + } +} + +/* handle RX data for serial port */ +static void put_rxbuf_data(struct urb *urb, struct hso_serial *serial) +{ + struct tty_struct *tty = serial->tty; + + /* Sanity check */ + if (urb == NULL || serial == NULL) { + D1("serial = NULL"); + return; + } + + /* Push data to tty */ + if (tty && urb->actual_length) { + D1("data to push to tty"); + tty_insert_flip_string(tty, urb->transfer_buffer, + urb->actual_length); + tty_flip_buffer_push(tty); + } +} + +/* read callback for Diag and CS port */ +static void hso_std_serial_read_bulk_callback(struct urb *urb) +{ + struct hso_serial *serial = urb->context; + int result; + int status = urb->status; + + /* sanity check */ + if (!serial) { + D1("serial == NULL"); + return; + } else if (status) { + log_usb_status(status, __func__); + return; + } + + D4("\n--- Got serial_read_bulk callback %02x ---", status); + D1("Actual length = %d\n", urb->actual_length); + DUMP1(urb->transfer_buffer, urb->actual_length); + + /* Anyone listening? */ + if (serial->open_count == 0) + return; + + if (status == 0) { + if (serial->parent->port_spec & HSO_INFO_CRC_BUG) { + u32 rest; + u8 crc_check[4] = { 0xDE, 0xAD, 0xBE, 0xEF }; + rest = + urb->actual_length % + serial->in_endp->wMaxPacketSize; + if (((rest == 5) || (rest == 6)) + && !memcmp(((u8 *) urb->transfer_buffer) + + urb->actual_length - 4, crc_check, 4)) { + urb->actual_length -= 4; + } + } + /* Valid data, handle RX data */ + put_rxbuf_data(urb, serial); + } else if (status == -ENOENT || status == -ECONNRESET) { + /* Unlinked - check for throttled port. */ + D2("Port %d, successfully unlinked urb", serial->minor); + } else { + D2("Port %d, status = %d for read urb", serial->minor, status); + return; + } + + usb_mark_last_busy(urb->dev); + + /* We are done with this URB, resubmit it. Prep the USB to wait for + * another frame */ + usb_fill_bulk_urb(urb, serial->parent->usb, + usb_rcvbulkpipe(serial->parent->usb, + serial->in_endp-> + bEndpointAddress & 0x7F), + urb->transfer_buffer, serial->rx_data_length, + hso_std_serial_read_bulk_callback, serial); + /* Give this to the USB subsystem so it can tell us when more data + * arrives. */ + result = usb_submit_urb(urb, GFP_ATOMIC); + if (result) { + dev_err(&urb->dev->dev, "%s failed submit serial rx_urb %d", + __func__, result); + } +} + +/* Base driver functions */ + +static void hso_log_port(struct hso_device *hso_dev) +{ + char *port_type; + char port_dev[20]; + + switch (hso_dev->port_spec & HSO_PORT_MASK) { + case HSO_PORT_CONTROL: + port_type = "Control"; + break; + case HSO_PORT_APP: + port_type = "Application"; + break; + case HSO_PORT_GPS: + port_type = "GPS"; + break; + case HSO_PORT_GPS_CONTROL: + port_type = "GPS control"; + break; + case HSO_PORT_APP2: + port_type = "Application2"; + break; + case HSO_PORT_PCSC: + port_type = "PCSC"; + break; + case HSO_PORT_DIAG: + port_type = "Diagnostic"; + break; + case HSO_PORT_DIAG2: + port_type = "Diagnostic2"; + break; + case HSO_PORT_MODEM: + port_type = "Modem"; + break; + case HSO_PORT_NETWORK: + port_type = "Network"; + break; + default: + port_type = "Unknown"; + break; + } + if ((hso_dev->port_spec & HSO_PORT_MASK) == HSO_PORT_NETWORK) { + sprintf(port_dev, "%s", dev2net(hso_dev)->net->name); + } else + sprintf(port_dev, "/dev/%s%d", tty_filename, + dev2ser(hso_dev)->minor); + + dev_dbg(&hso_dev->interface->dev, "HSO: Found %s port %s\n", + port_type, port_dev); +} + +static int hso_start_net_device(struct hso_device *hso_dev) +{ + int i, result = 0; + struct hso_net *hso_net = dev2net(hso_dev); + + if (!hso_net) + return -ENODEV; + + /* send URBs for all read buffers */ + for (i = 0; i < MUX_BULK_RX_BUF_COUNT; i++) { + + /* Prep a receive URB */ + usb_fill_bulk_urb(hso_net->mux_bulk_rx_urb_pool[i], + hso_dev->usb, + usb_rcvbulkpipe(hso_dev->usb, + hso_net->in_endp-> + bEndpointAddress & 0x7F), + hso_net->mux_bulk_rx_buf_pool[i], + MUX_BULK_RX_BUF_SIZE, read_bulk_callback, + hso_net); + + /* Put it out there so the device can send us stuff */ + result = usb_submit_urb(hso_net->mux_bulk_rx_urb_pool[i], + GFP_NOIO); + if (result) + dev_warn(&hso_dev->usb->dev, + "%s failed mux_bulk_rx_urb[%d] %d\n", __func__, + i, result); + } + + return result; +} + +static int hso_stop_net_device(struct hso_device *hso_dev) +{ + int i; + struct hso_net *hso_net = dev2net(hso_dev); + + if (!hso_net) + return -ENODEV; + + for (i = 0; i < MUX_BULK_RX_BUF_COUNT; i++) { + if (hso_net->mux_bulk_rx_urb_pool[i]) + usb_kill_urb(hso_net->mux_bulk_rx_urb_pool[i]); + + } + if (hso_net->mux_bulk_tx_urb) + usb_kill_urb(hso_net->mux_bulk_tx_urb); + + return 0; +} + +static int hso_start_serial_device(struct hso_device *hso_dev, gfp_t flags) +{ + int i, result = 0; + struct hso_serial *serial = dev2ser(hso_dev); + + if (!serial) + return -ENODEV; + + /* If it is not the MUX port fill in and submit a bulk urb (already + * allocated in hso_serial_start) */ + if (!(serial->parent->port_spec & HSO_INTF_MUX)) { + for (i = 0; i < serial->num_rx_urbs; i++) { + usb_fill_bulk_urb(serial->rx_urb[i], + serial->parent->usb, + usb_rcvbulkpipe(serial->parent->usb, + serial->in_endp-> + bEndpointAddress & + 0x7F), + serial->rx_data[i], + serial->rx_data_length, + hso_std_serial_read_bulk_callback, + serial); + result = usb_submit_urb(serial->rx_urb[i], flags); + if (result) { + dev_warn(&serial->parent->usb->dev, + "Failed to submit urb - res %d\n", + result); + break; + } + } + } else { + mutex_lock(&serial->shared_int->shared_int_lock); + if (!serial->shared_int->use_count) { + result = + hso_mux_submit_intr_urb(serial->shared_int, + hso_dev->usb, flags); + } + serial->shared_int->use_count++; + mutex_unlock(&serial->shared_int->shared_int_lock); + } + + return result; +} + +static int hso_stop_serial_device(struct hso_device *hso_dev) +{ + int i; + struct hso_serial *serial = dev2ser(hso_dev); + + if (!serial) + return -ENODEV; + + for (i = 0; i < serial->num_rx_urbs; i++) { + if (serial->rx_urb[i]) + usb_kill_urb(serial->rx_urb[i]); + } + + if (serial->tx_urb) + usb_kill_urb(serial->tx_urb); + + if (serial->shared_int) { + mutex_lock(&serial->shared_int->shared_int_lock); + if (serial->shared_int->use_count && + (--serial->shared_int->use_count == 0)) { + struct urb *urb; + + urb = serial->shared_int->shared_intr_urb; + if (urb) + usb_kill_urb(urb); + } + mutex_unlock(&serial->shared_int->shared_int_lock); + } + + return 0; +} + +static void hso_serial_common_free(struct hso_serial *serial) +{ + int i; + + if (serial->parent->dev) + device_remove_file(serial->parent->dev, &dev_attr_hsotype); + + tty_unregister_device(tty_drv, serial->minor); + + for (i = 0; i < serial->num_rx_urbs; i++) { + /* unlink and free RX URB */ + usb_free_urb(serial->rx_urb[i]); + /* free the RX buffer */ + kfree(serial->rx_data[i]); + } + + /* unlink and free TX URB */ + usb_free_urb(serial->tx_urb); + kfree(serial->tx_data); +} + +static int hso_serial_common_create(struct hso_serial *serial, int num_urbs, + int rx_size, int tx_size) +{ + struct device *dev; + int minor; + int i; + + minor = get_free_serial_index(); + if (minor < 0) + goto exit; + + /* register our minor number */ + serial->parent->dev = tty_register_device(tty_drv, minor, + &serial->parent->interface->dev); + dev = serial->parent->dev; + dev->driver_data = serial->parent; + i = device_create_file(dev, &dev_attr_hsotype); + + /* fill in specific data for later use */ + serial->minor = minor; + serial->magic = HSO_SERIAL_MAGIC; + spin_lock_init(&serial->serial_lock); + serial->num_rx_urbs = num_urbs; + + /* RX, allocate urb and initialize */ + + /* prepare our RX buffer */ + serial->rx_data_length = rx_size; + for (i = 0; i < serial->num_rx_urbs; i++) { + serial->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL); + if (!serial->rx_urb[i]) { + dev_err(dev, "Could not allocate urb?\n"); + goto exit; + } + serial->rx_urb[i]->transfer_buffer = NULL; + serial->rx_urb[i]->transfer_buffer_length = 0; + serial->rx_data[i] = kzalloc(serial->rx_data_length, + GFP_KERNEL); + if (!serial->rx_data[i]) { + dev_err(dev, "%s - Out of memory\n", __func__); + goto exit; + } + } + + /* TX, allocate urb and initialize */ + serial->tx_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!serial->tx_urb) { + dev_err(dev, "Could not allocate urb?\n"); + goto exit; + } + serial->tx_urb->transfer_buffer = NULL; + serial->tx_urb->transfer_buffer_length = 0; + /* prepare our TX buffer */ + serial->tx_data_count = 0; + serial->tx_buffer_count = 0; + serial->tx_data_length = tx_size; + serial->tx_data = kzalloc(serial->tx_data_length, GFP_KERNEL); + if (!serial->tx_data) { + dev_err(dev, "%s - Out of memory", __func__); + goto exit; + } + serial->tx_buffer = kzalloc(serial->tx_data_length, GFP_KERNEL); + if (!serial->tx_buffer) { + dev_err(dev, "%s - Out of memory", __func__); + goto exit; + } + + return 0; +exit: + hso_serial_common_free(serial); + return -1; +} + +/* Frees a general hso device */ +static void hso_free_device(struct hso_device *hso_dev) +{ + kfree(hso_dev); +} + +/* Creates a general hso device */ +static struct hso_device *hso_create_device(struct usb_interface *intf, + int port_spec) +{ + struct hso_device *hso_dev; + + hso_dev = kzalloc(sizeof(*hso_dev), GFP_ATOMIC); + if (!hso_dev) + return NULL; + + hso_dev->port_spec = port_spec; + hso_dev->usb = interface_to_usbdev(intf); + hso_dev->interface = intf; + kref_init(&hso_dev->ref); + mutex_init(&hso_dev->mutex); + + INIT_WORK(&hso_dev->async_get_intf, async_get_intf); + INIT_WORK(&hso_dev->async_put_intf, async_put_intf); + + return hso_dev; +} + +/* Removes a network device in the network device table */ +static int remove_net_device(struct hso_device *hso_dev) +{ + int i; + + for (i = 0; i < HSO_MAX_NET_DEVICES; i++) { + if (network_table[i] == hso_dev) { + network_table[i] = NULL; + break; + } + } + if (i == HSO_MAX_NET_DEVICES) + return -1; + return 0; +} + +/* Frees our network device */ +static void hso_free_net_device(struct hso_device *hso_dev) +{ + int i; + struct hso_net *hso_net = dev2net(hso_dev); + + if (!hso_net) + return; + + /* start freeing */ + for (i = 0; i < MUX_BULK_RX_BUF_COUNT; i++) { + usb_free_urb(hso_net->mux_bulk_rx_urb_pool[i]); + kfree(hso_net->mux_bulk_rx_buf_pool[i]); + } + usb_free_urb(hso_net->mux_bulk_tx_urb); + kfree(hso_net->mux_bulk_tx_buf); + + remove_net_device(hso_net->parent); + + if (hso_net->net) { + unregister_netdev(hso_net->net); + free_netdev(hso_net->net); + } + + hso_free_device(hso_dev); +} + +/* initialize the network interface */ +static void hso_net_init(struct net_device *net) +{ + struct hso_net *hso_net = netdev_priv(net); + + D1("sizeof hso_net is %d", (int)sizeof(*hso_net)); + + /* fill in the other fields */ + net->open = hso_net_open; + net->stop = hso_net_close; + net->hard_start_xmit = hso_net_start_xmit; + net->tx_timeout = hso_net_tx_timeout; + net->watchdog_timeo = HSO_NET_TX_TIMEOUT; + net->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; + net->type = ARPHRD_NONE; + net->mtu = DEFAULT_MTU - 14; + net->tx_queue_len = 10; + SET_ETHTOOL_OPS(net, &ops); + + /* and initialize the semaphore */ + spin_lock_init(&hso_net->net_lock); +} + +/* Adds a network device in the network device table */ +static int add_net_device(struct hso_device *hso_dev) +{ + int i; + + for (i = 0; i < HSO_MAX_NET_DEVICES; i++) { + if (network_table[i] == NULL) { + network_table[i] = hso_dev; + break; + } + } + if (i == HSO_MAX_NET_DEVICES) + return -1; + return 0; +} + +static int hso_radio_toggle(void *data, enum rfkill_state state) +{ + struct hso_device *hso_dev = data; + int enabled = (state == RFKILL_STATE_ON); + int rv; + + mutex_lock(&hso_dev->mutex); + if (hso_dev->usb_gone) + rv = 0; + else + rv = usb_control_msg(hso_dev->usb, usb_rcvctrlpipe(hso_dev->usb, 0), + enabled ? 0x82 : 0x81, 0x40, 0, 0, NULL, 0, + USB_CTRL_SET_TIMEOUT); + mutex_unlock(&hso_dev->mutex); + return rv; +} + +/* Creates and sets up everything for rfkill */ +static void hso_create_rfkill(struct hso_device *hso_dev, + struct usb_interface *interface) +{ + struct hso_net *hso_net = dev2net(hso_dev); + struct device *dev = hso_dev->dev; + char *rfkn; + + hso_net->rfkill = rfkill_allocate(&interface_to_usbdev(interface)->dev, + RFKILL_TYPE_WLAN); + if (!hso_net->rfkill) { + dev_err(dev, "%s - Out of memory", __func__); + return; + } + rfkn = kzalloc(20, GFP_KERNEL); + if (!rfkn) { + rfkill_free(hso_net->rfkill); + dev_err(dev, "%s - Out of memory", __func__); + return; + } + snprintf(rfkn, 20, "hso-%d", + interface->altsetting->desc.bInterfaceNumber); + hso_net->rfkill->name = rfkn; + hso_net->rfkill->state = RFKILL_STATE_ON; + hso_net->rfkill->data = hso_dev; + hso_net->rfkill->toggle_radio = hso_radio_toggle; + if (rfkill_register(hso_net->rfkill) < 0) { + kfree(rfkn); + hso_net->rfkill->name = NULL; + rfkill_free(hso_net->rfkill); + dev_err(dev, "%s - Failed to register rfkill", __func__); + return; + } +} + +/* Creates our network device */ +static struct hso_device *hso_create_net_device(struct usb_interface *interface) +{ + int result, i; + struct net_device *net; + struct hso_net *hso_net; + struct hso_device *hso_dev; + + hso_dev = hso_create_device(interface, HSO_INTF_MUX | HSO_PORT_NETWORK); + if (!hso_dev) + return NULL; + + /* allocate our network device, then we can put in our private data */ + /* call hso_net_init to do the basic initialization */ + net = alloc_netdev(sizeof(struct hso_net), "hso%d", hso_net_init); + if (!net) { + dev_err(&interface->dev, "Unable to create ethernet device\n"); + goto exit; + } + + hso_net = netdev_priv(net); + + hso_dev->port_data.dev_net = hso_net; + hso_net->net = net; + hso_net->parent = hso_dev; + + hso_net->in_endp = hso_get_ep(interface, USB_ENDPOINT_XFER_BULK, + USB_DIR_IN); + if (!hso_net->in_endp) { + dev_err(&interface->dev, "Can't find BULK IN endpoint\n"); + goto exit; + } + hso_net->out_endp = hso_get_ep(interface, USB_ENDPOINT_XFER_BULK, + USB_DIR_OUT); + if (!hso_net->out_endp) { + dev_err(&interface->dev, "Can't find BULK OUT endpoint\n"); + goto exit; + } + SET_NETDEV_DEV(net, &interface->dev); + + /* registering our net device */ + result = register_netdev(net); + if (result) { + dev_err(&interface->dev, "Failed to register device\n"); + goto exit; + } + + /* start allocating */ + for (i = 0; i < MUX_BULK_RX_BUF_COUNT; i++) { + hso_net->mux_bulk_rx_urb_pool[i] = usb_alloc_urb(0, GFP_KERNEL); + if (!hso_net->mux_bulk_rx_urb_pool[i]) { + dev_err(&interface->dev, "Could not allocate rx urb\n"); + goto exit; + } + hso_net->mux_bulk_rx_buf_pool[i] = kzalloc(MUX_BULK_RX_BUF_SIZE, + GFP_KERNEL); + if (!hso_net->mux_bulk_rx_buf_pool[i]) { + dev_err(&interface->dev, "Could not allocate rx buf\n"); + goto exit; + } + } + hso_net->mux_bulk_tx_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!hso_net->mux_bulk_tx_urb) { + dev_err(&interface->dev, "Could not allocate tx urb\n"); + goto exit; + } + hso_net->mux_bulk_tx_buf = kzalloc(MUX_BULK_TX_BUF_SIZE, GFP_KERNEL); + if (!hso_net->mux_bulk_tx_buf) { + dev_err(&interface->dev, "Could not allocate tx buf\n"); + goto exit; + } + + add_net_device(hso_dev); + + hso_log_port(hso_dev); + + hso_create_rfkill(hso_dev, interface); + + return hso_dev; +exit: + hso_free_net_device(hso_dev); + return NULL; +} + +/* Frees an AT channel ( goes for both mux and non-mux ) */ +static void hso_free_serial_device(struct hso_device *hso_dev) +{ + struct hso_serial *serial = dev2ser(hso_dev); + + if (!serial) + return; + set_serial_by_index(serial->minor, NULL); + + hso_serial_common_free(serial); + + if (serial->shared_int) { + mutex_lock(&serial->shared_int->shared_int_lock); + if (--serial->shared_int->ref_count == 0) + hso_free_shared_int(serial->shared_int); + else + mutex_unlock(&serial->shared_int->shared_int_lock); + } + kfree(serial); + hso_free_device(hso_dev); +} + +/* Creates a bulk AT channel */ +static struct hso_device *hso_create_bulk_serial_device( + struct usb_interface *interface, int port) +{ + struct hso_device *hso_dev; + struct hso_serial *serial; + int num_urbs; + + hso_dev = hso_create_device(interface, port); + if (!hso_dev) + return NULL; + + serial = kzalloc(sizeof(*serial), GFP_KERNEL); + if (!serial) + goto exit; + + serial->parent = hso_dev; + hso_dev->port_data.dev_serial = serial; + + if (port & HSO_PORT_MODEM) + num_urbs = 2; + else + num_urbs = 1; + + if (hso_serial_common_create(serial, num_urbs, BULK_URB_RX_SIZE, + BULK_URB_TX_SIZE)) + goto exit; + + serial->in_endp = hso_get_ep(interface, USB_ENDPOINT_XFER_BULK, + USB_DIR_IN); + if (!serial->in_endp) { + dev_err(&interface->dev, "Failed to find BULK IN ep\n"); + goto exit; + } + + if (! + (serial->out_endp = + hso_get_ep(interface, USB_ENDPOINT_XFER_BULK, USB_DIR_OUT))) { + dev_err(&interface->dev, "Failed to find BULK IN ep\n"); + goto exit; + } + + serial->write_data = hso_std_serial_write_data; + + /* and record this serial */ + set_serial_by_index(serial->minor, serial); + + /* setup the proc dirs and files if needed */ + hso_log_port(hso_dev); + + /* done, return it */ + return hso_dev; +exit: + if (hso_dev && serial) + hso_serial_common_free(serial); + kfree(serial); + hso_free_device(hso_dev); + return NULL; +} + +/* Creates a multiplexed AT channel */ +static +struct hso_device *hso_create_mux_serial_device(struct usb_interface *interface, + int port, + struct hso_shared_int *mux) +{ + struct hso_device *hso_dev; + struct hso_serial *serial; + int port_spec; + + port_spec = HSO_INTF_MUX; + port_spec &= ~HSO_PORT_MASK; + + port_spec |= hso_mux_to_port(port); + if ((port_spec & HSO_PORT_MASK) == HSO_PORT_NO_PORT) + return NULL; + + hso_dev = hso_create_device(interface, port_spec); + if (!hso_dev) + return NULL; + + serial = kzalloc(sizeof(*serial), GFP_KERNEL); + if (!serial) + goto exit; + + hso_dev->port_data.dev_serial = serial; + serial->parent = hso_dev; + + if (hso_serial_common_create + (serial, 1, CTRL_URB_RX_SIZE, CTRL_URB_TX_SIZE)) + goto exit; + + serial->tx_data_length--; + serial->write_data = hso_mux_serial_write_data; + + serial->shared_int = mux; + mutex_lock(&serial->shared_int->shared_int_lock); + serial->shared_int->ref_count++; + mutex_unlock(&serial->shared_int->shared_int_lock); + + /* and record this serial */ + set_serial_by_index(serial->minor, serial); + + /* setup the proc dirs and files if needed */ + hso_log_port(hso_dev); + + /* done, return it */ + return hso_dev; + +exit: + if (serial) { + tty_unregister_device(tty_drv, serial->minor); + kfree(serial); + } + if (hso_dev) + hso_free_device(hso_dev); + return NULL; + +} + +static void hso_free_shared_int(struct hso_shared_int *mux) +{ + usb_free_urb(mux->shared_intr_urb); + kfree(mux->shared_intr_buf); + mutex_unlock(&mux->shared_int_lock); + kfree(mux); +} + +static +struct hso_shared_int *hso_create_shared_int(struct usb_interface *interface) +{ + struct hso_shared_int *mux = kzalloc(sizeof(*mux), GFP_KERNEL); + + if (!mux) + return NULL; + + mux->intr_endp = hso_get_ep(interface, USB_ENDPOINT_XFER_INT, + USB_DIR_IN); + if (!mux->intr_endp) { + dev_err(&interface->dev, "Can't find INT IN endpoint\n"); + goto exit; + } + + mux->shared_intr_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!mux->shared_intr_urb) { + dev_err(&interface->dev, "Could not allocate intr urb?"); + goto exit; + } + mux->shared_intr_buf = kzalloc(mux->intr_endp->wMaxPacketSize, + GFP_KERNEL); + if (!mux->shared_intr_buf) { + dev_err(&interface->dev, "Could not allocate intr buf?"); + goto exit; + } + + mutex_init(&mux->shared_int_lock); + + return mux; + +exit: + kfree(mux->shared_intr_buf); + usb_free_urb(mux->shared_intr_urb); + kfree(mux); + return NULL; +} + +/* Gets the port spec for a certain interface */ +static int hso_get_config_data(struct usb_interface *interface) +{ + struct usb_device *usbdev = interface_to_usbdev(interface); + u8 config_data[17]; + u32 if_num = interface->altsetting->desc.bInterfaceNumber; + s32 result; + + if (usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), + 0x86, 0xC0, 0, 0, config_data, 17, + USB_CTRL_SET_TIMEOUT) != 0x11) { + return -EIO; + } + + switch (config_data[if_num]) { + case 0x0: + result = 0; + break; + case 0x1: + result = HSO_PORT_DIAG; + break; + case 0x2: + result = HSO_PORT_GPS; + break; + case 0x3: + result = HSO_PORT_GPS_CONTROL; + break; + case 0x4: + result = HSO_PORT_APP; + break; + case 0x5: + result = HSO_PORT_APP2; + break; + case 0x6: + result = HSO_PORT_CONTROL; + break; + case 0x7: + result = HSO_PORT_NETWORK; + break; + case 0x8: + result = HSO_PORT_MODEM; + break; + case 0x9: + result = HSO_PORT_MSD; + break; + case 0xa: + result = HSO_PORT_PCSC; + break; + case 0xb: + result = HSO_PORT_VOICE; + break; + default: + result = 0; + } + + if (result) + result |= HSO_INTF_BULK; + + if (config_data[16] & 0x1) + result |= HSO_INFO_CRC_BUG; + + return result; +} + +/* called once for each interface upon device insertion */ +static int hso_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + int mux, i, if_num, port_spec; + unsigned char port_mask; + struct hso_device *hso_dev = NULL; + struct hso_shared_int *shared_int; + struct hso_device *tmp_dev = NULL; + + if_num = interface->altsetting->desc.bInterfaceNumber; + + /* Get the interface/port specification from either driver_info or from + * the device itself */ + if (id->driver_info) + port_spec = ((u32 *)(id->driver_info))[if_num]; + else + port_spec = hso_get_config_data(interface); + + if (interface->cur_altsetting->desc.bInterfaceClass != 0xFF) { + dev_err(&interface->dev, "Not our interface\n"); + return -ENODEV; + } + /* Check if we need to switch to alt interfaces prior to port + * configuration */ + if (interface->num_altsetting > 1) + usb_set_interface(interface_to_usbdev(interface), if_num, 1); + interface->needs_remote_wakeup = 1; + + /* Allocate new hso device(s) */ + switch (port_spec & HSO_INTF_MASK) { + case HSO_INTF_MUX: + if ((port_spec & HSO_PORT_MASK) == HSO_PORT_NETWORK) { + /* Create the network device */ + if (!disable_net) { + hso_dev = hso_create_net_device(interface); + if (!hso_dev) + goto exit; + tmp_dev = hso_dev; + } + } + + if (hso_get_mux_ports(interface, &port_mask)) + /* TODO: de-allocate everything */ + goto exit; + + shared_int = hso_create_shared_int(interface); + if (!shared_int) + goto exit; + + for (i = 1, mux = 0; i < 0x100; i = i << 1, mux++) { + if (port_mask & i) { + hso_dev = hso_create_mux_serial_device( + interface, i, shared_int); + if (!hso_dev) + goto exit; + } + } + + if (tmp_dev) + hso_dev = tmp_dev; + break; + + case HSO_INTF_BULK: + /* It's a regular bulk interface */ + if (((port_spec & HSO_PORT_MASK) == HSO_PORT_NETWORK) + && !disable_net) + hso_dev = hso_create_net_device(interface); + else + hso_dev = + hso_create_bulk_serial_device(interface, port_spec); + if (!hso_dev) + goto exit; + break; + default: + goto exit; + } + + usb_driver_claim_interface(&hso_driver, interface, hso_dev); + + /* save our data pointer in this device */ + usb_set_intfdata(interface, hso_dev); + + /* done */ + return 0; +exit: + hso_free_interface(interface); + return -ENODEV; +} + +/* device removed, cleaning up */ +static void hso_disconnect(struct usb_interface *interface) +{ + hso_free_interface(interface); + + /* remove reference of our private data */ + usb_set_intfdata(interface, NULL); + + usb_driver_release_interface(&hso_driver, interface); +} + +static void async_get_intf(struct work_struct *data) +{ + struct hso_device *hso_dev = + container_of(data, struct hso_device, async_get_intf); + usb_autopm_get_interface(hso_dev->interface); +} + +static void async_put_intf(struct work_struct *data) +{ + struct hso_device *hso_dev = + container_of(data, struct hso_device, async_put_intf); + usb_autopm_put_interface(hso_dev->interface); +} + +static int hso_get_activity(struct hso_device *hso_dev) +{ + if (hso_dev->usb->state == USB_STATE_SUSPENDED) { + if (!hso_dev->is_active) { + hso_dev->is_active = 1; + schedule_work(&hso_dev->async_get_intf); + } + } + + if (hso_dev->usb->state != USB_STATE_CONFIGURED) + return -EAGAIN; + + usb_mark_last_busy(hso_dev->usb); + + return 0; +} + +static int hso_put_activity(struct hso_device *hso_dev) +{ + if (hso_dev->usb->state != USB_STATE_SUSPENDED) { + if (hso_dev->is_active) { + hso_dev->is_active = 0; + schedule_work(&hso_dev->async_put_intf); + return -EAGAIN; + } + } + hso_dev->is_active = 0; + return 0; +} + +/* called by kernel when we need to suspend device */ +static int hso_suspend(struct usb_interface *iface, pm_message_t message) +{ + int i, result; + + /* Stop all serial ports */ + for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) { + if (serial_table[i] && (serial_table[i]->interface == iface)) { + result = hso_stop_serial_device(serial_table[i]); + if (result) + goto out; + } + } + + /* Stop all network ports */ + for (i = 0; i < HSO_MAX_NET_DEVICES; i++) { + if (network_table[i] && + (network_table[i]->interface == iface)) { + result = hso_stop_net_device(network_table[i]); + if (result) + goto out; + } + } + +out: + return 0; +} + +/* called by kernel when we need to resume device */ +static int hso_resume(struct usb_interface *iface) +{ + int i, result = 0; + struct hso_net *hso_net; + + /* Start all serial ports */ + for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) { + if (serial_table[i] && (serial_table[i]->interface == iface)) { + if (dev2ser(serial_table[i])->open_count) { + result = + hso_start_serial_device(serial_table[i], GFP_NOIO); + hso_kick_transmit(dev2ser(serial_table[i])); + if (result) + goto out; + } + } + } + + /* Start all network ports */ + for (i = 0; i < HSO_MAX_NET_DEVICES; i++) { + if (network_table[i] && + (network_table[i]->interface == iface)) { + hso_net = dev2net(network_table[i]); + /* First transmit any lingering data, then restart the + * device. */ + if (hso_net->skb_tx_buf) { + dev_dbg(&iface->dev, + "Transmitting lingering data\n"); + hso_net_start_xmit(hso_net->skb_tx_buf, + hso_net->net); + } + result = hso_start_net_device(network_table[i]); + if (result) + goto out; + } + } + +out: + return result; +} + +static void hso_serial_ref_free(struct kref *ref) +{ + struct hso_device *hso_dev = container_of(ref, struct hso_device, ref); + + hso_free_serial_device(hso_dev); +} + +static void hso_free_interface(struct usb_interface *interface) +{ + struct hso_serial *hso_dev; + int i; + + for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) { + if (serial_table[i] + && (serial_table[i]->interface == interface)) { + hso_dev = dev2ser(serial_table[i]); + if (hso_dev->tty) + tty_hangup(hso_dev->tty); + mutex_lock(&hso_dev->parent->mutex); + hso_dev->parent->usb_gone = 1; + mutex_unlock(&hso_dev->parent->mutex); + kref_put(&serial_table[i]->ref, hso_serial_ref_free); + } + } + + for (i = 0; i < HSO_MAX_NET_DEVICES; i++) { + if (network_table[i] + && (network_table[i]->interface == interface)) { + struct rfkill *rfk = dev2net(network_table[i])->rfkill; + /* hso_stop_net_device doesn't stop the net queue since + * traffic needs to start it again when suspended */ + netif_stop_queue(dev2net(network_table[i])->net); + hso_stop_net_device(network_table[i]); + cancel_work_sync(&network_table[i]->async_put_intf); + cancel_work_sync(&network_table[i]->async_get_intf); + if(rfk) + rfkill_unregister(rfk); + hso_free_net_device(network_table[i]); + } + } +} + +/* Helper functions */ + +/* Get the endpoint ! */ +static struct usb_endpoint_descriptor *hso_get_ep(struct usb_interface *intf, + int type, int dir) +{ + int i; + struct usb_host_interface *iface = intf->cur_altsetting; + struct usb_endpoint_descriptor *endp; + + for (i = 0; i < iface->desc.bNumEndpoints; i++) { + endp = &iface->endpoint[i].desc; + if (((endp->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == dir) && + ((endp->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == type)) + return endp; + } + + return NULL; +} + +/* Get the byte that describes which ports are enabled */ +static int hso_get_mux_ports(struct usb_interface *intf, unsigned char *ports) +{ + int i; + struct usb_host_interface *iface = intf->cur_altsetting; + + if (iface->extralen == 3) { + *ports = iface->extra[2]; + return 0; + } + + for (i = 0; i < iface->desc.bNumEndpoints; i++) { + if (iface->endpoint[i].extralen == 3) { + *ports = iface->endpoint[i].extra[2]; + return 0; + } + } + + return -1; +} + +/* interrupt urb needs to be submitted, used for serial read of muxed port */ +static int hso_mux_submit_intr_urb(struct hso_shared_int *shared_int, + struct usb_device *usb, gfp_t gfp) +{ + int result; + + usb_fill_int_urb(shared_int->shared_intr_urb, usb, + usb_rcvintpipe(usb, + shared_int->intr_endp->bEndpointAddress & 0x7F), + shared_int->shared_intr_buf, + shared_int->intr_endp->wMaxPacketSize, + intr_callback, shared_int, + shared_int->intr_endp->bInterval); + + result = usb_submit_urb(shared_int->shared_intr_urb, gfp); + if (result) + dev_warn(&usb->dev, "%s failed mux_intr_urb %d", __func__, + result); + + return result; +} + +/* operations setup of the serial interface */ +static struct tty_operations hso_serial_ops = { + .open = hso_serial_open, + .close = hso_serial_close, + .write = hso_serial_write, + .write_room = hso_serial_write_room, + .set_termios = hso_serial_set_termios, + .chars_in_buffer = hso_serial_chars_in_buffer, + .tiocmget = hso_serial_tiocmget, + .tiocmset = hso_serial_tiocmset, +}; + +static struct usb_driver hso_driver = { + .name = driver_name, + .probe = hso_probe, + .disconnect = hso_disconnect, + .id_table = hso_ids, + .suspend = hso_suspend, + .resume = hso_resume, + .supports_autosuspend = 1, +}; + +static int __init hso_init(void) +{ + int i; + int result; + + /* put it in the log */ + printk(KERN_INFO "hso: %s\n", version); + + /* Initialise the serial table semaphore and table */ + spin_lock_init(&serial_table_lock); + for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) + serial_table[i] = NULL; + + /* allocate our driver using the proper amount of supported minors */ + tty_drv = alloc_tty_driver(HSO_SERIAL_TTY_MINORS); + if (!tty_drv) + return -ENOMEM; + + /* fill in all needed values */ + tty_drv->magic = TTY_DRIVER_MAGIC; + tty_drv->owner = THIS_MODULE; + tty_drv->driver_name = driver_name; + tty_drv->name = tty_filename; + + /* if major number is provided as parameter, use that one */ + if (tty_major) + tty_drv->major = tty_major; + + tty_drv->minor_start = 0; + tty_drv->num = HSO_SERIAL_TTY_MINORS; + tty_drv->type = TTY_DRIVER_TYPE_SERIAL; + tty_drv->subtype = SERIAL_TYPE_NORMAL; + tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; + tty_drv->init_termios = tty_std_termios; + tty_drv->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + tty_drv->termios = hso_serial_termios; + tty_drv->termios_locked = hso_serial_termios_locked; + tty_set_operations(tty_drv, &hso_serial_ops); + + /* register the tty driver */ + result = tty_register_driver(tty_drv); + if (result) { + printk(KERN_ERR "%s - tty_register_driver failed(%d)\n", + __func__, result); + return result; + } + + /* register this module as an usb driver */ + result = usb_register(&hso_driver); + if (result) { + printk(KERN_ERR "Could not register hso driver? error: %d\n", + result); + /* cleanup serial interface */ + tty_unregister_driver(tty_drv); + return result; + } + + /* done */ + return 0; +} + +static void __exit hso_exit(void) +{ + printk(KERN_INFO "hso: unloaded\n"); + + tty_unregister_driver(tty_drv); + /* deregister the usb driver */ + usb_deregister(&hso_driver); +} + +/* Module definitions */ +module_init(hso_init); +module_exit(hso_exit); + +MODULE_AUTHOR(MOD_AUTHOR); +MODULE_DESCRIPTION(MOD_DESCRIPTION); +MODULE_LICENSE(MOD_LICENSE); +MODULE_INFO(Version, DRIVER_VERSION); + +/* change the debug level (eg: insmod hso.ko debug=0x04) */ +MODULE_PARM_DESC(debug, "Level of debug [0x01 | 0x02 | 0x04 | 0x08 | 0x10]"); +module_param(debug, int, S_IRUGO | S_IWUSR); + +/* set the major tty number (eg: insmod hso.ko tty_major=245) */ +MODULE_PARM_DESC(tty_major, "Set the major tty number"); +module_param(tty_major, int, S_IRUGO | S_IWUSR); + +/* disable network interface (eg: insmod hso.ko disable_net=1) */ +MODULE_PARM_DESC(disable_net, "Disable the network interface"); +module_param(disable_net, int, S_IRUGO | S_IWUSR); diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index 0dcfc031026..7c66b052f55 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 5450eac9e26..4452306d532 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -44,11 +44,15 @@ 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; @@ -72,7 +76,7 @@ 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 @@ -94,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++; @@ -106,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) { @@ -238,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; @@ -283,7 +305,11 @@ 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) @@ -295,6 +321,8 @@ static void xmit_tasklet(unsigned long data) 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); } @@ -435,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)) { @@ -454,6 +486,9 @@ static int virtnet_probe(struct virtio_device *vdev) 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"); @@ -491,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); @@ -514,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/Kconfig b/drivers/net/wireless/Kconfig index fdf5aa8b842..22e1e9a1fb7 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -673,6 +673,19 @@ config ADM8211 Thanks to Infineon-ADMtek for their support of this driver. +config MAC80211_HWSIM + tristate "Simulated radio testing tool for mac80211" + depends on MAC80211 && WLAN_80211 + ---help--- + This driver is a developer testing tool that can be used to test + IEEE 802.11 networking stack (mac80211) functionality. This is not + needed for normal wireless LAN usage and is only for testing. See + Documentation/networking/mac80211_hwsim for more information on how + to use this tool. + + To compile this driver as a module, choose M here: the module will be + called mac80211_hwsim. If unsure, say N. + source "drivers/net/wireless/p54/Kconfig" source "drivers/net/wireless/ath5k/Kconfig" source "drivers/net/wireless/iwlwifi/Kconfig" diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 2c343aae38d..54a4f6f1db6 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -62,3 +62,5 @@ obj-$(CONFIG_RT2X00) += rt2x00/ obj-$(CONFIG_P54_COMMON) += p54/ obj-$(CONFIG_ATH5K) += ath5k/ + +obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 1e1446bf4b4..e30f8b79ea8 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -4561,22 +4561,13 @@ static ssize_t proc_read( struct file *file, size_t len, loff_t *offset ) { - loff_t pos = *offset; - struct proc_data *priv = (struct proc_data*)file->private_data; + struct proc_data *priv = file->private_data; if (!priv->rbuffer) return -EINVAL; - if (pos < 0) - return -EINVAL; - if (pos >= priv->readlen) - return 0; - if (len > priv->readlen - pos) - len = priv->readlen - pos; - if (copy_to_user(buffer, priv->rbuffer + pos, len)) - return -EFAULT; - *offset = pos + len; - return len; + return simple_read_from_buffer(buffer, len, offset, priv->rbuffer, + priv->readlen); } /* diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 239e71c3d1b..532365f5ece 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -649,7 +649,6 @@ struct b43_pio { /* Context information for a noise calculation (Link Quality). */ struct b43_noise_calculation { - u8 channel_at_start; bool calculation_running; u8 nr_samples; s8 samples[8][4]; diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index b4eadd908be..8a09a1db08d 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -795,24 +795,49 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, { struct b43_dmaring *ring; int err; - int nr_slots; dma_addr_t dma_test; ring = kzalloc(sizeof(*ring), GFP_KERNEL); if (!ring) goto out; - ring->type = type; - nr_slots = B43_RXRING_SLOTS; + ring->nr_slots = B43_RXRING_SLOTS; if (for_tx) - nr_slots = B43_TXRING_SLOTS; + ring->nr_slots = B43_TXRING_SLOTS; - ring->meta = kcalloc(nr_slots, sizeof(struct b43_dmadesc_meta), + ring->meta = kcalloc(ring->nr_slots, sizeof(struct b43_dmadesc_meta), GFP_KERNEL); if (!ring->meta) goto err_kfree_ring; + + ring->type = type; + ring->dev = dev; + ring->mmio_base = b43_dmacontroller_base(type, controller_index); + ring->index = controller_index; + if (type == B43_DMA_64BIT) + ring->ops = &dma64_ops; + else + ring->ops = &dma32_ops; if (for_tx) { - ring->txhdr_cache = kcalloc(nr_slots, + ring->tx = 1; + ring->current_slot = -1; + } else { + if (ring->index == 0) { + ring->rx_buffersize = B43_DMA0_RX_BUFFERSIZE; + ring->frameoffset = B43_DMA0_RX_FRAMEOFFSET; + } else if (ring->index == 3) { + ring->rx_buffersize = B43_DMA3_RX_BUFFERSIZE; + ring->frameoffset = B43_DMA3_RX_FRAMEOFFSET; + } else + B43_WARN_ON(1); + } + spin_lock_init(&ring->lock); +#ifdef CONFIG_B43_DEBUG + ring->last_injected_overflow = jiffies; +#endif + + if (for_tx) { + ring->txhdr_cache = kcalloc(ring->nr_slots, b43_txhdr_size(dev), GFP_KERNEL); if (!ring->txhdr_cache) @@ -828,7 +853,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, b43_txhdr_size(dev), 1)) { /* ugh realloc */ kfree(ring->txhdr_cache); - ring->txhdr_cache = kcalloc(nr_slots, + ring->txhdr_cache = kcalloc(ring->nr_slots, b43_txhdr_size(dev), GFP_KERNEL | GFP_DMA); if (!ring->txhdr_cache) @@ -853,32 +878,6 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, DMA_TO_DEVICE); } - ring->dev = dev; - ring->nr_slots = nr_slots; - ring->mmio_base = b43_dmacontroller_base(type, controller_index); - ring->index = controller_index; - if (type == B43_DMA_64BIT) - ring->ops = &dma64_ops; - else - ring->ops = &dma32_ops; - if (for_tx) { - ring->tx = 1; - ring->current_slot = -1; - } else { - if (ring->index == 0) { - ring->rx_buffersize = B43_DMA0_RX_BUFFERSIZE; - ring->frameoffset = B43_DMA0_RX_FRAMEOFFSET; - } else if (ring->index == 3) { - ring->rx_buffersize = B43_DMA3_RX_BUFFERSIZE; - ring->frameoffset = B43_DMA3_RX_FRAMEOFFSET; - } else - B43_WARN_ON(1); - } - spin_lock_init(&ring->lock); -#ifdef CONFIG_B43_DEBUG - ring->last_injected_overflow = jiffies; -#endif - err = alloc_ringmemory(ring); if (err) goto err_kfree_txhdr_cache; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 1e31e0bca74..7bca8e98151 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1145,7 +1145,6 @@ static void b43_generate_noise_sample(struct b43_wldev *dev) b43_jssi_write(dev, 0x7F7F7F7F); b43_write32(dev, B43_MMIO_MACCMD, b43_read32(dev, B43_MMIO_MACCMD) | B43_MACCMD_BGNOISE); - B43_WARN_ON(dev->noisecalc.channel_at_start != dev->phy.channel); } static void b43_calculate_link_quality(struct b43_wldev *dev) @@ -1154,7 +1153,6 @@ static void b43_calculate_link_quality(struct b43_wldev *dev) if (dev->noisecalc.calculation_running) return; - dev->noisecalc.channel_at_start = dev->phy.channel; dev->noisecalc.calculation_running = 1; dev->noisecalc.nr_samples = 0; @@ -1171,9 +1169,16 @@ static void handle_irq_noise(struct b43_wldev *dev) /* Bottom half of Link Quality calculation. */ + /* Possible race condition: It might be possible that the user + * changed to a different channel in the meantime since we + * started the calculation. We ignore that fact, since it's + * not really that much of a problem. The background noise is + * an estimation only anyway. Slightly wrong results will get damped + * by the averaging of the 8 sample rounds. Additionally the + * value is shortlived. So it will be replaced by the next noise + * calculation round soon. */ + B43_WARN_ON(!dev->noisecalc.calculation_running); - if (dev->noisecalc.channel_at_start != phy->channel) - goto drop_calculation; *((__le32 *)noise) = cpu_to_le32(b43_jssi_read(dev)); if (noise[0] == 0x7F || noise[1] == 0x7F || noise[2] == 0x7F || noise[3] == 0x7F) @@ -1214,11 +1219,10 @@ static void handle_irq_noise(struct b43_wldev *dev) average -= 48; dev->stats.link_noise = average; - drop_calculation: dev->noisecalc.calculation_running = 0; return; } - generate_new: +generate_new: b43_generate_noise_sample(dev); } diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c index 20d387f6658..f7aec9309d0 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/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 5f3e849043f..a382c007892 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -14,15 +14,6 @@ config IWLWIFI_LEDS bool default n -config IWLWIFI_RUN_TIME_CALIB - bool - depends on IWLCORE - default n - ---help--- - This option will enable run time calibration for the iwlwifi driver. - These calibrations are Sensitivity and Chain Noise. - - config IWLWIFI_RFKILL boolean "IWLWIFI RF kill support" depends on IWLCORE @@ -54,14 +45,6 @@ config IWL4965 say M here and read <file:Documentation/kbuild/modules.txt>. The module will be called iwl4965.ko. -config IWL4965_HT - bool "Enable 802.11n HT features in iwl4965 driver" - depends on EXPERIMENTAL - depends on IWL4965 - ---help--- - This option enables IEEE 802.11n High Throughput features - for the iwl4965 driver. - config IWL4965_LEDS bool "Enable LEDS features in iwl4965 driver" depends on IWL4965 @@ -76,15 +59,6 @@ config IWL4965_SPECTRUM_MEASUREMENT ---help--- This option will enable spectrum measurement for the iwl4965 driver. -config IWL4965_RUN_TIME_CALIB - bool "Enable run time Calibration for 4965 NIC" - select IWLWIFI_RUN_TIME_CALIB - depends on IWL4965 - default y - ---help--- - This option will enable run time calibration for the iwl4965 driver. - These calibrations are Sensitivity and Chain Noise. If unsure, say yes - config IWLWIFI_DEBUG bool "Enable full debugging output in iwl4965 driver" depends on IWL4965 @@ -118,16 +92,6 @@ config IWL5000 This option enables support for Intel Wireless WiFi Link 5000AGN Family Dependency on 4965 is temporary -config IWL5000_RUN_TIME_CALIB - bool "Enable run time Calibration for 5000 NIC" - select IWLWIFI_RUN_TIME_CALIB - depends on IWL5000 - default y - ---help--- - This option will enable run time calibration for the iwl5000 driver. - These calibrations are Sensitivity and Chain Noise. If unsure, say yes - - config IWLWIFI_DEBUGFS bool "Iwlwifi debugfs support" depends on IWLCORE && IWLWIFI_DEBUG && MAC80211_DEBUGFS diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 5c73eede719..1f52b92f08b 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -1,10 +1,10 @@ obj-$(CONFIG_IWLCORE) += iwlcore.o iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o -iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o +iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o iwl-calib.o +iwlcore-objs += iwl-scan.o iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o iwlcore-$(CONFIG_IWLWIFI_RFKILL) += iwl-rfkill.o -iwlcore-$(CONFIG_IWLWIFI_RUN_TIME_CALIB) += iwl-calib.o obj-$(CONFIG_IWL3945) += iwl3945.o iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 0ba6889dfd4..63f20370032 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -388,7 +388,7 @@ static void iwl3945_dbg_report_frame(struct iwl3945_priv *priv, u32 print_dump = 0; /* set to 1 to dump all frames' contents */ u32 hundred = 0; u32 dataframe = 0; - u16 fc; + __le16 fc; u16 seq_ctl; u16 channel; u16 phy_flags; @@ -407,7 +407,7 @@ static void iwl3945_dbg_report_frame(struct iwl3945_priv *priv, u8 *data = IWL_RX_DATA(pkt); /* MAC header */ - fc = le16_to_cpu(header->frame_control); + fc = header->frame_control; seq_ctl = le16_to_cpu(header->seq_ctrl); /* metadata */ @@ -431,8 +431,8 @@ static void iwl3945_dbg_report_frame(struct iwl3945_priv *priv, /* if data frame is to us and all is good, * (optionally) print summary for only 1 out of every 100 */ - if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) == - (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { + if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) == + cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { dataframe = 1; if (!group100) print_summary = 1; /* print each frame */ @@ -455,13 +455,13 @@ static void iwl3945_dbg_report_frame(struct iwl3945_priv *priv, if (hundred) title = "100Frames"; - else if (fc & IEEE80211_FCTL_RETRY) + else if (ieee80211_has_retry(fc)) title = "Retry"; - else if (ieee80211_is_assoc_response(fc)) + else if (ieee80211_is_assoc_resp(fc)) title = "AscRsp"; - else if (ieee80211_is_reassoc_response(fc)) + else if (ieee80211_is_reassoc_resp(fc)) title = "RasRsp"; - else if (ieee80211_is_probe_response(fc)) { + else if (ieee80211_is_probe_resp(fc)) { title = "PrbRsp"; print_dump = 1; /* dump frame contents */ } else if (ieee80211_is_beacon(fc)) { @@ -490,14 +490,14 @@ static void iwl3945_dbg_report_frame(struct iwl3945_priv *priv, if (dataframe) IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, " "len=%u, rssi=%d, chnl=%d, rate=%u, \n", - title, fc, header->addr1[5], + title, le16_to_cpu(fc), header->addr1[5], length, rssi, channel, rate); else { /* src/dst addresses assume managed mode */ IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, " "src=0x%02x, rssi=%u, tim=%lu usec, " "phy=0x%02x, chnl=%d\n", - title, fc, header->addr1[5], + title, le16_to_cpu(fc), header->addr1[5], header->addr3[5], rssi, tsf_low - priv->scan_start_tsf, phy_flags, channel); @@ -971,7 +971,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv, u8 rts_retry_limit; u8 data_retry_limit; __le32 tx_flags; - u16 fc = le16_to_cpu(hdr->frame_control); + __le16 fc = hdr->frame_control; rate = iwl3945_rates[rate_index].plcp; tx_flags = cmd->cmd.tx.tx_flags; @@ -996,7 +996,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv, else rts_retry_limit = 7; - if (ieee80211_is_probe_response(fc)) { + if (ieee80211_is_probe_resp(fc)) { data_retry_limit = 3; if (data_retry_limit < rts_retry_limit) rts_retry_limit = data_retry_limit; @@ -1006,12 +1006,12 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv, if (priv->data_retry_limit != -1) data_retry_limit = priv->data_retry_limit; - if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) { - switch (fc & IEEE80211_FCTL_STYPE) { - case IEEE80211_STYPE_AUTH: - case IEEE80211_STYPE_DEAUTH: - case IEEE80211_STYPE_ASSOC_REQ: - case IEEE80211_STYPE_REASSOC_REQ: + if (ieee80211_is_mgmt(fc)) { + switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { + case cpu_to_le16(IEEE80211_STYPE_AUTH): + case cpu_to_le16(IEEE80211_STYPE_DEAUTH): + case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): + case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): if (tx_flags & TX_CMD_FLG_RTS_MSK) { tx_flags &= ~TX_CMD_FLG_RTS_MSK; tx_flags |= TX_CMD_FLG_CTS_MSK; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index fc118335b60..10f630e1afa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -82,7 +82,7 @@ */ #define IWL_CMD_QUEUE_NUM 4 #define IWL_CMD_FIFO_NUM 4 -#define IWL_BACK_QUEUE_FIRST_ID 7 +#define IWL49_FIRST_AMPDU_QUEUE 7 /* Tx rates */ #define IWL_CCK_RATES 4 @@ -793,19 +793,6 @@ enum { /********************* END TXPOWER *****************************************/ -static inline u8 iwl4965_hw_get_rate(__le32 rate_n_flags) -{ - return le32_to_cpu(rate_n_flags) & 0xFF; -} -static inline u32 iwl4965_hw_get_rate_n_flags(__le32 rate_n_flags) -{ - return le32_to_cpu(rate_n_flags) & 0x1FFFF; -} -static inline __le32 iwl4965_hw_set_rate_n_flags(u8 rate, u16 flags) -{ - return cpu_to_le32(flags|(u16)rate); -} - /** * Tx/Rx Queues diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index d8f2b4d33fd..20230311728 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c @@ -38,6 +38,7 @@ #include "../net/mac80211/rate.h" #include "iwl-dev.h" +#include "iwl-sta.h" #include "iwl-core.h" #include "iwl-helpers.h" @@ -105,8 +106,6 @@ struct iwl4965_scale_tbl_info { struct iwl4965_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */ }; -#ifdef CONFIG_IWL4965_HT - struct iwl4965_traffic_load { unsigned long time_stamp; /* age of the oldest statistics */ u32 packet_count[TID_QUEUE_MAX_SIZE]; /* packet count in this time @@ -118,8 +117,6 @@ struct iwl4965_traffic_load { u8 head; /* start of the circular buffer */ }; -#endif /* CONFIG_IWL4965_HT */ - /** * struct iwl4965_lq_sta -- driver's rate scaling private structure * @@ -157,16 +154,12 @@ struct iwl4965_lq_sta { struct iwl_link_quality_cmd lq; struct iwl4965_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */ -#ifdef CONFIG_IWL4965_HT struct iwl4965_traffic_load load[TID_MAX_LOAD_COUNT]; u8 tx_agg_tid_en; -#endif #ifdef CONFIG_MAC80211_DEBUGFS struct dentry *rs_sta_dbgfs_scale_table_file; struct dentry *rs_sta_dbgfs_stats_table_file; -#ifdef CONFIG_IWL4965_HT struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file; -#endif u32 dbg_fixed_rate; #endif struct iwl_priv *drv; @@ -256,7 +249,6 @@ static inline u8 rs_is_valid_ant(u8 valid_antenna, u8 ant_type) return ((ant_type & valid_antenna) == ant_type); } -#ifdef CONFIG_IWL4965_HT /* * removes the old data from the statistics. All data that is older than * TID_MAX_TIME_DIFF, will be deleted. @@ -282,21 +274,21 @@ static void rs_tl_rm_old_stats(struct iwl4965_traffic_load *tl, u32 curr_time) * increment traffic load value for tid and also remove * any old values if passed the certain time period */ -static void rs_tl_add_packet(struct iwl4965_lq_sta *lq_data, - struct ieee80211_hdr *hdr) +static u8 rs_tl_add_packet(struct iwl4965_lq_sta *lq_data, + struct ieee80211_hdr *hdr) { u32 curr_time = jiffies_to_msecs(jiffies); u32 time_diff; s32 index; struct iwl4965_traffic_load *tl = NULL; - u16 fc = le16_to_cpu(hdr->frame_control); + __le16 fc = hdr->frame_control; u8 tid; - if (ieee80211_is_qos_data(fc)) { - u8 *qc = ieee80211_get_qos_ctrl(hdr, ieee80211_get_hdrlen(fc)); + if (ieee80211_is_data_qos(fc)) { + u8 *qc = ieee80211_get_qos_ctl(hdr); tid = qc[0] & 0xf; } else - return; + return MAX_TID_COUNT; tl = &lq_data->load[tid]; @@ -309,7 +301,7 @@ static void rs_tl_add_packet(struct iwl4965_lq_sta *lq_data, tl->queue_count = 1; tl->head = 0; tl->packet_count[0] = 1; - return; + return MAX_TID_COUNT; } time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time); @@ -326,6 +318,8 @@ static void rs_tl_add_packet(struct iwl4965_lq_sta *lq_data, if ((index + 1) > tl->queue_count) tl->queue_count = index + 1; + + return tid; } /* @@ -389,8 +383,6 @@ static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid, rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); } -#endif /* CONFIG_IWLWIFI_HT */ - static inline int get_num_of_ant_from_rate(u32 rate_n_flags) { return (!!(rate_n_flags & RATE_MCS_ANT_A_MSK) + @@ -545,7 +537,7 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags, u8 num_of_ant = get_num_of_ant_from_rate(rate_n_flags); u8 mcs; - *rate_idx = iwl4965_hwrate_to_plcp_idx(rate_n_flags); + *rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); if (*rate_idx == IWL_RATE_INVALID) { *rate_idx = -1; @@ -626,7 +618,6 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, /* FIXME:RS: in 4965 we don't use greenfield at all */ /* FIXME:RS: don't use greenfield for now in TX */ -/* #ifdef CONFIG_IWL4965_HT */ #if 0 static inline u8 rs_use_green(struct iwl_priv *priv, struct ieee80211_conf *conf) { @@ -634,12 +625,11 @@ static inline u8 rs_use_green(struct iwl_priv *priv, struct ieee80211_conf *conf priv->current_ht_config.is_green_field && !priv->current_ht_config.non_GF_STA_present); } -#else +#endif static inline u8 rs_use_green(struct iwl_priv *priv, struct ieee80211_conf *conf) { return 0; } -#endif /* CONFIG_IWL4965_HT */ /** * rs_get_supported_rates - get the available rates @@ -804,7 +794,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, struct iwl4965_scale_tbl_info tbl_type; struct iwl4965_scale_tbl_info *curr_tbl, *search_tbl; u8 active_index = 0; - u16 fc = le16_to_cpu(hdr->frame_control); + __le16 fc = hdr->frame_control; s32 tpt = 0; IWL_DEBUG_RATE_LIMIT("get frame ack response, update rate scale window\n"); @@ -1050,7 +1040,6 @@ static void rs_set_expected_tpt_table(struct iwl4965_lq_sta *lq_sta, tbl->expected_tpt = expected_tpt_G; } -#ifdef CONFIG_IWL4965_HT /* * Find starting rate for new "search" high-throughput mode of modulation. * Goal is to find lowest expected rate (under perfect conditions) that is @@ -1152,12 +1141,10 @@ static s32 rs_get_best_rate(struct iwl_priv *priv, return new_rate; } -#endif /* CONFIG_IWL4965_HT */ /* * Set up search table for MIMO */ -#ifdef CONFIG_IWL4965_HT static int rs_switch_to_mimo2(struct iwl_priv *priv, struct iwl4965_lq_sta *lq_sta, struct ieee80211_conf *conf, @@ -1221,16 +1208,6 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, tbl->current_rate, is_green); return 0; } -#else -static int rs_switch_to_mimo2(struct iwl_priv *priv, - struct iwl4965_lq_sta *lq_sta, - struct ieee80211_conf *conf, - struct sta_info *sta, - struct iwl4965_scale_tbl_info *tbl, int index) -{ - return -1; -} -#endif /*CONFIG_IWL4965_HT */ /* * Set up search table for SISO @@ -1241,7 +1218,6 @@ static int rs_switch_to_siso(struct iwl_priv *priv, struct sta_info *sta, struct iwl4965_scale_tbl_info *tbl, int index) { -#ifdef CONFIG_IWL4965_HT u16 rate_mask; u8 is_green = lq_sta->is_green; s32 rate; @@ -1291,9 +1267,6 @@ static int rs_switch_to_siso(struct iwl_priv *priv, IWL_DEBUG_RATE("LQ: Switch to new mcs %X index is green %X\n", tbl->current_rate, is_green); return 0; -#else - return -1; -#endif /*CONFIG_IWL4965_HT */ } /* @@ -1678,7 +1651,8 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, int high_tpt = IWL_INVALID_VALUE; u32 fail_count; s8 scale_action = 0; - u16 fc, rate_mask; + __le16 fc; + u16 rate_mask; u8 update_lq = 0; struct iwl4965_lq_sta *lq_sta; struct iwl4965_scale_tbl_info *tbl, *tbl1; @@ -1689,13 +1663,11 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, u8 done_search = 0; u16 high_low; s32 sr; -#ifdef CONFIG_IWL4965_HT u8 tid = MAX_TID_COUNT; -#endif IWL_DEBUG_RATE("rate scale calculate new rate for skb\n"); - fc = le16_to_cpu(hdr->frame_control); + fc = hdr->frame_control; if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1)) { /* Send management frames and broadcast/multicast data using * lowest rate. */ @@ -1712,9 +1684,8 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, } lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv; -#ifdef CONFIG_IWL4965_HT - rs_tl_add_packet(lq_sta, hdr); -#endif + tid = rs_tl_add_packet(lq_sta, hdr); + /* * Select rate-scale / modulation-mode table to work with in * the rest of this function: "search" if searching for better @@ -1842,8 +1813,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, tbl = &(lq_sta->lq_info[active_tbl]); /* Revert to "active" rate and throughput info */ - index = iwl4965_hwrate_to_plcp_idx( - tbl->current_rate); + index = iwl_hwrate_to_plcp_idx(tbl->current_rate); current_tpt = lq_sta->last_tpt; /* Need to set up a new rate table in uCode */ @@ -1997,8 +1967,7 @@ lq_update: rs_rate_scale_clear_window(&(tbl->win[i])); /* Use new "search" start rate */ - index = iwl4965_hwrate_to_plcp_idx( - tbl->current_rate); + index = iwl_hwrate_to_plcp_idx(tbl->current_rate); IWL_DEBUG_RATE("Switch current mcs: %X index: %d\n", tbl->current_rate, index); @@ -2013,9 +1982,7 @@ lq_update: * before next round of mode comparisons. */ tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]); if (is_legacy(tbl1->lq_type) && -#ifdef CONFIG_IWL4965_HT (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)) && -#endif (lq_sta->action_counter >= 1)) { lq_sta->action_counter = 0; IWL_DEBUG_RATE("LQ: STAY in legacy table\n"); @@ -2027,14 +1994,12 @@ lq_update: * mode for a while before next round of mode comparisons. */ if (lq_sta->enable_counter && (lq_sta->action_counter >= IWL_ACTION_LIMIT)) { -#ifdef CONFIG_IWL4965_HT if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) && (lq_sta->tx_agg_tid_en & (1 << tid)) && (tid != MAX_TID_COUNT)) { IWL_DEBUG_RATE("try to aggregate tid %d\n", tid); rs_tl_turn_on_agg(priv, tid, lq_sta, sta); } -#endif /*CONFIG_IWL4965_HT */ lq_sta->action_counter = 0; rs_set_stay_in_table(priv, 0, lq_sta); } @@ -2136,7 +2101,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, struct ieee80211_conf *conf = &local->hw.conf; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct sta_info *sta; - u16 fc; + __le16 fc; struct iwl_priv *priv = (struct iwl_priv *)priv_rate; struct iwl4965_lq_sta *lq_sta; @@ -2148,7 +2113,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, /* Send management frames and broadcast/multicast data using lowest * rate. */ - fc = le16_to_cpu(hdr->frame_control); + fc = hdr->frame_control; if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) || !sta || !sta->rate_ctrl_priv) { sel->rate_idx = rate_lowest_index(local, sband, sta); @@ -2279,30 +2244,23 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000); lq_sta->active_rate_basic = priv->active_rate_basic; lq_sta->band = priv->band; -#ifdef CONFIG_IWL4965_HT /* * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3), * supp_rates[] does not; shift to convert format, force 9 MBits off. */ - lq_sta->active_siso_rate = - priv->current_ht_config.supp_mcs_set[0] << 1; - lq_sta->active_siso_rate |= - priv->current_ht_config.supp_mcs_set[0] & 0x1; + lq_sta->active_siso_rate = conf->ht_conf.supp_mcs_set[0] << 1; + lq_sta->active_siso_rate |= conf->ht_conf.supp_mcs_set[0] & 0x1; lq_sta->active_siso_rate &= ~((u16)0x2); lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE; /* Same here */ - lq_sta->active_mimo2_rate = - priv->current_ht_config.supp_mcs_set[1] << 1; - lq_sta->active_mimo2_rate |= - priv->current_ht_config.supp_mcs_set[1] & 0x1; + lq_sta->active_mimo2_rate = conf->ht_conf.supp_mcs_set[1] << 1; + lq_sta->active_mimo2_rate |= conf->ht_conf.supp_mcs_set[1] & 0x1; lq_sta->active_mimo2_rate &= ~((u16)0x2); lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE; - lq_sta->active_mimo3_rate = - priv->current_ht_config.supp_mcs_set[2] << 1; - lq_sta->active_mimo3_rate |= - priv->current_ht_config.supp_mcs_set[2] & 0x1; + lq_sta->active_mimo3_rate = conf->ht_conf.supp_mcs_set[2] << 1; + lq_sta->active_mimo3_rate |= conf->ht_conf.supp_mcs_set[2] & 0x1; lq_sta->active_mimo3_rate &= ~((u16)0x2); lq_sta->active_mimo3_rate <<= IWL_FIRST_OFDM_RATE; @@ -2317,7 +2275,6 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, /* as default allow aggregation for all tids */ lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID; -#endif /*CONFIG_IWL4965_HT*/ #ifdef CONFIG_MAC80211_DEBUGFS lq_sta->drv = priv; #endif @@ -2635,11 +2592,9 @@ static void rs_add_debugfs(void *priv, void *priv_sta, lq_sta->rs_sta_dbgfs_stats_table_file = debugfs_create_file("rate_stats_table", 0600, dir, lq_sta, &rs_sta_dbgfs_stats_table_ops); -#ifdef CONFIG_IWL4965_HT lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file = debugfs_create_u8("tx_agg_tid_enable", 0600, dir, &lq_sta->tx_agg_tid_en); -#endif } @@ -2648,9 +2603,7 @@ static void rs_remove_debugfs(void *priv, void *priv_sta) struct iwl4965_lq_sta *lq_sta = priv_sta; debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file); debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file); -#ifdef CONFIG_IWL4965_HT debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file); -#endif } #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h index 1dd4124227a..cbd12641849 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h @@ -286,8 +286,6 @@ static inline u8 iwl4965_get_prev_ieee_rate(u8 rate_index) return rate; } -extern int iwl4965_hwrate_to_plcp_idx(u32 rate_n_flags); - /** * iwl4965_fill_rs_info - Fill an output text buffer with the rate representation * diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index aee7014bcb9..ab5027345a0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -46,6 +46,9 @@ #include "iwl-calib.h" #include "iwl-sta.h" +static int iwl4965_send_tx_power(struct iwl_priv *priv); +static int iwl4965_hw_get_temperature(const struct iwl_priv *priv); + /* module parameters */ static struct iwl_mod_params iwl4965_mod_params = { .num_of_queues = IWL49_NUM_QUEUES, @@ -281,7 +284,7 @@ static void iwl4965_init_alive_start(struct iwl_priv *priv) } /* Calculate temperature */ - priv->temperature = iwl4965_get_temperature(priv); + priv->temperature = iwl4965_hw_get_temperature(priv); /* Send pointers to protocol/runtime uCode image ... init code will * load and launch runtime uCode, which will send us another "Alive" @@ -305,60 +308,6 @@ static int is_fat_channel(__le32 rxon_flags) (rxon_flags & RXON_FLG_CHANNEL_MODE_MIXED_MSK); } -int iwl4965_hwrate_to_plcp_idx(u32 rate_n_flags) -{ - int idx = 0; - - /* 4965 HT rate format */ - if (rate_n_flags & RATE_MCS_HT_MSK) { - idx = (rate_n_flags & 0xff); - - if (idx >= IWL_RATE_MIMO2_6M_PLCP) - idx = idx - IWL_RATE_MIMO2_6M_PLCP; - - idx += IWL_FIRST_OFDM_RATE; - /* skip 9M not supported in ht*/ - if (idx >= IWL_RATE_9M_INDEX) - idx += 1; - if ((idx >= IWL_FIRST_OFDM_RATE) && (idx <= IWL_LAST_OFDM_RATE)) - return idx; - - /* 4965 legacy rate format, search for match in table */ - } else { - for (idx = 0; idx < ARRAY_SIZE(iwl_rates); idx++) - if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF)) - return idx; - } - - return -1; -} - -/** - * translate ucode response to mac80211 tx status control values - */ -void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, - struct ieee80211_tx_info *control) -{ - int rate_index; - - control->antenna_sel_tx = - ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); - if (rate_n_flags & RATE_MCS_HT_MSK) - control->flags |= IEEE80211_TX_CTL_OFDM_HT; - if (rate_n_flags & RATE_MCS_GF_MSK) - control->flags |= IEEE80211_TX_CTL_GREEN_FIELD; - if (rate_n_flags & RATE_MCS_FAT_MSK) - control->flags |= IEEE80211_TX_CTL_40_MHZ_WIDTH; - if (rate_n_flags & RATE_MCS_DUP_MSK) - control->flags |= IEEE80211_TX_CTL_DUP_DATA; - if (rate_n_flags & RATE_MCS_SGI_MSK) - control->flags |= IEEE80211_TX_CTL_SHORT_GI; - rate_index = iwl4965_hwrate_to_plcp_idx(rate_n_flags); - if (control->band == IEEE80211_BAND_5GHZ) - rate_index -= IWL_FIRST_OFDM_RATE; - control->tx_rate_idx = rate_index; -} - /* * EEPROM handlers */ @@ -608,52 +557,6 @@ out: #define REG_RECALIB_PERIOD (60) -/** - * iwl4965_bg_statistics_periodic - Timer callback to queue statistics - * - * This callback is provided in order to send a statistics request. - * - * This timer function is continually reset to execute within - * REG_RECALIB_PERIOD seconds since the last STATISTICS_NOTIFICATION - * was received. We need to ensure we receive the statistics in order - * to update the temperature used for calibrating the TXPOWER. - */ -static void iwl4965_bg_statistics_periodic(unsigned long data) -{ - struct iwl_priv *priv = (struct iwl_priv *)data; - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - iwl_send_statistics_request(priv, CMD_ASYNC); -} - -void iwl4965_rf_kill_ct_config(struct iwl_priv *priv) -{ - struct iwl4965_ct_kill_config cmd; - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&priv->lock, flags); - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, - CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); - spin_unlock_irqrestore(&priv->lock, flags); - - cmd.critical_temperature_R = - cpu_to_le32(priv->hw_params.ct_kill_threshold); - - ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, - sizeof(cmd), &cmd); - if (ret) - IWL_ERROR("REPLY_CT_KILL_CONFIG_CMD failed\n"); - else - IWL_DEBUG_INFO("REPLY_CT_KILL_CONFIG_CMD succeeded, " - "critical temperature is %d\n", - cmd.critical_temperature_R); -} - -#ifdef CONFIG_IWL4965_RUN_TIME_CALIB - /* Reset differential Rx gains in NIC to prepare for chain noise calibration. * Called after every association, but this runs only once! * ... once chain noise is calibrated the first time, it's good forever. */ @@ -741,30 +644,6 @@ static void iwl4965_gain_computation(struct iwl_priv *priv, data->beacon_count = 0; } -static void iwl4965_bg_sensitivity_work(struct work_struct *work) -{ - struct iwl_priv *priv = container_of(work, struct iwl_priv, - sensitivity_work); - - mutex_lock(&priv->mutex); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status) || - test_bit(STATUS_SCANNING, &priv->status)) { - mutex_unlock(&priv->mutex); - return; - } - - if (priv->start_calib) { - iwl_chain_noise_calibration(priv, &priv->statistics); - - iwl_sensitivity_calibration(priv, &priv->statistics); - } - - mutex_unlock(&priv->mutex); - return; -} -#endif /*CONFIG_IWL4965_RUN_TIME_CALIB*/ - static void iwl4965_bg_txpower_work(struct work_struct *work) { struct iwl_priv *priv = container_of(work, struct iwl_priv, @@ -783,7 +662,7 @@ static void iwl4965_bg_txpower_work(struct work_struct *work) /* Regardless of if we are assocaited, we must reconfigure the * TX power since frames can be sent on non-radar channels while * not associated */ - iwl4965_hw_reg_send_txpower(priv); + iwl4965_send_tx_power(priv); /* Update last_temperature to keep is_calib_needed from running * when it isn't needed... */ @@ -843,7 +722,7 @@ static const u16 default_queue_to_tx_fifo[] = { IWL_TX_FIFO_HCCA_2 }; -int iwl4965_alive_notify(struct iwl_priv *priv) +static int iwl4965_alive_notify(struct iwl_priv *priv) { u32 a; int i = 0; @@ -920,7 +799,6 @@ int iwl4965_alive_notify(struct iwl_priv *priv) return ret; } -#ifdef CONFIG_IWL4965_RUN_TIME_CALIB static struct iwl_sensitivity_ranges iwl4965_sensitivity = { .min_nrg_cck = 97, .max_nrg_cck = 0, @@ -943,14 +821,13 @@ static struct iwl_sensitivity_ranges iwl4965_sensitivity = { .nrg_th_cck = 100, .nrg_th_ofdm = 100, }; -#endif /** * iwl4965_hw_set_hw_params * * Called when initializing driver */ -int iwl4965_hw_set_hw_params(struct iwl_priv *priv) +static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) { if ((priv->cfg->mod_params->num_of_queues > IWL49_NUM_QUEUES) || @@ -961,6 +838,7 @@ int iwl4965_hw_set_hw_params(struct iwl_priv *priv) } priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; + priv->hw_params.first_ampdu_q = IWL49_FIRST_AMPDU_QUEUE; priv->hw_params.sw_crypto = priv->cfg->mod_params->sw_crypto; priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; @@ -983,9 +861,7 @@ int iwl4965_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.valid_rx_ant = ANT_A | ANT_B; priv->hw_params.ct_kill_threshold = CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD); -#ifdef CONFIG_IWL4965_RUN_TIME_CALIB priv->hw_params.sens = &iwl4965_sensitivity; -#endif return 0; } @@ -1001,11 +877,6 @@ static int iwl4965_set_power(struct iwl_priv *priv, cmd, NULL); return ret; } -int iwl4965_hw_reg_set_txpower(struct iwl_priv *priv, s8 power) -{ - IWL_ERROR("TODO: Implement iwl4965_hw_reg_set_txpower!\n"); - return -EINVAL; -} static s32 iwl4965_math_div_round(s32 num, s32 denom, s32 *res) { @@ -1056,20 +927,6 @@ static s32 iwl4965_get_voltage_compensation(s32 eeprom_voltage, return comp; } -static const struct iwl_channel_info * -iwl4965_get_channel_txpower_info(struct iwl_priv *priv, - enum ieee80211_band band, u16 channel) -{ - const struct iwl_channel_info *ch_info; - - ch_info = iwl_get_channel_info(priv, band, channel); - - if (!is_channel_valid(ch_info)) - return NULL; - - return ch_info; -} - static s32 iwl4965_get_tx_atten_grp(u16 channel) { if (channel >= CALIB_IWL_TX_ATTEN_GR5_FCH && @@ -1493,30 +1350,17 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, s32 factory_actual_pwr[2]; s32 power_index; - /* Sanity check requested level (dBm) */ - if (priv->user_txpower_limit < IWL_TX_POWER_TARGET_POWER_MIN) { - IWL_WARNING("Requested user TXPOWER %d below limit.\n", - priv->user_txpower_limit); - return -EINVAL; - } - if (priv->user_txpower_limit > IWL_TX_POWER_TARGET_POWER_MAX) { - IWL_WARNING("Requested user TXPOWER %d above limit.\n", - priv->user_txpower_limit); - return -EINVAL; - } - /* user_txpower_limit is in dBm, convert to half-dBm (half-dB units * are used for indexing into txpower table) */ - user_target_power = 2 * priv->user_txpower_limit; + user_target_power = 2 * priv->tx_power_user_lmt; /* Get current (RXON) channel, band, width */ - ch_info = - iwl4965_get_channel_txpower_info(priv, priv->band, channel); - IWL_DEBUG_TXPOWER("chan %d band %d is_fat %d\n", channel, band, is_fat); - if (!ch_info) + ch_info = iwl_get_channel_info(priv, priv->band, channel); + + if (!is_channel_valid(ch_info)) return -EINVAL; /* get txatten group, used to select 1) thermal txpower adjustment @@ -1717,12 +1561,12 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, } /** - * iwl4965_hw_reg_send_txpower - Configure the TXPOWER level user limit + * iwl4965_send_tx_power - Configure the TXPOWER level user limit * * Uses the active RXON for channel, band, and characteristics (fat, high) - * The power limit is taken from priv->user_txpower_limit. + * The power limit is taken from priv->tx_power_user_lmt. */ -int iwl4965_hw_reg_send_txpower(struct iwl_priv *priv) +static int iwl4965_send_tx_power(struct iwl_priv *priv) { struct iwl4965_txpowertable_cmd cmd = { 0 }; int ret; @@ -1848,11 +1692,6 @@ static int iwl4965_shared_mem_rx_idx(struct iwl_priv *priv) return le32_to_cpu(s->rb_closed) & 0xFFF; } -int iwl4965_hw_get_temperature(struct iwl_priv *priv) -{ - return priv->temperature; -} - unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv, struct iwl_frame *frame, u8 rate) { @@ -1875,10 +1714,10 @@ unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv, if ((rate == IWL_RATE_1M_PLCP) || (rate >= IWL_RATE_2M_PLCP)) tx_beacon_cmd->tx.rate_n_flags = - iwl4965_hw_set_rate_n_flags(rate, RATE_MCS_CCK_MSK); + iwl_hw_set_rate_n_flags(rate, RATE_MCS_CCK_MSK); else tx_beacon_cmd->tx.rate_n_flags = - iwl4965_hw_set_rate_n_flags(rate, 0); + iwl_hw_set_rate_n_flags(rate, 0); tx_beacon_cmd->tx.tx_flags = (TX_CMD_FLG_SEQ_CTL_MSK | TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK); @@ -1950,12 +1789,12 @@ static s32 sign_extend(u32 oper, int index) } /** - * iwl4965_get_temperature - return the calibrated temperature (in Kelvin) + * iwl4965_hw_get_temperature - return the calibrated temperature (in Kelvin) * @statistics: Provides the temperature reading from the uCode * * A return of <0 indicates bogus data in the statistics */ -int iwl4965_get_temperature(const struct iwl_priv *priv) +static int iwl4965_hw_get_temperature(const struct iwl_priv *priv) { s32 temperature; s32 vt; @@ -1990,8 +1829,7 @@ int iwl4965_get_temperature(const struct iwl_priv *priv) vt = sign_extend( le32_to_cpu(priv->statistics.general.temperature), 23); - IWL_DEBUG_TEMP("Calib values R[1-3]: %d %d %d R4: %d\n", - R1, R2, R3, vt); + IWL_DEBUG_TEMP("Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt); if (R3 == R1) { IWL_ERROR("Calibration conflict R1 == R3\n"); @@ -2002,11 +1840,10 @@ int iwl4965_get_temperature(const struct iwl_priv *priv) * Add offset to center the adjustment around 0 degrees Centigrade. */ temperature = TEMPERATURE_CALIB_A_VAL * (vt - R2); temperature /= (R3 - R1); - temperature = (temperature * 97) / 100 + - TEMPERATURE_CALIB_KELVIN_OFFSET; + temperature = (temperature * 97) / 100 + TEMPERATURE_CALIB_KELVIN_OFFSET; - IWL_DEBUG_TEMP("Calibrated temperature: %dK, %dC\n", temperature, - KELVIN_TO_CELSIUS(temperature)); + IWL_DEBUG_TEMP("Calibrated temperature: %dK, %dC\n", + temperature, KELVIN_TO_CELSIUS(temperature)); return temperature; } @@ -2123,9 +1960,7 @@ void iwl4965_hw_rx_statistics(struct iwl_priv *priv, if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) && (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) { iwl4965_rx_calc_noise(priv); -#ifdef CONFIG_IWL4965_RUN_TIME_CALIB - queue_work(priv->workqueue, &priv->sensitivity_work); -#endif + queue_work(priv->workqueue, &priv->run_time_calib_work); } iwl_leds_background(priv); @@ -2136,7 +1971,7 @@ void iwl4965_hw_rx_statistics(struct iwl_priv *priv, if (!change) return; - temp = iwl4965_get_temperature(priv); + temp = iwl4965_hw_get_temperature(priv); if (temp < 0) return; @@ -2155,8 +1990,9 @@ void iwl4965_hw_rx_statistics(struct iwl_priv *priv, priv->temperature = temp; set_bit(STATUS_TEMPERATURE, &priv->status); - if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) && - iwl4965_is_temp_calib_needed(priv)) + if (!priv->disable_tx_power_cal && + unlikely(!test_bit(STATUS_SCANNING, &priv->status)) && + iwl4965_is_temp_calib_needed(priv)) queue_work(priv->workqueue, &priv->txpower_work); } @@ -2552,7 +2388,7 @@ static void iwl4965_dbg_report_frame(struct iwl_priv *priv, u32 print_dump = 0; /* set to 1 to dump all frames' contents */ u32 hundred = 0; u32 dataframe = 0; - u16 fc; + __le16 fc; u16 seq_ctl; u16 channel; u16 phy_flags; @@ -2575,7 +2411,7 @@ static void iwl4965_dbg_report_frame(struct iwl_priv *priv, return; /* MAC header */ - fc = le16_to_cpu(header->frame_control); + fc = header->frame_control; seq_ctl = le16_to_cpu(header->seq_ctrl); /* metadata */ @@ -2600,8 +2436,8 @@ static void iwl4965_dbg_report_frame(struct iwl_priv *priv, /* if data frame is to us and all is good, * (optionally) print summary for only 1 out of every 100 */ - if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) == - (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { + if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) == + cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { dataframe = 1; if (!group100) print_summary = 1; /* print each frame */ @@ -2625,13 +2461,13 @@ static void iwl4965_dbg_report_frame(struct iwl_priv *priv, if (hundred) title = "100Frames"; - else if (fc & IEEE80211_FCTL_RETRY) + else if (ieee80211_has_retry(fc)) title = "Retry"; - else if (ieee80211_is_assoc_response(fc)) + else if (ieee80211_is_assoc_resp(fc)) title = "AscRsp"; - else if (ieee80211_is_reassoc_response(fc)) + else if (ieee80211_is_reassoc_resp(fc)) title = "RasRsp"; - else if (ieee80211_is_probe_response(fc)) { + else if (ieee80211_is_probe_resp(fc)) { title = "PrbRsp"; print_dump = 1; /* dump frame contents */ } else if (ieee80211_is_beacon(fc)) { @@ -2648,7 +2484,7 @@ static void iwl4965_dbg_report_frame(struct iwl_priv *priv, else title = "Frame"; - rate_idx = iwl4965_hwrate_to_plcp_idx(rate_sym); + rate_idx = iwl_hwrate_to_plcp_idx(rate_sym); if (unlikely(rate_idx == -1)) bitrate = 0; else @@ -2660,14 +2496,14 @@ static void iwl4965_dbg_report_frame(struct iwl_priv *priv, if (dataframe) IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, " "len=%u, rssi=%d, chnl=%d, rate=%u, \n", - title, fc, header->addr1[5], + title, le16_to_cpu(fc), header->addr1[5], length, rssi, channel, bitrate); else { /* src/dst addresses assume managed mode */ IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, " "src=0x%02x, rssi=%u, tim=%lu usec, " "phy=0x%02x, chnl=%d\n", - title, fc, header->addr1[5], + title, le16_to_cpu(fc), header->addr1[5], header->addr3[5], rssi, tsf_low - priv->scan_start_tsf, phy_flags, channel); @@ -2713,7 +2549,7 @@ void iwl4965_rx_reply_rx(struct iwl_priv *priv, rx_status.band = (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; rx_status.rate_idx = - iwl4965_hwrate_to_plcp_idx(le32_to_cpu(rx_start->rate_n_flags)); + iwl_hwrate_to_plcp_idx(le32_to_cpu(rx_start->rate_n_flags)); if (rx_status.band == IEEE80211_BAND_5GHZ) rx_status.rate_idx -= IWL_FIRST_OFDM_RATE; @@ -2819,7 +2655,6 @@ void iwl4965_rx_reply_rx(struct iwl_priv *priv, break; case IEEE80211_FTYPE_CTL: -#ifdef CONFIG_IWL4965_HT switch (fc & IEEE80211_FCTL_STYPE) { case IEEE80211_STYPE_BACK_REQ: IWL_DEBUG_HT("IEEE80211_STYPE_BACK_REQ arrived\n"); @@ -2829,7 +2664,6 @@ void iwl4965_rx_reply_rx(struct iwl_priv *priv, default: break; } -#endif break; case IEEE80211_FTYPE_DATA: { @@ -2863,8 +2697,6 @@ void iwl4965_rx_reply_rx(struct iwl_priv *priv, } } -#ifdef CONFIG_IWL4965_HT - /** * iwl4965_tx_status_reply_compressed_ba - Update tx status from block-ack * @@ -2926,7 +2758,7 @@ static int iwl4965_tx_status_reply_compressed_ba(struct iwl_priv *priv, info->flags |= IEEE80211_TX_STAT_AMPDU; info->status.ampdu_ack_map = successes; info->status.ampdu_ack_len = agg->frame_count; - iwl4965_hwrate_to_tx_control(priv, agg->rate_n_flags, info); + iwl_hwrate_to_tx_control(priv, agg->rate_n_flags, info); IWL_DEBUG_TX_REPLY("Bitmap %llx\n", (unsigned long long)bitmap); @@ -2948,7 +2780,7 @@ static void iwl4965_tx_queue_stop_scheduler(struct iwl_priv *priv, } /** - * txq_id must be greater than IWL_BACK_QUEUE_FIRST_ID + * txq_id must be greater than IWL49_FIRST_AMPDU_QUEUE * priv->lock must be held by the caller */ static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, @@ -2956,9 +2788,9 @@ static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, { int ret = 0; - if (IWL_BACK_QUEUE_FIRST_ID > txq_id) { + if (IWL49_FIRST_AMPDU_QUEUE > txq_id) { IWL_WARNING("queue number too small: %d, must be > %d\n", - txq_id, IWL_BACK_QUEUE_FIRST_ID); + txq_id, IWL49_FIRST_AMPDU_QUEUE); return -EINVAL; } @@ -3046,7 +2878,7 @@ static void iwl4965_rx_reply_compressed_ba(struct iwl_priv *priv, if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) { /* calculate mac80211 ampdu sw queue to wake */ int ampdu_q = - scd_flow - IWL_BACK_QUEUE_FIRST_ID + priv->hw->queues; + scd_flow - priv->hw_params.first_ampdu_q + priv->hw->queues; int freed = iwl_tx_queue_reclaim(priv, scd_flow, index); priv->stations[ba_resp->sta_id]. tid[ba_resp->tid].tfds_in_queue -= freed; @@ -3091,7 +2923,7 @@ static int iwl4965_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, /** * iwl4965_tx_queue_agg_enable - Set up & enable aggregation for selected queue * - * NOTE: txq_id must be greater than IWL_BACK_QUEUE_FIRST_ID, + * NOTE: txq_id must be greater than IWL49_FIRST_AMPDU_QUEUE, * i.e. it must be one of the higher queues used for aggregation */ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id, @@ -3101,9 +2933,9 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id, int ret; u16 ra_tid; - if (IWL_BACK_QUEUE_FIRST_ID > txq_id) + if (IWL49_FIRST_AMPDU_QUEUE > txq_id) IWL_WARNING("queue number too small: %d, must be > %d\n", - txq_id, IWL_BACK_QUEUE_FIRST_ID); + txq_id, IWL49_FIRST_AMPDU_QUEUE); ra_tid = BUILD_RAxTID(sta_id, tid); @@ -3154,10 +2986,6 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id, return 0; } -#endif /* CONFIG_IWL4965_HT */ - - -#ifdef CONFIG_IWL4965_HT static int iwl4965_rx_agg_start(struct iwl_priv *priv, const u8 *addr, int tid, u16 ssn) { @@ -3231,8 +3059,6 @@ int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, } return 0; } -#endif /* CONFIG_IWL4965_HT */ - static u16 iwl4965_get_hcmd_size(u8 cmd_id, u16 len) { @@ -3262,13 +3088,9 @@ static u16 iwl4965_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) return (u16)sizeof(struct iwl4965_addsta_cmd); } -#ifdef CONFIG_IWL4965_HT static inline u32 iwl4965_get_scd_ssn(struct iwl4965_tx_resp *tx_resp) { - __le32 *scd_ssn = (__le32 *)((u32 *)&tx_resp->status + - tx_resp->frame_count); - return le32_to_cpu(*scd_ssn) & MAX_SN; - + return le32_to_cpup(&tx_resp->u.status + tx_resp->frame_count) & MAX_SN; } /** @@ -3276,32 +3098,29 @@ static inline u32 iwl4965_get_scd_ssn(struct iwl4965_tx_resp *tx_resp) */ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, struct iwl_ht_agg *agg, - struct iwl4965_tx_resp_agg *tx_resp, - u16 start_idx) + struct iwl4965_tx_resp *tx_resp, + int txq_id, u16 start_idx) { u16 status; - struct agg_tx_status *frame_status = &tx_resp->status; + struct agg_tx_status *frame_status = tx_resp->u.agg_status; struct ieee80211_tx_info *info = NULL; struct ieee80211_hdr *hdr = NULL; - int i, sh; - int txq_id, idx; + u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); + int i, sh, idx; u16 seq; - if (agg->wait_for_ba) IWL_DEBUG_TX_REPLY("got tx response w/o block-ack\n"); agg->frame_count = tx_resp->frame_count; agg->start_idx = start_idx; - agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); + agg->rate_n_flags = rate_n_flags; agg->bitmap = 0; /* # frames attempted by Tx command */ if (agg->frame_count == 1) { /* Only one frame was attempted; no block-ack will arrive */ status = le16_to_cpu(frame_status[0].status); - seq = le16_to_cpu(frame_status[0].sequence); - idx = SEQ_TO_INDEX(seq); - txq_id = SEQ_TO_QUEUE(seq); + idx = start_idx; /* FIXME: code repetition */ IWL_DEBUG_TX_REPLY("FrameCnt = %d, StartIdx=%d idx=%d\n", @@ -3312,15 +3131,12 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, info->flags &= ~IEEE80211_TX_CTL_AMPDU; info->flags |= iwl_is_tx_success(status)? IEEE80211_TX_STAT_ACK : 0; - iwl4965_hwrate_to_tx_control(priv, - le32_to_cpu(tx_resp->rate_n_flags), - info); + iwl_hwrate_to_tx_control(priv, rate_n_flags, info); /* FIXME: code repetition end */ IWL_DEBUG_TX_REPLY("1 Frame 0x%x failure :%d\n", status & 0xff, tx_resp->failure_frame); - IWL_DEBUG_TX_REPLY("Rate Info rate_n_flags=%x\n", - iwl4965_hw_get_rate_n_flags(tx_resp->rate_n_flags)); + IWL_DEBUG_TX_REPLY("Rate Info rate_n_flags=%x\n", rate_n_flags); agg->wait_for_ba = 0; } else { @@ -3378,7 +3194,6 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, agg->bitmap = bitmap; agg->start_idx = start; - agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); IWL_DEBUG_TX_REPLY("Frames %d start_idx=%d bitmap=0x%llx\n", agg->frame_count, agg->start_idx, (unsigned long long)agg->bitmap); @@ -3388,7 +3203,6 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, } return 0; } -#endif /** * iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response @@ -3403,13 +3217,11 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct ieee80211_tx_info *info; struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; - u32 status = le32_to_cpu(tx_resp->status); -#ifdef CONFIG_IWL4965_HT + u32 status = le32_to_cpu(tx_resp->u.status); int tid = MAX_TID_COUNT, sta_id = IWL_INVALID_STATION; - u16 fc; + __le16 fc; struct ieee80211_hdr *hdr; u8 *qc = NULL; -#endif if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { IWL_ERROR("Read index for DMA queue txq_id (%d) index %d " @@ -3422,11 +3234,10 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); memset(&info->status, 0, sizeof(info->status)); -#ifdef CONFIG_IWL4965_HT hdr = iwl_tx_queue_get_hdr(priv, txq_id, index); - fc = le16_to_cpu(hdr->frame_control); - if (ieee80211_is_qos_data(fc)) { - qc = ieee80211_get_qos_ctrl(hdr, ieee80211_get_hdrlen(fc)); + fc = hdr->frame_control; + if (ieee80211_is_data_qos(fc)) { + qc = ieee80211_get_qos_ctl(hdr); tid = qc[0] & 0xf; } @@ -3445,8 +3256,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, agg = &priv->stations[sta_id].tid[tid].agg; - iwl4965_tx_status_reply_tx(priv, agg, - (struct iwl4965_tx_resp_agg *)tx_resp, index); + iwl4965_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) { /* TODO: send BAR */ @@ -3464,7 +3274,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, txq_id >= 0 && priv->mac80211_registered && agg->state != IWL_EMPTYING_HW_QUEUE_DELBA) { /* calculate mac80211 ampdu sw queue to wake */ - ampdu_q = txq_id - IWL_BACK_QUEUE_FIRST_ID + + ampdu_q = txq_id - IWL49_FIRST_AMPDU_QUEUE + priv->hw->queues; if (agg->state == IWL_AGG_OFF) ieee80211_wake_queue(priv->hw, txq_id); @@ -3474,32 +3284,32 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, iwl_txq_check_empty(priv, sta_id, tid, txq_id); } } else { -#endif /* CONFIG_IWL4965_HT */ - - info->status.retry_count = tx_resp->failure_frame; - info->flags |= iwl_is_tx_success(status) ? IEEE80211_TX_STAT_ACK : 0; - iwl4965_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags), - info); - - IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags 0x%x " - "retries %d\n", txq_id, iwl_get_tx_fail_reason(status), - status, le32_to_cpu(tx_resp->rate_n_flags), - tx_resp->failure_frame); - - IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index); -#ifdef CONFIG_IWL4965_HT - if (index != -1) { - int freed = iwl_tx_queue_reclaim(priv, txq_id, index); - if (tid != MAX_TID_COUNT) + info->status.retry_count = tx_resp->failure_frame; + info->flags |= + iwl_is_tx_success(status) ? IEEE80211_TX_STAT_ACK : 0; + iwl_hwrate_to_tx_control(priv, + le32_to_cpu(tx_resp->rate_n_flags), + info); + + IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags " + "0x%x retries %d\n", txq_id, + iwl_get_tx_fail_reason(status), + status, le32_to_cpu(tx_resp->rate_n_flags), + tx_resp->failure_frame); + + IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index); + + if (index != -1) { + int freed = iwl_tx_queue_reclaim(priv, txq_id, index); + if (tid != MAX_TID_COUNT) priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; - if (iwl_queue_space(&txq->q) > txq->q.low_mark && + if (iwl_queue_space(&txq->q) > txq->q.low_mark && (txq_id >= 0) && priv->mac80211_registered) ieee80211_wake_queue(priv->hw, txq_id); - if (tid != MAX_TID_COUNT) + if (tid != MAX_TID_COUNT) iwl_txq_check_empty(priv, sta_id, tid, txq_id); + } } - } -#endif /* CONFIG_IWL4965_HT */ if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n"); @@ -3513,28 +3323,18 @@ static void iwl4965_rx_handler_setup(struct iwl_priv *priv) priv->rx_handlers[REPLY_RX] = iwl4965_rx_reply_rx; /* Tx response */ priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx; - -#ifdef CONFIG_IWL4965_HT + /* block ack */ priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl4965_rx_reply_compressed_ba; -#endif /* CONFIG_IWL4965_HT */ } -void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv) +static void iwl4965_setup_deferred_work(struct iwl_priv *priv) { INIT_WORK(&priv->txpower_work, iwl4965_bg_txpower_work); -#ifdef CONFIG_IWL4965_RUN_TIME_CALIB - INIT_WORK(&priv->sensitivity_work, iwl4965_bg_sensitivity_work); -#endif - init_timer(&priv->statistics_periodic); - priv->statistics_periodic.data = (unsigned long)priv; - priv->statistics_periodic.function = iwl4965_bg_statistics_periodic; } -void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv) +static void iwl4965_cancel_deferred_work(struct iwl_priv *priv) { - del_timer_sync(&priv->statistics_periodic); - - cancel_delayed_work(&priv->init_alive_start); + cancel_work_sync(&priv->txpower_work); } @@ -3545,10 +3345,8 @@ static struct iwl_hcmd_ops iwl4965_hcmd = { static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { .get_hcmd_size = iwl4965_get_hcmd_size, .build_addsta_hcmd = iwl4965_build_addsta_hcmd, -#ifdef CONFIG_IWL4965_RUN_TIME_CALIB .chain_noise_reset = iwl4965_chain_noise_reset, .gain_computation = iwl4965_gain_computation, -#endif }; static struct iwl_lib_ops iwl4965_lib = { @@ -3558,11 +3356,11 @@ static struct iwl_lib_ops iwl4965_lib = { .shared_mem_rx_idx = iwl4965_shared_mem_rx_idx, .txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl, .txq_set_sched = iwl4965_txq_set_sched, -#ifdef CONFIG_IWL4965_HT .txq_agg_enable = iwl4965_txq_agg_enable, .txq_agg_disable = iwl4965_txq_agg_disable, -#endif .rx_handler_setup = iwl4965_rx_handler_setup, + .setup_deferred_work = iwl4965_setup_deferred_work, + .cancel_deferred_work = iwl4965_cancel_deferred_work, .is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr, .alive_notify = iwl4965_alive_notify, .init_alive_start = iwl4965_init_alive_start, @@ -3590,8 +3388,8 @@ static struct iwl_lib_ops iwl4965_lib = { .check_version = iwl4965_eeprom_check_version, .query_addr = iwlcore_eeprom_query_addr, }, - .radio_kill_sw = iwl4965_radio_kill_sw, .set_power = iwl4965_set_power, + .send_tx_power = iwl4965_send_tx_power, .update_chain_flags = iwl4965_update_chain_flags, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h index 9e557ce315b..4efe0c06b5b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h @@ -81,7 +81,7 @@ #define IWL50_QUEUE_SIZE 256 #define IWL50_CMD_FIFO_NUM 7 #define IWL50_NUM_QUEUES 20 -#define IWL50_BACK_QUEUE_FIRST_ID 10 +#define IWL50_FIRST_AMPDU_QUEUE 10 #define IWL_sta_id_POS 12 #define IWL_sta_id_LEN 4 diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 7e525ad4513..438c3812c39 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -41,6 +41,7 @@ #include "iwl-dev.h" #include "iwl-core.h" #include "iwl-io.h" +#include "iwl-sta.h" #include "iwl-helpers.h" #include "iwl-5000-hw.h" @@ -300,8 +301,6 @@ err: } -#ifdef CONFIG_IWL5000_RUN_TIME_CALIB - static void iwl5000_gain_computation(struct iwl_priv *priv, u32 average_noise[NUM_RX_CHAINS], u16 min_average_noise_antenna_i, @@ -354,7 +353,6 @@ static void iwl5000_gain_computation(struct iwl_priv *priv, data->beacon_count = 0; } - static void iwl5000_chain_noise_reset(struct iwl_priv *priv) { struct iwl_chain_noise_data *data = &priv->chain_noise_data; @@ -393,10 +391,6 @@ static struct iwl_sensitivity_ranges iwl5000_sensitivity = { .nrg_th_ofdm = 95, }; -#endif /* CONFIG_IWL5000_RUN_TIME_CALIB */ - - - static const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv, size_t offset) { @@ -832,6 +826,7 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) } priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; + priv->hw_params.first_ampdu_q = IWL50_FIRST_AMPDU_QUEUE; priv->hw_params.sw_crypto = priv->cfg->mod_params->sw_crypto; priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; @@ -847,9 +842,7 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.max_bsm_size = BSM_SRAM_SIZE; priv->hw_params.fat_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); -#ifdef CONFIG_IWL5000_RUN_TIME_CALIB priv->hw_params.sens = &iwl5000_sensitivity; -#endif switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { case CSR_HW_REV_TYPE_5100: @@ -984,6 +977,135 @@ static void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, } } +static int iwl5000_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, + u16 txq_id) +{ + u32 tbl_dw_addr; + u32 tbl_dw; + u16 scd_q2ratid; + + scd_q2ratid = ra_tid & IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK; + + tbl_dw_addr = priv->scd_base_addr + + IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id); + + tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr); + + if (txq_id & 0x1) + tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); + else + tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); + + iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw); + + return 0; +} +static void iwl5000_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id) +{ + /* Simply stop the queue, but don't change any configuration; + * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ + iwl_write_prph(priv, + IWL50_SCD_QUEUE_STATUS_BITS(txq_id), + (0 << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE)| + (1 << IWL50_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); +} + +static int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id, + int tx_fifo, int sta_id, int tid, u16 ssn_idx) +{ + unsigned long flags; + int ret; + u16 ra_tid; + + if (IWL50_FIRST_AMPDU_QUEUE > txq_id) + IWL_WARNING("queue number too small: %d, must be > %d\n", + txq_id, IWL50_FIRST_AMPDU_QUEUE); + + ra_tid = BUILD_RAxTID(sta_id, tid); + + /* Modify device's station table to Tx this TID */ + iwl_sta_modify_enable_tid_tx(priv, sta_id, tid); + + spin_lock_irqsave(&priv->lock, flags); + ret = iwl_grab_nic_access(priv); + if (ret) { + spin_unlock_irqrestore(&priv->lock, flags); + return ret; + } + + /* Stop this Tx queue before configuring it */ + iwl5000_tx_queue_stop_scheduler(priv, txq_id); + + /* Map receiver-address / traffic-ID to this queue */ + iwl5000_tx_queue_set_q2ratid(priv, ra_tid, txq_id); + + /* Set this queue as a chain-building queue */ + iwl_set_bits_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, (1<<txq_id)); + + /* enable aggregations for the queue */ + iwl_set_bits_prph(priv, IWL50_SCD_AGGR_SEL, (1<<txq_id)); + + /* Place first TFD at index corresponding to start sequence number. + * Assumes that ssn_idx is valid (!= 0xFFF) */ + priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); + priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); + iwl5000_set_wr_ptrs(priv, txq_id, ssn_idx); + + /* Set up Tx window size and frame limit for this queue */ + iwl_write_targ_mem(priv, priv->scd_base_addr + + IWL50_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + + sizeof(u32), + ((SCD_WIN_SIZE << + IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & + IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | + ((SCD_FRAME_LIMIT << + IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & + IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); + + iwl_set_bits_prph(priv, IWL50_SCD_INTERRUPT_MASK, (1 << txq_id)); + + /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ + iwl5000_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); + + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} + +static int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, + u16 ssn_idx, u8 tx_fifo) +{ + int ret; + + if (IWL50_FIRST_AMPDU_QUEUE > txq_id) { + IWL_WARNING("queue number too small: %d, must be > %d\n", + txq_id, IWL50_FIRST_AMPDU_QUEUE); + return -EINVAL; + } + + ret = iwl_grab_nic_access(priv); + if (ret) + return ret; + + iwl5000_tx_queue_stop_scheduler(priv, txq_id); + + iwl_clear_bits_prph(priv, IWL50_SCD_AGGR_SEL, (1 << txq_id)); + + priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); + priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); + /* supposes that ssn_idx is valid (!= 0xFFF) */ + iwl5000_set_wr_ptrs(priv, txq_id, ssn_idx); + + iwl_clear_bits_prph(priv, IWL50_SCD_INTERRUPT_MASK, (1 << txq_id)); + iwl_txq_ctx_deactivate(priv, txq_id); + iwl5000_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); + + iwl_release_nic_access(priv); + + return 0; +} + static u16 iwl5000_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) { u16 size = (u16)sizeof(struct iwl_addsta_cmd); @@ -1004,23 +1126,21 @@ static void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask) static inline u32 iwl5000_get_scd_ssn(struct iwl5000_tx_resp *tx_resp) { - __le32 *scd_ssn = (__le32 *)((u32 *)&tx_resp->status + - tx_resp->frame_count); - return le32_to_cpu(*scd_ssn) & MAX_SN; - + return le32_to_cpup((__le32*)&tx_resp->status + + tx_resp->frame_count) & MAX_SN; } static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, struct iwl_ht_agg *agg, struct iwl5000_tx_resp *tx_resp, - u16 start_idx) + int txq_id, u16 start_idx) { u16 status; struct agg_tx_status *frame_status = &tx_resp->status; struct ieee80211_tx_info *info = NULL; struct ieee80211_hdr *hdr = NULL; - int i, sh; - int txq_id, idx; + u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); + int i, sh, idx; u16 seq; if (agg->wait_for_ba) @@ -1028,16 +1148,14 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, agg->frame_count = tx_resp->frame_count; agg->start_idx = start_idx; - agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); + agg->rate_n_flags = rate_n_flags; agg->bitmap = 0; /* # frames attempted by Tx command */ if (agg->frame_count == 1) { /* Only one frame was attempted; no block-ack will arrive */ status = le16_to_cpu(frame_status[0].status); - seq = le16_to_cpu(frame_status[0].sequence); - idx = SEQ_TO_INDEX(seq); - txq_id = SEQ_TO_QUEUE(seq); + idx = start_idx; /* FIXME: code repetition */ IWL_DEBUG_TX_REPLY("FrameCnt = %d, StartIdx=%d idx=%d\n", @@ -1048,15 +1166,13 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, info->flags &= ~IEEE80211_TX_CTL_AMPDU; info->flags |= iwl_is_tx_success(status)? IEEE80211_TX_STAT_ACK : 0; - iwl4965_hwrate_to_tx_control(priv, - le32_to_cpu(tx_resp->rate_n_flags), - info); + iwl_hwrate_to_tx_control(priv, rate_n_flags, info); + /* FIXME: code repetition end */ IWL_DEBUG_TX_REPLY("1 Frame 0x%x failure :%d\n", status & 0xff, tx_resp->failure_frame); - IWL_DEBUG_TX_REPLY("Rate Info rate_n_flags=%x\n", - iwl4965_hw_get_rate_n_flags(tx_resp->rate_n_flags)); + IWL_DEBUG_TX_REPLY("Rate Info rate_n_flags=%x\n", rate_n_flags); agg->wait_for_ba = 0; } else { @@ -1114,7 +1230,6 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, agg->bitmap = bitmap; agg->start_idx = start; - agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); IWL_DEBUG_TX_REPLY("Frames %d start_idx=%d bitmap=0x%llx\n", agg->frame_count, agg->start_idx, (unsigned long long)agg->bitmap); @@ -1136,12 +1251,9 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, struct ieee80211_tx_info *info; struct iwl5000_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; u32 status = le16_to_cpu(tx_resp->status.status); -#ifdef CONFIG_IWL4965_HT int tid = MAX_TID_COUNT, sta_id = IWL_INVALID_STATION; - u16 fc; struct ieee80211_hdr *hdr; u8 *qc = NULL; -#endif if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { IWL_ERROR("Read index for DMA queue txq_id (%d) index %d " @@ -1154,11 +1266,9 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); memset(&info->status, 0, sizeof(info->status)); -#ifdef CONFIG_IWL4965_HT hdr = iwl_tx_queue_get_hdr(priv, txq_id, index); - fc = le16_to_cpu(hdr->frame_control); - if (ieee80211_is_qos_data(fc)) { - qc = ieee80211_get_qos_ctrl(hdr, ieee80211_get_hdrlen(fc)); + if (ieee80211_is_data_qos(hdr->frame_control)) { + qc = ieee80211_get_qos_ctl(hdr); tid = qc[0] & 0xf; } @@ -1177,7 +1287,7 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, agg = &priv->stations[sta_id].tid[tid].agg; - iwl5000_tx_status_reply_tx(priv, agg, tx_resp, index); + iwl5000_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) { /* TODO: send BAR */ @@ -1195,7 +1305,7 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, txq_id >= 0 && priv->mac80211_registered && agg->state != IWL_EMPTYING_HW_QUEUE_DELBA) { /* calculate mac80211 ampdu sw queue to wake */ - ampdu_q = txq_id - IWL_BACK_QUEUE_FIRST_ID + + ampdu_q = txq_id - IWL50_FIRST_AMPDU_QUEUE + priv->hw->queues; if (agg->state == IWL_AGG_OFF) ieee80211_wake_queue(priv->hw, txq_id); @@ -1205,32 +1315,31 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, iwl_txq_check_empty(priv, sta_id, tid, txq_id); } } else { -#endif /* CONFIG_IWL4965_HT */ - - info->status.retry_count = tx_resp->failure_frame; - info->flags = iwl_is_tx_success(status) ? IEEE80211_TX_STAT_ACK : 0; - iwl4965_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags), - info); - - IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags 0x%x " - "retries %d\n", txq_id, iwl_get_tx_fail_reason(status), - status, le32_to_cpu(tx_resp->rate_n_flags), - tx_resp->failure_frame); - - IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index); -#ifdef CONFIG_IWL4965_HT - if (index != -1) { - int freed = iwl_tx_queue_reclaim(priv, txq_id, index); - if (tid != MAX_TID_COUNT) + info->status.retry_count = tx_resp->failure_frame; + info->flags = + iwl_is_tx_success(status) ? IEEE80211_TX_STAT_ACK : 0; + iwl_hwrate_to_tx_control(priv, + le32_to_cpu(tx_resp->rate_n_flags), + info); + + IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags " + "0x%x retries %d\n", txq_id, + iwl_get_tx_fail_reason(status), + status, le32_to_cpu(tx_resp->rate_n_flags), + tx_resp->failure_frame); + + IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index); + if (index != -1) { + int freed = iwl_tx_queue_reclaim(priv, txq_id, index); + if (tid != MAX_TID_COUNT) priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; - if (iwl_queue_space(&txq->q) > txq->q.low_mark && + if (iwl_queue_space(&txq->q) > txq->q.low_mark && (txq_id >= 0) && priv->mac80211_registered) ieee80211_wake_queue(priv->hw, txq_id); - if (tid != MAX_TID_COUNT) + if (tid != MAX_TID_COUNT) iwl_txq_check_empty(priv, sta_id, tid, txq_id); + } } - } -#endif /* CONFIG_IWL4965_HT */ if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n"); @@ -1242,6 +1351,12 @@ static u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len) return len; } +static void iwl5000_setup_deferred_work(struct iwl_priv *priv) +{ + /* in 5000 the tx power calibration is done in uCode */ + priv->disable_tx_power_cal = 1; +} + static void iwl5000_rx_handler_setup(struct iwl_priv *priv) { /* init calibration handlers */ @@ -1305,6 +1420,19 @@ static int iwl5000_send_rxon_assoc(struct iwl_priv *priv) return ret; } +static int iwl5000_send_tx_power(struct iwl_priv *priv) +{ + struct iwl5000_tx_power_dbm_cmd tx_power_cmd; + + /* half dBm need to multiply */ + tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt); + tx_power_cmd.flags = 0; + tx_power_cmd.srv_chan_lmt = IWL50_TX_POWER_AUTO; + return iwl_send_cmd_pdu_async(priv, REPLY_TX_POWER_DBM_CMD, + sizeof(tx_power_cmd), &tx_power_cmd, + NULL); +} + static struct iwl_hcmd_ops iwl5000_hcmd = { .rxon_assoc = iwl5000_send_rxon_assoc, @@ -1313,10 +1441,8 @@ static struct iwl_hcmd_ops iwl5000_hcmd = { static struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { .get_hcmd_size = iwl5000_get_hcmd_size, .build_addsta_hcmd = iwl5000_build_addsta_hcmd, -#ifdef CONFIG_IWL5000_RUN_TIME_CALIB .gain_computation = iwl5000_gain_computation, .chain_noise_reset = iwl5000_chain_noise_reset, -#endif }; static struct iwl_lib_ops iwl5000_lib = { @@ -1327,11 +1453,15 @@ static struct iwl_lib_ops iwl5000_lib = { .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, .txq_set_sched = iwl5000_txq_set_sched, + .txq_agg_enable = iwl5000_txq_agg_enable, + .txq_agg_disable = iwl5000_txq_agg_disable, .rx_handler_setup = iwl5000_rx_handler_setup, + .setup_deferred_work = iwl5000_setup_deferred_work, .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, .load_ucode = iwl5000_load_ucode, .init_alive_start = iwl5000_init_alive_start, .alive_notify = iwl5000_alive_notify, + .send_tx_power = iwl5000_send_tx_power, .apm_ops = { .init = iwl5000_apm_init, .reset = iwl5000_apm_reset, diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c index a6c7f0d9a41..48f58000b64 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-calib.c @@ -60,13 +60,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -#include <linux/kernel.h> #include <net/mac80211.h> #include "iwl-dev.h" #include "iwl-core.h" #include "iwl-calib.h" -#include "iwl-eeprom.h" /* "false alarms" are signals that our DSP tries to lock onto, * but then determines that they are either noise, or transmissions @@ -435,8 +433,6 @@ void iwl_init_sensitivity(struct iwl_priv *priv) data = &(priv->sensitivity_data); if (ranges == NULL) - /* can happen if IWLWIFI_RUN_TIME_CALIB is selected - * but no IWLXXXX_RUN_TIME_CALIB for specific is selected */ return; memset(data, 0, sizeof(struct iwl_sensitivity_data)); diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.h b/drivers/net/wireless/iwlwifi/iwl-calib.h index b8e57c59eac..5524a29e22d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.h +++ b/drivers/net/wireless/iwlwifi/iwl-calib.h @@ -62,16 +62,10 @@ #ifndef __iwl_calib_h__ #define __iwl_calib_h__ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/version.h> - -#include <net/mac80211.h> -#include "iwl-eeprom.h" -#include "iwl-core.h" #include "iwl-dev.h" +#include "iwl-core.h" +#include "iwl-commands.h" -#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB void iwl_chain_noise_calibration(struct iwl_priv *priv, struct iwl4965_notif_statistics *stat_resp); void iwl_sensitivity_calibration(struct iwl_priv *priv, @@ -86,24 +80,5 @@ static inline void iwl_chain_noise_reset(struct iwl_priv *priv) priv->cfg->ops->utils->chain_noise_reset) priv->cfg->ops->utils->chain_noise_reset(priv); } -#else -static inline void iwl_chain_noise_calibration(struct iwl_priv *priv, - struct iwl4965_notif_statistics *stat_resp) -{ -} -static inline void iwl_sensitivity_calibration(struct iwl_priv *priv, - struct iwl4965_notif_statistics *resp) -{ -} -static inline void iwl_init_sensitivity(struct iwl_priv *priv) -{ -} -static inline void iwl_chain_noise_reset(struct iwl_priv *priv) -{ -} -static inline void iwl_reset_run_time_calib(struct iwl_priv *priv) -{ -} -#endif #endif /* __iwl_calib_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index fb6f5ffb9f1..920dfc1b2db 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -126,6 +126,7 @@ enum { /* Miscellaneous commands */ QUIET_NOTIFICATION = 0x96, /* not used */ REPLY_TX_PWR_TABLE_CMD = 0x97, + REPLY_TX_POWER_DBM_CMD = 0x98, MEASURE_ABORT_NOTIFICATION = 0x99, /* not used */ /* Bluetooth device coexistance config command */ @@ -280,16 +281,7 @@ struct iwl_cmd_header { #define RATE_MCS_ANT_C_MSK 0x10000 #define RATE_MCS_ANT_ABC_MSK 0x1C000 - -/** - * struct iwl4965_tx_power - txpower format used in REPLY_SCAN_CMD - * - * Scan uses only one transmitter, so only one analog/dsp gain pair is needed. - */ -struct iwl4965_tx_power { - u8 tx_gain; /* gain for analog radio */ - u8 dsp_atten; /* gain for DSP */ -} __attribute__ ((packed)); +#define RATE_MCS_ANT_INIT_IND 1 #define POWER_TABLE_NUM_ENTRIES 33 #define POWER_TABLE_NUM_HT_OFDM_ENTRIES 32 @@ -339,6 +331,17 @@ struct iwl4965_tx_power_db { struct tx_power_dual_stream power_tbl[POWER_TABLE_NUM_ENTRIES]; } __attribute__ ((packed)); +/** + * Commad REPLY_TX_POWER_DBM_CMD = 0x98 + * struct iwl5000_tx_power_dbm_cmd + */ +#define IWL50_TX_POWER_AUTO 0x7f +struct iwl5000_tx_power_dbm_cmd { + s8 global_lmt; /*in half-dBm (e.g. 30 = 15 dBm) */ + u8 flags; + s8 srv_chan_lmt; /*in half-dBm (e.g. 30 = 15 dBm) */ + u8 reserved; +} __attribute__ ((packed)); /****************************************************************************** * (0a) @@ -990,6 +993,7 @@ struct iwl_wep_cmd { #define WEP_KEY_WEP_TYPE 1 #define WEP_KEYS_MAX 4 #define WEP_INVALID_OFFSET 0xff +#define WEP_KEY_LEN_64 5 #define WEP_KEY_LEN_128 13 /****************************************************************************** @@ -1481,21 +1485,10 @@ struct iwl4965_tx_resp { * table entry used for all frames in the new agg. * 31-16: Sequence # for this frame's Tx cmd (not SSN!) */ - __le32 status; /* TX status (for aggregation status of 1st frame) */ -} __attribute__ ((packed)); - -struct iwl4965_tx_resp_agg { - u8 frame_count; /* 1 no aggregation, >1 aggregation */ - u8 reserved1; - u8 failure_rts; - u8 failure_frame; - __le32 rate_n_flags; - __le16 wireless_media_time; - __le16 reserved3; - __le32 pa_power1; - __le32 pa_power2; - struct agg_tx_status status; /* TX status (for aggregation status */ - /* of 1st frame) */ + union { + __le32 status; + struct agg_tx_status agg_status[0]; /* for each agg frame */ + } u; } __attribute__ ((packed)); struct iwl5000_tx_resp { @@ -2085,7 +2078,7 @@ struct iwl4965_card_state_notif { #define RF_CARD_DISABLED 0x04 #define RXON_CARD_DISABLED 0x10 -struct iwl4965_ct_kill_config { +struct iwl_ct_kill_config { __le32 reserved; __le32 critical_temperature_M; __le32 critical_temperature_R; @@ -2098,7 +2091,7 @@ struct iwl4965_ct_kill_config { *****************************************************************************/ /** - * struct iwl4965_scan_channel - entry in REPLY_SCAN_CMD channel table + * struct iwl_scan_channel - entry in REPLY_SCAN_CMD channel table * * One for each channel in the scan list. * Each channel can independently select: @@ -2108,7 +2101,7 @@ struct iwl4965_ct_kill_config { * quiet_plcp_th, good_CRC_th) * * To avoid uCode errors, make sure the following are true (see comments - * under struct iwl4965_scan_cmd about max_out_time and quiet_time): + * under struct iwl_scan_cmd about max_out_time and quiet_time): * 1) If using passive_dwell (i.e. passive_dwell != 0): * active_dwell <= passive_dwell (< max_out_time if max_out_time != 0) * 2) quiet_time <= active_dwell @@ -2116,7 +2109,7 @@ struct iwl4965_ct_kill_config { * passive_dwell < max_out_time * active_dwell < max_out_time */ -struct iwl4965_scan_channel { +struct iwl_scan_channel { /* * type is defined as: * 0:0 1 = active, 0 = passive @@ -2126,19 +2119,20 @@ struct iwl4965_scan_channel { */ u8 type; u8 channel; /* band is selected by iwl4965_scan_cmd "flags" field */ - struct iwl4965_tx_power tpc; + u8 tx_gain; /* gain for analog radio */ + u8 dsp_atten; /* gain for DSP */ __le16 active_dwell; /* in 1024-uSec TU (time units), typ 5-50 */ __le16 passive_dwell; /* in 1024-uSec TU (time units), typ 20-500 */ } __attribute__ ((packed)); /** - * struct iwl4965_ssid_ie - directed scan network information element + * struct iwl_ssid_ie - directed scan network information element * * Up to 4 of these may appear in REPLY_SCAN_CMD, selected by "type" field * in struct iwl4965_scan_channel; each channel may select different ssids from * among the 4 entries. SSID IEs get transmitted in reverse order of entry. */ -struct iwl4965_ssid_ie { +struct iwl_ssid_ie { u8 id; u8 len; u8 ssid[32]; @@ -2199,9 +2193,9 @@ struct iwl4965_ssid_ie { * Driver must use separate scan commands for 2.4 vs. 5 GHz bands. * * To avoid uCode errors, see timing restrictions described under - * struct iwl4965_scan_channel. + * struct iwl_scan_channel. */ -struct iwl4965_scan_cmd { +struct iwl_scan_cmd { __le16 len; u8 reserved0; u8 channel_count; /* # channels in channel list */ @@ -2225,7 +2219,7 @@ struct iwl4965_scan_cmd { struct iwl_tx_cmd tx_cmd; /* For directed active scans (set to all-0s otherwise) */ - struct iwl4965_ssid_ie direct_scan[PROBE_OPTION_MAX]; + struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX]; /* * Probe request frame, followed by channel list. @@ -2253,14 +2247,14 @@ struct iwl4965_scan_cmd { /* * REPLY_SCAN_CMD = 0x80 (response) */ -struct iwl4965_scanreq_notification { +struct iwl_scanreq_notification { __le32 status; /* 1: okay, 2: cannot fulfill request */ } __attribute__ ((packed)); /* * SCAN_START_NOTIFICATION = 0x82 (notification only, not a command) */ -struct iwl4965_scanstart_notification { +struct iwl_scanstart_notification { __le32 tsf_low; __le32 tsf_high; __le32 beacon_timer; @@ -2277,7 +2271,7 @@ struct iwl4965_scanstart_notification { /* * SCAN_RESULTS_NOTIFICATION = 0x83 (notification only, not a command) */ -struct iwl4965_scanresults_notification { +struct iwl_scanresults_notification { u8 channel; u8 band; u8 reserved[2]; @@ -2289,7 +2283,7 @@ struct iwl4965_scanresults_notification { /* * SCAN_COMPLETE_NOTIFICATION = 0x84 (notification only, not a command) */ -struct iwl4965_scancomplete_notification { +struct iwl_scancomplete_notification { u8 scanned_channels; u8 status; u8 reserved; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 61716ba9042..eb74a40a62e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -85,6 +85,63 @@ const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = { }; EXPORT_SYMBOL(iwl_rates); +/** + * translate ucode response to mac80211 tx status control values + */ +void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, + struct ieee80211_tx_info *control) +{ + int rate_index; + + control->antenna_sel_tx = + ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); + if (rate_n_flags & RATE_MCS_HT_MSK) + control->flags |= IEEE80211_TX_CTL_OFDM_HT; + if (rate_n_flags & RATE_MCS_GF_MSK) + control->flags |= IEEE80211_TX_CTL_GREEN_FIELD; + if (rate_n_flags & RATE_MCS_FAT_MSK) + control->flags |= IEEE80211_TX_CTL_40_MHZ_WIDTH; + if (rate_n_flags & RATE_MCS_DUP_MSK) + control->flags |= IEEE80211_TX_CTL_DUP_DATA; + if (rate_n_flags & RATE_MCS_SGI_MSK) + control->flags |= IEEE80211_TX_CTL_SHORT_GI; + rate_index = iwl_hwrate_to_plcp_idx(rate_n_flags); + if (control->band == IEEE80211_BAND_5GHZ) + rate_index -= IWL_FIRST_OFDM_RATE; + control->tx_rate_idx = rate_index; +} +EXPORT_SYMBOL(iwl_hwrate_to_tx_control); + +int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) +{ + int idx = 0; + + /* HT rate format */ + if (rate_n_flags & RATE_MCS_HT_MSK) { + idx = (rate_n_flags & 0xff); + + if (idx >= IWL_RATE_MIMO2_6M_PLCP) + idx = idx - IWL_RATE_MIMO2_6M_PLCP; + + idx += IWL_FIRST_OFDM_RATE; + /* skip 9M not supported in ht*/ + if (idx >= IWL_RATE_9M_INDEX) + idx += 1; + if ((idx >= IWL_FIRST_OFDM_RATE) && (idx <= IWL_LAST_OFDM_RATE)) + return idx; + + /* legacy rate format, search for match in table */ + } else { + for (idx = 0; idx < ARRAY_SIZE(iwl_rates); idx++) + if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF)) + return idx; + } + + return -1; +} +EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx); + + const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; EXPORT_SYMBOL(iwl_bcast_addr); @@ -321,7 +378,6 @@ void iwl_reset_qos(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_reset_qos); -#ifdef CONFIG_IWL4965_HT #define MAX_BIT_RATE_40_MHZ 0x96; /* 150 Mbps */ #define MAX_BIT_RATE_20_MHZ 0x48; /* 72 Mbps */ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, @@ -374,13 +430,6 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, ht_info->supp_mcs_set[12] |= ((tx_chains_num - 1) << 2); } } -#else -static inline void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, - struct ieee80211_ht_info *ht_info, - enum ieee80211_band band) -{ -} -#endif /* CONFIG_IWL4965_HT */ static void iwlcore_init_hw_rates(struct iwl_priv *priv, struct ieee80211_rate *rates) @@ -486,28 +535,10 @@ static int iwlcore_init_geos(struct iwl_priv *priv) if (ch->flags & EEPROM_CHANNEL_RADAR) geo_ch->flags |= IEEE80211_CHAN_RADAR; - switch (ch->fat_extension_channel) { - case HT_IE_EXT_CHANNEL_ABOVE: - /* only above is allowed, disable below */ - geo_ch->flags |= IEEE80211_CHAN_NO_FAT_BELOW; - break; - case HT_IE_EXT_CHANNEL_BELOW: - /* only below is allowed, disable above */ - geo_ch->flags |= IEEE80211_CHAN_NO_FAT_ABOVE; - break; - case HT_IE_EXT_CHANNEL_NONE: - /* fat not allowed: disable both*/ - geo_ch->flags |= (IEEE80211_CHAN_NO_FAT_ABOVE | - IEEE80211_CHAN_NO_FAT_BELOW); - break; - case HT_IE_EXT_CHANNEL_MAX: - /* both above and below are permitted */ - break; - } + geo_ch->flags |= ch->fat_extension_channel; - if (ch->max_power_avg > priv->max_channel_txpower_limit) - priv->max_channel_txpower_limit = - ch->max_power_avg; + if (ch->max_power_avg > priv->tx_power_channel_lmt) + priv->tx_power_channel_lmt = ch->max_power_avg; } else { geo_ch->flags |= IEEE80211_CHAN_DISABLED; } @@ -515,7 +546,7 @@ static int iwlcore_init_geos(struct iwl_priv *priv) /* Save flags for reg domain usage */ geo_ch->orig_flags = geo_ch->flags; - IWL_DEBUG_INFO("Channel %d Freq=%d[%sGHz] %s flag=0%X\n", + IWL_DEBUG_INFO("Channel %d Freq=%d[%sGHz] %s flag=0x%X\n", ch->channel, geo_ch->center_freq, is_channel_a_band(ch) ? "5.2" : "2.4", geo_ch->flags & IEEE80211_CHAN_DISABLED ? @@ -553,7 +584,6 @@ static void iwlcore_free_geos(struct iwl_priv *priv) clear_bit(STATUS_GEO_CONFIGURED, &priv->status); } -#ifdef CONFIG_IWL4965_HT static u8 is_single_rx_stream(struct iwl_priv *priv) { return !priv->current_ht_config.is_ht || @@ -561,6 +591,7 @@ static u8 is_single_rx_stream(struct iwl_priv *priv) (priv->current_ht_config.supp_mcs_set[2] == 0)) || priv->ps_mode == IWL_MIMO_PS_STATIC; } + static u8 iwl_is_channel_extension(struct iwl_priv *priv, enum ieee80211_band band, u16 channel, u8 extension_chan_offset) @@ -571,12 +602,12 @@ static u8 iwl_is_channel_extension(struct iwl_priv *priv, if (!is_channel_valid(ch_info)) return 0; - if (extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_NONE) - return 0; - - if ((ch_info->fat_extension_channel == extension_chan_offset) || - (ch_info->fat_extension_channel == HT_IE_EXT_CHANNEL_MAX)) - return 1; + if (extension_chan_offset == IEEE80211_HT_IE_CHA_SEC_ABOVE) + return !(ch_info->fat_extension_channel & + IEEE80211_CHAN_NO_FAT_ABOVE); + else if (extension_chan_offset == IEEE80211_HT_IE_CHA_SEC_BELOW) + return !(ch_info->fat_extension_channel & + IEEE80211_CHAN_NO_FAT_BELOW); return 0; } @@ -588,7 +619,7 @@ u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv, if ((!iwl_ht_conf->is_ht) || (iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ) || - (iwl_ht_conf->extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_NONE)) + (iwl_ht_conf->extension_chan_offset == IEEE80211_HT_IE_CHA_SEC_NONE)) return 0; if (sta_ht_inf) { @@ -622,19 +653,18 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) IWL_DEBUG_ASSOC("control diff than current %d %d\n", le16_to_cpu(rxon->channel), ht_info->control_channel); - rxon->channel = cpu_to_le16(ht_info->control_channel); return; } /* Note: control channel is opposite of extension channel */ switch (ht_info->extension_chan_offset) { - case IWL_EXT_CHANNEL_OFFSET_ABOVE: + case IEEE80211_HT_IE_CHA_SEC_ABOVE: rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); break; - case IWL_EXT_CHANNEL_OFFSET_BELOW: + case IEEE80211_HT_IE_CHA_SEC_BELOW: rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; break; - case IWL_EXT_CHANNEL_OFFSET_NONE: + case IEEE80211_HT_IE_CHA_SEC_NONE: default: rxon->flags &= ~RXON_FLG_CHANNEL_MODE_MIXED_MSK; break; @@ -660,13 +690,6 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) } EXPORT_SYMBOL(iwl_set_rxon_ht); -#else -static inline u8 is_single_rx_stream(struct iwl_priv *priv) -{ - return 1; -} -#endif /*CONFIG_IWL4965_HT */ - /* * Determine how many receiver/antenna chains to use. * More provides better reception via diversity. Fewer saves power. @@ -791,10 +814,8 @@ int iwl_setup_mac(struct iwl_priv *priv) IEEE80211_HW_NOISE_DBM; /* Default value; 4 EDCA QOS priorities */ hw->queues = 4; -#ifdef CONFIG_IWL4965_HT /* Enhanced value; more queues, to support 11n aggregation */ hw->ampdu_queues = 12; -#endif /* CONFIG_IWL4965_HT */ hw->conf.beacon_int = 100; @@ -853,6 +874,7 @@ int iwl_init_drv(struct iwl_priv *priv) /* Choose which receivers/antennas to use */ iwl_set_rxon_chain(priv); + iwl_init_scan_params(priv); if (priv->cfg->mod_params->enable_qos) priv->qos_data.qos_enable = 1; @@ -867,7 +889,7 @@ int iwl_init_drv(struct iwl_priv *priv) priv->rates_mask = IWL_RATES_MASK; /* If power management is turned on, default to AC mode */ priv->power_mode = IWL_POWER_AC; - priv->user_txpower_limit = IWL_DEFAULT_TX_POWER; + priv->tx_power_user_lmt = IWL_TX_POWER_TARGET_POWER_MAX; ret = iwl_init_channel_map(priv); if (ret) { @@ -906,6 +928,34 @@ void iwl_free_calib_results(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_free_calib_results); +int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) +{ + int ret = 0; + if (tx_power < IWL_TX_POWER_TARGET_POWER_MIN) { + IWL_WARNING("Requested user TXPOWER %d below limit.\n", + priv->tx_power_user_lmt); + return -EINVAL; + } + + if (tx_power > IWL_TX_POWER_TARGET_POWER_MAX) { + IWL_WARNING("Requested user TXPOWER %d above limit.\n", + priv->tx_power_user_lmt); + return -EINVAL; + } + + if (priv->tx_power_user_lmt != tx_power) + force = true; + + priv->tx_power_user_lmt = tx_power; + + if (force && priv->cfg->ops->lib->send_tx_power) + ret = priv->cfg->ops->lib->send_tx_power(priv); + + return ret; +} +EXPORT_SYMBOL(iwl_set_tx_power); + + void iwl_uninit_drv(struct iwl_priv *priv) { iwl_free_calib_results(priv); @@ -915,35 +965,6 @@ void iwl_uninit_drv(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_uninit_drv); -/* Low level driver call this function to update iwlcore with - * driver status. - */ -int iwlcore_low_level_notify(struct iwl_priv *priv, - enum iwlcore_card_notify notify) -{ - int ret; - switch (notify) { - case IWLCORE_INIT_EVT: - ret = iwl_rfkill_init(priv); - if (ret) - IWL_ERROR("Unable to initialize RFKILL system. " - "Ignoring error: %d\n", ret); - iwl_power_initialize(priv); - break; - case IWLCORE_START_EVT: - iwl_power_update_mode(priv, 1); - break; - case IWLCORE_STOP_EVT: - break; - case IWLCORE_REMOVE_EVT: - iwl_rfkill_unregister(priv); - break; - } - - return 0; -} -EXPORT_SYMBOL(iwlcore_low_level_notify); - int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags) { u32 stat_flags = 0; @@ -1204,12 +1225,14 @@ void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, ptr += sizeof(u32); time = iwl_read_targ_mem(priv, ptr); ptr += sizeof(u32); - if (mode == 0) - IWL_ERROR("0x%08x\t%04u\n", time, ev); /* data, ev */ - else { + if (mode == 0) { + /* data, ev */ + IWL_ERROR("EVT_LOG:0x%08x:%04u\n", time, ev); + } else { data = iwl_read_targ_mem(priv, ptr); ptr += sizeof(u32); - IWL_ERROR("%010u\t0x%08x\t%04u\n", time, data, ev); + IWL_ERROR("EVT_LOGT:%010u:0x%08x:%04u\n", + time, data, ev); } } } @@ -1272,4 +1295,114 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_dump_nic_event_log); +void iwl_rf_kill_ct_config(struct iwl_priv *priv) +{ + struct iwl_ct_kill_config cmd; + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&priv->lock, flags); + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, + CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); + spin_unlock_irqrestore(&priv->lock, flags); + + cmd.critical_temperature_R = + cpu_to_le32(priv->hw_params.ct_kill_threshold); + + ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, + sizeof(cmd), &cmd); + if (ret) + IWL_ERROR("REPLY_CT_KILL_CONFIG_CMD failed\n"); + else + IWL_DEBUG_INFO("REPLY_CT_KILL_CONFIG_CMD succeeded, " + "critical temperature is %d\n", + cmd.critical_temperature_R); +} +EXPORT_SYMBOL(iwl_rf_kill_ct_config); + +/* + * CARD_STATE_CMD + * + * Use: Sets the device's internal card state to enable, disable, or halt + * + * When in the 'enable' state the card operates as normal. + * When in the 'disable' state, the card enters into a low power mode. + * When in the 'halt' state, the card is shut down and must be fully + * restarted to come back on. + */ +static int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag) +{ + struct iwl_host_cmd cmd = { + .id = REPLY_CARD_STATE_CMD, + .len = sizeof(u32), + .data = &flags, + .meta.flags = meta_flag, + }; + + return iwl_send_cmd(priv, &cmd); +} + +void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv) +{ + unsigned long flags; + + if (test_bit(STATUS_RF_KILL_SW, &priv->status)) + return; + + IWL_DEBUG_RF_KILL("Manual SW RF KILL set to: RADIO OFF\n"); + + iwl_scan_cancel(priv); + /* FIXME: This is a workaround for AP */ + if (priv->iw_mode != IEEE80211_IF_TYPE_AP) { + spin_lock_irqsave(&priv->lock, flags); + iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, + CSR_UCODE_SW_BIT_RFKILL); + spin_unlock_irqrestore(&priv->lock, flags); + /* call the host command only if no hw rf-kill set */ + if (!test_bit(STATUS_RF_KILL_HW, &priv->status) && + iwl_is_ready(priv)) + iwl_send_card_state(priv, + CARD_STATE_CMD_DISABLE, 0); + set_bit(STATUS_RF_KILL_SW, &priv->status); + /* make sure mac80211 stop sending Tx frame */ + if (priv->mac80211_registered) + ieee80211_stop_queues(priv->hw); + } +} +EXPORT_SYMBOL(iwl_radio_kill_sw_disable_radio); +int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv) +{ + unsigned long flags; + + if (!test_bit(STATUS_RF_KILL_SW, &priv->status)) + return 0; + + IWL_DEBUG_RF_KILL("Manual SW RF KILL set to: RADIO ON\n"); + + spin_lock_irqsave(&priv->lock, flags); + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + + clear_bit(STATUS_RF_KILL_SW, &priv->status); + spin_unlock_irqrestore(&priv->lock, flags); + + /* wake up ucode */ + msleep(10); + + spin_lock_irqsave(&priv->lock, flags); + iwl_read32(priv, CSR_UCODE_DRV_GP1); + if (!iwl_grab_nic_access(priv)) + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->lock, flags); + + if (test_bit(STATUS_RF_KILL_HW, &priv->status)) { + IWL_DEBUG_RF_KILL("Can not turn radio back on - " + "disabled by HW switch\n"); + return 0; + } + + if (priv->is_open) + queue_work(priv->workqueue, &priv->restart); + return 1; +} +EXPORT_SYMBOL(iwl_radio_kill_sw_enable_radio); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 6b5af7afbb2..2838093b445 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -88,13 +88,11 @@ struct iwl_hcmd_ops { struct iwl_hcmd_utils_ops { u16 (*get_hcmd_size)(u8 cmd_id, u16 len); u16 (*build_addsta_hcmd)(const struct iwl_addsta_cmd *cmd, u8 *data); -#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB void (*gain_computation)(struct iwl_priv *priv, u32 *average_noise, u16 min_average_noise_antennat_i, u32 min_average_noise); void (*chain_noise_reset)(struct iwl_priv *priv); -#endif }; struct iwl_lib_ops { @@ -111,15 +109,17 @@ struct iwl_lib_ops { void (*txq_inval_byte_cnt_tbl)(struct iwl_priv *priv, struct iwl_tx_queue *txq); void (*txq_set_sched)(struct iwl_priv *priv, u32 mask); -#ifdef CONFIG_IWL4965_HT /* aggregations */ int (*txq_agg_enable)(struct iwl_priv *priv, int txq_id, int tx_fifo, int sta_id, int tid, u16 ssn_idx); int (*txq_agg_disable)(struct iwl_priv *priv, u16 txq_id, u16 ssn_idx, u8 tx_fifo); -#endif /* CONFIG_IWL4965_HT */ /* setup Rx handler */ void (*rx_handler_setup)(struct iwl_priv *priv); + /* setup deferred work */ + void (*setup_deferred_work)(struct iwl_priv *priv); + /* cancel deferred work */ + void (*cancel_deferred_work)(struct iwl_priv *priv); /* alive notification after init uCode load */ void (*init_alive_start)(struct iwl_priv *priv); /* alive notification */ @@ -128,8 +128,6 @@ struct iwl_lib_ops { int (*is_valid_rtc_data_addr)(u32 addr); /* 1st ucode load */ int (*load_ucode)(struct iwl_priv *priv); - /* rfkill */ - void (*radio_kill_sw)(struct iwl_priv *priv, int disable_radio); /* power management */ struct { int (*init)(struct iwl_priv *priv); @@ -140,6 +138,7 @@ struct iwl_lib_ops { } apm_ops; /* power */ int (*set_power)(struct iwl_priv *priv, void *cmd); + int (*send_tx_power) (struct iwl_priv *priv); void (*update_chain_flags)(struct iwl_priv *priv); /* eeprom operations (as defined in iwl-eeprom.h) */ struct iwl_eeprom_ops eeprom_ops; @@ -233,11 +232,53 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv); int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *tfd, dma_addr_t addr, u16 len); int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); -#ifdef CONFIG_IWL4965_HT int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id); -#endif + +/***************************************************** + * TX power + ****************************************************/ +int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force); + +/***************************************************** + * RF -Kill - here and not in iwl-rfkill.h to be available when + * RF-kill subsystem is not compiled. + ****************************************************/ +void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv); +int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv); + +/******************************************************************************* + * Rate + ******************************************************************************/ + +void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, + struct ieee80211_tx_info *info); +int iwl_hwrate_to_plcp_idx(u32 rate_n_flags); + +static inline u8 iwl_hw_get_rate(__le32 rate_n_flags) +{ + return le32_to_cpu(rate_n_flags) & 0xFF; +} +static inline u32 iwl_hw_get_rate_n_flags(__le32 rate_n_flags) +{ + return le32_to_cpu(rate_n_flags) & 0x1FFFF; +} +static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) +{ + return cpu_to_le32(flags|(u32)rate); +} + +/******************************************************************************* + * Scanning + ******************************************************************************/ +void iwl_init_scan_params(struct iwl_priv *priv); +int iwl_scan_cancel(struct iwl_priv *priv); +int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); +const char *iwl_escape_essid(const char *essid, u8 essid_len); +int iwl_scan_initiate(struct iwl_priv *priv); +void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); +void iwl_setup_scan_deferred_work(struct iwl_priv *priv); /***************************************************** * S e n d i n g H o s t C o m m a n d s * @@ -286,6 +327,7 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv); #define STATUS_POWER_PMI 16 #define STATUS_FW_ERROR 17 #define STATUS_CONF_PENDING 18 +#define STATUS_MODE_PENDING 19 static inline int iwl_is_ready(struct iwl_priv *priv) @@ -322,19 +364,10 @@ static inline int iwl_is_ready_rf(struct iwl_priv *priv) return iwl_is_ready(priv); } - -enum iwlcore_card_notify { - IWLCORE_INIT_EVT = 0, - IWLCORE_START_EVT = 1, - IWLCORE_STOP_EVT = 2, - IWLCORE_REMOVE_EVT = 3, -}; - -int iwlcore_low_level_notify(struct iwl_priv *priv, - enum iwlcore_card_notify notify); +extern void iwl_rf_kill_ct_config(struct iwl_priv *priv); extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags); extern int iwl_verify_ucode(struct iwl_priv *priv); -int iwl_send_lq_cmd(struct iwl_priv *priv, +extern int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_link_quality_cmd *lq, u8 flags); static inline int iwl_send_rxon_assoc(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 11de561c7bf..58384805a49 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -55,10 +55,9 @@ struct iwl_debugfs { struct dentry *file_log_event; } dbgfs_data_files; struct dir_rf_files { -#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB struct dentry *file_disable_sensitivity; struct dentry *file_disable_chain_noise; -#endif /* CONFIG_IWLWIFI_RUN_TIME_CALIB */ + struct dentry *file_disable_tx_power; } dbgfs_rf_files; u32 sram_offset; u32 sram_len; diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 29e16ba69cd..ed948dc59b3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -255,21 +255,18 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, pos += scnprintf(buf + pos, bufsz - pos, "tid data:\n"); pos += scnprintf(buf + pos, bufsz - pos, "seq_num\t\ttxq_id"); -#ifdef CONFIG_IWL4965_HT pos += scnprintf(buf + pos, bufsz - pos, "\tframe_count\twait_for_ba\t"); pos += scnprintf(buf + pos, bufsz - pos, "start_idx\tbitmap0\t"); pos += scnprintf(buf + pos, bufsz - pos, "bitmap1\trate_n_flags"); -#endif pos += scnprintf(buf + pos, bufsz - pos, "\n"); for (j = 0; j < MAX_TID_COUNT; j++) { pos += scnprintf(buf + pos, bufsz - pos, "[%d]:\t\t%u", j, station->tid[j].seq_number); -#ifdef CONFIG_IWL4965_HT pos += scnprintf(buf + pos, bufsz - pos, "\t%u\t\t%u\t\t%u\t\t", station->tid[j].agg.txq_id, @@ -280,7 +277,6 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, station->tid[j].agg.start_idx, (unsigned long long)station->tid[j].agg.bitmap, station->tid[j].agg.rate_n_flags); -#endif pos += scnprintf(buf + pos, bufsz - pos, "\n"); } pos += scnprintf(buf + pos, bufsz - pos, "\n"); @@ -389,11 +385,10 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(stations, data); DEBUGFS_ADD_FILE(rx_statistics, data); DEBUGFS_ADD_FILE(tx_statistics, data); -#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal); DEBUGFS_ADD_BOOL(disable_chain_noise, rf, &priv->disable_chain_noise_cal); -#endif /* CONFIG_IWLWIFI_RUN_TIME_CALIB */ + DEBUGFS_ADD_BOOL(disable_tx_power, rf, &priv->disable_tx_power_cal); return 0; err: @@ -419,10 +414,9 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_log_event); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations); DEBUGFS_REMOVE(priv->dbgfs->dir_data); -#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise); -#endif /* CONFIG_IWLWIFI_RUN_TIME_CALIB */ + DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_tx_power); DEBUGFS_REMOVE(priv->dbgfs->dir_rf); DEBUGFS_REMOVE(priv->dbgfs->dir_drv); kfree(priv->dbgfs); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 802f1a12b1a..81ff4c2c6a5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -29,8 +29,8 @@ * Please use iwl-4965-hw.h for hardware-related definitions. */ -#ifndef __iwl_4965_h__ -#define __iwl_4965_h__ +#ifndef __iwl_dev_h__ +#define __iwl_dev_h__ #include <linux/pci.h> /* for struct pci_device_id */ #include <linux/kernel.h> @@ -157,44 +157,11 @@ struct iwl4965_channel_tgh_info { s64 last_radar_time; }; -/* current Tx power values to use, one for each rate for each channel. - * requested power is limited by: - * -- regulatory EEPROM limits for this channel - * -- hardware capabilities (clip-powers) - * -- spectrum management - * -- user preference (e.g. iwconfig) - * when requested power is set, base power index must also be set. */ -struct iwl4965_channel_power_info { - struct iwl4965_tx_power tpc; /* actual radio and DSP gain settings */ - s8 power_table_index; /* actual (compenst'd) index into gain table */ - s8 base_power_index; /* gain index for power at factory temp. */ - s8 requested_power; /* power (dBm) requested for this chnl/rate */ -}; - -/* current scan Tx power values to use, one for each scan rate for each - * channel. */ -struct iwl4965_scan_power_info { - struct iwl4965_tx_power tpc; /* actual radio and DSP gain settings */ - s8 power_table_index; /* actual (compenst'd) index into gain table */ - s8 requested_power; /* scan pwr (dBm) requested for chnl/rate */ -}; - -/* For fat_extension_channel */ -enum { - HT_IE_EXT_CHANNEL_NONE = 0, - HT_IE_EXT_CHANNEL_ABOVE, - HT_IE_EXT_CHANNEL_INVALID, - HT_IE_EXT_CHANNEL_BELOW, - HT_IE_EXT_CHANNEL_MAX -}; - /* * One for each channel, holds all channel setup data * Some of the fields (e.g. eeprom and flags/max_power_avg) are redundant * with one another! */ -#define IWL4965_MAX_RATE (33) - struct iwl_channel_info { struct iwl4965_channel_tgd_info tgd; struct iwl4965_channel_tgh_info tgh; @@ -213,11 +180,6 @@ struct iwl_channel_info { u8 band_index; /* 0-4, maps channel to band1/2/3/4/5 */ enum ieee80211_band band; - /* Radio/DSP gain settings for each "normal" data Tx rate. - * These include, in addition to RF and DSP gain, a few fields for - * remembering/modifying gain settings (indexes). */ - struct iwl4965_channel_power_info power_info[IWL4965_MAX_RATE]; - /* FAT channel info */ s8 fat_max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */ s8 fat_curr_txpow; /* (dBm) regulatory/spectrum/user (not h/w) */ @@ -225,9 +187,6 @@ struct iwl_channel_info { s8 fat_scan_power; /* (dBm) eeprom, direct scans, any rate */ u8 fat_flags; /* flags copied from EEPROM */ u8 fat_extension_channel; /* HT_IE_EXT_CHANNEL_* */ - - /* Radio/DSP gain settings for each scan rate, for directed scans. */ - struct iwl4965_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES]; }; struct iwl4965_clip_group { @@ -401,7 +360,6 @@ struct iwl_rx_queue { #define IWL_INVALID_RATE 0xFF #define IWL_INVALID_VALUE -1 -#ifdef CONFIG_IWL4965_HT /** * struct iwl_ht_agg -- aggregation status while waiting for block-ack * @txq_id: Tx queue used for Tx attempt @@ -430,14 +388,11 @@ struct iwl_ht_agg { u8 state; }; -#endif /* CONFIG_IWL4965_HT */ struct iwl_tid_data { u16 seq_number; u16 tfds_in_queue; -#ifdef CONFIG_IWL4965_HT struct iwl_ht_agg agg; -#endif /* CONFIG_IWL4965_HT */ }; struct iwl_hw_key { @@ -525,7 +480,7 @@ struct fw_desc { }; /* uCode file layout */ -struct iwl4965_ucode { +struct iwl_ucode { __le32 ver; /* major/minor/subminor */ __le32 inst_size; /* bytes of runtime instructions */ __le32 data_size; /* bytes of runtime data */ @@ -587,6 +542,7 @@ struct iwl_sensitivity_ranges { * @max_xxx_size: for ucode uses * @ct_kill_threshold: temperature threshold * @struct iwl_sensitivity_ranges: range of sensitivity values + * @first_ampdu_q: first HW queue available for ampdu */ struct iwl_hw_params { u16 max_txq_num; @@ -606,9 +562,8 @@ struct iwl_hw_params { u32 max_data_size; u32 max_bsm_size; u32 ct_kill_threshold; /* value in hw-dependent units */ -#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB const struct iwl_sensitivity_ranges *sens; -#endif + u8 first_ampdu_q; }; #define HT_SHORT_GI_20MHZ (1 << 0) @@ -638,15 +593,8 @@ u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flags, struct ieee80211_ht_info *ht_info); extern int iwl4965_is_network_packet(struct iwl_priv *priv, struct ieee80211_hdr *header); -extern int iwl4965_power_init_handle(struct iwl_priv *priv); -extern void iwl4965_handle_data_packet_monitor(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, - void *data, short len, - struct ieee80211_rx_status *stats, - u16 phy_flags); extern int iwl4965_is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr *header); -extern int iwl4965_calc_db_from_ratio(int sig_ratio); extern int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm); extern unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv, struct ieee80211_hdr *hdr, @@ -654,18 +602,7 @@ extern unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv, extern void iwl4965_update_chain_flags(struct iwl_priv *priv); int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src); -int iwl4965_init_geos(struct iwl_priv *priv); -void iwl4965_free_geos(struct iwl_priv *priv); - extern const u8 iwl_bcast_addr[ETH_ALEN]; -int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); - -/* - * Currently used by iwl-3945-rs... look at restructuring so that it doesn't - * call this... todo... fix that. -*/ -extern u8 iwl4965_sync_station(struct iwl_priv *priv, int sta_id, - u16 tx_rate, u8 flags); /****************************************************************************** * @@ -683,38 +620,16 @@ extern u8 iwl4965_sync_station(struct iwl_priv *priv, int sta_id, * iwl4965_mac_ <-- mac80211 callback * ****************************************************************************/ -extern void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv); -extern void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv); -extern int iwl4965_hw_set_hw_params(struct iwl_priv *priv); extern int iwl_rxq_stop(struct iwl_priv *priv); extern void iwl_txq_ctx_stop(struct iwl_priv *priv); -extern int iwl4965_hw_get_temperature(struct iwl_priv *priv); extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv, struct iwl_frame *frame, u8 rate); -extern void iwl4965_hw_build_tx_cmd_rate(struct iwl_priv *priv, - struct iwl_cmd *cmd, - struct ieee80211_tx_info *info, - struct ieee80211_hdr *hdr, - int sta_id, int tx_id); -extern int iwl4965_hw_reg_send_txpower(struct iwl_priv *priv); -extern int iwl4965_hw_reg_set_txpower(struct iwl_priv *priv, s8 power); extern void iwl4965_hw_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); extern void iwl4965_disable_events(struct iwl_priv *priv); -extern int iwl4965_get_temperature(const struct iwl_priv *priv); extern void iwl4965_rx_reply_rx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); -/** - * iwl_find_station - Find station id for a given BSSID - * @bssid: MAC address of station ID to find - * - * NOTE: This should not be hardware specific but the code has - * not yet been merged into a single common layer for managing the - * station tables. - */ -extern u8 iwl_find_station(struct iwl_priv *priv, const u8 *bssid); - extern int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel); extern int iwl_queue_space(const struct iwl_queue *q); static inline int iwl_queue_used(const struct iwl_queue *q, int i) @@ -738,37 +653,17 @@ static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge) struct iwl_priv; -extern void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio); /* * Forward declare iwl-4965.c functions for iwl-base.c */ -extern int iwl4965_tx_queue_update_wr_ptr(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - u16 byte_cnt); -extern int iwl4965_alive_notify(struct iwl_priv *priv); -extern void iwl4965_update_rate_scaling(struct iwl_priv *priv, u8 mode); extern void iwl4965_rf_kill_ct_config(struct iwl_priv *priv); -extern void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv, - u32 rate_n_flags, - struct ieee80211_tx_info *info); - -#ifdef CONFIG_IWL4965_HT -extern void iwl4965_init_ht_hw_capab(const struct iwl_priv *priv, - struct ieee80211_ht_info *ht_info, - enum ieee80211_band band); -void iwl4965_set_rxon_ht(struct iwl_priv *priv, - struct iwl_ht_info *ht_info); + int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, enum ieee80211_ampdu_mlme_action action, const u8 *addr, u16 tid, u16 *ssn); int iwl4965_check_empty_hw_queue(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id); -#else -static inline void iwl4965_init_ht_hw_capab(const struct iwl_priv *priv, - struct ieee80211_ht_info *ht_info, - enum ieee80211_band band) {} -#endif /*CONFIG_IWL4965_HT */ /* Structures, enum, and defines specific to the 4965 */ #define IWL_KW_SIZE 0x1000 /*4k */ @@ -792,11 +687,6 @@ struct iwl_kw { #define IWL_OPERATION_MODE_MIXED 2 #define IWL_OPERATION_MODE_20MHZ 3 -#define IWL_EXT_CHANNEL_OFFSET_NONE 0 -#define IWL_EXT_CHANNEL_OFFSET_ABOVE 1 -#define IWL_EXT_CHANNEL_OFFSET_RESERVE1 2 -#define IWL_EXT_CHANNEL_OFFSET_BELOW 3 - #define IWL_TX_CRC_SIZE 4 #define IWL_TX_DELIMITER_SIZE 4 @@ -892,7 +782,6 @@ enum ucode_type { UCODE_RT }; -#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB /* Sensitivity calib data */ struct iwl_sensitivity_data { u32 auto_corr_ofdm; @@ -934,7 +823,6 @@ struct iwl_chain_noise_data { u8 delta_gain_code[NUM_RX_CHAINS]; u8 radio_write; }; -#endif /* CONFIG_IWLWIFI_RUN_TIME_CALIB */ #define EEPROM_SEM_TIMEOUT 10 /* milliseconds */ #define EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */ @@ -1006,7 +894,8 @@ struct iwl_priv { int one_direct_scan; u8 direct_ssid_len; u8 direct_ssid[IW_ESSID_MAX_SIZE]; - struct iwl4965_scan_cmd *scan; + struct iwl_scan_cmd *scan; + u32 scan_tx_ant[IEEE80211_NUM_BANDS]; /* spinlock */ spinlock_t lock; /* protect general shared data */ @@ -1067,15 +956,11 @@ struct iwl_priv { u8 assoc_station_added; u8 use_ant_b_for_management_frame; /* Tx antenna selection */ u8 start_calib; -#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB struct iwl_sensitivity_data sensitivity_data; struct iwl_chain_noise_data chain_noise_data; __le16 sensitivity_tbl[HD_TABLE_SIZE]; -#endif /*CONFIG_IWLWIFI_RUN_TIME_CALIB*/ -#ifdef CONFIG_IWL4965_HT struct iwl_ht_info current_ht_config; -#endif u8 last_phy_res[100]; /* Rate scaling data */ @@ -1197,15 +1082,11 @@ struct iwl_priv { struct delayed_work init_alive_start; struct delayed_work alive_start; - struct delayed_work activity_timer; - struct delayed_work thermal_periodic; - struct delayed_work gather_stats; struct delayed_work scan_check; struct delayed_work post_associate; - -#define IWL_DEFAULT_TX_POWER 0x0F - s8 user_txpower_limit; - s8 max_channel_txpower_limit; + /* TX Power */ + s8 tx_power_user_lmt; + s8 tx_power_channel_lmt; #ifdef CONFIG_PM u32 pm_state[16]; @@ -1223,13 +1104,10 @@ struct iwl_priv { #endif /* CONFIG_IWLWIFI_DEBUG */ struct work_struct txpower_work; -#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB u32 disable_sens_cal; u32 disable_chain_noise_cal; -#endif /* CONFIG_IWLWIFI_RUN_TIME_CALIB */ -#ifdef CONFIG_IWL4965_RUN_TIME_CALIB - struct work_struct sensitivity_work; -#endif /* CONFIG_IWL4965_RUN_TIME_CALIB */ + u32 disable_tx_power_cal; + struct work_struct run_time_calib_work; struct timer_list statistics_periodic; }; /*iwl_priv */ @@ -1250,18 +1128,6 @@ static inline const char *iwl_get_tx_fail_reason(u32 status) { return ""; } #endif -#ifdef CONFIG_IWL4965_HT -static inline int iwl_get_ra_sta_id(struct iwl_priv *priv, - struct ieee80211_hdr *hdr) -{ - if (priv->iw_mode == IEEE80211_IF_TYPE_STA) { - return IWL_AP_ID; - } else { - u8 *da = ieee80211_get_DA(hdr); - return iwl_find_station(priv, da); - } -} - static inline struct ieee80211_hdr *iwl_tx_queue_get_hdr(struct iwl_priv *priv, int txq_id, int idx) { @@ -1270,7 +1136,6 @@ static inline struct ieee80211_hdr *iwl_tx_queue_get_hdr(struct iwl_priv *priv, txb[idx].skb[0]->data; return NULL; } -#endif static inline int iwl_is_associated(struct iwl_priv *priv) @@ -1332,4 +1197,4 @@ extern const struct iwl_channel_info *iwl_get_channel_info( /* Requires full declaration of iwl_priv before including */ -#endif /* __iwl4965_4965_h__ */ +#endif /* __iwl_dev_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 11f9d9557a0..4a08a1b5097 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -382,8 +382,8 @@ static int iwl_set_fat_chan_info(struct iwl_priv *priv, if (!is_channel_valid(ch_info)) return -1; - IWL_DEBUG_INFO("FAT Ch. %d [%sGHz] %s%s%s%s%s(0x%02x" - " %ddBm): Ad-Hoc %ssupported\n", + IWL_DEBUG_INFO("FAT Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm):" + " Ad-Hoc %ssupported\n", ch_info->channel, is_channel_a_band(ch_info) ? "5.2" : "2.4", @@ -470,6 +470,11 @@ int iwl_init_channel_map(struct iwl_priv *priv) /* Copy the run-time flags so they are there even on * invalid channels */ ch_info->flags = eeprom_ch_info[ch].flags; + /* First write that fat is not enabled, and then enable + * one by one */ + ch_info->fat_extension_channel = + (IEEE80211_CHAN_NO_FAT_ABOVE | + IEEE80211_CHAN_NO_FAT_BELOW); if (!(is_channel_valid(ch_info))) { IWL_DEBUG_INFO("Ch. %d Flags %x [%sGHz] - " @@ -488,8 +493,8 @@ int iwl_init_channel_map(struct iwl_priv *priv) ch_info->scan_power = eeprom_ch_info[ch].max_power_avg; ch_info->min_power = 0; - IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x" - " %ddBm): Ad-Hoc %ssupported\n", + IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm):" + " Ad-Hoc %ssupported\n", ch_info->channel, is_channel_a_band(ch_info) ? "5.2" : "2.4", @@ -510,8 +515,8 @@ int iwl_init_channel_map(struct iwl_priv *priv) /* Set the user_txpower_limit to the highest power * supported by any channel */ if (eeprom_ch_info[ch].max_power_avg > - priv->user_txpower_limit) - priv->user_txpower_limit = + priv->tx_power_user_lmt) + priv->tx_power_user_lmt = eeprom_ch_info[ch].max_power_avg; ch_info++; @@ -534,12 +539,14 @@ int iwl_init_channel_map(struct iwl_priv *priv) for (ch = 0; ch < eeprom_ch_count; ch++) { if ((band == 6) && - ((eeprom_ch_index[ch] == 5) || - (eeprom_ch_index[ch] == 6) || - (eeprom_ch_index[ch] == 7))) - fat_extension_chan = HT_IE_EXT_CHANNEL_MAX; + ((eeprom_ch_index[ch] == 5) || + (eeprom_ch_index[ch] == 6) || + (eeprom_ch_index[ch] == 7))) + /* both are allowed: above and below */ + fat_extension_chan = 0; else - fat_extension_chan = HT_IE_EXT_CHANNEL_ABOVE; + fat_extension_chan = + IEEE80211_CHAN_NO_FAT_BELOW; /* Set up driver's info for lower half */ iwl_set_fat_chan_info(priv, ieeeband, @@ -551,7 +558,7 @@ int iwl_init_channel_map(struct iwl_priv *priv) iwl_set_fat_chan_info(priv, ieeeband, (eeprom_ch_index[ch] + 4), &(eeprom_ch_info[ch]), - HT_IE_EXT_CHANNEL_BELOW); + IEEE80211_CHAN_NO_FAT_ABOVE); } } diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index dedefa06ad8..41eed679332 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -139,123 +139,12 @@ static inline void iwl_set_bits16(__le16 *dst, u8 pos, u8 len, int val) #define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo)))) -#define IEEE80211_CHAN_W_RADAR_DETECT 0x00000010 - static inline struct ieee80211_conf *ieee80211_get_hw_conf( struct ieee80211_hw *hw) { return &hw->conf; } -#define QOS_CONTROL_LEN 2 - - -static inline int ieee80211_is_management(u16 fc) -{ - return (fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT; -} - -static inline int ieee80211_is_control(u16 fc) -{ - return (fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL; -} - -static inline int ieee80211_is_data(u16 fc) -{ - return (fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA; -} - -static inline int ieee80211_is_back_request(u16 fc) -{ - return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) && - ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BACK_REQ); -} - -static inline int ieee80211_is_probe_response(u16 fc) -{ - return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) && - ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP); -} - -static inline int ieee80211_is_probe_request(u16 fc) -{ - return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) && - ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_REQ); -} - -static inline int ieee80211_is_beacon(u16 fc) -{ - return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) && - ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON); -} - -static inline int ieee80211_is_atim(u16 fc) -{ - return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) && - ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ATIM); -} - -static inline int ieee80211_is_assoc_request(u16 fc) -{ - return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) && - ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ); -} - -static inline int ieee80211_is_assoc_response(u16 fc) -{ - return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) && - ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_RESP); -} - -static inline int ieee80211_is_auth(u16 fc) -{ - return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) && - ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ); -} - -static inline int ieee80211_is_deauth(u16 fc) -{ - return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) && - ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ); -} - -static inline int ieee80211_is_disassoc(u16 fc) -{ - return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) && - ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ); -} - -static inline int ieee80211_is_reassoc_request(u16 fc) -{ - return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) && - ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_REASSOC_REQ); -} - -static inline int ieee80211_is_reassoc_response(u16 fc) -{ - return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) && - ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_REASSOC_RESP); -} - -static inline int ieee80211_is_qos_data(u16 fc) -{ - return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) && - ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_QOS_DATA); -} -/** - * ieee80211_get_qos_ctrl - get pointer to the QoS control field - * - * This function returns the pointer to 802.11 header QoS field (2 bytes) - * This function doesn't check whether hdr is a QoS hdr, use with care - * @hdr: struct ieee80211_hdr *hdr - * @hdr_len: header length - */ - -static inline u8 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr, int hdr_len) -{ - return ((u8 *) hdr + hdr_len - QOS_CONTROL_LEN); -} - static inline int iwl_check_bits(unsigned long field, unsigned long mask) { return ((field & mask) == mask) ? 1 : 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c index 59c8a716bd9..5f098747cf9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c @@ -55,13 +55,13 @@ static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state) switch (state) { case RFKILL_STATE_ON: - priv->cfg->ops->lib->radio_kill_sw(priv, 0); + iwl_radio_kill_sw_enable_radio(priv); /* if HW rf-kill is set dont allow ON state */ if (iwl_is_rfkill(priv)) err = -EBUSY; break; case RFKILL_STATE_OFF: - priv->cfg->ops->lib->radio_kill_sw(priv, 1); + iwl_radio_kill_sw_disable_radio(priv); if (!iwl_is_rfkill(priv)) err = -EBUSY; break; diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.h b/drivers/net/wireless/iwlwifi/iwl-rfkill.h index a7f04b85540..b3c04dba45c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.h +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.h @@ -33,7 +33,6 @@ struct iwl_priv; #include <linux/rfkill.h> #include <linux/input.h> - #ifdef CONFIG_IWLWIFI_RFKILL struct iwl_rfkill_mngr { struct rfkill *rfkill; diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index cc61c937320..c24844802a8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -451,7 +451,6 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { -#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; struct iwl4965_missed_beacon_notif *missed_beacon; @@ -465,6 +464,5 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, if (!test_bit(STATUS_SCANNING, &priv->status)) iwl_init_sensitivity(priv); } -#endif /* CONFIG_IWLWIFI_RUN_TIME_CALIB */ } EXPORT_SYMBOL(iwl_rx_missed_beacon_notif); diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c new file mode 100644 index 00000000000..5ca181f7125 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -0,0 +1,921 @@ +/****************************************************************************** + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * 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 Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Tomas Winkler <tomas.winkler@intel.com> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + *****************************************************************************/ +#include <net/mac80211.h> +#include <linux/etherdevice.h> + +#include "iwl-eeprom.h" +#include "iwl-dev.h" +#include "iwl-core.h" +#include "iwl-sta.h" +#include "iwl-io.h" +#include "iwl-helpers.h" + +/* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after + * sending probe req. This should be set long enough to hear probe responses + * from more than one AP. */ +#define IWL_ACTIVE_DWELL_TIME_24 (20) /* all times in msec */ +#define IWL_ACTIVE_DWELL_TIME_52 (10) + +/* For faster active scanning, scan will move to the next channel if fewer than + * PLCP_QUIET_THRESH packets are heard on this channel within + * ACTIVE_QUIET_TIME after sending probe request. This shortens the dwell + * time if it's a quiet channel (nothing responded to our probe, and there's + * no other traffic). + * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */ +#define IWL_PLCP_QUIET_THRESH __constant_cpu_to_le16(1) /* packets */ +#define IWL_ACTIVE_QUIET_TIME __constant_cpu_to_le16(5) /* msec */ + +/* For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel. + * Must be set longer than active dwell time. + * For the most reliable scan, set > AP beacon interval (typically 100msec). */ +#define IWL_PASSIVE_DWELL_TIME_24 (20) /* all times in msec */ +#define IWL_PASSIVE_DWELL_TIME_52 (10) +#define IWL_PASSIVE_DWELL_BASE (100) +#define IWL_CHANNEL_TUNE_TIME 5 + +static int scan_tx_ant[3] = { + RATE_MCS_ANT_A_MSK, RATE_MCS_ANT_B_MSK, RATE_MCS_ANT_C_MSK +}; + +static int iwl_is_empty_essid(const char *essid, int essid_len) +{ + /* Single white space is for Linksys APs */ + if (essid_len == 1 && essid[0] == ' ') + return 1; + + /* Otherwise, if the entire essid is 0, we assume it is hidden */ + while (essid_len) { + essid_len--; + if (essid[essid_len] != '\0') + return 0; + } + + return 1; +} + + + +const char *iwl_escape_essid(const char *essid, u8 essid_len) +{ + static char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; + const char *s = essid; + char *d = escaped; + + if (iwl_is_empty_essid(essid, essid_len)) { + memcpy(escaped, "<hidden>", sizeof("<hidden>")); + return escaped; + } + + essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE); + while (essid_len--) { + if (*s == '\0') { + *d++ = '\\'; + *d++ = '0'; + s++; + } else + *d++ = *s++; + } + *d = '\0'; + return escaped; +} +EXPORT_SYMBOL(iwl_escape_essid); + +/** + * iwl_scan_cancel - Cancel any currently executing HW scan + * + * NOTE: priv->mutex is not required before calling this function + */ +int iwl_scan_cancel(struct iwl_priv *priv) +{ + if (!test_bit(STATUS_SCAN_HW, &priv->status)) { + clear_bit(STATUS_SCANNING, &priv->status); + return 0; + } + + if (test_bit(STATUS_SCANNING, &priv->status)) { + if (!test_bit(STATUS_SCAN_ABORTING, &priv->status)) { + IWL_DEBUG_SCAN("Queuing scan abort.\n"); + set_bit(STATUS_SCAN_ABORTING, &priv->status); + queue_work(priv->workqueue, &priv->abort_scan); + + } else + IWL_DEBUG_SCAN("Scan abort already in progress.\n"); + + return test_bit(STATUS_SCANNING, &priv->status); + } + + return 0; +} +EXPORT_SYMBOL(iwl_scan_cancel); +/** + * iwl_scan_cancel_timeout - Cancel any currently executing HW scan + * @ms: amount of time to wait (in milliseconds) for scan to abort + * + * NOTE: priv->mutex must be held before calling this function + */ +int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms) +{ + unsigned long now = jiffies; + int ret; + + ret = iwl_scan_cancel(priv); + if (ret && ms) { + mutex_unlock(&priv->mutex); + while (!time_after(jiffies, now + msecs_to_jiffies(ms)) && + test_bit(STATUS_SCANNING, &priv->status)) + msleep(1); + mutex_lock(&priv->mutex); + + return test_bit(STATUS_SCANNING, &priv->status); + } + + return ret; +} +EXPORT_SYMBOL(iwl_scan_cancel_timeout); + +static int iwl_send_scan_abort(struct iwl_priv *priv) +{ + int ret = 0; + struct iwl_rx_packet *res; + struct iwl_host_cmd cmd = { + .id = REPLY_SCAN_ABORT_CMD, + .meta.flags = CMD_WANT_SKB, + }; + + /* If there isn't a scan actively going on in the hardware + * then we are in between scan bands and not actually + * actively scanning, so don't send the abort command */ + if (!test_bit(STATUS_SCAN_HW, &priv->status)) { + clear_bit(STATUS_SCAN_ABORTING, &priv->status); + return 0; + } + + ret = iwl_send_cmd_sync(priv, &cmd); + if (ret) { + clear_bit(STATUS_SCAN_ABORTING, &priv->status); + return ret; + } + + res = (struct iwl_rx_packet *)cmd.meta.u.skb->data; + if (res->u.status != CAN_ABORT_STATUS) { + /* The scan abort will return 1 for success or + * 2 for "failure". A failure condition can be + * due to simply not being in an active scan which + * can occur if we send the scan abort before we + * the microcode has notified us that a scan is + * completed. */ + IWL_DEBUG_INFO("SCAN_ABORT returned %d.\n", res->u.status); + clear_bit(STATUS_SCAN_ABORTING, &priv->status); + clear_bit(STATUS_SCAN_HW, &priv->status); + } + + dev_kfree_skb_any(cmd.meta.u.skb); + + return ret; +} + + +/* Service response to REPLY_SCAN_CMD (0x80) */ +static void iwl_rx_reply_scan(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) +{ +#ifdef CONFIG_IWLWIFI_DEBUG + struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; + struct iwl_scanreq_notification *notif = + (struct iwl_scanreq_notification *)pkt->u.raw; + + IWL_DEBUG_RX("Scan request status = 0x%x\n", notif->status); +#endif +} + +/* Service SCAN_START_NOTIFICATION (0x82) */ +static void iwl_rx_scan_start_notif(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) +{ + struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; + struct iwl_scanstart_notification *notif = + (struct iwl_scanstart_notification *)pkt->u.raw; + priv->scan_start_tsf = le32_to_cpu(notif->tsf_low); + IWL_DEBUG_SCAN("Scan start: " + "%d [802.11%s] " + "(TSF: 0x%08X:%08X) - %d (beacon timer %u)\n", + notif->channel, + notif->band ? "bg" : "a", + notif->tsf_high, + notif->tsf_low, notif->status, notif->beacon_timer); +} + +/* Service SCAN_RESULTS_NOTIFICATION (0x83) */ +static void iwl_rx_scan_results_notif(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) +{ +#ifdef CONFIG_IWLWIFI_DEBUG + struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; + struct iwl_scanresults_notification *notif = + (struct iwl_scanresults_notification *)pkt->u.raw; + + IWL_DEBUG_SCAN("Scan ch.res: " + "%d [802.11%s] " + "(TSF: 0x%08X:%08X) - %d " + "elapsed=%lu usec (%dms since last)\n", + notif->channel, + notif->band ? "bg" : "a", + le32_to_cpu(notif->tsf_high), + le32_to_cpu(notif->tsf_low), + le32_to_cpu(notif->statistics[0]), + le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf, + jiffies_to_msecs(elapsed_jiffies + (priv->last_scan_jiffies, jiffies))); +#endif + + priv->last_scan_jiffies = jiffies; + priv->next_scan_jiffies = 0; +} + +/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */ +static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) +{ + struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; + struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw; + + IWL_DEBUG_SCAN("Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n", + scan_notif->scanned_channels, + scan_notif->tsf_low, + scan_notif->tsf_high, scan_notif->status); + + /* The HW is no longer scanning */ + clear_bit(STATUS_SCAN_HW, &priv->status); + + /* The scan completion notification came in, so kill that timer... */ + cancel_delayed_work(&priv->scan_check); + + IWL_DEBUG_INFO("Scan pass on %sGHz took %dms\n", + (priv->scan_bands == 2) ? "2.4" : "5.2", + jiffies_to_msecs(elapsed_jiffies + (priv->scan_pass_start, jiffies))); + + /* Remove this scanned band from the list + * of pending bands to scan */ + priv->scan_bands--; + + /* If a request to abort was given, or the scan did not succeed + * then we reset the scan state machine and terminate, + * re-queuing another scan if one has been requested */ + if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { + IWL_DEBUG_INFO("Aborted scan completed.\n"); + clear_bit(STATUS_SCAN_ABORTING, &priv->status); + } else { + /* If there are more bands on this scan pass reschedule */ + if (priv->scan_bands > 0) + goto reschedule; + } + + priv->last_scan_jiffies = jiffies; + priv->next_scan_jiffies = 0; + IWL_DEBUG_INFO("Setting scan to off\n"); + + clear_bit(STATUS_SCANNING, &priv->status); + + IWL_DEBUG_INFO("Scan took %dms\n", + jiffies_to_msecs(elapsed_jiffies(priv->scan_start, jiffies))); + + queue_work(priv->workqueue, &priv->scan_completed); + + return; + +reschedule: + priv->scan_pass_start = jiffies; + queue_work(priv->workqueue, &priv->request_scan); +} + +void iwl_setup_rx_scan_handlers(struct iwl_priv *priv) +{ + /* scan handlers */ + priv->rx_handlers[REPLY_SCAN_CMD] = iwl_rx_reply_scan; + priv->rx_handlers[SCAN_START_NOTIFICATION] = iwl_rx_scan_start_notif; + priv->rx_handlers[SCAN_RESULTS_NOTIFICATION] = + iwl_rx_scan_results_notif; + priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] = + iwl_rx_scan_complete_notif; +} +EXPORT_SYMBOL(iwl_setup_rx_scan_handlers); + +static inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, + enum ieee80211_band band) +{ + if (band == IEEE80211_BAND_5GHZ) + return IWL_ACTIVE_DWELL_TIME_52; + else + return IWL_ACTIVE_DWELL_TIME_24; +} + +static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, + enum ieee80211_band band) +{ + u16 active = iwl_get_active_dwell_time(priv, band); + u16 passive = (band != IEEE80211_BAND_5GHZ) ? + IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : + IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; + + if (iwl_is_associated(priv)) { + /* If we're associated, we clamp the maximum passive + * dwell time to be 98% of the beacon interval (minus + * 2 * channel tune time) */ + passive = priv->beacon_int; + if ((passive > IWL_PASSIVE_DWELL_BASE) || !passive) + passive = IWL_PASSIVE_DWELL_BASE; + passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; + } + + if (passive <= active) + passive = active + 1; + + return passive; +} + +static int iwl_get_channels_for_scan(struct iwl_priv *priv, + enum ieee80211_band band, + u8 is_active, u8 direct_mask, + struct iwl_scan_channel *scan_ch) +{ + const struct ieee80211_channel *channels = NULL; + const struct ieee80211_supported_band *sband; + const struct iwl_channel_info *ch_info; + u16 passive_dwell = 0; + u16 active_dwell = 0; + int added, i; + + sband = iwl_get_hw_mode(priv, band); + if (!sband) + return 0; + + channels = sband->channels; + + active_dwell = iwl_get_active_dwell_time(priv, band); + passive_dwell = iwl_get_passive_dwell_time(priv, band); + + for (i = 0, added = 0; i < sband->n_channels; i++) { + if (channels[i].flags & IEEE80211_CHAN_DISABLED) + continue; + + scan_ch->channel = + ieee80211_frequency_to_channel(channels[i].center_freq); + + ch_info = iwl_get_channel_info(priv, band, scan_ch->channel); + if (!is_channel_valid(ch_info)) { + IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n", + scan_ch->channel); + continue; + } + + if (!is_active || is_channel_passive(ch_info) || + (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN)) + scan_ch->type = 0; + else + scan_ch->type = 1; + + if (scan_ch->type & 1) + scan_ch->type |= (direct_mask << 1); + + scan_ch->active_dwell = cpu_to_le16(active_dwell); + scan_ch->passive_dwell = cpu_to_le16(passive_dwell); + + /* Set txpower levels to defaults */ + scan_ch->dsp_atten = 110; + + if (band == IEEE80211_BAND_5GHZ) + scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; + else { + scan_ch->tx_gain = ((1 << 5) | (5 << 3)); + /* NOTE: if we were doing 6Mb OFDM for scans we'd use + * power level: + * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; + */ + } + + IWL_DEBUG_SCAN("Scanning %d [%s %d]\n", + scan_ch->channel, + (scan_ch->type & 1) ? "ACTIVE" : "PASSIVE", + (scan_ch->type & 1) ? + active_dwell : passive_dwell); + + scan_ch++; + added++; + } + + IWL_DEBUG_SCAN("total channels to scan %d \n", added); + return added; +} + +void iwl_init_scan_params(struct iwl_priv *priv) +{ + if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ]) + priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = RATE_MCS_ANT_INIT_IND; + if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ]) + priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = RATE_MCS_ANT_INIT_IND; +} + +int iwl_scan_initiate(struct iwl_priv *priv) +{ + if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { + IWL_ERROR("APs don't scan.\n"); + return 0; + } + + if (!iwl_is_ready_rf(priv)) { + IWL_DEBUG_SCAN("Aborting scan due to not ready.\n"); + return -EIO; + } + + if (test_bit(STATUS_SCANNING, &priv->status)) { + IWL_DEBUG_SCAN("Scan already in progress.\n"); + return -EAGAIN; + } + + if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { + IWL_DEBUG_SCAN("Scan request while abort pending. " + "Queuing.\n"); + return -EAGAIN; + } + + IWL_DEBUG_INFO("Starting scan...\n"); + priv->scan_bands = 2; + set_bit(STATUS_SCANNING, &priv->status); + priv->scan_start = jiffies; + priv->scan_pass_start = priv->scan_start; + + queue_work(priv->workqueue, &priv->request_scan); + + return 0; +} +EXPORT_SYMBOL(iwl_scan_initiate); + +#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ) + +static void iwl_bg_scan_check(struct work_struct *data) +{ + struct iwl_priv *priv = + container_of(data, struct iwl_priv, scan_check.work); + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + mutex_lock(&priv->mutex); + if (test_bit(STATUS_SCANNING, &priv->status) || + test_bit(STATUS_SCAN_ABORTING, &priv->status)) { + IWL_DEBUG(IWL_DL_SCAN, "Scan completion watchdog resetting " + "adapter (%dms)\n", + jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG)); + + if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) + iwl_send_scan_abort(priv); + } + mutex_unlock(&priv->mutex); +} +/** + * iwl_supported_rate_to_ie - fill in the supported rate in IE field + * + * return : set the bit for each supported rate insert in ie + */ +static u16 iwl_supported_rate_to_ie(u8 *ie, u16 supported_rate, + u16 basic_rate, int *left) +{ + u16 ret_rates = 0, bit; + int i; + u8 *cnt = ie; + u8 *rates = ie + 1; + + for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) { + if (bit & supported_rate) { + ret_rates |= bit; + rates[*cnt] = iwl_rates[i].ieee | + ((bit & basic_rate) ? 0x80 : 0x00); + (*cnt)++; + (*left)--; + if ((*left <= 0) || + (*cnt >= IWL_SUPPORTED_RATES_IE_LEN)) + break; + } + } + + return ret_rates; +} + + +static void iwl_ht_cap_to_ie(const struct ieee80211_supported_band *sband, + u8 *pos, int *left) +{ + struct ieee80211_ht_cap *ht_cap; + + if (!sband || !sband->ht_info.ht_supported) + return; + + if (*left < sizeof(struct ieee80211_ht_cap)) + return; + + *pos++ = sizeof(struct ieee80211_ht_cap); + ht_cap = (struct ieee80211_ht_cap *) pos; + + ht_cap->cap_info = cpu_to_le16(sband->ht_info.cap); + memcpy(ht_cap->supp_mcs_set, sband->ht_info.supp_mcs_set, 16); + ht_cap->ampdu_params_info = + (sband->ht_info.ampdu_factor & IEEE80211_HT_CAP_AMPDU_FACTOR) | + ((sband->ht_info.ampdu_density << 2) & + IEEE80211_HT_CAP_AMPDU_DENSITY); + *left -= sizeof(struct ieee80211_ht_cap); +} + +/** + * iwl_fill_probe_req - fill in all required fields and IE for probe request + */ + +static u16 iwl_fill_probe_req(struct iwl_priv *priv, + enum ieee80211_band band, + struct ieee80211_mgmt *frame, + int left) +{ + int len = 0; + u8 *pos = NULL; + u16 active_rates, ret_rates, cck_rates, active_rate_basic; + const struct ieee80211_supported_band *sband = + iwl_get_hw_mode(priv, band); + + + /* Make sure there is enough space for the probe request, + * two mandatory IEs and the data */ + left -= 24; + if (left < 0) + return 0; + + frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); + memcpy(frame->da, iwl_bcast_addr, ETH_ALEN); + memcpy(frame->sa, priv->mac_addr, ETH_ALEN); + memcpy(frame->bssid, iwl_bcast_addr, ETH_ALEN); + frame->seq_ctrl = 0; + + len += 24; + + /* ...next IE... */ + pos = &frame->u.probe_req.variable[0]; + + /* fill in our indirect SSID IE */ + left -= 2; + if (left < 0) + return 0; + *pos++ = WLAN_EID_SSID; + *pos++ = 0; + + len += 2; + + /* fill in supported rate */ + left -= 2; + if (left < 0) + return 0; + + *pos++ = WLAN_EID_SUPP_RATES; + *pos = 0; + + /* exclude 60M rate */ + active_rates = priv->rates_mask; + active_rates &= ~IWL_RATE_60M_MASK; + + active_rate_basic = active_rates & IWL_BASIC_RATES_MASK; + + cck_rates = IWL_CCK_RATES_MASK & active_rates; + ret_rates = iwl_supported_rate_to_ie(pos, cck_rates, + active_rate_basic, &left); + active_rates &= ~ret_rates; + + ret_rates = iwl_supported_rate_to_ie(pos, active_rates, + active_rate_basic, &left); + active_rates &= ~ret_rates; + + len += 2 + *pos; + pos += (*pos) + 1; + + if (active_rates == 0) + goto fill_end; + + /* fill in supported extended rate */ + /* ...next IE... */ + left -= 2; + if (left < 0) + return 0; + /* ... fill it in... */ + *pos++ = WLAN_EID_EXT_SUPP_RATES; + *pos = 0; + iwl_supported_rate_to_ie(pos, active_rates, active_rate_basic, &left); + if (*pos > 0) { + len += 2 + *pos; + pos += (*pos) + 1; + } else { + pos--; + } + + fill_end: + + left -= 2; + if (left < 0) + return 0; + + *pos++ = WLAN_EID_HT_CAPABILITY; + *pos = 0; + iwl_ht_cap_to_ie(sband, pos, &left); + if (*pos > 0) + len += 2 + *pos; + + return (u16)len; +} + +static u32 iwl_scan_tx_ant(struct iwl_priv *priv, enum ieee80211_band band) +{ + int i, ind; + + ind = priv->scan_tx_ant[band]; + for (i = 0; i < priv->hw_params.tx_chains_num; i++) { + ind = (ind+1) >= priv->hw_params.tx_chains_num ? 0 : ind+1; + if (priv->hw_params.valid_tx_ant & (1 << ind)) { + priv->scan_tx_ant[band] = ind; + break; + } + } + + return scan_tx_ant[ind]; +} + + +static void iwl_bg_request_scan(struct work_struct *data) +{ + struct iwl_priv *priv = + container_of(data, struct iwl_priv, request_scan); + struct iwl_host_cmd cmd = { + .id = REPLY_SCAN_CMD, + .len = sizeof(struct iwl_scan_cmd), + .meta.flags = CMD_SIZE_HUGE, + }; + struct iwl_scan_cmd *scan; + struct ieee80211_conf *conf = NULL; + int ret = 0; + u32 tx_ant; + u16 cmd_len; + enum ieee80211_band band; + u8 direct_mask; + u8 rx_chain = 0x7; /* bitmap: ABC chains */ + + conf = ieee80211_get_hw_conf(priv->hw); + + mutex_lock(&priv->mutex); + + if (!iwl_is_ready(priv)) { + IWL_WARNING("request scan called when driver not ready.\n"); + goto done; + } + + /* Make sure the scan wasn't cancelled before this queued work + * was given the chance to run... */ + if (!test_bit(STATUS_SCANNING, &priv->status)) + goto done; + + /* This should never be called or scheduled if there is currently + * a scan active in the hardware. */ + if (test_bit(STATUS_SCAN_HW, &priv->status)) { + IWL_DEBUG_INFO("Multiple concurrent scan requests in parallel. " + "Ignoring second request.\n"); + ret = -EIO; + goto done; + } + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { + IWL_DEBUG_SCAN("Aborting scan due to device shutdown\n"); + goto done; + } + + if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { + IWL_DEBUG_HC("Scan request while abort pending. Queuing.\n"); + goto done; + } + + if (iwl_is_rfkill(priv)) { + IWL_DEBUG_HC("Aborting scan due to RF Kill activation\n"); + goto done; + } + + if (!test_bit(STATUS_READY, &priv->status)) { + IWL_DEBUG_HC("Scan request while uninitialized. Queuing.\n"); + goto done; + } + + if (!priv->scan_bands) { + IWL_DEBUG_HC("Aborting scan due to no requested bands\n"); + goto done; + } + + if (!priv->scan) { + priv->scan = kmalloc(sizeof(struct iwl_scan_cmd) + + IWL_MAX_SCAN_SIZE, GFP_KERNEL); + if (!priv->scan) { + ret = -ENOMEM; + goto done; + } + } + scan = priv->scan; + memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE); + + scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; + scan->quiet_time = IWL_ACTIVE_QUIET_TIME; + + if (iwl_is_associated(priv)) { + u16 interval = 0; + u32 extra; + u32 suspend_time = 100; + u32 scan_suspend_time = 100; + unsigned long flags; + + IWL_DEBUG_INFO("Scanning while associated...\n"); + + spin_lock_irqsave(&priv->lock, flags); + interval = priv->beacon_int; + spin_unlock_irqrestore(&priv->lock, flags); + + scan->suspend_time = 0; + scan->max_out_time = cpu_to_le32(200 * 1024); + if (!interval) + interval = suspend_time; + + extra = (suspend_time / interval) << 22; + scan_suspend_time = (extra | + ((suspend_time % interval) * 1024)); + scan->suspend_time = cpu_to_le32(scan_suspend_time); + IWL_DEBUG_SCAN("suspend_time 0x%X beacon interval %d\n", + scan_suspend_time, interval); + } + + /* We should add the ability for user to lock to PASSIVE ONLY */ + if (priv->one_direct_scan) { + IWL_DEBUG_SCAN("Start direct scan for '%s'\n", + iwl_escape_essid(priv->direct_ssid, + priv->direct_ssid_len)); + scan->direct_scan[0].id = WLAN_EID_SSID; + scan->direct_scan[0].len = priv->direct_ssid_len; + memcpy(scan->direct_scan[0].ssid, + priv->direct_ssid, priv->direct_ssid_len); + direct_mask = 1; + } else if (!iwl_is_associated(priv) && priv->essid_len) { + IWL_DEBUG_SCAN("Start direct scan for '%s' (not associated)\n", + iwl_escape_essid(priv->essid, priv->essid_len)); + scan->direct_scan[0].id = WLAN_EID_SSID; + scan->direct_scan[0].len = priv->essid_len; + memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len); + direct_mask = 1; + } else { + IWL_DEBUG_SCAN("Start indirect scan.\n"); + direct_mask = 0; + } + + scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; + scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id; + scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; + + + switch (priv->scan_bands) { + case 2: + band = IEEE80211_BAND_2GHZ; + scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; + tx_ant = iwl_scan_tx_ant(priv, band); + if (priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_PURE_40_MSK) + scan->tx_cmd.rate_n_flags = + iwl_hw_set_rate_n_flags(IWL_RATE_6M_PLCP, + tx_ant); + else + scan->tx_cmd.rate_n_flags = + iwl_hw_set_rate_n_flags(IWL_RATE_1M_PLCP, + tx_ant | + RATE_MCS_CCK_MSK); + scan->good_CRC_th = 0; + break; + + case 1: + band = IEEE80211_BAND_5GHZ; + tx_ant = iwl_scan_tx_ant(priv, band); + scan->tx_cmd.rate_n_flags = + iwl_hw_set_rate_n_flags(IWL_RATE_6M_PLCP, + tx_ant); + scan->good_CRC_th = IWL_GOOD_CRC_TH; + + /* Force use of chains B and C (0x6) for scan Rx for 4965 + * Avoid A (0x1) because of its off-channel reception on A-band. + * MIMO is not used here, but value is required */ + if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) + rx_chain = 0x6; + + break; + default: + IWL_WARNING("Invalid scan band count\n"); + goto done; + } + + scan->rx_chain = RXON_RX_CHAIN_DRIVER_FORCE_MSK | + cpu_to_le16((0x7 << RXON_RX_CHAIN_VALID_POS) | + (rx_chain << RXON_RX_CHAIN_FORCE_SEL_POS) | + (0x7 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS)); + + cmd_len = iwl_fill_probe_req(priv, band, + (struct ieee80211_mgmt *)scan->data, + IWL_MAX_SCAN_SIZE - sizeof(*scan)); + + scan->tx_cmd.len = cpu_to_le16(cmd_len); + + if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) + scan->filter_flags = RXON_FILTER_PROMISC_MSK; + + scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | + RXON_FILTER_BCON_AWARE_MSK); + + if (direct_mask) + scan->channel_count = + iwl_get_channels_for_scan(priv, band, 1, /* active */ + direct_mask, + (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); + else + scan->channel_count = + iwl_get_channels_for_scan(priv, band, 0, /* passive */ + direct_mask, + (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); + if (scan->channel_count == 0) { + IWL_DEBUG_SCAN("channel count %d\n", scan->channel_count); + goto done; + } + + cmd.len += le16_to_cpu(scan->tx_cmd.len) + + scan->channel_count * sizeof(struct iwl_scan_channel); + cmd.data = scan; + scan->len = cpu_to_le16(cmd.len); + + set_bit(STATUS_SCAN_HW, &priv->status); + ret = iwl_send_cmd_sync(priv, &cmd); + if (ret) + goto done; + + queue_delayed_work(priv->workqueue, &priv->scan_check, + IWL_SCAN_CHECK_WATCHDOG); + + mutex_unlock(&priv->mutex); + return; + + done: + /* inform mac80211 scan aborted */ + queue_work(priv->workqueue, &priv->scan_completed); + mutex_unlock(&priv->mutex); +} + +static void iwl_bg_abort_scan(struct work_struct *work) +{ + struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan); + + if (!iwl_is_ready(priv)) + return; + + mutex_lock(&priv->mutex); + + set_bit(STATUS_SCAN_ABORTING, &priv->status); + iwl_send_scan_abort(priv); + + mutex_unlock(&priv->mutex); +} + +void iwl_setup_scan_deferred_work(struct iwl_priv *priv) +{ + /* FIXME: move here when resolved PENDING + * INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); */ + INIT_WORK(&priv->request_scan, iwl_bg_request_scan); + INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); + INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check); +} +EXPORT_SYMBOL(iwl_setup_scan_deferred_work); + diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 983f10760fb..f874e7d7b22 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -30,11 +30,9 @@ #include <net/mac80211.h> #include <linux/etherdevice.h> -#include "iwl-eeprom.h" #include "iwl-dev.h" #include "iwl-core.h" #include "iwl-sta.h" -#include "iwl-io.h" #include "iwl-helpers.h" @@ -74,6 +72,17 @@ u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr) } EXPORT_SYMBOL(iwl_find_station); +int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) +{ + if (priv->iw_mode == IEEE80211_IF_TYPE_STA) { + return IWL_AP_ID; + } else { + u8 *da = ieee80211_get_DA(hdr); + return iwl_find_station(priv, da); + } +} +EXPORT_SYMBOL(iwl_get_ra_sta_id); + static int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_cmd *cmd, struct sk_buff *skb) { @@ -105,8 +114,6 @@ static int iwl_add_sta_callback(struct iwl_priv *priv, return 1; } - - int iwl_send_add_sta(struct iwl_priv *priv, struct iwl_addsta_cmd *sta, u8 flags) { @@ -156,8 +163,6 @@ int iwl_send_add_sta(struct iwl_priv *priv, } EXPORT_SYMBOL(iwl_send_add_sta); -#ifdef CONFIG_IWL4965_HT - static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, struct ieee80211_ht_info *sta_ht_inf) { @@ -202,12 +207,6 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, done: return; } -#else -static inline void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, - struct ieee80211_ht_info *sta_ht_info) -{ -} -#endif /** * iwl_add_station_flags - Add station to tables in driver and device @@ -280,7 +279,6 @@ u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap, } EXPORT_SYMBOL(iwl_add_station_flags); - static int iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr) { unsigned long flags; @@ -384,9 +382,9 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, return ret; } + /** * iwl_remove_station - Remove driver's knowledge of station. - * */ u8 iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap) { @@ -426,7 +424,7 @@ out: return 0; } EXPORT_SYMBOL(iwl_remove_station); -int iwl_get_free_ucode_key_index(struct iwl_priv *priv) +static int iwl_get_free_ucode_key_index(struct iwl_priv *priv) { int i; @@ -496,6 +494,8 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, priv->default_wep_key--; memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0])); ret = iwl_send_static_wepkey_cmd(priv, 1); + IWL_DEBUG_WEP("Remove default WEP key: idx=%d ret=%d\n", + keyconf->keyidx, ret); spin_unlock_irqrestore(&priv->sta_lock, flags); return ret; @@ -508,6 +508,12 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, int ret; unsigned long flags; + if (keyconf->keylen != WEP_KEY_LEN_128 && + keyconf->keylen != WEP_KEY_LEN_64) { + IWL_DEBUG_WEP("Bad WEP key length %d\n", keyconf->keylen); + return -EINVAL; + } + keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; keyconf->hw_key_idx = HW_KEY_DEFAULT; priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP; @@ -524,6 +530,8 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, keyconf->keylen); ret = iwl_send_static_wepkey_cmd(priv, 0); + IWL_DEBUG_WEP("Set default WEP key: len=%d idx=%d ret=%d\n", + keyconf->keylen, keyconf->keyidx, ret); spin_unlock_irqrestore(&priv->sta_lock, flags); return ret; @@ -670,6 +678,9 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags); keyidx = (key_flags >> STA_KEY_FLG_KEYID_POS) & 0x3; + IWL_DEBUG_WEP("Remove dynamic key: idx=%d sta=%d\n", + keyconf->keyidx, sta_id); + if (keyconf->keyidx != keyidx) { /* We need to remove a key with index different that the one * in the uCode. This means that the key we need to remove has @@ -694,7 +705,6 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n"); ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); spin_unlock_irqrestore(&priv->sta_lock, flags); return ret; @@ -724,6 +734,10 @@ int iwl_set_dynamic_key(struct iwl_priv *priv, ret = -EINVAL; } + IWL_DEBUG_WEP("Set dynamic key: alg= %d len=%d idx=%d sta=%d ret=%d\n", + keyconf->alg, keyconf->keylen, keyconf->keyidx, + sta_id, ret); + return ret; } EXPORT_SYMBOL(iwl_set_dynamic_key); @@ -816,7 +830,7 @@ static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, int is_ap) rate_flags |= RATE_MCS_ANT_B_MSK; /*FIXME:RS*/ link_cmd.rs_table[i].rate_n_flags = - iwl4965_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); + iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); r = iwl4965_get_prev_ieee_rate(r); } @@ -842,7 +856,6 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap) u8 sta_id; /* Add station to device's station table */ -#ifdef CONFIG_IWL4965_HT struct ieee80211_conf *conf = &priv->hw->conf; struct ieee80211_ht_info *cur_ht_config = &conf->ht_conf; @@ -852,7 +865,6 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap) sta_id = iwl_add_station_flags(priv, addr, is_ap, 0, cur_ht_config); else -#endif /* CONFIG_IWL4965_HT */ sta_id = iwl_add_station_flags(priv, addr, is_ap, 0, NULL); @@ -863,7 +875,6 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap) } EXPORT_SYMBOL(iwl_rxon_add_station); - /** * iwl_get_sta_id - Find station's index within station table * @@ -921,7 +932,6 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) } EXPORT_SYMBOL(iwl_get_sta_id); - /** * iwl_sta_modify_enable_tid_tx - Enable Tx for this TID in station table */ @@ -940,4 +950,3 @@ void iwl_sta_modify_enable_tid_tx(struct iwl_priv *priv, int sta_id, int tid) } EXPORT_SYMBOL(iwl_sta_modify_enable_tid_tx); - diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 3d55716f530..b6bb209fdd5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -32,18 +32,24 @@ #define HW_KEY_DYNAMIC 0 #define HW_KEY_DEFAULT 1 -int iwl_get_free_ucode_key_index(struct iwl_priv *priv); +/** + * iwl_find_station - Find station id for a given BSSID + * @bssid: MAC address of station ID to find + */ +u8 iwl_find_station(struct iwl_priv *priv, const u8 *bssid); + int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty); int iwl_remove_default_wep_key(struct iwl_priv *priv, - struct ieee80211_key_conf *key); + struct ieee80211_key_conf *key); int iwl_set_default_wep_key(struct iwl_priv *priv, - struct ieee80211_key_conf *key); + struct ieee80211_key_conf *key); int iwl_set_dynamic_key(struct iwl_priv *priv, - struct ieee80211_key_conf *key, u8 sta_id); + struct ieee80211_key_conf *key, u8 sta_id); int iwl_remove_dynamic_key(struct iwl_priv *priv, - struct ieee80211_key_conf *key, u8 sta_id); + struct ieee80211_key_conf *key, u8 sta_id); int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap); u8 iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap); int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); void iwl_sta_modify_enable_tid_tx(struct iwl_priv *priv, int sta_id, int tid); +int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); #endif /* __iwl_sta_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index cfe6f4b233d..7296e2846ec 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -36,8 +36,6 @@ #include "iwl-io.h" #include "iwl-helpers.h" -#ifdef CONFIG_IWL4965_HT - static const u16 default_tid_to_tx_fifo[] = { IWL_TX_FIFO_AC1, IWL_TX_FIFO_AC0, @@ -58,9 +56,6 @@ static const u16 default_tid_to_tx_fifo[] = { IWL_TX_FIFO_AC3 }; -#endif /*CONFIG_IWL4965_HT */ - - /** * iwl_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] @@ -574,15 +569,15 @@ static void iwl_tx_cmd_build_basic(struct iwl_priv *priv, struct ieee80211_hdr *hdr, int is_unicast, u8 std_id) { - u16 fc = le16_to_cpu(hdr->frame_control); + __le16 fc = hdr->frame_control; __le32 tx_flags = tx_cmd->tx_flags; tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { tx_flags |= TX_CMD_FLG_ACK_MSK; - if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) + if (ieee80211_is_mgmt(fc)) tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; - if (ieee80211_is_probe_response(fc) && + if (ieee80211_is_probe_resp(fc) && !(le16_to_cpu(hdr->seq_ctrl) & 0xf)) tx_flags |= TX_CMD_FLG_TSF_MSK; } else { @@ -590,16 +585,16 @@ static void iwl_tx_cmd_build_basic(struct iwl_priv *priv, tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; } - if (ieee80211_is_back_request(fc)) + if (ieee80211_is_back_req(fc)) tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK; tx_cmd->sta_id = std_id; - if (ieee80211_get_morefrag(hdr)) + if (ieee80211_has_morefrags(fc)) tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK; - if (ieee80211_is_qos_data(fc)) { - u8 *qc = ieee80211_get_qos_ctrl(hdr, ieee80211_get_hdrlen(fc)); + if (ieee80211_is_data_qos(fc)) { + u8 *qc = ieee80211_get_qos_ctl(hdr); tx_cmd->tid_tspec = qc[0] & 0xf; tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; } else { @@ -618,9 +613,8 @@ static void iwl_tx_cmd_build_basic(struct iwl_priv *priv, tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); - if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) { - if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ || - (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_REASSOC_REQ) + if (ieee80211_is_mgmt(fc)) { + if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc)) tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3); else tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2); @@ -639,7 +633,7 @@ static void iwl_tx_cmd_build_basic(struct iwl_priv *priv, static void iwl_tx_cmd_build_rate(struct iwl_priv *priv, struct iwl_tx_cmd *tx_cmd, struct ieee80211_tx_info *info, - u16 fc, int sta_id, + __le16 fc, int sta_id, int is_hcca) { u8 rts_retry_limit = 0; @@ -660,7 +654,7 @@ static void iwl_tx_cmd_build_rate(struct iwl_priv *priv, rate_flags |= RATE_MCS_CCK_MSK; - if (ieee80211_is_probe_response(fc)) { + if (ieee80211_is_probe_resp(fc)) { data_retry_limit = 3; if (data_retry_limit < rts_retry_limit) rts_retry_limit = data_retry_limit; @@ -675,11 +669,11 @@ static void iwl_tx_cmd_build_rate(struct iwl_priv *priv, tx_cmd->initial_rate_index = 0; tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; } else { - switch (fc & IEEE80211_FCTL_STYPE) { - case IEEE80211_STYPE_AUTH: - case IEEE80211_STYPE_DEAUTH: - case IEEE80211_STYPE_ASSOC_REQ: - case IEEE80211_STYPE_REASSOC_REQ: + switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { + case cpu_to_le16(IEEE80211_STYPE_AUTH): + case cpu_to_le16(IEEE80211_STYPE_DEAUTH): + case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): + case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): if (tx_cmd->tx_flags & TX_CMD_FLG_RTS_MSK) { tx_cmd->tx_flags &= ~TX_CMD_FLG_RTS_MSK; tx_cmd->tx_flags |= TX_CMD_FLG_CTS_MSK; @@ -701,7 +695,7 @@ static void iwl_tx_cmd_build_rate(struct iwl_priv *priv, tx_cmd->rts_retry_limit = rts_retry_limit; tx_cmd->data_retry_limit = data_retry_limit; - tx_cmd->rate_n_flags = iwl4965_hw_set_rate_n_flags(rate_plcp, rate_flags); + tx_cmd->rate_n_flags = iwl_hw_set_rate_n_flags(rate_plcp, rate_flags); } static void iwl_tx_cmd_build_hwcrypto(struct iwl_priv *priv, @@ -776,7 +770,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) u16 seq_number = 0; u8 id, hdr_len, unicast; u8 sta_id; - u16 fc; + __le16 fc; u8 wait_write_ptr = 0; u8 tid = 0; u8 *qc = NULL; @@ -803,19 +797,19 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) unicast = !is_multicast_ether_addr(hdr->addr1); id = 0; - fc = le16_to_cpu(hdr->frame_control); + fc = hdr->frame_control; #ifdef CONFIG_IWLWIFI_DEBUG if (ieee80211_is_auth(fc)) IWL_DEBUG_TX("Sending AUTH frame\n"); - else if (ieee80211_is_assoc_request(fc)) + else if (ieee80211_is_assoc_req(fc)) IWL_DEBUG_TX("Sending ASSOC frame\n"); - else if (ieee80211_is_reassoc_request(fc)) + else if (ieee80211_is_reassoc_req(fc)) IWL_DEBUG_TX("Sending REASSOC frame\n"); #endif /* drop all data frame if we are not associated */ - if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) && + if (ieee80211_is_data(fc) && (!iwl_is_associated(priv) || ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id) || !priv->assoc_station_added)) { @@ -825,7 +819,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) spin_unlock_irqrestore(&priv->lock, flags); - hdr_len = ieee80211_get_hdrlen(fc); + hdr_len = ieee80211_get_hdrlen(le16_to_cpu(fc)); /* Find (or create) index into station table for destination station */ sta_id = iwl_get_sta_id(priv, hdr); @@ -839,8 +833,8 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) IWL_DEBUG_TX("station Id %d\n", sta_id); - if (ieee80211_is_qos_data(fc)) { - qc = ieee80211_get_qos_ctrl(hdr, hdr_len); + if (ieee80211_is_data_qos(fc)) { + qc = ieee80211_get_qos_ctl(hdr); tid = qc[0] & 0xf; seq_number = priv->stations[sta_id].tid[tid].seq_number & IEEE80211_SCTL_SEQ; @@ -848,12 +842,10 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) (hdr->seq_ctrl & __constant_cpu_to_le16(IEEE80211_SCTL_FRAG)); seq_number += 0x10; -#ifdef CONFIG_IWL4965_HT /* aggregation is on for this <sta,tid> */ if (info->flags & IEEE80211_TX_CTL_AMPDU) txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; priv->stations[sta_id].tid[tid].tfds_in_queue++; -#endif /* CONFIG_IWL4965_HT */ } /* Descriptor for chosen Tx queue */ @@ -945,14 +937,14 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* set is_hcca to 0; it probably will never be implemented */ iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc, sta_id, 0); - iwl_update_tx_stats(priv, fc, len); + iwl_update_tx_stats(priv, le16_to_cpu(fc), len); scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + offsetof(struct iwl_tx_cmd, scratch); tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); tx_cmd->dram_msb_ptr = iwl_get_dma_hi_address(scratch_phys); - if (!ieee80211_get_morefrag(hdr)) { + if (!ieee80211_has_morefrags(hdr->frame_control)) { txq->need_update = 1; if (qc) priv->stations[sta_id].tid[tid].seq_number = seq_number; @@ -1196,8 +1188,6 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) } EXPORT_SYMBOL(iwl_tx_cmd_complete); - -#ifdef CONFIG_IWL4965_HT /* * Find first available (lowest unused) Tx Queue, mark it "active". * Called only when finding queue for aggregation. @@ -1359,7 +1349,6 @@ int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id) return 0; } EXPORT_SYMBOL(iwl_txq_check_empty); -#endif /* CONFIG_IWL4965_HT */ #ifdef CONFIG_IWLWIF_DEBUG #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 72279e07fe3..47cf4b997f5 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2431,15 +2431,15 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv, struct ieee80211_hdr *hdr, int is_unicast, u8 std_id) { - u16 fc = le16_to_cpu(hdr->frame_control); + __le16 fc = hdr->frame_control; __le32 tx_flags = cmd->cmd.tx.tx_flags; cmd->cmd.tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { tx_flags |= TX_CMD_FLG_ACK_MSK; - if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) + if (ieee80211_is_mgmt(fc)) tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; - if (ieee80211_is_probe_response(fc) && + if (ieee80211_is_probe_resp(fc) && !(le16_to_cpu(hdr->seq_ctrl) & 0xf)) tx_flags |= TX_CMD_FLG_TSF_MSK; } else { @@ -2448,11 +2448,11 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv, } cmd->cmd.tx.sta_id = std_id; - if (ieee80211_get_morefrag(hdr)) + if (ieee80211_has_morefrags(fc)) tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK; - if (ieee80211_is_qos_data(fc)) { - u8 *qc = ieee80211_get_qos_ctrl(hdr, ieee80211_get_hdrlen(fc)); + if (ieee80211_is_data_qos(fc)) { + u8 *qc = ieee80211_get_qos_ctl(hdr); cmd->cmd.tx.tid_tspec = qc[0] & 0xf; tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; } else { @@ -2471,9 +2471,8 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv, tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); - if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) { - if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ || - (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_REASSOC_REQ) + if (ieee80211_is_mgmt(fc)) { + if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc)) cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(3); else cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(2); @@ -2564,7 +2563,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb) u8 sta_id; u8 tid = 0; u16 seq_number = 0; - u16 fc; + __le16 fc; u8 wait_write_ptr = 0; u8 *qc = NULL; unsigned long flags; @@ -2589,28 +2588,28 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb) unicast = !is_multicast_ether_addr(hdr->addr1); id = 0; - fc = le16_to_cpu(hdr->frame_control); + fc = hdr->frame_control; #ifdef CONFIG_IWL3945_DEBUG if (ieee80211_is_auth(fc)) IWL_DEBUG_TX("Sending AUTH frame\n"); - else if (ieee80211_is_assoc_request(fc)) + else if (ieee80211_is_assoc_req(fc)) IWL_DEBUG_TX("Sending ASSOC frame\n"); - else if (ieee80211_is_reassoc_request(fc)) + else if (ieee80211_is_reassoc_req(fc)) IWL_DEBUG_TX("Sending REASSOC frame\n"); #endif /* drop all data frame if we are not associated */ if ((!iwl3945_is_associated(priv) || ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id)) && - ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) { + ieee80211_is_data(fc)) { IWL_DEBUG_DROP("Dropping - !iwl3945_is_associated\n"); goto drop_unlock; } spin_unlock_irqrestore(&priv->lock, flags); - hdr_len = ieee80211_get_hdrlen(fc); + hdr_len = ieee80211_get_hdrlen(le16_to_cpu(fc)); /* Find (or create) index into station table for destination station */ sta_id = iwl3945_get_sta_id(priv, hdr); @@ -2624,8 +2623,8 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb) IWL_DEBUG_RATE("station Id %d\n", sta_id); - if (ieee80211_is_qos_data(fc)) { - qc = ieee80211_get_qos_ctrl(hdr, hdr_len); + if (ieee80211_is_data_qos(fc)) { + qc = ieee80211_get_qos_ctl(hdr); tid = qc[0] & 0xf; seq_number = priv->stations[sta_id].tid[tid].seq_number & IEEE80211_SCTL_SEQ; @@ -2732,7 +2731,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb) out_cmd->cmd.tx.tx_flags &= ~TX_CMD_FLG_ANT_A_MSK; out_cmd->cmd.tx.tx_flags &= ~TX_CMD_FLG_ANT_B_MSK; - if (!ieee80211_get_morefrag(hdr)) { + if (!ieee80211_has_morefrags(hdr->frame_control)) { txq->need_update = 1; if (qc) { priv->stations[sta_id].tid[tid].seq_number = seq_number; @@ -2746,7 +2745,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb) sizeof(out_cmd->cmd.tx)); iwl3945_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr, - ieee80211_get_hdrlen(fc)); + ieee80211_get_hdrlen(le16_to_cpu(fc))); /* Tell device the write index *just past* this latest filled TFD */ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); @@ -2875,7 +2874,8 @@ static void iwl3945_radio_kill_sw(struct iwl3945_priv *priv, int disable_radio) return; } - queue_work(priv->workqueue, &priv->restart); + if (priv->is_open) + queue_work(priv->workqueue, &priv->restart); return; } diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index c71daec8c74..f5911687671 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -87,46 +87,6 @@ MODULE_VERSION(DRV_VERSION); MODULE_AUTHOR(DRV_COPYRIGHT); MODULE_LICENSE("GPL"); -static int iwl4965_is_empty_essid(const char *essid, int essid_len) -{ - /* Single white space is for Linksys APs */ - if (essid_len == 1 && essid[0] == ' ') - return 1; - - /* Otherwise, if the entire essid is 0, we assume it is hidden */ - while (essid_len) { - essid_len--; - if (essid[essid_len] != '\0') - return 0; - } - - return 1; -} - -static const char *iwl4965_escape_essid(const char *essid, u8 essid_len) -{ - static char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; - const char *s = essid; - char *d = escaped; - - if (iwl4965_is_empty_essid(essid, essid_len)) { - memcpy(escaped, "<hidden>", sizeof("<hidden>")); - return escaped; - } - - essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE); - while (essid_len--) { - if (*s == '\0') { - *d++ = '\\'; - *d++ = '0'; - s++; - } else - *d++ = *s++; - } - *d = '\0'; - return escaped; -} - /*************** STATION TABLE MANAGEMENT **** * mac80211 should be examined to determine if sta_info is duplicating * the functionality provided here @@ -367,9 +327,9 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) /* If we issue a new RXON command which required a tune then we must * send a new TXPOWER command or we won't be able to Tx any frames */ - rc = iwl4965_hw_reg_send_txpower(priv); + rc = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); if (rc) { - IWL_ERROR("Error setting Tx power (%d).\n", rc); + IWL_ERROR("Error sending TX power (%d).\n", rc); return rc; } @@ -419,69 +379,6 @@ static int iwl4965_send_bt_config(struct iwl_priv *priv) sizeof(struct iwl4965_bt_cmd), &bt_cmd); } -static int iwl4965_send_scan_abort(struct iwl_priv *priv) -{ - int ret = 0; - struct iwl_rx_packet *res; - struct iwl_host_cmd cmd = { - .id = REPLY_SCAN_ABORT_CMD, - .meta.flags = CMD_WANT_SKB, - }; - - /* If there isn't a scan actively going on in the hardware - * then we are in between scan bands and not actually - * actively scanning, so don't send the abort command */ - if (!test_bit(STATUS_SCAN_HW, &priv->status)) { - clear_bit(STATUS_SCAN_ABORTING, &priv->status); - return 0; - } - - ret = iwl_send_cmd_sync(priv, &cmd); - if (ret) { - clear_bit(STATUS_SCAN_ABORTING, &priv->status); - return ret; - } - - res = (struct iwl_rx_packet *)cmd.meta.u.skb->data; - if (res->u.status != CAN_ABORT_STATUS) { - /* The scan abort will return 1 for success or - * 2 for "failure". A failure condition can be - * due to simply not being in an active scan which - * can occur if we send the scan abort before we - * the microcode has notified us that a scan is - * completed. */ - IWL_DEBUG_INFO("SCAN_ABORT returned %d.\n", res->u.status); - clear_bit(STATUS_SCAN_ABORTING, &priv->status); - clear_bit(STATUS_SCAN_HW, &priv->status); - } - - dev_kfree_skb_any(cmd.meta.u.skb); - - return ret; -} - -/* - * CARD_STATE_CMD - * - * Use: Sets the device's internal card state to enable, disable, or halt - * - * When in the 'enable' state the card operates as normal. - * When in the 'disable' state, the card enters into a low power mode. - * When in the 'halt' state, the card is shut down and must be fully - * restarted to come back on. - */ -static int iwl4965_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag) -{ - struct iwl_host_cmd cmd = { - .id = REPLY_CARD_STATE_CMD, - .len = sizeof(u32), - .data = &flags, - .meta.flags = meta_flag, - }; - - return iwl_send_cmd(priv, &cmd); -} - static void iwl_clear_free_frames(struct iwl_priv *priv) { struct list_head *element; @@ -605,36 +502,6 @@ static int iwl4965_send_beacon_cmd(struct iwl_priv *priv) * ******************************************************************************/ -/** - * iwl4965_supported_rate_to_ie - fill in the supported rate in IE field - * - * return : set the bit for each supported rate insert in ie - */ -static u16 iwl4965_supported_rate_to_ie(u8 *ie, u16 supported_rate, - u16 basic_rate, int *left) -{ - u16 ret_rates = 0, bit; - int i; - u8 *cnt = ie; - u8 *rates = ie + 1; - - for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) { - if (bit & supported_rate) { - ret_rates |= bit; - rates[*cnt] = iwl_rates[i].ieee | - ((bit & basic_rate) ? 0x80 : 0x00); - (*cnt)++; - (*left)--; - if ((*left <= 0) || - (*cnt >= IWL_SUPPORTED_RATES_IE_LEN)) - break; - } - } - - return ret_rates; -} - -#ifdef CONFIG_IWL4965_HT static void iwl4965_ht_conf(struct iwl_priv *priv, struct ieee80211_bss_conf *bss_conf) { @@ -665,9 +532,11 @@ static void iwl4965_ht_conf(struct iwl_priv *priv, iwl_conf->extension_chan_offset = ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_SEC_OFFSET; /* If no above or below channel supplied disable FAT channel */ - if (iwl_conf->extension_chan_offset != IWL_EXT_CHANNEL_OFFSET_ABOVE && - iwl_conf->extension_chan_offset != IWL_EXT_CHANNEL_OFFSET_BELOW) + if (iwl_conf->extension_chan_offset != IEEE80211_HT_IE_CHA_SEC_ABOVE && + iwl_conf->extension_chan_offset != IEEE80211_HT_IE_CHA_SEC_BELOW) { + iwl_conf->extension_chan_offset = IEEE80211_HT_IE_CHA_SEC_NONE; iwl_conf->supported_chan_width = 0; + } iwl_conf->tx_mimo_ps_mode = (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2); @@ -685,151 +554,6 @@ static void iwl4965_ht_conf(struct iwl_priv *priv, IWL_DEBUG_MAC80211("leave\n"); } -static void iwl_ht_cap_to_ie(const struct ieee80211_supported_band *sband, - u8 *pos, int *left) -{ - struct ieee80211_ht_cap *ht_cap; - - if (!sband || !sband->ht_info.ht_supported) - return; - - if (*left < sizeof(struct ieee80211_ht_cap)) - return; - - *pos++ = sizeof(struct ieee80211_ht_cap); - ht_cap = (struct ieee80211_ht_cap *) pos; - - ht_cap->cap_info = cpu_to_le16(sband->ht_info.cap); - memcpy(ht_cap->supp_mcs_set, sband->ht_info.supp_mcs_set, 16); - ht_cap->ampdu_params_info = - (sband->ht_info.ampdu_factor & IEEE80211_HT_CAP_AMPDU_FACTOR) | - ((sband->ht_info.ampdu_density << 2) & - IEEE80211_HT_CAP_AMPDU_DENSITY); - *left -= sizeof(struct ieee80211_ht_cap); -} -#else -static inline void iwl4965_ht_conf(struct iwl_priv *priv, - struct ieee80211_bss_conf *bss_conf) -{ -} -static void iwl_ht_cap_to_ie(const struct ieee80211_supported_band *sband, - u8 *pos, int *left) -{ -} -#endif - - -/** - * iwl4965_fill_probe_req - fill in all required fields and IE for probe request - */ -static u16 iwl4965_fill_probe_req(struct iwl_priv *priv, - enum ieee80211_band band, - struct ieee80211_mgmt *frame, - int left, int is_direct) -{ - int len = 0; - u8 *pos = NULL; - u16 active_rates, ret_rates, cck_rates, active_rate_basic; - const struct ieee80211_supported_band *sband = - iwl_get_hw_mode(priv, band); - - /* Make sure there is enough space for the probe request, - * two mandatory IEs and the data */ - left -= 24; - if (left < 0) - return 0; - len += 24; - - frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); - memcpy(frame->da, iwl_bcast_addr, ETH_ALEN); - memcpy(frame->sa, priv->mac_addr, ETH_ALEN); - memcpy(frame->bssid, iwl_bcast_addr, ETH_ALEN); - frame->seq_ctrl = 0; - - /* fill in our indirect SSID IE */ - /* ...next IE... */ - - left -= 2; - if (left < 0) - return 0; - len += 2; - pos = &(frame->u.probe_req.variable[0]); - *pos++ = WLAN_EID_SSID; - *pos++ = 0; - - /* fill in our direct SSID IE... */ - if (is_direct) { - /* ...next IE... */ - left -= 2 + priv->essid_len; - if (left < 0) - return 0; - /* ... fill it in... */ - *pos++ = WLAN_EID_SSID; - *pos++ = priv->essid_len; - memcpy(pos, priv->essid, priv->essid_len); - pos += priv->essid_len; - len += 2 + priv->essid_len; - } - - /* fill in supported rate */ - /* ...next IE... */ - left -= 2; - if (left < 0) - return 0; - - /* ... fill it in... */ - *pos++ = WLAN_EID_SUPP_RATES; - *pos = 0; - - /* exclude 60M rate */ - active_rates = priv->rates_mask; - active_rates &= ~IWL_RATE_60M_MASK; - - active_rate_basic = active_rates & IWL_BASIC_RATES_MASK; - - cck_rates = IWL_CCK_RATES_MASK & active_rates; - ret_rates = iwl4965_supported_rate_to_ie(pos, cck_rates, - active_rate_basic, &left); - active_rates &= ~ret_rates; - - ret_rates = iwl4965_supported_rate_to_ie(pos, active_rates, - active_rate_basic, &left); - active_rates &= ~ret_rates; - - len += 2 + *pos; - pos += (*pos) + 1; - if (active_rates == 0) - goto fill_end; - - /* fill in supported extended rate */ - /* ...next IE... */ - left -= 2; - if (left < 0) - return 0; - /* ... fill it in... */ - *pos++ = WLAN_EID_EXT_SUPP_RATES; - *pos = 0; - iwl4965_supported_rate_to_ie(pos, active_rates, - active_rate_basic, &left); - if (*pos > 0) - len += 2 + *pos; - - fill_end: - /* fill in HT IE */ - left -= 2; - if (left < 0) - return 0; - - *pos++ = WLAN_EID_HT_CAPABILITY; - *pos = 0; - - iwl_ht_cap_to_ie(sband, pos, &left); - - if (*pos > 0) - len += 2 + *pos; - return (u16)len; -} - /* * QoS support */ @@ -862,10 +586,8 @@ static void iwl4965_activate_qos(struct iwl_priv *priv, u8 force) priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_UPDATE_EDCA_MSK; -#ifdef CONFIG_IWL4965_HT if (priv->current_ht_config.is_ht) priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; -#endif /* CONFIG_IWL4965_HT */ spin_unlock_irqrestore(&priv->lock, flags); @@ -909,60 +631,6 @@ int iwl4965_is_network_packet(struct iwl_priv *priv, struct ieee80211_hdr *heade return 1; } - - -/** - * iwl4965_scan_cancel - Cancel any currently executing HW scan - * - * NOTE: priv->mutex is not required before calling this function - */ -static int iwl4965_scan_cancel(struct iwl_priv *priv) -{ - if (!test_bit(STATUS_SCAN_HW, &priv->status)) { - clear_bit(STATUS_SCANNING, &priv->status); - return 0; - } - - if (test_bit(STATUS_SCANNING, &priv->status)) { - if (!test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG_SCAN("Queuing scan abort.\n"); - set_bit(STATUS_SCAN_ABORTING, &priv->status); - queue_work(priv->workqueue, &priv->abort_scan); - - } else - IWL_DEBUG_SCAN("Scan abort already in progress.\n"); - - return test_bit(STATUS_SCANNING, &priv->status); - } - - return 0; -} - -/** - * iwl4965_scan_cancel_timeout - Cancel any currently executing HW scan - * @ms: amount of time to wait (in milliseconds) for scan to abort - * - * NOTE: priv->mutex must be held before calling this function - */ -static int iwl4965_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms) -{ - unsigned long now = jiffies; - int ret; - - ret = iwl4965_scan_cancel(priv); - if (ret && ms) { - mutex_unlock(&priv->mutex); - while (!time_after(jiffies, now + msecs_to_jiffies(ms)) && - test_bit(STATUS_SCANNING, &priv->status)) - msleep(1); - mutex_lock(&priv->mutex); - - return test_bit(STATUS_SCANNING, &priv->status); - } - - return ret; -} - static void iwl4965_sequence_reset(struct iwl_priv *priv) { /* Reset ieee stats */ @@ -974,7 +642,7 @@ static void iwl4965_sequence_reset(struct iwl_priv *priv) priv->last_frag_num = -1; priv->last_packet_time = 0; - iwl4965_scan_cancel(priv); + iwl_scan_cancel(priv); } #define MAX_UCODE_BEACON_INTERVAL 4096 @@ -1049,41 +717,6 @@ static void iwl4965_setup_rxon_timing(struct iwl_priv *priv) le16_to_cpu(priv->rxon_timing.atim_window)); } -static int iwl4965_scan_initiate(struct iwl_priv *priv) -{ - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { - IWL_ERROR("APs don't scan.\n"); - return 0; - } - - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_SCAN("Aborting scan due to not ready.\n"); - return -EIO; - } - - if (test_bit(STATUS_SCANNING, &priv->status)) { - IWL_DEBUG_SCAN("Scan already in progress.\n"); - return -EAGAIN; - } - - if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG_SCAN("Scan request while abort pending. " - "Queuing.\n"); - return -EAGAIN; - } - - IWL_DEBUG_INFO("Starting scan...\n"); - priv->scan_bands = 2; - set_bit(STATUS_SCANNING, &priv->status); - priv->scan_start = jiffies; - priv->scan_pass_start = priv->scan_start; - - queue_work(priv->workqueue, &priv->request_scan); - - return 0; -} - - static void iwl_set_flags_for_band(struct iwl_priv *priv, enum ieee80211_band band) { @@ -1188,22 +821,11 @@ static void iwl4965_connection_init_rx_config(struct iwl_priv *priv) static int iwl4965_set_mode(struct iwl_priv *priv, int mode) { - if (mode == IEEE80211_IF_TYPE_IBSS) { - const struct iwl_channel_info *ch_info; - - ch_info = iwl_get_channel_info(priv, - priv->band, - le16_to_cpu(priv->staging_rxon.channel)); - - if (!ch_info || !is_channel_ibss(ch_info)) { - IWL_ERROR("channel %d not IBSS channel\n", - le16_to_cpu(priv->staging_rxon.channel)); - return -EINVAL; - } - } - priv->iw_mode = mode; + /* init channel/phymode to values given at driver init */ + iwl_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6); + iwl4965_connection_init_rx_config(priv); memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); @@ -1214,7 +836,7 @@ static int iwl4965_set_mode(struct iwl_priv *priv, int mode) return -EAGAIN; cancel_delayed_work(&priv->scan_check); - if (iwl4965_scan_cancel_timeout(priv, 100)) { + if (iwl_scan_cancel_timeout(priv, 100)) { IWL_WARNING("Aborted scan still in progress after 100ms\n"); IWL_DEBUG_MAC80211("leaving - scan abort failed.\n"); return -EAGAIN; @@ -1272,64 +894,6 @@ static void iwl4965_set_rate(struct iwl_priv *priv) (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; } -void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio) -{ - unsigned long flags; - - if (!!disable_radio == test_bit(STATUS_RF_KILL_SW, &priv->status)) - return; - - IWL_DEBUG_RF_KILL("Manual SW RF KILL set to: RADIO %s\n", - disable_radio ? "OFF" : "ON"); - - if (disable_radio) { - iwl4965_scan_cancel(priv); - /* FIXME: This is a workaround for AP */ - if (priv->iw_mode != IEEE80211_IF_TYPE_AP) { - spin_lock_irqsave(&priv->lock, flags); - iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, - CSR_UCODE_SW_BIT_RFKILL); - spin_unlock_irqrestore(&priv->lock, flags); - /* call the host command only if no hw rf-kill set */ - if (!test_bit(STATUS_RF_KILL_HW, &priv->status) && - iwl_is_ready(priv)) - iwl4965_send_card_state(priv, - CARD_STATE_CMD_DISABLE, - 0); - set_bit(STATUS_RF_KILL_SW, &priv->status); - - /* make sure mac80211 stop sending Tx frame */ - if (priv->mac80211_registered) - ieee80211_stop_queues(priv->hw); - } - return; - } - - spin_lock_irqsave(&priv->lock, flags); - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - - clear_bit(STATUS_RF_KILL_SW, &priv->status); - spin_unlock_irqrestore(&priv->lock, flags); - - /* wake up ucode */ - msleep(10); - - spin_lock_irqsave(&priv->lock, flags); - iwl_read32(priv, CSR_UCODE_DRV_GP1); - if (!iwl_grab_nic_access(priv)) - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->lock, flags); - - if (test_bit(STATUS_RF_KILL_HW, &priv->status)) { - IWL_DEBUG_RF_KILL("Can not turn radio back on - " - "disabled by HW switch\n"); - return; - } - - queue_work(priv->workqueue, &priv->restart); - return; -} - #define IWL_PACKET_RETRY_TIME HZ int iwl4965_is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr *header) @@ -1661,17 +1225,37 @@ static void iwl4965_bg_beacon_update(struct work_struct *work) iwl4965_send_beacon_cmd(priv); } +/** + * iwl4965_bg_statistics_periodic - Timer callback to queue statistics + * + * This callback is provided in order to send a statistics request. + * + * This timer function is continually reset to execute within + * REG_RECALIB_PERIOD seconds since the last STATISTICS_NOTIFICATION + * was received. We need to ensure we receive the statistics in order + * to update the temperature used for calibrating the TXPOWER. + */ +static void iwl4965_bg_statistics_periodic(unsigned long data) +{ + struct iwl_priv *priv = (struct iwl_priv *)data; + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + iwl_send_statistics_request(priv, CMD_ASYNC); +} + static void iwl4965_rx_beacon_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { #ifdef CONFIG_IWLWIFI_DEBUG struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; struct iwl4965_beacon_notif *beacon = &(pkt->u.beacon_status); - u8 rate = iwl4965_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags); + u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags); IWL_DEBUG_RX("beacon status %x retries %d iss %d " "tsf %d %d rate %d\n", - le32_to_cpu(beacon->beacon_notify_hdr.status) & TX_STATUS_MSK, + le32_to_cpu(beacon->beacon_notify_hdr.u.status) & TX_STATUS_MSK, beacon->beacon_notify_hdr.failure_frame, le32_to_cpu(beacon->ibss_mgr_status), le32_to_cpu(beacon->high_tsf), @@ -1683,118 +1267,6 @@ static void iwl4965_rx_beacon_notif(struct iwl_priv *priv, queue_work(priv->workqueue, &priv->beacon_update); } -/* Service response to REPLY_SCAN_CMD (0x80) */ -static void iwl4965_rx_reply_scan(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ -#ifdef CONFIG_IWLWIFI_DEBUG - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - struct iwl4965_scanreq_notification *notif = - (struct iwl4965_scanreq_notification *)pkt->u.raw; - - IWL_DEBUG_RX("Scan request status = 0x%x\n", notif->status); -#endif -} - -/* Service SCAN_START_NOTIFICATION (0x82) */ -static void iwl4965_rx_scan_start_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - struct iwl4965_scanstart_notification *notif = - (struct iwl4965_scanstart_notification *)pkt->u.raw; - priv->scan_start_tsf = le32_to_cpu(notif->tsf_low); - IWL_DEBUG_SCAN("Scan start: " - "%d [802.11%s] " - "(TSF: 0x%08X:%08X) - %d (beacon timer %u)\n", - notif->channel, - notif->band ? "bg" : "a", - notif->tsf_high, - notif->tsf_low, notif->status, notif->beacon_timer); -} - -/* Service SCAN_RESULTS_NOTIFICATION (0x83) */ -static void iwl4965_rx_scan_results_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - struct iwl4965_scanresults_notification *notif = - (struct iwl4965_scanresults_notification *)pkt->u.raw; - - IWL_DEBUG_SCAN("Scan ch.res: " - "%d [802.11%s] " - "(TSF: 0x%08X:%08X) - %d " - "elapsed=%lu usec (%dms since last)\n", - notif->channel, - notif->band ? "bg" : "a", - le32_to_cpu(notif->tsf_high), - le32_to_cpu(notif->tsf_low), - le32_to_cpu(notif->statistics[0]), - le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf, - jiffies_to_msecs(elapsed_jiffies - (priv->last_scan_jiffies, jiffies))); - - priv->last_scan_jiffies = jiffies; - priv->next_scan_jiffies = 0; -} - -/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */ -static void iwl4965_rx_scan_complete_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - struct iwl4965_scancomplete_notification *scan_notif = (void *)pkt->u.raw; - - IWL_DEBUG_SCAN("Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n", - scan_notif->scanned_channels, - scan_notif->tsf_low, - scan_notif->tsf_high, scan_notif->status); - - /* The HW is no longer scanning */ - clear_bit(STATUS_SCAN_HW, &priv->status); - - /* The scan completion notification came in, so kill that timer... */ - cancel_delayed_work(&priv->scan_check); - - IWL_DEBUG_INFO("Scan pass on %sGHz took %dms\n", - (priv->scan_bands == 2) ? "2.4" : "5.2", - jiffies_to_msecs(elapsed_jiffies - (priv->scan_pass_start, jiffies))); - - /* Remove this scanned band from the list - * of pending bands to scan */ - priv->scan_bands--; - - /* If a request to abort was given, or the scan did not succeed - * then we reset the scan state machine and terminate, - * re-queuing another scan if one has been requested */ - if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG_INFO("Aborted scan completed.\n"); - clear_bit(STATUS_SCAN_ABORTING, &priv->status); - } else { - /* If there are more bands on this scan pass reschedule */ - if (priv->scan_bands > 0) - goto reschedule; - } - - priv->last_scan_jiffies = jiffies; - priv->next_scan_jiffies = 0; - IWL_DEBUG_INFO("Setting scan to off\n"); - - clear_bit(STATUS_SCANNING, &priv->status); - - IWL_DEBUG_INFO("Scan took %dms\n", - jiffies_to_msecs(elapsed_jiffies(priv->scan_start, jiffies))); - - queue_work(priv->workqueue, &priv->scan_completed); - - return; - -reschedule: - priv->scan_pass_start = jiffies; - queue_work(priv->workqueue, &priv->request_scan); -} - /* Handle notification from uCode that card's power state is changing * due to software, hardware, or critical temperature RFKILL */ static void iwl4965_rx_card_state_notif(struct iwl_priv *priv, @@ -1855,7 +1327,7 @@ static void iwl4965_rx_card_state_notif(struct iwl_priv *priv, clear_bit(STATUS_RF_KILL_SW, &priv->status); if (!(flags & RXON_CARD_DISABLED)) - iwl4965_scan_cancel(priv); + iwl_scan_cancel(priv); if ((test_bit(STATUS_RF_KILL_HW, &status) != test_bit(STATUS_RF_KILL_HW, &priv->status)) || @@ -1905,13 +1377,9 @@ static void iwl4965_setup_rx_handlers(struct iwl_priv *priv) */ priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl4965_hw_rx_statistics; priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl4965_hw_rx_statistics; - /* scan handlers */ - priv->rx_handlers[REPLY_SCAN_CMD] = iwl4965_rx_reply_scan; - priv->rx_handlers[SCAN_START_NOTIFICATION] = iwl4965_rx_scan_start_notif; - priv->rx_handlers[SCAN_RESULTS_NOTIFICATION] = - iwl4965_rx_scan_results_notif; - priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] = - iwl4965_rx_scan_complete_notif; + + iwl_setup_rx_scan_handlers(priv); + /* status change handler */ priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl4965_rx_card_state_notif; @@ -2049,42 +1517,6 @@ void iwl_rx_handle(struct iwl_priv *priv) priv->rxq.read = i; iwl_rx_queue_restock(priv); } -/* Convert linear signal-to-noise ratio into dB */ -static u8 ratio2dB[100] = { -/* 0 1 2 3 4 5 6 7 8 9 */ - 0, 0, 6, 10, 12, 14, 16, 17, 18, 19, /* 00 - 09 */ - 20, 21, 22, 22, 23, 23, 24, 25, 26, 26, /* 10 - 19 */ - 26, 26, 26, 27, 27, 28, 28, 28, 29, 29, /* 20 - 29 */ - 29, 30, 30, 30, 31, 31, 31, 31, 32, 32, /* 30 - 39 */ - 32, 32, 32, 33, 33, 33, 33, 33, 34, 34, /* 40 - 49 */ - 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, /* 50 - 59 */ - 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, /* 60 - 69 */ - 37, 37, 37, 37, 37, 38, 38, 38, 38, 38, /* 70 - 79 */ - 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, /* 80 - 89 */ - 39, 39, 39, 39, 39, 40, 40, 40, 40, 40 /* 90 - 99 */ -}; - -/* Calculates a relative dB value from a ratio of linear - * (i.e. not dB) signal levels. - * Conversion assumes that levels are voltages (20*log), not powers (10*log). */ -int iwl4965_calc_db_from_ratio(int sig_ratio) -{ - /* 1000:1 or higher just report as 60 dB */ - if (sig_ratio >= 1000) - return 60; - - /* 100:1 or higher, divide by 10 and use table, - * add 20 dB to make up for divide by 10 */ - if (sig_ratio >= 100) - return (20 + (int)ratio2dB[sig_ratio/10]); - - /* We shouldn't see this */ - if (sig_ratio < 1) - return 0; - - /* Use table for ratios 1:1 - 99:1 */ - return (int)ratio2dB[sig_ratio]; -} #define PERFECT_RSSI (-20) /* dBm */ #define WORST_RSSI (-95) /* dBm */ @@ -2459,138 +1891,6 @@ static irqreturn_t iwl4965_isr(int irq, void *data) return IRQ_NONE; } -/* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after - * sending probe req. This should be set long enough to hear probe responses - * from more than one AP. */ -#define IWL_ACTIVE_DWELL_TIME_24 (20) /* all times in msec */ -#define IWL_ACTIVE_DWELL_TIME_52 (10) - -/* For faster active scanning, scan will move to the next channel if fewer than - * PLCP_QUIET_THRESH packets are heard on this channel within - * ACTIVE_QUIET_TIME after sending probe request. This shortens the dwell - * time if it's a quiet channel (nothing responded to our probe, and there's - * no other traffic). - * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */ -#define IWL_PLCP_QUIET_THRESH __constant_cpu_to_le16(1) /* packets */ -#define IWL_ACTIVE_QUIET_TIME __constant_cpu_to_le16(5) /* msec */ - -/* For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel. - * Must be set longer than active dwell time. - * For the most reliable scan, set > AP beacon interval (typically 100msec). */ -#define IWL_PASSIVE_DWELL_TIME_24 (20) /* all times in msec */ -#define IWL_PASSIVE_DWELL_TIME_52 (10) -#define IWL_PASSIVE_DWELL_BASE (100) -#define IWL_CHANNEL_TUNE_TIME 5 - -static inline u16 iwl4965_get_active_dwell_time(struct iwl_priv *priv, - enum ieee80211_band band) -{ - if (band == IEEE80211_BAND_5GHZ) - return IWL_ACTIVE_DWELL_TIME_52; - else - return IWL_ACTIVE_DWELL_TIME_24; -} - -static u16 iwl4965_get_passive_dwell_time(struct iwl_priv *priv, - enum ieee80211_band band) -{ - u16 active = iwl4965_get_active_dwell_time(priv, band); - u16 passive = (band != IEEE80211_BAND_5GHZ) ? - IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : - IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; - - if (iwl_is_associated(priv)) { - /* If we're associated, we clamp the maximum passive - * dwell time to be 98% of the beacon interval (minus - * 2 * channel tune time) */ - passive = priv->beacon_int; - if ((passive > IWL_PASSIVE_DWELL_BASE) || !passive) - passive = IWL_PASSIVE_DWELL_BASE; - passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; - } - - if (passive <= active) - passive = active + 1; - - return passive; -} - -static int iwl4965_get_channels_for_scan(struct iwl_priv *priv, - enum ieee80211_band band, - u8 is_active, u8 direct_mask, - struct iwl4965_scan_channel *scan_ch) -{ - const struct ieee80211_channel *channels = NULL; - const struct ieee80211_supported_band *sband; - const struct iwl_channel_info *ch_info; - u16 passive_dwell = 0; - u16 active_dwell = 0; - int added, i; - - sband = iwl_get_hw_mode(priv, band); - if (!sband) - return 0; - - channels = sband->channels; - - active_dwell = iwl4965_get_active_dwell_time(priv, band); - passive_dwell = iwl4965_get_passive_dwell_time(priv, band); - - for (i = 0, added = 0; i < sband->n_channels; i++) { - if (channels[i].flags & IEEE80211_CHAN_DISABLED) - continue; - - scan_ch->channel = ieee80211_frequency_to_channel(channels[i].center_freq); - - ch_info = iwl_get_channel_info(priv, band, - scan_ch->channel); - if (!is_channel_valid(ch_info)) { - IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n", - scan_ch->channel); - continue; - } - - if (!is_active || is_channel_passive(ch_info) || - (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN)) - scan_ch->type = 0; /* passive */ - else - scan_ch->type = 1; /* active */ - - if (scan_ch->type & 1) - scan_ch->type |= (direct_mask << 1); - - scan_ch->active_dwell = cpu_to_le16(active_dwell); - scan_ch->passive_dwell = cpu_to_le16(passive_dwell); - - /* Set txpower levels to defaults */ - scan_ch->tpc.dsp_atten = 110; - /* scan_pwr_info->tpc.dsp_atten; */ - - /*scan_pwr_info->tpc.tx_gain; */ - if (band == IEEE80211_BAND_5GHZ) - scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3; - else { - scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3)); - /* NOTE: if we were doing 6Mb OFDM for scans we'd use - * power level: - * scan_ch->tpc.tx_gain = ((1 << 5) | (2 << 3)) | 3; - */ - } - - IWL_DEBUG_SCAN("Scanning %d [%s %d]\n", - scan_ch->channel, - (scan_ch->type & 1) ? "ACTIVE" : "PASSIVE", - (scan_ch->type & 1) ? - active_dwell : passive_dwell); - - scan_ch++; - added++; - } - - IWL_DEBUG_SCAN("total channels to scan %d \n", added); - return added; -} - /****************************************************************************** * * uCode download functions @@ -2621,7 +1921,7 @@ static void iwl4965_nic_start(struct iwl_priv *priv) */ static int iwl4965_read_ucode(struct iwl_priv *priv) { - struct iwl4965_ucode *ucode; + struct iwl_ucode *ucode; int ret; const struct firmware *ucode_raw; const char *name = priv->cfg->fw_name; @@ -2849,9 +2149,6 @@ static void iwl_alive_start(struct iwl_priv *priv) /* After the ALIVE response, we can send host commands to 4965 uCode */ set_bit(STATUS_ALIVE, &priv->status); - /* Clear out the uCode error bit if it is set */ - clear_bit(STATUS_FW_ERROR, &priv->status); - if (iwl_is_rfkill(priv)) return; @@ -2882,7 +2179,7 @@ static void iwl_alive_start(struct iwl_priv *priv) iwl4965_commit_rxon(priv); /* At this point, the NIC is initialized and operational */ - iwl4965_rf_kill_ct_config(priv); + iwl_rf_kill_ct_config(priv); iwl_leds_register(priv); @@ -2893,15 +2190,19 @@ static void iwl_alive_start(struct iwl_priv *priv) if (priv->error_recovering) iwl4965_error_recovery(priv); - iwlcore_low_level_notify(priv, IWLCORE_START_EVT); + iwl_power_update_mode(priv, 1); ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC); + + if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status)) + iwl4965_set_mode(priv, priv->iw_mode); + return; restart: queue_work(priv->workqueue, &priv->restart); } -static void iwl4965_cancel_deferred_work(struct iwl_priv *priv); +static void iwl_cancel_deferred_work(struct iwl_priv *priv); static void __iwl4965_down(struct iwl_priv *priv) { @@ -2915,8 +2216,6 @@ static void __iwl4965_down(struct iwl_priv *priv) iwl_leds_unregister(priv); - iwlcore_low_level_notify(priv, IWLCORE_STOP_EVT); - iwlcore_clear_stations_table(priv); /* Unblock any waiting calls */ @@ -3005,7 +2304,7 @@ static void iwl4965_down(struct iwl_priv *priv) __iwl4965_down(priv); mutex_unlock(&priv->mutex); - iwl4965_cancel_deferred_work(priv); + iwl_cancel_deferred_work(priv); } #define MAX_HW_RESTARTS 5 @@ -3020,13 +2319,6 @@ static int __iwl4965_up(struct iwl_priv *priv) return -EIO; } - if (test_bit(STATUS_RF_KILL_SW, &priv->status)) { - IWL_WARNING("Radio disabled by SW RF kill (module " - "parameter)\n"); - iwl_rfkill_set_hw_state(priv); - return -ENODEV; - } - if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) { IWL_ERROR("ucode not available for device bringup\n"); return -EIO; @@ -3080,7 +2372,8 @@ static int __iwl4965_up(struct iwl_priv *priv) priv->ucode_data.len); /* We return success when we resume from suspend and rf_kill is on. */ - if (test_bit(STATUS_RF_KILL_HW, &priv->status)) + if (test_bit(STATUS_RF_KILL_HW, &priv->status) || + test_bit(STATUS_RF_KILL_SW, &priv->status)) return 0; for (i = 0; i < MAX_HW_RESTARTS; i++) { @@ -3097,6 +2390,9 @@ static int __iwl4965_up(struct iwl_priv *priv) continue; } + /* Clear out the uCode error bit if it is set */ + clear_bit(STATUS_FW_ERROR, &priv->status); + /* start card; "initialize" will load runtime ucode */ iwl4965_nic_start(priv); @@ -3107,6 +2403,7 @@ static int __iwl4965_up(struct iwl_priv *priv) set_bit(STATUS_EXIT_PENDING, &priv->status); __iwl4965_down(priv); + clear_bit(STATUS_EXIT_PENDING, &priv->status); /* tried to restart and config the device for as long as our * patience could withstand */ @@ -3186,255 +2483,45 @@ static void iwl4965_bg_set_monitor(struct work_struct *work) { struct iwl_priv *priv = container_of(work, struct iwl_priv, set_monitor); + int ret; IWL_DEBUG(IWL_DL_STATE, "setting monitor mode\n"); mutex_lock(&priv->mutex); - if (!iwl_is_ready(priv)) - IWL_DEBUG(IWL_DL_STATE, "leave - not ready\n"); - else - if (iwl4965_set_mode(priv, IEEE80211_IF_TYPE_MNTR) != 0) - IWL_ERROR("iwl4965_set_mode() failed\n"); - - mutex_unlock(&priv->mutex); -} + ret = iwl4965_set_mode(priv, IEEE80211_IF_TYPE_MNTR); -#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ) - -static void iwl4965_bg_scan_check(struct work_struct *data) -{ - struct iwl_priv *priv = - container_of(data, struct iwl_priv, scan_check.work); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - mutex_lock(&priv->mutex); - if (test_bit(STATUS_SCANNING, &priv->status) || - test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG(IWL_DL_SCAN, "Scan completion watchdog resetting " - "adapter (%dms)\n", - jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG)); - - if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) - iwl4965_send_scan_abort(priv); + if (ret) { + if (ret == -EAGAIN) + IWL_DEBUG(IWL_DL_STATE, "leave - not ready\n"); + else + IWL_ERROR("iwl4965_set_mode() failed ret = %d\n", ret); } + mutex_unlock(&priv->mutex); } -static void iwl4965_bg_request_scan(struct work_struct *data) +static void iwl_bg_run_time_calib_work(struct work_struct *work) { - struct iwl_priv *priv = - container_of(data, struct iwl_priv, request_scan); - struct iwl_host_cmd cmd = { - .id = REPLY_SCAN_CMD, - .len = sizeof(struct iwl4965_scan_cmd), - .meta.flags = CMD_SIZE_HUGE, - }; - struct iwl4965_scan_cmd *scan; - struct ieee80211_conf *conf = NULL; - u16 cmd_len; - enum ieee80211_band band; - u8 direct_mask; - int ret = 0; - - conf = ieee80211_get_hw_conf(priv->hw); + struct iwl_priv *priv = container_of(work, struct iwl_priv, + run_time_calib_work); mutex_lock(&priv->mutex); - if (!iwl_is_ready(priv)) { - IWL_WARNING("request scan called when driver not ready.\n"); - goto done; - } - - /* Make sure the scan wasn't cancelled before this queued work - * was given the chance to run... */ - if (!test_bit(STATUS_SCANNING, &priv->status)) - goto done; - - /* This should never be called or scheduled if there is currently - * a scan active in the hardware. */ - if (test_bit(STATUS_SCAN_HW, &priv->status)) { - IWL_DEBUG_INFO("Multiple concurrent scan requests in parallel. " - "Ignoring second request.\n"); - ret = -EIO; - goto done; - } - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { - IWL_DEBUG_SCAN("Aborting scan due to device shutdown\n"); - goto done; - } - - if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG_HC("Scan request while abort pending. Queuing.\n"); - goto done; - } - - if (iwl_is_rfkill(priv)) { - IWL_DEBUG_HC("Aborting scan due to RF Kill activation\n"); - goto done; - } - - if (!test_bit(STATUS_READY, &priv->status)) { - IWL_DEBUG_HC("Scan request while uninitialized. Queuing.\n"); - goto done; - } - - if (!priv->scan_bands) { - IWL_DEBUG_HC("Aborting scan due to no requested bands\n"); - goto done; - } - - if (!priv->scan) { - priv->scan = kmalloc(sizeof(struct iwl4965_scan_cmd) + - IWL_MAX_SCAN_SIZE, GFP_KERNEL); - if (!priv->scan) { - ret = -ENOMEM; - goto done; - } - } - scan = priv->scan; - memset(scan, 0, sizeof(struct iwl4965_scan_cmd) + IWL_MAX_SCAN_SIZE); - - scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; - scan->quiet_time = IWL_ACTIVE_QUIET_TIME; - - if (iwl_is_associated(priv)) { - u16 interval = 0; - u32 extra; - u32 suspend_time = 100; - u32 scan_suspend_time = 100; - unsigned long flags; - - IWL_DEBUG_INFO("Scanning while associated...\n"); - - spin_lock_irqsave(&priv->lock, flags); - interval = priv->beacon_int; - spin_unlock_irqrestore(&priv->lock, flags); - - scan->suspend_time = 0; - scan->max_out_time = cpu_to_le32(200 * 1024); - if (!interval) - interval = suspend_time; - - extra = (suspend_time / interval) << 22; - scan_suspend_time = (extra | - ((suspend_time % interval) * 1024)); - scan->suspend_time = cpu_to_le32(scan_suspend_time); - IWL_DEBUG_SCAN("suspend_time 0x%X beacon interval %d\n", - scan_suspend_time, interval); - } - - /* We should add the ability for user to lock to PASSIVE ONLY */ - if (priv->one_direct_scan) { - IWL_DEBUG_SCAN - ("Kicking off one direct scan for '%s'\n", - iwl4965_escape_essid(priv->direct_ssid, - priv->direct_ssid_len)); - scan->direct_scan[0].id = WLAN_EID_SSID; - scan->direct_scan[0].len = priv->direct_ssid_len; - memcpy(scan->direct_scan[0].ssid, - priv->direct_ssid, priv->direct_ssid_len); - direct_mask = 1; - } else if (!iwl_is_associated(priv) && priv->essid_len) { - IWL_DEBUG_SCAN - ("Kicking off one direct scan for '%s' when not associated\n", - iwl4965_escape_essid(priv->essid, priv->essid_len)); - scan->direct_scan[0].id = WLAN_EID_SSID; - scan->direct_scan[0].len = priv->essid_len; - memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len); - direct_mask = 1; - } else { - IWL_DEBUG_SCAN("Kicking off one indirect scan.\n"); - direct_mask = 0; + if (test_bit(STATUS_EXIT_PENDING, &priv->status) || + test_bit(STATUS_SCANNING, &priv->status)) { + mutex_unlock(&priv->mutex); + return; } - scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; - scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id; - scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; - - - switch (priv->scan_bands) { - case 2: - scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; - scan->tx_cmd.rate_n_flags = - iwl4965_hw_set_rate_n_flags(IWL_RATE_1M_PLCP, - RATE_MCS_ANT_B_MSK|RATE_MCS_CCK_MSK); - - scan->good_CRC_th = 0; - band = IEEE80211_BAND_2GHZ; - break; - - case 1: - scan->tx_cmd.rate_n_flags = - iwl4965_hw_set_rate_n_flags(IWL_RATE_6M_PLCP, - RATE_MCS_ANT_B_MSK); - scan->good_CRC_th = IWL_GOOD_CRC_TH; - band = IEEE80211_BAND_5GHZ; - break; + if (priv->start_calib) { + iwl_chain_noise_calibration(priv, &priv->statistics); - default: - IWL_WARNING("Invalid scan band count\n"); - goto done; + iwl_sensitivity_calibration(priv, &priv->statistics); } - /* We don't build a direct scan probe request; the uCode will do - * that based on the direct_mask added to each channel entry */ - cmd_len = iwl4965_fill_probe_req(priv, band, - (struct ieee80211_mgmt *)scan->data, - IWL_MAX_SCAN_SIZE - sizeof(*scan), 0); - - scan->tx_cmd.len = cpu_to_le16(cmd_len); - /* select Rx chains */ - - /* Force use of chains B and C (0x6) for scan Rx. - * Avoid A (0x1) because of its off-channel reception on A-band. - * MIMO is not used here, but value is required to make uCode happy. */ - scan->rx_chain = RXON_RX_CHAIN_DRIVER_FORCE_MSK | - cpu_to_le16((0x7 << RXON_RX_CHAIN_VALID_POS) | - (0x6 << RXON_RX_CHAIN_FORCE_SEL_POS) | - (0x7 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS)); - - if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) - scan->filter_flags = RXON_FILTER_PROMISC_MSK; - - if (direct_mask) - scan->channel_count = - iwl4965_get_channels_for_scan( - priv, band, 1, /* active */ - direct_mask, - (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); - else - scan->channel_count = - iwl4965_get_channels_for_scan( - priv, band, 0, /* passive */ - direct_mask, - (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); - - scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | - RXON_FILTER_BCON_AWARE_MSK); - cmd.len += le16_to_cpu(scan->tx_cmd.len) + - scan->channel_count * sizeof(struct iwl4965_scan_channel); - cmd.data = scan; - scan->len = cpu_to_le16(cmd.len); - - set_bit(STATUS_SCAN_HW, &priv->status); - ret = iwl_send_cmd_sync(priv, &cmd); - if (ret) - goto done; - - queue_delayed_work(priv->workqueue, &priv->scan_check, - IWL_SCAN_CHECK_WATCHDOG); - mutex_unlock(&priv->mutex); return; - - done: - /* inform mac80211 scan aborted */ - queue_work(priv->workqueue, &priv->scan_completed); - mutex_unlock(&priv->mutex); } static void iwl4965_bg_up(struct work_struct *data) @@ -3498,7 +2585,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv) if (!priv->vif || !priv->is_open) return; - iwl4965_scan_cancel_timeout(priv, 200); + iwl_scan_cancel_timeout(priv, 200); conf = ieee80211_get_hw_conf(priv->hw); @@ -3515,10 +2602,9 @@ static void iwl4965_post_associate(struct iwl_priv *priv) priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; -#ifdef CONFIG_IWL4965_HT if (priv->current_ht_config.is_ht) iwl_set_rxon_ht(priv, &priv->current_ht_config); -#endif /* CONFIG_IWL4965_HT*/ + iwl_set_rxon_chain(priv); priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); @@ -3550,10 +2636,9 @@ static void iwl4965_post_associate(struct iwl_priv *priv) case IEEE80211_IF_TYPE_IBSS: - /* clear out the station table */ - iwlcore_clear_stations_table(priv); + /* assume default assoc id */ + priv->assoc_id = 1; - iwl_rxon_add_station(priv, iwl_bcast_addr, 0); iwl_rxon_add_station(priv, priv->bssid, 0); iwl4965_rate_scale_init(priv->hw, IWL_STA_ID); iwl4965_send_beacon_cmd(priv); @@ -3594,29 +2679,14 @@ static void iwl4965_bg_post_associate(struct work_struct *data) } -static void iwl4965_bg_abort_scan(struct work_struct *work) -{ - struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan); - - if (!iwl_is_ready(priv)) - return; - - mutex_lock(&priv->mutex); - - set_bit(STATUS_SCAN_ABORTING, &priv->status); - iwl4965_send_scan_abort(priv); - - mutex_unlock(&priv->mutex); -} - static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf); -static void iwl4965_bg_scan_completed(struct work_struct *work) +static void iwl_bg_scan_completed(struct work_struct *work) { struct iwl_priv *priv = container_of(work, struct iwl_priv, scan_completed); - IWL_DEBUG(IWL_DL_SCAN, "SCAN complete scan\n"); + IWL_DEBUG_SCAN("SCAN complete scan\n"); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; @@ -3629,7 +2699,7 @@ static void iwl4965_bg_scan_completed(struct work_struct *work) /* Since setting the TXPOWER may have been deferred while * performing the scan, fire one off */ mutex_lock(&priv->mutex); - iwl4965_hw_reg_send_txpower(priv); + iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); mutex_unlock(&priv->mutex); } @@ -3738,7 +2808,7 @@ static void iwl4965_mac_stop(struct ieee80211_hw *hw) * RXON_FILTER_ASSOC_MSK BIT */ mutex_lock(&priv->mutex); - iwl4965_scan_cancel_timeout(priv, 100); + iwl_scan_cancel_timeout(priv, 100); cancel_delayed_work(&priv->post_associate); mutex_unlock(&priv->mutex); } @@ -3801,8 +2871,9 @@ static int iwl4965_mac_add_interface(struct ieee80211_hw *hw, memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); } - if (iwl_is_ready(priv)) - iwl4965_set_mode(priv, conf->type); + if (iwl4965_set_mode(priv, conf->type) == -EAGAIN) + /* we are not ready, will run again when ready */ + set_bit(STATUS_MODE_PENDING, &priv->status); mutex_unlock(&priv->mutex); @@ -3830,6 +2901,14 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP); + if (conf->radio_enabled && iwl_radio_kill_sw_enable_radio(priv)) { + IWL_DEBUG_MAC80211("leave - RF-KILL - waiting for uCode\n"); + goto out; + } + + if (!conf->radio_enabled) + iwl_radio_kill_sw_disable_radio(priv); + if (!iwl_is_ready(priv)) { IWL_DEBUG_MAC80211("leave - not ready\n"); ret = -EIO; @@ -3852,9 +2931,16 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co goto out; } + if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS && + !is_channel_ibss(ch_info)) { + IWL_ERROR("channel %d in band %d not IBSS channel\n", + conf->channel->hw_value, conf->channel->band); + ret = -EINVAL; + goto out; + } + spin_lock_irqsave(&priv->lock, flags); -#ifdef CONFIG_IWL4965_HT /* if we are switching from ht to 2.4 clear flags * from any ht related info since 2.4 does not * support ht */ @@ -3864,7 +2950,6 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co #endif ) priv->staging_rxon.flags = 0; -#endif /* CONFIG_IWL4965_HT */ iwl_set_rxon_channel(priv, conf->channel->band, channel); @@ -3884,9 +2969,6 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co } #endif - if (priv->cfg->ops->lib->radio_kill_sw) - priv->cfg->ops->lib->radio_kill_sw(priv, !conf->radio_enabled); - if (!conf->radio_enabled) { IWL_DEBUG_MAC80211("leave - radio disabled\n"); goto out; @@ -3898,6 +2980,11 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co goto out; } + IWL_DEBUG_MAC80211("TX Power old=%d new=%d\n", + priv->tx_power_user_lmt, conf->power_level); + + iwl_set_tx_power(priv, conf->power_level, false); + iwl4965_set_rate(priv); if (memcmp(&priv->active_rxon, @@ -4034,7 +3121,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, !is_multicast_ether_addr(conf->bssid)) { /* If there is currently a HW scan going on in the background * then we need to cancel it else the RXON below will fail. */ - if (iwl4965_scan_cancel_timeout(priv, 100)) { + if (iwl_scan_cancel_timeout(priv, 100)) { IWL_WARNING("Aborted scan still in progress " "after 100ms\n"); IWL_DEBUG_MAC80211("leaving - scan abort failed.\n"); @@ -4059,7 +3146,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, } } else { - iwl4965_scan_cancel_timeout(priv, 100); + iwl_scan_cancel_timeout(priv, 100); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl4965_commit_rxon(priv); } @@ -4117,7 +3204,7 @@ static void iwl4965_mac_remove_interface(struct ieee80211_hw *hw, mutex_lock(&priv->mutex); if (iwl_is_ready_rf(priv)) { - iwl4965_scan_cancel_timeout(priv, 100); + iwl_scan_cancel_timeout(priv, 100); cancel_delayed_work(&priv->post_associate); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl4965_commit_rxon(priv); @@ -4231,7 +3318,7 @@ static int iwl4965_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) } if (len) { IWL_DEBUG_SCAN("direct scan for %s [%d]\n ", - iwl4965_escape_essid(ssid, len), (int)len); + iwl_escape_essid(ssid, len), (int)len); priv->one_direct_scan = 1; priv->direct_ssid_len = (u8) @@ -4240,7 +3327,7 @@ static int iwl4965_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) } else priv->one_direct_scan = 0; - rc = iwl4965_scan_initiate(priv); + rc = iwl_scan_initiate(priv); IWL_DEBUG_MAC80211("leave\n"); @@ -4271,7 +3358,7 @@ static void iwl4965_mac_update_tkip_key(struct ieee80211_hw *hw, return; } - iwl4965_scan_cancel_timeout(priv, 100); + iwl_scan_cancel_timeout(priv, 100); key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK); key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); @@ -4329,7 +3416,7 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, } mutex_lock(&priv->mutex); - iwl4965_scan_cancel_timeout(priv, 100); + iwl_scan_cancel_timeout(priv, 100); mutex_unlock(&priv->mutex); /* If we are getting WEP group key and we didn't receive any key mapping @@ -4489,11 +3576,9 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw) IWL_DEBUG_MAC80211("enter\n"); priv->lq_mngr.lq_ready = 0; -#ifdef CONFIG_IWL4965_HT spin_lock_irqsave(&priv->lock, flags); memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_info)); spin_unlock_irqrestore(&priv->lock, flags); -#endif /* CONFIG_IWL4965_HT */ iwl_reset_qos(priv); @@ -4527,7 +3612,7 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw) * clear RXON_FILTER_ASSOC_MSK bit */ if (priv->iw_mode != IEEE80211_IF_TYPE_AP) { - iwl4965_scan_cancel_timeout(priv, 100); + iwl_scan_cancel_timeout(priv, 100); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl4965_commit_rxon(priv); } @@ -4583,7 +3668,7 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk iwl_reset_qos(priv); - queue_work(priv->workqueue, &priv->post_associate.work); + iwl4965_post_associate(priv); mutex_unlock(&priv->mutex); @@ -4665,7 +3750,7 @@ static ssize_t show_temperature(struct device *d, if (!iwl_is_alive(priv)) return -EAGAIN; - return sprintf(buf, "%d\n", iwl4965_hw_get_temperature(priv)); + return sprintf(buf, "%d\n", priv->temperature); } static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL); @@ -4683,7 +3768,7 @@ static ssize_t show_tx_power(struct device *d, struct device_attribute *attr, char *buf) { struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; - return sprintf(buf, "%d\n", priv->user_txpower_limit); + return sprintf(buf, "%d\n", priv->tx_power_user_lmt); } static ssize_t store_tx_power(struct device *d, @@ -4699,7 +3784,7 @@ static ssize_t store_tx_power(struct device *d, printk(KERN_INFO DRV_NAME ": %s is not in decimal form.\n", buf); else - iwl4965_hw_reg_set_txpower(priv, val); + iwl_set_tx_power(priv, val, false); return count; } @@ -4724,7 +3809,7 @@ static ssize_t store_flags(struct device *d, mutex_lock(&priv->mutex); if (le32_to_cpu(priv->staging_rxon.flags) != flags) { /* Cancel any currently running scans... */ - if (iwl4965_scan_cancel_timeout(priv, 100)) + if (iwl_scan_cancel_timeout(priv, 100)) IWL_WARNING("Could not cancel scan.\n"); else { IWL_DEBUG_INFO("Committing rxon.flags = 0x%04X\n", @@ -4759,7 +3844,7 @@ static ssize_t store_filter_flags(struct device *d, mutex_lock(&priv->mutex); if (le32_to_cpu(priv->staging_rxon.filter_flags) != filter_flags) { /* Cancel any currently running scans... */ - if (iwl4965_scan_cancel_timeout(priv, 100)) + if (iwl_scan_cancel_timeout(priv, 100)) IWL_WARNING("Could not cancel scan.\n"); else { IWL_DEBUG_INFO("Committing rxon.filter_flags = " @@ -4957,8 +4042,62 @@ static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level, static ssize_t show_channels(struct device *d, struct device_attribute *attr, char *buf) { - /* all this shit doesn't belong into sysfs anyway */ - return 0; + + struct iwl_priv *priv = dev_get_drvdata(d); + struct ieee80211_channel *channels = NULL; + const struct ieee80211_supported_band *supp_band = NULL; + int len = 0, i; + int count = 0; + + if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status)) + return -EAGAIN; + + supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ); + channels = supp_band->channels; + count = supp_band->n_channels; + + len += sprintf(&buf[len], + "Displaying %d channels in 2.4GHz band " + "(802.11bg):\n", count); + + for (i = 0; i < count; i++) + len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n", + ieee80211_frequency_to_channel( + channels[i].center_freq), + channels[i].max_power, + channels[i].flags & IEEE80211_CHAN_RADAR ? + " (IEEE 802.11h required)" : "", + (!(channels[i].flags & IEEE80211_CHAN_NO_IBSS) + || (channels[i].flags & + IEEE80211_CHAN_RADAR)) ? "" : + ", IBSS", + channels[i].flags & + IEEE80211_CHAN_PASSIVE_SCAN ? + "passive only" : "active/passive"); + + supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ); + channels = supp_band->channels; + count = supp_band->n_channels; + + len += sprintf(&buf[len], "Displaying %d channels in 5.2GHz band " + "(802.11a):\n", count); + + for (i = 0; i < count; i++) + len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n", + ieee80211_frequency_to_channel( + channels[i].center_freq), + channels[i].max_power, + channels[i].flags & IEEE80211_CHAN_RADAR ? + " (IEEE 802.11h required)" : "", + ((channels[i].flags & IEEE80211_CHAN_NO_IBSS) + || (channels[i].flags & + IEEE80211_CHAN_RADAR)) ? "" : + ", IBSS", + channels[i].flags & + IEEE80211_CHAN_PASSIVE_SCAN ? + "passive only" : "active/passive"); + + return len; } static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL); @@ -5018,7 +4157,7 @@ static DEVICE_ATTR(status, S_IRUGO, show_status, NULL); * *****************************************************************************/ -static void iwl4965_setup_deferred_work(struct iwl_priv *priv) +static void iwl_setup_deferred_work(struct iwl_priv *priv) { priv->workqueue = create_workqueue(DRV_NAME); @@ -5027,32 +4166,40 @@ static void iwl4965_setup_deferred_work(struct iwl_priv *priv) INIT_WORK(&priv->up, iwl4965_bg_up); INIT_WORK(&priv->restart, iwl4965_bg_restart); INIT_WORK(&priv->rx_replenish, iwl4965_bg_rx_replenish); - INIT_WORK(&priv->scan_completed, iwl4965_bg_scan_completed); - INIT_WORK(&priv->request_scan, iwl4965_bg_request_scan); - INIT_WORK(&priv->abort_scan, iwl4965_bg_abort_scan); INIT_WORK(&priv->rf_kill, iwl4965_bg_rf_kill); INIT_WORK(&priv->beacon_update, iwl4965_bg_beacon_update); INIT_WORK(&priv->set_monitor, iwl4965_bg_set_monitor); + INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work); INIT_DELAYED_WORK(&priv->post_associate, iwl4965_bg_post_associate); INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start); INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); - INIT_DELAYED_WORK(&priv->scan_check, iwl4965_bg_scan_check); - iwl4965_hw_setup_deferred_work(priv); + /* FIXME : remove when resolved PENDING */ + INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); + iwl_setup_scan_deferred_work(priv); + + if (priv->cfg->ops->lib->setup_deferred_work) + priv->cfg->ops->lib->setup_deferred_work(priv); + + init_timer(&priv->statistics_periodic); + priv->statistics_periodic.data = (unsigned long)priv; + priv->statistics_periodic.function = iwl4965_bg_statistics_periodic; tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) iwl4965_irq_tasklet, (unsigned long)priv); } -static void iwl4965_cancel_deferred_work(struct iwl_priv *priv) +static void iwl_cancel_deferred_work(struct iwl_priv *priv) { - iwl4965_hw_cancel_deferred_work(priv); + if (priv->cfg->ops->lib->cancel_deferred_work) + priv->cfg->ops->lib->cancel_deferred_work(priv); cancel_delayed_work_sync(&priv->init_alive_start); cancel_delayed_work(&priv->scan_check); cancel_delayed_work(&priv->alive_start); cancel_delayed_work(&priv->post_associate); cancel_work_sync(&priv->beacon_update); + del_timer_sync(&priv->statistics_periodic); } static struct attribute *iwl4965_sysfs_entries[] = { @@ -5100,9 +4247,7 @@ static struct ieee80211_ops iwl4965_hw_ops = { .reset_tsf = iwl4965_mac_reset_tsf, .beacon_update = iwl4965_mac_beacon_update, .bss_info_changed = iwl4965_bss_info_changed, -#ifdef CONFIG_IWL4965_HT .ampdu_action = iwl4965_mac_ampdu_action, -#endif /* CONFIG_IWL4965_HT */ .hw_scan = iwl4965_mac_hw_scan }; @@ -5266,7 +4411,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e } - iwl4965_setup_deferred_work(priv); + iwl_setup_deferred_work(priv); iwl4965_setup_rx_handlers(priv); /******************** @@ -5287,8 +4432,11 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e if (err) IWL_ERROR("failed to create debugfs files\n"); - /* notify iwlcore to init */ - iwlcore_low_level_notify(priv, IWLCORE_INIT_EVT); + err = iwl_rfkill_init(priv); + if (err) + IWL_ERROR("Unable to initialize RFKILL system. " + "Ignoring error: %d\n", err); + iwl_power_initialize(priv); return 0; out_remove_sysfs: @@ -5351,8 +4499,7 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev) } } - iwlcore_low_level_notify(priv, IWLCORE_REMOVE_EVT); - + iwl_rfkill_unregister(priv); iwl4965_dealloc_ucode_pci(priv); if (priv->rxq.bd) diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 873ab10a078..cc70d53fadd 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c @@ -159,7 +159,9 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r -/* First the bitmasks for the host/card interrupt/status registers: */ +/* + * First the bitmasks for the host/card interrupt/status registers: + */ #define IF_CS_BIT_TX 0x0001 #define IF_CS_BIT_RX 0x0002 #define IF_CS_BIT_COMMAND 0x0004 @@ -167,35 +169,110 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r #define IF_CS_BIT_EVENT 0x0010 #define IF_CS_BIT_MASK 0x001f -/* And now the individual registers and assorted masks */ + + +/* + * It's not really clear to me what the host status register is for. It + * needs to be set almost in union with "host int cause". The following + * bits from above are used: + * + * IF_CS_BIT_TX driver downloaded a data packet + * IF_CS_BIT_RX driver got a data packet + * IF_CS_BIT_COMMAND driver downloaded a command + * IF_CS_BIT_RESP not used (has some meaning with powerdown) + * IF_CS_BIT_EVENT driver read a host event + */ #define IF_CS_HOST_STATUS 0x00000000 +/* + * With the host int cause register can the host (that is, Linux) cause + * an interrupt in the firmware, to tell the firmware about those events: + * + * IF_CS_BIT_TX a data packet has been downloaded + * IF_CS_BIT_RX a received data packet has retrieved + * IF_CS_BIT_COMMAND a firmware block or a command has been downloaded + * IF_CS_BIT_RESP not used (has some meaning with powerdown) + * IF_CS_BIT_EVENT a host event (link lost etc) has been retrieved + */ #define IF_CS_HOST_INT_CAUSE 0x00000002 +/* + * The host int mask register is used to enable/disable interrupt. However, + * I have the suspicion that disabled interrupts are lost. + */ #define IF_CS_HOST_INT_MASK 0x00000004 -#define IF_CS_HOST_WRITE 0x00000016 -#define IF_CS_HOST_WRITE_LEN 0x00000014 - -#define IF_CS_HOST_CMD 0x0000001A -#define IF_CS_HOST_CMD_LEN 0x00000018 - +/* + * Used to send or receive data packets: + */ +#define IF_CS_WRITE 0x00000016 +#define IF_CS_WRITE_LEN 0x00000014 #define IF_CS_READ 0x00000010 #define IF_CS_READ_LEN 0x00000024 -#define IF_CS_CARD_CMD 0x00000012 -#define IF_CS_CARD_CMD_LEN 0x00000030 +/* + * Used to send commands (and to send firmware block) and to + * receive command responses: + */ +#define IF_CS_CMD 0x0000001A +#define IF_CS_CMD_LEN 0x00000018 +#define IF_CS_RESP 0x00000012 +#define IF_CS_RESP_LEN 0x00000030 +/* + * The card status registers shows what the card/firmware actually + * accepts: + * + * IF_CS_BIT_TX you may send a data packet + * IF_CS_BIT_RX you may retrieve a data packet + * IF_CS_BIT_COMMAND you may send a command + * IF_CS_BIT_RESP you may retrieve a command response + * IF_CS_BIT_EVENT the card has a event for use (link lost, snr low etc) + * + * When reading this register several times, you will get back the same + * results --- with one exception: the IF_CS_BIT_EVENT clear itself + * automatically. + * + * Not that we don't rely on BIT_RX,_BIT_RESP or BIT_EVENT because + * we handle this via the card int cause register. + */ #define IF_CS_CARD_STATUS 0x00000020 #define IF_CS_CARD_STATUS_MASK 0x7f00 +/* + * The card int cause register is used by the card/firmware to notify us + * about the following events: + * + * IF_CS_BIT_TX a data packet has successfully been sentx + * IF_CS_BIT_RX a data packet has been received and can be retrieved + * IF_CS_BIT_COMMAND not used + * IF_CS_BIT_RESP the firmware has a command response for us + * IF_CS_BIT_EVENT the card has a event for use (link lost, snr low etc) + */ #define IF_CS_CARD_INT_CAUSE 0x00000022 -#define IF_CS_CARD_SQ_READ_LOW 0x00000028 -#define IF_CS_CARD_SQ_HELPER_OK 0x10 +/* + * This is used to for handshaking with the card's bootloader/helper image + * to synchronize downloading of firmware blocks. + */ +#define IF_CS_SQ_READ_LOW 0x00000028 +#define IF_CS_SQ_HELPER_OK 0x10 +/* + * The scratch register tells us ... + * + * IF_CS_SCRATCH_BOOT_OK the bootloader runs + * IF_CS_SCRATCH_HELPER_OK the helper firmware already runs + */ #define IF_CS_SCRATCH 0x0000003F +#define IF_CS_SCRATCH_BOOT_OK 0x00 +#define IF_CS_SCRATCH_HELPER_OK 0x5a +/* + * Used to detect ancient chips: + */ +#define IF_CS_PRODUCT_ID 0x0000001C +#define IF_CS_CF8385_B1_REV 0x12 /********************************************************************/ @@ -228,8 +305,8 @@ static int if_cs_send_cmd(struct lbs_private *priv, u8 *buf, u16 nb) /* Is hardware ready? */ while (1) { - u16 val = if_cs_read16(card, IF_CS_CARD_STATUS); - if (val & IF_CS_BIT_COMMAND) + u16 status = if_cs_read16(card, IF_CS_CARD_STATUS); + if (status & IF_CS_BIT_COMMAND) break; if (++loops > 100) { lbs_pr_err("card not ready for commands\n"); @@ -238,12 +315,12 @@ static int if_cs_send_cmd(struct lbs_private *priv, u8 *buf, u16 nb) mdelay(1); } - if_cs_write16(card, IF_CS_HOST_CMD_LEN, nb); + if_cs_write16(card, IF_CS_CMD_LEN, nb); - if_cs_write16_rep(card, IF_CS_HOST_CMD, buf, nb / 2); + if_cs_write16_rep(card, IF_CS_CMD, buf, nb / 2); /* Are we supposed to transfer an odd amount of bytes? */ if (nb & 1) - if_cs_write8(card, IF_CS_HOST_CMD, buf[nb-1]); + if_cs_write8(card, IF_CS_CMD, buf[nb-1]); /* "Assert the download over interrupt command in the Host * status register" */ @@ -274,12 +351,12 @@ static void if_cs_send_data(struct lbs_private *priv, u8 *buf, u16 nb) status = if_cs_read16(card, IF_CS_CARD_STATUS); BUG_ON((status & IF_CS_BIT_TX) == 0); - if_cs_write16(card, IF_CS_HOST_WRITE_LEN, nb); + if_cs_write16(card, IF_CS_WRITE_LEN, nb); /* write even number of bytes, then odd byte if necessary */ - if_cs_write16_rep(card, IF_CS_HOST_WRITE, buf, nb / 2); + if_cs_write16_rep(card, IF_CS_WRITE, buf, nb / 2); if (nb & 1) - if_cs_write8(card, IF_CS_HOST_WRITE, buf[nb-1]); + if_cs_write8(card, IF_CS_WRITE, buf[nb-1]); if_cs_write16(card, IF_CS_HOST_STATUS, IF_CS_BIT_TX); if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_TX); @@ -307,16 +384,16 @@ static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len) goto out; } - *len = if_cs_read16(priv->card, IF_CS_CARD_CMD_LEN); + *len = if_cs_read16(priv->card, IF_CS_RESP_LEN); if ((*len == 0) || (*len > LBS_CMD_BUFFER_SIZE)) { lbs_pr_err("card cmd buffer has invalid # of bytes (%d)\n", *len); goto out; } /* read even number of bytes, then odd byte if necessary */ - if_cs_read16_rep(priv->card, IF_CS_CARD_CMD, data, *len/sizeof(u16)); + if_cs_read16_rep(priv->card, IF_CS_RESP, data, *len/sizeof(u16)); if (*len & 1) - data[*len-1] = if_cs_read8(priv->card, IF_CS_CARD_CMD); + data[*len-1] = if_cs_read8(priv->card, IF_CS_RESP); /* This is a workaround for a firmware that reports too much * bytes */ @@ -379,6 +456,8 @@ static irqreturn_t if_cs_interrupt(int irq, void *data) /* Ask card interrupt cause register if there is something for us */ cause = if_cs_read16(card, IF_CS_CARD_INT_CAUSE); + lbs_deb_cs("cause 0x%04x\n", cause); + if (cause == 0) { /* Not for us */ return IRQ_NONE; @@ -390,10 +469,6 @@ static irqreturn_t if_cs_interrupt(int irq, void *data) return IRQ_HANDLED; } - /* Clear interrupt cause */ - if_cs_write16(card, IF_CS_CARD_INT_CAUSE, cause & IF_CS_BIT_MASK); - lbs_deb_cs("cause 0x%04x\n", cause); - if (cause & IF_CS_BIT_RX) { struct sk_buff *skb; lbs_deb_cs("rx packet\n"); @@ -426,14 +501,15 @@ static irqreturn_t if_cs_interrupt(int irq, void *data) } if (cause & IF_CS_BIT_EVENT) { - u16 event = if_cs_read16(priv->card, IF_CS_CARD_STATUS) - & IF_CS_CARD_STATUS_MASK; + u16 status = if_cs_read16(priv->card, IF_CS_CARD_STATUS); if_cs_write16(priv->card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_EVENT); - lbs_deb_cs("host event 0x%04x\n", event); - lbs_queue_event(priv, event >> 8 & 0xff); + lbs_queue_event(priv, (status & IF_CS_CARD_STATUS_MASK) >> 8); } + /* Clear interrupt cause */ + if_cs_write16(card, IF_CS_CARD_INT_CAUSE, cause & IF_CS_BIT_MASK); + lbs_deb_leave(LBS_DEB_CS); return IRQ_HANDLED; } @@ -464,11 +540,11 @@ static int if_cs_prog_helper(struct if_cs_card *card) /* "If the value is 0x5a, the firmware is already * downloaded successfully" */ - if (scratch == 0x5a) + if (scratch == IF_CS_SCRATCH_HELPER_OK) goto done; /* "If the value is != 00, it is invalid value of register */ - if (scratch != 0x00) { + if (scratch != IF_CS_SCRATCH_BOOT_OK) { ret = -ENODEV; goto done; } @@ -496,11 +572,11 @@ static int if_cs_prog_helper(struct if_cs_card *card) /* "write the number of bytes to be sent to the I/O Command * write length register" */ - if_cs_write16(card, IF_CS_HOST_CMD_LEN, count); + if_cs_write16(card, IF_CS_CMD_LEN, count); /* "write this to I/O Command port register as 16 bit writes */ if (count) - if_cs_write16_rep(card, IF_CS_HOST_CMD, + if_cs_write16_rep(card, IF_CS_CMD, &fw->data[sent], count >> 1); @@ -557,15 +633,15 @@ static int if_cs_prog_real(struct if_cs_card *card) } lbs_deb_cs("fw size %td\n", fw->size); - ret = if_cs_poll_while_fw_download(card, IF_CS_CARD_SQ_READ_LOW, - IF_CS_CARD_SQ_HELPER_OK); + ret = if_cs_poll_while_fw_download(card, IF_CS_SQ_READ_LOW, + IF_CS_SQ_HELPER_OK); if (ret < 0) { lbs_pr_err("helper firmware doesn't answer\n"); goto err_release; } for (sent = 0; sent < fw->size; sent += len) { - len = if_cs_read16(card, IF_CS_CARD_SQ_READ_LOW); + len = if_cs_read16(card, IF_CS_SQ_READ_LOW); if (len & 1) { retry++; lbs_pr_info("odd, need to retry this firmware block\n"); @@ -583,9 +659,9 @@ static int if_cs_prog_real(struct if_cs_card *card) } - if_cs_write16(card, IF_CS_HOST_CMD_LEN, len); + if_cs_write16(card, IF_CS_CMD_LEN, len); - if_cs_write16_rep(card, IF_CS_HOST_CMD, + if_cs_write16_rep(card, IF_CS_CMD, &fw->data[sent], (len+1) >> 1); if_cs_write8(card, IF_CS_HOST_STATUS, IF_CS_BIT_COMMAND); @@ -789,6 +865,12 @@ static int if_cs_probe(struct pcmcia_device *p_dev) p_dev->irq.AssignedIRQ, p_dev->io.BasePort1, p_dev->io.BasePort1 + p_dev->io.NumPorts1 - 1); + /* Check if we have a current silicon */ + if (if_cs_read8(card, IF_CS_PRODUCT_ID) < IF_CS_CF8385_B1_REV) { + lbs_pr_err("old chips like 8385 rev B1 aren't supported\n"); + ret = -ENODEV; + goto out2; + } /* Load the firmware early, before calling into libertas.ko */ ret = if_cs_prog_helper(card); diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c new file mode 100644 index 00000000000..8da352ae682 --- /dev/null +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -0,0 +1,514 @@ +/* + * mac80211_hwsim - software simulator of 802.11 radio(s) for mac80211 + * Copyright (c) 2008, Jouni Malinen <j@w1.fi> + * + * 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. + */ + +/* + * TODO: + * - IBSS mode simulation (Beacon transmission with competition for "air time") + * - IEEE 802.11a and 802.11n modes + * - RX filtering based on filter configuration (data->rx_filter) + */ + +#include <net/mac80211.h> +#include <net/ieee80211_radiotap.h> +#include <linux/if_arp.h> +#include <linux/rtnetlink.h> +#include <linux/etherdevice.h> + +MODULE_AUTHOR("Jouni Malinen"); +MODULE_DESCRIPTION("Software simulator of 802.11 radio(s) for mac80211"); +MODULE_LICENSE("GPL"); + +static int radios = 2; +module_param(radios, int, 0444); +MODULE_PARM_DESC(radios, "Number of simulated radios"); + + +static struct class *hwsim_class; + +static struct ieee80211_hw **hwsim_radios; +static int hwsim_radio_count; +static struct net_device *hwsim_mon; /* global monitor netdev */ + + +static const struct ieee80211_channel hwsim_channels[] = { + { .center_freq = 2412 }, + { .center_freq = 2417 }, + { .center_freq = 2422 }, + { .center_freq = 2427 }, + { .center_freq = 2432 }, + { .center_freq = 2437 }, + { .center_freq = 2442 }, + { .center_freq = 2447 }, + { .center_freq = 2452 }, + { .center_freq = 2457 }, + { .center_freq = 2462 }, + { .center_freq = 2467 }, + { .center_freq = 2472 }, + { .center_freq = 2484 }, +}; + +static const struct ieee80211_rate hwsim_rates[] = { + { .bitrate = 10 }, + { .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 60 }, + { .bitrate = 90 }, + { .bitrate = 120 }, + { .bitrate = 180 }, + { .bitrate = 240 }, + { .bitrate = 360 }, + { .bitrate = 480 }, + { .bitrate = 540 } +}; + +struct mac80211_hwsim_data { + struct device *dev; + struct ieee80211_supported_band band; + struct ieee80211_channel channels[ARRAY_SIZE(hwsim_channels)]; + struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)]; + + struct ieee80211_channel *channel; + int radio_enabled; + unsigned long beacon_int; /* in jiffies unit */ + unsigned int rx_filter; + int started; + struct timer_list beacon_timer; +}; + + +struct hwsim_radiotap_hdr { + struct ieee80211_radiotap_header hdr; + u8 rt_flags; + u8 rt_rate; + __le16 rt_channel; + __le16 rt_chbitmask; +} __attribute__ ((packed)); + + +static int hwsim_mon_xmit(struct sk_buff *skb, struct net_device *dev) +{ + /* TODO: allow packet injection */ + dev_kfree_skb(skb); + return 0; +} + + +static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw, + struct sk_buff *tx_skb) +{ + struct mac80211_hwsim_data *data = hw->priv; + struct sk_buff *skb; + struct hwsim_radiotap_hdr *hdr; + u16 flags; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_skb); + struct ieee80211_rate *txrate = ieee80211_get_tx_rate(hw, info); + + if (!netif_running(hwsim_mon)) + return; + + skb = skb_copy_expand(tx_skb, sizeof(*hdr), 0, GFP_ATOMIC); + if (skb == NULL) + return; + + hdr = (struct hwsim_radiotap_hdr *) skb_push(skb, sizeof(*hdr)); + hdr->hdr.it_version = PKTHDR_RADIOTAP_VERSION; + hdr->hdr.it_pad = 0; + hdr->hdr.it_len = cpu_to_le16(sizeof(*hdr)); + hdr->hdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | + (1 << IEEE80211_RADIOTAP_RATE) | + (1 << IEEE80211_RADIOTAP_CHANNEL)); + hdr->rt_flags = 0; + hdr->rt_rate = txrate->bitrate / 5; + hdr->rt_channel = data->channel->center_freq; + flags = IEEE80211_CHAN_2GHZ; + if (txrate->flags & IEEE80211_RATE_ERP_G) + flags |= IEEE80211_CHAN_OFDM; + else + flags |= IEEE80211_CHAN_CCK; + hdr->rt_chbitmask = cpu_to_le16(flags); + + skb->dev = hwsim_mon; + skb_set_mac_header(skb, 0); + skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->pkt_type = PACKET_OTHERHOST; + skb->protocol = htons(ETH_P_802_2); + memset(skb->cb, 0, sizeof(skb->cb)); + netif_rx(skb); +} + + +static int mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, + struct sk_buff *skb) +{ + struct mac80211_hwsim_data *data = hw->priv; + int i, ack = 0; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_rx_status rx_status; + + memset(&rx_status, 0, sizeof(rx_status)); + /* TODO: set mactime */ + rx_status.freq = data->channel->center_freq; + rx_status.band = data->channel->band; + rx_status.rate_idx = info->tx_rate_idx; + /* TODO: simulate signal strength (and optional packet drop) */ + + /* Copy skb to all enabled radios that are on the current frequency */ + for (i = 0; i < hwsim_radio_count; i++) { + struct mac80211_hwsim_data *data2; + struct sk_buff *nskb; + + if (hwsim_radios[i] == NULL || hwsim_radios[i] == hw) + continue; + data2 = hwsim_radios[i]->priv; + if (!data2->started || !data2->radio_enabled || + data->channel->center_freq != data2->channel->center_freq) + continue; + + nskb = skb_copy(skb, GFP_ATOMIC); + if (nskb == NULL) + continue; + + if (memcmp(hdr->addr1, hwsim_radios[i]->wiphy->perm_addr, + ETH_ALEN) == 0) + ack = 1; + ieee80211_rx_irqsafe(hwsim_radios[i], nskb, &rx_status); + } + + return ack; +} + + +static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct mac80211_hwsim_data *data = hw->priv; + int ack; + struct ieee80211_tx_info *txi; + + mac80211_hwsim_monitor_rx(hw, skb); + + if (skb->len < 10) { + /* Should not happen; just a sanity check for addr1 use */ + dev_kfree_skb(skb); + return NETDEV_TX_OK; + } + + if (!data->radio_enabled) { + printk(KERN_DEBUG "%s: dropped TX frame since radio " + "disabled\n", wiphy_name(hw->wiphy)); + dev_kfree_skb(skb); + return NETDEV_TX_OK; + } + + ack = mac80211_hwsim_tx_frame(hw, skb); + + txi = IEEE80211_SKB_CB(skb); + memset(&txi->status, 0, sizeof(txi->status)); + if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK)) { + if (ack) + txi->flags |= IEEE80211_TX_STAT_ACK; + else + txi->status.excessive_retries = 1; + } + ieee80211_tx_status_irqsafe(hw, skb); + return NETDEV_TX_OK; +} + + +static int mac80211_hwsim_start(struct ieee80211_hw *hw) +{ + struct mac80211_hwsim_data *data = hw->priv; + printk(KERN_DEBUG "%s:%s\n", wiphy_name(hw->wiphy), __func__); + data->started = 1; + return 0; +} + + +static void mac80211_hwsim_stop(struct ieee80211_hw *hw) +{ + struct mac80211_hwsim_data *data = hw->priv; + data->started = 0; + printk(KERN_DEBUG "%s:%s\n", wiphy_name(hw->wiphy), __func__); +} + + +static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw, + struct ieee80211_if_init_conf *conf) +{ + DECLARE_MAC_BUF(mac); + printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%s)\n", + wiphy_name(hw->wiphy), __func__, conf->type, + print_mac(mac, conf->mac_addr)); + return 0; +} + + +static void mac80211_hwsim_remove_interface( + struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf) +{ + DECLARE_MAC_BUF(mac); + printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%s)\n", + wiphy_name(hw->wiphy), __func__, conf->type, + print_mac(mac, conf->mac_addr)); +} + + +static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, + struct ieee80211_vif *vif) +{ + struct ieee80211_hw *hw = arg; + struct sk_buff *skb; + struct ieee80211_tx_info *info; + + if (vif->type != IEEE80211_IF_TYPE_AP) + return; + + skb = ieee80211_beacon_get(hw, vif); + if (skb == NULL) + return; + info = IEEE80211_SKB_CB(skb); + + mac80211_hwsim_monitor_rx(hw, skb); + mac80211_hwsim_tx_frame(hw, skb); + dev_kfree_skb(skb); +} + + +static void mac80211_hwsim_beacon(unsigned long arg) +{ + struct ieee80211_hw *hw = (struct ieee80211_hw *) arg; + struct mac80211_hwsim_data *data = hw->priv; + + if (!data->started || !data->radio_enabled) + return; + + ieee80211_iterate_active_interfaces_atomic( + hw, mac80211_hwsim_beacon_tx, hw); + + data->beacon_timer.expires = jiffies + data->beacon_int; + add_timer(&data->beacon_timer); +} + + +static int mac80211_hwsim_config(struct ieee80211_hw *hw, + struct ieee80211_conf *conf) +{ + struct mac80211_hwsim_data *data = hw->priv; + + printk(KERN_DEBUG "%s:%s (freq=%d radio_enabled=%d beacon_int=%d)\n", + wiphy_name(hw->wiphy), __func__, + conf->channel->center_freq, conf->radio_enabled, + conf->beacon_int); + + data->channel = conf->channel; + data->radio_enabled = conf->radio_enabled; + data->beacon_int = 1024 * conf->beacon_int / 1000 * HZ / 1000; + if (data->beacon_int < 1) + data->beacon_int = 1; + + if (!data->started || !data->radio_enabled) + del_timer(&data->beacon_timer); + else + mod_timer(&data->beacon_timer, jiffies + data->beacon_int); + + return 0; +} + + +static void mac80211_hwsim_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + int mc_count, + struct dev_addr_list *mc_list) +{ + struct mac80211_hwsim_data *data = hw->priv; + + printk(KERN_DEBUG "%s:%s\n", wiphy_name(hw->wiphy), __func__); + + data->rx_filter = 0; + if (*total_flags & FIF_PROMISC_IN_BSS) + data->rx_filter |= FIF_PROMISC_IN_BSS; + if (*total_flags & FIF_ALLMULTI) + data->rx_filter |= FIF_ALLMULTI; + + *total_flags = data->rx_filter; +} + + + +static const struct ieee80211_ops mac80211_hwsim_ops = +{ + .tx = mac80211_hwsim_tx, + .start = mac80211_hwsim_start, + .stop = mac80211_hwsim_stop, + .add_interface = mac80211_hwsim_add_interface, + .remove_interface = mac80211_hwsim_remove_interface, + .config = mac80211_hwsim_config, + .configure_filter = mac80211_hwsim_configure_filter, +}; + + +static void mac80211_hwsim_free(void) +{ + int i; + + for (i = 0; i < hwsim_radio_count; i++) { + if (hwsim_radios[i]) { + struct mac80211_hwsim_data *data; + data = hwsim_radios[i]->priv; + ieee80211_unregister_hw(hwsim_radios[i]); + if (!IS_ERR(data->dev)) + device_unregister(data->dev); + ieee80211_free_hw(hwsim_radios[i]); + } + } + kfree(hwsim_radios); + class_destroy(hwsim_class); +} + + +static struct device_driver mac80211_hwsim_driver = { + .name = "mac80211_hwsim" +}; + + +static void hwsim_mon_setup(struct net_device *dev) +{ + dev->hard_start_xmit = hwsim_mon_xmit; + dev->destructor = free_netdev; + ether_setup(dev); + dev->tx_queue_len = 0; + dev->type = ARPHRD_IEEE80211_RADIOTAP; + memset(dev->dev_addr, 0, ETH_ALEN); + dev->dev_addr[0] = 0x12; +} + + +static int __init init_mac80211_hwsim(void) +{ + int i, err = 0; + u8 addr[ETH_ALEN]; + struct mac80211_hwsim_data *data; + struct ieee80211_hw *hw; + DECLARE_MAC_BUF(mac); + + if (radios < 1 || radios > 65535) + return -EINVAL; + + hwsim_radio_count = radios; + hwsim_radios = kcalloc(hwsim_radio_count, + sizeof(struct ieee80211_hw *), GFP_KERNEL); + if (hwsim_radios == NULL) + return -ENOMEM; + + hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim"); + if (IS_ERR(hwsim_class)) { + kfree(hwsim_radios); + return PTR_ERR(hwsim_class); + } + + memset(addr, 0, ETH_ALEN); + addr[0] = 0x02; + + for (i = 0; i < hwsim_radio_count; i++) { + printk(KERN_DEBUG "mac80211_hwsim: Initializing radio %d\n", + i); + hw = ieee80211_alloc_hw(sizeof(*data), &mac80211_hwsim_ops); + if (hw == NULL) { + printk(KERN_DEBUG "mac80211_hwsim: ieee80211_alloc_hw " + "failed\n"); + err = -ENOMEM; + goto failed; + } + hwsim_radios[i] = hw; + + data = hw->priv; + data->dev = device_create(hwsim_class, NULL, 0, "hwsim%d", i); + if (IS_ERR(data->dev)) { + printk(KERN_DEBUG "mac80211_hwsim: device_create " + "failed (%ld)\n", PTR_ERR(data->dev)); + err = -ENOMEM; + goto failed; + } + data->dev->driver = &mac80211_hwsim_driver; + dev_set_drvdata(data->dev, hw); + + SET_IEEE80211_DEV(hw, data->dev); + addr[3] = i >> 8; + addr[4] = i; + SET_IEEE80211_PERM_ADDR(hw, addr); + + hw->channel_change_time = 1; + hw->queues = 1; + + memcpy(data->channels, hwsim_channels, sizeof(hwsim_channels)); + memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates)); + data->band.channels = data->channels; + data->band.n_channels = ARRAY_SIZE(hwsim_channels); + data->band.bitrates = data->rates; + data->band.n_bitrates = ARRAY_SIZE(hwsim_rates); + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &data->band; + + err = ieee80211_register_hw(hw); + if (err < 0) { + printk(KERN_DEBUG "mac80211_hwsim: " + "ieee80211_register_hw failed (%d)\n", err); + goto failed; + } + + printk(KERN_DEBUG "%s: hwaddr %s registered\n", + wiphy_name(hw->wiphy), + print_mac(mac, hw->wiphy->perm_addr)); + + setup_timer(&data->beacon_timer, mac80211_hwsim_beacon, + (unsigned long) hw); + } + + hwsim_mon = alloc_netdev(0, "hwsim%d", hwsim_mon_setup); + if (hwsim_mon == NULL) + goto failed; + + rtnl_lock(); + + err = dev_alloc_name(hwsim_mon, hwsim_mon->name); + if (err < 0) { + goto failed_mon; + } + + err = register_netdevice(hwsim_mon); + if (err < 0) + goto failed_mon; + + rtnl_unlock(); + + return 0; + +failed_mon: + rtnl_unlock(); + free_netdev(hwsim_mon); + +failed: + mac80211_hwsim_free(); + return err; +} + + +static void __exit exit_mac80211_hwsim(void) +{ + printk(KERN_DEBUG "mac80211_hwsim: unregister %d radios\n", + hwsim_radio_count); + + unregister_netdev(hwsim_mon); + mac80211_hwsim_free(); +} + + +module_init(init_mac80211_hwsim); +module_exit(exit_mac80211_hwsim); diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 3954897d067..a36d2c85e26 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -310,8 +310,11 @@ enum wpa_key_mgmt { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE, #define CAP_MODE_MASK 7 #define CAP_SUPPORT_TXPOWER 8 -#define WORK_CONNECTION_EVENT (1<<0) -#define WORK_SET_MULTICAST_LIST (1<<1) +#define WORK_LINK_UP (1<<0) +#define WORK_LINK_DOWN (1<<1) +#define WORK_SET_MULTICAST_LIST (1<<2) + +#define COMMAND_BUFFER_SIZE (CONTROL_BUFFER_SIZE + sizeof(struct rndis_set)) /* RNDIS device private data */ struct rndis_wext_private { @@ -361,6 +364,8 @@ struct rndis_wext_private { u8 *wpa_ie; int wpa_cipher_pair; int wpa_cipher_group; + + u8 command_buffer[COMMAND_BUFFER_SIZE]; }; @@ -427,18 +432,23 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len) buflen = *len + sizeof(*u.get); if (buflen < CONTROL_BUFFER_SIZE) buflen = CONTROL_BUFFER_SIZE; - u.buf = kmalloc(buflen, GFP_KERNEL); - if (!u.buf) - return -ENOMEM; + + if (buflen > COMMAND_BUFFER_SIZE) { + u.buf = kmalloc(buflen, GFP_KERNEL); + if (!u.buf) + return -ENOMEM; + } else { + u.buf = priv->command_buffer; + } + + mutex_lock(&priv->command_lock); + memset(u.get, 0, sizeof *u.get); u.get->msg_type = RNDIS_MSG_QUERY; u.get->msg_len = ccpu2(sizeof *u.get); u.get->oid = oid; - mutex_lock(&priv->command_lock); ret = rndis_command(dev, u.header); - mutex_unlock(&priv->command_lock); - if (ret == 0) { ret = le32_to_cpu(u.get_c->len); *len = (*len > ret) ? ret : *len; @@ -446,7 +456,10 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len) ret = rndis_error_status(u.get_c->status); } - kfree(u.buf); + mutex_unlock(&priv->command_lock); + + if (u.buf != priv->command_buffer) + kfree(u.buf); return ret; } @@ -465,9 +478,16 @@ static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len) buflen = len + sizeof(*u.set); if (buflen < CONTROL_BUFFER_SIZE) buflen = CONTROL_BUFFER_SIZE; - u.buf = kmalloc(buflen, GFP_KERNEL); - if (!u.buf) - return -ENOMEM; + + if (buflen > COMMAND_BUFFER_SIZE) { + u.buf = kmalloc(buflen, GFP_KERNEL); + if (!u.buf) + return -ENOMEM; + } else { + u.buf = priv->command_buffer; + } + + mutex_lock(&priv->command_lock); memset(u.set, 0, sizeof *u.set); u.set->msg_type = RNDIS_MSG_SET; @@ -478,14 +498,14 @@ static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len) u.set->handle = ccpu2(0); memcpy(u.buf + sizeof(*u.set), data, len); - mutex_lock(&priv->command_lock); ret = rndis_command(dev, u.header); - mutex_unlock(&priv->command_lock); - if (ret == 0) ret = rndis_error_status(u.set_c->status); - kfree(u.buf); + mutex_unlock(&priv->command_lock); + + if (u.buf != priv->command_buffer) + kfree(u.buf); return ret; } @@ -620,8 +640,7 @@ static void dsconfig_to_freq(unsigned int dsconfig, struct iw_freq *freq) static int freq_to_dsconfig(struct iw_freq *freq, unsigned int *dsconfig) { if (freq->m < 1000 && freq->e == 0) { - if (freq->m >= 1 && - freq->m <= (sizeof(freq_chan) / sizeof(freq_chan[0]))) + if (freq->m >= 1 && freq->m <= ARRAY_SIZE(freq_chan)) *dsconfig = freq_chan[freq->m - 1] * 1000; else return -1; @@ -1159,10 +1178,9 @@ static int rndis_iw_get_range(struct net_device *dev, range->throughput = 11 * 1000 * 1000 / 2; } - range->num_channels = (sizeof(freq_chan)/sizeof(freq_chan[0])); + range->num_channels = ARRAY_SIZE(freq_chan); - for (i = 0; i < (sizeof(freq_chan)/sizeof(freq_chan[0])) && - i < IW_MAX_FREQUENCIES; i++) { + for (i = 0; i < ARRAY_SIZE(freq_chan) && i < IW_MAX_FREQUENCIES; i++) { range->freq[i].i = i + 1; range->freq[i].m = freq_chan[i] * 100000; range->freq[i].e = 1; @@ -2213,7 +2231,9 @@ static void rndis_wext_worker(struct work_struct *work) int assoc_size = sizeof(*info) + IW_CUSTOM_MAX + 32; int ret, offset; - if (test_and_clear_bit(WORK_CONNECTION_EVENT, &priv->work_pending)) { + if (test_and_clear_bit(WORK_LINK_UP, &priv->work_pending)) { + netif_carrier_on(usbdev->net); + info = kzalloc(assoc_size, GFP_KERNEL); if (!info) goto get_bssid; @@ -2251,6 +2271,15 @@ get_bssid: } } + if (test_and_clear_bit(WORK_LINK_DOWN, &priv->work_pending)) { + netif_carrier_off(usbdev->net); + + evt.data.flags = 0; + evt.data.length = 0; + memset(evt.ap_addr.sa_data, 0, ETH_ALEN); + wireless_send_event(usbdev->net, SIOCGIWAP, &evt, NULL); + } + if (test_and_clear_bit(WORK_SET_MULTICAST_LIST, &priv->work_pending)) set_multicast_list(usbdev); } @@ -2260,29 +2289,24 @@ static void rndis_wext_set_multicast_list(struct net_device *dev) struct usbnet *usbdev = dev->priv; struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + if (test_bit(WORK_SET_MULTICAST_LIST, &priv->work_pending)) + return; + set_bit(WORK_SET_MULTICAST_LIST, &priv->work_pending); queue_work(priv->workqueue, &priv->work); } -static void rndis_wext_link_change(struct usbnet *dev, int state) +static void rndis_wext_link_change(struct usbnet *usbdev, int state) { - struct rndis_wext_private *priv = get_rndis_wext_priv(dev); - union iwreq_data evt; + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); - if (state) { - /* queue work to avoid recursive calls into rndis_command */ - set_bit(WORK_CONNECTION_EVENT, &priv->work_pending); - queue_work(priv->workqueue, &priv->work); - } else { - evt.data.flags = 0; - evt.data.length = 0; - memset(evt.ap_addr.sa_data, 0, ETH_ALEN); - wireless_send_event(dev->net, SIOCGIWAP, &evt, NULL); - } + /* queue work to avoid recursive calls into rndis_command */ + set_bit(state ? WORK_LINK_UP : WORK_LINK_DOWN, &priv->work_pending); + queue_work(priv->workqueue, &priv->work); } -static int rndis_wext_get_caps(struct usbnet *dev) +static int rndis_wext_get_caps(struct usbnet *usbdev) { struct { __le32 num_items; @@ -2290,18 +2314,18 @@ static int rndis_wext_get_caps(struct usbnet *dev) } networks_supported; int len, retval, i, n; __le32 tx_power; - struct rndis_wext_private *priv = get_rndis_wext_priv(dev); + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); /* determine if supports setting txpower */ len = sizeof(tx_power); - retval = rndis_query_oid(dev, OID_802_11_TX_POWER_LEVEL, &tx_power, - &len); + retval = rndis_query_oid(usbdev, OID_802_11_TX_POWER_LEVEL, &tx_power, + &len); if (retval == 0 && le32_to_cpu(tx_power) != 0xFF) priv->caps |= CAP_SUPPORT_TXPOWER; /* determine supported modes */ len = sizeof(networks_supported); - retval = rndis_query_oid(dev, OID_802_11_NETWORK_TYPES_SUPPORTED, + retval = rndis_query_oid(usbdev, OID_802_11_NETWORK_TYPES_SUPPORTED, &networks_supported, &len); if (retval >= 0) { n = le32_to_cpu(networks_supported.num_items); @@ -2440,9 +2464,9 @@ end: } -static int bcm4320_early_init(struct usbnet *dev) +static int bcm4320_early_init(struct usbnet *usbdev) { - struct rndis_wext_private *priv = get_rndis_wext_priv(dev); + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); char buf[8]; /* Early initialization settings, setting these won't have effect @@ -2490,51 +2514,48 @@ static int bcm4320_early_init(struct usbnet *dev) else priv->param_workaround_interval = modparam_workaround_interval; - rndis_set_config_parameter_str(dev, "Country", priv->param_country); - rndis_set_config_parameter_str(dev, "FrameBursting", + rndis_set_config_parameter_str(usbdev, "Country", priv->param_country); + rndis_set_config_parameter_str(usbdev, "FrameBursting", priv->param_frameburst ? "1" : "0"); - rndis_set_config_parameter_str(dev, "Afterburner", + rndis_set_config_parameter_str(usbdev, "Afterburner", priv->param_afterburner ? "1" : "0"); sprintf(buf, "%d", priv->param_power_save); - rndis_set_config_parameter_str(dev, "PowerSaveMode", buf); + rndis_set_config_parameter_str(usbdev, "PowerSaveMode", buf); sprintf(buf, "%d", priv->param_power_output); - rndis_set_config_parameter_str(dev, "PwrOut", buf); + rndis_set_config_parameter_str(usbdev, "PwrOut", buf); sprintf(buf, "%d", priv->param_roamtrigger); - rndis_set_config_parameter_str(dev, "RoamTrigger", buf); + rndis_set_config_parameter_str(usbdev, "RoamTrigger", buf); sprintf(buf, "%d", priv->param_roamdelta); - rndis_set_config_parameter_str(dev, "RoamDelta", buf); + rndis_set_config_parameter_str(usbdev, "RoamDelta", buf); return 0; } -static int rndis_wext_bind(struct usbnet *dev, struct usb_interface *intf) +static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf) { - struct net_device *net = dev->net; struct rndis_wext_private *priv; int retval, len; __le32 tmp; /* allocate rndis private data */ - priv = kmalloc(sizeof(struct rndis_wext_private), GFP_KERNEL); + priv = kzalloc(sizeof(struct rndis_wext_private), GFP_KERNEL); if (!priv) return -ENOMEM; /* These have to be initialized before calling generic_rndis_bind(). * Otherwise we'll be in big trouble in rndis_wext_early_init(). */ - dev->driver_priv = priv; - memset(priv, 0, sizeof(*priv)); - memset(priv->name, 0, sizeof(priv->name)); + usbdev->driver_priv = priv; strcpy(priv->name, "IEEE802.11"); - net->wireless_handlers = &rndis_iw_handlers; - priv->usbdev = dev; + usbdev->net->wireless_handlers = &rndis_iw_handlers; + priv->usbdev = usbdev; mutex_init(&priv->command_lock); spin_lock_init(&priv->stats_lock); /* try bind rndis_host */ - retval = generic_rndis_bind(dev, intf, FLAG_RNDIS_PHYM_WIRELESS); + retval = generic_rndis_bind(usbdev, intf, FLAG_RNDIS_PHYM_WIRELESS); if (retval < 0) goto fail; @@ -2545,20 +2566,21 @@ static int rndis_wext_bind(struct usbnet *dev, struct usb_interface *intf) * rndis_host wants to avoid all OID as much as possible * so do promisc/multicast handling in rndis_wext. */ - dev->net->set_multicast_list = rndis_wext_set_multicast_list; + usbdev->net->set_multicast_list = rndis_wext_set_multicast_list; tmp = RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_BROADCAST; - retval = rndis_set_oid(dev, OID_GEN_CURRENT_PACKET_FILTER, &tmp, + retval = rndis_set_oid(usbdev, OID_GEN_CURRENT_PACKET_FILTER, &tmp, sizeof(tmp)); len = sizeof(tmp); - retval = rndis_query_oid(dev, OID_802_3_MAXIMUM_LIST_SIZE, &tmp, &len); + retval = rndis_query_oid(usbdev, OID_802_3_MAXIMUM_LIST_SIZE, &tmp, + &len); priv->multicast_size = le32_to_cpu(tmp); if (retval < 0 || priv->multicast_size < 0) priv->multicast_size = 0; if (priv->multicast_size > 0) - dev->net->flags |= IFF_MULTICAST; + usbdev->net->flags |= IFF_MULTICAST; else - dev->net->flags &= ~IFF_MULTICAST; + usbdev->net->flags &= ~IFF_MULTICAST; priv->iwstats.qual.qual = 0; priv->iwstats.qual.level = 0; @@ -2568,12 +2590,13 @@ static int rndis_wext_bind(struct usbnet *dev, struct usb_interface *intf) | IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID; - rndis_wext_get_caps(dev); - set_default_iw_params(dev); + rndis_wext_get_caps(usbdev); + set_default_iw_params(usbdev); /* turn radio on */ priv->radio_on = 1; - disassociate(dev, 1); + disassociate(usbdev, 1); + netif_carrier_off(usbdev->net); /* because rndis_command() sleeps we need to use workqueue */ priv->workqueue = create_singlethread_workqueue("rndis_wlan"); @@ -2590,12 +2613,12 @@ fail: } -static void rndis_wext_unbind(struct usbnet *dev, struct usb_interface *intf) +static void rndis_wext_unbind(struct usbnet *usbdev, struct usb_interface *intf) { - struct rndis_wext_private *priv = get_rndis_wext_priv(dev); + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); /* turn radio off */ - disassociate(dev, 0); + disassociate(usbdev, 0); cancel_delayed_work_sync(&priv->stats_work); cancel_work_sync(&priv->work); @@ -2606,13 +2629,13 @@ static void rndis_wext_unbind(struct usbnet *dev, struct usb_interface *intf) kfree(priv->wpa_ie); kfree(priv); - rndis_unbind(dev, intf); + rndis_unbind(usbdev, intf); } -static int rndis_wext_reset(struct usbnet *dev) +static int rndis_wext_reset(struct usbnet *usbdev) { - return deauthenticate(dev); + return deauthenticate(usbdev); } diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 0ace7614942..3a9b1d72caf 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -36,12 +36,13 @@ config RT2X00_LIB_FIRMWARE config RT2X00_LIB_RFKILL boolean depends on RT2X00_LIB + depends on INPUT select RFKILL select INPUT_POLLDEV config RT2X00_LIB_LEDS boolean - depends on RT2X00_LIB + depends on RT2X00_LIB && NEW_LEDS config RT2400PCI tristate "Ralink rt2400 (PCI/PCMCIA) support" @@ -56,7 +57,7 @@ config RT2400PCI config RT2400PCI_RFKILL bool "Ralink rt2400 rfkill support" - depends on RT2400PCI + depends on RT2400PCI && INPUT select RT2X00_LIB_RFKILL ---help--- This adds support for integrated rt2400 hardware that features a @@ -65,7 +66,7 @@ config RT2400PCI_RFKILL config RT2400PCI_LEDS bool "Ralink rt2400 leds support" - depends on RT2400PCI + depends on RT2400PCI && NEW_LEDS select LEDS_CLASS select RT2X00_LIB_LEDS ---help--- @@ -84,7 +85,7 @@ config RT2500PCI config RT2500PCI_RFKILL bool "Ralink rt2500 rfkill support" - depends on RT2500PCI + depends on RT2500PCI && INPUT select RT2X00_LIB_RFKILL ---help--- This adds support for integrated rt2500 hardware that features a @@ -93,7 +94,7 @@ config RT2500PCI_RFKILL config RT2500PCI_LEDS bool "Ralink rt2500 leds support" - depends on RT2500PCI + depends on RT2500PCI && NEW_LEDS select LEDS_CLASS select RT2X00_LIB_LEDS ---help--- @@ -114,7 +115,7 @@ config RT61PCI config RT61PCI_RFKILL bool "Ralink rt2501/rt61 rfkill support" - depends on RT61PCI + depends on RT61PCI && INPUT select RT2X00_LIB_RFKILL ---help--- This adds support for integrated rt61 hardware that features a @@ -123,7 +124,7 @@ config RT61PCI_RFKILL config RT61PCI_LEDS bool "Ralink rt2501/rt61 leds support" - depends on RT61PCI + depends on RT61PCI && NEW_LEDS select LEDS_CLASS select RT2X00_LIB_LEDS ---help--- @@ -141,7 +142,7 @@ config RT2500USB config RT2500USB_LEDS bool "Ralink rt2500 leds support" - depends on RT2500USB + depends on RT2500USB && NEW_LEDS select LEDS_CLASS select RT2X00_LIB_LEDS ---help--- @@ -161,7 +162,7 @@ config RT73USB config RT73USB_LEDS bool "Ralink rt2501/rt73 leds support" - depends on RT73USB + depends on RT73USB && NEW_LEDS select LEDS_CLASS select RT2X00_LIB_LEDS ---help--- diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 900140d3b30..bb3d83560d0 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -277,6 +277,17 @@ static int rt2400pci_blink_set(struct led_classdev *led_cdev, return 0; } + +static void rt2400pci_init_led(struct rt2x00_dev *rt2x00dev, + struct rt2x00_led *led, + enum led_type type) +{ + led->rt2x00dev = rt2x00dev; + led->type = type; + led->led_dev.brightness_set = rt2400pci_brightness_set; + led->led_dev.blink_set = rt2400pci_blink_set; + led->flags = LED_INITIALIZED; +} #endif /* CONFIG_RT2400PCI_LEDS */ /* @@ -781,25 +792,32 @@ static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev) return 0; } -static int rt2400pci_init_bbp(struct rt2x00_dev *rt2x00dev) +static int rt2400pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev) { unsigned int i; - u16 eeprom; - u8 reg_id; u8 value; for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt2400pci_bbp_read(rt2x00dev, 0, &value); if ((value != 0xff) && (value != 0x00)) - goto continue_csr_init; - NOTICE(rt2x00dev, "Waiting for BBP register.\n"); + return 0; udelay(REGISTER_BUSY_DELAY); } ERROR(rt2x00dev, "BBP register access failed, aborting.\n"); return -EACCES; +} + +static int rt2400pci_init_bbp(struct rt2x00_dev *rt2x00dev) +{ + unsigned int i; + u16 eeprom; + u8 reg_id; + u8 value; + + if (unlikely(rt2400pci_wait_bbp_ready(rt2x00dev))) + return -EACCES; -continue_csr_init: rt2400pci_bbp_write(rt2x00dev, 1, 0x00); rt2400pci_bbp_write(rt2x00dev, 3, 0x27); rt2400pci_bbp_write(rt2x00dev, 4, 0x08); @@ -838,7 +856,8 @@ static void rt2400pci_toggle_rx(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); rt2x00_set_field32(®, RXCSR0_DISABLE_RX, - state == STATE_RADIO_RX_OFF); + (state == STATE_RADIO_RX_OFF) || + (state == STATE_RADIO_RX_OFF_LINK)); rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); } @@ -875,17 +894,10 @@ static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev) /* * Initialize all registers. */ - if (rt2400pci_init_queues(rt2x00dev) || - rt2400pci_init_registers(rt2x00dev) || - rt2400pci_init_bbp(rt2x00dev)) { - ERROR(rt2x00dev, "Register initialization failed.\n"); + if (unlikely(rt2400pci_init_queues(rt2x00dev) || + rt2400pci_init_registers(rt2x00dev) || + rt2400pci_init_bbp(rt2x00dev))) return -EIO; - } - - /* - * Enable interrupts. - */ - rt2400pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_ON); return 0; } @@ -907,11 +919,6 @@ static void rt2400pci_disable_radio(struct rt2x00_dev *rt2x00dev) rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); rt2x00_set_field32(®, TXCSR0_ABORT, 1); rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); - - /* - * Disable interrupts. - */ - rt2400pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_OFF); } static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev, @@ -946,10 +953,6 @@ static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev, msleep(10); } - NOTICE(rt2x00dev, "Device failed to enter state %d, " - "current device state: bbp %d and rf %d.\n", - state, bbp_state, rf_state); - return -EBUSY; } @@ -967,11 +970,13 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev, break; case STATE_RADIO_RX_ON: case STATE_RADIO_RX_ON_LINK: - rt2400pci_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); - break; case STATE_RADIO_RX_OFF: case STATE_RADIO_RX_OFF_LINK: - rt2400pci_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); + rt2400pci_toggle_rx(rt2x00dev, state); + break; + case STATE_RADIO_IRQ_ON: + case STATE_RADIO_IRQ_OFF: + rt2400pci_toggle_irq(rt2x00dev, state); break; case STATE_DEEP_SLEEP: case STATE_SLEEP: @@ -984,6 +989,10 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev, break; } + if (unlikely(retval)) + ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n", + state, retval); + return retval; } @@ -1007,8 +1016,8 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_desc_write(entry_priv->desc, 1, word); rt2x00_desc_read(txd, 2, &word); - rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, skbdesc->data_len); - rt2x00_set_field32(&word, TXD_W2_DATABYTE_COUNT, skbdesc->data_len); + rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, skb->len); + rt2x00_set_field32(&word, TXD_W2_DATABYTE_COUNT, skb->len); rt2x00_desc_write(txd, 2, word); rt2x00_desc_read(txd, 3, &word); @@ -1300,23 +1309,10 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev) #ifdef CONFIG_RT2400PCI_LEDS value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE); - rt2x00dev->led_radio.rt2x00dev = rt2x00dev; - rt2x00dev->led_radio.type = LED_TYPE_RADIO; - rt2x00dev->led_radio.led_dev.brightness_set = - rt2400pci_brightness_set; - rt2x00dev->led_radio.led_dev.blink_set = - rt2400pci_blink_set; - rt2x00dev->led_radio.flags = LED_INITIALIZED; - - if (value == LED_MODE_TXRX_ACTIVITY) { - rt2x00dev->led_qual.rt2x00dev = rt2x00dev; - rt2x00dev->led_qual.type = LED_TYPE_ACTIVITY; - rt2x00dev->led_qual.led_dev.brightness_set = - rt2400pci_brightness_set; - rt2x00dev->led_qual.led_dev.blink_set = - rt2400pci_blink_set; - rt2x00dev->led_qual.flags = LED_INITIALIZED; - } + rt2400pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); + if (value == LED_MODE_TXRX_ACTIVITY) + rt2400pci_init_led(rt2x00dev, &rt2x00dev->led_qual, + LED_TYPE_ACTIVITY); #endif /* CONFIG_RT2400PCI_LEDS */ /* @@ -1511,9 +1507,6 @@ static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) */ skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED; - skbdesc->data = skb->data; - skbdesc->data_len = skb->len; skbdesc->desc = entry_priv->desc; skbdesc->desc_len = intf->beacon->queue->desc_size; skbdesc->entry = intf->beacon; diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h index e9aa326be9f..bc556425822 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/rt2x00/rt2400pci.h @@ -37,8 +37,6 @@ * Signal information. * Defaul offset is required for RSSI <-> dBm conversion. */ -#define MAX_SIGNAL 100 -#define MAX_RX_SSI -1 #define DEFAULT_RSSI_OFFSET 100 /* diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 673350953b8..3c956b91c4e 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -277,6 +277,17 @@ static int rt2500pci_blink_set(struct led_classdev *led_cdev, return 0; } + +static void rt2500pci_init_led(struct rt2x00_dev *rt2x00dev, + struct rt2x00_led *led, + enum led_type type) +{ + led->rt2x00dev = rt2x00dev; + led->type = type; + led->led_dev.brightness_set = rt2500pci_brightness_set; + led->led_dev.blink_set = rt2500pci_blink_set; + led->flags = LED_INITIALIZED; +} #endif /* CONFIG_RT2500PCI_LEDS */ /* @@ -924,25 +935,32 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev) return 0; } -static int rt2500pci_init_bbp(struct rt2x00_dev *rt2x00dev) +static int rt2500pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev) { unsigned int i; - u16 eeprom; - u8 reg_id; u8 value; for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt2500pci_bbp_read(rt2x00dev, 0, &value); if ((value != 0xff) && (value != 0x00)) - goto continue_csr_init; - NOTICE(rt2x00dev, "Waiting for BBP register.\n"); + return 0; udelay(REGISTER_BUSY_DELAY); } ERROR(rt2x00dev, "BBP register access failed, aborting.\n"); return -EACCES; +} + +static int rt2500pci_init_bbp(struct rt2x00_dev *rt2x00dev) +{ + unsigned int i; + u16 eeprom; + u8 reg_id; + u8 value; + + if (unlikely(rt2500pci_wait_bbp_ready(rt2x00dev))) + return -EACCES; -continue_csr_init: rt2500pci_bbp_write(rt2x00dev, 3, 0x02); rt2500pci_bbp_write(rt2x00dev, 4, 0x19); rt2500pci_bbp_write(rt2x00dev, 14, 0x1c); @@ -997,7 +1015,8 @@ static void rt2500pci_toggle_rx(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); rt2x00_set_field32(®, RXCSR0_DISABLE_RX, - state == STATE_RADIO_RX_OFF); + (state == STATE_RADIO_RX_OFF) || + (state == STATE_RADIO_RX_OFF_LINK)); rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); } @@ -1034,17 +1053,10 @@ static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev) /* * Initialize all registers. */ - if (rt2500pci_init_queues(rt2x00dev) || - rt2500pci_init_registers(rt2x00dev) || - rt2500pci_init_bbp(rt2x00dev)) { - ERROR(rt2x00dev, "Register initialization failed.\n"); + if (unlikely(rt2500pci_init_queues(rt2x00dev) || + rt2500pci_init_registers(rt2x00dev) || + rt2500pci_init_bbp(rt2x00dev))) return -EIO; - } - - /* - * Enable interrupts. - */ - rt2500pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_ON); return 0; } @@ -1066,11 +1078,6 @@ static void rt2500pci_disable_radio(struct rt2x00_dev *rt2x00dev) rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); rt2x00_set_field32(®, TXCSR0_ABORT, 1); rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); - - /* - * Disable interrupts. - */ - rt2500pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_OFF); } static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev, @@ -1105,10 +1112,6 @@ static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev, msleep(10); } - NOTICE(rt2x00dev, "Device failed to enter state %d, " - "current device state: bbp %d and rf %d.\n", - state, bbp_state, rf_state); - return -EBUSY; } @@ -1126,11 +1129,13 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev, break; case STATE_RADIO_RX_ON: case STATE_RADIO_RX_ON_LINK: - rt2500pci_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); - break; case STATE_RADIO_RX_OFF: case STATE_RADIO_RX_OFF_LINK: - rt2500pci_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); + rt2500pci_toggle_rx(rt2x00dev, state); + break; + case STATE_RADIO_IRQ_ON: + case STATE_RADIO_IRQ_OFF: + rt2500pci_toggle_irq(rt2x00dev, state); break; case STATE_DEEP_SLEEP: case STATE_SLEEP: @@ -1143,6 +1148,10 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev, break; } + if (unlikely(retval)) + ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n", + state, retval); + return retval; } @@ -1478,23 +1487,10 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev) #ifdef CONFIG_RT2500PCI_LEDS value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE); - rt2x00dev->led_radio.rt2x00dev = rt2x00dev; - rt2x00dev->led_radio.type = LED_TYPE_RADIO; - rt2x00dev->led_radio.led_dev.brightness_set = - rt2500pci_brightness_set; - rt2x00dev->led_radio.led_dev.blink_set = - rt2500pci_blink_set; - rt2x00dev->led_radio.flags = LED_INITIALIZED; - - if (value == LED_MODE_TXRX_ACTIVITY) { - rt2x00dev->led_qual.rt2x00dev = rt2x00dev; - rt2x00dev->led_qual.type = LED_TYPE_ACTIVITY; - rt2x00dev->led_qual.led_dev.brightness_set = - rt2500pci_brightness_set; - rt2x00dev->led_qual.led_dev.blink_set = - rt2500pci_blink_set; - rt2x00dev->led_qual.flags = LED_INITIALIZED; - } + rt2500pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); + if (value == LED_MODE_TXRX_ACTIVITY) + rt2500pci_init_led(rt2x00dev, &rt2x00dev->led_qual, + LED_TYPE_ACTIVITY); #endif /* CONFIG_RT2500PCI_LEDS */ /* @@ -1827,9 +1823,6 @@ static int rt2500pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) */ skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED; - skbdesc->data = skb->data; - skbdesc->data_len = skb->len; skbdesc->desc = entry_priv->desc; skbdesc->desc_len = intf->beacon->queue->desc_size; skbdesc->entry = intf->beacon; diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h index ea93b8f423a..cb648c30a5b 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.h +++ b/drivers/net/wireless/rt2x00/rt2500pci.h @@ -48,8 +48,6 @@ * Signal information. * Defaul offset is required for RSSI <-> dBm conversion. */ -#define MAX_SIGNAL 100 -#define MAX_RX_SSI -1 #define DEFAULT_RSSI_OFFSET 121 /* diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index cca1504550d..9851cefaabf 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -316,6 +316,17 @@ static int rt2500usb_blink_set(struct led_classdev *led_cdev, return 0; } + +static void rt2500usb_init_led(struct rt2x00_dev *rt2x00dev, + struct rt2x00_led *led, + enum led_type type) +{ + led->rt2x00dev = rt2x00dev; + led->type = type; + led->led_dev.brightness_set = rt2500usb_brightness_set; + led->led_dev.blink_set = rt2500usb_blink_set; + led->flags = LED_INITIALIZED; +} #endif /* CONFIG_RT2500USB_LEDS */ /* @@ -847,25 +858,32 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev) return 0; } -static int rt2500usb_init_bbp(struct rt2x00_dev *rt2x00dev) +static int rt2500usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev) { unsigned int i; - u16 eeprom; u8 value; - u8 reg_id; for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt2500usb_bbp_read(rt2x00dev, 0, &value); if ((value != 0xff) && (value != 0x00)) - goto continue_csr_init; - NOTICE(rt2x00dev, "Waiting for BBP register.\n"); + return 0; udelay(REGISTER_BUSY_DELAY); } ERROR(rt2x00dev, "BBP register access failed, aborting.\n"); return -EACCES; +} + +static int rt2500usb_init_bbp(struct rt2x00_dev *rt2x00dev) +{ + unsigned int i; + u16 eeprom; + u8 value; + u8 reg_id; + + if (unlikely(rt2500usb_wait_bbp_ready(rt2x00dev))) + return -EACCES; -continue_csr_init: rt2500usb_bbp_write(rt2x00dev, 3, 0x02); rt2500usb_bbp_write(rt2x00dev, 4, 0x19); rt2500usb_bbp_write(rt2x00dev, 14, 0x1c); @@ -921,7 +939,8 @@ static void rt2500usb_toggle_rx(struct rt2x00_dev *rt2x00dev, rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®); rt2x00_set_field16(®, TXRX_CSR2_DISABLE_RX, - state == STATE_RADIO_RX_OFF); + (state == STATE_RADIO_RX_OFF) || + (state == STATE_RADIO_RX_OFF_LINK)); rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); } @@ -930,11 +949,9 @@ static int rt2500usb_enable_radio(struct rt2x00_dev *rt2x00dev) /* * Initialize all registers. */ - if (rt2500usb_init_registers(rt2x00dev) || - rt2500usb_init_bbp(rt2x00dev)) { - ERROR(rt2x00dev, "Register initialization failed.\n"); + if (unlikely(rt2500usb_init_registers(rt2x00dev) || + rt2500usb_init_bbp(rt2x00dev))) return -EIO; - } return 0; } @@ -987,10 +1004,6 @@ static int rt2500usb_set_state(struct rt2x00_dev *rt2x00dev, msleep(30); } - NOTICE(rt2x00dev, "Device failed to enter state %d, " - "current device state: bbp %d and rf %d.\n", - state, bbp_state, rf_state); - return -EBUSY; } @@ -1008,11 +1021,13 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev, break; case STATE_RADIO_RX_ON: case STATE_RADIO_RX_ON_LINK: - rt2500usb_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); - break; case STATE_RADIO_RX_OFF: case STATE_RADIO_RX_OFF_LINK: - rt2500usb_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); + rt2500usb_toggle_rx(rt2x00dev, state); + break; + case STATE_RADIO_IRQ_ON: + case STATE_RADIO_IRQ_OFF: + /* No support, but no error either */ break; case STATE_DEEP_SLEEP: case STATE_SLEEP: @@ -1025,6 +1040,10 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev, break; } + if (unlikely(retval)) + ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n", + state, retval); + return retval; } @@ -1069,7 +1088,8 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_NEW_SEQ, test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); - rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len); + rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, + skb->len - skbdesc->desc_len); rt2x00_set_field32(&word, TXD_W0_CIPHER, CIPHER_NONE); rt2x00_desc_write(txd, 0, word); } @@ -1097,8 +1117,10 @@ static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, { u16 reg; - if (queue != QID_BEACON) + if (queue != QID_BEACON) { + rt2x00usb_kick_tx_queue(rt2x00dev, queue); return; + } rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); if (!rt2x00_get_field16(reg, TXRX_CSR19_BEACON_GEN)) { @@ -1134,14 +1156,10 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry, u32 word1; /* - * Copy descriptor to the skb->cb array, this has 2 benefits: - * 1) Each descriptor word is 4 byte aligned. - * 2) Descriptor is safe from moving of frame data in rt2x00usb. + * Copy descriptor to the skbdesc->desc buffer, making it safe from moving of + * frame data in rt2x00usb. */ - skbdesc->desc_len = - min_t(u16, entry->queue->desc_size, sizeof(entry->skb->cb)); - memcpy(entry->skb->cb, rxd, skbdesc->desc_len); - skbdesc->desc = entry->skb->cb; + memcpy(skbdesc->desc, rxd, skbdesc->desc_len); rxd = (__le32 *)skbdesc->desc; /* @@ -1175,8 +1193,6 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry, * Adjust the skb memory window to the frame boundaries. */ skb_trim(entry->skb, rxdesc->size); - skbdesc->data = entry->skb->data; - skbdesc->data_len = rxdesc->size; } /* @@ -1377,23 +1393,10 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) #ifdef CONFIG_RT2500USB_LEDS value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE); - rt2x00dev->led_radio.rt2x00dev = rt2x00dev; - rt2x00dev->led_radio.type = LED_TYPE_RADIO; - rt2x00dev->led_radio.led_dev.brightness_set = - rt2500usb_brightness_set; - rt2x00dev->led_radio.led_dev.blink_set = - rt2500usb_blink_set; - rt2x00dev->led_radio.flags = LED_INITIALIZED; - - if (value == LED_MODE_TXRX_ACTIVITY) { - rt2x00dev->led_qual.rt2x00dev = rt2x00dev; - rt2x00dev->led_qual.type = LED_TYPE_ACTIVITY; - rt2x00dev->led_qual.led_dev.brightness_set = - rt2500usb_brightness_set; - rt2x00dev->led_qual.led_dev.blink_set = - rt2500usb_blink_set; - rt2x00dev->led_qual.flags = LED_INITIALIZED; - } + rt2500usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); + if (value == LED_MODE_TXRX_ACTIVITY) + rt2500usb_init_led(rt2x00dev, &rt2x00dev->led_qual, + LED_TYPE_ACTIVITY); #endif /* CONFIG_RT2500USB_LEDS */ /* @@ -1703,9 +1706,6 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) */ skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED; - skbdesc->data = skb->data + intf->beacon->queue->desc_size; - skbdesc->data_len = skb->len - intf->beacon->queue->desc_size; skbdesc->desc = skb->data; skbdesc->desc_len = intf->beacon->queue->desc_size; skbdesc->entry = intf->beacon; diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index 7d50098f0cc..3e21fdf2b00 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -48,8 +48,6 @@ * Signal information. * Defaul offset is required for RSSI <-> dBm conversion. */ -#define MAX_SIGNAL 100 -#define MAX_RX_SSI -1 #define DEFAULT_RSSI_OFFSET 120 /* diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 15ec797c5ec..0da8f972a1b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -44,7 +44,7 @@ /* * Module information. */ -#define DRV_VERSION "2.1.6" +#define DRV_VERSION "2.1.7" #define DRV_PROJECT "http://rt2x00.serialmonkey.com" /* @@ -546,8 +546,7 @@ struct rt2x00lib_ops { void (*write_tx_desc) (struct rt2x00_dev *rt2x00dev, struct sk_buff *skb, struct txentry_desc *txdesc); - int (*write_tx_data) (struct rt2x00_dev *rt2x00dev, - struct data_queue *queue, struct sk_buff *skb); + int (*write_tx_data) (struct queue_entry *entry); int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev, @@ -827,7 +826,7 @@ struct rt2x00_dev { * The Beacon array also contains the Atim queue * if that is supported by the device. */ - int data_queues; + unsigned int data_queues; struct data_queue *rx; struct data_queue *tx; struct data_queue *bcn; @@ -931,6 +930,12 @@ static inline u16 get_duration_res(const unsigned int size, const u8 rate) } /** + * rt2x00queue_alloc_rxskb - allocate a skb for RX purposes. + * @queue: The queue for which the skb will be applicable. + */ +struct sk_buff *rt2x00queue_alloc_rxskb(struct data_queue *queue); + +/** * rt2x00queue_create_tx_descriptor - Create TX descriptor from mac80211 input * @entry: The entry which will be used to transfer the TX frame. * @txdesc: rt2x00 TX descriptor which will be initialized by this function. diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index bd92cb8e68e..300cf061035 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -133,7 +133,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, return; } - skbcopy = alloc_skb(sizeof(*dump_hdr) + desc->desc_len + desc->data_len, + skbcopy = alloc_skb(sizeof(*dump_hdr) + desc->desc_len + skb->len, GFP_ATOMIC); if (!skbcopy) { DEBUG(rt2x00dev, "Failed to copy skb for dump.\n"); @@ -144,7 +144,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, dump_hdr->version = cpu_to_le32(DUMP_HEADER_VERSION); dump_hdr->header_length = cpu_to_le32(sizeof(*dump_hdr)); dump_hdr->desc_length = cpu_to_le32(desc->desc_len); - dump_hdr->data_length = cpu_to_le32(desc->data_len); + dump_hdr->data_length = cpu_to_le32(skb->len); dump_hdr->chip_rt = cpu_to_le16(rt2x00dev->chip.rt); dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf); dump_hdr->chip_rev = cpu_to_le32(rt2x00dev->chip.rev); @@ -155,7 +155,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, dump_hdr->timestamp_usec = cpu_to_le32(timestamp.tv_usec); memcpy(skb_put(skbcopy, desc->desc_len), desc->desc, desc->desc_len); - memcpy(skb_put(skbcopy, desc->data_len), desc->data, desc->data_len); + memcpy(skb_put(skbcopy, skb->len), skb->data, skb->len); skb_queue_tail(&intf->frame_dump_skbqueue, skbcopy); wake_up_interruptible(&intf->frame_dump_waitqueue); diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index dc5ab90a52c..9ea677320da 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -112,6 +112,8 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev) if (status) return status; + rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_IRQ_ON); + rt2x00leds_led_radio(rt2x00dev, true); rt2x00led_led_activity(rt2x00dev, true); @@ -157,6 +159,7 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev) * Disable radio. */ rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_OFF); + rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_IRQ_OFF); rt2x00led_led_activity(rt2x00dev, false); rt2x00leds_led_radio(rt2x00dev, false); } @@ -551,14 +554,32 @@ void rt2x00lib_rxdone(struct queue_entry *entry, { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; + unsigned int header_size = ieee80211_get_hdrlen_from_skb(entry->skb); struct ieee80211_supported_band *sband; struct ieee80211_hdr *hdr; const struct rt2x00_rate *rate; + unsigned int align; unsigned int i; int idx = -1; u16 fc; /* + * The data behind the ieee80211 header must be + * aligned on a 4 byte boundary. + */ + align = ((unsigned long)(entry->skb->data + header_size)) & 3; + + if (align) { + skb_push(entry->skb, align); + /* Move entire frame in 1 command */ + memmove(entry->skb->data, entry->skb->data + align, + rxdesc->size); + } + + /* Update data pointers, trim buffer to correct size */ + skb_trim(entry->skb, rxdesc->size); + + /* * Update RX statistics. */ sband = &rt2x00dev->bands[rt2x00dev->curr_band]; diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index c4ce534e3cd..558f45bf27e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -101,6 +101,7 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, /* * Queue handlers. */ +int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb); void rt2x00queue_init_rx(struct rt2x00_dev *rt2x00dev); void rt2x00queue_init_tx(struct rt2x00_dev *rt2x00dev); int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index b02dbc8a666..c90992f613f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -34,7 +34,6 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, struct sk_buff *frag_skb) { struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(frag_skb); - struct skb_frame_desc *skbdesc; struct ieee80211_tx_info *rts_info; struct sk_buff *skb; int size; @@ -65,6 +64,7 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, memcpy(skb->cb, frag_skb->cb, sizeof(skb->cb)); rts_info = IEEE80211_SKB_CB(skb); rts_info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT; + rts_info->flags &= ~IEEE80211_TX_CTL_USE_RTS_CTS; rts_info->flags &= ~IEEE80211_TX_CTL_USE_CTS_PROTECT; rts_info->flags &= ~IEEE80211_TX_CTL_REQ_TX_STATUS; @@ -82,14 +82,7 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, frag_skb->data, size, tx_info, (struct ieee80211_rts *)(skb->data)); - /* - * Initialize skb descriptor - */ - skbdesc = get_skb_frame_desc(skb); - memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED; - - if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb)) { + if (rt2x00queue_write_tx_frame(queue, skb)) { WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n"); return NETDEV_TX_BUSY; } @@ -135,18 +128,16 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) } /* - * If CTS/RTS is required. and this frame is not CTS or RTS, - * create and queue that frame first. But make sure we have - * at least enough entries available to send this CTS/RTS - * frame as well as the data frame. + * If CTS/RTS is required. create and queue that frame first. + * Make sure we have at least enough entries available to send + * this CTS/RTS frame as well as the data frame. * Note that when the driver has set the set_rts_threshold() * callback function it doesn't need software generation of - * neither RTS or CTS-to-self frames and handles everything + * either RTS or CTS-to-self frame and handles everything * inside the hardware. */ frame_control = le16_to_cpu(ieee80211hdr->frame_control); - if (!is_rts_frame(frame_control) && !is_cts_frame(frame_control) && - (tx_info->flags & (IEEE80211_TX_CTL_USE_RTS_CTS | + if ((tx_info->flags & (IEEE80211_TX_CTL_USE_RTS_CTS | IEEE80211_TX_CTL_USE_CTS_PROTECT)) && !rt2x00dev->ops->hw->set_rts_threshold) { if (rt2x00queue_available(queue) <= 1) { @@ -160,17 +151,14 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) } } - if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb)) { + if (rt2x00queue_write_tx_frame(queue, skb)) { ieee80211_stop_queue(rt2x00dev->hw, qid); return NETDEV_TX_BUSY; } - if (rt2x00queue_full(queue)) + if (rt2x00queue_threshold(queue)) ieee80211_stop_queue(rt2x00dev->hw, qid); - if (rt2x00dev->ops->lib->kick_tx_queue) - rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, qid); - return NETDEV_TX_OK; } EXPORT_SYMBOL_GPL(rt2x00mac_tx); diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 70a3d135f64..8d6ad18d389 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -34,52 +34,38 @@ /* * TX data handlers. */ -int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev, - struct data_queue *queue, struct sk_buff *skb) +int rt2x00pci_write_tx_data(struct queue_entry *entry) { - struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); struct queue_entry_priv_pci *entry_priv = entry->priv_data; struct skb_frame_desc *skbdesc; - struct txentry_desc txdesc; u32 word; - if (rt2x00queue_full(queue)) - return -EINVAL; - rt2x00_desc_read(entry_priv->desc, 0, &word); - if (rt2x00_get_field32(word, TXD_ENTRY_OWNER_NIC) || - rt2x00_get_field32(word, TXD_ENTRY_VALID)) { - ERROR(rt2x00dev, - "Arrived at non-free entry in the non-full queue %d.\n" + /* + * This should not happen, we already checked the entry + * was ours. When the hardware disagrees there has been + * a queue corruption! + */ + if (unlikely(rt2x00_get_field32(word, TXD_ENTRY_OWNER_NIC) || + rt2x00_get_field32(word, TXD_ENTRY_VALID))) { + ERROR(entry->queue->rt2x00dev, + "Corrupt queue %d, accessing entry which is not ours.\n" "Please file bug report to %s.\n", entry->queue->qid, DRV_PROJECT); return -EINVAL; } /* - * Copy all TX descriptor information into txdesc, - * after that we are free to use the skb->cb array - * for our information. - */ - entry->skb = skb; - rt2x00queue_create_tx_descriptor(entry, &txdesc); - - /* * Fill in skb descriptor */ - skbdesc = get_skb_frame_desc(skb); + skbdesc = get_skb_frame_desc(entry->skb); memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->data = skb->data; - skbdesc->data_len = skb->len; skbdesc->desc = entry_priv->desc; - skbdesc->desc_len = queue->desc_size; + skbdesc->desc_len = entry->queue->desc_size; skbdesc->entry = entry; - memcpy(entry_priv->data, skb->data, skb->len); - - rt2x00queue_write_tx_descriptor(entry, &txdesc); - rt2x00queue_index_inc(queue, Q_INDEX); + memcpy(entry_priv->data, entry->skb->data, entry->skb->len); return 0; } @@ -93,11 +79,8 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) struct data_queue *queue = rt2x00dev->rx; struct queue_entry *entry; struct queue_entry_priv_pci *entry_priv; - struct ieee80211_hdr *hdr; struct skb_frame_desc *skbdesc; struct rxdone_entry_desc rxdesc; - int header_size; - int align; u32 word; while (1) { @@ -111,35 +94,21 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) memset(&rxdesc, 0, sizeof(rxdesc)); rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); - hdr = (struct ieee80211_hdr *)entry_priv->data; - header_size = - ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control)); - - /* - * The data behind the ieee80211 header must be - * aligned on a 4 byte boundary. - */ - align = header_size % 4; - /* - * Allocate the sk_buffer, initialize it and copy - * all data into it. + * Allocate the sk_buffer and copy all data into it. */ - entry->skb = dev_alloc_skb(rxdesc.size + align); + entry->skb = rt2x00queue_alloc_rxskb(queue); if (!entry->skb) return; - skb_reserve(entry->skb, align); - memcpy(skb_put(entry->skb, rxdesc.size), - entry_priv->data, rxdesc.size); + memcpy(entry->skb->data, entry_priv->data, rxdesc.size); + skb_trim(entry->skb, rxdesc.size); /* * Fill in skb descriptor */ skbdesc = get_skb_frame_desc(entry->skb); memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->data = entry->skb->data; - skbdesc->data_len = entry->skb->len; skbdesc->desc = entry_priv->desc; skbdesc->desc_len = queue->desc_size; skbdesc->entry = entry; @@ -178,14 +147,15 @@ void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry, rt2x00_set_field32(&word, TXD_ENTRY_VALID, 0); rt2x00_desc_write(entry_priv->desc, 0, word); + __clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); /* - * If the data queue was full before the txdone handler - * we must make sure the packet queue in the mac80211 stack + * If the data queue was below the threshold before the txdone + * handler we must make sure the packet queue in the mac80211 stack * is reenabled when the txdone handler has finished. */ - if (!rt2x00queue_full(entry->queue)) + if (!rt2x00queue_threshold(entry->queue)) ieee80211_wake_queue(rt2x00dev->hw, qid); } @@ -387,8 +357,7 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) if (pci_set_mwi(pci_dev)) ERROR_PROBE("MWI not available.\n"); - if (pci_set_dma_mask(pci_dev, DMA_64BIT_MASK) && - pci_set_dma_mask(pci_dev, DMA_32BIT_MASK)) { + if (pci_set_dma_mask(pci_dev, DMA_32BIT_MASK)) { ERROR_PROBE("PCI DMA not supported.\n"); retval = -EIO; goto exit_disable_device; diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index 37c851e442c..87c4a0cd78d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h @@ -87,11 +87,14 @@ rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev, memcpy_toio(rt2x00dev->csr.base + offset, value, length); } -/* - * TX data handlers. +/** + * rt2x00pci_write_tx_data - Initialize data for TX operation + * @entry: The entry where the frame is located + * + * This function will initialize the DMA and skb descriptor + * to prepare the entry for the actual TX operation. */ -int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev, - struct data_queue *queue, struct sk_buff *skb); +int rt2x00pci_write_tx_data(struct queue_entry *entry); /** * struct queue_entry_priv_pci: Per entry PCI specific information diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index e69ef4b1923..7b52039b01a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -29,6 +29,45 @@ #include "rt2x00.h" #include "rt2x00lib.h" +struct sk_buff *rt2x00queue_alloc_rxskb(struct data_queue *queue) +{ + struct sk_buff *skb; + unsigned int frame_size; + unsigned int reserved_size; + + /* + * The frame size includes descriptor size, because the + * hardware directly receive the frame into the skbuffer. + */ + frame_size = queue->data_size + queue->desc_size; + + /* + * For the allocation we should keep a few things in mind: + * 1) 4byte alignment of 802.11 payload + * + * For (1) we need at most 4 bytes to guarentee the correct + * alignment. We are going to optimize the fact that the chance + * that the 802.11 header_size % 4 == 2 is much bigger then + * anything else. However since we need to move the frame up + * to 3 bytes to the front, which means we need to preallocate + * 6 bytes. + */ + reserved_size = 6; + + /* + * Allocate skbuffer. + */ + skb = dev_alloc_skb(frame_size + reserved_size); + if (!skb) + return NULL; + + skb_reserve(skb, reserved_size); + skb_put(skb, frame_size); + + return skb; +} +EXPORT_SYMBOL_GPL(rt2x00queue_alloc_rxskb); + void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, struct txentry_desc *txdesc) { @@ -91,7 +130,7 @@ void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, /* * Check if more fragments are pending */ - if (ieee80211_get_morefrag(hdr)) { + if (ieee80211_has_morefrags(hdr->frame_control)) { __set_bit(ENTRY_TXD_BURST, &txdesc->flags); __set_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags); } @@ -163,8 +202,8 @@ EXPORT_SYMBOL_GPL(rt2x00queue_create_tx_descriptor); void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, struct txentry_desc *txdesc) { - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + struct data_queue *queue = entry->queue; + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, entry->skb, txdesc); @@ -175,19 +214,61 @@ void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TX, entry->skb); /* - * We are done writing the frame to the queue entry, - * also kick the queue in case the correct flags are set, - * note that this will automatically filter beacons and - * RTS/CTS frames since those frames don't have this flag - * set. + * Check if we need to kick the queue, there are however a few rules + * 1) Don't kick beacon queue + * 2) Don't kick unless this is the last in frame in a burst. + * When the burst flag is set, this frame is always followed + * by another frame which in some way are related to eachother. + * This is true for fragments, RTS or CTS-to-self frames. + * 3) Rule 2 can be broken when the available entries + * in the queue are less then a certain threshold. */ - if (rt2x00dev->ops->lib->kick_tx_queue && - !(skbdesc->flags & FRAME_DESC_DRIVER_GENERATED)) - rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, - entry->queue->qid); + if (entry->queue->qid == QID_BEACON) + return; + + if (rt2x00queue_threshold(queue) || + !test_bit(ENTRY_TXD_BURST, &txdesc->flags)) + rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, queue->qid); } EXPORT_SYMBOL_GPL(rt2x00queue_write_tx_descriptor); +int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) +{ + struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); + struct txentry_desc txdesc; + + if (unlikely(rt2x00queue_full(queue))) + return -EINVAL; + + if (__test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) { + ERROR(queue->rt2x00dev, + "Arrived at non-free entry in the non-full queue %d.\n" + "Please file bug report to %s.\n", + queue->qid, DRV_PROJECT); + return -EINVAL; + } + + /* + * Copy all TX descriptor information into txdesc, + * after that we are free to use the skb->cb array + * for our information. + */ + entry->skb = skb; + rt2x00queue_create_tx_descriptor(entry, &txdesc); + + if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry))) { + __clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); + return -EIO; + } + + __set_bit(ENTRY_DATA_PENDING, &entry->flags); + + rt2x00queue_index_inc(queue, Q_INDEX); + rt2x00queue_write_tx_descriptor(entry, &txdesc); + + return 0; +} + struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, const enum data_queue_qid queue) { @@ -312,6 +393,7 @@ static int rt2x00queue_alloc_entries(struct data_queue *queue, rt2x00queue_reset(queue); queue->limit = qdesc->entry_num; + queue->threshold = DIV_ROUND_UP(qdesc->entry_num, 10); queue->data_size = qdesc->data_size; queue->desc_size = qdesc->desc_size; @@ -439,7 +521,8 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev) * TX: qid = QID_AC_BE + index * TX: cw_min: 2^5 = 32. * TX: cw_max: 2^10 = 1024. - * BCN & Atim: qid = QID_MGMT + * BCN: qid = QID_BEACON + * ATIM: qid = QID_ATIM */ rt2x00queue_init(rt2x00dev, rt2x00dev->rx, QID_RX); @@ -447,9 +530,9 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev) tx_queue_for_each(rt2x00dev, queue) rt2x00queue_init(rt2x00dev, queue, qid++); - rt2x00queue_init(rt2x00dev, &rt2x00dev->bcn[0], QID_MGMT); + rt2x00queue_init(rt2x00dev, &rt2x00dev->bcn[0], QID_BEACON); if (req_atim) - rt2x00queue_init(rt2x00dev, &rt2x00dev->bcn[1], QID_MGMT); + rt2x00queue_init(rt2x00dev, &rt2x00dev->bcn[1], QID_ATIM); return 0; } diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 4d00ced14cc..fcf52520b01 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -82,12 +82,10 @@ enum data_queue_qid { /** * enum skb_frame_desc_flags: Flags for &struct skb_frame_desc * - * @FRAME_DESC_DRIVER_GENERATED: Frame was generated inside driver - * and should not be reported back to mac80211 during txdone. */ -enum skb_frame_desc_flags { - FRAME_DESC_DRIVER_GENERATED = 1 << 0, -}; +//enum skb_frame_desc_flags { +// TEMPORARILY EMPTY +//}; /** * struct skb_frame_desc: Descriptor information for the skb buffer @@ -107,11 +105,8 @@ enum skb_frame_desc_flags { struct skb_frame_desc { unsigned int flags; - unsigned short data_len; - unsigned short desc_len; - - void *data; void *desc; + unsigned int desc_len; struct queue_entry *entry; }; @@ -260,11 +255,14 @@ struct txentry_desc { * @ENTRY_OWNER_DEVICE_CRYPTO: This entry is owned by the device for data * encryption or decryption. The entry should only be touched after * the device has signaled it is done with it. + * @ENTRY_DATA_PENDING: This entry contains a valid frame and is waiting + * for the signal to start sending. */ enum queue_entry_flags { ENTRY_BCN_ASSIGNED, ENTRY_OWNER_DEVICE_DATA, ENTRY_OWNER_DEVICE_CRYPTO, + ENTRY_DATA_PENDING, }; /** @@ -322,6 +320,7 @@ enum queue_index { * index corruption due to concurrency. * @count: Number of frames handled in the queue. * @limit: Maximum number of entries in the queue. + * @threshold: Minimum number of free entries before queue is kicked by force. * @length: Number of frames in queue. * @index: Index pointers to entry positions in the queue, * use &enum queue_index to get a specific index field. @@ -340,6 +339,7 @@ struct data_queue { spinlock_t lock; unsigned int count; unsigned short limit; + unsigned short threshold; unsigned short length; unsigned short index[Q_INDEX_MAX]; @@ -464,6 +464,15 @@ static inline int rt2x00queue_available(struct data_queue *queue) } /** + * rt2x00queue_threshold - Check if the queue is below threshold + * @queue: Queue to check. + */ +static inline int rt2x00queue_threshold(struct data_queue *queue) +{ + return rt2x00queue_available(queue) < queue->threshold; +} + +/** * rt2x00_desc_read - Read a word from the hardware descriptor. * @desc: Base descriptor address * @word: Word index from where the descriptor should be read. diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h index 3f255df58b7..7e88ce5651b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ b/drivers/net/wireless/rt2x00/rt2x00reg.h @@ -130,83 +130,107 @@ struct rt2x00_field32 { /* * Power of two check, this will check - * if the mask that has been given contains - * and contiguous set of bits. + * if the mask that has been given contains and contiguous set of bits. + * Note that we cannot use the is_power_of_2() function since this + * check must be done at compile-time. */ #define is_power_of_two(x) ( !((x) & ((x)-1)) ) #define low_bit_mask(x) ( ((x)-1) & ~(x) ) #define is_valid_mask(x) is_power_of_two(1 + (x) + low_bit_mask(x)) +/* + * Macro's to find first set bit in a variable. + * These macro's behaves the same as the __ffs() function with + * the most important difference that this is done during + * compile-time rather then run-time. + */ +#define compile_ffs2(__x) \ + __builtin_choose_expr(((__x) & 0x1), 0, 1) + +#define compile_ffs4(__x) \ + __builtin_choose_expr(((__x) & 0x3), \ + (compile_ffs2((__x))), \ + (compile_ffs2((__x) >> 2) + 2)) + +#define compile_ffs8(__x) \ + __builtin_choose_expr(((__x) & 0xf), \ + (compile_ffs4((__x))), \ + (compile_ffs4((__x) >> 4) + 4)) + +#define compile_ffs16(__x) \ + __builtin_choose_expr(((__x) & 0xff), \ + (compile_ffs8((__x))), \ + (compile_ffs8((__x) >> 8) + 8)) + +#define compile_ffs32(__x) \ + __builtin_choose_expr(((__x) & 0xffff), \ + (compile_ffs16((__x))), \ + (compile_ffs16((__x) >> 16) + 16)) + +/* + * This macro will check the requirements for the FIELD{8,16,32} macros + * The mask should be a constant non-zero contiguous set of bits which + * does not exceed the given typelimit. + */ +#define FIELD_CHECK(__mask, __type) \ + BUILD_BUG_ON(!__builtin_constant_p(__mask) || \ + !(__mask) || \ + !is_valid_mask(__mask) || \ + (__mask) != (__type)(__mask)) \ + #define FIELD8(__mask) \ ({ \ - BUILD_BUG_ON(!(__mask) || \ - !is_valid_mask(__mask) || \ - (__mask) != (u8)(__mask)); \ + FIELD_CHECK(__mask, u8); \ (struct rt2x00_field8) { \ - __ffs(__mask), (__mask) \ + compile_ffs8(__mask), (__mask) \ }; \ }) #define FIELD16(__mask) \ ({ \ - BUILD_BUG_ON(!(__mask) || \ - !is_valid_mask(__mask) || \ - (__mask) != (u16)(__mask));\ + FIELD_CHECK(__mask, u16); \ (struct rt2x00_field16) { \ - __ffs(__mask), (__mask) \ + compile_ffs16(__mask), (__mask) \ }; \ }) #define FIELD32(__mask) \ ({ \ - BUILD_BUG_ON(!(__mask) || \ - !is_valid_mask(__mask) || \ - (__mask) != (u32)(__mask));\ + FIELD_CHECK(__mask, u32); \ (struct rt2x00_field32) { \ - __ffs(__mask), (__mask) \ + compile_ffs32(__mask), (__mask) \ }; \ }) -static inline void rt2x00_set_field32(u32 *reg, - const struct rt2x00_field32 field, - const u32 value) -{ - *reg &= ~(field.bit_mask); - *reg |= (value << field.bit_offset) & field.bit_mask; -} - -static inline u32 rt2x00_get_field32(const u32 reg, - const struct rt2x00_field32 field) -{ - return (reg & field.bit_mask) >> field.bit_offset; -} - -static inline void rt2x00_set_field16(u16 *reg, - const struct rt2x00_field16 field, - const u16 value) -{ - *reg &= ~(field.bit_mask); - *reg |= (value << field.bit_offset) & field.bit_mask; -} - -static inline u16 rt2x00_get_field16(const u16 reg, - const struct rt2x00_field16 field) -{ - return (reg & field.bit_mask) >> field.bit_offset; -} - -static inline void rt2x00_set_field8(u8 *reg, - const struct rt2x00_field8 field, - const u8 value) -{ - *reg &= ~(field.bit_mask); - *reg |= (value << field.bit_offset) & field.bit_mask; -} - -static inline u8 rt2x00_get_field8(const u8 reg, - const struct rt2x00_field8 field) -{ - return (reg & field.bit_mask) >> field.bit_offset; -} +#define SET_FIELD(__reg, __type, __field, __value)\ +({ \ + typecheck(__type, __field); \ + *(__reg) &= ~((__field).bit_mask); \ + *(__reg) |= ((__value) << \ + ((__field).bit_offset)) & \ + ((__field).bit_mask); \ +}) + +#define GET_FIELD(__reg, __type, __field) \ +({ \ + typecheck(__type, __field); \ + ((__reg) & ((__field).bit_mask)) >> \ + ((__field).bit_offset); \ +}) + +#define rt2x00_set_field32(__reg, __field, __value) \ + SET_FIELD(__reg, struct rt2x00_field32, __field, __value) +#define rt2x00_get_field32(__reg, __field) \ + GET_FIELD(__reg, struct rt2x00_field32, __field) + +#define rt2x00_set_field16(__reg, __field, __value) \ + SET_FIELD(__reg, struct rt2x00_field16, __field, __value) +#define rt2x00_get_field16(__reg, __field) \ + GET_FIELD(__reg, struct rt2x00_field16, __field) + +#define rt2x00_set_field8(__reg, __field, __value) \ + SET_FIELD(__reg, struct rt2x00_field8, __field, __value) +#define rt2x00_get_field8(__reg, __field) \ + GET_FIELD(__reg, struct rt2x00_field8, __field) #endif /* RT2X00REG_H */ diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 52d12fdc0cc..3080969ae5b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -130,16 +130,12 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) struct queue_entry *entry = (struct queue_entry *)urb->context; struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct txdone_entry_desc txdesc; - __le32 *txd = (__le32 *)entry->skb->data; enum data_queue_qid qid = skb_get_queue_mapping(entry->skb); - u32 word; if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || !__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) return; - rt2x00_desc_read(txd, 0, &word); - /* * Remove the descriptor data from the buffer. */ @@ -169,124 +165,101 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); /* - * If the data queue was full before the txdone handler - * we must make sure the packet queue in the mac80211 stack + * If the data queue was below the threshold before the txdone + * handler we must make sure the packet queue in the mac80211 stack * is reenabled when the txdone handler has finished. */ - if (!rt2x00queue_full(entry->queue)) + if (!rt2x00queue_threshold(entry->queue)) ieee80211_wake_queue(rt2x00dev->hw, qid); } -int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev, - struct data_queue *queue, struct sk_buff *skb) +int rt2x00usb_write_tx_data(struct queue_entry *entry) { + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev); - struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); struct queue_entry_priv_usb *entry_priv = entry->priv_data; struct skb_frame_desc *skbdesc; - struct txentry_desc txdesc; u32 length; - if (rt2x00queue_full(queue)) - return -EINVAL; - - if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) { - ERROR(rt2x00dev, - "Arrived at non-free entry in the non-full queue %d.\n" - "Please file bug report to %s.\n", - entry->queue->qid, DRV_PROJECT); - return -EINVAL; - } - - /* - * Copy all TX descriptor information into txdesc, - * after that we are free to use the skb->cb array - * for our information. - */ - entry->skb = skb; - rt2x00queue_create_tx_descriptor(entry, &txdesc); - /* * Add the descriptor in front of the skb. */ - skb_push(skb, queue->desc_size); - memset(skb->data, 0, queue->desc_size); + skb_push(entry->skb, entry->queue->desc_size); + memset(entry->skb->data, 0, entry->queue->desc_size); /* * Fill in skb descriptor */ - skbdesc = get_skb_frame_desc(skb); + skbdesc = get_skb_frame_desc(entry->skb); memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->data = skb->data + queue->desc_size; - skbdesc->data_len = skb->len - queue->desc_size; - skbdesc->desc = skb->data; - skbdesc->desc_len = queue->desc_size; + skbdesc->desc = entry->skb->data; + skbdesc->desc_len = entry->queue->desc_size; skbdesc->entry = entry; - rt2x00queue_write_tx_descriptor(entry, &txdesc); - /* * USB devices cannot blindly pass the skb->len as the * length of the data to usb_fill_bulk_urb. Pass the skb * to the driver to determine what the length should be. */ - length = rt2x00dev->ops->lib->get_tx_data_len(rt2x00dev, skb); + length = rt2x00dev->ops->lib->get_tx_data_len(rt2x00dev, entry->skb); - /* - * Initialize URB and send the frame to the device. - */ - __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); - usb_fill_bulk_urb(entry_priv->urb, usb_dev, usb_sndbulkpipe(usb_dev, 1), - skb->data, length, rt2x00usb_interrupt_txdone, entry); - usb_submit_urb(entry_priv->urb, GFP_ATOMIC); - - rt2x00queue_index_inc(queue, Q_INDEX); + usb_fill_bulk_urb(entry_priv->urb, usb_dev, + usb_sndbulkpipe(usb_dev, 1), + entry->skb->data, length, + rt2x00usb_interrupt_txdone, entry); return 0; } EXPORT_SYMBOL_GPL(rt2x00usb_write_tx_data); -/* - * RX data handlers. - */ -static struct sk_buff* rt2x00usb_alloc_rxskb(struct data_queue *queue) +static inline void rt2x00usb_kick_tx_entry(struct queue_entry *entry) { - struct sk_buff *skb; - unsigned int frame_size; - unsigned int reserved_size; + struct queue_entry_priv_usb *entry_priv = entry->priv_data; - /* - * The frame size includes descriptor size, because the - * hardware directly receive the frame into the skbuffer. - */ - frame_size = queue->data_size + queue->desc_size; + if (__test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags)) + usb_submit_urb(entry_priv->urb, GFP_ATOMIC); +} + +void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, + const enum data_queue_qid qid) +{ + struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, qid); + unsigned long irqflags; + unsigned int index; + unsigned int index_done; + unsigned int i; /* - * For the allocation we should keep a few things in mind: - * 1) 4byte alignment of 802.11 payload - * - * For (1) we need at most 4 bytes to guarentee the correct - * alignment. We are going to optimize the fact that the chance - * that the 802.11 header_size % 4 == 2 is much bigger then - * anything else. However since we need to move the frame up - * to 3 bytes to the front, which means we need to preallocate - * 6 bytes. + * Only protect the range we are going to loop over, + * if during our loop a extra entry is set to pending + * it should not be kicked during this run, since it + * is part of another TX operation. */ - reserved_size = 6; + spin_lock_irqsave(&queue->lock, irqflags); + index = queue->index[Q_INDEX]; + index_done = queue->index[Q_INDEX_DONE]; + spin_unlock_irqrestore(&queue->lock, irqflags); /* - * Allocate skbuffer. + * Start from the TX done pointer, this guarentees that we will + * send out all frames in the correct order. */ - skb = dev_alloc_skb(frame_size + reserved_size); - if (!skb) - return NULL; - - skb_reserve(skb, reserved_size); - skb_put(skb, frame_size); - - return skb; + if (index_done < index) { + for (i = index_done; i < index; i++) + rt2x00usb_kick_tx_entry(&queue->entries[i]); + } else { + for (i = index_done; i < queue->limit; i++) + rt2x00usb_kick_tx_entry(&queue->entries[i]); + + for (i = 0; i < index; i++) + rt2x00usb_kick_tx_entry(&queue->entries[i]); + } } +EXPORT_SYMBOL_GPL(rt2x00usb_kick_tx_queue); +/* + * RX data handlers. + */ static void rt2x00usb_interrupt_rxdone(struct urb *urb) { struct queue_entry *entry = (struct queue_entry *)urb->context; @@ -294,8 +267,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) struct sk_buff *skb; struct skb_frame_desc *skbdesc; struct rxdone_entry_desc rxdesc; - unsigned int header_size; - unsigned int align; + u8 rxd[32]; if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || !test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) @@ -315,39 +287,18 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) skbdesc = get_skb_frame_desc(entry->skb); memset(skbdesc, 0, sizeof(*skbdesc)); skbdesc->entry = entry; + skbdesc->desc = rxd; + skbdesc->desc_len = entry->queue->desc_size; memset(&rxdesc, 0, sizeof(rxdesc)); rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); - header_size = ieee80211_get_hdrlen_from_skb(entry->skb); - - /* - * The data behind the ieee80211 header must be - * aligned on a 4 byte boundary. We already reserved - * 2 bytes for header_size % 4 == 2 optimization. - * To determine the number of bytes which the data - * should be moved to the left, we must add these - * 2 bytes to the header_size. - */ - align = (header_size + 2) % 4; - - if (align) { - skb_push(entry->skb, align); - /* Move entire frame in 1 command */ - memmove(entry->skb->data, entry->skb->data + align, - rxdesc.size); - } - - /* Update data pointers, trim buffer to correct size */ - skbdesc->data = entry->skb->data; - skb_trim(entry->skb, rxdesc.size); - /* * Allocate a new sk buffer to replace the current one. * If allocation fails, we should drop the current frame * so we can recycle the existing sk buffer for the new frame. */ - skb = rt2x00usb_alloc_rxskb(entry->queue); + skb = rt2x00queue_alloc_rxskb(entry->queue); if (!skb) goto skip_entry; @@ -394,8 +345,11 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev) } /* - * Kill guardian urb. + * Kill guardian urb (if required by driver). */ + if (!test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)) + return; + for (i = 0; i < rt2x00dev->bcn->limit; i++) { bcn_priv = rt2x00dev->bcn->entries[i].priv_data; if (bcn_priv->guardian_urb) @@ -519,7 +473,7 @@ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev) */ entry_size = rt2x00dev->rx->data_size + rt2x00dev->rx->desc_size; for (i = 0; i < rt2x00dev->rx->limit; i++) { - skb = rt2x00usb_alloc_rxskb(rt2x00dev->rx); + skb = rt2x00queue_alloc_rxskb(rt2x00dev->rx); if (!skb) goto exit; diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index 26f53f868af..b1187c812e7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -212,11 +212,14 @@ static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev, */ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev); -/* - * TX data handlers. +/** + * rt2x00usb_write_tx_data - Initialize URB for TX operation + * @entry: The entry where the frame is located + * + * This function will initialize the URB and skb descriptor + * to prepare the entry for the actual TX operation. */ -int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev, - struct data_queue *queue, struct sk_buff *skb); +int rt2x00usb_write_tx_data(struct queue_entry *entry); /** * struct queue_entry_priv_usb: Per entry USB specific information @@ -245,6 +248,17 @@ struct queue_entry_priv_usb_bcn { struct urb *guardian_urb; }; +/** + * rt2x00usb_kick_tx_queue - Kick data queue + * @rt2x00dev: Pointer to &struct rt2x00_dev + * @qid: Data queue to kick + * + * This will walk through all entries of the queue and push all pending + * frames to the hardware as a single burst. + */ +void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, + const enum data_queue_qid qid); + /* * Device initialization handlers. */ diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index e13ed5ced26..5b7267ece1b 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -330,6 +330,17 @@ static int rt61pci_blink_set(struct led_classdev *led_cdev, return 0; } + +static void rt61pci_init_led(struct rt2x00_dev *rt2x00dev, + struct rt2x00_led *led, + enum led_type type) +{ + led->rt2x00dev = rt2x00dev; + led->type = type; + led->led_dev.brightness_set = rt61pci_brightness_set; + led->led_dev.blink_set = rt61pci_blink_set; + led->flags = LED_INITIALIZED; +} #endif /* CONFIG_RT61PCI_LEDS */ /* @@ -1270,25 +1281,32 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev) return 0; } -static int rt61pci_init_bbp(struct rt2x00_dev *rt2x00dev) +static int rt61pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev) { unsigned int i; - u16 eeprom; - u8 reg_id; u8 value; for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt61pci_bbp_read(rt2x00dev, 0, &value); if ((value != 0xff) && (value != 0x00)) - goto continue_csr_init; - NOTICE(rt2x00dev, "Waiting for BBP register.\n"); + return 0; udelay(REGISTER_BUSY_DELAY); } ERROR(rt2x00dev, "BBP register access failed, aborting.\n"); return -EACCES; +} + +static int rt61pci_init_bbp(struct rt2x00_dev *rt2x00dev) +{ + unsigned int i; + u16 eeprom; + u8 reg_id; + u8 value; + + if (unlikely(rt61pci_wait_bbp_ready(rt2x00dev))) + return -EACCES; -continue_csr_init: rt61pci_bbp_write(rt2x00dev, 3, 0x00); rt61pci_bbp_write(rt2x00dev, 15, 0x30); rt61pci_bbp_write(rt2x00dev, 21, 0xc8); @@ -1337,7 +1355,8 @@ static void rt61pci_toggle_rx(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, - state == STATE_RADIO_RX_OFF); + (state == STATE_RADIO_RX_OFF) || + (state == STATE_RADIO_RX_OFF_LINK)); rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); } @@ -1389,17 +1408,10 @@ static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev) /* * Initialize all registers. */ - if (rt61pci_init_queues(rt2x00dev) || - rt61pci_init_registers(rt2x00dev) || - rt61pci_init_bbp(rt2x00dev)) { - ERROR(rt2x00dev, "Register initialization failed.\n"); + if (unlikely(rt61pci_init_queues(rt2x00dev) || + rt61pci_init_registers(rt2x00dev) || + rt61pci_init_bbp(rt2x00dev))) return -EIO; - } - - /* - * Enable interrupts. - */ - rt61pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_ON); /* * Enable RX. @@ -1431,11 +1443,6 @@ static void rt61pci_disable_radio(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC2, 1); rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC3, 1); rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); - - /* - * Disable interrupts. - */ - rt61pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_OFF); } static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) @@ -1443,7 +1450,6 @@ static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) u32 reg; unsigned int i; char put_to_sleep; - char current_state; put_to_sleep = (state != STATE_AWAKE); @@ -1459,16 +1465,12 @@ static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) */ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt2x00pci_register_read(rt2x00dev, MAC_CSR12, ®); - current_state = - rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE); - if (current_state == !put_to_sleep) + state = rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE); + if (state == !put_to_sleep) return 0; msleep(10); } - NOTICE(rt2x00dev, "Device failed to enter state %d, " - "current device state %d.\n", !put_to_sleep, current_state); - return -EBUSY; } @@ -1486,11 +1488,13 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev, break; case STATE_RADIO_RX_ON: case STATE_RADIO_RX_ON_LINK: - rt61pci_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); - break; case STATE_RADIO_RX_OFF: case STATE_RADIO_RX_OFF_LINK: - rt61pci_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); + rt61pci_toggle_rx(rt2x00dev, state); + break; + case STATE_RADIO_IRQ_ON: + case STATE_RADIO_IRQ_OFF: + rt61pci_toggle_irq(rt2x00dev, state); break; case STATE_DEEP_SLEEP: case STATE_SLEEP: @@ -1503,6 +1507,10 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev, break; } + if (unlikely(retval)) + ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n", + state, retval); + return retval; } @@ -1554,7 +1562,7 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, if (skbdesc->desc_len > TXINFO_SIZE) { rt2x00_desc_read(txd, 11, &word); - rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, skbdesc->data_len); + rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, skb->len); rt2x00_desc_write(txd, 11, word); } @@ -1573,7 +1581,7 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0); - rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len); + rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len); rt2x00_set_field32(&word, TXD_W0_BURST, test_bit(ENTRY_TXD_BURST, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE); @@ -2067,31 +2075,11 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom); value = rt2x00_get_field16(eeprom, EEPROM_LED_LED_MODE); - rt2x00dev->led_radio.rt2x00dev = rt2x00dev; - rt2x00dev->led_radio.type = LED_TYPE_RADIO; - rt2x00dev->led_radio.led_dev.brightness_set = - rt61pci_brightness_set; - rt2x00dev->led_radio.led_dev.blink_set = - rt61pci_blink_set; - rt2x00dev->led_radio.flags = LED_INITIALIZED; - - rt2x00dev->led_assoc.rt2x00dev = rt2x00dev; - rt2x00dev->led_assoc.type = LED_TYPE_ASSOC; - rt2x00dev->led_assoc.led_dev.brightness_set = - rt61pci_brightness_set; - rt2x00dev->led_assoc.led_dev.blink_set = - rt61pci_blink_set; - rt2x00dev->led_assoc.flags = LED_INITIALIZED; - - if (value == LED_MODE_SIGNAL_STRENGTH) { - rt2x00dev->led_qual.rt2x00dev = rt2x00dev; - rt2x00dev->led_qual.type = LED_TYPE_QUALITY; - rt2x00dev->led_qual.led_dev.brightness_set = - rt61pci_brightness_set; - rt2x00dev->led_qual.led_dev.blink_set = - rt61pci_blink_set; - rt2x00dev->led_qual.flags = LED_INITIALIZED; - } + rt61pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); + rt61pci_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); + if (value == LED_MODE_SIGNAL_STRENGTH) + rt61pci_init_led(rt2x00dev, &rt2x00dev->led_qual, + LED_TYPE_QUALITY); rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value); rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0, @@ -2387,9 +2375,6 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) */ skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED; - skbdesc->data = skb->data; - skbdesc->data_len = skb->len; skbdesc->desc = entry_priv->desc; skbdesc->desc_len = intf->beacon->queue->desc_size; skbdesc->entry = intf->beacon; @@ -2414,7 +2399,7 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) skbdesc->desc, skbdesc->desc_len); rt2x00pci_register_multiwrite(rt2x00dev, beacon_base + skbdesc->desc_len, - skbdesc->data, skbdesc->data_len); + skb->data, skb->len); rt61pci_kick_tx_queue(rt2x00dev, QID_BEACON); return 0; diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index c5a04b9329d..1004d5b899e 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -39,8 +39,6 @@ * Signal information. * Defaul offset is required for RSSI <-> dBm conversion. */ -#define MAX_SIGNAL 100 -#define MAX_RX_SSI -1 #define DEFAULT_RSSI_OFFSET 120 /* diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 26c2e0a1a30..fceefd730ab 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -335,6 +335,17 @@ static int rt73usb_blink_set(struct led_classdev *led_cdev, return 0; } + +static void rt73usb_init_led(struct rt2x00_dev *rt2x00dev, + struct rt2x00_led *led, + enum led_type type) +{ + led->rt2x00dev = rt2x00dev; + led->type = type; + led->led_dev.brightness_set = rt73usb_brightness_set; + led->led_dev.blink_set = rt73usb_blink_set; + led->flags = LED_INITIALIZED; +} #endif /* CONFIG_RT73USB_LEDS */ /* @@ -1084,25 +1095,32 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev) return 0; } -static int rt73usb_init_bbp(struct rt2x00_dev *rt2x00dev) +static int rt73usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev) { unsigned int i; - u16 eeprom; - u8 reg_id; u8 value; for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt73usb_bbp_read(rt2x00dev, 0, &value); if ((value != 0xff) && (value != 0x00)) - goto continue_csr_init; - NOTICE(rt2x00dev, "Waiting for BBP register.\n"); + return 0; udelay(REGISTER_BUSY_DELAY); } ERROR(rt2x00dev, "BBP register access failed, aborting.\n"); return -EACCES; +} + +static int rt73usb_init_bbp(struct rt2x00_dev *rt2x00dev) +{ + unsigned int i; + u16 eeprom; + u8 reg_id; + u8 value; + + if (unlikely(rt73usb_wait_bbp_ready(rt2x00dev))) + return -EACCES; -continue_csr_init: rt73usb_bbp_write(rt2x00dev, 3, 0x80); rt73usb_bbp_write(rt2x00dev, 15, 0x30); rt73usb_bbp_write(rt2x00dev, 21, 0xc8); @@ -1152,7 +1170,8 @@ static void rt73usb_toggle_rx(struct rt2x00_dev *rt2x00dev, rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, - state == STATE_RADIO_RX_OFF); + (state == STATE_RADIO_RX_OFF) || + (state == STATE_RADIO_RX_OFF_LINK)); rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); } @@ -1161,11 +1180,9 @@ static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev) /* * Initialize all registers. */ - if (rt73usb_init_registers(rt2x00dev) || - rt73usb_init_bbp(rt2x00dev)) { - ERROR(rt2x00dev, "Register initialization failed.\n"); + if (unlikely(rt73usb_init_registers(rt2x00dev) || + rt73usb_init_bbp(rt2x00dev))) return -EIO; - } return 0; } @@ -1187,7 +1204,6 @@ static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) u32 reg; unsigned int i; char put_to_sleep; - char current_state; put_to_sleep = (state != STATE_AWAKE); @@ -1203,16 +1219,12 @@ static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) */ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt73usb_register_read(rt2x00dev, MAC_CSR12, ®); - current_state = - rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE); - if (current_state == !put_to_sleep) + state = rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE); + if (state == !put_to_sleep) return 0; msleep(10); } - NOTICE(rt2x00dev, "Device failed to enter state %d, " - "current device state %d.\n", !put_to_sleep, current_state); - return -EBUSY; } @@ -1230,11 +1242,13 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev, break; case STATE_RADIO_RX_ON: case STATE_RADIO_RX_ON_LINK: - rt73usb_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); - break; case STATE_RADIO_RX_OFF: case STATE_RADIO_RX_OFF_LINK: - rt73usb_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); + rt73usb_toggle_rx(rt2x00dev, state); + break; + case STATE_RADIO_IRQ_ON: + case STATE_RADIO_IRQ_OFF: + /* No support, but no error either */ break; case STATE_DEEP_SLEEP: case STATE_SLEEP: @@ -1247,6 +1261,10 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev, break; } + if (unlikely(retval)) + ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n", + state, retval); + return retval; } @@ -1302,7 +1320,8 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0); - rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len); + rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, + skb->len - skbdesc->desc_len); rt2x00_set_field32(&word, TXD_W0_BURST2, test_bit(ENTRY_TXD_BURST, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE); @@ -1332,8 +1351,10 @@ static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, { u32 reg; - if (queue != QID_BEACON) + if (queue != QID_BEACON) { + rt2x00usb_kick_tx_queue(rt2x00dev, queue); return; + } /* * For Wi-Fi faily generated beacons between participating stations. @@ -1407,14 +1428,10 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry, u32 word1; /* - * Copy descriptor to the skb->cb array, this has 2 benefits: - * 1) Each descriptor word is 4 byte aligned. - * 2) Descriptor is safe from moving of frame data in rt2x00usb. + * Copy descriptor to the skbdesc->desc buffer, making it safe from moving of + * frame data in rt2x00usb. */ - skbdesc->desc_len = - min_t(u16, entry->queue->desc_size, sizeof(entry->skb->cb)); - memcpy(entry->skb->cb, rxd, skbdesc->desc_len); - skbdesc->desc = entry->skb->cb; + memcpy(skbdesc->desc, rxd, skbdesc->desc_len); rxd = (__le32 *)skbdesc->desc; /* @@ -1446,8 +1463,6 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry, */ skb_pull(entry->skb, entry->queue->desc_size); skb_trim(entry->skb, rxdesc->size); - skbdesc->data = entry->skb->data; - skbdesc->data_len = rxdesc->size; } /* @@ -1620,31 +1635,11 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) #ifdef CONFIG_RT73USB_LEDS rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom); - rt2x00dev->led_radio.rt2x00dev = rt2x00dev; - rt2x00dev->led_radio.type = LED_TYPE_RADIO; - rt2x00dev->led_radio.led_dev.brightness_set = - rt73usb_brightness_set; - rt2x00dev->led_radio.led_dev.blink_set = - rt73usb_blink_set; - rt2x00dev->led_radio.flags = LED_INITIALIZED; - - rt2x00dev->led_assoc.rt2x00dev = rt2x00dev; - rt2x00dev->led_assoc.type = LED_TYPE_ASSOC; - rt2x00dev->led_assoc.led_dev.brightness_set = - rt73usb_brightness_set; - rt2x00dev->led_assoc.led_dev.blink_set = - rt73usb_blink_set; - rt2x00dev->led_assoc.flags = LED_INITIALIZED; - - if (value == LED_MODE_SIGNAL_STRENGTH) { - rt2x00dev->led_qual.rt2x00dev = rt2x00dev; - rt2x00dev->led_qual.type = LED_TYPE_QUALITY; - rt2x00dev->led_qual.led_dev.brightness_set = - rt73usb_brightness_set; - rt2x00dev->led_qual.led_dev.blink_set = - rt73usb_blink_set; - rt2x00dev->led_qual.flags = LED_INITIALIZED; - } + rt73usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); + rt73usb_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); + if (value == LED_MODE_SIGNAL_STRENGTH) + rt73usb_init_led(rt2x00dev, &rt2x00dev->led_qual, + LED_TYPE_QUALITY); rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value); rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0, @@ -1980,9 +1975,6 @@ static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) */ skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED; - skbdesc->data = skb->data + intf->beacon->queue->desc_size; - skbdesc->data_len = skb->len - intf->beacon->queue->desc_size; skbdesc->desc = skb->data; skbdesc->desc_len = intf->beacon->queue->desc_size; skbdesc->entry = intf->beacon; @@ -2122,6 +2114,7 @@ static struct usb_device_id rt73usb_device_table[] = { /* D-Link */ { USB_DEVICE(0x07d1, 0x3c03), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x07d1, 0x3c04), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c06), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x07d1, 0x3c07), USB_DEVICE_DATA(&rt73usb_ops) }, /* Gemtek */ { USB_DEVICE(0x15a9, 0x0004), USB_DEVICE_DATA(&rt73usb_ops) }, diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index 25cdcc9bf7c..14849350101 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -39,8 +39,6 @@ * Signal information. * Defaul offset is required for RSSI <-> dBm conversion. */ -#define MAX_SIGNAL 100 -#define MAX_RX_SSI -1 #define DEFAULT_RSSI_OFFSET 120 /* diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index 0078c7e9918..bec96d762c6 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -181,7 +181,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) flags |= RTL8187_TX_FLAG_NO_ENCRYPT; flags |= ieee80211_get_tx_rate(dev, info)->hw_value << 24; - if (ieee80211_get_morefrag((struct ieee80211_hdr *)skb->data)) + if (ieee80211_has_morefrags(((struct ieee80211_hdr *)skb->data)->frame_control)) flags |= RTL8187_TX_FLAG_MORE_FRAG; if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { flags |= RTL8187_TX_FLAG_RTS; diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c index 715a4447161..b2ccdcbeb89 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/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 0201c8adfda..46c791adb89 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 e2b7de4cb05..1ff3bb585ab 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 9c2496dbeee..cf4e07b01d4 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 c444d6b10c5..49215da5249 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 6cc2c033023..4949dc4859b 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 872f1218ff9..b6e14d51670 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 42244f14b41..2ef8cdfda4a 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 d060a06ce05..d7bb9bac71d 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 fa2d2f8b3f4..640acd20fdd 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 00000000000..11644c8fca8 --- /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 00000000000..c8e97e25ef7 --- /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/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c index 62576af36f4..3e577f655b1 100644 --- a/drivers/s390/char/sclp_vt220.c +++ b/drivers/s390/char/sclp_vt220.c @@ -773,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_3590.c b/drivers/s390/char/tape_3590.c index 8246ef3ab09..42ce7915fc5 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/cio/blacklist.c b/drivers/s390/cio/blacklist.c index a4a5f2efea4..0bfcbbe375c 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 82c6a2d4512..b32d7eb3d81 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/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 436bf1f6d4a..9a71dae223e 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 822df836285..452874e8974 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 08a50f05728..c26e842ad90 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 86ec50ddae1..f682f7b1448 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 94a8ead64ed..999552c83bb 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 08f51fd902c..ac1993708ae 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 5080f343ad7..5bfbe765983 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 ccfd8aca376..5d23368a1bc 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 4c4aadb3e40..204604501ad 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 287690853ca..8dd88fc1244 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 299eccf6cab..8dd600013bd 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 f8827068d30..9b4bebee687 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 e9bae27737d..92fafbdbbaa 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 5d9a64a7879..ec63b79f900 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 21006042080..250d2f60439 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 f2b04979e5f..62a3ad6e8ec 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 3223fd16bcf..48eaa3bb543 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 afeae2bfe7e..d058c8862b3 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 049103f1d16..93d2b671445 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/atmel_serial.c b/drivers/serial/atmel_serial.c index c065a704a93..42be8b01a40 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 d6b4ead693b..f20952c43cb 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 2d6c08b3dbc..f8e1447a022 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 53b03c629af..c9b64e73c98 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 01917c433f1..566a8b42e05 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 41620c0fb04..799337f7fde 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/main.c b/drivers/ssb/main.c index 7cf8851286b..d184f2aea78 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c @@ -1168,15 +1168,21 @@ EXPORT_SYMBOL(ssb_dma_translation); int ssb_dma_set_mask(struct ssb_device *ssb_dev, u64 mask) { struct device *dma_dev = ssb_dev->dma_dev; + int err = 0; #ifdef CONFIG_SSB_PCIHOST - if (ssb_dev->bus->bustype == SSB_BUSTYPE_PCI) - return dma_set_mask(dma_dev, mask); + if (ssb_dev->bus->bustype == SSB_BUSTYPE_PCI) { + err = pci_set_dma_mask(ssb_dev->bus->host_pci, mask); + if (err) + return err; + err = pci_set_consistent_dma_mask(ssb_dev->bus->host_pci, mask); + return err; + } #endif dma_dev->coherent_dma_mask = mask; dma_dev->dma_mask = &dma_dev->coherent_dma_mask; - return 0; + return err; } EXPORT_SYMBOL(ssb_dma_set_mask); diff --git a/drivers/usb/c67x00/c67x00-ll-hpi.c b/drivers/usb/c67x00/c67x00-ll-hpi.c index 5100fbbf6cb..a9636f43bca 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 107666d4e2e..731db051070 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/hub.c b/drivers/usb/core/hub.c index 8eb4da332f5..94789be54ca 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); diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 1ef6df395e0..228797e54f9 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/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index c9cec873826..65aa5ecf569 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 440bf94f0d4..c9db3fe9872 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 eb6c06979f3..001789c9a11 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -272,6 +272,7 @@ config USB_TEST 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 diff --git a/drivers/usb/misc/isight_firmware.c b/drivers/usb/misc/isight_firmware.c index 390e0488553..9f30aa1f8a5 100644 --- a/drivers/usb/misc/isight_firmware.c +++ b/drivers/usb/misc/isight_firmware.c @@ -39,9 +39,12 @@ static int isight_firmware_load(struct usb_interface *intf, struct usb_device *dev = interface_to_usbdev(intf); int llen, len, req, ret = 0; const struct firmware *firmware; - unsigned char *buf; + unsigned char *buf = kmalloc(50, GFP_KERNEL); unsigned char data[4]; - char *ptr; + u8 *ptr; + + if (!buf) + return -ENOMEM; if (request_firmware(&firmware, "isight.fw", &dev->dev) != 0) { printk(KERN_ERR "Unable to load isight firmware\n"); @@ -59,7 +62,7 @@ static int isight_firmware_load(struct usb_interface *intf, goto out; } - while (1) { + while (ptr+4 <= firmware->data+firmware->size) { memcpy(data, ptr, 4); len = (data[0] << 8 | data[1]); req = (data[2] << 8 | data[3]); @@ -71,10 +74,14 @@ static int isight_firmware_load(struct usb_interface *intf, continue; for (; len > 0; req += 50) { - llen = len > 50 ? 50 : len; + llen = min(len, 50); len -= llen; - - buf = kmalloc(llen, GFP_KERNEL); + if (ptr+llen > firmware->data+firmware->size) { + printk(KERN_ERR + "Malformed isight firmware"); + ret = -ENODEV; + goto out; + } memcpy(buf, ptr, llen); ptr += llen; @@ -89,16 +96,18 @@ static int isight_firmware_load(struct usb_interface *intf, goto out; } - kfree(buf); } } + 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; } diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 35ac9d956b3..c14b2435d23 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 5fa8b76673c..97aff8db10b 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 b50bb03cb5a..0a2785361ca 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 fb9e6722854..c18880d9db1 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 8bc46e93034..13fea61d6ae 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 47356219158..d3c3af53a29 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 274bc93ab7d..7dcda187d9b 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; |