diff options
Diffstat (limited to 'drivers')
349 files changed, 7318 insertions, 4577 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index da3a08fa9e4f..b9f923ef173d 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -67,7 +67,21 @@ config ACPI_PROCFS and functions which do not yet exist in /sys. Say N to delete /proc/acpi/ files that have moved to /sys/ - +config ACPI_PROCFS_POWER + bool "Deprecated power /proc/acpi folders" + depends on PROC_FS + default y + ---help--- + For backwards compatibility, this option allows + deprecated power /proc/acpi/ folders to exist, even when + they have been replaced by functions in /sys. + The deprecated folders (and their replacements) include: + /proc/acpi/battery/* (/sys/class/power_supply/*) + /proc/acpi/ac_adapter/* (sys/class/power_supply/*) + This option has no effect on /proc/acpi/ folders + and functions, which do not yet exist in /sys + + Say N to delete power /proc/acpi/ folders that have moved to /sys/ config ACPI_PROC_EVENT bool "Deprecated /proc/acpi/event support" depends on PROC_FS diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 54e3ab0e5fc0..456446f90077 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -58,6 +58,6 @@ obj-$(CONFIG_ACPI_NUMA) += numa.o obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o -obj-y += cm_sbs.o +obj-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o obj-$(CONFIG_ACPI_SBS) += sbs.o obj-$(CONFIG_ACPI_SBS) += sbshc.o diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index e03de37a750d..76ed4f52bebd 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -27,8 +27,10 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/types.h> +#ifdef CONFIG_ACPI_PROCFS_POWER #include <linux/proc_fs.h> #include <linux/seq_file.h> +#endif #include <linux/power_supply.h> #include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h> @@ -49,12 +51,15 @@ MODULE_AUTHOR("Paul Diefenbaugh"); MODULE_DESCRIPTION("ACPI AC Adapter Driver"); MODULE_LICENSE("GPL"); +#ifdef CONFIG_ACPI_PROCFS_POWER extern struct proc_dir_entry *acpi_lock_ac_dir(void); extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); +static int acpi_ac_open_fs(struct inode *inode, struct file *file); +#endif static int acpi_ac_add(struct acpi_device *device); static int acpi_ac_remove(struct acpi_device *device, int type); -static int acpi_ac_open_fs(struct inode *inode, struct file *file); +static int acpi_ac_resume(struct acpi_device *device); const static struct acpi_device_id ac_device_ids[] = { {"ACPI0003", 0}, @@ -69,6 +74,7 @@ static struct acpi_driver acpi_ac_driver = { .ops = { .add = acpi_ac_add, .remove = acpi_ac_remove, + .resume = acpi_ac_resume, }, }; @@ -80,12 +86,15 @@ struct acpi_ac { #define to_acpi_ac(x) container_of(x, struct acpi_ac, charger); +#ifdef CONFIG_ACPI_PROCFS_POWER static const struct file_operations acpi_ac_fops = { .open = acpi_ac_open_fs, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; +#endif + static int get_ac_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) @@ -127,6 +136,7 @@ static int acpi_ac_get_state(struct acpi_ac *ac) return 0; } +#ifdef CONFIG_ACPI_PROCFS_POWER /* -------------------------------------------------------------------------- FS Interface (/proc) -------------------------------------------------------------------------- */ @@ -206,6 +216,7 @@ static int acpi_ac_remove_fs(struct acpi_device *device) return 0; } +#endif /* -------------------------------------------------------------------------- Driver Model @@ -264,7 +275,9 @@ static int acpi_ac_add(struct acpi_device *device) if (result) goto end; +#ifdef CONFIG_ACPI_PROCFS_POWER result = acpi_ac_add_fs(device); +#endif if (result) goto end; ac->charger.name = acpi_device_bid(device); @@ -287,13 +300,30 @@ static int acpi_ac_add(struct acpi_device *device) end: if (result) { +#ifdef CONFIG_ACPI_PROCFS_POWER acpi_ac_remove_fs(device); +#endif kfree(ac); } return result; } +static int acpi_ac_resume(struct acpi_device *device) +{ + struct acpi_ac *ac; + unsigned old_state; + if (!device || !acpi_driver_data(device)) + return -EINVAL; + ac = acpi_driver_data(device); + old_state = ac->state; + if (acpi_ac_get_state(ac)) + return 0; + if (old_state != ac->state) + kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); + return 0; +} + static int acpi_ac_remove(struct acpi_device *device, int type) { acpi_status status = AE_OK; @@ -309,7 +339,9 @@ static int acpi_ac_remove(struct acpi_device *device, int type) ACPI_ALL_NOTIFY, acpi_ac_notify); if (ac->charger.dev) power_supply_unregister(&ac->charger); +#ifdef CONFIG_ACPI_PROCFS_POWER acpi_ac_remove_fs(device); +#endif kfree(ac); @@ -323,13 +355,17 @@ static int __init acpi_ac_init(void) if (acpi_disabled) return -ENODEV; +#ifdef CONFIG_ACPI_PROCFS_POWER acpi_ac_dir = acpi_lock_ac_dir(); if (!acpi_ac_dir) return -ENODEV; +#endif result = acpi_bus_register_driver(&acpi_ac_driver); if (result < 0) { +#ifdef CONFIG_ACPI_PROCFS_POWER acpi_unlock_ac_dir(acpi_ac_dir); +#endif return -ENODEV; } @@ -341,7 +377,9 @@ static void __exit acpi_ac_exit(void) acpi_bus_unregister_driver(&acpi_ac_driver); +#ifdef CONFIG_ACPI_PROCFS_POWER acpi_unlock_ac_dir(acpi_ac_dir); +#endif return; } diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index c2ce0ad21693..7d6be23eff89 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -31,7 +31,7 @@ #include <linux/types.h> #include <linux/jiffies.h> -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <asm/uaccess.h> @@ -63,7 +63,7 @@ static unsigned int cache_time = 1000; module_param(cache_time, uint, 0644); MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER extern struct proc_dir_entry *acpi_lock_battery_dir(void); extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); @@ -132,7 +132,7 @@ static int acpi_battery_technology(struct acpi_battery *battery) return POWER_SUPPLY_TECHNOLOGY_UNKNOWN; } -static int acpi_battery_update(struct acpi_battery *battery); +static int acpi_battery_get_state(struct acpi_battery *battery); static int acpi_battery_get_property(struct power_supply *psy, enum power_supply_property psp, @@ -140,10 +140,11 @@ static int acpi_battery_get_property(struct power_supply *psy, { struct acpi_battery *battery = to_acpi_battery(psy); - if ((!acpi_battery_present(battery)) && - psp != POWER_SUPPLY_PROP_PRESENT) + if (acpi_battery_present(battery)) { + /* run battery update only if it is present */ + acpi_battery_get_state(battery); + } else if (psp != POWER_SUPPLY_PROP_PRESENT) return -ENODEV; - acpi_battery_update(battery); switch (psp) { case POWER_SUPPLY_PROP_STATUS: if (battery->state & 0x01) @@ -152,6 +153,8 @@ static int acpi_battery_get_property(struct power_supply *psy, val->intval = POWER_SUPPLY_STATUS_CHARGING; else if (battery->state == 0) val->intval = POWER_SUPPLY_STATUS_FULL; + else + val->intval = POWER_SUPPLY_STATUS_UNKNOWN; break; case POWER_SUPPLY_PROP_PRESENT: val->intval = acpi_battery_present(battery); @@ -220,7 +223,7 @@ static enum power_supply_property energy_battery_props[] = { POWER_SUPPLY_PROP_MANUFACTURER, }; -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER inline char *acpi_battery_units(struct acpi_battery *battery) { return (battery->power_unit)?"mA":"mW"; @@ -457,6 +460,7 @@ static void sysfs_remove_battery(struct acpi_battery *battery) return; device_remove_file(battery->bat.dev, &alarm_attr); power_supply_unregister(&battery->bat); + battery->bat.dev = NULL; } static int acpi_battery_update(struct acpi_battery *battery) @@ -477,7 +481,7 @@ static int acpi_battery_update(struct acpi_battery *battery) FS Interface (/proc) -------------------------------------------------------------------------- */ -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER static struct proc_dir_entry *acpi_battery_dir; static int acpi_battery_print_info(struct seq_file *seq, int result) @@ -784,7 +788,7 @@ static int acpi_battery_add(struct acpi_device *device) acpi_driver_data(device) = battery; mutex_init(&battery->lock); acpi_battery_update(battery); -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER result = acpi_battery_add_fs(device); if (result) goto end; @@ -802,7 +806,7 @@ static int acpi_battery_add(struct acpi_device *device) device->status.battery_present ? "present" : "absent"); end: if (result) { -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER acpi_battery_remove_fs(device); #endif kfree(battery); @@ -821,7 +825,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type) status = acpi_remove_notify_handler(device->handle, ACPI_ALL_NOTIFY, acpi_battery_notify); -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER acpi_battery_remove_fs(device); #endif sysfs_remove_battery(battery); @@ -857,13 +861,13 @@ static int __init acpi_battery_init(void) { if (acpi_disabled) return -ENODEV; -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER acpi_battery_dir = acpi_lock_battery_dir(); if (!acpi_battery_dir) return -ENODEV; #endif if (acpi_bus_register_driver(&acpi_battery_driver) < 0) { -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER acpi_unlock_battery_dir(acpi_battery_dir); #endif return -ENODEV; @@ -874,7 +878,7 @@ static int __init acpi_battery_init(void) static void __exit acpi_battery_exit(void) { acpi_bus_unregister_driver(&acpi_battery_driver); -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER acpi_unlock_battery_dir(acpi_battery_dir); #endif } diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 06b78e5e33a1..d411017f8c06 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -47,6 +47,9 @@ #undef PREFIX #define PREFIX "ACPI: EC: " +/* Uncomment next line to get verbose print outs*/ +/* #define DEBUG */ + /* EC status register */ #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ @@ -75,7 +78,10 @@ enum { EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */ EC_FLAGS_QUERY_PENDING, /* Query is pending */ EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */ - EC_FLAGS_ONLY_IBF_GPE, /* Expect GPE only for IBF = 0 event */ + EC_FLAGS_NO_ADDRESS_GPE, /* Expect GPE only for non-address event */ + EC_FLAGS_ADDRESS, /* Address is being written */ + EC_FLAGS_NO_WDATA_GPE, /* Don't expect WDATA GPE event */ + EC_FLAGS_WDATA, /* Data is being written */ }; static int acpi_ec_remove(struct acpi_device *device, int type); @@ -131,21 +137,27 @@ static struct acpi_ec { static inline u8 acpi_ec_read_status(struct acpi_ec *ec) { - return inb(ec->command_addr); + u8 x = inb(ec->command_addr); + pr_debug(PREFIX "---> status = 0x%2x\n", x); + return x; } static inline u8 acpi_ec_read_data(struct acpi_ec *ec) { + u8 x = inb(ec->data_addr); + pr_debug(PREFIX "---> data = 0x%2x\n", x); return inb(ec->data_addr); } static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command) { + pr_debug(PREFIX "<--- command = 0x%2x\n", command); outb(command, ec->command_addr); } static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) { + pr_debug(PREFIX "<--- data = 0x%2x\n", data); outb(data, ec->data_addr); } @@ -166,38 +178,54 @@ static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event) static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) { + int ret = 0; + if (unlikely(test_bit(EC_FLAGS_ADDRESS, &ec->flags) && + test_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags))) + force_poll = 1; + if (unlikely(test_bit(EC_FLAGS_WDATA, &ec->flags) && + test_bit(EC_FLAGS_NO_WDATA_GPE, &ec->flags))) + force_poll = 1; if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) && likely(!force_poll)) { if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event), msecs_to_jiffies(ACPI_EC_DELAY))) - return 0; + goto end; clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); if (acpi_ec_check_status(ec, event)) { - if (event == ACPI_EC_EVENT_OBF_1) { - /* miss OBF = 1 GPE, don't expect it anymore */ - printk(KERN_INFO PREFIX "missing OBF_1 confirmation," - "switching to degraded mode.\n"); - set_bit(EC_FLAGS_ONLY_IBF_GPE, &ec->flags); + if (test_bit(EC_FLAGS_ADDRESS, &ec->flags)) { + /* miss address GPE, don't expect it anymore */ + pr_info(PREFIX "missing address confirmation, " + "don't expect it any longer.\n"); + set_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags); + } else if (test_bit(EC_FLAGS_WDATA, &ec->flags)) { + /* miss write data GPE, don't expect it */ + pr_info(PREFIX "missing write data confirmation, " + "don't expect it any longer.\n"); + set_bit(EC_FLAGS_NO_WDATA_GPE, &ec->flags); } else { /* missing GPEs, switch back to poll mode */ - printk(KERN_INFO PREFIX "missing IBF_1 confirmations," - "switch off interrupt mode.\n"); + if (printk_ratelimit()) + pr_info(PREFIX "missing confirmations, " + "switch off interrupt mode.\n"); clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); } - return 0; + goto end; } } else { unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); while (time_before(jiffies, delay)) { if (acpi_ec_check_status(ec, event)) - return 0; + goto end; } } - printk(KERN_ERR PREFIX "acpi_ec_wait timeout," + pr_err(PREFIX "acpi_ec_wait timeout," " status = %d, expect_event = %d\n", acpi_ec_read_status(ec), event); - return -ETIME; + ret = -ETIME; + end: + clear_bit(EC_FLAGS_ADDRESS, &ec->flags); + return ret; } static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, @@ -208,22 +236,26 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, int result = 0; set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); acpi_ec_write_cmd(ec, command); - + pr_debug(PREFIX "transaction start\n"); for (; wdata_len > 0; --wdata_len) { result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); if (result) { - printk(KERN_ERR PREFIX + pr_err(PREFIX "write_cmd timeout, command = %d\n", command); goto end; } + /* mark the address byte written to EC */ + if (rdata_len + wdata_len > 1) + set_bit(EC_FLAGS_ADDRESS, &ec->flags); set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); acpi_ec_write_data(ec, *(wdata++)); } if (!rdata_len) { + set_bit(EC_FLAGS_WDATA, &ec->flags); result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); if (result) { - printk(KERN_ERR PREFIX + pr_err(PREFIX "finish-write timeout, command = %d\n", command); goto end; } @@ -231,12 +263,9 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); for (; rdata_len > 0; --rdata_len) { - if (test_bit(EC_FLAGS_ONLY_IBF_GPE, &ec->flags)) - force_poll = 1; result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, force_poll); if (result) { - printk(KERN_ERR PREFIX "read timeout, command = %d\n", - command); + pr_err(PREFIX "read timeout, command = %d\n", command); goto end; } /* Don't expect GPE after last read */ @@ -245,6 +274,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, *(rdata++) = acpi_ec_read_data(ec); } end: + pr_debug(PREFIX "transaction end\n"); return result; } @@ -273,8 +303,8 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0); if (status) { - printk(KERN_ERR PREFIX - "input buffer is not empty, aborting transaction\n"); + pr_err(PREFIX "input buffer is not empty, " + "aborting transaction\n"); goto end; } @@ -488,6 +518,7 @@ static u32 acpi_ec_gpe_handler(void *data) acpi_status status = AE_OK; struct acpi_ec *ec = data; + pr_debug(PREFIX "~~~> interrupt\n"); clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) wake_up(&ec->wait); @@ -498,8 +529,9 @@ static u32 acpi_ec_gpe_handler(void *data) acpi_ec_gpe_query, ec); } else if (unlikely(!test_bit(EC_FLAGS_GPE_MODE, &ec->flags))) { /* this is non-query, must be confirmation */ - printk(KERN_INFO PREFIX "non-query interrupt received," - " switching to interrupt mode\n"); + if (printk_ratelimit()) + pr_info(PREFIX "non-query interrupt received," + " switching to interrupt mode\n"); set_bit(EC_FLAGS_GPE_MODE, &ec->flags); } @@ -701,10 +733,10 @@ static void ec_remove_handlers(struct acpi_ec *ec) { if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler))) - printk(KERN_ERR PREFIX "failed to remove space handler\n"); + pr_err(PREFIX "failed to remove space handler\n"); if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler))) - printk(KERN_ERR PREFIX "failed to remove gpe handler\n"); + pr_err(PREFIX "failed to remove gpe handler\n"); ec->handlers_installed = 0; } @@ -747,9 +779,9 @@ static int acpi_ec_add(struct acpi_device *device) first_ec = ec; acpi_driver_data(device) = ec; acpi_ec_add_fs(device); - printk(KERN_INFO PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", + pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", ec->gpe, ec->command_addr, ec->data_addr); - printk(KERN_INFO PREFIX "driver started in %s mode\n", + pr_info(PREFIX "driver started in %s mode\n", (test_bit(EC_FLAGS_GPE_MODE, &ec->flags))?"interrupt":"poll"); return 0; } @@ -875,18 +907,26 @@ int __init acpi_ec_ecdt_probe(void) status = acpi_get_table(ACPI_SIG_ECDT, 1, (struct acpi_table_header **)&ecdt_ptr); if (ACPI_SUCCESS(status)) { - printk(KERN_INFO PREFIX "EC description table is found, configuring boot EC\n"); + pr_info(PREFIX "EC description table is found, configuring boot EC\n"); boot_ec->command_addr = ecdt_ptr->control.address; boot_ec->data_addr = ecdt_ptr->data.address; boot_ec->gpe = ecdt_ptr->gpe; boot_ec->handle = ACPI_ROOT_OBJECT; } else { + /* This workaround is needed only on some broken machines, + * which require early EC, but fail to provide ECDT */ + acpi_handle x; printk(KERN_DEBUG PREFIX "Look up EC in DSDT\n"); status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device, boot_ec, NULL); /* Check that acpi_get_devices actually find something */ if (ACPI_FAILURE(status) || !boot_ec->handle) goto error; + /* We really need to limit this workaround, the only ASUS, + * which needs it, has fake EC._INI method, so use it as flag. + */ + if (ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI", &x))) + goto error; } ret = ec_install_handlers(boot_ec); diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index aabc6ca4a81c..e3a673a00845 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -387,17 +387,14 @@ acpi_status acpi_os_read_port(acpi_io_address port, u32 * value, u32 width) if (!value) value = &dummy; - switch (width) { - case 8: + *value = 0; + if (width <= 8) { *(u8 *) value = inb(port); - break; - case 16: + } else if (width <= 16) { *(u16 *) value = inw(port); - break; - case 32: + } else if (width <= 32) { *(u32 *) value = inl(port); - break; - default: + } else { BUG(); } @@ -408,17 +405,13 @@ EXPORT_SYMBOL(acpi_os_read_port); acpi_status acpi_os_write_port(acpi_io_address port, u32 value, u32 width) { - switch (width) { - case 8: + if (width <= 8) { outb(value, port); - break; - case 16: + } else if (width <= 16) { outw(value, port); - break; - case 32: + } else if (width <= 32) { outl(value, port); - break; - default: + } else { BUG(); } diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 235a51e328c3..e48ee4f8749f 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -494,7 +494,7 @@ static int get_cpu_id(acpi_handle handle, u32 acpi_id) if (apic_id == -1) return apic_id; - for (i = 0; i < NR_CPUS; ++i) { + for_each_possible_cpu(i) { if (cpu_physical_id(i) == apic_id) return i; } @@ -612,12 +612,6 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid) request_region(pr->throttling.address, 6, "ACPI CPU throttle"); } -#ifdef CONFIG_CPU_FREQ - acpi_processor_ppc_has_changed(pr); -#endif - acpi_processor_get_throttling_info(pr); - acpi_processor_get_limit_info(pr); - return 0; } @@ -638,7 +632,7 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device) return 0; } - BUG_ON((pr->id >= NR_CPUS) || (pr->id < 0)); + BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0)); /* * Buggy BIOS check @@ -647,7 +641,7 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device) */ if (processor_device_array[pr->id] != NULL && processor_device_array[pr->id] != device) { - printk(KERN_WARNING "BIOS reported wrong ACPI id" + printk(KERN_WARNING "BIOS reported wrong ACPI id " "for the processor\n"); return -ENODEV; } @@ -665,6 +659,12 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device) /* _PDC call should be done before doing anything else (if reqd.). */ arch_acpi_processor_init_pdc(pr); acpi_processor_set_pdc(pr); +#ifdef CONFIG_CPU_FREQ + acpi_processor_ppc_has_changed(pr); +#endif + acpi_processor_get_throttling_info(pr); + acpi_processor_get_limit_info(pr); + acpi_processor_power_init(pr, device); @@ -684,7 +684,7 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data) { struct acpi_processor *pr = data; struct acpi_device *device = NULL; - + int saved; if (!pr) return; @@ -694,7 +694,10 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data) switch (event) { case ACPI_PROCESSOR_NOTIFY_PERFORMANCE: + saved = pr->performance_platform_limit; acpi_processor_ppc_has_changed(pr); + if (saved == pr->performance_platform_limit) + break; acpi_bus_generate_proc_event(device, event, pr->performance_platform_limit); acpi_bus_generate_netlink_event(device->pnp.device_class, @@ -771,7 +774,7 @@ static int acpi_processor_remove(struct acpi_device *device, int type) pr = acpi_driver_data(device); - if (pr->id >= NR_CPUS) { + if (pr->id >= nr_cpu_ids) { kfree(pr); return 0; } @@ -842,7 +845,7 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device) if (!pr) return -ENODEV; - if ((pr->id >= 0) && (pr->id < NR_CPUS)) { + if ((pr->id >= 0) && (pr->id < nr_cpu_ids)) { kobject_uevent(&(*device)->dev.kobj, KOBJ_ONLINE); } return 0; @@ -880,13 +883,13 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data) break; } - if (pr->id >= 0 && (pr->id < NR_CPUS)) { + if (pr->id >= 0 && (pr->id < nr_cpu_ids)) { kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); break; } result = acpi_processor_start(device); - if ((!result) && ((pr->id >= 0) && (pr->id < NR_CPUS))) { + if ((!result) && ((pr->id >= 0) && (pr->id < nr_cpu_ids))) { kobject_uevent(&device->dev.kobj, KOBJ_ONLINE); } else { printk(KERN_ERR PREFIX "Device [%s] failed to start\n", @@ -909,7 +912,7 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data) return; } - if ((pr->id < NR_CPUS) && (cpu_present(pr->id))) + if ((pr->id < nr_cpu_ids) && (cpu_present(pr->id))) kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); break; default: diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index f996d0e37689..b1fbee3f7fe1 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -197,6 +197,19 @@ static inline u32 ticks_elapsed_in_us(u32 t1, u32 t2) return PM_TIMER_TICKS_TO_US((0xFFFFFFFF - t1) + t2); } +static void acpi_safe_halt(void) +{ + current_thread_info()->status &= ~TS_POLLING; + /* + * TS_POLLING-cleared state must be visible before we + * test NEED_RESCHED: + */ + smp_mb(); + if (!need_resched()) + safe_halt(); + current_thread_info()->status |= TS_POLLING; +} + #ifndef CONFIG_CPU_IDLE static void @@ -239,19 +252,6 @@ acpi_processor_power_activate(struct acpi_processor *pr, return; } -static void acpi_safe_halt(void) -{ - current_thread_info()->status &= ~TS_POLLING; - /* - * TS_POLLING-cleared state must be visible before we - * test NEED_RESCHED: - */ - smp_mb(); - if (!need_resched()) - safe_halt(); - current_thread_info()->status |= TS_POLLING; -} - static atomic_t c3_cpu_count; /* Common C-state entry for C2, C3, .. */ @@ -1373,15 +1373,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, if (pr->flags.bm_check) acpi_idle_update_bm_rld(pr, cx); - current_thread_info()->status &= ~TS_POLLING; - /* - * TS_POLLING-cleared state must be visible before we test - * NEED_RESCHED: - */ - smp_mb(); - if (!need_resched()) - safe_halt(); - current_thread_info()->status |= TS_POLLING; + acpi_safe_halt(); cx->usage++; @@ -1399,6 +1391,8 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, struct acpi_processor *pr; struct acpi_processor_cx *cx = cpuidle_get_statedata(state); u32 t1, t2; + int sleep_ticks = 0; + pr = processors[smp_processor_id()]; if (unlikely(!pr)) @@ -1428,6 +1422,8 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, ACPI_FLUSH_CPU_CACHE(); t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); + /* Tell the scheduler that we are going deep-idle: */ + sched_clock_idle_sleep_event(); acpi_state_timer_broadcast(pr, cx, 1); acpi_idle_do_entry(cx); t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); @@ -1436,6 +1432,10 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, /* TSC could halt in idle, so notify users */ mark_tsc_unstable("TSC halts in idle");; #endif + sleep_ticks = ticks_elapsed(t1, t2); + + /* Tell the scheduler how much we idled: */ + sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); local_irq_enable(); current_thread_info()->status |= TS_POLLING; @@ -1443,7 +1443,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, cx->usage++; acpi_state_timer_broadcast(pr, cx, 0); - cx->time += ticks_elapsed(t1, t2); + cx->time += sleep_ticks; return ticks_elapsed_in_us(t1, t2); } @@ -1463,6 +1463,8 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, struct acpi_processor *pr; struct acpi_processor_cx *cx = cpuidle_get_statedata(state); u32 t1, t2; + int sleep_ticks = 0; + pr = processors[smp_processor_id()]; if (unlikely(!pr)) @@ -1471,6 +1473,15 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, if (acpi_idle_suspend) return(acpi_idle_enter_c1(dev, state)); + if (acpi_idle_bm_check()) { + if (dev->safe_state) { + return dev->safe_state->enter(dev, dev->safe_state); + } else { + acpi_safe_halt(); + return 0; + } + } + local_irq_disable(); current_thread_info()->status &= ~TS_POLLING; /* @@ -1485,38 +1496,45 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, return 0; } + /* Tell the scheduler that we are going deep-idle: */ + sched_clock_idle_sleep_event(); /* * Must be done before busmaster disable as we might need to * access HPET ! */ acpi_state_timer_broadcast(pr, cx, 1); - if (acpi_idle_bm_check()) { - cx = pr->power.bm_state; - - acpi_idle_update_bm_rld(pr, cx); - - t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); - acpi_idle_do_entry(cx); - t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); - } else { - acpi_idle_update_bm_rld(pr, cx); + acpi_idle_update_bm_rld(pr, cx); + /* + * disable bus master + * bm_check implies we need ARB_DIS + * !bm_check implies we need cache flush + * bm_control implies whether we can do ARB_DIS + * + * That leaves a case where bm_check is set and bm_control is + * not set. In that case we cannot do much, we enter C3 + * without doing anything. + */ + if (pr->flags.bm_check && pr->flags.bm_control) { spin_lock(&c3_lock); c3_cpu_count++; /* Disable bus master arbitration when all CPUs are in C3 */ if (c3_cpu_count == num_online_cpus()) acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1); spin_unlock(&c3_lock); + } else if (!pr->flags.bm_check) { + ACPI_FLUSH_CPU_CACHE(); + } - t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); - acpi_idle_do_entry(cx); - t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); + t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); + acpi_idle_do_entry(cx); + t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); + /* Re-enable bus master arbitration */ + if (pr->flags.bm_check && pr->flags.bm_control) { spin_lock(&c3_lock); - /* Re-enable bus master arbitration */ - if (c3_cpu_count == num_online_cpus()) - acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0); + acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0); c3_cpu_count--; spin_unlock(&c3_lock); } @@ -1525,6 +1543,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, /* TSC could halt in idle, so notify users */ mark_tsc_unstable("TSC halts in idle"); #endif + sleep_ticks = ticks_elapsed(t1, t2); + /* Tell the scheduler how much we idled: */ + sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); local_irq_enable(); current_thread_info()->status |= TS_POLLING; @@ -1532,7 +1553,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, cx->usage++; acpi_state_timer_broadcast(pr, cx, 0); - cx->time += ticks_elapsed(t1, t2); + cx->time += sleep_ticks; return ticks_elapsed_in_us(t1, t2); } @@ -1584,12 +1605,14 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) case ACPI_STATE_C1: state->flags |= CPUIDLE_FLAG_SHALLOW; state->enter = acpi_idle_enter_c1; + dev->safe_state = state; break; case ACPI_STATE_C2: state->flags |= CPUIDLE_FLAG_BALANCED; state->flags |= CPUIDLE_FLAG_TIME_VALID; state->enter = acpi_idle_enter_simple; + dev->safe_state = state; break; case ACPI_STATE_C3: @@ -1610,14 +1633,6 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) if (!count) return -EINVAL; - /* find the deepest state that can handle active BM */ - if (pr->flags.bm_check) { - for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) - if (pr->power.states[i].type == ACPI_STATE_C3) - break; - pr->power.bm_state = &pr->power.states[i-1]; - } - return 0; } @@ -1658,6 +1673,7 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, if (!first_run) { dmi_check_system(processor_power_dmi_table); + max_cstate = acpi_processor_cstate_check(max_cstate); if (max_cstate < ACPI_C_STATES_MAX) printk(KERN_NOTICE "ACPI: processor limited to max C-state %d\n", diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 0b8204e7082a..c26c61fb36c3 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -70,7 +70,55 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr) int acpi_processor_tstate_has_changed(struct acpi_processor *pr) { - return acpi_processor_get_platform_limit(pr); + int result = 0; + int throttling_limit; + int current_state; + struct acpi_processor_limit *limit; + int target_state; + + result = acpi_processor_get_platform_limit(pr); + if (result) { + /* Throttling Limit is unsupported */ + return result; + } + + throttling_limit = pr->throttling_platform_limit; + if (throttling_limit >= pr->throttling.state_count) { + /* Uncorrect Throttling Limit */ + return -EINVAL; + } + + current_state = pr->throttling.state; + if (current_state > throttling_limit) { + /* + * The current state can meet the requirement of + * _TPC limit. But it is reasonable that OSPM changes + * t-states from high to low for better performance. + * Of course the limit condition of thermal + * and user should be considered. + */ + limit = &pr->limit; + target_state = throttling_limit; + if (limit->thermal.tx > target_state) + target_state = limit->thermal.tx; + if (limit->user.tx > target_state) + target_state = limit->user.tx; + } else if (current_state == throttling_limit) { + /* + * Unnecessary to change the throttling state + */ + return 0; + } else { + /* + * If the current state is lower than the limit of _TPC, it + * will be forced to switch to the throttling state defined + * by throttling_platfor_limit. + * Because the previous state meets with the limit condition + * of thermal and user, it is unnecessary to check it again. + */ + target_state = throttling_limit; + } + return acpi_processor_set_throttling(pr, target_state); } /* @@ -83,6 +131,7 @@ static int acpi_processor_get_throttling_control(struct acpi_processor *pr) struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *ptc = NULL; union acpi_object obj = { 0 }; + struct acpi_processor_throttling *throttling; status = acpi_evaluate_object(pr->handle, "_PTC", NULL, &buffer); if (ACPI_FAILURE(status)) { @@ -134,6 +183,22 @@ static int acpi_processor_get_throttling_control(struct acpi_processor *pr) memcpy(&pr->throttling.status_register, obj.buffer.pointer, sizeof(struct acpi_ptc_register)); + throttling = &pr->throttling; + + if ((throttling->control_register.bit_width + + throttling->control_register.bit_offset) > 32) { + printk(KERN_ERR PREFIX "Invalid _PTC control register\n"); + result = -EFAULT; + goto end; + } + + if ((throttling->status_register.bit_width + + throttling->status_register.bit_offset) > 32) { + printk(KERN_ERR PREFIX "Invalid _PTC status register\n"); + result = -EFAULT; + goto end; + } + end: kfree(buffer.pointer); @@ -328,44 +393,132 @@ static int acpi_processor_get_throttling_fadt(struct acpi_processor *pr) return 0; } -static int acpi_read_throttling_status(struct acpi_processor_throttling - *throttling) +#ifdef CONFIG_X86 +static int acpi_throttling_rdmsr(struct acpi_processor *pr, + acpi_integer * value) { - int value = -1; + struct cpuinfo_x86 *c; + u64 msr_high, msr_low; + unsigned int cpu; + u64 msr = 0; + int ret = -1; + + cpu = pr->id; + c = &cpu_data(cpu); + + if ((c->x86_vendor != X86_VENDOR_INTEL) || + !cpu_has(c, X86_FEATURE_ACPI)) { + printk(KERN_ERR PREFIX + "HARDWARE addr space,NOT supported yet\n"); + } else { + msr_low = 0; + msr_high = 0; + rdmsr_on_cpu(cpu, MSR_IA32_THERM_CONTROL, + (u32 *)&msr_low , (u32 *) &msr_high); + msr = (msr_high << 32) | msr_low; + *value = (acpi_integer) msr; + ret = 0; + } + return ret; +} + +static int acpi_throttling_wrmsr(struct acpi_processor *pr, acpi_integer value) +{ + struct cpuinfo_x86 *c; + unsigned int cpu; + int ret = -1; + u64 msr; + + cpu = pr->id; + c = &cpu_data(cpu); + + if ((c->x86_vendor != X86_VENDOR_INTEL) || + !cpu_has(c, X86_FEATURE_ACPI)) { + printk(KERN_ERR PREFIX + "HARDWARE addr space,NOT supported yet\n"); + } else { + msr = value; + wrmsr_on_cpu(cpu, MSR_IA32_THERM_CONTROL, + msr & 0xffffffff, msr >> 32); + ret = 0; + } + return ret; +} +#else +static int acpi_throttling_rdmsr(struct acpi_processor *pr, + acpi_integer * value) +{ + printk(KERN_ERR PREFIX + "HARDWARE addr space,NOT supported yet\n"); + return -1; +} + +static int acpi_throttling_wrmsr(struct acpi_processor *pr, acpi_integer value) +{ + printk(KERN_ERR PREFIX + "HARDWARE addr space,NOT supported yet\n"); + return -1; +} +#endif + +static int acpi_read_throttling_status(struct acpi_processor *pr, + acpi_integer *value) +{ + u32 bit_width, bit_offset; + u64 ptc_value; + u64 ptc_mask; + struct acpi_processor_throttling *throttling; + int ret = -1; + + throttling = &pr->throttling; switch (throttling->status_register.space_id) { case ACPI_ADR_SPACE_SYSTEM_IO: + ptc_value = 0; + bit_width = throttling->status_register.bit_width; + bit_offset = throttling->status_register.bit_offset; + acpi_os_read_port((acpi_io_address) throttling->status_register. - address, &value, - (u32) throttling->status_register.bit_width * - 8); + address, (u32 *) &ptc_value, + (u32) (bit_width + bit_offset)); + ptc_mask = (1 << bit_width) - 1; + *value = (acpi_integer) ((ptc_value >> bit_offset) & ptc_mask); + ret = 0; break; case ACPI_ADR_SPACE_FIXED_HARDWARE: - printk(KERN_ERR PREFIX - "HARDWARE addr space,NOT supported yet\n"); + ret = acpi_throttling_rdmsr(pr, value); break; default: printk(KERN_ERR PREFIX "Unknown addr space %d\n", (u32) (throttling->status_register.space_id)); } - return value; + return ret; } -static int acpi_write_throttling_state(struct acpi_processor_throttling - *throttling, int value) +static int acpi_write_throttling_state(struct acpi_processor *pr, + acpi_integer value) { + u32 bit_width, bit_offset; + u64 ptc_value; + u64 ptc_mask; + struct acpi_processor_throttling *throttling; int ret = -1; + throttling = &pr->throttling; switch (throttling->control_register.space_id) { case ACPI_ADR_SPACE_SYSTEM_IO: + bit_width = throttling->control_register.bit_width; + bit_offset = throttling->control_register.bit_offset; + ptc_mask = (1 << bit_width) - 1; + ptc_value = value & ptc_mask; + acpi_os_write_port((acpi_io_address) throttling-> - control_register.address, value, - (u32) throttling->control_register. - bit_width * 8); + control_register.address, + (u32) (ptc_value << bit_offset), + (u32) (bit_width + bit_offset)); ret = 0; break; case ACPI_ADR_SPACE_FIXED_HARDWARE: - printk(KERN_ERR PREFIX - "HARDWARE addr space,NOT supported yet\n"); + ret = acpi_throttling_wrmsr(pr, value); break; default: printk(KERN_ERR PREFIX "Unknown addr space %d\n", @@ -374,7 +527,8 @@ static int acpi_write_throttling_state(struct acpi_processor_throttling return ret; } -static int acpi_get_throttling_state(struct acpi_processor *pr, int value) +static int acpi_get_throttling_state(struct acpi_processor *pr, + acpi_integer value) { int i; @@ -390,22 +544,26 @@ static int acpi_get_throttling_state(struct acpi_processor *pr, int value) return i; } -static int acpi_get_throttling_value(struct acpi_processor *pr, int state) +static int acpi_get_throttling_value(struct acpi_processor *pr, + int state, acpi_integer *value) { - int value = -1; + int ret = -1; + if (state >= 0 && state <= pr->throttling.state_count) { struct acpi_processor_tx_tss *tx = (struct acpi_processor_tx_tss *)&(pr->throttling. states_tss[state]); - value = tx->control; + *value = tx->control; + ret = 0; } - return value; + return ret; } static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr) { int state = 0; - u32 value = 0; + int ret; + acpi_integer value; if (!pr) return -EINVAL; @@ -415,8 +573,9 @@ static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr) pr->throttling.state = 0; local_irq_disable(); - value = acpi_read_throttling_status(&pr->throttling); - if (value >= 0) { + value = 0; + ret = acpi_read_throttling_status(pr, &value); + if (ret >= 0) { state = acpi_get_throttling_state(pr, value); pr->throttling.state = state; } @@ -430,6 +589,40 @@ static int acpi_processor_get_throttling(struct acpi_processor *pr) return pr->throttling.acpi_processor_get_throttling(pr); } +static int acpi_processor_get_fadt_info(struct acpi_processor *pr) +{ + int i, step; + + if (!pr->throttling.address) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling register\n")); + return -EINVAL; + } else if (!pr->throttling.duty_width) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling states\n")); + return -EINVAL; + } + /* TBD: Support duty_cycle values that span bit 4. */ + else if ((pr->throttling.duty_offset + pr->throttling.duty_width) > 4) { + printk(KERN_WARNING PREFIX "duty_cycle spans bit 4\n"); + return -EINVAL; + } + + pr->throttling.state_count = 1 << acpi_gbl_FADT.duty_width; + + /* + * Compute state values. Note that throttling displays a linear power + * performance relationship (at 50% performance the CPU will consume + * 50% power). Values are in 1/10th of a percent to preserve accuracy. + */ + + step = (1000 / pr->throttling.state_count); + + for (i = 0; i < pr->throttling.state_count; i++) { + pr->throttling.states[i].performance = 1000 - step * i; + pr->throttling.states[i].power = 1000 - step * i; + } + return 0; +} + static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr, int state) { @@ -506,7 +699,8 @@ static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr, static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr, int state) { - u32 value = 0; + int ret; + acpi_integer value; if (!pr) return -EINVAL; @@ -524,10 +718,10 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr, return -EPERM; local_irq_disable(); - - value = acpi_get_throttling_value(pr, state); - if (value >= 0) { - acpi_write_throttling_state(&pr->throttling, value); + value = 0; + ret = acpi_get_throttling_value(pr, state, &value); + if (ret >= 0) { + acpi_write_throttling_state(pr, value); pr->throttling.state = state; } local_irq_enable(); @@ -543,8 +737,6 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state) int acpi_processor_get_throttling_info(struct acpi_processor *pr) { int result = 0; - int step = 0; - int i = 0; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n", @@ -563,6 +755,8 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr) acpi_processor_get_throttling_states(pr) || acpi_processor_get_platform_limit(pr)) { + if (acpi_processor_get_fadt_info(pr)) + return 0; pr->throttling.acpi_processor_get_throttling = &acpi_processor_get_throttling_fadt; pr->throttling.acpi_processor_set_throttling = @@ -576,19 +770,6 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr) acpi_processor_get_tsd(pr); - if (!pr->throttling.address) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling register\n")); - return 0; - } else if (!pr->throttling.duty_width) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling states\n")); - return 0; - } - /* TBD: Support duty_cycle values that span bit 4. */ - else if ((pr->throttling.duty_offset + pr->throttling.duty_width) > 4) { - printk(KERN_WARNING PREFIX "duty_cycle spans bit 4\n"); - return 0; - } - /* * PIIX4 Errata: We don't support throttling on the original PIIX4. * This shouldn't be an issue as few (if any) mobile systems ever @@ -600,21 +781,6 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr) return 0; } - pr->throttling.state_count = 1 << acpi_gbl_FADT.duty_width; - - /* - * Compute state values. Note that throttling displays a linear power/ - * performance relationship (at 50% performance the CPU will consume - * 50% power). Values are in 1/10th of a percent to preserve accuracy. - */ - - step = (1000 / pr->throttling.state_count); - - for (i = 0; i < pr->throttling.state_count; i++) { - pr->throttling.states[i].performance = step * i; - pr->throttling.states[i].power = step * i; - } - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d throttling states\n", pr->throttling.state_count)); diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 90fd09c65f95..6045cdbe176b 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -29,7 +29,7 @@ #include <linux/moduleparam.h> #include <linux/kernel.h> -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <asm/uaccess.h> @@ -88,7 +88,7 @@ MODULE_DEVICE_TABLE(acpi, sbs_device_ids); struct acpi_battery { struct power_supply bat; struct acpi_sbs *sbs; -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER struct proc_dir_entry *proc_entry; #endif unsigned long update_time; @@ -113,6 +113,7 @@ struct acpi_battery { u16 spec; u8 id; u8 present:1; + u8 have_sysfs_alarm:1; }; #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat); @@ -122,7 +123,7 @@ struct acpi_sbs { struct acpi_device *device; struct acpi_smb_hc *hc; struct mutex lock; -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER struct proc_dir_entry *charger_entry; #endif struct acpi_battery battery[MAX_SBS_BAT]; @@ -468,7 +469,7 @@ static struct device_attribute alarm_attr = { FS Interface (/proc/acpi) -------------------------------------------------------------------------- */ -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER /* Generic Routines */ static int acpi_sbs_add_fs(struct proc_dir_entry **dir, @@ -789,7 +790,7 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) return result; sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id); -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER acpi_sbs_add_fs(&battery->proc_entry, acpi_battery_dir, battery->name, &acpi_battery_info_fops, &acpi_battery_state_fops, &acpi_battery_alarm_fops, @@ -808,7 +809,13 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) } battery->bat.get_property = acpi_sbs_battery_get_property; result = power_supply_register(&sbs->device->dev, &battery->bat); - device_create_file(battery->bat.dev, &alarm_attr); + if (result) + goto end; + result = device_create_file(battery->bat.dev, &alarm_attr); + if (result) + goto end; + battery->have_sysfs_alarm = 1; + end: printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n", ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), battery->name, sbs->battery->present ? "present" : "absent"); @@ -817,14 +824,16 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) static void acpi_battery_remove(struct acpi_sbs *sbs, int id) { - if (sbs->battery[id].bat.dev) - device_remove_file(sbs->battery[id].bat.dev, &alarm_attr); - power_supply_unregister(&sbs->battery[id].bat); -#ifdef CONFIG_ACPI_PROCFS - if (sbs->battery[id].proc_entry) { - acpi_sbs_remove_fs(&(sbs->battery[id].proc_entry), - acpi_battery_dir); + struct acpi_battery *battery = &sbs->battery[id]; + + if (battery->bat.dev) { + if (battery->have_sysfs_alarm) + device_remove_file(battery->bat.dev, &alarm_attr); + power_supply_unregister(&battery->bat); } +#ifdef CONFIG_ACPI_PROCFS_POWER + if (battery->proc_entry) + acpi_sbs_remove_fs(&battery->proc_entry, acpi_battery_dir); #endif } @@ -835,7 +844,7 @@ static int acpi_charger_add(struct acpi_sbs *sbs) result = acpi_ac_get_present(sbs); if (result) goto end; -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER result = acpi_sbs_add_fs(&sbs->charger_entry, acpi_ac_dir, ACPI_AC_DIR_NAME, NULL, &acpi_ac_state_fops, NULL, sbs); @@ -859,7 +868,7 @@ static void acpi_charger_remove(struct acpi_sbs *sbs) { if (sbs->charger.dev) power_supply_unregister(&sbs->charger); -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER if (sbs->charger_entry) acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir); #endif @@ -965,7 +974,7 @@ static int acpi_sbs_remove(struct acpi_device *device, int type) static void acpi_sbs_rmdirs(void) { -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER if (acpi_ac_dir) { acpi_unlock_ac_dir(acpi_ac_dir); acpi_ac_dir = NULL; @@ -1004,7 +1013,7 @@ static int __init acpi_sbs_init(void) if (acpi_disabled) return -ENODEV; -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER acpi_ac_dir = acpi_lock_ac_dir(); if (!acpi_ac_dir) return -ENODEV; diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c index 5f1d85f2ffe4..010f19652f80 100644 --- a/drivers/acpi/tables/tbutils.c +++ b/drivers/acpi/tables/tbutils.c @@ -449,7 +449,7 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags) /* XSDT has NULL entry, RSDT is used */ address = rsdt_address; table_entry_size = sizeof(u32); - ACPI_WARNING((AE_INFO, "BIOS XSDT has NULL entry," + ACPI_WARNING((AE_INFO, "BIOS XSDT has NULL entry, " "using RSDT")); } } diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c index a736ef7bdee4..9e8c20c6a0b7 100644 --- a/drivers/acpi/toshiba_acpi.c +++ b/drivers/acpi/toshiba_acpi.c @@ -591,9 +591,12 @@ static int __init toshiba_acpi_init(void) NULL, &toshiba_backlight_data); if (IS_ERR(toshiba_backlight_device)) { + int ret = PTR_ERR(toshiba_backlight_device); + printk(KERN_ERR "Could not register toshiba backlight device\n"); toshiba_backlight_device = NULL; toshiba_acpi_exit(); + return ret; } toshiba_backlight_device->props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1; diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index bac956b30c57..44a0d9ba9bd6 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -29,6 +29,7 @@ #include <linux/init.h> #include <linux/types.h> #include <linux/list.h> +#include <linux/mutex.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/input.h> @@ -135,8 +136,8 @@ struct acpi_video_bus { u8 attached_count; struct acpi_video_bus_cap cap; struct acpi_video_bus_flags flags; - struct semaphore sem; struct list_head video_device_list; + struct mutex device_list_lock; /* protects video_device_list */ struct proc_dir_entry *dir; struct input_dev *input; char phys[32]; /* for input device */ @@ -896,7 +897,7 @@ acpi_video_device_write_brightness(struct file *file, { struct seq_file *m = file->private_data; struct acpi_video_device *dev = m->private; - char str[4] = { 0 }; + char str[5] = { 0 }; unsigned int level = 0; int i; @@ -1436,9 +1437,9 @@ acpi_video_bus_get_one_device(struct acpi_device *device, return -ENODEV; } - down(&video->sem); + mutex_lock(&video->device_list_lock); list_add_tail(&data->entry, &video->video_device_list); - up(&video->sem); + mutex_unlock(&video->device_list_lock); acpi_video_device_add_fs(device); @@ -1462,12 +1463,14 @@ acpi_video_bus_get_one_device(struct acpi_device *device, static void acpi_video_device_rebind(struct acpi_video_bus *video) { - struct list_head *node, *next; - list_for_each_safe(node, next, &video->video_device_list) { - struct acpi_video_device *dev = - container_of(node, struct acpi_video_device, entry); + struct acpi_video_device *dev; + + mutex_lock(&video->device_list_lock); + + list_for_each_entry(dev, &video->video_device_list, entry) acpi_video_device_bind(video, dev); - } + + mutex_unlock(&video->device_list_lock); } /* @@ -1592,30 +1595,33 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) static int acpi_video_switch_output(struct acpi_video_bus *video, int event) { - struct list_head *node, *next; + struct list_head *node; struct acpi_video_device *dev = NULL; struct acpi_video_device *dev_next = NULL; struct acpi_video_device *dev_prev = NULL; unsigned long state; int status = 0; + mutex_lock(&video->device_list_lock); - list_for_each_safe(node, next, &video->video_device_list) { + list_for_each(node, &video->video_device_list) { dev = container_of(node, struct acpi_video_device, entry); status = acpi_video_device_get_state(dev, &state); if (state & 0x2) { - dev_next = - container_of(node->next, struct acpi_video_device, - entry); - dev_prev = - container_of(node->prev, struct acpi_video_device, - entry); + dev_next = container_of(node->next, + struct acpi_video_device, entry); + dev_prev = container_of(node->prev, + struct acpi_video_device, entry); goto out; } } + dev_next = container_of(node->next, struct acpi_video_device, entry); dev_prev = container_of(node->prev, struct acpi_video_device, entry); - out: + + out: + mutex_unlock(&video->device_list_lock); + switch (event) { case ACPI_VIDEO_NOTIFY_CYCLE: case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: @@ -1691,24 +1697,17 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video, struct acpi_device *device) { int status = 0; - struct list_head *node, *next; - + struct acpi_device *dev; acpi_video_device_enumerate(video); - list_for_each_safe(node, next, &device->children) { - struct acpi_device *dev = - list_entry(node, struct acpi_device, node); - - if (!dev) - continue; + list_for_each_entry(dev, &device->children, node) { status = acpi_video_bus_get_one_device(dev, video); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Cant attach device")); continue; } - } return status; } @@ -1724,9 +1723,6 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) video = device->video; - down(&video->sem); - list_del(&device->entry); - up(&video->sem); acpi_video_device_remove_fs(device->dev); status = acpi_remove_notify_handler(device->dev->handle, @@ -1734,32 +1730,34 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) acpi_video_device_notify); backlight_device_unregister(device->backlight); video_output_unregister(device->output_dev); + return 0; } static int acpi_video_bus_put_devices(struct acpi_video_bus *video) { int status; - struct list_head *node, *next; + struct acpi_video_device *dev, *next; + mutex_lock(&video->device_list_lock); - list_for_each_safe(node, next, &video->video_device_list) { - struct acpi_video_device *data = - list_entry(node, struct acpi_video_device, entry); - if (!data) - continue; + list_for_each_entry_safe(dev, next, &video->video_device_list, entry) { - status = acpi_video_bus_put_one_device(data); + status = acpi_video_bus_put_one_device(dev); if (ACPI_FAILURE(status)) printk(KERN_WARNING PREFIX "hhuuhhuu bug in acpi video driver.\n"); - if (data->brightness) - kfree(data->brightness->levels); - kfree(data->brightness); - kfree(data); + if (dev->brightness) { + kfree(dev->brightness->levels); + kfree(dev->brightness); + } + list_del(&dev->entry); + kfree(dev); } + mutex_unlock(&video->device_list_lock); + return 0; } @@ -1782,9 +1780,6 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data) struct input_dev *input; int keycode; - - printk("video bus notify\n"); - if (!video) return; @@ -1897,14 +1892,10 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) static int instance; static int acpi_video_bus_add(struct acpi_device *device) { - int result = 0; - acpi_status status = 0; - struct acpi_video_bus *video = NULL; + acpi_status status; + struct acpi_video_bus *video; struct input_dev *input; - - - if (!device) - return -EINVAL; + int error; video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL); if (!video) @@ -1923,15 +1914,15 @@ static int acpi_video_bus_add(struct acpi_device *device) acpi_driver_data(device) = video; acpi_video_bus_find_cap(video); - result = acpi_video_bus_check(video); - if (result) - goto end; + error = acpi_video_bus_check(video); + if (error) + goto err_free_video; - result = acpi_video_bus_add_fs(device); - if (result) - goto end; + error = acpi_video_bus_add_fs(device); + if (error) + goto err_free_video; - init_MUTEX(&video->sem); + mutex_init(&video->device_list_lock); INIT_LIST_HEAD(&video->video_device_list); acpi_video_bus_get_devices(video, device); @@ -1943,16 +1934,15 @@ static int acpi_video_bus_add(struct acpi_device *device) if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error installing notify handler\n")); - acpi_video_bus_stop_devices(video); - acpi_video_bus_put_devices(video); - kfree(video->attached_array); - acpi_video_bus_remove_fs(device); - result = -ENODEV; - goto end; + error = -ENODEV; + goto err_stop_video; } - video->input = input = input_allocate_device(); + if (!input) { + error = -ENOMEM; + goto err_uninstall_notify; + } snprintf(video->phys, sizeof(video->phys), "%s/video/input0", acpi_device_hid(video->device)); @@ -1961,6 +1951,7 @@ static int acpi_video_bus_add(struct acpi_device *device) input->phys = video->phys; input->id.bustype = BUS_HOST; input->id.product = 0x06; + input->dev.parent = &device->dev; input->evbit[0] = BIT(EV_KEY); set_bit(KEY_SWITCHVIDEOMODE, input->keybit); set_bit(KEY_VIDEO_NEXT, input->keybit); @@ -1971,18 +1962,10 @@ static int acpi_video_bus_add(struct acpi_device *device) set_bit(KEY_BRIGHTNESS_ZERO, input->keybit); set_bit(KEY_DISPLAY_OFF, input->keybit); set_bit(KEY_UNKNOWN, input->keybit); - result = input_register_device(input); - if (result) { - acpi_remove_notify_handler(video->device->handle, - ACPI_DEVICE_NOTIFY, - acpi_video_bus_notify); - acpi_video_bus_stop_devices(video); - acpi_video_bus_put_devices(video); - kfree(video->attached_array); - acpi_video_bus_remove_fs(device); - goto end; - } + error = input_register_device(input); + if (error) + goto err_free_input_dev; printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), @@ -1990,11 +1973,23 @@ static int acpi_video_bus_add(struct acpi_device *device) video->flags.rom ? "yes" : "no", video->flags.post ? "yes" : "no"); - end: - if (result) - kfree(video); + return 0; + + err_free_input_dev: + input_free_device(input); + err_uninstall_notify: + acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, + acpi_video_bus_notify); + err_stop_video: + acpi_video_bus_stop_devices(video); + acpi_video_bus_put_devices(video); + kfree(video->attached_array); + acpi_video_bus_remove_fs(device); + err_free_video: + kfree(video); + acpi_driver_data(device) = NULL; - return result; + return error; } static int acpi_video_bus_remove(struct acpi_device *device, int type) diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index f08cca21702c..b538e1d22bf2 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -119,18 +119,19 @@ enum { PIIX_80C_SEC = (1 << 7) | (1 << 6), /* controller IDs */ - piix_pata_33 = 0, /* PIIX4 at 33Mhz */ - ich_pata_33 = 1, /* ICH up to UDMA 33 only */ - ich_pata_66 = 2, /* ICH up to 66 Mhz */ - ich_pata_100 = 3, /* ICH up to UDMA 100 */ - ich5_sata = 5, - ich6_sata = 6, - ich6_sata_ahci = 7, - ich6m_sata_ahci = 8, - ich8_sata_ahci = 9, - piix_pata_mwdma = 10, /* PIIX3 MWDMA only */ - tolapai_sata_ahci = 11, - ich9_2port_sata = 12, + piix_pata_mwdma = 0, /* PIIX3 MWDMA only */ + piix_pata_33, /* PIIX4 at 33Mhz */ + ich_pata_33, /* ICH up to UDMA 33 only */ + ich_pata_66, /* ICH up to 66 Mhz */ + ich_pata_100, /* ICH up to UDMA 100 */ + ich5_sata, + ich6_sata, + ich6_sata_ahci, + ich6m_sata_ahci, + ich8_sata_ahci, + ich8_2port_sata, + ich8m_apple_sata_ahci, /* locks up on second port enable */ + tolapai_sata_ahci, /* constants for mapping table */ P0 = 0, /* port 0 */ @@ -239,19 +240,21 @@ static const struct pci_device_id piix_pci_tbl[] = { /* SATA Controller 1 IDE (ICH8) */ { 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, /* SATA Controller 2 IDE (ICH8) */ - { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata }, + { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, /* Mobile SATA Controller IDE (ICH8M) */ { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, + /* Mobile SATA Controller IDE (ICH8M), Apple */ + { 0x8086, 0x2828, 0x106b, 0x00a0, 0, 0, ich8m_apple_sata_ahci }, /* SATA Controller IDE (ICH9) */ { 0x8086, 0x2920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, /* SATA Controller IDE (ICH9) */ - { 0x8086, 0x2921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata }, + { 0x8086, 0x2921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, /* SATA Controller IDE (ICH9) */ - { 0x8086, 0x2926, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata }, + { 0x8086, 0x2926, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, /* SATA Controller IDE (ICH9M) */ - { 0x8086, 0x2928, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata }, + { 0x8086, 0x2928, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, /* SATA Controller IDE (ICH9M) */ - { 0x8086, 0x292d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata }, + { 0x8086, 0x292d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, /* SATA Controller IDE (ICH9M) */ { 0x8086, 0x292e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, /* SATA Controller IDE (Tolapai) */ @@ -427,7 +430,7 @@ static const struct piix_map_db ich6m_map_db = { static const struct piix_map_db ich8_map_db = { .mask = 0x3, - .port_enable = 0x3, + .port_enable = 0xf, .map = { /* PM PS SM SS MAP */ { P0, P2, P1, P3 }, /* 00b (hardwired when in AHCI) */ @@ -437,7 +440,7 @@ static const struct piix_map_db ich8_map_db = { }, }; -static const struct piix_map_db tolapai_map_db = { +static const struct piix_map_db ich8_2port_map_db = { .mask = 0x3, .port_enable = 0x3, .map = { @@ -449,7 +452,19 @@ static const struct piix_map_db tolapai_map_db = { }, }; -static const struct piix_map_db ich9_2port_map_db = { +static const struct piix_map_db ich8m_apple_map_db = { + .mask = 0x3, + .port_enable = 0x1, + .map = { + /* PM PS SM SS MAP */ + { P0, NA, NA, NA }, /* 00b */ + { RV, RV, RV, RV }, + { P0, P2, IDE, IDE }, /* 10b */ + { RV, RV, RV, RV }, + }, +}; + +static const struct piix_map_db tolapai_map_db = { .mask = 0x3, .port_enable = 0x3, .map = { @@ -467,11 +482,21 @@ static const struct piix_map_db *piix_map_db_table[] = { [ich6_sata_ahci] = &ich6_map_db, [ich6m_sata_ahci] = &ich6m_map_db, [ich8_sata_ahci] = &ich8_map_db, + [ich8_2port_sata] = &ich8_2port_map_db, + [ich8m_apple_sata_ahci] = &ich8m_apple_map_db, [tolapai_sata_ahci] = &tolapai_map_db, - [ich9_2port_sata] = &ich9_2port_map_db, }; static struct ata_port_info piix_port_info[] = { + [piix_pata_mwdma] = /* PIIX3 MWDMA only */ + { + .sht = &piix_sht, + .flags = PIIX_PATA_FLAGS, + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ + .port_ops = &piix_pata_ops, + }, + [piix_pata_33] = /* PIIX4 at 33MHz */ { .sht = &piix_sht, @@ -565,13 +590,15 @@ static struct ata_port_info piix_port_info[] = { .port_ops = &piix_sata_ops, }, - [piix_pata_mwdma] = /* PIIX3 MWDMA only */ + [ich8_2port_sata] = { .sht = &piix_sht, - .flags = PIIX_PATA_FLAGS, + .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR | + PIIX_FLAG_AHCI, .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ - .port_ops = &piix_pata_ops, + .mwdma_mask = 0x07, /* mwdma0-2 */ + .udma_mask = ATA_UDMA6, + .port_ops = &piix_sata_ops, }, [tolapai_sata_ahci] = @@ -585,7 +612,7 @@ static struct ata_port_info piix_port_info[] = { .port_ops = &piix_sata_ops, }, - [ich9_2port_sata] = + [ich8m_apple_sata_ahci] = { .sht = &piix_sht, .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR | @@ -595,6 +622,7 @@ static struct ata_port_info piix_port_info[] = { .udma_mask = ATA_UDMA6, .port_ops = &piix_sata_ops, }, + }; static struct pci_bits piix_enable_bits[] = { @@ -939,6 +967,13 @@ static int piix_broken_suspend(void) }, }, { + .ident = "TECRA M3", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Tecra M3"), + }, + }, + { .ident = "TECRA M5", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), @@ -953,6 +988,20 @@ static int piix_broken_suspend(void) }, }, { + .ident = "TECRA A8", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "TECRA A8"), + }, + }, + { + .ident = "Satellite R25", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite R25"), + }, + }, + { .ident = "Satellite U200", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), @@ -960,6 +1009,20 @@ static int piix_broken_suspend(void) }, }, { + .ident = "Satellite U200", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE U200"), + }, + }, + { + .ident = "Satellite Pro U200", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE PRO U200"), + }, + }, + { .ident = "Satellite U205", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), @@ -967,6 +1030,13 @@ static int piix_broken_suspend(void) }, }, { + .ident = "SATELLITE U205", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE U205"), + }, + }, + { .ident = "Portege M500", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), @@ -1079,12 +1149,12 @@ static int piix_disable_ahci(struct pci_dev *pdev) if (!mmio) return -ENOMEM; - tmp = readl(mmio + AHCI_GLOBAL_CTL); + tmp = ioread32(mmio + AHCI_GLOBAL_CTL); if (tmp & AHCI_ENABLE) { tmp &= ~AHCI_ENABLE; - writel(tmp, mmio + AHCI_GLOBAL_CTL); + iowrite32(tmp, mmio + AHCI_GLOBAL_CTL); - tmp = readl(mmio + AHCI_GLOBAL_CTL); + tmp = ioread32(mmio + AHCI_GLOBAL_CTL); if (tmp & AHCI_ENABLE) rc = -EIO; } diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 08a52dd45fb6..545ea865ceb5 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -312,7 +312,7 @@ EXPORT_SYMBOL_GPL(ata_acpi_stm); * * RETURNS: * Number of taskfiles on success, 0 if _GTF doesn't exist or doesn't - * contain valid data. -errno on other errors. + * contain valid data. */ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf, void **ptr_to_free) @@ -339,7 +339,6 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf, ata_dev_printk(dev, KERN_WARNING, "_GTF evaluation failed (AE 0x%x)\n", status); - rc = -EIO; } goto out_free; } @@ -359,7 +358,6 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf, ata_dev_printk(dev, KERN_WARNING, "_GTF unexpected object type 0x%x\n", out_obj->type); - rc = -EINVAL; goto out_free; } @@ -367,7 +365,6 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf, ata_dev_printk(dev, KERN_WARNING, "unexpected _GTF length (%d)\n", out_obj->buffer.length); - rc = -EINVAL; goto out_free; } @@ -511,10 +508,7 @@ static int ata_acpi_exec_tfs(struct ata_device *dev) int gtf_count, i, rc; /* get taskfiles */ - rc = ata_dev_get_GTF(dev, >f, &ptr_to_free); - if (rc < 0) - return rc; - gtf_count = rc; + gtf_count = ata_dev_get_GTF(dev, >f, &ptr_to_free); /* execute them */ for (i = 0, rc = 0; i < gtf_count; i++) { diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index ec3ce120a517..b514a80f1370 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -30,6 +30,14 @@ * Hardware documentation available from http://www.t13.org/ and * http://www.sata-io.org/ * + * Standards documents from: + * http://www.t13.org (ATA standards, PCI DMA IDE spec) + * http://www.t10.org (SCSI MMC - for ATAPI MMC) + * http://www.sata-io.org (SATA) + * http://www.compactflash.org (CF) + * http://www.qic.org (QIC157 - Tape and DSC) + * http://www.ce-ata.org (CE-ATA: not supported) + * */ #include <linux/kernel.h> @@ -2307,8 +2315,10 @@ int ata_dev_configure(struct ata_device *dev) } if ((dev->class == ATA_DEV_ATAPI) && - (atapi_command_packet_set(id) == TYPE_TAPE)) + (atapi_command_packet_set(id) == TYPE_TAPE)) { dev->max_sectors = ATA_MAX_SECTORS_TAPE; + dev->horkage |= ATA_HORKAGE_STUCK_ERR; + } if (dev->horkage & ATA_HORKAGE_MAX_SEC_128) dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128, @@ -2581,81 +2591,6 @@ void sata_print_link_status(struct ata_link *link) } /** - * __sata_phy_reset - Wake/reset a low-level SATA PHY - * @ap: SATA port associated with target SATA PHY. - * - * This function issues commands to standard SATA Sxxx - * PHY registers, to wake up the phy (and device), and - * clear any reset condition. - * - * LOCKING: - * PCI/etc. bus probe sem. - * - */ -void __sata_phy_reset(struct ata_port *ap) -{ - struct ata_link *link = &ap->link; - unsigned long timeout = jiffies + (HZ * 5); - u32 sstatus; - - if (ap->flags & ATA_FLAG_SATA_RESET) { - /* issue phy wake/reset */ - sata_scr_write_flush(link, SCR_CONTROL, 0x301); - /* Couldn't find anything in SATA I/II specs, but - * AHCI-1.1 10.4.2 says at least 1 ms. */ - mdelay(1); - } - /* phy wake/clear reset */ - sata_scr_write_flush(link, SCR_CONTROL, 0x300); - - /* wait for phy to become ready, if necessary */ - do { - msleep(200); - sata_scr_read(link, SCR_STATUS, &sstatus); - if ((sstatus & 0xf) != 1) - break; - } while (time_before(jiffies, timeout)); - - /* print link status */ - sata_print_link_status(link); - - /* TODO: phy layer with polling, timeouts, etc. */ - if (!ata_link_offline(link)) - ata_port_probe(ap); - else - ata_port_disable(ap); - - if (ap->flags & ATA_FLAG_DISABLED) - return; - - if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { - ata_port_disable(ap); - return; - } - - ap->cbl = ATA_CBL_SATA; -} - -/** - * sata_phy_reset - Reset SATA bus. - * @ap: SATA port associated with target SATA PHY. - * - * This function resets the SATA bus, and then probes - * the bus for devices. - * - * LOCKING: - * PCI/etc. bus probe sem. - * - */ -void sata_phy_reset(struct ata_port *ap) -{ - __sata_phy_reset(ap); - if (ap->flags & ATA_FLAG_DISABLED) - return; - ata_bus_reset(ap); -} - -/** * ata_dev_pair - return other device on cable * @adev: device * @@ -3373,14 +3308,20 @@ void ata_wait_after_reset(struct ata_port *ap, unsigned long deadline) * to clear 0xff after reset. For example, HHD424020F7SV00 * iVDR needs >= 800ms while. Quantum GoVault needs even more * than that. + * + * Note that some PATA controllers (pata_ali) explode if + * status register is read more than once when there's no + * device attached. */ - while (1) { - u8 status = ata_chk_status(ap); + if (ap->flags & ATA_FLAG_SATA) { + while (1) { + u8 status = ata_chk_status(ap); - if (status != 0xff || time_after(jiffies, deadline)) - return; + if (status != 0xff || time_after(jiffies, deadline)) + return; - msleep(50); + msleep(50); + } } } @@ -4244,6 +4185,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { /* Devices which get the IVB wrong */ { "QUANTUM FIREBALLlct10 05", "A03.0900", ATA_HORKAGE_IVB, }, { "TSSTcorp CDDVDW SH-S202J", "SB00", ATA_HORKAGE_IVB, }, + { "TSSTcorp CDDVDW SH-S202J", "SB01", ATA_HORKAGE_IVB, }, + { "TSSTcorp CDDVDW SH-S202N", "SB00", ATA_HORKAGE_IVB, }, + { "TSSTcorp CDDVDW SH-S202N", "SB01", ATA_HORKAGE_IVB, }, /* End Marker */ { } @@ -5484,11 +5428,19 @@ fsm_start: * let the EH abort the command or reset the device. */ if (unlikely(status & (ATA_ERR | ATA_DF))) { - ata_port_printk(ap, KERN_WARNING, "DRQ=1 with device " - "error, dev_stat 0x%X\n", status); - qc->err_mask |= AC_ERR_HSM; - ap->hsm_task_state = HSM_ST_ERR; - goto fsm_start; + /* Some ATAPI tape drives forget to clear the ERR bit + * when doing the next command (mostly request sense). + * We ignore ERR here to workaround and proceed sending + * the CDB. + */ + if (!(qc->dev->horkage & ATA_HORKAGE_STUCK_ERR)) { + ata_port_printk(ap, KERN_WARNING, + "DRQ=1 with device error, " + "dev_stat 0x%X\n", status); + qc->err_mask |= AC_ERR_HSM; + ap->hsm_task_state = HSM_ST_ERR; + goto fsm_start; + } } /* Send the CDB (atapi) or the first data block (ata pio out). @@ -6821,19 +6773,6 @@ static void ata_host_release(struct device *gendev, void *res) if (!ap) continue; - if ((host->flags & ATA_HOST_STARTED) && ap->ops->port_stop) - ap->ops->port_stop(ap); - } - - if ((host->flags & ATA_HOST_STARTED) && host->ops->host_stop) - host->ops->host_stop(host); - - for (i = 0; i < host->n_ports; i++) { - struct ata_port *ap = host->ports[i]; - - if (!ap) - continue; - if (ap->scsi_host) scsi_host_put(ap->scsi_host); @@ -6960,6 +6899,24 @@ struct ata_host *ata_host_alloc_pinfo(struct device *dev, return host; } +static void ata_host_stop(struct device *gendev, void *res) +{ + struct ata_host *host = dev_get_drvdata(gendev); + int i; + + WARN_ON(!(host->flags & ATA_HOST_STARTED)); + + for (i = 0; i < host->n_ports; i++) { + struct ata_port *ap = host->ports[i]; + + if (ap->ops->port_stop) + ap->ops->port_stop(ap); + } + + if (host->ops->host_stop) + host->ops->host_stop(host); +} + /** * ata_host_start - start and freeze ports of an ATA host * @host: ATA host to start ports for @@ -6978,6 +6935,8 @@ struct ata_host *ata_host_alloc_pinfo(struct device *dev, */ int ata_host_start(struct ata_host *host) { + int have_stop = 0; + void *start_dr = NULL; int i, rc; if (host->flags & ATA_HOST_STARTED) @@ -6989,18 +6948,35 @@ int ata_host_start(struct ata_host *host) if (!host->ops && !ata_port_is_dummy(ap)) host->ops = ap->ops; + if (ap->ops->port_stop) + have_stop = 1; + } + + if (host->ops->host_stop) + have_stop = 1; + + if (have_stop) { + start_dr = devres_alloc(ata_host_stop, 0, GFP_KERNEL); + if (!start_dr) + return -ENOMEM; + } + + for (i = 0; i < host->n_ports; i++) { + struct ata_port *ap = host->ports[i]; + if (ap->ops->port_start) { rc = ap->ops->port_start(ap); if (rc) { - ata_port_printk(ap, KERN_ERR, "failed to " - "start port (errno=%d)\n", rc); + if (rc != -ENODEV) + dev_printk(KERN_ERR, host->dev, "failed to start port %d (errno=%d)\n", i, rc); goto err_out; } } - ata_eh_freeze_port(ap); } + if (start_dr) + devres_add(host->dev, start_dr); host->flags |= ATA_HOST_STARTED; return 0; @@ -7011,6 +6987,7 @@ int ata_host_start(struct ata_host *host) if (ap->ops->port_stop) ap->ops->port_stop(ap); } + devres_free(start_dr); return rc; } @@ -7178,6 +7155,10 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) * request IRQ and register it. This helper takes necessasry * arguments and performs the three steps in one go. * + * An invalid IRQ skips the IRQ registration and expects the host to + * have set polling mode on the port. In this case, @irq_handler + * should be NULL. + * * LOCKING: * Inherited from calling layer (may sleep). * @@ -7194,6 +7175,12 @@ int ata_host_activate(struct ata_host *host, int irq, if (rc) return rc; + /* Special case for polling mode */ + if (!irq) { + WARN_ON(irq_handler); + return ata_host_register(host, sht); + } + rc = devm_request_irq(host->dev, irq, irq_handler, irq_flags, dev_driver_string(host->dev), host); if (rc) @@ -7611,8 +7598,6 @@ EXPORT_SYMBOL_GPL(ata_dev_disable); EXPORT_SYMBOL_GPL(sata_set_spd); EXPORT_SYMBOL_GPL(sata_link_debounce); EXPORT_SYMBOL_GPL(sata_link_resume); -EXPORT_SYMBOL_GPL(sata_phy_reset); -EXPORT_SYMBOL_GPL(__sata_phy_reset); EXPORT_SYMBOL_GPL(ata_bus_reset); EXPORT_SYMBOL_GPL(ata_std_prereset); EXPORT_SYMBOL_GPL(ata_std_softreset); @@ -7683,7 +7668,6 @@ EXPORT_SYMBOL_GPL(ata_port_desc); #ifdef CONFIG_PCI EXPORT_SYMBOL_GPL(ata_port_pbar_desc); #endif /* CONFIG_PCI */ -EXPORT_SYMBOL_GPL(ata_eng_timeout); EXPORT_SYMBOL_GPL(ata_port_schedule_eh); EXPORT_SYMBOL_GPL(ata_link_abort); EXPORT_SYMBOL_GPL(ata_port_abort); diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index ed8813b222a0..e6605f038647 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -559,101 +559,6 @@ void ata_port_wait_eh(struct ata_port *ap) } } -/** - * ata_qc_timeout - Handle timeout of queued command - * @qc: Command that timed out - * - * Some part of the kernel (currently, only the SCSI layer) - * has noticed that the active command on port @ap has not - * completed after a specified length of time. Handle this - * condition by disabling DMA (if necessary) and completing - * transactions, with error if necessary. - * - * This also handles the case of the "lost interrupt", where - * for some reason (possibly hardware bug, possibly driver bug) - * an interrupt was not delivered to the driver, even though the - * transaction completed successfully. - * - * TODO: kill this function once old EH is gone. - * - * LOCKING: - * Inherited from SCSI layer (none, can sleep) - */ -static void ata_qc_timeout(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - u8 host_stat = 0, drv_stat; - unsigned long flags; - - DPRINTK("ENTER\n"); - - ap->hsm_task_state = HSM_ST_IDLE; - - spin_lock_irqsave(ap->lock, flags); - - switch (qc->tf.protocol) { - - case ATA_PROT_DMA: - case ATA_PROT_ATAPI_DMA: - host_stat = ap->ops->bmdma_status(ap); - - /* before we do anything else, clear DMA-Start bit */ - ap->ops->bmdma_stop(qc); - - /* fall through */ - - default: - ata_altstatus(ap); - drv_stat = ata_chk_status(ap); - - /* ack bmdma irq events */ - ap->ops->irq_clear(ap); - - ata_dev_printk(qc->dev, KERN_ERR, "command 0x%x timeout, " - "stat 0x%x host_stat 0x%x\n", - qc->tf.command, drv_stat, host_stat); - - /* complete taskfile transaction */ - qc->err_mask |= AC_ERR_TIMEOUT; - break; - } - - spin_unlock_irqrestore(ap->lock, flags); - - ata_eh_qc_complete(qc); - - DPRINTK("EXIT\n"); -} - -/** - * ata_eng_timeout - Handle timeout of queued command - * @ap: Port on which timed-out command is active - * - * Some part of the kernel (currently, only the SCSI layer) - * has noticed that the active command on port @ap has not - * completed after a specified length of time. Handle this - * condition by disabling DMA (if necessary) and completing - * transactions, with error if necessary. - * - * This also handles the case of the "lost interrupt", where - * for some reason (possibly hardware bug, possibly driver bug) - * an interrupt was not delivered to the driver, even though the - * transaction completed successfully. - * - * TODO: kill this function once old EH is gone. - * - * LOCKING: - * Inherited from SCSI layer (none, can sleep) - */ -void ata_eng_timeout(struct ata_port *ap) -{ - DPRINTK("ENTER\n"); - - ata_qc_timeout(ata_qc_from_tag(ap, ap->link.active_tag)); - - DPRINTK("EXIT\n"); -} - static int ata_eh_nr_in_flight(struct ata_port *ap) { unsigned int tag; @@ -1945,30 +1850,54 @@ static void ata_eh_link_report(struct ata_link *link) ehc->i.serror & SERR_DEV_XCHG ? "DevExch " : ""); for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { - static const char *dma_str[] = { - [DMA_BIDIRECTIONAL] = "bidi", - [DMA_TO_DEVICE] = "out", - [DMA_FROM_DEVICE] = "in", - [DMA_NONE] = "", - }; struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); struct ata_taskfile *cmd = &qc->tf, *res = &qc->result_tf; + const u8 *cdb = qc->cdb; + char data_buf[20] = ""; + char cdb_buf[70] = ""; if (!(qc->flags & ATA_QCFLAG_FAILED) || qc->dev->link != link || !qc->err_mask) continue; + if (qc->dma_dir != DMA_NONE) { + static const char *dma_str[] = { + [DMA_BIDIRECTIONAL] = "bidi", + [DMA_TO_DEVICE] = "out", + [DMA_FROM_DEVICE] = "in", + }; + static const char *prot_str[] = { + [ATA_PROT_PIO] = "pio", + [ATA_PROT_DMA] = "dma", + [ATA_PROT_NCQ] = "ncq", + [ATA_PROT_ATAPI] = "pio", + [ATA_PROT_ATAPI_DMA] = "dma", + }; + + snprintf(data_buf, sizeof(data_buf), " %s %u %s", + prot_str[qc->tf.protocol], qc->nbytes, + dma_str[qc->dma_dir]); + } + + if (is_atapi_taskfile(&qc->tf)) + snprintf(cdb_buf, sizeof(cdb_buf), + "cdb %02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x\n ", + cdb[0], cdb[1], cdb[2], cdb[3], + cdb[4], cdb[5], cdb[6], cdb[7], + cdb[8], cdb[9], cdb[10], cdb[11], + cdb[12], cdb[13], cdb[14], cdb[15]); + ata_dev_printk(qc->dev, KERN_ERR, "cmd %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x " - "tag %d cdb 0x%x data %u %s\n " + "tag %d%s\n %s" "res %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x " "Emask 0x%x (%s)%s\n", cmd->command, cmd->feature, cmd->nsect, cmd->lbal, cmd->lbam, cmd->lbah, cmd->hob_feature, cmd->hob_nsect, cmd->hob_lbal, cmd->hob_lbam, cmd->hob_lbah, - cmd->device, qc->tag, qc->cdb[0], qc->nbytes, - dma_str[qc->dma_dir], + cmd->device, qc->tag, data_buf, cdb_buf, res->command, res->feature, res->nsect, res->lbal, res->lbam, res->lbah, res->hob_feature, res->hob_nsect, diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 94144ed50a6b..a883bb03d4c7 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -2485,11 +2485,40 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc) if (!using_pio && ata_check_atapi_dma(qc)) using_pio = 1; - /* Some controller variants snoop this value for Packet transfers - to do state machine and FIFO management. Thus we want to set it - properly, and for DMA where it is effectively meaningless */ + /* Some controller variants snoop this value for Packet + * transfers to do state machine and FIFO management. Thus we + * want to set it properly, and for DMA where it is + * effectively meaningless. + */ nbytes = min(qc->nbytes, (unsigned int)63 * 1024); + /* Most ATAPI devices which honor transfer chunk size don't + * behave according to the spec when odd chunk size which + * matches the transfer length is specified. If the number of + * bytes to transfer is 2n+1. According to the spec, what + * should happen is to indicate that 2n+1 is going to be + * transferred and transfer 2n+2 bytes where the last byte is + * padding. + * + * In practice, this doesn't happen. ATAPI devices first + * indicate and transfer 2n bytes and then indicate and + * transfer 2 bytes where the last byte is padding. + * + * This inconsistency confuses several controllers which + * perform PIO using DMA such as Intel AHCIs and sil3124/32. + * These controllers use actual number of transferred bytes to + * update DMA poitner and transfer of 4n+2 bytes make those + * controller push DMA pointer by 4n+4 bytes because SATA data + * FISes are aligned to 4 bytes. This causes data corruption + * and buffer overrun. + * + * Always setting nbytes to even number solves this problem + * because then ATAPI devices don't have to split data at 2n + * boundaries. + */ + if (nbytes & 0x1) + nbytes++; + qc->tf.lbam = (nbytes & 0xFF); qc->tf.lbah = (nbytes >> 8); @@ -2869,7 +2898,8 @@ static inline int __ata_scsi_queuecmd(struct scsi_cmnd *scmd, xlat_func = NULL; if (likely((scsi_op != ATA_16) || !atapi_passthru16)) { /* relay SCSI command to ATAPI device */ - if (unlikely(scmd->cmd_len > dev->cdb_len)) + int len = COMMAND_SIZE(scsi_op); + if (unlikely(len > scmd->cmd_len || len > dev->cdb_len)) goto bad_cdb_len; xlat_func = atapi_xlat; diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c index 364534e7aff4..8caf9afc8b90 100644 --- a/drivers/ata/pata_ali.c +++ b/drivers/ata/pata_ali.c @@ -63,6 +63,9 @@ static int ali_cable_override(struct pci_dev *pdev) /* Fujitsu P2000 */ if (pdev->subsystem_vendor == 0x10CF && pdev->subsystem_device == 0x10AF) return 1; + /* Mitac 8317 (Winbook-A) and relatives */ + if (pdev->subsystem_vendor == 0x1071 && pdev->subsystem_device == 0x8317) + return 1; /* Systems by DMI */ if (dmi_check_system(cable_dmi_table)) return 1; @@ -282,6 +285,21 @@ static void ali_lock_sectors(struct ata_device *adev) adev->max_sectors = 255; } +/** + * ali_check_atapi_dma - DMA check for most ALi controllers + * @adev: Device + * + * Called to decide whether commands should be sent by DMA or PIO + */ + +static int ali_check_atapi_dma(struct ata_queued_cmd *qc) +{ + /* If its not a media command, its not worth it */ + if (qc->nbytes < 2048) + return -EOPNOTSUPP; + return 0; +} + static struct scsi_host_template ali_sht = { .module = THIS_MODULE, .name = DRV_NAME, @@ -378,6 +396,7 @@ static struct ata_port_operations ali_c2_port_ops = { .mode_filter = ata_pci_default_filter, .tf_load = ata_tf_load, .tf_read = ata_tf_read, + .check_atapi_dma = ali_check_atapi_dma, .check_status = ata_check_status, .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, @@ -415,6 +434,7 @@ static struct ata_port_operations ali_c5_port_ops = { .mode_filter = ata_pci_default_filter, .tf_load = ata_tf_load, .tf_read = ata_tf_read, + .check_atapi_dma = ali_check_atapi_dma, .check_status = ata_check_status, .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, diff --git a/drivers/ata/pata_at32.c b/drivers/ata/pata_at32.c index bb250a48e27c..67e574de31e8 100644 --- a/drivers/ata/pata_at32.c +++ b/drivers/ata/pata_at32.c @@ -28,7 +28,7 @@ #include <asm/arch/smc.h> #define DRV_NAME "pata_at32" -#define DRV_VERSION "0.0.2" +#define DRV_VERSION "0.0.3" /* * CompactFlash controller memory layout relative to the base address: @@ -64,6 +64,8 @@ * Mode 2 | 8.3 | 240 ns | 0x07 * Mode 3 | 11.1 | 180 ns | 0x0f * Mode 4 | 16.7 | 120 ns | 0x1f + * + * Alter PIO_MASK below according to table to set maximal PIO mode. */ #define PIO_MASK (0x1f) @@ -85,36 +87,40 @@ struct at32_ide_info { */ static int pata_at32_setup_timing(struct device *dev, struct at32_ide_info *info, - const struct ata_timing *timing) + const struct ata_timing *ata) { - /* These two values are found through testing */ - const int min_recover = 25; - const int ncs_hold = 15; - struct smc_config *smc = &info->smc; + struct smc_timing timing; int active; int recover; + memset(&timing, 0, sizeof(struct smc_timing)); + /* Total cycle time */ - smc->read_cycle = timing->cyc8b; + timing.read_cycle = ata->cyc8b; /* DIOR <= CFIOR timings */ - smc->nrd_setup = timing->setup; - smc->nrd_pulse = timing->act8b; + timing.nrd_setup = ata->setup; + timing.nrd_pulse = ata->act8b; + timing.nrd_recover = ata->rec8b; + + /* Convert nanosecond timing to clock cycles */ + smc_set_timing(smc, &timing); - /* Compute recover, extend total cycle if needed */ - active = smc->nrd_setup + smc->nrd_pulse; + /* Add one extra cycle setup due to signal ring */ + smc->nrd_setup = smc->nrd_setup + 1; + + active = smc->nrd_setup + smc->nrd_pulse; recover = smc->read_cycle - active; - if (recover < min_recover) { - smc->read_cycle = active + min_recover; - recover = min_recover; - } + /* Need at least two cycles recovery */ + if (recover < 2) + smc->read_cycle = active + 2; /* (CS0, CS1, DIR, OE) <= (CFCE1, CFCE2, CFRNW, NCSX) timings */ - smc->ncs_read_setup = 0; - smc->ncs_read_pulse = active + ncs_hold; + smc->ncs_read_setup = 1; + smc->ncs_read_pulse = smc->read_cycle - 2; /* Write timings same as read timings */ smc->write_cycle = smc->read_cycle; @@ -123,11 +129,13 @@ static int pata_at32_setup_timing(struct device *dev, smc->ncs_write_setup = smc->ncs_read_setup; smc->ncs_write_pulse = smc->ncs_read_pulse; - /* Do some debugging output */ - dev_dbg(dev, "SMC: C=%d S=%d P=%d R=%d NCSS=%d NCSP=%d NCSR=%d\n", + /* Do some debugging output of ATA and SMC timings */ + dev_dbg(dev, "ATA: C=%d S=%d P=%d R=%d\n", + ata->cyc8b, ata->setup, ata->act8b, ata->rec8b); + + dev_dbg(dev, "SMC: C=%d S=%d P=%d NS=%d NP=%d\n", smc->read_cycle, smc->nrd_setup, smc->nrd_pulse, - recover, smc->ncs_read_setup, smc->ncs_read_pulse, - smc->read_cycle - smc->ncs_read_pulse); + smc->ncs_read_setup, smc->ncs_read_pulse); /* Finally, configure the SMC */ return smc_set_configuration(info->cs, smc); @@ -182,7 +190,6 @@ static struct scsi_host_template at32_sht = { }; static struct ata_port_operations at32_port_ops = { - .port_disable = ata_port_disable, .set_piomode = pata_at32_set_piomode, .tf_load = ata_tf_load, .tf_read = ata_tf_read, @@ -203,7 +210,6 @@ static struct ata_port_operations at32_port_ops = { .irq_clear = pata_at32_irq_clear, .irq_on = ata_irq_on, - .irq_ack = ata_irq_ack, .port_start = ata_sff_port_start, }; @@ -223,8 +229,7 @@ static int __init pata_at32_init_one(struct device *dev, /* Setup ATA bindings */ ap->ops = &at32_port_ops; ap->pio_mask = PIO_MASK; - ap->flags = ATA_FLAG_MMIO | ATA_FLAG_SLAVE_POSS - | ATA_FLAG_PIO_POLLING; + ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_SLAVE_POSS; /* * Since all 8-bit taskfile transfers has to go on the lower @@ -357,12 +362,12 @@ static int __init pata_at32_probe(struct platform_device *pdev) info->smc.tdf_mode = 0; /* TDF optimization disabled */ info->smc.tdf_cycles = 0; /* No TDF wait cycles */ - /* Setup ATA timing */ + /* Setup SMC to ATA timing */ ret = pata_at32_setup_timing(dev, info, &initial_timing); if (ret) goto err_setup_timing; - /* Setup ATA addresses */ + /* Map ATA address space */ ret = -ENOMEM; info->ide_addr = devm_ioremap(dev, info->res_ide.start, 16); info->alt_addr = devm_ioremap(dev, info->res_alt.start, 16); @@ -373,7 +378,7 @@ static int __init pata_at32_probe(struct platform_device *pdev) pata_at32_debug_bus(dev, info); #endif - /* Register ATA device */ + /* Setup and register ATA device */ ret = pata_at32_init_one(dev, info); if (ret) goto err_ata_device; diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c index b5e38426b815..088a41f4e656 100644 --- a/drivers/ata/pata_bf54x.c +++ b/drivers/ata/pata_bf54x.c @@ -1145,13 +1145,13 @@ static unsigned char bfin_bmdma_status(struct ata_port *ap) unsigned short int_status = ATAPI_GET_INT_STATUS(base); if (ATAPI_GET_STATUS(base) & (MULTI_XFER_ON|ULTRA_XFER_ON)) { - host_stat = ATA_DMA_ACTIVE; + host_stat |= ATA_DMA_ACTIVE; } if (int_status & (MULTI_DONE_INT|UDMAIN_DONE_INT|UDMAOUT_DONE_INT)) { - host_stat = ATA_DMA_INTR; + host_stat |= ATA_DMA_INTR; } if (int_status & (MULTI_TERM_INT|UDMAIN_TERM_INT|UDMAOUT_TERM_INT)) { - host_stat = ATA_DMA_ERR; + host_stat |= ATA_DMA_ERR; } return host_stat; @@ -1489,6 +1489,8 @@ static int __devinit bfin_atapi_probe(struct platform_device *pdev) int board_idx = 0; struct resource *res; struct ata_host *host; + unsigned int fsclk = get_sclk(); + int udma_mode = 5; const struct ata_port_info *ppi[] = { &bfin_port_info[board_idx], NULL }; @@ -1507,6 +1509,11 @@ static int __devinit bfin_atapi_probe(struct platform_device *pdev) if (res == NULL) return -EINVAL; + while (bfin_port_info[board_idx].udma_mask>0 && udma_fsclk[udma_mode] > fsclk) { + udma_mode--; + bfin_port_info[board_idx].udma_mask >>= 1; + } + /* * Now that that's out of the way, wire up the port.. */ diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c index 3816b8605e0d..46dc70e0dee7 100644 --- a/drivers/ata/pata_hpt37x.c +++ b/drivers/ata/pata_hpt37x.c @@ -329,7 +329,7 @@ static int hpt37x_pre_reset(struct ata_link *link, unsigned long deadline) /* Restore state */ pci_write_config_byte(pdev, 0x5B, scr2); - if (ata66 & (1 << ap->port_no)) + if (ata66 & (2 >> ap->port_no)) ap->cbl = ATA_CBL_PATA40; else ap->cbl = ATA_CBL_PATA80; diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c index 88ab0e1d353f..4320e7986321 100644 --- a/drivers/ata/pata_isapnp.c +++ b/drivers/ata/pata_isapnp.c @@ -75,13 +75,16 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev struct ata_host *host; struct ata_port *ap; void __iomem *cmd_addr, *ctl_addr; + int irq = 0; + irq_handler_t handler = NULL; if (pnp_port_valid(idev, 0) == 0) return -ENODEV; - /* FIXME: Should selected polled PIO here not fail */ - if (pnp_irq_valid(idev, 0) == 0) - return -ENODEV; + if (pnp_irq_valid(idev, 0)) { + irq = pnp_irq(idev, 0); + handler = ata_interrupt; + } /* allocate host */ host = ata_host_alloc(&idev->dev, 1); @@ -115,7 +118,7 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev (unsigned long long)pnp_port_start(idev, 1)); /* activate */ - return ata_host_activate(host, pnp_irq(idev, 0), ata_interrupt, 0, + return ata_host_activate(host, irq, handler, 0, &isapnp_sht); } diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c index 225a7223a726..5b8174d94067 100644 --- a/drivers/ata/pata_jmicron.c +++ b/drivers/ata/pata_jmicron.c @@ -80,11 +80,10 @@ static int jmicron_pre_reset(struct ata_link *link, unsigned long deadline) * actually do our cable checking etc. Thankfully we don't need * to do the plumbing for other cases. */ - switch (port_map[port]) - { + switch (port_map[port]) { case PORT_PATA0: - if (control & (1 << 5)) - return 0; + if ((control & (1 << 5)) == 0) + return -ENOENT; if (control & (1 << 3)) /* 40/80 pin primary */ ap->cbl = ATA_CBL_PATA40; else @@ -93,7 +92,7 @@ static int jmicron_pre_reset(struct ata_link *link, unsigned long deadline) case PORT_PATA1: /* Bit 21 is set if the port is enabled */ if ((control5 & (1 << 21)) == 0) - return 0; + return -ENOENT; if (control5 & (1 << 19)) /* 40/80 pin secondary */ ap->cbl = ATA_CBL_PATA40; else diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c index fc72a965643d..ac03a90a6168 100644 --- a/drivers/ata/pata_platform.c +++ b/drivers/ata/pata_platform.c @@ -1,7 +1,7 @@ /* * Generic platform device PATA driver * - * Copyright (C) 2006 Paul Mundt + * Copyright (C) 2006 - 2007 Paul Mundt * * Based on pata_pcmcia: * @@ -22,7 +22,7 @@ #include <linux/pata_platform.h> #define DRV_NAME "pata_platform" -#define DRV_VERSION "1.1" +#define DRV_VERSION "1.2" static int pio_mask = 1; @@ -120,15 +120,20 @@ static void pata_platform_setup_port(struct ata_ioports *ioaddr, * Register a platform bus IDE interface. Such interfaces are PIO and we * assume do not support IRQ sharing. * - * Platform devices are expected to contain 3 resources per port: + * Platform devices are expected to contain at least 2 resources per port: * * - I/O Base (IORESOURCE_IO or IORESOURCE_MEM) * - CTL Base (IORESOURCE_IO or IORESOURCE_MEM) + * + * and optionally: + * * - IRQ (IORESOURCE_IRQ) * * If the base resources are both mem types, the ioremap() is handled * here. For IORESOURCE_IO, it's assumed that there's no remapping * necessary. + * + * If no IRQ resource is present, PIO polling mode is used instead. */ static int __devinit pata_platform_probe(struct platform_device *pdev) { @@ -137,11 +142,12 @@ static int __devinit pata_platform_probe(struct platform_device *pdev) struct ata_port *ap; struct pata_platform_info *pp_info; unsigned int mmio; + int irq; /* * Simple resource validation .. */ - if (unlikely(pdev->num_resources != 3)) { + if ((pdev->num_resources != 3) && (pdev->num_resources != 2)) { dev_err(&pdev->dev, "invalid number of resources\n"); return -EINVAL; } @@ -173,6 +179,13 @@ static int __devinit pata_platform_probe(struct platform_device *pdev) (ctl_res->flags == IORESOURCE_MEM)); /* + * And the IRQ + */ + irq = platform_get_irq(pdev, 0); + if (irq < 0) + irq = 0; /* no irq */ + + /* * Now that that's out of the way, wire up the port.. */ host = ata_host_alloc(&pdev->dev, 1); @@ -185,6 +198,14 @@ static int __devinit pata_platform_probe(struct platform_device *pdev) ap->flags |= ATA_FLAG_SLAVE_POSS; /* + * Use polling mode if there's no IRQ + */ + if (!irq) { + ap->flags |= ATA_FLAG_PIO_POLLING; + ata_port_desc(ap, "no IRQ, using PIO polling"); + } + + /* * Handle the MMIO case */ if (mmio) { @@ -213,9 +234,9 @@ static int __devinit pata_platform_probe(struct platform_device *pdev) (unsigned long long)ctl_res->start); /* activate */ - return ata_host_activate(host, platform_get_irq(pdev, 0), - ata_interrupt, pp_info ? pp_info->irq_flags - : 0, &pata_platform_sht); + return ata_host_activate(host, irq, irq ? ata_interrupt : NULL, + pp_info ? pp_info->irq_flags : 0, + &pata_platform_sht); } /** diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c index 5c1e9cb59ecb..503245a1eafa 100644 --- a/drivers/ata/pata_sil680.c +++ b/drivers/ata/pata_sil680.c @@ -33,7 +33,7 @@ #include <linux/libata.h> #define DRV_NAME "pata_sil680" -#define DRV_VERSION "0.4.7" +#define DRV_VERSION "0.4.8" #define SIL680_MMIO_BAR 5 @@ -94,34 +94,6 @@ static int sil680_cable_detect(struct ata_port *ap) { } /** - * sil680_bus_reset - reset the SIL680 bus - * @link: ATA link to reset - * @deadline: deadline jiffies for the operation - * - * Perform the SIL680 housekeeping when doing an ATA bus reset - */ - -static int sil680_bus_reset(struct ata_link *link, unsigned int *classes, - unsigned long deadline) -{ - struct ata_port *ap = link->ap; - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - unsigned long addr = sil680_selreg(ap, 0); - u8 reset; - - pci_read_config_byte(pdev, addr, &reset); - pci_write_config_byte(pdev, addr, reset | 0x03); - udelay(25); - pci_write_config_byte(pdev, addr, reset); - return ata_std_softreset(link, classes, deadline); -} - -static void sil680_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, ata_std_prereset, sil680_bus_reset, NULL, ata_std_postreset); -} - -/** * sil680_set_piomode - set initial PIO mode data * @ap: ATA interface * @adev: ATA device @@ -249,7 +221,7 @@ static struct ata_port_operations sil680_port_ops = { .freeze = ata_bmdma_freeze, .thaw = ata_bmdma_thaw, - .error_handler = sil680_error_handler, + .error_handler = ata_bmdma_error_handler, .post_internal_cmd = ata_bmdma_post_internal_cmd, .cable_detect = sil680_cable_detect, diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c index 3b5be77e861c..87546d9f1ca0 100644 --- a/drivers/ata/pata_sis.c +++ b/drivers/ata/pata_sis.c @@ -55,6 +55,7 @@ static const struct sis_laptop sis_laptop[] = { /* devid, subvendor, subdev */ { 0x5513, 0x1043, 0x1107 }, /* ASUS A6K */ { 0x5513, 0x1734, 0x105F }, /* FSC Amilo A1630 */ + { 0x5513, 0x1071, 0x8640 }, /* EasyNote K5305 */ /* end marker */ { 0, } }; diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index a43f64d2775b..8d864e5e97ed 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -164,10 +164,14 @@ enum { MV_PCI_ERR_ATTRIBUTE = 0x1d48, MV_PCI_ERR_COMMAND = 0x1d50, - PCI_IRQ_CAUSE_OFS = 0x1d58, - PCI_IRQ_MASK_OFS = 0x1d5c, + PCI_IRQ_CAUSE_OFS = 0x1d58, + PCI_IRQ_MASK_OFS = 0x1d5c, PCI_UNMASK_ALL_IRQS = 0x7fffff, /* bits 22-0 */ + PCIE_IRQ_CAUSE_OFS = 0x1900, + PCIE_IRQ_MASK_OFS = 0x1910, + PCIE_UNMASK_ALL_IRQS = 0x70a, /* assorted bits */ + HC_MAIN_IRQ_CAUSE_OFS = 0x1d60, HC_MAIN_IRQ_MASK_OFS = 0x1d64, PORT0_ERR = (1 << 0), /* shift by port # */ @@ -303,6 +307,7 @@ enum { MV_HP_GEN_I = (1 << 6), /* Generation I: 50xx */ MV_HP_GEN_II = (1 << 7), /* Generation II: 60xx */ MV_HP_GEN_IIE = (1 << 8), /* Generation IIE: 6042/7042 */ + MV_HP_PCIE = (1 << 9), /* PCIe bus/regs: 7042 */ /* Port private flags (pp_flags) */ MV_PP_FLAG_EDMA_EN = (1 << 0), /* is EDMA engine enabled? */ @@ -388,7 +393,15 @@ struct mv_port_signal { u32 pre; }; -struct mv_host_priv; +struct mv_host_priv { + u32 hp_flags; + struct mv_port_signal signal[8]; + const struct mv_hw_ops *ops; + u32 irq_cause_ofs; + u32 irq_mask_ofs; + u32 unmask_all_irqs; +}; + struct mv_hw_ops { void (*phy_errata)(struct mv_host_priv *hpriv, void __iomem *mmio, unsigned int port); @@ -401,12 +414,6 @@ struct mv_hw_ops { void (*reset_bus)(struct pci_dev *pdev, void __iomem *mmio); }; -struct mv_host_priv { - u32 hp_flags; - struct mv_port_signal signal[8]; - const struct mv_hw_ops *ops; -}; - static void mv_irq_clear(struct ata_port *ap); static int mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val); static int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val); @@ -631,11 +638,13 @@ static const struct pci_device_id mv_pci_tbl[] = { /* Adaptec 1430SA */ { PCI_VDEVICE(ADAPTEC2, 0x0243), chip_7042 }, - { PCI_VDEVICE(TTI, 0x2310), chip_7042 }, - - /* add Marvell 7042 support */ + /* Marvell 7042 support */ { PCI_VDEVICE(MARVELL, 0x7042), chip_7042 }, + /* Highpoint RocketRAID PCIe series */ + { PCI_VDEVICE(TTI, 0x2300), chip_7042 }, + { PCI_VDEVICE(TTI, 0x2310), chip_7042 }, + { } /* terminate list */ }; @@ -1648,13 +1657,14 @@ static void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc) static void mv_pci_error(struct ata_host *host, void __iomem *mmio) { + struct mv_host_priv *hpriv = host->private_data; struct ata_port *ap; struct ata_queued_cmd *qc; struct ata_eh_info *ehi; unsigned int i, err_mask, printed = 0; u32 err_cause; - err_cause = readl(mmio + PCI_IRQ_CAUSE_OFS); + err_cause = readl(mmio + hpriv->irq_cause_ofs); dev_printk(KERN_ERR, host->dev, "PCI ERROR; PCI IRQ cause=0x%08x\n", err_cause); @@ -1662,7 +1672,7 @@ static void mv_pci_error(struct ata_host *host, void __iomem *mmio) DPRINTK("All regs @ PCI error\n"); mv_dump_all_regs(mmio, -1, to_pci_dev(host->dev)); - writelfl(0, mmio + PCI_IRQ_CAUSE_OFS); + writelfl(0, mmio + hpriv->irq_cause_ofs); for (i = 0; i < host->n_ports; i++) { ap = host->ports[i]; @@ -1926,6 +1936,8 @@ static int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, #define ZERO(reg) writel(0, mmio + (reg)) static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio) { + struct ata_host *host = dev_get_drvdata(&pdev->dev); + struct mv_host_priv *hpriv = host->private_data; u32 tmp; tmp = readl(mmio + MV_PCI_MODE); @@ -1937,8 +1949,8 @@ static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio) writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT); ZERO(HC_MAIN_IRQ_MASK_OFS); ZERO(MV_PCI_SERR_MASK); - ZERO(PCI_IRQ_CAUSE_OFS); - ZERO(PCI_IRQ_MASK_OFS); + ZERO(hpriv->irq_cause_ofs); + ZERO(hpriv->irq_mask_ofs); ZERO(MV_PCI_ERR_LOW_ADDRESS); ZERO(MV_PCI_ERR_HIGH_ADDRESS); ZERO(MV_PCI_ERR_ATTRIBUTE); @@ -2170,7 +2182,7 @@ static void mv_phy_reset(struct ata_port *ap, unsigned int *class, mv_scr_read(ap, SCR_ERROR, &serror); mv_scr_read(ap, SCR_CONTROL, &scontrol); DPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x " - "SCtrl 0x%08x\n", status, serror, scontrol); + "SCtrl 0x%08x\n", sstatus, serror, scontrol); } #endif @@ -2490,6 +2502,7 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx) break; case chip_7042: + hp_flags |= MV_HP_PCIE; case chip_6042: hpriv->ops = &mv6xxx_ops; hp_flags |= MV_HP_GEN_IIE; @@ -2516,6 +2529,15 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx) } hpriv->hp_flags = hp_flags; + if (hp_flags & MV_HP_PCIE) { + hpriv->irq_cause_ofs = PCIE_IRQ_CAUSE_OFS; + hpriv->irq_mask_ofs = PCIE_IRQ_MASK_OFS; + hpriv->unmask_all_irqs = PCIE_UNMASK_ALL_IRQS; + } else { + hpriv->irq_cause_ofs = PCI_IRQ_CAUSE_OFS; + hpriv->irq_mask_ofs = PCI_IRQ_MASK_OFS; + hpriv->unmask_all_irqs = PCI_UNMASK_ALL_IRQS; + } return 0; } @@ -2595,10 +2617,10 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx) } /* Clear any currently outstanding host interrupt conditions */ - writelfl(0, mmio + PCI_IRQ_CAUSE_OFS); + writelfl(0, mmio + hpriv->irq_cause_ofs); /* and unmask interrupt generation for host regs */ - writelfl(PCI_UNMASK_ALL_IRQS, mmio + PCI_IRQ_MASK_OFS); + writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs); if (IS_GEN_I(hpriv)) writelfl(~HC_MAIN_MASKED_IRQS_5, mmio + HC_MAIN_IRQ_MASK_OFS); @@ -2609,8 +2631,8 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx) "PCI int cause/mask=0x%08x/0x%08x\n", readl(mmio + HC_MAIN_IRQ_CAUSE_OFS), readl(mmio + HC_MAIN_IRQ_MASK_OFS), - readl(mmio + PCI_IRQ_CAUSE_OFS), - readl(mmio + PCI_IRQ_MASK_OFS)); + readl(mmio + hpriv->irq_cause_ofs), + readl(mmio + hpriv->irq_mask_ofs)); done: return rc; diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 35b2df297527..44f9e5d9e362 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -1629,7 +1629,7 @@ static int nv_hardreset(struct ata_link *link, unsigned int *class, /* SATA hardreset fails to retrieve proper device signature on * some controllers. Don't classify on hardreset. For more - * info, see http://bugme.osdl.org/show_bug.cgi?id=3352 + * info, see http://bugzilla.kernel.org/show_bug.cgi?id=3352 */ return sata_std_hardreset(link, &dummy, deadline); } diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c index 6d43ba79e154..2f1de6ec044c 100644 --- a/drivers/ata/sata_qstor.c +++ b/drivers/ata/sata_qstor.c @@ -103,7 +103,7 @@ enum { QS_DMA_BOUNDARY = ~0UL }; -typedef enum { qs_state_idle, qs_state_pkt, qs_state_mmio } qs_state_t; +typedef enum { qs_state_mmio, qs_state_pkt } qs_state_t; struct qs_port_priv { u8 *pkt; @@ -116,14 +116,15 @@ static int qs_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val); static int qs_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); static int qs_port_start(struct ata_port *ap); static void qs_host_stop(struct ata_host *host); -static void qs_phy_reset(struct ata_port *ap); static void qs_qc_prep(struct ata_queued_cmd *qc); static unsigned int qs_qc_issue(struct ata_queued_cmd *qc); static int qs_check_atapi_dma(struct ata_queued_cmd *qc); static void qs_bmdma_stop(struct ata_queued_cmd *qc); static u8 qs_bmdma_status(struct ata_port *ap); static void qs_irq_clear(struct ata_port *ap); -static void qs_eng_timeout(struct ata_port *ap); +static void qs_freeze(struct ata_port *ap); +static void qs_thaw(struct ata_port *ap); +static void qs_error_handler(struct ata_port *ap); static struct scsi_host_template qs_ata_sht = { .module = THIS_MODULE, @@ -150,11 +151,12 @@ static const struct ata_port_operations qs_ata_ops = { .check_atapi_dma = qs_check_atapi_dma, .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, - .phy_reset = qs_phy_reset, .qc_prep = qs_qc_prep, .qc_issue = qs_qc_issue, .data_xfer = ata_data_xfer, - .eng_timeout = qs_eng_timeout, + .freeze = qs_freeze, + .thaw = qs_thaw, + .error_handler = qs_error_handler, .irq_clear = qs_irq_clear, .irq_on = ata_irq_on, .scr_read = qs_scr_read, @@ -169,8 +171,6 @@ static const struct ata_port_info qs_port_info[] = { /* board_2068_idx */ { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_SATA_RESET | - //FIXME ATA_FLAG_SRST | ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING, .pio_mask = 0x10, /* pio4 */ .udma_mask = ATA_UDMA6, @@ -219,7 +219,9 @@ static void qs_irq_clear(struct ata_port *ap) static inline void qs_enter_reg_mode(struct ata_port *ap) { u8 __iomem *chan = qs_mmio_base(ap->host) + (ap->port_no * 0x4000); + struct qs_port_priv *pp = ap->private_data; + pp->state = qs_state_mmio; writeb(QS_CTR0_REG, chan + QS_CCT_CTR0); readb(chan + QS_CCT_CTR0); /* flush */ } @@ -233,23 +235,28 @@ static inline void qs_reset_channel_logic(struct ata_port *ap) qs_enter_reg_mode(ap); } -static void qs_phy_reset(struct ata_port *ap) +static void qs_freeze(struct ata_port *ap) { - struct qs_port_priv *pp = ap->private_data; + u8 __iomem *mmio_base = qs_mmio_base(ap->host); - pp->state = qs_state_idle; - qs_reset_channel_logic(ap); - sata_phy_reset(ap); + writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */ + qs_enter_reg_mode(ap); } -static void qs_eng_timeout(struct ata_port *ap) +static void qs_thaw(struct ata_port *ap) { - struct qs_port_priv *pp = ap->private_data; + u8 __iomem *mmio_base = qs_mmio_base(ap->host); + + qs_enter_reg_mode(ap); + writeb(1, mmio_base + QS_HCT_CTRL); /* enable host interrupts */ +} + +static int qs_prereset(struct ata_link *link, unsigned long deadline) +{ + struct ata_port *ap = link->ap; - if (pp->state != qs_state_idle) /* healthy paranoia */ - pp->state = qs_state_mmio; qs_reset_channel_logic(ap); - ata_eng_timeout(ap); + return ata_std_prereset(link, deadline); } static int qs_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) @@ -260,6 +267,13 @@ static int qs_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) return 0; } +static void qs_error_handler(struct ata_port *ap) +{ + qs_enter_reg_mode(ap); + ata_do_eh(ap, qs_prereset, ata_std_softreset, NULL, + ata_std_postreset); +} + static int qs_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val) { if (sc_reg > SCR_CONTROL) @@ -358,7 +372,6 @@ static unsigned int qs_qc_issue(struct ata_queued_cmd *qc) switch (qc->tf.protocol) { case ATA_PROT_DMA: - pp->state = qs_state_pkt; qs_packet_start(qc); return 0; @@ -375,6 +388,26 @@ static unsigned int qs_qc_issue(struct ata_queued_cmd *qc) return ata_qc_issue_prot(qc); } +static void qs_do_or_die(struct ata_queued_cmd *qc, u8 status) +{ + qc->err_mask |= ac_err_mask(status); + + if (!qc->err_mask) { + ata_qc_complete(qc); + } else { + struct ata_port *ap = qc->ap; + struct ata_eh_info *ehi = &ap->link.eh_info; + + ata_ehi_clear_desc(ehi); + ata_ehi_push_desc(ehi, "status 0x%02X", status); + + if (qc->err_mask == AC_ERR_DEV) + ata_port_abort(ap); + else + ata_port_freeze(ap); + } +} + static inline unsigned int qs_intr_pkt(struct ata_host *host) { unsigned int handled = 0; @@ -406,10 +439,8 @@ static inline unsigned int qs_intr_pkt(struct ata_host *host) switch (sHST) { case 0: /* successful CPB */ case 3: /* device error */ - pp->state = qs_state_idle; qs_enter_reg_mode(qc->ap); - qc->err_mask |= ac_err_mask(sDST); - ata_qc_complete(qc); + qs_do_or_die(qc, sDST); break; default: break; @@ -431,25 +462,27 @@ static inline unsigned int qs_intr_mmio(struct ata_host *host) if (ap && !(ap->flags & ATA_FLAG_DISABLED)) { struct ata_queued_cmd *qc; - struct qs_port_priv *pp = ap->private_data; - if (!pp || pp->state != qs_state_mmio) - continue; + struct qs_port_priv *pp; qc = ata_qc_from_tag(ap, ap->link.active_tag); - if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) { - - /* check main status, clearing INTRQ */ - u8 status = ata_check_status(ap); - if ((status & ATA_BUSY)) - continue; - DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n", - ap->print_id, qc->tf.protocol, status); - - /* complete taskfile transaction */ - pp->state = qs_state_idle; - qc->err_mask |= ac_err_mask(status); - ata_qc_complete(qc); + if (!qc || !(qc->flags & ATA_QCFLAG_ACTIVE)) { + /* + * The qstor hardware generates spurious + * interrupts from time to time when switching + * in and out of packet mode. + * There's no obvious way to know if we're + * here now due to that, so just ack the irq + * and pretend we knew it was ours.. (ugh). + * This does not affect packet mode. + */ + ata_check_status(ap); handled = 1; + continue; } + pp = ap->private_data; + if (!pp || pp->state != qs_state_mmio) + continue; + if (!(qc->tf.flags & ATA_TFLAG_POLLING)) + handled |= ata_host_intr(ap, qc); } } return handled; @@ -459,12 +492,13 @@ static irqreturn_t qs_intr(int irq, void *dev_instance) { struct ata_host *host = dev_instance; unsigned int handled = 0; + unsigned long flags; VPRINTK("ENTER\n"); - spin_lock(&host->lock); + spin_lock_irqsave(&host->lock, flags); handled = qs_intr_pkt(host) | qs_intr_mmio(host); - spin_unlock(&host->lock); + spin_unlock_irqrestore(&host->lock, flags); VPRINTK("EXIT\n"); @@ -501,7 +535,6 @@ static int qs_port_start(struct ata_port *ap) rc = ata_port_start(ap); if (rc) return rc; - qs_enter_reg_mode(ap); pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL); if (!pp) return -ENOMEM; @@ -512,6 +545,7 @@ static int qs_port_start(struct ata_port *ap) memset(pp->pkt, 0, QS_PKT_BYTES); ap->private_data = pp; + qs_enter_reg_mode(ap); addr = (u64)pp->pkt_dma; writel((u32) addr, chan + QS_CCF_CPBA); writel((u32)(addr >> 32), chan + QS_CCF_CPBA + 4); diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 187dcb02c681..96fd5260446d 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -63,6 +63,21 @@ enum { SIL24_HOST_BAR = 0, SIL24_PORT_BAR = 2, + /* sil24 fetches in chunks of 64bytes. The first block + * contains the PRB and two SGEs. From the second block, it's + * consisted of four SGEs and called SGT. Calculate the + * number of SGTs that fit into one page. + */ + SIL24_PRB_SZ = sizeof(struct sil24_prb) + + 2 * sizeof(struct sil24_sge), + SIL24_MAX_SGT = (PAGE_SIZE - SIL24_PRB_SZ) + / (4 * sizeof(struct sil24_sge)), + + /* This will give us one unused SGEs for ATA. This extra SGE + * will be used to store CDB for ATAPI devices. + */ + SIL24_MAX_SGE = 4 * SIL24_MAX_SGT + 1, + /* * Global controller registers (128 bytes @ BAR0) */ @@ -247,13 +262,13 @@ enum { struct sil24_ata_block { struct sil24_prb prb; - struct sil24_sge sge[LIBATA_MAX_PRD]; + struct sil24_sge sge[SIL24_MAX_SGE]; }; struct sil24_atapi_block { struct sil24_prb prb; u8 cdb[16]; - struct sil24_sge sge[LIBATA_MAX_PRD - 1]; + struct sil24_sge sge[SIL24_MAX_SGE]; }; union sil24_cmd_block { @@ -378,7 +393,7 @@ static struct scsi_host_template sil24_sht = { .change_queue_depth = ata_scsi_change_queue_depth, .can_queue = SIL24_MAX_CMDS, .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, + .sg_tablesize = SIL24_MAX_SGE, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, .use_clustering = ATA_SHT_USE_CLUSTERING, @@ -1284,6 +1299,7 @@ static void sil24_init_controller(struct ata_host *host) static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { + extern int __MARKER__sil24_cmd_block_is_sized_wrongly; static int printed_version; struct ata_port_info pi = sil24_port_info[ent->driver_data]; const struct ata_port_info *ppi[] = { &pi, NULL }; @@ -1292,6 +1308,10 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) int i, rc; u32 tmp; + /* cause link error if sil24_cmd_block is sized wrongly */ + if (sizeof(union sil24_cmd_block) != PAGE_SIZE) + __MARKER__sil24_cmd_block_is_sized_wrongly = 1; + if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); diff --git a/drivers/atm/he.c b/drivers/atm/he.c index d33aba6864c2..3b64a99772ea 100644 --- a/drivers/atm/he.c +++ b/drivers/atm/he.c @@ -394,6 +394,11 @@ 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)) { he_stop(he_dev); err = -ENODEV; @@ -1173,11 +1178,6 @@ he_start(struct atm_dev *dev) if ((err = he_init_irq(he_dev)) != 0) return err; -#ifdef USE_TASKLET - tasklet_init(&he_dev->tasklet, he_tasklet, (unsigned long) he_dev); -#endif - spin_lock_init(&he_dev->global_lock); - /* 4.11 enable pci bus controller state machines */ host_cntl |= (OUTFF_ENB | CMDFF_ENB | QUICK_RD_RETRY | QUICK_WR_RETRY | PERR_INT_ENB); diff --git a/drivers/base/core.c b/drivers/base/core.c index 3f4d6aa13990..2683eac30c68 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -770,9 +770,10 @@ int device_add(struct device *dev) error = device_add_attrs(dev); if (error) goto AttrsError; - error = device_pm_add(dev); + error = dpm_sysfs_add(dev); if (error) goto PMError; + device_pm_add(dev); error = bus_add_device(dev); if (error) goto BusError; @@ -797,6 +798,7 @@ int device_add(struct device *dev) return error; BusError: device_pm_remove(dev); + dpm_sysfs_remove(dev); PMError: if (dev->bus) blocking_notifier_call_chain(&dev->bus->bus_notifier, diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile index a803733c839e..44504e6618fb 100644 --- a/drivers/base/power/Makefile +++ b/drivers/base/power/Makefile @@ -1,5 +1,6 @@ obj-y := shutdown.o -obj-$(CONFIG_PM_SLEEP) += main.o sysfs.o +obj-$(CONFIG_PM) += sysfs.o +obj-$(CONFIG_PM_SLEEP) += main.o obj-$(CONFIG_PM_TRACE) += trace.o ifeq ($(CONFIG_DEBUG_DRIVER),y) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 0ab4ab21f564..691ffb64cc37 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -38,20 +38,14 @@ static DEFINE_MUTEX(dpm_list_mtx); int (*platform_enable_wakeup)(struct device *dev, int is_on); -int device_pm_add(struct device *dev) +void device_pm_add(struct device *dev) { - int error; - pr_debug("PM: Adding info for %s:%s\n", dev->bus ? dev->bus->name : "No Bus", kobject_name(&dev->kobj)); mutex_lock(&dpm_list_mtx); list_add_tail(&dev->power.entry, &dpm_active); - error = dpm_sysfs_add(dev); - if (error) - list_del(&dev->power.entry); mutex_unlock(&dpm_list_mtx); - return error; } void device_pm_remove(struct device *dev) diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index 5c4efd493fa5..379da4e958e0 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h @@ -13,14 +13,29 @@ extern void device_shutdown(void); extern struct list_head dpm_active; /* The active device list */ -static inline struct device * to_device(struct list_head * entry) +static inline struct device *to_device(struct list_head *entry) { return container_of(entry, struct device, power.entry); } -extern int device_pm_add(struct device *); +extern void device_pm_add(struct device *); extern void device_pm_remove(struct device *); +#else /* CONFIG_PM_SLEEP */ + + +static inline void device_pm_add(struct device *dev) +{ +} + +static inline void device_pm_remove(struct device *dev) +{ +} + +#endif + +#ifdef CONFIG_PM + /* * sysfs.c */ @@ -28,16 +43,15 @@ extern void device_pm_remove(struct device *); extern int dpm_sysfs_add(struct device *); extern void dpm_sysfs_remove(struct device *); -#else /* CONFIG_PM_SLEEP */ - +#else /* CONFIG_PM */ -static inline int device_pm_add(struct device * dev) +static inline int dpm_sysfs_add(struct device *dev) { return 0; } -static inline void device_pm_remove(struct device * dev) -{ +static inline void dpm_sysfs_remove(struct device *dev) +{ } #endif diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 6332acad078c..b4c0888aedc3 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -28,6 +28,7 @@ #include <linux/err.h> #include <linux/kernel.h> #include <net/sock.h> +#include <linux/net.h> #include <asm/uaccess.h> #include <asm/system.h> @@ -126,7 +127,7 @@ static void sock_shutdown(struct nbd_device *lo, int lock) if (lo->sock) { printk(KERN_WARNING "%s: shutting down socket\n", lo->disk->disk_name); - lo->sock->ops->shutdown(lo->sock, SEND_SHUTDOWN|RCV_SHUTDOWN); + kernel_sock_shutdown(lo->sock, SHUT_RDWR); lo->sock = NULL; } if (lock) diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c index ceffa6034e20..e7fe6ca97dd8 100644 --- a/drivers/block/paride/pf.c +++ b/drivers/block/paride/pf.c @@ -488,13 +488,11 @@ static int pf_atapi(struct pf_unit *pf, char *cmd, int dlen, char *buf, char *fu return r; } -#define DBMSG(msg) ((verbose>1)?(msg):NULL) - static void pf_lock(struct pf_unit *pf, int func) { char lo_cmd[12] = { ATAPI_LOCK, pf->lun << 5, 0, 0, func, 0, 0, 0, 0, 0, 0, 0 }; - pf_atapi(pf, lo_cmd, 0, pf_scratch, func ? "unlock" : "lock"); + pf_atapi(pf, lo_cmd, 0, pf_scratch, func ? "lock" : "unlock"); } static void pf_eject(struct pf_unit *pf) @@ -555,7 +553,7 @@ static void pf_mode_sense(struct pf_unit *pf) { ATAPI_MODE_SENSE, pf->lun << 5, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0 }; char buf[8]; - pf_atapi(pf, ms_cmd, 8, buf, DBMSG("mode sense")); + pf_atapi(pf, ms_cmd, 8, buf, "mode sense"); pf->media_status = PF_RW; if (buf[3] & 0x80) pf->media_status = PF_RO; @@ -591,7 +589,7 @@ static void pf_get_capacity(struct pf_unit *pf) char buf[8]; int bs; - if (pf_atapi(pf, rc_cmd, 8, buf, DBMSG("get capacity"))) { + if (pf_atapi(pf, rc_cmd, 8, buf, "get capacity")) { pf->media_status = PF_NM; return; } @@ -804,13 +802,18 @@ static int pf_next_buf(void) pf_buf += 512; pf_block++; if (!pf_run) - return 0; - if (!pf_count) return 1; - spin_lock_irqsave(&pf_spin_lock, saved_flags); - pf_end_request(1); - spin_unlock_irqrestore(&pf_spin_lock, saved_flags); - return 1; + if (!pf_count) { + spin_lock_irqsave(&pf_spin_lock, saved_flags); + pf_end_request(1); + pf_req = elv_next_request(pf_queue); + spin_unlock_irqrestore(&pf_spin_lock, saved_flags); + if (!pf_req) + return 1; + pf_count = pf_req->current_nr_sectors; + pf_buf = pf_req->buffer; + } + return 0; } static inline void next_request(int success) diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index a8130a4ad6d4..a5ee21319d37 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -358,10 +358,19 @@ static ssize_t class_pktcdvd_store_add(struct class *c, const char *buf, size_t count) { unsigned int major, minor; + if (sscanf(buf, "%u:%u", &major, &minor) == 2) { + /* pkt_setup_dev() expects caller to hold reference to self */ + if (!try_module_get(THIS_MODULE)) + return -ENODEV; + pkt_setup_dev(MKDEV(major, minor), NULL); + + module_put(THIS_MODULE); + return count; } + return -EINVAL; } diff --git a/drivers/block/rd.c b/drivers/block/rd.c index 47f8ac6cce57..82f4eecc8699 100644 --- a/drivers/block/rd.c +++ b/drivers/block/rd.c @@ -189,6 +189,18 @@ static int ramdisk_set_page_dirty(struct page *page) return 0; } +/* + * releasepage is called by pagevec_strip/try_to_release_page if + * buffers_heads_over_limit is true. Without a releasepage function + * try_to_free_buffers is called instead. That can unset the dirty + * bit of our ram disk pages, which will be eventually freed, even + * if the page is still in use. + */ +static int ramdisk_releasepage(struct page *page, gfp_t dummy) +{ + return 0; +} + static const struct address_space_operations ramdisk_aops = { .readpage = ramdisk_readpage, .prepare_write = ramdisk_prepare_write, @@ -196,6 +208,7 @@ static const struct address_space_operations ramdisk_aops = { .writepage = ramdisk_writepage, .set_page_dirty = ramdisk_set_page_dirty, .writepages = ramdisk_writepages, + .releasepage = ramdisk_releasepage, }; static int rd_blkdev_pagecache_IO(int rw, struct bio_vec *vec, sector_t sector, diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 3cf7129d83e6..924ddd8bccd2 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -223,7 +223,7 @@ static int virtblk_probe(struct virtio_device *vdev) err = virtio_config_val(vdev, VIRTIO_CONFIG_BLK_F_CAPACITY, &cap); if (err) { dev_err(&vdev->dev, "Bad/missing capacity in config\n"); - goto out_put_disk; + goto out_cleanup_queue; } /* If capacity is too big, truncate with warning. */ @@ -239,7 +239,7 @@ static int virtblk_probe(struct virtio_device *vdev) blk_queue_max_segment_size(vblk->disk->queue, v); else if (err != -ENOENT) { dev_err(&vdev->dev, "Bad SIZE_MAX in config\n"); - goto out_put_disk; + goto out_cleanup_queue; } err = virtio_config_val(vdev, VIRTIO_CONFIG_BLK_F_SEG_MAX, &v); @@ -247,12 +247,14 @@ static int virtblk_probe(struct virtio_device *vdev) blk_queue_max_hw_segments(vblk->disk->queue, v); else if (err != -ENOENT) { dev_err(&vdev->dev, "Bad SEG_MAX in config\n"); - goto out_put_disk; + goto out_cleanup_queue; } add_disk(vblk->disk); return 0; +out_cleanup_queue: + blk_cleanup_queue(vblk->disk->queue); out_put_disk: put_disk(vblk->disk); out_unregister_blkdev: @@ -277,6 +279,8 @@ static void virtblk_remove(struct virtio_device *vdev) put_disk(vblk->disk); unregister_blkdev(major, "virtblk"); mempool_destroy(vblk->pool); + /* There should be nothing in the queue now, so no need to shutdown */ + vdev->config->del_vq(vblk->vq); kfree(vblk); } diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index bf18d757b876..a509b8d79781 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -457,7 +457,7 @@ config LEGACY_PTYS config LEGACY_PTY_COUNT int "Maximum number of legacy PTY in use" depends on LEGACY_PTYS - range 1 256 + range 0 256 default "256" ---help--- The maximum number of legacy PTYs that can be used at any one time. diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index cc5d77797def..02518da6a386 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -47,7 +47,7 @@ /* #define ATR_CSUM */ #ifdef PCMCIA_DEBUG -#define reader_to_dev(x) (&handle_to_dev(x->p_dev->handle)) +#define reader_to_dev(x) (&handle_to_dev(x->p_dev)) static int pc_debug = PCMCIA_DEBUG; module_param(pc_debug, int, 0600); #define DEBUGP(n, rdr, x, args...) do { \ diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index a0b9c8728d56..5f291bf739a6 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c @@ -41,7 +41,7 @@ #ifdef PCMCIA_DEBUG -#define reader_to_dev(x) (&handle_to_dev(x->p_dev->handle)) +#define reader_to_dev(x) (&handle_to_dev(x->p_dev)) static int pc_debug = PCMCIA_DEBUG; module_param(pc_debug, int, 0600); #define DEBUGP(n, rdr, x, args...) do { \ diff --git a/drivers/char/random.c b/drivers/char/random.c index 1756b1f7cb72..5fee05661823 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1494,7 +1494,7 @@ __u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr, seq = twothirdsMD4Transform((const __u32 *)daddr, hash) & HASH_MASK; seq += keyptr->count; - seq += ktime_get_real().tv64; + seq += ktime_to_ns(ktime_get_real()); return seq; } @@ -1556,7 +1556,7 @@ __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr, * overlaps less than one time per MSL (2 minutes). * Choosing a clock of 64 ns period is OK. (period of 274 s) */ - seq += ktime_get_real().tv64 >> 6; + seq += ktime_to_ns(ktime_get_real()) >> 6; #if 0 printk("init_seq(%lx, %lx, %d, %d) = %d\n", saddr, daddr, sport, dport, seq); @@ -1616,7 +1616,7 @@ u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr, seq = half_md4_transform(hash, keyptr->secret); seq |= ((u64)keyptr->count) << (32 - HASH_BITS); - seq += ktime_get_real().tv64; + seq += ktime_to_ns(ktime_get_real()); seq &= (1ull << 48) - 1; #if 0 printk("dccp init_seq(%lx, %lx, %d, %d) = %d\n", diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index ec6b65ec69ea..0c66b802736a 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -918,6 +918,31 @@ static const struct file_operations rtc_proc_fops = { }; #endif +static resource_size_t rtc_size; + +static struct resource * __init rtc_request_region(resource_size_t size) +{ + struct resource *r; + + if (RTC_IOMAPPED) + r = request_region(RTC_PORT(0), size, "rtc"); + else + r = request_mem_region(RTC_PORT(0), size, "rtc"); + + if (r) + rtc_size = size; + + return r; +} + +static void rtc_release_region(void) +{ + if (RTC_IOMAPPED) + release_region(RTC_PORT(0), rtc_size); + else + release_mem_region(RTC_PORT(0), rtc_size); +} + static int __init rtc_init(void) { #ifdef CONFIG_PROC_FS @@ -968,10 +993,17 @@ found: } no_irq: #else - if (RTC_IOMAPPED) - r = request_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc"); - else - r = request_mem_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc"); + r = rtc_request_region(RTC_IO_EXTENT); + + /* + * If we've already requested a smaller range (for example, because + * PNPBIOS or ACPI told us how the device is configured), the request + * above might fail because it's too big. + * + * If so, request just the range we actually use. + */ + if (!r) + r = rtc_request_region(RTC_IO_EXTENT_USED); if (!r) { #ifdef RTC_IRQ rtc_has_irq = 0; @@ -992,10 +1024,7 @@ no_irq: /* Yeah right, seeing as irq 8 doesn't even hit the bus. */ rtc_has_irq = 0; printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ); - if (RTC_IOMAPPED) - release_region(RTC_PORT(0), RTC_IO_EXTENT); - else - release_mem_region(RTC_PORT(0), RTC_IO_EXTENT); + rtc_release_region(); return -EIO; } hpet_rtc_timer_init(); @@ -1009,7 +1038,7 @@ no_irq: free_irq(RTC_IRQ, NULL); rtc_has_irq = 0; #endif - release_region(RTC_PORT(0), RTC_IO_EXTENT); + rtc_release_region(); return -ENODEV; } @@ -1091,10 +1120,7 @@ static void __exit rtc_exit (void) if (rtc_has_irq) free_irq (rtc_irq, &rtc_port); #else - if (RTC_IOMAPPED) - release_region(RTC_PORT(0), RTC_IO_EXTENT); - else - release_mem_region(RTC_PORT(0), RTC_IO_EXTENT); + rtc_release_region(); #ifdef RTC_IRQ if (rtc_has_irq) free_irq (RTC_IRQ, NULL); diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index 877e53dcb996..921c6d2bc8fc 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -1163,7 +1163,7 @@ static struct acpi_driver sonypi_acpi_driver = { }; #endif -static int __devinit sonypi_create_input_devices(void) +static int __devinit sonypi_create_input_devices(struct platform_device *pdev) { struct input_dev *jog_dev; struct input_dev *key_dev; @@ -1177,6 +1177,7 @@ static int __devinit sonypi_create_input_devices(void) jog_dev->name = "Sony Vaio Jogdial"; jog_dev->id.bustype = BUS_ISA; jog_dev->id.vendor = PCI_VENDOR_ID_SONY; + jog_dev->dev.parent = &pdev->dev; jog_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); jog_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_MIDDLE); @@ -1191,6 +1192,7 @@ static int __devinit sonypi_create_input_devices(void) key_dev->name = "Sony Vaio Keys"; key_dev->id.bustype = BUS_ISA; key_dev->id.vendor = PCI_VENDOR_ID_SONY; + key_dev->dev.parent = &pdev->dev; /* Initialize the Input Drivers: special keys */ key_dev->evbit[0] = BIT_MASK(EV_KEY); @@ -1385,7 +1387,7 @@ static int __devinit sonypi_probe(struct platform_device *dev) if (useinput) { - error = sonypi_create_input_devices(); + error = sonypi_create_input_devices(dev); if (error) { printk(KERN_ERR "sonypi: failed to create input devices\n"); @@ -1432,7 +1434,7 @@ static int __devexit sonypi_remove(struct platform_device *dev) { sonypi_disable(); - synchronize_sched(); /* Allow sonypi interrupt to complete. */ + synchronize_irq(sonypi_device.irq); flush_scheduled_work(); if (useinput) { diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index fd771a4d6d18..81503d94fecc 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -450,6 +450,11 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, goto out_err; } + if (request_locality(chip, 0) != 0) { + rc = -ENODEV; + goto out_err; + } + vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); /* Default timeouts */ @@ -487,11 +492,6 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, if (intfcaps & TPM_INTF_DATA_AVAIL_INT) dev_dbg(dev, "\tData Avail Int Support\n"); - if (request_locality(chip, 0) != 0) { - rc = -ENODEV; - goto out_err; - } - /* INTERRUPT Setup */ init_waitqueue_head(&chip->vendor.read_queue); init_waitqueue_head(&chip->vendor.int_queue); diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index 7a003504c265..1bdd2bf4f37d 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c @@ -730,13 +730,23 @@ static int send_prio_char(struct tty_struct *tty, char ch) return 0; } -int n_tty_ioctl(struct tty_struct * tty, struct file * file, - unsigned int cmd, unsigned long arg) +/** + * tty_mode_ioctl - mode related ioctls + * @tty: tty for the ioctl + * @file: file pointer for the tty + * @cmd: command + * @arg: ioctl argument + * + * Perform non line discipline specific mode control ioctls. This + * is designed to be called by line disciplines to ensure they provide + * consistent mode setting. + */ + +int tty_mode_ioctl(struct tty_struct * tty, struct file *file, + unsigned int cmd, unsigned long arg) { struct tty_struct * real_tty; void __user *p = (void __user *)arg; - int retval; - struct tty_ldisc *ld; if (tty->driver->type == TTY_DRIVER_TYPE_PTY && tty->driver->subtype == PTY_TYPE_MASTER) @@ -799,6 +809,93 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file, return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO); case TCSETA: return set_termios(real_tty, p, TERMIOS_TERMIO); +#ifndef TCGETS2 + case TIOCGLCKTRMIOS: + if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked)) + return -EFAULT; + return 0; + + case TIOCSLCKTRMIOS: + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg)) + return -EFAULT; + return 0; +#else + case TIOCGLCKTRMIOS: + if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked)) + return -EFAULT; + return 0; + + case TIOCSLCKTRMIOS: + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (user_termios_to_kernel_termios_1(real_tty->termios_locked, (struct termios __user *) arg)) + return -EFAULT; + return 0; +#endif + case TIOCGSOFTCAR: + return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)arg); + case TIOCSSOFTCAR: + if (get_user(arg, (unsigned int __user *) arg)) + return -EFAULT; + mutex_lock(&tty->termios_mutex); + tty->termios->c_cflag = + ((tty->termios->c_cflag & ~CLOCAL) | + (arg ? CLOCAL : 0)); + mutex_unlock(&tty->termios_mutex); + return 0; + default: + return -ENOIOCTLCMD; + } +} + +EXPORT_SYMBOL_GPL(tty_mode_ioctl); + +int tty_perform_flush(struct tty_struct *tty, unsigned long arg) +{ + struct tty_ldisc *ld; + int retval = tty_check_change(tty); + if (retval) + return retval; + + ld = tty_ldisc_ref(tty); + switch (arg) { + case TCIFLUSH: + if (ld && ld->flush_buffer) + ld->flush_buffer(tty); + break; + case TCIOFLUSH: + if (ld && ld->flush_buffer) + ld->flush_buffer(tty); + /* fall through */ + case TCOFLUSH: + if (tty->driver->flush_buffer) + tty->driver->flush_buffer(tty); + break; + default: + tty_ldisc_deref(ld); + return -EINVAL; + } + tty_ldisc_deref(ld); + return 0; +} + +EXPORT_SYMBOL_GPL(tty_perform_flush); + +int n_tty_ioctl(struct tty_struct * tty, struct file * file, + unsigned int cmd, unsigned long arg) +{ + struct tty_struct * real_tty; + int retval; + + if (tty->driver->type == TTY_DRIVER_TYPE_PTY && + tty->driver->subtype == PTY_TYPE_MASTER) + real_tty = tty->link; + else + real_tty = tty; + + switch (cmd) { case TCXONC: retval = tty_check_change(tty); if (retval) @@ -829,30 +926,7 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file, } return 0; case TCFLSH: - retval = tty_check_change(tty); - if (retval) - return retval; - - ld = tty_ldisc_ref(tty); - switch (arg) { - case TCIFLUSH: - if (ld && ld->flush_buffer) - ld->flush_buffer(tty); - break; - case TCIOFLUSH: - if (ld && ld->flush_buffer) - ld->flush_buffer(tty); - /* fall through */ - case TCOFLUSH: - if (tty->driver->flush_buffer) - tty->driver->flush_buffer(tty); - break; - default: - tty_ldisc_deref(ld); - return -EINVAL; - } - tty_ldisc_deref(ld); - return 0; + return tty_perform_flush(tty, arg); case TIOCOUTQ: return put_user(tty->driver->chars_in_buffer ? tty->driver->chars_in_buffer(tty) : 0, @@ -862,32 +936,6 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file, if (L_ICANON(tty)) retval = inq_canon(tty); return put_user(retval, (unsigned int __user *) arg); -#ifndef TCGETS2 - case TIOCGLCKTRMIOS: - if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked)) - return -EFAULT; - return 0; - - case TIOCSLCKTRMIOS: - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg)) - return -EFAULT; - return 0; -#else - case TIOCGLCKTRMIOS: - if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked)) - return -EFAULT; - return 0; - - case TIOCSLCKTRMIOS: - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (user_termios_to_kernel_termios_1(real_tty->termios_locked, (struct termios __user *) arg)) - return -EFAULT; - return 0; -#endif - case TIOCPKT: { int pktmode; @@ -906,19 +954,9 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file, tty->packet = 0; return 0; } - case TIOCGSOFTCAR: - return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)arg); - case TIOCSSOFTCAR: - if (get_user(arg, (unsigned int __user *) arg)) - return -EFAULT; - mutex_lock(&tty->termios_mutex); - tty->termios->c_cflag = - ((tty->termios->c_cflag & ~CLOCAL) | - (arg ? CLOCAL : 0)); - mutex_unlock(&tty->termios_mutex); - return 0; default: - return -ENOIOCTLCMD; + /* Try the mode commands */ + return tty_mode_ioctl(tty, file, cmd, arg); } } diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 4bd33ce8a6f3..1bba99747f5b 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -37,17 +37,17 @@ #define DEF_FREQUENCY_UP_THRESHOLD (80) #define DEF_FREQUENCY_DOWN_THRESHOLD (20) -/* - * The polling frequency of this governor depends on the capability of +/* + * The polling frequency of this governor depends on the capability of * the processor. Default polling frequency is 1000 times the transition - * latency of the processor. The governor will work on any processor with - * transition latency <= 10mS, using appropriate sampling + * latency of the processor. The governor will work on any processor with + * transition latency <= 10mS, using appropriate sampling * rate. * For CPUs with transition latency > 10mS (mostly drivers * with CPUFREQ_ETERNAL), this governor will not work. * All times here are in uS. */ -static unsigned int def_sampling_rate; +static unsigned int def_sampling_rate; #define MIN_SAMPLING_RATE_RATIO (2) /* for correct statistics, we need at least 10 ticks between each measure */ #define MIN_STAT_SAMPLING_RATE \ @@ -63,12 +63,12 @@ static unsigned int def_sampling_rate; static void do_dbs_timer(struct work_struct *work); struct cpu_dbs_info_s { - struct cpufreq_policy *cur_policy; - unsigned int prev_cpu_idle_up; - unsigned int prev_cpu_idle_down; - unsigned int enable; - unsigned int down_skip; - unsigned int requested_freq; + struct cpufreq_policy *cur_policy; + unsigned int prev_cpu_idle_up; + unsigned int prev_cpu_idle_down; + unsigned int enable; + unsigned int down_skip; + unsigned int requested_freq; }; static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); @@ -82,24 +82,24 @@ static unsigned int dbs_enable; /* number of CPUs using this policy */ * cpu_hotplug lock should be taken before that. Note that cpu_hotplug lock * is recursive for the same process. -Venki */ -static DEFINE_MUTEX (dbs_mutex); +static DEFINE_MUTEX (dbs_mutex); static DECLARE_DELAYED_WORK(dbs_work, do_dbs_timer); struct dbs_tuners { - unsigned int sampling_rate; - unsigned int sampling_down_factor; - unsigned int up_threshold; - unsigned int down_threshold; - unsigned int ignore_nice; - unsigned int freq_step; + unsigned int sampling_rate; + unsigned int sampling_down_factor; + unsigned int up_threshold; + unsigned int down_threshold; + unsigned int ignore_nice; + unsigned int freq_step; }; static struct dbs_tuners dbs_tuners_ins = { - .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, - .down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD, - .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR, - .ignore_nice = 0, - .freq_step = 5, + .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, + .down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD, + .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR, + .ignore_nice = 0, + .freq_step = 5, }; static inline unsigned int get_cpu_idle_time(unsigned int cpu) @@ -109,13 +109,34 @@ static inline unsigned int get_cpu_idle_time(unsigned int cpu) if (dbs_tuners_ins.ignore_nice) add_nice = kstat_cpu(cpu).cpustat.nice; - ret = kstat_cpu(cpu).cpustat.idle + + ret = kstat_cpu(cpu).cpustat.idle + kstat_cpu(cpu).cpustat.iowait + add_nice; return ret; } +/* keep track of frequency transitions */ +static int +dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val, + void *data) +{ + struct cpufreq_freqs *freq = data; + struct cpu_dbs_info_s *this_dbs_info = &per_cpu(cpu_dbs_info, + freq->cpu); + + if (!this_dbs_info->enable) + return 0; + + this_dbs_info->requested_freq = freq->new; + + return 0; +} + +static struct notifier_block dbs_cpufreq_notifier_block = { + .notifier_call = dbs_cpufreq_notifier +}; + /************************** sysfs interface ************************/ static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf) { @@ -127,8 +148,8 @@ static ssize_t show_sampling_rate_min(struct cpufreq_policy *policy, char *buf) return sprintf (buf, "%u\n", MIN_SAMPLING_RATE); } -#define define_one_ro(_name) \ -static struct freq_attr _name = \ +#define define_one_ro(_name) \ +static struct freq_attr _name = \ __ATTR(_name, 0444, show_##_name, NULL) define_one_ro(sampling_rate_max); @@ -148,7 +169,7 @@ show_one(down_threshold, down_threshold); show_one(ignore_nice_load, ignore_nice); show_one(freq_step, freq_step); -static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, +static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, const char *buf, size_t count) { unsigned int input; @@ -164,7 +185,7 @@ static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, return count; } -static ssize_t store_sampling_rate(struct cpufreq_policy *unused, +static ssize_t store_sampling_rate(struct cpufreq_policy *unused, const char *buf, size_t count) { unsigned int input; @@ -183,7 +204,7 @@ static ssize_t store_sampling_rate(struct cpufreq_policy *unused, return count; } -static ssize_t store_up_threshold(struct cpufreq_policy *unused, +static ssize_t store_up_threshold(struct cpufreq_policy *unused, const char *buf, size_t count) { unsigned int input; @@ -202,7 +223,7 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused, return count; } -static ssize_t store_down_threshold(struct cpufreq_policy *unused, +static ssize_t store_down_threshold(struct cpufreq_policy *unused, const char *buf, size_t count) { unsigned int input; @@ -228,16 +249,16 @@ static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy, int ret; unsigned int j; - - ret = sscanf (buf, "%u", &input); - if ( ret != 1 ) + + ret = sscanf(buf, "%u", &input); + if (ret != 1) return -EINVAL; - if ( input > 1 ) + if (input > 1) input = 1; - + mutex_lock(&dbs_mutex); - if ( input == dbs_tuners_ins.ignore_nice ) { /* nothing to do */ + if (input == dbs_tuners_ins.ignore_nice) { /* nothing to do */ mutex_unlock(&dbs_mutex); return count; } @@ -261,14 +282,14 @@ static ssize_t store_freq_step(struct cpufreq_policy *policy, unsigned int input; int ret; - ret = sscanf (buf, "%u", &input); + ret = sscanf(buf, "%u", &input); - if ( ret != 1 ) + if (ret != 1) return -EINVAL; - if ( input > 100 ) + if (input > 100) input = 100; - + /* no need to test here if freq_step is zero as the user might actually * want this, they would be crazy though :) */ mutex_lock(&dbs_mutex); @@ -322,18 +343,18 @@ static void dbs_check_cpu(int cpu) policy = this_dbs_info->cur_policy; - /* - * The default safe range is 20% to 80% + /* + * The default safe range is 20% to 80% * Every sampling_rate, we check - * - If current idle time is less than 20%, then we try to - * increase frequency + * - If current idle time is less than 20%, then we try to + * increase frequency * Every sampling_rate*sampling_down_factor, we check - * - If current idle time is more than 80%, then we try to - * decrease frequency + * - If current idle time is more than 80%, then we try to + * decrease frequency * - * Any frequency increase takes it to the maximum frequency. - * Frequency reduction happens at minimum steps of - * 5% (default) of max_frequency + * Any frequency increase takes it to the maximum frequency. + * Frequency reduction happens at minimum steps of + * 5% (default) of max_frequency */ /* Check for frequency increase */ @@ -361,13 +382,13 @@ static void dbs_check_cpu(int cpu) /* if we are already at full speed then break out early */ if (this_dbs_info->requested_freq == policy->max) return; - + freq_step = (dbs_tuners_ins.freq_step * policy->max) / 100; /* max freq cannot be less than 100. But who knows.... */ if (unlikely(freq_step == 0)) freq_step = 5; - + this_dbs_info->requested_freq += freq_step; if (this_dbs_info->requested_freq > policy->max) this_dbs_info->requested_freq = policy->max; @@ -427,15 +448,15 @@ static void dbs_check_cpu(int cpu) } static void do_dbs_timer(struct work_struct *work) -{ +{ int i; mutex_lock(&dbs_mutex); for_each_online_cpu(i) dbs_check_cpu(i); - schedule_delayed_work(&dbs_work, + schedule_delayed_work(&dbs_work, usecs_to_jiffies(dbs_tuners_ins.sampling_rate)); mutex_unlock(&dbs_mutex); -} +} static inline void dbs_timer_init(void) { @@ -462,13 +483,12 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, switch (event) { case CPUFREQ_GOV_START: - if ((!cpu_online(cpu)) || - (!policy->cur)) + if ((!cpu_online(cpu)) || (!policy->cur)) return -EINVAL; if (this_dbs_info->enable) /* Already enabled */ break; - + mutex_lock(&dbs_mutex); rc = sysfs_create_group(&policy->kobj, &dbs_attr_group); @@ -481,7 +501,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, struct cpu_dbs_info_s *j_dbs_info; j_dbs_info = &per_cpu(cpu_dbs_info, j); j_dbs_info->cur_policy = policy; - + j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(cpu); j_dbs_info->prev_cpu_idle_down = j_dbs_info->prev_cpu_idle_up; @@ -511,8 +531,11 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, dbs_tuners_ins.sampling_rate = def_sampling_rate; dbs_timer_init(); + cpufreq_register_notifier( + &dbs_cpufreq_notifier_block, + CPUFREQ_TRANSITION_NOTIFIER); } - + mutex_unlock(&dbs_mutex); break; @@ -525,9 +548,13 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, * Stop the timerschedule work, when this governor * is used for first time */ - if (dbs_enable == 0) + if (dbs_enable == 0) { dbs_timer_exit(); - + cpufreq_unregister_notifier( + &dbs_cpufreq_notifier_block, + CPUFREQ_TRANSITION_NOTIFIER); + } + mutex_unlock(&dbs_mutex); break; @@ -537,11 +564,11 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, if (policy->max < this_dbs_info->cur_policy->cur) __cpufreq_driver_target( this_dbs_info->cur_policy, - policy->max, CPUFREQ_RELATION_H); + policy->max, CPUFREQ_RELATION_H); else if (policy->min > this_dbs_info->cur_policy->cur) __cpufreq_driver_target( this_dbs_info->cur_policy, - policy->min, CPUFREQ_RELATION_L); + policy->min, CPUFREQ_RELATION_L); mutex_unlock(&dbs_mutex); break; } diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 5fd6688a444a..ddd3a259cea1 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -12,7 +12,7 @@ if CRYPTO_HW config CRYPTO_DEV_PADLOCK tristate "Support for VIA PadLock ACE" - depends on X86_32 + depends on X86_32 && !UML select CRYPTO_ALGAPI help Some VIA processors come with an integrated crypto engine diff --git a/drivers/crypto/geode-aes.c b/drivers/crypto/geode-aes.c index f9a34abbf4fa..711e246e1ef0 100644 --- a/drivers/crypto/geode-aes.c +++ b/drivers/crypto/geode-aes.c @@ -110,8 +110,7 @@ geode_aes_crypt(struct geode_aes_op *op) * we don't need to worry */ - if (op->src == op->dst) - flags |= (AES_CTRL_DCA | AES_CTRL_SCA); + flags |= (AES_CTRL_DCA | AES_CTRL_SCA); if (op->dir == AES_DIR_ENCRYPT) flags |= AES_CTRL_ENCRYPT; diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 6a7d25fc2470..c46b7c219ee9 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -3,11 +3,13 @@ # menuconfig DMADEVICES - bool "DMA Offload Engine support" + bool "DMA Engine support" depends on (PCI && X86) || ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX help - Intel(R) offload engines enable offloading memory copies in the - network stack and RAID operations in the MD driver. + DMA engines can do asynchronous data transfers without + involving the host CPU. Currently, this framework can be + used to offload memory copies in the network stack and + RAID operations in the MD driver. if DMADEVICES diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 82489923af09..d59b2f417306 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -182,10 +182,9 @@ static void dma_client_chan_alloc(struct dma_client *client) /* we are done once this client rejects * an available resource */ - if (ack == DMA_ACK) { + if (ack == DMA_ACK) dma_chan_get(chan); - kref_get(&device->refcount); - } else if (ack == DMA_NAK) + else if (ack == DMA_NAK) return; } } @@ -272,11 +271,8 @@ static void dma_clients_notify_removed(struct dma_chan *chan) /* client was holding resources for this channel so * free it */ - if (ack == DMA_ACK) { + if (ack == DMA_ACK) dma_chan_put(chan); - kref_put(&chan->device->refcount, - dma_async_device_cleanup); - } } mutex_unlock(&dma_list_mutex); @@ -316,11 +312,8 @@ void dma_async_client_unregister(struct dma_client *client) ack = client->event_callback(client, chan, DMA_RESOURCE_REMOVED); - if (ack == DMA_ACK) { + if (ack == DMA_ACK) dma_chan_put(chan); - kref_put(&chan->device->refcount, - dma_async_device_cleanup); - } } list_del(&client->global_node); @@ -397,6 +390,8 @@ int dma_async_device_register(struct dma_device *device) goto err_out; } + /* One for the channel, one of the class device */ + kref_get(&device->refcount); kref_get(&device->refcount); kref_init(&chan->refcount); chan->slow_ref = 0; diff --git a/drivers/dma/ioat.c b/drivers/dma/ioat.c index f204c39fb412..16e0fd8facfb 100644 --- a/drivers/dma/ioat.c +++ b/drivers/dma/ioat.c @@ -39,10 +39,14 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Intel Corporation"); static struct pci_device_id ioat_pci_tbl[] = { + /* I/OAT v1 platforms */ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_CNB) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SCNB) }, { PCI_DEVICE(PCI_VENDOR_ID_UNISYS, PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR) }, + + /* I/OAT v2 platforms */ + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB) }, { 0, } }; @@ -74,10 +78,17 @@ static int ioat_setup_functionality(struct pci_dev *pdev, void __iomem *iobase) if (device->dma && ioat_dca_enabled) device->dca = ioat_dca_init(pdev, iobase); break; + case IOAT_VER_2_0: + device->dma = ioat_dma_probe(pdev, iobase); + if (device->dma && ioat_dca_enabled) + device->dca = ioat2_dca_init(pdev, iobase); + break; default: err = -ENODEV; break; } + if (!device->dma) + err = -ENODEV; return err; } diff --git a/drivers/dma/ioat_dca.c b/drivers/dma/ioat_dca.c index ba985715b803..0fa8a98051a8 100644 --- a/drivers/dma/ioat_dca.c +++ b/drivers/dma/ioat_dca.c @@ -261,3 +261,167 @@ struct dca_provider *ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase) return dca; } + +static int ioat2_dca_add_requester(struct dca_provider *dca, struct device *dev) +{ + struct ioat_dca_priv *ioatdca = dca_priv(dca); + struct pci_dev *pdev; + int i; + u16 id; + u16 global_req_table; + + /* This implementation only supports PCI-Express */ + if (dev->bus != &pci_bus_type) + return -ENODEV; + pdev = to_pci_dev(dev); + id = dcaid_from_pcidev(pdev); + + if (ioatdca->requester_count == ioatdca->max_requesters) + return -ENODEV; + + for (i = 0; i < ioatdca->max_requesters; i++) { + if (ioatdca->req_slots[i].pdev == NULL) { + /* found an empty slot */ + ioatdca->requester_count++; + ioatdca->req_slots[i].pdev = pdev; + ioatdca->req_slots[i].rid = id; + global_req_table = + readw(ioatdca->dca_base + IOAT_DCA_GREQID_OFFSET); + writel(id | IOAT_DCA_GREQID_VALID, + ioatdca->iobase + global_req_table + (i * 4)); + return i; + } + } + /* Error, ioatdma->requester_count is out of whack */ + return -EFAULT; +} + +static int ioat2_dca_remove_requester(struct dca_provider *dca, + struct device *dev) +{ + struct ioat_dca_priv *ioatdca = dca_priv(dca); + struct pci_dev *pdev; + int i; + u16 global_req_table; + + /* This implementation only supports PCI-Express */ + if (dev->bus != &pci_bus_type) + return -ENODEV; + pdev = to_pci_dev(dev); + + for (i = 0; i < ioatdca->max_requesters; i++) { + if (ioatdca->req_slots[i].pdev == pdev) { + global_req_table = + readw(ioatdca->dca_base + IOAT_DCA_GREQID_OFFSET); + writel(0, ioatdca->iobase + global_req_table + (i * 4)); + ioatdca->req_slots[i].pdev = NULL; + ioatdca->req_slots[i].rid = 0; + ioatdca->requester_count--; + return i; + } + } + return -ENODEV; +} + +static u8 ioat2_dca_get_tag(struct dca_provider *dca, int cpu) +{ + u8 tag; + + tag = ioat_dca_get_tag(dca, cpu); + tag = (~tag) & 0x1F; + return tag; +} + +static struct dca_ops ioat2_dca_ops = { + .add_requester = ioat2_dca_add_requester, + .remove_requester = ioat2_dca_remove_requester, + .get_tag = ioat2_dca_get_tag, +}; + +static int ioat2_dca_count_dca_slots(void *iobase, u16 dca_offset) +{ + int slots = 0; + u32 req; + u16 global_req_table; + + global_req_table = readw(iobase + dca_offset + IOAT_DCA_GREQID_OFFSET); + if (global_req_table == 0) + return 0; + do { + req = readl(iobase + global_req_table + (slots * sizeof(u32))); + slots++; + } while ((req & IOAT_DCA_GREQID_LASTID) == 0); + + return slots; +} + +struct dca_provider *ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase) +{ + struct dca_provider *dca; + struct ioat_dca_priv *ioatdca; + int slots; + int i; + int err; + u32 tag_map; + u16 dca_offset; + u16 csi_fsb_control; + u16 pcie_control; + u8 bit; + + if (!system_has_dca_enabled(pdev)) + return NULL; + + dca_offset = readw(iobase + IOAT_DCAOFFSET_OFFSET); + if (dca_offset == 0) + return NULL; + + slots = ioat2_dca_count_dca_slots(iobase, dca_offset); + if (slots == 0) + return NULL; + + dca = alloc_dca_provider(&ioat2_dca_ops, + sizeof(*ioatdca) + + (sizeof(struct ioat_dca_slot) * slots)); + if (!dca) + return NULL; + + ioatdca = dca_priv(dca); + ioatdca->iobase = iobase; + ioatdca->dca_base = iobase + dca_offset; + ioatdca->max_requesters = slots; + + /* some bios might not know to turn these on */ + csi_fsb_control = readw(ioatdca->dca_base + IOAT_FSB_CAP_ENABLE_OFFSET); + if ((csi_fsb_control & IOAT_FSB_CAP_ENABLE_PREFETCH) == 0) { + csi_fsb_control |= IOAT_FSB_CAP_ENABLE_PREFETCH; + writew(csi_fsb_control, + ioatdca->dca_base + IOAT_FSB_CAP_ENABLE_OFFSET); + } + pcie_control = readw(ioatdca->dca_base + IOAT_PCI_CAP_ENABLE_OFFSET); + if ((pcie_control & IOAT_PCI_CAP_ENABLE_MEMWR) == 0) { + pcie_control |= IOAT_PCI_CAP_ENABLE_MEMWR; + writew(pcie_control, + ioatdca->dca_base + IOAT_PCI_CAP_ENABLE_OFFSET); + } + + + /* TODO version, compatibility and configuration checks */ + + /* copy out the APIC to DCA tag map */ + tag_map = readl(ioatdca->dca_base + IOAT_APICID_TAG_MAP_OFFSET); + for (i = 0; i < 5; i++) { + bit = (tag_map >> (4 * i)) & 0x0f; + if (bit < 8) + ioatdca->tag_map[i] = bit | DCA_TAG_MAP_VALID; + else + ioatdca->tag_map[i] = 0; + } + + err = register_dca_provider(dca, &pdev->dev); + if (err) { + free_dca_provider(dca); + return NULL; + } + + return dca; +} diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c index 7e4a785c2dff..c1c2dcc6fc2e 100644 --- a/drivers/dma/ioat_dma.c +++ b/drivers/dma/ioat_dma.c @@ -36,18 +36,24 @@ #include "ioatdma_registers.h" #include "ioatdma_hw.h" -#define INITIAL_IOAT_DESC_COUNT 128 - #define to_ioat_chan(chan) container_of(chan, struct ioat_dma_chan, common) #define to_ioatdma_device(dev) container_of(dev, struct ioatdma_device, common) #define to_ioat_desc(lh) container_of(lh, struct ioat_desc_sw, node) #define tx_to_ioat_desc(tx) container_of(tx, struct ioat_desc_sw, async_tx) +static int ioat_pending_level = 4; +module_param(ioat_pending_level, int, 0644); +MODULE_PARM_DESC(ioat_pending_level, + "high-water mark for pushing ioat descriptors (default: 4)"); + /* internal functions */ static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan); static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan); + +static struct ioat_desc_sw * +ioat1_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan); static struct ioat_desc_sw * -ioat_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan); +ioat2_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan); static inline struct ioat_dma_chan *ioat_lookup_chan_by_index( struct ioatdma_device *device, @@ -130,6 +136,12 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device) ioat_chan->device = device; ioat_chan->reg_base = device->reg_base + (0x80 * (i + 1)); ioat_chan->xfercap = xfercap; + ioat_chan->desccount = 0; + if (ioat_chan->device->version != IOAT_VER_1_2) { + writel(IOAT_DCACTRL_CMPL_WRITE_ENABLE + | IOAT_DMA_DCA_ANY_CPU, + ioat_chan->reg_base + IOAT_DCACTRL_OFFSET); + } spin_lock_init(&ioat_chan->cleanup_lock); spin_lock_init(&ioat_chan->desc_lock); INIT_LIST_HEAD(&ioat_chan->free_desc); @@ -161,13 +173,17 @@ static void ioat_set_dest(dma_addr_t addr, tx_to_ioat_desc(tx)->dst = addr; } -static dma_cookie_t ioat_tx_submit(struct dma_async_tx_descriptor *tx) +static inline void __ioat1_dma_memcpy_issue_pending( + struct ioat_dma_chan *ioat_chan); +static inline void __ioat2_dma_memcpy_issue_pending( + struct ioat_dma_chan *ioat_chan); + +static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx) { struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan); struct ioat_desc_sw *first = tx_to_ioat_desc(tx); struct ioat_desc_sw *prev, *new; struct ioat_dma_descriptor *hw; - int append = 0; dma_cookie_t cookie; LIST_HEAD(new_chain); u32 copy; @@ -209,7 +225,7 @@ static dma_cookie_t ioat_tx_submit(struct dma_async_tx_descriptor *tx) list_add_tail(&new->node, &new_chain); desc_count++; prev = new; - } while (len && (new = ioat_dma_get_next_descriptor(ioat_chan))); + } while (len && (new = ioat1_dma_get_next_descriptor(ioat_chan))); hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS; if (new->async_tx.callback) { @@ -246,20 +262,98 @@ static dma_cookie_t ioat_tx_submit(struct dma_async_tx_descriptor *tx) first->async_tx.phys; __list_splice(&new_chain, ioat_chan->used_desc.prev); + ioat_chan->dmacount += desc_count; ioat_chan->pending += desc_count; - if (ioat_chan->pending >= 4) { - append = 1; - ioat_chan->pending = 0; - } + if (ioat_chan->pending >= ioat_pending_level) + __ioat1_dma_memcpy_issue_pending(ioat_chan); spin_unlock_bh(&ioat_chan->desc_lock); - if (append) - writeb(IOAT_CHANCMD_APPEND, - ioat_chan->reg_base + IOAT_CHANCMD_OFFSET); + return cookie; +} + +static dma_cookie_t ioat2_tx_submit(struct dma_async_tx_descriptor *tx) +{ + struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan); + struct ioat_desc_sw *first = tx_to_ioat_desc(tx); + struct ioat_desc_sw *new; + struct ioat_dma_descriptor *hw; + dma_cookie_t cookie; + u32 copy; + size_t len; + dma_addr_t src, dst; + int orig_ack; + unsigned int desc_count = 0; + + /* src and dest and len are stored in the initial descriptor */ + len = first->len; + src = first->src; + dst = first->dst; + orig_ack = first->async_tx.ack; + new = first; + + /* ioat_chan->desc_lock is still in force in version 2 path */ + + do { + copy = min((u32) len, ioat_chan->xfercap); + + new->async_tx.ack = 1; + + hw = new->hw; + hw->size = copy; + hw->ctl = 0; + hw->src_addr = src; + hw->dst_addr = dst; + + len -= copy; + dst += copy; + src += copy; + desc_count++; + } while (len && (new = ioat2_dma_get_next_descriptor(ioat_chan))); + + hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS; + if (new->async_tx.callback) { + hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_INT_GN; + if (first != new) { + /* move callback into to last desc */ + new->async_tx.callback = first->async_tx.callback; + new->async_tx.callback_param + = first->async_tx.callback_param; + first->async_tx.callback = NULL; + first->async_tx.callback_param = NULL; + } + } + + new->tx_cnt = desc_count; + new->async_tx.ack = orig_ack; /* client is in control of this ack */ + + /* store the original values for use in later cleanup */ + if (new != first) { + new->src = first->src; + new->dst = first->dst; + new->len = first->len; + } + + /* cookie incr and addition to used_list must be atomic */ + cookie = ioat_chan->common.cookie; + cookie++; + if (cookie < 0) + cookie = 1; + ioat_chan->common.cookie = new->async_tx.cookie = cookie; + + ioat_chan->dmacount += desc_count; + ioat_chan->pending += desc_count; + if (ioat_chan->pending >= ioat_pending_level) + __ioat2_dma_memcpy_issue_pending(ioat_chan); + spin_unlock_bh(&ioat_chan->desc_lock); return cookie; } +/** + * ioat_dma_alloc_descriptor - allocate and return a sw and hw descriptor pair + * @ioat_chan: the channel supplying the memory pool for the descriptors + * @flags: allocation flags + */ static struct ioat_desc_sw *ioat_dma_alloc_descriptor( struct ioat_dma_chan *ioat_chan, gfp_t flags) @@ -284,15 +378,57 @@ static struct ioat_desc_sw *ioat_dma_alloc_descriptor( dma_async_tx_descriptor_init(&desc_sw->async_tx, &ioat_chan->common); desc_sw->async_tx.tx_set_src = ioat_set_src; desc_sw->async_tx.tx_set_dest = ioat_set_dest; - desc_sw->async_tx.tx_submit = ioat_tx_submit; + switch (ioat_chan->device->version) { + case IOAT_VER_1_2: + desc_sw->async_tx.tx_submit = ioat1_tx_submit; + break; + case IOAT_VER_2_0: + desc_sw->async_tx.tx_submit = ioat2_tx_submit; + break; + } INIT_LIST_HEAD(&desc_sw->async_tx.tx_list); + desc_sw->hw = desc; desc_sw->async_tx.phys = phys; return desc_sw; } -/* returns the actual number of allocated descriptors */ +static int ioat_initial_desc_count = 256; +module_param(ioat_initial_desc_count, int, 0644); +MODULE_PARM_DESC(ioat_initial_desc_count, + "initial descriptors per channel (default: 256)"); + +/** + * ioat2_dma_massage_chan_desc - link the descriptors into a circle + * @ioat_chan: the channel to be massaged + */ +static void ioat2_dma_massage_chan_desc(struct ioat_dma_chan *ioat_chan) +{ + struct ioat_desc_sw *desc, *_desc; + + /* setup used_desc */ + ioat_chan->used_desc.next = ioat_chan->free_desc.next; + ioat_chan->used_desc.prev = NULL; + + /* pull free_desc out of the circle so that every node is a hw + * descriptor, but leave it pointing to the list + */ + ioat_chan->free_desc.prev->next = ioat_chan->free_desc.next; + ioat_chan->free_desc.next->prev = ioat_chan->free_desc.prev; + + /* circle link the hw descriptors */ + desc = to_ioat_desc(ioat_chan->free_desc.next); + desc->hw->next = to_ioat_desc(desc->node.next)->async_tx.phys; + list_for_each_entry_safe(desc, _desc, ioat_chan->free_desc.next, node) { + desc->hw->next = to_ioat_desc(desc->node.next)->async_tx.phys; + } +} + +/** + * ioat_dma_alloc_chan_resources - returns the number of allocated descriptors + * @chan: the channel to be filled out + */ static int ioat_dma_alloc_chan_resources(struct dma_chan *chan) { struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); @@ -304,7 +440,7 @@ static int ioat_dma_alloc_chan_resources(struct dma_chan *chan) /* have we already been set up? */ if (!list_empty(&ioat_chan->free_desc)) - return INITIAL_IOAT_DESC_COUNT; + return ioat_chan->desccount; /* Setup register to interrupt and write completion status on error */ chanctrl = IOAT_CHANCTRL_ERR_INT_EN | @@ -320,7 +456,7 @@ static int ioat_dma_alloc_chan_resources(struct dma_chan *chan) } /* Allocate descriptors */ - for (i = 0; i < INITIAL_IOAT_DESC_COUNT; i++) { + for (i = 0; i < ioat_initial_desc_count; i++) { desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_KERNEL); if (!desc) { dev_err(&ioat_chan->device->pdev->dev, @@ -330,7 +466,10 @@ static int ioat_dma_alloc_chan_resources(struct dma_chan *chan) list_add_tail(&desc->node, &tmp_list); } spin_lock_bh(&ioat_chan->desc_lock); + ioat_chan->desccount = i; list_splice(&tmp_list, &ioat_chan->free_desc); + if (ioat_chan->device->version != IOAT_VER_1_2) + ioat2_dma_massage_chan_desc(ioat_chan); spin_unlock_bh(&ioat_chan->desc_lock); /* allocate a completion writeback area */ @@ -347,10 +486,14 @@ static int ioat_dma_alloc_chan_resources(struct dma_chan *chan) ioat_chan->reg_base + IOAT_CHANCMP_OFFSET_HIGH); tasklet_enable(&ioat_chan->cleanup_task); - ioat_dma_start_null_desc(ioat_chan); - return i; + ioat_dma_start_null_desc(ioat_chan); /* give chain to dma device */ + return ioat_chan->desccount; } +/** + * ioat_dma_free_chan_resources - release all the descriptors + * @chan: the channel to be cleaned + */ static void ioat_dma_free_chan_resources(struct dma_chan *chan) { struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); @@ -364,22 +507,45 @@ static void ioat_dma_free_chan_resources(struct dma_chan *chan) /* Delay 100ms after reset to allow internal DMA logic to quiesce * before removing DMA descriptor resources. */ - writeb(IOAT_CHANCMD_RESET, ioat_chan->reg_base + IOAT_CHANCMD_OFFSET); + writeb(IOAT_CHANCMD_RESET, + ioat_chan->reg_base + + IOAT_CHANCMD_OFFSET(ioat_chan->device->version)); mdelay(100); spin_lock_bh(&ioat_chan->desc_lock); - list_for_each_entry_safe(desc, _desc, &ioat_chan->used_desc, node) { - in_use_descs++; - list_del(&desc->node); - pci_pool_free(ioatdma_device->dma_pool, desc->hw, - desc->async_tx.phys); - kfree(desc); - } - list_for_each_entry_safe(desc, _desc, &ioat_chan->free_desc, node) { - list_del(&desc->node); + switch (ioat_chan->device->version) { + case IOAT_VER_1_2: + list_for_each_entry_safe(desc, _desc, + &ioat_chan->used_desc, node) { + in_use_descs++; + list_del(&desc->node); + pci_pool_free(ioatdma_device->dma_pool, desc->hw, + desc->async_tx.phys); + kfree(desc); + } + list_for_each_entry_safe(desc, _desc, + &ioat_chan->free_desc, node) { + list_del(&desc->node); + pci_pool_free(ioatdma_device->dma_pool, desc->hw, + desc->async_tx.phys); + kfree(desc); + } + break; + case IOAT_VER_2_0: + list_for_each_entry_safe(desc, _desc, + ioat_chan->free_desc.next, node) { + list_del(&desc->node); + pci_pool_free(ioatdma_device->dma_pool, desc->hw, + desc->async_tx.phys); + kfree(desc); + } + desc = to_ioat_desc(ioat_chan->free_desc.next); pci_pool_free(ioatdma_device->dma_pool, desc->hw, desc->async_tx.phys); kfree(desc); + INIT_LIST_HEAD(&ioat_chan->free_desc); + INIT_LIST_HEAD(&ioat_chan->used_desc); + break; } spin_unlock_bh(&ioat_chan->desc_lock); @@ -395,6 +561,7 @@ static void ioat_dma_free_chan_resources(struct dma_chan *chan) ioat_chan->last_completion = ioat_chan->completion_addr = 0; ioat_chan->pending = 0; + ioat_chan->dmacount = 0; } /** @@ -406,7 +573,7 @@ static void ioat_dma_free_chan_resources(struct dma_chan *chan) * has run out. */ static struct ioat_desc_sw * -ioat_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan) +ioat1_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan) { struct ioat_desc_sw *new = NULL; @@ -425,7 +592,82 @@ ioat_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan) return new; } -static struct dma_async_tx_descriptor *ioat_dma_prep_memcpy( +static struct ioat_desc_sw * +ioat2_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan) +{ + struct ioat_desc_sw *new = NULL; + + /* + * used.prev points to where to start processing + * used.next points to next free descriptor + * if used.prev == NULL, there are none waiting to be processed + * if used.next == used.prev.prev, there is only one free descriptor, + * and we need to use it to as a noop descriptor before + * linking in a new set of descriptors, since the device + * has probably already read the pointer to it + */ + if (ioat_chan->used_desc.prev && + ioat_chan->used_desc.next == ioat_chan->used_desc.prev->prev) { + + struct ioat_desc_sw *desc = NULL; + struct ioat_desc_sw *noop_desc = NULL; + int i; + + /* set up the noop descriptor */ + noop_desc = to_ioat_desc(ioat_chan->used_desc.next); + noop_desc->hw->size = 0; + noop_desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL; + noop_desc->hw->src_addr = 0; + noop_desc->hw->dst_addr = 0; + + ioat_chan->used_desc.next = ioat_chan->used_desc.next->next; + ioat_chan->pending++; + ioat_chan->dmacount++; + + /* get a few more descriptors */ + for (i = 16; i; i--) { + desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_ATOMIC); + BUG_ON(!desc); + list_add_tail(&desc->node, ioat_chan->used_desc.next); + + desc->hw->next + = to_ioat_desc(desc->node.next)->async_tx.phys; + to_ioat_desc(desc->node.prev)->hw->next + = desc->async_tx.phys; + ioat_chan->desccount++; + } + + ioat_chan->used_desc.next = noop_desc->node.next; + } + new = to_ioat_desc(ioat_chan->used_desc.next); + prefetch(new); + ioat_chan->used_desc.next = new->node.next; + + if (ioat_chan->used_desc.prev == NULL) + ioat_chan->used_desc.prev = &new->node; + + prefetch(new->hw); + return new; +} + +static struct ioat_desc_sw *ioat_dma_get_next_descriptor( + struct ioat_dma_chan *ioat_chan) +{ + if (!ioat_chan) + return NULL; + + switch (ioat_chan->device->version) { + case IOAT_VER_1_2: + return ioat1_dma_get_next_descriptor(ioat_chan); + break; + case IOAT_VER_2_0: + return ioat2_dma_get_next_descriptor(ioat_chan); + break; + } + return NULL; +} + +static struct dma_async_tx_descriptor *ioat1_dma_prep_memcpy( struct dma_chan *chan, size_t len, int int_en) @@ -441,19 +683,62 @@ static struct dma_async_tx_descriptor *ioat_dma_prep_memcpy( return new ? &new->async_tx : NULL; } +static struct dma_async_tx_descriptor *ioat2_dma_prep_memcpy( + struct dma_chan *chan, + size_t len, + int int_en) +{ + struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); + struct ioat_desc_sw *new; + + spin_lock_bh(&ioat_chan->desc_lock); + new = ioat2_dma_get_next_descriptor(ioat_chan); + new->len = len; + + /* leave ioat_chan->desc_lock set in version 2 path */ + return new ? &new->async_tx : NULL; +} + + /** * ioat_dma_memcpy_issue_pending - push potentially unrecognized appended * descriptors to hw * @chan: DMA channel handle */ -static void ioat_dma_memcpy_issue_pending(struct dma_chan *chan) +static inline void __ioat1_dma_memcpy_issue_pending( + struct ioat_dma_chan *ioat_chan) +{ + ioat_chan->pending = 0; + writeb(IOAT_CHANCMD_APPEND, ioat_chan->reg_base + IOAT1_CHANCMD_OFFSET); +} + +static void ioat1_dma_memcpy_issue_pending(struct dma_chan *chan) { struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); if (ioat_chan->pending != 0) { - ioat_chan->pending = 0; - writeb(IOAT_CHANCMD_APPEND, - ioat_chan->reg_base + IOAT_CHANCMD_OFFSET); + spin_lock_bh(&ioat_chan->desc_lock); + __ioat1_dma_memcpy_issue_pending(ioat_chan); + spin_unlock_bh(&ioat_chan->desc_lock); + } +} + +static inline void __ioat2_dma_memcpy_issue_pending( + struct ioat_dma_chan *ioat_chan) +{ + ioat_chan->pending = 0; + writew(ioat_chan->dmacount, + ioat_chan->reg_base + IOAT_CHAN_DMACOUNT_OFFSET); +} + +static void ioat2_dma_memcpy_issue_pending(struct dma_chan *chan) +{ + struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); + + if (ioat_chan->pending != 0) { + spin_lock_bh(&ioat_chan->desc_lock); + __ioat2_dma_memcpy_issue_pending(ioat_chan); + spin_unlock_bh(&ioat_chan->desc_lock); } } @@ -465,11 +750,17 @@ static void ioat_dma_cleanup_tasklet(unsigned long data) chan->reg_base + IOAT_CHANCTRL_OFFSET); } +/** + * ioat_dma_memcpy_cleanup - cleanup up finished descriptors + * @chan: ioat channel to be cleaned up + */ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan) { unsigned long phys_complete; struct ioat_desc_sw *desc, *_desc; dma_cookie_t cookie = 0; + unsigned long desc_phys; + struct ioat_desc_sw *latest_desc; prefetch(ioat_chan->completion_virt); @@ -507,56 +798,115 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan) cookie = 0; spin_lock_bh(&ioat_chan->desc_lock); - list_for_each_entry_safe(desc, _desc, &ioat_chan->used_desc, node) { - - /* - * Incoming DMA requests may use multiple descriptors, due to - * exceeding xfercap, perhaps. If so, only the last one will - * have a cookie, and require unmapping. - */ - if (desc->async_tx.cookie) { - cookie = desc->async_tx.cookie; + switch (ioat_chan->device->version) { + case IOAT_VER_1_2: + list_for_each_entry_safe(desc, _desc, + &ioat_chan->used_desc, node) { /* - * yes we are unmapping both _page and _single alloc'd - * regions with unmap_page. Is this *really* that bad? + * Incoming DMA requests may use multiple descriptors, + * due to exceeding xfercap, perhaps. If so, only the + * last one will have a cookie, and require unmapping. */ - pci_unmap_page(ioat_chan->device->pdev, - pci_unmap_addr(desc, dst), - pci_unmap_len(desc, len), - PCI_DMA_FROMDEVICE); - pci_unmap_page(ioat_chan->device->pdev, - pci_unmap_addr(desc, src), - pci_unmap_len(desc, len), - PCI_DMA_TODEVICE); - if (desc->async_tx.callback) { - desc->async_tx.callback( - desc->async_tx.callback_param); - desc->async_tx.callback = NULL; + if (desc->async_tx.cookie) { + cookie = desc->async_tx.cookie; + + /* + * yes we are unmapping both _page and _single + * alloc'd regions with unmap_page. Is this + * *really* that bad? + */ + pci_unmap_page(ioat_chan->device->pdev, + pci_unmap_addr(desc, dst), + pci_unmap_len(desc, len), + PCI_DMA_FROMDEVICE); + pci_unmap_page(ioat_chan->device->pdev, + pci_unmap_addr(desc, src), + pci_unmap_len(desc, len), + PCI_DMA_TODEVICE); + + if (desc->async_tx.callback) { + desc->async_tx.callback(desc->async_tx.callback_param); + desc->async_tx.callback = NULL; + } } - } - if (desc->async_tx.phys != phys_complete) { - /* - * a completed entry, but not the last, so cleanup - * if the client is done with the descriptor - */ - if (desc->async_tx.ack) { - list_del(&desc->node); - list_add_tail(&desc->node, - &ioat_chan->free_desc); - } else + if (desc->async_tx.phys != phys_complete) { + /* + * a completed entry, but not the last, so clean + * up if the client is done with the descriptor + */ + if (desc->async_tx.ack) { + list_del(&desc->node); + list_add_tail(&desc->node, + &ioat_chan->free_desc); + } else + desc->async_tx.cookie = 0; + } else { + /* + * last used desc. Do not remove, so we can + * append from it, but don't look at it next + * time, either + */ desc->async_tx.cookie = 0; - } else { - /* - * last used desc. Do not remove, so we can append from - * it, but don't look at it next time, either - */ - desc->async_tx.cookie = 0; - /* TODO check status bits? */ + /* TODO check status bits? */ + break; + } + } + break; + case IOAT_VER_2_0: + /* has some other thread has already cleaned up? */ + if (ioat_chan->used_desc.prev == NULL) break; + + /* work backwards to find latest finished desc */ + desc = to_ioat_desc(ioat_chan->used_desc.next); + latest_desc = NULL; + do { + desc = to_ioat_desc(desc->node.prev); + desc_phys = (unsigned long)desc->async_tx.phys + & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR; + if (desc_phys == phys_complete) { + latest_desc = desc; + break; + } + } while (&desc->node != ioat_chan->used_desc.prev); + + if (latest_desc != NULL) { + + /* work forwards to clear finished descriptors */ + for (desc = to_ioat_desc(ioat_chan->used_desc.prev); + &desc->node != latest_desc->node.next && + &desc->node != ioat_chan->used_desc.next; + desc = to_ioat_desc(desc->node.next)) { + if (desc->async_tx.cookie) { + cookie = desc->async_tx.cookie; + desc->async_tx.cookie = 0; + + pci_unmap_page(ioat_chan->device->pdev, + pci_unmap_addr(desc, dst), + pci_unmap_len(desc, len), + PCI_DMA_FROMDEVICE); + pci_unmap_page(ioat_chan->device->pdev, + pci_unmap_addr(desc, src), + pci_unmap_len(desc, len), + PCI_DMA_TODEVICE); + + if (desc->async_tx.callback) { + desc->async_tx.callback(desc->async_tx.callback_param); + desc->async_tx.callback = NULL; + } + } + } + + /* move used.prev up beyond those that are finished */ + if (&desc->node == ioat_chan->used_desc.next) + ioat_chan->used_desc.prev = NULL; + else + ioat_chan->used_desc.prev = &desc->node; } + break; } spin_unlock_bh(&ioat_chan->desc_lock); @@ -621,8 +971,6 @@ static enum dma_status ioat_dma_is_complete(struct dma_chan *chan, return dma_async_is_complete(cookie, last_complete, last_used); } -/* PCI API */ - static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan) { struct ioat_desc_sw *desc; @@ -633,21 +981,34 @@ static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan) desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL | IOAT_DMA_DESCRIPTOR_CTL_INT_GN | IOAT_DMA_DESCRIPTOR_CTL_CP_STS; - desc->hw->next = 0; desc->hw->size = 0; desc->hw->src_addr = 0; desc->hw->dst_addr = 0; desc->async_tx.ack = 1; - - list_add_tail(&desc->node, &ioat_chan->used_desc); + switch (ioat_chan->device->version) { + case IOAT_VER_1_2: + desc->hw->next = 0; + list_add_tail(&desc->node, &ioat_chan->used_desc); + + writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF, + ioat_chan->reg_base + IOAT1_CHAINADDR_OFFSET_LOW); + writel(((u64) desc->async_tx.phys) >> 32, + ioat_chan->reg_base + IOAT1_CHAINADDR_OFFSET_HIGH); + + writeb(IOAT_CHANCMD_START, ioat_chan->reg_base + + IOAT_CHANCMD_OFFSET(ioat_chan->device->version)); + break; + case IOAT_VER_2_0: + writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF, + ioat_chan->reg_base + IOAT2_CHAINADDR_OFFSET_LOW); + writel(((u64) desc->async_tx.phys) >> 32, + ioat_chan->reg_base + IOAT2_CHAINADDR_OFFSET_HIGH); + + ioat_chan->dmacount++; + __ioat2_dma_memcpy_issue_pending(ioat_chan); + break; + } spin_unlock_bh(&ioat_chan->desc_lock); - - writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF, - ioat_chan->reg_base + IOAT_CHAINADDR_OFFSET_LOW); - writel(((u64) desc->async_tx.phys) >> 32, - ioat_chan->reg_base + IOAT_CHAINADDR_OFFSET_HIGH); - - writeb(IOAT_CHANCMD_START, ioat_chan->reg_base + IOAT_CHANCMD_OFFSET); } /* @@ -693,14 +1054,14 @@ static int ioat_dma_self_test(struct ioatdma_device *device) dma_chan = container_of(device->common.channels.next, struct dma_chan, device_node); - if (ioat_dma_alloc_chan_resources(dma_chan) < 1) { + if (device->common.device_alloc_chan_resources(dma_chan) < 1) { dev_err(&device->pdev->dev, "selftest cannot allocate chan resource\n"); err = -ENODEV; goto out; } - tx = ioat_dma_prep_memcpy(dma_chan, IOAT_TEST_SIZE, 0); + tx = device->common.device_prep_dma_memcpy(dma_chan, IOAT_TEST_SIZE, 0); if (!tx) { dev_err(&device->pdev->dev, "Self-test prep failed, disabling\n"); @@ -710,24 +1071,25 @@ static int ioat_dma_self_test(struct ioatdma_device *device) async_tx_ack(tx); addr = dma_map_single(dma_chan->device->dev, src, IOAT_TEST_SIZE, - DMA_TO_DEVICE); - ioat_set_src(addr, tx, 0); + DMA_TO_DEVICE); + tx->tx_set_src(addr, tx, 0); addr = dma_map_single(dma_chan->device->dev, dest, IOAT_TEST_SIZE, - DMA_FROM_DEVICE); - ioat_set_dest(addr, tx, 0); + DMA_FROM_DEVICE); + tx->tx_set_dest(addr, tx, 0); tx->callback = ioat_dma_test_callback; tx->callback_param = (void *)0x8086; - cookie = ioat_tx_submit(tx); + cookie = tx->tx_submit(tx); if (cookie < 0) { dev_err(&device->pdev->dev, "Self-test setup failed, disabling\n"); err = -ENODEV; goto free_resources; } - ioat_dma_memcpy_issue_pending(dma_chan); + device->common.device_issue_pending(dma_chan); msleep(1); - if (ioat_dma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) { + if (device->common.device_is_tx_complete(dma_chan, cookie, NULL, NULL) + != DMA_SUCCESS) { dev_err(&device->pdev->dev, "Self-test copy timed out, disabling\n"); err = -ENODEV; @@ -741,7 +1103,7 @@ static int ioat_dma_self_test(struct ioatdma_device *device) } free_resources: - ioat_dma_free_chan_resources(dma_chan); + device->common.device_free_chan_resources(dma_chan); out: kfree(src); kfree(dest); @@ -941,16 +1303,28 @@ struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev, INIT_LIST_HEAD(&device->common.channels); ioat_dma_enumerate_channels(device); - dma_cap_set(DMA_MEMCPY, device->common.cap_mask); device->common.device_alloc_chan_resources = ioat_dma_alloc_chan_resources; device->common.device_free_chan_resources = ioat_dma_free_chan_resources; - device->common.device_prep_dma_memcpy = ioat_dma_prep_memcpy; + device->common.dev = &pdev->dev; + + dma_cap_set(DMA_MEMCPY, device->common.cap_mask); device->common.device_is_tx_complete = ioat_dma_is_complete; - device->common.device_issue_pending = ioat_dma_memcpy_issue_pending; device->common.device_dependency_added = ioat_dma_dependency_added; - device->common.dev = &pdev->dev; + switch (device->version) { + case IOAT_VER_1_2: + device->common.device_prep_dma_memcpy = ioat1_dma_prep_memcpy; + device->common.device_issue_pending = + ioat1_dma_memcpy_issue_pending; + break; + case IOAT_VER_2_0: + device->common.device_prep_dma_memcpy = ioat2_dma_prep_memcpy; + device->common.device_issue_pending = + ioat2_dma_memcpy_issue_pending; + break; + } + dev_err(&device->pdev->dev, "Intel(R) I/OAT DMA Engine found," " %d channels, device version 0x%02x, driver version %s\n", diff --git a/drivers/dma/ioatdma.h b/drivers/dma/ioatdma.h index 5f9881e7b0ed..b668234ef654 100644 --- a/drivers/dma/ioatdma.h +++ b/drivers/dma/ioatdma.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved. + * Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -28,7 +28,7 @@ #include <linux/cache.h> #include <linux/pci_ids.h> -#define IOAT_DMA_VERSION "1.26" +#define IOAT_DMA_VERSION "2.04" enum ioat_interrupt { none = 0, @@ -39,6 +39,8 @@ enum ioat_interrupt { }; #define IOAT_LOW_COMPLETION_MASK 0xffffffc0 +#define IOAT_DMA_DCA_ANY_CPU ~0 + /** * struct ioatdma_device - internal representation of a IOAT device @@ -47,6 +49,9 @@ enum ioat_interrupt { * @dma_pool: for allocating DMA descriptors * @common: embedded struct dma_device * @version: version of ioatdma device + * @irq_mode: which style irq to use + * @msix_entries: irq handlers + * @idx: per channel data */ struct ioatdma_device { @@ -63,23 +68,7 @@ struct ioatdma_device { /** * struct ioat_dma_chan - internal representation of a DMA channel - * @device: - * @reg_base: - * @sw_in_use: - * @completion: - * @completion_low: - * @completion_high: - * @completed_cookie: last cookie seen completed on cleanup - * @cookie: value of last cookie given to client - * @last_completion: - * @xfercap: - * @desc_lock: - * @free_desc: - * @used_desc: - * @resource: - * @device_node: */ - struct ioat_dma_chan { void __iomem *reg_base; @@ -95,6 +84,8 @@ struct ioat_dma_chan { struct list_head used_desc; int pending; + int dmacount; + int desccount; struct ioatdma_device *device; struct dma_chan common; @@ -134,12 +125,13 @@ struct ioat_desc_sw { struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev, void __iomem *iobase); void ioat_dma_remove(struct ioatdma_device *device); -struct dca_provider *ioat_dca_init(struct pci_dev *pdev, - void __iomem *iobase); +struct dca_provider *ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase); +struct dca_provider *ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase); #else #define ioat_dma_probe(pdev, iobase) NULL #define ioat_dma_remove(device) do { } while (0) #define ioat_dca_init(pdev, iobase) NULL +#define ioat2_dca_init(pdev, iobase) NULL #endif #endif /* IOATDMA_H */ diff --git a/drivers/dma/ioatdma_hw.h b/drivers/dma/ioatdma_hw.h index 9e7434e1551f..dd470fa91d86 100644 --- a/drivers/dma/ioatdma_hw.h +++ b/drivers/dma/ioatdma_hw.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved. + * Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -22,12 +22,19 @@ #define _IOAT_HW_H_ /* PCI Configuration Space Values */ -#define IOAT_PCI_VID 0x8086 -#define IOAT_PCI_DID 0x1A38 -#define IOAT_PCI_RID 0x00 -#define IOAT_PCI_SVID 0x8086 -#define IOAT_PCI_SID 0x8086 -#define IOAT_VER_1_2 0x12 /* Version 1.2 */ +#define IOAT_PCI_VID 0x8086 + +/* CB device ID's */ +#define IOAT_PCI_DID_5000 0x1A38 +#define IOAT_PCI_DID_CNB 0x360B +#define IOAT_PCI_DID_SCNB 0x65FF +#define IOAT_PCI_DID_SNB 0x402F + +#define IOAT_PCI_RID 0x00 +#define IOAT_PCI_SVID 0x8086 +#define IOAT_PCI_SID 0x8086 +#define IOAT_VER_1_2 0x12 /* Version 1.2 */ +#define IOAT_VER_2_0 0x20 /* Version 2.0 */ struct ioat_dma_descriptor { uint32_t size; @@ -47,6 +54,16 @@ struct ioat_dma_descriptor { #define IOAT_DMA_DESCRIPTOR_CTL_CP_STS 0x00000008 #define IOAT_DMA_DESCRIPTOR_CTL_FRAME 0x00000010 #define IOAT_DMA_DESCRIPTOR_NUL 0x00000020 -#define IOAT_DMA_DESCRIPTOR_OPCODE 0xFF000000 +#define IOAT_DMA_DESCRIPTOR_CTL_SP_BRK 0x00000040 +#define IOAT_DMA_DESCRIPTOR_CTL_DP_BRK 0x00000080 +#define IOAT_DMA_DESCRIPTOR_CTL_BNDL 0x00000100 +#define IOAT_DMA_DESCRIPTOR_CTL_DCA 0x00000200 +#define IOAT_DMA_DESCRIPTOR_CTL_BUFHINT 0x00000400 + +#define IOAT_DMA_DESCRIPTOR_CTL_OPCODE_CONTEXT 0xFF000000 +#define IOAT_DMA_DESCRIPTOR_CTL_OPCODE_DMA 0x00000000 + +#define IOAT_DMA_DESCRIPTOR_CTL_CONTEXT_DCA 0x00000001 +#define IOAT_DMA_DESCRIPTOR_CTL_OPCODE_MASK 0xFF000000 #endif diff --git a/drivers/dma/ioatdma_registers.h b/drivers/dma/ioatdma_registers.h index baaab5ea146a..9832d7ebd931 100644 --- a/drivers/dma/ioatdma_registers.h +++ b/drivers/dma/ioatdma_registers.h @@ -42,26 +42,25 @@ #define IOAT_INTRCTRL_MASTER_INT_EN 0x01 /* Master Interrupt Enable */ #define IOAT_INTRCTRL_INT_STATUS 0x02 /* ATTNSTATUS -or- Channel Int */ #define IOAT_INTRCTRL_INT 0x04 /* INT_STATUS -and- MASTER_INT_EN */ -#define IOAT_INTRCTRL_MSIX_VECTOR_CONTROL 0x08 /* Enable all MSI-X vectors */ +#define IOAT_INTRCTRL_MSIX_VECTOR_CONTROL 0x08 /* Enable all MSI-X vectors */ #define IOAT_ATTNSTATUS_OFFSET 0x04 /* Each bit is a channel */ #define IOAT_VER_OFFSET 0x08 /* 8-bit */ #define IOAT_VER_MAJOR_MASK 0xF0 #define IOAT_VER_MINOR_MASK 0x0F -#define GET_IOAT_VER_MAJOR(x) ((x) & IOAT_VER_MAJOR_MASK) +#define GET_IOAT_VER_MAJOR(x) (((x) & IOAT_VER_MAJOR_MASK) >> 4) #define GET_IOAT_VER_MINOR(x) ((x) & IOAT_VER_MINOR_MASK) #define IOAT_PERPORTOFFSET_OFFSET 0x0A /* 16-bit */ #define IOAT_INTRDELAY_OFFSET 0x0C /* 16-bit */ #define IOAT_INTRDELAY_INT_DELAY_MASK 0x3FFF /* Interrupt Delay Time */ -#define IOAT_INTRDELAY_COALESE_SUPPORT 0x8000 /* Interrupt Coalesing Supported */ +#define IOAT_INTRDELAY_COALESE_SUPPORT 0x8000 /* Interrupt Coalescing Supported */ #define IOAT_DEVICE_STATUS_OFFSET 0x0E /* 16-bit */ #define IOAT_DEVICE_STATUS_DEGRADED_MODE 0x0001 - #define IOAT_CHANNEL_MMIO_SIZE 0x80 /* Each Channel MMIO space is this size */ /* DMA Channel Registers */ @@ -74,25 +73,101 @@ #define IOAT_CHANCTRL_ERR_COMPLETION_EN 0x0004 #define IOAT_CHANCTRL_INT_DISABLE 0x0001 -#define IOAT_DMA_COMP_OFFSET 0x02 /* 16-bit DMA channel compatability */ -#define IOAT_DMA_COMP_V1 0x0001 /* Compatability with DMA version 1 */ - -#define IOAT_CHANSTS_OFFSET 0x04 /* 64-bit Channel Status Register */ -#define IOAT_CHANSTS_OFFSET_LOW 0x04 -#define IOAT_CHANSTS_OFFSET_HIGH 0x08 -#define IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR 0xFFFFFFFFFFFFFFC0UL +#define IOAT_DMA_COMP_OFFSET 0x02 /* 16-bit DMA channel compatibility */ +#define IOAT_DMA_COMP_V1 0x0001 /* Compatibility with DMA version 1 */ +#define IOAT_DMA_COMP_V2 0x0002 /* Compatibility with DMA version 2 */ + + +#define IOAT1_CHANSTS_OFFSET 0x04 /* 64-bit Channel Status Register */ +#define IOAT2_CHANSTS_OFFSET 0x08 /* 64-bit Channel Status Register */ +#define IOAT_CHANSTS_OFFSET(ver) ((ver) < IOAT_VER_2_0 \ + ? IOAT1_CHANSTS_OFFSET : IOAT2_CHANSTS_OFFSET) +#define IOAT1_CHANSTS_OFFSET_LOW 0x04 +#define IOAT2_CHANSTS_OFFSET_LOW 0x08 +#define IOAT_CHANSTS_OFFSET_LOW(ver) ((ver) < IOAT_VER_2_0 \ + ? IOAT1_CHANSTS_OFFSET_LOW : IOAT2_CHANSTS_OFFSET_LOW) +#define IOAT1_CHANSTS_OFFSET_HIGH 0x08 +#define IOAT2_CHANSTS_OFFSET_HIGH 0x0C +#define IOAT_CHANSTS_OFFSET_HIGH(ver) ((ver) < IOAT_VER_2_0 \ + ? IOAT1_CHANSTS_OFFSET_HIGH : IOAT2_CHANSTS_OFFSET_HIGH) +#define IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR ~0x3F #define IOAT_CHANSTS_SOFT_ERR 0x0000000000000010 +#define IOAT_CHANSTS_UNAFFILIATED_ERR 0x0000000000000008 #define IOAT_CHANSTS_DMA_TRANSFER_STATUS 0x0000000000000007 #define IOAT_CHANSTS_DMA_TRANSFER_STATUS_ACTIVE 0x0 #define IOAT_CHANSTS_DMA_TRANSFER_STATUS_DONE 0x1 #define IOAT_CHANSTS_DMA_TRANSFER_STATUS_SUSPENDED 0x2 #define IOAT_CHANSTS_DMA_TRANSFER_STATUS_HALTED 0x3 -#define IOAT_CHAINADDR_OFFSET 0x0C /* 64-bit Descriptor Chain Address Register */ -#define IOAT_CHAINADDR_OFFSET_LOW 0x0C -#define IOAT_CHAINADDR_OFFSET_HIGH 0x10 -#define IOAT_CHANCMD_OFFSET 0x14 /* 8-bit DMA Channel Command Register */ + +#define IOAT_CHAN_DMACOUNT_OFFSET 0x06 /* 16-bit DMA Count register */ + +#define IOAT_DCACTRL_OFFSET 0x30 /* 32 bit Direct Cache Access Control Register */ +#define IOAT_DCACTRL_CMPL_WRITE_ENABLE 0x10000 +#define IOAT_DCACTRL_TARGET_CPU_MASK 0xFFFF /* APIC ID */ + +/* CB DCA Memory Space Registers */ +#define IOAT_DCAOFFSET_OFFSET 0x14 +/* CB_BAR + IOAT_DCAOFFSET value */ +#define IOAT_DCA_VER_OFFSET 0x00 +#define IOAT_DCA_VER_MAJOR_MASK 0xF0 +#define IOAT_DCA_VER_MINOR_MASK 0x0F + +#define IOAT_DCA_COMP_OFFSET 0x02 +#define IOAT_DCA_COMP_V1 0x1 + +#define IOAT_FSB_CAPABILITY_OFFSET 0x04 +#define IOAT_FSB_CAPABILITY_PREFETCH 0x1 + +#define IOAT_PCI_CAPABILITY_OFFSET 0x06 +#define IOAT_PCI_CAPABILITY_MEMWR 0x1 + +#define IOAT_FSB_CAP_ENABLE_OFFSET 0x08 +#define IOAT_FSB_CAP_ENABLE_PREFETCH 0x1 + +#define IOAT_PCI_CAP_ENABLE_OFFSET 0x0A +#define IOAT_PCI_CAP_ENABLE_MEMWR 0x1 + +#define IOAT_APICID_TAG_MAP_OFFSET 0x0C +#define IOAT_APICID_TAG_MAP_TAG0 0x0000000F +#define IOAT_APICID_TAG_MAP_TAG0_SHIFT 0 +#define IOAT_APICID_TAG_MAP_TAG1 0x000000F0 +#define IOAT_APICID_TAG_MAP_TAG1_SHIFT 4 +#define IOAT_APICID_TAG_MAP_TAG2 0x00000F00 +#define IOAT_APICID_TAG_MAP_TAG2_SHIFT 8 +#define IOAT_APICID_TAG_MAP_TAG3 0x0000F000 +#define IOAT_APICID_TAG_MAP_TAG3_SHIFT 12 +#define IOAT_APICID_TAG_MAP_TAG4 0x000F0000 +#define IOAT_APICID_TAG_MAP_TAG4_SHIFT 16 +#define IOAT_APICID_TAG_CB2_VALID 0x8080808080 + +#define IOAT_DCA_GREQID_OFFSET 0x10 +#define IOAT_DCA_GREQID_SIZE 0x04 +#define IOAT_DCA_GREQID_MASK 0xFFFF +#define IOAT_DCA_GREQID_IGNOREFUN 0x10000000 +#define IOAT_DCA_GREQID_VALID 0x20000000 +#define IOAT_DCA_GREQID_LASTID 0x80000000 + + + +#define IOAT1_CHAINADDR_OFFSET 0x0C /* 64-bit Descriptor Chain Address Register */ +#define IOAT2_CHAINADDR_OFFSET 0x10 /* 64-bit Descriptor Chain Address Register */ +#define IOAT_CHAINADDR_OFFSET(ver) ((ver) < IOAT_VER_2_0 \ + ? IOAT1_CHAINADDR_OFFSET : IOAT2_CHAINADDR_OFFSET) +#define IOAT1_CHAINADDR_OFFSET_LOW 0x0C +#define IOAT2_CHAINADDR_OFFSET_LOW 0x10 +#define IOAT_CHAINADDR_OFFSET_LOW(ver) ((ver) < IOAT_VER_2_0 \ + ? IOAT1_CHAINADDR_OFFSET_LOW : IOAT2_CHAINADDR_OFFSET_LOW) +#define IOAT1_CHAINADDR_OFFSET_HIGH 0x10 +#define IOAT2_CHAINADDR_OFFSET_HIGH 0x14 +#define IOAT_CHAINADDR_OFFSET_HIGH(ver) ((ver) < IOAT_VER_2_0 \ + ? IOAT1_CHAINADDR_OFFSET_HIGH : IOAT2_CHAINADDR_OFFSET_HIGH) + +#define IOAT1_CHANCMD_OFFSET 0x14 /* 8-bit DMA Channel Command Register */ +#define IOAT2_CHANCMD_OFFSET 0x04 /* 8-bit DMA Channel Command Register */ +#define IOAT_CHANCMD_OFFSET(ver) ((ver) < IOAT_VER_2_0 \ + ? IOAT1_CHANCMD_OFFSET : IOAT2_CHANCMD_OFFSET) #define IOAT_CHANCMD_RESET 0x20 #define IOAT_CHANCMD_RESUME 0x10 #define IOAT_CHANCMD_ABORT 0x08 @@ -124,6 +199,7 @@ #define IOAT_CHANERR_COMPLETION_ADDR_ERR 0x1000 #define IOAT_CHANERR_INT_CONFIGURATION_ERR 0x2000 #define IOAT_CHANERR_SOFT_ERR 0x4000 +#define IOAT_CHANERR_UNAFFILIATED_ERR 0x8000 #define IOAT_CHANERR_MASK_OFFSET 0x2C /* 32-bit Channel Error Register */ diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index 96f7e63e3996..a1f24c42d5ff 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -1462,7 +1462,7 @@ MODULE_DEVICE_TABLE(pci, i5000_pci_tbl); * */ static struct pci_driver i5000_driver = { - .name = __stringify(KBUILD_BASENAME), + .name = KBUILD_BASENAME, .probe = i5000_init_one, .remove = __devexit_p(i5000_remove_one), .id_table = i5000_pci_tbl, diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index 5596df65c8ed..624ff3e082f6 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c @@ -650,13 +650,14 @@ static void sbp2_login(struct work_struct *work) if (sbp2_send_management_orb(lu, node_id, generation, SBP2_LOGIN_REQUEST, lu->lun, &response) < 0) { if (lu->retries++ < 5) { - queue_delayed_work(sbp2_wq, &lu->work, - DIV_ROUND_UP(HZ, 5)); + if (queue_delayed_work(sbp2_wq, &lu->work, + DIV_ROUND_UP(HZ, 5))) + kref_get(&lu->tgt->kref); } else { fw_error("failed to login to %s LUN %04x\n", unit->device.bus_id, lu->lun); - kref_put(&lu->tgt->kref, sbp2_release_target); } + kref_put(&lu->tgt->kref, sbp2_release_target); return; } @@ -914,7 +915,9 @@ static void sbp2_reconnect(struct work_struct *work) lu->retries = 0; PREPARE_DELAYED_WORK(&lu->work, sbp2_login); } - queue_delayed_work(sbp2_wq, &lu->work, DIV_ROUND_UP(HZ, 5)); + if (queue_delayed_work(sbp2_wq, &lu->work, DIV_ROUND_UP(HZ, 5))) + kref_get(&lu->tgt->kref); + kref_put(&lu->tgt->kref, sbp2_release_target); return; } diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 700a1657554f..a0445bea9f75 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -216,6 +216,16 @@ config SENSORS_DS1621 This driver can also be built as a module. If so, the module will be called ds1621. +config SENSORS_I5K_AMB + tristate "FB-DIMM AMB temperature sensor on Intel 5000 series chipsets" + depends on PCI && EXPERIMENTAL + help + If you say yes here you get support for FB-DIMM AMB temperature + monitoring chips on systems with the Intel 5000 series chipset. + + This driver can also be built as a module. If so, the module + will be called i5k_amb. + config SENSORS_F71805F tristate "Fintek F71805F/FG, F71806F/FG and F71872F/FG" depends on EXPERIMENTAL diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 6da3eef94306..55595f6e1aa6 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o +obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o obj-$(CONFIG_SENSORS_IT87) += it87.o obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c index cb2331bfd9d5..d9f04ce90327 100644 --- a/drivers/hwmon/abituguru3.c +++ b/drivers/hwmon/abituguru3.c @@ -503,7 +503,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "AUX3 FAN", 36, 2, 60, 1, 0 }, { NULL, 0, 0, 0, 0, 0 } } }, - { 0x001A, "unknown", { + { 0x001A, "Abit IP35 Pro", { { "CPU Core", 0, 0, 10, 1, 0 }, { "DDR2", 1, 0, 20, 1, 0 }, { "DDR2 VTT", 2, 0, 10, 1, 0 }, @@ -530,6 +530,60 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "AUX3 Fan", 36, 2, 60, 1, 0 }, { NULL, 0, 0, 0, 0, 0 } } }, + { 0x001B, "unknown", { + { "CPU Core", 0, 0, 10, 1, 0 }, + { "DDR3", 1, 0, 20, 1, 0 }, + { "DDR3 VTT", 2, 0, 10, 1, 0 }, + { "CPU VTT", 3, 0, 10, 1, 0 }, + { "MCH 1.25V", 4, 0, 10, 1, 0 }, + { "ICHIO 1.5V", 5, 0, 10, 1, 0 }, + { "ICH 1.05V", 6, 0, 10, 1, 0 }, + { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, + { "ATX +12V (8-pin)", 8, 0, 60, 1, 0 }, + { "ATX +5V", 9, 0, 30, 1, 0 }, + { "+3.3V", 10, 0, 20, 1, 0 }, + { "5VSB", 11, 0, 30, 1, 0 }, + { "CPU", 24, 1, 1, 1, 0 }, + { "System", 25, 1, 1, 1, 0 }, + { "PWM Phase1", 26, 1, 1, 1, 0 }, + { "PWM Phase2", 27, 1, 1, 1, 0 }, + { "PWM Phase3", 28, 1, 1, 1, 0 }, + { "PWM Phase4", 29, 1, 1, 1, 0 }, + { "PWM Phase5", 30, 1, 1, 1, 0 }, + { "CPU Fan", 32, 2, 60, 1, 0 }, + { "SYS Fan", 34, 2, 60, 1, 0 }, + { "AUX1 Fan", 33, 2, 60, 1, 0 }, + { "AUX2 Fan", 35, 2, 60, 1, 0 }, + { "AUX3 Fan", 36, 2, 60, 1, 0 }, + { NULL, 0, 0, 0, 0, 0 } } + }, + { 0x001C, "unknown", { + { "CPU Core", 0, 0, 10, 1, 0 }, + { "DDR2", 1, 0, 20, 1, 0 }, + { "DDR2 VTT", 2, 0, 10, 1, 0 }, + { "CPU VTT", 3, 0, 10, 1, 0 }, + { "MCH 1.25V", 4, 0, 10, 1, 0 }, + { "ICHIO 1.5V", 5, 0, 10, 1, 0 }, + { "ICH 1.05V", 6, 0, 10, 1, 0 }, + { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, + { "ATX +12V (8-pin)", 8, 0, 60, 1, 0 }, + { "ATX +5V", 9, 0, 30, 1, 0 }, + { "+3.3V", 10, 0, 20, 1, 0 }, + { "5VSB", 11, 0, 30, 1, 0 }, + { "CPU", 24, 1, 1, 1, 0 }, + { "System", 25, 1, 1, 1, 0 }, + { "PWM Phase1", 26, 1, 1, 1, 0 }, + { "PWM Phase2", 27, 1, 1, 1, 0 }, + { "PWM Phase3", 28, 1, 1, 1, 0 }, + { "PWM Phase4", 29, 1, 1, 1, 0 }, + { "PWM Phase5", 30, 1, 1, 1, 0 }, + { "CPU Fan", 32, 2, 60, 1, 0 }, + { "SYS Fan", 34, 2, 60, 1, 0 }, + { "AUX1 Fan", 33, 2, 60, 1, 0 }, + { "AUX2 Fan", 35, 2, 60, 1, 0 }, + { "AUX3 Fan", 36, 2, 60, 1, 0 }, + { NULL, 0, 0, 0, 0, 0 } } + }, { 0x0000, NULL, { { NULL, 0, 0, 0, 0, 0 } } } }; diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index 1001d2e122a2..86c66c345f8b 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -80,7 +80,7 @@ /* * Temperature sensors keys (sp78 - 2 bytes). */ -static const char* temperature_sensors_sets[][13] = { +static const char* temperature_sensors_sets[][36] = { /* Set 0: Macbook Pro */ { "TA0P", "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "Th0H", "Th1H", "Tm0P", "Ts0P", "Ts1P", NULL }, @@ -88,7 +88,13 @@ static const char* temperature_sensors_sets[][13] = { { "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TN1P", "Th0H", "Th0S", "Th1H", "Ts0P", NULL }, /* Set 2: Macmini set */ - { "TC0D", "TC0P", NULL } + { "TC0D", "TC0P", NULL }, +/* Set 3: Mac Pro (2 x Quad-Core) */ + { "TA0P", "TCAG", "TCAH", "TCBG", "TCBH", "TC0C", "TC0D", "TC0P", + "TC1C", "TC1D", "TC2C", "TC2D", "TC3C", "TC3D", "THTG", "TH0P", + "TH1P", "TH2P", "TH3P", "TMAP", "TMAS", "TMBS", "TM0P", "TM0S", + "TM1P", "TM1S", "TM2P", "TM2S", "TM3S", "TM8P", "TM8S", "TM9P", + "TM9S", "TN0H", "TS0C", NULL }, }; /* List of keys used to read/write fan speeds */ @@ -990,14 +996,18 @@ static struct attribute *fan##offset##_attributes[] = { \ /* * Create the needed functions for each fan using the macro defined above - * (2 fans are supported) + * (4 fans are supported) */ sysfs_fan_speeds_offset(1); sysfs_fan_speeds_offset(2); +sysfs_fan_speeds_offset(3); +sysfs_fan_speeds_offset(4); static const struct attribute_group fan_attribute_groups[] = { { .attrs = fan1_attributes }, - { .attrs = fan2_attributes } + { .attrs = fan2_attributes }, + { .attrs = fan3_attributes }, + { .attrs = fan4_attributes }, }; /* @@ -1027,6 +1037,52 @@ static SENSOR_DEVICE_ATTR(temp11_input, S_IRUGO, applesmc_show_temperature, NULL, 10); static SENSOR_DEVICE_ATTR(temp12_input, S_IRUGO, applesmc_show_temperature, NULL, 11); +static SENSOR_DEVICE_ATTR(temp13_input, S_IRUGO, + applesmc_show_temperature, NULL, 12); +static SENSOR_DEVICE_ATTR(temp14_input, S_IRUGO, + applesmc_show_temperature, NULL, 13); +static SENSOR_DEVICE_ATTR(temp15_input, S_IRUGO, + applesmc_show_temperature, NULL, 14); +static SENSOR_DEVICE_ATTR(temp16_input, S_IRUGO, + applesmc_show_temperature, NULL, 15); +static SENSOR_DEVICE_ATTR(temp17_input, S_IRUGO, + applesmc_show_temperature, NULL, 16); +static SENSOR_DEVICE_ATTR(temp18_input, S_IRUGO, + applesmc_show_temperature, NULL, 17); +static SENSOR_DEVICE_ATTR(temp19_input, S_IRUGO, + applesmc_show_temperature, NULL, 18); +static SENSOR_DEVICE_ATTR(temp20_input, S_IRUGO, + applesmc_show_temperature, NULL, 19); +static SENSOR_DEVICE_ATTR(temp21_input, S_IRUGO, + applesmc_show_temperature, NULL, 20); +static SENSOR_DEVICE_ATTR(temp22_input, S_IRUGO, + applesmc_show_temperature, NULL, 21); +static SENSOR_DEVICE_ATTR(temp23_input, S_IRUGO, + applesmc_show_temperature, NULL, 22); +static SENSOR_DEVICE_ATTR(temp24_input, S_IRUGO, + applesmc_show_temperature, NULL, 23); +static SENSOR_DEVICE_ATTR(temp25_input, S_IRUGO, + applesmc_show_temperature, NULL, 24); +static SENSOR_DEVICE_ATTR(temp26_input, S_IRUGO, + applesmc_show_temperature, NULL, 25); +static SENSOR_DEVICE_ATTR(temp27_input, S_IRUGO, + applesmc_show_temperature, NULL, 26); +static SENSOR_DEVICE_ATTR(temp28_input, S_IRUGO, + applesmc_show_temperature, NULL, 27); +static SENSOR_DEVICE_ATTR(temp29_input, S_IRUGO, + applesmc_show_temperature, NULL, 28); +static SENSOR_DEVICE_ATTR(temp30_input, S_IRUGO, + applesmc_show_temperature, NULL, 29); +static SENSOR_DEVICE_ATTR(temp31_input, S_IRUGO, + applesmc_show_temperature, NULL, 30); +static SENSOR_DEVICE_ATTR(temp32_input, S_IRUGO, + applesmc_show_temperature, NULL, 31); +static SENSOR_DEVICE_ATTR(temp33_input, S_IRUGO, + applesmc_show_temperature, NULL, 32); +static SENSOR_DEVICE_ATTR(temp34_input, S_IRUGO, + applesmc_show_temperature, NULL, 33); +static SENSOR_DEVICE_ATTR(temp35_input, S_IRUGO, + applesmc_show_temperature, NULL, 34); static struct attribute *temperature_attributes[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, @@ -1041,6 +1097,29 @@ static struct attribute *temperature_attributes[] = { &sensor_dev_attr_temp10_input.dev_attr.attr, &sensor_dev_attr_temp11_input.dev_attr.attr, &sensor_dev_attr_temp12_input.dev_attr.attr, + &sensor_dev_attr_temp13_input.dev_attr.attr, + &sensor_dev_attr_temp14_input.dev_attr.attr, + &sensor_dev_attr_temp15_input.dev_attr.attr, + &sensor_dev_attr_temp16_input.dev_attr.attr, + &sensor_dev_attr_temp17_input.dev_attr.attr, + &sensor_dev_attr_temp18_input.dev_attr.attr, + &sensor_dev_attr_temp19_input.dev_attr.attr, + &sensor_dev_attr_temp20_input.dev_attr.attr, + &sensor_dev_attr_temp21_input.dev_attr.attr, + &sensor_dev_attr_temp22_input.dev_attr.attr, + &sensor_dev_attr_temp23_input.dev_attr.attr, + &sensor_dev_attr_temp24_input.dev_attr.attr, + &sensor_dev_attr_temp25_input.dev_attr.attr, + &sensor_dev_attr_temp26_input.dev_attr.attr, + &sensor_dev_attr_temp27_input.dev_attr.attr, + &sensor_dev_attr_temp28_input.dev_attr.attr, + &sensor_dev_attr_temp29_input.dev_attr.attr, + &sensor_dev_attr_temp30_input.dev_attr.attr, + &sensor_dev_attr_temp31_input.dev_attr.attr, + &sensor_dev_attr_temp32_input.dev_attr.attr, + &sensor_dev_attr_temp33_input.dev_attr.attr, + &sensor_dev_attr_temp34_input.dev_attr.attr, + &sensor_dev_attr_temp35_input.dev_attr.attr, NULL }; @@ -1137,6 +1216,8 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = { { .accelerometer = 1, .light = 0, .temperature_set = 1 }, /* MacMini: temperature set 2 */ { .accelerometer = 0, .light = 0, .temperature_set = 2 }, +/* MacPro: temperature set 3 */ + { .accelerometer = 0, .light = 0, .temperature_set = 3 }, }; /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". @@ -1154,6 +1235,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = { DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), DMI_MATCH(DMI_PRODUCT_NAME,"Macmini") }, (void*)&applesmc_dmi_data[2]}, + { applesmc_dmi_match, "Apple MacPro2", { + DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), + DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") }, + (void*)&applesmc_dmi_data[3]}, { .ident = NULL } }; @@ -1204,9 +1289,19 @@ static int __init applesmc_init(void) switch (count) { default: - printk(KERN_WARNING "applesmc: More than 2 fans found," - " but at most 2 fans are supported" + printk(KERN_WARNING "applesmc: More than 4 fans found," + " but at most 4 fans are supported" " by the driver.\n"); + case 4: + ret = sysfs_create_group(&pdev->dev.kobj, + &fan_attribute_groups[3]); + if (ret) + goto out_key_enumeration; + case 3: + ret = sysfs_create_group(&pdev->dev.kobj, + &fan_attribute_groups[2]); + if (ret) + goto out_key_enumeration; case 2: ret = sysfs_create_group(&pdev->dev.kobj, &fan_attribute_groups[1]); diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c index 13a041326a04..6892f76fc18a 100644 --- a/drivers/hwmon/f75375s.c +++ b/drivers/hwmon/f75375s.c @@ -34,6 +34,7 @@ #include <linux/i2c.h> #include <linux/err.h> #include <linux/mutex.h> +#include <linux/f75375s.h> /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x2d, 0x2e, I2C_CLIENT_END }; @@ -86,7 +87,7 @@ I2C_CLIENT_INSMOD_2(f75373, f75375); struct f75375_data { unsigned short addr; - struct i2c_client client; + struct i2c_client *client; struct device *hwmon_dev; const char *name; @@ -116,15 +117,25 @@ struct f75375_data { static int f75375_attach_adapter(struct i2c_adapter *adapter); static int f75375_detect(struct i2c_adapter *adapter, int address, int kind); static int f75375_detach_client(struct i2c_client *client); +static int f75375_probe(struct i2c_client *client); +static int f75375_remove(struct i2c_client *client); -static struct i2c_driver f75375_driver = { +static struct i2c_driver f75375_legacy_driver = { .driver = { - .name = "f75375", + .name = "f75375_legacy", }, .attach_adapter = f75375_attach_adapter, .detach_client = f75375_detach_client, }; +static struct i2c_driver f75375_driver = { + .driver = { + .name = "f75375", + }, + .probe = f75375_probe, + .remove = f75375_remove, +}; + static inline int f75375_read8(struct i2c_client *client, u8 reg) { return i2c_smbus_read_byte_data(client, reg); @@ -276,19 +287,14 @@ static ssize_t show_pwm_enable(struct device *dev, struct device_attribute return sprintf(buf, "%d\n", data->pwm_enable[nr]); } -static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val) { - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); struct f75375_data *data = i2c_get_clientdata(client); - int val = simple_strtoul(buf, NULL, 10); u8 fanmode; if (val < 0 || val > 4) return -EINVAL; - mutex_lock(&data->update_lock); fanmode = f75375_read8(client, F75375_REG_FAN_TIMER); fanmode = ~(3 << FAN_CTRL_MODE(nr)); @@ -310,8 +316,22 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, } f75375_write8(client, F75375_REG_FAN_TIMER, fanmode); data->pwm_enable[nr] = val; + return 0; +} + +static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct f75375_data *data = i2c_get_clientdata(client); + int val = simple_strtoul(buf, NULL, 10); + int err = 0; + + mutex_lock(&data->update_lock); + err = set_pwm_enable_direct(client, nr, val); mutex_unlock(&data->update_lock); - return count; + return err ? err : count; } static ssize_t set_pwm_mode(struct device *dev, struct device_attribute *attr, @@ -323,7 +343,7 @@ static ssize_t set_pwm_mode(struct device *dev, struct device_attribute *attr, int val = simple_strtoul(buf, NULL, 10); u8 conf = 0; - if (val != 0 || val != 1 || data->kind == f75373) + if (!(val == 0 || val == 1)) return -EINVAL; mutex_lock(&data->update_lock); @@ -529,13 +549,13 @@ static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO|S_IWUSR, show_pwm, set_pwm, 0); static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable, set_pwm_enable, 0); -static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO|S_IWUSR, +static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO, show_pwm_mode, set_pwm_mode, 0); static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 1); static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable, set_pwm_enable, 1); -static SENSOR_DEVICE_ATTR(pwm2_mode, S_IRUGO|S_IWUSR, +static SENSOR_DEVICE_ATTR(pwm2_mode, S_IRUGO, show_pwm_mode, set_pwm_mode, 1); static struct attribute *f75375_attributes[] = { @@ -580,12 +600,9 @@ static const struct attribute_group f75375_group = { static int f75375_detach_client(struct i2c_client *client) { - struct f75375_data *data = i2c_get_clientdata(client); int err; - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &f75375_group); - + f75375_remove(client); err = i2c_detach_client(client); if (err) { dev_err(&client->dev, @@ -593,7 +610,91 @@ static int f75375_detach_client(struct i2c_client *client) "client not detached.\n"); return err; } + kfree(client); + return 0; +} + +static void f75375_init(struct i2c_client *client, struct f75375_data *data, + struct f75375s_platform_data *f75375s_pdata) +{ + int nr; + set_pwm_enable_direct(client, 0, f75375s_pdata->pwm_enable[0]); + set_pwm_enable_direct(client, 1, f75375s_pdata->pwm_enable[1]); + for (nr = 0; nr < 2; nr++) { + data->pwm[nr] = SENSORS_LIMIT(f75375s_pdata->pwm[nr], 0, 255); + f75375_write8(client, F75375_REG_FAN_PWM_DUTY(nr), + data->pwm[nr]); + } + +} + +static int f75375_probe(struct i2c_client *client) +{ + struct f75375_data *data = i2c_get_clientdata(client); + struct f75375s_platform_data *f75375s_pdata = client->dev.platform_data; + int err; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) + return -EIO; + if (!(data = kzalloc(sizeof(struct f75375_data), GFP_KERNEL))) + return -ENOMEM; + + i2c_set_clientdata(client, data); + data->client = client; + mutex_init(&data->update_lock); + + if (strcmp(client->name, "f75375") == 0) + data->kind = f75375; + else if (strcmp(client->name, "f75373") == 0) + data->kind = f75373; + else { + dev_err(&client->dev, "Unsupported device: %s\n", client->name); + return -ENODEV; + } + + if ((err = sysfs_create_group(&client->dev.kobj, &f75375_group))) + goto exit_free; + + if (data->kind == f75375) { + err = sysfs_chmod_file(&client->dev.kobj, + &sensor_dev_attr_pwm1_mode.dev_attr.attr, + S_IRUGO | S_IWUSR); + if (err) + goto exit_remove; + err = sysfs_chmod_file(&client->dev.kobj, + &sensor_dev_attr_pwm2_mode.dev_attr.attr, + S_IRUGO | S_IWUSR); + if (err) + goto exit_remove; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + if (f75375s_pdata != NULL) + f75375_init(client, data, f75375s_pdata); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &f75375_group); +exit_free: kfree(data); + i2c_set_clientdata(client, NULL); + return err; +} + +static int f75375_remove(struct i2c_client *client) +{ + struct f75375_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &f75375_group); + kfree(data); + i2c_set_clientdata(client, NULL); return 0; } @@ -608,20 +709,17 @@ static int f75375_attach_adapter(struct i2c_adapter *adapter) static int f75375_detect(struct i2c_adapter *adapter, int address, int kind) { struct i2c_client *client; - struct f75375_data *data; u8 version = 0; int err = 0; const char *name = ""; - if (!(data = kzalloc(sizeof(struct f75375_data), GFP_KERNEL))) { + if (!(client = kzalloc(sizeof(*client), GFP_KERNEL))) { err = -ENOMEM; goto exit; } - client = &data->client; - i2c_set_clientdata(client, data); client->addr = address; client->adapter = adapter; - client->driver = &f75375_driver; + client->driver = &f75375_legacy_driver; if (kind < 0) { u16 vendid = f75375_read16(client, F75375_REG_VENDOR); @@ -644,42 +742,42 @@ static int f75375_detect(struct i2c_adapter *adapter, int address, int kind) } else if (kind == f75373) { name = "f75373"; } - dev_info(&adapter->dev, "found %s version: %02X\n", name, version); strlcpy(client->name, name, I2C_NAME_SIZE); - data->kind = kind; - mutex_init(&data->update_lock); + if ((err = i2c_attach_client(client))) goto exit_free; - if ((err = sysfs_create_group(&client->dev.kobj, &f75375_group))) + if ((err = f75375_probe(client)) < 0) goto exit_detach; - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - return 0; -exit_remove: - sysfs_remove_group(&client->dev.kobj, &f75375_group); exit_detach: i2c_detach_client(client); exit_free: - kfree(data); + kfree(client); exit: return err; } static int __init sensors_f75375_init(void) { - return i2c_add_driver(&f75375_driver); + int status; + status = i2c_add_driver(&f75375_driver); + if (status) + return status; + + status = i2c_add_driver(&f75375_legacy_driver); + if (status) + i2c_del_driver(&f75375_driver); + + return status; } static void __exit sensors_f75375_exit(void) { + i2c_del_driver(&f75375_legacy_driver); i2c_del_driver(&f75375_driver); } diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c new file mode 100644 index 000000000000..6ac5c6f53585 --- /dev/null +++ b/drivers/hwmon/i5k_amb.c @@ -0,0 +1,552 @@ +/* + * A hwmon driver for the Intel 5000 series chipset FB-DIMM AMB + * temperature sensors + * Copyright (C) 2007 IBM + * + * Author: Darrick J. Wong <djwong@us.ibm.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/module.h> +#include <linux/jiffies.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/err.h> +#include <linux/mutex.h> +#include <linux/delay.h> +#include <linux/log2.h> +#include <linux/pci.h> +#include <linux/platform_device.h> + +#define DRVNAME "i5k_amb" + +#define I5K_REG_AMB_BASE_ADDR 0x48 +#define I5K_REG_AMB_LEN_ADDR 0x50 +#define I5K_REG_CHAN0_PRESENCE_ADDR 0x64 +#define I5K_REG_CHAN1_PRESENCE_ADDR 0x66 + +#define AMB_REG_TEMP_MIN_ADDR 0x80 +#define AMB_REG_TEMP_MID_ADDR 0x81 +#define AMB_REG_TEMP_MAX_ADDR 0x82 +#define AMB_REG_TEMP_STATUS_ADDR 0x84 +#define AMB_REG_TEMP_ADDR 0x85 + +#define AMB_CONFIG_SIZE 2048 +#define AMB_FUNC_3_OFFSET 768 + +static unsigned long amb_reg_temp_status(unsigned int amb) +{ + return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_STATUS_ADDR + + AMB_CONFIG_SIZE * amb; +} + +static unsigned long amb_reg_temp_min(unsigned int amb) +{ + return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_MIN_ADDR + + AMB_CONFIG_SIZE * amb; +} + +static unsigned long amb_reg_temp_mid(unsigned int amb) +{ + return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_MID_ADDR + + AMB_CONFIG_SIZE * amb; +} + +static unsigned long amb_reg_temp_max(unsigned int amb) +{ + return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_MAX_ADDR + + AMB_CONFIG_SIZE * amb; +} + +static unsigned long amb_reg_temp(unsigned int amb) +{ + return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_ADDR + + AMB_CONFIG_SIZE * amb; +} + +#define MAX_MEM_CHANNELS 4 +#define MAX_AMBS_PER_CHANNEL 16 +#define MAX_AMBS (MAX_MEM_CHANNELS * \ + MAX_AMBS_PER_CHANNEL) +/* + * Ugly hack: For some reason the highest bit is set if there + * are _any_ DIMMs in the channel. Attempting to read from + * this "high-order" AMB results in a memory bus error, so + * for now we'll just ignore that top bit, even though that + * might prevent us from seeing the 16th DIMM in the channel. + */ +#define REAL_MAX_AMBS_PER_CHANNEL 15 +#define KNOBS_PER_AMB 5 + +static unsigned long amb_num_from_reg(unsigned int byte_num, unsigned int bit) +{ + return byte_num * MAX_AMBS_PER_CHANNEL + bit; +} + +#define AMB_SYSFS_NAME_LEN 16 +struct i5k_device_attribute { + struct sensor_device_attribute s_attr; + char name[AMB_SYSFS_NAME_LEN]; +}; + +struct i5k_amb_data { + struct device *hwmon_dev; + + unsigned long amb_base; + unsigned long amb_len; + u16 amb_present[MAX_MEM_CHANNELS]; + void __iomem *amb_mmio; + struct i5k_device_attribute *attrs; + unsigned int num_attrs; +}; + +static ssize_t show_name(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + return sprintf(buf, "%s\n", DRVNAME); +} + + +static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); + +static struct platform_device *amb_pdev; + +static u8 amb_read_byte(struct i5k_amb_data *data, unsigned long offset) +{ + return ioread8(data->amb_mmio + offset); +} + +static void amb_write_byte(struct i5k_amb_data *data, unsigned long offset, + u8 val) +{ + iowrite8(val, data->amb_mmio + offset); +} + +static ssize_t show_amb_alarm(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i5k_amb_data *data = dev_get_drvdata(dev); + + if (!(amb_read_byte(data, amb_reg_temp_status(attr->index)) & 0x20) && + (amb_read_byte(data, amb_reg_temp_status(attr->index)) & 0x8)) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static ssize_t store_amb_min(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i5k_amb_data *data = dev_get_drvdata(dev); + unsigned long temp = simple_strtoul(buf, NULL, 10) / 500; + + if (temp > 255) + temp = 255; + + amb_write_byte(data, amb_reg_temp_min(attr->index), temp); + return count; +} + +static ssize_t store_amb_mid(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i5k_amb_data *data = dev_get_drvdata(dev); + unsigned long temp = simple_strtoul(buf, NULL, 10) / 500; + + if (temp > 255) + temp = 255; + + amb_write_byte(data, amb_reg_temp_mid(attr->index), temp); + return count; +} + +static ssize_t store_amb_max(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i5k_amb_data *data = dev_get_drvdata(dev); + unsigned long temp = simple_strtoul(buf, NULL, 10) / 500; + + if (temp > 255) + temp = 255; + + amb_write_byte(data, amb_reg_temp_max(attr->index), temp); + return count; +} + +static ssize_t show_amb_min(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i5k_amb_data *data = dev_get_drvdata(dev); + return sprintf(buf, "%d\n", + 500 * amb_read_byte(data, amb_reg_temp_min(attr->index))); +} + +static ssize_t show_amb_mid(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i5k_amb_data *data = dev_get_drvdata(dev); + return sprintf(buf, "%d\n", + 500 * amb_read_byte(data, amb_reg_temp_mid(attr->index))); +} + +static ssize_t show_amb_max(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i5k_amb_data *data = dev_get_drvdata(dev); + return sprintf(buf, "%d\n", + 500 * amb_read_byte(data, amb_reg_temp_max(attr->index))); +} + +static ssize_t show_amb_temp(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i5k_amb_data *data = dev_get_drvdata(dev); + return sprintf(buf, "%d\n", + 500 * amb_read_byte(data, amb_reg_temp(attr->index))); +} + +static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev) +{ + int i, j, k, d = 0; + u16 c; + int res = 0; + int num_ambs = 0; + struct i5k_amb_data *data = platform_get_drvdata(pdev); + + /* Count the number of AMBs found */ + /* ignore the high-order bit, see "Ugly hack" comment above */ + for (i = 0; i < MAX_MEM_CHANNELS; i++) + num_ambs += hweight16(data->amb_present[i] & 0x7fff); + + /* Set up sysfs stuff */ + data->attrs = kzalloc(sizeof(*data->attrs) * num_ambs * KNOBS_PER_AMB, + GFP_KERNEL); + if (!data->attrs) + return -ENOMEM; + data->num_attrs = 0; + + for (i = 0; i < MAX_MEM_CHANNELS; i++) { + c = data->amb_present[i]; + for (j = 0; j < REAL_MAX_AMBS_PER_CHANNEL; j++, c >>= 1) { + struct i5k_device_attribute *iattr; + + k = amb_num_from_reg(i, j); + if (!(c & 0x1)) + continue; + d++; + + /* Temperature sysfs knob */ + iattr = data->attrs + data->num_attrs; + snprintf(iattr->name, AMB_SYSFS_NAME_LEN, + "temp%d_input", d); + iattr->s_attr.dev_attr.attr.name = iattr->name; + iattr->s_attr.dev_attr.attr.mode = S_IRUGO; + iattr->s_attr.dev_attr.show = show_amb_temp; + iattr->s_attr.index = k; + res = device_create_file(&pdev->dev, + &iattr->s_attr.dev_attr); + if (res) + goto exit_remove; + data->num_attrs++; + + /* Temperature min sysfs knob */ + iattr = data->attrs + data->num_attrs; + snprintf(iattr->name, AMB_SYSFS_NAME_LEN, + "temp%d_min", d); + iattr->s_attr.dev_attr.attr.name = iattr->name; + iattr->s_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO; + iattr->s_attr.dev_attr.show = show_amb_min; + iattr->s_attr.dev_attr.store = store_amb_min; + iattr->s_attr.index = k; + res = device_create_file(&pdev->dev, + &iattr->s_attr.dev_attr); + if (res) + goto exit_remove; + data->num_attrs++; + + /* Temperature mid sysfs knob */ + iattr = data->attrs + data->num_attrs; + snprintf(iattr->name, AMB_SYSFS_NAME_LEN, + "temp%d_mid", d); + iattr->s_attr.dev_attr.attr.name = iattr->name; + iattr->s_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO; + iattr->s_attr.dev_attr.show = show_amb_mid; + iattr->s_attr.dev_attr.store = store_amb_mid; + iattr->s_attr.index = k; + res = device_create_file(&pdev->dev, + &iattr->s_attr.dev_attr); + if (res) + goto exit_remove; + data->num_attrs++; + + /* Temperature max sysfs knob */ + iattr = data->attrs + data->num_attrs; + snprintf(iattr->name, AMB_SYSFS_NAME_LEN, + "temp%d_max", d); + iattr->s_attr.dev_attr.attr.name = iattr->name; + iattr->s_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO; + iattr->s_attr.dev_attr.show = show_amb_max; + iattr->s_attr.dev_attr.store = store_amb_max; + iattr->s_attr.index = k; + res = device_create_file(&pdev->dev, + &iattr->s_attr.dev_attr); + if (res) + goto exit_remove; + data->num_attrs++; + + /* Temperature alarm sysfs knob */ + iattr = data->attrs + data->num_attrs; + snprintf(iattr->name, AMB_SYSFS_NAME_LEN, + "temp%d_alarm", d); + iattr->s_attr.dev_attr.attr.name = iattr->name; + iattr->s_attr.dev_attr.attr.mode = S_IRUGO; + iattr->s_attr.dev_attr.show = show_amb_alarm; + iattr->s_attr.index = k; + res = device_create_file(&pdev->dev, + &iattr->s_attr.dev_attr); + if (res) + goto exit_remove; + data->num_attrs++; + } + } + + res = device_create_file(&pdev->dev, &dev_attr_name); + if (res) + goto exit_remove; + + data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(data->hwmon_dev)) { + res = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + return res; + +exit_remove: + device_remove_file(&pdev->dev, &dev_attr_name); + for (i = 0; i < data->num_attrs; i++) + device_remove_file(&pdev->dev, &data->attrs[i].s_attr.dev_attr); + kfree(data->attrs); + + return res; +} + +static int __devinit i5k_amb_add(void) +{ + int res = -ENODEV; + + /* only ever going to be one of these */ + amb_pdev = platform_device_alloc(DRVNAME, 0); + if (!amb_pdev) + return -ENOMEM; + + res = platform_device_add(amb_pdev); + if (res) + goto err; + return 0; + +err: + platform_device_put(amb_pdev); + return res; +} + +static int __devinit i5k_find_amb_registers(struct i5k_amb_data *data) +{ + struct pci_dev *pcidev; + u32 val32; + int res = -ENODEV; + + /* Find AMB register memory space */ + pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_5000_ERR, + NULL); + if (!pcidev) + return -ENODEV; + + if (pci_read_config_dword(pcidev, I5K_REG_AMB_BASE_ADDR, &val32)) + goto out; + data->amb_base = val32; + + if (pci_read_config_dword(pcidev, I5K_REG_AMB_LEN_ADDR, &val32)) + goto out; + data->amb_len = val32; + + /* Is it big enough? */ + if (data->amb_len < AMB_CONFIG_SIZE * MAX_AMBS) { + dev_err(&pcidev->dev, "AMB region too small!\n"); + goto out; + } + + res = 0; +out: + pci_dev_put(pcidev); + return res; +} + +static int __devinit i5k_channel_probe(u16 *amb_present, unsigned long dev_id) +{ + struct pci_dev *pcidev; + u16 val16; + int res = -ENODEV; + + /* Copy the DIMM presence map for these two channels */ + pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, dev_id, NULL); + if (!pcidev) + return -ENODEV; + + if (pci_read_config_word(pcidev, I5K_REG_CHAN0_PRESENCE_ADDR, &val16)) + goto out; + amb_present[0] = val16; + + if (pci_read_config_word(pcidev, I5K_REG_CHAN1_PRESENCE_ADDR, &val16)) + goto out; + amb_present[1] = val16; + + res = 0; + +out: + pci_dev_put(pcidev); + return res; +} + +static int __devinit i5k_amb_probe(struct platform_device *pdev) +{ + struct i5k_amb_data *data; + struct resource *reso; + int res = -ENODEV; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* Figure out where the AMB registers live */ + res = i5k_find_amb_registers(data); + if (res) + goto err; + + /* Copy the DIMM presence map for the first two channels */ + res = i5k_channel_probe(&data->amb_present[0], + PCI_DEVICE_ID_INTEL_5000_FBD0); + if (res) + goto err; + + /* Copy the DIMM presence map for the optional second two channels */ + i5k_channel_probe(&data->amb_present[2], + PCI_DEVICE_ID_INTEL_5000_FBD1); + + /* Set up resource regions */ + reso = request_mem_region(data->amb_base, data->amb_len, DRVNAME); + if (!reso) { + res = -EBUSY; + goto err; + } + + data->amb_mmio = ioremap_nocache(data->amb_base, data->amb_len); + if (!data->amb_mmio) { + res = -EBUSY; + goto err_map_failed; + } + + platform_set_drvdata(pdev, data); + + res = i5k_amb_hwmon_init(pdev); + if (res) + goto err_init_failed; + + return res; + +err_init_failed: + iounmap(data->amb_mmio); + platform_set_drvdata(pdev, NULL); +err_map_failed: + release_mem_region(data->amb_base, data->amb_len); +err: + kfree(data); + return res; +} + +static int __devexit i5k_amb_remove(struct platform_device *pdev) +{ + int i; + struct i5k_amb_data *data = platform_get_drvdata(pdev); + + hwmon_device_unregister(data->hwmon_dev); + device_remove_file(&pdev->dev, &dev_attr_name); + for (i = 0; i < data->num_attrs; i++) + device_remove_file(&pdev->dev, &data->attrs[i].s_attr.dev_attr); + kfree(data->attrs); + iounmap(data->amb_mmio); + release_mem_region(data->amb_base, data->amb_len); + platform_set_drvdata(pdev, NULL); + kfree(data); + return 0; +} + +static struct platform_driver i5k_amb_driver = { + .driver = { + .owner = THIS_MODULE, + .name = DRVNAME, + }, + .probe = i5k_amb_probe, + .remove = __devexit_p(i5k_amb_remove), +}; + +static int __init i5k_amb_init(void) +{ + int res; + + res = platform_driver_register(&i5k_amb_driver); + if (res) + return res; + + res = i5k_amb_add(); + if (res) + platform_driver_unregister(&i5k_amb_driver); + + return res; +} + +static void __exit i5k_amb_exit(void) +{ + platform_device_unregister(amb_pdev); + platform_driver_unregister(&i5k_amb_driver); +} + +MODULE_AUTHOR("Darrick J. Wong <djwong@us.ibm.com>"); +MODULE_DESCRIPTION("Intel 5000 chipset FB-DIMM AMB temperature sensor"); +MODULE_LICENSE("GPL"); + +module_init(i5k_amb_init); +module_exit(i5k_amb_exit); diff --git a/drivers/hwmon/ibmpex.c b/drivers/hwmon/ibmpex.c index c462824ffccf..9c9cdb0685e4 100644 --- a/drivers/hwmon/ibmpex.c +++ b/drivers/hwmon/ibmpex.c @@ -140,10 +140,10 @@ static int ibmpex_send_message(struct ibmpex_bmc_data *data) return 0; out1: - printk(KERN_ERR "%s: request_settime=%x\n", __FUNCTION__, err); + dev_err(data->bmc_device, "request_settime=%x\n", err); return err; out: - printk(KERN_ERR "%s: validate_addr=%x\n", __FUNCTION__, err); + dev_err(data->bmc_device, "validate_addr=%x\n", err); return err; } @@ -161,14 +161,14 @@ static int ibmpex_ver_check(struct ibmpex_bmc_data *data) data->sensor_major = data->rx_msg_data[0]; data->sensor_minor = data->rx_msg_data[1]; - printk(KERN_INFO DRVNAME ": Found BMC with sensor interface " - "v%d.%d %d-%02d-%02d on interface %d\n", - data->sensor_major, - data->sensor_minor, - extract_value(data->rx_msg_data, 2), - data->rx_msg_data[4], - data->rx_msg_data[5], - data->interface); + dev_info(data->bmc_device, "Found BMC with sensor interface " + "v%d.%d %d-%02d-%02d on interface %d\n", + data->sensor_major, + data->sensor_minor, + extract_value(data->rx_msg_data, 2), + data->rx_msg_data[4], + data->rx_msg_data[5], + data->interface); return 0; } @@ -212,8 +212,8 @@ static int ibmpex_query_sensor_data(struct ibmpex_bmc_data *data, int sensor) wait_for_completion(&data->read_complete); if (data->rx_result || data->rx_msg_len < 26) { - printk(KERN_ERR "Error reading sensor %d, please check.\n", - sensor); + dev_err(data->bmc_device, "Error reading sensor %d.\n", + sensor); return -ENOENT; } @@ -456,8 +456,7 @@ static void ibmpex_register_bmc(int iface, struct device *dev) data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) { - printk(KERN_ERR DRVNAME ": Insufficient memory for BMC " - "interface %d.\n", data->interface); + dev_err(dev, "Insufficient memory for BMC interface.\n"); return; } @@ -471,9 +470,8 @@ static void ibmpex_register_bmc(int iface, struct device *dev) err = ipmi_create_user(data->interface, &driver_data.ipmi_hndlrs, data, &data->user); if (err < 0) { - printk(KERN_ERR DRVNAME ": Error, unable to register user with " - "ipmi interface %d\n", - data->interface); + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", data->interface); goto out; } @@ -495,9 +493,9 @@ static void ibmpex_register_bmc(int iface, struct device *dev) data->hwmon_dev = hwmon_device_register(data->bmc_device); if (IS_ERR(data->hwmon_dev)) { - printk(KERN_ERR DRVNAME ": Error, unable to register hwmon " - "class device for interface %d\n", - data->interface); + dev_err(data->bmc_device, "Unable to register hwmon " + "device for IPMI interface %d\n", + data->interface); goto out_user; } @@ -508,7 +506,7 @@ static void ibmpex_register_bmc(int iface, struct device *dev) /* Now go find all the sensors */ err = ibmpex_find_sensors(data); if (err) { - printk(KERN_ERR "Error %d allocating memory\n", err); + dev_err(data->bmc_device, "Error %d finding sensors\n", err); goto out_register; } @@ -561,10 +559,10 @@ static void ibmpex_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) struct ibmpex_bmc_data *data = (struct ibmpex_bmc_data *)user_msg_data; if (msg->msgid != data->tx_msgid) { - printk(KERN_ERR "Received msgid (%02x) and transmitted " - "msgid (%02x) mismatch!\n", - (int)msg->msgid, - (int)data->tx_msgid); + dev_err(data->bmc_device, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)data->tx_msgid); ipmi_free_recv_msg(msg); return; } diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c index dd366889ce9b..d435f003292d 100644 --- a/drivers/hwmon/lm70.c +++ b/drivers/hwmon/lm70.c @@ -31,14 +31,15 @@ #include <linux/err.h> #include <linux/sysfs.h> #include <linux/hwmon.h> +#include <linux/mutex.h> #include <linux/spi/spi.h> -#include <asm/semaphore.h> + #define DRVNAME "lm70" struct lm70 { struct device *hwmon_dev; - struct semaphore sem; + struct mutex lock; }; /* sysfs hook function */ @@ -51,7 +52,7 @@ static ssize_t lm70_sense_temp(struct device *dev, s16 raw=0; struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev); - if (down_interruptible(&p_lm70->sem)) + if (mutex_lock_interruptible(&p_lm70->lock)) return -ERESTARTSYS; /* @@ -83,7 +84,7 @@ static ssize_t lm70_sense_temp(struct device *dev, val = ((int)raw/32) * 250; status = sprintf(buf, "%d\n", val); /* millidegrees Celsius */ out: - up(&p_lm70->sem); + mutex_unlock(&p_lm70->lock); return status; } @@ -112,7 +113,7 @@ static int __devinit lm70_probe(struct spi_device *spi) if (!p_lm70) return -ENOMEM; - init_MUTEX(&p_lm70->sem); + mutex_init(&p_lm70->lock); /* sysfs hook */ p_lm70->hwmon_dev = hwmon_device_register(&spi->dev); diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c index 7e2d9787babc..a276806f3d53 100644 --- a/drivers/hwmon/sis5595.c +++ b/drivers/hwmon/sis5595.c @@ -435,6 +435,22 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch } static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); +static ssize_t show_alarm(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sis5595_data *data = sis5595_update_device(dev); + int nr = to_sensor_dev_attr(da)->index; + return sprintf(buf, "%u\n", (data->alarms >> nr) & 1); +} +static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); +static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 15); +static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6); +static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7); +static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 15); + static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) { @@ -447,22 +463,28 @@ static struct attribute *sis5595_attributes[] = { &sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_in0_min.dev_attr.attr, &sensor_dev_attr_in0_max.dev_attr.attr, + &sensor_dev_attr_in0_alarm.dev_attr.attr, &sensor_dev_attr_in1_input.dev_attr.attr, &sensor_dev_attr_in1_min.dev_attr.attr, &sensor_dev_attr_in1_max.dev_attr.attr, + &sensor_dev_attr_in1_alarm.dev_attr.attr, &sensor_dev_attr_in2_input.dev_attr.attr, &sensor_dev_attr_in2_min.dev_attr.attr, &sensor_dev_attr_in2_max.dev_attr.attr, + &sensor_dev_attr_in2_alarm.dev_attr.attr, &sensor_dev_attr_in3_input.dev_attr.attr, &sensor_dev_attr_in3_min.dev_attr.attr, &sensor_dev_attr_in3_max.dev_attr.attr, + &sensor_dev_attr_in3_alarm.dev_attr.attr, &sensor_dev_attr_fan1_input.dev_attr.attr, &sensor_dev_attr_fan1_min.dev_attr.attr, &sensor_dev_attr_fan1_div.dev_attr.attr, + &sensor_dev_attr_fan1_alarm.dev_attr.attr, &sensor_dev_attr_fan2_input.dev_attr.attr, &sensor_dev_attr_fan2_min.dev_attr.attr, &sensor_dev_attr_fan2_div.dev_attr.attr, + &sensor_dev_attr_fan2_alarm.dev_attr.attr, &dev_attr_alarms.attr, &dev_attr_name.attr, @@ -473,19 +495,28 @@ static const struct attribute_group sis5595_group = { .attrs = sis5595_attributes, }; -static struct attribute *sis5595_attributes_opt[] = { +static struct attribute *sis5595_attributes_in4[] = { &sensor_dev_attr_in4_input.dev_attr.attr, &sensor_dev_attr_in4_min.dev_attr.attr, &sensor_dev_attr_in4_max.dev_attr.attr, + &sensor_dev_attr_in4_alarm.dev_attr.attr, + NULL +}; + +static const struct attribute_group sis5595_group_in4 = { + .attrs = sis5595_attributes_in4, +}; +static struct attribute *sis5595_attributes_temp1[] = { &dev_attr_temp1_input.attr, &dev_attr_temp1_max.attr, &dev_attr_temp1_max_hyst.attr, + &sensor_dev_attr_temp1_alarm.dev_attr.attr, NULL }; -static const struct attribute_group sis5595_group_opt = { - .attrs = sis5595_attributes_opt, +static const struct attribute_group sis5595_group_temp1 = { + .attrs = sis5595_attributes_temp1, }; /* This is called when the module is loaded */ @@ -540,20 +571,12 @@ static int __devinit sis5595_probe(struct platform_device *pdev) if ((err = sysfs_create_group(&pdev->dev.kobj, &sis5595_group))) goto exit_free; if (data->maxins == 4) { - if ((err = device_create_file(&pdev->dev, - &sensor_dev_attr_in4_input.dev_attr)) - || (err = device_create_file(&pdev->dev, - &sensor_dev_attr_in4_min.dev_attr)) - || (err = device_create_file(&pdev->dev, - &sensor_dev_attr_in4_max.dev_attr))) + if ((err = sysfs_create_group(&pdev->dev.kobj, + &sis5595_group_in4))) goto exit_remove_files; } else { - if ((err = device_create_file(&pdev->dev, - &dev_attr_temp1_input)) - || (err = device_create_file(&pdev->dev, - &dev_attr_temp1_max)) - || (err = device_create_file(&pdev->dev, - &dev_attr_temp1_max_hyst))) + if ((err = sysfs_create_group(&pdev->dev.kobj, + &sis5595_group_temp1))) goto exit_remove_files; } @@ -567,7 +590,8 @@ static int __devinit sis5595_probe(struct platform_device *pdev) exit_remove_files: sysfs_remove_group(&pdev->dev.kobj, &sis5595_group); - sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_opt); + sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_in4); + sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_temp1); exit_free: kfree(data); exit_release: @@ -582,7 +606,8 @@ static int __devexit sis5595_remove(struct platform_device *pdev) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&pdev->dev.kobj, &sis5595_group); - sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_opt); + sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_in4); + sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_temp1); release_region(data->addr, SIS5595_EXTENT); platform_set_drvdata(pdev, NULL); diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 20ae425a1980..879d0a6544cc 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -170,20 +170,16 @@ superio_exit(void) #define W83781D_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \ (0x550 + (nr) - 7)) -#define W83781D_REG_FAN_MIN(nr) (0x3a + (nr)) -#define W83781D_REG_FAN(nr) (0x27 + (nr)) - -#define W83781D_REG_TEMP2_CONFIG 0x152 -#define W83781D_REG_TEMP3_CONFIG 0x252 -#define W83781D_REG_TEMP(nr) ((nr == 3) ? (0x0250) : \ - ((nr == 2) ? (0x0150) : \ - (0x27))) -#define W83781D_REG_TEMP_HYST(nr) ((nr == 3) ? (0x253) : \ - ((nr == 2) ? (0x153) : \ - (0x3A))) -#define W83781D_REG_TEMP_OVER(nr) ((nr == 3) ? (0x255) : \ - ((nr == 2) ? (0x155) : \ - (0x39))) +/* nr:0-2 for fans:1-3 */ +#define W83627HF_REG_FAN_MIN(nr) (0x3b + (nr)) +#define W83627HF_REG_FAN(nr) (0x28 + (nr)) + +#define W83627HF_REG_TEMP2_CONFIG 0x152 +#define W83627HF_REG_TEMP3_CONFIG 0x252 +/* these are zero-based, unlike config constants above */ +static const u16 w83627hf_reg_temp[] = { 0x27, 0x150, 0x250 }; +static const u16 w83627hf_reg_temp_hyst[] = { 0x3A, 0x153, 0x253 }; +static const u16 w83627hf_reg_temp_over[] = { 0x39, 0x155, 0x255 }; #define W83781D_REG_BANK 0x4E @@ -360,12 +356,9 @@ struct w83627hf_data { u8 in_min[9]; /* Register value */ u8 fan[3]; /* Register value */ u8 fan_min[3]; /* Register value */ - u8 temp; - u8 temp_max; /* Register value */ - u8 temp_max_hyst; /* Register value */ - u16 temp_add[2]; /* Register value */ - u16 temp_max_add[2]; /* Register value */ - u16 temp_max_hyst_add[2]; /* Register value */ + u16 temp[3]; /* Register value */ + u16 temp_max[3]; /* Register value */ + u16 temp_max_hyst[3]; /* Register value */ u8 fan_div[3]; /* Register encoding, shifted right */ u8 vid; /* Register encoding, combined */ u32 alarms; /* Register encoding, combined */ @@ -590,7 +583,7 @@ store_fan_min(struct device *dev, struct device_attribute *devattr, mutex_lock(&data->update_lock); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); - w83627hf_write_value(data, W83781D_REG_FAN_MIN(nr+1), + w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr), data->fan_min[nr]); mutex_unlock(&data->update_lock); @@ -611,12 +604,10 @@ show_temp(struct device *dev, struct device_attribute *devattr, char *buf) { int nr = to_sensor_dev_attr(devattr)->index; struct w83627hf_data *data = w83627hf_update_device(dev); - if (nr >= 2) { /* TEMP2 and TEMP3 */ - return sprintf(buf, "%ld\n", - (long)LM75_TEMP_FROM_REG(data->temp_add[nr-2])); - } else { /* TEMP1 */ - return sprintf(buf, "%ld\n", (long)TEMP_FROM_REG(data->temp)); - } + + u16 tmp = data->temp[nr]; + return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp) + : (long) TEMP_FROM_REG(tmp)); } static ssize_t @@ -625,13 +616,10 @@ show_temp_max(struct device *dev, struct device_attribute *devattr, { int nr = to_sensor_dev_attr(devattr)->index; struct w83627hf_data *data = w83627hf_update_device(dev); - if (nr >= 2) { /* TEMP2 and TEMP3 */ - return sprintf(buf, "%ld\n", - (long)LM75_TEMP_FROM_REG(data->temp_max_add[nr-2])); - } else { /* TEMP1 */ - return sprintf(buf, "%ld\n", - (long)TEMP_FROM_REG(data->temp_max)); - } + + u16 tmp = data->temp_max[nr]; + return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp) + : (long) TEMP_FROM_REG(tmp)); } static ssize_t @@ -640,13 +628,10 @@ show_temp_max_hyst(struct device *dev, struct device_attribute *devattr, { int nr = to_sensor_dev_attr(devattr)->index; struct w83627hf_data *data = w83627hf_update_device(dev); - if (nr >= 2) { /* TEMP2 and TEMP3 */ - return sprintf(buf, "%ld\n", - (long)LM75_TEMP_FROM_REG(data->temp_max_hyst_add[nr-2])); - } else { /* TEMP1 */ - return sprintf(buf, "%ld\n", - (long)TEMP_FROM_REG(data->temp_max_hyst)); - } + + u16 tmp = data->temp_max_hyst[nr]; + return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp) + : (long) TEMP_FROM_REG(tmp)); } static ssize_t @@ -656,18 +641,11 @@ store_temp_max(struct device *dev, struct device_attribute *devattr, int nr = to_sensor_dev_attr(devattr)->index; struct w83627hf_data *data = dev_get_drvdata(dev); long val = simple_strtol(buf, NULL, 10); + u16 tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val); mutex_lock(&data->update_lock); - - if (nr >= 2) { /* TEMP2 and TEMP3 */ - data->temp_max_add[nr-2] = LM75_TEMP_TO_REG(val); - w83627hf_write_value(data, W83781D_REG_TEMP_OVER(nr), - data->temp_max_add[nr-2]); - } else { /* TEMP1 */ - data->temp_max = TEMP_TO_REG(val); - w83627hf_write_value(data, W83781D_REG_TEMP_OVER(nr), - data->temp_max); - } + data->temp_max[nr] = tmp; + w83627hf_write_value(data, w83627hf_reg_temp_over[nr], tmp); mutex_unlock(&data->update_lock); return count; } @@ -679,29 +657,22 @@ store_temp_max_hyst(struct device *dev, struct device_attribute *devattr, int nr = to_sensor_dev_attr(devattr)->index; struct w83627hf_data *data = dev_get_drvdata(dev); long val = simple_strtol(buf, NULL, 10); + u16 tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val); mutex_lock(&data->update_lock); - - if (nr >= 2) { /* TEMP2 and TEMP3 */ - data->temp_max_hyst_add[nr-2] = LM75_TEMP_TO_REG(val); - w83627hf_write_value(data, W83781D_REG_TEMP_HYST(nr), - data->temp_max_hyst_add[nr-2]); - } else { /* TEMP1 */ - data->temp_max_hyst = TEMP_TO_REG(val); - w83627hf_write_value(data, W83781D_REG_TEMP_HYST(nr), - data->temp_max_hyst); - } + data->temp_max_hyst[nr] = tmp; + w83627hf_write_value(data, w83627hf_reg_temp_hyst[nr], tmp); mutex_unlock(&data->update_lock); return count; } #define sysfs_temp_decl(offset) \ static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ - show_temp, NULL, offset); \ + show_temp, NULL, offset - 1); \ static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO|S_IWUSR, \ - show_temp_max, store_temp_max, offset); \ + show_temp_max, store_temp_max, offset - 1); \ static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO|S_IWUSR, \ - show_temp_max_hyst, store_temp_max_hyst, offset); + show_temp_max_hyst, store_temp_max_hyst, offset - 1); sysfs_temp_decl(1); sysfs_temp_decl(2); @@ -844,7 +815,7 @@ store_fan_div(struct device *dev, struct device_attribute *devattr, /* Restore fan_min */ data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); - w83627hf_write_value(data, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]); + w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr), data->fan_min[nr]); mutex_unlock(&data->update_lock); return count; @@ -1170,7 +1141,7 @@ static int __devinit w83627hf_probe(struct platform_device *pdev) struct w83627hf_sio_data *sio_data = dev->platform_data; struct w83627hf_data *data; struct resource *res; - int err; + int err, i; static const char *names[] = { "w83627hf", @@ -1204,9 +1175,9 @@ static int __devinit w83627hf_probe(struct platform_device *pdev) w83627hf_init_device(pdev); /* A few vars need to be filled upon startup */ - data->fan_min[0] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(1)); - data->fan_min[1] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(2)); - data->fan_min[2] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(3)); + for (i = 0; i <= 2; i++) + data->fan_min[i] = w83627hf_read_value( + data, W83627HF_REG_FAN_MIN(i)); w83627hf_update_fan_div(data); /* Register common device attributes */ @@ -1514,23 +1485,23 @@ static void __devinit w83627hf_init_device(struct platform_device *pdev) if(init) { /* Enable temp2 */ - tmp = w83627hf_read_value(data, W83781D_REG_TEMP2_CONFIG); + tmp = w83627hf_read_value(data, W83627HF_REG_TEMP2_CONFIG); if (tmp & 0x01) { dev_warn(&pdev->dev, "Enabling temp2, readings " "might not make sense\n"); - w83627hf_write_value(data, W83781D_REG_TEMP2_CONFIG, + w83627hf_write_value(data, W83627HF_REG_TEMP2_CONFIG, tmp & 0xfe); } /* Enable temp3 */ if (type != w83697hf) { tmp = w83627hf_read_value(data, - W83781D_REG_TEMP3_CONFIG); + W83627HF_REG_TEMP3_CONFIG); if (tmp & 0x01) { dev_warn(&pdev->dev, "Enabling temp3, " "readings might not make sense\n"); w83627hf_write_value(data, - W83781D_REG_TEMP3_CONFIG, tmp & 0xfe); + W83627HF_REG_TEMP3_CONFIG, tmp & 0xfe); } } } @@ -1563,7 +1534,7 @@ static void w83627hf_update_fan_div(struct w83627hf_data *data) static struct w83627hf_data *w83627hf_update_device(struct device *dev) { struct w83627hf_data *data = dev_get_drvdata(dev); - int i; + int i, num_temps = (data->type == w83697hf) ? 2 : 3; mutex_lock(&data->update_lock); @@ -1584,12 +1555,12 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev) w83627hf_read_value(data, W83781D_REG_IN_MAX(i)); } - for (i = 1; i <= 3; i++) { - data->fan[i - 1] = - w83627hf_read_value(data, W83781D_REG_FAN(i)); - data->fan_min[i - 1] = + for (i = 0; i <= 2; i++) { + data->fan[i] = + w83627hf_read_value(data, W83627HF_REG_FAN(i)); + data->fan_min[i] = w83627hf_read_value(data, - W83781D_REG_FAN_MIN(i)); + W83627HF_REG_FAN_MIN(i)); } for (i = 0; i <= 2; i++) { u8 tmp = w83627hf_read_value(data, @@ -1616,25 +1587,13 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev) break; } } - - data->temp = w83627hf_read_value(data, W83781D_REG_TEMP(1)); - data->temp_max = - w83627hf_read_value(data, W83781D_REG_TEMP_OVER(1)); - data->temp_max_hyst = - w83627hf_read_value(data, W83781D_REG_TEMP_HYST(1)); - data->temp_add[0] = - w83627hf_read_value(data, W83781D_REG_TEMP(2)); - data->temp_max_add[0] = - w83627hf_read_value(data, W83781D_REG_TEMP_OVER(2)); - data->temp_max_hyst_add[0] = - w83627hf_read_value(data, W83781D_REG_TEMP_HYST(2)); - if (data->type != w83697hf) { - data->temp_add[1] = - w83627hf_read_value(data, W83781D_REG_TEMP(3)); - data->temp_max_add[1] = - w83627hf_read_value(data, W83781D_REG_TEMP_OVER(3)); - data->temp_max_hyst_add[1] = - w83627hf_read_value(data, W83781D_REG_TEMP_HYST(3)); + for (i = 0; i < num_temps; i++) { + data->temp[i] = w83627hf_read_value( + data, w83627hf_reg_temp[i]); + data->temp_max[i] = w83627hf_read_value( + data, w83627hf_reg_temp_over[i]); + data->temp_max_hyst[i] = w83627hf_read_value( + data, w83627hf_reg_temp_hyst[i]); } w83627hf_update_fan_div(data); diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index a6a1edfe7614..e0fa7520400d 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -1122,12 +1122,13 @@ w83781d_create_files(struct device *dev, int kind, int is_isa) &sensor_dev_attr_temp3_beep.dev_attr))) return err; - if (kind != w83781d) + if (kind != w83781d) { err = sysfs_chmod_file(&dev->kobj, &sensor_dev_attr_temp3_alarm.dev_attr.attr, S_IRUGO | S_IWUSR); if (err) return err; + } } if (kind != w83781d && kind != as99127f) { diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c index 58e32714afb5..ca18e0be4901 100644 --- a/drivers/i2c/busses/i2c-pasemi.c +++ b/drivers/i2c/busses/i2c-pasemi.c @@ -51,6 +51,7 @@ struct pasemi_smbus { #define MRXFIFO_DATA_M 0x000000ff #define SMSTA_XEN 0x08000000 +#define SMSTA_MTN 0x00200000 #define CTL_MRR 0x00000400 #define CTL_MTR 0x00000200 @@ -98,6 +99,10 @@ static unsigned int pasemi_smb_waitready(struct pasemi_smbus *smbus) status = reg_read(smbus, REG_SMSTA); } + /* Got NACK? */ + if (status & SMSTA_MTN) + return -ENXIO; + if (timeout < 0) { dev_warn(&smbus->dev->dev, "Timeout, status 0x%08x\n", status); reg_write(smbus, REG_SMSTA, status); @@ -364,7 +369,7 @@ static int __devinit pasemi_smb_probe(struct pci_dev *dev, smbus->adapter.algo = &smbus_algorithm; smbus->adapter.algo_data = smbus; - /* set up the driverfs linkage to our parent device */ + /* set up the sysfs linkage to our parent device */ smbus->adapter.dev.parent = &dev->dev; reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR | diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c index d3da1fb05b9b..1a7eeebac506 100644 --- a/drivers/i2c/chips/eeprom.c +++ b/drivers/i2c/chips/eeprom.c @@ -128,13 +128,20 @@ static ssize_t eeprom_read(struct kobject *kobj, struct bin_attribute *bin_attr, for (slice = off >> 5; slice <= (off + count - 1) >> 5; slice++) eeprom_update_client(client, slice); - /* Hide Vaio security settings to regular users (16 first bytes) */ - if (data->nature == VAIO && off < 16 && !capable(CAP_SYS_ADMIN)) { - size_t in_row1 = 16 - off; - in_row1 = min(in_row1, count); - memset(buf, 0, in_row1); - if (count - in_row1 > 0) - memcpy(buf + in_row1, &data->data[16], count - in_row1); + /* Hide Vaio private settings to regular users: + - BIOS passwords: bytes 0x00 to 0x0f + - UUID: bytes 0x10 to 0x1f + - Serial number: 0xc0 to 0xdf */ + if (data->nature == VAIO && !capable(CAP_SYS_ADMIN)) { + int i; + + for (i = 0; i < count; i++) { + if ((off + i <= 0x1f) || + (off + i >= 0xc0 && off + i <= 0xdf)) + buf[i] = 0; + else + buf[i] = data->data[off + i]; + } } else { memcpy(buf, &data->data[off], count); } @@ -197,14 +204,18 @@ static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind) goto exit_kfree; /* Detect the Vaio nature of EEPROMs. - We use the "PCG-" prefix as the signature. */ + We use the "PCG-" or "VGN-" prefix as the signature. */ if (address == 0x57) { - if (i2c_smbus_read_byte_data(new_client, 0x80) == 'P' - && i2c_smbus_read_byte(new_client) == 'C' - && i2c_smbus_read_byte(new_client) == 'G' - && i2c_smbus_read_byte(new_client) == '-') { + char name[4]; + + name[0] = i2c_smbus_read_byte_data(new_client, 0x80); + name[1] = i2c_smbus_read_byte(new_client); + name[2] = i2c_smbus_read_byte(new_client); + name[3] = i2c_smbus_read_byte(new_client); + + if (!memcmp(name, "PCG-", 4) || !memcmp(name, "VGN-", 4)) { dev_info(&new_client->dev, "Vaio EEPROM detected, " - "enabling password protection\n"); + "enabling privacy protection\n"); data->nature = VAIO; } } diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 1a4e8dc03b36..b5e13e405e72 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -673,7 +673,7 @@ static int __i2c_check_addr(struct i2c_adapter *adapter, unsigned int addr) return 0; } -int i2c_check_addr(struct i2c_adapter *adapter, int addr) +static int i2c_check_addr(struct i2c_adapter *adapter, int addr) { int rval; @@ -683,7 +683,6 @@ int i2c_check_addr(struct i2c_adapter *adapter, int addr) return rval; } -EXPORT_SYMBOL(i2c_check_addr); int i2c_attach_client(struct i2c_client *client) { diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 5a15e50748de..c21ae20ae362 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -38,6 +38,15 @@ static struct i2c_driver i2cdev_driver; +/* + * An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a + * slave (i2c_client) with which messages will be exchanged. It's coupled + * with a character special file which is accessed by user mode drivers. + * + * The list of i2c_dev structures is parallel to the i2c_adapter lists + * maintained by the driver model, and is updated using notifications + * delivered to the i2cdev_driver. + */ struct i2c_dev { struct list_head list; struct i2c_adapter *adap; @@ -103,6 +112,25 @@ static ssize_t show_adapter_name(struct device *dev, } static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL); +/* ------------------------------------------------------------------------- */ + +/* + * After opening an instance of this character special file, a file + * descriptor starts out associated only with an i2c_adapter (and bus). + * + * Using the I2C_RDWR ioctl(), you can then *immediately* issue i2c_msg + * traffic to any devices on the bus used by that adapter. That's because + * the i2c_msg vectors embed all the addressing information they need, and + * are submitted directly to an i2c_adapter. However, SMBus-only adapters + * don't support that interface. + * + * To use read()/write() system calls on that file descriptor, or to use + * SMBus interfaces (and work with SMBus-only hosts!), you must first issue + * an I2C_SLAVE (or I2C_SLAVE_FORCE) ioctl. That configures an anonymous + * (never registered) i2c_client so it holds the addressing information + * needed by those system calls and by this SMBus interface. + */ + static ssize_t i2cdev_read (struct file *file, char __user *buf, size_t count, loff_t *offset) { @@ -154,6 +182,29 @@ static ssize_t i2cdev_write (struct file *file, const char __user *buf, size_t c return ret; } +/* This address checking function differs from the one in i2c-core + in that it considers an address with a registered device, but no + bounded driver, as NOT busy. */ +static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr) +{ + struct list_head *item; + struct i2c_client *client; + int res = 0; + + mutex_lock(&adapter->clist_lock); + list_for_each(item, &adapter->clients) { + client = list_entry(item, struct i2c_client, list); + if (client->addr == addr) { + if (client->driver) + res = -EBUSY; + break; + } + } + mutex_unlock(&adapter->clist_lock); + + return res; +} + static int i2cdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { @@ -172,11 +223,22 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file, switch ( cmd ) { case I2C_SLAVE: case I2C_SLAVE_FORCE: + /* NOTE: devices set up to work with "new style" drivers + * can't use I2C_SLAVE, even when the device node is not + * bound to a driver. Only I2C_SLAVE_FORCE will work. + * + * Setting the PEC flag here won't affect kernel drivers, + * which will be using the i2c_client node registered with + * the driver model core. Likewise, when that client has + * the PEC flag already set, the i2c-dev driver won't see + * (or use) this setting. + */ if ((arg > 0x3ff) || (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f)) return -EINVAL; - if ((cmd == I2C_SLAVE) && i2c_check_addr(client->adapter,arg)) + if (cmd == I2C_SLAVE && i2cdev_check_addr(client->adapter, arg)) return -EBUSY; + /* REVISIT: address could become busy later */ client->addr = arg; return 0; case I2C_TENBIT: @@ -386,6 +448,13 @@ static int i2cdev_open(struct inode *inode, struct file *file) if (!adap) return -ENODEV; + /* This creates an anonymous i2c_client, which may later be + * pointed to some address using I2C_SLAVE or I2C_SLAVE_FORCE. + * + * This client is ** NEVER REGISTERED ** with the driver model + * or I2C core code!! It just holds private copies of addressing + * information and maybe a PEC flag. + */ client = kzalloc(sizeof(*client), GFP_KERNEL); if (!client) { i2c_put_adapter(adap); @@ -394,7 +463,6 @@ static int i2cdev_open(struct inode *inode, struct file *file) snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr); client->driver = &i2cdev_driver; - /* registered with adapter, passed as client to user */ client->adapter = adap; file->private_data = client; @@ -422,6 +490,14 @@ static const struct file_operations i2cdev_fops = { .release = i2cdev_release, }; +/* ------------------------------------------------------------------------- */ + +/* + * The legacy "i2cdev_driver" is used primarily to get notifications when + * I2C adapters are added or removed, so that each one gets an i2c_dev + * and is thus made available to userspace driver code. + */ + static struct class *i2c_dev_class; static int i2cdev_attach_adapter(struct i2c_adapter *adap) @@ -486,6 +562,12 @@ static struct i2c_driver i2cdev_driver = { .detach_client = i2cdev_detach_client, }; +/* ------------------------------------------------------------------------- */ + +/* + * module load/unload record keeping + */ + static int __init i2c_dev_init(void) { int res; diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index d1e8df187222..45b22282f149 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -203,10 +203,6 @@ config BLK_DEV_IDECD CD-ROM drive, you can say N to all other CD-ROM options, but be sure to say Y or M to "ISO 9660 CD-ROM file system support". - Note that older versions of LILO (LInux LOader) cannot properly deal - with IDE/ATAPI CD-ROMs, so install LILO 16 or higher, available from - <http://lilo.go.dyndns.org/>. - To compile this driver as a module, choose M here: the module will be called ide-cd. @@ -317,7 +313,6 @@ comment "IDE chipset support/bugfixes" config IDE_GENERIC tristate "generic/default IDE chipset support" - default H8300 help If unsure, say N. @@ -488,6 +483,7 @@ config WDC_ALI15X3 config BLK_DEV_AMD74XX tristate "AMD and nVidia IDE support" + depends on !ARM select BLK_DEV_IDEDMA_PCI help This driver adds explicit support for AMD-7xx and AMD-8111 chips @@ -887,6 +883,49 @@ config BLK_DEV_IDE_BAST Say Y here if you want to support the onboard IDE channels on the Simtec BAST or the Thorcom VR1000 +config ETRAX_IDE + bool "ETRAX IDE support" + depends on CRIS && BROKEN + select BLK_DEV_IDEDMA + select IDE_GENERIC + help + Enables the ETRAX IDE driver. + + You can't use parallel ports or SCSI ports at the same time. + +config ETRAX_IDE_DELAY + int "Delay for drives to regain consciousness" + depends on ETRAX_IDE && ETRAX_ARCH_V10 + default 15 + help + Number of seconds to wait for IDE drives to spin up after an IDE + reset. + +choice + prompt "IDE reset pin" + depends on ETRAX_IDE && ETRAX_ARCH_V10 + default ETRAX_IDE_PB7_RESET + +config ETRAX_IDE_PB7_RESET + bool "Port_PB_Bit_7" + help + IDE reset on pin 7 on port B + +config ETRAX_IDE_G27_RESET + bool "Port_G_Bit_27" + help + IDE reset on pin 27 on port G + +endchoice + +config IDE_H8300 + bool "H8300 IDE support" + depends on H8300 + select IDE_GENERIC + default y + help + Enables the H8300 IDE driver. + config BLK_DEV_GAYLE bool "Amiga Gayle IDE interface support" depends on AMIGA @@ -967,7 +1006,7 @@ config BLK_DEV_Q40IDE config BLK_DEV_MPC8xx_IDE bool "MPC8xx IDE support" - depends on 8xx && IDE=y && BLK_DEV_IDE=y && !PPC_MERGE + depends on 8xx && (LWMON || IVMS8 || IVML24 || TQM8xxL) && IDE=y && BLK_DEV_IDE=y && !PPC_MERGE select IDE_GENERIC help This option provides support for IDE on Motorola MPC8xx Systems. diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index 75dc6969e0a7..b181fc672057 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -39,7 +39,7 @@ ide-core-$(CONFIG_BLK_DEV_MPC8xx_IDE) += ppc/mpc8xx.o ide-core-$(CONFIG_BLK_DEV_IDE_PMAC) += ppc/pmac.o # built-in only drivers from h8300/ -ide-core-$(CONFIG_H8300) += h8300/ide-h8300.o +ide-core-$(CONFIG_IDE_H8300) += h8300/ide-h8300.o obj-$(CONFIG_BLK_DEV_IDE) += ide-core.o obj-$(CONFIG_IDE_GENERIC) += ide-generic.o diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c index e196aefa2070..476e0d65ed43 100644 --- a/drivers/ide/cris/ide-cris.c +++ b/drivers/ide/cris/ide-cris.c @@ -748,8 +748,7 @@ static void cris_set_dma_mode(ide_drive_t *drive, const u8 speed) hold = ATA_DMA2_HOLD; break; default: - BUG(); - break; + return; } if (speed >= XFER_UDMA_0) @@ -774,15 +773,16 @@ init_e100_ide (void) /* the IDE control register is at ATA address 6, with CS1 active instead of CS0 */ ide_offsets[IDE_CONTROL_OFFSET] = cris_ide_reg_addr(6, 1, 0); - /* first fill in some stuff in the ide_hwifs fields */ + for (h = 0; h < 4; h++) { + ide_hwif_t *hwif = NULL; - for(h = 0; h < MAX_HWIFS; h++) { - ide_hwif_t *hwif = &ide_hwifs[h]; ide_setup_ports(&hw, cris_ide_base_address(h), ide_offsets, 0, 0, cris_ide_ack_intr, ide_default_irq(0)); ide_register_hw(&hw, NULL, 1, &hwif); + if (hwif == NULL) + continue; hwif->mmio = 1; hwif->chipset = ide_etrax100; hwif->set_pio_mode = &cris_set_pio_mode; diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index e3add70b9cd8..0d795a1678c7 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -130,6 +130,7 @@ static const struct drive_list_entry drive_blacklist [] = { { "_NEC DV5800A", NULL }, { "SAMSUNG CD-ROM SN-124", "N001" }, { "Seagate STT20000A", NULL }, + { "CD-ROM CDR_U200", "1.09" }, { NULL , NULL } }; diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 755011827afa..db22d1ff4e55 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -885,7 +885,6 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, return do_rw_taskfile(drive, args); } else if (rq->cmd_type == REQ_TYPE_ATA_TASK) { u8 *args = rq->buffer; - u8 sel; if (!args) goto done; @@ -903,10 +902,7 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, hwif->OUTB(args[3], IDE_SECTOR_REG); hwif->OUTB(args[4], IDE_LCYL_REG); hwif->OUTB(args[5], IDE_HCYL_REG); - sel = (args[6] & ~0x10); - if (drive->select.b.unit) - sel |= 0x10; - hwif->OUTB(sel, IDE_SELECT_REG); + hwif->OUTB((args[6] & 0xEF)|drive->select.all, IDE_SELECT_REG); ide_cmd(drive, args[0], args[2], &drive_cmd_intr); return ide_started; } else if (rq->cmd_type == REQ_TYPE_ATA_CMD) { diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index e17a9ee120ea..5c3256180ae5 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -303,9 +303,6 @@ void default_hwif_transport(ide_hwif_t *hwif) hwif->atapi_output_bytes = atapi_output_bytes; } -/* - * Beginning of Taskfile OPCODE Library and feature sets. - */ void ide_fix_driveid (struct hd_driveid *id) { #ifndef __LITTLE_ENDIAN @@ -592,6 +589,9 @@ EXPORT_SYMBOL_GPL(ide_in_drive_list); static const struct drive_list_entry ivb_list[] = { { "QUANTUM FIREBALLlct10 05" , "A03.0900" }, { "TSSTcorp CDDVDW SH-S202J" , "SB00" }, + { "TSSTcorp CDDVDW SH-S202J" , "SB01" }, + { "TSSTcorp CDDVDW SH-S202N" , "SB00" }, + { "TSSTcorp CDDVDW SH-S202N" , "SB01" }, { NULL , NULL } }; @@ -756,7 +756,7 @@ int ide_driveid_update(ide_drive_t *drive) int ide_config_drive_speed(ide_drive_t *drive, u8 speed) { ide_hwif_t *hwif = drive->hwif; - int error; + int error = 0; u8 stat; // while (HWGROUP(drive)->busy) @@ -767,6 +767,10 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) hwif->dma_host_off(drive); #endif + /* Skip setting PIO flow-control modes on pre-EIDE drives */ + if ((speed & 0xf8) == XFER_PIO_0 && !(drive->id->capability & 0x08)) + goto skip; + /* * Don't use ide_wait_cmd here - it will * attempt to set_geometry and recalibrate, @@ -814,6 +818,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) drive->id->dma_mword &= ~0x0F00; drive->id->dma_1word &= ~0x0F00; + skip: #ifdef CONFIG_BLK_DEV_IDEDMA if (speed >= XFER_SW_DMA_0) hwif->dma_host_on(drive); diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index af86433baede..1609b8604f56 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -514,6 +514,7 @@ static u8 ide_dump_ata_status(ide_drive_t *drive, const char *msg, u8 stat) if (drive->addressing == 1) { __u64 sectors = 0; u32 low = 0, high = 0; + hwif->OUTB(drive->ctl&~0x80, IDE_CONTROL_REG); low = ide_read_24(drive); hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG); high = ide_read_24(drive); diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 56fb0b843429..ee848c705995 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -644,7 +644,7 @@ static void hwif_register (ide_hwif_t *hwif) static int wait_hwif_ready(ide_hwif_t *hwif) { - int rc; + int unit, rc; printk(KERN_DEBUG "Probing IDE interface %s...\n", hwif->name); @@ -661,20 +661,26 @@ static int wait_hwif_ready(ide_hwif_t *hwif) return rc; /* Now make sure both master & slave are ready */ - SELECT_DRIVE(&hwif->drives[0]); - hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]); - mdelay(2); - rc = ide_wait_not_busy(hwif, 35000); - if (rc) - return rc; - SELECT_DRIVE(&hwif->drives[1]); - hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]); - mdelay(2); - rc = ide_wait_not_busy(hwif, 35000); + for (unit = 0; unit < MAX_DRIVES; unit++) { + ide_drive_t *drive = &hwif->drives[unit]; + /* Ignore disks that we will not probe for later. */ + if (!drive->noprobe || drive->present) { + SELECT_DRIVE(drive); + hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]); + mdelay(2); + rc = ide_wait_not_busy(hwif, 35000); + if (rc) + goto out; + } else + printk(KERN_DEBUG "%s: ide_wait_not_busy() skipped\n", + drive->name); + } +out: /* Exit function with master reselected (let's be sane) */ - SELECT_DRIVE(&hwif->drives[0]); - + if (unit) + SELECT_DRIVE(&hwif->drives[0]); + return rc; } diff --git a/drivers/ide/legacy/ali14xx.c b/drivers/ide/legacy/ali14xx.c index 10311ecc674a..38c3a6d63f30 100644 --- a/drivers/ide/legacy/ali14xx.c +++ b/drivers/ide/legacy/ali14xx.c @@ -53,12 +53,13 @@ /* port addresses for auto-detection */ #define ALI_NUM_PORTS 4 -static int ports[ALI_NUM_PORTS] __initdata = {0x074, 0x0f4, 0x034, 0x0e4}; +static const int ports[ALI_NUM_PORTS] __initdata = + { 0x074, 0x0f4, 0x034, 0x0e4 }; /* register initialization data */ typedef struct { u8 reg, data; } RegInitializer; -static RegInitializer initData[] __initdata = { +static const RegInitializer initData[] __initdata = { {0x01, 0x0f}, {0x02, 0x00}, {0x03, 0x00}, {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x2b}, {0x0a, 0x0f}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00}, {0x28, 0x00}, @@ -177,7 +178,7 @@ static int __init findPort (void) * Initialize controller registers with default values. */ static int __init initRegisters (void) { - RegInitializer *p; + const RegInitializer *p; u8 t; unsigned long flags; diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c index e87cd2f16430..5c6aa77c2370 100644 --- a/drivers/ide/legacy/macide.c +++ b/drivers/ide/legacy/macide.c @@ -81,7 +81,7 @@ int macide_ack_intr(ide_hwif_t* hwif) * Probe for a Macintosh IDE interface */ -void macide_init(void) +void __init macide_init(void) { hw_regs_t hw; ide_hwif_t *hwif; diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c index a73db1bd482d..6ea46a6723e2 100644 --- a/drivers/ide/legacy/q40ide.c +++ b/drivers/ide/legacy/q40ide.c @@ -111,7 +111,7 @@ static const char *q40_ide_names[Q40IDE_NUM_HWIFS]={ * Probe for Q40 IDE interfaces */ -void q40ide_init(void) +void __init q40ide_init(void) { int i; ide_hwif_t *hwif; diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c index 19ec421f7b9f..44268504ae43 100644 --- a/drivers/ide/pci/aec62xx.c +++ b/drivers/ide/pci/aec62xx.c @@ -260,6 +260,11 @@ static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_devi { struct ide_port_info d; u8 idx = id->driver_data; + int err; + + err = pci_enable_device(dev); + if (err) + return err; d = aec62xx_chipsets[idx]; @@ -272,7 +277,11 @@ static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_devi } } - return ide_setup_pci_device(dev, &d); + err = ide_setup_pci_device(dev, &d); + if (err) + pci_disable_device(dev); + + return err; } static const struct pci_device_id aec62xx_pci_tbl[] = { diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c index a607dd31a64c..ce293936af4b 100644 --- a/drivers/ide/pci/alim15x3.c +++ b/drivers/ide/pci/alim15x3.c @@ -603,6 +603,11 @@ static int ali_cable_override(struct pci_dev *pdev) pdev->subsystem_device == 0x10AF) return 1; + /* Mitac 8317 (Winbook-A) and relatives */ + if (pdev->subsystem_vendor == 0x1071 && + pdev->subsystem_device == 0x8317) + return 1; + /* Systems by DMI */ if (dmi_check_system(cable_dmi_table)) return 1; diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c index ea0143ef5fe5..51fca441c294 100644 --- a/drivers/ide/pci/cmd64x.c +++ b/drivers/ide/pci/cmd64x.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/cmd64x.c Version 1.50 May 10, 2007 + * linux/drivers/ide/pci/cmd64x.c Version 1.51 Nov 8, 2007 * * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines. * Due to massive hardware bugs, UltraDMA is only supported @@ -339,7 +339,8 @@ static int cmd648_ide_dma_end (ide_drive_t *drive) u8 mrdmode = inb(hwif->dma_master + 0x01); /* clear the interrupt bit */ - outb(mrdmode | irq_mask, hwif->dma_master + 0x01); + outb((mrdmode & ~(MRDMODE_INTR_CH0 | MRDMODE_INTR_CH1)) | irq_mask, + hwif->dma_master + 0x01); return err; } diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c index 599408952bd4..547690395eee 100644 --- a/drivers/ide/pci/cs5530.c +++ b/drivers/ide/pci/cs5530.c @@ -117,8 +117,7 @@ static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode) case XFER_MW_DMA_1: timings = 0x00012121; break; case XFER_MW_DMA_2: timings = 0x00002020; break; default: - BUG(); - break; + return; } basereg = CS5530_BASEREG(drive->hwif); reg = inl(basereg + 4); /* get drive0 config register */ diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c index 5c9975435319..99b7d763b6c7 100644 --- a/drivers/ide/pci/it821x.c +++ b/drivers/ide/pci/it821x.c @@ -653,8 +653,7 @@ static const struct ide_port_info it821x_chipsets[] __devinitdata = { static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]); - return 0; + return ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]); } static const struct pci_device_id it821x_pci_tbl[] = { diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c index bdf64d997708..0083eaf89c77 100644 --- a/drivers/ide/pci/jmicron.c +++ b/drivers/ide/pci/jmicron.c @@ -139,8 +139,7 @@ static const struct ide_port_info jmicron_chipset __devinitdata = { static int __devinit jmicron_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - ide_setup_pci_device(dev, &jmicron_chipset); - return 0; + return ide_setup_pci_device(dev, &jmicron_chipset); } /* All JMB PATA controllers have and will continue to have the same diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c index 63625a0be712..27781d294cea 100644 --- a/drivers/ide/pci/piix.c +++ b/drivers/ide/pci/piix.c @@ -306,6 +306,7 @@ static const struct ich_laptop ich_laptop[] = { { 0x27DF, 0x0005, 0x0280 }, /* ICH7 on Acer 5602WLMi */ { 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */ { 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */ + { 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */ { 0x24CA, 0x1025, 0x0061 }, /* ICH4 on Acer Aspire 2023WLMi */ /* end marker */ { 0, } diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c index 0a7b3202066d..707d5ff66b03 100644 --- a/drivers/ide/pci/sc1200.c +++ b/drivers/ide/pci/sc1200.c @@ -186,8 +186,7 @@ static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode) } break; default: - BUG(); - break; + return; } if (unit == 0) { /* are we configuring drive0? */ diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c index 6d99441c605b..5709c252543b 100644 --- a/drivers/ide/pci/siimage.c +++ b/drivers/ide/pci/siimage.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/siimage.c Version 1.18 Oct 18 2007 + * linux/drivers/ide/pci/siimage.c Version 1.19 Nov 16 2007 * * Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 2003 Red Hat <alan@redhat.com> @@ -460,48 +460,6 @@ static void sil_sata_pre_reset(ide_drive_t *drive) } /** - * siimage_reset - reset a device on an siimage controller - * @drive: drive to reset - * - * Perform a controller level reset fo the device. For - * SATA we must also check the PHY. - */ - -static void siimage_reset (ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - u8 reset = 0; - unsigned long addr = siimage_selreg(hwif, 0); - - if (hwif->mmio) { - reset = hwif->INB(addr); - hwif->OUTB((reset|0x03), addr); - /* FIXME:posting */ - udelay(25); - hwif->OUTB(reset, addr); - (void) hwif->INB(addr); - } else { - pci_read_config_byte(hwif->pci_dev, addr, &reset); - pci_write_config_byte(hwif->pci_dev, addr, reset|0x03); - udelay(25); - pci_write_config_byte(hwif->pci_dev, addr, reset); - pci_read_config_byte(hwif->pci_dev, addr, &reset); - } - - if (SATA_STATUS_REG) { - /* SATA_STATUS_REG is valid only when in MMIO mode */ - u32 sata_stat = readl((void __iomem *)SATA_STATUS_REG); - printk(KERN_WARNING "%s: reset phy, status=0x%08x, %s\n", - hwif->name, sata_stat, __FUNCTION__); - if (!(sata_stat)) { - printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n", - hwif->name, sata_stat); - drive->failures++; - } - } -} - -/** * proc_reports_siimage - add siimage controller to proc * @dev: PCI device * @clocking: SCSC value @@ -857,7 +815,6 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif) { u8 sata = is_sata(hwif); - hwif->resetproc = &siimage_reset; hwif->set_pio_mode = &sil_set_pio_mode; hwif->set_dma_mode = &sil_set_dma_mode; diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c index 6b7bb53acefd..d90b42917775 100644 --- a/drivers/ide/pci/sis5513.c +++ b/drivers/ide/pci/sis5513.c @@ -356,7 +356,6 @@ static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed) sis_program_timings(drive, speed); break; default: - BUG(); break; } } @@ -527,6 +526,7 @@ static const struct sis_laptop sis_laptop[] = { /* devid, subvendor, subdev */ { 0x5513, 0x1043, 0x1107 }, /* ASUS A6K */ { 0x5513, 0x1734, 0x105f }, /* FSC Amilo A1630 */ + { 0x5513, 0x1071, 0x8640 }, /* EasyNote K5305 */ /* end marker */ { 0, } }; diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c index 5011ba22e36c..0895e753a35d 100644 --- a/drivers/ide/pci/trm290.c +++ b/drivers/ide/pci/trm290.c @@ -240,9 +240,6 @@ static int trm290_ide_dma_test_irq (ide_drive_t *drive) return (status == 0x00ff); } -/* - * Invoked from ide-dma.c at boot time. - */ static void __devinit init_hwif_trm290(ide_hwif_t *hwif) { unsigned int cfgbase = 0; diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index 816b5311dad6..7f7a59885777 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -1138,6 +1138,7 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) hwif->drives[0].autotune = IDE_TUNE_AUTO; hwif->drives[1].autotune = IDE_TUNE_AUTO; hwif->host_flags = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA | + IDE_HFLAG_PIO_NO_DOWNGRADE | IDE_HFLAG_POST_SET_MODE; hwif->pio_mask = ATA_PIO4; hwif->set_pio_mode = pmac_ide_set_pio_mode; @@ -1512,7 +1513,7 @@ pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq) if (pmif->broken_dma && cur_addr & (L1_CACHE_BYTES - 1)) { if (pmif->broken_dma_warn == 0) { - printk(KERN_WARNING "%s: DMA on non aligned address," + printk(KERN_WARNING "%s: DMA on non aligned address, " "switching to PIO on Ohare chipset\n", drive->name); pmif->broken_dma_warn = 1; } diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 02d14bf85ab2..25fd09053220 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -7,11 +7,6 @@ * May be copied or modified under the terms of the GNU General Public License */ -/* - * This module provides support for automatic detection and - * configuration of all PCI IDE interfaces present in a system. - */ - #include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c index f0c777589374..b5436ca92e68 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_provider.c +++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c @@ -1000,6 +1000,7 @@ static int iwch_query_device(struct ib_device *ibdev, props->max_sge = dev->attr.max_sge_per_wr; props->max_sge_rd = 1; props->max_qp_rd_atom = dev->attr.max_rdma_reads_per_qp; + props->max_qp_init_rd_atom = dev->attr.max_rdma_reads_per_qp; props->max_cq = dev->attr.max_cqs; props->max_cqe = dev->attr.max_cqes_per_cq; props->max_mr = dev->attr.max_mem_regs; diff --git a/drivers/infiniband/hw/ehca/ehca_av.c b/drivers/infiniband/hw/ehca/ehca_av.c index 97d108634c58..f7782c882ab4 100644 --- a/drivers/infiniband/hw/ehca/ehca_av.c +++ b/drivers/infiniband/hw/ehca/ehca_av.c @@ -50,6 +50,42 @@ static struct kmem_cache *av_cache; +int ehca_calc_ipd(struct ehca_shca *shca, int port, + enum ib_rate path_rate, u32 *ipd) +{ + int path = ib_rate_to_mult(path_rate); + int link, ret; + struct ib_port_attr pa; + + if (path_rate == IB_RATE_PORT_CURRENT) { + *ipd = 0; + return 0; + } + + if (unlikely(path < 0)) { + ehca_err(&shca->ib_device, "Invalid static rate! path_rate=%x", + path_rate); + return -EINVAL; + } + + ret = ehca_query_port(&shca->ib_device, port, &pa); + if (unlikely(ret < 0)) { + ehca_err(&shca->ib_device, "Failed to query port ret=%i", ret); + return ret; + } + + link = ib_width_enum_to_int(pa.active_width) * pa.active_speed; + + if (path >= link) + /* no need to throttle if path faster than link */ + *ipd = 0; + else + /* IPD = round((link / path) - 1) */ + *ipd = ((link + (path >> 1)) / path) - 1; + + return 0; +} + struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr) { int ret; @@ -69,15 +105,13 @@ struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr) av->av.slid_path_bits = ah_attr->src_path_bits; if (ehca_static_rate < 0) { - int ah_mult = ib_rate_to_mult(ah_attr->static_rate); - int ehca_mult = - ib_rate_to_mult(shca->sport[ah_attr->port_num].rate ); - - if (ah_mult >= ehca_mult) - av->av.ipd = 0; - else - av->av.ipd = (ah_mult > 0) ? - ((ehca_mult - 1) / ah_mult) : 0; + u32 ipd; + if (ehca_calc_ipd(shca, ah_attr->port_num, + ah_attr->static_rate, &ipd)) { + ret = -EINVAL; + goto create_ah_exit1; + } + av->av.ipd = ipd; } else av->av.ipd = ehca_static_rate; diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h index 2d660ae189e5..87f12d4312a7 100644 --- a/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/drivers/infiniband/hw/ehca/ehca_classes.h @@ -95,7 +95,6 @@ struct ehca_sma_attr { struct ehca_sport { struct ib_cq *ibcq_aqp1; struct ib_qp *ibqp_aqp1; - enum ib_rate rate; enum ib_port_state port_state; struct ehca_sma_attr saved_attr; }; diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c index 15806d140461..5bd7b591987e 100644 --- a/drivers/infiniband/hw/ehca/ehca_hca.c +++ b/drivers/infiniband/hw/ehca/ehca_hca.c @@ -151,7 +151,6 @@ int ehca_query_port(struct ib_device *ibdev, } memset(props, 0, sizeof(struct ib_port_attr)); - props->state = rblock->state; switch (rblock->max_mtu) { case 0x1: @@ -188,11 +187,20 @@ int ehca_query_port(struct ib_device *ibdev, props->subnet_timeout = rblock->subnet_timeout; props->init_type_reply = rblock->init_type_reply; - props->active_width = IB_WIDTH_12X; - props->active_speed = 0x1; - - /* at the moment (logical) link state is always LINK_UP */ - props->phys_state = 0x5; + if (rblock->state && rblock->phys_width) { + props->phys_state = rblock->phys_pstate; + props->state = rblock->phys_state; + props->active_width = rblock->phys_width; + props->active_speed = rblock->phys_speed; + } else { + /* old firmware releases don't report physical + * port info, so use default values + */ + props->phys_state = 5; + props->state = rblock->state; + props->active_width = IB_WIDTH_12X; + props->active_speed = 0x1; + } query_port1: ehca_free_fw_ctrlblock(rblock); diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h b/drivers/infiniband/hw/ehca/ehca_iverbs.h index dce503bb7d6b..5485799cdc8d 100644 --- a/drivers/infiniband/hw/ehca/ehca_iverbs.h +++ b/drivers/infiniband/hw/ehca/ehca_iverbs.h @@ -189,6 +189,9 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma); void ehca_poll_eqs(unsigned long data); +int ehca_calc_ipd(struct ehca_shca *shca, int port, + enum ib_rate path_rate, u32 *ipd); + #ifdef CONFIG_PPC_64K_PAGES void *ehca_alloc_fw_ctrlblock(gfp_t flags); void ehca_free_fw_ctrlblock(void *ptr); diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c index c6cd38c5321f..90d4334179bf 100644 --- a/drivers/infiniband/hw/ehca/ehca_main.c +++ b/drivers/infiniband/hw/ehca/ehca_main.c @@ -327,9 +327,6 @@ static int ehca_sense_attributes(struct ehca_shca *shca) shca->hw_level = ehca_hw_level; ehca_gen_dbg(" ... hardware level=%x", shca->hw_level); - shca->sport[0].rate = IB_RATE_30_GBPS; - shca->sport[1].rate = IB_RATE_30_GBPS; - shca->hca_cap = rblock->hca_cap_indicators; ehca_gen_dbg(" ... HCA capabilities:"); for (i = 0; i < ARRAY_SIZE(hca_cap_descr); i++) diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c index de182648b282..dd126681fed0 100644 --- a/drivers/infiniband/hw/ehca/ehca_qp.c +++ b/drivers/infiniband/hw/ehca/ehca_qp.c @@ -1196,10 +1196,6 @@ static int internal_modify_qp(struct ib_qp *ibqp, update_mask |= EHCA_BMASK_SET(MQPCB_MASK_QKEY, 1); } if (attr_mask & IB_QP_AV) { - int ah_mult = ib_rate_to_mult(attr->ah_attr.static_rate); - int ehca_mult = ib_rate_to_mult(shca->sport[my_qp-> - init_attr.port_num].rate); - mqpcb->dlid = attr->ah_attr.dlid; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DLID, 1); mqpcb->source_path_bits = attr->ah_attr.src_path_bits; @@ -1207,11 +1203,12 @@ static int internal_modify_qp(struct ib_qp *ibqp, mqpcb->service_level = attr->ah_attr.sl; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SERVICE_LEVEL, 1); - if (ah_mult < ehca_mult) - mqpcb->max_static_rate = (ah_mult > 0) ? - ((ehca_mult - 1) / ah_mult) : 0; - else - mqpcb->max_static_rate = 0; + if (ehca_calc_ipd(shca, mqpcb->prim_phys_port, + attr->ah_attr.static_rate, + &mqpcb->max_static_rate)) { + ret = -EINVAL; + goto modify_qp_exit2; + } update_mask |= EHCA_BMASK_SET(MQPCB_MASK_MAX_STATIC_RATE, 1); /* @@ -1280,10 +1277,6 @@ static int internal_modify_qp(struct ib_qp *ibqp, (MQPCB_MASK_RDMA_ATOMIC_OUTST_DEST_QP, 1); } if (attr_mask & IB_QP_ALT_PATH) { - int ah_mult = ib_rate_to_mult(attr->alt_ah_attr.static_rate); - int ehca_mult = ib_rate_to_mult( - shca->sport[my_qp->init_attr.port_num].rate); - if (attr->alt_port_num < 1 || attr->alt_port_num > shca->num_ports) { ret = -EINVAL; @@ -1309,10 +1302,12 @@ static int internal_modify_qp(struct ib_qp *ibqp, mqpcb->source_path_bits_al = attr->alt_ah_attr.src_path_bits; mqpcb->service_level_al = attr->alt_ah_attr.sl; - if (ah_mult > 0 && ah_mult < ehca_mult) - mqpcb->max_static_rate_al = (ehca_mult - 1) / ah_mult; - else - mqpcb->max_static_rate_al = 0; + if (ehca_calc_ipd(shca, mqpcb->alt_phys_port, + attr->alt_ah_attr.static_rate, + &mqpcb->max_static_rate_al)) { + ret = -EINVAL; + goto modify_qp_exit2; + } /* OpenIB doesn't support alternate retry counts - copy them */ mqpcb->retry_count_al = mqpcb->retry_count; diff --git a/drivers/infiniband/hw/ehca/hipz_hw.h b/drivers/infiniband/hw/ehca/hipz_hw.h index d9739e554515..485b8400359e 100644 --- a/drivers/infiniband/hw/ehca/hipz_hw.h +++ b/drivers/infiniband/hw/ehca/hipz_hw.h @@ -402,7 +402,11 @@ struct hipz_query_port { u64 max_msg_sz; u32 max_mtu; u32 vl_cap; - u8 reserved2[1900]; + u32 phys_pstate; + u32 phys_state; + u32 phys_speed; + u32 phys_width; + u8 reserved2[1884]; u64 guid_entries[255]; } __attribute__ ((packed)); diff --git a/drivers/infiniband/hw/ipath/ipath_cq.c b/drivers/infiniband/hw/ipath/ipath_cq.c index 645ed71fd797..d1380c7a1703 100644 --- a/drivers/infiniband/hw/ipath/ipath_cq.c +++ b/drivers/infiniband/hw/ipath/ipath_cq.c @@ -395,16 +395,13 @@ int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata) goto bail; } - /* - * Return the address of the WC as the offset to mmap. - * See ipath_mmap() for details. - */ + /* Check that we can write the offset to mmap. */ if (udata && udata->outlen >= sizeof(__u64)) { - __u64 offset = (__u64) wc; + __u64 offset = 0; ret = ib_copy_to_udata(udata, &offset, sizeof(offset)); if (ret) - goto bail; + goto bail_free; } spin_lock_irq(&cq->lock); @@ -424,10 +421,8 @@ int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata) else n = head - tail; if (unlikely((u32)cqe < n)) { - spin_unlock_irq(&cq->lock); - vfree(wc); ret = -EOVERFLOW; - goto bail; + goto bail_unlock; } for (n = 0; tail != head; n++) { if (cq->ip) @@ -452,6 +447,18 @@ int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata) struct ipath_mmap_info *ip = cq->ip; ipath_update_mmap_info(dev, ip, sz, wc); + + /* + * Return the offset to mmap. + * See ipath_mmap() for details. + */ + if (udata && udata->outlen >= sizeof(__u64)) { + ret = ib_copy_to_udata(udata, &ip->offset, + sizeof(ip->offset)); + if (ret) + goto bail; + } + spin_lock_irq(&dev->pending_lock); if (list_empty(&ip->pending_mmaps)) list_add(&ip->pending_mmaps, &dev->pending_mmaps); @@ -459,7 +466,12 @@ int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata) } ret = 0; + goto bail; +bail_unlock: + spin_unlock_irq(&cq->lock); +bail_free: + vfree(wc); bail: return ret; } diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c index 6a41fdbc8e57..b997ff88401b 100644 --- a/drivers/infiniband/hw/ipath/ipath_qp.c +++ b/drivers/infiniband/hw/ipath/ipath_qp.c @@ -835,7 +835,8 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd, init_attr->qp_type); if (err) { ret = ERR_PTR(err); - goto bail_rwq; + vfree(qp->r_rq.wq); + goto bail_qp; } qp->ip = NULL; ipath_reset_qp(qp); @@ -863,7 +864,7 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd, sizeof(offset)); if (err) { ret = ERR_PTR(err); - goto bail_rwq; + goto bail_ip; } } else { u32 s = sizeof(struct ipath_rwq) + @@ -875,7 +876,7 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd, qp->r_rq.wq); if (!qp->ip) { ret = ERR_PTR(-ENOMEM); - goto bail_rwq; + goto bail_ip; } err = ib_copy_to_udata(udata, &(qp->ip->offset), @@ -907,9 +908,11 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd, goto bail; bail_ip: - kfree(qp->ip); -bail_rwq: - vfree(qp->r_rq.wq); + if (qp->ip) + kref_put(&qp->ip->ref, ipath_release_mmap_info); + else + vfree(qp->r_rq.wq); + ipath_free_qp(&dev->qp_table, qp); bail_qp: kfree(qp); bail_swq: diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c index 5c29b2bfea17..120a61b03bc4 100644 --- a/drivers/infiniband/hw/ipath/ipath_rc.c +++ b/drivers/infiniband/hw/ipath/ipath_rc.c @@ -959,8 +959,9 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode, /* If this is a partial ACK, reset the retransmit timer. */ if (qp->s_last != qp->s_tail) { spin_lock(&dev->pending_lock); - list_add_tail(&qp->timerwait, - &dev->pending[dev->pending_index]); + if (list_empty(&qp->timerwait)) + list_add_tail(&qp->timerwait, + &dev->pending[dev->pending_index]); spin_unlock(&dev->pending_lock); /* * If we get a partial ACK for a resent operation, diff --git a/drivers/infiniband/hw/ipath/ipath_srq.c b/drivers/infiniband/hw/ipath/ipath_srq.c index 40c36ec19016..2fef36f4b675 100644 --- a/drivers/infiniband/hw/ipath/ipath_srq.c +++ b/drivers/infiniband/hw/ipath/ipath_srq.c @@ -59,7 +59,7 @@ int ipath_post_srq_receive(struct ib_srq *ibsrq, struct ib_recv_wr *wr, if ((unsigned) wr->num_sge > srq->rq.max_sge) { *bad_wr = wr; - ret = -ENOMEM; + ret = -EINVAL; goto bail; } @@ -211,11 +211,11 @@ int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, struct ib_udata *udata) { struct ipath_srq *srq = to_isrq(ibsrq); + struct ipath_rwq *wq; int ret = 0; if (attr_mask & IB_SRQ_MAX_WR) { struct ipath_rwq *owq; - struct ipath_rwq *wq; struct ipath_rwqe *p; u32 sz, size, n, head, tail; @@ -236,27 +236,20 @@ int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, goto bail; } - /* - * Return the address of the RWQ as the offset to mmap. - * See ipath_mmap() for details. - */ + /* Check that we can write the offset to mmap. */ if (udata && udata->inlen >= sizeof(__u64)) { __u64 offset_addr; - __u64 offset = (__u64) wq; + __u64 offset = 0; ret = ib_copy_from_udata(&offset_addr, udata, sizeof(offset_addr)); - if (ret) { - vfree(wq); - goto bail; - } + if (ret) + goto bail_free; udata->outbuf = (void __user *) offset_addr; ret = ib_copy_to_udata(udata, &offset, sizeof(offset)); - if (ret) { - vfree(wq); - goto bail; - } + if (ret) + goto bail_free; } spin_lock_irq(&srq->rq.lock); @@ -277,10 +270,8 @@ int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, else n -= tail; if (size <= n) { - spin_unlock_irq(&srq->rq.lock); - vfree(wq); ret = -EINVAL; - goto bail; + goto bail_unlock; } n = 0; p = wq->wq; @@ -314,6 +305,18 @@ int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, u32 s = sizeof(struct ipath_rwq) + size * sz; ipath_update_mmap_info(dev, ip, s, wq); + + /* + * Return the offset to mmap. + * See ipath_mmap() for details. + */ + if (udata && udata->inlen >= sizeof(__u64)) { + ret = ib_copy_to_udata(udata, &ip->offset, + sizeof(ip->offset)); + if (ret) + goto bail; + } + spin_lock_irq(&dev->pending_lock); if (list_empty(&ip->pending_mmaps)) list_add(&ip->pending_mmaps, @@ -328,7 +331,12 @@ int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, srq->limit = attr->srq_limit; spin_unlock_irq(&srq->rq.lock); } + goto bail; +bail_unlock: + spin_unlock_irq(&srq->rq.lock); +bail_free: + vfree(wq); bail: return ret; } diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c index 74f77e7c2c1b..c4c998446c7b 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.c +++ b/drivers/infiniband/hw/ipath/ipath_verbs.c @@ -302,8 +302,10 @@ static int ipath_post_one_send(struct ipath_qp *qp, struct ib_send_wr *wr) next = qp->s_head + 1; if (next >= qp->s_size) next = 0; - if (next == qp->s_last) - goto bail_inval; + if (next == qp->s_last) { + ret = -ENOMEM; + goto bail; + } wqe = get_swqe_ptr(qp, qp->s_head); wqe->wr = *wr; @@ -404,7 +406,7 @@ static int ipath_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, if ((unsigned) wr->num_sge > qp->r_rq.max_sge) { *bad_wr = wr; - ret = -ENOMEM; + ret = -EINVAL; goto bail; } diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index a03a65ebcf0c..c9f6077b615e 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -460,6 +460,9 @@ static struct ipoib_path *path_rec_create(struct net_device *dev, void *gid) struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_path *path; + if (!priv->broadcast) + return NULL; + path = kzalloc(sizeof *path, GFP_ATOMIC); if (!path) return NULL; diff --git a/drivers/infiniband/ulp/iser/iser_memory.c b/drivers/infiniband/ulp/iser/iser_memory.c index d68798061795..4a17743a639f 100644 --- a/drivers/infiniband/ulp/iser/iser_memory.c +++ b/drivers/infiniband/ulp/iser/iser_memory.c @@ -310,13 +310,15 @@ static unsigned int iser_data_buf_aligned_len(struct iser_data_buf *data, if (i + 1 < data->dma_nents) { next_addr = ib_sg_dma_address(ibdev, sg_next(sg)); /* are i, i+1 fragments of the same page? */ - if (end_addr == next_addr) + if (end_addr == next_addr) { + cnt++; continue; - else if (!IS_4K_ALIGNED(end_addr)) { + } else if (!IS_4K_ALIGNED(end_addr)) { ret_len = cnt + 1; break; } } + cnt++; } if (i == data->dma_nents) ret_len = cnt; /* loop ended */ diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 2316a018fae6..dfa6592c10f6 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -286,7 +286,7 @@ config KEYBOARD_MAPLE config KEYBOARD_BFIN tristate "Blackfin BF54x keypad support" - depends on BF54x + depends on (BF54x && !BF544) help Say Y here if you want to use the BF54x keypad. diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 3eddf52a0bba..6a9ca4bdcb74 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -75,16 +75,32 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) for (i = 0; i < pdata->nbuttons; i++) { struct gpio_keys_button *button = &pdata->buttons[i]; - int irq = gpio_to_irq(button->gpio); + int irq; unsigned int type = button->type ?: EV_KEY; + error = gpio_request(button->gpio, button->desc ?: "gpio_keys"); + if (error < 0) { + pr_err("gpio-keys: failed to request GPIO %d," + " error %d\n", button->gpio, error); + goto fail; + } + + error = gpio_direction_input(button->gpio); + if (error < 0) { + pr_err("gpio-keys: failed to configure input" + " direction for GPIO %d, error %d\n", + button->gpio, error); + gpio_free(button->gpio); + goto fail; + } + + irq = gpio_to_irq(button->gpio); if (irq < 0) { error = irq; - printk(KERN_ERR - "gpio-keys: " - "Unable to get irq number for GPIO %d," - "error %d\n", + pr_err("gpio-keys: Unable to get irq number" + " for GPIO %d, error %d\n", button->gpio, error); + gpio_free(button->gpio); goto fail; } @@ -94,9 +110,9 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) button->desc ? button->desc : "gpio_keys", pdev); if (error) { - printk(KERN_ERR - "gpio-keys: Unable to claim irq %d; error %d\n", + pr_err("gpio-keys: Unable to claim irq %d; error %d\n", irq, error); + gpio_free(button->gpio); goto fail; } @@ -108,8 +124,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) error = input_register_device(input); if (error) { - printk(KERN_ERR - "gpio-keys: Unable to register input device, " + pr_err("gpio-keys: Unable to register input device, " "error: %d\n", error); goto fail; } @@ -119,8 +134,10 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) return 0; fail: - while (--i >= 0) + while (--i >= 0) { free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev); + gpio_free(pdata->buttons[i].gpio); + } platform_set_drvdata(pdev, NULL); input_free_device(input); @@ -139,6 +156,7 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) for (i = 0; i < pdata->nbuttons; i++) { int irq = gpio_to_irq(pdata->buttons[i].gpio); free_irq(irq, pdev); + gpio_free(pdata->buttons[i].gpio); } input_unregister_device(input); diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index 5ce632ca6815..b88569e21d60 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig @@ -21,7 +21,7 @@ if SERIO config SERIO_I8042 tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86 default y - depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && !M68K && !BFIN + depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && !M68K && !BLACKFIN ---help--- i8042 is the chip over which the standard AT keyboard and PS/2 mouse are connected to the computer. If you use these devices, diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index f8fe42148093..c5e68dcd88ac 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -110,6 +110,14 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { DMI_MATCH(DMI_PRODUCT_VERSION, "5a"), }, }, + { + .ident = "Microsoft Virtual Machine", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"), + DMI_MATCH(DMI_PRODUCT_VERSION, "VS2005R2"), + }, + }, { } }; diff --git a/drivers/isdn/hisax/hfcscard.c b/drivers/isdn/hisax/hfcscard.c index 57670dc5034d..909d6709ec16 100644 --- a/drivers/isdn/hisax/hfcscard.c +++ b/drivers/isdn/hisax/hfcscard.c @@ -118,8 +118,7 @@ hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); case CARD_INIT: delay = (75*HZ)/100 +1; - cs->hw.hfcD.timer.expires = jiffies + delay; - add_timer(&cs->hw.hfcD.timer); + mod_timer(&cs->hw.hfcD.timer, jiffies + delay); spin_lock_irqsave(&cs->lock, flags); reset_hfcs(cs); init2bds0(cs); diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index c6df2925ebd0..d6952959d72a 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -1515,6 +1515,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) if (copy_from_user(&iocts, argp, sizeof(isdn_ioctl_struct))) return -EFAULT; + iocts.drvid[sizeof(iocts.drvid)-1] = 0; if (strlen(iocts.drvid)) { if ((p = strchr(iocts.drvid, ','))) *p = 0; @@ -1599,6 +1600,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) if (copy_from_user(&iocts, argp, sizeof(isdn_ioctl_struct))) return -EFAULT; + iocts.drvid[sizeof(iocts.drvid)-1] = 0; if (strlen(iocts.drvid)) { drvidx = -1; for (i = 0; i < ISDN_MAX_DRIVERS; i++) @@ -1643,7 +1645,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) } else { p = (char __user *) iocts.arg; for (i = 0; i < 10; i++) { - sprintf(bname, "%s%s", + snprintf(bname, sizeof(bname), "%s%s", strlen(dev->drv[drvidx]->msn2eaz[i]) ? dev->drv[drvidx]->msn2eaz[i] : "_", (i < 9) ? "," : "\0"); @@ -1673,6 +1675,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) char *p; if (copy_from_user(&iocts, argp, sizeof(isdn_ioctl_struct))) return -EFAULT; + iocts.drvid[sizeof(iocts.drvid)-1] = 0; if (strlen(iocts.drvid)) { if ((p = strchr(iocts.drvid, ','))) *p = 0; diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c index b39d1f5b378e..ced83c202cac 100644 --- a/drivers/isdn/i4l/isdn_net.c +++ b/drivers/isdn/i4l/isdn_net.c @@ -2104,7 +2104,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) u_long flags; isdn_net_dev *p; isdn_net_phone *n; - char nr[32]; + char nr[ISDN_MSNLEN]; char *my_eaz; /* Search name in netdev-chain */ @@ -2113,7 +2113,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) nr[1] = '\0'; printk(KERN_INFO "isdn_net: Incoming call without OAD, assuming '0'\n"); } else - strcpy(nr, setup->phone); + strlcpy(nr, setup->phone, ISDN_MSNLEN); si1 = (int) setup->si1; si2 = (int) setup->si2; if (!setup->eazmsn[0]) { @@ -2789,7 +2789,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg) chidx = -1; } } - strcpy(lp->msn, cfg->eaz); + strlcpy(lp->msn, cfg->eaz, sizeof(lp->msn)); lp->pre_device = drvidx; lp->pre_channel = chidx; lp->onhtime = cfg->onhtime; @@ -2936,7 +2936,7 @@ isdn_net_addphone(isdn_net_ioctl_phone * phone) if (p) { if (!(n = kmalloc(sizeof(isdn_net_phone), GFP_KERNEL))) return -ENOMEM; - strcpy(n->num, phone->phone); + strlcpy(n->num, phone->phone, sizeof(n->num)); n->next = p->local->phone[phone->outgoing & 1]; p->local->phone[phone->outgoing & 1] = n; return 0; diff --git a/drivers/isdn/sc/card.h b/drivers/isdn/sc/card.h index 5992f63c383e..0120bcf88311 100644 --- a/drivers/isdn/sc/card.h +++ b/drivers/isdn/sc/card.h @@ -109,7 +109,7 @@ void memcpy_fromshmem(int card, void *dest, const void *src, size_t n); int get_card_from_id(int driver); int indicate_status(int card, int event, ulong Channel, char *Data); irqreturn_t interrupt_handler(int interrupt, void *cardptr); -int sndpkt(int devId, int channel, struct sk_buff *data); +int sndpkt(int devId, int channel, int ack, struct sk_buff *data); void rcvpkt(int card, RspMessage *rcvmsg); int command(isdn_ctrl *cmd); int reset(int card); diff --git a/drivers/isdn/sc/packet.c b/drivers/isdn/sc/packet.c index 92016a2608e9..5ff6ae868440 100644 --- a/drivers/isdn/sc/packet.c +++ b/drivers/isdn/sc/packet.c @@ -20,7 +20,7 @@ #include "message.h" #include "card.h" -int sndpkt(int devId, int channel, struct sk_buff *data) +int sndpkt(int devId, int channel, int ack, struct sk_buff *data) { LLData ReqLnkWrite; int status; diff --git a/drivers/isdn/sc/shmem.c b/drivers/isdn/sc/shmem.c index e0331e0094f1..712220cef139 100644 --- a/drivers/isdn/sc/shmem.c +++ b/drivers/isdn/sc/shmem.c @@ -50,7 +50,7 @@ void memcpy_toshmem(int card, void *dest, const void *src, size_t n) outb(((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80, sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]); - memcpy_toio(sc_adapter[card]->rambase + dest_rem, src, n); + memcpy_toio((void __iomem *)(sc_adapter[card]->rambase + dest_rem), src, n); spin_unlock_irqrestore(&sc_adapter[card]->lock, flags); pr_debug("%s: set page to %#x\n",sc_adapter[card]->devicename, ((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80); diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index 07ae280e8fe5..47c10b8f89b3 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c @@ -1188,8 +1188,7 @@ int emulate_invlpg(struct kvm_vcpu *vcpu, gva_t address) int emulate_clts(struct kvm_vcpu *vcpu) { - vcpu->cr0 &= ~X86_CR0_TS; - kvm_x86_ops->set_cr0(vcpu, vcpu->cr0); + kvm_x86_ops->set_cr0(vcpu, vcpu->cr0 & ~X86_CR0_TS); return X86EMUL_CONTINUE; } diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c index 729f1cd93606..4e04e49a2f1c 100644 --- a/drivers/kvm/svm.c +++ b/drivers/kvm/svm.c @@ -494,6 +494,7 @@ static void init_vmcb(struct vmcb *vmcb) */ /* (1ULL << INTERCEPT_SELECTIVE_CR0) | */ (1ULL << INTERCEPT_CPUID) | + (1ULL << INTERCEPT_INVD) | (1ULL << INTERCEPT_HLT) | (1ULL << INTERCEPT_INVLPGA) | (1ULL << INTERCEPT_IOIO_PROT) | @@ -507,6 +508,7 @@ static void init_vmcb(struct vmcb *vmcb) (1ULL << INTERCEPT_STGI) | (1ULL << INTERCEPT_CLGI) | (1ULL << INTERCEPT_SKINIT) | + (1ULL << INTERCEPT_WBINVD) | (1ULL << INTERCEPT_MONITOR) | (1ULL << INTERCEPT_MWAIT); @@ -561,6 +563,12 @@ static void svm_vcpu_reset(struct kvm_vcpu *vcpu) struct vcpu_svm *svm = to_svm(vcpu); init_vmcb(svm->vmcb); + + if (vcpu->vcpu_id != 0) { + svm->vmcb->save.rip = 0; + svm->vmcb->save.cs.base = svm->vcpu.sipi_vector << 12; + svm->vmcb->save.cs.selector = svm->vcpu.sipi_vector << 8; + } } static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id) @@ -655,6 +663,7 @@ static void svm_vcpu_put(struct kvm_vcpu *vcpu) wrmsrl(host_save_user_msrs[i], svm->host_user_msrs[i]); rdtscll(vcpu->host_tsc); + kvm_put_guest_fpu(vcpu); } static void svm_vcpu_decache(struct kvm_vcpu *vcpu) @@ -1241,6 +1250,7 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm, [SVM_EXIT_VINTR] = interrupt_window_interception, /* [SVM_EXIT_CR0_SEL_WRITE] = emulate_on_interception, */ [SVM_EXIT_CPUID] = cpuid_interception, + [SVM_EXIT_INVD] = emulate_on_interception, [SVM_EXIT_HLT] = halt_interception, [SVM_EXIT_INVLPG] = emulate_on_interception, [SVM_EXIT_INVLPGA] = invalid_op_interception, @@ -1255,6 +1265,7 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm, [SVM_EXIT_STGI] = invalid_op_interception, [SVM_EXIT_CLGI] = invalid_op_interception, [SVM_EXIT_SKINIT] = invalid_op_interception, + [SVM_EXIT_WBINVD] = emulate_on_interception, [SVM_EXIT_MONITOR] = invalid_op_interception, [SVM_EXIT_MWAIT] = invalid_op_interception, }; @@ -1579,10 +1590,6 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) #endif : "cc", "memory" ); - local_irq_disable(); - - stgi(); - if ((svm->vmcb->save.dr7 & 0xff)) load_db_regs(svm->host_db_regs); @@ -1599,6 +1606,10 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) reload_tss(vcpu); + local_irq_disable(); + + stgi(); + svm->next_rip = 0; } diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c index a6ace302e0cd..bd46de6bf891 100644 --- a/drivers/kvm/x86_emulate.c +++ b/drivers/kvm/x86_emulate.c @@ -167,7 +167,7 @@ static u8 opcode_table[256] = { static u16 twobyte_table[256] = { /* 0x00 - 0x0F */ 0, SrcMem | ModRM | DstReg, 0, 0, 0, 0, ImplicitOps, 0, - 0, ImplicitOps, 0, 0, 0, ImplicitOps | ModRM, 0, 0, + ImplicitOps, ImplicitOps, 0, 0, 0, ImplicitOps | ModRM, 0, 0, /* 0x10 - 0x1F */ 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x2F */ @@ -448,8 +448,7 @@ struct operand { #define JMP_REL(rel) \ do { \ - _eip += (int)(rel); \ - _eip = ((op_bytes == 2) ? (uint16_t)_eip : (uint32_t)_eip); \ + register_address_increment(_eip, rel); \ } while (0) /* @@ -980,17 +979,6 @@ done_prefixes: goto cannot_emulate; dst.val = (s32) src.val; break; - case 0x6a: /* push imm8 */ - src.val = 0L; - src.val = insn_fetch(s8, 1, _eip); -push: - dst.type = OP_MEM; - dst.bytes = op_bytes; - dst.val = src.val; - register_address_increment(_regs[VCPU_REGS_RSP], -op_bytes); - dst.ptr = (void *) register_address(ctxt->ss_base, - _regs[VCPU_REGS_RSP]); - break; case 0x80 ... 0x83: /* Grp1 */ switch (modrm_reg) { case 0: @@ -1158,7 +1146,7 @@ push: } register_address_increment(_regs[VCPU_REGS_RSP], -dst.bytes); - if ((rc = ops->write_std( + if ((rc = ops->write_emulated( register_address(ctxt->ss_base, _regs[VCPU_REGS_RSP]), &dst.val, dst.bytes, ctxt->vcpu)) != 0) @@ -1243,6 +1231,17 @@ special_insn: register_address_increment(_regs[VCPU_REGS_RSP], op_bytes); no_wb = 1; /* Disable writeback. */ break; + case 0x6a: /* push imm8 */ + src.val = 0L; + src.val = insn_fetch(s8, 1, _eip); + push: + dst.type = OP_MEM; + dst.bytes = op_bytes; + dst.val = src.val; + register_address_increment(_regs[VCPU_REGS_RSP], -op_bytes); + dst.ptr = (void *) register_address(ctxt->ss_base, + _regs[VCPU_REGS_RSP]); + break; case 0x6c: /* insb */ case 0x6d: /* insw/insd */ if (kvm_emulate_pio_string(ctxt->vcpu, NULL, @@ -1359,6 +1358,7 @@ special_insn: } src.val = (unsigned long) _eip; JMP_REL(rel); + op_bytes = ad_bytes; goto push; } case 0xe9: /* jmp rel */ @@ -1532,6 +1532,8 @@ twobyte_special_insn: case 0x06: emulate_clts(ctxt->vcpu); break; + case 0x08: /* invd */ + break; case 0x09: /* wbinvd */ break; case 0x0d: /* GrpP (prefetch) */ diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c index 8904f72f97c6..e2eec38c83c2 100644 --- a/drivers/lguest/lguest_device.c +++ b/drivers/lguest/lguest_device.c @@ -200,7 +200,8 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev, /* Figure out how many pages the ring will take, and map that memory */ lvq->pages = lguest_map((unsigned long)lvq->config.pfn << PAGE_SHIFT, - DIV_ROUND_UP(vring_size(lvq->config.num), + DIV_ROUND_UP(vring_size(lvq->config.num, + PAGE_SIZE), PAGE_SIZE)); if (!lvq->pages) { err = -ENOMEM; @@ -246,6 +247,8 @@ static void lg_del_vq(struct virtqueue *vq) { struct lguest_vq_info *lvq = vq->priv; + /* Release the interrupt */ + free_irq(lvq->config.irq, vq); /* Tell virtio_ring.c to free the virtqueue. */ vring_del_virtqueue(vq); /* Unmap the pages containing the ring. */ diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c index 9d716fa42cad..3b92a61ba8d2 100644 --- a/drivers/lguest/lguest_user.c +++ b/drivers/lguest/lguest_user.c @@ -184,7 +184,7 @@ static int initialize(struct file *file, const unsigned long __user *input) free_regs: free_page(lg->regs_page); release_guest: - memset(lg, 0, sizeof(*lg)); + kfree(lg); unlock: mutex_unlock(&lguest_lock); return err; diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c index 516d943227e2..075b4d99e354 100644 --- a/drivers/macintosh/windfarm_core.c +++ b/drivers/macintosh/windfarm_core.c @@ -94,7 +94,9 @@ static int wf_thread_func(void *data) DBG("wf: thread started\n"); set_freezable(); - while(!kthread_should_stop()) { + while (!kthread_should_stop()) { + try_to_freeze(); + if (time_after_eq(jiffies, next)) { wf_notify(WF_EVENT_TICK, NULL); if (wf_overtemp) { @@ -116,12 +118,6 @@ static int wf_thread_func(void *data) delay = next - jiffies; if (delay <= HZ) schedule_timeout_interruptible(delay); - - /* there should be no non-suspend signal, but oh well */ - if (signal_pending(current) && !try_to_freeze()) { - printk(KERN_WARNING "windfarm: thread got sigl !\n"); - break; - } } DBG("wf: thread stopped\n"); diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 7c426d07a555..1b1ef3130e6e 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -1207,8 +1207,7 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect prepare_to_wait(&bitmap->overflow_wait, &__wait, TASK_UNINTERRUPTIBLE); spin_unlock_irq(&bitmap->lock); - bitmap->mddev->queue - ->unplug_fn(bitmap->mddev->queue); + blk_unplug(bitmap->mddev->queue); schedule(); finish_wait(&bitmap->overflow_wait, &__wait); continue; diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 5a7eb650181e..e298d8d11f24 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -1000,8 +1000,7 @@ void dm_table_unplug_all(struct dm_table *t) struct dm_dev *dd = list_entry(d, struct dm_dev, list); struct request_queue *q = bdev_get_queue(dd->bdev); - if (q->unplug_fn) - q->unplug_fn(q); + blk_unplug(q); } } diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 56a11f6c127b..3dac1cfb8189 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -87,8 +87,7 @@ static void linear_unplug(struct request_queue *q) for (i=0; i < mddev->raid_disks; i++) { struct request_queue *r_queue = bdev_get_queue(conf->disks[i].rdev->bdev); - if (r_queue->unplug_fn) - r_queue->unplug_fn(r_queue); + blk_unplug(r_queue); } } diff --git a/drivers/md/md.c b/drivers/md/md.c index 808cd9549456..cef9ebd5a046 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5445,7 +5445,7 @@ void md_do_sync(mddev_t *mddev) * about not overloading the IO subsystem. (things like an * e2fsck being done on the RAID array should execute fast) */ - mddev->queue->unplug_fn(mddev->queue); + blk_unplug(mddev->queue); cond_resched(); currspeed = ((unsigned long)(io_sectors-mddev->resync_mark_cnt))/2 @@ -5464,7 +5464,7 @@ void md_do_sync(mddev_t *mddev) * this also signals 'finished resyncing' to md_stop */ out: - mddev->queue->unplug_fn(mddev->queue); + blk_unplug(mddev->queue); wait_event(mddev->recovery_wait, !atomic_read(&mddev->recovery_active)); diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index b35731cceac6..eb631ebed686 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -125,8 +125,7 @@ static void unplug_slaves(mddev_t *mddev) atomic_inc(&rdev->nr_pending); rcu_read_unlock(); - if (r_queue->unplug_fn) - r_queue->unplug_fn(r_queue); + blk_unplug(r_queue); rdev_dec_pending(rdev, mddev); rcu_read_lock(); diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index c111105fc2dc..f8e591708d1f 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -35,8 +35,7 @@ static void raid0_unplug(struct request_queue *q) for (i=0; i<mddev->raid_disks; i++) { struct request_queue *r_queue = bdev_get_queue(devlist[i]->bdev); - if (r_queue->unplug_fn) - r_queue->unplug_fn(r_queue); + blk_unplug(r_queue); } } diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 85478d6a9c1a..4a69c416e045 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -549,8 +549,7 @@ static void unplug_slaves(mddev_t *mddev) atomic_inc(&rdev->nr_pending); rcu_read_unlock(); - if (r_queue->unplug_fn) - r_queue->unplug_fn(r_queue); + blk_unplug(r_queue); rdev_dec_pending(rdev, mddev); rcu_read_lock(); diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index fc6607acb6e4..5cdcc9386200 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -593,8 +593,7 @@ static void unplug_slaves(mddev_t *mddev) atomic_inc(&rdev->nr_pending); rcu_read_unlock(); - if (r_queue->unplug_fn) - r_queue->unplug_fn(r_queue); + blk_unplug(r_queue); rdev_dec_pending(rdev, mddev); rcu_read_lock(); diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 82af3465a900..a5aad8cad843 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -688,7 +688,8 @@ ops_run_prexor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx) } static struct dma_async_tx_descriptor * -ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx) +ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx, + unsigned long pending) { int disks = sh->disks; int pd_idx = sh->pd_idx, i; @@ -696,7 +697,7 @@ ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx) /* check if prexor is active which means only process blocks * that are part of a read-modify-write (Wantprexor) */ - int prexor = test_bit(STRIPE_OP_PREXOR, &sh->ops.pending); + int prexor = test_bit(STRIPE_OP_PREXOR, &pending); pr_debug("%s: stripe %llu\n", __FUNCTION__, (unsigned long long)sh->sector); @@ -773,7 +774,8 @@ static void ops_complete_write(void *stripe_head_ref) } static void -ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx) +ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx, + unsigned long pending) { /* kernel stack size limits the total number of disks */ int disks = sh->disks; @@ -781,7 +783,7 @@ ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx) int count = 0, pd_idx = sh->pd_idx, i; struct page *xor_dest; - int prexor = test_bit(STRIPE_OP_PREXOR, &sh->ops.pending); + int prexor = test_bit(STRIPE_OP_PREXOR, &pending); unsigned long flags; dma_async_tx_callback callback; @@ -808,7 +810,7 @@ ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx) } /* check whether this postxor is part of a write */ - callback = test_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending) ? + callback = test_bit(STRIPE_OP_BIODRAIN, &pending) ? ops_complete_write : ops_complete_postxor; /* 1/ if we prexor'd then the dest is reused as a source @@ -896,12 +898,12 @@ static void raid5_run_ops(struct stripe_head *sh, unsigned long pending) tx = ops_run_prexor(sh, tx); if (test_bit(STRIPE_OP_BIODRAIN, &pending)) { - tx = ops_run_biodrain(sh, tx); + tx = ops_run_biodrain(sh, tx, pending); overlap_clear++; } if (test_bit(STRIPE_OP_POSTXOR, &pending)) - ops_run_postxor(sh, tx); + ops_run_postxor(sh, tx, pending); if (test_bit(STRIPE_OP_CHECK, &pending)) ops_run_check(sh); @@ -3186,8 +3188,7 @@ static void unplug_slaves(mddev_t *mddev) atomic_inc(&rdev->nr_pending); rcu_read_unlock(); - if (r_queue->unplug_fn) - r_queue->unplug_fn(r_queue); + blk_unplug(r_queue); rdev_dec_pending(rdev, mddev); rcu_read_lock(); diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index 8135e4c3bf47..afd82966f9a0 100644 --- a/drivers/mfd/sm501.c +++ b/drivers/mfd/sm501.c @@ -156,7 +156,7 @@ static void sm501_dump_clk(struct sm501_devdata *sm) dev_dbg(sm->dev, "PM0[%c]: " "P2 %ld.%ld MHz (%ld), V2 %ld.%ld (%ld), " -x "M %ld.%ld (%ld), MX1 %ld.%ld (%ld)\n", + "M %ld.%ld (%ld), MX1 %ld.%ld (%ld)\n", (pmc & 3 ) == 0 ? '*' : '-', fmt_freq(decode_div(pll2, pm0, 24, 1<<29, 31, px_div)), fmt_freq(decode_div(pll2, pm0, 16, 1<<20, 15, misc_div)), diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c index 6a5a05d1f392..05172d2613d6 100644 --- a/drivers/misc/ioc4.c +++ b/drivers/misc/ioc4.c @@ -244,10 +244,11 @@ ioc4_variant(struct ioc4_driver_data *idd) idd->idd_pdev->bus->number == pdev->bus->number && 3 == PCI_SLOT(pdev->devfn)) found = 1; - pci_dev_put(pdev); } while (pdev && !found); - if (NULL != pdev) + if (NULL != pdev) { + pci_dev_put(pdev); return IOC4_VARIANT_IO9; + } /* IO10: Look for a Vitesse VSC 7174 at the same bus and slot 3. */ pdev = NULL; @@ -258,10 +259,11 @@ ioc4_variant(struct ioc4_driver_data *idd) idd->idd_pdev->bus->number == pdev->bus->number && 3 == PCI_SLOT(pdev->devfn)) found = 1; - pci_dev_put(pdev); } while (pdev && !found); - if (NULL != pdev) + if (NULL != pdev) { + pci_dev_put(pdev); return IOC4_VARIANT_IO10; + } /* PCI-RT: No SCSI/SATA controller will be present */ return IOC4_VARIANT_PCI_RT; diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c index bb13858f60a1..b0f68031b49d 100644 --- a/drivers/misc/sony-laptop.c +++ b/drivers/misc/sony-laptop.c @@ -338,7 +338,7 @@ static void sony_laptop_report_input_event(u8 event) dprintk("unknown input event %.2x\n", event); } -static int sony_laptop_setup_input(void) +static int sony_laptop_setup_input(struct acpi_device *acpi_device) { struct input_dev *jog_dev; struct input_dev *key_dev; @@ -379,6 +379,7 @@ static int sony_laptop_setup_input(void) key_dev->name = "Sony Vaio Keys"; key_dev->id.bustype = BUS_ISA; key_dev->id.vendor = PCI_VENDOR_ID_SONY; + key_dev->dev.parent = &acpi_device->dev; /* Initialize the Input Drivers: special keys */ set_bit(EV_KEY, key_dev->evbit); @@ -410,6 +411,7 @@ static int sony_laptop_setup_input(void) jog_dev->name = "Sony Vaio Jogdial"; jog_dev->id.bustype = BUS_ISA; jog_dev->id.vendor = PCI_VENDOR_ID_SONY; + key_dev->dev.parent = &acpi_device->dev; jog_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); jog_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_MIDDLE); @@ -1006,7 +1008,7 @@ static int sony_nc_add(struct acpi_device *device) } /* setup input devices and helper fifo */ - result = sony_laptop_setup_input(); + result = sony_laptop_setup_input(device); if (result) { printk(KERN_ERR DRV_PFX "Unabe to create input devices.\n"); @@ -1034,7 +1036,7 @@ static int sony_nc_add(struct acpi_device *device) sony_backlight_device->props.brightness = sony_backlight_get_brightness (sony_backlight_device); - sony_backlight_device->props.max_brightness = + sony_backlight_device->props.max_brightness = SONY_MAX_BRIGHTNESS - 1; } @@ -2453,7 +2455,7 @@ static int sony_pic_add(struct acpi_device *device) } /* setup input devices and helper fifo */ - result = sony_laptop_setup_input(); + result = sony_laptop_setup_input(device); if (result) { printk(KERN_ERR DRV_PFX "Unabe to create input devices.\n"); diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index e953276664a0..ab23a3221585 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -21,7 +21,7 @@ * 02110-1301, USA. */ -#define IBM_VERSION "0.16" +#define IBM_VERSION "0.17" #define TPACPI_SYSFS_VERSION 0x020000 /* @@ -964,15 +964,15 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) KEY_UNKNOWN, /* 0x0C: FN+BACKSPACE */ KEY_UNKNOWN, /* 0x0D: FN+INSERT */ KEY_UNKNOWN, /* 0x0E: FN+DELETE */ - KEY_BRIGHTNESSUP, /* 0x0F: FN+HOME (brightness up) */ + KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */ /* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */ - KEY_BRIGHTNESSDOWN, /* 0x10: FN+END (brightness down) */ + KEY_RESERVED, /* 0x10: FN+END (brightness down) */ KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */ KEY_UNKNOWN, /* 0x12: FN+PGDOWN */ KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */ - KEY_VOLUMEUP, /* 0x14: VOLUME UP */ - KEY_VOLUMEDOWN, /* 0x15: VOLUME DOWN */ - KEY_MUTE, /* 0x16: MUTE */ + KEY_RESERVED, /* 0x14: VOLUME UP */ + KEY_RESERVED, /* 0x15: VOLUME DOWN */ + KEY_RESERVED, /* 0x16: MUTE */ KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */ /* (assignments unknown, please report if found) */ KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, @@ -993,9 +993,9 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */ KEY_UNKNOWN, /* 0x12: FN+PGDOWN */ KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */ - KEY_VOLUMEUP, /* 0x14: VOLUME UP */ - KEY_VOLUMEDOWN, /* 0x15: VOLUME DOWN */ - KEY_MUTE, /* 0x16: MUTE */ + KEY_RESERVED, /* 0x14: VOLUME UP */ + KEY_RESERVED, /* 0x15: VOLUME DOWN */ + KEY_RESERVED, /* 0x16: MUTE */ KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */ /* (assignments unknown, please report if found) */ KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, @@ -1342,9 +1342,8 @@ static int hotkey_read(char *p) return len; } - res = mutex_lock_interruptible(&hotkey_mutex); - if (res < 0) - return res; + if (mutex_lock_interruptible(&hotkey_mutex)) + return -ERESTARTSYS; res = hotkey_get(&status, &mask); mutex_unlock(&hotkey_mutex); if (res) @@ -1373,9 +1372,8 @@ static int hotkey_write(char *buf) if (!tp_features.hotkey) return -ENODEV; - res = mutex_lock_interruptible(&hotkey_mutex); - if (res < 0) - return res; + if (mutex_lock_interruptible(&hotkey_mutex)) + return -ERESTARTSYS; res = hotkey_get(&status, &mask); if (res) @@ -3114,6 +3112,99 @@ static struct backlight_ops ibm_backlight_data = { static struct mutex brightness_mutex; +static int __init tpacpi_query_bcll_levels(acpi_handle handle) +{ + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *obj; + int rc; + + if (ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buffer))) { + obj = (union acpi_object *)buffer.pointer; + if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) { + printk(IBM_ERR "Unknown BCLL data, " + "please report this to %s\n", IBM_MAIL); + rc = 0; + } else { + rc = obj->package.count; + } + } else { + return 0; + } + + kfree(buffer.pointer); + return rc; +} + +static acpi_status __init brightness_find_bcll(acpi_handle handle, u32 lvl, + void *context, void **rv) +{ + char name[ACPI_PATH_SEGMENT_LENGTH]; + struct acpi_buffer buffer = { sizeof(name), &name }; + + if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) && + !strncmp("BCLL", name, sizeof(name) - 1)) { + if (tpacpi_query_bcll_levels(handle) == 16) { + *rv = handle; + return AE_CTRL_TERMINATE; + } else { + return AE_OK; + } + } else { + return AE_OK; + } +} + +static int __init brightness_check_levels(void) +{ + int status; + void *found_node = NULL; + + if (!vid_handle) { + IBM_ACPIHANDLE_INIT(vid); + } + if (!vid_handle) + return 0; + + /* Search for a BCLL package with 16 levels */ + status = acpi_walk_namespace(ACPI_TYPE_PACKAGE, vid_handle, 3, + brightness_find_bcll, NULL, &found_node); + + return (ACPI_SUCCESS(status) && found_node != NULL); +} + +static acpi_status __init brightness_find_bcl(acpi_handle handle, u32 lvl, + void *context, void **rv) +{ + char name[ACPI_PATH_SEGMENT_LENGTH]; + struct acpi_buffer buffer = { sizeof(name), &name }; + + if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) && + !strncmp("_BCL", name, sizeof(name) - 1)) { + *rv = handle; + return AE_CTRL_TERMINATE; + } else { + return AE_OK; + } +} + +static int __init brightness_check_std_acpi_support(void) +{ + int status; + void *found_node = NULL; + + if (!vid_handle) { + IBM_ACPIHANDLE_INIT(vid); + } + if (!vid_handle) + return 0; + + /* Search for a _BCL method, but don't execute it */ + status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3, + brightness_find_bcl, NULL, &found_node); + + return (ACPI_SUCCESS(status) && found_node != NULL); +} + static int __init brightness_init(struct ibm_init_struct *iibm) { int b; @@ -3122,6 +3213,18 @@ static int __init brightness_init(struct ibm_init_struct *iibm) mutex_init(&brightness_mutex); + if (!brightness_enable) { + dbg_printk(TPACPI_DBG_INIT, + "brightness support disabled by module parameter\n"); + return 1; + } else if (brightness_enable > 1) { + if (brightness_check_std_acpi_support()) { + printk(IBM_NOTICE + "standard ACPI backlight interface available, not loading native one...\n"); + return 1; + } + } + if (!brightness_mode) { if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) brightness_mode = 2; @@ -3135,10 +3238,17 @@ static int __init brightness_init(struct ibm_init_struct *iibm) if (brightness_mode > 3) return -EINVAL; + tp_features.bright_16levels = + thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO && + brightness_check_levels(); + b = brightness_get(NULL); if (b < 0) return 1; + if (tp_features.bright_16levels) + printk(IBM_INFO "detected a 16-level brightness capable ThinkPad\n"); + ibm_backlight_device = backlight_device_register( TPACPI_BACKLIGHT_DEV_NAME, NULL, NULL, &ibm_backlight_data); @@ -3148,7 +3258,8 @@ static int __init brightness_init(struct ibm_init_struct *iibm) } vdbg_printk(TPACPI_DBG_INIT, "brightness is supported\n"); - ibm_backlight_device->props.max_brightness = 7; + ibm_backlight_device->props.max_brightness = + (tp_features.bright_16levels)? 15 : 7; ibm_backlight_device->props.brightness = b; backlight_update_status(ibm_backlight_device); @@ -3167,6 +3278,8 @@ static void brightness_exit(void) static int brightness_update_status(struct backlight_device *bd) { + /* it is the backlight class's job (caller) to handle + * EINTR and other errors properly */ return brightness_set( (bd->props.fb_blank == FB_BLANK_UNBLANK && bd->props.power == FB_BLANK_UNBLANK) ? @@ -3184,13 +3297,14 @@ static int brightness_get(struct backlight_device *bd) if (brightness_mode & 1) { if (!acpi_ec_read(brightness_offset, &lec)) return -EIO; - lec &= 7; + lec &= (tp_features.bright_16levels)? 0x0f : 0x07; level = lec; }; if (brightness_mode & 2) { lcmos = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS) & TP_NVRAM_MASK_LEVEL_BRIGHTNESS) >> TP_NVRAM_POS_LEVEL_BRIGHTNESS; + lcmos &= (tp_features.bright_16levels)? 0x0f : 0x07; level = lcmos; } @@ -3206,12 +3320,13 @@ static int brightness_get(struct backlight_device *bd) return level; } +/* May return EINTR which can always be mapped to ERESTARTSYS */ static int brightness_set(int value) { int cmos_cmd, inc, i, res; int current_value; - if (value > 7) + if (value > ((tp_features.bright_16levels)? 15 : 7)) return -EINVAL; res = mutex_lock_interruptible(&brightness_mutex); @@ -3227,7 +3342,7 @@ static int brightness_set(int value) cmos_cmd = value > current_value ? TP_CMOS_BRIGHTNESS_UP : TP_CMOS_BRIGHTNESS_DOWN; - inc = value > current_value ? 1 : -1; + inc = (value > current_value)? 1 : -1; res = 0; for (i = current_value; i != value; i += inc) { @@ -3256,10 +3371,11 @@ static int brightness_read(char *p) if ((level = brightness_get(NULL)) < 0) { len += sprintf(p + len, "level:\t\tunreadable\n"); } else { - len += sprintf(p + len, "level:\t\t%d\n", level & 0x7); + len += sprintf(p + len, "level:\t\t%d\n", level); len += sprintf(p + len, "commands:\tup, down\n"); len += sprintf(p + len, "commands:\tlevel <level>" - " (<level> is 0-7)\n"); + " (<level> is 0-%d)\n", + (tp_features.bright_16levels) ? 15 : 7); } return len; @@ -3268,28 +3384,34 @@ static int brightness_read(char *p) static int brightness_write(char *buf) { int level; - int new_level; + int rc; char *cmd; + int max_level = (tp_features.bright_16levels) ? 15 : 7; - while ((cmd = next_cmd(&buf))) { - if ((level = brightness_get(NULL)) < 0) - return level; - level &= 7; + level = brightness_get(NULL); + if (level < 0) + return level; + while ((cmd = next_cmd(&buf))) { if (strlencmp(cmd, "up") == 0) { - new_level = level == 7 ? 7 : level + 1; + if (level < max_level) + level++; } else if (strlencmp(cmd, "down") == 0) { - new_level = level == 0 ? 0 : level - 1; - } else if (sscanf(cmd, "level %d", &new_level) == 1 && - new_level >= 0 && new_level <= 7) { - /* new_level set */ + if (level > 0) + level--; + } else if (sscanf(cmd, "level %d", &level) == 1 && + level >= 0 && level <= max_level) { + /* new level set */ } else return -EINVAL; - - brightness_set(new_level); } - return 0; + /* + * Now we know what the final level should be, so we try to set it. + * Doing it this way makes the syscall restartable in case of EINTR + */ + rc = brightness_set(level); + return (rc == -EINTR)? ERESTARTSYS : rc; } static struct ibm_struct brightness_driver_data = { @@ -3652,9 +3774,8 @@ static ssize_t fan_pwm1_store(struct device *dev, /* scale down from 0-255 to 0-7 */ newlevel = (s >> 5) & 0x07; - rc = mutex_lock_interruptible(&fan_mutex); - if (rc < 0) - return rc; + if (mutex_lock_interruptible(&fan_mutex)) + return -ERESTARTSYS; rc = fan_get_status(&status); if (!rc && (status & @@ -3904,9 +4025,8 @@ static int fan_get_status_safe(u8 *status) int rc; u8 s; - rc = mutex_lock_interruptible(&fan_mutex); - if (rc < 0) - return rc; + if (mutex_lock_interruptible(&fan_mutex)) + return -ERESTARTSYS; rc = fan_get_status(&s); if (!rc) fan_update_desired_level(s); @@ -4040,9 +4160,8 @@ static int fan_set_level_safe(int level) if (!fan_control_allowed) return -EPERM; - rc = mutex_lock_interruptible(&fan_mutex); - if (rc < 0) - return rc; + if (mutex_lock_interruptible(&fan_mutex)) + return -ERESTARTSYS; if (level == TPACPI_FAN_LAST_LEVEL) level = fan_control_desired_level; @@ -4063,9 +4182,8 @@ static int fan_set_enable(void) if (!fan_control_allowed) return -EPERM; - rc = mutex_lock_interruptible(&fan_mutex); - if (rc < 0) - return rc; + if (mutex_lock_interruptible(&fan_mutex)) + return -ERESTARTSYS; switch (fan_control_access_mode) { case TPACPI_FAN_WR_ACPI_FANS: @@ -4119,9 +4237,8 @@ static int fan_set_disable(void) if (!fan_control_allowed) return -EPERM; - rc = mutex_lock_interruptible(&fan_mutex); - if (rc < 0) - return rc; + if (mutex_lock_interruptible(&fan_mutex)) + return -ERESTARTSYS; rc = 0; switch (fan_control_access_mode) { @@ -4158,9 +4275,8 @@ static int fan_set_speed(int speed) if (!fan_control_allowed) return -EPERM; - rc = mutex_lock_interruptible(&fan_mutex); - if (rc < 0) - return rc; + if (mutex_lock_interruptible(&fan_mutex)) + return -ERESTARTSYS; rc = 0; switch (fan_control_access_mode) { @@ -4701,9 +4817,15 @@ static int __init set_ibm_param(const char *val, struct kernel_param *kp) unsigned int i; struct ibm_struct *ibm; + if (!kp || !kp->name || !val) + return -EINVAL; + for (i = 0; i < ARRAY_SIZE(ibms_init); i++) { ibm = ibms_init[i].data; - BUG_ON(ibm == NULL); + WARN_ON(ibm == NULL); + + if (!ibm || !ibm->name) + continue; if (strcmp(ibm->name, kp->name) == 0 && ibm->write) { if (strlen(val) > sizeof(ibms_init[i].param) - 2) @@ -4732,6 +4854,9 @@ module_param_named(fan_control, fan_control_allowed, bool, 0); static int brightness_mode; module_param_named(brightness_mode, brightness_mode, int, 0); +static unsigned int brightness_enable = 2; /* 2 = auto, 0 = no, 1 = yes */ +module_param(brightness_enable, uint, 0); + static unsigned int hotkey_report_mode; module_param(hotkey_report_mode, uint, 0); diff --git a/drivers/misc/thinkpad_acpi.h b/drivers/misc/thinkpad_acpi.h index 3abcc8120634..8fba2bbe345e 100644 --- a/drivers/misc/thinkpad_acpi.h +++ b/drivers/misc/thinkpad_acpi.h @@ -84,7 +84,7 @@ /* ThinkPad CMOS NVRAM constants */ #define TP_NVRAM_ADDR_BRIGHTNESS 0x5e -#define TP_NVRAM_MASK_LEVEL_BRIGHTNESS 0x07 +#define TP_NVRAM_MASK_LEVEL_BRIGHTNESS 0x0f #define TP_NVRAM_POS_LEVEL_BRIGHTNESS 0 #define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off") @@ -246,6 +246,7 @@ static struct { u32 hotkey_wlsw:1; u32 light:1; u32 light_status:1; + u32 bright_16levels:1; u32 wan:1; u32 fan_ctrl_status_undef:1; u32 input_device_registered:1; @@ -338,6 +339,7 @@ static int bluetooth_write(char *buf); static struct backlight_device *ibm_backlight_device; static int brightness_offset = 0x31; static int brightness_mode; +static unsigned int brightness_enable; /* 0 = no, 1 = yes, 2 = auto */ static int brightness_init(struct ibm_init_struct *iibm); static void brightness_exit(void); diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index e38d5a3b2a89..aeb32a93f6a0 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -44,6 +44,9 @@ * max 8 partitions per card */ #define MMC_SHIFT 3 +#define MMC_NUM_MINORS (256 >> MMC_SHIFT) + +static unsigned long dev_use[MMC_NUM_MINORS/(8*sizeof(unsigned long))]; /* * There is one mmc_blk_data per slot. @@ -80,6 +83,9 @@ static void mmc_blk_put(struct mmc_blk_data *md) mutex_lock(&open_lock); md->usage--; if (md->usage == 0) { + int devidx = md->disk->first_minor >> MMC_SHIFT; + __clear_bit(devidx, dev_use); + put_disk(md->disk); kfree(md); } @@ -321,7 +327,13 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) req->rq_disk->disk_name, err); goto cmd_err; } - } while (!(cmd.resp[0] & R1_READY_FOR_DATA)); + /* + * Some cards mishandle the status bits, + * so make sure to check both the busy + * indication and the card state. + */ + } while (!(cmd.resp[0] & R1_READY_FOR_DATA) || + (R1_CURRENT_STATE(cmd.resp[0]) == 7)); #if 0 if (cmd.resp[0] & ~0x00000900) @@ -400,9 +412,6 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) return 0; } -#define MMC_NUM_MINORS (256 >> MMC_SHIFT) - -static unsigned long dev_use[MMC_NUM_MINORS/(8*sizeof(unsigned long))]; static inline int mmc_blk_readonly(struct mmc_card *card) { @@ -568,17 +577,12 @@ static void mmc_blk_remove(struct mmc_card *card) struct mmc_blk_data *md = mmc_get_drvdata(card); if (md) { - int devidx; - /* Stop new requests from getting into the queue */ del_gendisk(md->disk); /* Then flush out any already in there */ mmc_cleanup_queue(&md->queue); - devidx = md->disk->first_minor >> MMC_SHIFT; - __clear_bit(devidx, dev_use); - mmc_blk_put(md); } mmc_set_drvdata(card, NULL); diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 9203a0b221b3..30cd13b13ac3 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -180,12 +180,13 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock blk_queue_max_hw_segments(mq->queue, host->max_hw_segs); blk_queue_max_segment_size(mq->queue, host->max_seg_size); - mq->sg = kzalloc(sizeof(struct scatterlist) * + mq->sg = kmalloc(sizeof(struct scatterlist) * host->max_phys_segs, GFP_KERNEL); if (!mq->sg) { ret = -ENOMEM; goto cleanup_queue; } + sg_init_table(mq->sg, host->max_phys_segs); } init_MUTEX(&mq->thread_sem); @@ -310,7 +311,7 @@ static void copy_sg(struct scatterlist *dst, unsigned int dst_len, } if (src_size == 0) { - src_buf = sg_virt(dst); + src_buf = sg_virt(src); src_size = src->length; } diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c index d552de683110..eeea84c309e6 100644 --- a/drivers/mmc/card/sdio_uart.c +++ b/drivers/mmc/card/sdio_uart.c @@ -386,7 +386,7 @@ static void sdio_uart_stop_rx(struct sdio_uart_port *port) sdio_out(port, UART_IER, port->ier); } -static void sdio_uart_receive_chars(struct sdio_uart_port *port, int *status) +static void sdio_uart_receive_chars(struct sdio_uart_port *port, unsigned int *status) { struct tty_struct *tty = port->tty; unsigned int ch, flag; diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 6b80bf77a4ef..ff59d2e0475b 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1301,7 +1301,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) if ((chip->quirks & SDHCI_QUIRK_BROKEN_DMA) && (host->flags & SDHCI_USE_DMA)) { - DBG("Disabling DMA as it is marked broken"); + DBG("Disabling DMA as it is marked broken\n"); host->flags &= ~SDHCI_USE_DMA; } diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c index c11a3d256051..20d5c7bd940a 100644 --- a/drivers/mmc/host/tifm_sd.c +++ b/drivers/mmc/host/tifm_sd.c @@ -16,7 +16,6 @@ #include <linux/mmc/host.h> #include <linux/highmem.h> #include <linux/scatterlist.h> -#include <linux/log2.h> #include <asm/io.h> #define DRIVER_NAME "tifm_sd" @@ -638,17 +637,15 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) goto err_out; } - if (mrq->data && !is_power_of_2(mrq->data->blksz)) { - printk(KERN_ERR "%s: Unsupported block size (%d bytes)\n", - sock->dev.bus_id, mrq->data->blksz); - mrq->cmd->error = -EINVAL; - goto err_out; - } - host->cmd_flags = 0; host->block_pos = 0; host->sg_pos = 0; + if (mrq->data && !is_power_of_2(mrq->data->blksz)) + host->no_dma = 1; + else + host->no_dma = no_dma ? 1 : 0; + if (r_data) { tifm_sd_set_data_timeout(host, r_data); @@ -676,7 +673,7 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) : PCI_DMA_FROMDEVICE)) { printk(KERN_ERR "%s : scatterlist map failed\n", sock->dev.bus_id); - spin_unlock_irqrestore(&sock->lock, flags); + mrq->cmd->error = -ENOMEM; goto err_out; } host->sg_len = tifm_map_sg(sock, r_data->sg, @@ -692,7 +689,7 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) r_data->flags & MMC_DATA_WRITE ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); - spin_unlock_irqrestore(&sock->lock, flags); + mrq->cmd->error = -ENOMEM; goto err_out; } @@ -966,7 +963,6 @@ static int tifm_sd_probe(struct tifm_dev *sock) return -ENOMEM; host = mmc_priv(mmc); - host->no_dma = no_dma; tifm_set_drvdata(sock, mmc); host->dev = sock; host->timeout_jiffies = msecs_to_jiffies(1000); diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 5f800a6dd978..d9107e542dfa 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -136,10 +136,11 @@ config TUN If you don't know what to use this for, you don't need it. config VETH - tristate "Virtual ethernet device" + tristate "Virtual ethernet pair device" ---help--- - The device is an ethernet tunnel. Devices are created in pairs. When - one end receives the packet it appears on its pair and vice versa. + This device is a local ethernet tunnel. Devices are created in pairs. + When one end receives the packet it appears on its pair and vice + versa. config NET_SB1000 tristate "General Instruments Surfboard 1000" @@ -234,7 +235,7 @@ source "drivers/net/arm/Kconfig" config AX88796 tristate "ASIX AX88796 NE2000 clone support" - depends on ARM || MIPS + depends on ARM || MIPS || SUPERH select CRC32 select MII help @@ -365,8 +366,7 @@ config MAC89x0 read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. This module will + To compile this driver as a module, choose M here. This module will be called mac89x0. config MACSONIC @@ -379,8 +379,7 @@ config MACSONIC one of these say Y and read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. This module will + To compile this driver as a module, choose M here. This module will be called macsonic. config MACMACE @@ -618,8 +617,7 @@ config EL1 have problems. Some people suggest to ping ("man ping") a nearby machine every minute ("man cron") when using this card. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called 3c501. config EL2 @@ -631,8 +629,7 @@ config EL2 the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called 3c503. config ELPLUS @@ -644,8 +641,7 @@ config ELPLUS this type, say Y and read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called 3c505. config EL16 @@ -656,8 +652,7 @@ config EL16 the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called 3c507. config EL3 @@ -672,8 +667,7 @@ config EL3 setup disk to disable Plug & Play mode, and to select the default media type. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called 3c509. config 3C515 @@ -684,8 +678,7 @@ config 3C515 network card, say Y and read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called 3c515. config ELMC @@ -696,8 +689,7 @@ config ELMC the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called 3c523. config ELMC_II @@ -708,8 +700,7 @@ config ELMC_II the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called 3c527. config VORTEX @@ -732,8 +723,7 @@ config VORTEX <file:Documentation/networking/vortex.txt> and in the comments at the beginning of <file:drivers/net/3c59x.c>. - To compile this support as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. + To compile this support as a module, choose M here. config TYPHOON tristate "3cr990 series \"Typhoon\" support" @@ -750,8 +740,7 @@ config TYPHOON the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called typhoon. config LANCE @@ -788,8 +777,7 @@ config WD80x3 the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called wd. config ULTRAMCA @@ -801,8 +789,7 @@ config ULTRAMCA an MCA based system (PS/2), say Y and read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called smc-mca. config ULTRA @@ -821,8 +808,7 @@ config ULTRA this but keep it in mind if you have such a SCSI card and have problems. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called smc-ultra. config ULTRA32 @@ -834,8 +820,7 @@ config ULTRA32 the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called smc-ultra32. config BFIN_MAC @@ -896,15 +881,14 @@ config SMC9194 <file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called smc9194. config SMC91X tristate "SMC 91C9x/91C1xxx support" select CRC32 select MII - depends on ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || SOC_AU1X00 || BFIN + depends on ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || SOC_AU1X00 || BLACKFIN help This is a driver for SMC's 91x series of Ethernet chipsets, including the SMC91C94 and the SMC91C111. Say Y if you want it @@ -915,8 +899,7 @@ config SMC91X This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). The module will be called smc91x. If you want to compile it as a - module, say M here and read <file:Documentation/kbuild/modules.txt> - as well as <file:Documentation/networking/net-modules.txt>. + module, say M here and read <file:Documentation/kbuild/modules.txt>. config NET_NETX tristate "NetX Ethernet support" @@ -925,8 +908,7 @@ config NET_NETX help This is support for the Hilscher netX builtin Ethernet ports - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called netx-eth. config DM9000 @@ -937,15 +919,14 @@ config DM9000 ---help--- Support for DM9000 chipset. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will be - called dm9000. + To compile this driver as a module, choose M here. The module + will be called dm9000. config SMC911X tristate "SMSC LAN911[5678] support" select CRC32 select MII - depends on ARCH_PXA || SUPERH + depends on ARCH_PXA || SH_MAGIC_PANEL_R2 help This is a driver for SMSC's LAN911x series of Ethernet chipsets including the new LAN9115, LAN9116, LAN9117, and LAN9118. @@ -979,8 +960,7 @@ config NI5010 <http://www.tldp.org/docs.html#howto>. Note that this is still experimental code. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called ni5010. config NI52 @@ -991,8 +971,7 @@ config NI52 the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called ni52. config NI65 @@ -1003,8 +982,7 @@ config NI65 the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called ni65. source "drivers/net/tulip/Kconfig" @@ -1018,8 +996,7 @@ config AT1700 the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called at1700. config DEPCA @@ -1032,8 +1009,7 @@ config DEPCA <http://www.tldp.org/docs.html#howto> as well as <file:drivers/net/depca.c>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called depca. config HP100 @@ -1044,8 +1020,7 @@ config HP100 the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called hp100. config NET_ISA @@ -1074,8 +1049,7 @@ config E2100 the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called e2100. config EWRK3 @@ -1089,8 +1063,7 @@ config EWRK3 well as the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called ewrk3. config EEXPRESS @@ -1104,8 +1077,7 @@ config EEXPRESS because the driver was very unreliable. We now have a new driver that should do better. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called eexpress. config EEXPRESS_PRO @@ -1118,8 +1090,7 @@ config EEXPRESS_PRO driver. Please read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called eepro. config HPLAN_PLUS @@ -1131,8 +1102,7 @@ config HPLAN_PLUS the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called hp-plus. config HPLAN @@ -1144,8 +1114,7 @@ config HPLAN the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called hp. config LP486E @@ -1164,8 +1133,7 @@ config ETH16I the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called eth16i. config NE2000 @@ -1185,8 +1153,7 @@ config NE2000 laptops), say N here and Y to "NE/2 (ne2000 MCA version) support", below. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called ne. config ZNET @@ -1207,8 +1174,7 @@ config SEEQ8005 is for you, read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called seeq8005. config NE2_MCA @@ -1220,8 +1186,7 @@ config NE2_MCA the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called ne2. config IBMLANA @@ -1232,8 +1197,7 @@ config IBMLANA CONFIG_MCA to use this driver. It is both available as an in-kernel driver and as a module. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The only + To compile this driver as a module, choose M here. The only currently supported card is the IBM LAN Adapter/A for Ethernet. It will both support 16K and 32K memory windows, however a 32K window gives a better security against packet losses. Usage of multiple @@ -1247,8 +1211,7 @@ config IBMVETH This driver supports virtual ethernet adapters on newer IBM iSeries and pSeries systems. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will + To compile this driver as a module, choose M here. The module will be called ibmveth. source "drivers/net/ibm_emac/Kconfig" @@ -1278,8 +1241,7 @@ config PCNET32 answer Y here and read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called pcnet32. config PCNET32_NAPI @@ -1306,8 +1268,7 @@ config AMD8111_ETH answer Y here and read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called amd8111e. config AMD8111E_NAPI @@ -1361,8 +1322,7 @@ config AC3200 the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called ac3200. config APRICOT @@ -1373,9 +1333,8 @@ config APRICOT read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will be - called apricot. + To compile this driver as a module, choose M here. The module + will be called apricot. config B44 tristate "Broadcom 440x/47xx ethernet support" @@ -1387,9 +1346,8 @@ config B44 or M and read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will be - called b44. + To compile this driver as a module, choose M here. The module + will be called b44. # Auto-select SSB PCI-HOST support, if possible config B44_PCI_AUTOSELECT @@ -1418,9 +1376,8 @@ config FORCEDETH read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will be - called forcedeth. + To compile this driver as a module, choose M here. The module + will be called forcedeth. config FORCEDETH_NAPI bool "Use Rx Polling (NAPI) (EXPERIMENTAL)" @@ -1446,9 +1403,8 @@ config CS89x0 <http://www.tldp.org/docs.html#howto> as well as <file:Documentation/networking/cs89x0.txt>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will be - called cs89x0. + To compile this driver as a module, choose M here. The module + will be called cs89x0. config TC35815 tristate "TOSHIBA TC35815 Ethernet support" @@ -1464,8 +1420,7 @@ config EEPRO100 card, say Y and read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called eepro100. @@ -1492,8 +1447,7 @@ config E100 More specific information on configuring the driver is in <file:Documentation/networking/e100.txt>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called e100. config LNE390 @@ -1505,8 +1459,7 @@ config LNE390 the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called lne390. config FEALNX @@ -1546,8 +1499,7 @@ config NE2K_PCI NetVin NV5000SC Via 86C926 SureCom NE34 Winbond Holtek HT80232 Holtek HT80229 - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called ne2k-pci. config NE3210 @@ -1560,8 +1512,7 @@ config NE3210 <http://www.tldp.org/docs.html#howto>. Note that this driver will NOT WORK for NE3200 cards as they are completely different. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called ne3210. config ES3210 @@ -1573,8 +1524,7 @@ config ES3210 the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called es3210. config 8139CP @@ -1704,8 +1654,7 @@ config TLAN Compaq NetFlex and Olicom cards. Please read the file <file:Documentation/networking/tlan.txt> for more details. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called tlan. Please email feedback to <torben.mathiasen@compaq.com>. @@ -1995,8 +1944,7 @@ config E1000 More specific information on configuring the driver is in <file:Documentation/networking/e1000.txt>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called e1000. config E1000_NAPI @@ -2041,8 +1989,7 @@ config E1000E More specific information on configuring the driver is in <file:Documentation/networking/e1000e.txt>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called e1000e. source "drivers/net/ixp2000/Kconfig" @@ -2075,8 +2022,7 @@ config HAMACHI the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will be + To compile this driver as a module, choose M here. The module will be called hamachi. config YELLOWFIN @@ -2525,8 +2471,7 @@ config IXGBE More specific information on configuring the driver is in <file:Documentation/networking/ixgbe.txt>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called ixgbe. config IXGB @@ -2548,8 +2493,7 @@ config IXGB More specific information on configuring the driver is in <file:Documentation/networking/ixgb.txt>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called ixgb. config IXGB_NAPI @@ -2602,8 +2546,7 @@ config MYRI10GE <http://www.myri.com/scs/download-Myri10GE.html> - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called myri10ge. config NETXEN_NIC @@ -2827,10 +2770,9 @@ config PLIP with the PLIP support in Linux versions 1.0.x. This option enlarges your kernel by about 8 KB. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will be - called plip. If unsure, say Y or M, in case you buy a laptop - later. + To compile this driver as a module, choose M here. The module + will be called plip. If unsure, say Y or M, in case you buy + a laptop later. config PPP tristate "PPP (point-to-point protocol) support" @@ -2860,8 +2802,7 @@ config PPP If you said Y to "Version information on all symbols" above, then you cannot compile the PPP driver into the kernel; you can then only compile it as a module. To compile this driver as a module, choose M - here and read <file:Documentation/networking/net-modules.txt>. - The module will be called ppp_generic. + here. The module will be called ppp_generic. config PPP_MULTILINK bool "PPP multilink support (EXPERIMENTAL)" @@ -3022,9 +2963,8 @@ config SLIP <http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html>). SLIP support will enlarge your kernel by about 4 KB. If unsure, say N. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will be - called slip. + To compile this driver as a module, choose M here. The module + will be called slip. config SLIP_COMPRESSED bool "CSLIP compressed headers" diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index eebf5bb2b03a..e7fdd81919bd 100644 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -1340,7 +1340,9 @@ static int amd8111e_close(struct net_device * dev) struct amd8111e_priv *lp = netdev_priv(dev); netif_stop_queue(dev); +#ifdef CONFIG_AMD8111E_NAPI napi_disable(&lp->napi); +#endif spin_lock_irq(&lp->lock); @@ -1372,7 +1374,9 @@ static int amd8111e_open(struct net_device * dev ) dev->name, dev)) return -EAGAIN; +#ifdef CONFIG_AMD8111E_NAPI napi_enable(&lp->napi); +#endif spin_lock_irq(&lp->lock); @@ -1380,7 +1384,9 @@ static int amd8111e_open(struct net_device * dev ) if(amd8111e_restart(dev)){ spin_unlock_irq(&lp->lock); +#ifdef CONFIG_AMD8111E_NAPI napi_disable(&lp->napi); +#endif if (dev->irq) free_irq(dev->irq, dev); return -ENOMEM; diff --git a/drivers/net/arcnet/Kconfig b/drivers/net/arcnet/Kconfig index 4030274fe788..3b2f7f115464 100644 --- a/drivers/net/arcnet/Kconfig +++ b/drivers/net/arcnet/Kconfig @@ -19,8 +19,7 @@ menuconfig ARCNET from <http://www.tldp.org/docs.html#howto>(even though ARCnet is not really Ethernet). - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will + To compile this driver as a module, choose M here. The module will be called arcnet. if ARCNET @@ -81,8 +80,7 @@ config ARCNET_COM90xx have always used the old ARCnet driver without knowing what type of card you had, this is probably the one for you. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will + To compile this driver as a module, choose M here. The module will be called com90xx. config ARCNET_COM90xxIO @@ -93,8 +91,7 @@ config ARCNET_COM90xxIO the normal driver. Only use it if your card doesn't support shared memory. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will + To compile this driver as a module, choose M here. The module will be called com90io. config ARCNET_RIM_I @@ -105,8 +102,7 @@ config ARCNET_RIM_I driver is completely untested, so if you have one of these cards, please mail <dwmw2@infradead.org>, especially if it works! - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will + To compile this driver as a module, choose M here. The module will be called arc-rimi. config ARCNET_COM20020 @@ -116,8 +112,7 @@ config ARCNET_COM20020 things as promiscuous mode, so packet sniffing is possible, and extra diagnostic information. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will + To compile this driver as a module, choose M here. The module will be called com20020. config ARCNET_COM20020_ISA diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index 7f016f3d5bf0..91a6590d107b 100644 --- a/drivers/net/arm/ep93xx_eth.c +++ b/drivers/net/arm/ep93xx_eth.c @@ -417,7 +417,7 @@ static irqreturn_t ep93xx_irq(int irq, void *dev_id) if (status & REG_INTSTS_RX) { spin_lock(&ep->rx_lock); - if (likely(__netif_rx_schedule_prep(dev, &ep->napi))) { + if (likely(netif_rx_schedule_prep(dev, &ep->napi))) { wrl(ep, REG_INTEN, REG_INTEN_TX); __netif_rx_schedule(dev, &ep->napi); } diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 084acfd6fc5f..eb971755a3ff 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -676,7 +676,7 @@ static void bf537mac_rx(struct net_device *dev) skb->protocol = eth_type_trans(skb, dev); #if defined(BFIN_MAC_CSUM_OFFLOAD) skb->csum = current_rx_ptr->status.ip_payload_csum; - skb->ip_summed = CHECKSUM_PARTIAL; + skb->ip_summed = CHECKSUM_COMPLETE; #endif netif_rx(skb); @@ -924,7 +924,7 @@ static int __init bf537mac_probe(struct net_device *dev) if (!is_valid_ether_addr(dev->dev_addr)) { /* Grab the MAC from the board somehow - this is done in the arch/blackfin/mach-bf537/boards/eth_mac.c */ - get_bf537_ether_addr(dev->dev_addr); + bfin_get_ether_addr(dev->dev_addr); } /* If still not valid, get a random one */ diff --git a/drivers/net/bfin_mac.h b/drivers/net/bfin_mac.h index 3a107ad75381..5970ea7142cd 100644 --- a/drivers/net/bfin_mac.h +++ b/drivers/net/bfin_mac.h @@ -92,4 +92,4 @@ struct bf537mac_local { struct mii_bus mii_bus; }; -extern void get_bf537_ether_addr(char *addr); +extern void bfin_get_ether_addr(char *addr); diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 6937ef0e7275..423298c84a1d 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1847,9 +1847,9 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) */ void bond_destroy(struct bonding *bond) { - unregister_netdevice(bond->dev); bond_deinit(bond->dev); bond_destroy_sysfs_entry(bond); + unregister_netdevice(bond->dev); } /* @@ -4405,6 +4405,7 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params) bond_dev->set_multicast_list = bond_set_multicast_list; bond_dev->change_mtu = bond_change_mtu; bond_dev->set_mac_address = bond_set_mac_address; + bond_dev->validate_addr = NULL; bond_set_mode_ops(bond, bond->params.mode); @@ -4474,8 +4475,8 @@ static void bond_free_all(void) bond_mc_list_destroy(bond); /* Release the bonded slaves */ bond_release_all(bond_dev); - unregister_netdevice(bond_dev); bond_deinit(bond_dev); + unregister_netdevice(bond_dev); } #ifdef CONFIG_PROC_FS diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 7a06ade85b02..b29330d8e309 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -1193,8 +1193,6 @@ static ssize_t bonding_show_active_slave(struct device *d, struct bonding *bond = to_bond(d); int count; - rtnl_lock(); - read_lock(&bond->curr_slave_lock); curr = bond->curr_active_slave; read_unlock(&bond->curr_slave_lock); @@ -1216,7 +1214,9 @@ static ssize_t bonding_store_active_slave(struct device *d, struct slave *new_active = NULL; struct bonding *bond = to_bond(d); + rtnl_lock(); write_lock_bh(&bond->lock); + if (!USES_PRIMARY(bond->params.mode)) { printk(KERN_INFO DRV_NAME ": %s: Unable to change active slave; %s is in mode %d\n", diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index 2dbf8dc116c6..c5975047c89b 100644..100755 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c @@ -374,7 +374,9 @@ static char stats_strings[][ETH_GSTRING_LEN] = { "TxInternalMACXmitError", "TxFramesWithExcessiveDeferral", "TxFCSErrors", - + "TxJumboFramesOk", + "TxJumboOctetsOk", + "RxOctetsOK", "RxOctetsBad", "RxUnicastFramesOK", @@ -392,16 +394,17 @@ static char stats_strings[][ETH_GSTRING_LEN] = { "RxInRangeLengthErrors", "RxOutOfRangeLengthField", "RxFrameTooLongErrors", + "RxJumboFramesOk", + "RxJumboOctetsOk", /* Port stats */ - "RxPackets", "RxCsumGood", - "TxPackets", "TxCsumOffload", "TxTso", "RxVlan", "TxVlan", - + "TxNeedHeadroom", + /* Interrupt stats */ "rx drops", "pure_rsps", @@ -463,23 +466,56 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats, const struct cmac_statistics *s; const struct sge_intr_counts *t; struct sge_port_stats ss; - unsigned int len; s = mac->ops->statistics_update(mac, MAC_STATS_UPDATE_FULL); - - len = sizeof(u64)*(&s->TxFCSErrors + 1 - &s->TxOctetsOK); - memcpy(data, &s->TxOctetsOK, len); - data += len; - - len = sizeof(u64)*(&s->RxFrameTooLongErrors + 1 - &s->RxOctetsOK); - memcpy(data, &s->RxOctetsOK, len); - data += len; - + t = t1_sge_get_intr_counts(adapter->sge); t1_sge_get_port_stats(adapter->sge, dev->if_port, &ss); - memcpy(data, &ss, sizeof(ss)); - data += sizeof(ss); - t = t1_sge_get_intr_counts(adapter->sge); + *data++ = s->TxOctetsOK; + *data++ = s->TxOctetsBad; + *data++ = s->TxUnicastFramesOK; + *data++ = s->TxMulticastFramesOK; + *data++ = s->TxBroadcastFramesOK; + *data++ = s->TxPauseFrames; + *data++ = s->TxFramesWithDeferredXmissions; + *data++ = s->TxLateCollisions; + *data++ = s->TxTotalCollisions; + *data++ = s->TxFramesAbortedDueToXSCollisions; + *data++ = s->TxUnderrun; + *data++ = s->TxLengthErrors; + *data++ = s->TxInternalMACXmitError; + *data++ = s->TxFramesWithExcessiveDeferral; + *data++ = s->TxFCSErrors; + *data++ = s->TxJumboFramesOK; + *data++ = s->TxJumboOctetsOK; + + *data++ = s->RxOctetsOK; + *data++ = s->RxOctetsBad; + *data++ = s->RxUnicastFramesOK; + *data++ = s->RxMulticastFramesOK; + *data++ = s->RxBroadcastFramesOK; + *data++ = s->RxPauseFrames; + *data++ = s->RxFCSErrors; + *data++ = s->RxAlignErrors; + *data++ = s->RxSymbolErrors; + *data++ = s->RxDataErrors; + *data++ = s->RxSequenceErrors; + *data++ = s->RxRuntErrors; + *data++ = s->RxJabberErrors; + *data++ = s->RxInternalMACRcvError; + *data++ = s->RxInRangeLengthErrors; + *data++ = s->RxOutOfRangeLengthField; + *data++ = s->RxFrameTooLongErrors; + *data++ = s->RxJumboFramesOK; + *data++ = s->RxJumboOctetsOK; + + *data++ = ss.rx_cso_good; + *data++ = ss.tx_cso; + *data++ = ss.tx_tso; + *data++ = ss.vlan_xtract; + *data++ = ss.vlan_insert; + *data++ = ss.tx_need_hdrroom; + *data++ = t->rx_drops; *data++ = t->pure_rsps; *data++ = t->unhandled_irqs; diff --git a/drivers/net/chelsio/pm3393.c b/drivers/net/chelsio/pm3393.c index 678778a8d133..2117c4fbb107 100644..100755 --- a/drivers/net/chelsio/pm3393.c +++ b/drivers/net/chelsio/pm3393.c @@ -45,7 +45,7 @@ #include <linux/crc32.h> -#define OFFSET(REG_ADDR) (REG_ADDR << 2) +#define OFFSET(REG_ADDR) ((REG_ADDR) << 2) /* Max frame size PM3393 can handle. Includes Ethernet header and CRC. */ #define MAX_FRAME_SIZE 9600 @@ -428,69 +428,26 @@ static int pm3393_set_speed_duplex_fc(struct cmac *cmac, int speed, int duplex, return 0; } -static void pm3393_rmon_update(struct adapter *adapter, u32 offs, u64 *val, - int over) -{ - u32 val0, val1, val2; - - t1_tpi_read(adapter, offs, &val0); - t1_tpi_read(adapter, offs + 4, &val1); - t1_tpi_read(adapter, offs + 8, &val2); - - *val &= ~0ull << 40; - *val |= val0 & 0xffff; - *val |= (val1 & 0xffff) << 16; - *val |= (u64)(val2 & 0xff) << 32; - - if (over) - *val += 1ull << 40; +#define RMON_UPDATE(mac, name, stat_name) \ +{ \ + t1_tpi_read((mac)->adapter, OFFSET(name), &val0); \ + t1_tpi_read((mac)->adapter, OFFSET((name)+1), &val1); \ + t1_tpi_read((mac)->adapter, OFFSET((name)+2), &val2); \ + (mac)->stats.stat_name = (u64)(val0 & 0xffff) | \ + ((u64)(val1 & 0xffff) << 16) | \ + ((u64)(val2 & 0xff) << 32) | \ + ((mac)->stats.stat_name & \ + 0xffffff0000000000ULL); \ + if (ro & \ + (1ULL << ((name - SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW) >> 2))) \ + (mac)->stats.stat_name += 1ULL << 40; \ } static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac, int flag) { - static struct { - unsigned int reg; - unsigned int offset; - } hw_stats [] = { - -#define HW_STAT(name, stat_name) \ - { name, (&((struct cmac_statistics *)NULL)->stat_name) - (u64 *)NULL } - - /* Rx stats */ - HW_STAT(RxOctetsReceivedOK, RxOctetsOK), - HW_STAT(RxUnicastFramesReceivedOK, RxUnicastFramesOK), - HW_STAT(RxMulticastFramesReceivedOK, RxMulticastFramesOK), - HW_STAT(RxBroadcastFramesReceivedOK, RxBroadcastFramesOK), - HW_STAT(RxPAUSEMACCtrlFramesReceived, RxPauseFrames), - HW_STAT(RxFrameCheckSequenceErrors, RxFCSErrors), - HW_STAT(RxFramesLostDueToInternalMACErrors, - RxInternalMACRcvError), - HW_STAT(RxSymbolErrors, RxSymbolErrors), - HW_STAT(RxInRangeLengthErrors, RxInRangeLengthErrors), - HW_STAT(RxFramesTooLongErrors , RxFrameTooLongErrors), - HW_STAT(RxJabbers, RxJabberErrors), - HW_STAT(RxFragments, RxRuntErrors), - HW_STAT(RxUndersizedFrames, RxRuntErrors), - HW_STAT(RxJumboFramesReceivedOK, RxJumboFramesOK), - HW_STAT(RxJumboOctetsReceivedOK, RxJumboOctetsOK), - - /* Tx stats */ - HW_STAT(TxOctetsTransmittedOK, TxOctetsOK), - HW_STAT(TxFramesLostDueToInternalMACTransmissionError, - TxInternalMACXmitError), - HW_STAT(TxTransmitSystemError, TxFCSErrors), - HW_STAT(TxUnicastFramesTransmittedOK, TxUnicastFramesOK), - HW_STAT(TxMulticastFramesTransmittedOK, TxMulticastFramesOK), - HW_STAT(TxBroadcastFramesTransmittedOK, TxBroadcastFramesOK), - HW_STAT(TxPAUSEMACCtrlFramesTransmitted, TxPauseFrames), - HW_STAT(TxJumboFramesReceivedOK, TxJumboFramesOK), - HW_STAT(TxJumboOctetsReceivedOK, TxJumboOctetsOK) - }, *p = hw_stats; - u64 ro; - u32 val0, val1, val2, val3; - u64 *stats = (u64 *) &mac->stats; - unsigned int i; + u64 ro; + u32 val0, val1, val2, val3; /* Snap the counters */ pmwrite(mac, SUNI1x10GEXP_REG_MSTAT_CONTROL, @@ -504,14 +461,35 @@ static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac, ro = ((u64)val0 & 0xffff) | (((u64)val1 & 0xffff) << 16) | (((u64)val2 & 0xffff) << 32) | (((u64)val3 & 0xffff) << 48); - for (i = 0; i < ARRAY_SIZE(hw_stats); i++) { - unsigned reg = p->reg - SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW; - - pm3393_rmon_update((mac)->adapter, OFFSET(p->reg), - stats + p->offset, ro & (reg >> 2)); - } - - + /* Rx stats */ + RMON_UPDATE(mac, RxOctetsReceivedOK, RxOctetsOK); + RMON_UPDATE(mac, RxUnicastFramesReceivedOK, RxUnicastFramesOK); + RMON_UPDATE(mac, RxMulticastFramesReceivedOK, RxMulticastFramesOK); + RMON_UPDATE(mac, RxBroadcastFramesReceivedOK, RxBroadcastFramesOK); + RMON_UPDATE(mac, RxPAUSEMACCtrlFramesReceived, RxPauseFrames); + RMON_UPDATE(mac, RxFrameCheckSequenceErrors, RxFCSErrors); + RMON_UPDATE(mac, RxFramesLostDueToInternalMACErrors, + RxInternalMACRcvError); + RMON_UPDATE(mac, RxSymbolErrors, RxSymbolErrors); + RMON_UPDATE(mac, RxInRangeLengthErrors, RxInRangeLengthErrors); + RMON_UPDATE(mac, RxFramesTooLongErrors , RxFrameTooLongErrors); + RMON_UPDATE(mac, RxJabbers, RxJabberErrors); + RMON_UPDATE(mac, RxFragments, RxRuntErrors); + RMON_UPDATE(mac, RxUndersizedFrames, RxRuntErrors); + RMON_UPDATE(mac, RxJumboFramesReceivedOK, RxJumboFramesOK); + RMON_UPDATE(mac, RxJumboOctetsReceivedOK, RxJumboOctetsOK); + + /* Tx stats */ + RMON_UPDATE(mac, TxOctetsTransmittedOK, TxOctetsOK); + RMON_UPDATE(mac, TxFramesLostDueToInternalMACTransmissionError, + TxInternalMACXmitError); + RMON_UPDATE(mac, TxTransmitSystemError, TxFCSErrors); + RMON_UPDATE(mac, TxUnicastFramesTransmittedOK, TxUnicastFramesOK); + RMON_UPDATE(mac, TxMulticastFramesTransmittedOK, TxMulticastFramesOK); + RMON_UPDATE(mac, TxBroadcastFramesTransmittedOK, TxBroadcastFramesOK); + RMON_UPDATE(mac, TxPAUSEMACCtrlFramesTransmitted, TxPauseFrames); + RMON_UPDATE(mac, TxJumboFramesReceivedOK, TxJumboFramesOK); + RMON_UPDATE(mac, TxJumboOctetsReceivedOK, TxJumboOctetsOK); return &mac->stats; } diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c index ffa7e649a6ef..b301c0428ae0 100644..100755 --- a/drivers/net/chelsio/sge.c +++ b/drivers/net/chelsio/sge.c @@ -986,11 +986,10 @@ void t1_sge_get_port_stats(const struct sge *sge, int port, for_each_possible_cpu(cpu) { struct sge_port_stats *st = per_cpu_ptr(sge->port_stats[port], cpu); - ss->rx_packets += st->rx_packets; ss->rx_cso_good += st->rx_cso_good; - ss->tx_packets += st->tx_packets; ss->tx_cso += st->tx_cso; ss->tx_tso += st->tx_tso; + ss->tx_need_hdrroom += st->tx_need_hdrroom; ss->vlan_xtract += st->vlan_xtract; ss->vlan_insert += st->vlan_insert; } @@ -1379,11 +1378,10 @@ static void sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len) } __skb_pull(skb, sizeof(*p)); - skb->dev->last_rx = jiffies; st = per_cpu_ptr(sge->port_stats[p->iff], smp_processor_id()); - st->rx_packets++; skb->protocol = eth_type_trans(skb, adapter->port[p->iff].dev); + skb->dev->last_rx = jiffies; if ((adapter->flags & RX_CSUM_ENABLED) && p->csum == 0xffff && skb->protocol == htons(ETH_P_IP) && (skb->data[9] == IPPROTO_TCP || skb->data[9] == IPPROTO_UDP)) { @@ -1624,11 +1622,9 @@ int t1_poll(struct napi_struct *napi, int budget) { struct adapter *adapter = container_of(napi, struct adapter, napi); struct net_device *dev = adapter->port[0].dev; - int work_done; - - work_done = process_responses(adapter, budget); + int work_done = process_responses(adapter, budget); - if (likely(!responses_pending(adapter))) { + if (likely(work_done < budget)) { netif_rx_complete(dev, napi); writel(adapter->sge->respQ.cidx, adapter->regs + A_SG_SLEEPING); @@ -1848,7 +1844,8 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct adapter *adapter = dev->priv; struct sge *sge = adapter->sge; - struct sge_port_stats *st = per_cpu_ptr(sge->port_stats[dev->if_port], smp_processor_id()); + struct sge_port_stats *st = per_cpu_ptr(sge->port_stats[dev->if_port], + smp_processor_id()); struct cpl_tx_pkt *cpl; struct sk_buff *orig_skb = skb; int ret; @@ -1856,6 +1853,18 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) if (skb->protocol == htons(ETH_P_CPL5)) goto send; + /* + * We are using a non-standard hard_header_len. + * Allocate more header room in the rare cases it is not big enough. + */ + if (unlikely(skb_headroom(skb) < dev->hard_header_len - ETH_HLEN)) { + skb = skb_realloc_headroom(skb, sizeof(struct cpl_tx_pkt_lso)); + ++st->tx_need_hdrroom; + dev_kfree_skb_any(orig_skb); + if (!skb) + return NETDEV_TX_OK; + } + if (skb_shinfo(skb)->gso_size) { int eth_type; struct cpl_tx_pkt_lso *hdr; @@ -1889,24 +1898,6 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } - /* - * We are using a non-standard hard_header_len and some kernel - * components, such as pktgen, do not handle it right. - * Complain when this happens but try to fix things up. - */ - if (unlikely(skb_headroom(skb) < dev->hard_header_len - ETH_HLEN)) { - pr_debug("%s: headroom %d header_len %d\n", dev->name, - skb_headroom(skb), dev->hard_header_len); - - if (net_ratelimit()) - printk(KERN_ERR "%s: inadequate headroom in " - "Tx packet\n", dev->name); - skb = skb_realloc_headroom(skb, sizeof(*cpl)); - dev_kfree_skb_any(orig_skb); - if (!skb) - return NETDEV_TX_OK; - } - if (!(adapter->flags & UDP_CSUM_CAPABLE) && skb->ip_summed == CHECKSUM_PARTIAL && ip_hdr(skb)->protocol == IPPROTO_UDP) { @@ -1952,7 +1943,6 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) cpl->vlan_valid = 0; send: - st->tx_packets++; dev->trans_start = jiffies; ret = t1_sge_tx(skb, adapter, 0, dev); diff --git a/drivers/net/chelsio/sge.h b/drivers/net/chelsio/sge.h index 713d9c55f24d..cced9dff91c5 100644..100755 --- a/drivers/net/chelsio/sge.h +++ b/drivers/net/chelsio/sge.h @@ -57,13 +57,12 @@ struct sge_intr_counts { }; struct sge_port_stats { - u64 rx_packets; /* # of Ethernet packets received */ u64 rx_cso_good; /* # of successful RX csum offloads */ - u64 tx_packets; /* # of TX packets */ u64 tx_cso; /* # of TX checksum offloads */ u64 tx_tso; /* # of TSO requests */ u64 vlan_xtract; /* # of VLAN tag extractions */ u64 vlan_insert; /* # of VLAN tag insertions */ + u64 tx_need_hdrroom; /* # of TX skbs in need of more header room */ }; struct sk_buff; diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c index edd6828f0a78..917b7b46f1a7 100644 --- a/drivers/net/cris/eth_v10.c +++ b/drivers/net/cris/eth_v10.c @@ -250,6 +250,7 @@ #include <asm/system.h> #include <asm/ethernet.h> #include <asm/cache.h> +#include <asm/arch/io_interface_mux.h> //#define ETHDEBUG #define D(x) @@ -279,6 +280,9 @@ struct net_local { * by this lock as well. */ spinlock_t lock; + + spinlock_t led_lock; /* Protect LED state */ + spinlock_t transceiver_lock; /* Protect transceiver state. */ }; typedef struct etrax_eth_descr @@ -295,8 +299,6 @@ struct transceiver_ops void (*check_duplex)(struct net_device* dev); }; -struct transceiver_ops* transceiver; - /* Duplex settings */ enum duplex { @@ -307,7 +309,7 @@ enum duplex /* Dma descriptors etc. */ -#define MAX_MEDIA_DATA_SIZE 1518 +#define MAX_MEDIA_DATA_SIZE 1522 #define MIN_PACKET_LEN 46 #define ETHER_HEAD_LEN 14 @@ -332,8 +334,8 @@ enum duplex /*Intel LXT972A specific*/ #define MDIO_INT_STATUS_REG_2 0x0011 -#define MDIO_INT_FULL_DUPLEX_IND ( 1 << 9 ) -#define MDIO_INT_SPEED ( 1 << 14 ) +#define MDIO_INT_FULL_DUPLEX_IND (1 << 9) +#define MDIO_INT_SPEED (1 << 14) /* Network flash constants */ #define NET_FLASH_TIME (HZ/50) /* 20 ms */ @@ -344,8 +346,8 @@ enum duplex #define NO_NETWORK_ACTIVITY 0 #define NETWORK_ACTIVITY 1 -#define NBR_OF_RX_DESC 64 -#define NBR_OF_TX_DESC 256 +#define NBR_OF_RX_DESC 32 +#define NBR_OF_TX_DESC 16 /* Large packets are sent directly to upper layers while small packets are */ /* copied (to reduce memory waste). The following constant decides the breakpoint */ @@ -367,7 +369,6 @@ enum duplex static etrax_eth_descr *myNextRxDesc; /* Points to the next descriptor to to be processed */ static etrax_eth_descr *myLastRxDesc; /* The last processed descriptor */ -static etrax_eth_descr *myPrevRxDesc; /* The descriptor right before myNextRxDesc */ static etrax_eth_descr RxDescList[NBR_OF_RX_DESC] __attribute__ ((aligned(32))); @@ -377,7 +378,6 @@ static etrax_eth_descr* myNextTxDesc; /* Next descriptor to use */ static etrax_eth_descr TxDescList[NBR_OF_TX_DESC] __attribute__ ((aligned(32))); static unsigned int network_rec_config_shadow = 0; -static unsigned int mdio_phy_addr; /* Transciever address */ static unsigned int network_tr_ctrl_shadow = 0; @@ -411,7 +411,7 @@ static int e100_set_config(struct net_device* dev, struct ifmap* map); static void e100_tx_timeout(struct net_device *dev); static struct net_device_stats *e100_get_stats(struct net_device *dev); static void set_multicast_list(struct net_device *dev); -static void e100_hardware_send_packet(char *buf, int length); +static void e100_hardware_send_packet(struct net_local* np, char *buf, int length); static void update_rx_stats(struct net_device_stats *); static void update_tx_stats(struct net_device_stats *); static int e100_probe_transceiver(struct net_device* dev); @@ -434,7 +434,10 @@ static void e100_clear_network_leds(unsigned long dummy); static void e100_set_network_leds(int active); static const struct ethtool_ops e100_ethtool_ops; - +#if defined(CONFIG_ETRAX_NO_PHY) +static void dummy_check_speed(struct net_device* dev); +static void dummy_check_duplex(struct net_device* dev); +#else static void broadcom_check_speed(struct net_device* dev); static void broadcom_check_duplex(struct net_device* dev); static void tdk_check_speed(struct net_device* dev); @@ -443,16 +446,28 @@ static void intel_check_speed(struct net_device* dev); static void intel_check_duplex(struct net_device* dev); static void generic_check_speed(struct net_device* dev); static void generic_check_duplex(struct net_device* dev); +#endif +#ifdef CONFIG_NET_POLL_CONTROLLER +static void e100_netpoll(struct net_device* dev); +#endif + +static int autoneg_normal = 1; struct transceiver_ops transceivers[] = { +#if defined(CONFIG_ETRAX_NO_PHY) + {0x0000, dummy_check_speed, dummy_check_duplex} /* Dummy */ +#else {0x1018, broadcom_check_speed, broadcom_check_duplex}, /* Broadcom */ {0xC039, tdk_check_speed, tdk_check_duplex}, /* TDK 2120 */ {0x039C, tdk_check_speed, tdk_check_duplex}, /* TDK 2120C */ {0x04de, intel_check_speed, intel_check_duplex}, /* Intel LXT972A*/ {0x0000, generic_check_speed, generic_check_duplex} /* Generic, must be last */ +#endif }; +struct transceiver_ops* transceiver = &transceivers[0]; + #define tx_done(dev) (*R_DMA_CH0_CMD == 0) /* @@ -471,14 +486,22 @@ etrax_ethernet_init(void) int i, err; printk(KERN_INFO - "ETRAX 100LX 10/100MBit ethernet v2.0 (c) 2000-2003 Axis Communications AB\n"); + "ETRAX 100LX 10/100MBit ethernet v2.0 (c) 1998-2007 Axis Communications AB\n"); - dev = alloc_etherdev(sizeof(struct net_local)); - np = dev->priv; + if (cris_request_io_interface(if_eth, cardname)) { + printk(KERN_CRIT "etrax_ethernet_init failed to get IO interface\n"); + return -EBUSY; + } + dev = alloc_etherdev(sizeof(struct net_local)); if (!dev) return -ENOMEM; + np = netdev_priv(dev); + + /* we do our own locking */ + dev->features |= NETIF_F_LLTX; + dev->base_addr = (unsigned int)R_NETWORK_SA_0; /* just to have something to show */ /* now setup our etrax specific stuff */ @@ -498,14 +521,22 @@ etrax_ethernet_init(void) dev->do_ioctl = e100_ioctl; dev->set_config = e100_set_config; dev->tx_timeout = e100_tx_timeout; +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = e100_netpoll; +#endif + + spin_lock_init(&np->lock); + spin_lock_init(&np->led_lock); + spin_lock_init(&np->transceiver_lock); /* Initialise the list of Etrax DMA-descriptors */ /* Initialise receive descriptors */ for (i = 0; i < NBR_OF_RX_DESC; i++) { - /* Allocate two extra cachelines to make sure that buffer used by DMA - * does not share cacheline with any other data (to avoid cache bug) + /* Allocate two extra cachelines to make sure that buffer used + * by DMA does not share cacheline with any other data (to + * avoid cache bug) */ RxDescList[i].skb = dev_alloc_skb(MAX_MEDIA_DATA_SIZE + 2 * L1_CACHE_BYTES); if (!RxDescList[i].skb) @@ -541,7 +572,6 @@ etrax_ethernet_init(void) myNextRxDesc = &RxDescList[0]; myLastRxDesc = &RxDescList[NBR_OF_RX_DESC - 1]; - myPrevRxDesc = &RxDescList[NBR_OF_RX_DESC - 1]; myFirstTxDesc = &TxDescList[0]; myNextTxDesc = &TxDescList[0]; myLastTxDesc = &TxDescList[NBR_OF_TX_DESC - 1]; @@ -562,10 +592,11 @@ etrax_ethernet_init(void) current_speed = 10; current_speed_selection = 0; /* Auto */ speed_timer.expires = jiffies + NET_LINK_UP_CHECK_INTERVAL; - duplex_timer.data = (unsigned long)dev; + speed_timer.data = (unsigned long)dev; speed_timer.function = e100_check_speed; clear_led_timer.function = e100_clear_network_leds; + clear_led_timer.data = (unsigned long)dev; full_duplex = 0; current_duplex = autoneg; @@ -574,7 +605,6 @@ etrax_ethernet_init(void) duplex_timer.function = e100_check_duplex; /* Initialize mii interface */ - np->mii_if.phy_id = mdio_phy_addr; np->mii_if.phy_id_mask = 0x1f; np->mii_if.reg_num_mask = 0x1f; np->mii_if.dev = dev; @@ -585,6 +615,9 @@ etrax_ethernet_init(void) /* unwanted addresses are matched */ *R_NETWORK_GA_0 = 0x00000000; *R_NETWORK_GA_1 = 0x00000000; + + /* Initialize next time the led can flash */ + led_next_time = jiffies; return 0; } @@ -595,9 +628,9 @@ etrax_ethernet_init(void) static int e100_set_mac_address(struct net_device *dev, void *p) { - struct net_local *np = (struct net_local *)dev->priv; + struct net_local *np = netdev_priv(dev); struct sockaddr *addr = p; - int i; + DECLARE_MAC_BUF(mac); spin_lock(&np->lock); /* preemption protection */ @@ -686,6 +719,25 @@ e100_open(struct net_device *dev) goto grace_exit2; } + /* + * Always allocate the DMA channels after the IRQ, + * and clean up on failure. + */ + + if (cris_request_dma(NETWORK_TX_DMA_NBR, + cardname, + DMA_VERBOSE_ON_ERROR, + dma_eth)) { + goto grace_exit3; + } + + if (cris_request_dma(NETWORK_RX_DMA_NBR, + cardname, + DMA_VERBOSE_ON_ERROR, + dma_eth)) { + goto grace_exit4; + } + /* give the HW an idea of what MAC address we want */ *R_NETWORK_SA_0 = dev->dev_addr[0] | (dev->dev_addr[1] << 8) | @@ -700,6 +752,7 @@ e100_open(struct net_device *dev) *R_NETWORK_REC_CONFIG = 0xd; /* broadcast rec, individ. rec, ma0 enabled */ #else + SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, max_size, size1522); SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, broadcast, receive); SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, ma0, enable); SETF(network_rec_config_shadow, R_NETWORK_REC_CONFIG, duplex, full_duplex); @@ -719,8 +772,7 @@ e100_open(struct net_device *dev) SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, crc, enable); *R_NETWORK_TR_CTRL = network_tr_ctrl_shadow; - save_flags(flags); - cli(); + local_irq_save(flags); /* enable the irq's for ethernet DMA */ @@ -752,12 +804,13 @@ e100_open(struct net_device *dev) *R_DMA_CH0_FIRST = 0; *R_DMA_CH0_DESCR = virt_to_phys(myLastTxDesc); + netif_start_queue(dev); - restore_flags(flags); + local_irq_restore(flags); /* Probe for transceiver */ if (e100_probe_transceiver(dev)) - goto grace_exit3; + goto grace_exit5; /* Start duplex/speed timers */ add_timer(&speed_timer); @@ -766,10 +819,14 @@ e100_open(struct net_device *dev) /* We are now ready to accept transmit requeusts from * the queueing layer of the networking. */ - netif_start_queue(dev); + netif_carrier_on(dev); return 0; +grace_exit5: + cris_free_dma(NETWORK_RX_DMA_NBR, cardname); +grace_exit4: + cris_free_dma(NETWORK_TX_DMA_NBR, cardname); grace_exit3: free_irq(NETWORK_STATUS_IRQ_NBR, (void *)dev); grace_exit2: @@ -780,12 +837,20 @@ grace_exit0: return -EAGAIN; } - +#if defined(CONFIG_ETRAX_NO_PHY) +static void +dummy_check_speed(struct net_device* dev) +{ + current_speed = 100; +} +#else static void generic_check_speed(struct net_device* dev) { unsigned long data; - data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_ADVERTISE); + struct net_local *np = netdev_priv(dev); + + data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_ADVERTISE); if ((data & ADVERTISE_100FULL) || (data & ADVERTISE_100HALF)) current_speed = 100; @@ -797,7 +862,10 @@ static void tdk_check_speed(struct net_device* dev) { unsigned long data; - data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_TDK_DIAGNOSTIC_REG); + struct net_local *np = netdev_priv(dev); + + data = e100_get_mdio_reg(dev, np->mii_if.phy_id, + MDIO_TDK_DIAGNOSTIC_REG); current_speed = (data & MDIO_TDK_DIAGNOSTIC_RATE ? 100 : 10); } @@ -805,7 +873,10 @@ static void broadcom_check_speed(struct net_device* dev) { unsigned long data; - data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_AUX_CTRL_STATUS_REG); + struct net_local *np = netdev_priv(dev); + + data = e100_get_mdio_reg(dev, np->mii_if.phy_id, + MDIO_AUX_CTRL_STATUS_REG); current_speed = (data & MDIO_BC_SPEED ? 100 : 10); } @@ -813,46 +884,62 @@ static void intel_check_speed(struct net_device* dev) { unsigned long data; - data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_INT_STATUS_REG_2); + struct net_local *np = netdev_priv(dev); + + data = e100_get_mdio_reg(dev, np->mii_if.phy_id, + MDIO_INT_STATUS_REG_2); current_speed = (data & MDIO_INT_SPEED ? 100 : 10); } - +#endif static void e100_check_speed(unsigned long priv) { struct net_device* dev = (struct net_device*)priv; + struct net_local *np = netdev_priv(dev); static int led_initiated = 0; unsigned long data; int old_speed = current_speed; - data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_BMSR); + spin_lock(&np->transceiver_lock); + + data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_BMSR); if (!(data & BMSR_LSTATUS)) { current_speed = 0; } else { transceiver->check_speed(dev); } + spin_lock(&np->led_lock); if ((old_speed != current_speed) || !led_initiated) { led_initiated = 1; e100_set_network_leds(NO_NETWORK_ACTIVITY); + if (current_speed) + netif_carrier_on(dev); + else + netif_carrier_off(dev); } + spin_unlock(&np->led_lock); /* Reinitialize the timer. */ speed_timer.expires = jiffies + NET_LINK_UP_CHECK_INTERVAL; add_timer(&speed_timer); + + spin_unlock(&np->transceiver_lock); } static void e100_negotiate(struct net_device* dev) { - unsigned short data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_ADVERTISE); + struct net_local *np = netdev_priv(dev); + unsigned short data = e100_get_mdio_reg(dev, np->mii_if.phy_id, + MII_ADVERTISE); /* Discard old speed and duplex settings */ data &= ~(ADVERTISE_100HALF | ADVERTISE_100FULL | ADVERTISE_10HALF | ADVERTISE_10FULL); switch (current_speed_selection) { - case 10 : + case 10: if (current_duplex == full) data |= ADVERTISE_10FULL; else if (current_duplex == half) @@ -861,7 +948,7 @@ e100_negotiate(struct net_device* dev) data |= ADVERTISE_10HALF | ADVERTISE_10FULL; break; - case 100 : + case 100: if (current_duplex == full) data |= ADVERTISE_100FULL; else if (current_duplex == half) @@ -870,7 +957,7 @@ e100_negotiate(struct net_device* dev) data |= ADVERTISE_100HALF | ADVERTISE_100FULL; break; - case 0 : /* Auto */ + case 0: /* Auto */ if (current_duplex == full) data |= ADVERTISE_100FULL | ADVERTISE_10FULL; else if (current_duplex == half) @@ -880,35 +967,44 @@ e100_negotiate(struct net_device* dev) ADVERTISE_100HALF | ADVERTISE_100FULL; break; - default : /* assume autoneg speed and duplex */ + default: /* assume autoneg speed and duplex */ data |= ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_100HALF | ADVERTISE_100FULL; + break; } - e100_set_mdio_reg(dev, mdio_phy_addr, MII_ADVERTISE, data); + e100_set_mdio_reg(dev, np->mii_if.phy_id, MII_ADVERTISE, data); /* Renegotiate with link partner */ - data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_BMCR); + if (autoneg_normal) { + data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_BMCR); data |= BMCR_ANENABLE | BMCR_ANRESTART; - - e100_set_mdio_reg(dev, mdio_phy_addr, MII_BMCR, data); + } + e100_set_mdio_reg(dev, np->mii_if.phy_id, MII_BMCR, data); } static void e100_set_speed(struct net_device* dev, unsigned long speed) { + struct net_local *np = netdev_priv(dev); + + spin_lock(&np->transceiver_lock); if (speed != current_speed_selection) { current_speed_selection = speed; e100_negotiate(dev); } + spin_unlock(&np->transceiver_lock); } static void e100_check_duplex(unsigned long priv) { struct net_device *dev = (struct net_device *)priv; - struct net_local *np = (struct net_local *)dev->priv; - int old_duplex = full_duplex; + struct net_local *np = netdev_priv(dev); + int old_duplex; + + spin_lock(&np->transceiver_lock); + old_duplex = full_duplex; transceiver->check_duplex(dev); if (old_duplex != full_duplex) { /* Duplex changed */ @@ -920,13 +1016,22 @@ e100_check_duplex(unsigned long priv) duplex_timer.expires = jiffies + NET_DUPLEX_CHECK_INTERVAL; add_timer(&duplex_timer); np->mii_if.full_duplex = full_duplex; + spin_unlock(&np->transceiver_lock); } - +#if defined(CONFIG_ETRAX_NO_PHY) +static void +dummy_check_duplex(struct net_device* dev) +{ + full_duplex = 1; +} +#else static void generic_check_duplex(struct net_device* dev) { unsigned long data; - data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_ADVERTISE); + struct net_local *np = netdev_priv(dev); + + data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_ADVERTISE); if ((data & ADVERTISE_10FULL) || (data & ADVERTISE_100FULL)) full_duplex = 1; @@ -938,7 +1043,10 @@ static void tdk_check_duplex(struct net_device* dev) { unsigned long data; - data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_TDK_DIAGNOSTIC_REG); + struct net_local *np = netdev_priv(dev); + + data = e100_get_mdio_reg(dev, np->mii_if.phy_id, + MDIO_TDK_DIAGNOSTIC_REG); full_duplex = (data & MDIO_TDK_DIAGNOSTIC_DPLX) ? 1 : 0; } @@ -946,7 +1054,10 @@ static void broadcom_check_duplex(struct net_device* dev) { unsigned long data; - data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_AUX_CTRL_STATUS_REG); + struct net_local *np = netdev_priv(dev); + + data = e100_get_mdio_reg(dev, np->mii_if.phy_id, + MDIO_AUX_CTRL_STATUS_REG); full_duplex = (data & MDIO_BC_FULL_DUPLEX_IND) ? 1 : 0; } @@ -954,38 +1065,55 @@ static void intel_check_duplex(struct net_device* dev) { unsigned long data; - data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_INT_STATUS_REG_2); + struct net_local *np = netdev_priv(dev); + + data = e100_get_mdio_reg(dev, np->mii_if.phy_id, + MDIO_INT_STATUS_REG_2); full_duplex = (data & MDIO_INT_FULL_DUPLEX_IND) ? 1 : 0; } - +#endif static void e100_set_duplex(struct net_device* dev, enum duplex new_duplex) { + struct net_local *np = netdev_priv(dev); + + spin_lock(&np->transceiver_lock); if (new_duplex != current_duplex) { current_duplex = new_duplex; e100_negotiate(dev); } + spin_unlock(&np->transceiver_lock); } static int e100_probe_transceiver(struct net_device* dev) { + int ret = 0; + +#if !defined(CONFIG_ETRAX_NO_PHY) unsigned int phyid_high; unsigned int phyid_low; unsigned int oui; struct transceiver_ops* ops = NULL; + struct net_local *np = netdev_priv(dev); + + spin_lock(&np->transceiver_lock); /* Probe MDIO physical address */ - for (mdio_phy_addr = 0; mdio_phy_addr <= 31; mdio_phy_addr++) { - if (e100_get_mdio_reg(dev, mdio_phy_addr, MII_BMSR) != 0xffff) + for (np->mii_if.phy_id = 0; np->mii_if.phy_id <= 31; + np->mii_if.phy_id++) { + if (e100_get_mdio_reg(dev, + np->mii_if.phy_id, MII_BMSR) != 0xffff) break; } - if (mdio_phy_addr == 32) - return -ENODEV; + if (np->mii_if.phy_id == 32) { + ret = -ENODEV; + goto out; + } /* Get manufacturer */ - phyid_high = e100_get_mdio_reg(dev, mdio_phy_addr, MII_PHYSID1); - phyid_low = e100_get_mdio_reg(dev, mdio_phy_addr, MII_PHYSID2); + phyid_high = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_PHYSID1); + phyid_low = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_PHYSID2); oui = (phyid_high << 6) | (phyid_low >> 10); for (ops = &transceivers[0]; ops->oui; ops++) { @@ -993,8 +1121,10 @@ e100_probe_transceiver(struct net_device* dev) break; } transceiver = ops; - - return 0; +out: + spin_unlock(&np->transceiver_lock); +#endif + return ret; } static int @@ -1088,13 +1218,14 @@ e100_receive_mdio_bit() static void e100_reset_transceiver(struct net_device* dev) { + struct net_local *np = netdev_priv(dev); unsigned short cmd; unsigned short data; int bitCounter; - data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_BMCR); + data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_BMCR); - cmd = (MDIO_START << 14) | (MDIO_WRITE << 12) | (mdio_phy_addr << 7) | (MII_BMCR << 2); + cmd = (MDIO_START << 14) | (MDIO_WRITE << 12) | (np->mii_if.phy_id << 7) | (MII_BMCR << 2); e100_send_mdio_cmd(cmd, 1); @@ -1112,7 +1243,7 @@ e100_reset_transceiver(struct net_device* dev) static void e100_tx_timeout(struct net_device *dev) { - struct net_local *np = (struct net_local *)dev->priv; + struct net_local *np = netdev_priv(dev); unsigned long flags; spin_lock_irqsave(&np->lock, flags); @@ -1134,8 +1265,7 @@ e100_tx_timeout(struct net_device *dev) e100_reset_transceiver(dev); /* and get rid of the packets that never got an interrupt */ - while (myFirstTxDesc != myNextTxDesc) - { + while (myFirstTxDesc != myNextTxDesc) { dev_kfree_skb(myFirstTxDesc->skb); myFirstTxDesc->skb = 0; myFirstTxDesc = phys_to_virt(myFirstTxDesc->descr.next); @@ -1161,7 +1291,7 @@ e100_tx_timeout(struct net_device *dev) static int e100_send_packet(struct sk_buff *skb, struct net_device *dev) { - struct net_local *np = (struct net_local *)dev->priv; + struct net_local *np = netdev_priv(dev); unsigned char *buf = skb->data; unsigned long flags; @@ -1174,7 +1304,7 @@ e100_send_packet(struct sk_buff *skb, struct net_device *dev) dev->trans_start = jiffies; - e100_hardware_send_packet(buf, skb->len); + e100_hardware_send_packet(np, buf, skb->len); myNextTxDesc = phys_to_virt(myNextTxDesc->descr.next); @@ -1197,13 +1327,15 @@ static irqreturn_t e100rxtx_interrupt(int irq, void *dev_id) { struct net_device *dev = (struct net_device *)dev_id; - struct net_local *np = (struct net_local *)dev->priv; - unsigned long irqbits = *R_IRQ_MASK2_RD; + struct net_local *np = netdev_priv(dev); + unsigned long irqbits; - /* Disable RX/TX IRQs to avoid reentrancy */ - *R_IRQ_MASK2_CLR = - IO_STATE(R_IRQ_MASK2_CLR, dma0_eop, clr) | - IO_STATE(R_IRQ_MASK2_CLR, dma1_eop, clr); + /* + * Note that both rx and tx interrupts are blocked at this point, + * regardless of which got us here. + */ + + irqbits = *R_IRQ_MASK2_RD; /* Handle received packets */ if (irqbits & IO_STATE(R_IRQ_MASK2_RD, dma1_eop, active)) { @@ -1219,7 +1351,7 @@ e100rxtx_interrupt(int irq, void *dev_id) * allocate a new buffer to put a packet in. */ e100_rx(dev); - ((struct net_local *)dev->priv)->stats.rx_packets++; + np->stats.rx_packets++; /* restart/continue on the channel, for safety */ *R_DMA_CH1_CMD = IO_STATE(R_DMA_CH1_CMD, cmd, restart); /* clear dma channel 1 eop/descr irq bits */ @@ -1233,9 +1365,8 @@ e100rxtx_interrupt(int irq, void *dev_id) } /* Report any packets that have been sent */ - while (myFirstTxDesc != phys_to_virt(*R_DMA_CH0_FIRST) && - myFirstTxDesc != myNextTxDesc) - { + while (virt_to_phys(myFirstTxDesc) != *R_DMA_CH0_FIRST && + (netif_queue_stopped(dev) || myFirstTxDesc != myNextTxDesc)) { np->stats.tx_bytes += myFirstTxDesc->skb->len; np->stats.tx_packets++; @@ -1244,19 +1375,15 @@ e100rxtx_interrupt(int irq, void *dev_id) dev_kfree_skb_irq(myFirstTxDesc->skb); myFirstTxDesc->skb = 0; myFirstTxDesc = phys_to_virt(myFirstTxDesc->descr.next); + /* Wake up queue. */ + netif_wake_queue(dev); } if (irqbits & IO_STATE(R_IRQ_MASK2_RD, dma0_eop, active)) { - /* acknowledge the eop interrupt and wake up queue */ + /* acknowledge the eop interrupt. */ *R_DMA_CH0_CLR_INTR = IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do); - netif_wake_queue(dev); } - /* Enable RX/TX IRQs again */ - *R_IRQ_MASK2_SET = - IO_STATE(R_IRQ_MASK2_SET, dma0_eop, set) | - IO_STATE(R_IRQ_MASK2_SET, dma1_eop, set); - return IRQ_HANDLED; } @@ -1264,7 +1391,7 @@ static irqreturn_t e100nw_interrupt(int irq, void *dev_id) { struct net_device *dev = (struct net_device *)dev_id; - struct net_local *np = (struct net_local *)dev->priv; + struct net_local *np = netdev_priv(dev); unsigned long irqbits = *R_IRQ_MASK0_RD; /* check for underrun irq */ @@ -1286,7 +1413,6 @@ e100nw_interrupt(int irq, void *dev_id) SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, clr_error, clr); *R_NETWORK_TR_CTRL = network_tr_ctrl_shadow; SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, clr_error, nop); - *R_NETWORK_TR_CTRL = IO_STATE(R_NETWORK_TR_CTRL, clr_error, clr); np->stats.tx_errors++; D(printk("ethernet excessive collisions!\n")); } @@ -1299,12 +1425,13 @@ e100_rx(struct net_device *dev) { struct sk_buff *skb; int length = 0; - struct net_local *np = (struct net_local *)dev->priv; + struct net_local *np = netdev_priv(dev); unsigned char *skb_data_ptr; #ifdef ETHDEBUG int i; #endif - + etrax_eth_descr *prevRxDesc; /* The descriptor right before myNextRxDesc */ + spin_lock(&np->led_lock); if (!led_active && time_after(jiffies, led_next_time)) { /* light the network leds depending on the current speed. */ e100_set_network_leds(NETWORK_ACTIVITY); @@ -1314,9 +1441,10 @@ e100_rx(struct net_device *dev) led_active = 1; mod_timer(&clear_led_timer, jiffies + HZ/10); } + spin_unlock(&np->led_lock); length = myNextRxDesc->descr.hw_len - 4; - ((struct net_local *)dev->priv)->stats.rx_bytes += length; + np->stats.rx_bytes += length; #ifdef ETHDEBUG printk("Got a packet of length %d:\n", length); @@ -1336,7 +1464,7 @@ e100_rx(struct net_device *dev) if (!skb) { np->stats.rx_errors++; printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); - return; + goto update_nextrxdesc; } skb_put(skb, length - ETHER_HEAD_LEN); /* allocate room for the packet body */ @@ -1354,15 +1482,15 @@ e100_rx(struct net_device *dev) else { /* Large packet, send directly to upper layers and allocate new * memory (aligned to cache line boundary to avoid bug). - * Before sending the skb to upper layers we must make sure that - * skb->data points to the aligned start of the packet. + * Before sending the skb to upper layers we must make sure + * that skb->data points to the aligned start of the packet. */ int align; struct sk_buff *new_skb = dev_alloc_skb(MAX_MEDIA_DATA_SIZE + 2 * L1_CACHE_BYTES); if (!new_skb) { np->stats.rx_errors++; printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); - return; + goto update_nextrxdesc; } skb = myNextRxDesc->skb; align = (int)phys_to_virt(myNextRxDesc->descr.buf) - (int)skb->data; @@ -1377,9 +1505,10 @@ e100_rx(struct net_device *dev) /* Send the packet to the upper layers */ netif_rx(skb); + update_nextrxdesc: /* Prepare for next packet */ myNextRxDesc->descr.status = 0; - myPrevRxDesc = myNextRxDesc; + prevRxDesc = myNextRxDesc; myNextRxDesc = phys_to_virt(myNextRxDesc->descr.next); rx_queue_len++; @@ -1387,9 +1516,9 @@ e100_rx(struct net_device *dev) /* Check if descriptors should be returned */ if (rx_queue_len == RX_QUEUE_THRESHOLD) { flush_etrax_cache(); - myPrevRxDesc->descr.ctrl |= d_eol; + prevRxDesc->descr.ctrl |= d_eol; myLastRxDesc->descr.ctrl &= ~d_eol; - myLastRxDesc = myPrevRxDesc; + myLastRxDesc = prevRxDesc; rx_queue_len = 0; } } @@ -1398,7 +1527,7 @@ e100_rx(struct net_device *dev) static int e100_close(struct net_device *dev) { - struct net_local *np = (struct net_local *)dev->priv; + struct net_local *np = netdev_priv(dev); printk(KERN_INFO "Closing %s.\n", dev->name); @@ -1426,6 +1555,9 @@ e100_close(struct net_device *dev) free_irq(NETWORK_DMA_TX_IRQ_NBR, (void *)dev); free_irq(NETWORK_STATUS_IRQ_NBR, (void *)dev); + cris_free_dma(NETWORK_TX_DMA_NBR, cardname); + cris_free_dma(NETWORK_RX_DMA_NBR, cardname); + /* Update the statistics here. */ update_rx_stats(&np->stats); @@ -1443,18 +1575,11 @@ e100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct mii_ioctl_data *data = if_mii(ifr); struct net_local *np = netdev_priv(dev); + int rc = 0; + int old_autoneg; spin_lock(&np->lock); /* Preempt protection */ switch (cmd) { - case SIOCGMIIPHY: /* Get PHY address */ - data->phy_id = mdio_phy_addr; - break; - case SIOCGMIIREG: /* Read MII register */ - data->val_out = e100_get_mdio_reg(dev, mdio_phy_addr, data->reg_num); - break; - case SIOCSMIIREG: /* Write MII register */ - e100_set_mdio_reg(dev, mdio_phy_addr, data->reg_num, data->val_in); - break; /* The ioctls below should be considered obsolete but are */ /* still present for compatability with old scripts/apps */ case SET_ETH_SPEED_10: /* 10 Mbps */ @@ -1463,60 +1588,47 @@ e100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case SET_ETH_SPEED_100: /* 100 Mbps */ e100_set_speed(dev, 100); break; - case SET_ETH_SPEED_AUTO: /* Auto negotiate speed */ + case SET_ETH_SPEED_AUTO: /* Auto-negotiate speed */ e100_set_speed(dev, 0); break; - case SET_ETH_DUPLEX_HALF: /* Half duplex. */ + case SET_ETH_DUPLEX_HALF: /* Half duplex */ e100_set_duplex(dev, half); break; - case SET_ETH_DUPLEX_FULL: /* Full duplex. */ + case SET_ETH_DUPLEX_FULL: /* Full duplex */ e100_set_duplex(dev, full); break; - case SET_ETH_DUPLEX_AUTO: /* Autonegotiate duplex*/ + case SET_ETH_DUPLEX_AUTO: /* Auto-negotiate duplex */ e100_set_duplex(dev, autoneg); break; + case SET_ETH_AUTONEG: + old_autoneg = autoneg_normal; + autoneg_normal = *(int*)data; + if (autoneg_normal != old_autoneg) + e100_negotiate(dev); + break; default: - return -EINVAL; + rc = generic_mii_ioctl(&np->mii_if, if_mii(ifr), + cmd, NULL); + break; } spin_unlock(&np->lock); - return 0; + return rc; } -static int e100_set_settings(struct net_device *dev, - struct ethtool_cmd *ecmd) +static int e100_get_settings(struct net_device *dev, + struct ethtool_cmd *cmd) { - ecmd->supported = SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII | - SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full; - ecmd->port = PORT_TP; - ecmd->transceiver = XCVR_EXTERNAL; - ecmd->phy_address = mdio_phy_addr; - ecmd->speed = current_speed; - ecmd->duplex = full_duplex ? DUPLEX_FULL : DUPLEX_HALF; - ecmd->advertising = ADVERTISED_TP; + struct net_local *np = netdev_priv(dev); + int err; - if (current_duplex == autoneg && current_speed_selection == 0) - ecmd->advertising |= ADVERTISED_Autoneg; - else { - ecmd->advertising |= - ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full; - if (current_speed_selection == 10) - ecmd->advertising &= ~(ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full); - else if (current_speed_selection == 100) - ecmd->advertising &= ~(ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full); - if (current_duplex == half) - ecmd->advertising &= ~(ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Full); - else if (current_duplex == full) - ecmd->advertising &= ~(ADVERTISED_10baseT_Half | - ADVERTISED_100baseT_Half); - } + spin_lock_irq(&np->lock); + err = mii_ethtool_gset(&np->mii_if, cmd); + spin_unlock_irq(&np->lock); - ecmd->autoneg = AUTONEG_ENABLE; - return 0; + /* The PHY may support 1000baseT, but the Etrax100 does not. */ + cmd->supported &= ~(SUPPORTED_1000baseT_Half + | SUPPORTED_1000baseT_Full); + return err; } static int e100_set_settings(struct net_device *dev, @@ -1560,7 +1672,8 @@ static const struct ethtool_ops e100_ethtool_ops = { static int e100_set_config(struct net_device *dev, struct ifmap *map) { - struct net_local *np = (struct net_local *)dev->priv; + struct net_local *np = netdev_priv(dev); + spin_lock(&np->lock); /* Preempt protection */ switch(map->port) { @@ -1612,7 +1725,6 @@ update_tx_stats(struct net_device_stats *es) es->collisions += IO_EXTRACT(R_TR_COUNTERS, single_col, r) + IO_EXTRACT(R_TR_COUNTERS, multiple_col, r); - es->tx_errors += IO_EXTRACT(R_TR_COUNTERS, deferred, r); } /* @@ -1622,8 +1734,9 @@ update_tx_stats(struct net_device_stats *es) static struct net_device_stats * e100_get_stats(struct net_device *dev) { - struct net_local *lp = (struct net_local *)dev->priv; + struct net_local *lp = netdev_priv(dev); unsigned long flags; + spin_lock_irqsave(&lp->lock, flags); update_rx_stats(&lp->stats); @@ -1643,13 +1756,13 @@ e100_get_stats(struct net_device *dev) static void set_multicast_list(struct net_device *dev) { - struct net_local *lp = (struct net_local *)dev->priv; + struct net_local *lp = netdev_priv(dev); int num_addr = dev->mc_count; unsigned long int lo_bits; unsigned long int hi_bits; + spin_lock(&lp->lock); - if (dev->flags & IFF_PROMISC) - { + if (dev->flags & IFF_PROMISC) { /* promiscuous mode */ lo_bits = 0xfffffffful; hi_bits = 0xfffffffful; @@ -1679,9 +1792,10 @@ set_multicast_list(struct net_device *dev) struct dev_mc_list *dmi = dev->mc_list; int i; char *baddr; + lo_bits = 0x00000000ul; hi_bits = 0x00000000ul; - for (i=0; i<num_addr; i++) { + for (i = 0; i < num_addr; i++) { /* Calculate the hash index for the GA registers */ hash_ix = 0; @@ -1708,8 +1822,7 @@ set_multicast_list(struct net_device *dev) if (hash_ix >= 32) { hi_bits |= (1 << (hash_ix-32)); - } - else { + } else { lo_bits |= (1 << hash_ix); } dmi = dmi->next; @@ -1724,10 +1837,11 @@ set_multicast_list(struct net_device *dev) } void -e100_hardware_send_packet(char *buf, int length) +e100_hardware_send_packet(struct net_local *np, char *buf, int length) { D(printk("e100 send pack, buf 0x%x len %d\n", buf, length)); + spin_lock(&np->led_lock); if (!led_active && time_after(jiffies, led_next_time)) { /* light the network leds depending on the current speed. */ e100_set_network_leds(NETWORK_ACTIVITY); @@ -1737,6 +1851,7 @@ e100_hardware_send_packet(char *buf, int length) led_active = 1; mod_timer(&clear_led_timer, jiffies + HZ/10); } + spin_unlock(&np->led_lock); /* configure the tx dma descriptor */ myNextTxDesc->descr.sw_len = length; @@ -1754,6 +1869,11 @@ e100_hardware_send_packet(char *buf, int length) static void e100_clear_network_leds(unsigned long dummy) { + struct net_device *dev = (struct net_device *)dummy; + struct net_local *np = netdev_priv(dev); + + spin_lock(&np->led_lock); + if (led_active && time_after(jiffies, led_next_time)) { e100_set_network_leds(NO_NETWORK_ACTIVITY); @@ -1761,6 +1881,8 @@ e100_clear_network_leds(unsigned long dummy) led_next_time = jiffies + NET_FLASH_PAUSE; led_active = 0; } + + spin_unlock(&np->led_lock); } static void @@ -1781,19 +1903,25 @@ e100_set_network_leds(int active) #else LED_NETWORK_SET(LED_OFF); #endif - } - else if (light_leds) { + } else if (light_leds) { if (current_speed == 10) { LED_NETWORK_SET(LED_ORANGE); } else { LED_NETWORK_SET(LED_GREEN); } - } - else { + } else { LED_NETWORK_SET(LED_OFF); } } +#ifdef CONFIG_NET_POLL_CONTROLLER +static void +e100_netpoll(struct net_device* netdev) +{ + e100rxtx_interrupt(NETWORK_DMA_TX_IRQ_NBR, netdev, NULL); +} +#endif + static int etrax_init_module(void) { diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 72deff0d4d90..4f37506ad374 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -3942,7 +3942,7 @@ e1000_clean(struct napi_struct *napi, int budget) &work_done, budget); /* If no Tx and not enough Rx work done, exit the polling mode */ - if ((!tx_cleaned && (work_done < budget)) || + if ((!tx_cleaned && (work_done == 0)) || !netif_running(poll_dev)) { quit_polling: if (likely(adapter->itr_setting & 3)) @@ -4804,6 +4804,7 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) spin_unlock_irqrestore(&adapter->stats_lock, flags); return -EIO; } + spin_unlock_irqrestore(&adapter->stats_lock, flags); if (adapter->hw.media_type == e1000_media_type_copper) { switch (data->reg_num) { case PHY_CTRL: @@ -4824,12 +4825,8 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) DUPLEX_HALF; retval = e1000_set_spd_dplx(adapter, spddplx); - if (retval) { - spin_unlock_irqrestore( - &adapter->stats_lock, - flags); + if (retval) return retval; - } } if (netif_running(adapter->netdev)) e1000_reinit_locked(adapter); @@ -4838,11 +4835,8 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) break; case M88E1000_PHY_SPEC_CTRL: case M88E1000_EXT_PHY_SPEC_CTRL: - if (e1000_phy_reset(&adapter->hw)) { - spin_unlock_irqrestore( - &adapter->stats_lock, flags); + if (e1000_phy_reset(&adapter->hw)) return -EIO; - } break; } } else { @@ -4857,7 +4851,6 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) break; } } - spin_unlock_irqrestore(&adapter->stats_lock, flags); break; default: return -EOPNOTSUPP; diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index f78e5bf7cb33..5f82a4647eee 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -40,7 +40,7 @@ #include <asm/io.h> #define DRV_NAME "ehea" -#define DRV_VERSION "EHEA_0080" +#define DRV_VERSION "EHEA_0083" /* eHEA capability flags */ #define DLPAR_PORT_ADD_REM 1 diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index f0319f1e8e05..869e1604b16e 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -136,7 +136,7 @@ static struct net_device_stats *ehea_get_stats(struct net_device *dev) struct ehea_port *port = netdev_priv(dev); struct net_device_stats *stats = &port->stats; struct hcp_ehea_port_cb2 *cb2; - u64 hret, rx_packets; + u64 hret, rx_packets, tx_packets; int i; memset(stats, 0, sizeof(*stats)); @@ -162,7 +162,11 @@ static struct net_device_stats *ehea_get_stats(struct net_device *dev) for (i = 0; i < port->num_def_qps; i++) rx_packets += port->port_res[i].rx_packets; - stats->tx_packets = cb2->txucp + cb2->txmcp + cb2->txbcp; + tx_packets = 0; + for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) + tx_packets += port->port_res[i].tx_packets; + + stats->tx_packets = tx_packets; stats->multicast = cb2->rxmcp; stats->rx_errors = cb2->rxuerr; stats->rx_bytes = cb2->rxo; @@ -406,11 +410,6 @@ static int ehea_treat_poll_error(struct ehea_port_res *pr, int rq, if (cqe->status & EHEA_CQE_STAT_ERR_CRC) pr->p_stats.err_frame_crc++; - if (netif_msg_rx_err(pr->port)) { - ehea_error("CQE Error for QP %d", pr->qp->init_attr.qp_nr); - ehea_dump(cqe, sizeof(*cqe), "CQE"); - } - if (rq == 2) { *processed_rq2 += 1; skb = get_skb_by_index(pr->rq2_skba.arr, pr->rq2_skba.len, cqe); @@ -422,7 +421,11 @@ static int ehea_treat_poll_error(struct ehea_port_res *pr, int rq, } if (cqe->status & EHEA_CQE_STAT_FAT_ERR_MASK) { - ehea_error("Critical receive error. Resetting port."); + if (netif_msg_rx_err(pr->port)) { + ehea_error("Critical receive error for QP %d. " + "Resetting port.", pr->qp->init_attr.qp_nr); + ehea_dump(cqe, sizeof(*cqe), "CQE"); + } schedule_work(&pr->port->reset_task); return 1; } @@ -2000,6 +2003,7 @@ static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev) } ehea_post_swqe(pr->qp, swqe); + pr->tx_packets++; if (unlikely(atomic_read(&pr->swqe_avail) <= 1)) { spin_lock_irqsave(&pr->netif_queue, flags); diff --git a/drivers/net/ehea/ehea_qmr.h b/drivers/net/ehea/ehea_qmr.h index 562de0ebdd85..bc62d389c166 100644 --- a/drivers/net/ehea/ehea_qmr.h +++ b/drivers/net/ehea/ehea_qmr.h @@ -145,8 +145,8 @@ struct ehea_rwqe { #define EHEA_CQE_VLAN_TAG_XTRACT 0x0400 #define EHEA_CQE_TYPE_RQ 0x60 -#define EHEA_CQE_STAT_ERR_MASK 0x720F -#define EHEA_CQE_STAT_FAT_ERR_MASK 0x1F +#define EHEA_CQE_STAT_ERR_MASK 0x700F +#define EHEA_CQE_STAT_FAT_ERR_MASK 0xF #define EHEA_CQE_STAT_ERR_TCP 0x4000 #define EHEA_CQE_STAT_ERR_IP 0x2000 #define EHEA_CQE_STAT_ERR_CRC 0x1000 diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c index a8a0ee220da6..bf5a7caa5b52 100644 --- a/drivers/net/fec_mpc52xx.c +++ b/drivers/net/fec_mpc52xx.c @@ -971,6 +971,8 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match) mpc52xx_fec_reset_stats(ndev); + SET_NETDEV_DEV(ndev, &op->dev); + /* Register the new network device */ rv = register_netdev(ndev); if (rv < 0) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 92ce2e38f0d5..a96583cceb5e 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -5286,19 +5286,15 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i if (readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_PHY_INIT) { np->mac_in_use = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_MGMT_ST; dprintk(KERN_INFO "%s: mgmt unit is running. mac in use %x.\n", pci_name(pci_dev), np->mac_in_use); - for (i = 0; i < 5000; i++) { - msleep(1); - if (nv_mgmt_acquire_sema(dev)) { - /* management unit setup the phy already? */ - if ((readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK) == - NVREG_XMITCTL_SYNC_PHY_INIT) { - /* phy is inited by mgmt unit */ - phyinitialized = 1; - dprintk(KERN_INFO "%s: Phy already initialized by mgmt unit.\n", pci_name(pci_dev)); - } else { - /* we need to init the phy */ - } - break; + if (nv_mgmt_acquire_sema(dev)) { + /* management unit setup the phy already? */ + if ((readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK) == + NVREG_XMITCTL_SYNC_PHY_INIT) { + /* phy is inited by mgmt unit */ + phyinitialized = 1; + dprintk(KERN_INFO "%s: Phy already initialized by mgmt unit.\n", pci_name(pci_dev)); + } else { + /* we need to init the phy */ } } } @@ -5613,6 +5609,22 @@ static struct pci_device_id pci_tbl[] = { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_35), .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, + { /* MCP79 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_36), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + }, + { /* MCP79 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_37), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + }, + { /* MCP79 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_38), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + }, + { /* MCP79 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_39), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + }, {0,}, }; diff --git a/drivers/net/fs_enet/Kconfig b/drivers/net/fs_enet/Kconfig index 2765e49e07df..562ea68ed99b 100644 --- a/drivers/net/fs_enet/Kconfig +++ b/drivers/net/fs_enet/Kconfig @@ -2,6 +2,7 @@ config FS_ENET tristate "Freescale Ethernet Driver" depends on CPM1 || CPM2 select MII + select PHYLIB config FS_ENET_HAS_SCC bool "Chip has an SCC usable for ethernet" @@ -11,11 +12,19 @@ config FS_ENET_HAS_SCC config FS_ENET_HAS_FCC bool "Chip has an FCC usable for ethernet" depends on FS_ENET && CPM2 - select MDIO_BITBANG default y config FS_ENET_HAS_FEC bool "Chip has an FEC usable for ethernet" depends on FS_ENET && CPM1 + select FS_ENET_MDIO_FEC default y +config FS_ENET_MDIO_FEC + tristate "MDIO driver for FEC" + depends on FS_ENET && CPM1 + +config FS_ENET_MDIO_FCC + tristate "MDIO driver for FCC" + depends on FS_ENET && CPM2 + select MDIO_BITBANG diff --git a/drivers/net/fs_enet/Makefile b/drivers/net/fs_enet/Makefile index 02d4dc18ba69..1ffbe0756a0c 100644 --- a/drivers/net/fs_enet/Makefile +++ b/drivers/net/fs_enet/Makefile @@ -4,7 +4,16 @@ obj-$(CONFIG_FS_ENET) += fs_enet.o -obj-$(CONFIG_8xx) += mac-fec.o mac-scc.o mii-fec.o -obj-$(CONFIG_CPM2) += mac-fcc.o mii-bitbang.o +fs_enet-$(CONFIG_FS_ENET_HAS_SCC) += mac-scc.o +fs_enet-$(CONFIG_FS_ENET_HAS_FEC) += mac-fec.o +fs_enet-$(CONFIG_FS_ENET_HAS_FCC) += mac-fcc.o -fs_enet-objs := fs_enet-main.o +ifeq ($(CONFIG_PPC_CPM_NEW_BINDING),y) +obj-$(CONFIG_FS_ENET_MDIO_FEC) += mii-fec.o +obj-$(CONFIG_FS_ENET_MDIO_FCC) += mii-bitbang.o +else +fs_enet-$(CONFIG_FS_ENET_MDIO_FEC) += mii-fec.o +fs_enet-$(CONFIG_FS_ENET_MDIO_FCC) += mii-bitbang.o +endif + +fs_enet-objs := fs_enet-main.o $(fs_enet-m) diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index e0119f6a3319..580cb4ab2af1 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -762,26 +762,20 @@ static int sixpack_ioctl(struct tty_struct *tty, struct file *file, if (copy_from_user(&addr, (void __user *) arg, AX25_ADDR_LEN)) { - err = -EFAULT; - break; - } + err = -EFAULT; + break; + } - netif_tx_lock_bh(dev); - memcpy(dev->dev_addr, &addr, AX25_ADDR_LEN); - netif_tx_unlock_bh(dev); + netif_tx_lock_bh(dev); + memcpy(dev->dev_addr, &addr, AX25_ADDR_LEN); + netif_tx_unlock_bh(dev); - err = 0; - break; - } - - /* Allow stty to read, but not set, the serial port */ - case TCGETS: - case TCGETA: - err = n_tty_ioctl(tty, (struct file *) file, cmd, arg); - break; + err = 0; + break; + } default: - err = -ENOIOCTLCMD; + err = tty_mode_ioctl(tty, file, cmd, arg); } sp_put(sp); diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index 0de3aa2a2e44..eb0718b441bb 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c @@ -642,9 +642,11 @@ static void emac_reset_work(struct work_struct *work) DBG(dev, "reset_work" NL); mutex_lock(&dev->link_lock); - emac_netif_stop(dev); - emac_full_tx_reset(dev); - emac_netif_start(dev); + if (dev->opened) { + emac_netif_stop(dev); + emac_full_tx_reset(dev); + emac_netif_start(dev); + } mutex_unlock(&dev->link_lock); } @@ -1063,10 +1065,9 @@ static int emac_open(struct net_device *ndev) dev->rx_sg_skb = NULL; mutex_lock(&dev->link_lock); + dev->opened = 1; - /* XXX Start PHY polling now. Shouldn't wr do like sungem instead and - * always poll the PHY even when the iface is down ? That would allow - * things like laptop-net to work. --BenH + /* Start PHY polling now. */ if (dev->phy.address >= 0) { int link_poll_interval; @@ -1145,9 +1146,11 @@ static void emac_link_timer(struct work_struct *work) int link_poll_interval; mutex_lock(&dev->link_lock); - DBG2(dev, "link timer" NL); + if (!dev->opened) + goto bail; + if (dev->phy.def->ops->poll_link(&dev->phy)) { if (!netif_carrier_ok(dev->ndev)) { /* Get new link parameters */ @@ -1170,13 +1173,14 @@ static void emac_link_timer(struct work_struct *work) link_poll_interval = PHY_POLL_LINK_OFF; } schedule_delayed_work(&dev->link_work, link_poll_interval); - + bail: mutex_unlock(&dev->link_lock); } static void emac_force_link_update(struct emac_instance *dev) { netif_carrier_off(dev->ndev); + smp_rmb(); if (dev->link_polling) { cancel_rearming_delayed_work(&dev->link_work); if (dev->link_polling) @@ -1191,11 +1195,14 @@ static int emac_close(struct net_device *ndev) DBG(dev, "close" NL); - if (dev->phy.address >= 0) + if (dev->phy.address >= 0) { + dev->link_polling = 0; cancel_rearming_delayed_work(&dev->link_work); - + } + mutex_lock(&dev->link_lock); emac_netif_stop(dev); - flush_scheduled_work(); + dev->opened = 0; + mutex_unlock(&dev->link_lock); emac_rx_disable(dev); emac_tx_disable(dev); @@ -2756,6 +2763,8 @@ static int __devexit emac_remove(struct of_device *ofdev) unregister_netdev(dev->ndev); + flush_scheduled_work(); + if (emac_has_feature(dev, EMAC_FTR_HAS_TAH)) tah_detach(dev->tah_dev, dev->tah_port); if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII)) diff --git a/drivers/net/ibm_newemac/core.h b/drivers/net/ibm_newemac/core.h index 4011803117ca..a010b2463fd9 100644 --- a/drivers/net/ibm_newemac/core.h +++ b/drivers/net/ibm_newemac/core.h @@ -258,6 +258,7 @@ struct emac_instance { int stop_timeout; /* in us */ int no_mcast; int mcast_pending; + int opened; struct work_struct reset_work; spinlock_t lock; }; diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c index 2c6f7be36e8a..fc753d7f674e 100644 --- a/drivers/net/irda/irtty-sir.c +++ b/drivers/net/irda/irtty-sir.c @@ -434,11 +434,6 @@ static int irtty_ioctl(struct tty_struct *tty, struct file *file, unsigned int c IRDA_ASSERT(dev != NULL, return -1;); switch (cmd) { - case TCGETS: - case TCGETA: - err = n_tty_ioctl(tty, file, cmd, arg); - break; - case IRTTY_IOCTDONGLE: /* this call blocks for completion */ err = sirdev_set_dongle(dev, (IRDA_DONGLE) arg); @@ -454,7 +449,7 @@ static int irtty_ioctl(struct tty_struct *tty, struct file *file, unsigned int c err = -EFAULT; break; default: - err = -ENOIOCTLCMD; + err = tty_mode_ioctl(tty, file, cmd, arg); break; } return err; diff --git a/drivers/net/lib82596.c b/drivers/net/lib82596.c index 9a855e512147..b59f442bbf36 100644 --- a/drivers/net/lib82596.c +++ b/drivers/net/lib82596.c @@ -176,8 +176,8 @@ struct i596_reg { struct i596_tbd { unsigned short size; unsigned short pad; - dma_addr_t next; - dma_addr_t data; + u32 next; + u32 data; u32 cache_pad[5]; /* Total 32 bytes... */ }; @@ -195,12 +195,12 @@ struct i596_cmd { struct i596_cmd *v_next; /* Address from CPUs viewpoint */ unsigned short status; unsigned short command; - dma_addr_t b_next; /* Address from i596 viewpoint */ + u32 b_next; /* Address from i596 viewpoint */ }; struct tx_cmd { struct i596_cmd cmd; - dma_addr_t tbd; + u32 tbd; unsigned short size; unsigned short pad; struct sk_buff *skb; /* So we can free it after tx */ @@ -237,8 +237,8 @@ struct cf_cmd { struct i596_rfd { unsigned short stat; unsigned short cmd; - dma_addr_t b_next; /* Address from i596 viewpoint */ - dma_addr_t rbd; + u32 b_next; /* Address from i596 viewpoint */ + u32 rbd; unsigned short count; unsigned short size; struct i596_rfd *v_next; /* Address from CPUs viewpoint */ @@ -249,18 +249,18 @@ struct i596_rfd { }; struct i596_rbd { - /* hardware data */ - unsigned short count; - unsigned short zero1; - dma_addr_t b_next; - dma_addr_t b_data; /* Address from i596 viewpoint */ - unsigned short size; - unsigned short zero2; - /* driver data */ - struct sk_buff *skb; - struct i596_rbd *v_next; - dma_addr_t b_addr; /* This rbd addr from i596 view */ - unsigned char *v_data; /* Address from CPUs viewpoint */ + /* hardware data */ + unsigned short count; + unsigned short zero1; + u32 b_next; + u32 b_data; /* Address from i596 viewpoint */ + unsigned short size; + unsigned short zero2; + /* driver data */ + struct sk_buff *skb; + struct i596_rbd *v_next; + u32 b_addr; /* This rbd addr from i596 view */ + unsigned char *v_data; /* Address from CPUs viewpoint */ /* Total 32 bytes... */ #ifdef __LP64__ u32 cache_pad[4]; @@ -275,8 +275,8 @@ struct i596_rbd { struct i596_scb { unsigned short status; unsigned short command; - dma_addr_t cmd; - dma_addr_t rfd; + u32 cmd; + u32 rfd; u32 crc_err; u32 align_err; u32 resource_err; @@ -288,14 +288,14 @@ struct i596_scb { }; struct i596_iscp { - u32 stat; - dma_addr_t scb; + u32 stat; + u32 scb; }; struct i596_scp { - u32 sysbus; - u32 pad; - dma_addr_t iscp; + u32 sysbus; + u32 pad; + u32 iscp; }; struct i596_dma { diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 45f30a2974b8..662b8d16803c 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -284,7 +284,7 @@ static __net_exit void loopback_net_exit(struct net *net) unregister_netdev(dev); } -static struct pernet_operations loopback_net_ops = { +static struct pernet_operations __net_initdata loopback_net_ops = { .init = loopback_net_init, .exit = loopback_net_exit, }; diff --git a/drivers/net/mlx4/alloc.c b/drivers/net/mlx4/alloc.c index f8d63d39f592..b226e019bc8b 100644 --- a/drivers/net/mlx4/alloc.c +++ b/drivers/net/mlx4/alloc.c @@ -171,9 +171,10 @@ void mlx4_buf_free(struct mlx4_dev *dev, int size, struct mlx4_buf *buf) buf->u.direct.map); else { for (i = 0; i < buf->nbufs; ++i) - dma_free_coherent(&dev->pdev->dev, PAGE_SIZE, - buf->u.page_list[i].buf, - buf->u.page_list[i].map); + if (buf->u.page_list[i].buf) + dma_free_coherent(&dev->pdev->dev, PAGE_SIZE, + buf->u.page_list[i].buf, + buf->u.page_list[i].map); kfree(buf->u.page_list); } } diff --git a/drivers/net/mlx4/qp.c b/drivers/net/mlx4/qp.c index cc4b1be18219..fa24e6597591 100644 --- a/drivers/net/mlx4/qp.c +++ b/drivers/net/mlx4/qp.c @@ -113,7 +113,7 @@ int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt, struct mlx4_cmd_mailbox *mailbox; int ret = 0; - if (cur_state >= MLX4_QP_NUM_STATE || cur_state >= MLX4_QP_NUM_STATE || + if (cur_state >= MLX4_QP_NUM_STATE || new_state >= MLX4_QP_NUM_STATE || !op[cur_state][new_state]) return -EINVAL; @@ -240,7 +240,7 @@ void mlx4_qp_free(struct mlx4_dev *dev, struct mlx4_qp *qp) mlx4_table_put(dev, &qp_table->auxc_table, qp->qpn); mlx4_table_put(dev, &qp_table->qp_table, qp->qpn); - if (qp->qpn < dev->caps.sqp_start + 8) + if (qp->qpn >= dev->caps.sqp_start + 8) mlx4_bitmap_free(&qp_table->bitmap, qp->qpn); } EXPORT_SYMBOL_GPL(mlx4_qp_free); diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index 8d29319cc5cb..656a260fc956 100644 --- a/drivers/net/myri_sbus.c +++ b/drivers/net/myri_sbus.c @@ -134,7 +134,7 @@ static int myri_do_handshake(struct myri_eth *mp) myri_disable_irq(mp->lregs, cregs); - while (tick++ <= 25) { + while (tick++ < 25) { u32 softstate; /* Wake it up. */ diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c index eb0aff787dfd..5267e031daa0 100644 --- a/drivers/net/netx-eth.c +++ b/drivers/net/netx-eth.c @@ -128,8 +128,8 @@ netx_eth_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev) FIFO_PTR_FRAMELEN(len)); ndev->trans_start = jiffies; - dev->stats.tx_packets++; - dev->stats.tx_bytes += skb->len; + ndev->stats.tx_packets++; + ndev->stats.tx_bytes += skb->len; netif_stop_queue(ndev); spin_unlock_irq(&priv->lock); @@ -155,7 +155,7 @@ static void netx_eth_receive(struct net_device *ndev) if (unlikely(skb == NULL)) { printk(KERN_NOTICE "%s: Low memory, packet dropped.\n", ndev->name); - dev->stats.rx_dropped++; + ndev->stats.rx_dropped++; return; } diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c index ab4d309a858f..09b4fde8d924 100644 --- a/drivers/net/pasemi_mac.c +++ b/drivers/net/pasemi_mac.c @@ -580,6 +580,16 @@ static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit) len = (macrx & XCT_MACRX_LLEN_M) >> XCT_MACRX_LLEN_S; + pci_unmap_single(mac->dma_pdev, dma, len, PCI_DMA_FROMDEVICE); + + if (macrx & XCT_MACRX_CRC) { + /* CRC error flagged */ + mac->netdev->stats.rx_errors++; + mac->netdev->stats.rx_crc_errors++; + dev_kfree_skb_irq(skb); + goto next; + } + if (len < 256) { struct sk_buff *new_skb; @@ -595,11 +605,10 @@ static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit) } else info->skb = NULL; - pci_unmap_single(mac->dma_pdev, dma, len, PCI_DMA_FROMDEVICE); - info->dma = 0; - skb_put(skb, len); + /* Don't include CRC */ + skb_put(skb, len-4); if (likely((macrx & XCT_MACRX_HTY_M) == XCT_MACRX_HTY_IPV4_OK)) { skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -614,6 +623,7 @@ static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit) skb->protocol = eth_type_trans(skb, mac->netdev); netif_receive_skb(skb); +next: RX_RING(mac, n) = 0; RX_RING(mac, n+1) = 0; @@ -1126,7 +1136,7 @@ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev) unsigned long flags; int i, nfrags; - dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_SS | XCT_MACTX_CRC_PAD; + dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_CRC_PAD; if (skb->ip_summed == CHECKSUM_PARTIAL) { const unsigned char *nh = skb_network_header(skb); diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 035fd41fb61f..f0574073a2a3 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -143,21 +143,29 @@ static int m88e1111_config_init(struct phy_device *phydev) int err; if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || - (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)) { + (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || + (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) || + (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) { int temp; - if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { - temp = phy_read(phydev, MII_M1111_PHY_EXT_CR); - if (temp < 0) - return temp; + temp = phy_read(phydev, MII_M1111_PHY_EXT_CR); + if (temp < 0) + return temp; + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY); - - err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp); - if (err < 0) - return err; + } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { + temp &= ~MII_M1111_TX_DELAY; + temp |= MII_M1111_RX_DELAY; + } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { + temp &= ~MII_M1111_RX_DELAY; + temp |= MII_M1111_TX_DELAY; } + err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp); + if (err < 0) + return err; + temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); if (temp < 0) return temp; diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 9bc11773705b..7c9e6e349503 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -406,6 +406,9 @@ int phy_mii_ioctl(struct phy_device *phydev, && phydev->drv->config_init) phydev->drv->config_init(phydev); break; + + default: + return -ENOTTY; } return 0; diff --git a/drivers/net/plip.c b/drivers/net/plip.c index 5071fcd8a0bd..57c98669984d 100644 --- a/drivers/net/plip.c +++ b/drivers/net/plip.c @@ -663,7 +663,7 @@ plip_receive_packet(struct net_device *dev, struct net_local *nl, case PLIP_PK_DONE: /* Inform the upper layer for the arrival of a packet. */ rcv->skb->protocol=plip_type_trans(rcv->skb, dev); - netif_rx(rcv->skb); + netif_rx_ni(rcv->skb); dev->last_rx = jiffies; dev->stats.rx_bytes += rcv->length.h; dev->stats.rx_packets++; @@ -1269,7 +1269,7 @@ static void plip_attach (struct parport *port) nl = netdev_priv(dev); nl->dev = dev; - nl->pardev = parport_register_device(port, name, plip_preempt, + nl->pardev = parport_register_device(port, dev->name, plip_preempt, plip_wakeup, plip_interrupt, 0, dev); diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c index 27f5b904f48e..f023d5b67e6e 100644 --- a/drivers/net/ppp_async.c +++ b/drivers/net/ppp_async.c @@ -160,7 +160,7 @@ ppp_asynctty_open(struct tty_struct *tty) err = -ENOMEM; ap = kzalloc(sizeof(*ap), GFP_KERNEL); - if (ap == 0) + if (!ap) goto out; /* initialize the asyncppp structure */ @@ -215,7 +215,7 @@ ppp_asynctty_close(struct tty_struct *tty) ap = tty->disc_data; tty->disc_data = NULL; write_unlock_irq(&disc_data_lock); - if (ap == 0) + if (!ap) return; /* @@ -230,10 +230,10 @@ ppp_asynctty_close(struct tty_struct *tty) tasklet_kill(&ap->tsk); ppp_unregister_channel(&ap->chan); - if (ap->rpkt != 0) + if (ap->rpkt) kfree_skb(ap->rpkt); skb_queue_purge(&ap->rqueue); - if (ap->tpkt != 0) + if (ap->tpkt) kfree_skb(ap->tpkt); kfree(ap); } @@ -285,13 +285,13 @@ ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file, int err, val; int __user *p = (int __user *)arg; - if (ap == 0) + if (!ap) return -ENXIO; err = -EFAULT; switch (cmd) { case PPPIOCGCHAN: err = -ENXIO; - if (ap == 0) + if (!ap) break; err = -EFAULT; if (put_user(ppp_channel_index(&ap->chan), p)) @@ -301,7 +301,7 @@ ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file, case PPPIOCGUNIT: err = -ENXIO; - if (ap == 0) + if (!ap) break; err = -EFAULT; if (put_user(ppp_unit_number(&ap->chan), p)) @@ -309,16 +309,11 @@ ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file, err = 0; break; - case TCGETS: - case TCGETA: - err = n_tty_ioctl(tty, file, cmd, arg); - break; - case TCFLSH: /* flush our buffers and the serial port's buffer */ if (arg == TCIOFLUSH || arg == TCOFLUSH) ppp_async_flush_output(ap); - err = n_tty_ioctl(tty, file, cmd, arg); + err = tty_perform_flush(tty, arg); break; case FIONREAD: @@ -329,7 +324,8 @@ ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file, break; default: - err = -ENOIOCTLCMD; + /* Try the various mode ioctls */ + err = tty_mode_ioctl(tty, file, cmd, arg); } ap_put(ap); @@ -354,7 +350,7 @@ ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf, struct asyncppp *ap = ap_get(tty); unsigned long flags; - if (ap == 0) + if (!ap) return; spin_lock_irqsave(&ap->recv_lock, flags); ppp_async_input(ap, buf, cflags, count); @@ -373,7 +369,7 @@ ppp_asynctty_wakeup(struct tty_struct *tty) struct asyncppp *ap = ap_get(tty); clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - if (ap == 0) + if (!ap) return; set_bit(XMIT_WAKEUP, &ap->xmit_flags); tasklet_schedule(&ap->tsk); @@ -688,7 +684,7 @@ ppp_async_push(struct asyncppp *ap) tty_stuffed = 1; continue; } - if (ap->optr >= ap->olim && ap->tpkt != 0) { + if (ap->optr >= ap->olim && ap->tpkt) { if (ppp_async_encode(ap)) { /* finished processing ap->tpkt */ clear_bit(XMIT_FULL, &ap->xmit_flags); @@ -708,7 +704,7 @@ ppp_async_push(struct asyncppp *ap) clear_bit(XMIT_BUSY, &ap->xmit_flags); /* any more work to do? if not, exit the loop */ if (!(test_bit(XMIT_WAKEUP, &ap->xmit_flags) - || (!tty_stuffed && ap->tpkt != 0))) + || (!tty_stuffed && ap->tpkt))) break; /* more work to do, see if we can do it now */ if (test_and_set_bit(XMIT_BUSY, &ap->xmit_flags)) @@ -719,7 +715,7 @@ ppp_async_push(struct asyncppp *ap) flush: clear_bit(XMIT_BUSY, &ap->xmit_flags); - if (ap->tpkt != 0) { + if (ap->tpkt) { kfree_skb(ap->tpkt); ap->tpkt = NULL; clear_bit(XMIT_FULL, &ap->xmit_flags); @@ -852,7 +848,7 @@ ppp_async_input(struct asyncppp *ap, const unsigned char *buf, s = 0; for (i = 0; i < count; ++i) { c = buf[i]; - if (flags != 0 && flags[i] != 0) + if (flags && flags[i] != 0) continue; s |= (c & 0x80)? SC_RCV_B7_1: SC_RCV_B7_0; c = ((c >> 4) ^ c) & 0xf; @@ -869,7 +865,7 @@ ppp_async_input(struct asyncppp *ap, const unsigned char *buf, n = scan_ordinary(ap, buf, count); f = 0; - if (flags != 0 && (ap->state & SC_TOSS) == 0) { + if (flags && (ap->state & SC_TOSS) == 0) { /* check the flags to see if any char had an error */ for (j = 0; j < n; ++j) if ((f = flags[j]) != 0) @@ -882,9 +878,9 @@ ppp_async_input(struct asyncppp *ap, const unsigned char *buf, } else if (n > 0 && (ap->state & SC_TOSS) == 0) { /* stuff the chars in the skb */ skb = ap->rpkt; - if (skb == 0) { + if (!skb) { skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2); - if (skb == 0) + if (!skb) goto nomem; ap->rpkt = skb; } @@ -931,7 +927,7 @@ ppp_async_input(struct asyncppp *ap, const unsigned char *buf, ++n; buf += n; - if (flags != 0) + if (flags) flags += n; count -= n; } diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 4b49d0e8c7eb..4f690378bb77 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -367,7 +367,7 @@ static int ppp_release(struct inode *inode, struct file *file) struct ppp_file *pf = file->private_data; struct ppp *ppp; - if (pf != 0) { + if (pf) { file->private_data = NULL; if (pf->kind == INTERFACE) { ppp = PF_TO_PPP(pf); @@ -398,7 +398,7 @@ static ssize_t ppp_read(struct file *file, char __user *buf, ret = count; - if (pf == 0) + if (!pf) return -ENXIO; add_wait_queue(&pf->rwait, &wait); for (;;) { @@ -431,7 +431,7 @@ static ssize_t ppp_read(struct file *file, char __user *buf, set_current_state(TASK_RUNNING); remove_wait_queue(&pf->rwait, &wait); - if (skb == 0) + if (!skb) goto out; ret = -EOVERFLOW; @@ -455,11 +455,11 @@ static ssize_t ppp_write(struct file *file, const char __user *buf, struct sk_buff *skb; ssize_t ret; - if (pf == 0) + if (!pf) return -ENXIO; ret = -ENOMEM; skb = alloc_skb(count + pf->hdrlen, GFP_KERNEL); - if (skb == 0) + if (!skb) goto out; skb_reserve(skb, pf->hdrlen); ret = -EFAULT; @@ -491,11 +491,11 @@ static unsigned int ppp_poll(struct file *file, poll_table *wait) struct ppp_file *pf = file->private_data; unsigned int mask; - if (pf == 0) + if (!pf) return 0; poll_wait(file, &pf->rwait, wait); mask = POLLOUT | POLLWRNORM; - if (skb_peek(&pf->rq) != 0) + if (skb_peek(&pf->rq)) mask |= POLLIN | POLLRDNORM; if (pf->dead) mask |= POLLHUP; @@ -559,7 +559,7 @@ static int ppp_ioctl(struct inode *inode, struct file *file, void __user *argp = (void __user *)arg; int __user *p = argp; - if (pf == 0) + if (!pf) return ppp_unattached_ioctl(pf, file, cmd, arg); if (cmd == PPPIOCDETACH) { @@ -689,13 +689,13 @@ static int ppp_ioctl(struct inode *inode, struct file *file, val &= 0xffff; } vj = slhc_init(val2+1, val+1); - if (vj == 0) { + if (!vj) { printk(KERN_ERR "PPP: no memory (VJ compressor)\n"); err = -ENOMEM; break; } ppp_lock(ppp); - if (ppp->vj != 0) + if (ppp->vj) slhc_free(ppp->vj); ppp->vj = vj; ppp_unlock(ppp); @@ -786,7 +786,7 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file, if (get_user(unit, p)) break; ppp = ppp_create_interface(unit, &err); - if (ppp == 0) + if (!ppp) break; file->private_data = &ppp->file; ppp->owner = file; @@ -803,7 +803,7 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file, mutex_lock(&all_ppp_mutex); err = -ENXIO; ppp = ppp_find_unit(unit); - if (ppp != 0) { + if (ppp) { atomic_inc(&ppp->file.refcnt); file->private_data = &ppp->file; err = 0; @@ -817,7 +817,7 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file, spin_lock_bh(&all_channels_lock); err = -ENXIO; chan = ppp_find_channel(unit); - if (chan != 0) { + if (chan) { atomic_inc(&chan->file.refcnt); file->private_data = &chan->file; err = 0; @@ -946,9 +946,9 @@ ppp_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case SIOCGPPPCSTATS: memset(&cstats, 0, sizeof(cstats)); - if (ppp->xc_state != 0) + if (ppp->xc_state) ppp->xcomp->comp_stat(ppp->xc_state, &cstats.c); - if (ppp->rc_state != 0) + if (ppp->rc_state) ppp->rcomp->decomp_stat(ppp->rc_state, &cstats.d); if (copy_to_user(addr, &cstats, sizeof(cstats))) break; @@ -993,14 +993,14 @@ ppp_xmit_process(struct ppp *ppp) struct sk_buff *skb; ppp_xmit_lock(ppp); - if (ppp->dev != 0) { + if (ppp->dev) { ppp_push(ppp); - while (ppp->xmit_pending == 0 - && (skb = skb_dequeue(&ppp->file.xq)) != 0) + while (!ppp->xmit_pending + && (skb = skb_dequeue(&ppp->file.xq))) ppp_send_frame(ppp, skb); /* If there's no work left to do, tell the core net code that we can accept some more. */ - if (ppp->xmit_pending == 0 && skb_peek(&ppp->file.xq) == 0) + if (!ppp->xmit_pending && !skb_peek(&ppp->file.xq)) netif_wake_queue(ppp->dev); } ppp_xmit_unlock(ppp); @@ -1100,12 +1100,12 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) switch (proto) { case PPP_IP: - if (ppp->vj == 0 || (ppp->flags & SC_COMP_TCP) == 0) + if (!ppp->vj || (ppp->flags & SC_COMP_TCP) == 0) break; /* try to do VJ TCP header compression */ new_skb = alloc_skb(skb->len + ppp->dev->hard_header_len - 2, GFP_ATOMIC); - if (new_skb == 0) { + if (!new_skb) { printk(KERN_ERR "PPP: no memory (VJ comp pkt)\n"); goto drop; } @@ -1140,7 +1140,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) } /* try to do packet compression */ - if ((ppp->xstate & SC_COMP_RUN) && ppp->xc_state != 0 + if ((ppp->xstate & SC_COMP_RUN) && ppp->xc_state && proto != PPP_LCP && proto != PPP_CCP) { if (!(ppp->flags & SC_CCP_UP) && (ppp->flags & SC_MUST_COMP)) { if (net_ratelimit()) @@ -1185,7 +1185,7 @@ ppp_push(struct ppp *ppp) struct channel *pch; struct sk_buff *skb = ppp->xmit_pending; - if (skb == 0) + if (!skb) return; list = &ppp->channels; @@ -1355,7 +1355,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) if (flen == len && nfree == 0) bits |= E; frag = alloc_skb(flen + hdrlen + (flen == 0), GFP_ATOMIC); - if (frag == 0) + if (!frag) goto noskb; q = skb_put(frag, flen + hdrlen); @@ -1425,7 +1425,7 @@ ppp_channel_push(struct channel *pch) struct ppp *ppp; spin_lock_bh(&pch->downl); - if (pch->chan != 0) { + if (pch->chan) { while (!skb_queue_empty(&pch->file.xq)) { skb = skb_dequeue(&pch->file.xq); if (!pch->chan->ops->start_xmit(pch->chan, skb)) { @@ -1443,7 +1443,7 @@ ppp_channel_push(struct channel *pch) if (skb_queue_empty(&pch->file.xq)) { read_lock_bh(&pch->upl); ppp = pch->ppp; - if (ppp != 0) + if (ppp) ppp_xmit_process(ppp); read_unlock_bh(&pch->upl); } @@ -1462,7 +1462,7 @@ ppp_do_recv(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) { ppp_recv_lock(ppp); /* ppp->dev == 0 means interface is closing down */ - if (ppp->dev != 0) + if (ppp->dev) ppp_receive_frame(ppp, skb, pch); else kfree_skb(skb); @@ -1475,19 +1475,19 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb) struct channel *pch = chan->ppp; int proto; - if (pch == 0 || skb->len == 0) { + if (!pch || skb->len == 0) { kfree_skb(skb); return; } proto = PPP_PROTO(skb); read_lock_bh(&pch->upl); - if (pch->ppp == 0 || proto >= 0xc000 || proto == PPP_CCPFRAG) { + if (!pch->ppp || proto >= 0xc000 || proto == PPP_CCPFRAG) { /* put it on the channel queue */ skb_queue_tail(&pch->file.rq, skb); /* drop old frames if queue too long */ while (pch->file.rq.qlen > PPP_MAX_RQLEN - && (skb = skb_dequeue(&pch->file.rq)) != 0) + && (skb = skb_dequeue(&pch->file.rq))) kfree_skb(skb); wake_up_interruptible(&pch->file.rwait); } else { @@ -1503,13 +1503,13 @@ ppp_input_error(struct ppp_channel *chan, int code) struct channel *pch = chan->ppp; struct sk_buff *skb; - if (pch == 0) + if (!pch) return; read_lock_bh(&pch->upl); - if (pch->ppp != 0) { + if (pch->ppp) { skb = alloc_skb(0, GFP_ATOMIC); - if (skb != 0) { + if (skb) { skb->len = 0; /* probably unnecessary */ skb->cb[0] = code; ppp_do_recv(pch->ppp, skb, pch); @@ -1548,7 +1548,7 @@ static void ppp_receive_error(struct ppp *ppp) { ++ppp->stats.rx_errors; - if (ppp->vj != 0) + if (ppp->vj) slhc_toss(ppp->vj); } @@ -1563,7 +1563,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) * Note that some decompressors need to see uncompressed frames * that come in as well as compressed frames. */ - if (ppp->rc_state != 0 && (ppp->rstate & SC_DECOMP_RUN) + if (ppp->rc_state && (ppp->rstate & SC_DECOMP_RUN) && (ppp->rstate & (SC_DC_FERROR | SC_DC_ERROR)) == 0) skb = ppp_decompress_frame(ppp, skb); @@ -1574,13 +1574,13 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) switch (proto) { case PPP_VJC_COMP: /* decompress VJ compressed packets */ - if (ppp->vj == 0 || (ppp->flags & SC_REJ_COMP_TCP)) + if (!ppp->vj || (ppp->flags & SC_REJ_COMP_TCP)) goto err; if (skb_tailroom(skb) < 124 || skb_cloned(skb)) { /* copy to a new sk_buff with more tailroom */ ns = dev_alloc_skb(skb->len + 128); - if (ns == 0) { + if (!ns) { printk(KERN_ERR"PPP: no memory (VJ decomp)\n"); goto err; } @@ -1606,7 +1606,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) break; case PPP_VJC_UNCOMP: - if (ppp->vj == 0 || (ppp->flags & SC_REJ_COMP_TCP)) + if (!ppp->vj || (ppp->flags & SC_REJ_COMP_TCP)) goto err; /* Until we fix the decompressor need to make sure @@ -1636,7 +1636,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) skb_queue_tail(&ppp->file.rq, skb); /* limit queue length by dropping old frames */ while (ppp->file.rq.qlen > PPP_MAX_RQLEN - && (skb = skb_dequeue(&ppp->file.rq)) != 0) + && (skb = skb_dequeue(&ppp->file.rq))) kfree_skb(skb); /* wake up any process polling or blocking on read */ wake_up_interruptible(&ppp->file.rwait); @@ -1718,7 +1718,7 @@ ppp_decompress_frame(struct ppp *ppp, struct sk_buff *skb) } ns = dev_alloc_skb(obuff_size); - if (ns == 0) { + if (!ns) { printk(KERN_ERR "ppp_decompress_frame: no memory\n"); goto err; } @@ -1836,7 +1836,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) ppp->minseq = ppp->mrq.next->sequence; /* Pull completed packets off the queue and receive them. */ - while ((skb = ppp_mp_reconstruct(ppp)) != 0) + while ((skb = ppp_mp_reconstruct(ppp))) ppp_receive_nonmp_frame(ppp, skb); return; @@ -2002,7 +2002,7 @@ ppp_register_channel(struct ppp_channel *chan) struct channel *pch; pch = kzalloc(sizeof(struct channel), GFP_KERNEL); - if (pch == 0) + if (!pch) return -ENOMEM; pch->ppp = NULL; pch->chan = chan; @@ -2030,7 +2030,7 @@ int ppp_channel_index(struct ppp_channel *chan) { struct channel *pch = chan->ppp; - if (pch != 0) + if (pch) return pch->file.index; return -1; } @@ -2043,9 +2043,9 @@ int ppp_unit_number(struct ppp_channel *chan) struct channel *pch = chan->ppp; int unit = -1; - if (pch != 0) { + if (pch) { read_lock_bh(&pch->upl); - if (pch->ppp != 0) + if (pch->ppp) unit = pch->ppp->file.index; read_unlock_bh(&pch->upl); } @@ -2061,7 +2061,7 @@ ppp_unregister_channel(struct ppp_channel *chan) { struct channel *pch = chan->ppp; - if (pch == 0) + if (!pch) return; /* should never happen */ chan->ppp = NULL; @@ -2093,7 +2093,7 @@ ppp_output_wakeup(struct ppp_channel *chan) { struct channel *pch = chan->ppp; - if (pch == 0) + if (!pch) return; ppp_channel_push(pch); } @@ -2124,18 +2124,18 @@ ppp_set_compress(struct ppp *ppp, unsigned long arg) cp = find_compressor(ccp_option[0]); #ifdef CONFIG_KMOD - if (cp == 0) { + if (!cp) { request_module("ppp-compress-%d", ccp_option[0]); cp = find_compressor(ccp_option[0]); } #endif /* CONFIG_KMOD */ - if (cp == 0) + if (!cp) goto out; err = -ENOBUFS; if (data.transmit) { state = cp->comp_alloc(ccp_option, data.length); - if (state != 0) { + if (state) { ppp_xmit_lock(ppp); ppp->xstate &= ~SC_COMP_RUN; ocomp = ppp->xcomp; @@ -2143,7 +2143,7 @@ ppp_set_compress(struct ppp *ppp, unsigned long arg) ppp->xcomp = cp; ppp->xc_state = state; ppp_xmit_unlock(ppp); - if (ostate != 0) { + if (ostate) { ocomp->comp_free(ostate); module_put(ocomp->owner); } @@ -2153,7 +2153,7 @@ ppp_set_compress(struct ppp *ppp, unsigned long arg) } else { state = cp->decomp_alloc(ccp_option, data.length); - if (state != 0) { + if (state) { ppp_recv_lock(ppp); ppp->rstate &= ~SC_DECOMP_RUN; ocomp = ppp->rcomp; @@ -2161,7 +2161,7 @@ ppp_set_compress(struct ppp *ppp, unsigned long arg) ppp->rcomp = cp; ppp->rc_state = state; ppp_recv_unlock(ppp); - if (ostate != 0) { + if (ostate) { ocomp->decomp_free(ostate); module_put(ocomp->owner); } @@ -2228,7 +2228,7 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound) break; if (inbound) { /* we will start receiving compressed packets */ - if (ppp->rc_state == 0) + if (!ppp->rc_state) break; if (ppp->rcomp->decomp_init(ppp->rc_state, dp, len, ppp->file.index, 0, ppp->mru, ppp->debug)) { @@ -2237,7 +2237,7 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound) } } else { /* we will soon start sending compressed packets */ - if (ppp->xc_state == 0) + if (!ppp->xc_state) break; if (ppp->xcomp->comp_init(ppp->xc_state, dp, len, ppp->file.index, 0, ppp->debug)) @@ -2320,11 +2320,11 @@ ppp_register_compressor(struct compressor *cp) int ret; spin_lock(&compressor_list_lock); ret = -EEXIST; - if (find_comp_entry(cp->compress_proto) != 0) + if (find_comp_entry(cp->compress_proto)) goto out; ret = -ENOMEM; ce = kmalloc(sizeof(struct compressor_entry), GFP_ATOMIC); - if (ce == 0) + if (!ce) goto out; ret = 0; ce->comp = cp; @@ -2342,7 +2342,7 @@ ppp_unregister_compressor(struct compressor *cp) spin_lock(&compressor_list_lock); ce = find_comp_entry(cp->compress_proto); - if (ce != 0 && ce->comp == cp) { + if (ce && ce->comp == cp) { list_del(&ce->list); kfree(ce); } @@ -2358,7 +2358,7 @@ find_compressor(int type) spin_lock(&compressor_list_lock); ce = find_comp_entry(type); - if (ce != 0) { + if (ce) { cp = ce->comp; if (!try_module_get(cp->owner)) cp = NULL; @@ -2383,7 +2383,7 @@ ppp_get_stats(struct ppp *ppp, struct ppp_stats *st) st->p.ppp_opackets = ppp->stats.tx_packets; st->p.ppp_oerrors = ppp->stats.tx_errors; st->p.ppp_obytes = ppp->stats.tx_bytes; - if (vj == 0) + if (!vj) return; st->vj.vjs_packets = vj->sls_o_compressed + vj->sls_o_uncompressed; st->vj.vjs_compressed = vj->sls_o_compressed; @@ -2604,11 +2604,11 @@ ppp_connect_channel(struct channel *pch, int unit) mutex_lock(&all_ppp_mutex); ppp = ppp_find_unit(unit); - if (ppp == 0) + if (!ppp) goto out; write_lock_bh(&pch->upl); ret = -EINVAL; - if (pch->ppp != 0) + if (pch->ppp) goto outl; ppp_lock(ppp); @@ -2644,7 +2644,7 @@ ppp_disconnect_channel(struct channel *pch) ppp = pch->ppp; pch->ppp = NULL; write_unlock_bh(&pch->upl); - if (ppp != 0) { + if (ppp) { /* remove it from the ppp unit's list */ ppp_lock(ppp); list_del(&pch->clist); diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c index ce64032a465a..f0c6a1926a02 100644 --- a/drivers/net/ppp_synctty.c +++ b/drivers/net/ppp_synctty.c @@ -209,7 +209,7 @@ ppp_sync_open(struct tty_struct *tty) ap = kzalloc(sizeof(*ap), GFP_KERNEL); err = -ENOMEM; - if (ap == 0) + if (!ap) goto out; /* initialize the syncppp structure */ @@ -262,7 +262,7 @@ ppp_sync_close(struct tty_struct *tty) ap = tty->disc_data; tty->disc_data = NULL; write_unlock_irq(&disc_data_lock); - if (ap == 0) + if (!ap) return; /* @@ -278,7 +278,7 @@ ppp_sync_close(struct tty_struct *tty) ppp_unregister_channel(&ap->chan); skb_queue_purge(&ap->rqueue); - if (ap->tpkt != 0) + if (ap->tpkt) kfree_skb(ap->tpkt); kfree(ap); } @@ -325,13 +325,13 @@ ppp_synctty_ioctl(struct tty_struct *tty, struct file *file, int __user *p = (int __user *)arg; int err, val; - if (ap == 0) + if (!ap) return -ENXIO; err = -EFAULT; switch (cmd) { case PPPIOCGCHAN: err = -ENXIO; - if (ap == 0) + if (!ap) break; err = -EFAULT; if (put_user(ppp_channel_index(&ap->chan), p)) @@ -341,7 +341,7 @@ ppp_synctty_ioctl(struct tty_struct *tty, struct file *file, case PPPIOCGUNIT: err = -ENXIO; - if (ap == 0) + if (!ap) break; err = -EFAULT; if (put_user(ppp_unit_number(&ap->chan), p)) @@ -349,16 +349,11 @@ ppp_synctty_ioctl(struct tty_struct *tty, struct file *file, err = 0; break; - case TCGETS: - case TCGETA: - err = n_tty_ioctl(tty, file, cmd, arg); - break; - case TCFLSH: /* flush our buffers and the serial port's buffer */ if (arg == TCIOFLUSH || arg == TCOFLUSH) ppp_sync_flush_output(ap); - err = n_tty_ioctl(tty, file, cmd, arg); + err = tty_perform_flush(tty, arg); break; case FIONREAD: @@ -369,7 +364,8 @@ ppp_synctty_ioctl(struct tty_struct *tty, struct file *file, break; default: - err = -ENOIOCTLCMD; + err = tty_mode_ioctl(tty, file, cmd, arg); + break; } sp_put(ap); @@ -394,7 +390,7 @@ ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf, struct syncppp *ap = sp_get(tty); unsigned long flags; - if (ap == 0) + if (!ap) return; spin_lock_irqsave(&ap->recv_lock, flags); ppp_sync_input(ap, buf, cflags, count); @@ -413,7 +409,7 @@ ppp_sync_wakeup(struct tty_struct *tty) struct syncppp *ap = sp_get(tty); clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - if (ap == 0) + if (!ap) return; set_bit(XMIT_WAKEUP, &ap->xmit_flags); tasklet_schedule(&ap->tsk); @@ -655,7 +651,7 @@ ppp_sync_push(struct syncppp *ap) for (;;) { if (test_and_clear_bit(XMIT_WAKEUP, &ap->xmit_flags)) tty_stuffed = 0; - if (!tty_stuffed && ap->tpkt != 0) { + if (!tty_stuffed && ap->tpkt) { set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); sent = tty->driver->write(tty, ap->tpkt->data, ap->tpkt->len); if (sent < 0) @@ -673,7 +669,7 @@ ppp_sync_push(struct syncppp *ap) /* haven't made any progress */ spin_unlock_bh(&ap->xmit_lock); if (!(test_bit(XMIT_WAKEUP, &ap->xmit_flags) - || (!tty_stuffed && ap->tpkt != 0))) + || (!tty_stuffed && ap->tpkt))) break; if (!spin_trylock_bh(&ap->xmit_lock)) break; @@ -681,7 +677,7 @@ ppp_sync_push(struct syncppp *ap) return done; flush: - if (ap->tpkt != 0) { + if (ap->tpkt) { kfree_skb(ap->tpkt); ap->tpkt = NULL; clear_bit(XMIT_FULL, &ap->xmit_flags); @@ -736,7 +732,8 @@ ppp_sync_input(struct syncppp *ap, const unsigned char *buf, ppp_print_buffer ("receive buffer", buf, count); /* stuff the chars in the skb */ - if ((skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2)) == 0) { + skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2); + if (!skb) { printk(KERN_ERR "PPPsync: no memory (input pkt)\n"); goto err; } @@ -744,7 +741,7 @@ ppp_sync_input(struct syncppp *ap, const unsigned char *buf, if (buf[0] != PPP_ALLSTATIONS) skb_reserve(skb, 2 + (buf[0] & 1)); - if (flags != 0 && *flags) { + if (flags && *flags) { /* error flag set, ignore frame */ goto err; } else if (count > skb_tailroom(skb)) { diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c index f8904fd92369..a7556cd2df79 100644 --- a/drivers/net/pppol2tp.c +++ b/drivers/net/pppol2tp.c @@ -488,7 +488,7 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb) { struct pppol2tp_session *session = NULL; struct pppol2tp_tunnel *tunnel; - unsigned char *ptr; + unsigned char *ptr, *optr; u16 hdrflags; u16 tunnel_id, session_id; int length; @@ -496,7 +496,7 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb) tunnel = pppol2tp_sock_to_tunnel(sock); if (tunnel == NULL) - goto error; + goto no_tunnel; /* UDP always verifies the packet length. */ __skb_pull(skb, sizeof(struct udphdr)); @@ -509,7 +509,7 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb) } /* Point to L2TP header */ - ptr = skb->data; + optr = ptr = skb->data; /* Get L2TP header flags */ hdrflags = ntohs(*(__be16*)ptr); @@ -637,12 +637,14 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb) /* If offset bit set, skip it. */ if (hdrflags & L2TP_HDRFLAG_O) { offset = ntohs(*(__be16 *)ptr); - skb->transport_header += 2 + offset; - if (!pskb_may_pull(skb, skb_transport_offset(skb) + 2)) - goto discard; + ptr += 2 + offset; } - __skb_pull(skb, skb_transport_offset(skb)); + offset = ptr - optr; + if (!pskb_may_pull(skb, offset)) + goto discard; + + __skb_pull(skb, offset); /* Skip PPP header, if present. In testing, Microsoft L2TP clients * don't send the PPP header (PPP header compression enabled), but @@ -652,6 +654,9 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb) * Note that skb->data[] isn't dereferenced from a u16 ptr here since * the field may be unaligned. */ + if (!pskb_may_pull(skb, 2)) + goto discard; + if ((skb->data[0] == 0xff) && (skb->data[1] == 0x03)) skb_pull(skb, 2); @@ -709,6 +714,10 @@ discard: return 0; error: + /* Put UDP header back */ + __skb_push(skb, sizeof(struct udphdr)); + +no_tunnel: return 1; } @@ -1050,6 +1059,8 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) /* Get routing info from the tunnel socket */ dst_release(skb->dst); skb->dst = sk_dst_get(sk_tun); + skb_orphan(skb); + skb->sk = sk_tun; /* Queue the packet to IP for output */ len = skb->len; diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index 30adf726743c..a5791114b7bd 100644 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c @@ -1456,16 +1456,11 @@ static void ql_phy_start_neg_ex(struct ql3_adapter *qdev) PHYAddr[qdev->mac_index]); reg &= ~PHY_GIG_ALL_PARAMS; - if(portConfiguration & - PORT_CONFIG_FULL_DUPLEX_ENABLED & - PORT_CONFIG_1000MB_SPEED) { - reg |= PHY_GIG_ADV_1000F; - } - - if(portConfiguration & - PORT_CONFIG_HALF_DUPLEX_ENABLED & - PORT_CONFIG_1000MB_SPEED) { - reg |= PHY_GIG_ADV_1000H; + if(portConfiguration & PORT_CONFIG_1000MB_SPEED) { + if(portConfiguration & PORT_CONFIG_FULL_DUPLEX_ENABLED) + reg |= PHY_GIG_ADV_1000F; + else + reg |= PHY_GIG_ADV_1000H; } ql_mii_write_reg_ex(qdev, PHY_GIG_CONTROL, reg, @@ -1645,8 +1640,11 @@ static int ql_finish_auto_neg(struct ql3_adapter *qdev) return 0; } -static void ql_link_state_machine(struct ql3_adapter *qdev) +static void ql_link_state_machine_work(struct work_struct *work) { + struct ql3_adapter *qdev = + container_of(work, struct ql3_adapter, link_state_work.work); + u32 curr_link_state; unsigned long hw_flags; @@ -1661,6 +1659,10 @@ static void ql_link_state_machine(struct ql3_adapter *qdev) "state.\n", qdev->ndev->name); spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); + + /* Restart timer on 2 second interval. */ + mod_timer(&qdev->adapter_timer, jiffies + HZ * 1);\ + return; } @@ -1705,6 +1707,9 @@ static void ql_link_state_machine(struct ql3_adapter *qdev) break; } spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); + + /* Restart timer on 2 second interval. */ + mod_timer(&qdev->adapter_timer, jiffies + HZ * 1); } /* @@ -3941,19 +3946,7 @@ static void ql_get_board_info(struct ql3_adapter *qdev) static void ql3xxx_timer(unsigned long ptr) { struct ql3_adapter *qdev = (struct ql3_adapter *)ptr; - - if (test_bit(QL_RESET_ACTIVE,&qdev->flags)) { - printk(KERN_DEBUG PFX - "%s: Reset in progress.\n", - qdev->ndev->name); - goto end; - } - - ql_link_state_machine(qdev); - - /* Restart timer on 2 second interval. */ -end: - mod_timer(&qdev->adapter_timer, jiffies + HZ * 1); + queue_delayed_work(qdev->workqueue, &qdev->link_state_work, 0); } static int __devinit ql3xxx_probe(struct pci_dev *pdev, @@ -4103,6 +4096,7 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev, qdev->workqueue = create_singlethread_workqueue(ndev->name); INIT_DELAYED_WORK(&qdev->reset_work, ql_reset_work); INIT_DELAYED_WORK(&qdev->tx_timeout_work, ql_tx_timeout_work); + INIT_DELAYED_WORK(&qdev->link_state_work, ql_link_state_machine_work); init_timer(&qdev->adapter_timer); qdev->adapter_timer.function = ql3xxx_timer; diff --git a/drivers/net/qla3xxx.h b/drivers/net/qla3xxx.h index fbcb0b949639..d0ffb30ef371 100644 --- a/drivers/net/qla3xxx.h +++ b/drivers/net/qla3xxx.h @@ -1286,6 +1286,7 @@ struct ql3_adapter { struct workqueue_struct *workqueue; struct delayed_work reset_work; struct delayed_work tx_timeout_work; + struct delayed_work link_state_work; u32 max_frame_size; u32 device_id; u16 phyType; diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index b94fa7ef1955..1f647b9ce352 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -171,6 +171,8 @@ static struct pci_device_id rtl8169_pci_tbl[] = { { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 }, + { 0x0001, 0x8168, + PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 }, {0,}, }; @@ -468,7 +470,7 @@ static void mdio_write(void __iomem *ioaddr, int reg_addr, int value) { int i; - RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0xFF) << 16 | value); + RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0x1f) << 16 | (value & 0xffff)); for (i = 20; i > 0; i--) { /* @@ -485,7 +487,7 @@ static int mdio_read(void __iomem *ioaddr, int reg_addr) { int i, value = -1; - RTL_W32(PHYAR, 0x0 | (reg_addr & 0xFF) << 16); + RTL_W32(PHYAR, 0x0 | (reg_addr & 0x1f) << 16); for (i = 20; i > 0; i--) { /* @@ -493,7 +495,7 @@ static int mdio_read(void __iomem *ioaddr, int reg_addr) * the specified MII register. */ if (RTL_R32(PHYAR) & 0x80000000) { - value = (int) (RTL_R32(PHYAR) & 0xFFFF); + value = RTL_R32(PHYAR) & 0xffff; break; } udelay(25); @@ -1245,16 +1247,6 @@ static void rtl8169sb_hw_phy_config(void __iomem *ioaddr) rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); } -static void rtl8168b_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} static void rtl8168cp_hw_phy_config(void __iomem *ioaddr) { @@ -1324,11 +1316,6 @@ static void rtl_hw_phy_config(struct net_device *dev) case RTL_GIGA_MAC_VER_04: rtl8169sb_hw_phy_config(ioaddr); break; - case RTL_GIGA_MAC_VER_11: - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - rtl8168b_hw_phy_config(ioaddr); - break; case RTL_GIGA_MAC_VER_18: rtl8168cp_hw_phy_config(ioaddr); break; @@ -1739,7 +1726,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->features |= rtl_try_msi(pdev, ioaddr, cfg); RTL_W8(Cfg9346, Cfg9346_Lock); - if (RTL_R8(PHYstatus) & TBI_Enable) { + if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) && + (RTL_R8(PHYstatus) & TBI_Enable)) { tp->set_speed = rtl8169_set_speed_tbi; tp->get_settings = rtl8169_gset_tbi; tp->phy_reset_enable = rtl8169_tbi_reset_enable; diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c index b822859c8de3..73a7e6529ee0 100644 --- a/drivers/net/rrunner.c +++ b/drivers/net/rrunner.c @@ -78,12 +78,6 @@ static char version[] __devinitdata = "rrunner.c: v0.50 11/11/2002 Jes Sorensen * stack will need to know about I/O vectors or something similar. */ -/* - * sysctl_[wr]mem_max are checked at init time to see if they are at - * least 256KB and increased to 256KB if they are not. This is done to - * avoid ending up with socket buffers smaller than the MTU size, - */ - static int __devinit rr_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -561,18 +555,6 @@ static int __devinit rr_init(struct net_device *dev) sram_size = rr_read_eeprom_word(rrpriv, (void *)8); printk(" SRAM size 0x%06x\n", sram_size); - if (sysctl_rmem_max < 262144){ - printk(" Receive socket buffer limit too low (%i), " - "setting to 262144\n", sysctl_rmem_max); - sysctl_rmem_max = 262144; - } - - if (sysctl_wmem_max < 262144){ - printk(" Transmit socket buffer limit too low (%i), " - "setting to 262144\n", sysctl_wmem_max); - sysctl_wmem_max = 262144; - } - return 0; } diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index b8c0e7b4ca1c..d5113dd712c2 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -84,7 +84,7 @@ #include "s2io.h" #include "s2io-regs.h" -#define DRV_VERSION "2.0.26.5" +#define DRV_VERSION "2.0.26.6" /* S2io Driver name & version. */ static char s2io_driver_name[] = "Neterion"; @@ -1081,7 +1081,7 @@ static int init_nic(struct s2io_nic *nic) /* to set the swapper controle on the card */ if(s2io_set_swapper(nic)) { DBG_PRINT(ERR_DBG,"ERROR: Setting Swapper failed\n"); - return -1; + return -EIO; } /* @@ -1503,7 +1503,7 @@ static int init_nic(struct s2io_nic *nic) DBG_PRINT(ERR_DBG, "%s: failed rts ds steering", dev->name); DBG_PRINT(ERR_DBG, "set on codepoint %d\n", i); - return FAILURE; + return -ENODEV; } } @@ -1570,7 +1570,7 @@ static int init_nic(struct s2io_nic *nic) if (time > 10) { DBG_PRINT(ERR_DBG, "%s: TTI init Failed\n", dev->name); - return -1; + return -ENODEV; } msleep(50); time++; @@ -1623,7 +1623,7 @@ static int init_nic(struct s2io_nic *nic) if (time > 10) { DBG_PRINT(ERR_DBG, "%s: RTI init Failed\n", dev->name); - return -1; + return -ENODEV; } time++; msleep(50); @@ -3775,6 +3775,40 @@ static int __devinit s2io_test_msi(struct s2io_nic *sp) return err; } + +static void remove_msix_isr(struct s2io_nic *sp) +{ + int i; + u16 msi_control; + + for (i = 0; i < MAX_REQUESTED_MSI_X; i++) { + if (sp->s2io_entries[i].in_use == + MSIX_REGISTERED_SUCCESS) { + int vector = sp->entries[i].vector; + void *arg = sp->s2io_entries[i].arg; + free_irq(vector, arg); + } + } + + kfree(sp->entries); + kfree(sp->s2io_entries); + sp->entries = NULL; + sp->s2io_entries = NULL; + + pci_read_config_word(sp->pdev, 0x42, &msi_control); + msi_control &= 0xFFFE; /* Disable MSI */ + pci_write_config_word(sp->pdev, 0x42, msi_control); + + pci_disable_msix(sp->pdev); +} + +static void remove_inta_isr(struct s2io_nic *sp) +{ + struct net_device *dev = sp->dev; + + free_irq(sp->pdev->irq, dev); +} + /* ********************************************************* * * Functions defined below concern the OS part of the driver * * ********************************************************* */ @@ -3809,28 +3843,9 @@ static int s2io_open(struct net_device *dev) int ret = s2io_enable_msi_x(sp); if (!ret) { - u16 msi_control; - ret = s2io_test_msi(sp); - /* rollback MSI-X, will re-enable during add_isr() */ - kfree(sp->entries); - sp->mac_control.stats_info->sw_stat.mem_freed += - (MAX_REQUESTED_MSI_X * - sizeof(struct msix_entry)); - kfree(sp->s2io_entries); - sp->mac_control.stats_info->sw_stat.mem_freed += - (MAX_REQUESTED_MSI_X * - sizeof(struct s2io_msix_entry)); - sp->entries = NULL; - sp->s2io_entries = NULL; - - pci_read_config_word(sp->pdev, 0x42, &msi_control); - msi_control &= 0xFFFE; /* Disable MSI */ - pci_write_config_word(sp->pdev, 0x42, msi_control); - - pci_disable_msix(sp->pdev); - + remove_msix_isr(sp); } if (ret) { @@ -3899,6 +3914,12 @@ static int s2io_close(struct net_device *dev) { struct s2io_nic *sp = dev->priv; + /* Return if the device is already closed * + * Can happen when s2io_card_up failed in change_mtu * + */ + if (!is_s2io_card_up(sp)) + return 0; + netif_stop_queue(dev); napi_disable(&sp->napi); /* Reset card, kill tasklet and free Tx and Rx buffers. */ @@ -6340,6 +6361,7 @@ static int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) static int s2io_change_mtu(struct net_device *dev, int new_mtu) { struct s2io_nic *sp = dev->priv; + int ret = 0; if ((new_mtu < MIN_MTU) || (new_mtu > S2IO_JUMBO_SIZE)) { DBG_PRINT(ERR_DBG, "%s: MTU size is invalid.\n", @@ -6351,9 +6373,11 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu) if (netif_running(dev)) { s2io_card_down(sp); netif_stop_queue(dev); - if (s2io_card_up(sp)) { + ret = s2io_card_up(sp); + if (ret) { DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n", __FUNCTION__); + return ret; } if (netif_queue_stopped(dev)) netif_wake_queue(dev); @@ -6364,7 +6388,7 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu) writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len); } - return 0; + return ret; } /** @@ -6719,15 +6743,22 @@ static int s2io_add_isr(struct s2io_nic * sp) } } if (err) { + remove_msix_isr(sp); DBG_PRINT(ERR_DBG,"%s:MSI-X-%d registration " "failed\n", dev->name, i); - DBG_PRINT(ERR_DBG, "Returned: %d\n", err); - return -1; + DBG_PRINT(ERR_DBG, "%s: defaulting to INTA\n", + dev->name); + sp->config.intr_type = INTA; + break; } sp->s2io_entries[i].in_use = MSIX_REGISTERED_SUCCESS; } - printk("MSI-X-TX %d entries enabled\n",msix_tx_cnt); - printk("MSI-X-RX %d entries enabled\n",msix_rx_cnt); + if (!err) { + printk(KERN_INFO "MSI-X-TX %d entries enabled\n", + msix_tx_cnt); + printk(KERN_INFO "MSI-X-RX %d entries enabled\n", + msix_rx_cnt); + } } if (sp->config.intr_type == INTA) { err = request_irq((int) sp->pdev->irq, s2io_isr, IRQF_SHARED, @@ -6742,40 +6773,10 @@ static int s2io_add_isr(struct s2io_nic * sp) } static void s2io_rem_isr(struct s2io_nic * sp) { - struct net_device *dev = sp->dev; - struct swStat *stats = &sp->mac_control.stats_info->sw_stat; - - if (sp->config.intr_type == MSI_X) { - int i; - u16 msi_control; - - for (i=1; (sp->s2io_entries[i].in_use == - MSIX_REGISTERED_SUCCESS); i++) { - int vector = sp->entries[i].vector; - void *arg = sp->s2io_entries[i].arg; - - synchronize_irq(vector); - free_irq(vector, arg); - } - - kfree(sp->entries); - stats->mem_freed += - (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry)); - kfree(sp->s2io_entries); - stats->mem_freed += - (MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry)); - sp->entries = NULL; - sp->s2io_entries = NULL; - - pci_read_config_word(sp->pdev, 0x42, &msi_control); - msi_control &= 0xFFFE; /* Disable MSI */ - pci_write_config_word(sp->pdev, 0x42, msi_control); - - pci_disable_msix(sp->pdev); - } else { - synchronize_irq(sp->pdev->irq); - free_irq(sp->pdev->irq, dev); - } + if (sp->config.intr_type == MSI_X) + remove_msix_isr(sp); + else + remove_inta_isr(sp); } static void do_s2io_card_down(struct s2io_nic * sp, int do_io) @@ -6785,6 +6786,9 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io) unsigned long flags; register u64 val64 = 0; + if (!is_s2io_card_up(sp)) + return; + del_timer_sync(&sp->alarm_timer); /* If s2io_set_link task is executing, wait till it completes. */ while (test_and_set_bit(__S2IO_STATE_LINK_TASK, &(sp->state))) { @@ -6858,11 +6862,13 @@ static int s2io_card_up(struct s2io_nic * sp) u16 interruptible; /* Initialize the H/W I/O registers */ - if (init_nic(sp) != 0) { + ret = init_nic(sp); + if (ret != 0) { DBG_PRINT(ERR_DBG, "%s: H/W initialization failed\n", dev->name); - s2io_reset(sp); - return -ENODEV; + if (ret != -EIO) + s2io_reset(sp); + return ret; } /* diff --git a/drivers/net/skge.c b/drivers/net/skge.c index b9961dc47606..186eb8ebfda6 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -44,7 +44,7 @@ #include "skge.h" #define DRV_NAME "skge" -#define DRV_VERSION "1.12" +#define DRV_VERSION "1.13" #define PFX DRV_NAME " " #define DEFAULT_TX_RING_SIZE 128 @@ -1095,16 +1095,9 @@ static void xm_link_down(struct skge_hw *hw, int port) { struct net_device *dev = hw->dev[port]; struct skge_port *skge = netdev_priv(dev); - u16 cmd = xm_read16(hw, port, XM_MMU_CMD); xm_write16(hw, port, XM_IMSK, XM_IMSK_DISABLE); - cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX); - xm_write16(hw, port, XM_MMU_CMD, cmd); - - /* dummy read to ensure writing */ - xm_read16(hw, port, XM_MMU_CMD); - if (netif_carrier_ok(dev)) skge_link_down(skge); } @@ -1194,6 +1187,7 @@ static void genesis_init(struct skge_hw *hw) static void genesis_reset(struct skge_hw *hw, int port) { const u8 zero[8] = { 0 }; + u32 reg; skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0); @@ -1209,6 +1203,11 @@ static void genesis_reset(struct skge_hw *hw, int port) xm_write16(hw, port, PHY_BCOM_INT_MASK, 0xffff); xm_outhash(hw, port, XM_HSM, zero); + + /* Flush TX and RX fifo */ + reg = xm_read32(hw, port, XM_MODE); + xm_write32(hw, port, XM_MODE, reg | XM_MD_FTF); + xm_write32(hw, port, XM_MODE, reg | XM_MD_FRF); } @@ -1634,15 +1633,14 @@ static void genesis_mac_init(struct skge_hw *hw, int port) } xm_write16(hw, port, XM_RX_CMD, r); - /* We want short frames padded to 60 bytes. */ xm_write16(hw, port, XM_TX_CMD, XM_TX_AUTO_PAD); - /* - * Bump up the transmit threshold. This helps hold off transmit - * underruns when we're blasting traffic from both ports at once. - */ - xm_write16(hw, port, XM_TX_THR, 512); + /* Increase threshold for jumbo frames on dual port */ + if (hw->ports > 1 && jumbo) + xm_write16(hw, port, XM_TX_THR, 1020); + else + xm_write16(hw, port, XM_TX_THR, 512); /* * Enable the reception of all error frames. This is is @@ -1713,7 +1711,13 @@ static void genesis_stop(struct skge_port *skge) { struct skge_hw *hw = skge->hw; int port = skge->port; - u32 reg; + unsigned retries = 1000; + u16 cmd; + + /* Disable Tx and Rx */ + cmd = xm_read16(hw, port, XM_MMU_CMD); + cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX); + xm_write16(hw, port, XM_MMU_CMD, cmd); genesis_reset(hw, port); @@ -1721,20 +1725,17 @@ static void genesis_stop(struct skge_port *skge) skge_write16(hw, B3_PA_CTRL, port == 0 ? PA_CLR_TO_TX1 : PA_CLR_TO_TX2); - /* - * If the transfer sticks at the MAC the STOP command will not - * terminate if we don't flush the XMAC's transmit FIFO ! - */ - xm_write32(hw, port, XM_MODE, - xm_read32(hw, port, XM_MODE)|XM_MD_FTF); - - /* Reset the MAC */ - skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_SET_MAC_RST); + skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); + do { + skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_SET_MAC_RST); + if (!(skge_read16(hw, SK_REG(port, TX_MFF_CTRL1)) & MFF_SET_MAC_RST)) + break; + } while (--retries > 0); /* For external PHYs there must be special handling */ if (hw->phy_type != SK_PHY_XMAC) { - reg = skge_read32(hw, B2_GP_IO); + u32 reg = skge_read32(hw, B2_GP_IO); if (port == 0) { reg |= GP_DIR_0; reg &= ~GP_IO_0; @@ -1801,11 +1802,6 @@ static void genesis_mac_intr(struct skge_hw *hw, int port) xm_write32(hw, port, XM_MODE, XM_MD_FTF); ++dev->stats.tx_fifo_errors; } - - if (status & XM_IS_RXF_OV) { - xm_write32(hw, port, XM_MODE, XM_MD_FRF); - ++dev->stats.rx_fifo_errors; - } } static void genesis_link_up(struct skge_port *skge) @@ -1862,9 +1858,9 @@ static void genesis_link_up(struct skge_port *skge) xm_write32(hw, port, XM_MODE, mode); - /* Turn on detection of Tx underrun, Rx overrun */ + /* Turn on detection of Tx underrun */ msk = xm_read16(hw, port, XM_IMSK); - msk &= ~(XM_IS_RXF_OV | XM_IS_TXF_UR); + msk &= ~XM_IS_TXF_UR; xm_write16(hw, port, XM_IMSK, msk); xm_read16(hw, port, XM_ISRC); @@ -2194,9 +2190,12 @@ static void yukon_mac_init(struct skge_hw *hw, int port) TX_JAM_IPG_VAL(TX_JAM_IPG_DEF) | TX_IPG_JAM_DATA(TX_IPG_JAM_DEF)); - /* serial mode register */ - reg = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF); - if (hw->dev[port]->mtu > 1500) + /* configure the Serial Mode Register */ + reg = DATA_BLIND_VAL(DATA_BLIND_DEF) + | GM_SMOD_VLAN_ENA + | IPG_DATA_VAL(IPG_DATA_DEF); + + if (hw->dev[port]->mtu > ETH_DATA_LEN) reg |= GM_SMOD_JUMBO_ENA; gma_write16(hw, port, GM_SERIAL_MODE, reg); @@ -2512,31 +2511,32 @@ static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return err; } -/* Assign Ram Buffer allocation to queue */ -static void skge_ramset(struct skge_hw *hw, u16 q, u32 start, u32 space) +static void skge_ramset(struct skge_hw *hw, u16 q, u32 start, size_t len) { u32 end; - /* convert from K bytes to qwords used for hw register */ - start *= 1024/8; - space *= 1024/8; - end = start + space - 1; + start /= 8; + len /= 8; + end = start + len - 1; skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR); skge_write32(hw, RB_ADDR(q, RB_START), start); - skge_write32(hw, RB_ADDR(q, RB_END), end); skge_write32(hw, RB_ADDR(q, RB_WP), start); skge_write32(hw, RB_ADDR(q, RB_RP), start); + skge_write32(hw, RB_ADDR(q, RB_END), end); if (q == Q_R1 || q == Q_R2) { - u32 tp = space - space/4; - /* Set thresholds on receive queue's */ - skge_write32(hw, RB_ADDR(q, RB_RX_UTPP), tp); - skge_write32(hw, RB_ADDR(q, RB_RX_LTPP), space/4); - } else if (hw->chip_id != CHIP_ID_GENESIS) - /* Genesis Tx Fifo is too small for normal store/forward */ + skge_write32(hw, RB_ADDR(q, RB_RX_UTPP), + start + (2*len)/3); + skge_write32(hw, RB_ADDR(q, RB_RX_LTPP), + start + (len/3)); + } else { + /* Enable store & forward on Tx queue's because + * Tx FIFO is only 4K on Genesis and 1K on Yukon + */ skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_STFWD); + } skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_OP_MD); } @@ -2564,7 +2564,7 @@ static int skge_up(struct net_device *dev) struct skge_port *skge = netdev_priv(dev); struct skge_hw *hw = skge->hw; int port = skge->port; - u32 ramaddr, ramsize, rxspace; + u32 chunk, ram_addr; size_t rx_size, tx_size; int err; @@ -2618,16 +2618,15 @@ static int skge_up(struct net_device *dev) yukon_mac_init(hw, port); spin_unlock_bh(&hw->phy_lock); - /* Configure RAMbuffers */ - ramsize = (hw->ram_size - hw->ram_offset) / hw->ports; - ramaddr = hw->ram_offset + port * ramsize; - rxspace = 8 + (2*(ramsize - 16))/3; - - skge_ramset(hw, rxqaddr[port], ramaddr, rxspace); - skge_ramset(hw, txqaddr[port], ramaddr + rxspace, ramsize - rxspace); + /* Configure RAMbuffers - equally between ports and tx/rx */ + chunk = (hw->ram_size - hw->ram_offset) / (hw->ports * 2); + ram_addr = hw->ram_offset + 2 * chunk * port; + skge_ramset(hw, rxqaddr[port], ram_addr, chunk); skge_qset(skge, rxqaddr[port], skge->rx_ring.to_clean); + BUG_ON(skge->tx_ring.to_use != skge->tx_ring.to_clean); + skge_ramset(hw, txqaddr[port], ram_addr+chunk, chunk); skge_qset(skge, txqaddr[port], skge->tx_ring.to_use); /* Start receiver BMU */ @@ -2897,11 +2896,7 @@ static void skge_tx_timeout(struct net_device *dev) static int skge_change_mtu(struct net_device *dev, int new_mtu) { - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - int port = skge->port; int err; - u16 ctl, reg; if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) return -EINVAL; @@ -2911,40 +2906,13 @@ static int skge_change_mtu(struct net_device *dev, int new_mtu) return 0; } - skge_write32(hw, B0_IMSK, 0); - dev->trans_start = jiffies; /* prevent tx timeout */ - netif_stop_queue(dev); - napi_disable(&skge->napi); - - ctl = gma_read16(hw, port, GM_GP_CTRL); - gma_write16(hw, port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA); - - skge_rx_clean(skge); - skge_rx_stop(hw, port); + skge_down(dev); dev->mtu = new_mtu; - reg = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF); - if (new_mtu > 1500) - reg |= GM_SMOD_JUMBO_ENA; - gma_write16(hw, port, GM_SERIAL_MODE, reg); - - skge_write8(hw, RB_ADDR(rxqaddr[port], RB_CTRL), RB_ENA_OP_MD); - - err = skge_rx_fill(dev); - wmb(); - if (!err) - skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F); - skge_write32(hw, B0_IMSK, hw->intr_mask); - + err = skge_up(dev); if (err) dev_close(dev); - else { - gma_write16(hw, port, GM_GP_CTRL, ctl); - - napi_enable(&skge->napi); - netif_wake_queue(dev); - } return err; } @@ -3591,12 +3559,15 @@ static int skge_reset(struct skge_hw *hw) if (hw->chip_id == CHIP_ID_GENESIS) { if (t8 == 3) { /* special case: 4 x 64k x 36, offset = 0x80000 */ - hw->ram_size = 1024; - hw->ram_offset = 512; + hw->ram_size = 0x100000; + hw->ram_offset = 0x80000; } else hw->ram_size = t8 * 512; - } else /* Yukon */ - hw->ram_size = t8 ? t8 * 4 : 128; + } + else if (t8 == 0) + hw->ram_size = 0x20000; + else + hw->ram_size = t8 * 4096; hw->intr_mask = IS_HW_ERR; diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index c27c7d63b6a5..3d1dfc948405 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -31,7 +31,6 @@ #include <linux/etherdevice.h> #include <linux/ethtool.h> #include <linux/pci.h> -#include <linux/aer.h> #include <linux/ip.h> #include <net/ip.h> #include <linux/tcp.h> @@ -52,7 +51,7 @@ #include "sky2.h" #define DRV_NAME "sky2" -#define DRV_VERSION "1.19" +#define DRV_VERSION "1.20" #define PFX DRV_NAME " " /* @@ -121,6 +120,7 @@ static const struct pci_device_id sky2_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4353) }, /* 88E8039 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4354) }, /* 88E8040 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4356) }, /* 88EC033 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4357) }, /* 88E8042 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x435A) }, /* 88E8048 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) }, /* 88E8052 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, /* 88E8050 */ @@ -134,6 +134,7 @@ static const struct pci_device_id sky2_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4369) }, /* 88EC042 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436A) }, /* 88E8058 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436C) }, /* 88E8072 */ { 0 } }; @@ -156,7 +157,7 @@ static const char *yukon2_name[] = { static void sky2_set_multicast(struct net_device *dev); -/* Access to external PHY */ +/* Access to PHY via serial interconnect */ static int gm_phy_write(struct sky2_hw *hw, unsigned port, u16 reg, u16 val) { int i; @@ -166,13 +167,22 @@ static int gm_phy_write(struct sky2_hw *hw, unsigned port, u16 reg, u16 val) GM_SMI_CT_PHY_AD(PHY_ADDR_MARV) | GM_SMI_CT_REG_AD(reg)); for (i = 0; i < PHY_RETRIES; i++) { - if (!(gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_BUSY)) + u16 ctrl = gma_read16(hw, port, GM_SMI_CTRL); + if (ctrl == 0xffff) + goto io_error; + + if (!(ctrl & GM_SMI_CT_BUSY)) return 0; - udelay(1); + + udelay(10); } - printk(KERN_WARNING PFX "%s: phy write timeout\n", hw->dev[port]->name); + dev_warn(&hw->pdev->dev,"%s: phy write timeout\n", hw->dev[port]->name); return -ETIMEDOUT; + +io_error: + dev_err(&hw->pdev->dev, "%s: phy I/O error\n", hw->dev[port]->name); + return -EIO; } static int __gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg, u16 *val) @@ -183,23 +193,29 @@ static int __gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg, u16 *val) | GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD); for (i = 0; i < PHY_RETRIES; i++) { - if (gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_RD_VAL) { + u16 ctrl = gma_read16(hw, port, GM_SMI_CTRL); + if (ctrl == 0xffff) + goto io_error; + + if (ctrl & GM_SMI_CT_RD_VAL) { *val = gma_read16(hw, port, GM_SMI_DATA); return 0; } - udelay(1); + udelay(10); } + dev_warn(&hw->pdev->dev, "%s: phy read timeout\n", hw->dev[port]->name); return -ETIMEDOUT; +io_error: + dev_err(&hw->pdev->dev, "%s: phy I/O error\n", hw->dev[port]->name); + return -EIO; } -static u16 gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg) +static inline u16 gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg) { u16 v; - - if (__gm_phy_read(hw, port, reg, &v) != 0) - printk(KERN_WARNING PFX "%s: phy read timeout\n", hw->dev[port]->name); + __gm_phy_read(hw, port, reg, &v); return v; } @@ -223,22 +239,21 @@ static void sky2_power_on(struct sky2_hw *hw) sky2_write8(hw, B2_Y2_CLK_GATE, 0); if (hw->flags & SKY2_HW_ADV_POWER_CTL) { - struct pci_dev *pdev = hw->pdev; u32 reg; - pci_write_config_dword(pdev, PCI_DEV_REG3, 0); + sky2_pci_write32(hw, PCI_DEV_REG3, 0); - pci_read_config_dword(pdev, PCI_DEV_REG4, ®); + reg = sky2_pci_read32(hw, PCI_DEV_REG4); /* set all bits to 0 except bits 15..12 and 8 */ reg &= P_ASPM_CONTROL_MSK; - pci_write_config_dword(pdev, PCI_DEV_REG4, reg); + sky2_pci_write32(hw, PCI_DEV_REG4, reg); - pci_read_config_dword(pdev, PCI_DEV_REG5, ®); + reg = sky2_pci_read32(hw, PCI_DEV_REG5); /* set all bits to 0 except bits 28 & 27 */ reg &= P_CTL_TIM_VMAIN_AV_MSK; - pci_write_config_dword(pdev, PCI_DEV_REG5, reg); + sky2_pci_write32(hw, PCI_DEV_REG5, reg); - pci_write_config_dword(pdev, PCI_CFG_REG_1, 0); + sky2_pci_write32(hw, PCI_CFG_REG_1, 0); /* Enable workaround for dev 4.107 on Yukon-Ultra & Extreme */ reg = sky2_read32(hw, B2_GP_IO); @@ -273,8 +288,6 @@ static void sky2_gmac_reset(struct sky2_hw *hw, unsigned port) /* disable all GMAC IRQ's */ sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0); - /* disable PHY IRQs */ - gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0); gma_write16(hw, port, GM_MC_ADDR_H1, 0); /* clear MC hash */ gma_write16(hw, port, GM_MC_ADDR_H2, 0); @@ -604,12 +617,11 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) static void sky2_phy_power(struct sky2_hw *hw, unsigned port, int onoff) { - struct pci_dev *pdev = hw->pdev; u32 reg1; static const u32 phy_power[] = { PCI_Y2_PHY1_POWD, PCI_Y2_PHY2_POWD }; static const u32 coma_mode[] = { PCI_Y2_PHY1_COMA, PCI_Y2_PHY2_COMA }; - pci_read_config_dword(pdev, PCI_DEV_REG1, ®1); + reg1 = sky2_pci_read32(hw, PCI_DEV_REG1); /* Turn on/off phy power saving */ if (onoff) reg1 &= ~phy_power[port]; @@ -619,8 +631,8 @@ static void sky2_phy_power(struct sky2_hw *hw, unsigned port, int onoff) if (onoff && hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) reg1 |= coma_mode[port]; - pci_write_config_dword(pdev, PCI_DEV_REG1, reg1); - pci_read_config_dword(pdev, PCI_DEV_REG1, ®1); + sky2_pci_write32(hw, PCI_DEV_REG1, reg1); + reg1 = sky2_pci_read32(hw, PCI_DEV_REG1); udelay(100); } @@ -689,9 +701,9 @@ static void sky2_wol_init(struct sky2_port *sky2) sky2_write16(hw, WOL_REGS(port, WOL_CTRL_STAT), ctrl); /* Turn on legacy PCI-Express PME mode */ - pci_read_config_dword(hw->pdev, PCI_DEV_REG1, ®1); + reg1 = sky2_pci_read32(hw, PCI_DEV_REG1); reg1 |= PCI_Y2_PME_LEGACY; - pci_write_config_dword(hw->pdev, PCI_DEV_REG1, reg1); + sky2_pci_write32(hw, PCI_DEV_REG1, reg1); /* block receiver */ sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); @@ -833,6 +845,13 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) sky2_set_tx_stfwd(hw, port); } + if (hw->chip_id == CHIP_ID_YUKON_FE_P && + hw->chip_rev == CHIP_REV_YU_FE2_A0) { + /* disable dynamic watermark */ + reg = sky2_read16(hw, SK_REG(port, TX_GMF_EA)); + reg &= ~TX_DYN_WM_ENA; + sky2_write16(hw, SK_REG(port, TX_GMF_EA), reg); + } } /* Assign Ram Buffer allocation to queue */ @@ -1305,15 +1324,12 @@ static int sky2_up(struct net_device *dev) */ if (otherdev && netif_running(otherdev) && (cap = pci_find_capability(hw->pdev, PCI_CAP_ID_PCIX))) { - struct sky2_port *osky2 = netdev_priv(otherdev); u16 cmd; - pci_read_config_word(hw->pdev, cap + PCI_X_CMD, &cmd); + cmd = sky2_pci_read16(hw, cap + PCI_X_CMD); cmd &= ~PCI_X_CMD_MAX_SPLIT; - pci_write_config_word(hw->pdev, cap + PCI_X_CMD, cmd); + sky2_pci_write16(hw, cap + PCI_X_CMD, cmd); - sky2->rx_csum = 0; - osky2->rx_csum = 0; } if (netif_msg_ifup(sky2)) @@ -1805,29 +1821,6 @@ static void sky2_link_up(struct sky2_port *sky2) sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF); - if (hw->flags & SKY2_HW_NEWER_PHY) { - u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); - u16 led = PHY_M_LEDC_LOS_CTRL(1); /* link active */ - - switch(sky2->speed) { - case SPEED_10: - led |= PHY_M_LEDC_INIT_CTRL(7); - break; - - case SPEED_100: - led |= PHY_M_LEDC_STA1_CTRL(7); - break; - - case SPEED_1000: - led |= PHY_M_LEDC_STA0_CTRL(7); - break; - } - - gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); - gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, led); - gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); - } - if (netif_msg_link(sky2)) printk(KERN_INFO PFX "%s: Link is up at %d Mbps, %s duplex, flow control %s\n", @@ -2247,20 +2240,26 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) do { struct sky2_port *sky2; struct sky2_status_le *le = hw->st_le + hw->st_idx; - unsigned port = le->css & CSS_LINK_BIT; + unsigned port; struct net_device *dev; struct sk_buff *skb; u32 status; u16 length; + u8 opcode = le->opcode; + + if (!(opcode & HW_OWNER)) + break; hw->st_idx = RING_NEXT(hw->st_idx, STATUS_RING_SIZE); + port = le->css & CSS_LINK_BIT; dev = hw->dev[port]; sky2 = netdev_priv(dev); length = le16_to_cpu(le->length); status = le32_to_cpu(le->status); - switch (le->opcode & ~HW_OWNER) { + le->opcode = 0; + switch (opcode & ~HW_OWNER) { case OP_RXSTAT: ++rx[port]; skb = sky2_receive(dev, length, status); @@ -2353,7 +2352,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) default: if (net_ratelimit()) printk(KERN_WARNING PFX - "unknown status opcode 0x%x\n", le->opcode); + "unknown status opcode 0x%x\n", opcode); } } while (hw->st_idx != idx); @@ -2428,24 +2427,26 @@ static void sky2_hw_intr(struct sky2_hw *hw) if (status & (Y2_IS_MST_ERR | Y2_IS_IRQ_STAT)) { u16 pci_err; - pci_read_config_word(pdev, PCI_STATUS, &pci_err); + pci_err = sky2_pci_read16(hw, PCI_STATUS); if (net_ratelimit()) dev_err(&pdev->dev, "PCI hardware error (0x%x)\n", pci_err); - pci_write_config_word(pdev, PCI_STATUS, + sky2_pci_write16(hw, PCI_STATUS, pci_err | PCI_STATUS_ERROR_BITS); } if (status & Y2_IS_PCI_EXP) { /* PCI-Express uncorrectable Error occurred */ - int pos = pci_find_aer_capability(hw->pdev); u32 err; - pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_STATUS, &err); + err = sky2_read32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS); + sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS, + 0xfffffffful); if (net_ratelimit()) dev_err(&pdev->dev, "PCI Express error (0x%x)\n", err); - pci_cleanup_aer_uncorrect_error_status(pdev); + + sky2_read32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS); } if (status & Y2_HWE_L1_MASK) @@ -2692,13 +2693,10 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk) static int __devinit sky2_init(struct sky2_hw *hw) { - int rc; u8 t8; /* Enable all clocks and check for bad PCI access */ - rc = pci_write_config_dword(hw->pdev, PCI_DEV_REG3, 0); - if (rc) - return rc; + sky2_pci_write32(hw, PCI_DEV_REG3, 0); sky2_write8(hw, B0_CTST, CS_RST_CLR); @@ -2791,24 +2789,25 @@ static void sky2_reset(struct sky2_hw *hw) sky2_write8(hw, B0_CTST, CS_RST_SET); sky2_write8(hw, B0_CTST, CS_RST_CLR); + /* allow writes to PCI config */ + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); + /* clear PCI errors, if any */ - pci_read_config_word(pdev, PCI_STATUS, &status); + status = sky2_pci_read16(hw, PCI_STATUS); status |= PCI_STATUS_ERROR_BITS; - pci_write_config_word(pdev, PCI_STATUS, status); + sky2_pci_write16(hw, PCI_STATUS, status); sky2_write8(hw, B0_CTST, CS_MRST_CLR); cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); if (cap) { - /* Check for advanced error reporting */ - pci_cleanup_aer_uncorrect_error_status(pdev); - pci_cleanup_aer_correct_error_status(pdev); + sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS, + 0xfffffffful); /* If error bit is stuck on ignore it */ if (sky2_read32(hw, B0_HWE_ISRC) & Y2_IS_PCI_EXP) dev_info(&pdev->dev, "ignoring stuck error report bit\n"); - - else if (pci_enable_pcie_error_reporting(pdev)) + else hwe_mask |= Y2_IS_PCI_EXP; } @@ -3649,32 +3648,33 @@ static int sky2_set_tso(struct net_device *dev, u32 data) static int sky2_get_eeprom_len(struct net_device *dev) { struct sky2_port *sky2 = netdev_priv(dev); + struct sky2_hw *hw = sky2->hw; u16 reg2; - pci_read_config_word(sky2->hw->pdev, PCI_DEV_REG2, ®2); + reg2 = sky2_pci_read16(hw, PCI_DEV_REG2); return 1 << ( ((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8); } -static u32 sky2_vpd_read(struct pci_dev *pdev, int cap, u16 offset) +static u32 sky2_vpd_read(struct sky2_hw *hw, int cap, u16 offset) { u32 val; - pci_write_config_word(pdev, cap + PCI_VPD_ADDR, offset); + sky2_pci_write16(hw, cap + PCI_VPD_ADDR, offset); do { - pci_read_config_word(pdev, cap + PCI_VPD_ADDR, &offset); + offset = sky2_pci_read16(hw, cap + PCI_VPD_ADDR); } while (!(offset & PCI_VPD_ADDR_F)); - pci_read_config_dword(pdev, cap + PCI_VPD_DATA, &val); + val = sky2_pci_read32(hw, cap + PCI_VPD_DATA); return val; } -static void sky2_vpd_write(struct pci_dev *pdev, int cap, u16 offset, u32 val) +static void sky2_vpd_write(struct sky2_hw *hw, int cap, u16 offset, u32 val) { - pci_write_config_word(pdev, cap + PCI_VPD_DATA, val); - pci_write_config_dword(pdev, cap + PCI_VPD_ADDR, offset | PCI_VPD_ADDR_F); + sky2_pci_write16(hw, cap + PCI_VPD_DATA, val); + sky2_pci_write32(hw, cap + PCI_VPD_ADDR, offset | PCI_VPD_ADDR_F); do { - pci_read_config_word(pdev, cap + PCI_VPD_ADDR, &offset); + offset = sky2_pci_read16(hw, cap + PCI_VPD_ADDR); } while (offset & PCI_VPD_ADDR_F); } @@ -3692,7 +3692,7 @@ static int sky2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom eeprom->magic = SKY2_EEPROM_MAGIC; while (length > 0) { - u32 val = sky2_vpd_read(sky2->hw->pdev, cap, offset); + u32 val = sky2_vpd_read(sky2->hw, cap, offset); int n = min_t(int, length, sizeof(val)); memcpy(data, &val, n); @@ -3722,10 +3722,10 @@ static int sky2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom int n = min_t(int, length, sizeof(val)); if (n < sizeof(val)) - val = sky2_vpd_read(sky2->hw->pdev, cap, offset); + val = sky2_vpd_read(sky2->hw, cap, offset); memcpy(&val, data, n); - sky2_vpd_write(sky2->hw->pdev, cap, offset, val); + sky2_vpd_write(sky2->hw, cap, offset, val); length -= n; data += n; @@ -3974,7 +3974,8 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, dev->tx_timeout = sky2_tx_timeout; dev->watchdog_timeo = TX_WATCHDOG; #ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = sky2_netpoll; + if (port == 0) + dev->poll_controller = sky2_netpoll; #endif sky2 = netdev_priv(dev); @@ -3989,7 +3990,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, sky2->duplex = -1; sky2->speed = -1; sky2->advertising = sky2_supported_modes(hw); - sky2->rx_csum = 1; + sky2->rx_csum = (hw->chip_id != CHIP_ID_YUKON_XL); sky2->wol = wol; spin_lock_init(&sky2->phy_lock); @@ -4160,9 +4161,9 @@ static int __devinit sky2_probe(struct pci_dev *pdev, */ { u32 reg; - pci_read_config_dword(pdev,PCI_DEV_REG2, ®); + reg = sky2_pci_read32(hw, PCI_DEV_REG2); reg &= ~PCI_REV_DESC; - pci_write_config_dword(pdev, PCI_DEV_REG2, reg); + sky2_pci_write32(hw, PCI_DEV_REG2, reg); } #endif @@ -4353,7 +4354,7 @@ static int sky2_resume(struct pci_dev *pdev) if (hw->chip_id == CHIP_ID_YUKON_EX || hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_FE_P) - pci_write_config_dword(pdev, PCI_DEV_REG3, 0); + sky2_pci_write32(hw, PCI_DEV_REG3, 0); sky2_reset(hw); sky2_write32(hw, B0_IMSK, Y2_IS_BASE); diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 49ee264064ab..bc646a47edd2 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -247,7 +247,8 @@ enum csr_regs { B3_PA_CTRL = 0x01f0, B3_PA_TEST = 0x01f2, - Y2_CFG_SPC = 0x1c00, + Y2_CFG_SPC = 0x1c00, /* PCI config space region */ + Y2_CFG_AER = 0x1d00, /* PCI Advanced Error Report region */ }; /* B0_CTST 16 bit Control/Status register */ @@ -2127,4 +2128,25 @@ static inline void gma_set_addr(struct sky2_hw *hw, unsigned port, unsigned reg, gma_write16(hw, port, reg+4,(u16) addr[2] | ((u16) addr[3] << 8)); gma_write16(hw, port, reg+8,(u16) addr[4] | ((u16) addr[5] << 8)); } + +/* PCI config space access */ +static inline u32 sky2_pci_read32(const struct sky2_hw *hw, unsigned reg) +{ + return sky2_read32(hw, Y2_CFG_SPC + reg); +} + +static inline u16 sky2_pci_read16(const struct sky2_hw *hw, unsigned reg) +{ + return sky2_read16(hw, Y2_CFG_SPC + reg); +} + +static inline void sky2_pci_write32(struct sky2_hw *hw, unsigned reg, u32 val) +{ + sky2_write32(hw, Y2_CFG_SPC + reg, val); +} + +static inline void sky2_pci_write16(struct sky2_hw *hw, unsigned reg, u16 val) +{ + sky2_write16(hw, Y2_CFG_SPC + reg, val); +} #endif diff --git a/drivers/net/slip.c b/drivers/net/slip.c index 335b7cc80eba..251a3ce376ac 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -1218,14 +1218,8 @@ static int slip_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm return 0; /* VSV changes end */ #endif - - /* Allow stty to read, but not set, the serial port */ - case TCGETS: - case TCGETA: - return n_tty_ioctl(tty, file, cmd, arg); - default: - return -ENOIOCTLCMD; + return tty_mode_ioctl(tty, file, cmd, arg); } } diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index dd18af0ce676..1a3d80bfe9ea 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -428,7 +428,6 @@ static inline void smc911x_drop_pkt(struct net_device *dev) */ static inline void smc911x_rcv(struct net_device *dev) { - struct smc911x_local *lp = netdev_priv(dev); unsigned long ioaddr = dev->base_addr; unsigned int pkt_len, status; struct sk_buff *skb; @@ -473,6 +472,7 @@ 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(); @@ -1379,13 +1379,6 @@ static void smc911x_set_multicast_list(struct net_device *dev) unsigned int multicast_table[2]; unsigned int mcr, update_multicast = 0; unsigned long flags; - /* table for flipping the order of 5 bits */ - static const unsigned char invert5[] = - {0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0C, 0x1C, - 0x02, 0x12, 0x0A, 0x1A, 0x06, 0x16, 0x0E, 0x1E, - 0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0D, 0x1D, - 0x03, 0x13, 0x0B, 0x1B, 0x07, 0x17, 0x0F, 0x1F}; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); @@ -1432,7 +1425,7 @@ static void smc911x_set_multicast_list(struct net_device *dev) cur_addr = dev->mc_list; for (i = 0; i < dev->mc_count; i++, cur_addr = cur_addr->next) { - int position; + u32 position; /* do we have a pointer here? */ if (!cur_addr) @@ -1442,12 +1435,10 @@ static void smc911x_set_multicast_list(struct net_device *dev) if (!(*cur_addr->dmi_addr & 1)) continue; - /* only use the low order bits */ - position = crc32_le(~0, cur_addr->dmi_addr, 6) & 0x3f; + /* upper 6 bits are used as hash index */ + position = ether_crc(ETH_ALEN, cur_addr->dmi_addr)>>26; - /* do some messy swapping to put the bit in the right spot */ - multicast_table[invert5[position&0x1F]&0x1] |= - (1<<invert5[(position>>1)&0x1F]); + multicast_table[position>>5] |= 1 << (position&0x1f); } /* be sure I get rid of flags I might have set */ diff --git a/drivers/net/smc911x.h b/drivers/net/smc911x.h index 16a0edc078fd..d04e4fa35206 100644 --- a/drivers/net/smc911x.h +++ b/drivers/net/smc911x.h @@ -37,7 +37,7 @@ #define SMC_USE_16BIT 0 #define SMC_USE_32BIT 1 #define SMC_IRQ_SENSE IRQF_TRIGGER_FALLING -#elif CONFIG_SH_MAGIC_PANEL_R2 +#elif defined(CONFIG_SH_MAGIC_PANEL_R2) #define SMC_USE_SH_DMA 0 #define SMC_USE_16BIT 0 #define SMC_USE_32BIT 1 diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index 729fd28c08b5..07b7f7120e37 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -55,7 +55,7 @@ #define SMC_insw(a, r, p, l) readsw((a) + (r), p, l) #define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l) -#elif defined(CONFIG_BFIN) +#elif defined(CONFIG_BLACKFIN) #define SMC_IRQ_FLAGS IRQF_TRIGGER_HIGH #define RPC_LSA_DEFAULT RPC_LED_100_10 @@ -224,6 +224,21 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg) } } +#elif defined(CONFIG_MACH_ZYLONITE) + +#define SMC_CAN_USE_8BIT 1 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 0 +#define SMC_IO_SHIFT 0 +#define SMC_NOWAIT 1 +#define SMC_USE_PXA_DMA 1 +#define SMC_inb(a, r) readb((a) + (r)) +#define SMC_inw(a, r) readw((a) + (r)) +#define SMC_insw(a, r, p, l) insw((a) + (r), p, l) +#define SMC_outsw(a, r, p, l) outsw((a) + (r), p, l) +#define SMC_outb(v, a, r) writeb(v, (a) + (r)) +#define SMC_outw(v, a, r) writew(v, (a) + (r)) + #elif defined(CONFIG_ARCH_OMAP) /* We can only do 16-bit reads and writes in the static memory space. */ diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 53b8344a68ef..68872142530b 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -2281,14 +2281,12 @@ static void gem_reset_task(struct work_struct *work) mutex_lock(&gp->pm_mutex); - napi_disable(&gp->napi); + if (gp->opened) + napi_disable(&gp->napi); spin_lock_irq(&gp->lock); spin_lock(&gp->tx_lock); - if (gp->running == 0) - goto not_running; - if (gp->running) { netif_stop_queue(gp->dev); @@ -2298,13 +2296,14 @@ static void gem_reset_task(struct work_struct *work) gem_set_link_modes(gp); netif_wake_queue(gp->dev); } - not_running: + gp->reset_task_pending = 0; spin_unlock(&gp->tx_lock); spin_unlock_irq(&gp->lock); - napi_enable(&gp->napi); + if (gp->opened) + napi_enable(&gp->napi); mutex_unlock(&gp->pm_mutex); } @@ -2333,10 +2332,10 @@ static int gem_close(struct net_device *dev) { struct gem *gp = dev->priv; - napi_disable(&gp->napi); - mutex_lock(&gp->pm_mutex); + napi_disable(&gp->napi); + gp->opened = 0; if (!gp->asleep) gem_do_stop(dev, 0); @@ -2355,8 +2354,6 @@ static int gem_suspend(struct pci_dev *pdev, pm_message_t state) mutex_lock(&gp->pm_mutex); - napi_disable(&gp->napi); - printk(KERN_INFO "%s: suspending, WakeOnLan %s\n", dev->name, (gp->wake_on_lan && gp->opened) ? "enabled" : "disabled"); @@ -2370,6 +2367,8 @@ static int gem_suspend(struct pci_dev *pdev, pm_message_t state) /* If the driver is opened, we stop the MAC */ if (gp->opened) { + napi_disable(&gp->napi); + /* Stop traffic, mark us closed */ netif_device_detach(dev); @@ -2460,6 +2459,7 @@ static int gem_resume(struct pci_dev *pdev) /* Re-attach net device */ netif_device_attach(dev); + napi_enable(&gp->napi); } spin_lock_irqsave(&gp->lock, flags); @@ -2479,8 +2479,6 @@ static int gem_resume(struct pci_dev *pdev) spin_unlock(&gp->tx_lock); spin_unlock_irqrestore(&gp->lock, flags); - napi_enable(&gp->napi); - mutex_unlock(&gp->pm_mutex); return 0; diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index c20a3bd21bb2..9cc13dd8a821 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -1281,7 +1281,7 @@ static void happy_meal_init_rings(struct happy_meal *hp) skb->dev = dev; /* Because we reserve afterwards. */ - skb_put(skb, (ETH_FRAME_LEN + RX_OFFSET)); + skb_put(skb, (ETH_FRAME_LEN + RX_OFFSET + 4)); hme_write_rxd(hp, &hb->happy_meal_rxd[i], (RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16)), hme_dma_map(hp, skb->data, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE)); @@ -1700,6 +1700,11 @@ static int happy_meal_init(struct happy_meal *hp) HMD(("tx old[%08x] and rx [%08x] ON!\n", hme_read32(hp, bregs + BMAC_TXCFG), hme_read32(hp, bregs + BMAC_RXCFG))); + + /* Set larger TX/RX size to allow for 802.1q */ + hme_write32(hp, bregs + BMAC_TXMAX, ETH_FRAME_LEN + 8); + hme_write32(hp, bregs + BMAC_RXMAX, ETH_FRAME_LEN + 8); + hme_write32(hp, bregs + BMAC_TXCFG, hme_read32(hp, bregs + BMAC_TXCFG) | BIGMAC_TXCFG_ENABLE); hme_write32(hp, bregs + BMAC_RXCFG, @@ -2039,7 +2044,7 @@ static void happy_meal_rx(struct happy_meal *hp, struct net_device *dev) hme_dma_unmap(hp, dma_addr, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE); hp->rx_skbs[elem] = new_skb; new_skb->dev = dev; - skb_put(new_skb, (ETH_FRAME_LEN + RX_OFFSET)); + skb_put(new_skb, (ETH_FRAME_LEN + RX_OFFSET + 4)); hme_write_rxd(hp, this, (RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)), hme_dma_map(hp, new_skb->data, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE)); @@ -2809,8 +2814,8 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe dev->watchdog_timeo = 5*HZ; dev->ethtool_ops = &hme_ethtool_ops; - /* Happy Meal can do it all... except VLAN. */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_VLAN_CHALLENGED; + /* Happy Meal can do it all... */ + dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; dev->irq = sdev->irqs[0]; @@ -3143,8 +3148,8 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, dev->irq = pdev->irq; dev->dma = 0; - /* Happy Meal can do it all... except VLAN. */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_VLAN_CHALLENGED; + /* Happy Meal can do it all... */ + dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; #if defined(CONFIG_SBUS) && defined(CONFIG_PCI) /* Hook up PCI register/dma accessors. */ diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c index 4e1b84e6d66a..21230c97b2a0 100644 --- a/drivers/net/tehuti.c +++ b/drivers/net/tehuti.c @@ -2168,10 +2168,10 @@ bdx_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) { struct bdx_priv *priv = netdev->priv; - strncat(drvinfo->driver, BDX_DRV_NAME, sizeof(drvinfo->driver)); - strncat(drvinfo->version, BDX_DRV_VERSION, sizeof(drvinfo->version)); - strncat(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); - strncat(drvinfo->bus_info, pci_name(priv->pdev), + strlcat(drvinfo->driver, BDX_DRV_NAME, sizeof(drvinfo->driver)); + strlcat(drvinfo->version, BDX_DRV_VERSION, sizeof(drvinfo->version)); + strlcat(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); + strlcat(drvinfo->bus_info, pci_name(priv->pdev), sizeof(drvinfo->bus_info)); drvinfo->n_stats = ((priv->stats_flag) ? diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index cad519910767..4942f7d18937 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -64,8 +64,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.85" -#define DRV_MODULE_RELDATE "October 18, 2007" +#define DRV_MODULE_VERSION "3.86" +#define DRV_MODULE_RELDATE "November 9, 2007" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -1106,6 +1106,24 @@ static int tg3_phy_reset(struct tg3 *tp) if (err) return err; + if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) { + u32 val; + + val = tr32(TG3_CPMU_LSPD_1000MB_CLK); + if ((val & CPMU_LSPD_1000MB_MACCLK_MASK) == + CPMU_LSPD_1000MB_MACCLK_12_5) { + val &= ~CPMU_LSPD_1000MB_MACCLK_MASK; + udelay(40); + tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val); + } + + /* Disable GPHY autopowerdown. */ + tg3_writephy(tp, MII_TG3_MISC_SHDW, + MII_TG3_MISC_SHDW_WREN | + MII_TG3_MISC_SHDW_APD_SEL | + MII_TG3_MISC_SHDW_APD_WKTM_84MS); + } + out: if (tp->tg3_flags2 & TG3_FLG2_PHY_ADC_BUG) { tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); @@ -1297,6 +1315,8 @@ static void tg3_nvram_unlock(struct tg3 *); static void tg3_power_down_phy(struct tg3 *tp) { + u32 val; + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { u32 sg_dig_ctrl = tr32(SG_DIG_CTRL); @@ -1311,8 +1331,6 @@ static void tg3_power_down_phy(struct tg3 *tp) } if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { - u32 val; - tg3_bmcr_reset(tp); val = tr32(GRC_MISC_CFG); tw32_f(GRC_MISC_CFG, val | GRC_MISC_CFG_EPHY_IDDQ); @@ -1332,6 +1350,14 @@ static void tg3_power_down_phy(struct tg3 *tp) (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 && (tp->tg3_flags2 & TG3_FLG2_MII_SERDES))) return; + + if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) { + val = tr32(TG3_CPMU_LSPD_1000MB_CLK); + val &= ~CPMU_LSPD_1000MB_MACCLK_MASK; + val |= CPMU_LSPD_1000MB_MACCLK_12_5; + tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val); + } + tg3_writephy(tp, MII_BMCR, BMCR_PDOWN); } @@ -3126,6 +3152,23 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset) err = tg3_setup_copper_phy(tp, force_reset); } + if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 || + tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) { + u32 val, scale; + + val = tr32(TG3_CPMU_CLCK_STAT) & CPMU_CLCK_STAT_MAC_CLCK_MASK; + if (val == CPMU_CLCK_STAT_MAC_CLCK_62_5) + scale = 65; + else if (val == CPMU_CLCK_STAT_MAC_CLCK_6_25) + scale = 6; + else + scale = 12; + + val = tr32(GRC_MISC_CFG) & ~GRC_MISC_CFG_PRESCALAR_MASK; + val |= (scale << GRC_MISC_CFG_PRESCALAR_SHIFT); + tw32(GRC_MISC_CFG, val); + } + if (tp->link_config.active_speed == SPEED_1000 && tp->link_config.active_duplex == DUPLEX_HALF) tw32(MAC_TX_LENGTHS, @@ -5054,12 +5097,15 @@ static void tg3_restore_pci_state(struct tg3 *tp) pci_write_config_word(tp->pdev, PCI_COMMAND, tp->pci_cmd); - if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) { + if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) + pcie_set_readrq(tp->pdev, 4096); + else { pci_write_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE, tp->pci_cacheline_sz); pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER, tp->pci_lat_timer); } + /* Make sure PCI-X relaxed ordering bit is clear. */ if (tp->pcix_cap) { u16 pcix_cmd; @@ -6343,10 +6389,26 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tg3_write_sig_legacy(tp, RESET_KIND_INIT); - if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0) { + if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 || + tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) { val = tr32(TG3_CPMU_CTRL); val &= ~(CPMU_CTRL_LINK_AWARE_MODE | CPMU_CTRL_LINK_IDLE_MODE); tw32(TG3_CPMU_CTRL, val); + + val = tr32(TG3_CPMU_LSPD_10MB_CLK); + val &= ~CPMU_LSPD_10MB_MACCLK_MASK; + val |= CPMU_LSPD_10MB_MACCLK_6_25; + tw32(TG3_CPMU_LSPD_10MB_CLK, val); + + val = tr32(TG3_CPMU_LNK_AWARE_PWRMD); + val &= ~CPMU_LNK_AWARE_MACCLK_MASK; + val |= CPMU_LNK_AWARE_MACCLK_6_25; + tw32(TG3_CPMU_LNK_AWARE_PWRMD, val); + + val = tr32(TG3_CPMU_HST_ACC); + val &= ~CPMU_HST_ACC_MACCLK_MASK; + val |= CPMU_HST_ACC_MACCLK_6_25; + tw32(TG3_CPMU_HST_ACC, val); } /* This works around an issue with Athlon chipsets on @@ -8267,7 +8329,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) SUPPORTED_100baseT_Full | SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | - SUPPORTED_MII); + SUPPORTED_TP); cmd->port = PORT_TP; } else { cmd->supported |= SUPPORTED_FIBRE; @@ -8664,7 +8726,9 @@ static void tg3_get_ethtool_stats (struct net_device *dev, } #define NVRAM_TEST_SIZE 0x100 -#define NVRAM_SELFBOOT_FORMAT1_SIZE 0x14 +#define NVRAM_SELFBOOT_FORMAT1_0_SIZE 0x14 +#define NVRAM_SELFBOOT_FORMAT1_2_SIZE 0x18 +#define NVRAM_SELFBOOT_FORMAT1_3_SIZE 0x1c #define NVRAM_SELFBOOT_HW_SIZE 0x20 #define NVRAM_SELFBOOT_DATA_SIZE 0x1c @@ -8679,9 +8743,22 @@ static int tg3_test_nvram(struct tg3 *tp) if (magic == TG3_EEPROM_MAGIC) size = NVRAM_TEST_SIZE; else if ((magic & TG3_EEPROM_MAGIC_FW_MSK) == TG3_EEPROM_MAGIC_FW) { - if ((magic & 0xe00000) == 0x200000) - size = NVRAM_SELFBOOT_FORMAT1_SIZE; - else + if ((magic & TG3_EEPROM_SB_FORMAT_MASK) == + TG3_EEPROM_SB_FORMAT_1) { + switch (magic & TG3_EEPROM_SB_REVISION_MASK) { + case TG3_EEPROM_SB_REVISION_0: + size = NVRAM_SELFBOOT_FORMAT1_0_SIZE; + break; + case TG3_EEPROM_SB_REVISION_2: + size = NVRAM_SELFBOOT_FORMAT1_2_SIZE; + break; + case TG3_EEPROM_SB_REVISION_3: + size = NVRAM_SELFBOOT_FORMAT1_3_SIZE; + break; + default: + return 0; + } + } else return 0; } else if ((magic & TG3_EEPROM_MAGIC_HW_MSK) == TG3_EEPROM_MAGIC_HW) size = NVRAM_SELFBOOT_HW_SIZE; @@ -8708,8 +8785,17 @@ static int tg3_test_nvram(struct tg3 *tp) TG3_EEPROM_MAGIC_FW) { u8 *buf8 = (u8 *) buf, csum8 = 0; - for (i = 0; i < size; i++) - csum8 += buf8[i]; + if ((cpu_to_be32(buf[0]) & TG3_EEPROM_SB_REVISION_MASK) == + TG3_EEPROM_SB_REVISION_2) { + /* For rev 2, the csum doesn't include the MBA. */ + for (i = 0; i < TG3_EEPROM_SB_F1R2_MBA_OFF; i++) + csum8 += buf8[i]; + for (i = TG3_EEPROM_SB_F1R2_MBA_OFF + 4; i < size; i++) + csum8 += buf8[i]; + } else { + for (i = 0; i < size; i++) + csum8 += buf8[i]; + } if (csum8 == 0) { err = 0; @@ -9293,7 +9379,7 @@ static int tg3_test_loopback(struct tg3 *tp) if (err) return TG3_LOOPBACK_FAILED; - if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) { + if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) { int i; u32 status; @@ -9310,17 +9396,17 @@ static int tg3_test_loopback(struct tg3 *tp) if (status != CPMU_MUTEX_GNT_DRIVER) return TG3_LOOPBACK_FAILED; - cpmuctrl = tr32(TG3_CPMU_CTRL); - /* Turn off power management based on link speed. */ + cpmuctrl = tr32(TG3_CPMU_CTRL); tw32(TG3_CPMU_CTRL, - cpmuctrl & ~CPMU_CTRL_LINK_SPEED_MODE); + cpmuctrl & ~(CPMU_CTRL_LINK_SPEED_MODE | + CPMU_CTRL_LINK_AWARE_MODE)); } if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK)) err |= TG3_MAC_LOOPBACK_FAILED; - if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) { + if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) { tw32(TG3_CPMU_CTRL, cpmuctrl); /* Release the mutex */ @@ -10541,6 +10627,10 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL) tp->led_ctrl = LED_CTRL_MODE_PHY_2; + if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 || + tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) + tp->led_ctrl = LED_CTRL_MODE_MAC; + if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP) { tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT; if ((tp->pdev->subsystem_vendor == @@ -10859,7 +10949,7 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp) } if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) || - (tp->tg3_flags & TG3_FLG3_ENABLE_APE)) + (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) return; for (offset = TG3_NVM_DIR_START; @@ -11127,6 +11217,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) pcie_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP); if (pcie_cap != 0) { tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS; + + pcie_set_readrq(tp->pdev, 4096); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { u16 lnkctl; @@ -11307,9 +11400,16 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) { tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT; + if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 || + tp->pci_chip_rev_id == CHIPREV_ID_5784_A1 || + tp->pci_chip_rev_id == CHIPREV_ID_5761_A0 || + tp->pci_chip_rev_id == CHIPREV_ID_5761_A1) + tp->tg3_flags3 |= TG3_FLG3_5761_5784_AX_FIXES; + } + /* Set up tp->grc_local_ctrl before calling tg3_set_power_state(). * GPIO1 driven high will bring 5700's external PHY out of reset. * It is also used as eeprom write protect on LOMs. @@ -12464,6 +12564,28 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, goto err_out_iounmap; } + if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) { + if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) { + printk(KERN_ERR PFX "Cannot find proper PCI device " + "base address for APE, aborting.\n"); + err = -ENODEV; + goto err_out_iounmap; + } + + tg3reg_base = pci_resource_start(pdev, 2); + tg3reg_len = pci_resource_len(pdev, 2); + + tp->aperegs = ioremap_nocache(tg3reg_base, tg3reg_len); + if (tp->aperegs == 0UL) { + printk(KERN_ERR PFX "Cannot map APE registers, " + "aborting.\n"); + err = -ENOMEM; + goto err_out_iounmap; + } + + tg3_ape_lock_init(tp); + } + /* * Reset chip in case UNDI or EFI driver did not shutdown * DMA self test will enable WDMAC and we'll see (spurious) @@ -12478,7 +12600,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, err = tg3_test_dma(tp); if (err) { printk(KERN_ERR PFX "DMA engine test failed, aborting.\n"); - goto err_out_iounmap; + goto err_out_apeunmap; } /* Tigon3 can do ipv4 only... and some chips have buggy @@ -12501,28 +12623,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tg3_init_coal(tp); - if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) { - if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) { - printk(KERN_ERR PFX "Cannot find proper PCI device " - "base address for APE, aborting.\n"); - err = -ENODEV; - goto err_out_iounmap; - } - - tg3reg_base = pci_resource_start(pdev, 2); - tg3reg_len = pci_resource_len(pdev, 2); - - tp->aperegs = ioremap_nocache(tg3reg_base, tg3reg_len); - if (tp->aperegs == 0UL) { - printk(KERN_ERR PFX "Cannot map APE registers, " - "aborting.\n"); - err = -ENOMEM; - goto err_out_iounmap; - } - - tg3_ape_lock_init(tp); - } - pci_set_drvdata(pdev, dev); err = register_netdev(dev); diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 1d5b2a3dd29d..da18fb220712 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -109,6 +109,9 @@ #define CHIPREV_ID_5714_A2 0x9002 #define CHIPREV_ID_5906_A1 0xc001 #define CHIPREV_ID_5784_A0 0x5784000 +#define CHIPREV_ID_5784_A1 0x5784001 +#define CHIPREV_ID_5761_A0 0x5761000 +#define CHIPREV_ID_5761_A1 0x5761001 #define GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12) #define ASIC_REV_5700 0x07 #define ASIC_REV_5701 0x00 @@ -856,7 +859,31 @@ #define CPMU_CTRL_LINK_IDLE_MODE 0x00000200 #define CPMU_CTRL_LINK_AWARE_MODE 0x00000400 #define CPMU_CTRL_LINK_SPEED_MODE 0x00004000 -/* 0x3604 --> 0x365c unused */ +#define TG3_CPMU_LSPD_10MB_CLK 0x00003604 +#define CPMU_LSPD_10MB_MACCLK_MASK 0x001f0000 +#define CPMU_LSPD_10MB_MACCLK_6_25 0x00130000 +/* 0x3608 --> 0x360c unused */ + +#define TG3_CPMU_LSPD_1000MB_CLK 0x0000360c +#define CPMU_LSPD_1000MB_MACCLK_62_5 0x00000000 +#define CPMU_LSPD_1000MB_MACCLK_12_5 0x00110000 +#define CPMU_LSPD_1000MB_MACCLK_MASK 0x001f0000 +#define TG3_CPMU_LNK_AWARE_PWRMD 0x00003610 +#define CPMU_LNK_AWARE_MACCLK_MASK 0x001f0000 +#define CPMU_LNK_AWARE_MACCLK_6_25 0x00130000 +/* 0x3614 --> 0x361c unused */ + +#define TG3_CPMU_HST_ACC 0x0000361c +#define CPMU_HST_ACC_MACCLK_MASK 0x001f0000 +#define CPMU_HST_ACC_MACCLK_6_25 0x00130000 +/* 0x3620 --> 0x3630 unused */ + +#define TG3_CPMU_CLCK_STAT 0x00003630 +#define CPMU_CLCK_STAT_MAC_CLCK_MASK 0x001f0000 +#define CPMU_CLCK_STAT_MAC_CLCK_62_5 0x00000000 +#define CPMU_CLCK_STAT_MAC_CLCK_12_5 0x00110000 +#define CPMU_CLCK_STAT_MAC_CLCK_6_25 0x00130000 +/* 0x3634 --> 0x365c unused */ #define TG3_CPMU_MUTEX_REQ 0x0000365c #define CPMU_MUTEX_REQ_DRIVER 0x00001000 @@ -1537,6 +1564,12 @@ #define TG3_EEPROM_MAGIC 0x669955aa #define TG3_EEPROM_MAGIC_FW 0xa5000000 #define TG3_EEPROM_MAGIC_FW_MSK 0xff000000 +#define TG3_EEPROM_SB_FORMAT_MASK 0x00e00000 +#define TG3_EEPROM_SB_FORMAT_1 0x00200000 +#define TG3_EEPROM_SB_REVISION_MASK 0x001f0000 +#define TG3_EEPROM_SB_REVISION_0 0x00000000 +#define TG3_EEPROM_SB_REVISION_2 0x00020000 +#define TG3_EEPROM_SB_REVISION_3 0x00030000 #define TG3_EEPROM_MAGIC_HW 0xabcd #define TG3_EEPROM_MAGIC_HW_MSK 0xffff @@ -1691,6 +1724,12 @@ #define MII_TG3_ISTAT 0x1a /* IRQ status register */ #define MII_TG3_IMASK 0x1b /* IRQ mask register */ +#define MII_TG3_MISC_SHDW 0x1c +#define MII_TG3_MISC_SHDW_WREN 0x8000 +#define MII_TG3_MISC_SHDW_APD_SEL 0x2800 + +#define MII_TG3_MISC_SHDW_APD_WKTM_84MS 0x0001 + /* ISTAT/IMASK event bits */ #define MII_TG3_INT_LINKCHG 0x0002 #define MII_TG3_INT_SPEEDCHG 0x0004 @@ -1747,6 +1786,8 @@ /* APE convenience enumerations. */ #define TG3_APE_LOCK_MEM 4 +#define TG3_EEPROM_SB_F1R2_MBA_OFF 0x10 + /* There are two ways to manage the TX descriptors on the tigon3. * Either the descriptors are in host DMA'able memory, or they @@ -2352,6 +2393,7 @@ struct tg3 { u32 tg3_flags3; #define TG3_FLG3_NO_NVRAM_ADDR_TRANS 0x00000001 #define TG3_FLG3_ENABLE_APE 0x00000002 +#define TG3_FLG3_5761_5784_AX_FIXES 0x00000004 struct timer_list timer; u16 timer_counter; diff --git a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig index 49d7a290dbbc..20ac1503021e 100644 --- a/drivers/net/tulip/Kconfig +++ b/drivers/net/tulip/Kconfig @@ -24,8 +24,7 @@ config DE2104X will say Y here.) Do read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will + To compile this driver as a module, choose M here. The module will be called de2104x. config TULIP @@ -42,8 +41,7 @@ config TULIP will say Y here.) Do read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will + To compile this driver as a module, choose M here. The module will be called tulip. config TULIP_MWI @@ -104,8 +102,7 @@ config DE4X5 information is contained in <file:Documentation/networking/de4x5.txt>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will + To compile this driver as a module, choose M here. The module will be called de4x5. config WINBOND_840 @@ -129,8 +126,7 @@ config DM9102 (Ethernet) card, say Y. Some information is contained in the file <file:Documentation/networking/dmfe.txt>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will + To compile this driver as a module, choose M here. The module will be called dmfe. config ULI526X @@ -141,8 +137,7 @@ config ULI526X This driver is for ULi M5261/M5263 10/100M Ethernet Controller (<http://www.uli.com.tw/>). - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will + To compile this driver as a module, choose M here. The module will be called uli526x. config PCMCIA_XIRCOM @@ -154,8 +149,7 @@ config PCMCIA_XIRCOM as with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and ASIX. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will + To compile this driver as a module, choose M here. The module will be called xircom_cb. If unsure, say N. config PCMCIA_XIRTULIP @@ -168,8 +162,7 @@ config PCMCIA_XIRTULIP as with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and ASIX. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will + To compile this driver as a module, choose M here. The module will be called xircom_tulip_cb. If unsure, say N. endif # NET_TULIP diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c index ca90566d5bcd..b4891caeae5a 100644 --- a/drivers/net/tulip/dmfe.c +++ b/drivers/net/tulip/dmfe.c @@ -2118,8 +2118,8 @@ static int dmfe_suspend(struct pci_dev *pci_dev, pm_message_t state) pci_enable_wake(pci_dev, PCI_D3cold, 1); /* Power down device*/ - pci_set_power_state(pci_dev, pci_choose_state (pci_dev,state)); pci_save_state(pci_dev); + pci_set_power_state(pci_dev, pci_choose_state (pci_dev, state)); return 0; } @@ -2129,8 +2129,8 @@ static int dmfe_resume(struct pci_dev *pci_dev) struct net_device *dev = pci_get_drvdata(pci_dev); u32 tmp; - pci_restore_state(pci_dev); pci_set_power_state(pci_dev, PCI_D0); + pci_restore_state(pci_dev); /* Re-initilize DM910X board */ dmfe_init_dm910x(dev); diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index a3ff270593f1..7f689907ac28 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -1460,6 +1460,8 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth) if ((ugeth->phy_interface == PHY_INTERFACE_MODE_RMII) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) || + (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) || + (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { upsmr |= UPSMR_RPM; switch (ugeth->max_speed) { @@ -1557,6 +1559,8 @@ static void adjust_link(struct net_device *dev) if ((ugeth->phy_interface == PHY_INTERFACE_MODE_RMII) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) || + (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) || + (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { if (phydev->speed == SPEED_10) upsmr |= UPSMR_R10M; @@ -3795,6 +3799,10 @@ static phy_interface_t to_phy_interface(const char *phy_connection_type) return PHY_INTERFACE_MODE_RGMII; if (strcasecmp(phy_connection_type, "rgmii-id") == 0) return PHY_INTERFACE_MODE_RGMII_ID; + if (strcasecmp(phy_connection_type, "rgmii-txid") == 0) + return PHY_INTERFACE_MODE_RGMII_TXID; + if (strcasecmp(phy_connection_type, "rgmii-rxid") == 0) + return PHY_INTERFACE_MODE_RGMII_RXID; if (strcasecmp(phy_connection_type, "rtbi") == 0) return PHY_INTERFACE_MODE_RTBI; @@ -3889,6 +3897,8 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma case PHY_INTERFACE_MODE_GMII: case PHY_INTERFACE_MODE_RGMII: case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: case PHY_INTERFACE_MODE_TBI: case PHY_INTERFACE_MODE_RTBI: max_speed = SPEED_1000; diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 5a96d74e4ce8..a12c9c41b217 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -93,13 +93,9 @@ config USB_RTL8150 To compile this driver as a module, choose M here: the module will be called rtl8150. -config USB_USBNET_MII - tristate - default n - config USB_USBNET tristate "Multi-purpose USB Networking Framework" - select MII if USB_USBNET_MII != n + select MII ---help--- This driver supports several kinds of network links over USB, with "minidrivers" built around a common network driver core @@ -135,7 +131,6 @@ config USB_NET_AX8817X tristate "ASIX AX88xxx Based USB 2.0 Ethernet Adapters" depends on USB_USBNET && NET_ETHERNET select CRC32 - select USB_USBNET_MII default y help This option adds support for ASIX AX88xxx based USB 2.0 @@ -190,7 +185,6 @@ config USB_NET_DM9601 tristate "Davicom DM9601 based USB 1.1 10/100 ethernet devices" depends on USB_USBNET select CRC32 - select USB_USBNET_MII help This option adds support for Davicom DM9601 based USB 1.1 10/100 Ethernet adapters. @@ -225,7 +219,6 @@ config USB_NET_PLUSB config USB_NET_MCS7830 tristate "MosChip MCS7830 based Ethernet adapters" depends on USB_USBNET - select USB_USBNET_MII help Choose this option if you're using a 10/100 Ethernet USB2 adapter based on the MosChip 7830 controller. This includes diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 2c685734b7a4..1ffdd106f4c4 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -94,7 +94,7 @@ static void dm_write_async_callback(struct urb *urb) struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context; if (urb->status < 0) - printk(KERN_DEBUG "dm_write_async_callback() failed with %d", + printk(KERN_DEBUG "dm_write_async_callback() failed with %d\n", urb->status); kfree(req); diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index acd5f1c0e63a..8ed1fc5cbc70 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -683,9 +683,6 @@ done_nopm: * they'll probably want to use this base set. */ -#if defined(CONFIG_MII) || defined(CONFIG_MII_MODULE) -#define HAVE_MII - int usbnet_get_settings (struct net_device *net, struct ethtool_cmd *cmd) { struct usbnet *dev = netdev_priv(net); @@ -744,8 +741,6 @@ int usbnet_nway_reset(struct net_device *net) } EXPORT_SYMBOL_GPL(usbnet_nway_reset); -#endif /* HAVE_MII */ - void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *info) { struct usbnet *dev = netdev_priv(net); @@ -776,12 +771,10 @@ EXPORT_SYMBOL_GPL(usbnet_set_msglevel); /* drivers may override default ethtool_ops in their bind() routine */ static struct ethtool_ops usbnet_ethtool_ops = { -#ifdef HAVE_MII .get_settings = usbnet_get_settings, .set_settings = usbnet_set_settings, .get_link = usbnet_get_link, .nway_reset = usbnet_nway_reset, -#endif .get_drvinfo = usbnet_get_drvinfo, .get_msglevel = usbnet_get_msglevel, .set_msglevel = usbnet_set_msglevel, diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 5c4a92de9a07..35cd65d6b9ed 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -1242,6 +1242,9 @@ static int velocity_rx_refill(struct velocity_info *vptr) static int velocity_init_rd_ring(struct velocity_info *vptr) { int ret; + int mtu = vptr->dev->mtu; + + vptr->rx_buf_sz = (mtu <= ETH_DATA_LEN) ? PKT_BUF_SZ : mtu + 32; vptr->rd_info = kcalloc(vptr->options.numrx, sizeof(struct velocity_rd_info), GFP_KERNEL); @@ -1898,8 +1901,6 @@ static int velocity_open(struct net_device *dev) struct velocity_info *vptr = netdev_priv(dev); int ret; - vptr->rx_buf_sz = (dev->mtu <= 1504 ? PKT_BUF_SZ : dev->mtu + 32); - ret = velocity_init_rings(vptr); if (ret < 0) goto out; @@ -1963,6 +1964,11 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu) return -EINVAL; } + if (!netif_running(dev)) { + dev->mtu = new_mtu; + return 0; + } + if (new_mtu != oldmtu) { spin_lock_irqsave(&vptr->lock, flags); @@ -1973,12 +1979,6 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu) velocity_free_rd_ring(vptr); dev->mtu = new_mtu; - if (new_mtu > 8192) - vptr->rx_buf_sz = 9 * 1024; - else if (new_mtu > 4096) - vptr->rx_buf_sz = 8192; - else - vptr->rx_buf_sz = 4 * 1024; ret = velocity_init_rd_ring(vptr); if (ret < 0) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index e396c9d2af8d..5413dbf3d4ac 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -146,6 +146,7 @@ static void try_fill_recv(struct virtnet_info *vi) struct scatterlist sg[1+MAX_SKB_FRAGS]; int num, err; + sg_init_table(sg, 1+MAX_SKB_FRAGS); for (;;) { skb = netdev_alloc_skb(vi->dev, MAX_PACKET_LEN); if (unlikely(!skb)) @@ -197,8 +198,8 @@ again: if (vi->num < vi->max / 2) try_fill_recv(vi); - /* All done? */ - if (!skb) { + /* Out of packets? */ + if (received < budget) { netif_rx_complete(vi->dev, napi); if (unlikely(!vi->rvq->vq_ops->restart(vi->rvq)) && netif_rx_reschedule(vi->dev, napi)) @@ -231,6 +232,8 @@ static int start_xmit(struct sk_buff *skb, struct net_device *dev) const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; DECLARE_MAC_BUF(mac); + sg_init_table(sg, 1+MAX_SKB_FRAGS); + pr_debug("%s: xmit %p %s\n", dev->name, skb, print_mac(mac, dest)); free_old_xmit_skbs(vi); @@ -401,8 +404,12 @@ free: static void virtnet_remove(struct virtio_device *vdev) { - unregister_netdev(vdev->priv); - free_netdev(vdev->priv); + struct virtnet_info *vi = vdev->priv; + + vdev->config->del_vq(vi->svq); + vdev->config->del_vq(vi->rvq); + unregister_netdev(vi->dev); + free_netdev(vi->dev); } static struct virtio_device_id id_table[] = { diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index c48b1cc63fd5..1e89d4de1bb7 100644 --- a/drivers/net/wan/x25_asy.c +++ b/drivers/net/wan/x25_asy.c @@ -719,12 +719,8 @@ static int x25_asy_ioctl(struct tty_struct *tty, struct file *file, return 0; case SIOCSIFHWADDR: return -EINVAL; - /* Allow stty to read, but not set, the serial port */ - case TCGETS: - case TCGETA: - return n_tty_ioctl(tty, file, cmd, arg); default: - return -ENOIOCTLCMD; + return tty_mode_ioctl(tty, file, cmd, arg); } } diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index dae5c8d5a318..2b733c582915 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -325,7 +325,7 @@ config HERMES Cabletron/EnteraSys Roamabout, ELSA AirLancer, MELCO Buffalo, Avaya, IBM High Rate Wireless, Farralon Syyline, Samsung MagicLAN, Netgear MA401, LinkSys WPC-11, D-Link DWL-650, 3Com AirConnect, Intel - PRO/Wireless, and Symbol Spectrum24 High Rate amongst others. + IPW2011, and Symbol Spectrum24 High Rate amongst others. This option includes the guts of the driver, but in order to actually use a card you will also need to enable support for PCMCIA diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index e3c573e56b63..fdbc351ac333 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig @@ -61,16 +61,18 @@ config B43_PCMCIA If unsure, say N. -# LED support +# This config option automatically enables b43 LEDS support, +# if it's possible. config B43_LEDS bool - depends on B43 && MAC80211_LEDS + depends on B43 && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = B43) default y -# RFKILL support +# This config option automatically enables b43 RFKILL support, +# if it's possible. config B43_RFKILL bool - depends on B43 && RFKILL && RFKILL_INPUT && INPUT_POLLDEV + depends on B43 && (RFKILL = y || RFKILL = B43) && RFKILL_INPUT && (INPUT_POLLDEV = y || INPUT_POLLDEV = B43) default y config B43_DEBUG diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c index 734e70e1a06d..ef0075d9f9cb 100644 --- a/drivers/net/wireless/b43/debugfs.c +++ b/drivers/net/wireless/b43/debugfs.c @@ -128,7 +128,7 @@ static ssize_t shm_read_file(struct b43_wldev *dev, __le16 *le16buf = (__le16 *)buf; for (i = 0; i < 0x1000; i++) { - if (bufsize <= 0) + if (bufsize < sizeof(tmp)) break; tmp = b43_shm_read16(dev, B43_SHM_SHARED, 2 * i); le16buf[i] = cpu_to_le16(tmp); diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 5058e60e5703..b45eecc53c4a 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1566,7 +1566,7 @@ static void b43_release_firmware(struct b43_wldev *dev) static void b43_print_fw_helptext(struct b43_wl *wl) { b43err(wl, "You must go to " - "http://linuxwireless.org/en/users/Drivers/bcm43xx#devicefirmware " + "http://linuxwireless.org/en/users/Drivers/b43#devicefirmware " "and download the correct firmware (version 4).\n"); } @@ -2985,6 +2985,16 @@ static void b43_wireless_core_stop(struct b43_wldev *dev) if (b43_status(dev) < B43_STAT_STARTED) return; + + /* Disable and sync interrupts. We must do this before than + * setting the status to INITIALIZED, as the interrupt handler + * won't care about IRQs then. */ + spin_lock_irqsave(&wl->irq_lock, flags); + dev->irq_savedstate = b43_interrupt_disable(dev, B43_IRQ_ALL); + b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* flush */ + spin_unlock_irqrestore(&wl->irq_lock, flags); + b43_synchronize_irq(dev); + b43_set_status(dev, B43_STAT_INITIALIZED); mutex_unlock(&wl->mutex); @@ -2995,13 +3005,6 @@ static void b43_wireless_core_stop(struct b43_wldev *dev) ieee80211_stop_queues(wl->hw); //FIXME this could cause a deadlock, as mac80211 seems buggy. - /* Disable and sync interrupts. */ - spin_lock_irqsave(&wl->irq_lock, flags); - dev->irq_savedstate = b43_interrupt_disable(dev, B43_IRQ_ALL); - b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* flush */ - spin_unlock_irqrestore(&wl->irq_lock, flags); - b43_synchronize_irq(dev); - b43_mac_suspend(dev); free_irq(dev->dev->irq, dev); b43dbg(wl, "Wireless interface stopped\n"); @@ -3661,7 +3664,6 @@ static int b43_setup_modes(struct b43_wldev *dev, static void b43_wireless_core_detach(struct b43_wldev *dev) { - b43_rfkill_free(dev); /* We release firmware that late to not be required to re-request * is all the time when we reinit the core. */ b43_release_firmware(dev); @@ -3747,7 +3749,6 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) if (!wl->current_dev) wl->current_dev = dev; INIT_WORK(&dev->restart_work, b43_chip_reset); - b43_rfkill_alloc(dev); b43_radio_turn_off(dev, 1); b43_switch_analog(dev, 0); diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c index b242a9a90dd2..b79a6bd5396d 100644 --- a/drivers/net/wireless/b43/pcmcia.c +++ b/drivers/net/wireless/b43/pcmcia.c @@ -65,12 +65,12 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev) tuple_t tuple; cisparse_t parse; int err = -ENOMEM; - int res; + int res = 0; unsigned char buf[64]; ssb = kzalloc(sizeof(*ssb), GFP_KERNEL); if (!ssb) - goto out; + goto out_error; err = -ENODEV; tuple.DesiredTuple = CISTPL_CONFIG; @@ -96,10 +96,12 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev) dev->io.NumPorts2 = 0; dev->io.Attributes2 = 0; - win.Attributes = WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT; + win.Attributes = WIN_ADDR_SPACE_MEM | WIN_MEMORY_TYPE_CM | + WIN_ENABLE | WIN_DATA_WIDTH_16 | + WIN_USE_WAIT; win.Base = 0; win.Size = SSB_CORE_SIZE; - win.AccessSpeed = 1000; + win.AccessSpeed = 250; res = pcmcia_request_window(&dev, &win, &dev->win); if (res != CS_SUCCESS) goto err_kfree_ssb; @@ -108,21 +110,34 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev) mem.Page = 0; res = pcmcia_map_mem_page(dev->win, &mem); if (res != CS_SUCCESS) - goto err_kfree_ssb; + goto err_disable; + + dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_FIRST_SHARED; + dev->irq.IRQInfo1 = IRQ_LEVEL_ID | IRQ_SHARE_ID; + dev->irq.Handler = NULL; /* The handler is registered later. */ + dev->irq.Instance = NULL; + res = pcmcia_request_irq(dev, &dev->irq); + if (res != CS_SUCCESS) + goto err_disable; res = pcmcia_request_configuration(dev, &dev->conf); if (res != CS_SUCCESS) goto err_disable; err = ssb_bus_pcmciabus_register(ssb, dev, win.Base); + if (err) + goto err_disable; dev->priv = ssb; - out: - return err; - err_disable: + return 0; + +err_disable: pcmcia_disable_device(dev); - err_kfree_ssb: +err_kfree_ssb: kfree(ssb); +out_error: + printk(KERN_ERR "b43-pcmcia: Initialization failed (%d, %d)\n", + res, err); return err; } @@ -131,22 +146,21 @@ static void __devexit b43_pcmcia_remove(struct pcmcia_device *dev) struct ssb_bus *ssb = dev->priv; ssb_bus_unregister(ssb); - pcmcia_release_window(dev->win); pcmcia_disable_device(dev); kfree(ssb); dev->priv = NULL; } static struct pcmcia_driver b43_pcmcia_driver = { - .owner = THIS_MODULE, - .drv = { - .name = "b43-pcmcia", - }, - .id_table = b43_pcmcia_tbl, - .probe = b43_pcmcia_probe, - .remove = b43_pcmcia_remove, - .suspend = b43_pcmcia_suspend, - .resume = b43_pcmcia_resume, + .owner = THIS_MODULE, + .drv = { + .name = "b43-pcmcia", + }, + .id_table = b43_pcmcia_tbl, + .probe = b43_pcmcia_probe, + .remove = __devexit_p(b43_pcmcia_remove), + .suspend = b43_pcmcia_suspend, + .resume = b43_pcmcia_resume, }; int b43_pcmcia_init(void) diff --git a/drivers/net/wireless/b43/phy.c b/drivers/net/wireless/b43/phy.c index 3d4ed647c311..7ff091e69f05 100644 --- a/drivers/net/wireless/b43/phy.c +++ b/drivers/net/wireless/b43/phy.c @@ -2214,7 +2214,7 @@ int b43_phy_init_tssi2dbm_table(struct b43_wldev *dev) } dyn_tssi2dbm = kmalloc(64, GFP_KERNEL); if (dyn_tssi2dbm == NULL) { - b43err(dev->wl, "Could not allocate memory" + b43err(dev->wl, "Could not allocate memory " "for tssi2dbm table\n"); return -ENOMEM; } diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c index 800e0a61a7f5..9b1f905ffbf4 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c @@ -47,32 +47,35 @@ static void b43_rfkill_poll(struct input_polled_dev *poll_dev) struct b43_wldev *dev = poll_dev->private; struct b43_wl *wl = dev->wl; bool enabled; + bool report_change = 0; mutex_lock(&wl->mutex); B43_WARN_ON(b43_status(dev) < B43_STAT_INITIALIZED); enabled = b43_is_hw_radio_enabled(dev); if (unlikely(enabled != dev->radio_hw_enable)) { dev->radio_hw_enable = enabled; + report_change = 1; b43info(wl, "Radio hardware status changed to %s\n", enabled ? "ENABLED" : "DISABLED"); - mutex_unlock(&wl->mutex); + } + mutex_unlock(&wl->mutex); + + if (unlikely(report_change)) input_report_key(poll_dev->input, KEY_WLAN, enabled); - } else - mutex_unlock(&wl->mutex); } -/* Called when the RFKILL toggled in software. - * This is called without locking. */ +/* Called when the RFKILL toggled in software. */ static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state) { struct b43_wldev *dev = data; struct b43_wl *wl = dev->wl; int err = 0; - mutex_lock(&wl->mutex); - if (b43_status(dev) < B43_STAT_INITIALIZED) - goto out_unlock; + if (!wl->rfkill.registered) + return 0; + mutex_lock(&wl->mutex); + B43_WARN_ON(b43_status(dev) < B43_STAT_INITIALIZED); switch (state) { case RFKILL_STATE_ON: if (!dev->radio_hw_enable) { @@ -89,7 +92,6 @@ static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state) b43_radio_turn_off(dev, 0); break; } - out_unlock: mutex_unlock(&wl->mutex); @@ -98,11 +100,11 @@ out_unlock: char * b43_rfkill_led_name(struct b43_wldev *dev) { - struct b43_wl *wl = dev->wl; + struct b43_rfkill *rfk = &(dev->wl->rfkill); - if (!wl->rfkill.rfkill) + if (!rfk->registered) return NULL; - return rfkill_get_led_name(wl->rfkill.rfkill); + return rfkill_get_led_name(rfk->rfkill); } void b43_rfkill_init(struct b43_wldev *dev) @@ -111,53 +113,13 @@ void b43_rfkill_init(struct b43_wldev *dev) struct b43_rfkill *rfk = &(wl->rfkill); int err; - if (rfk->rfkill) { - err = rfkill_register(rfk->rfkill); - if (err) { - b43warn(wl, "Failed to register RF-kill button\n"); - goto err_free_rfk; - } - } - if (rfk->poll_dev) { - err = input_register_polled_device(rfk->poll_dev); - if (err) { - b43warn(wl, "Failed to register RF-kill polldev\n"); - goto err_free_polldev; - } - } - - return; -err_free_rfk: - rfkill_free(rfk->rfkill); - rfk->rfkill = NULL; -err_free_polldev: - input_free_polled_device(rfk->poll_dev); - rfk->poll_dev = NULL; -} - -void b43_rfkill_exit(struct b43_wldev *dev) -{ - struct b43_rfkill *rfk = &(dev->wl->rfkill); - - if (rfk->poll_dev) - input_unregister_polled_device(rfk->poll_dev); - if (rfk->rfkill) - rfkill_unregister(rfk->rfkill); -} - -void b43_rfkill_alloc(struct b43_wldev *dev) -{ - struct b43_wl *wl = dev->wl; - struct b43_rfkill *rfk = &(wl->rfkill); + rfk->registered = 0; + rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN); + if (!rfk->rfkill) + goto out_error; snprintf(rfk->name, sizeof(rfk->name), "b43-%s", wiphy_name(wl->hw->wiphy)); - - rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN); - if (!rfk->rfkill) { - b43warn(wl, "Failed to allocate RF-kill button\n"); - return; - } rfk->rfkill->name = rfk->name; rfk->rfkill->state = RFKILL_STATE_ON; rfk->rfkill->data = dev; @@ -165,18 +127,45 @@ void b43_rfkill_alloc(struct b43_wldev *dev) rfk->rfkill->user_claim_unsupported = 1; rfk->poll_dev = input_allocate_polled_device(); - if (rfk->poll_dev) { - rfk->poll_dev->private = dev; - rfk->poll_dev->poll = b43_rfkill_poll; - rfk->poll_dev->poll_interval = 1000; /* msecs */ - } else - b43warn(wl, "Failed to allocate RF-kill polldev\n"); + if (!rfk->poll_dev) + goto err_free_rfk; + rfk->poll_dev->private = dev; + rfk->poll_dev->poll = b43_rfkill_poll; + rfk->poll_dev->poll_interval = 1000; /* msecs */ + + err = rfkill_register(rfk->rfkill); + if (err) + goto err_free_polldev; + err = input_register_polled_device(rfk->poll_dev); + if (err) + goto err_unreg_rfk; + + rfk->registered = 1; + + return; +err_unreg_rfk: + rfkill_unregister(rfk->rfkill); +err_free_polldev: + input_free_polled_device(rfk->poll_dev); + rfk->poll_dev = NULL; +err_free_rfk: + rfkill_free(rfk->rfkill); + rfk->rfkill = NULL; +out_error: + rfk->registered = 0; + b43warn(wl, "RF-kill button init failed\n"); } -void b43_rfkill_free(struct b43_wldev *dev) +void b43_rfkill_exit(struct b43_wldev *dev) { struct b43_rfkill *rfk = &(dev->wl->rfkill); + if (!rfk->registered) + return; + rfk->registered = 0; + + input_unregister_polled_device(rfk->poll_dev); + rfkill_unregister(rfk->rfkill); input_free_polled_device(rfk->poll_dev); rfk->poll_dev = NULL; rfkill_free(rfk->rfkill); diff --git a/drivers/net/wireless/b43/rfkill.h b/drivers/net/wireless/b43/rfkill.h index 29544e8c9e5f..adacf936d815 100644 --- a/drivers/net/wireless/b43/rfkill.h +++ b/drivers/net/wireless/b43/rfkill.h @@ -15,14 +15,14 @@ struct b43_rfkill { struct rfkill *rfkill; /* The poll device for the RFKILL input button */ struct input_polled_dev *poll_dev; + /* Did initialization succeed? Used for freeing. */ + bool registered; /* The unique name of this rfkill switch */ - char name[32]; + char name[sizeof("b43-phy4294967295")]; }; -/* All the init functions return void, because we are not interested +/* The init function returns void, because we are not interested * in failing the b43 init process when rfkill init failed. */ -void b43_rfkill_alloc(struct b43_wldev *dev); -void b43_rfkill_free(struct b43_wldev *dev); void b43_rfkill_init(struct b43_wldev *dev); void b43_rfkill_exit(struct b43_wldev *dev); @@ -36,12 +36,6 @@ struct b43_rfkill { /* empty */ }; -static inline void b43_rfkill_alloc(struct b43_wldev *dev) -{ -} -static inline void b43_rfkill_free(struct b43_wldev *dev) -{ -} static inline void b43_rfkill_init(struct b43_wldev *dev) { } diff --git a/drivers/net/wireless/b43legacy/debugfs.c b/drivers/net/wireless/b43legacy/debugfs.c index eefa6fb79685..619b4534ef09 100644 --- a/drivers/net/wireless/b43legacy/debugfs.c +++ b/drivers/net/wireless/b43legacy/debugfs.c @@ -124,7 +124,7 @@ static ssize_t shm_read_file(struct b43legacy_wldev *dev, char *buf, size_t bufs __le16 *le16buf = (__le16 *)buf; for (i = 0; i < 0x1000; i++) { - if (bufsize <= 0) + if (bufsize < sizeof(tmp)) break; tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 2 * i); le16buf[i] = cpu_to_le16(tmp); diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c index 8cb3dc4c4745..83161d9af813 100644 --- a/drivers/net/wireless/b43legacy/dma.c +++ b/drivers/net/wireless/b43legacy/dma.c @@ -996,7 +996,7 @@ int b43legacy_dma_init(struct b43legacy_wldev *dev) err = ssb_dma_set_mask(dev->dev, dmamask); if (err) { -#ifdef BCM43XX_PIO +#ifdef CONFIG_B43LEGACY_PIO b43legacywarn(dev->wl, "DMA for this device not supported. " "Falling back to PIO\n"); dev->__using_pio = 1; diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index f0e56dfc9ecf..32d5e1785bda 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -1419,7 +1419,7 @@ static void b43legacy_release_firmware(struct b43legacy_wldev *dev) static void b43legacy_print_fw_helptext(struct b43legacy_wl *wl) { b43legacyerr(wl, "You must go to http://linuxwireless.org/en/users/" - "Drivers/bcm43xx#devicefirmware " + "Drivers/b43#devicefirmware " "and download the correct firmware (version 3).\n"); } @@ -2781,6 +2781,17 @@ static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev) if (b43legacy_status(dev) < B43legacy_STAT_STARTED) return; + + /* Disable and sync interrupts. We must do this before than + * setting the status to INITIALIZED, as the interrupt handler + * won't care about IRQs then. */ + spin_lock_irqsave(&wl->irq_lock, flags); + dev->irq_savedstate = b43legacy_interrupt_disable(dev, + B43legacy_IRQ_ALL); + b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); /* flush */ + spin_unlock_irqrestore(&wl->irq_lock, flags); + b43legacy_synchronize_irq(dev); + b43legacy_set_status(dev, B43legacy_STAT_INITIALIZED); mutex_unlock(&wl->mutex); @@ -2791,14 +2802,6 @@ static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev) ieee80211_stop_queues(wl->hw); /* FIXME this could cause a deadlock */ - /* Disable and sync interrupts. */ - spin_lock_irqsave(&wl->irq_lock, flags); - dev->irq_savedstate = b43legacy_interrupt_disable(dev, - B43legacy_IRQ_ALL); - b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); /* flush */ - spin_unlock_irqrestore(&wl->irq_lock, flags); - b43legacy_synchronize_irq(dev); - b43legacy_mac_suspend(dev); free_irq(dev->dev->irq, dev); b43legacydbg(wl, "Wireless interface stopped\n"); @@ -3332,7 +3335,7 @@ out_mutex_unlock: return err; } -void b43legacy_stop(struct ieee80211_hw *hw) +static void b43legacy_stop(struct ieee80211_hw *hw) { struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); struct b43legacy_wldev *dev = wl->current_dev; diff --git a/drivers/net/wireless/b43legacy/phy.c b/drivers/net/wireless/b43legacy/phy.c index 22a4b3d0186d..491e518e4aeb 100644 --- a/drivers/net/wireless/b43legacy/phy.c +++ b/drivers/net/wireless/b43legacy/phy.c @@ -2020,7 +2020,7 @@ int b43legacy_phy_init_tssi2dbm_table(struct b43legacy_wldev *dev) phy->idle_tssi = 62; dyn_tssi2dbm = kmalloc(64, GFP_KERNEL); if (dyn_tssi2dbm == NULL) { - b43legacyerr(dev->wl, "Could not allocate memory" + b43legacyerr(dev->wl, "Could not allocate memory " "for tssi2dbm table\n"); return -ENOMEM; } diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index b37f1e348700..af3de3343650 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -2149,7 +2149,7 @@ int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm) } dyn_tssi2dbm = kmalloc(64, GFP_KERNEL); if (dyn_tssi2dbm == NULL) { - printk(KERN_ERR PFX "Could not allocate memory" + printk(KERN_ERR PFX "Could not allocate memory " "for tssi2dbm table\n"); return -ENOMEM; } diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c index 7da3664b8515..fc876ba18572 100644 --- a/drivers/net/wireless/hostap/hostap_pci.c +++ b/drivers/net/wireless/hostap/hostap_pci.c @@ -444,7 +444,7 @@ static int prism2_pci_resume(struct pci_dev *pdev) MODULE_DEVICE_TABLE(pci, prism2_pci_id_table); -static struct pci_driver prism2_pci_drv_id = { +static struct pci_driver prism2_pci_driver = { .name = "hostap_pci", .id_table = prism2_pci_id_table, .probe = prism2_pci_probe, @@ -458,13 +458,13 @@ static struct pci_driver prism2_pci_drv_id = { static int __init init_prism2_pci(void) { - return pci_register_driver(&prism2_pci_drv_id); + return pci_register_driver(&prism2_pci_driver); } static void __exit exit_prism2_pci(void) { - pci_unregister_driver(&prism2_pci_drv_id); + pci_unregister_driver(&prism2_pci_driver); } diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 8d53d08b9691..fc6cdd8086c1 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -1267,7 +1267,7 @@ static int ipw2100_start_adapter(struct ipw2100_priv *priv) IPW2100_INTA_FATAL_ERROR | IPW2100_INTA_PARITY_ERROR); } - } while (i--); + } while (--i); /* Clear out any pending INTAs since we aren't supposed to have * interrupts enabled at this point... */ @@ -1339,7 +1339,7 @@ static int ipw2100_power_cycle_adapter(struct ipw2100_priv *priv) if (reg & IPW_AUX_HOST_RESET_REG_MASTER_DISABLED) break; - } while (i--); + } while (--i); priv->status &= ~STATUS_RESET_PENDING; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 262ab0b55824..c48b1b537d2b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -71,19 +71,19 @@ struct iwl_rate_scale_priv { }; static s32 iwl_expected_tpt_g[IWL_RATE_COUNT] = { - 0, 0, 76, 104, 130, 168, 191, 202, 7, 13, 35, 58 + 7, 13, 35, 58, 0, 0, 76, 104, 130, 168, 191, 202 }; static s32 iwl_expected_tpt_g_prot[IWL_RATE_COUNT] = { - 0, 0, 0, 80, 93, 113, 123, 125, 7, 13, 35, 58 + 7, 13, 35, 58, 0, 0, 0, 80, 93, 113, 123, 125 }; static s32 iwl_expected_tpt_a[IWL_RATE_COUNT] = { - 40, 57, 72, 98, 121, 154, 177, 186, 0, 0, 0, 0 + 0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186 }; static s32 iwl_expected_tpt_b[IWL_RATE_COUNT] = { - 0, 0, 0, 0, 0, 0, 0, 0, 7, 13, 35, 58 + 7, 13, 35, 58, 0, 0, 0, 0, 0, 0, 0, 0 }; struct iwl_tpt_entry { @@ -350,6 +350,10 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, sta->last_txrate = sta->txrate; + /* For MODE_IEEE80211A mode it start at IWL_FIRST_OFDM_RATE */ + if (local->hw.conf.phymode == MODE_IEEE80211A) + sta->last_txrate += IWL_FIRST_OFDM_RATE; + IWL_DEBUG_RATE("leave\n"); } @@ -417,6 +421,33 @@ static void rs_free_sta(void *priv, void *priv_sta) IWL_DEBUG_RATE("leave\n"); } + +/* + * get ieee prev rate from rate scale table. + * for A and B mode we need to overright prev + * value + */ +static int rs_adjust_next_rate(struct iwl_priv *priv, int rate) +{ + int next_rate = iwl_get_prev_ieee_rate(rate); + + switch (priv->phymode) { + case MODE_IEEE80211A: + if (rate == IWL_RATE_12M_INDEX) + next_rate = IWL_RATE_9M_INDEX; + else if (rate == IWL_RATE_6M_INDEX) + next_rate = IWL_RATE_6M_INDEX; + break; + case MODE_IEEE80211B: + if (rate == IWL_RATE_11M_INDEX_TABLE) + next_rate = IWL_RATE_5M_INDEX_TABLE; + break; + default: + break; + } + + return next_rate; +} /** * rs_tx_status - Update rate control values based on Tx results * @@ -479,7 +510,8 @@ static void rs_tx_status(void *priv_rate, last_index = scale_rate_index; } else { current_count = priv->retry_rate; - last_index = iwl_get_prev_ieee_rate(scale_rate_index); + last_index = rs_adjust_next_rate(priv, + scale_rate_index); } /* Update this rate accounting for as many retries @@ -494,9 +526,10 @@ static void rs_tx_status(void *priv_rate, if (retries) scale_rate_index = - iwl_get_prev_ieee_rate(scale_rate_index); + rs_adjust_next_rate(priv, scale_rate_index); } + /* Update the last index window with success/failure based on ACK */ IWL_DEBUG_RATE("Update rate %d with %s.\n", last_index, @@ -672,7 +705,10 @@ static struct ieee80211_rate *rs_get_rate(void *priv_rate, } rate_mask = sta->supp_rates; - index = min(sta->txrate & 0xffff, IWL_RATE_COUNT - 1); + index = min(sta->last_txrate & 0xffff, IWL_RATE_COUNT - 1); + + if (priv->phymode == (u8) MODE_IEEE80211A) + rate_mask = rate_mask << IWL_FIRST_OFDM_RATE; rs_priv = (void *)sta->rate_ctrl_priv; @@ -801,7 +837,11 @@ static struct ieee80211_rate *rs_get_rate(void *priv_rate, out: sta->last_txrate = index; - sta->txrate = sta->last_txrate; + if (priv->phymode == (u8) MODE_IEEE80211A) + sta->txrate = sta->last_txrate - IWL_FIRST_OFDM_RATE; + else + sta->txrate = sta->last_txrate; + sta_info_put(sta); IWL_DEBUG_RATE("leave: %d\n", index); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h index b926738e0ea1..bec4d3ffca1d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h @@ -36,10 +36,17 @@ struct iwl_rate_info { u8 next_rs; /* next rate used in rs algo */ u8 prev_rs_tgg; /* previous rate used in TGG rs algo */ u8 next_rs_tgg; /* next rate used in TGG rs algo */ + u8 table_rs_index; /* index in rate scale table cmd */ + u8 prev_table_rs; /* prev in rate table cmd */ + }; enum { - IWL_RATE_6M_INDEX = 0, + IWL_RATE_1M_INDEX = 0, + IWL_RATE_2M_INDEX, + IWL_RATE_5M_INDEX, + IWL_RATE_11M_INDEX, + IWL_RATE_6M_INDEX, IWL_RATE_9M_INDEX, IWL_RATE_12M_INDEX, IWL_RATE_18M_INDEX, @@ -47,16 +54,28 @@ enum { IWL_RATE_36M_INDEX, IWL_RATE_48M_INDEX, IWL_RATE_54M_INDEX, - IWL_RATE_1M_INDEX, - IWL_RATE_2M_INDEX, - IWL_RATE_5M_INDEX, - IWL_RATE_11M_INDEX, IWL_RATE_COUNT, IWL_RATE_INVM_INDEX, IWL_RATE_INVALID = IWL_RATE_INVM_INDEX }; enum { + IWL_RATE_6M_INDEX_TABLE = 0, + IWL_RATE_9M_INDEX_TABLE, + IWL_RATE_12M_INDEX_TABLE, + IWL_RATE_18M_INDEX_TABLE, + IWL_RATE_24M_INDEX_TABLE, + IWL_RATE_36M_INDEX_TABLE, + IWL_RATE_48M_INDEX_TABLE, + IWL_RATE_54M_INDEX_TABLE, + IWL_RATE_1M_INDEX_TABLE, + IWL_RATE_2M_INDEX_TABLE, + IWL_RATE_5M_INDEX_TABLE, + IWL_RATE_11M_INDEX_TABLE, + IWL_RATE_INVM_INDEX_TABLE = IWL_RATE_INVM_INDEX, +}; + +enum { IWL_FIRST_OFDM_RATE = IWL_RATE_6M_INDEX, IWL_LAST_OFDM_RATE = IWL_RATE_54M_INDEX, IWL_FIRST_CCK_RATE = IWL_RATE_1M_INDEX, diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 19bcb01e2784..3a45fe99a83e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -54,7 +54,9 @@ IWL_RATE_##rp##M_INDEX, \ IWL_RATE_##rn##M_INDEX, \ IWL_RATE_##pp##M_INDEX, \ - IWL_RATE_##np##M_INDEX } + IWL_RATE_##np##M_INDEX, \ + IWL_RATE_##r##M_INDEX_TABLE, \ + IWL_RATE_##ip##M_INDEX_TABLE } /* * Parameter order: @@ -65,6 +67,10 @@ * */ const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = { + IWL_DECLARE_RATE_INFO(1, INV, 2, INV, 2, INV, 2), /* 1mbps */ + IWL_DECLARE_RATE_INFO(2, 1, 5, 1, 5, 1, 5), /* 2mbps */ + IWL_DECLARE_RATE_INFO(5, 2, 6, 2, 11, 2, 11), /*5.5mbps */ + IWL_DECLARE_RATE_INFO(11, 9, 12, 5, 12, 5, 18), /* 11mbps */ IWL_DECLARE_RATE_INFO(6, 5, 9, 5, 11, 5, 11), /* 6mbps */ IWL_DECLARE_RATE_INFO(9, 6, 11, 5, 11, 5, 11), /* 9mbps */ IWL_DECLARE_RATE_INFO(12, 11, 18, 11, 18, 11, 18), /* 12mbps */ @@ -73,10 +79,6 @@ const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = { IWL_DECLARE_RATE_INFO(36, 24, 48, 24, 48, 24, 48), /* 36mbps */ IWL_DECLARE_RATE_INFO(48, 36, 54, 36, 54, 36, 54), /* 48mbps */ IWL_DECLARE_RATE_INFO(54, 48, INV, 48, INV, 48, INV),/* 54mbps */ - IWL_DECLARE_RATE_INFO(1, INV, 2, INV, 2, INV, 2), /* 1mbps */ - IWL_DECLARE_RATE_INFO(2, 1, 5, 1, 5, 1, 5), /* 2mbps */ - IWL_DECLARE_RATE_INFO(5, 2, 6, 2, 11, 2, 11), /*5.5mbps */ - IWL_DECLARE_RATE_INFO(11, 9, 12, 5, 12, 5, 18), /* 11mbps */ }; /* 1 = enable the iwl_disable_events() function */ @@ -662,10 +664,11 @@ void iwl_hw_build_tx_cmd_rate(struct iwl_priv *priv, cmd->cmd.tx.tx_flags = tx_flags; /* OFDM */ - cmd->cmd.tx.supp_rates[0] = rate_mask & IWL_OFDM_RATES_MASK; + cmd->cmd.tx.supp_rates[0] = + ((rate_mask & IWL_OFDM_RATES_MASK) >> IWL_FIRST_OFDM_RATE) & 0xFF; /* CCK */ - cmd->cmd.tx.supp_rates[1] = (rate_mask >> 8) & 0xF; + cmd->cmd.tx.supp_rates[1] = (rate_mask & 0xF); IWL_DEBUG_RATE("Tx sta id: %d, rate: %d (plcp), flags: 0x%4X " "cck/ofdm mask: 0x%x/0x%x\n", sta_id, @@ -1432,7 +1435,7 @@ static void iwl_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index, /* use this channel group's 6Mbit clipping/saturation pwr, * but cap at regulatory scan power restriction (set during init * based on eeprom channel data) for this channel. */ - power = min(ch_info->scan_power, clip_pwrs[IWL_RATE_6M_INDEX]); + power = min(ch_info->scan_power, clip_pwrs[IWL_RATE_6M_INDEX_TABLE]); /* further limit to user's max power preference. * FIXME: Other spectrum management power limitations do not @@ -1447,7 +1450,7 @@ static void iwl_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index, * *index*. */ power_index = ch_info->power_info[rate_index].power_table_index - (power - ch_info->power_info - [IWL_RATE_6M_INDEX].requested_power) * 2; + [IWL_RATE_6M_INDEX_TABLE].requested_power) * 2; /* store reference index that we use when adjusting *all* scan * powers. So we can accommodate user (all channel) or spectrum @@ -1476,7 +1479,7 @@ static void iwl_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index, */ int iwl_hw_reg_send_txpower(struct iwl_priv *priv) { - int rate_idx; + int rate_idx, i; const struct iwl_channel_info *ch_info = NULL; struct iwl_txpowertable_cmd txpower = { .channel = priv->active_rxon.channel, @@ -1500,20 +1503,36 @@ int iwl_hw_reg_send_txpower(struct iwl_priv *priv) } /* fill cmd with power settings for all rates for current channel */ - for (rate_idx = 0; rate_idx < IWL_RATE_COUNT; rate_idx++) { - txpower.power[rate_idx].tpc = ch_info->power_info[rate_idx].tpc; - txpower.power[rate_idx].rate = iwl_rates[rate_idx].plcp; + /* Fill OFDM rate */ + for (rate_idx = IWL_FIRST_OFDM_RATE, i = 0; + rate_idx <= IWL_LAST_OFDM_RATE; rate_idx++, i++) { + + txpower.power[i].tpc = ch_info->power_info[i].tpc; + txpower.power[i].rate = iwl_rates[rate_idx].plcp; IWL_DEBUG_POWER("ch %d:%d rf %d dsp %3d rate code 0x%02x\n", le16_to_cpu(txpower.channel), txpower.band, - txpower.power[rate_idx].tpc.tx_gain, - txpower.power[rate_idx].tpc.dsp_atten, - txpower.power[rate_idx].rate); + txpower.power[i].tpc.tx_gain, + txpower.power[i].tpc.dsp_atten, + txpower.power[i].rate); + } + /* Fill CCK rates */ + for (rate_idx = IWL_FIRST_CCK_RATE; + rate_idx <= IWL_LAST_CCK_RATE; rate_idx++, i++) { + txpower.power[i].tpc = ch_info->power_info[i].tpc; + txpower.power[i].rate = iwl_rates[rate_idx].plcp; + + IWL_DEBUG_POWER("ch %d:%d rf %d dsp %3d rate code 0x%02x\n", + le16_to_cpu(txpower.channel), + txpower.band, + txpower.power[i].tpc.tx_gain, + txpower.power[i].tpc.dsp_atten, + txpower.power[i].rate); } return iwl_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD, - sizeof(struct iwl_txpowertable_cmd), &txpower); + sizeof(struct iwl_txpowertable_cmd), &txpower); } @@ -1549,7 +1568,7 @@ static int iwl_hw_reg_set_new_power(struct iwl_priv *priv, power_info = ch_info->power_info; /* update OFDM Txpower settings */ - for (i = IWL_FIRST_OFDM_RATE; i <= IWL_LAST_OFDM_RATE; + for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE; i++, ++power_info) { int delta_idx; @@ -1573,14 +1592,14 @@ static int iwl_hw_reg_set_new_power(struct iwl_priv *priv, * ... all CCK power settings for a given channel are the *same*. */ if (power_changed) { power = - ch_info->power_info[IWL_RATE_12M_INDEX]. + ch_info->power_info[IWL_RATE_12M_INDEX_TABLE]. requested_power + IWL_CCK_FROM_OFDM_POWER_DIFF; /* do all CCK rates' iwl_channel_power_info structures */ - for (i = IWL_FIRST_CCK_RATE; i <= IWL_LAST_CCK_RATE; i++) { + for (i = IWL_RATE_1M_INDEX_TABLE; i <= IWL_RATE_11M_INDEX_TABLE; i++) { power_info->requested_power = power; power_info->base_power_index = - ch_info->power_info[IWL_RATE_12M_INDEX]. + ch_info->power_info[IWL_RATE_12M_INDEX_TABLE]. base_power_index + IWL_CCK_FROM_OFDM_INDEX_DIFF; ++power_info; } @@ -1674,7 +1693,7 @@ static int iwl_hw_reg_comp_txpower_temp(struct iwl_priv *priv) for (scan_tbl_index = 0; scan_tbl_index < IWL_NUM_SCAN_RATES; scan_tbl_index++) { s32 actual_index = (scan_tbl_index == 0) ? - IWL_RATE_1M_INDEX : IWL_RATE_6M_INDEX; + IWL_RATE_1M_INDEX_TABLE : IWL_RATE_6M_INDEX_TABLE; iwl_hw_reg_set_scan_power(priv, scan_tbl_index, actual_index, clip_pwrs, ch_info, a_band); @@ -1905,19 +1924,19 @@ static void iwl_hw_reg_init_channel_groups(struct iwl_priv *priv) for (rate_index = 0; rate_index < IWL_RATE_COUNT; rate_index++, clip_pwrs++) { switch (rate_index) { - case IWL_RATE_36M_INDEX: + case IWL_RATE_36M_INDEX_TABLE: if (i == 0) /* B/G */ *clip_pwrs = satur_pwr; else /* A */ *clip_pwrs = satur_pwr - 5; break; - case IWL_RATE_48M_INDEX: + case IWL_RATE_48M_INDEX_TABLE: if (i == 0) *clip_pwrs = satur_pwr - 7; else *clip_pwrs = satur_pwr - 10; break; - case IWL_RATE_54M_INDEX: + case IWL_RATE_54M_INDEX_TABLE: if (i == 0) *clip_pwrs = satur_pwr - 9; else @@ -2031,7 +2050,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv) } /* set tx power for CCK rates, based on OFDM 12 Mbit settings*/ - pwr_info = &ch_info->power_info[IWL_RATE_12M_INDEX]; + pwr_info = &ch_info->power_info[IWL_RATE_12M_INDEX_TABLE]; power = pwr_info->requested_power + IWL_CCK_FROM_OFDM_POWER_DIFF; pwr_index = pwr_info->power_table_index + @@ -2047,9 +2066,9 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv) /* fill each CCK rate's iwl_channel_power_info structure * NOTE: All CCK-rate Txpwrs are the same for a given chnl! * NOTE: CCK rates start at end of OFDM rates! */ - for (rate_index = IWL_OFDM_RATES; - rate_index < IWL_RATE_COUNT; rate_index++) { - pwr_info = &ch_info->power_info[rate_index]; + for (rate_index = 0; + rate_index < IWL_CCK_RATES; rate_index++) { + pwr_info = &ch_info->power_info[rate_index+IWL_OFDM_RATES]; pwr_info->requested_power = power; pwr_info->power_table_index = pwr_index; pwr_info->base_power_index = base_pwr_index; @@ -2061,7 +2080,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv) for (scan_tbl_index = 0; scan_tbl_index < IWL_NUM_SCAN_RATES; scan_tbl_index++) { s32 actual_index = (scan_tbl_index == 0) ? - IWL_RATE_1M_INDEX : IWL_RATE_6M_INDEX; + IWL_RATE_1M_INDEX_TABLE : IWL_RATE_6M_INDEX_TABLE; iwl_hw_reg_set_scan_power(priv, scan_tbl_index, actual_index, clip_pwrs, ch_info, a_band); } @@ -2139,17 +2158,20 @@ int iwl_hw_get_rx_read(struct iwl_priv *priv) */ int iwl3945_init_hw_rate_table(struct iwl_priv *priv) { - int rc, i; + int rc, i, index, prev_index; struct iwl_rate_scaling_cmd rate_cmd = { .reserved = {0, 0, 0}, }; struct iwl_rate_scaling_info *table = rate_cmd.table; for (i = 0; i < ARRAY_SIZE(iwl_rates); i++) { - table[i].rate_n_flags = + index = iwl_rates[i].table_rs_index; + + table[index].rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[i].plcp, 0); - table[i].try_cnt = priv->retry_rate; - table[i].next_rate_index = iwl_get_prev_ieee_rate(i); + table[index].try_cnt = priv->retry_rate; + prev_index = iwl_get_prev_ieee_rate(i); + table[index].next_rate_index = iwl_rates[prev_index].table_rs_index; } switch (priv->phymode) { @@ -2157,26 +2179,26 @@ int iwl3945_init_hw_rate_table(struct iwl_priv *priv) IWL_DEBUG_RATE("Select A mode rate scale\n"); /* If one of the following CCK rates is used, * have it fall back to the 6M OFDM rate */ - for (i = IWL_FIRST_CCK_RATE; i <= IWL_LAST_CCK_RATE; i++) - table[i].next_rate_index = IWL_FIRST_OFDM_RATE; + for (i = IWL_RATE_1M_INDEX_TABLE; i <= IWL_RATE_11M_INDEX_TABLE; i++) + table[i].next_rate_index = iwl_rates[IWL_FIRST_OFDM_RATE].table_rs_index; /* Don't fall back to CCK rates */ - table[IWL_RATE_12M_INDEX].next_rate_index = IWL_RATE_9M_INDEX; + table[IWL_RATE_12M_INDEX_TABLE].next_rate_index = IWL_RATE_9M_INDEX_TABLE; /* Don't drop out of OFDM rates */ - table[IWL_FIRST_OFDM_RATE].next_rate_index = - IWL_FIRST_OFDM_RATE; + table[IWL_RATE_6M_INDEX_TABLE].next_rate_index = + iwl_rates[IWL_FIRST_OFDM_RATE].table_rs_index; break; case MODE_IEEE80211B: IWL_DEBUG_RATE("Select B mode rate scale\n"); /* If an OFDM rate is used, have it fall back to the * 1M CCK rates */ - for (i = IWL_FIRST_OFDM_RATE; i <= IWL_LAST_OFDM_RATE; i++) - table[i].next_rate_index = IWL_FIRST_CCK_RATE; + for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE; i++) + table[i].next_rate_index = iwl_rates[IWL_FIRST_CCK_RATE].table_rs_index; /* CCK shouldn't fall back to OFDM... */ - table[IWL_RATE_11M_INDEX].next_rate_index = IWL_RATE_5M_INDEX; + table[IWL_RATE_11M_INDEX_TABLE].next_rate_index = IWL_RATE_5M_INDEX_TABLE; break; default: @@ -2248,22 +2270,12 @@ unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, tx_beacon_cmd->tx.tx_flags = (TX_CMD_FLG_SEQ_CTL_MSK | TX_CMD_FLG_TSF_MSK); - /* supp_rates[0] == OFDM */ - tx_beacon_cmd->tx.supp_rates[0] = IWL_OFDM_BASIC_RATES_MASK; - - /* supp_rates[1] == CCK - * - * NOTE: IWL_*_RATES_MASK are not in the order that supp_rates - * expects so we have to shift them around. - * - * supp_rates expects: - * CCK rates are bit0..3 - * - * However IWL_*_RATES_MASK has: - * CCK rates are bit8..11 - */ + /* supp_rates[0] == OFDM start at IWL_FIRST_OFDM_RATE*/ + tx_beacon_cmd->tx.supp_rates[0] = + (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; + tx_beacon_cmd->tx.supp_rates[1] = - (IWL_CCK_BASIC_RATES_MASK >> 8) & 0xF; + (IWL_CCK_BASIC_RATES_MASK & 0xF); return (sizeof(struct iwl_tx_beacon_cmd) + frame_size); } diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 4f22a7174caf..4bdf237f6adc 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2915,6 +2915,10 @@ static void iwl_set_rate(struct iwl_priv *priv) int i; hw = iwl_get_hw_mode(priv, priv->phymode); + if (!hw) { + IWL_ERROR("Failed to set rate: unable to get hw mode\n"); + return; + } priv->active_rate = 0; priv->active_rate_basic = 0; @@ -4850,7 +4854,7 @@ static irqreturn_t iwl_isr(int irq, void *data) if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { /* Hardware disappeared */ IWL_WARNING("HARDWARE GONE?? INTA == 0x%080x\n", inta); - goto none; + goto unplugged; } IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", @@ -4858,6 +4862,7 @@ static irqreturn_t iwl_isr(int irq, void *data) /* iwl_irq_tasklet() will service interrupts and re-enable them */ tasklet_schedule(&priv->irq_tasklet); +unplugged: spin_unlock(&priv->lock); return IRQ_HANDLED; @@ -5331,13 +5336,13 @@ static int iwl_init_geos(struct iwl_priv *priv) /* 5.2GHz channels start after the 2.4GHz channels */ modes[A].mode = MODE_IEEE80211A; modes[A].channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)]; - modes[A].rates = rates; + modes[A].rates = &rates[4]; modes[A].num_rates = 8; /* just OFDM */ modes[A].num_channels = 0; modes[B].mode = MODE_IEEE80211B; modes[B].channels = channels; - modes[B].rates = &rates[8]; + modes[B].rates = rates; modes[B].num_rates = 4; /* just CCK */ modes[B].num_channels = 0; @@ -6935,13 +6940,10 @@ static int iwl_mac_add_interface(struct ieee80211_hw *hw, DECLARE_MAC_BUF(mac); IWL_DEBUG_MAC80211("enter: id %d, type %d\n", conf->if_id, conf->type); - if (conf->mac_addr) - IWL_DEBUG_MAC80211("enter: MAC %s\n", - print_mac(mac, conf->mac_addr)); if (priv->interface_id) { IWL_DEBUG_MAC80211("leave - interface_id != 0\n"); - return 0; + return -EOPNOTSUPP; } spin_lock_irqsave(&priv->lock, flags); @@ -6950,6 +6952,12 @@ static int iwl_mac_add_interface(struct ieee80211_hw *hw, spin_unlock_irqrestore(&priv->lock, flags); mutex_lock(&priv->mutex); + + if (conf->mac_addr) { + IWL_DEBUG_MAC80211("Set: %s\n", print_mac(mac, conf->mac_addr)); + memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); + } + iwl_set_mode(priv, conf->type); IWL_DEBUG_MAC80211("leave\n"); @@ -8269,6 +8277,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) { iwl_hw_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); @@ -8354,6 +8363,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } SET_IEEE80211_DEV(hw, &pdev->dev); + hw->rate_control_algorithm = "iwl-3945-rs"; + IWL_DEBUG_INFO("*** LOAD DRIVER ***\n"); priv = hw->priv; priv->hw = hw; diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index d60adcb9bd4a..8f85564ec6fa 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -3003,6 +3003,10 @@ static void iwl_set_rate(struct iwl_priv *priv) int i; hw = iwl_get_hw_mode(priv, priv->phymode); + if (!hw) { + IWL_ERROR("Failed to set rate: unable to get hw mode\n"); + return; + } priv->active_rate = 0; priv->active_rate_basic = 0; @@ -5156,9 +5160,10 @@ static irqreturn_t iwl_isr(int irq, void *data) } if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { - /* Hardware disappeared */ + /* Hardware disappeared. It might have already raised + * an interrupt */ IWL_WARNING("HARDWARE GONE?? INTA == 0x%080x\n", inta); - goto none; + goto unplugged; } IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", @@ -5166,8 +5171,9 @@ static irqreturn_t iwl_isr(int irq, void *data) /* iwl_irq_tasklet() will service interrupts and re-enable them */ tasklet_schedule(&priv->irq_tasklet); - spin_unlock(&priv->lock); + unplugged: + spin_unlock(&priv->lock); return IRQ_HANDLED; none: @@ -7324,9 +7330,6 @@ static int iwl_mac_add_interface(struct ieee80211_hw *hw, DECLARE_MAC_BUF(mac); IWL_DEBUG_MAC80211("enter: id %d, type %d\n", conf->if_id, conf->type); - if (conf->mac_addr) - IWL_DEBUG_MAC80211("enter: MAC %s\n", - print_mac(mac, conf->mac_addr)); if (priv->interface_id) { IWL_DEBUG_MAC80211("leave - interface_id != 0\n"); @@ -7339,6 +7342,11 @@ static int iwl_mac_add_interface(struct ieee80211_hw *hw, spin_unlock_irqrestore(&priv->lock, flags); mutex_lock(&priv->mutex); + + if (conf->mac_addr) { + IWL_DEBUG_MAC80211("Set %s\n", print_mac(mac, conf->mac_addr)); + memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); + } iwl_set_mode(priv, conf->type); IWL_DEBUG_MAC80211("leave\n"); @@ -8862,6 +8870,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) { iwl_hw_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); @@ -8955,6 +8964,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } SET_IEEE80211_DEV(hw, &pdev->dev); + hw->rate_control_algorithm = "iwl-4965-rs"; + IWL_DEBUG_INFO("*** LOAD DRIVER ***\n"); priv = hw->priv; priv->hw = hw; diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 1cbbd96fdbde..be5cfd8402c7 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -912,6 +912,10 @@ static int wlan_cmd_set_boot2_ver(wlan_private * priv, return 0; } +/* + * Note: NEVER use libertas_queue_cmd() with addtail==0 other than for + * the command timer, because it does not account for queued commands. + */ void libertas_queue_cmd(wlan_adapter * adapter, struct cmd_ctrl_node *cmdnode, u8 addtail) { unsigned long flags; @@ -941,10 +945,11 @@ void libertas_queue_cmd(wlan_adapter * adapter, struct cmd_ctrl_node *cmdnode, u spin_lock_irqsave(&adapter->driver_lock, flags); - if (addtail) + if (addtail) { list_add_tail((struct list_head *)cmdnode, &adapter->cmdpendingq); - else + adapter->nr_cmd_pending++; + } else list_add((struct list_head *)cmdnode, &adapter->cmdpendingq); spin_unlock_irqrestore(&adapter->driver_lock, flags); @@ -1412,7 +1417,6 @@ int libertas_prepare_and_send_command(wlan_private * priv, cmdnode->cmdwaitqwoken = 0; libertas_queue_cmd(adapter, cmdnode, 1); - adapter->nr_cmd_pending++; wake_up_interruptible(&priv->waitq); if (wait_option & CMD_OPTION_WAITFORRSP) { diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 0360cad363a8..ba4fc2b3bf0a 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c @@ -148,11 +148,11 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r { int i; - for (i = 0; i < 500; i++) { + for (i = 0; i < 1000; i++) { u8 val = if_cs_read8(card, addr); if (val == reg) return i; - udelay(100); + udelay(500); } return -ETIME; } @@ -170,7 +170,8 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r #define IF_CS_H_IC_TX_OVER 0x0001 #define IF_CS_H_IC_RX_OVER 0x0002 #define IF_CS_H_IC_DNLD_OVER 0x0004 -#define IF_CS_H_IC_HOST_EVENT 0x0008 +#define IF_CS_H_IC_POWER_DOWN 0x0008 +#define IF_CS_H_IC_HOST_EVENT 0x0010 #define IF_CS_H_IC_MASK 0x001f #define IF_CS_H_INT_MASK 0x00000004 @@ -878,6 +879,9 @@ static int if_cs_probe(struct pcmcia_device *p_dev) goto out3; } + /* Clear any interrupt cause that happend while sending + * firmware/initializing card */ + if_cs_write16(card, IF_CS_C_INT_CAUSE, IF_CS_C_IC_MASK); if_cs_enable_ints(card); /* And finally bring the card up */ diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index a8e17076e7de..b24425f74883 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -182,12 +182,14 @@ static int if_sdio_handle_data(struct if_sdio_card *card, goto out; } - skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE); + skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + NET_IP_ALIGN); if (!skb) { ret = -ENOMEM; goto out; } + skb_reserve(skb, NET_IP_ALIGN); + data = skb_put(skb, size); memcpy(data, buffer, size); diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 5ead08312e1e..1823b48a8ba7 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -1165,8 +1165,6 @@ wlan_private *libertas_add_card(void *card, struct device *dmdev) #ifdef WIRELESS_EXT dev->wireless_handlers = (struct iw_handler_def *)&libertas_handler_def; #endif -#define NETIF_F_DYNALLOC 16 - dev->features |= NETIF_F_DYNALLOC; dev->flags |= IFF_BROADCAST | IFF_MULTICAST; dev->set_multicast_list = libertas_set_multicast_list; @@ -1348,8 +1346,6 @@ int libertas_add_mesh(wlan_private *priv, struct device *dev) #ifdef WIRELESS_EXT mesh_dev->wireless_handlers = (struct iw_handler_def *)&mesh_handler_def; #endif -#define NETIF_F_DYNALLOC 16 - /* Register virtual mesh interface */ ret = register_netdev(mesh_dev); if (ret) { diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index c6f5aa3cb465..395b7882d4d6 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -1528,7 +1528,7 @@ static int wlan_set_encodeext(struct net_device *dev, && (ext->key_len != KEY_LEN_WPA_TKIP)) || ((alg == IW_ENCODE_ALG_CCMP) && (ext->key_len != KEY_LEN_WPA_AES))) { - lbs_deb_wext("invalid size %d for key of alg" + lbs_deb_wext("invalid size %d for key of alg " "type %d\n", ext->key_len, alg); diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c index 2402cb8dd328..d2fa079fbc4c 100644 --- a/drivers/net/wireless/netwave_cs.c +++ b/drivers/net/wireless/netwave_cs.c @@ -806,7 +806,7 @@ static int netwave_pcmcia_config(struct pcmcia_device *link) { for (i = 0; i < 6; i++) dev->dev_addr[i] = readb(ramBase + NETWAVE_EREG_PA + i); - printk(KERN_INFO "%s: Netwave: port %#3lx, irq %d, mem %lx" + printk(KERN_INFO "%s: Netwave: port %#3lx, irq %d, mem %lx, " "id %c%c, hw_addr %s\n", dev->name, dev->base_addr, dev->irq, (u_long) ramBase, diff --git a/drivers/net/wireless/p54usb.c b/drivers/net/wireless/p54usb.c index 755482a5a938..60d286eb0b8b 100644 --- a/drivers/net/wireless/p54usb.c +++ b/drivers/net/wireless/p54usb.c @@ -308,7 +308,7 @@ static int p54u_read_eeprom(struct ieee80211_hw *dev) buf = kmalloc(0x2020, GFP_KERNEL); if (!buf) { - printk(KERN_ERR "prism54usb: cannot allocate memory for" + printk(KERN_ERR "prism54usb: cannot allocate memory for " "eeprom readback!\n"); return -ENOMEM; } diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index ff2d63267b19..702321c30164 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -620,7 +620,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) * up to version C the link tuning should halt after 20 * seconds. */ - if (rt2x00_get_rev(&rt2x00dev->chip) < RT2560_VERSION_D && + if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D && rt2x00dev->link.count > 20) return; @@ -630,7 +630,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) * Chipset versions C and lower should directly continue * to the dynamic CCA tuning. */ - if (rt2x00_get_rev(&rt2x00dev->chip) < RT2560_VERSION_D) + if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D) goto dynamic_cca_tune; /* diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 7cdc80a122bb..50775f9234cc 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -753,7 +753,7 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field16(®, MAC_CSR1_HOST_READY, 1); rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg); - if (rt2x00_get_rev(&rt2x00dev->chip) >= RT2570_VERSION_C) { + if (rt2x00_rev(&rt2x00dev->chip) >= RT2570_VERSION_C) { rt2500usb_register_read(rt2x00dev, PHY_CSR2, ®); reg &= ~0x0002; } else { @@ -1032,7 +1032,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, } static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, - int maxpacket, struct sk_buff *skb) + struct sk_buff *skb) { int length; @@ -1041,7 +1041,7 @@ static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, * but it must _not_ be a multiple of the USB packet size. */ length = roundup(skb->len, 2); - length += (2 * !(length % maxpacket)); + length += (2 * !(length % rt2x00dev->usb_maxpacket)); return length; } @@ -1257,7 +1257,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2500usb_register_read(rt2x00dev, MAC_CSR0, ®); rt2x00_set_chip(rt2x00dev, RT2570, value, reg); - if (rt2x00_rev(&rt2x00dev->chip, 0xffff0)) { + if (!rt2x00_check_rev(&rt2x00dev->chip, 0)) { ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); return -ENODEV; } @@ -1643,7 +1643,6 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, struct data_entry *beacon; struct data_entry *guardian; int pipe = usb_sndbulkpipe(usb_dev, 1); - int max_packet = usb_maxpacket(usb_dev, pipe, 1); int length; /* @@ -1672,7 +1671,7 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, ring->desc_size), skb->len - ring->desc_size, control); - length = rt2500usb_get_tx_data_len(rt2x00dev, max_packet, skb); + length = rt2500usb_get_tx_data_len(rt2x00dev, skb); usb_fill_bulk_urb(beacon->priv, usb_dev, pipe, skb->data, length, rt2500usb_beacondone, beacon); diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 9845e584b731..c8f16f161c28 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -418,7 +418,7 @@ struct rt2x00lib_ops { int (*write_tx_data) (struct rt2x00_dev *rt2x00dev, struct data_ring *ring, struct sk_buff *skb, struct ieee80211_tx_control *control); - int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev, int maxpacket, + int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev, unsigned int queue); @@ -599,6 +599,11 @@ struct rt2x00_dev { u32 *rf; /* + * USB Max frame size (for rt2500usb & rt73usb). + */ + u16 usb_maxpacket; + + /* * Current TX power value. */ u16 tx_power; @@ -751,14 +756,16 @@ static inline char rt2x00_rf(const struct rt2x00_chip *chipset, const u16 chip) return (chipset->rf == chip); } -static inline u16 rt2x00_get_rev(const struct rt2x00_chip *chipset) +static inline u16 rt2x00_rev(const struct rt2x00_chip *chipset) { return chipset->rev; } -static inline u16 rt2x00_rev(const struct rt2x00_chip *chipset, const u32 mask) +static inline u16 rt2x00_check_rev(const struct rt2x00_chip *chipset, + const u32 rev) { - return chipset->rev & mask; + return (((chipset->rev & 0xffff0) == rev) && + !!(chipset->rev & 0x0000f)); } /* diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 4a6a0bd01ff1..85ea8a8e658e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -196,6 +196,14 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, struct rt2x00_dev *rt2x00dev = hw->priv; struct interface *intf = &rt2x00dev->interface; + /* FIXME: Beaconing is broken in rt2x00. */ + if (conf->type == IEEE80211_IF_TYPE_IBSS || + conf->type == IEEE80211_IF_TYPE_AP) { + ERROR(rt2x00dev, + "rt2x00 does not support Adhoc or Master mode"); + return -EOPNOTSUPP; + } + /* * Don't allow interfaces to be added while * either the device has disappeared or when diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 73cc726c4046..1f5675dd329f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -159,7 +159,6 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev, interface_to_usbdev(rt2x00dev_usb(rt2x00dev)); struct data_entry *entry = rt2x00_get_data_entry(ring); int pipe = usb_sndbulkpipe(usb_dev, 1); - int max_packet = usb_maxpacket(usb_dev, pipe, 1); u32 length; if (rt2x00_ring_full(ring)) { @@ -194,8 +193,7 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev, * 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, - max_packet, skb); + length = rt2x00dev->ops->lib->get_tx_data_len(rt2x00dev, skb); /* * Initialize URB and send the frame to the device. @@ -490,6 +488,11 @@ int rt2x00usb_probe(struct usb_interface *usb_intf, rt2x00dev->ops = ops; rt2x00dev->hw = hw; + rt2x00dev->usb_maxpacket = + usb_maxpacket(usb_dev, usb_sndbulkpipe(usb_dev, 1), 1); + if (!rt2x00dev->usb_maxpacket) + rt2x00dev->usb_maxpacket = 1; + retval = rt2x00usb_alloc_reg(rt2x00dev); if (retval) goto exit_free_device; diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 46c8c0840a65..c0671c2e6e73 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1251,7 +1251,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, } static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, - int maxpacket, struct sk_buff *skb) + struct sk_buff *skb) { int length; @@ -1260,7 +1260,7 @@ static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, * but it must _not_ be a multiple of the USB packet size. */ length = roundup(skb->len, 4); - length += (4 * !(length % maxpacket)); + length += (4 * !(length % rt2x00dev->usb_maxpacket)); return length; } @@ -1486,7 +1486,7 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) rt73usb_register_read(rt2x00dev, MAC_CSR0, ®); rt2x00_set_chip(rt2x00dev, RT2571, value, reg); - if (!rt2x00_rev(&rt2x00dev->chip, 0x25730)) { + if (!rt2x00_check_rev(&rt2x00dev->chip, 0x25730)) { ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); return -ENODEV; } diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c index 4bd14b331862..88efe1bae58f 100644 --- a/drivers/net/wireless/strip.c +++ b/drivers/net/wireless/strip.c @@ -2735,16 +2735,8 @@ static int strip_ioctl(struct tty_struct *tty, struct file *file, return -EFAULT; return set_mac_address(strip_info, &addr); } - /* - * Allow stty to read, but not set, the serial port - */ - - case TCGETS: - case TCGETA: - return n_tty_ioctl(tty, file, cmd, arg); - break; default: - return -ENOIOCTLCMD; + return tty_mode_ioctl(tty, file, cmd, arg); break; } return 0; diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index a83c3db7d18f..c93d3d2640ab 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -64,6 +64,8 @@ int alloc_cpu_buffers(void) b->head_pos = 0; b->sample_received = 0; b->sample_lost_overflow = 0; + b->backtrace_aborted = 0; + b->sample_invalid_eip = 0; b->cpu = i; INIT_DELAYED_WORK(&b->work, wq_sync_buffer); } @@ -175,6 +177,11 @@ static int log_sample(struct oprofile_cpu_buffer * cpu_buf, unsigned long pc, cpu_buf->sample_received++; + if (pc == ESCAPE_CODE) { + cpu_buf->sample_invalid_eip++; + return 0; + } + if (nr_available_slots(cpu_buf) < 3) { cpu_buf->sample_lost_overflow++; return 0; diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h index 49900d9e3235..c66c025abe75 100644 --- a/drivers/oprofile/cpu_buffer.h +++ b/drivers/oprofile/cpu_buffer.h @@ -42,6 +42,7 @@ struct oprofile_cpu_buffer { unsigned long sample_received; unsigned long sample_lost_overflow; unsigned long backtrace_aborted; + unsigned long sample_invalid_eip; int cpu; struct delayed_work work; } ____cacheline_aligned; diff --git a/drivers/oprofile/oprofile_stats.c b/drivers/oprofile/oprofile_stats.c index f0acb661c253..d1f6d776e9e4 100644 --- a/drivers/oprofile/oprofile_stats.c +++ b/drivers/oprofile/oprofile_stats.c @@ -26,6 +26,8 @@ void oprofile_reset_stats(void) cpu_buf = &cpu_buffer[i]; cpu_buf->sample_received = 0; cpu_buf->sample_lost_overflow = 0; + cpu_buf->backtrace_aborted = 0; + cpu_buf->sample_invalid_eip = 0; } atomic_set(&oprofile_stats.sample_lost_no_mm, 0); @@ -61,6 +63,8 @@ void oprofile_create_stats_files(struct super_block * sb, struct dentry * root) &cpu_buf->sample_lost_overflow); oprofilefs_create_ro_ulong(sb, cpudir, "backtrace_aborted", &cpu_buf->backtrace_aborted); + oprofilefs_create_ro_ulong(sb, cpudir, "sample_invalid_eip", + &cpu_buf->sample_invalid_eip); } oprofilefs_create_ro_atomic(sb, dir, "sample_lost_no_mm", diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index f6cc0c5b5657..1ef417cca2db 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -66,7 +66,7 @@ struct slot { char name[SLOT_NAME_SIZE]; }; -/** +/* * struct acpiphp_bridge - PCI bridge information * * for each bridge device in ACPI namespace @@ -97,7 +97,7 @@ struct acpiphp_bridge { }; -/** +/* * struct acpiphp_slot - PCI slot information * * PCI slot information for each *physical* PCI slot @@ -118,7 +118,7 @@ struct acpiphp_slot { }; -/** +/* * struct acpiphp_func - PCI function information * * PCI function information for each object in ACPI namespace @@ -137,7 +137,7 @@ struct acpiphp_func { u32 flags; /* see below */ }; -/** +/* * struct acpiphp_attention_info - device specific attention registration * * ACPI has no generic method of setting/getting attention status diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index a0ca63adad5a..c8c263875c21 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c @@ -91,10 +91,10 @@ static struct hotplug_slot_ops acpi_hotplug_slot_ops = { * acpiphp_register_attention - set attention LED callback * @info: must be completely filled with LED callbacks * - * Description: this is used to register a hardware specific ACPI + * Description: This is used to register a hardware specific ACPI * driver that manipulates the attention LED. All the fields in * info must be set. - **/ + */ int acpiphp_register_attention(struct acpiphp_attention_info *info) { int retval = -EINVAL; @@ -112,10 +112,10 @@ int acpiphp_register_attention(struct acpiphp_attention_info *info) * acpiphp_unregister_attention - unset attention LED callback * @info: must match the pointer used to register * - * Description: this is used to un-register a hardware specific acpi + * Description: This is used to un-register a hardware specific acpi * driver that manipulates the attention LED. The pointer to the * info struct must be the same as the one used to set it. - **/ + */ int acpiphp_unregister_attention(struct acpiphp_attention_info *info) { int retval = -EINVAL; @@ -133,7 +133,6 @@ int acpiphp_unregister_attention(struct acpiphp_attention_info *info) * @hotplug_slot: slot to enable * * Actual tasks are done in acpiphp_enable_slot() - * */ static int enable_slot(struct hotplug_slot *hotplug_slot) { @@ -151,7 +150,6 @@ static int enable_slot(struct hotplug_slot *hotplug_slot) * @hotplug_slot: slot to disable * * Actual tasks are done in acpiphp_disable_slot() - * */ static int disable_slot(struct hotplug_slot *hotplug_slot) { @@ -168,15 +166,15 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) } - /** - * set_attention_status - set attention LED +/** + * set_attention_status - set attention LED * @hotplug_slot: slot to set attention LED on * @status: value to set attention LED to (0 or 1) * * attention status LED, so we use a callback that * was registered with us. This allows hardware specific * ACPI implementations to blink the light for us. - **/ + */ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) { int retval = -ENODEV; @@ -199,7 +197,6 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) * * Some platforms may not implement _STA method properly. * In that case, the value returned may not be reliable. - * */ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) { @@ -213,7 +210,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) } - /** +/** * get_attention_status - get attention LED status * @hotplug_slot: slot to get status from * @value: returns with value of attention LED @@ -221,8 +218,8 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) * ACPI doesn't have known method to determine the state * of the attention status LED, so we use a callback that * was registered with us. This allows hardware specific - * ACPI implementations to determine its state - **/ + * ACPI implementations to determine its state. + */ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) { int retval = -EINVAL; @@ -244,8 +241,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) * @value: pointer to store status * * ACPI doesn't provide any formal means to access latch status. - * Instead, we fake latch status from _STA - * + * Instead, we fake latch status from _STA. */ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) { @@ -265,8 +261,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) * @value: pointer to store status * * ACPI doesn't provide any formal means to access adapter status. - * Instead, we fake adapter status from _STA - * + * Instead, we fake adapter status from _STA. */ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) { diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 1e125b56c9a9..ff1b1c71291a 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -82,7 +82,6 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *contex * 2. has _PS0 method * 3. has _PS3 method * 4. .. - * */ static int is_ejectable(acpi_handle handle) { @@ -986,10 +985,8 @@ static int power_off_slot(struct acpiphp_slot *slot) /** - * acpiphp_max_busnr - return the highest reserved bus number under - * the given bus. + * acpiphp_max_busnr - return the highest reserved bus number under the given bus. * @bus: bus to start search with - * */ static unsigned char acpiphp_max_busnr(struct pci_bus *bus) { @@ -1018,7 +1015,6 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus) /** * acpiphp_bus_add - add a new bus to acpi subsystem * @func: acpiphp_func of the bridge - * */ static int acpiphp_bus_add(struct acpiphp_func *func) { @@ -1063,7 +1059,6 @@ acpiphp_bus_add_out: /** * acpiphp_bus_trim - trim a bus from acpi subsystem * @handle: handle to acpi namespace - * */ static int acpiphp_bus_trim(acpi_handle handle) { @@ -1089,7 +1084,6 @@ static int acpiphp_bus_trim(acpi_handle handle) * * This function should be called per *physical slot*, * not per each slot object in ACPI namespace. - * */ static int enable_device(struct acpiphp_slot *slot) { @@ -1185,6 +1179,7 @@ static void disable_bridges(struct pci_bus *bus) /** * disable_device - disable a slot + * @slot: ACPI PHP slot */ static int disable_device(struct acpiphp_slot *slot) { @@ -1240,14 +1235,15 @@ static int disable_device(struct acpiphp_slot *slot) /** * get_slot_status - get ACPI slot status + * @slot: ACPI PHP slot * - * if a slot has _STA for each function and if any one of them - * returned non-zero status, return it + * If a slot has _STA for each function and if any one of them + * returned non-zero status, return it. * - * if a slot doesn't have _STA and if any one of its functions' - * configuration space is configured, return 0x0f as a _STA + * If a slot doesn't have _STA and if any one of its functions' + * configuration space is configured, return 0x0f as a _STA. * - * otherwise return 0 + * Otherwise return 0. */ static unsigned int get_slot_status(struct acpiphp_slot *slot) { @@ -1281,6 +1277,7 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot) /** * acpiphp_eject_slot - physically eject the slot + * @slot: ACPI PHP slot */ int acpiphp_eject_slot(struct acpiphp_slot *slot) { @@ -1314,6 +1311,7 @@ int acpiphp_eject_slot(struct acpiphp_slot *slot) /** * acpiphp_check_bridge - re-enumerate devices + * @bridge: where to begin re-enumeration * * Iterate over all slots under this bridge and make sure that if a * card is present they are enabled, and if not they are disabled. @@ -1538,13 +1536,11 @@ check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) /** * handle_hotplug_event_bridge - handle ACPI event on bridges - * * @handle: Notify()'ed acpi_handle * @type: Notify code * @context: pointer to acpiphp_bridge structure * - * handles ACPI event notification on {host,p2p} bridges - * + * Handles ACPI event notification on {host,p2p} bridges. */ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *context) { @@ -1634,13 +1630,11 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont /** * handle_hotplug_event_func - handle ACPI event on functions (i.e. slots) - * * @handle: Notify()'ed acpi_handle * @type: Notify code * @context: pointer to acpiphp_func structure * - * handles ACPI event notification on slots - * + * Handles ACPI event notification on slots. */ static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context) { @@ -1705,7 +1699,6 @@ static struct acpi_pci_driver acpi_pci_hp_driver = { /** * acpiphp_glue_init - initializes all PCI hotplug - ACPI glue data structures - * */ int __init acpiphp_glue_init(void) { @@ -1726,7 +1719,7 @@ int __init acpiphp_glue_init(void) /** * acpiphp_glue_exit - terminates all PCI hotplug - ACPI glue data structures * - * This function frees all data allocated in acpiphp_glue_init() + * This function frees all data allocated in acpiphp_glue_init(). */ void acpiphp_glue_exit(void) { @@ -1760,7 +1753,6 @@ int __init acpiphp_get_num_slots(void) * acpiphp_for_each_slot - call function for each slot * @fn: callback function * @data: context to be passed to callback function - * */ static int acpiphp_for_each_slot(acpiphp_callback fn, void *data) { @@ -1786,6 +1778,7 @@ static int acpiphp_for_each_slot(acpiphp_callback fn, void *data) /** * acpiphp_enable_slot - power on slot + * @slot: ACPI PHP slot */ int acpiphp_enable_slot(struct acpiphp_slot *slot) { @@ -1815,6 +1808,7 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot) /** * acpiphp_disable_slot - power off slot + * @slot: ACPI PHP slot */ int acpiphp_disable_slot(struct acpiphp_slot *slot) { diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index 56829f82be4a..47d26b65e99a 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c @@ -134,11 +134,11 @@ static struct acpiphp_attention_info ibm_attention_info = * ibm_slot_from_id - workaround for bad ibm hardware * @id: the slot number that linux refers to the slot by * - * Description: this method returns the aCPI slot descriptor + * Description: This method returns the aCPI slot descriptor * corresponding to the Linux slot number. This descriptor * has info about the aPCI slot id and attention status. * This descriptor must be freed using kfree when done. - **/ + */ static union apci_descriptor *ibm_slot_from_id(int id) { int ind = 0, size; @@ -173,9 +173,9 @@ ibm_slot_done: * @slot: the hotplug_slot to work with * @status: what to set the LED to (0 or 1) * - * Description: this method is registered with the acpiphp module as a - * callback to do the device specific task of setting the LED status - **/ + * Description: This method is registered with the acpiphp module as a + * callback to do the device specific task of setting the LED status. + */ static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status) { union acpi_object args[2]; @@ -213,13 +213,13 @@ static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status) * @slot: the hotplug_slot to work with * @status: returns what the LED is set to (0 or 1) * - * Description: this method is registered with the acpiphp module as a - * callback to do the device specific task of getting the LED status + * Description: This method is registered with the acpiphp module as a + * callback to do the device specific task of getting the LED status. * * Because there is no direct method of getting the LED status directly * from an ACPI call, we read the aPCI table and parse out our * slot descriptor to read the status from that. - **/ + */ static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status) { union apci_descriptor *ibm_slot; @@ -245,8 +245,8 @@ static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status) * @event: the event info (device specific) * @context: passed context (our notification struct) * - * Description: this method is registered as a callback with the ACPI - * subsystem it is called when this device has an event to notify the OS of + * Description: This method is registered as a callback with the ACPI + * subsystem it is called when this device has an event to notify the OS of. * * The events actually come from the device as two events that get * synthesized into one event with data by this function. The event @@ -256,7 +256,7 @@ static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status) * From section 5.6.2.2 of the ACPI 2.0 spec, I understand that the OSPM will * only re-enable the interrupt that causes this event AFTER this method * has returned, thereby enforcing serial access for the notification struct. - **/ + */ static void ibm_handle_events(acpi_handle handle, u32 event, void *context) { u8 detail = event & 0x0f; @@ -279,16 +279,16 @@ static void ibm_handle_events(acpi_handle handle, u32 event, void *context) * ibm_get_table_from_acpi - reads the APLS buffer from ACPI * @bufp: address to pointer to allocate for the table * - * Description: this method reads the APLS buffer in from ACPI and + * Description: This method reads the APLS buffer in from ACPI and * stores the "stripped" table into a single buffer - * it allocates and passes the address back in bufp + * it allocates and passes the address back in bufp. * * If NULL is passed in as buffer, this method only calculates * the size of the table and returns that without filling - * in the buffer + * in the buffer. * - * returns < 0 on error or the size of the table on success - **/ + * Returns < 0 on error or the size of the table on success. + */ static int ibm_get_table_from_acpi(char **bufp) { union acpi_object *package; @@ -349,17 +349,18 @@ read_table_done: /** * ibm_read_apci_table - callback for the sysfs apci_table file * @kobj: the kobject this binary attribute is a part of + * @bin_attr: struct bin_attribute for this file * @buffer: the kernel space buffer to fill * @pos: the offset into the file * @size: the number of bytes requested * - * Description: gets registered with sysfs as the reader callback - * to be executed when /sys/bus/pci/slots/apci_table gets read + * Description: Gets registered with sysfs as the reader callback + * to be executed when /sys/bus/pci/slots/apci_table gets read. * * Since we don't get notified on open and close for this file, * things get really tricky here... - * our solution is to only allow reading the table in all at once - **/ + * our solution is to only allow reading the table in all at once. + */ static ssize_t ibm_read_apci_table(struct kobject *kobj, struct bin_attribute *bin_attr, char *buffer, loff_t pos, size_t size) @@ -385,10 +386,10 @@ static ssize_t ibm_read_apci_table(struct kobject *kobj, * @context: a pointer to our handle to fill when we find the device * @rv: a return value to fill if desired * - * Description: used as a callback when calling acpi_walk_namespace + * Description: Used as a callback when calling acpi_walk_namespace * to find our device. When this method returns non-zero - * acpi_walk_namespace quits its search and returns our value - **/ + * acpi_walk_namespace quits its search and returns our value. + */ static acpi_status __init ibm_find_acpi_device(acpi_handle handle, u32 lvl, void *context, void **rv) { diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index a96b739b2d35..74178875b949 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c @@ -117,12 +117,10 @@ static inline int is_slot66mhz(struct slot *slot) /** * detect_SMBIOS_pointer - find the System Management BIOS Table in mem region. - * * @begin: begin pointer for region to be scanned. * @end: end pointer for region to be scanned. * - * Returns pointer to the head of the SMBIOS tables (or NULL) - * + * Returns pointer to the head of the SMBIOS tables (or %NULL). */ static void __iomem * detect_SMBIOS_pointer(void __iomem *begin, void __iomem *end) { @@ -157,9 +155,9 @@ static void __iomem * detect_SMBIOS_pointer(void __iomem *begin, void __iomem *e /** * init_SERR - Initializes the per slot SERR generation. + * @ctrl: controller to use * * For unexpected switch opens - * */ static int init_SERR(struct controller * ctrl) { @@ -224,14 +222,15 @@ static int pci_print_IRQ_route (void) /** * get_subsequent_smbios_entry: get the next entry from bios table. - * - * Gets the first entry if previous == NULL - * Otherwise, returns the next entry - * Uses global SMBIOS Table pointer - * + * @smbios_start: where to start in the SMBIOS table + * @smbios_table: location of the SMBIOS table * @curr: %NULL or pointer to previously returned structure * - * returns a pointer to an SMBIOS structure or NULL if none found + * Gets the first entry if previous == NULL; + * otherwise, returns the next entry. + * Uses global SMBIOS Table pointer. + * + * Returns a pointer to an SMBIOS structure or NULL if none found. */ static void __iomem *get_subsequent_smbios_entry(void __iomem *smbios_start, void __iomem *smbios_table, @@ -272,17 +271,18 @@ static void __iomem *get_subsequent_smbios_entry(void __iomem *smbios_start, /** - * get_SMBIOS_entry - * - * @type:SMBIOS structure type to be returned + * get_SMBIOS_entry - return the requested SMBIOS entry or %NULL + * @smbios_start: where to start in the SMBIOS table + * @smbios_table: location of the SMBIOS table + * @type: SMBIOS structure type to be returned * @previous: %NULL or pointer to previously returned structure * - * Gets the first entry of the specified type if previous == NULL + * Gets the first entry of the specified type if previous == %NULL; * Otherwise, returns the next entry of the given type. - * Uses global SMBIOS Table pointer - * Uses get_subsequent_smbios_entry + * Uses global SMBIOS Table pointer. + * Uses get_subsequent_smbios_entry. * - * returns a pointer to an SMBIOS structure or %NULL if none found + * Returns a pointer to an SMBIOS structure or %NULL if none found. */ static void __iomem *get_SMBIOS_entry(void __iomem *smbios_start, void __iomem *smbios_table, @@ -581,7 +581,9 @@ get_slot_mapping(struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *slot) /** * cpqhp_set_attention_status - Turns the Amber LED for a slot on or off - * + * @ctrl: struct controller to use + * @func: PCI device/function info + * @status: LED control flag: 1 = LED on, 0 = LED off */ static int cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func, @@ -621,7 +623,8 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func, /** * set_attention_status - Turns the Amber LED for a slot on or off - * + * @hotplug_slot: slot to change LED on + * @status: LED control flag */ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) { diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c index 856d57b4d604..4018420c6f95 100644 --- a/drivers/pci/hotplug/cpqphp_ctrl.c +++ b/drivers/pci/hotplug/cpqphp_ctrl.c @@ -123,7 +123,7 @@ static u8 handle_switch_change(u8 change, struct controller * ctrl) } /** - * cpqhp_find_slot: find the struct slot of given device + * cpqhp_find_slot - find the struct slot of given device * @ctrl: scan lots of this controller * @device: the device id to find */ @@ -305,9 +305,8 @@ static u8 handle_power_fault(u8 change, struct controller * ctrl) /** - * sort_by_size: sort nodes on the list by their length, smallest first. + * sort_by_size - sort nodes on the list by their length, smallest first. * @head: list to sort - * */ static int sort_by_size(struct pci_resource **head) { @@ -354,9 +353,8 @@ static int sort_by_size(struct pci_resource **head) /** - * sort_by_max_size: sort nodes on the list by their length, largest first. + * sort_by_max_size - sort nodes on the list by their length, largest first. * @head: list to sort - * */ static int sort_by_max_size(struct pci_resource **head) { @@ -403,8 +401,10 @@ static int sort_by_max_size(struct pci_resource **head) /** - * do_pre_bridge_resource_split: find node of resources that are unused - * + * do_pre_bridge_resource_split - find node of resources that are unused + * @head: new list head + * @orig_head: original list head + * @alignment: max node size (?) */ static struct pci_resource *do_pre_bridge_resource_split(struct pci_resource **head, struct pci_resource **orig_head, u32 alignment) @@ -477,8 +477,9 @@ static struct pci_resource *do_pre_bridge_resource_split(struct pci_resource **h /** - * do_bridge_resource_split: find one node of resources that aren't in use - * + * do_bridge_resource_split - find one node of resources that aren't in use + * @head: list head + * @alignment: max node size (?) */ static struct pci_resource *do_bridge_resource_split(struct pci_resource **head, u32 alignment) { @@ -525,14 +526,13 @@ error: /** - * get_io_resource: find first node of given size not in ISA aliasing window. + * get_io_resource - find first node of given size not in ISA aliasing window. * @head: list to search * @size: size of node to find, must be a power of two. * - * Description: this function sorts the resource list by size and then returns + * Description: This function sorts the resource list by size and then returns * returns the first node of "size" length that is not in the ISA aliasing * window. If it finds a node larger than "size" it will split it up. - * */ static struct pci_resource *get_io_resource(struct pci_resource **head, u32 size) { @@ -620,7 +620,7 @@ static struct pci_resource *get_io_resource(struct pci_resource **head, u32 size /** - * get_max_resource: get largest node which has at least the given size. + * get_max_resource - get largest node which has at least the given size. * @head: the list to search the node in * @size: the minimum size of the node to find * @@ -712,7 +712,7 @@ static struct pci_resource *get_max_resource(struct pci_resource **head, u32 siz /** - * get_resource: find resource of given size and split up larger ones. + * get_resource - find resource of given size and split up larger ones. * @head: the list to search for resources * @size: the size limit to use * @@ -804,14 +804,14 @@ static struct pci_resource *get_resource(struct pci_resource **head, u32 size) /** - * cpqhp_resource_sort_and_combine: sort nodes by base addresses and clean up. + * cpqhp_resource_sort_and_combine - sort nodes by base addresses and clean up * @head: the list to sort and clean up * * Description: Sorts all of the nodes in the list in ascending order by * their base addresses. Also does garbage collection by * combining adjacent nodes. * - * returns 0 if success + * Returns %0 if success. */ int cpqhp_resource_sort_and_combine(struct pci_resource **head) { @@ -951,9 +951,9 @@ irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data) /** * cpqhp_slot_create - Creates a node and adds it to the proper bus. - * @busnumber - bus where new node is to be located + * @busnumber: bus where new node is to be located * - * Returns pointer to the new node or NULL if unsuccessful + * Returns pointer to the new node or %NULL if unsuccessful. */ struct pci_func *cpqhp_slot_create(u8 busnumber) { @@ -986,7 +986,7 @@ struct pci_func *cpqhp_slot_create(u8 busnumber) * slot_remove - Removes a node from the linked list of slots. * @old_slot: slot to remove * - * Returns 0 if successful, !0 otherwise. + * Returns %0 if successful, !0 otherwise. */ static int slot_remove(struct pci_func * old_slot) { @@ -1026,7 +1026,7 @@ static int slot_remove(struct pci_func * old_slot) * bridge_slot_remove - Removes a node from the linked list of slots. * @bridge: bridge to remove * - * Returns 0 if successful, !0 otherwise. + * Returns %0 if successful, !0 otherwise. */ static int bridge_slot_remove(struct pci_func *bridge) { @@ -1071,7 +1071,7 @@ out: * cpqhp_slot_find - Looks for a node by bus, and device, multiple functions accessed * @bus: bus to find * @device: device to find - * @index: is 0 for first function found, 1 for the second... + * @index: is %0 for first function found, %1 for the second... * * Returns pointer to the node if successful, %NULL otherwise. */ @@ -1115,16 +1115,13 @@ static int is_bridge(struct pci_func * func) /** - * set_controller_speed - set the frequency and/or mode of a specific - * controller segment. - * + * set_controller_speed - set the frequency and/or mode of a specific controller segment. * @ctrl: controller to change frequency/mode for. * @adapter_speed: the speed of the adapter we want to match. * @hp_slot: the slot number where the adapter is installed. * - * Returns 0 if we successfully change frequency and/or mode to match the + * Returns %0 if we successfully change frequency and/or mode to match the * adapter speed. - * */ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_slot) { @@ -1253,13 +1250,14 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_ /** * board_replaced - Called after a board has been replaced in the system. + * @func: PCI device/function information + * @ctrl: hotplug controller * - * This is only used if we don't have resources for hot add - * Turns power on for the board - * Checks to see if board is the same - * If board is same, reconfigures it + * This is only used if we don't have resources for hot add. + * Turns power on for the board. + * Checks to see if board is the same. + * If board is same, reconfigures it. * If board isn't same, turns it back off. - * */ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) { @@ -1403,10 +1401,11 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) /** * board_added - Called after a board has been added to the system. + * @func: PCI device/function info + * @ctrl: hotplug controller * - * Turns power on for the board - * Configures board - * + * Turns power on for the board. + * Configures board. */ static u32 board_added(struct pci_func *func, struct controller *ctrl) { @@ -1607,8 +1606,10 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) /** - * remove_board - Turns off slot and LED's - * + * remove_board - Turns off slot and LEDs + * @func: PCI device/function info + * @replace_flag: whether replacing or adding a new device + * @ctrl: target controller */ static u32 remove_board(struct pci_func * func, u32 replace_flag, struct controller * ctrl) { @@ -1902,11 +1903,11 @@ static void interrupt_event_handler(struct controller *ctrl) /** - * cpqhp_pushbutton_thread + * cpqhp_pushbutton_thread - handle pushbutton events + * @slot: target slot (struct) * - * Scheduled procedure to handle blocking stuff for the pushbuttons + * Scheduled procedure to handle blocking stuff for the pushbuttons. * Handles all pending events and exits. - * */ void cpqhp_pushbutton_thread(unsigned long slot) { @@ -2137,9 +2138,10 @@ int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func) } /** - * switch_leds: switch the leds, go from one site to the other. + * switch_leds - switch the leds, go from one site to the other. * @ctrl: controller to use * @num_of_slots: number of slots to use + * @work_LED: LED control value * @direction: 1 to start from the left side, 0 to start right. */ static void switch_leds(struct controller *ctrl, const int num_of_slots, @@ -2165,11 +2167,11 @@ static void switch_leds(struct controller *ctrl, const int num_of_slots, } /** - * hardware_test - runs hardware tests + * cpqhp_hardware_test - runs hardware tests + * @ctrl: target controller + * @test_num: the number written to the "test" file in sysfs. * * For hot plug ctrl folks to play with. - * test_num is the number written to the "test" file in sysfs - * */ int cpqhp_hardware_test(struct controller *ctrl, int test_num) { @@ -2249,14 +2251,12 @@ int cpqhp_hardware_test(struct controller *ctrl, int test_num) /** * configure_new_device - Configures the PCI header information of one board. - * * @ctrl: pointer to controller structure * @func: pointer to function structure * @behind_bridge: 1 if this is a recursive call, 0 if not * @resources: pointer to set of resource lists * - * Returns 0 if success - * + * Returns 0 if success. */ static u32 configure_new_device(struct controller * ctrl, struct pci_func * func, u8 behind_bridge, struct resource_lists * resources) @@ -2346,15 +2346,13 @@ static u32 configure_new_device(struct controller * ctrl, struct pci_func * func /** * configure_new_function - Configures the PCI header information of one device - * * @ctrl: pointer to controller structure * @func: pointer to function structure * @behind_bridge: 1 if this is a recursive call, 0 if not * @resources: pointer to set of resource lists * * Calls itself recursively for bridged devices. - * Returns 0 if success - * + * Returns 0 if success. */ static int configure_new_function(struct controller *ctrl, struct pci_func *func, u8 behind_bridge, diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c index 027f6865d7e3..d7a293e3faf5 100644 --- a/drivers/pci/hotplug/fakephp.c +++ b/drivers/pci/hotplug/fakephp.c @@ -165,11 +165,11 @@ static void remove_slot(struct dummy_slot *dslot) } /** - * Rescan slot. - * Tries hard not to re-enable already existing devices - * also handles scanning of subfunctions + * pci_rescan_slot - Rescan slot + * @temp: Device template. Should be set: bus and devfn. * - * @param temp Device template. Should be set: bus and devfn. + * Tries hard not to re-enable already existing devices; + * also handles scanning of subfunctions. */ static void pci_rescan_slot(struct pci_dev *temp) { @@ -229,10 +229,10 @@ static void pci_rescan_slot(struct pci_dev *temp) /** - * Rescan PCI bus. - * call pci_rescan_slot for each possible function of the bus + * pci_rescan_bus - Rescan PCI bus + * @bus: the PCI bus to rescan * - * @param bus + * Call pci_rescan_slot for each possible function of the bus. */ static void pci_rescan_bus(const struct pci_bus *bus) { diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index c8cb49c5a752..f1e0966cee95 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -208,10 +208,10 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) /** * board_added - Called after a board has been added to the system. + * @p_slot: &slot where board is added * - * Turns power on for the board - * Configures board - * + * Turns power on for the board. + * Configures board. */ static int board_added(struct slot *p_slot) { @@ -276,8 +276,8 @@ err_exit: } /** - * remove_board - Turns off slot and LED's - * + * remove_board - Turns off slot and LEDs + * @p_slot: slot where board is being removed */ static int remove_board(struct slot *p_slot) { @@ -319,11 +319,11 @@ struct power_work_info { }; /** - * pciehp_pushbutton_thread + * pciehp_power_thread - handle pushbutton events + * @work: &struct work_struct describing work to be done * - * Scheduled procedure to handle blocking stuff for the pushbuttons + * Scheduled procedure to handle blocking stuff for the pushbuttons. * Handles all pending events and exits. - * */ static void pciehp_power_thread(struct work_struct *work) { diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index deb6b5e35feb..b169b0e2647f 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c @@ -100,6 +100,7 @@ static struct device_node *find_dlpar_node(char *drc_name, int *node_type) /** * find_php_slot - return hotplug slot structure for device node + * @dn: target &device_node * * This routine will return the hotplug slot structure * for a given device node. Note that built-in PCI slots @@ -293,9 +294,8 @@ static int dlpar_add_vio_slot(char *drc_name, struct device_node *dn) * dlpar_add_slot - DLPAR add an I/O Slot * @drc_name: drc-name of newly added slot * - * Make the hotplug module and the kernel aware - * of a newly added I/O Slot. - * Return Codes - + * Make the hotplug module and the kernel aware of a newly added I/O Slot. + * Return Codes: * 0 Success * -ENODEV Not a valid drc_name * -EINVAL Slot already added @@ -339,9 +339,9 @@ exit: /** * dlpar_remove_vio_slot - DLPAR remove a virtual I/O Slot * @drc_name: drc-name of newly added slot + * @dn: &device_node * - * Remove the kernel and hotplug representations - * of an I/O Slot. + * Remove the kernel and hotplug representations of an I/O Slot. * Return Codes: * 0 Success * -EINVAL Vio dev doesn't exist @@ -359,11 +359,11 @@ static int dlpar_remove_vio_slot(char *drc_name, struct device_node *dn) } /** - * dlpar_remove_slot - DLPAR remove a PCI I/O Slot + * dlpar_remove_pci_slot - DLPAR remove a PCI I/O Slot * @drc_name: drc-name of newly added slot + * @dn: &device_node * - * Remove the kernel and hotplug representations - * of a PCI I/O Slot. + * Remove the kernel and hotplug representations of a PCI I/O Slot. * Return Codes: * 0 Success * -ENODEV Not a valid drc_name @@ -405,8 +405,7 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn) * dlpar_remove_slot - DLPAR remove an I/O Slot * @drc_name: drc-name of newly added slot * - * Remove the kernel and hotplug representations - * of an I/O Slot. + * Remove the kernel and hotplug representations of an I/O Slot. * Return Codes: * 0 Success * -ENODEV Not a valid drc_name diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index 458c08ef2654..58f1a9927709 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c @@ -54,10 +54,12 @@ module_param(debug, bool, 0644); /** * set_attention_status - set attention LED + * @hotplug_slot: target &hotplug_slot + * @value: LED control value + * * echo 0 > attention -- set LED OFF * echo 1 > attention -- set LED ON * echo 2 > attention -- set LED ID(identify, light is blinking) - * */ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value) { @@ -99,6 +101,8 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value) /** * get_attention_status - get attention LED status + * @hotplug_slot: slot to get status + * @value: pointer to store status */ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value) { @@ -254,6 +258,11 @@ static int is_php_type(char *drc_type) /** * is_php_dn() - return 1 if this is a hotpluggable pci slot, else 0 + * @dn: target &device_node + * @indexes: passed to get_children_props() + * @names: passed to get_children_props() + * @types: returned from get_children_props() + * @power_domains: * * This routine will return true only if the device node is * a hotpluggable slot. This routine will return false @@ -279,7 +288,7 @@ static int is_php_dn(struct device_node *dn, const int **indexes, /** * rpaphp_add_slot -- declare a hotplug slot to the hotplug subsystem. - * @dn device node of slot + * @dn: device node of slot * * This subroutine will register a hotplugable slot with the * PCI hotplug infrastructure. This routine is typicaly called @@ -291,7 +300,7 @@ static int is_php_dn(struct device_node *dn, const int **indexes, * routine will just return without doing anything, since embedded * slots cannot be hotplugged. * - * To remove a slot, it suffices to call rpaphp_deregister_slot() + * To remove a slot, it suffices to call rpaphp_deregister_slot(). */ int rpaphp_add_slot(struct device_node *dn) { diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index 54ca8650d511..0de84533cd80 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c @@ -79,6 +79,7 @@ static void set_slot_name(struct slot *slot) /** * rpaphp_enable_slot - record slot state, config pci device + * @slot: target &slot * * Initialize values in the slot, and the hotplug_slot info * structures to indicate if there is a pci card plugged into diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index d2fc35598cdd..eb5cac6f08ae 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -231,10 +231,10 @@ static int fix_bus_speed(struct controller *ctrl, struct slot *pslot, /** * board_added - Called after a board has been added to the system. + * @p_slot: target &slot * - * Turns power on for the board - * Configures board - * + * Turns power on for the board. + * Configures board. */ static int board_added(struct slot *p_slot) { @@ -350,8 +350,8 @@ err_exit: /** - * remove_board - Turns off slot and LED's - * + * remove_board - Turns off slot and LEDs + * @p_slot: target &slot */ static int remove_board(struct slot *p_slot) { @@ -397,11 +397,11 @@ struct pushbutton_work_info { }; /** - * shpchp_pushbutton_thread + * shpchp_pushbutton_thread - handle pushbutton events + * @work: &struct work_struct to be handled * - * Scheduled procedure to handle blocking stuff for the pushbuttons + * Scheduled procedure to handle blocking stuff for the pushbuttons. * Handles all pending events and exits. - * */ static void shpchp_pushbutton_thread(struct work_struct *work) { diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 1b7b2812bf2d..7d1877341aad 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -702,8 +702,10 @@ static int __init pci_sysfs_init(void) sysfs_initialized = 1; for_each_pci_dev(pdev) { retval = pci_create_sysfs_dev_files(pdev); - if (retval) + if (retval) { + pci_dev_put(pdev); return retval; + } } return 0; diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 92a8469b21ba..3c0d8d138f5a 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -168,11 +168,11 @@ static int find_device_iter(struct device *device, void *data) /** * find_source_device - search through device hierarchy for source device - * @p_dev: pointer to Root Port pci_dev data structure + * @parent: pointer to Root Port pci_dev data structure * @id: device ID of agent who sends an error message to this Root Port * * Invoked when error is detected at the Root Port. - **/ + */ static struct device* find_source_device(struct pci_dev *parent, u16 id) { struct pci_dev *dev = parent; @@ -286,14 +286,15 @@ static void report_resume(struct pci_dev *dev, void *data) /** * broadcast_error_message - handle message broadcast to downstream drivers - * @device: pointer to from where in a hierarchy message is broadcasted down - * @api: callback to be broadcasted + * @dev: pointer to from where in a hierarchy message is broadcasted down * @state: error state + * @error_mesg: message to print + * @cb: callback to be broadcasted * * Invoked during error recovery process. Once being invoked, the content * of error severity will be broadcasted to all downstream drivers in a * hierarchy in question. - **/ + */ static pci_ers_result_t broadcast_error_message(struct pci_dev *dev, enum pci_channel_state state, char *error_mesg, @@ -428,7 +429,7 @@ static pci_ers_result_t reset_link(struct pcie_device *aerdev, * Invoked when an error is nonfatal/fatal. Once being invoked, broadcast * error detected message to all downstream drivers within a hierarchy in * question and return the returned code. - **/ + */ static pci_ers_result_t do_recovery(struct pcie_device *aerdev, struct pci_dev *dev, int severity) @@ -488,7 +489,7 @@ static pci_ers_result_t do_recovery(struct pcie_device *aerdev, * @info: comprehensive error information * * Invoked when an error being detected by Root Port. - **/ + */ static void handle_error_source(struct pcie_device * aerdev, struct pci_dev *dev, struct aer_err_info info) @@ -521,7 +522,7 @@ static void handle_error_source(struct pcie_device * aerdev, * @rpc: pointer to a Root Port data structure * * Invoked when PCIE bus loads AER service driver. - **/ + */ void aer_enable_rootport(struct aer_rpc *rpc) { struct pci_dev *pdev = rpc->rpd->port; @@ -569,7 +570,7 @@ void aer_enable_rootport(struct aer_rpc *rpc) * @rpc: pointer to a Root Port data structure * * Invoked when PCIE bus unloads AER service driver. - **/ + */ static void disable_root_aer(struct aer_rpc *rpc) { struct pci_dev *pdev = rpc->rpd->port; @@ -590,7 +591,7 @@ static void disable_root_aer(struct aer_rpc *rpc) * @rpc: pointer to the root port which holds an error * * Invoked by DPC handler to consume an error. - **/ + */ static struct aer_err_source* get_e_source(struct aer_rpc *rpc) { struct aer_err_source *e_source; @@ -655,7 +656,7 @@ static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info) * aer_isr_one_error - consume an error detected by root port * @p_device: pointer to error root port service device * @e_src: pointer to an error source - **/ + */ static void aer_isr_one_error(struct pcie_device *p_device, struct aer_err_source *e_src) { @@ -706,7 +707,7 @@ static void aer_isr_one_error(struct pcie_device *p_device, * @work: definition of this work item * * Invoked, as DPC, when root port records new detected error - **/ + */ void aer_isr(struct work_struct *work) { struct aer_rpc *rpc = container_of(work, struct aer_rpc, dpc_handler); @@ -729,7 +730,7 @@ void aer_isr(struct work_struct *work) * @rpc: pointer to a root port device being deleted * * Invoked when AER service unloaded on a specific Root Port - **/ + */ void aer_delete_rootport(struct aer_rpc *rpc) { /* Disable root port AER itself */ @@ -743,7 +744,7 @@ void aer_delete_rootport(struct aer_rpc *rpc) * @dev: pointer to AER pcie device * * Invoked when AER service driver is loaded. - **/ + */ int aer_init(struct pcie_device *dev) { if (aer_osc_setup(dev) && !forceload) diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index df383645e366..26057f98f72e 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -217,7 +217,7 @@ static int slot_reset_iter(struct device *device, void *data) static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev) { - pci_ers_result_t status; + pci_ers_result_t status = PCI_ERS_RESULT_NONE; int retval; /* If fatal, restore cfg space for possible link reset at upstream */ diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index cd0a204d96d1..3c5eb374adf8 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -75,6 +75,7 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, { int i = 0; int irq; + int p, t; if (!valid_IRQ(gsi)) return; @@ -82,18 +83,27 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) && i < PNP_MAX_IRQ) i++; - if (i >= PNP_MAX_IRQ) + if (i >= PNP_MAX_IRQ) { + printk(KERN_ERR "pnpacpi: exceeded the max number of IRQ " + "resources: %d \n", PNP_MAX_IRQ); return; - -#ifdef CONFIG_X86 - if (gsi < 16 && (triggering != ACPI_EDGE_SENSITIVE || - polarity != ACPI_ACTIVE_HIGH)) { - pnp_warn("BIOS BUG: legacy PNP IRQ %d should be edge trigger, " - "active high", gsi); - triggering = ACPI_EDGE_SENSITIVE; - polarity = ACPI_ACTIVE_HIGH; } -#endif + /* + * in IO-APIC mode, use overrided attribute. Two reasons: + * 1. BIOS bug in DSDT + * 2. BIOS uses IO-APIC mode Interrupt Source Override + */ + if (!acpi_get_override_irq(gsi, &t, &p)) { + t = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE; + p = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; + + if (triggering != t || polarity != p) { + pnp_warn("IRQ %d override to %s, %s", + gsi, t ? "edge":"level", p ? "low":"high"); + triggering = t; + polarity = p; + } + } res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag res->irq_resource[i].flags |= irq_flags(triggering, polarity); @@ -173,6 +183,9 @@ static void pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, } res->dma_resource[i].start = dma; res->dma_resource[i].end = dma; + } else { + printk(KERN_ERR "pnpacpi: exceeded the max number of DMA " + "resources: %d \n", PNP_MAX_DMA); } } @@ -194,6 +207,9 @@ static void pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res, } res->port_resource[i].start = io; res->port_resource[i].end = io + len - 1; + } else { + printk(KERN_ERR "pnpacpi: exceeded the max number of IO " + "resources: %d \n", PNP_MAX_PORT); } } @@ -217,6 +233,9 @@ static void pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res, res->mem_resource[i].start = mem; res->mem_resource[i].end = mem + len - 1; + } else { + printk(KERN_ERR "pnpacpi: exceeded the max number of mem " + "resources: %d\n", PNP_MAX_MEM); } } diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index 41d73a5e9312..e50ebcffb962 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -367,8 +367,10 @@ int pnp_check_irq(struct pnp_dev *dev, int idx) { struct pci_dev *pci = NULL; for_each_pci_dev(pci) { - if (pci->irq == *irq) + if (pci->irq == *irq) { + pci_dev_put(pci); return 0; + } } } #endif diff --git a/drivers/ps3/Makefile b/drivers/ps3/Makefile index 746031de2195..1f5a2d33bf5b 100644 --- a/drivers/ps3/Makefile +++ b/drivers/ps3/Makefile @@ -1,6 +1,6 @@ -obj-$(CONFIG_PS3_VUART) += vuart.o +obj-$(CONFIG_PS3_VUART) += ps3-vuart.o obj-$(CONFIG_PS3_PS3AV) += ps3av_mod.o ps3av_mod-objs += ps3av.o ps3av_cmd.o obj-$(CONFIG_PPC_PS3) += sys-manager-core.o -obj-$(CONFIG_PS3_SYS_MANAGER) += sys-manager.o +obj-$(CONFIG_PS3_SYS_MANAGER) += ps3-sys-manager.o obj-$(CONFIG_PS3_STORAGE) += ps3stor_lib.o diff --git a/drivers/ps3/sys-manager.c b/drivers/ps3/ps3-sys-manager.c index 8461b08ab9fb..8461b08ab9fb 100644 --- a/drivers/ps3/sys-manager.c +++ b/drivers/ps3/ps3-sys-manager.c diff --git a/drivers/ps3/vuart.c b/drivers/ps3/ps3-vuart.c index 9dea585ef806..9dea585ef806 100644 --- a/drivers/ps3/vuart.c +++ b/drivers/ps3/ps3-vuart.c diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index cbde770eb121..1e6715ec51ef 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -36,7 +36,9 @@ config RTC_HCTOSYS_DEVICE help The RTC device that will be used to (re)initialize the system clock, usually rtc0. Initialization is done when the system - starts up, and when it resumes from a low power state. + starts up, and when it resumes from a low power state. This + device should record time in UTC, since the kernel won't do + timezone correction. The driver for this RTC device must be loaded before late_initcall functions run, so it must usually be statically linked. @@ -133,8 +135,8 @@ config RTC_DRV_DS1307 The first seven registers on these chips hold an RTC, and other registers may add features such as NVRAM, a trickle charger for - the RTC/NVRAM backup power, and alarms. This driver may not - expose all those available chip features. + the RTC/NVRAM backup power, and alarms. NVRAM is visible in + sysfs, but other chip features may not be available. This driver can also be built as a module. If so, the module will be called rtc-ds1307. @@ -445,7 +447,7 @@ config RTC_DRV_AT91RM9200 config RTC_DRV_BFIN tristate "Blackfin On-Chip RTC" - depends on BFIN + depends on BLACKFIN help If you say yes here you will get support for the Blackfin On-Chip Real Time Clock. diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c index 178527252c6a..33c0e98243ee 100644 --- a/drivers/rtc/hctosys.c +++ b/drivers/rtc/hctosys.c @@ -47,8 +47,8 @@ static int __init rtc_hctosys(void) do_settimeofday(&tv); dev_info(rtc->dev.parent, - "setting the system clock to " - "%d-%02d-%02d %02d:%02d:%02d (%u)\n", + "setting system clock to " + "%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, (unsigned int) tv.tv_sec); diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index de0da545c7a1..a4f56e95cf96 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -293,7 +293,7 @@ int rtc_irq_register(struct rtc_device *rtc, struct rtc_task *task) return -EINVAL; /* Cannot register while the char dev is in use */ - if (!(mutex_trylock(&rtc->char_lock))) + if (test_and_set_bit(RTC_DEV_BUSY, &rtc->flags)) return -EBUSY; spin_lock_irq(&rtc->irq_task_lock); @@ -303,7 +303,7 @@ int rtc_irq_register(struct rtc_device *rtc, struct rtc_task *task) } spin_unlock_irq(&rtc->irq_task_lock); - mutex_unlock(&rtc->char_lock); + clear_bit(RTC_DEV_BUSY, &rtc->flags); return retval; } diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 814583bd2fe7..ae1bf177d625 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c @@ -26,10 +26,7 @@ static int rtc_dev_open(struct inode *inode, struct file *file) struct rtc_device, char_dev); const struct rtc_class_ops *ops = rtc->ops; - /* We keep the lock as long as the device is in use - * and return immediately if busy - */ - if (!(mutex_trylock(&rtc->char_lock))) + if (test_and_set_bit(RTC_DEV_BUSY, &rtc->flags)) return -EBUSY; file->private_data = rtc; @@ -43,8 +40,8 @@ static int rtc_dev_open(struct inode *inode, struct file *file) return 0; } - /* something has gone wrong, release the lock */ - mutex_unlock(&rtc->char_lock); + /* something has gone wrong */ + clear_bit(RTC_DEV_BUSY, &rtc->flags); return err; } @@ -405,7 +402,7 @@ static int rtc_dev_release(struct inode *inode, struct file *file) if (rtc->ops->release) rtc->ops->release(rtc->dev.parent); - mutex_unlock(&rtc->char_lock); + clear_bit(RTC_DEV_BUSY, &rtc->flags); return 0; } @@ -440,7 +437,6 @@ void rtc_dev_prepare(struct rtc_device *rtc) rtc->dev.devt = MKDEV(MAJOR(rtc_devt), rtc->id); - mutex_init(&rtc->char_lock); #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL INIT_WORK(&rtc->uie_task, rtc_uie_task); setup_timer(&rtc->uie_timer, rtc_uie_timer, (unsigned long)rtc); diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index db6f3f0d8982..bc1c7fe94ad3 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -89,6 +89,7 @@ enum ds_type { struct ds1307 { u8 reg_addr; + bool has_nvram; u8 regs[8]; enum ds_type type; struct i2c_msg msg[2]; @@ -242,6 +243,87 @@ static const struct rtc_class_ops ds13xx_rtc_ops = { .set_time = ds1307_set_time, }; +/*----------------------------------------------------------------------*/ + +#define NVRAM_SIZE 56 + +static ssize_t +ds1307_nvram_read(struct kobject *kobj, struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client; + struct ds1307 *ds1307; + struct i2c_msg msg[2]; + int result; + + client = to_i2c_client(container_of(kobj, struct device, kobj)); + ds1307 = i2c_get_clientdata(client); + + if (unlikely(off >= NVRAM_SIZE)) + return 0; + if ((off + count) > NVRAM_SIZE) + count = NVRAM_SIZE - off; + if (unlikely(!count)) + return count; + + msg[0].addr = client->addr; + msg[0].flags = 0; + msg[0].len = 1; + msg[0].buf = buf; + + buf[0] = 8 + off; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].len = count; + msg[1].buf = buf; + + result = i2c_transfer(to_i2c_adapter(client->dev.parent), msg, 2); + if (result != 2) { + dev_err(&client->dev, "%s error %d\n", "nvram read", result); + return -EIO; + } + return count; +} + +static ssize_t +ds1307_nvram_write(struct kobject *kobj, struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client; + u8 buffer[NVRAM_SIZE + 1]; + int ret; + + client = to_i2c_client(container_of(kobj, struct device, kobj)); + + if (unlikely(off >= NVRAM_SIZE)) + return -EFBIG; + if ((off + count) > NVRAM_SIZE) + count = NVRAM_SIZE - off; + if (unlikely(!count)) + return count; + + buffer[0] = 8 + off; + memcpy(buffer + 1, buf, count); + + ret = i2c_master_send(client, buffer, count + 1); + return (ret < 0) ? ret : (ret - 1); +} + +static struct bin_attribute nvram = { + .attr = { + .name = "nvram", + .mode = S_IRUGO | S_IWUSR, + .owner = THIS_MODULE, + }, + + .read = ds1307_nvram_read, + .write = ds1307_nvram_write, + .size = NVRAM_SIZE, +}; + +/*----------------------------------------------------------------------*/ + static struct i2c_driver ds1307_driver; static int __devinit ds1307_probe(struct i2c_client *client) @@ -413,6 +495,14 @@ read_rtc: goto exit_free; } + if (chip->nvram56) { + err = sysfs_create_bin_file(&client->dev.kobj, &nvram); + if (err == 0) { + ds1307->has_nvram = true; + dev_info(&client->dev, "56 bytes nvram\n"); + } + } + return 0; exit_bad: @@ -432,6 +522,9 @@ static int __devexit ds1307_remove(struct i2c_client *client) { struct ds1307 *ds1307 = i2c_get_clientdata(client); + if (ds1307->has_nvram) + sysfs_remove_bin_file(&client->dev.kobj, &nvram); + rtc_device_unregister(ds1307->rtc); kfree(ds1307); return 0; diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index bb53c09bad16..d9e848dcd450 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c @@ -291,7 +291,7 @@ static ssize_t ds1553_nvram_write(struct kobject *kobj, static struct bin_attribute ds1553_nvram_attr = { .attr = { .name = "nvram", - .mode = S_IRUGO | S_IWUGO, + .mode = S_IRUGO | S_IWUSR, }, .size = RTC_OFFSET, .read = ds1553_nvram_read, diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index c535b78698e2..2e73f0b183b2 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c @@ -160,10 +160,13 @@ static ssize_t ds1742_nvram_write(struct kobject *kobj, static struct bin_attribute ds1742_nvram_attr = { .attr = { .name = "nvram", - .mode = S_IRUGO | S_IWUGO, + .mode = S_IRUGO | S_IWUSR, }, .read = ds1742_nvram_read, .write = ds1742_nvram_write, + /* REVISIT: size in sysfs won't match actual size... if it's + * not a constant, each RTC should have its own attribute. + */ }; static int __devinit ds1742_rtc_probe(struct platform_device *pdev) diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index 2bad1637330a..cd0bbc0e8038 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c @@ -353,11 +353,12 @@ static ssize_t m48t59_nvram_write(struct kobject *kobj, static struct bin_attribute m48t59_nvram_attr = { .attr = { .name = "nvram", - .mode = S_IRUGO | S_IWUGO, + .mode = S_IRUGO | S_IWUSR, .owner = THIS_MODULE, }, .read = m48t59_nvram_read, .write = m48t59_nvram_write, + .size = M48T59_NVRAM_SIZE, }; static int __devinit m48t59_rtc_probe(struct platform_device *pdev) diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index 78277a118b67..8e8c8b8e81ee 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c @@ -351,8 +351,10 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday); - if (rtc_valid_tm(tm) < 0) + if (rtc_valid_tm(tm) < 0) { dev_err(dev, "invalid date\n"); + rtc_time_to_tm(0, tm); + } return 0; } @@ -588,7 +590,7 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) rtc->rtc_dev = rtc_device_register("sh", &pdev->dev, &sh_rtc_ops, THIS_MODULE); - if (IS_ERR(rtc)) { + if (IS_ERR(rtc->rtc_dev)) { ret = PTR_ERR(rtc->rtc_dev); goto err_badmap; } diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index 8288b6b2bf2b..a265da7c6ff8 100644 --- a/drivers/rtc/rtc-stk17ta8.c +++ b/drivers/rtc/rtc-stk17ta8.c @@ -291,7 +291,7 @@ static ssize_t stk17ta8_nvram_write(struct kobject *kobj, static struct bin_attribute stk17ta8_nvram_attr = { .attr = { .name = "nvram", - .mode = S_IRUGO | S_IWUGO, + .mode = S_IRUGO | S_IWUSR, .owner = THIS_MODULE, }, .size = RTC_OFFSET, diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 838f7ac0dc32..6db31089d2d7 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -483,7 +483,7 @@ static DECLARE_WORK(css_reprobe_work, reprobe_all); void css_schedule_reprobe(void) { need_reprobe = 1; - queue_work(ccw_device_work, &css_reprobe_work); + queue_work(slow_path_wq, &css_reprobe_work); } EXPORT_SYMBOL_GPL(css_schedule_reprobe); diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 8867443b8060..bfad421cda66 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -1034,7 +1034,7 @@ device_trigger_reprobe(struct subchannel *sch) if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) { PREPARE_WORK(&cdev->private->kick_work, ccw_device_move_to_orphanage); - queue_work(ccw_device_work, &cdev->private->kick_work); + queue_work(slow_path_wq, &cdev->private->kick_work); } else ccw_device_start_id(cdev, 0); } diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c index f232832f2b22..2f6bf462425e 100644 --- a/drivers/s390/cio/device_id.c +++ b/drivers/s390/cio/device_id.c @@ -113,19 +113,10 @@ __ccw_device_sense_id_start(struct ccw_device *cdev) { struct subchannel *sch; struct ccw1 *ccw; - int ret; sch = to_subchannel(cdev->dev.parent); /* Setup sense channel program. */ ccw = cdev->private->iccws; - if (sch->schib.pmcw.pim != 0x80) { - /* more than one path installed. */ - ccw->cmd_code = CCW_CMD_SUSPEND_RECONN; - ccw->cda = 0; - ccw->count = 0; - ccw->flags = CCW_FLAG_SLI | CCW_FLAG_CC; - ccw++; - } ccw->cmd_code = CCW_CMD_SENSE_ID; ccw->cda = (__u32) __pa (&cdev->private->senseid); ccw->count = sizeof (struct senseid); @@ -133,25 +124,9 @@ __ccw_device_sense_id_start(struct ccw_device *cdev) /* Reset device status. */ memset(&cdev->private->irb, 0, sizeof(struct irb)); + cdev->private->flags.intretry = 0; - /* Try on every path. */ - ret = -ENODEV; - while (cdev->private->imask != 0) { - if ((sch->opm & cdev->private->imask) != 0 && - cdev->private->iretry > 0) { - cdev->private->iretry--; - /* Reset internal retry indication. */ - cdev->private->flags.intretry = 0; - ret = cio_start (sch, cdev->private->iccws, - cdev->private->imask); - /* ret is 0, -EBUSY, -EACCES or -ENODEV */ - if (ret != -EACCES) - return ret; - } - cdev->private->imask >>= 1; - cdev->private->iretry = 5; - } - return ret; + return cio_start(sch, ccw, LPM_ANYPATH); } void @@ -161,8 +136,7 @@ ccw_device_sense_id_start(struct ccw_device *cdev) memset (&cdev->private->senseid, 0, sizeof (struct senseid)); cdev->private->senseid.cu_type = 0xFFFF; - cdev->private->imask = 0x80; - cdev->private->iretry = 5; + cdev->private->iretry = 3; ret = __ccw_device_sense_id_start(cdev); if (ret && ret != -EBUSY) ccw_device_sense_id_done(cdev, ret); @@ -278,14 +252,13 @@ ccw_device_sense_id_irq(struct ccw_device *cdev, enum dev_event dev_event) ccw_device_sense_id_done(cdev, ret); break; case -EACCES: /* channel is not operational. */ - sch->lpm &= ~cdev->private->imask; - cdev->private->imask >>= 1; - cdev->private->iretry = 5; - /* fall through. */ case -EAGAIN: /* try again. */ - ret = __ccw_device_sense_id_start(cdev); - if (ret == 0 || ret == -EBUSY) - break; + cdev->private->iretry--; + if (cdev->private->iretry > 0) { + ret = __ccw_device_sense_id_start(cdev); + if (ret == 0 || ret == -EBUSY) + break; + } /* fall through. */ default: /* Sense ID failed. Try asking VM. */ if (MACHINE_IS_VM) { diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c index 6bf3ebbe985a..b3b6f654365c 100644 --- a/drivers/s390/net/ctcmain.c +++ b/drivers/s390/net/ctcmain.c @@ -2782,35 +2782,14 @@ ctc_probe_device(struct ccwgroup_device *cgdev) } /** - * Initialize everything of the net device except the name and the - * channel structs. + * Device setup function called by alloc_netdev(). + * + * @param dev Device to be setup. */ -static struct net_device * -ctc_init_netdevice(struct net_device * dev, int alloc_device, - struct ctc_priv *privptr) +void ctc_init_netdevice(struct net_device * dev) { - if (!privptr) - return NULL; - DBF_TEXT(setup, 3, __FUNCTION__); - if (alloc_device) { - dev = kzalloc(sizeof(struct net_device), GFP_KERNEL); - if (!dev) - return NULL; - } - - dev->priv = privptr; - privptr->fsm = init_fsm("ctcdev", dev_state_names, - dev_event_names, CTC_NR_DEV_STATES, CTC_NR_DEV_EVENTS, - dev_fsm, DEV_FSM_LEN, GFP_KERNEL); - if (privptr->fsm == NULL) { - if (alloc_device) - kfree(dev); - return NULL; - } - fsm_newstate(privptr->fsm, DEV_STATE_STOPPED); - fsm_settimer(privptr->fsm, &privptr->restart_timer); if (dev->mtu == 0) dev->mtu = CTC_BUFSIZE_DEFAULT - LL_HEADER_LENGTH - 2; dev->hard_start_xmit = ctc_tx; @@ -2823,7 +2802,7 @@ ctc_init_netdevice(struct net_device * dev, int alloc_device, dev->type = ARPHRD_SLIP; dev->tx_queue_len = 100; dev->flags = IFF_POINTOPOINT | IFF_NOARP; - return dev; + SET_MODULE_OWNER(dev); } @@ -2879,14 +2858,22 @@ ctc_new_device(struct ccwgroup_device *cgdev) "ccw_device_set_online (cdev[1]) failed with ret = %d\n", ret); } - dev = ctc_init_netdevice(NULL, 1, privptr); - + dev = alloc_netdev(0, "ctc%d", ctc_init_netdevice); if (!dev) { ctc_pr_warn("ctc_init_netdevice failed\n"); goto out; } + dev->priv = privptr; - strlcpy(dev->name, "ctc%d", IFNAMSIZ); + privptr->fsm = init_fsm("ctcdev", dev_state_names, + dev_event_names, CTC_NR_DEV_STATES, CTC_NR_DEV_EVENTS, + dev_fsm, DEV_FSM_LEN, GFP_KERNEL); + if (privptr->fsm == NULL) { + free_netdev(dev); + goto out; + } + fsm_newstate(privptr->fsm, DEV_STATE_STOPPED); + fsm_settimer(privptr->fsm, &privptr->restart_timer); for (direction = READ; direction <= WRITE; direction++) { privptr->channel[direction] = diff --git a/drivers/scsi/aic94xx/aic94xx_sds.c b/drivers/scsi/aic94xx/aic94xx_sds.c index 5b0932f61473..06509bff71f7 100644 --- a/drivers/scsi/aic94xx/aic94xx_sds.c +++ b/drivers/scsi/aic94xx/aic94xx_sds.c @@ -377,7 +377,7 @@ out: #define FLASH_RESET 0xF0 -#define FLASH_SIZE 0x200000 +#define ASD_FLASH_SIZE 0x200000 #define FLASH_DIR_COOKIE "*** ADAPTEC FLASH DIRECTORY *** " #define FLASH_NEXT_ENTRY_OFFS 0x2000 #define FLASH_MAX_DIR_ENTRIES 32 @@ -609,7 +609,7 @@ static int asd_find_flash_dir(struct asd_ha_struct *asd_ha, struct asd_flash_dir *flash_dir) { u32 v; - for (v = 0; v < FLASH_SIZE; v += FLASH_NEXT_ENTRY_OFFS) { + for (v = 0; v < ASD_FLASH_SIZE; v += FLASH_NEXT_ENTRY_OFFS) { asd_read_flash_seg(asd_ha, flash_dir, v, sizeof(FLASH_DIR_COOKIE)-1); if (memcmp(flash_dir->cookie, FLASH_DIR_COOKIE, diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 8d0244c2e7d4..7a835a35f21d 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -242,16 +242,6 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign } } -static void hexdump(u8 *x, int len) -{ - int i; - - printk("[ "); - for (i = 0; i < len; i++) - printk("%x ", x[i]); - printk("]\n"); -} - static int idescsi_check_condition(ide_drive_t *drive, struct request *failed_command) { idescsi_scsi_t *scsi = drive_to_idescsi(drive); @@ -282,7 +272,8 @@ static int idescsi_check_condition(ide_drive_t *drive, struct request *failed_co pc->scsi_cmd = ((idescsi_pc_t *) failed_command->special)->scsi_cmd; if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) { printk ("ide-scsi: %s: queue cmd = ", drive->name); - hexdump(pc->c, 6); + print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1, pc->c, + 6, 0); } rq->rq_disk = scsi->disk; return ide_do_drive_cmd(drive, rq, ide_preempt); @@ -337,7 +328,8 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs) idescsi_pc_t *opc = (idescsi_pc_t *) rq->buffer; if (log) { printk ("ide-scsi: %s: wrap up check %lu, rst = ", drive->name, opc->scsi_cmd->serial_number); - hexdump(pc->buffer,16); + print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1, + pc->buffer, 16, 0); } memcpy((void *) opc->scsi_cmd->sense_buffer, pc->buffer, SCSI_SENSE_BUFFERSIZE); kfree(pc->buffer); @@ -816,10 +808,12 @@ static int idescsi_queue (struct scsi_cmnd *cmd, if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) { printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number); - hexdump(cmd->cmnd, cmd->cmd_len); + print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1, + cmd->cmnd, cmd->cmd_len, 0); if (memcmp(pc->c, cmd->cmnd, cmd->cmd_len)) { printk ("ide-scsi: %s: que %lu, tsl = ", drive->name, cmd->serial_number); - hexdump(pc->c, 12); + print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1, + pc->c, 12, 0); } } diff --git a/drivers/scsi/zorro7xx.c b/drivers/scsi/zorro7xx.c index ac67394c7373..64d40a2d4d4d 100644 --- a/drivers/scsi/zorro7xx.c +++ b/drivers/scsi/zorro7xx.c @@ -13,7 +13,10 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/zorro.h> + +#include <asm/amigahw.h> #include <asm/amigaints.h> + #include <scsi/scsi_host.h> #include <scsi/scsi_transport_spi.h> diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c index 926f58a674a1..1de098e75497 100644 --- a/drivers/serial/8250_pnp.c +++ b/drivers/serial/8250_pnp.c @@ -69,6 +69,8 @@ static const struct pnp_device_id pnp_dev_table[] = { { "CTL3001", 0 }, /* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */ { "CTL3011", 0 }, + /* Davicom ISA 33.6K Modem */ + { "DAV0336", 0 }, /* Creative */ /* Creative Modem Blaster Flash56 DI5601-1 */ { "DMB1032", 0 }, @@ -345,6 +347,11 @@ static const struct pnp_device_id pnp_dev_table[] = { /* Fujitsu Wacom Tablet PC devices */ { "FUJ02E5", 0 }, { "FUJ02E6", 0 }, + /* + * LG C1 EXPRESS DUAL (C1-PB11A3) touch screen (actually a FUJ02E6 in + * disguise) + */ + { "LTS0001", 0 }, /* Rockwell's (PORALiNK) 33600 INT PNP */ { "WCI0003", 0 }, /* Unkown PnP modems */ @@ -432,7 +439,8 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) } memset(&port, 0, sizeof(struct uart_port)); - port.irq = pnp_irq(dev, 0); + if (pnp_irq_valid(dev, 0)) + port.irq = pnp_irq(dev, 0); if (pnp_port_valid(dev, 0)) { port.iobase = pnp_port_start(dev, 0); port.iotype = UPIO_PORT; diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index ed438bc7e98d..d7e1996e2fec 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -600,7 +600,7 @@ config SERIAL_SA1100_CONSOLE config SERIAL_BFIN tristate "Blackfin serial port support" - depends on BFIN + depends on BLACKFIN select SERIAL_CORE select SERIAL_BFIN_UART0 if (BF531 || BF532 || BF533 || BF561) help diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index 4d6b3c56d20e..111da57f5334 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c @@ -204,8 +204,6 @@ static u_int atmel_get_mctrl(struct uart_port *port) */ static void atmel_stop_tx(struct uart_port *port) { - struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; - UART_PUT_IDR(port, ATMEL_US_TXRDY); } @@ -214,8 +212,6 @@ static void atmel_stop_tx(struct uart_port *port) */ static void atmel_start_tx(struct uart_port *port) { - struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; - UART_PUT_IER(port, ATMEL_US_TXRDY); } @@ -224,8 +220,6 @@ static void atmel_start_tx(struct uart_port *port) */ static void atmel_stop_rx(struct uart_port *port) { - struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; - UART_PUT_IDR(port, ATMEL_US_RXRDY); } @@ -409,7 +403,6 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id) */ static int atmel_startup(struct uart_port *port) { - struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; int retval; /* @@ -456,8 +449,6 @@ static int atmel_startup(struct uart_port *port) */ static void atmel_shutdown(struct uart_port *port) { - struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; - /* * Disable all interrupts, port and break condition. */ diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index f523cdf4b02b..a4e23cf47906 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c @@ -1,426 +1,10 @@ -/* $Id: serial.c,v 1.25 2004/09/29 10:33:49 starvik Exp $ - * +/* * Serial port driver for the ETRAX 100LX chip * - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Axis Communications AB + * Copyright (C) 1998-2007 Axis Communications AB * * Many, many authors. Based once upon a time on serial.c for 16x50. * - * $Log: serial.c,v $ - * Revision 1.25 2004/09/29 10:33:49 starvik - * Resolved a dealock when printing debug from kernel. - * - * Revision 1.24 2004/08/27 23:25:59 johana - * rs_set_termios() must call change_speed() if c_iflag has changed or - * automatic XOFF handling will be enabled and transmitter will stop - * if 0x13 is received. - * - * Revision 1.23 2004/08/24 06:57:13 starvik - * More whitespace cleanup - * - * Revision 1.22 2004/08/24 06:12:20 starvik - * Whitespace cleanup - * - * Revision 1.20 2004/05/24 12:00:20 starvik - * Big merge of stuff from Linux 2.4 (e.g. manual mode for the serial port). - * - * Revision 1.19 2004/05/17 13:12:15 starvik - * Kernel console hook - * Big merge from Linux 2.4 still pending. - * - * Revision 1.18 2003/10/28 07:18:30 starvik - * Compiles with debug info - * - * Revision 1.17 2003/07/04 08:27:37 starvik - * Merge of Linux 2.5.74 - * - * Revision 1.16 2003/06/13 10:05:19 johana - * Help the user to avoid trouble by: - * Forcing mixed mode for status/control lines if not all pins are used. - * - * Revision 1.15 2003/06/13 09:43:01 johana - * Merged in the following changes from os/linux/arch/cris/drivers/serial.c - * + some minor changes to reduce diff. - * - * Revision 1.49 2003/05/30 11:31:54 johana - * Merged in change-branch--serial9bit that adds CMSPAR support for sticky - * parity (mark/space) - * - * Revision 1.48 2003/05/30 11:03:57 johana - * Implemented rs_send_xchar() by disabling the DMA and writing manually. - * Added e100_disable_txdma_channel() and e100_enable_txdma_channel(). - * Fixed rs_throttle() and rs_unthrottle() to properly call rs_send_xchar - * instead of setting info->x_char and check the CRTSCTS flag before - * controlling the rts pin. - * - * Revision 1.14 2003/04/09 08:12:44 pkj - * Corrected typo changes made upstream. - * - * Revision 1.13 2003/04/09 05:20:47 starvik - * Merge of Linux 2.5.67 - * - * Revision 1.11 2003/01/22 06:48:37 starvik - * Fixed warnings issued by GCC 3.2.1 - * - * Revision 1.9 2002/12/13 09:07:47 starvik - * Alert user that RX_TIMEOUT_TICKS==0 doesn't work - * - * Revision 1.8 2002/12/11 13:13:57 starvik - * Added arch/ to v10 specific includes - * Added fix from Linux 2.4 in serial.c (flush_to_flip_buffer) - * - * Revision 1.7 2002/12/06 07:13:57 starvik - * Corrected work queue stuff - * Removed CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST - * - * Revision 1.6 2002/11/21 07:17:46 starvik - * Change static inline to extern inline where otherwise outlined with gcc-3.2 - * - * Revision 1.5 2002/11/14 15:59:49 starvik - * Linux 2.5 port of the latest serial driver from 2.4. The work queue stuff - * probably doesn't work yet. - * - * Revision 1.42 2002/11/05 09:08:47 johana - * Better implementation of rs_stop() and rs_start() that uses the XOFF - * register to start/stop transmission. - * change_speed() also initilises XOFF register correctly so that - * auto_xoff is enabled when IXON flag is set by user. - * This gives fast XOFF response times. - * - * Revision 1.41 2002/11/04 18:40:57 johana - * Implemented rs_stop() and rs_start(). - * Simple tests using hwtestserial indicates that this should be enough - * to make it work. - * - * Revision 1.40 2002/10/14 05:33:18 starvik - * RS-485 uses fast timers even if SERIAL_FAST_TIMER is disabled - * - * Revision 1.39 2002/09/30 21:00:57 johana - * Support for CONFIG_ETRAX_SERx_DTR_RI_DSR_CD_MIXED where the status and - * control pins can be mixed between PA and PB. - * If no serial port uses MIXED old solution is used - * (saves a few bytes and cycles). - * control_pins struct uses masks instead of bit numbers. - * Corrected dummy values and polarity in line_info() so - * /proc/tty/driver/serial is now correct. - * (the E100_xxx_GET() macros is really active low - perhaps not obvious) - * - * Revision 1.38 2002/08/23 11:01:36 starvik - * Check that serial port is enabled in all interrupt handlers to avoid - * restarts of DMA channels not assigned to serial ports - * - * Revision 1.37 2002/08/13 13:02:37 bjornw - * Removed some warnings because of unused code - * - * Revision 1.36 2002/08/08 12:50:01 starvik - * Serial interrupt is shared with synchronous serial port driver - * - * Revision 1.35 2002/06/03 10:40:49 starvik - * Increased RS-485 RTS toggle timer to 2 characters - * - * Revision 1.34 2002/05/28 18:59:36 johana - * Whitespace and comment fixing to be more like etrax100ser.c 1.71. - * - * Revision 1.33 2002/05/28 17:55:43 johana - * RS-485 uses FAST_TIMER if enabled, and starts a short (one char time) - * timer from tranismit_chars (interrupt context). - * The timer toggles RTS in interrupt context when expired giving minimum - * latencies. - * - * Revision 1.32 2002/05/22 13:58:00 johana - * Renamed rs_write() to raw_write() and made it inline. - * New rs_write() handles RS-485 if configured and enabled - * (moved code from e100_write_rs485()). - * RS-485 ioctl's uses copy_from_user() instead of verify_area(). - * - * Revision 1.31 2002/04/22 11:20:03 johana - * Updated copyright years. - * - * Revision 1.30 2002/04/22 09:39:12 johana - * RS-485 support compiles. - * - * Revision 1.29 2002/01/14 16:10:01 pkj - * Allocate the receive buffers dynamically. The static 4kB buffer was - * too small for the peaks. This means that we can get rid of the extra - * buffer and the copying to it. It also means we require less memory - * under normal operations, but can use more when needed (there is a - * cap at 64kB for safety reasons). If there is no memory available - * we panic(), and die a horrible death... - * - * Revision 1.28 2001/12/18 15:04:53 johana - * Cleaned up write_rs485() - now it works correctly without padding extra - * char. - * Added sane default initialisation of rs485. - * Added #ifdef around dummy variables. - * - * Revision 1.27 2001/11/29 17:00:41 pkj - * 2kB seems to be too small a buffer when using 921600 bps, - * so increase it to 4kB (this was already done for the elinux - * version of the serial driver). - * - * Revision 1.26 2001/11/19 14:20:41 pkj - * Minor changes to comments and unused code. - * - * Revision 1.25 2001/11/12 20:03:43 pkj - * Fixed compiler warnings. - * - * Revision 1.24 2001/11/12 15:10:05 pkj - * Total redesign of the receiving part of the serial driver. - * Uses eight chained descriptors to write to a 4kB buffer. - * This data is then serialised into a 2kB buffer. From there it - * is copied into the TTY's flip buffers when they become available. - * A lot of copying, and the sizes of the buffers might need to be - * tweaked, but all in all it should work better than the previous - * version, without the need to modify the TTY code in any way. - * Also note that erroneous bytes are now correctly marked in the - * flag buffers (instead of always marking the first byte). - * - * Revision 1.23 2001/10/30 17:53:26 pkj - * * Set info->uses_dma to 0 when a port is closed. - * * Mark the timer1 interrupt as a fast one (SA_INTERRUPT). - * * Call start_flush_timer() in start_receive() if - * CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST is defined. - * - * Revision 1.22 2001/10/30 17:44:03 pkj - * Use %lu for received and transmitted counters in line_info(). - * - * Revision 1.21 2001/10/30 17:40:34 pkj - * Clean-up. The only change to functionality is that - * CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS(=5) is used instead of - * MAX_FLUSH_TIME(=8). - * - * Revision 1.20 2001/10/30 15:24:49 johana - * Added char_time stuff from 2.0 driver. - * - * Revision 1.19 2001/10/30 15:23:03 johana - * Merged with 1.13.2 branch + fixed indentation - * and changed CONFIG_ETRAX100_XYS to CONFIG_ETRAX_XYZ - * - * Revision 1.18 2001/09/24 09:27:22 pkj - * Completed ext_baud_table[] in cflag_to_baud() and cflag_to_etrax_baud(). - * - * Revision 1.17 2001/08/24 11:32:49 ronny - * More fixes for the CONFIG_ETRAX_SERIAL_PORT0 define. - * - * Revision 1.16 2001/08/24 07:56:22 ronny - * Added config ifdefs around ser0 irq requests. - * - * Revision 1.15 2001/08/16 09:10:31 bjarne - * serial.c - corrected the initialization of rs_table, the wrong defines - * where used. - * Corrected a test in timed_flush_handler. - * Changed configured to enabled. - * serial.h - Changed configured to enabled. - * - * Revision 1.14 2001/08/15 07:31:23 bjarne - * Introduced two new members to the e100_serial struct. - * configured - Will be set to 1 if the port has been configured in .config - * uses_dma - Should be set to 1 if the port uses DMA. Currently it is set - * to 1 - * when a port is opened. This is used to limit the DMA interrupt - * routines to only manipulate DMA channels actually used by the - * serial driver. - * - * Revision 1.13.2.2 2001/10/17 13:57:13 starvik - * Receiver was broken by the break fixes - * - * Revision 1.13.2.1 2001/07/20 13:57:39 ronny - * Merge with new stuff from etrax100ser.c. Works but haven't checked stuff - * like break handling. - * - * Revision 1.13 2001/05/09 12:40:31 johana - * Use DMA_NBR and IRQ_NBR defines from dma.h and irq.h - * - * Revision 1.12 2001/04/19 12:23:07 bjornw - * CONFIG_RS485 -> CONFIG_ETRAX_RS485 - * - * Revision 1.11 2001/04/05 14:29:48 markusl - * Updated according to review remarks i.e. - * -Use correct types in port structure to avoid compiler warnings - * -Try to use IO_* macros whenever possible - * -Open should never return -EBUSY - * - * Revision 1.10 2001/03/05 13:14:07 bjornw - * Another spelling fix - * - * Revision 1.9 2001/02/23 13:46:38 bjornw - * Spellling check - * - * Revision 1.8 2001/01/23 14:56:35 markusl - * Made use of ser1 optional - * Needed by USB - * - * Revision 1.7 2001/01/19 16:14:48 perf - * Added kernel options for serial ports 234. - * Changed option names from CONFIG_ETRAX100_XYZ to CONFIG_ETRAX_XYZ. - * - * Revision 1.6 2000/11/22 16:36:09 bjornw - * Please marketing by using the correct case when spelling Etrax. - * - * Revision 1.5 2000/11/21 16:43:37 bjornw - * Fixed so it compiles under CONFIG_SVINTO_SIM - * - * Revision 1.4 2000/11/15 17:34:12 bjornw - * Added a timeout timer for flushing input channels. The interrupt-based - * fast flush system should be easy to merge with this later (works the same - * way, only with an irq instead of a system timer_list) - * - * Revision 1.3 2000/11/13 17:19:57 bjornw - * * Incredibly, this almost complete rewrite of serial.c worked (at least - * for output) the first time. - * - * Items worth noticing: - * - * No Etrax100 port 1 workarounds (does only compile on 2.4 anyway now) - * RS485 is not ported (why can't it be done in userspace as on x86 ?) - * Statistics done through async_icount - if any more stats are needed, - * that's the place to put them or in an arch-dep version of it. - * timeout_interrupt and the other fast timeout stuff not ported yet - * There be dragons in this 3k+ line driver - * - * Revision 1.2 2000/11/10 16:50:28 bjornw - * First shot at a 2.4 port, does not compile totally yet - * - * Revision 1.1 2000/11/10 16:47:32 bjornw - * Added verbatim copy of rev 1.49 etrax100ser.c from elinux - * - * Revision 1.49 2000/10/30 15:47:14 tobiasa - * Changed version number. - * - * Revision 1.48 2000/10/25 11:02:43 johana - * Changed %ul to %lu in printf's - * - * Revision 1.47 2000/10/18 15:06:53 pkj - * Compile correctly with CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST and - * CONFIG_ETRAX_SERIAL_PROC_ENTRY together. - * Some clean-up of the /proc/serial file. - * - * Revision 1.46 2000/10/16 12:59:40 johana - * Added CONFIG_ETRAX_SERIAL_PROC_ENTRY for statistics and debug info. - * - * Revision 1.45 2000/10/13 17:10:59 pkj - * Do not flush DMAs while flipping TTY buffers. - * - * Revision 1.44 2000/10/13 16:34:29 pkj - * Added a delay in ser_interrupt() for 2.3ms when an error is detected. - * We do not know why this delay is required yet, but without it the - * irmaflash program does not work (this was the program that needed - * the ser_interrupt() to be needed in the first place). This should not - * affect normal use of the serial ports. - * - * Revision 1.43 2000/10/13 16:30:44 pkj - * New version of the fast flush of serial buffers code. This time - * it is localized to the serial driver and uses a fast timer to - * do the work. - * - * Revision 1.42 2000/10/13 14:54:26 bennyo - * Fix for switching RTS when using rs485 - * - * Revision 1.41 2000/10/12 11:43:44 pkj - * Cleaned up a number of comments. - * - * Revision 1.40 2000/10/10 11:58:39 johana - * Made RS485 support generic for all ports. - * Toggle rts in interrupt if no delay wanted. - * WARNING: No true transmitter empty check?? - * Set d_wait bit when sending data so interrupt is delayed until - * fifo flushed. (Fix tcdrain() problem) - * - * Revision 1.39 2000/10/04 16:08:02 bjornw - * * Use virt_to_phys etc. for DMA addresses - * * Removed CONFIG_FLUSH_DMA_FAST hacks - * * Indentation fix - * - * Revision 1.38 2000/10/02 12:27:10 mattias - * * added variable used when using fast flush on serial dma. - * (CONFIG_FLUSH_DMA_FAST) - * - * Revision 1.37 2000/09/27 09:44:24 pkj - * Uncomment definition of SERIAL_HANDLE_EARLY_ERRORS. - * - * Revision 1.36 2000/09/20 13:12:52 johana - * Support for CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS: - * Number of timer ticks between flush of receive fifo (1 tick = 10ms). - * Try 0-3 for low latency applications. Approx 5 for high load - * applications (e.g. PPP). Maybe this should be more adaptive some day... - * - * Revision 1.35 2000/09/20 10:36:08 johana - * Typo in get_lsr_info() - * - * Revision 1.34 2000/09/20 10:29:59 johana - * Let rs_chars_in_buffer() check fifo content as well. - * get_lsr_info() might work now (not tested). - * Easier to change the port to debug. - * - * Revision 1.33 2000/09/13 07:52:11 torbjore - * Support RS485 - * - * Revision 1.32 2000/08/31 14:45:37 bjornw - * After sending a break we need to reset the transmit DMA channel - * - * Revision 1.31 2000/06/21 12:13:29 johana - * Fixed wait for all chars sent when closing port. - * (Used to always take 1 second!) - * Added shadows for directions of status/ctrl signals. - * - * Revision 1.30 2000/05/29 16:27:55 bjornw - * Simulator ifdef moved a bit - * - * Revision 1.29 2000/05/09 09:40:30 mattias - * * Added description of dma registers used in timeout_interrupt - * * Removed old code - * - * Revision 1.28 2000/05/08 16:38:58 mattias - * * Bugfix for flushing fifo in timeout_interrupt - * Problem occurs when bluetooth stack waits for a small number of bytes - * containing an event acknowledging free buffers in bluetooth HW - * As before, data was stuck in fifo until more data came on uart and - * flushed it up to the stack. - * - * Revision 1.27 2000/05/02 09:52:28 jonasd - * Added fix for peculiar etrax behaviour when eop is forced on an empty - * fifo. This is used when flashing the IRMA chip. Disabled by default. - * - * Revision 1.26 2000/03/29 15:32:02 bjornw - * 2.0.34 updates - * - * Revision 1.25 2000/02/16 16:59:36 bjornw - * * Receive DMA directly into the flip-buffer, eliminating an intermediary - * receive buffer and a memcpy. Will avoid some overruns. - * * Error message on debug port if an overrun or flip buffer overrun occurs. - * * Just use the first byte in the flag flip buffer for errors. - * * Check for timeout on the serial ports only each 5/100 s, not 1/100. - * - * Revision 1.24 2000/02/09 18:02:28 bjornw - * * Clear serial errors (overrun, framing, parity) correctly. Before, the - * receiver would get stuck if an error occurred and we did not restart - * the input DMA. - * * Cosmetics (indentation, some code made into inlines) - * * Some more debug options - * * Actually shut down the serial port (DMA irq, DMA reset, receiver stop) - * when the last open is closed. Corresponding fixes in startup(). - * * rs_close() "tx FIFO wait" code moved into right place, bug & -> && fixed - * and make a special case out of port 1 (R_DMA_CHx_STATUS is broken for that) - * * e100_disable_rx/enable_rx just disables/enables the receiver, not RTS - * - * Revision 1.23 2000/01/24 17:46:19 johana - * Wait for flush of DMA/FIFO when closing port. - * - * Revision 1.22 2000/01/20 18:10:23 johana - * Added TIOCMGET ioctl to return modem status. - * Implemented modem status/control that works with the extra signals - * (DTR, DSR, RI,CD) as well. - * 3 different modes supported: - * ser0 on PB (Bundy), ser1 on PB (Lisa) and ser2 on PA (Bundy) - * Fixed DEF_TX value that caused the serial transmitter pin (txd) to go to 0 when - * closing the last filehandle, NASTY!. - * Added break generation, not tested though! - * Use IRQF_SHARED when request_irq() for ser2 and ser3 (shared with) par0 and par1. - * You can't use them at the same time (yet..), but you can hopefully switch - * between ser2/par0, ser3/par1 with the same kernel config. - * Replaced some magic constants with defines - * - * */ static char *serial_version = "$Revision: 1.25 $"; @@ -446,6 +30,7 @@ static char *serial_version = "$Revision: 1.25 $"; #include <asm/io.h> #include <asm/irq.h> +#include <asm/dma.h> #include <asm/system.h> #include <linux/delay.h> @@ -454,8 +39,9 @@ static char *serial_version = "$Revision: 1.25 $"; /* non-arch dependent serial structures are in linux/serial.h */ #include <linux/serial.h> /* while we keep our own stuff (struct e100_serial) in a local .h file */ -#include "serial.h" +#include "crisv10.h" #include <asm/fasttimer.h> +#include <asm/arch/io_interface_mux.h> #ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER #ifndef CONFIG_ETRAX_FAST_TIMER @@ -504,18 +90,6 @@ struct tty_driver *serial_driver; from eLinux */ #define SERIAL_HANDLE_EARLY_ERRORS -/* Defined and used in n_tty.c, but we need it here as well */ -#define TTY_THRESHOLD_THROTTLE 128 - -/* Due to buffersizes and threshold values, our SERIAL_DESCR_BUF_SIZE - * must not be to high or flow control won't work if we leave it to the tty - * layer so we have our own throttling in flush_to_flip - * TTY_FLIPBUF_SIZE=512, - * TTY_THRESHOLD_THROTTLE/UNTHROTTLE=128 - * BUF_SIZE can't be > 128 - */ -#define CRIS_BUF_SIZE 512 - /* Currently 16 descriptors x 128 bytes = 2048 bytes */ #define SERIAL_DESCR_BUF_SIZE 256 @@ -588,13 +162,13 @@ unsigned long timer_data_to_ns(unsigned long timer_data); static void change_speed(struct e100_serial *info); static void rs_throttle(struct tty_struct * tty); static void rs_wait_until_sent(struct tty_struct *tty, int timeout); -static int rs_write(struct tty_struct * tty, int from_user, - const unsigned char *buf, int count); +static int rs_write(struct tty_struct *tty, + const unsigned char *buf, int count); #ifdef CONFIG_ETRAX_RS485 -static int e100_write_rs485(struct tty_struct * tty, int from_user, - const unsigned char *buf, int count); +static int e100_write_rs485(struct tty_struct *tty, + const unsigned char *buf, int count); #endif -static int get_lsr_info(struct e100_serial * info, unsigned int *value); +static int get_lsr_info(struct e100_serial *info, unsigned int *value); #define DEF_BAUD 115200 /* 115.2 kbit/s */ @@ -679,20 +253,39 @@ static struct e100_serial rs_table[] = { .rx_ctrl = DEF_RX, .tx_ctrl = DEF_TX, .iseteop = 2, + .dma_owner = dma_ser0, + .io_if = if_serial_0, #ifdef CONFIG_ETRAX_SERIAL_PORT0 .enabled = 1, #ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT .dma_out_enabled = 1, + .dma_out_nbr = SER0_TX_DMA_NBR, + .dma_out_irq_nbr = SER0_DMA_TX_IRQ_NBR, + .dma_out_irq_flags = IRQF_DISABLED, + .dma_out_irq_description = "serial 0 dma tr", #else .dma_out_enabled = 0, + .dma_out_nbr = UINT_MAX, + .dma_out_irq_nbr = 0, + .dma_out_irq_flags = 0, + .dma_out_irq_description = NULL, #endif #ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN .dma_in_enabled = 1, + .dma_in_nbr = SER0_RX_DMA_NBR, + .dma_in_irq_nbr = SER0_DMA_RX_IRQ_NBR, + .dma_in_irq_flags = IRQF_DISABLED, + .dma_in_irq_description = "serial 0 dma rec", #else - .dma_in_enabled = 0 + .dma_in_enabled = 0, + .dma_in_nbr = UINT_MAX, + .dma_in_irq_nbr = 0, + .dma_in_irq_flags = 0, + .dma_in_irq_description = NULL, #endif #else .enabled = 0, + .io_if_description = NULL, .dma_out_enabled = 0, .dma_in_enabled = 0 #endif @@ -714,20 +307,42 @@ static struct e100_serial rs_table[] = { .rx_ctrl = DEF_RX, .tx_ctrl = DEF_TX, .iseteop = 3, + .dma_owner = dma_ser1, + .io_if = if_serial_1, #ifdef CONFIG_ETRAX_SERIAL_PORT1 .enabled = 1, + .io_if_description = "ser1", #ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA8_OUT .dma_out_enabled = 1, + .dma_out_nbr = SER1_TX_DMA_NBR, + .dma_out_irq_nbr = SER1_DMA_TX_IRQ_NBR, + .dma_out_irq_flags = IRQF_DISABLED, + .dma_out_irq_description = "serial 1 dma tr", #else .dma_out_enabled = 0, + .dma_out_nbr = UINT_MAX, + .dma_out_irq_nbr = 0, + .dma_out_irq_flags = 0, + .dma_out_irq_description = NULL, #endif #ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA9_IN .dma_in_enabled = 1, + .dma_in_nbr = SER1_RX_DMA_NBR, + .dma_in_irq_nbr = SER1_DMA_RX_IRQ_NBR, + .dma_in_irq_flags = IRQF_DISABLED, + .dma_in_irq_description = "serial 1 dma rec", #else - .dma_in_enabled = 0 + .dma_in_enabled = 0, + .dma_in_enabled = 0, + .dma_in_nbr = UINT_MAX, + .dma_in_irq_nbr = 0, + .dma_in_irq_flags = 0, + .dma_in_irq_description = NULL, #endif #else .enabled = 0, + .io_if_description = NULL, + .dma_in_irq_nbr = 0, .dma_out_enabled = 0, .dma_in_enabled = 0 #endif @@ -748,20 +363,40 @@ static struct e100_serial rs_table[] = { .rx_ctrl = DEF_RX, .tx_ctrl = DEF_TX, .iseteop = 0, + .dma_owner = dma_ser2, + .io_if = if_serial_2, #ifdef CONFIG_ETRAX_SERIAL_PORT2 .enabled = 1, + .io_if_description = "ser2", #ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT .dma_out_enabled = 1, + .dma_out_nbr = SER2_TX_DMA_NBR, + .dma_out_irq_nbr = SER2_DMA_TX_IRQ_NBR, + .dma_out_irq_flags = IRQF_DISABLED, + .dma_out_irq_description = "serial 2 dma tr", #else .dma_out_enabled = 0, + .dma_out_nbr = UINT_MAX, + .dma_out_irq_nbr = 0, + .dma_out_irq_flags = 0, + .dma_out_irq_description = NULL, #endif #ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN .dma_in_enabled = 1, + .dma_in_nbr = SER2_RX_DMA_NBR, + .dma_in_irq_nbr = SER2_DMA_RX_IRQ_NBR, + .dma_in_irq_flags = IRQF_DISABLED, + .dma_in_irq_description = "serial 2 dma rec", #else - .dma_in_enabled = 0 + .dma_in_enabled = 0, + .dma_in_nbr = UINT_MAX, + .dma_in_irq_nbr = 0, + .dma_in_irq_flags = 0, + .dma_in_irq_description = NULL, #endif #else .enabled = 0, + .io_if_description = NULL, .dma_out_enabled = 0, .dma_in_enabled = 0 #endif @@ -782,20 +417,40 @@ static struct e100_serial rs_table[] = { .rx_ctrl = DEF_RX, .tx_ctrl = DEF_TX, .iseteop = 1, + .dma_owner = dma_ser3, + .io_if = if_serial_3, #ifdef CONFIG_ETRAX_SERIAL_PORT3 .enabled = 1, + .io_if_description = "ser3", #ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA4_OUT .dma_out_enabled = 1, + .dma_out_nbr = SER3_TX_DMA_NBR, + .dma_out_irq_nbr = SER3_DMA_TX_IRQ_NBR, + .dma_out_irq_flags = IRQF_DISABLED, + .dma_out_irq_description = "serial 3 dma tr", #else .dma_out_enabled = 0, + .dma_out_nbr = UINT_MAX, + .dma_out_irq_nbr = 0, + .dma_out_irq_flags = 0, + .dma_out_irq_description = NULL, #endif #ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA5_IN .dma_in_enabled = 1, + .dma_in_nbr = SER3_RX_DMA_NBR, + .dma_in_irq_nbr = SER3_DMA_RX_IRQ_NBR, + .dma_in_irq_flags = IRQF_DISABLED, + .dma_in_irq_description = "serial 3 dma rec", #else - .dma_in_enabled = 0 + .dma_in_enabled = 0, + .dma_in_nbr = UINT_MAX, + .dma_in_irq_nbr = 0, + .dma_in_irq_flags = 0, + .dma_in_irq_description = NULL #endif #else .enabled = 0, + .io_if_description = NULL, .dma_out_enabled = 0, .dma_in_enabled = 0 #endif @@ -1416,12 +1071,11 @@ e100_dtr(struct e100_serial *info, int set) { unsigned long flags; - save_flags(flags); - cli(); + local_irq_save(flags); *e100_modem_pins[info->line].dtr_shadow &= ~mask; *e100_modem_pins[info->line].dtr_shadow |= (set ? 0 : mask); *e100_modem_pins[info->line].dtr_port = *e100_modem_pins[info->line].dtr_shadow; - restore_flags(flags); + local_irq_restore(flags); } #ifdef SERIAL_DEBUG_IO @@ -1440,12 +1094,11 @@ e100_rts(struct e100_serial *info, int set) { #ifndef CONFIG_SVINTO_SIM unsigned long flags; - save_flags(flags); - cli(); + local_irq_save(flags); info->rx_ctrl &= ~E100_RTS_MASK; info->rx_ctrl |= (set ? 0 : E100_RTS_MASK); /* RTS is active low */ info->port[REG_REC_CTRL] = info->rx_ctrl; - restore_flags(flags); + local_irq_restore(flags); #ifdef SERIAL_DEBUG_IO printk("ser%i rts %i\n", info->line, set); #endif @@ -1463,12 +1116,11 @@ e100_ri_out(struct e100_serial *info, int set) unsigned char mask = e100_modem_pins[info->line].ri_mask; unsigned long flags; - save_flags(flags); - cli(); + local_irq_save(flags); *e100_modem_pins[info->line].ri_shadow &= ~mask; *e100_modem_pins[info->line].ri_shadow |= (set ? 0 : mask); *e100_modem_pins[info->line].ri_port = *e100_modem_pins[info->line].ri_shadow; - restore_flags(flags); + local_irq_restore(flags); } #endif } @@ -1481,12 +1133,11 @@ e100_cd_out(struct e100_serial *info, int set) unsigned char mask = e100_modem_pins[info->line].cd_mask; unsigned long flags; - save_flags(flags); - cli(); + local_irq_save(flags); *e100_modem_pins[info->line].cd_shadow &= ~mask; *e100_modem_pins[info->line].cd_shadow |= (set ? 0 : mask); *e100_modem_pins[info->line].cd_port = *e100_modem_pins[info->line].cd_shadow; - restore_flags(flags); + local_irq_restore(flags); } #endif } @@ -1560,8 +1211,7 @@ static void e100_disable_txdma_channel(struct e100_serial *info) /* Disable output DMA channel for the serial port in question * ( set to something other then serialX) */ - save_flags(flags); - cli(); + local_irq_save(flags); DFLOW(DEBUG_LOG(info->line, "disable_txdma_channel %i\n", info->line)); if (info->line == 0) { if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma6)) == @@ -1589,7 +1239,7 @@ static void e100_disable_txdma_channel(struct e100_serial *info) } } *R_GEN_CONFIG = genconfig_shadow; - restore_flags(flags); + local_irq_restore(flags); } @@ -1597,8 +1247,7 @@ static void e100_enable_txdma_channel(struct e100_serial *info) { unsigned long flags; - save_flags(flags); - cli(); + local_irq_save(flags); DFLOW(DEBUG_LOG(info->line, "enable_txdma_channel %i\n", info->line)); /* Enable output DMA channel for the serial port in question */ if (info->line == 0) { @@ -1615,7 +1264,7 @@ static void e100_enable_txdma_channel(struct e100_serial *info) genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma4, serial3); } *R_GEN_CONFIG = genconfig_shadow; - restore_flags(flags); + local_irq_restore(flags); } static void e100_disable_rxdma_channel(struct e100_serial *info) @@ -1625,8 +1274,7 @@ static void e100_disable_rxdma_channel(struct e100_serial *info) /* Disable input DMA channel for the serial port in question * ( set to something other then serialX) */ - save_flags(flags); - cli(); + local_irq_save(flags); if (info->line == 0) { if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma7)) == IO_STATE(R_GEN_CONFIG, dma7, serial0)) { @@ -1653,7 +1301,7 @@ static void e100_disable_rxdma_channel(struct e100_serial *info) } } *R_GEN_CONFIG = genconfig_shadow; - restore_flags(flags); + local_irq_restore(flags); } @@ -1661,8 +1309,7 @@ static void e100_enable_rxdma_channel(struct e100_serial *info) { unsigned long flags; - save_flags(flags); - cli(); + local_irq_save(flags); /* Enable input DMA channel for the serial port in question */ if (info->line == 0) { genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma7); @@ -1678,7 +1325,7 @@ static void e100_enable_rxdma_channel(struct e100_serial *info) genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma5, serial3); } *R_GEN_CONFIG = genconfig_shadow; - restore_flags(flags); + local_irq_restore(flags); } #ifdef SERIAL_HANDLE_EARLY_ERRORS @@ -1785,7 +1432,7 @@ e100_enable_rs485(struct tty_struct *tty,struct rs485_control *r) } static int -e100_write_rs485(struct tty_struct *tty, int from_user, +e100_write_rs485(struct tty_struct *tty, const unsigned char *buf, int count) { struct e100_serial * info = (struct e100_serial *)tty->driver_data; @@ -1798,7 +1445,7 @@ e100_write_rs485(struct tty_struct *tty, int from_user, */ info->rs485.enabled = 1; /* rs_write now deals with RS485 if enabled */ - count = rs_write(tty, from_user, buf, count); + count = rs_write(tty, buf, count); info->rs485.enabled = old_enabled; return count; } @@ -1836,7 +1483,7 @@ rs_stop(struct tty_struct *tty) unsigned long flags; unsigned long xoff; - save_flags(flags); cli(); + local_irq_save(flags); DFLOW(DEBUG_LOG(info->line, "XOFF rs_stop xmit %i\n", CIRC_CNT(info->xmit.head, info->xmit.tail,SERIAL_XMIT_SIZE))); @@ -1848,7 +1495,7 @@ rs_stop(struct tty_struct *tty) } *((unsigned long *)&info->port[REG_XOFF]) = xoff; - restore_flags(flags); + local_irq_restore(flags); } } @@ -1860,7 +1507,7 @@ rs_start(struct tty_struct *tty) unsigned long flags; unsigned long xoff; - save_flags(flags); cli(); + local_irq_save(flags); DFLOW(DEBUG_LOG(info->line, "XOFF rs_start xmit %i\n", CIRC_CNT(info->xmit.head, info->xmit.tail,SERIAL_XMIT_SIZE))); @@ -1875,7 +1522,7 @@ rs_start(struct tty_struct *tty) info->xmit.head != info->xmit.tail && info->xmit.buf) e100_enable_serial_tx_ready_irq(info); - restore_flags(flags); + local_irq_restore(flags); } } @@ -2055,8 +1702,7 @@ static int serial_fast_timer_expired = 0; static void flush_timeout_function(unsigned long data); #define START_FLUSH_FAST_TIMER_TIME(info, string, usec) {\ unsigned long timer_flags; \ - save_flags(timer_flags); \ - cli(); \ + local_irq_save(timer_flags); \ if (fast_timers[info->line].function == NULL) { \ serial_fast_timer_started++; \ TIMERD(DEBUG_LOG(info->line, "start_timer %i ", info->line)); \ @@ -2070,7 +1716,7 @@ static void flush_timeout_function(unsigned long data); else { \ TIMERD(DEBUG_LOG(info->line, "timer %i already running\n", info->line)); \ } \ - restore_flags(timer_flags); \ + local_irq_restore(timer_flags); \ } #define START_FLUSH_FAST_TIMER(info, string) START_FLUSH_FAST_TIMER_TIME(info, string, info->flush_time_usec) @@ -2099,8 +1745,7 @@ append_recv_buffer(struct e100_serial *info, struct etrax_recv_buffer *buffer) { unsigned long flags; - save_flags(flags); - cli(); + local_irq_save(flags); if (!info->first_recv_buffer) info->first_recv_buffer = buffer; @@ -2113,7 +1758,7 @@ append_recv_buffer(struct e100_serial *info, struct etrax_recv_buffer *buffer) if (info->recv_cnt > info->max_recv_cnt) info->max_recv_cnt = info->recv_cnt; - restore_flags(flags); + local_irq_restore(flags); } static int @@ -2133,11 +1778,7 @@ add_char_and_flag(struct e100_serial *info, unsigned char data, unsigned char fl info->icount.rx++; } else { struct tty_struct *tty = info->tty; - *tty->flip.char_buf_ptr = data; - *tty->flip.flag_buf_ptr = flag; - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; + tty_insert_flip_char(tty, data, flag); info->icount.rx++; } @@ -2322,7 +1963,6 @@ start_receive(struct e100_serial *info) */ return; #endif - info->tty->flip.count = 0; if (info->uses_dma_in) { /* reset the input dma channel to be sure it works */ @@ -2484,32 +2124,20 @@ static void flush_to_flip_buffer(struct e100_serial *info) { struct tty_struct *tty; struct etrax_recv_buffer *buffer; - unsigned int length; unsigned long flags; - int max_flip_size; - - if (!info->first_recv_buffer) - return; - save_flags(flags); - cli(); + local_irq_save(flags); + tty = info->tty; - if (!(tty = info->tty)) { - restore_flags(flags); + if (!tty) { + local_irq_restore(flags); return; } while ((buffer = info->first_recv_buffer) != NULL) { unsigned int count = buffer->length; - count = tty_buffer_request_room(tty, count); - if (count == 0) /* Throttle ?? */ - break; - - if (count > 1) - tty_insert_flip_strings(tty, buffer->buffer, count - 1); - tty_insert_flip_char(tty, buffer->buffer[count-1], buffer->error); - + tty_insert_flip_string(tty, buffer->buffer, count); info->recv_cnt -= count; if (count == buffer->length) { @@ -2525,18 +2153,9 @@ static void flush_to_flip_buffer(struct e100_serial *info) if (!info->first_recv_buffer) info->last_recv_buffer = NULL; - restore_flags(flags); - - DFLIP( - if (1) { - DEBUG_LOG(info->line, "*** rxtot %i\n", info->icount.rx); - DEBUG_LOG(info->line, "ldisc %lu\n", tty->ldisc.chars_in_buffer(tty)); - DEBUG_LOG(info->line, "room %lu\n", tty->ldisc.receive_room(tty)); - } + local_irq_restore(flags); - ); - - /* this includes a check for low-latency */ + /* This includes a check for low-latency */ tty_flip_buffer_push(tty); } @@ -2679,21 +2298,7 @@ struct e100_serial * handle_ser_rx_interrupt_no_dma(struct e100_serial *info) printk("!NO TTY!\n"); return info; } - if (tty->flip.count >= CRIS_BUF_SIZE - TTY_THRESHOLD_THROTTLE) { - /* check TTY_THROTTLED first so it indicates our state */ - if (!test_and_set_bit(TTY_THROTTLED, &tty->flags)) { - DFLOW(DEBUG_LOG(info->line, "rs_throttle flip.count: %i\n", tty->flip.count)); - rs_throttle(tty); - } - } - if (tty->flip.count >= CRIS_BUF_SIZE) { - DEBUG_LOG(info->line, "force FLIP! %i\n", tty->flip.count); - tty->flip.work.func((void *) tty); - if (tty->flip.count >= CRIS_BUF_SIZE) { - DEBUG_LOG(info->line, "FLIP FULL! %i\n", tty->flip.count); - return info; /* if TTY_DONT_FLIP is set */ - } - } + /* Read data and status at the same time */ data_read = *((unsigned long *)&info->port[REG_DATA_STATUS32]); more_data: @@ -2746,27 +2351,26 @@ more_data: DEBUG_LOG(info->line, "EBRK %i\n", info->break_detected_cnt); info->errorcode = ERRCODE_INSERT_BREAK; } else { + unsigned char data = IO_EXTRACT(R_SERIAL0_READ, + data_in, data_read); + char flag = TTY_NORMAL; if (info->errorcode == ERRCODE_INSERT_BREAK) { - info->icount.brk++; - *tty->flip.char_buf_ptr = 0; - *tty->flip.flag_buf_ptr = TTY_BREAK; - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; + struct tty_struct *tty = info->tty; + tty_insert_flip_char(tty, 0, flag); info->icount.rx++; } - *tty->flip.char_buf_ptr = IO_EXTRACT(R_SERIAL0_READ, data_in, data_read); if (data_read & IO_MASK(R_SERIAL0_READ, par_err)) { info->icount.parity++; - *tty->flip.flag_buf_ptr = TTY_PARITY; + flag = TTY_PARITY; } else if (data_read & IO_MASK(R_SERIAL0_READ, overrun)) { info->icount.overrun++; - *tty->flip.flag_buf_ptr = TTY_OVERRUN; + flag = TTY_OVERRUN; } else if (data_read & IO_MASK(R_SERIAL0_READ, framing_err)) { info->icount.frame++; - *tty->flip.flag_buf_ptr = TTY_FRAME; + flag = TTY_FRAME; } + tty_insert_flip_char(tty, data, flag); info->errorcode = 0; } info->break_detected_cnt = 0; @@ -2782,16 +2386,14 @@ more_data: log_int(rdpc(), 0, 0); } ); - *tty->flip.char_buf_ptr = IO_EXTRACT(R_SERIAL0_READ, data_in, data_read); - *tty->flip.flag_buf_ptr = 0; + tty_insert_flip_char(tty, + IO_EXTRACT(R_SERIAL0_READ, data_in, data_read), + TTY_NORMAL); } else { DEBUG_LOG(info->line, "ser_rx int but no data_avail %08lX\n", data_read); } - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; info->icount.rx++; data_read = *((unsigned long *)&info->port[REG_DATA_STATUS32]); if (data_read & IO_MASK(R_SERIAL0_READ, data_avail)) { @@ -2929,7 +2531,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) if (info->x_char) { unsigned char rstat; DFLOW(DEBUG_LOG(info->line, "tx_int: xchar 0x%02X\n", info->x_char)); - save_flags(flags); cli(); + local_irq_save(flags); rstat = info->port[REG_STATUS]; DFLOW(DEBUG_LOG(info->line, "stat %x\n", rstat)); @@ -2938,7 +2540,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) info->x_char = 0; /* We must enable since it is disabled in ser_interrupt */ e100_enable_serial_tx_ready_irq(info); - restore_flags(flags); + local_irq_restore(flags); return; } if (info->uses_dma_out) { @@ -2946,7 +2548,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) int i; /* We only use normal tx interrupt when sending x_char */ DFLOW(DEBUG_LOG(info->line, "tx_int: xchar sent\n", 0)); - save_flags(flags); cli(); + local_irq_save(flags); rstat = info->port[REG_STATUS]; DFLOW(DEBUG_LOG(info->line, "stat %x\n", rstat)); e100_disable_serial_tx_ready_irq(info); @@ -2959,7 +2561,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) nop(); *info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, continue); - restore_flags(flags); + local_irq_restore(flags); return; } /* Normal char-by-char interrupt */ @@ -2973,7 +2575,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) } DINTR2(DEBUG_LOG(info->line, "tx_int %c\n", info->xmit.buf[info->xmit.tail])); /* Send a byte, rs485 timing is critical so turn of ints */ - save_flags(flags); cli(); + local_irq_save(flags); info->port[REG_TR_DATA] = info->xmit.buf[info->xmit.tail]; info->xmit.tail = (info->xmit.tail + 1) & (SERIAL_XMIT_SIZE-1); info->icount.tx++; @@ -2997,7 +2599,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) /* We must enable since it is disabled in ser_interrupt */ e100_enable_serial_tx_ready_irq(info); } - restore_flags(flags); + local_irq_restore(flags); if (CIRC_CNT(info->xmit.head, info->xmit.tail, @@ -3022,7 +2624,7 @@ ser_interrupt(int irq, void *dev_id) int handled = 0; static volatile unsigned long reentered_ready_mask = 0; - save_flags(flags); cli(); + local_irq_save(flags); irq_mask1_rd = *R_IRQ_MASK1_RD; /* First handle all rx interrupts with ints disabled */ info = rs_table; @@ -3067,7 +2669,7 @@ ser_interrupt(int irq, void *dev_id) /* Unblock the serial interrupt */ *R_VECT_MASK_SET = IO_STATE(R_VECT_MASK_SET, serial, set); - sti(); + local_irq_enable(); ready_mask = (1 << (8+1+2*0)); /* ser0 tr_ready */ info = rs_table; for (i = 0; i < NR_PORTS; i++) { @@ -3080,11 +2682,11 @@ ser_interrupt(int irq, void *dev_id) ready_mask <<= 2; } /* handle_ser_tx_interrupt enables tr_ready interrupts */ - cli(); + local_irq_disable(); /* Handle reentered TX interrupt */ irq_mask1_rd = reentered_ready_mask; } - cli(); + local_irq_disable(); tx_started = 0; } else { unsigned long ready_mask; @@ -3100,7 +2702,7 @@ ser_interrupt(int irq, void *dev_id) } } - restore_flags(flags); + local_irq_restore(flags); return IRQ_RETVAL(handled); } /* ser_interrupt */ #endif @@ -3121,11 +2723,13 @@ ser_interrupt(int irq, void *dev_id) * them using rs_sched_event(), and they get done here. */ static void -do_softint(void *private_) +do_softint(struct work_struct *work) { - struct e100_serial *info = (struct e100_serial *) private_; + struct e100_serial *info; struct tty_struct *tty; + info = container_of(work, struct e100_serial, work); + tty = info->tty; if (!tty) return; @@ -3145,13 +2749,12 @@ startup(struct e100_serial * info) if (!xmit_page) return -ENOMEM; - save_flags(flags); - cli(); + local_irq_save(flags); /* if it was already initialized, skip this */ if (info->flags & ASYNC_INITIALIZED) { - restore_flags(flags); + local_irq_restore(flags); free_page(xmit_page); return 0; } @@ -3277,7 +2880,7 @@ startup(struct e100_serial * info) info->flags |= ASYNC_INITIALIZED; - restore_flags(flags); + local_irq_restore(flags); return 0; } @@ -3328,8 +2931,7 @@ shutdown(struct e100_serial * info) info->irq); #endif - save_flags(flags); - cli(); /* Disable interrupts */ + local_irq_save(flags); if (info->xmit.buf) { free_page((unsigned long)info->xmit.buf); @@ -3353,7 +2955,7 @@ shutdown(struct e100_serial * info) set_bit(TTY_IO_ERROR, &info->tty->flags); info->flags &= ~ASYNC_INITIALIZED; - restore_flags(flags); + local_irq_restore(flags); } @@ -3411,7 +3013,6 @@ change_speed(struct e100_serial *info) DBAUD(printk("using external baudrate: %lu\n", CONFIG_ETRAX_EXTERN_PB6CLK_FREQ/8)); info->baud = CONFIG_ETRAX_EXTERN_PB6CLK_FREQ/8; } - } #endif else { @@ -3445,8 +3046,7 @@ change_speed(struct e100_serial *info) #ifndef CONFIG_SVINTO_SIM /* start with default settings and then fill in changes */ - save_flags(flags); - cli(); + local_irq_save(flags); /* 8 bit, no/even parity */ info->rx_ctrl &= ~(IO_MASK(R_SERIAL0_REC_CTRL, rec_bitnr) | IO_MASK(R_SERIAL0_REC_CTRL, rec_par_en) | @@ -3510,7 +3110,7 @@ change_speed(struct e100_serial *info) } *((unsigned long *)&info->port[REG_XOFF]) = xoff; - restore_flags(flags); + local_irq_restore(flags); #endif /* !CONFIG_SVINTO_SIM */ update_char_time(info); @@ -3538,13 +3138,12 @@ rs_flush_chars(struct tty_struct *tty) /* this protection might not exactly be necessary here */ - save_flags(flags); - cli(); + local_irq_save(flags); start_transmit(info); - restore_flags(flags); + local_irq_restore(flags); } -static int rs_raw_write(struct tty_struct * tty, int from_user, +static int rs_raw_write(struct tty_struct *tty, const unsigned char *buf, int count) { int c, ret = 0; @@ -3567,53 +3166,19 @@ static int rs_raw_write(struct tty_struct * tty, int from_user, SIMCOUT(buf, count); return count; #endif - save_flags(flags); + local_save_flags(flags); DFLOW(DEBUG_LOG(info->line, "write count %i ", count)); DFLOW(DEBUG_LOG(info->line, "ldisc %i\n", tty->ldisc.chars_in_buffer(tty))); - /* the cli/restore_flags pairs below are needed because the - * DMA interrupt handler moves the info->xmit values. the memcpy - * needs to be in the critical region unfortunately, because we - * need to read xmit values, memcpy, write xmit values in one - * atomic operation... this could perhaps be avoided by more clever - * design. + /* The local_irq_disable/restore_flags pairs below are needed + * because the DMA interrupt handler moves the info->xmit values. + * the memcpy needs to be in the critical region unfortunately, + * because we need to read xmit values, memcpy, write xmit values + * in one atomic operation... this could perhaps be avoided by + * more clever design. */ - if (from_user) { - mutex_lock(&tmp_buf_mutex); - while (1) { - int c1; - c = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) - break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!ret) - ret = -EFAULT; - break; - } - cli(); - c1 = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE); - if (c1 < c) - c = c1; - memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c); - info->xmit.head = ((info->xmit.head + c) & - (SERIAL_XMIT_SIZE-1)); - restore_flags(flags); - buf += c; - count -= c; - ret += c; - } - mutex_unlock(&tmp_buf_mutex); - } else { - cli(); + local_irq_disable(); while (count) { c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, @@ -3631,8 +3196,7 @@ static int rs_raw_write(struct tty_struct * tty, int from_user, count -= c; ret += c; } - restore_flags(flags); - } + local_irq_restore(flags); /* enable transmitter if not running, unless the tty is stopped * this does not need IRQ protection since if tr_running == 0 @@ -3651,7 +3215,7 @@ static int rs_raw_write(struct tty_struct * tty, int from_user, } /* raw_raw_write() */ static int -rs_write(struct tty_struct * tty, int from_user, +rs_write(struct tty_struct *tty, const unsigned char *buf, int count) { #if defined(CONFIG_ETRAX_RS485) @@ -3678,7 +3242,7 @@ rs_write(struct tty_struct * tty, int from_user, } #endif /* CONFIG_ETRAX_RS485 */ - count = rs_raw_write(tty, from_user, buf, count); + count = rs_raw_write(tty, buf, count); #if defined(CONFIG_ETRAX_RS485) if (info->rs485.enabled) @@ -3746,10 +3310,9 @@ rs_flush_buffer(struct tty_struct *tty) struct e100_serial *info = (struct e100_serial *)tty->driver_data; unsigned long flags; - save_flags(flags); - cli(); + local_irq_save(flags); info->xmit.head = info->xmit.tail = 0; - restore_flags(flags); + local_irq_restore(flags); tty_wakeup(tty); } @@ -3767,7 +3330,7 @@ static void rs_send_xchar(struct tty_struct *tty, char ch) { struct e100_serial *info = (struct e100_serial *)tty->driver_data; unsigned long flags; - save_flags(flags); cli(); + local_irq_save(flags); if (info->uses_dma_out) { /* Put the DMA on hold and disable the channel */ *info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, hold); @@ -3784,7 +3347,7 @@ static void rs_send_xchar(struct tty_struct *tty, char ch) DFLOW(DEBUG_LOG(info->line, "rs_send_xchar 0x%02X\n", ch)); info->x_char = ch; e100_enable_serial_tx_ready_irq(info); - restore_flags(flags); + local_irq_restore(flags); } /* @@ -3996,21 +3559,61 @@ char *get_control_state_str(int MLines, char *s) } #endif +static void +rs_break(struct tty_struct *tty, int break_state) +{ + struct e100_serial *info = (struct e100_serial *)tty->driver_data; + unsigned long flags; + + if (!info->port) + return; + + local_irq_save(flags); + if (break_state == -1) { + /* Go to manual mode and set the txd pin to 0 */ + /* Clear bit 7 (txd) and 6 (tr_enable) */ + info->tx_ctrl &= 0x3F; + } else { + /* Set bit 7 (txd) and 6 (tr_enable) */ + info->tx_ctrl |= (0x80 | 0x40); + } + info->port[REG_TR_CTRL] = info->tx_ctrl; + local_irq_restore(flags); +} + static int -get_modem_info(struct e100_serial * info, unsigned int *value) +rs_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) { - unsigned int result; - /* Polarity isn't verified */ -#if 0 /*def SERIAL_DEBUG_IO */ + struct e100_serial *info = (struct e100_serial *)tty->driver_data; - printk("get_modem_info: RTS: %i DTR: %i CD: %i RI: %i DSR: %i CTS: %i\n", - E100_RTS_GET(info), - E100_DTR_GET(info), - E100_CD_GET(info), - E100_RI_GET(info), - E100_DSR_GET(info), - E100_CTS_GET(info)); -#endif + if (clear & TIOCM_RTS) + e100_rts(info, 0); + if (clear & TIOCM_DTR) + e100_dtr(info, 0); + /* Handle FEMALE behaviour */ + if (clear & TIOCM_RI) + e100_ri_out(info, 0); + if (clear & TIOCM_CD) + e100_cd_out(info, 0); + + if (set & TIOCM_RTS) + e100_rts(info, 1); + if (set & TIOCM_DTR) + e100_dtr(info, 1); + /* Handle FEMALE behaviour */ + if (set & TIOCM_RI) + e100_ri_out(info, 1); + if (set & TIOCM_CD) + e100_cd_out(info, 1); + return 0; +} + +static int +rs_tiocmget(struct tty_struct *tty, struct file *file) +{ + struct e100_serial *info = (struct e100_serial *)tty->driver_data; + unsigned int result; result = (!E100_RTS_GET(info) ? TIOCM_RTS : 0) @@ -4021,95 +3624,20 @@ get_modem_info(struct e100_serial * info, unsigned int *value) | (!E100_CTS_GET(info) ? TIOCM_CTS : 0); #ifdef SERIAL_DEBUG_IO - printk("e100ser: modem state: %i 0x%08X\n", result, result); + printk(KERN_DEBUG "ser%i: modem state: %i 0x%08X\n", + info->line, result, result); { char s[100]; get_control_state_str(result, s); - printk("state: %s\n", s); + printk(KERN_DEBUG "state: %s\n", s); } #endif - if (copy_to_user(value, &result, sizeof(int))) - return -EFAULT; - return 0; -} + return result; - -static int -set_modem_info(struct e100_serial * info, unsigned int cmd, - unsigned int *value) -{ - unsigned int arg; - - if (copy_from_user(&arg, value, sizeof(int))) - return -EFAULT; - - switch (cmd) { - case TIOCMBIS: - if (arg & TIOCM_RTS) { - e100_rts(info, 1); - } - if (arg & TIOCM_DTR) { - e100_dtr(info, 1); - } - /* Handle FEMALE behaviour */ - if (arg & TIOCM_RI) { - e100_ri_out(info, 1); - } - if (arg & TIOCM_CD) { - e100_cd_out(info, 1); - } - break; - case TIOCMBIC: - if (arg & TIOCM_RTS) { - e100_rts(info, 0); - } - if (arg & TIOCM_DTR) { - e100_dtr(info, 0); - } - /* Handle FEMALE behaviour */ - if (arg & TIOCM_RI) { - e100_ri_out(info, 0); - } - if (arg & TIOCM_CD) { - e100_cd_out(info, 0); - } - break; - case TIOCMSET: - e100_rts(info, arg & TIOCM_RTS); - e100_dtr(info, arg & TIOCM_DTR); - /* Handle FEMALE behaviour */ - e100_ri_out(info, arg & TIOCM_RI); - e100_cd_out(info, arg & TIOCM_CD); - break; - default: - return -EINVAL; - } - return 0; } -static void -rs_break(struct tty_struct *tty, int break_state) -{ - struct e100_serial * info = (struct e100_serial *)tty->driver_data; - unsigned long flags; - - if (!info->port) - return; - - save_flags(flags); - cli(); - if (break_state == -1) { - /* Go to manual mode and set the txd pin to 0 */ - info->tx_ctrl &= 0x3F; /* Clear bit 7 (txd) and 6 (tr_enable) */ - } else { - info->tx_ctrl |= (0x80 | 0x40); /* Set bit 7 (txd) and 6 (tr_enable) */ - } - info->port[REG_TR_CTRL] = info->tx_ctrl; - restore_flags(flags); -} - static int rs_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) @@ -4124,49 +3652,45 @@ rs_ioctl(struct tty_struct *tty, struct file * file, } switch (cmd) { - case TIOCMGET: - return get_modem_info(info, (unsigned int *) arg); - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - return set_modem_info(info, cmd, (unsigned int *) arg); - case TIOCGSERIAL: - return get_serial_info(info, - (struct serial_struct *) arg); - case TIOCSSERIAL: - return set_serial_info(info, - (struct serial_struct *) arg); - case TIOCSERGETLSR: /* Get line status register */ - return get_lsr_info(info, (unsigned int *) arg); - - case TIOCSERGSTRUCT: - if (copy_to_user((struct e100_serial *) arg, - info, sizeof(struct e100_serial))) - return -EFAULT; - return 0; + case TIOCGSERIAL: + return get_serial_info(info, + (struct serial_struct *) arg); + case TIOCSSERIAL: + return set_serial_info(info, + (struct serial_struct *) arg); + case TIOCSERGETLSR: /* Get line status register */ + return get_lsr_info(info, (unsigned int *) arg); + + case TIOCSERGSTRUCT: + if (copy_to_user((struct e100_serial *) arg, + info, sizeof(struct e100_serial))) + return -EFAULT; + return 0; #if defined(CONFIG_ETRAX_RS485) - case TIOCSERSETRS485: - { - struct rs485_control rs485ctrl; - if (copy_from_user(&rs485ctrl, (struct rs485_control*)arg, sizeof(rs485ctrl))) - return -EFAULT; + case TIOCSERSETRS485: + { + struct rs485_control rs485ctrl; + if (copy_from_user(&rs485ctrl, (struct rs485_control *)arg, + sizeof(rs485ctrl))) + return -EFAULT; - return e100_enable_rs485(tty, &rs485ctrl); - } + return e100_enable_rs485(tty, &rs485ctrl); + } - case TIOCSERWRRS485: - { - struct rs485_write rs485wr; - if (copy_from_user(&rs485wr, (struct rs485_write*)arg, sizeof(rs485wr))) - return -EFAULT; + case TIOCSERWRRS485: + { + struct rs485_write rs485wr; + if (copy_from_user(&rs485wr, (struct rs485_write *)arg, + sizeof(rs485wr))) + return -EFAULT; - return e100_write_rs485(tty, 1, rs485wr.outc, rs485wr.outc_size); - } + return e100_write_rs485(tty, rs485wr.outc, rs485wr.outc_size); + } #endif - default: - return -ENOIOCTLCMD; + default: + return -ENOIOCTLCMD; } return 0; } @@ -4191,46 +3715,6 @@ rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) } -/* In debugport.c - register a console write function that uses the normal - * serial driver - */ -typedef int (*debugport_write_function)(int i, const char *buf, unsigned int len); - -extern debugport_write_function debug_write_function; - -static int rs_debug_write_function(int i, const char *buf, unsigned int len) -{ - int cnt; - int written = 0; - struct tty_struct *tty; - static int recurse_cnt = 0; - - tty = rs_table[i].tty; - if (tty) { - unsigned long flags; - if (recurse_cnt > 5) /* We skip this debug output */ - return 1; - - local_irq_save(flags); - recurse_cnt++; - local_irq_restore(flags); - do { - cnt = rs_write(tty, 0, buf + written, len); - if (cnt >= 0) { - written += cnt; - buf += cnt; - len -= cnt; - } else - len = cnt; - } while(len > 0); - local_irq_save(flags); - recurse_cnt--; - local_irq_restore(flags); - return 1; - } - return 0; -} - /* * ------------------------------------------------------------ * rs_close() @@ -4252,11 +3736,10 @@ rs_close(struct tty_struct *tty, struct file * filp) /* interrupts are disabled for this entire function */ - save_flags(flags); - cli(); + local_irq_save(flags); if (tty_hung_up_p(filp)) { - restore_flags(flags); + local_irq_restore(flags); return; } @@ -4283,7 +3766,7 @@ rs_close(struct tty_struct *tty, struct file * filp) info->count = 0; } if (info->count) { - restore_flags(flags); + local_irq_restore(flags); return; } info->flags |= ASYNC_CLOSING; @@ -4337,7 +3820,7 @@ rs_close(struct tty_struct *tty, struct file * filp) } info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); wake_up_interruptible(&info->close_wait); - restore_flags(flags); + local_irq_restore(flags); /* port closed */ @@ -4359,6 +3842,28 @@ rs_close(struct tty_struct *tty, struct file * filp) #endif } #endif + + /* + * Release any allocated DMA irq's. + */ + if (info->dma_in_enabled) { + free_irq(info->dma_in_irq_nbr, info); + cris_free_dma(info->dma_in_nbr, info->dma_in_irq_description); + info->uses_dma_in = 0; +#ifdef SERIAL_DEBUG_OPEN + printk(KERN_DEBUG "DMA irq '%s' freed\n", + info->dma_in_irq_description); +#endif + } + if (info->dma_out_enabled) { + free_irq(info->dma_out_irq_nbr, info); + cris_free_dma(info->dma_out_nbr, info->dma_out_irq_description); + info->uses_dma_out = 0; +#ifdef SERIAL_DEBUG_OPEN + printk(KERN_DEBUG "DMA irq '%s' freed\n", + info->dma_out_irq_description); +#endif + } } /* @@ -4433,8 +3938,8 @@ block_til_ready(struct tty_struct *tty, struct file * filp, */ if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); + wait_event_interruptible(info->close_wait, + !(info->flags & ASYNC_CLOSING)); #ifdef SERIAL_DO_RESTART if (info->flags & ASYNC_HUP_NOTIFY) return -EAGAIN; @@ -4472,21 +3977,19 @@ block_til_ready(struct tty_struct *tty, struct file * filp, printk("block_til_ready before block: ttyS%d, count = %d\n", info->line, info->count); #endif - save_flags(flags); - cli(); + local_irq_save(flags); if (!tty_hung_up_p(filp)) { extra_count++; info->count--; } - restore_flags(flags); + local_irq_restore(flags); info->blocked_open++; while (1) { - save_flags(flags); - cli(); + local_irq_save(flags); /* assert RTS and DTR */ e100_rts(info, 1); e100_dtr(info, 1); - restore_flags(flags); + local_irq_restore(flags); set_current_state(TASK_INTERRUPTIBLE); if (tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED)) { @@ -4528,6 +4031,19 @@ block_til_ready(struct tty_struct *tty, struct file * filp, return 0; } +static void +deinit_port(struct e100_serial *info) +{ + if (info->dma_out_enabled) { + cris_free_dma(info->dma_out_nbr, info->dma_out_irq_description); + free_irq(info->dma_out_irq_nbr, info); + } + if (info->dma_in_enabled) { + cris_free_dma(info->dma_in_nbr, info->dma_in_irq_description); + free_irq(info->dma_in_irq_nbr, info); + } +} + /* * This routine is called whenever a serial port is opened. * It performs the serial-specific initialization for the tty structure. @@ -4538,9 +4054,9 @@ rs_open(struct tty_struct *tty, struct file * filp) struct e100_serial *info; int retval, line; unsigned long page; + int allocated_resources = 0; /* find which port we want to open */ - line = tty->index; if (line < 0 || line >= NR_PORTS) @@ -4580,8 +4096,8 @@ rs_open(struct tty_struct *tty, struct file * filp) */ if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); + wait_event_interruptible(info->close_wait, + !(info->flags & ASYNC_CLOSING)); #ifdef SERIAL_DO_RESTART return ((info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); @@ -4591,12 +4107,85 @@ rs_open(struct tty_struct *tty, struct file * filp) } /* + * If DMA is enabled try to allocate the irq's. + */ + if (info->count == 1) { + allocated_resources = 1; + if (info->dma_in_enabled) { + if (request_irq(info->dma_in_irq_nbr, + rec_interrupt, + info->dma_in_irq_flags, + info->dma_in_irq_description, + info)) { + printk(KERN_WARNING "DMA irq '%s' busy; " + "falling back to non-DMA mode\n", + info->dma_in_irq_description); + /* Make sure we never try to use DMA in */ + /* for the port again. */ + info->dma_in_enabled = 0; + } else if (cris_request_dma(info->dma_in_nbr, + info->dma_in_irq_description, + DMA_VERBOSE_ON_ERROR, + info->dma_owner)) { + free_irq(info->dma_in_irq_nbr, info); + printk(KERN_WARNING "DMA '%s' busy; " + "falling back to non-DMA mode\n", + info->dma_in_irq_description); + /* Make sure we never try to use DMA in */ + /* for the port again. */ + info->dma_in_enabled = 0; + } +#ifdef SERIAL_DEBUG_OPEN + else + printk(KERN_DEBUG "DMA irq '%s' allocated\n", + info->dma_in_irq_description); +#endif + } + if (info->dma_out_enabled) { + if (request_irq(info->dma_out_irq_nbr, + tr_interrupt, + info->dma_out_irq_flags, + info->dma_out_irq_description, + info)) { + printk(KERN_WARNING "DMA irq '%s' busy; " + "falling back to non-DMA mode\n", + info->dma_out_irq_description); + /* Make sure we never try to use DMA out */ + /* for the port again. */ + info->dma_out_enabled = 0; + } else if (cris_request_dma(info->dma_out_nbr, + info->dma_out_irq_description, + DMA_VERBOSE_ON_ERROR, + info->dma_owner)) { + free_irq(info->dma_out_irq_nbr, info); + printk(KERN_WARNING "DMA '%s' busy; " + "falling back to non-DMA mode\n", + info->dma_out_irq_description); + /* Make sure we never try to use DMA out */ + /* for the port again. */ + info->dma_out_enabled = 0; + } +#ifdef SERIAL_DEBUG_OPEN + else + printk(KERN_DEBUG "DMA irq '%s' allocated\n", + info->dma_out_irq_description); +#endif + } + } + + /* * Start up the serial port */ retval = startup(info); - if (retval) + if (retval) { + if (allocated_resources) + deinit_port(info); + + /* FIXME Decrease count info->count here too? */ return retval; + } + retval = block_til_ready(tty, filp, info); if (retval) { @@ -4604,6 +4193,9 @@ rs_open(struct tty_struct *tty, struct file * filp) printk("rs_open returning after block_til_ready with %d\n", retval); #endif + if (allocated_resources) + deinit_port(info); + return retval; } @@ -4793,6 +4385,8 @@ static const struct tty_operations rs_ops = { .send_xchar = rs_send_xchar, .wait_until_sent = rs_wait_until_sent, .read_proc = rs_read_proc, + .tiocmget = rs_tiocmget, + .tiocmset = rs_tiocmset }; static int __init @@ -4810,9 +4404,27 @@ rs_init(void) /* Setup the timed flush handler system */ #if !defined(CONFIG_ETRAX_SERIAL_FAST_TIMER) - init_timer(&flush_timer); - flush_timer.function = timed_flush_handler; - mod_timer(&flush_timer, jiffies + CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS); + setup_timer(&flush_timer, timed_flush_handler, 0); + mod_timer(&flush_timer, jiffies + 5); +#endif + +#if defined(CONFIG_ETRAX_RS485) +#if defined(CONFIG_ETRAX_RS485_ON_PA) + if (cris_io_interface_allocate_pins(if_ser0, 'a', rs485_pa_bit, + rs485_pa_bit)) { + printk(KERN_CRIT "ETRAX100LX serial: Could not allocate " + "RS485 pin\n"); + return -EBUSY; + } +#endif +#if defined(CONFIG_ETRAX_RS485_ON_PORT_G) + if (cris_io_interface_allocate_pins(if_ser0, 'g', rs485_pa_bit, + rs485_port_g_bit)) { + printk(KERN_CRIT "ETRAX100LX serial: Could not allocate " + "RS485 pin\n"); + return -EBUSY; + } +#endif #endif /* Initialize the tty_driver structure */ @@ -4839,6 +4451,16 @@ rs_init(void) /* do some initializing for the separate ports */ for (i = 0, info = rs_table; i < NR_PORTS; i++,info++) { + if (info->enabled) { + if (cris_request_io_interface(info->io_if, + info->io_if_description)) { + printk(KERN_CRIT "ETRAX100LX async serial: " + "Could not allocate IO pins for " + "%s, port %d\n", + info->io_if_description, i); + info->enabled = 0; + } + } info->uses_dma_in = 0; info->uses_dma_out = 0; info->line = i; @@ -4872,7 +4494,7 @@ rs_init(void) info->rs485.delay_rts_before_send = 0; info->rs485.enabled = 0; #endif - INIT_WORK(&info->work, do_softint, info); + INIT_WORK(&info->work, do_softint); if (info->enabled) { printk(KERN_INFO "%s%d at 0x%x is a builtin UART with DMA\n", @@ -4890,64 +4512,17 @@ rs_init(void) #endif #ifndef CONFIG_SVINTO_SIM +#ifndef CONFIG_ETRAX_KGDB /* Not needed in simulator. May only complicate stuff. */ /* hook the irq's for DMA channel 6 and 7, serial output and input, and some more... */ - if (request_irq(SERIAL_IRQ_NBR, ser_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial ", NULL)) - panic("irq8"); - -#ifdef CONFIG_ETRAX_SERIAL_PORT0 -#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT - if (request_irq(SER0_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_DISABLED, "serial 0 dma tr", NULL)) - panic("irq22"); -#endif -#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN - if (request_irq(SER0_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_DISABLED, "serial 0 dma rec", NULL)) - panic("irq23"); -#endif -#endif - -#ifdef CONFIG_ETRAX_SERIAL_PORT1 -#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA8_OUT - if (request_irq(SER1_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_DISABLED, "serial 1 dma tr", NULL)) - panic("irq24"); -#endif -#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA9_IN - if (request_irq(SER1_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_DISABLED, "serial 1 dma rec", NULL)) - panic("irq25"); -#endif -#endif -#ifdef CONFIG_ETRAX_SERIAL_PORT2 - /* DMA Shared with par0 (and SCSI0 and ATA) */ -#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT - if (request_irq(SER2_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 2 dma tr", NULL)) - panic("irq18"); -#endif -#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN - if (request_irq(SER2_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 2 dma rec", NULL)) - panic("irq19"); -#endif -#endif -#ifdef CONFIG_ETRAX_SERIAL_PORT3 - /* DMA Shared with par1 (and SCSI1 and Extern DMA 0) */ -#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA4_OUT - if (request_irq(SER3_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 3 dma tr", NULL)) - panic("irq20"); -#endif -#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA5_IN - if (request_irq(SER3_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 3 dma rec", NULL)) - panic("irq21"); -#endif -#endif + if (request_irq(SERIAL_IRQ_NBR, ser_interrupt, + IRQF_SHARED | IRQF_DISABLED, "serial ", driver)) + panic("%s: Failed to request irq8", __FUNCTION__); -#ifdef CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST - if (request_irq(TIMER1_IRQ_NBR, timeout_interrupt, IRQF_SHARED | IRQF_DISABLED, - "fast serial dma timeout", NULL)) { - printk(KERN_CRIT "err: timer1 irq\n"); - } #endif #endif /* CONFIG_SVINTO_SIM */ - debug_write_function = rs_debug_write_function; + return 0; } diff --git a/drivers/serial/crisv10.h b/drivers/serial/crisv10.h new file mode 100644 index 000000000000..ccd0f32b7372 --- /dev/null +++ b/drivers/serial/crisv10.h @@ -0,0 +1,146 @@ +/* + * serial.h: Arch-dep definitions for the Etrax100 serial driver. + * + * Copyright (C) 1998-2007 Axis Communications AB + */ + +#ifndef _ETRAX_SERIAL_H +#define _ETRAX_SERIAL_H + +#include <linux/circ_buf.h> +#include <asm/termios.h> +#include <asm/dma.h> +#include <asm/arch/io_interface_mux.h> + +/* Software state per channel */ + +#ifdef __KERNEL__ +/* + * This is our internal structure for each serial port's state. + * + * Many fields are paralleled by the structure used by the serial_struct + * structure. + * + * For definitions of the flags field, see tty.h + */ + +#define SERIAL_RECV_DESCRIPTORS 8 + +struct etrax_recv_buffer { + struct etrax_recv_buffer *next; + unsigned short length; + unsigned char error; + unsigned char pad; + + unsigned char buffer[0]; +}; + +struct e100_serial { + int baud; + volatile u8 *port; /* R_SERIALx_CTRL */ + u32 irq; /* bitnr in R_IRQ_MASK2 for dmaX_descr */ + + /* Output registers */ + volatile u8 *oclrintradr; /* adr to R_DMA_CHx_CLR_INTR */ + volatile u32 *ofirstadr; /* adr to R_DMA_CHx_FIRST */ + volatile u8 *ocmdadr; /* adr to R_DMA_CHx_CMD */ + const volatile u8 *ostatusadr; /* adr to R_DMA_CHx_STATUS */ + + /* Input registers */ + volatile u8 *iclrintradr; /* adr to R_DMA_CHx_CLR_INTR */ + volatile u32 *ifirstadr; /* adr to R_DMA_CHx_FIRST */ + volatile u8 *icmdadr; /* adr to R_DMA_CHx_CMD */ + volatile u32 *idescradr; /* adr to R_DMA_CHx_DESCR */ + + int flags; /* defined in tty.h */ + + u8 rx_ctrl; /* shadow for R_SERIALx_REC_CTRL */ + u8 tx_ctrl; /* shadow for R_SERIALx_TR_CTRL */ + u8 iseteop; /* bit number for R_SET_EOP for the input dma */ + int enabled; /* Set to 1 if the port is enabled in HW config */ + + u8 dma_out_enabled; /* Set to 1 if DMA should be used */ + u8 dma_in_enabled; /* Set to 1 if DMA should be used */ + + /* end of fields defined in rs_table[] in .c-file */ + int dma_owner; + unsigned int dma_in_nbr; + unsigned int dma_out_nbr; + unsigned int dma_in_irq_nbr; + unsigned int dma_out_irq_nbr; + unsigned long dma_in_irq_flags; + unsigned long dma_out_irq_flags; + char *dma_in_irq_description; + char *dma_out_irq_description; + + enum cris_io_interface io_if; + char *io_if_description; + + u8 uses_dma_in; /* Set to 1 if DMA is used */ + u8 uses_dma_out; /* Set to 1 if DMA is used */ + u8 forced_eop; /* a fifo eop has been forced */ + int baud_base; /* For special baudrates */ + int custom_divisor; /* For special baudrates */ + struct etrax_dma_descr tr_descr; + struct etrax_dma_descr rec_descr[SERIAL_RECV_DESCRIPTORS]; + int cur_rec_descr; + + volatile int tr_running; /* 1 if output is running */ + + struct tty_struct *tty; + int read_status_mask; + int ignore_status_mask; + int x_char; /* xon/xoff character */ + int close_delay; + unsigned short closing_wait; + unsigned short closing_wait2; + unsigned long event; + unsigned long last_active; + int line; + int type; /* PORT_ETRAX */ + int count; /* # of fd on device */ + int blocked_open; /* # of blocked opens */ + struct circ_buf xmit; + struct etrax_recv_buffer *first_recv_buffer; + struct etrax_recv_buffer *last_recv_buffer; + unsigned int recv_cnt; + unsigned int max_recv_cnt; + + struct work_struct work; + struct async_icount icount; /* error-statistics etc.*/ + struct ktermios normal_termios; + struct ktermios callout_termios; + wait_queue_head_t open_wait; + wait_queue_head_t close_wait; + + unsigned long char_time_usec; /* The time for 1 char, in usecs */ + unsigned long flush_time_usec; /* How often we should flush */ + unsigned long last_tx_active_usec; /* Last tx usec in the jiffies */ + unsigned long last_tx_active; /* Last tx time in jiffies */ + unsigned long last_rx_active_usec; /* Last rx usec in the jiffies */ + unsigned long last_rx_active; /* Last rx time in jiffies */ + + int break_detected_cnt; + int errorcode; + +#ifdef CONFIG_ETRAX_RS485 + struct rs485_control rs485; /* RS-485 support */ +#endif +}; + +/* this PORT is not in the standard serial.h. it's not actually used for + * anything since we only have one type of async serial-port anyway in this + * system. + */ + +#define PORT_ETRAX 1 + +/* + * Events are used to schedule things to happen at timer-interrupt + * time, instead of at rs interrupt time. + */ +#define RS_EVENT_WRITE_WAKEUP 0 + +#endif /* __KERNEL__ */ + +#endif /* !_ETRAX_SERIAL_H */ diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c index f3257f708ef9..9c95bc0398ad 100644 --- a/drivers/serial/ip22zilog.c +++ b/drivers/serial/ip22zilog.c @@ -45,8 +45,6 @@ #include "ip22zilog.h" -void ip22_do_break(void); - /* * On IP22 we need to delay after register accesses but we do not need to * flush writes. @@ -81,12 +79,9 @@ struct uart_ip22zilog_port { #define IP22ZILOG_FLAG_REGS_HELD 0x00000040 #define IP22ZILOG_FLAG_TX_STOPPED 0x00000080 #define IP22ZILOG_FLAG_TX_ACTIVE 0x00000100 +#define IP22ZILOG_FLAG_RESET_DONE 0x00000200 - unsigned int cflag; - - /* L1-A keyboard break state. */ - int kbd_id; - int l1_down; + unsigned int tty_break; unsigned char parity_mask; unsigned char prev_status; @@ -250,13 +245,26 @@ static void ip22zilog_maybe_update_regs(struct uart_ip22zilog_port *up, } } -static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up, - struct zilog_channel *channel) +#define Rx_BRK 0x0100 /* BREAK event software flag. */ +#define Rx_SYS 0x0200 /* SysRq event software flag. */ + +static struct tty_struct *ip22zilog_receive_chars(struct uart_ip22zilog_port *up, + struct zilog_channel *channel) { - struct tty_struct *tty = up->port.info->tty; /* XXX info==NULL? */ + struct tty_struct *tty; + unsigned char ch, flag; + unsigned int r1; + + tty = NULL; + if (up->port.info != NULL && + up->port.info->tty != NULL) + tty = up->port.info->tty; - while (1) { - unsigned char ch, r1, flag; + for (;;) { + ch = readb(&channel->control); + ZSDELAY(); + if (!(ch & Rx_CH_AV)) + break; r1 = read_zsreg(channel, R1); if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) { @@ -265,43 +273,26 @@ static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up, ZS_WSYNC(channel); } - ch = readb(&channel->control); - ZSDELAY(); - - /* This funny hack depends upon BRK_ABRT not interfering - * with the other bits we care about in R1. - */ - if (ch & BRK_ABRT) - r1 |= BRK_ABRT; - ch = readb(&channel->data); ZSDELAY(); ch &= up->parity_mask; - if (ZS_IS_CONS(up) && (r1 & BRK_ABRT)) { - /* Wait for BREAK to deassert to avoid potentially - * confusing the PROM. - */ - while (1) { - ch = readb(&channel->control); - ZSDELAY(); - if (!(ch & BRK_ABRT)) - break; - } - ip22_do_break(); - return; - } + /* Handle the null char got when BREAK is removed. */ + if (!ch) + r1 |= up->tty_break; /* A real serial line, record the character and status. */ flag = TTY_NORMAL; up->port.icount.rx++; - if (r1 & (BRK_ABRT | PAR_ERR | Rx_OVR | CRC_ERR)) { - if (r1 & BRK_ABRT) { - r1 &= ~(PAR_ERR | CRC_ERR); + if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR | Rx_SYS | Rx_BRK)) { + up->tty_break = 0; + + if (r1 & (Rx_SYS | Rx_BRK)) { up->port.icount.brk++; - if (uart_handle_break(&up->port)) - goto next_char; + if (r1 & Rx_SYS) + continue; + r1 &= ~(PAR_ERR | CRC_ERR); } else if (r1 & PAR_ERR) up->port.icount.parity++; @@ -310,30 +301,21 @@ static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up, if (r1 & Rx_OVR) up->port.icount.overrun++; r1 &= up->port.read_status_mask; - if (r1 & BRK_ABRT) + if (r1 & Rx_BRK) flag = TTY_BREAK; else if (r1 & PAR_ERR) flag = TTY_PARITY; else if (r1 & CRC_ERR) flag = TTY_FRAME; } - if (uart_handle_sysrq_char(&up->port, ch)) - goto next_char; - if (up->port.ignore_status_mask == 0xff || - (r1 & up->port.ignore_status_mask) == 0) - tty_insert_flip_char(tty, ch, flag); + if (uart_handle_sysrq_char(&up->port, ch)) + continue; - if (r1 & Rx_OVR) - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - next_char: - ch = readb(&channel->control); - ZSDELAY(); - if (!(ch & Rx_CH_AV)) - break; + if (tty) + uart_insert_char(&up->port, r1, Rx_OVR, ch, flag); } - - tty_flip_buffer_push(tty); + return tty; } static void ip22zilog_status_handle(struct uart_ip22zilog_port *up, @@ -348,6 +330,15 @@ static void ip22zilog_status_handle(struct uart_ip22zilog_port *up, ZSDELAY(); ZS_WSYNC(channel); + if (up->curregs[R15] & BRKIE) { + if ((status & BRK_ABRT) && !(up->prev_status & BRK_ABRT)) { + if (uart_handle_break(&up->port)) + up->tty_break = Rx_SYS; + else + up->tty_break = Rx_BRK; + } + } + if (ZS_WANTS_MODEM_STATUS(up)) { if (status & SYNC) up->port.icount.dsr++; @@ -356,10 +347,10 @@ static void ip22zilog_status_handle(struct uart_ip22zilog_port *up, * But it does not tell us which bit has changed, we have to keep * track of this ourselves. */ - if ((status & DCD) ^ up->prev_status) + if ((status ^ up->prev_status) ^ DCD) uart_handle_dcd_change(&up->port, (status & DCD)); - if ((status & CTS) ^ up->prev_status) + if ((status ^ up->prev_status) ^ CTS) uart_handle_cts_change(&up->port, (status & CTS)); @@ -447,19 +438,21 @@ static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id) while (up) { struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(&up->port); + struct tty_struct *tty; unsigned char r3; spin_lock(&up->port.lock); r3 = read_zsreg(channel, R3); /* Channel A */ + tty = NULL; if (r3 & (CHAEXT | CHATxIP | CHARxIP)) { writeb(RES_H_IUS, &channel->control); ZSDELAY(); ZS_WSYNC(channel); if (r3 & CHARxIP) - ip22zilog_receive_chars(up, channel); + tty = ip22zilog_receive_chars(up, channel); if (r3 & CHAEXT) ip22zilog_status_handle(up, channel); if (r3 & CHATxIP) @@ -467,18 +460,22 @@ static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id) } spin_unlock(&up->port.lock); + if (tty) + tty_flip_buffer_push(tty); + /* Channel B */ up = up->next; channel = ZILOG_CHANNEL_FROM_PORT(&up->port); spin_lock(&up->port.lock); + tty = NULL; if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) { writeb(RES_H_IUS, &channel->control); ZSDELAY(); ZS_WSYNC(channel); if (r3 & CHBRxIP) - ip22zilog_receive_chars(up, channel); + tty = ip22zilog_receive_chars(up, channel); if (r3 & CHBEXT) ip22zilog_status_handle(up, channel); if (r3 & CHBTxIP) @@ -486,6 +483,9 @@ static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id) } spin_unlock(&up->port.lock); + if (tty) + tty_flip_buffer_push(tty); + up = up->next; } @@ -681,11 +681,46 @@ static void ip22zilog_break_ctl(struct uart_port *port, int break_state) spin_unlock_irqrestore(&port->lock, flags); } +static void __ip22zilog_reset(struct uart_ip22zilog_port *up) +{ + struct zilog_channel *channel; + int i; + + if (up->flags & IP22ZILOG_FLAG_RESET_DONE) + return; + + /* Let pending transmits finish. */ + channel = ZILOG_CHANNEL_FROM_PORT(&up->port); + for (i = 0; i < 1000; i++) { + unsigned char stat = read_zsreg(channel, R1); + if (stat & ALL_SNT) + break; + udelay(100); + } + + if (!ZS_IS_CHANNEL_A(up)) { + up++; + channel = ZILOG_CHANNEL_FROM_PORT(&up->port); + } + write_zsreg(channel, R9, FHWRES); + ZSDELAY_LONG(); + (void) read_zsreg(channel, R0); + + up->flags |= IP22ZILOG_FLAG_RESET_DONE; + up->next->flags |= IP22ZILOG_FLAG_RESET_DONE; +} + static void __ip22zilog_startup(struct uart_ip22zilog_port *up) { struct zilog_channel *channel; channel = ZILOG_CHANNEL_FROM_PORT(&up->port); + + __ip22zilog_reset(up); + + __load_zsregs(channel, up->curregs); + /* set master interrupt enable */ + write_zsreg(channel, R9, up->curregs[R9]); up->prev_status = readb(&channel->control); /* Enable receiver and transmitter. */ @@ -859,8 +894,6 @@ ip22zilog_set_termios(struct uart_port *port, struct ktermios *termios, else up->flags &= ~IP22ZILOG_FLAG_MODEM_STATUS; - up->cflag = termios->c_cflag; - ip22zilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(port)); uart_update_timeout(port, termios->c_cflag, baud); @@ -992,74 +1025,29 @@ ip22zilog_console_write(struct console *con, const char *s, unsigned int count) spin_unlock_irqrestore(&up->port.lock, flags); } -void -ip22serial_console_termios(struct console *con, char *options) -{ - int baud = 9600, bits = 8, cflag; - int parity = 'n'; - int flow = 'n'; - - if (options) - uart_parse_options(options, &baud, &parity, &bits, &flow); - - cflag = CREAD | HUPCL | CLOCAL; - - switch (baud) { - case 150: cflag |= B150; break; - case 300: cflag |= B300; break; - case 600: cflag |= B600; break; - case 1200: cflag |= B1200; break; - case 2400: cflag |= B2400; break; - case 4800: cflag |= B4800; break; - case 9600: cflag |= B9600; break; - case 19200: cflag |= B19200; break; - case 38400: cflag |= B38400; break; - default: baud = 9600; cflag |= B9600; break; - } - - con->cflag = cflag | CS8; /* 8N1 */ - - uart_update_timeout(&ip22zilog_port_table[con->index].port, cflag, baud); -} - static int __init ip22zilog_console_setup(struct console *con, char *options) { struct uart_ip22zilog_port *up = &ip22zilog_port_table[con->index]; unsigned long flags; - int baud, brg; - - printk("Console: ttyS%d (IP22-Zilog)\n", con->index); + int baud = 9600, bits = 8; + int parity = 'n'; + int flow = 'n'; - /* Get firmware console settings. */ - ip22serial_console_termios(con, options); + up->flags |= IP22ZILOG_FLAG_IS_CONS; - /* Firmware console speed is limited to 150-->38400 baud so - * this hackish cflag thing is OK. - */ - switch (con->cflag & CBAUD) { - case B150: baud = 150; break; - case B300: baud = 300; break; - case B600: baud = 600; break; - case B1200: baud = 1200; break; - case B2400: baud = 2400; break; - case B4800: baud = 4800; break; - default: case B9600: baud = 9600; break; - case B19200: baud = 19200; break; - case B38400: baud = 38400; break; - }; - - brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); + printk(KERN_INFO "Console: ttyS%d (IP22-Zilog)\n", con->index); spin_lock_irqsave(&up->port.lock, flags); - up->curregs[R15] = BRKIE; - ip22zilog_convert_to_zs(up, con->cflag, 0, brg); + up->curregs[R15] |= BRKIE; __ip22zilog_startup(up); spin_unlock_irqrestore(&up->port.lock, flags); - return 0; + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + return uart_set_options(&up->port, con, baud, parity, bits, flow); } static struct uart_driver ip22zilog_reg; @@ -1140,25 +1128,10 @@ static void __init ip22zilog_prepare(void) up[(chip * 2) + 1].port.line = (chip * 2) + 1; up[(chip * 2) + 1].flags |= IP22ZILOG_FLAG_IS_CHANNEL_A; } -} - -static void __init ip22zilog_init_hw(void) -{ - int i; - - for (i = 0; i < NUM_CHANNELS; i++) { - struct uart_ip22zilog_port *up = &ip22zilog_port_table[i]; - struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(&up->port); - unsigned long flags; - int baud, brg; - spin_lock_irqsave(&up->port.lock, flags); - - if (ZS_IS_CHANNEL_A(up)) { - write_zsreg(channel, R9, FHWRES); - ZSDELAY_LONG(); - (void) read_zsreg(channel, R0); - } + for (channel = 0; channel < NUM_CHANNELS; channel++) { + struct uart_ip22zilog_port *up = &ip22zilog_port_table[channel]; + int brg; /* Normal serial TTY. */ up->parity_mask = 0xff; @@ -1169,16 +1142,10 @@ static void __init ip22zilog_init_hw(void) up->curregs[R9] = NV | MIE; up->curregs[R10] = NRZ; up->curregs[R11] = TCBR | RCBR; - baud = 9600; - brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); + brg = BPS_TO_BRG(9600, ZS_CLOCK / ZS_CLOCK_DIVISOR); up->curregs[R12] = (brg & 0xff); up->curregs[R13] = (brg >> 8) & 0xff; up->curregs[R14] = BRENAB; - __load_zsregs(channel, up->curregs); - /* set master interrupt enable */ - write_zsreg(channel, R9, up->curregs[R9]); - - spin_unlock_irqrestore(&up->port.lock, flags); } } @@ -1195,8 +1162,6 @@ static int __init ip22zilog_ports_init(void) panic("IP22-Zilog: Unable to register zs interrupt handler.\n"); } - ip22zilog_init_hw(); - ret = uart_register_driver(&ip22zilog_reg); if (ret == 0) { int i; diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index af3a011b2b24..352fcb8926a6 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c @@ -585,11 +585,11 @@ serial_pxa_type(struct uart_port *port) return up->name; } -#ifdef CONFIG_SERIAL_PXA_CONSOLE - static struct uart_pxa_port *serial_pxa_ports[4]; static struct uart_driver serial_pxa_reg; +#ifdef CONFIG_SERIAL_PXA_CONSOLE + #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) /* diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index e89ae29645d6..d24621ce799a 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -77,7 +77,6 @@ # define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) # define SCSPTR0 0xA4400000 /* 16 bit SCIF */ -# define SCI_NPORTS 2 # define SCIF_ORER 0x0001 /* overrun error bit */ # define PACR 0xa4050100 # define PBCR 0xa4050102 @@ -102,12 +101,6 @@ # define SCIF_ORER 0x0001 /* overrun error bit */ # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ # define SCIF_ONLY -#elif defined(CONFIG_CPU_SUBTYPE_ST40STB1) -# define SCSPTR1 0xffe00020 /* 16 bit SCIF */ -# define SCSPTR2 0xffe80020 /* 16 bit SCIF */ -# define SCIF_ORER 0x0001 /* overrun error bit */ -# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ -# define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103) # include <asm/hardware.h> # define SCIF_BASE_ADDR 0x01030000 @@ -116,8 +109,7 @@ # define SCIF_LSR2_OFFS 0x0000024 # define SCSPTR2 ((port->mapbase)+SCIF_PTR2_OFFS) /* 16 bit SCIF */ # define SCLSR2 ((port->mapbase)+SCIF_LSR2_OFFS) /* 16 bit SCIF */ -# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0, - TE=1,RE=1,REIE=1 */ +# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0, TE=1,RE=1,REIE=1 */ # define SCIF_ONLY #elif defined(CONFIG_H83007) || defined(CONFIG_H83068) # define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ @@ -577,15 +569,6 @@ static inline int sci_rxd_in(struct uart_port *port) return ctrl_inb(SCPDR0) & 0x0001 ? 1 : 0; /* SCIF0 */ return 1; } -#elif defined(CONFIG_CPU_SUBTYPE_ST40STB1) -static inline int sci_rxd_in(struct uart_port *port) -{ - if (port->mapbase == 0xffe00000) - return ctrl_inw(SCSPTR1)&0x0001 ? 1 : 0; /* SCIF */ - else - return ctrl_inw(SCSPTR2)&0x0001 ? 1 : 0; /* SCIF */ - -} #elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103) static inline int sci_rxd_in(struct uart_port *port) { diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c index dfef83f14960..a85f2d31a686 100644 --- a/drivers/serial/uartlite.c +++ b/drivers/serial/uartlite.c @@ -329,12 +329,14 @@ static struct uart_ops ulite_ops = { static void ulite_console_wait_tx(struct uart_port *port) { int i; + u8 val; - /* wait up to 10ms for the character(s) to be sent */ - for (i = 0; i < 10000; i++) { - if (readb(port->membase + ULITE_STATUS) & ULITE_STATUS_TXEMPTY) + /* Spin waiting for TX fifo to have space available */ + for (i = 0; i < 100000; i++) { + val = readb(port->membase + ULITE_STATUS); + if ((val & ULITE_STATUS_TXFULL) == 0) break; - udelay(1); + cpu_relax(); } } diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c index 7d873b3b0513..4d0282b821b5 100644 --- a/drivers/sh/superhyway/superhyway.c +++ b/drivers/sh/superhyway/superhyway.c @@ -107,16 +107,17 @@ int superhyway_add_devices(struct superhyway_bus *bus, static int __init superhyway_init(void) { struct superhyway_bus *bus; - int ret = 0; + int ret; - device_register(&superhyway_bus_device); + ret = device_register(&superhyway_bus_device); + if (unlikely(ret)) + return ret; for (bus = superhyway_channels; bus->ops; bus++) ret |= superhyway_scan_bus(bus); return ret; } - postcore_initcall(superhyway_init); static const struct superhyway_device_id * diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index a77ede598d34..abf05048c638 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -61,7 +61,7 @@ config SPI_ATMEL config SPI_BFIN tristate "SPI controller driver for ADI Blackfin5xx" - depends on SPI_MASTER && BFIN + depends on SPI_MASTER && BLACKFIN help This is the SPI controller master driver for Blackfin 5xx processor. diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c index 0d342dcdd302..ff6a14bf1280 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c @@ -497,7 +497,7 @@ static int atmel_spi_setup(struct spi_device *spi) /* chipselect must have been muxed as GPIO (e.g. in board setup) */ npcs_pin = (unsigned int)spi->controller_data; if (!spi->controller_state) { - ret = gpio_request(npcs_pin, "spi_npcs"); + ret = gpio_request(npcs_pin, spi->dev.bus_id); if (ret) return ret; spi->controller_state = (void *)npcs_pin; diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 89769ce16f88..b31f4431849b 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -457,10 +457,11 @@ done: EXPORT_SYMBOL_GPL(spi_register_master); -static int __unregister(struct device *dev, void *unused) +static int __unregister(struct device *dev, void *master_dev) { /* note: before about 2.6.14-rc1 this would corrupt memory: */ - spi_unregister_device(to_spi_device(dev)); + if (dev != master_dev) + spi_unregister_device(to_spi_device(dev)); return 0; } @@ -478,7 +479,8 @@ void spi_unregister_master(struct spi_master *master) { int dummy; - dummy = device_for_each_child(master->dev.parent, NULL, __unregister); + dummy = device_for_each_child(master->dev.parent, &master->dev, + __unregister); device_unregister(&master->dev); } EXPORT_SYMBOL_GPL(spi_unregister_master); diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c index 0fa25e2e80fe..109d82c1abc0 100644 --- a/drivers/spi/spi_s3c24xx_gpio.c +++ b/drivers/spi/spi_s3c24xx_gpio.c @@ -96,6 +96,7 @@ static void s3c2410_spigpio_chipselect(struct spi_device *dev, int value) static int s3c2410_spigpio_probe(struct platform_device *dev) { + struct s3c2410_spigpio_info *info; struct spi_master *master; struct s3c2410_spigpio *sp; int ret; @@ -113,10 +114,11 @@ static int s3c2410_spigpio_probe(struct platform_device *dev) platform_set_drvdata(dev, sp); /* copy in the plkatform data */ - sp->info = dev->dev.platform_data; + info = sp->info = dev->dev.platform_data; /* setup spi bitbang adaptor */ sp->bitbang.master = spi_master_get(master); + sp->bitbang.master->bus_num = info->bus_num; sp->bitbang.chipselect = s3c2410_spigpio_chipselect; sp->bitbang.txrx_word[SPI_MODE_0] = s3c2410_spigpio_txrx_mode0; @@ -124,13 +126,18 @@ static int s3c2410_spigpio_probe(struct platform_device *dev) sp->bitbang.txrx_word[SPI_MODE_2] = s3c2410_spigpio_txrx_mode2; sp->bitbang.txrx_word[SPI_MODE_3] = s3c2410_spigpio_txrx_mode3; - /* set state of spi pins */ - s3c2410_gpio_setpin(sp->info->pin_clk, 0); - s3c2410_gpio_setpin(sp->info->pin_mosi, 0); + /* set state of spi pins, always assume that the clock is + * available, but do check the MOSI and MISO. */ + s3c2410_gpio_setpin(info->pin_clk, 0); + s3c2410_gpio_cfgpin(info->pin_clk, S3C2410_GPIO_OUTPUT); - s3c2410_gpio_cfgpin(sp->info->pin_clk, S3C2410_GPIO_OUTPUT); - s3c2410_gpio_cfgpin(sp->info->pin_mosi, S3C2410_GPIO_OUTPUT); - s3c2410_gpio_cfgpin(sp->info->pin_miso, S3C2410_GPIO_INPUT); + if (info->pin_mosi < S3C2410_GPH10) { + s3c2410_gpio_setpin(info->pin_mosi, 0); + s3c2410_gpio_cfgpin(info->pin_mosi, S3C2410_GPIO_OUTPUT); + } + + if (info->pin_miso != S3C2410_GPA0 && info->pin_miso < S3C2410_GPH10) + s3c2410_gpio_cfgpin(info->pin_miso, S3C2410_GPIO_INPUT); ret = spi_bitbang_start(&sp->bitbang); if (ret) diff --git a/drivers/spi/spi_txx9.c b/drivers/spi/spi_txx9.c index cc5094f37dd3..363ac8e68821 100644 --- a/drivers/spi/spi_txx9.c +++ b/drivers/spi/spi_txx9.c @@ -24,6 +24,7 @@ #include <linux/spi/spi.h> #include <linux/err.h> #include <linux/clk.h> +#include <linux/io.h> #include <asm/gpio.h> @@ -74,7 +75,6 @@ struct txx9spi { struct list_head queue; wait_queue_head_t waitq; void __iomem *membase; - int irq; int baseclk; struct clk *clk; u32 max_speed_hz, min_speed_hz; @@ -350,12 +350,12 @@ static int __init txx9spi_probe(struct platform_device *dev) struct resource *res; int ret = -ENODEV; u32 mcr; + int irq; master = spi_alloc_master(&dev->dev, sizeof(*c)); if (!master) return ret; c = spi_master_get_devdata(master); - c->irq = -1; platform_set_drvdata(dev, master); INIT_WORK(&c->work, txx9spi_work); @@ -381,32 +381,36 @@ static int __init txx9spi_probe(struct platform_device *dev) res = platform_get_resource(dev, IORESOURCE_MEM, 0); if (!res) - goto exit; - c->membase = ioremap(res->start, res->end - res->start + 1); + goto exit_busy; + if (!devm_request_mem_region(&dev->dev, + res->start, res->end - res->start + 1, + "spi_txx9")) + goto exit_busy; + c->membase = devm_ioremap(&dev->dev, + res->start, res->end - res->start + 1); if (!c->membase) - goto exit; + goto exit_busy; /* enter config mode */ mcr = txx9spi_rd(c, TXx9_SPMCR); mcr &= ~(TXx9_SPMCR_OPMODE | TXx9_SPMCR_SPSTP | TXx9_SPMCR_BCLR); txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR, TXx9_SPMCR); - c->irq = platform_get_irq(dev, 0); - if (c->irq < 0) - goto exit; - ret = request_irq(c->irq, txx9spi_interrupt, 0, dev->name, c); - if (ret) { - c->irq = -1; + irq = platform_get_irq(dev, 0); + if (irq < 0) + goto exit_busy; + ret = devm_request_irq(&dev->dev, irq, txx9spi_interrupt, 0, + "spi_txx9", c); + if (ret) goto exit; - } c->workqueue = create_singlethread_workqueue(master->dev.parent->bus_id); if (!c->workqueue) - goto exit; + goto exit_busy; c->last_chipselect = -1; dev_info(&dev->dev, "at %#llx, irq %d, %dMHz\n", - (unsigned long long)res->start, c->irq, + (unsigned long long)res->start, irq, (c->baseclk + 500000) / 1000000); master->bus_num = dev->id; @@ -418,13 +422,11 @@ static int __init txx9spi_probe(struct platform_device *dev) if (ret) goto exit; return 0; +exit_busy: + ret = -EBUSY; exit: if (c->workqueue) destroy_workqueue(c->workqueue); - if (c->irq >= 0) - free_irq(c->irq, c); - if (c->membase) - iounmap(c->membase); if (c->clk) { clk_disable(c->clk); clk_put(c->clk); @@ -442,8 +444,6 @@ static int __exit txx9spi_remove(struct platform_device *dev) spi_unregister_master(master); platform_set_drvdata(dev, NULL); destroy_workqueue(c->workqueue); - free_irq(c->irq, c); - iounmap(c->membase); clk_disable(c->clk); clk_put(c->clk); spi_master_put(master); diff --git a/drivers/spi/tle62x0.c b/drivers/spi/tle62x0.c index 6da58ca48b33..455991fbe28f 100644 --- a/drivers/spi/tle62x0.c +++ b/drivers/spi/tle62x0.c @@ -107,8 +107,11 @@ static ssize_t tle62x0_status_show(struct device *dev, mutex_lock(&st->lock); ret = tle62x0_read(st); - dev_dbg(dev, "tle62x0_read() returned %d\n", ret); + if (ret < 0) { + mutex_unlock(&st->lock); + return ret; + } for (ptr = 0; ptr < (st->nr_gpio * 2)/8; ptr += 1) { fault <<= 8; diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index c12a741b5574..85a20546e827 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c @@ -440,6 +440,7 @@ static int ssb_devices_register(struct ssb_bus *bus) break; case SSB_BUSTYPE_PCMCIA: #ifdef CONFIG_SSB_PCMCIAHOST + sdev->irq = bus->host_pcmcia->irq.AssignedIRQ; dev->parent = &bus->host_pcmcia->dev; #endif break; @@ -1147,7 +1148,10 @@ static int __init ssb_modinit(void) return err; } -subsys_initcall(ssb_modinit); +/* ssb must be initialized after PCI but before the ssb drivers. + * That means we must use some initcall between subsys_initcall + * and device_initcall. */ +fs_initcall(ssb_modinit); static void __exit ssb_modexit(void) { diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c index b6abee846f02..bb44a76b3eb5 100644 --- a/drivers/ssb/pcmcia.c +++ b/drivers/ssb/pcmcia.c @@ -63,17 +63,17 @@ int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus, err = pcmcia_access_configuration_register(pdev, ®); if (err != CS_SUCCESS) goto error; - read_addr |= (reg.Value & 0xF) << 12; + read_addr |= ((u32)(reg.Value & 0x0F)) << 12; reg.Offset = 0x30; err = pcmcia_access_configuration_register(pdev, ®); if (err != CS_SUCCESS) goto error; - read_addr |= reg.Value << 16; + read_addr |= ((u32)reg.Value) << 16; reg.Offset = 0x32; err = pcmcia_access_configuration_register(pdev, ®); if (err != CS_SUCCESS) goto error; - read_addr |= reg.Value << 24; + read_addr |= ((u32)reg.Value) << 24; cur_core = (read_addr - SSB_ENUM_BASE) / SSB_CORE_SIZE; if (cur_core == coreidx) @@ -152,28 +152,29 @@ error: goto out_unlock; } -/* These are the main device register access functions. - * do_select_core is inline to have the likely hotpath inline. - * All unlikely codepaths are out-of-line. */ -static inline int do_select_core(struct ssb_bus *bus, - struct ssb_device *dev, - u16 *offset) +static int select_core_and_segment(struct ssb_device *dev, + u16 *offset) { + struct ssb_bus *bus = dev->bus; int err; - u8 need_seg = (*offset >= 0x800) ? 1 : 0; + u8 need_segment; + + if (*offset >= 0x800) { + *offset -= 0x800; + need_segment = 1; + } else + need_segment = 0; if (unlikely(dev != bus->mapped_device)) { err = ssb_pcmcia_switch_core(bus, dev); if (unlikely(err)) return err; } - if (unlikely(need_seg != bus->mapped_pcmcia_seg)) { - err = ssb_pcmcia_switch_segment(bus, need_seg); + if (unlikely(need_segment != bus->mapped_pcmcia_seg)) { + err = ssb_pcmcia_switch_segment(bus, need_segment); if (unlikely(err)) return err; } - if (need_seg == 1) - *offset -= 0x800; return 0; } @@ -181,32 +182,31 @@ static inline int do_select_core(struct ssb_bus *bus, static u16 ssb_pcmcia_read16(struct ssb_device *dev, u16 offset) { struct ssb_bus *bus = dev->bus; - u16 x; - if (unlikely(do_select_core(bus, dev, &offset))) + if (unlikely(select_core_and_segment(dev, &offset))) return 0xFFFF; - x = readw(bus->mmio + offset); - return x; + return readw(bus->mmio + offset); } static u32 ssb_pcmcia_read32(struct ssb_device *dev, u16 offset) { struct ssb_bus *bus = dev->bus; - u32 x; + u32 lo, hi; - if (unlikely(do_select_core(bus, dev, &offset))) + if (unlikely(select_core_and_segment(dev, &offset))) return 0xFFFFFFFF; - x = readl(bus->mmio + offset); + lo = readw(bus->mmio + offset); + hi = readw(bus->mmio + offset + 2); - return x; + return (lo | (hi << 16)); } static void ssb_pcmcia_write16(struct ssb_device *dev, u16 offset, u16 value) { struct ssb_bus *bus = dev->bus; - if (unlikely(do_select_core(bus, dev, &offset))) + if (unlikely(select_core_and_segment(dev, &offset))) return; writew(value, bus->mmio + offset); } @@ -215,12 +215,12 @@ static void ssb_pcmcia_write32(struct ssb_device *dev, u16 offset, u32 value) { struct ssb_bus *bus = dev->bus; - if (unlikely(do_select_core(bus, dev, &offset))) + if (unlikely(select_core_and_segment(dev, &offset))) return; - readw(bus->mmio + offset); - writew(value >> 16, bus->mmio + offset + 2); - readw(bus->mmio + offset); - writew(value, bus->mmio + offset); + writeb((value & 0xFF000000) >> 24, bus->mmio + offset + 3); + writeb((value & 0x00FF0000) >> 16, bus->mmio + offset + 2); + writeb((value & 0x0000FF00) >> 8, bus->mmio + offset + 1); + writeb((value & 0x000000FF) >> 0, bus->mmio + offset + 0); } /* Not "static", as it's used in main.c */ diff --git a/drivers/usb/README b/drivers/usb/README index 3c8434128554..284f46b3e1cc 100644 --- a/drivers/usb/README +++ b/drivers/usb/README @@ -39,12 +39,12 @@ first subdirectory in the list below that it fits into. image/ - This is for still image drivers, like scanners or digital cameras. -input/ - This is for any driver that uses the input subsystem, +../input/ - This is for any driver that uses the input subsystem, like keyboard, mice, touchscreens, tablets, etc. -media/ - This is for multimedia drivers, like video cameras, +../media/ - This is for multimedia drivers, like video cameras, radios, and any other drivers that talk to the v4l subsystem. -net/ - This is for network drivers. +../net/ - This is for network drivers. serial/ - This is for USB to serial drivers. storage/ - This is for USB mass-storage drivers. class/ - This is for all USB device drivers that do not fit diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 8586817698ad..c51f8e9312e0 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -585,9 +585,6 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env) { struct usb_device *usb_dev; - if (!dev) - return -ENODEV; - /* driver is often null here; dev_dbg() would oops */ pr_debug ("usb %s: uevent\n", dev->bus_id); @@ -631,14 +628,6 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env) usb_dev->descriptor.bDeviceProtocol)) return -ENOMEM; - if (add_uevent_var(env, "BUSNUM=%03d", - usb_dev->bus->busnum)) - return -ENOMEM; - - if (add_uevent_var(env, "DEVNUM=%03d", - usb_dev->devnum)) - return -ENOMEM; - return 0; } diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index fea8256a18d6..d5ed3fa9e304 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1311,8 +1311,8 @@ void usb_hcd_flush_endpoint(struct usb_device *udev, hcd = bus_to_hcd(udev->bus); /* No more submits can occur */ -rescan: spin_lock_irq(&hcd_urb_list_lock); +rescan: list_for_each_entry (urb, &ep->urb_list, urb_list) { int is_in; @@ -1345,6 +1345,7 @@ rescan: usb_put_urb (urb); /* list contents may have changed */ + spin_lock(&hcd_urb_list_lock); goto rescan; } spin_unlock_irq(&hcd_urb_list_lock); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 036c3dea855e..13b326a13377 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -335,7 +335,7 @@ static void kick_khubd(struct usb_hub *hub) to_usb_interface(hub->intfdev)->pm_usage_cnt = 1; spin_lock_irqsave(&hub_event_lock, flags); - if (!hub->disconnected & list_empty(&hub->event_list)) { + if (!hub->disconnected && list_empty(&hub->event_list)) { list_add_tail(&hub->event_list, &hub_event_list); wake_up(&khubd_wait); } diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 316a746e0080..fcd40ecbeecc 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1172,7 +1172,6 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) struct usb_host_interface *alt; int ret; int manual = 0; - int changed; if (dev->state == USB_STATE_SUSPENDED) return -EHOSTUNREACH; @@ -1212,8 +1211,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) */ /* prevent submissions using previous endpoint settings */ - changed = (iface->cur_altsetting != alt); - if (changed && device_is_registered(&iface->dev)) + if (iface->cur_altsetting != alt && device_is_registered(&iface->dev)) usb_remove_sysfs_intf_files(iface); usb_disable_interface(dev, iface); @@ -1250,7 +1248,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) * (Likewise, EP0 never "halts" on well designed devices.) */ usb_enable_interface(dev, iface); - if (changed && device_is_registered(&iface->dev)) + if (device_is_registered(&iface->dev)) usb_create_sysfs_intf_files(iface); return 0; @@ -1348,34 +1346,10 @@ static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env) struct usb_interface *intf; struct usb_host_interface *alt; - if (!dev) - return -ENODEV; - - /* driver is often null here; dev_dbg() would oops */ - pr_debug ("usb %s: uevent\n", dev->bus_id); - intf = to_usb_interface(dev); usb_dev = interface_to_usbdev(intf); alt = intf->cur_altsetting; -#ifdef CONFIG_USB_DEVICEFS - if (add_uevent_var(env, "DEVICE=/proc/bus/usb/%03d/%03d", - usb_dev->bus->busnum, usb_dev->devnum)) - return -ENOMEM; -#endif - - if (add_uevent_var(env, "PRODUCT=%x/%x/%x", - le16_to_cpu(usb_dev->descriptor.idVendor), - le16_to_cpu(usb_dev->descriptor.idProduct), - le16_to_cpu(usb_dev->descriptor.bcdDevice))) - return -ENOMEM; - - if (add_uevent_var(env, "TYPE=%d/%d/%d", - usb_dev->descriptor.bDeviceClass, - usb_dev->descriptor.bDeviceSubClass, - usb_dev->descriptor.bDeviceProtocol)) - return -ENOMEM; - if (add_uevent_var(env, "INTERFACE=%d/%d/%d", alt->desc.bInterfaceClass, alt->desc.bInterfaceSubClass, @@ -1641,12 +1615,6 @@ free_interfaces: intf->dev.bus_id, ret); continue; } - - /* The driver's probe method can call usb_set_interface(), - * which would mean the interface's sysfs files are already - * created. Just in case, we'll remove them first. - */ - usb_remove_sysfs_intf_files(intf); usb_create_sysfs_intf_files(intf); } diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index b04afd06e502..32bd130b1eed 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -735,6 +735,8 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf) struct usb_host_interface *alt = intf->cur_altsetting; int retval; + if (intf->sysfs_files_created) + return 0; retval = sysfs_create_group(&dev->kobj, &intf_attr_grp); if (retval) return retval; @@ -746,6 +748,7 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf) if (intf->intf_assoc) retval = sysfs_create_group(&dev->kobj, &intf_assoc_attr_grp); usb_create_intf_ep_files(intf, udev); + intf->sysfs_files_created = 1; return 0; } @@ -753,8 +756,11 @@ void usb_remove_sysfs_intf_files(struct usb_interface *intf) { struct device *dev = &intf->dev; + if (!intf->sysfs_files_created) + return; usb_remove_intf_ep_files(intf); device_remove_file(dev, &dev_attr_interface); sysfs_remove_group(&dev->kobj, &intf_attr_grp); sysfs_remove_group(&intf->dev.kobj, &intf_assoc_attr_grp); + intf->sysfs_files_created = 0; } diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index c4a6f1095b8b..8f142370103d 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -192,9 +192,34 @@ static void usb_release_dev(struct device *dev) kfree(udev); } +#ifdef CONFIG_HOTPLUG +static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + struct usb_device *usb_dev; + + usb_dev = to_usb_device(dev); + + if (add_uevent_var(env, "BUSNUM=%03d", usb_dev->bus->busnum)) + return -ENOMEM; + + if (add_uevent_var(env, "DEVNUM=%03d", usb_dev->devnum)) + return -ENOMEM; + + return 0; +} + +#else + +static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + return -ENODEV; +} +#endif /* CONFIG_HOTPLUG */ + struct device_type usb_device_type = { .name = "usb_device", .release = usb_release_dev, + .uevent = usb_dev_uevent, }; #ifdef CONFIG_PM diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 87c4f50dfb61..d377154658b5 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -1241,14 +1241,14 @@ static void pullup_enable(struct omap_udc *udc) udc->gadget.dev.parent->power.power_state = PMSG_ON; udc->gadget.dev.power.power_state = PMSG_ON; UDC_SYSCON1_REG |= UDC_PULLUP_EN; - if (!gadget_is_otg(udc->gadget) && !cpu_is_omap15xx()) + if (!gadget_is_otg(&udc->gadget) && !cpu_is_omap15xx()) OTG_CTRL_REG |= OTG_BSESSVLD; UDC_IRQ_EN_REG = UDC_DS_CHG_IE; } static void pullup_disable(struct omap_udc *udc) { - if (!gadget_is_otg(udc->gadget) && !cpu_is_omap15xx()) + if (!gadget_is_otg(&udc->gadget) && !cpu_is_omap15xx()) OTG_CTRL_REG &= ~OTG_BSESSVLD; UDC_IRQ_EN_REG = UDC_DS_CHG_IE; UDC_SYSCON1_REG &= ~UDC_PULLUP_EN; @@ -1386,7 +1386,7 @@ static void update_otg(struct omap_udc *udc) { u16 devstat; - if (!gadget_is_otg(udc->gadget)) + if (!gadget_is_otg(&udc->gadget)) return; if (OTG_CTRL_REG & OTG_ID) diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index e3e90f8a75e7..4ce050c3d13f 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -52,10 +52,10 @@ #include <asm/arch/irqs.h> #include <asm/arch/hardware.h> -#include <asm/arch/regs-clock.h> #include <asm/arch/regs-gpio.h> -#include <asm/arch/regs-udc.h> -#include <asm/arch/udc.h> + +#include <asm/plat-s3c24xx/regs-udc.h> +#include <asm/plat-s3c24xx/udc.h> #include <asm/mach-types.h> @@ -1511,7 +1511,11 @@ static irqreturn_t s3c2410_udc_vbus_irq(int irq, void *_dev) unsigned int value; dprintk(DEBUG_NORMAL, "%s()\n", __func__); + + /* some cpus cannot read from an line configured to IRQ! */ + s3c2410_gpio_cfgpin(udc_info->vbus_pin, S3C2410_GPIO_INPUT); value = s3c2410_gpio_getpin(udc_info->vbus_pin); + s3c2410_gpio_cfgpin(udc_info->vbus_pin, S3C2410_GPIO_SFN2); if (udc_info->vbus_pin_inverted) value = !value; @@ -1872,9 +1876,9 @@ static int s3c2410_udc_probe(struct platform_device *pdev) if (udc_info && udc_info->vbus_pin > 0) { irq = s3c2410_gpio_getirq(udc_info->vbus_pin); retval = request_irq(irq, s3c2410_udc_vbus_irq, - IRQF_DISABLED | IRQF_TRIGGER_RISING - | IRQF_TRIGGER_FALLING, - gadget_name, udc); + IRQF_DISABLED | IRQF_TRIGGER_RISING + | IRQF_TRIGGER_FALLING | IRQF_SHARED, + gadget_name, udc); if (retval != 0) { dev_err(dev, "can't get vbus irq %i, err %d\n", diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 177e78ed241b..49a91c5ee51b 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -156,7 +156,7 @@ config USB_OHCI_HCD_PCI config USB_OHCI_HCD_SSB bool "OHCI support for Broadcom SSB OHCI core" - depends on USB_OHCI_HCD && (SSB = y || SSB = CONFIG_USB_OHCI_HCD) && EXPERIMENTAL + depends on USB_OHCI_HCD && (SSB = y || SSB = USB_OHCI_HCD) && EXPERIMENTAL default n ---help--- Support for the Sonics Silicon Backplane (SSB) attached diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index c1514442883e..5f2d74ed5ad7 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -575,12 +575,15 @@ static int ehci_run (struct usb_hcd *hcd) * from the companions to the EHCI controller. If any of the * companions are in the middle of a port reset at the time, it * could cause trouble. Write-locking ehci_cf_port_reset_rwsem - * guarantees that no resets are in progress. + * guarantees that no resets are in progress. After we set CF, + * a short delay lets the hardware catch up; new resets shouldn't + * be started before the port switching actions could complete. */ down_write(&ehci_cf_port_reset_rwsem); hcd->state = HC_STATE_RUNNING; ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ + msleep(5); up_write(&ehci_cf_port_reset_rwsem); temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase)); diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c index 91e999c9f680..bc207e3c21f5 100644 --- a/drivers/usb/image/microtek.c +++ b/drivers/usb/image/microtek.c @@ -819,7 +819,7 @@ static int mts_usb_probe(struct usb_interface *intf, goto out_kfree2; new_desc->host->hostdata[0] = (unsigned long)new_desc; - if (scsi_add_host(new_desc->host, NULL)) { + if (scsi_add_host(new_desc->host, &dev->dev)) { err_retval = -EIO; goto out_host_put; } diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index c567aa7a41ea..5a2c44e4c1f7 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -79,12 +79,22 @@ MODULE_DEVICE_TABLE(usb, device_table); #define COMMAND_TIMEOUT (2*HZ) /* 60 second timeout for a command */ +/* + * The locking scheme is a vanilla 3-lock: + * adu_device.buflock: A spinlock, covers what IRQs touch. + * adutux_mutex: A Static lock to cover open_count. It would also cover + * any globals, but we don't have them in 2.6. + * adu_device.mtx: A mutex to hold across sleepers like copy_from_user. + * It covers all of adu_device, except the open_count + * and what .buflock covers. + */ + /* Structure to hold all of our device specific stuff */ struct adu_device { - struct mutex mtx; /* locks this structure */ + struct mutex mtx; struct usb_device* udev; /* save off the usb device pointer */ struct usb_interface* interface; - unsigned char minor; /* the starting minor number for this device */ + unsigned int minor; /* the starting minor number for this device */ char serial_number[8]; int open_count; /* number of times this port has been opened */ @@ -107,8 +117,11 @@ struct adu_device { char* interrupt_out_buffer; struct usb_endpoint_descriptor* interrupt_out_endpoint; struct urb* interrupt_out_urb; + int out_urb_finished; }; +static DEFINE_MUTEX(adutux_mutex); + static struct usb_driver adu_driver; static void adu_debug_data(int level, const char *function, int size, @@ -132,27 +145,31 @@ static void adu_debug_data(int level, const char *function, int size, */ static void adu_abort_transfers(struct adu_device *dev) { - dbg(2," %s : enter", __FUNCTION__); + unsigned long flags; - if (dev == NULL) { - dbg(1," %s : dev is null", __FUNCTION__); - goto exit; - } + dbg(2," %s : enter", __FUNCTION__); if (dev->udev == NULL) { dbg(1," %s : udev is null", __FUNCTION__); goto exit; } - dbg(2," %s : udev state %d", __FUNCTION__, dev->udev->state); - if (dev->udev->state == USB_STATE_NOTATTACHED) { - dbg(1," %s : udev is not attached", __FUNCTION__); - goto exit; - } - /* shutdown transfer */ - usb_unlink_urb(dev->interrupt_in_urb); - usb_unlink_urb(dev->interrupt_out_urb); + + /* XXX Anchor these instead */ + spin_lock_irqsave(&dev->buflock, flags); + if (!dev->read_urb_finished) { + spin_unlock_irqrestore(&dev->buflock, flags); + usb_kill_urb(dev->interrupt_in_urb); + } else + spin_unlock_irqrestore(&dev->buflock, flags); + + spin_lock_irqsave(&dev->buflock, flags); + if (!dev->out_urb_finished) { + spin_unlock_irqrestore(&dev->buflock, flags); + usb_kill_urb(dev->interrupt_out_urb); + } else + spin_unlock_irqrestore(&dev->buflock, flags); exit: dbg(2," %s : leave", __FUNCTION__); @@ -162,8 +179,6 @@ static void adu_delete(struct adu_device *dev) { dbg(2, "%s enter", __FUNCTION__); - adu_abort_transfers(dev); - /* free data structures */ usb_free_urb(dev->interrupt_in_urb); usb_free_urb(dev->interrupt_out_urb); @@ -239,7 +254,10 @@ static void adu_interrupt_out_callback(struct urb *urb) goto exit; } - wake_up_interruptible(&dev->write_wait); + spin_lock(&dev->buflock); + dev->out_urb_finished = 1; + wake_up(&dev->write_wait); + spin_unlock(&dev->buflock); exit: adu_debug_data(5, __FUNCTION__, urb->actual_length, @@ -252,12 +270,17 @@ static int adu_open(struct inode *inode, struct file *file) struct adu_device *dev = NULL; struct usb_interface *interface; int subminor; - int retval = 0; + int retval; dbg(2,"%s : enter", __FUNCTION__); subminor = iminor(inode); + if ((retval = mutex_lock_interruptible(&adutux_mutex))) { + dbg(2, "%s : mutex lock failed", __FUNCTION__); + goto exit_no_lock; + } + interface = usb_find_interface(&adu_driver, subminor); if (!interface) { err("%s - error, can't find device for minor %d", @@ -267,54 +290,54 @@ static int adu_open(struct inode *inode, struct file *file) } dev = usb_get_intfdata(interface); - if (!dev) { + if (!dev || !dev->udev) { retval = -ENODEV; goto exit_no_device; } - /* lock this device */ - if ((retval = mutex_lock_interruptible(&dev->mtx))) { - dbg(2, "%s : mutex lock failed", __FUNCTION__); + /* check that nobody else is using the device */ + if (dev->open_count) { + retval = -EBUSY; goto exit_no_device; } - /* increment our usage count for the device */ ++dev->open_count; dbg(2,"%s : open count %d", __FUNCTION__, dev->open_count); /* save device in the file's private structure */ file->private_data = dev; - if (dev->open_count == 1) { - /* initialize in direction */ - dev->read_buffer_length = 0; + /* initialize in direction */ + dev->read_buffer_length = 0; - /* fixup first read by having urb waiting for it */ - usb_fill_int_urb(dev->interrupt_in_urb,dev->udev, - usb_rcvintpipe(dev->udev, - dev->interrupt_in_endpoint->bEndpointAddress), - dev->interrupt_in_buffer, - le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize), - adu_interrupt_in_callback, dev, - dev->interrupt_in_endpoint->bInterval); - /* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */ - dev->read_urb_finished = 0; - retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL); - if (retval) - --dev->open_count; - } - mutex_unlock(&dev->mtx); + /* fixup first read by having urb waiting for it */ + usb_fill_int_urb(dev->interrupt_in_urb,dev->udev, + usb_rcvintpipe(dev->udev, + dev->interrupt_in_endpoint->bEndpointAddress), + dev->interrupt_in_buffer, + le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize), + adu_interrupt_in_callback, dev, + dev->interrupt_in_endpoint->bInterval); + dev->read_urb_finished = 0; + if (usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL)) + dev->read_urb_finished = 1; + /* we ignore failure */ + /* end of fixup for first read */ + + /* initialize out direction */ + dev->out_urb_finished = 1; + + retval = 0; exit_no_device: + mutex_unlock(&adutux_mutex); +exit_no_lock: dbg(2,"%s : leave, return value %d ", __FUNCTION__, retval); - return retval; } -static int adu_release_internal(struct adu_device *dev) +static void adu_release_internal(struct adu_device *dev) { - int retval = 0; - dbg(2," %s : enter", __FUNCTION__); /* decrement our usage count for the device */ @@ -326,12 +349,11 @@ static int adu_release_internal(struct adu_device *dev) } dbg(2," %s : leave", __FUNCTION__); - return retval; } static int adu_release(struct inode *inode, struct file *file) { - struct adu_device *dev = NULL; + struct adu_device *dev; int retval = 0; dbg(2," %s : enter", __FUNCTION__); @@ -343,15 +365,13 @@ static int adu_release(struct inode *inode, struct file *file) } dev = file->private_data; - if (dev == NULL) { dbg(1," %s : object is NULL", __FUNCTION__); retval = -ENODEV; goto exit; } - /* lock our device */ - mutex_lock(&dev->mtx); /* not interruptible */ + mutex_lock(&adutux_mutex); /* not interruptible */ if (dev->open_count <= 0) { dbg(1," %s : device not opened", __FUNCTION__); @@ -359,19 +379,15 @@ static int adu_release(struct inode *inode, struct file *file) goto exit; } + adu_release_internal(dev); if (dev->udev == NULL) { /* the device was unplugged before the file was released */ - mutex_unlock(&dev->mtx); - adu_delete(dev); - dev = NULL; - } else { - /* do the work */ - retval = adu_release_internal(dev); + if (!dev->open_count) /* ... and we're the last user */ + adu_delete(dev); } exit: - if (dev) - mutex_unlock(&dev->mtx); + mutex_unlock(&adutux_mutex); dbg(2," %s : leave, return value %d", __FUNCTION__, retval); return retval; } @@ -393,12 +409,12 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, dev = file->private_data; dbg(2," %s : dev=%p", __FUNCTION__, dev); - /* lock this object */ + if (mutex_lock_interruptible(&dev->mtx)) return -ERESTARTSYS; /* verify that the device wasn't unplugged */ - if (dev->udev == NULL || dev->minor == 0) { + if (dev->udev == NULL) { retval = -ENODEV; err("No device or device unplugged %d", retval); goto exit; @@ -452,7 +468,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, should_submit = 1; } else { /* even the primary was empty - we may need to do IO */ - if (dev->interrupt_in_urb->status == -EINPROGRESS) { + if (!dev->read_urb_finished) { /* somebody is doing IO */ spin_unlock_irqrestore(&dev->buflock, flags); dbg(2," %s : submitted already", __FUNCTION__); @@ -460,6 +476,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, /* we must initiate input */ dbg(2," %s : initiate input", __FUNCTION__); dev->read_urb_finished = 0; + spin_unlock_irqrestore(&dev->buflock, flags); usb_fill_int_urb(dev->interrupt_in_urb,dev->udev, usb_rcvintpipe(dev->udev, @@ -469,15 +486,12 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, adu_interrupt_in_callback, dev, dev->interrupt_in_endpoint->bInterval); - retval = usb_submit_urb(dev->interrupt_in_urb, GFP_ATOMIC); - if (!retval) { - spin_unlock_irqrestore(&dev->buflock, flags); - dbg(2," %s : submitted OK", __FUNCTION__); - } else { + retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL); + if (retval) { + dev->read_urb_finished = 1; if (retval == -ENOMEM) { retval = bytes_read ? bytes_read : -ENOMEM; } - spin_unlock_irqrestore(&dev->buflock, flags); dbg(2," %s : submit failed", __FUNCTION__); goto exit; } @@ -486,10 +500,14 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, /* we wait for I/O to complete */ set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(&dev->read_wait, &wait); - if (!dev->read_urb_finished) + spin_lock_irqsave(&dev->buflock, flags); + if (!dev->read_urb_finished) { + spin_unlock_irqrestore(&dev->buflock, flags); timeout = schedule_timeout(COMMAND_TIMEOUT); - else + } else { + spin_unlock_irqrestore(&dev->buflock, flags); set_current_state(TASK_RUNNING); + } remove_wait_queue(&dev->read_wait, &wait); if (timeout <= 0) { @@ -509,19 +527,23 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, retval = bytes_read; /* if the primary buffer is empty then use it */ - if (should_submit && !dev->interrupt_in_urb->status==-EINPROGRESS) { + spin_lock_irqsave(&dev->buflock, flags); + if (should_submit && dev->read_urb_finished) { + dev->read_urb_finished = 0; + spin_unlock_irqrestore(&dev->buflock, flags); usb_fill_int_urb(dev->interrupt_in_urb,dev->udev, usb_rcvintpipe(dev->udev, dev->interrupt_in_endpoint->bEndpointAddress), - dev->interrupt_in_buffer, - le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize), - adu_interrupt_in_callback, - dev, - dev->interrupt_in_endpoint->bInterval); - /* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */ - dev->read_urb_finished = 0; - usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL); + dev->interrupt_in_buffer, + le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize), + adu_interrupt_in_callback, + dev, + dev->interrupt_in_endpoint->bInterval); + if (usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL) != 0) + dev->read_urb_finished = 1; /* we ignore failure */ + } else { + spin_unlock_irqrestore(&dev->buflock, flags); } exit: @@ -535,24 +557,24 @@ exit: static ssize_t adu_write(struct file *file, const __user char *buffer, size_t count, loff_t *ppos) { + DECLARE_WAITQUEUE(waita, current); struct adu_device *dev; size_t bytes_written = 0; size_t bytes_to_write; size_t buffer_size; + unsigned long flags; int retval; - int timeout = 0; dbg(2," %s : enter, count = %Zd", __FUNCTION__, count); dev = file->private_data; - /* lock this object */ retval = mutex_lock_interruptible(&dev->mtx); if (retval) goto exit_nolock; /* verify that the device wasn't unplugged */ - if (dev->udev == NULL || dev->minor == 0) { + if (dev->udev == NULL) { retval = -ENODEV; err("No device or device unplugged %d", retval); goto exit; @@ -564,42 +586,37 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, goto exit; } - while (count > 0) { - if (dev->interrupt_out_urb->status == -EINPROGRESS) { - timeout = COMMAND_TIMEOUT; + add_wait_queue(&dev->write_wait, &waita); + set_current_state(TASK_INTERRUPTIBLE); + spin_lock_irqsave(&dev->buflock, flags); + if (!dev->out_urb_finished) { + spin_unlock_irqrestore(&dev->buflock, flags); - while (timeout > 0) { - if (signal_pending(current)) { + mutex_unlock(&dev->mtx); + if (signal_pending(current)) { dbg(1," %s : interrupted", __FUNCTION__); + set_current_state(TASK_RUNNING); retval = -EINTR; - goto exit; + goto exit_onqueue; } - mutex_unlock(&dev->mtx); - timeout = interruptible_sleep_on_timeout(&dev->write_wait, timeout); + if (schedule_timeout(COMMAND_TIMEOUT) == 0) { + dbg(1, "%s - command timed out.", __FUNCTION__); + retval = -ETIMEDOUT; + goto exit_onqueue; + } + remove_wait_queue(&dev->write_wait, &waita); retval = mutex_lock_interruptible(&dev->mtx); if (retval) { retval = bytes_written ? bytes_written : retval; goto exit_nolock; } - if (timeout > 0) { - break; - } - dbg(1," %s : interrupted timeout: %d", __FUNCTION__, timeout); - } - - - dbg(1," %s : final timeout: %d", __FUNCTION__, timeout); - - if (timeout == 0) { - dbg(1, "%s - command timed out.", __FUNCTION__); - retval = -ETIMEDOUT; - goto exit; - } - - dbg(4," %s : in progress, count = %Zd", __FUNCTION__, count); + dbg(4," %s : in progress, count = %Zd", __FUNCTION__, count); } else { + spin_unlock_irqrestore(&dev->buflock, flags); + set_current_state(TASK_RUNNING); + remove_wait_queue(&dev->write_wait, &waita); dbg(4," %s : sending, count = %Zd", __FUNCTION__, count); /* write the data into interrupt_out_buffer from userspace */ @@ -622,11 +639,12 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, bytes_to_write, adu_interrupt_out_callback, dev, - dev->interrupt_in_endpoint->bInterval); - /* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */ + dev->interrupt_out_endpoint->bInterval); dev->interrupt_out_urb->actual_length = bytes_to_write; + dev->out_urb_finished = 0; retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL); if (retval < 0) { + dev->out_urb_finished = 1; err("Couldn't submit interrupt_out_urb %d", retval); goto exit; } @@ -637,16 +655,17 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, bytes_written += bytes_to_write; } } - - retval = bytes_written; + mutex_unlock(&dev->mtx); + return bytes_written; exit: - /* unlock the device */ mutex_unlock(&dev->mtx); exit_nolock: - dbg(2," %s : leave, return value %d", __FUNCTION__, retval); + return retval; +exit_onqueue: + remove_wait_queue(&dev->write_wait, &waita); return retval; } @@ -831,25 +850,22 @@ static void adu_disconnect(struct usb_interface *interface) dbg(2," %s : enter", __FUNCTION__); dev = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); + mutex_lock(&dev->mtx); /* not interruptible */ + dev->udev = NULL; /* poison */ minor = dev->minor; - - /* give back our minor */ usb_deregister_dev(interface, &adu_class); - dev->minor = 0; + mutex_unlock(&dev->mtx); - mutex_lock(&dev->mtx); /* not interruptible */ + mutex_lock(&adutux_mutex); + usb_set_intfdata(interface, NULL); /* if the device is not opened, then we clean up right now */ dbg(2," %s : open count %d", __FUNCTION__, dev->open_count); - if (!dev->open_count) { - mutex_unlock(&dev->mtx); + if (!dev->open_count) adu_delete(dev); - } else { - dev->udev = NULL; - mutex_unlock(&dev->mtx); - } + + mutex_unlock(&adutux_mutex); dev_info(&interface->dev, "ADU device adutux%d now disconnected\n", (minor - ADU_MINOR_BASE)); diff --git a/drivers/usb/misc/usbled.c b/drivers/usb/misc/usbled.c index 49c5c5c4c431..06cb71942dc7 100644 --- a/drivers/usb/misc/usbled.c +++ b/drivers/usb/misc/usbled.c @@ -144,12 +144,14 @@ static void led_disconnect(struct usb_interface *interface) struct usb_led *dev; dev = usb_get_intfdata (interface); - usb_set_intfdata (interface, NULL); device_remove_file(&interface->dev, &dev_attr_blue); device_remove_file(&interface->dev, &dev_attr_red); device_remove_file(&interface->dev, &dev_attr_green); + /* first remove the files, then set the pointer to NULL */ + usb_set_intfdata (interface, NULL); + usb_put_dev(dev->udev); kfree(dev); diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 9eb4a65ee4d9..d41531139c55 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -327,6 +327,7 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb) struct usb_serial_port *port = (struct usb_serial_port *)urb->context; unsigned char *data = urb->transfer_buffer; int status = urb->status; + unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); @@ -339,11 +340,11 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb) usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); /* Throttle the device if requested by tty */ - spin_lock(&port->lock); + spin_lock_irqsave(&port->lock, flags); if (!(port->throttled = port->throttle_req)) /* Handle data and continue reading from device */ flush_and_resubmit_read_urb(port); - spin_unlock(&port->lock); + spin_unlock_irqrestore(&port->lock, flags); } EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback); diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 6bfdba6a213f..feba9679ace8 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -1227,8 +1227,8 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp) s_priv = usb_get_serial_data(serial); p_priv = usb_get_serial_port_data(port); d_details = p_priv->device_details; - - dbg("%s - port%d.", __FUNCTION__, port->number); + + dbg("%s - port%d.", __FUNCTION__, port->number); /* Set some sane defaults */ p_priv->rts_state = 1; @@ -1249,7 +1249,7 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp) urb->dev = serial->dev; /* make sure endpoint data toggle is synchronized with the device */ - + usb_clear_halt(urb->dev, urb->pipe); if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) { @@ -1265,7 +1265,7 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp) /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 0); */ } - /* get the terminal config for the setup message now so we don't + /* get the terminal config for the setup message now so we don't * need to send 2 of them */ cflag = port->tty->termios->c_cflag; @@ -1274,7 +1274,7 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp) /* Baud rate calculation takes baud rate as an integer so other rates can be generated if desired. */ baud_rate = tty_get_baud_rate(port->tty); - /* If no match or invalid, leave as default */ + /* If no match or invalid, leave as default */ if (baud_rate >= 0 && d_details->calculate_baud_rate(baud_rate, d_details->baudclk, NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) { diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index a5ced7e08cbf..c29c91271133 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -2711,7 +2711,7 @@ static int mos7840_startup(struct usb_serial *serial) status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data); if (status < 0) { dbg("Writing ZLP_REG5 failed status-0x%x\n", status); - return -1; + goto error; } else dbg("ZLP_REG5 Writing success status%d\n", status); diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 2cd3f1d4b687..cf8add91de05 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -86,6 +86,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) }, { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ID) }, { USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) }, + { USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index ed603e3decd6..d31f5d299989 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -104,3 +104,6 @@ #define WS002IN_VENDOR_ID 0x11f6 #define WS002IN_PRODUCT_ID 0x2001 +/* Corega CG-USBRS232R Serial Adapter */ +#define COREGA_VENDOR_ID 0x07aa +#define COREGA_PRODUCT_ID 0x002a diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 833f6e1e3721..605ebccdcd51 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -136,6 +136,8 @@ static struct usb_device_id id_table_3port [] = { { USB_DEVICE(0x0f30, 0x1b1d) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */ + { USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */ + { USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */ { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */ { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U*/ diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 1ba19eaa1970..836a34ae6ec6 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -177,6 +177,10 @@ static int slave_configure(struct scsi_device *sdev) * is an occasional series of retries that will all fail. */ sdev->retry_hwerror = 1; + /* USB disks should allow restart. Some drives spin down + * automatically, requiring a START-STOP UNIT command. */ + sdev->allow_restart = 1; + } else { /* Non-disk-type devices don't need to blacklist any pages diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 22ab2380367d..2c27721bd259 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -342,11 +342,11 @@ UNUSUAL_DEV( 0x04b0, 0x040d, 0x0100, 0x0100, US_FL_FIX_CAPACITY), /* Reported by Graber and Mike Pagano <mpagano-kernel@mpagano.com> */ -UNUSUAL_DEV( 0x04b0, 0x040f, 0x0200, 0x0200, - "NIKON", - "NIKON DSC D200", - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_FIX_CAPACITY), +UNUSUAL_DEV( 0x04b0, 0x040f, 0x0100, 0x0200, + "NIKON", + "NIKON DSC D200", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY), /* Reported by Emil Larsson <emil@swip.net> */ UNUSUAL_DEV( 0x04b0, 0x0411, 0x0100, 0x0101, @@ -731,6 +731,13 @@ UNUSUAL_DEV( 0x0584, 0x0008, 0x0102, 0x0102, US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ), #endif +/* Reported by RTE <raszilki@yandex.ru> */ +UNUSUAL_DEV( 0x058f, 0x6387, 0x0141, 0x0141, + "JetFlash", + "TS1GJF2A/120", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_MAX_SECTORS_64 ), + /* Fabrizio Fellini <fello@libero.it> */ UNUSUAL_DEV( 0x0595, 0x4343, 0x0000, 0x2210, "Fujifilm", diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index cc4b60f899ca..5b3dbcfcda48 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -503,7 +503,7 @@ config FB_VALKYRIE config FB_CT65550 bool "Chips 65550 display support" - depends on (FB = y) && PPC32 + depends on (FB = y) && PPC32 && PCI select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -641,6 +641,17 @@ config FB_VESA You will get a boot time penguin logo at no additional cost. Please read <file:Documentation/fb/vesafb.txt>. If unsure, say Y. +config FB_EFI + bool "EFI-based Framebuffer Support" + depends on (FB = y) && X86 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the EFI frame buffer device driver. If the firmware on + your platform is UEFI2.0, select Y to add support for + Graphics Output Protocol for early console messages to appear. + config FB_IMAC bool "Intel-based Macintosh Framebuffer Support" depends on (FB = y) && X86 && EFI diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 59d6c45a910d..83e02b3429b6 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -118,6 +118,7 @@ obj-$(CONFIG_FB_OMAP) += omap/ obj-$(CONFIG_FB_UVESA) += uvesafb.o obj-$(CONFIG_FB_VESA) += vesafb.o obj-$(CONFIG_FB_IMAC) += imacfb.o +obj-$(CONFIG_FB_EFI) += efifb.o obj-$(CONFIG_FB_VGA16) += vga16fb.o obj-$(CONFIG_FB_OF) += offb.o obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 235b618b4117..11a3a222dfc3 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -268,6 +268,10 @@ static int atmel_lcdfb_set_par(struct fb_info *info) /* Turn off the LCD controller and the DMA controller */ lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET); + /* Wait for the LCDC core to become idle */ + while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY) + msleep(10); + lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0); if (info->var.bits_per_pixel == 1) diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 1e32b3d13f2e..62867cb63fef 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -202,6 +202,7 @@ static struct pci_device_id radeonfb_pci_table[] = { CHIP_DEF(PCI_CHIP_RV380_3154, RV380, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), CHIP_DEF(PCI_CHIP_RV370_5B60, RV380, CHIP_HAS_CRTC2), CHIP_DEF(PCI_CHIP_RV370_5B62, RV380, CHIP_HAS_CRTC2), + CHIP_DEF(PCI_CHIP_RV370_5B63, RV380, CHIP_HAS_CRTC2), CHIP_DEF(PCI_CHIP_RV370_5B64, RV380, CHIP_HAS_CRTC2), CHIP_DEF(PCI_CHIP_RV370_5B65, RV380, CHIP_HAS_CRTC2), CHIP_DEF(PCI_CHIP_RV370_5460, RV380, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index 267422f66255..b87ed37ac0c1 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -6,7 +6,7 @@ menu "Console display driver support" config VGA_CONSOLE bool "VGA text console" if EMBEDDED || !X86 - depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE && !SUPERH && !BFIN + depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE && !SUPERH && !BLACKFIN default y help Saying Y here will allow you to use Linux in text mode through a diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c index 5fb8675e0d6b..d0e4cb618269 100644 --- a/drivers/video/cyber2000fb.c +++ b/drivers/video/cyber2000fb.c @@ -874,6 +874,8 @@ static int cyber2000fb_set_par(struct fb_info *info) default: BUG(); } + break; + case 24:/* TRUECOLOUR, 16m */ hw.co_pixfmt = CO_PIXFMT_24BPP; hw.width *= 3; diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c new file mode 100644 index 000000000000..bd779ae44b1e --- /dev/null +++ b/drivers/video/efifb.c @@ -0,0 +1,232 @@ +/* + * Framebuffer driver for EFI/UEFI based system + * + * (c) 2006 Edgar Hucek <gimli@dark-green.com> + * Original efi driver written by Gerd Knorr <kraxel@goldbach.in-berlin.de> + * + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/fb.h> +#include <linux/platform_device.h> +#include <linux/screen_info.h> + +#include <video/vga.h> + +static struct fb_var_screeninfo efifb_defined __initdata = { + .activate = FB_ACTIVATE_NOW, + .height = -1, + .width = -1, + .right_margin = 32, + .upper_margin = 16, + .lower_margin = 4, + .vsync_len = 4, + .vmode = FB_VMODE_NONINTERLACED, +}; + +static struct fb_fix_screeninfo efifb_fix __initdata = { + .id = "EFI VGA", + .type = FB_TYPE_PACKED_PIXELS, + .accel = FB_ACCEL_NONE, + .visual = FB_VISUAL_TRUECOLOR, +}; + +static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + struct fb_info *info) +{ + /* + * Set a single color register. The values supplied are + * already rounded down to the hardware's capabilities + * (according to the entries in the `var' structure). Return + * != 0 for invalid regno. + */ + + if (regno >= info->cmap.len) + return 1; + + if (regno < 16) { + red >>= 8; + green >>= 8; + blue >>= 8; + ((u32 *)(info->pseudo_palette))[regno] = + (red << info->var.red.offset) | + (green << info->var.green.offset) | + (blue << info->var.blue.offset); + } + return 0; +} + +static struct fb_ops efifb_ops = { + .owner = THIS_MODULE, + .fb_setcolreg = efifb_setcolreg, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + +static int __init efifb_probe(struct platform_device *dev) +{ + struct fb_info *info; + int err; + unsigned int size_vmode; + unsigned int size_remap; + unsigned int size_total; + + efifb_fix.smem_start = screen_info.lfb_base; + efifb_defined.bits_per_pixel = screen_info.lfb_depth; + efifb_defined.xres = screen_info.lfb_width; + efifb_defined.yres = screen_info.lfb_height; + efifb_fix.line_length = screen_info.lfb_linelength; + + /* size_vmode -- that is the amount of memory needed for the + * used video mode, i.e. the minimum amount of + * memory we need. */ + size_vmode = efifb_defined.yres * efifb_fix.line_length; + + /* size_total -- all video memory we have. Used for + * entries, ressource allocation and bounds + * checking. */ + size_total = screen_info.lfb_size; + if (size_total < size_vmode) + size_total = size_vmode; + + /* size_remap -- the amount of video memory we are going to + * use for efifb. With modern cards it is no + * option to simply use size_total as that + * wastes plenty of kernel address space. */ + size_remap = size_vmode * 2; + if (size_remap < size_vmode) + size_remap = size_vmode; + if (size_remap > size_total) + size_remap = size_total; + efifb_fix.smem_len = size_remap; + + if (!request_mem_region(efifb_fix.smem_start, size_total, "efifb")) + /* We cannot make this fatal. Sometimes this comes from magic + spaces our resource handlers simply don't know about */ + printk(KERN_WARNING + "efifb: cannot reserve video memory at 0x%lx\n", + efifb_fix.smem_start); + + info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev); + if (!info) { + err = -ENOMEM; + goto err_release_mem; + } + info->pseudo_palette = info->par; + info->par = NULL; + + info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len); + if (!info->screen_base) { + printk(KERN_ERR "efifb: abort, cannot ioremap video memory " + "0x%x @ 0x%lx\n", + efifb_fix.smem_len, efifb_fix.smem_start); + err = -EIO; + goto err_unmap; + } + + printk(KERN_INFO "efifb: framebuffer at 0x%lx, mapped to 0x%p, " + "using %dk, total %dk\n", + efifb_fix.smem_start, info->screen_base, + size_remap/1024, size_total/1024); + printk(KERN_INFO "efifb: mode is %dx%dx%d, linelength=%d, pages=%d\n", + efifb_defined.xres, efifb_defined.yres, + efifb_defined.bits_per_pixel, efifb_fix.line_length, + screen_info.pages); + + efifb_defined.xres_virtual = efifb_defined.xres; + efifb_defined.yres_virtual = efifb_fix.smem_len / + efifb_fix.line_length; + printk(KERN_INFO "efifb: scrolling: redraw\n"); + efifb_defined.yres_virtual = efifb_defined.yres; + + /* some dummy values for timing to make fbset happy */ + efifb_defined.pixclock = 10000000 / efifb_defined.xres * + 1000 / efifb_defined.yres; + efifb_defined.left_margin = (efifb_defined.xres / 8) & 0xf8; + efifb_defined.hsync_len = (efifb_defined.xres / 8) & 0xf8; + + efifb_defined.red.offset = screen_info.red_pos; + efifb_defined.red.length = screen_info.red_size; + efifb_defined.green.offset = screen_info.green_pos; + efifb_defined.green.length = screen_info.green_size; + efifb_defined.blue.offset = screen_info.blue_pos; + efifb_defined.blue.length = screen_info.blue_size; + efifb_defined.transp.offset = screen_info.rsvd_pos; + efifb_defined.transp.length = screen_info.rsvd_size; + + printk(KERN_INFO "efifb: %s: " + "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n", + "Truecolor", + screen_info.rsvd_size, + screen_info.red_size, + screen_info.green_size, + screen_info.blue_size, + screen_info.rsvd_pos, + screen_info.red_pos, + screen_info.green_pos, + screen_info.blue_pos); + + efifb_fix.ypanstep = 0; + efifb_fix.ywrapstep = 0; + + info->fbops = &efifb_ops; + info->var = efifb_defined; + info->fix = efifb_fix; + info->flags = FBINFO_FLAG_DEFAULT; + + if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { + err = -ENOMEM; + goto err_unmap; + } + if (register_framebuffer(info) < 0) { + err = -EINVAL; + goto err_fb_dealoc; + } + printk(KERN_INFO "fb%d: %s frame buffer device\n", + info->node, info->fix.id); + return 0; + +err_fb_dealoc: + fb_dealloc_cmap(&info->cmap); +err_unmap: + iounmap(info->screen_base); + framebuffer_release(info); +err_release_mem: + release_mem_region(efifb_fix.smem_start, size_total); + return err; +} + +static struct platform_driver efifb_driver = { + .probe = efifb_probe, + .driver = { + .name = "efifb", + }, +}; + +static struct platform_device efifb_device = { + .name = "efifb", +}; + +static int __init efifb_init(void) +{ + int ret; + + if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) + return -ENODEV; + + ret = platform_driver_register(&efifb_driver); + + if (!ret) { + ret = platform_device_register(&efifb_device); + if (ret) + platform_driver_unregister(&efifb_driver); + } + return ret; +} +module_init(efifb_init); + +MODULE_LICENSE("GPL"); diff --git a/drivers/video/fb_ddc.c b/drivers/video/fb_ddc.c index f836137a0eda..a0df63289b5f 100644 --- a/drivers/video/fb_ddc.c +++ b/drivers/video/fb_ddc.c @@ -56,13 +56,12 @@ unsigned char *fb_ddc_read(struct i2c_adapter *adapter) int i, j; algo_data->setscl(algo_data->data, 1); - algo_data->setscl(algo_data->data, 0); for (i = 0; i < 3; i++) { /* For some old monitors we need the * following process to initialize/stop DDC */ - algo_data->setsda(algo_data->data, 0); + algo_data->setsda(algo_data->data, 1); msleep(13); algo_data->setscl(algo_data->data, 1); @@ -97,14 +96,15 @@ unsigned char *fb_ddc_read(struct i2c_adapter *adapter) algo_data->setsda(algo_data->data, 1); msleep(15); algo_data->setscl(algo_data->data, 0); + algo_data->setsda(algo_data->data, 0); if (edid) break; } /* Release the DDC lines when done or the Apple Cinema HD display * will switch off */ - algo_data->setsda(algo_data->data, 0); - algo_data->setscl(algo_data->data, 0); + algo_data->setsda(algo_data->data, 1); + algo_data->setscl(algo_data->data, 1); return edid; } diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c index b9b572b293d4..2e552d5bbb5d 100644 --- a/drivers/video/gbefb.c +++ b/drivers/video/gbefb.c @@ -183,8 +183,8 @@ static struct fb_videomode default_mode_LCD __initdata = { .vmode = FB_VMODE_NONINTERLACED, }; -struct fb_videomode *default_mode = &default_mode_CRT; -struct fb_var_screeninfo *default_var = &default_var_CRT; +struct fb_videomode *default_mode __initdata = &default_mode_CRT; +struct fb_var_screeninfo *default_var __initdata = &default_var_CRT; static int flat_panel_enabled = 0; diff --git a/drivers/video/geode/lxfb.h b/drivers/video/geode/lxfb.h index 6c227f9592a5..ca13c48d19b0 100644 --- a/drivers/video/geode/lxfb.h +++ b/drivers/video/geode/lxfb.h @@ -33,7 +33,7 @@ void lx_set_palette_reg(struct fb_info *, unsigned int, unsigned int, #define MSR_LX_GLD_CONFIG 0x48002001 #define MSR_LX_GLCP_DOTPLL 0x4c000015 -#define MSR_LX_DF_PADSEL 0x48000011 +#define MSR_LX_DF_PADSEL 0x48002011 #define MSR_LX_DC_SPARE 0x80000011 #define MSR_LX_DF_GLCONFIG 0x48002001 diff --git a/drivers/video/imacfb.c b/drivers/video/imacfb.c index 6455fd2a39f2..9366ef2bb5f7 100644 --- a/drivers/video/imacfb.c +++ b/drivers/video/imacfb.c @@ -234,10 +234,6 @@ static int __init imacfb_probe(struct platform_device *dev) size_remap = size_total; imacfb_fix.smem_len = size_remap; -#ifndef __i386__ - screen_info.imacpm_seg = 0; -#endif - if (!request_mem_region(imacfb_fix.smem_start, size_total, "imacfb")) { printk(KERN_WARNING "imacfb: cannot reserve video memory at 0x%lx\n", diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c index b3463ddcfd60..9c56c492a693 100644 --- a/drivers/video/ps3fb.c +++ b/drivers/video/ps3fb.c @@ -51,7 +51,6 @@ #define L1GPU_DISPLAY_SYNC_HSYNC 1 #define L1GPU_DISPLAY_SYNC_VSYNC 2 -#define DDR_SIZE (0) /* used no ddr */ #define GPU_CMD_BUF_SIZE (64 * 1024) #define GPU_IOIF (0x0d000000UL) #define GPU_ALIGN_UP(x) _ALIGN_UP((x), 64) @@ -727,7 +726,7 @@ static int ps3fb_blank(int blank, struct fb_info *info) static int ps3fb_get_vblank(struct fb_vblank *vblank) { - memset(vblank, 0, sizeof(&vblank)); + memset(vblank, 0, sizeof(*vblank)); vblank->flags = FB_VBLANK_HAVE_VSYNC; return 0; } @@ -1060,6 +1059,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) u64 xdr_lpar; int status, res_index; struct task_struct *task; + unsigned long max_ps3fb_size; status = ps3_open_hv_device(dev); if (status) { @@ -1085,8 +1085,15 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) ps3fb_set_sync(&dev->core); + max_ps3fb_size = _ALIGN_UP(GPU_IOIF, 256*1024*1024) - GPU_IOIF; + if (ps3fb_videomemory.size > max_ps3fb_size) { + dev_info(&dev->core, "Limiting ps3fb mem size to %lu bytes\n", + max_ps3fb_size); + ps3fb_videomemory.size = max_ps3fb_size; + } + /* get gpu context handle */ - status = lv1_gpu_memory_allocate(DDR_SIZE, 0, 0, 0, 0, + status = lv1_gpu_memory_allocate(ps3fb_videomemory.size, 0, 0, 0, 0, &ps3fb.memory_handle, &ddr_lpar); if (status) { dev_err(&dev->core, "%s: lv1_gpu_memory_allocate failed: %d\n", diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c index a5333c190789..b829dc7c5edf 100644 --- a/drivers/video/s1d13xxxfb.c +++ b/drivers/video/s1d13xxxfb.c @@ -540,7 +540,7 @@ s1d13xxxfb_probe(struct platform_device *pdev) int ret = 0; u8 revision; - dbg("probe called: device is %p\n", dev); + dbg("probe called: device is %p\n", pdev); printk(KERN_INFO "Epson S1D13XXX FB Driver\n"); @@ -753,8 +753,11 @@ static struct platform_driver s1d13xxxfb_driver = { static int __init s1d13xxxfb_init(void) { + +#ifndef MODULE if (fb_get_options("s1d13xxxfb", NULL)) return -ENODEV; +#endif return platform_driver_register(&s1d13xxxfb_driver); } diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index bc7d23683735..37bd24b8d83b 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c @@ -1248,7 +1248,6 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in if(found_mode) { ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo, ivideo->sisfb_mode_idx, ivideo->currentvbflags); - ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]; } else { ivideo->sisfb_mode_idx = -1; } @@ -1260,6 +1259,8 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in return -EINVAL; } + ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]; + if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) { ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx; ivideo->refresh_rate = 60; diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c index b983d262ab78..d1d6c0facd54 100644 --- a/drivers/video/uvesafb.c +++ b/drivers/video/uvesafb.c @@ -926,8 +926,10 @@ static int uvesafb_setpalette(struct uvesafb_pal_entry *entries, int count, int start, struct fb_info *info) { struct uvesafb_ktask *task; +#ifdef CONFIG_X86 struct uvesafb_par *par = info->par; int i = par->mode_idx; +#endif int err = 0; /* @@ -1103,11 +1105,11 @@ static int uvesafb_pan_display(struct fb_var_screeninfo *var, static int uvesafb_blank(int blank, struct fb_info *info) { - struct uvesafb_par *par = info->par; struct uvesafb_ktask *task; int err = 1; - #ifdef CONFIG_X86 + struct uvesafb_par *par = info->par; + if (par->vbe_ib.capabilities & VBE_CAP_VGACOMPAT) { int loop = 10000; u8 seq = 0, crtc17 = 0; diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 15d7787dea87..69d7ea02cd48 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c @@ -96,10 +96,23 @@ static int virtio_dev_probe(struct device *_d) return err; } +static int virtio_dev_remove(struct device *_d) +{ + struct virtio_device *dev = container_of(_d,struct virtio_device,dev); + struct virtio_driver *drv = container_of(dev->dev.driver, + struct virtio_driver, driver); + + dev->config->set_status(dev, dev->config->get_status(dev) + & ~VIRTIO_CONFIG_S_DRIVER); + drv->remove(dev); + return 0; +} + int register_virtio_driver(struct virtio_driver *driver) { driver->driver.bus = &virtio_bus; driver->driver.probe = virtio_dev_probe; + driver->driver.remove = virtio_dev_remove; return driver_register(&driver->driver); } EXPORT_SYMBOL_GPL(register_virtio_driver); diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 0e4baca21b8f..1dc04b6684e6 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -53,7 +53,7 @@ struct vring_virtqueue unsigned int num_added; /* Last used index we've seen. */ - unsigned int last_used_idx; + u16 last_used_idx; /* How to notify other side. FIXME: commonalize hcalls! */ void (*notify)(struct virtqueue *vq); @@ -277,11 +277,17 @@ struct virtqueue *vring_new_virtqueue(unsigned int num, struct vring_virtqueue *vq; unsigned int i; + /* We assume num is a power of 2. */ + if (num & (num - 1)) { + dev_warn(&vdev->dev, "Bad virtqueue length %u\n", num); + return NULL; + } + vq = kmalloc(sizeof(*vq) + sizeof(void *)*num, GFP_KERNEL); if (!vq) return NULL; - vring_init(&vq->vring, num, pages); + vring_init(&vq->vring, num, pages, PAGE_SIZE); vq->vq.callback = callback; vq->vq.vdev = vdev; vq->vq.vq_ops = &vring_vq_ops; diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c index 299e274d241a..b63b5e044a4c 100644 --- a/drivers/w1/masters/ds2490.c +++ b/drivers/w1/masters/ds2490.c @@ -233,7 +233,7 @@ static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st, { int count, err; - memset(st, 0, sizeof(st)); + memset(st, 0, sizeof(*st)); count = 0; err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100); diff --git a/drivers/zorro/zorro-driver.c b/drivers/zorro/zorro-driver.c index 067c07be928c..e6c4390d8bd6 100644 --- a/drivers/zorro/zorro-driver.c +++ b/drivers/zorro/zorro-driver.c @@ -60,6 +60,20 @@ static int zorro_device_probe(struct device *dev) } +static int zorro_device_remove(struct device *dev) +{ + struct zorro_dev *z = to_zorro_dev(dev); + struct zorro_driver *drv = to_zorro_driver(dev->driver); + + if (drv) { + if (drv->remove) + drv->remove(z); + z->driver = NULL; + } + return 0; +} + + /** * zorro_register_driver - register a new Zorro driver * @drv: the driver structure to register @@ -128,6 +142,7 @@ struct bus_type zorro_bus_type = { .name = "zorro", .match = zorro_bus_match, .probe = zorro_device_probe, + .remove = zorro_device_remove, }; |