diff options
Diffstat (limited to 'drivers')
803 files changed, 17711 insertions, 10485 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 5d0e26a5c34..ccf6ea95f68 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -3,7 +3,7 @@ # menuconfig ACPI - bool "ACPI Support (Advanced Configuration and Power Interface) Support" + bool "ACPI (Advanced Configuration and Power Interface) Support" depends on !X86_NUMAQ depends on !X86_VISWS depends on !IA64_HP_SIM @@ -67,7 +67,27 @@ 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_SYSFS_POWER + bool "Future power /sys interface" + select POWER_SUPPLY + default y + ---help--- + Say N to disable power /sys interface config ACPI_PROC_EVENT bool "Deprecated /proc/acpi/event support" depends on PROC_FS @@ -88,7 +108,7 @@ config ACPI_PROC_EVENT config ACPI_AC tristate "AC Adapter" - depends on X86 && POWER_SUPPLY + depends on X86 default y help This driver adds support for the AC Adapter object, which indicates @@ -97,7 +117,7 @@ config ACPI_AC config ACPI_BATTERY tristate "Battery" - depends on X86 && POWER_SUPPLY + depends on X86 default y help This driver adds support for battery information through @@ -352,7 +372,6 @@ config ACPI_HOTPLUG_MEMORY config ACPI_SBS tristate "Smart Battery System" depends on X86 - depends on POWER_SUPPLY help This driver adds support for the Smart Battery System, another type of access to battery information, found on some laptops. diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 54e3ab0e5fc..456446f9007 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 e03de37a750..76b9bea98b6 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -27,9 +27,13 @@ #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 +#ifdef CONFIG_ACPI_SYSFS_POWER #include <linux/power_supply.h> +#endif #include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h> @@ -49,12 +53,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,23 +76,29 @@ static struct acpi_driver acpi_ac_driver = { .ops = { .add = acpi_ac_add, .remove = acpi_ac_remove, + .resume = acpi_ac_resume, }, }; struct acpi_ac { +#ifdef CONFIG_ACPI_SYSFS_POWER struct power_supply charger; +#endif struct acpi_device * device; unsigned long state; }; #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 +#ifdef CONFIG_ACPI_SYSFS_POWER static int get_ac_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) @@ -104,7 +117,7 @@ static int get_ac_property(struct power_supply *psy, static enum power_supply_property ac_props[] = { POWER_SUPPLY_PROP_ONLINE, }; - +#endif /* -------------------------------------------------------------------------- AC Adapter Management -------------------------------------------------------------------------- */ @@ -127,6 +140,7 @@ static int acpi_ac_get_state(struct acpi_ac *ac) return 0; } +#ifdef CONFIG_ACPI_PROCFS_POWER /* -------------------------------------------------------------------------- FS Interface (/proc) -------------------------------------------------------------------------- */ @@ -206,6 +220,7 @@ static int acpi_ac_remove_fs(struct acpi_device *device) return 0; } +#endif /* -------------------------------------------------------------------------- Driver Model @@ -230,7 +245,9 @@ static void acpi_ac_notify(acpi_handle handle, u32 event, void *data) acpi_bus_generate_netlink_event(device->pnp.device_class, device->dev.bus_id, event, (u32) ac->state); +#ifdef CONFIG_ACPI_SYSFS_POWER kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); +#endif break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -264,15 +281,19 @@ 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; +#ifdef CONFIG_ACPI_SYSFS_POWER ac->charger.name = acpi_device_bid(device); ac->charger.type = POWER_SUPPLY_TYPE_MAINS; ac->charger.properties = ac_props; ac->charger.num_properties = ARRAY_SIZE(ac_props); ac->charger.get_property = get_ac_property; power_supply_register(&ac->device->dev, &ac->charger); +#endif status = acpi_install_notify_handler(device->handle, ACPI_ALL_NOTIFY, acpi_ac_notify, ac); @@ -287,13 +308,32 @@ 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; +#ifdef CONFIG_ACPI_SYSFS_POWER + if (old_state != ac->state) + kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); +#endif + return 0; +} + static int acpi_ac_remove(struct acpi_device *device, int type) { acpi_status status = AE_OK; @@ -307,9 +347,13 @@ static int acpi_ac_remove(struct acpi_device *device, int type) status = acpi_remove_notify_handler(device->handle, ACPI_ALL_NOTIFY, acpi_ac_notify); +#ifdef CONFIG_ACPI_SYSFS_POWER if (ac->charger.dev) power_supply_unregister(&ac->charger); +#endif +#ifdef CONFIG_ACPI_PROCFS_POWER acpi_ac_remove_fs(device); +#endif kfree(ac); @@ -323,13 +367,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 +389,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 681e26b56b1..c4a769d1ba8 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> @@ -40,7 +40,9 @@ #include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h> +#ifdef CONFIG_ACPI_SYSFS_POWER #include <linux/power_supply.h> +#endif #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF @@ -63,7 +65,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); @@ -86,7 +88,9 @@ MODULE_DEVICE_TABLE(acpi, battery_device_ids); struct acpi_battery { struct mutex lock; +#ifdef CONFIG_ACPI_SYSFS_POWER struct power_supply bat; +#endif struct acpi_device *device; unsigned long update_time; int current_now; @@ -117,6 +121,7 @@ inline int acpi_battery_present(struct acpi_battery *battery) return battery->device->status.battery_present; } +#ifdef CONFIG_ACPI_SYSFS_POWER static int acpi_battery_technology(struct acpi_battery *battery) { if (!strcasecmp("NiCd", battery->type)) @@ -125,19 +130,25 @@ static int acpi_battery_technology(struct acpi_battery *battery) return POWER_SUPPLY_TECHNOLOGY_NiMH; if (!strcasecmp("LION", battery->type)) return POWER_SUPPLY_TECHNOLOGY_LION; + if (!strncasecmp("LI-ION", battery->type, 6)) + return POWER_SUPPLY_TECHNOLOGY_LION; if (!strcasecmp("LiP", battery->type)) return POWER_SUPPLY_TECHNOLOGY_LIPO; return POWER_SUPPLY_TECHNOLOGY_UNKNOWN; } +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, union power_supply_propval *val) { 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; switch (psp) { case POWER_SUPPLY_PROP_STATUS: @@ -147,6 +158,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); @@ -214,8 +227,9 @@ static enum power_supply_property energy_battery_props[] = { POWER_SUPPLY_PROP_MODEL_NAME, POWER_SUPPLY_PROP_MANUFACTURER, }; +#endif -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER inline char *acpi_battery_units(struct acpi_battery *battery) { return (battery->power_unit)?"mA":"mW"; @@ -257,7 +271,7 @@ static int extract_package(struct acpi_battery *battery, union acpi_object *package, struct acpi_offsets *offsets, int num) { - int i, *x; + int i; union acpi_object *element; if (package->type != ACPI_TYPE_PACKAGE) return -EFAULT; @@ -266,16 +280,21 @@ static int extract_package(struct acpi_battery *battery, return -EFAULT; element = &package->package.elements[i]; if (offsets[i].mode) { - if (element->type != ACPI_TYPE_STRING && - element->type != ACPI_TYPE_BUFFER) - return -EFAULT; - strncpy((u8 *)battery + offsets[i].offset, - element->string.pointer, 32); + u8 *ptr = (u8 *)battery + offsets[i].offset; + if (element->type == ACPI_TYPE_STRING || + element->type == ACPI_TYPE_BUFFER) + strncpy(ptr, element->string.pointer, 32); + else if (element->type == ACPI_TYPE_INTEGER) { + strncpy(ptr, (u8 *)&element->integer.value, + sizeof(acpi_integer)); + ptr[sizeof(acpi_integer)] = 0; + } else return -EFAULT; } else { - if (element->type != ACPI_TYPE_INTEGER) - return -EFAULT; - x = (int *)((u8 *)battery + offsets[i].offset); - *x = element->integer.value; + if (element->type == ACPI_TYPE_INTEGER) { + int *x = (int *)((u8 *)battery + + offsets[i].offset); + *x = element->integer.value; + } else return -EFAULT; } } return 0; @@ -385,29 +404,91 @@ static int acpi_battery_init_alarm(struct acpi_battery *battery) return acpi_battery_set_alarm(battery); } +#ifdef CONFIG_ACPI_SYSFS_POWER +static ssize_t acpi_battery_alarm_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); + return sprintf(buf, "%d\n", battery->alarm * 1000); +} + +static ssize_t acpi_battery_alarm_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long x; + struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); + if (sscanf(buf, "%ld\n", &x) == 1) + battery->alarm = x/1000; + if (acpi_battery_present(battery)) + acpi_battery_set_alarm(battery); + return count; +} + +static struct device_attribute alarm_attr = { + .attr = {.name = "alarm", .mode = 0644, .owner = THIS_MODULE}, + .show = acpi_battery_alarm_show, + .store = acpi_battery_alarm_store, +}; + +static int sysfs_add_battery(struct acpi_battery *battery) +{ + int result; + + if (battery->power_unit) { + battery->bat.properties = charge_battery_props; + battery->bat.num_properties = + ARRAY_SIZE(charge_battery_props); + } else { + battery->bat.properties = energy_battery_props; + battery->bat.num_properties = + ARRAY_SIZE(energy_battery_props); + } + + battery->bat.name = acpi_device_bid(battery->device); + battery->bat.type = POWER_SUPPLY_TYPE_BATTERY; + battery->bat.get_property = acpi_battery_get_property; + + result = power_supply_register(&battery->device->dev, &battery->bat); + if (result) + return result; + return device_create_file(battery->bat.dev, &alarm_attr); +} + +static void sysfs_remove_battery(struct acpi_battery *battery) +{ + if (!battery->bat.dev) + return; + device_remove_file(battery->bat.dev, &alarm_attr); + power_supply_unregister(&battery->bat); + battery->bat.dev = NULL; +} +#endif + static int acpi_battery_update(struct acpi_battery *battery) { - int saved_present = acpi_battery_present(battery); - int result = acpi_battery_get_status(battery); - if (result || !acpi_battery_present(battery)) + int result; + result = acpi_battery_get_status(battery); + if (result) return result; - if (saved_present != acpi_battery_present(battery) || - !battery->update_time) { +#ifdef CONFIG_ACPI_SYSFS_POWER + if (!acpi_battery_present(battery)) { + sysfs_remove_battery(battery); battery->update_time = 0; + return 0; + } +#endif + if (!battery->update_time) { result = acpi_battery_get_info(battery); if (result) return result; - if (battery->power_unit) { - battery->bat.properties = charge_battery_props; - battery->bat.num_properties = - ARRAY_SIZE(charge_battery_props); - } else { - battery->bat.properties = energy_battery_props; - battery->bat.num_properties = - ARRAY_SIZE(energy_battery_props); - } acpi_battery_init_alarm(battery); } +#ifdef CONFIG_ACPI_SYSFS_POWER + if (!battery->bat.dev) + sysfs_add_battery(battery); +#endif return acpi_battery_get_state(battery); } @@ -415,7 +496,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) @@ -554,10 +635,6 @@ static ssize_t acpi_battery_write_alarm(struct file *file, if (!battery || (count > sizeof(alarm_string) - 1)) return -EINVAL; - if (result) { - result = -ENODEV; - goto end; - } if (!acpi_battery_present(battery)) { result = -ENODEV; goto end; @@ -688,33 +765,6 @@ static void acpi_battery_remove_fs(struct acpi_device *device) #endif -static ssize_t acpi_battery_alarm_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); - return sprintf(buf, "%d\n", battery->alarm * 1000); -} - -static ssize_t acpi_battery_alarm_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned long x; - struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); - if (sscanf(buf, "%ld\n", &x) == 1) - battery->alarm = x/1000; - if (acpi_battery_present(battery)) - acpi_battery_set_alarm(battery); - return count; -} - -static struct device_attribute alarm_attr = { - .attr = {.name = "alarm", .mode = 0644, .owner = THIS_MODULE}, - .show = acpi_battery_alarm_show, - .store = acpi_battery_alarm_store, -}; - /* -------------------------------------------------------------------------- Driver Interface -------------------------------------------------------------------------- */ @@ -732,7 +782,11 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) acpi_bus_generate_netlink_event(device->pnp.device_class, device->dev.bus_id, event, acpi_battery_present(battery)); - kobject_uevent(&battery->bat.dev->kobj, KOBJ_CHANGE); +#ifdef CONFIG_ACPI_SYSFS_POWER + /* acpi_batter_update could remove power_supply object */ + if (battery->bat.dev) + kobject_uevent(&battery->bat.dev->kobj, KOBJ_CHANGE); +#endif } static int acpi_battery_add(struct acpi_device *device) @@ -751,16 +805,11 @@ 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; #endif - battery->bat.name = acpi_device_bid(device); - battery->bat.type = POWER_SUPPLY_TYPE_BATTERY; - battery->bat.get_property = acpi_battery_get_property; - result = power_supply_register(&battery->device->dev, &battery->bat); - result = device_create_file(battery->bat.dev, &alarm_attr); status = acpi_install_notify_handler(device->handle, ACPI_ALL_NOTIFY, acpi_battery_notify, battery); @@ -774,7 +823,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); @@ -793,13 +842,12 @@ 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 - if (battery->bat.dev) { - device_remove_file(battery->bat.dev, &alarm_attr); - power_supply_unregister(&battery->bat); - } +#ifdef CONFIG_ACPI_SYSFS_POWER + sysfs_remove_battery(battery); +#endif mutex_destroy(&battery->lock); kfree(battery); return 0; @@ -813,6 +861,7 @@ static int acpi_battery_resume(struct acpi_device *device) return -EINVAL; battery = acpi_driver_data(device); battery->update_time = 0; + acpi_battery_update(battery); return 0; } @@ -831,13 +880,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; @@ -848,7 +897,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/bus.c b/drivers/acpi/bus.c index fb2cff9a2d2..d7a115c362d 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -29,7 +29,6 @@ #include <linux/list.h> #include <linux/sched.h> #include <linux/pm.h> -#include <linux/pm_legacy.h> #include <linux/device.h> #include <linux/proc_fs.h> #ifdef CONFIG_X86 @@ -198,12 +197,10 @@ int acpi_bus_set_power(acpi_handle handle, int state) return -ENODEV; } /* - * Get device's current power state if it's unknown - * This means device power state isn't initialized or previous setting failed + * Get device's current power state */ - if ((device->power.state == ACPI_STATE_UNKNOWN) || device->flags.force_power_state) - acpi_bus_get_power(device->handle, &device->power.state); - if ((state == device->power.state) && !device->flags.force_power_state) { + acpi_bus_get_power(device->handle, &device->power.state); + if (state == device->power.state) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", state)); return 0; @@ -766,16 +763,14 @@ static int __init acpi_init(void) result = acpi_bus_init(); if (!result) { -#ifdef CONFIG_PM_LEGACY - if (!PM_IS_ACTIVE()) - pm_active = 1; + if (!(pm_flags & PM_APM)) + pm_flags |= PM_ACPI; else { printk(KERN_INFO PREFIX "APM is already active, exiting\n"); disable_acpi(); result = -ENODEV; } -#endif } else disable_acpi(); diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 301e832e696..24a7865a57c 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -78,6 +78,7 @@ MODULE_DEVICE_TABLE(acpi, button_device_ids); static int acpi_button_add(struct acpi_device *device); static int acpi_button_remove(struct acpi_device *device, int type); +static int acpi_button_resume(struct acpi_device *device); static int acpi_button_info_open_fs(struct inode *inode, struct file *file); static int acpi_button_state_open_fs(struct inode *inode, struct file *file); @@ -87,6 +88,7 @@ static struct acpi_driver acpi_button_driver = { .ids = button_device_ids, .ops = { .add = acpi_button_add, + .resume = acpi_button_resume, .remove = acpi_button_remove, }, }; @@ -253,6 +255,19 @@ static int acpi_button_remove_fs(struct acpi_device *device) /* -------------------------------------------------------------------------- Driver Interface -------------------------------------------------------------------------- */ +static int acpi_lid_send_state(struct acpi_button *button) +{ + unsigned long state; + acpi_status status; + + status = acpi_evaluate_integer(button->device->handle, "_LID", NULL, + &state); + if (ACPI_FAILURE(status)) + return -ENODEV; + /* input layer checks if event is redundant */ + input_report_switch(button->input, SW_LID, !state); + return 0; +} static void acpi_button_notify(acpi_handle handle, u32 event, void *data) { @@ -265,15 +280,8 @@ static void acpi_button_notify(acpi_handle handle, u32 event, void *data) switch (event) { case ACPI_BUTTON_NOTIFY_STATUS: input = button->input; - if (button->type == ACPI_BUTTON_TYPE_LID) { - struct acpi_handle *handle = button->device->handle; - unsigned long state; - - if (!ACPI_FAILURE(acpi_evaluate_integer(handle, "_LID", - NULL, &state))) - input_report_switch(input, SW_LID, !state); - + acpi_lid_send_state(button); } else { int keycode = test_bit(KEY_SLEEP, input->keybit) ? KEY_SLEEP : KEY_POWER; @@ -336,6 +344,17 @@ static int acpi_button_install_notify_handlers(struct acpi_button *button) return ACPI_FAILURE(status) ? -ENODEV : 0; } +static int acpi_button_resume(struct acpi_device *device) +{ + struct acpi_button *button; + if (!device) + return -EINVAL; + button = acpi_driver_data(device); + if (button && button->type == ACPI_BUTTON_TYPE_LID) + return acpi_lid_send_state(button); + return 0; +} + static void acpi_button_remove_notify_handlers(struct acpi_button *button) { switch (button->type) { @@ -453,6 +472,8 @@ static int acpi_button_add(struct acpi_device *device) error = input_register_device(input); if (error) goto err_remove_handlers; + if (button->type == ACPI_BUTTON_TYPE_LID) + acpi_lid_send_state(button); if (device->wakeup.flags.valid) { /* Button's GPE is run-wake GPE */ diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c index a474ca2334d..954ac8ce958 100644 --- a/drivers/acpi/dispatcher/dsobject.c +++ b/drivers/acpi/dispatcher/dsobject.c @@ -137,6 +137,71 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, return_ACPI_STATUS(status); } } + + /* Special object resolution for elements of a package */ + + if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) || + (op->common.parent->common.aml_opcode == + AML_VAR_PACKAGE_OP)) { + /* + * Attempt to resolve the node to a value before we insert it into + * the package. If this is a reference to a common data type, + * resolve it immediately. According to the ACPI spec, package + * elements can only be "data objects" or method references. + * Attempt to resolve to an Integer, Buffer, String or Package. + * If cannot, return the named reference (for things like Devices, + * Methods, etc.) Buffer Fields and Fields will resolve to simple + * objects (int/buf/str/pkg). + * + * NOTE: References to things like Devices, Methods, Mutexes, etc. + * will remain as named references. This behavior is not described + * in the ACPI spec, but it appears to be an oversight. + */ + obj_desc = (union acpi_operand_object *)op->common.node; + + status = + acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR + (struct + acpi_namespace_node, + &obj_desc), + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + switch (op->common.node->type) { + /* + * For these types, we need the actual node, not the subobject. + * However, the subobject got an extra reference count above. + */ + case ACPI_TYPE_MUTEX: + case ACPI_TYPE_METHOD: + case ACPI_TYPE_POWER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_EVENT: + case ACPI_TYPE_REGION: + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_THERMAL: + + obj_desc = + (union acpi_operand_object *)op->common. + node; + break; + + default: + break; + } + + /* + * If above resolved to an operand object, we are done. Otherwise, + * we have a NS node, we must create the package entry as a named + * reference. + */ + if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != + ACPI_DESC_TYPE_NAMED) { + goto exit; + } + } } /* Create and init a new internal ACPI object */ @@ -156,6 +221,7 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, return_ACPI_STATUS(status); } + exit: *obj_desc_ptr = obj_desc; return_ACPI_STATUS(AE_OK); } @@ -356,12 +422,25 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, arg = arg->common.next; for (i = 0; arg && (i < element_count); i++) { if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { - - /* This package element is already built, just get it */ - - obj_desc->package.elements[i] = - ACPI_CAST_PTR(union acpi_operand_object, - arg->common.node); + if (arg->common.node->type == ACPI_TYPE_METHOD) { + /* + * A method reference "looks" to the parser to be a method + * invocation, so we special case it here + */ + arg->common.aml_opcode = AML_INT_NAMEPATH_OP; + status = + acpi_ds_build_internal_object(walk_state, + arg, + &obj_desc-> + package. + elements[i]); + } else { + /* This package element is already built, just get it */ + + obj_desc->package.elements[i] = + ACPI_CAST_PTR(union acpi_operand_object, + arg->common.node); + } } else { status = acpi_ds_build_internal_object(walk_state, arg, &obj_desc-> diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 7b4178393e3..97dc16155a5 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 */ @@ -65,16 +68,21 @@ enum ec_command { /* EC events */ enum ec_event { ACPI_EC_EVENT_OBF_1 = 1, /* Output buffer full */ - ACPI_EC_EVENT_IBF_0, /* Input buffer empty */ + ACPI_EC_EVENT_IBF_0, /* Input buffer empty */ }; #define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */ #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ -static enum ec_mode { - EC_INTR = 1, /* Output buffer full */ - EC_POLL, /* Input buffer empty */ -} acpi_ec_mode = EC_INTR; +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_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); static int acpi_ec_start(struct acpi_device *device); @@ -116,9 +124,8 @@ static struct acpi_ec { unsigned long command_addr; unsigned long data_addr; unsigned long global_lock; + unsigned long flags; struct mutex lock; - atomic_t query_pending; - atomic_t event_count; wait_queue_head_t wait; struct list_head list; u8 handlers_installed; @@ -130,64 +137,95 @@ 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); } -static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event, - unsigned old_count) +static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event) { - u8 status = acpi_ec_read_status(ec); - if (old_count == atomic_read(&ec->event_count)) + if (test_bit(EC_FLAGS_WAIT_GPE, &ec->flags)) return 0; if (event == ACPI_EC_EVENT_OBF_1) { - if (status & ACPI_EC_FLAG_OBF) + if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_OBF) return 1; } else if (event == ACPI_EC_EVENT_IBF_0) { - if (!(status & ACPI_EC_FLAG_IBF)) + if (!(acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF)) return 1; } return 0; } -static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, - unsigned count, int force_poll) +static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) { - if (unlikely(force_poll) || acpi_ec_mode == EC_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))) + goto end; + clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); + if (acpi_ec_check_status(ec, event)) { + 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 */ + if (printk_ratelimit()) + pr_info(PREFIX "missing confirmations, " + "switch off interrupt mode.\n"); + clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); + } + 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, 0)) - return 0; + if (acpi_ec_check_status(ec, event)) + goto end; } - } else { - if (wait_event_timeout(ec->wait, - acpi_ec_check_status(ec, event, count), - msecs_to_jiffies(ACPI_EC_DELAY)) || - acpi_ec_check_status(ec, event, 0)) { - return 0; - } else { - 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, @@ -196,42 +234,47 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, int force_poll) { int result = 0; - unsigned count = atomic_read(&ec->event_count); + 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, count, force_poll); + 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; } - count = atomic_read(&ec->event_count); + /* 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) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count, force_poll); + 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; } - } else if (command == ACPI_EC_COMMAND_QUERY) { - atomic_set(&ec->query_pending, 0); - } + } else if (command == ACPI_EC_COMMAND_QUERY) + clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); for (; rdata_len > 0; --rdata_len) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, count, force_poll); + 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; } - count = atomic_read(&ec->event_count); + /* Don't expect GPE after last read */ + if (rdata_len > 1) + set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); *(rdata++) = acpi_ec_read_data(ec); } end: + pr_debug(PREFIX "transaction end\n"); return result; } @@ -258,13 +301,10 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, } } - /* Make sure GPE is enabled before doing transaction */ - acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); - - status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0, 0); + 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; } @@ -435,9 +475,9 @@ EXPORT_SYMBOL_GPL(acpi_ec_add_query_handler); void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit) { - struct acpi_ec_query_handler *handler; + struct acpi_ec_query_handler *handler, *tmp; mutex_lock(&ec->lock); - list_for_each_entry(handler, &ec->list, node) { + list_for_each_entry_safe(handler, tmp, &ec->list, node) { if (query_bit == handler->query_bit) { list_del(&handler->node); kfree(handler); @@ -476,23 +516,26 @@ static void acpi_ec_gpe_query(void *ec_cxt) static u32 acpi_ec_gpe_handler(void *data) { acpi_status status = AE_OK; - u8 value; struct acpi_ec *ec = data; - atomic_inc(&ec->event_count); - - if (acpi_ec_mode == EC_INTR) { + 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); - } - value = acpi_ec_read_status(ec); - if ((value & ACPI_EC_FLAG_SCI) && !atomic_read(&ec->query_pending)) { - atomic_set(&ec->query_pending, 1); - status = - acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec); + if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_SCI) { + if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) + status = acpi_os_execute(OSL_EC_BURST_HANDLER, + acpi_ec_gpe_query, ec); + } else if (unlikely(!test_bit(EC_FLAGS_GPE_MODE, &ec->flags))) { + /* this is non-query, must be confirmation */ + if (printk_ratelimit()) + pr_info(PREFIX "non-query interrupt received," + " switching to interrupt mode\n"); + set_bit(EC_FLAGS_GPE_MODE, &ec->flags); } - return status == AE_OK ? + return ACPI_SUCCESS(status) ? ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; } @@ -641,13 +684,10 @@ static struct acpi_ec *make_acpi_ec(void) struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL); if (!ec) return NULL; - - atomic_set(&ec->query_pending, 1); - atomic_set(&ec->event_count, 1); + ec->flags = 1 << EC_FLAGS_QUERY_PENDING; mutex_init(&ec->lock); init_waitqueue_head(&ec->wait); INIT_LIST_HEAD(&ec->list); - return ec; } @@ -693,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; } @@ -739,8 +779,10 @@ 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); + pr_info(PREFIX "driver started in %s mode\n", + (test_bit(EC_FLAGS_GPE_MODE, &ec->flags))?"interrupt":"poll"); return 0; } @@ -833,7 +875,7 @@ static int acpi_ec_start(struct acpi_device *device) ret = ec_install_handlers(ec); /* EC is fully operational, allow queries */ - atomic_set(&ec->query_pending, 0); + clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); return ret; } @@ -850,6 +892,17 @@ static int acpi_ec_stop(struct acpi_device *device, int type) return 0; } +int __init acpi_boot_ec_enable(void) +{ + if (!boot_ec || boot_ec->handlers_installed) + return 0; + if (!ec_install_handlers(boot_ec)) { + first_ec = boot_ec; + return 0; + } + return -EFAULT; +} + int __init acpi_ec_ecdt_probe(void) { int ret; @@ -865,18 +918,27 @@ 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. + * Keep boot_ec struct as it will be needed soon. + */ + if (ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI", &x))) + return -ENODEV; } ret = ec_install_handlers(boot_ec); @@ -924,20 +986,4 @@ static void __exit acpi_ec_exit(void) return; } -#endif /* 0 */ - -static int __init acpi_ec_set_intr_mode(char *str) -{ - int intr; - - if (!get_option(&str, &intr)) - return 0; - - acpi_ec_mode = (intr) ? EC_INTR : EC_POLL; - - printk(KERN_NOTICE PREFIX "%s mode.\n", intr ? "interrupt" : "polling"); - - return 1; -} - -__setup("ec_intr=", acpi_ec_set_intr_mode); +#endif /* 0 */ diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c index e99f0c435a4..58ad09725dd 100644 --- a/drivers/acpi/events/evregion.c +++ b/drivers/acpi/events/evregion.c @@ -344,7 +344,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, * setup will potentially execute control methods * (e.g., _REG method for this region) */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); status = region_setup(region_obj, ACPI_REGION_ACTIVATE, handler_desc->address_space.context, @@ -352,7 +352,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, /* Re-enter the interpreter */ - acpi_ex_reacquire_interpreter(); + acpi_ex_enter_interpreter(); /* Check for failure of the Region Setup */ @@ -405,7 +405,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, * exit the interpreter because the handler *might* block -- we don't * know what it will do, so we can't hold the lock on the intepreter. */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); } /* Call the handler */ @@ -426,7 +426,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, * We just returned from a non-default handler, we must re-enter the * interpreter */ - acpi_ex_reacquire_interpreter(); + acpi_ex_enter_interpreter(); } return_ACPI_STATUS(status); diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index c81f6bdb68b..a5a5532db26 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -47,8 +47,6 @@ MODULE_LICENSE("GPL"); static int acpi_fan_add(struct acpi_device *device); static int acpi_fan_remove(struct acpi_device *device, int type); -static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state); -static int acpi_fan_resume(struct acpi_device *device); static const struct acpi_device_id fan_device_ids[] = { {"PNP0C0B", 0}, @@ -63,15 +61,9 @@ static struct acpi_driver acpi_fan_driver = { .ops = { .add = acpi_fan_add, .remove = acpi_fan_remove, - .suspend = acpi_fan_suspend, - .resume = acpi_fan_resume, }, }; -struct acpi_fan { - struct acpi_device * device; -}; - /* -------------------------------------------------------------------------- FS Interface (/proc) -------------------------------------------------------------------------- */ @@ -80,12 +72,12 @@ static struct proc_dir_entry *acpi_fan_dir; static int acpi_fan_read_state(struct seq_file *seq, void *offset) { - struct acpi_fan *fan = seq->private; + struct acpi_device *device = seq->private; int state = 0; - if (fan) { - if (acpi_bus_get_power(fan->device->handle, &state)) + if (device) { + if (acpi_bus_get_power(device->handle, &state)) seq_printf(seq, "status: ERROR\n"); else seq_printf(seq, "status: %s\n", @@ -105,11 +97,10 @@ acpi_fan_write_state(struct file *file, const char __user * buffer, { int result = 0; struct seq_file *m = file->private_data; - struct acpi_fan *fan = m->private; + struct acpi_device *device = m->private; char state_string[12] = { '\0' }; - - if (!fan || (count > sizeof(state_string) - 1)) + if (count > sizeof(state_string) - 1) return -EINVAL; if (copy_from_user(state_string, buffer, count)) @@ -117,7 +108,7 @@ acpi_fan_write_state(struct file *file, const char __user * buffer, state_string[count] = '\0'; - result = acpi_bus_set_power(fan->device->handle, + result = acpi_bus_set_power(device->handle, simple_strtoul(state_string, NULL, 0)); if (result) return result; @@ -158,7 +149,7 @@ static int acpi_fan_add_fs(struct acpi_device *device) return -ENODEV; else { entry->proc_fops = &acpi_fan_state_ops; - entry->data = acpi_driver_data(device); + entry->data = device; entry->owner = THIS_MODULE; } @@ -191,14 +182,8 @@ static int acpi_fan_add(struct acpi_device *device) if (!device) return -EINVAL; - fan = kzalloc(sizeof(struct acpi_fan), GFP_KERNEL); - if (!fan) - return -ENOMEM; - - fan->device = device; strcpy(acpi_device_name(device), "Fan"); strcpy(acpi_device_class(device), ACPI_FAN_CLASS); - acpi_driver_data(device) = fan; result = acpi_bus_get_power(device->handle, &state); if (result) { @@ -206,10 +191,6 @@ static int acpi_fan_add(struct acpi_device *device) goto end; } - device->flags.force_power_state = 1; - acpi_bus_set_power(device->handle, state); - device->flags.force_power_state = 0; - result = acpi_fan_add_fs(device); if (result) goto end; @@ -227,53 +208,14 @@ static int acpi_fan_add(struct acpi_device *device) static int acpi_fan_remove(struct acpi_device *device, int type) { - struct acpi_fan *fan = NULL; - - if (!device || !acpi_driver_data(device)) return -EINVAL; - fan = acpi_driver_data(device); - acpi_fan_remove_fs(device); - kfree(fan); - return 0; } -static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state) -{ - if (!device) - return -EINVAL; - - acpi_bus_set_power(device->handle, ACPI_STATE_D0); - - return AE_OK; -} - -static int acpi_fan_resume(struct acpi_device *device) -{ - int result = 0; - int power_state = 0; - - if (!device) - return -EINVAL; - - result = acpi_bus_get_power(device->handle, &power_state); - if (result) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error reading fan power state\n")); - return result; - } - - device->flags.force_power_state = 1; - acpi_bus_set_power(device->handle, power_state); - device->flags.force_power_state = 0; - - return result; -} - static int __init acpi_fan_init(void) { int result = 0; diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index ab04d848b19..0822d9fc1cb 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -38,9 +38,9 @@ ACPI_MODULE_NAME("numa"); static nodemask_t nodes_found_map = NODE_MASK_NONE; /* maps to convert between proximity domain and logical node ID */ -static int __cpuinitdata pxm_to_node_map[MAX_PXM_DOMAINS] +static int pxm_to_node_map[MAX_PXM_DOMAINS] = { [0 ... MAX_PXM_DOMAINS - 1] = NID_INVAL }; -static int __cpuinitdata node_to_pxm_map[MAX_NUMNODES] +static int node_to_pxm_map[MAX_NUMNODES] = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL }; int pxm_to_node(int pxm) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index aabc6ca4a81..e3a673a0084 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/pci_bind.c b/drivers/acpi/pci_bind.c index 028969370bb..388300de005 100644 --- a/drivers/acpi/pci_bind.c +++ b/drivers/acpi/pci_bind.c @@ -294,9 +294,6 @@ int acpi_pci_unbind(struct acpi_device *device) acpi_get_data(device->handle, acpi_pci_data_handler, (void **)&data); if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Unable to get data from device %s", - acpi_device_bid(device))); result = -ENODEV; goto end; } diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index dd3186abe07..62010c2481b 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -429,6 +429,15 @@ int acpi_pci_irq_enable(struct pci_dev *dev) &polarity, &link, acpi_pci_allocate_irq); + if (irq < 0) { + /* + * IDE legacy mode controller IRQs are magic. Why do compat + * extensions always make such a nasty mess. + */ + if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && + (dev->class & 0x05) == 0) + return 0; + } /* * No IRQ known to the ACPI subsystem - maybe the BIOS / * driver reported one, then use it. Exit in any case. diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 57b9a2998fd..af1769a20c7 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -86,7 +86,6 @@ struct acpi_power_resource { acpi_bus_id name; u32 system_level; u32 order; - int state; struct mutex resource_lock; struct list_head reference; }; @@ -128,33 +127,31 @@ acpi_power_get_context(acpi_handle handle, return 0; } -static int acpi_power_get_state(struct acpi_power_resource *resource) +static int acpi_power_get_state(struct acpi_power_resource *resource, int *state) { acpi_status status = AE_OK; unsigned long sta = 0; - if (!resource) + if (!resource || !state) return -EINVAL; status = acpi_evaluate_integer(resource->device->handle, "_STA", NULL, &sta); if (ACPI_FAILURE(status)) return -ENODEV; - if (sta & 0x01) - resource->state = ACPI_POWER_RESOURCE_STATE_ON; - else - resource->state = ACPI_POWER_RESOURCE_STATE_OFF; + *state = (sta & 0x01)?ACPI_POWER_RESOURCE_STATE_ON: + ACPI_POWER_RESOURCE_STATE_OFF; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n", - resource->name, resource->state ? "on" : "off")); + resource->name, state ? "on" : "off")); return 0; } static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) { - int result = 0; + int result = 0, state1; struct acpi_power_resource *resource = NULL; u32 i = 0; @@ -168,11 +165,11 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) result = acpi_power_get_context(list->handles[i], &resource); if (result) return result; - result = acpi_power_get_state(resource); + result = acpi_power_get_state(resource, &state1); if (result) return result; - *state = resource->state; + *state = state1; if (*state != ACPI_POWER_RESOURCE_STATE_ON) break; @@ -186,7 +183,7 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) static int acpi_power_on(acpi_handle handle, struct acpi_device *dev) { - int result = 0; + int result = 0, state; int found = 0; acpi_status status = AE_OK; struct acpi_power_resource *resource = NULL; @@ -224,20 +221,14 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev) } mutex_unlock(&resource->resource_lock); - if (resource->state == ACPI_POWER_RESOURCE_STATE_ON) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already on\n", - resource->name)); - return 0; - } - status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL); if (ACPI_FAILURE(status)) return -ENODEV; - result = acpi_power_get_state(resource); + result = acpi_power_get_state(resource, &state); if (result) return result; - if (resource->state != ACPI_POWER_RESOURCE_STATE_ON) + if (state != ACPI_POWER_RESOURCE_STATE_ON) return -ENOEXEC; /* Update the power resource's _device_ power state */ @@ -250,7 +241,7 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev) static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev) { - int result = 0; + int result = 0, state; acpi_status status = AE_OK; struct acpi_power_resource *resource = NULL; struct list_head *node, *next; @@ -281,20 +272,14 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev) } mutex_unlock(&resource->resource_lock); - if (resource->state == ACPI_POWER_RESOURCE_STATE_OFF) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already off\n", - resource->name)); - return 0; - } - status = acpi_evaluate_object(resource->device->handle, "_OFF", NULL, NULL); if (ACPI_FAILURE(status)) return -ENODEV; - result = acpi_power_get_state(resource); + result = acpi_power_get_state(resource, &state); if (result) return result; - if (resource->state != ACPI_POWER_RESOURCE_STATE_OFF) + if (state != ACPI_POWER_RESOURCE_STATE_OFF) return -ENOEXEC; /* Update the power resource's _device_ power state */ @@ -494,7 +479,7 @@ static struct proc_dir_entry *acpi_power_dir; static int acpi_power_seq_show(struct seq_file *seq, void *offset) { int count = 0; - int result = 0; + int result = 0, state; struct acpi_power_resource *resource = NULL; struct list_head *node, *next; struct acpi_power_reference *ref; @@ -505,12 +490,12 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset) if (!resource) goto end; - result = acpi_power_get_state(resource); + result = acpi_power_get_state(resource, &state); if (result) goto end; seq_puts(seq, "state: "); - switch (resource->state) { + switch (state) { case ACPI_POWER_RESOURCE_STATE_ON: seq_puts(seq, "on\n"); break; @@ -591,7 +576,7 @@ static int acpi_power_remove_fs(struct acpi_device *device) static int acpi_power_add(struct acpi_device *device) { - int result = 0; + int result = 0, state; acpi_status status = AE_OK; struct acpi_power_resource *resource = NULL; union acpi_object acpi_object; @@ -622,11 +607,11 @@ static int acpi_power_add(struct acpi_device *device) resource->system_level = acpi_object.power_resource.system_level; resource->order = acpi_object.power_resource.resource_order; - result = acpi_power_get_state(resource); + result = acpi_power_get_state(resource, &state); if (result) goto end; - switch (resource->state) { + switch (state) { case ACPI_POWER_RESOURCE_STATE_ON: device->power.state = ACPI_STATE_D0; break; @@ -643,7 +628,7 @@ static int acpi_power_add(struct acpi_device *device) goto end; printk(KERN_INFO PREFIX "%s [%s] (%s)\n", acpi_device_name(device), - acpi_device_bid(device), resource->state ? "on" : "off"); + acpi_device_bid(device), state ? "on" : "off"); end: if (result) @@ -680,7 +665,7 @@ static int acpi_power_remove(struct acpi_device *device, int type) static int acpi_power_resume(struct acpi_device *device) { - int result = 0; + int result = 0, state; struct acpi_power_resource *resource = NULL; struct acpi_power_reference *ref; @@ -689,12 +674,12 @@ static int acpi_power_resume(struct acpi_device *device) resource = (struct acpi_power_resource *)acpi_driver_data(device); - result = acpi_power_get_state(resource); + result = acpi_power_get_state(resource, &state); if (result) return result; mutex_lock(&resource->resource_lock); - if ((resource->state == ACPI_POWER_RESOURCE_STATE_OFF) && + if (state == ACPI_POWER_RESOURCE_STATE_OFF && !list_empty(&resource->reference)) { ref = container_of(resource->reference.next, struct acpi_power_reference, node); mutex_unlock(&resource->resource_lock); diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 235a51e328c..e48ee4f8749 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 f996d0e3768..2235f4e02d2 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -76,7 +76,11 @@ static void (*pm_idle_save) (void) __read_mostly; #define PM_TIMER_TICKS_TO_US(p) (((p) * 1000)/(PM_TIMER_FREQUENCY/1000)) static unsigned int max_cstate __read_mostly = ACPI_PROCESSOR_MAX_POWER; +#ifdef CONFIG_CPU_IDLE module_param(max_cstate, uint, 0000); +#else +module_param(max_cstate, uint, 0644); +#endif static unsigned int nocst __read_mostly; module_param(nocst, uint, 0000); @@ -197,6 +201,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 +256,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, .. */ @@ -531,6 +535,11 @@ static void acpi_processor_idle(void) case ACPI_STATE_C3: /* + * Must be done before busmaster disable as we might + * need to access HPET ! + */ + acpi_state_timer_broadcast(pr, cx, 1); + /* * disable bus master * bm_check implies we need ARB_DIS * !bm_check implies we need cache flush @@ -557,7 +566,6 @@ static void acpi_processor_idle(void) /* Get start time (ticks) */ t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); /* Invoke C3 */ - acpi_state_timer_broadcast(pr, cx, 1); /* Tell the scheduler that we are going deep-idle: */ sched_clock_idle_sleep_event(); acpi_cstate_enter(cx); @@ -1373,15 +1381,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 +1399,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)) @@ -1407,9 +1409,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, if (acpi_idle_suspend) return(acpi_idle_enter_c1(dev, state)); - if (pr->flags.bm_check) - acpi_idle_update_bm_rld(pr, cx); - local_irq_disable(); current_thread_info()->status &= ~TS_POLLING; /* @@ -1424,11 +1423,21 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, return 0; } + /* + * Must be done before busmaster disable as we might need to + * access HPET ! + */ + acpi_state_timer_broadcast(pr, cx, 1); + + if (pr->flags.bm_check) + acpi_idle_update_bm_rld(pr, cx); + if (cx->type == ACPI_STATE_C3) ACPI_FLUSH_CPU_CACHE(); t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); - acpi_state_timer_broadcast(pr, cx, 1); + /* Tell the scheduler that we are going deep-idle: */ + sched_clock_idle_sleep_event(); acpi_idle_do_entry(cx); t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); @@ -1436,6 +1445,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 +1456,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 +1476,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 +1486,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 +1509,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 +1556,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 +1566,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 +1618,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 +1646,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 +1686,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 0b8204e7082..6742d7bc477 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -29,6 +29,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> +#include <linux/sched.h> #include <linux/cpufreq.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> @@ -70,7 +71,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 +132,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 +184,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 +394,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) +{ + 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_safe(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) { - int value = -1; + 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_safe(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 +528,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 +545,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; @@ -414,20 +573,66 @@ static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr) return -ENODEV; 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; } - local_irq_enable(); return 0; } static int acpi_processor_get_throttling(struct acpi_processor *pr) { - return pr->throttling.acpi_processor_get_throttling(pr); + cpumask_t saved_mask; + int ret; + + /* + * Migrate task to the cpu pointed by pr. + */ + saved_mask = current->cpus_allowed; + set_cpus_allowed(current, cpumask_of_cpu(pr->id)); + ret = pr->throttling.acpi_processor_get_throttling(pr); + /* restore the previous state */ + set_cpus_allowed(current, saved_mask); + + return ret; +} + +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, @@ -506,7 +711,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; @@ -523,28 +729,34 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr, if (state < pr->throttling_platform_limit) 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(); return 0; } int acpi_processor_set_throttling(struct acpi_processor *pr, int state) { - return pr->throttling.acpi_processor_set_throttling(pr, state); + cpumask_t saved_mask; + int ret; + /* + * Migrate task to the cpu pointed by pr. + */ + saved_mask = current->cpus_allowed; + set_cpus_allowed(current, cpumask_of_cpu(pr->id)); + ret = pr->throttling.acpi_processor_set_throttling(pr, state); + /* restore the previous state */ + set_cpus_allowed(current, saved_mask); + return ret; } 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 +775,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 +790,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 +801,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 90fd09c65f9..f136c7d3b3c 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> @@ -40,7 +40,9 @@ #include <linux/jiffies.h> #include <linux/delay.h> +#ifdef CONFIG_ACPI_SYSFS_POWER #include <linux/power_supply.h> +#endif #include "sbshc.h" @@ -54,12 +56,6 @@ #define ACPI_BATTERY_DIR_NAME "BAT%i" #define ACPI_AC_DIR_NAME "AC0" -enum acpi_sbs_device_addr { - ACPI_SBS_CHARGER = 0x9, - ACPI_SBS_MANAGER = 0xa, - ACPI_SBS_BATTERY = 0xb, -}; - #define ACPI_SBS_NOTIFY_STATUS 0x80 #define ACPI_SBS_NOTIFY_INFO 0x81 @@ -86,9 +82,11 @@ static const struct acpi_device_id sbs_device_ids[] = { MODULE_DEVICE_TABLE(acpi, sbs_device_ids); struct acpi_battery { +#ifdef CONFIG_ACPI_SYSFS_POWER struct power_supply bat; +#endif 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,16 +111,19 @@ 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); struct acpi_sbs { +#ifdef CONFIG_ACPI_SYSFS_POWER struct power_supply charger; +#endif 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]; @@ -162,6 +163,7 @@ static inline int acpi_battery_scale(struct acpi_battery *battery) acpi_battery_ipscale(battery); } +#ifdef CONFIG_ACPI_SYSFS_POWER static int sbs_get_ac_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) @@ -299,6 +301,7 @@ static enum power_supply_property sbs_energy_battery_props[] = { POWER_SUPPLY_PROP_MODEL_NAME, POWER_SUPPLY_PROP_MANUFACTURER, }; +#endif /* -------------------------------------------------------------------------- Smart Battery System Management @@ -434,6 +437,7 @@ static int acpi_ac_get_present(struct acpi_sbs *sbs) return result; } +#ifdef CONFIG_ACPI_SYSFS_POWER static ssize_t acpi_battery_alarm_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -463,12 +467,13 @@ static struct device_attribute alarm_attr = { .show = acpi_battery_alarm_show, .store = acpi_battery_alarm_store, }; +#endif /* -------------------------------------------------------------------------- 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, @@ -538,7 +543,7 @@ static struct proc_dir_entry *acpi_battery_dir = NULL; static inline char *acpi_battery_units(struct acpi_battery *battery) { - return acpi_battery_mode(battery) ? " mWh" : " mAh"; + return acpi_battery_mode(battery) ? " mW" : " mA"; } @@ -555,10 +560,10 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset) if (!battery->present) goto end; - seq_printf(seq, "design capacity: %i%s\n", + seq_printf(seq, "design capacity: %i%sh\n", battery->design_capacity * acpi_battery_scale(battery), acpi_battery_units(battery)); - seq_printf(seq, "last full capacity: %i%s\n", + seq_printf(seq, "last full capacity: %i%sh\n", battery->full_charge_capacity * acpi_battery_scale(battery), acpi_battery_units(battery)); seq_printf(seq, "battery technology: rechargeable\n"); @@ -589,7 +594,7 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset) { struct acpi_battery *battery = seq->private; struct acpi_sbs *sbs = battery->sbs; - int result = 0; + int rate; mutex_lock(&sbs->lock); seq_printf(seq, "present: %s\n", @@ -603,9 +608,12 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset) seq_printf(seq, "charging state: %s\n", (battery->current_now < 0) ? "discharging" : ((battery->current_now > 0) ? "charging" : "charged")); - seq_printf(seq, "present rate: %d mA\n", - abs(battery->current_now) * acpi_battery_ipscale(battery)); - seq_printf(seq, "remaining capacity: %i%s\n", + rate = abs(battery->current_now) * acpi_battery_ipscale(battery); + rate *= (acpi_battery_mode(battery))?(battery->voltage_now * + acpi_battery_vscale(battery)/1000):1; + seq_printf(seq, "present rate: %d%s\n", rate, + acpi_battery_units(battery)); + seq_printf(seq, "remaining capacity: %i%sh\n", battery->capacity_now * acpi_battery_scale(battery), acpi_battery_units(battery)); seq_printf(seq, "present voltage: %i mV\n", @@ -613,7 +621,7 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset) end: mutex_unlock(&sbs->lock); - return result; + return 0; } static int acpi_battery_state_open_fs(struct inode *inode, struct file *file) @@ -637,7 +645,7 @@ static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) acpi_battery_get_alarm(battery); seq_printf(seq, "alarm: "); if (battery->alarm_capacity) - seq_printf(seq, "%i%s\n", + seq_printf(seq, "%i%sh\n", battery->alarm_capacity * acpi_battery_scale(battery), acpi_battery_units(battery)); @@ -789,12 +797,13 @@ 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, battery); #endif +#ifdef CONFIG_ACPI_SYSFS_POWER battery->bat.name = battery->name; battery->bat.type = POWER_SUPPLY_TYPE_BATTERY; if (!acpi_battery_mode(battery)) { @@ -808,7 +817,14 @@ 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: +#endif 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,15 +833,18 @@ 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]; +#ifdef CONFIG_ACPI_SYSFS_POWER + if (battery->bat.dev) { + if (battery->have_sysfs_alarm) + device_remove_file(battery->bat.dev, &alarm_attr); + power_supply_unregister(&battery->bat); } #endif +#ifdef CONFIG_ACPI_PROCFS_POWER + if (battery->proc_entry) + acpi_sbs_remove_fs(&battery->proc_entry, acpi_battery_dir); +#endif } static int acpi_charger_add(struct acpi_sbs *sbs) @@ -835,19 +854,21 @@ 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); if (result) goto end; #endif +#ifdef CONFIG_ACPI_SYSFS_POWER sbs->charger.name = "sbs-charger"; sbs->charger.type = POWER_SUPPLY_TYPE_MAINS; sbs->charger.properties = sbs_ac_props; sbs->charger.num_properties = ARRAY_SIZE(sbs_ac_props); sbs->charger.get_property = sbs_get_ac_property; power_supply_register(&sbs->device->dev, &sbs->charger); +#endif printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n", ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line"); @@ -857,9 +878,11 @@ static int acpi_charger_add(struct acpi_sbs *sbs) static void acpi_charger_remove(struct acpi_sbs *sbs) { +#ifdef CONFIG_ACPI_SYSFS_POWER if (sbs->charger.dev) power_supply_unregister(&sbs->charger); -#ifdef CONFIG_ACPI_PROCFS +#endif +#ifdef CONFIG_ACPI_PROCFS_POWER if (sbs->charger_entry) acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir); #endif @@ -879,7 +902,9 @@ void acpi_sbs_callback(void *context) ACPI_SBS_NOTIFY_STATUS, sbs->charger_present); #endif +#ifdef CONFIG_ACPI_SYSFS_POWER kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE); +#endif } if (sbs->manager_present) { for (id = 0; id < MAX_SBS_BAT; ++id) { @@ -896,7 +921,9 @@ void acpi_sbs_callback(void *context) ACPI_SBS_NOTIFY_STATUS, bat->present); #endif +#ifdef CONFIG_ACPI_SYSFS_POWER kobject_uevent(&bat->bat.dev->kobj, KOBJ_CHANGE); +#endif } } } @@ -965,7 +992,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 +1031,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/sbshc.c b/drivers/acpi/sbshc.c index 046d7c3ed35..fd40b6a1d63 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c @@ -202,10 +202,9 @@ int acpi_smbus_unregister_callback(struct acpi_smb_hc *hc) EXPORT_SYMBOL_GPL(acpi_smbus_unregister_callback); -static void acpi_smbus_callback(void *context) +static inline void acpi_smbus_callback(void *context) { struct acpi_smb_hc *hc = context; - if (hc->callback) hc->callback(hc->context); } @@ -214,6 +213,7 @@ static int smbus_alarm(void *context) { struct acpi_smb_hc *hc = context; union acpi_smb_status status; + u8 address; if (smb_hc_read(hc, ACPI_SMB_STATUS, &status.raw)) return 0; /* Check if it is only a completion notify */ @@ -222,9 +222,18 @@ static int smbus_alarm(void *context) if (!status.fields.alarm) return 0; mutex_lock(&hc->lock); + smb_hc_read(hc, ACPI_SMB_ALARM_ADDRESS, &address); + status.fields.alarm = 0; smb_hc_write(hc, ACPI_SMB_STATUS, status.raw); - if (hc->callback) - acpi_os_execute(OSL_GPE_HANDLER, acpi_smbus_callback, hc); + /* We are only interested in events coming from known devices */ + switch (address >> 1) { + case ACPI_SBS_CHARGER: + case ACPI_SBS_MANAGER: + case ACPI_SBS_BATTERY: + acpi_os_execute(OSL_GPE_HANDLER, + acpi_smbus_callback, hc); + default:; + } mutex_unlock(&hc->lock); return 0; } diff --git a/drivers/acpi/sbshc.h b/drivers/acpi/sbshc.h index 3bda3491a97..a57b0762dd7 100644 --- a/drivers/acpi/sbshc.h +++ b/drivers/acpi/sbshc.h @@ -16,6 +16,12 @@ enum acpi_smb_protocol { static const u8 SMBUS_PEC = 0x80; +enum acpi_sbs_device_addr { + ACPI_SBS_CHARGER = 0x9, + ACPI_SBS_MANAGER = 0xa, + ACPI_SBS_BATTERY = 0xb, +}; + typedef void (*smbus_alarm_callback)(void *context); extern int acpi_smbus_read(struct acpi_smb_hc *hc, u8 protocol, u8 address, diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 5b4d462117c..cbfe9ae7a9e 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1449,6 +1449,8 @@ static int acpi_bus_scan_fixed(struct acpi_device *root) return result; } +int __init acpi_boot_ec_enable(void); + static int __init acpi_scan_init(void) { int result; @@ -1480,6 +1482,10 @@ static int __init acpi_scan_init(void) * Enumerate devices in the ACPI namespace. */ result = acpi_bus_scan_fixed(acpi_root); + + /* EC region might be needed at bus_scan, so enable it now */ + acpi_boot_ec_enable(); + if (!result) result = acpi_bus_scan(acpi_root, &ops); diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index f3d3867303e..2c0b6630f8b 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c @@ -167,8 +167,8 @@ static void acpi_pm_finish(void) { u32 acpi_state = acpi_target_sleep_state; - acpi_leave_sleep_state(acpi_state); acpi_disable_wakeup_device(acpi_state); + acpi_leave_sleep_state(acpi_state); /* reset firmware waking vector */ acpi_set_firmware_waking_vector((acpi_physical_address) 0); @@ -272,8 +272,8 @@ static void acpi_hibernation_finish(void) * enable it here. */ acpi_enable(); - acpi_leave_sleep_state(ACPI_STATE_S4); acpi_disable_wakeup_device(ACPI_STATE_S4); + acpi_leave_sleep_state(ACPI_STATE_S4); /* reset firmware waking vector */ acpi_set_firmware_waking_vector((acpi_physical_address) 0); @@ -410,6 +410,7 @@ static void acpi_power_off(void) /* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */ printk("%s called\n", __FUNCTION__); local_irq_disable(); + acpi_enable_wakeup_device(ACPI_STATE_S5); acpi_enter_sleep_state(ACPI_STATE_S5); } diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c index 5f1d85f2ffe..010f19652f8 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 a736ef7bdee..9e8c20c6a0b 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 bac956b30c5..bd77e81e81c 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 */ @@ -576,7 +577,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) struct acpi_video_device_brightness *br = NULL; - memset(&device->cap, 0, 4); + memset(&device->cap, 0, sizeof(device->cap)); if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_ADR", &h_dummy1))) { device->cap._ADR = 1; @@ -696,7 +697,7 @@ static void acpi_video_bus_find_cap(struct acpi_video_bus *video) { acpi_handle h_dummy1; - memset(&video->cap, 0, 4); + memset(&video->cap, 0, sizeof(video->cap)); if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOS", &h_dummy1))) { video->cap._DOS = 1; } @@ -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/ahci.c b/drivers/ata/ahci.c index 49cf4cf1a5a..54f38c21dd9 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -49,6 +49,9 @@ #define DRV_NAME "ahci" #define DRV_VERSION "3.0" +static int ahci_enable_alpm(struct ata_port *ap, + enum link_pm policy); +static void ahci_disable_alpm(struct ata_port *ap); enum { AHCI_PCI_BAR = 5, @@ -99,6 +102,7 @@ enum { HOST_CAP_SSC = (1 << 14), /* Slumber capable */ HOST_CAP_PMP = (1 << 17), /* Port Multiplier support */ HOST_CAP_CLO = (1 << 24), /* Command List Override support */ + HOST_CAP_ALPM = (1 << 26), /* Aggressive Link PM support */ HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */ HOST_CAP_SNTF = (1 << 29), /* SNotification register */ HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */ @@ -155,6 +159,8 @@ enum { PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS, /* PORT_CMD bits */ + PORT_CMD_ASP = (1 << 27), /* Aggressive Slumber/Partial */ + PORT_CMD_ALPE = (1 << 26), /* Aggressive Link PM enable */ PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */ PORT_CMD_PMP = (1 << 17), /* PMP attached */ PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */ @@ -178,14 +184,17 @@ enum { AHCI_HFLAG_MV_PATA = (1 << 4), /* PATA port */ AHCI_HFLAG_NO_MSI = (1 << 5), /* no PCI MSI */ AHCI_HFLAG_NO_PMP = (1 << 6), /* no PMP */ + AHCI_HFLAG_NO_HOTPLUG = (1 << 7), /* ignore PxSERR.DIAG.N */ /* ap->flags bits */ - AHCI_FLAG_NO_HOTPLUG = (1 << 24), /* ignore PxSERR.DIAG.N */ AHCI_FLAG_COMMON = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | - ATA_FLAG_ACPI_SATA | ATA_FLAG_AN, + ATA_FLAG_ACPI_SATA | ATA_FLAG_AN | + ATA_FLAG_IPM, AHCI_LFLAG_COMMON = ATA_LFLAG_SKIP_D2H_BSY, + + ICH_MAP = 0x90, /* ICH MAP register */ }; struct ahci_cmd_hdr { @@ -254,6 +263,11 @@ static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); static int ahci_pci_device_resume(struct pci_dev *pdev); #endif +static struct class_device_attribute *ahci_shost_attrs[] = { + &class_device_attr_link_power_management_policy, + NULL +}; + static struct scsi_host_template ahci_sht = { .module = THIS_MODULE, .name = DRV_NAME, @@ -271,6 +285,7 @@ static struct scsi_host_template ahci_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .shost_attrs = ahci_shost_attrs, }; static const struct ata_port_operations ahci_ops = { @@ -302,6 +317,8 @@ static const struct ata_port_operations ahci_ops = { .port_suspend = ahci_port_suspend, .port_resume = ahci_port_resume, #endif + .enable_pm = ahci_enable_alpm, + .disable_pm = ahci_disable_alpm, .port_start = ahci_port_start, .port_stop = ahci_port_stop, @@ -521,6 +538,10 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci }, /* MCP77 */ { PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci }, /* MCP77 */ { PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci }, /* MCP77 */ + { PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci }, /* MCP79 */ + { PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci }, /* MCP79 */ + { PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci }, /* MCP79 */ + { PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci }, /* MCP79 */ { PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci }, /* MCP79 */ { PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci }, /* MCP79 */ { PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci }, /* MCP79 */ @@ -836,6 +857,130 @@ static void ahci_power_up(struct ata_port *ap) writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD); } +static void ahci_disable_alpm(struct ata_port *ap) +{ + struct ahci_host_priv *hpriv = ap->host->private_data; + void __iomem *port_mmio = ahci_port_base(ap); + u32 cmd; + struct ahci_port_priv *pp = ap->private_data; + + /* IPM bits should be disabled by libata-core */ + /* get the existing command bits */ + cmd = readl(port_mmio + PORT_CMD); + + /* disable ALPM and ASP */ + cmd &= ~PORT_CMD_ASP; + cmd &= ~PORT_CMD_ALPE; + + /* force the interface back to active */ + cmd |= PORT_CMD_ICC_ACTIVE; + + /* write out new cmd value */ + writel(cmd, port_mmio + PORT_CMD); + cmd = readl(port_mmio + PORT_CMD); + + /* wait 10ms to be sure we've come out of any low power state */ + msleep(10); + + /* clear out any PhyRdy stuff from interrupt status */ + writel(PORT_IRQ_PHYRDY, port_mmio + PORT_IRQ_STAT); + + /* go ahead and clean out PhyRdy Change from Serror too */ + ahci_scr_write(ap, SCR_ERROR, ((1 << 16) | (1 << 18))); + + /* + * Clear flag to indicate that we should ignore all PhyRdy + * state changes + */ + hpriv->flags &= ~AHCI_HFLAG_NO_HOTPLUG; + + /* + * Enable interrupts on Phy Ready. + */ + pp->intr_mask |= PORT_IRQ_PHYRDY; + writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); + + /* + * don't change the link pm policy - we can be called + * just to turn of link pm temporarily + */ +} + +static int ahci_enable_alpm(struct ata_port *ap, + enum link_pm policy) +{ + struct ahci_host_priv *hpriv = ap->host->private_data; + void __iomem *port_mmio = ahci_port_base(ap); + u32 cmd; + struct ahci_port_priv *pp = ap->private_data; + u32 asp; + + /* Make sure the host is capable of link power management */ + if (!(hpriv->cap & HOST_CAP_ALPM)) + return -EINVAL; + + switch (policy) { + case MAX_PERFORMANCE: + case NOT_AVAILABLE: + /* + * if we came here with NOT_AVAILABLE, + * it just means this is the first time we + * have tried to enable - default to max performance, + * and let the user go to lower power modes on request. + */ + ahci_disable_alpm(ap); + return 0; + case MIN_POWER: + /* configure HBA to enter SLUMBER */ + asp = PORT_CMD_ASP; + break; + case MEDIUM_POWER: + /* configure HBA to enter PARTIAL */ + asp = 0; + break; + default: + return -EINVAL; + } + + /* + * Disable interrupts on Phy Ready. This keeps us from + * getting woken up due to spurious phy ready interrupts + * TBD - Hot plug should be done via polling now, is + * that even supported? + */ + pp->intr_mask &= ~PORT_IRQ_PHYRDY; + writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); + + /* + * Set a flag to indicate that we should ignore all PhyRdy + * state changes since these can happen now whenever we + * change link state + */ + hpriv->flags |= AHCI_HFLAG_NO_HOTPLUG; + + /* get the existing command bits */ + cmd = readl(port_mmio + PORT_CMD); + + /* + * Set ASP based on Policy + */ + cmd |= asp; + + /* + * Setting this bit will instruct the HBA to aggressively + * enter a lower power link state when it's appropriate and + * based on the value set above for ASP + */ + cmd |= PORT_CMD_ALPE; + + /* write out new cmd value */ + writel(cmd, port_mmio + PORT_CMD); + cmd = readl(port_mmio + PORT_CMD); + + /* IPM bits should be set by libata-core */ + return 0; +} + #ifdef CONFIG_PM static void ahci_power_down(struct ata_port *ap) { @@ -898,8 +1043,10 @@ static int ahci_reset_controller(struct ata_host *host) * AHCI-specific, such as HOST_RESET. */ tmp = readl(mmio + HOST_CTL); - if (!(tmp & HOST_AHCI_EN)) - writel(tmp | HOST_AHCI_EN, mmio + HOST_CTL); + if (!(tmp & HOST_AHCI_EN)) { + tmp |= HOST_AHCI_EN; + writel(tmp, mmio + HOST_CTL); + } /* global controller reset */ if ((tmp & HOST_RESET) == 0) { @@ -1126,9 +1273,9 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class, /* prepare for SRST (AHCI-1.1 10.4.1) */ rc = ahci_kick_engine(ap, 1); - if (rc) + if (rc && rc != -EOPNOTSUPP) ata_link_printk(link, KERN_WARNING, - "failed to reset engine (errno=%d)", rc); + "failed to reset engine (errno=%d)\n", rc); ata_tf_init(link->device, &tf); @@ -1153,15 +1300,8 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class, tf.ctl &= ~ATA_SRST; ahci_exec_polled_cmd(ap, pmp, &tf, 0, 0, 0); - /* spec mandates ">= 2ms" before checking status. - * We wait 150ms, because that was the magic delay used for - * ATAPI devices in Hale Landis's ATADRVR, for the period of time - * between when the ATA command register is written, and then - * status is checked. Because waiting for "a while" before - * checking status is fine, post SRST, we perform this magic - * delay here as well. - */ - msleep(150); + /* wait a while before checking status */ + ata_wait_after_reset(ap, deadline); rc = ata_wait_ready(ap, deadline); /* link occupied, -ENODEV too is an error */ @@ -1500,7 +1640,7 @@ static void ahci_port_intr(struct ata_port *ap) struct ahci_host_priv *hpriv = ap->host->private_data; int resetting = !!(ap->pflags & ATA_PFLAG_RESETTING); u32 status, qc_active; - int rc, known_irq = 0; + int rc; status = readl(port_mmio + PORT_IRQ_STAT); writel(status, port_mmio + PORT_IRQ_STAT); @@ -1509,6 +1649,17 @@ static void ahci_port_intr(struct ata_port *ap) if (unlikely(resetting)) status &= ~PORT_IRQ_BAD_PMP; + /* If we are getting PhyRdy, this is + * just a power state change, we should + * clear out this, plus the PhyRdy/Comm + * Wake bits from Serror + */ + if ((hpriv->flags & AHCI_HFLAG_NO_HOTPLUG) && + (status & PORT_IRQ_PHYRDY)) { + status &= ~PORT_IRQ_PHYRDY; + ahci_scr_write(ap, SCR_ERROR, ((1 << 16) | (1 << 18))); + } + if (unlikely(status & PORT_IRQ_ERROR)) { ahci_error_intr(ap, status); return; @@ -1547,80 +1698,12 @@ static void ahci_port_intr(struct ata_port *ap) rc = ata_qc_complete_multiple(ap, qc_active, NULL); - /* If resetting, spurious or invalid completions are expected, - * return unconditionally. - */ - if (resetting) - return; - - if (rc > 0) - return; - if (rc < 0) { + /* while resetting, invalid completions are expected */ + if (unlikely(rc < 0 && !resetting)) { ehi->err_mask |= AC_ERR_HSM; ehi->action |= ATA_EH_SOFTRESET; ata_port_freeze(ap); - return; } - - /* hmmm... a spurious interrupt */ - - /* if !NCQ, ignore. No modern ATA device has broken HSM - * implementation for non-NCQ commands. - */ - if (!ap->link.sactive) - return; - - if (status & PORT_IRQ_D2H_REG_FIS) { - if (!pp->ncq_saw_d2h) - ata_port_printk(ap, KERN_INFO, - "D2H reg with I during NCQ, " - "this message won't be printed again\n"); - pp->ncq_saw_d2h = 1; - known_irq = 1; - } - - if (status & PORT_IRQ_DMAS_FIS) { - if (!pp->ncq_saw_dmas) - ata_port_printk(ap, KERN_INFO, - "DMAS FIS during NCQ, " - "this message won't be printed again\n"); - pp->ncq_saw_dmas = 1; - known_irq = 1; - } - - if (status & PORT_IRQ_SDB_FIS) { - const __le32 *f = pp->rx_fis + RX_FIS_SDB; - - if (le32_to_cpu(f[1])) { - /* SDB FIS containing spurious completions - * might be dangerous, whine and fail commands - * with HSM violation. EH will turn off NCQ - * after several such failures. - */ - ata_ehi_push_desc(ehi, - "spurious completions during NCQ " - "issue=0x%x SAct=0x%x FIS=%08x:%08x", - readl(port_mmio + PORT_CMD_ISSUE), - readl(port_mmio + PORT_SCR_ACT), - le32_to_cpu(f[0]), le32_to_cpu(f[1])); - ehi->err_mask |= AC_ERR_HSM; - ehi->action |= ATA_EH_SOFTRESET; - ata_port_freeze(ap); - } else { - if (!pp->ncq_saw_sdb) - ata_port_printk(ap, KERN_INFO, - "spurious SDB FIS %08x:%08x during NCQ, " - "this message won't be printed again\n", - le32_to_cpu(f[0]), le32_to_cpu(f[1])); - pp->ncq_saw_sdb = 1; - } - known_irq = 1; - } - - if (!known_irq) - ata_port_printk(ap, KERN_INFO, "spurious interrupt " - "(irq_stat 0x%x active_tag 0x%x sactive 0x%x)\n", - status, ap->link.active_tag, ap->link.sactive); } static void ahci_irq_clear(struct ata_port *ap) @@ -2124,6 +2207,22 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) return rc; + if (pdev->vendor == PCI_VENDOR_ID_INTEL && + (pdev->device == 0x2652 || pdev->device == 0x2653)) { + u8 map; + + /* ICH6s share the same PCI ID for both piix and ahci + * modes. Enabling ahci mode while MAP indicates + * combined mode is a bad idea. Yield to ata_piix. + */ + pci_read_config_byte(pdev, ICH_MAP, &map); + if (map & 0x3) { + dev_printk(KERN_INFO, &pdev->dev, "controller is in " + "combined mode, can't enable AHCI mode\n"); + return -ENODEV; + } + } + hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); if (!hpriv) return -ENOMEM; @@ -2156,6 +2255,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ata_port_pbar_desc(ap, AHCI_PCI_BAR, 0x100 + ap->port_no * 0x80, "port"); + /* set initial link pm policy */ + ap->pm_policy = NOT_AVAILABLE; + /* standard SATA port setup */ if (hpriv->port_map & (1 << i)) ap->ioaddr.cmd_addr = port_mmio; diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index a4b2cb29f46..b406b39b878 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -119,18 +119,20 @@ 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, + piix_pata_vmw, /* PIIX4 for VMware, spurious DMA_ERR */ /* constants for mapping table */ P0 = 0, /* port 0 */ @@ -164,6 +166,7 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev); static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev); static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev); static int ich_pata_cable_detect(struct ata_port *ap); +static u8 piix_vmw_bmdma_status(struct ata_port *ap); #ifdef CONFIG_PM static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); static int piix_pci_device_resume(struct pci_dev *pdev); @@ -174,6 +177,8 @@ static unsigned int in_module_init = 1; static const struct pci_device_id piix_pci_tbl[] = { /* Intel PIIX3 for the 430HX etc */ { 0x8086, 0x7010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_mwdma }, + /* VMware ICH4 */ + { 0x8086, 0x7111, 0x15ad, 0x1976, 0, 0, piix_pata_vmw }, /* Intel PIIX4 for the 430TX/440BX/MX chipset: UDMA 33 */ /* Also PIIX4E (fn3 rev 2) and PIIX4M (fn3 rev 3) */ { 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 }, @@ -239,19 +244,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) */ @@ -380,6 +387,38 @@ static const struct ata_port_operations piix_sata_ops = { .port_start = ata_port_start, }; +static const struct ata_port_operations piix_vmw_ops = { + .set_piomode = piix_set_piomode, + .set_dmamode = piix_set_dmamode, + .mode_filter = ata_pci_default_filter, + + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .check_status = ata_check_status, + .exec_command = ata_exec_command, + .dev_select = ata_std_dev_select, + + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, + .bmdma_stop = ata_bmdma_stop, + .bmdma_status = piix_vmw_bmdma_status, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + .data_xfer = ata_data_xfer, + + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = piix_pata_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, + .cable_detect = ata_cable_40wire, + + .irq_handler = ata_interrupt, + .irq_clear = ata_bmdma_irq_clear, + .irq_on = ata_irq_on, + + .port_start = ata_port_start, +}; + static const struct piix_map_db ich5_map_db = { .mask = 0x7, .port_enable = 0x3, @@ -427,7 +466,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 +476,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 +488,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 +518,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 +626,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 +648,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 +658,17 @@ static struct ata_port_info piix_port_info[] = { .udma_mask = ATA_UDMA6, .port_ops = &piix_sata_ops, }, + + [piix_pata_vmw] = + { + .sht = &piix_sht, + .flags = PIIX_PATA_FLAGS, + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ + .udma_mask = ATA_UDMA_MASK_40C, + .port_ops = &piix_vmw_ops, + }, + }; static struct pci_bits piix_enable_bits[] = { @@ -621,6 +695,7 @@ struct ich_laptop { static const struct ich_laptop ich_laptop[] = { /* devid, subvendor, subdev */ { 0x27DF, 0x0005, 0x0280 }, /* ICH7 on Acer 5602WLMi */ + { 0x27DF, 0x1025, 0x0102 }, /* ICH7 on Acer 5602aWLMi */ { 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */ { 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */ { 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */ @@ -938,6 +1013,20 @@ 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 M4", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Tecra M4"), + }, + }, + { .ident = "TECRA M5", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), @@ -952,6 +1041,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"), @@ -959,6 +1062,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"), @@ -966,6 +1083,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"), @@ -1057,6 +1181,11 @@ static int piix_pci_device_resume(struct pci_dev *pdev) } #endif +static u8 piix_vmw_bmdma_status(struct ata_port *ap) +{ + return ata_bmdma_status(ap) & ~ATA_DMA_ERR; +} + #define AHCI_PCI_BAR 5 #define AHCI_GLOBAL_CTL 0x04 #define AHCI_ENABLE (1 << 31) @@ -1078,12 +1207,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 08a52dd45fb..7bf4befd96b 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -6,6 +6,7 @@ * Copyright (C) 2006 Randy Dunlap */ +#include <linux/module.h> #include <linux/ata.h> #include <linux/delay.h> #include <linux/device.h> @@ -25,6 +26,18 @@ #include <acpi/acmacros.h> #include <acpi/actypes.h> +enum { + ATA_ACPI_FILTER_SETXFER = 1 << 0, + ATA_ACPI_FILTER_LOCK = 1 << 1, + + ATA_ACPI_FILTER_DEFAULT = ATA_ACPI_FILTER_SETXFER | + ATA_ACPI_FILTER_LOCK, +}; + +static unsigned int ata_acpi_gtf_filter = ATA_ACPI_FILTER_DEFAULT; +module_param_named(acpi_gtf_filter, ata_acpi_gtf_filter, int, 0644); +MODULE_PARM_DESC(acpi_gtf_filter, "filter mask for ACPI _GTF commands, set to filter out (0x1=set xfermode, 0x2=lock/freeze lock)"); + #define NO_PORT_MULT 0xffff #define SATA_ADR(root, pmp) (((root) << 16) | (pmp)) @@ -41,6 +54,12 @@ static int is_pci_dev(struct device *dev) return (dev->bus == &pci_bus_type); } +static void ata_acpi_clear_gtf(struct ata_device *dev) +{ + kfree(dev->gtf_cache); + dev->gtf_cache = NULL; +} + /** * ata_acpi_associate_sata_port - associate SATA port with ACPI objects * @ap: target SATA port @@ -94,6 +113,9 @@ static void ata_acpi_associate_ide_port(struct ata_port *ap) dev->acpi_handle = acpi_get_child(ap->acpi_handle, i); } + + if (ata_acpi_gtm(ap, &ap->__acpi_init_gtm) == 0) + ap->pflags |= ATA_PFLAG_INIT_GTM_VALID; } static void ata_acpi_handle_hotplug(struct ata_port *ap, struct kobject *kobj, @@ -188,6 +210,32 @@ void ata_acpi_associate(struct ata_host *host) } /** + * ata_acpi_dissociate - dissociate ATA host from ACPI objects + * @host: target ATA host + * + * This function is called during driver detach after the whole host + * is shut down. + * + * LOCKING: + * EH context. + */ +void ata_acpi_dissociate(struct ata_host *host) +{ + int i; + + /* Restore initial _GTM values so that driver which attaches + * afterward can use them too. + */ + for (i = 0; i < host->n_ports; i++) { + struct ata_port *ap = host->ports[i]; + const struct ata_acpi_gtm *gtm = ata_acpi_init_gtm(ap); + + if (ap->acpi_handle && gtm) + ata_acpi_stm(ap, gtm); + } +} + +/** * ata_acpi_gtm - execute _GTM * @ap: target ATA port * @gtm: out parameter for _GTM result @@ -200,7 +248,7 @@ void ata_acpi_associate(struct ata_host *host) * RETURNS: * 0 on success, -ENOENT if _GTM doesn't exist, -errno on failure. */ -int ata_acpi_gtm(const struct ata_port *ap, struct ata_acpi_gtm *gtm) +int ata_acpi_gtm(struct ata_port *ap, struct ata_acpi_gtm *gtm) { struct acpi_buffer output = { .length = ACPI_ALLOCATE_BUFFER }; union acpi_object *out_obj; @@ -259,15 +307,16 @@ EXPORT_SYMBOL_GPL(ata_acpi_gtm); * RETURNS: * 0 on success, -ENOENT if _STM doesn't exist, -errno on failure. */ -int ata_acpi_stm(const struct ata_port *ap, struct ata_acpi_gtm *stm) +int ata_acpi_stm(struct ata_port *ap, const struct ata_acpi_gtm *stm) { acpi_status status; + struct ata_acpi_gtm stm_buf = *stm; struct acpi_object_list input; union acpi_object in_params[3]; in_params[0].type = ACPI_TYPE_BUFFER; in_params[0].buffer.length = sizeof(struct ata_acpi_gtm); - in_params[0].buffer.pointer = (u8 *)stm; + in_params[0].buffer.pointer = (u8 *)&stm_buf; /* Buffers for id may need byteswapping ? */ in_params[1].type = ACPI_TYPE_BUFFER; in_params[1].buffer.length = 512; @@ -297,7 +346,6 @@ EXPORT_SYMBOL_GPL(ata_acpi_stm); * ata_dev_get_GTF - get the drive bootup default taskfile settings * @dev: target ATA device * @gtf: output parameter for buffer containing _GTF taskfile arrays - * @ptr_to_free: pointer which should be freed * * This applies to both PATA and SATA drives. * @@ -311,11 +359,10 @@ EXPORT_SYMBOL_GPL(ata_acpi_stm); * EH context. * * RETURNS: - * Number of taskfiles on success, 0 if _GTF doesn't exist or doesn't - * contain valid data. -errno on other errors. + * Number of taskfiles on success, 0 if _GTF doesn't exist. -EINVAL + * if _GTF is invalid. */ -static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf, - void **ptr_to_free) +static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf) { struct ata_port *ap = dev->link->ap; acpi_status status; @@ -323,6 +370,12 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf, union acpi_object *out_obj; int rc = 0; + /* if _GTF is cached, use the cached value */ + if (dev->gtf_cache) { + out_obj = dev->gtf_cache; + goto done; + } + /* set up output buffer */ output.length = ACPI_ALLOCATE_BUFFER; output.pointer = NULL; /* ACPI-CA sets this; save/free it later */ @@ -333,13 +386,14 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf, /* _GTF has no input parameters */ status = acpi_evaluate_object(dev->acpi_handle, "_GTF", NULL, &output); + out_obj = dev->gtf_cache = output.pointer; if (ACPI_FAILURE(status)) { if (status != AE_NOT_FOUND) { ata_dev_printk(dev, KERN_WARNING, "_GTF evaluation failed (AE 0x%x)\n", status); - rc = -EIO; + rc = -EINVAL; } goto out_free; } @@ -351,10 +405,10 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf, __FUNCTION__, (unsigned long long)output.length, output.pointer); + rc = -EINVAL; goto out_free; } - out_obj = output.pointer; if (out_obj->type != ACPI_TYPE_BUFFER) { ata_dev_printk(dev, KERN_WARNING, "_GTF unexpected object type 0x%x\n", @@ -371,18 +425,19 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf, goto out_free; } - *ptr_to_free = out_obj; - *gtf = (void *)out_obj->buffer.pointer; + done: rc = out_obj->buffer.length / REGS_PER_GTF; - - if (ata_msg_probe(ap)) - ata_dev_printk(dev, KERN_DEBUG, "%s: returning " - "gtf=%p, gtf_count=%d, ptr_to_free=%p\n", - __FUNCTION__, *gtf, rc, *ptr_to_free); + if (gtf) { + *gtf = (void *)out_obj->buffer.pointer; + if (ata_msg_probe(ap)) + ata_dev_printk(dev, KERN_DEBUG, + "%s: returning gtf=%p, gtf_count=%d\n", + __FUNCTION__, *gtf, rc); + } return rc; out_free: - kfree(output.pointer); + ata_acpi_clear_gtf(dev); return rc; } @@ -396,22 +451,21 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf, int ata_acpi_cbl_80wire(struct ata_port *ap) { - struct ata_acpi_gtm gtm; + const struct ata_acpi_gtm *gtm = ata_acpi_init_gtm(ap); int valid = 0; - /* No _GTM data, no information */ - if (ata_acpi_gtm(ap, >m) < 0) + if (!gtm) return 0; /* Split timing, DMA enabled */ - if ((gtm.flags & 0x11) == 0x11 && gtm.drive[0].dma < 55) + if ((gtm->flags & 0x11) == 0x11 && gtm->drive[0].dma < 55) valid |= 1; - if ((gtm.flags & 0x14) == 0x14 && gtm.drive[1].dma < 55) + if ((gtm->flags & 0x14) == 0x14 && gtm->drive[1].dma < 55) valid |= 2; /* Shared timing, DMA enabled */ - if ((gtm.flags & 0x11) == 0x01 && gtm.drive[0].dma < 55) + if ((gtm->flags & 0x11) == 0x01 && gtm->drive[0].dma < 55) valid |= 1; - if ((gtm.flags & 0x14) == 0x04 && gtm.drive[0].dma < 55) + if ((gtm->flags & 0x14) == 0x04 && gtm->drive[0].dma < 55) valid |= 2; /* Drive check */ @@ -424,8 +478,62 @@ int ata_acpi_cbl_80wire(struct ata_port *ap) EXPORT_SYMBOL_GPL(ata_acpi_cbl_80wire); +static void ata_acpi_gtf_to_tf(struct ata_device *dev, + const struct ata_acpi_gtf *gtf, + struct ata_taskfile *tf) +{ + ata_tf_init(dev, tf); + + tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; + tf->protocol = ATA_PROT_NODATA; + tf->feature = gtf->tf[0]; /* 0x1f1 */ + tf->nsect = gtf->tf[1]; /* 0x1f2 */ + tf->lbal = gtf->tf[2]; /* 0x1f3 */ + tf->lbam = gtf->tf[3]; /* 0x1f4 */ + tf->lbah = gtf->tf[4]; /* 0x1f5 */ + tf->device = gtf->tf[5]; /* 0x1f6 */ + tf->command = gtf->tf[6]; /* 0x1f7 */ +} + +static int ata_acpi_filter_tf(const struct ata_taskfile *tf, + const struct ata_taskfile *ptf) +{ + if (ata_acpi_gtf_filter & ATA_ACPI_FILTER_SETXFER) { + /* libata doesn't use ACPI to configure transfer mode. + * It will only confuse device configuration. Skip. + */ + if (tf->command == ATA_CMD_SET_FEATURES && + tf->feature == SETFEATURES_XFER) + return 1; + } + + if (ata_acpi_gtf_filter & ATA_ACPI_FILTER_LOCK) { + /* BIOS writers, sorry but we don't wanna lock + * features unless the user explicitly said so. + */ + + /* DEVICE CONFIGURATION FREEZE LOCK */ + if (tf->command == ATA_CMD_CONF_OVERLAY && + tf->feature == ATA_DCO_FREEZE_LOCK) + return 1; + + /* SECURITY FREEZE LOCK */ + if (tf->command == ATA_CMD_SEC_FREEZE_LOCK) + return 1; + + /* SET MAX LOCK and SET MAX FREEZE LOCK */ + if ((!ptf || ptf->command != ATA_CMD_READ_NATIVE_MAX) && + tf->command == ATA_CMD_SET_MAX && + (tf->feature == ATA_SET_MAX_LOCK || + tf->feature == ATA_SET_MAX_FREEZE_LOCK)) + return 1; + } + + return 0; +} + /** - * taskfile_load_raw - send taskfile registers to host controller + * ata_acpi_run_tf - send taskfile registers to host controller * @dev: target ATA device * @gtf: raw ATA taskfile register set (0x1f1 - 0x1f7) * @@ -444,56 +552,77 @@ EXPORT_SYMBOL_GPL(ata_acpi_cbl_80wire); * EH context. * * RETURNS: - * 0 on success, -errno on failure. + * 1 if command is executed successfully. 0 if ignored, rejected or + * filtered out, -errno on other errors. */ -static int taskfile_load_raw(struct ata_device *dev, - const struct ata_acpi_gtf *gtf) +static int ata_acpi_run_tf(struct ata_device *dev, + const struct ata_acpi_gtf *gtf, + const struct ata_acpi_gtf *prev_gtf) { - struct ata_port *ap = dev->link->ap; - struct ata_taskfile tf, rtf; + struct ata_taskfile *pptf = NULL; + struct ata_taskfile tf, ptf, rtf; unsigned int err_mask; + const char *level; + char msg[60]; + int rc; if ((gtf->tf[0] == 0) && (gtf->tf[1] == 0) && (gtf->tf[2] == 0) && (gtf->tf[3] == 0) && (gtf->tf[4] == 0) && (gtf->tf[5] == 0) && (gtf->tf[6] == 0)) return 0; - ata_tf_init(dev, &tf); + ata_acpi_gtf_to_tf(dev, gtf, &tf); + if (prev_gtf) { + ata_acpi_gtf_to_tf(dev, prev_gtf, &ptf); + pptf = &ptf; + } - /* convert gtf to tf */ - tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; /* TBD */ - tf.protocol = ATA_PROT_NODATA; - tf.feature = gtf->tf[0]; /* 0x1f1 */ - tf.nsect = gtf->tf[1]; /* 0x1f2 */ - tf.lbal = gtf->tf[2]; /* 0x1f3 */ - tf.lbam = gtf->tf[3]; /* 0x1f4 */ - tf.lbah = gtf->tf[4]; /* 0x1f5 */ - tf.device = gtf->tf[5]; /* 0x1f6 */ - tf.command = gtf->tf[6]; /* 0x1f7 */ + if (!ata_acpi_filter_tf(&tf, pptf)) { + rtf = tf; + err_mask = ata_exec_internal(dev, &rtf, NULL, + DMA_NONE, NULL, 0, 0); - if (ata_msg_probe(ap)) - ata_dev_printk(dev, KERN_DEBUG, "executing ACPI cmd " - "%02x/%02x:%02x:%02x:%02x:%02x:%02x\n", - tf.command, tf.feature, tf.nsect, - tf.lbal, tf.lbam, tf.lbah, tf.device); - - rtf = tf; - err_mask = ata_exec_internal(dev, &rtf, NULL, DMA_NONE, NULL, 0, 0); - if (err_mask) { - ata_dev_printk(dev, KERN_ERR, - "ACPI cmd %02x/%02x:%02x:%02x:%02x:%02x:%02x failed " - "(Emask=0x%x Stat=0x%02x Err=0x%02x)\n", - tf.command, tf.feature, tf.nsect, tf.lbal, tf.lbam, - tf.lbah, tf.device, err_mask, rtf.command, rtf.feature); - return -EIO; + switch (err_mask) { + case 0: + level = KERN_DEBUG; + snprintf(msg, sizeof(msg), "succeeded"); + rc = 1; + break; + + case AC_ERR_DEV: + level = KERN_INFO; + snprintf(msg, sizeof(msg), + "rejected by device (Stat=0x%02x Err=0x%02x)", + rtf.command, rtf.feature); + rc = 0; + break; + + default: + level = KERN_ERR; + snprintf(msg, sizeof(msg), + "failed (Emask=0x%x Stat=0x%02x Err=0x%02x)", + err_mask, rtf.command, rtf.feature); + rc = -EIO; + break; + } + } else { + level = KERN_INFO; + snprintf(msg, sizeof(msg), "filtered out"); + rc = 0; } - return 0; + ata_dev_printk(dev, level, + "ACPI cmd %02x/%02x:%02x:%02x:%02x:%02x:%02x %s\n", + tf.command, tf.feature, tf.nsect, tf.lbal, + tf.lbam, tf.lbah, tf.device, msg); + + return rc; } /** * ata_acpi_exec_tfs - get then write drive taskfile settings * @dev: target ATA device + * @nr_executed: out paramter for the number of executed commands * * Evaluate _GTF and excute returned taskfiles. * @@ -501,38 +630,36 @@ static int taskfile_load_raw(struct ata_device *dev, * EH context. * * RETURNS: - * Number of executed taskfiles on success, 0 if _GTF doesn't exist or - * doesn't contain valid data. -errno on other errors. + * Number of executed taskfiles on success, 0 if _GTF doesn't exist. + * -errno on other errors. */ -static int ata_acpi_exec_tfs(struct ata_device *dev) +static int ata_acpi_exec_tfs(struct ata_device *dev, int *nr_executed) { - struct ata_acpi_gtf *gtf = NULL; - void *ptr_to_free = NULL; + struct ata_acpi_gtf *gtf = NULL, *pgtf = NULL; int gtf_count, i, rc; /* get taskfiles */ - rc = ata_dev_get_GTF(dev, >f, &ptr_to_free); + rc = ata_dev_get_GTF(dev, >f); if (rc < 0) return rc; gtf_count = rc; /* execute them */ - for (i = 0, rc = 0; i < gtf_count; i++) { - int tmp; - - /* ACPI errors are eventually ignored. Run till the - * end even after errors. - */ - tmp = taskfile_load_raw(dev, gtf++); - if (!rc) - rc = tmp; + for (i = 0; i < gtf_count; i++, gtf++) { + rc = ata_acpi_run_tf(dev, gtf, pgtf); + if (rc < 0) + break; + if (rc) { + (*nr_executed)++; + pgtf = gtf; + } } - kfree(ptr_to_free); + ata_acpi_clear_gtf(dev); - if (rc == 0) - return gtf_count; - return rc; + if (rc < 0) + return rc; + return 0; } /** @@ -602,27 +729,8 @@ static int ata_acpi_push_id(struct ata_device *dev) */ int ata_acpi_on_suspend(struct ata_port *ap) { - unsigned long flags; - int rc; - - /* proceed iff per-port acpi_handle is valid */ - if (!ap->acpi_handle) - return 0; - BUG_ON(ap->flags & ATA_FLAG_ACPI_SATA); - - /* store timing parameters */ - rc = ata_acpi_gtm(ap, &ap->acpi_gtm); - - spin_lock_irqsave(ap->lock, flags); - if (rc == 0) - ap->pflags |= ATA_PFLAG_GTM_VALID; - else - ap->pflags &= ~ATA_PFLAG_GTM_VALID; - spin_unlock_irqrestore(ap->lock, flags); - - if (rc == -ENOENT) - rc = 0; - return rc; + /* nada */ + return 0; } /** @@ -637,18 +745,34 @@ int ata_acpi_on_suspend(struct ata_port *ap) */ void ata_acpi_on_resume(struct ata_port *ap) { + const struct ata_acpi_gtm *gtm = ata_acpi_init_gtm(ap); struct ata_device *dev; - if (ap->acpi_handle && (ap->pflags & ATA_PFLAG_GTM_VALID)) { - BUG_ON(ap->flags & ATA_FLAG_ACPI_SATA); + if (ap->acpi_handle && gtm) { + /* _GTM valid */ /* restore timing parameters */ - ata_acpi_stm(ap, &ap->acpi_gtm); - } + ata_acpi_stm(ap, gtm); - /* schedule _GTF */ - ata_link_for_each_dev(dev, &ap->link) - dev->flags |= ATA_DFLAG_ACPI_PENDING; + /* _GTF should immediately follow _STM so that it can + * use values set by _STM. Cache _GTF result and + * schedule _GTF. + */ + ata_link_for_each_dev(dev, &ap->link) { + ata_acpi_clear_gtf(dev); + if (ata_dev_get_GTF(dev, NULL) >= 0) + dev->flags |= ATA_DFLAG_ACPI_PENDING; + } + } else { + /* SATA _GTF needs to be evaulated after _SDD and + * there's no reason to evaluate IDE _GTF early + * without _STM. Clear cache and schedule _GTF. + */ + ata_link_for_each_dev(dev, &ap->link) { + ata_acpi_clear_gtf(dev); + dev->flags |= ATA_DFLAG_ACPI_PENDING; + } + } } /** @@ -670,6 +794,7 @@ int ata_acpi_on_devcfg(struct ata_device *dev) struct ata_port *ap = dev->link->ap; struct ata_eh_context *ehc = &ap->link.eh_context; int acpi_sata = ap->flags & ATA_FLAG_ACPI_SATA; + int nr_executed = 0; int rc; if (!dev->acpi_handle) @@ -688,14 +813,14 @@ int ata_acpi_on_devcfg(struct ata_device *dev) } /* do _GTF */ - rc = ata_acpi_exec_tfs(dev); - if (rc < 0) + rc = ata_acpi_exec_tfs(dev, &nr_executed); + if (rc) goto acpi_err; dev->flags &= ~ATA_DFLAG_ACPI_PENDING; /* refresh IDENTIFY page if any _GTF command has been executed */ - if (rc > 0) { + if (nr_executed) { rc = ata_dev_reread_id(dev, 0); if (rc < 0) { ata_dev_printk(dev, KERN_ERR, "failed to IDENTIFY " @@ -707,17 +832,39 @@ int ata_acpi_on_devcfg(struct ata_device *dev) return 0; acpi_err: - /* let EH retry on the first failure, disable ACPI on the second */ - if (dev->flags & ATA_DFLAG_ACPI_FAILED) { - ata_dev_printk(dev, KERN_WARNING, "ACPI on devcfg failed the " - "second time, disabling (errno=%d)\n", rc); - - dev->acpi_handle = NULL; + /* ignore evaluation failure if we can continue safely */ + if (rc == -EINVAL && !nr_executed && !(ap->pflags & ATA_PFLAG_FROZEN)) + return 0; - /* if port is working, request IDENTIFY reload and continue */ - if (!(ap->pflags & ATA_PFLAG_FROZEN)) - rc = 1; + /* fail and let EH retry once more for unknown IO errors */ + if (!(dev->flags & ATA_DFLAG_ACPI_FAILED)) { + dev->flags |= ATA_DFLAG_ACPI_FAILED; + return rc; } - dev->flags |= ATA_DFLAG_ACPI_FAILED; + + ata_dev_printk(dev, KERN_WARNING, + "ACPI: failed the second time, disabled\n"); + dev->acpi_handle = NULL; + + /* We can safely continue if no _GTF command has been executed + * and port is not frozen. + */ + if (!nr_executed && !(ap->pflags & ATA_PFLAG_FROZEN)) + return 0; + return rc; } + +/** + * ata_acpi_on_disable - ATA ACPI hook called when a device is disabled + * @dev: target ATA device + * + * This function is called when @dev is about to be disabled. + * + * LOCKING: + * EH context. + */ +void ata_acpi_on_disable(struct ata_device *dev) +{ + ata_acpi_clear_gtf(dev); +} diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 081e3dfb64d..6380726f753 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> @@ -56,6 +64,7 @@ #include <linux/libata.h> #include <asm/semaphore.h> #include <asm/byteorder.h> +#include <linux/cdrom.h> #include "libata.h" @@ -614,12 +623,190 @@ void ata_dev_disable(struct ata_device *dev) if (ata_dev_enabled(dev)) { if (ata_msg_drv(dev->link->ap)) ata_dev_printk(dev, KERN_WARNING, "disabled\n"); + ata_acpi_on_disable(dev); ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 | ATA_DNXFER_QUIET); dev->class++; } } +static int ata_dev_set_dipm(struct ata_device *dev, enum link_pm policy) +{ + struct ata_link *link = dev->link; + struct ata_port *ap = link->ap; + u32 scontrol; + unsigned int err_mask; + int rc; + + /* + * disallow DIPM for drivers which haven't set + * ATA_FLAG_IPM. This is because when DIPM is enabled, + * phy ready will be set in the interrupt status on + * state changes, which will cause some drivers to + * think there are errors - additionally drivers will + * need to disable hot plug. + */ + if (!(ap->flags & ATA_FLAG_IPM) || !ata_dev_enabled(dev)) { + ap->pm_policy = NOT_AVAILABLE; + return -EINVAL; + } + + /* + * For DIPM, we will only enable it for the + * min_power setting. + * + * Why? Because Disks are too stupid to know that + * If the host rejects a request to go to SLUMBER + * they should retry at PARTIAL, and instead it + * just would give up. So, for medium_power to + * work at all, we need to only allow HIPM. + */ + rc = sata_scr_read(link, SCR_CONTROL, &scontrol); + if (rc) + return rc; + + switch (policy) { + case MIN_POWER: + /* no restrictions on IPM transitions */ + scontrol &= ~(0x3 << 8); + rc = sata_scr_write(link, SCR_CONTROL, scontrol); + if (rc) + return rc; + + /* enable DIPM */ + if (dev->flags & ATA_DFLAG_DIPM) + err_mask = ata_dev_set_feature(dev, + SETFEATURES_SATA_ENABLE, SATA_DIPM); + break; + case MEDIUM_POWER: + /* allow IPM to PARTIAL */ + scontrol &= ~(0x1 << 8); + scontrol |= (0x2 << 8); + rc = sata_scr_write(link, SCR_CONTROL, scontrol); + if (rc) + return rc; + + /* + * we don't have to disable DIPM since IPM flags + * disallow transitions to SLUMBER, which effectively + * disable DIPM if it does not support PARTIAL + */ + break; + case NOT_AVAILABLE: + case MAX_PERFORMANCE: + /* disable all IPM transitions */ + scontrol |= (0x3 << 8); + rc = sata_scr_write(link, SCR_CONTROL, scontrol); + if (rc) + return rc; + + /* + * we don't have to disable DIPM since IPM flags + * disallow all transitions which effectively + * disable DIPM anyway. + */ + break; + } + + /* FIXME: handle SET FEATURES failure */ + (void) err_mask; + + return 0; +} + +/** + * ata_dev_enable_pm - enable SATA interface power management + * @dev: device to enable power management + * @policy: the link power management policy + * + * Enable SATA Interface power management. This will enable + * Device Interface Power Management (DIPM) for min_power + * policy, and then call driver specific callbacks for + * enabling Host Initiated Power management. + * + * Locking: Caller. + * Returns: -EINVAL if IPM is not supported, 0 otherwise. + */ +void ata_dev_enable_pm(struct ata_device *dev, enum link_pm policy) +{ + int rc = 0; + struct ata_port *ap = dev->link->ap; + + /* set HIPM first, then DIPM */ + if (ap->ops->enable_pm) + rc = ap->ops->enable_pm(ap, policy); + if (rc) + goto enable_pm_out; + rc = ata_dev_set_dipm(dev, policy); + +enable_pm_out: + if (rc) + ap->pm_policy = MAX_PERFORMANCE; + else + ap->pm_policy = policy; + return /* rc */; /* hopefully we can use 'rc' eventually */ +} + +#ifdef CONFIG_PM +/** + * ata_dev_disable_pm - disable SATA interface power management + * @dev: device to disable power management + * + * Disable SATA Interface power management. This will disable + * Device Interface Power Management (DIPM) without changing + * policy, call driver specific callbacks for disabling Host + * Initiated Power management. + * + * Locking: Caller. + * Returns: void + */ +static void ata_dev_disable_pm(struct ata_device *dev) +{ + struct ata_port *ap = dev->link->ap; + + ata_dev_set_dipm(dev, MAX_PERFORMANCE); + if (ap->ops->disable_pm) + ap->ops->disable_pm(ap); +} +#endif /* CONFIG_PM */ + +void ata_lpm_schedule(struct ata_port *ap, enum link_pm policy) +{ + ap->pm_policy = policy; + ap->link.eh_info.action |= ATA_EHI_LPM; + ap->link.eh_info.flags |= ATA_EHI_NO_AUTOPSY; + ata_port_schedule_eh(ap); +} + +#ifdef CONFIG_PM +static void ata_lpm_enable(struct ata_host *host) +{ + struct ata_link *link; + struct ata_port *ap; + struct ata_device *dev; + int i; + + for (i = 0; i < host->n_ports; i++) { + ap = host->ports[i]; + ata_port_for_each_link(link, ap) { + ata_link_for_each_dev(dev, link) + ata_dev_disable_pm(dev); + } + } +} + +static void ata_lpm_disable(struct ata_host *host) +{ + int i; + + for (i = 0; i < host->n_ports; i++) { + struct ata_port *ap = host->ports[i]; + ata_lpm_schedule(ap, ap->pm_policy); + } +} +#endif /* CONFIG_PM */ + + /** * ata_devchk - PATA device presence detection * @ap: ATA channel to examine @@ -2101,6 +2288,13 @@ int ata_dev_configure(struct ata_device *dev) if (dev->flags & ATA_DFLAG_LBA48) dev->max_sectors = ATA_MAX_SECTORS_LBA48; + if (!(dev->horkage & ATA_HORKAGE_IPM)) { + if (ata_id_has_hipm(dev->id)) + dev->flags |= ATA_DFLAG_HIPM; + if (ata_id_has_dipm(dev->id)) + dev->flags |= ATA_DFLAG_DIPM; + } + if (dev->horkage & ATA_HORKAGE_DIAGNOSTIC) { /* Let the user know. We don't want to disallow opens for rescue purposes, or in case the vendor is just a blithering @@ -2122,10 +2316,23 @@ int ata_dev_configure(struct ata_device *dev) dev->max_sectors = ATA_MAX_SECTORS; } + if ((dev->class == ATA_DEV_ATAPI) && + (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, dev->max_sectors); + if (ata_dev_blacklisted(dev) & ATA_HORKAGE_IPM) { + dev->horkage |= ATA_HORKAGE_IPM; + + /* reset link pm_policy for this port to no pm */ + ap->pm_policy = MAX_PERFORMANCE; + } + if (ap->ops->dev_config) ap->ops->dev_config(dev); @@ -2219,6 +2426,25 @@ int ata_bus_probe(struct ata_port *ap) tries[dev->devno] = ATA_PROBE_MAX_TRIES; retry: + ata_link_for_each_dev(dev, &ap->link) { + /* If we issue an SRST then an ATA drive (not ATAPI) + * may change configuration and be in PIO0 timing. If + * we do a hard reset (or are coming from power on) + * this is true for ATA or ATAPI. Until we've set a + * suitable controller mode we should not touch the + * bus as we may be talking too fast. + */ + dev->pio_mode = XFER_PIO_0; + + /* If the controller has a pio mode setup function + * then use it to set the chipset to rights. Don't + * touch the DMA setup as that will be dealt with when + * configuring devices. + */ + if (ap->ops->set_piomode) + ap->ops->set_piomode(ap, dev); + } + /* reset and determine device classes */ ap->ops->phy_reset(ap); @@ -2234,12 +2460,6 @@ int ata_bus_probe(struct ata_port *ap) ata_port_probe(ap); - /* after the reset the device state is PIO 0 and the controller - state is undefined. Record the mode */ - - ata_link_for_each_dev(dev, &ap->link) - dev->pio_mode = XFER_PIO_0; - /* read IDENTIFY page and configure devices. We have to do the identify specific sequence bass-ackwards so that PDIAG- is released by the slave device */ @@ -2373,81 +2593,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 * @@ -2545,17 +2690,27 @@ int sata_down_spd_limit(struct ata_link *link) static int __sata_set_spd_needed(struct ata_link *link, u32 *scontrol) { - u32 spd, limit; + struct ata_link *host_link = &link->ap->link; + u32 limit, target, spd; + + limit = link->sata_spd_limit; - if (link->sata_spd_limit == UINT_MAX) - limit = 0; + /* Don't configure downstream link faster than upstream link. + * It doesn't speed up anything and some PMPs choke on such + * configuration. + */ + if (!ata_is_host_link(link) && host_link->sata_spd) + limit &= (1 << host_link->sata_spd) - 1; + + if (limit == UINT_MAX) + target = 0; else - limit = fls(link->sata_spd_limit); + target = fls(limit); spd = (*scontrol >> 4) & 0xf; - *scontrol = (*scontrol & ~0xf0) | ((limit & 0xf) << 4); + *scontrol = (*scontrol & ~0xf0) | ((target & 0xf) << 4); - return spd != limit; + return spd != target; } /** @@ -2578,7 +2733,7 @@ int sata_set_spd_needed(struct ata_link *link) u32 scontrol; if (sata_scr_read(link, SCR_CONTROL, &scontrol)) - return 0; + return 1; return __sata_set_spd_needed(link, &scontrol); } @@ -3118,6 +3273,61 @@ int ata_busy_sleep(struct ata_port *ap, } /** + * ata_wait_after_reset - wait before checking status after reset + * @ap: port containing status register to be polled + * @deadline: deadline jiffies for the operation + * + * After reset, we need to pause a while before reading status. + * Also, certain combination of controller and device report 0xff + * for some duration (e.g. until SATA PHY is up and running) + * which is interpreted as empty port in ATA world. This + * function also waits for such devices to get out of 0xff + * status. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +void ata_wait_after_reset(struct ata_port *ap, unsigned long deadline) +{ + unsigned long until = jiffies + ATA_TMOUT_FF_WAIT; + + if (time_before(until, deadline)) + deadline = until; + + /* Spec mandates ">= 2ms" before checking status. We wait + * 150ms, because that was the magic delay used for ATAPI + * devices in Hale Landis's ATADRVR, for the period of time + * between when the ATA command register is written, and then + * status is checked. Because waiting for "a while" before + * checking status is fine, post SRST, we perform this magic + * delay here as well. + * + * Old drivers/ide uses the 2mS rule and then waits for ready. + */ + msleep(150); + + /* Wait for 0xff to clear. Some SATA devices take a long time + * 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. + */ + if (ap->flags & ATA_FLAG_SATA) { + while (1) { + u8 status = ata_chk_status(ap); + + if (status != 0xff || time_after(jiffies, deadline)) + return; + + msleep(50); + } + } +} + +/** * ata_wait_ready - sleep until BSY clears, or timeout * @ap: port containing status register to be polled * @deadline: deadline jiffies for the operation @@ -3223,8 +3433,6 @@ static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask, unsigned long deadline) { struct ata_ioports *ioaddr = &ap->ioaddr; - struct ata_device *dev; - int i = 0; DPRINTK("ata%u: bus reset via SRST\n", ap->print_id); @@ -3235,36 +3443,8 @@ static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask, udelay(20); /* FIXME: flush */ iowrite8(ap->ctl, ioaddr->ctl_addr); - /* If we issued an SRST then an ATA drive (not ATAPI) - * may have changed configuration and be in PIO0 timing. If - * we did a hard reset (or are coming from power on) this is - * true for ATA or ATAPI. Until we've set a suitable controller - * mode we should not touch the bus as we may be talking too fast. - */ - - ata_link_for_each_dev(dev, &ap->link) - dev->pio_mode = XFER_PIO_0; - - /* If the controller has a pio mode setup function then use - it to set the chipset to rights. Don't touch the DMA setup - as that will be dealt with when revalidating */ - if (ap->ops->set_piomode) { - ata_link_for_each_dev(dev, &ap->link) - if (devmask & (1 << i++)) - ap->ops->set_piomode(ap, dev); - } - - /* spec mandates ">= 2ms" before checking status. - * We wait 150ms, because that was the magic delay used for - * ATAPI devices in Hale Landis's ATADRVR, for the period of time - * between when the ATA command register is written, and then - * status is checked. Because waiting for "a while" before - * checking status is fine, post SRST, we perform this magic - * delay here as well. - * - * Old drivers/ide uses the 2mS rule and then waits for ready - */ - msleep(150); + /* wait a while before checking status */ + ata_wait_after_reset(ap, deadline); /* Before we perform post reset processing we want to see if * the bus shows 0xFF because the odd clown forgets the D7 @@ -3691,8 +3871,8 @@ int sata_std_hardreset(struct ata_link *link, unsigned int *class, return 0; } - /* wait a while before checking status, see SRST for more info */ - msleep(150); + /* wait a while before checking status */ + ata_wait_after_reset(ap, deadline); /* If PMP is supported, we have to do follow-up SRST. Note * that some PMPs don't send D2H Reg FIS after hardreset at @@ -3745,6 +3925,7 @@ void ata_std_postreset(struct ata_link *link, unsigned int *classes) /* clear SError */ if (sata_scr_read(link, SCR_ERROR, &serror) == 0) sata_scr_write(link, SCR_ERROR, serror); + link->eh_info.serror = 0; /* is double-select really necessary? */ if (classes[0] != ATA_DEV_NONE) @@ -3962,6 +4143,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { /* Devices where NCQ should be avoided */ /* NCQ is slow */ { "WDC WD740ADFD-00", NULL, ATA_HORKAGE_NONCQ }, + { "WDC WD740ADFD-00NLR1", NULL, ATA_HORKAGE_NONCQ, }, /* http://thread.gmane.org/gmane.linux.ide/14907 */ { "FUJITSU MHT2060BH", NULL, ATA_HORKAGE_NONCQ }, /* NCQ is broken */ @@ -3970,28 +4152,13 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "HITACHI HDS7250SASUN500G*", NULL, ATA_HORKAGE_NONCQ }, { "HITACHI HDS7225SBSUN250G*", NULL, ATA_HORKAGE_NONCQ }, { "ST380817AS", "3.42", ATA_HORKAGE_NONCQ }, + { "ST3160023AS", "3.42", ATA_HORKAGE_NONCQ }, /* Blacklist entries taken from Silicon Image 3124/3132 Windows driver .inf file - also several Linux problem reports */ { "HTS541060G9SA00", "MB3OC60D", ATA_HORKAGE_NONCQ, }, { "HTS541080G9SA00", "MB4OC60D", ATA_HORKAGE_NONCQ, }, { "HTS541010G9SA00", "MBZOC60D", ATA_HORKAGE_NONCQ, }, - /* Drives which do spurious command completion */ - { "HTS541680J9SA00", "SB2IC7EP", ATA_HORKAGE_NONCQ, }, - { "HTS541612J9SA00", "SBDIC7JP", ATA_HORKAGE_NONCQ, }, - { "HDT722516DLA380", "V43OA96A", ATA_HORKAGE_NONCQ, }, - { "Hitachi HTS541616J9SA00", "SB4OC70P", ATA_HORKAGE_NONCQ, }, - { "Hitachi HTS542525K9SA00", "BBFOC31P", ATA_HORKAGE_NONCQ, }, - { "WDC WD740ADFD-00NLR1", NULL, ATA_HORKAGE_NONCQ, }, - { "WDC WD3200AAJS-00RYA0", "12.01B01", ATA_HORKAGE_NONCQ, }, - { "FUJITSU MHV2080BH", "00840028", ATA_HORKAGE_NONCQ, }, - { "ST9120822AS", "3.CLF", ATA_HORKAGE_NONCQ, }, - { "ST9160821AS", "3.CLF", ATA_HORKAGE_NONCQ, }, - { "ST9160821AS", "3.ALD", ATA_HORKAGE_NONCQ, }, - { "ST9160821AS", "3.CCD", ATA_HORKAGE_NONCQ, }, - { "ST3160812AS", "3.ADJ", ATA_HORKAGE_NONCQ, }, - { "ST980813AS", "3.ADB", ATA_HORKAGE_NONCQ, }, - { "SAMSUNG HD401LJ", "ZZ100-15", ATA_HORKAGE_NONCQ, }, /* devices which puke on READ_NATIVE_MAX */ { "HDS724040KLSA80", "KFAOA20N", ATA_HORKAGE_BROKEN_HPA, }, @@ -4003,6 +4170,13 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "ST340823A", NULL, ATA_HORKAGE_HPA_SIZE, }, { "ST320413A", NULL, ATA_HORKAGE_HPA_SIZE, }, + /* 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 */ { } }; @@ -4064,6 +4238,21 @@ static int ata_dma_blacklisted(const struct ata_device *dev) } /** + * ata_is_40wire - check drive side detection + * @dev: device + * + * Perform drive side detection decoding, allowing for device vendors + * who can't follow the documentation. + */ + +static int ata_is_40wire(struct ata_device *dev) +{ + if (dev->horkage & ATA_HORKAGE_IVB) + return ata_drive_40wire_relaxed(dev->id); + return ata_drive_40wire(dev->id); +} + +/** * ata_dev_xfermask - Compute supported xfermask of the given device * @dev: Device to compute xfermask for * @@ -4132,7 +4321,7 @@ static void ata_dev_xfermask(struct ata_device *dev) if (xfer_mask & (0xF8 << ATA_SHIFT_UDMA)) /* UDMA/44 or higher would be available */ if ((ap->cbl == ATA_CBL_PATA40) || - (ata_drive_40wire(dev->id) && + (ata_is_40wire(dev) && (ap->cbl == ATA_CBL_PATA_UNK || ap->cbl == ATA_CBL_PATA80))) { ata_dev_printk(dev, KERN_WARNING, @@ -4464,6 +4653,43 @@ int ata_check_atapi_dma(struct ata_queued_cmd *qc) } /** + * atapi_qc_may_overflow - Check whether data transfer may overflow + * @qc: ATA command in question + * + * ATAPI commands which transfer variable length data to host + * might overflow due to application error or hardare bug. This + * function checks whether overflow should be drained and ignored + * for @qc. + * + * LOCKING: + * None. + * + * RETURNS: + * 1 if @qc may overflow; otherwise, 0. + */ +static int atapi_qc_may_overflow(struct ata_queued_cmd *qc) +{ + if (qc->tf.protocol != ATA_PROT_ATAPI && + qc->tf.protocol != ATA_PROT_ATAPI_DMA) + return 0; + + if (qc->tf.flags & ATA_TFLAG_WRITE) + return 0; + + switch (qc->cdb[0]) { + case READ_10: + case READ_12: + case WRITE_10: + case WRITE_12: + case GPCMD_READ_CD: + case GPCMD_READ_CD_MSF: + return 0; + } + + return 1; +} + +/** * ata_std_qc_defer - Check whether a qc needs to be deferred * @qc: ATA command in question * @@ -4689,6 +4915,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) * data in this function or read data in ata_sg_clean. */ offset = lsg->offset + lsg->length - qc->pad_len; + sg_init_table(psg, 1); sg_set_page(psg, nth_page(sg_page(lsg), offset >> PAGE_SHIFT), qc->pad_len, offset_in_page(offset)); @@ -4950,23 +5177,19 @@ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc) * Inherited from caller. * */ - -static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes) +static int __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes) { int do_write = (qc->tf.flags & ATA_TFLAG_WRITE); - struct scatterlist *sg = qc->__sg; - struct scatterlist *lsg = sg_last(qc->__sg, qc->n_elem); struct ata_port *ap = qc->ap; + struct ata_eh_info *ehi = &qc->dev->link->eh_info; + struct scatterlist *sg; struct page *page; unsigned char *buf; unsigned int offset, count; - int no_more_sg = 0; - - if (qc->curbytes + bytes >= qc->nbytes) - ap->hsm_task_state = HSM_ST_LAST; next_sg: - if (unlikely(no_more_sg)) { + sg = qc->cursg; + if (unlikely(!sg)) { /* * The end of qc->sg is reached and the device expects * more data to transfer. In order not to overrun qc->sg @@ -4975,21 +5198,28 @@ next_sg: * - for write case, padding zero data to the device */ u16 pad_buf[1] = { 0 }; - unsigned int words = bytes >> 1; unsigned int i; - if (words) /* warning if bytes > 1 */ - ata_dev_printk(qc->dev, KERN_WARNING, - "%u bytes trailing data\n", bytes); + if (bytes > qc->curbytes - qc->nbytes + ATAPI_MAX_DRAIN) { + ata_ehi_push_desc(ehi, "too much trailing data " + "buf=%u cur=%u bytes=%u", + qc->nbytes, qc->curbytes, bytes); + return -1; + } + + /* overflow is exptected for misc ATAPI commands */ + if (bytes && !atapi_qc_may_overflow(qc)) + ata_dev_printk(qc->dev, KERN_WARNING, "ATAPI %u bytes " + "trailing data (cdb=%02x nbytes=%u)\n", + bytes, qc->cdb[0], qc->nbytes); - for (i = 0; i < words; i++) + for (i = 0; i < (bytes + 1) / 2; i++) ap->ops->data_xfer(qc->dev, (unsigned char *)pad_buf, 2, do_write); - ap->hsm_task_state = HSM_ST_LAST; - return; - } + qc->curbytes += bytes; - sg = qc->cursg; + return 0; + } page = sg_page(sg); offset = sg->offset + qc->cursg_ofs; @@ -5024,19 +5254,20 @@ next_sg: } bytes -= count; + if ((count & 1) && bytes) + bytes--; qc->curbytes += count; qc->cursg_ofs += count; if (qc->cursg_ofs == sg->length) { - if (qc->cursg == lsg) - no_more_sg = 1; - qc->cursg = sg_next(qc->cursg); qc->cursg_ofs = 0; } if (bytes) goto next_sg; + + return 0; } /** @@ -5079,7 +5310,8 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc) VPRINTK("ata%u: xfering %d bytes\n", ap->print_id, bytes); - __atapi_pio_bytes(qc, bytes); + if (__atapi_pio_bytes(qc, bytes)) + goto err_out; ata_altstatus(ap); /* flush */ return; @@ -5226,11 +5458,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). @@ -5594,6 +5834,9 @@ void ata_qc_complete(struct ata_queued_cmd *qc) * taken care of. */ if (ap->ops->error_handler) { + struct ata_device *dev = qc->dev; + struct ata_eh_info *ehi = &dev->link->eh_info; + WARN_ON(ap->pflags & ATA_PFLAG_FROZEN); if (unlikely(qc->err_mask)) @@ -5612,6 +5855,27 @@ void ata_qc_complete(struct ata_queued_cmd *qc) if (qc->flags & ATA_QCFLAG_RESULT_TF) fill_result_tf(qc); + /* Some commands need post-processing after successful + * completion. + */ + switch (qc->tf.command) { + case ATA_CMD_SET_FEATURES: + if (qc->tf.feature != SETFEATURES_WC_ON && + qc->tf.feature != SETFEATURES_WC_OFF) + break; + /* fall through */ + case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */ + case ATA_CMD_SET_MULTI: /* multi_count changed */ + /* revalidate device */ + ehi->dev_action[dev->devno] |= ATA_EH_REVALIDATE; + ata_port_schedule_eh(ap); + break; + + case ATA_CMD_SLEEP: + dev->flags |= ATA_DFLAG_SLEEPING; + break; + } + __ata_qc_complete(qc); } else { if (qc->flags & ATA_QCFLAG_EH_SCHEDULED) @@ -5749,6 +6013,14 @@ void ata_qc_issue(struct ata_queued_cmd *qc) qc->flags &= ~ATA_QCFLAG_DMAMAP; } + /* if device is sleeping, schedule softreset and abort the link */ + if (unlikely(qc->dev->flags & ATA_DFLAG_SLEEPING)) { + link->eh_info.action |= ATA_EH_SOFTRESET; + ata_ehi_push_desc(&link->eh_info, "waking up from sleep"); + ata_link_abort(link); + return; + } + ap->ops->qc_prep(qc); qc->err_mask |= ap->ops->qc_issue(qc); @@ -6296,6 +6568,12 @@ int ata_host_suspend(struct ata_host *host, pm_message_t mesg) { int rc; + /* + * disable link pm on all ports before requesting + * any pm activity + */ + ata_lpm_enable(host); + rc = ata_host_request_pm(host, mesg, 0, ATA_EHI_QUIET, 1); if (rc == 0) host->dev->power.power_state = mesg; @@ -6318,6 +6596,9 @@ void ata_host_resume(struct ata_host *host) ata_host_request_pm(host, PMSG_ON, ATA_EH_SOFTRESET, ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0); host->dev->power.power_state = PMSG_ON; + + /* reenable link pm */ + ata_lpm_disable(host); } #endif @@ -6522,19 +6803,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); @@ -6661,6 +6929,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 @@ -6679,6 +6965,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) @@ -6690,18 +6978,37 @@ 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; @@ -6712,6 +7019,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; } @@ -6860,6 +7168,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) struct ata_port *ap = host->ports[i]; ata_scsi_scan_host(ap, 1); + ata_lpm_schedule(ap, ap->pm_policy); } return 0; @@ -6878,6 +7187,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). * @@ -6894,6 +7207,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) @@ -6937,18 +7256,14 @@ static void ata_port_detach(struct ata_port *ap) ata_port_wait_eh(ap); - /* EH is now guaranteed to see UNLOADING, so no new device - * will be attached. Disable all existing devices. + /* EH is now guaranteed to see UNLOADING - EH context belongs + * to us. Disable all existing devices. */ - spin_lock_irqsave(ap->lock, flags); - ata_port_for_each_link(link, ap) { ata_link_for_each_dev(dev, link) ata_dev_disable(dev); } - spin_unlock_irqrestore(ap->lock, flags); - /* Final freeze & EH. All in-flight commands are aborted. EH * will be skipped and retrials will be terminated with bad * target. @@ -6980,6 +7295,9 @@ void ata_host_detach(struct ata_host *host) for (i = 0; i < host->n_ports; i++) ata_port_detach(host->ports[i]); + + /* the host is dead now, dissociate ACPI */ + ata_acpi_dissociate(host); } /** @@ -7256,7 +7574,6 @@ const struct ata_port_info ata_dummy_port_info = { * likely to change as new drivers are added and updated. * Do not depend on ABI/API stability. */ - EXPORT_SYMBOL_GPL(sata_deb_timing_normal); EXPORT_SYMBOL_GPL(sata_deb_timing_hotplug); EXPORT_SYMBOL_GPL(sata_deb_timing_long); @@ -7312,8 +7629,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); @@ -7326,6 +7641,7 @@ EXPORT_SYMBOL_GPL(ata_port_disable); EXPORT_SYMBOL_GPL(ata_ratelimit); EXPORT_SYMBOL_GPL(ata_wait_register); EXPORT_SYMBOL_GPL(ata_busy_sleep); +EXPORT_SYMBOL_GPL(ata_wait_after_reset); EXPORT_SYMBOL_GPL(ata_wait_ready); EXPORT_SYMBOL_GPL(ata_port_queue_task); EXPORT_SYMBOL_GPL(ata_scsi_ioctl); @@ -7383,7 +7699,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 8cb35bb8760..21a81cd148e 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; @@ -1359,8 +1264,8 @@ static unsigned int atapi_eh_request_sense(struct ata_queued_cmd *qc) tf.feature |= ATAPI_PKT_DMA; } else { tf.protocol = ATA_PROT_ATAPI; - tf.lbam = (8 * 1024) & 0xff; - tf.lbah = (8 * 1024) >> 8; + tf.lbam = SCSI_SENSE_BUFFERSIZE; + tf.lbah = 0; } return ata_exec_internal(dev, &tf, cdb, DMA_FROM_DEVICE, @@ -1747,6 +1652,7 @@ static void ata_eh_link_autopsy(struct ata_link *link) { struct ata_port *ap = link->ap; struct ata_eh_context *ehc = &link->eh_context; + struct ata_device *dev; unsigned int all_err_mask = 0; int tag, is_io = 0; u32 serror; @@ -1800,10 +1706,8 @@ static void ata_eh_link_autopsy(struct ata_link *link) qc->err_mask &= ~AC_ERR_OTHER; /* SENSE_VALID trumps dev/unknown error and revalidation */ - if (qc->flags & ATA_QCFLAG_SENSE_VALID) { + if (qc->flags & ATA_QCFLAG_SENSE_VALID) qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER); - ehc->i.action &= ~ATA_EH_REVALIDATE; - } /* accumulate error info */ ehc->i.dev = qc->dev; @@ -1816,21 +1720,32 @@ static void ata_eh_link_autopsy(struct ata_link *link) if (ap->pflags & ATA_PFLAG_FROZEN || all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT)) ehc->i.action |= ATA_EH_SOFTRESET; - else if (all_err_mask) + else if ((is_io && all_err_mask) || + (!is_io && (all_err_mask & ~AC_ERR_DEV))) ehc->i.action |= ATA_EH_REVALIDATE; - /* if we have offending qcs and the associated failed device */ + /* If we have offending qcs and the associated failed device, + * perform per-dev EH action only on the offending device. + */ if (ehc->i.dev) { - /* speed down */ - ehc->i.action |= ata_eh_speed_down(ehc->i.dev, is_io, - all_err_mask); - - /* perform per-dev EH action only on the offending device */ ehc->i.dev_action[ehc->i.dev->devno] |= ehc->i.action & ATA_EH_PERDEV_MASK; ehc->i.action &= ~ATA_EH_PERDEV_MASK; } + /* propagate timeout to host link */ + if ((all_err_mask & AC_ERR_TIMEOUT) && !ata_is_host_link(link)) + ap->link.eh_context.i.err_mask |= AC_ERR_TIMEOUT; + + /* record error and consider speeding down */ + dev = ehc->i.dev; + if (!dev && ((ata_link_max_devices(link) == 1 && + ata_dev_enabled(link->device)))) + dev = link->device; + + if (dev) + ehc->i.action |= ata_eh_speed_down(dev, is_io, all_err_mask); + DPRINTK("EXIT\n"); } @@ -1848,8 +1763,14 @@ void ata_eh_autopsy(struct ata_port *ap) { struct ata_link *link; - __ata_port_for_each_link(link, ap) + ata_port_for_each_link(link, ap) ata_eh_link_autopsy(link); + + /* Autopsy of fanout ports can affect host link autopsy. + * Perform host link autopsy last. + */ + if (ap->nr_pmp_links) + ata_eh_link_autopsy(&ap->link); } /** @@ -1879,7 +1800,9 @@ static void ata_eh_link_report(struct ata_link *link) for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); - if (!(qc->flags & ATA_QCFLAG_FAILED) || qc->dev->link != link) + if (!(qc->flags & ATA_QCFLAG_FAILED) || qc->dev->link != link || + ((qc->flags & ATA_QCFLAG_QUIET) && + qc->err_mask == AC_ERR_DEV)) continue; if (qc->flags & ATA_QCFLAG_SENSE_VALID && !qc->err_mask) continue; @@ -1937,30 +1860,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, @@ -2064,16 +2011,19 @@ int ata_eh_reset(struct ata_link *link, int classify, ata_prereset_fn_t prereset, ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) { + const int max_tries = ARRAY_SIZE(ata_eh_reset_timeouts); struct ata_port *ap = link->ap; struct ata_eh_context *ehc = &link->eh_context; unsigned int *classes = ehc->classes; + unsigned int lflags = link->flags; int verbose = !(ehc->i.flags & ATA_EHI_QUIET); int try = 0; struct ata_device *dev; - unsigned long deadline; + unsigned long deadline, now; unsigned int tmp_action; ata_reset_fn_t reset; unsigned long flags; + u32 sstatus; int rc; /* about to reset */ @@ -2083,10 +2033,29 @@ int ata_eh_reset(struct ata_link *link, int classify, ata_eh_about_to_do(link, NULL, ehc->i.action & ATA_EH_RESET_MASK); + ata_link_for_each_dev(dev, link) { + /* If we issue an SRST then an ATA drive (not ATAPI) + * may change configuration and be in PIO0 timing. If + * we do a hard reset (or are coming from power on) + * this is true for ATA or ATAPI. Until we've set a + * suitable controller mode we should not touch the + * bus as we may be talking too fast. + */ + dev->pio_mode = XFER_PIO_0; + + /* If the controller has a pio mode setup function + * then use it to set the chipset to rights. Don't + * touch the DMA setup as that will be dealt with when + * configuring devices. + */ + if (ap->ops->set_piomode) + ap->ops->set_piomode(ap, dev); + } + /* Determine which reset to use and record in ehc->i.action. * prereset() may examine and modify it. */ - if (softreset && (!hardreset || (!(link->flags & ATA_LFLAG_NO_SRST) && + if (softreset && (!hardreset || (!(lflags & ATA_LFLAG_NO_SRST) && !sata_set_spd_needed(link) && !(ehc->i.action & ATA_EH_HARDRESET)))) tmp_action = ATA_EH_SOFTRESET; @@ -2161,80 +2130,62 @@ int ata_eh_reset(struct ata_link *link, int classify, "follow-up softreset required " "but no softreset avaliable\n"); rc = -EINVAL; - goto out; + goto fail; } ata_eh_about_to_do(link, NULL, ATA_EH_RESET_MASK); rc = ata_do_reset(link, reset, classes, deadline); - - if (rc == 0 && classify && classes[0] == ATA_DEV_UNKNOWN && - !(link->flags & ATA_LFLAG_ASSUME_CLASS)) { - ata_link_printk(link, KERN_ERR, - "classification failed\n"); - rc = -EINVAL; - goto out; - } } - /* if we skipped follow-up srst, clear rc */ - if (rc == -EAGAIN) - rc = 0; - - if (rc && rc != -ERESTART && try < ARRAY_SIZE(ata_eh_reset_timeouts)) { - unsigned long now = jiffies; - - if (time_before(now, deadline)) { - unsigned long delta = deadline - jiffies; - - ata_link_printk(link, KERN_WARNING, "reset failed " - "(errno=%d), retrying in %u secs\n", - rc, (jiffies_to_msecs(delta) + 999) / 1000); + /* -EAGAIN can happen if we skipped followup SRST */ + if (rc && rc != -EAGAIN) + goto fail; - while (delta) - delta = schedule_timeout_uninterruptible(delta); + /* was classification successful? */ + if (classify && classes[0] == ATA_DEV_UNKNOWN && + !(lflags & ATA_LFLAG_ASSUME_CLASS)) { + if (try < max_tries) { + ata_link_printk(link, KERN_WARNING, + "classification failed\n"); + rc = -EINVAL; + goto fail; } - if (rc == -EPIPE || - try == ARRAY_SIZE(ata_eh_reset_timeouts) - 1) - sata_down_spd_limit(link); - if (hardreset) - reset = hardreset; - goto retry; + ata_link_printk(link, KERN_WARNING, + "classfication failed, assuming ATA\n"); + lflags |= ATA_LFLAG_ASSUME_ATA; } - if (rc == 0) { - u32 sstatus; + ata_link_for_each_dev(dev, link) { + /* After the reset, the device state is PIO 0 and the + * controller state is undefined. Reset also wakes up + * drives from sleeping mode. + */ + dev->pio_mode = XFER_PIO_0; + dev->flags &= ~ATA_DFLAG_SLEEPING; - ata_link_for_each_dev(dev, link) { - /* After the reset, the device state is PIO 0 - * and the controller state is undefined. - * Record the mode. - */ - dev->pio_mode = XFER_PIO_0; + if (ata_link_offline(link)) + continue; - if (ata_link_offline(link)) - continue; + /* apply class override */ + if (lflags & ATA_LFLAG_ASSUME_ATA) + classes[dev->devno] = ATA_DEV_ATA; + else if (lflags & ATA_LFLAG_ASSUME_SEMB) + classes[dev->devno] = ATA_DEV_SEMB_UNSUP; /* not yet */ + } - /* apply class override and convert UNKNOWN to NONE */ - if (link->flags & ATA_LFLAG_ASSUME_ATA) - classes[dev->devno] = ATA_DEV_ATA; - else if (link->flags & ATA_LFLAG_ASSUME_SEMB) - classes[dev->devno] = ATA_DEV_SEMB_UNSUP; /* not yet */ - else if (classes[dev->devno] == ATA_DEV_UNKNOWN) - classes[dev->devno] = ATA_DEV_NONE; - } + /* record current link speed */ + if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0) + link->sata_spd = (sstatus >> 4) & 0xf; - /* record current link speed */ - if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0) - link->sata_spd = (sstatus >> 4) & 0xf; + if (postreset) + postreset(link, classes); - if (postreset) - postreset(link, classes); + /* reset successful, schedule revalidation */ + ata_eh_done(link, NULL, ehc->i.action & ATA_EH_RESET_MASK); + ehc->i.action |= ATA_EH_REVALIDATE; - /* reset successful, schedule revalidation */ - ata_eh_done(link, NULL, ehc->i.action & ATA_EH_RESET_MASK); - ehc->i.action |= ATA_EH_REVALIDATE; - } + rc = 0; out: /* clear hotplug flag */ ehc->i.flags &= ~ATA_EHI_HOTPLUGGED; @@ -2244,6 +2195,28 @@ int ata_eh_reset(struct ata_link *link, int classify, spin_unlock_irqrestore(ap->lock, flags); return rc; + + fail: + if (rc == -ERESTART || try >= max_tries) + goto out; + + now = jiffies; + if (time_before(now, deadline)) { + unsigned long delta = deadline - now; + + ata_link_printk(link, KERN_WARNING, "reset failed " + "(errno=%d), retrying in %u secs\n", + rc, (jiffies_to_msecs(delta) + 999) / 1000); + + while (delta) + delta = schedule_timeout_uninterruptible(delta); + } + + if (rc == -EPIPE || try == max_tries - 1) + sata_down_spd_limit(link); + if (hardreset) + reset = hardreset; + goto retry; } static int ata_eh_revalidate_and_attach(struct ata_link *link, @@ -2416,7 +2389,7 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err) /* give it just one more chance */ ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1); case -EIO: - if (ehc->tries[dev->devno] == 1) { + if (ehc->tries[dev->devno] == 1 && dev->pio_mode > XFER_PIO_0) { /* This is the last chance, better to slow * down than lose it. */ @@ -2607,6 +2580,10 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, ehc->i.flags &= ~ATA_EHI_SETMODE; } + if (ehc->i.action & ATA_EHI_LPM) + ata_link_for_each_dev(dev, link) + ata_dev_enable_pm(dev, ap->pm_policy); + /* this link is okay now */ ehc->i.flags = 0; continue; @@ -2672,8 +2649,15 @@ void ata_eh_finish(struct ata_port *ap) /* FIXME: Once EH migration is complete, * generate sense data in this function, * considering both err_mask and tf. + * + * There's no point in retrying invalid + * (detected by libata) and non-IO device + * errors (rejected by device). Finish them + * immediately. */ - if (qc->err_mask & AC_ERR_INVALID) + if ((qc->err_mask & AC_ERR_INVALID) || + (!(qc->flags & ATA_QCFLAG_IO) && + qc->err_mask == AC_ERR_DEV)) ata_eh_qc_complete(qc); else ata_eh_qc_retry(qc); diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c index c0c4dbcde09..caef2bbd4a8 100644 --- a/drivers/ata/libata-pmp.c +++ b/drivers/ata/libata-pmp.c @@ -495,14 +495,12 @@ static void sata_pmp_quirks(struct ata_port *ap) /* SError.N need a kick in the ass to get working */ link->flags |= ATA_LFLAG_HRST_TO_RESUME; - /* class code report is unreliable */ - if (link->pmp < 5) - link->flags |= ATA_LFLAG_ASSUME_ATA; - - /* The config device, which can be either at - * port 0 or 5, locks up on SRST. + /* Class code report is unreliable and SRST + * times out under certain configurations. + * Config device can be at port 0 or 5 and + * locks up on SRST. */ - if (link->pmp == 0 || link->pmp == 5) + if (link->pmp <= 5) link->flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA; diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index f5d5420a1ba..14daf4848f0 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -110,6 +110,74 @@ static struct scsi_transport_template ata_scsi_transport_template = { }; +static const struct { + enum link_pm value; + const char *name; +} link_pm_policy[] = { + { NOT_AVAILABLE, "max_performance" }, + { MIN_POWER, "min_power" }, + { MAX_PERFORMANCE, "max_performance" }, + { MEDIUM_POWER, "medium_power" }, +}; + +static const char *ata_scsi_lpm_get(enum link_pm policy) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(link_pm_policy); i++) + if (link_pm_policy[i].value == policy) + return link_pm_policy[i].name; + + return NULL; +} + +static ssize_t ata_scsi_lpm_put(struct class_device *class_dev, + const char *buf, size_t count) +{ + struct Scsi_Host *shost = class_to_shost(class_dev); + struct ata_port *ap = ata_shost_to_port(shost); + enum link_pm policy = 0; + int i; + + /* + * we are skipping array location 0 on purpose - this + * is because a value of NOT_AVAILABLE is displayed + * to the user as max_performance, but when the user + * writes "max_performance", they actually want the + * value to match MAX_PERFORMANCE. + */ + for (i = 1; i < ARRAY_SIZE(link_pm_policy); i++) { + const int len = strlen(link_pm_policy[i].name); + if (strncmp(link_pm_policy[i].name, buf, len) == 0 && + buf[len] == '\n') { + policy = link_pm_policy[i].value; + break; + } + } + if (!policy) + return -EINVAL; + + ata_lpm_schedule(ap, policy); + return count; +} + +static ssize_t +ata_scsi_lpm_show(struct class_device *class_dev, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(class_dev); + struct ata_port *ap = ata_shost_to_port(shost); + const char *policy = + ata_scsi_lpm_get(ap->pm_policy); + + if (!policy) + return -EINVAL; + + return snprintf(buf, 23, "%s\n", policy); +} +CLASS_DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR, + ata_scsi_lpm_show, ata_scsi_lpm_put); +EXPORT_SYMBOL_GPL(class_device_attr_link_power_management_policy); + static void ata_scsi_invalid_field(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { @@ -773,6 +841,12 @@ static void ata_scsi_dev_config(struct scsi_device *sdev, blk_queue_max_hw_segments(q, q->max_hw_segments - 1); } + if (dev->class == ATA_DEV_ATA) + sdev->manage_start_stop = 1; + + if (dev->flags & ATA_DFLAG_AN) + set_bit(SDEV_EVT_MEDIA_CHANGE, sdev->supported_events); + if (dev->flags & ATA_DFLAG_NCQ) { int depth; @@ -801,8 +875,6 @@ int ata_scsi_slave_config(struct scsi_device *sdev) ata_scsi_sdev_config(sdev); - sdev->manage_start_stop = 1; - if (dev) ata_scsi_dev_config(sdev, dev); @@ -1040,6 +1112,9 @@ static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc) else tf->command = ATA_CMD_FLUSH; + /* flush is critical for IO integrity, consider it an IO command */ + qc->flags |= ATA_QCFLAG_IO; + return 0; } @@ -1361,33 +1436,10 @@ nothing_to_do: static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - struct ata_eh_info *ehi = &qc->dev->link->eh_info; struct scsi_cmnd *cmd = qc->scsicmd; u8 *cdb = cmd->cmnd; int need_sense = (qc->err_mask != 0); - /* We snoop the SET_FEATURES - Write Cache ON/OFF command, and - * schedule EH_REVALIDATE operation to update the IDENTIFY DEVICE - * cache - */ - if (ap->ops->error_handler && !need_sense) { - switch (qc->tf.command) { - case ATA_CMD_SET_FEATURES: - if ((qc->tf.feature == SETFEATURES_WC_ON) || - (qc->tf.feature == SETFEATURES_WC_OFF)) { - ehi->action |= ATA_EH_REVALIDATE; - ata_port_schedule_eh(ap); - } - break; - - case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */ - case ATA_CMD_SET_MULTI: /* multi_count changed */ - ehi->action |= ATA_EH_REVALIDATE; - ata_port_schedule_eh(ap); - break; - } - } - /* For ATA pass thru (SAT) commands, generate a sense block if * user mandated it or if there's an error. Note that if we * generate because the user forced us to, a check condition @@ -2434,11 +2486,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); @@ -2719,8 +2800,8 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) */ qc->nbytes = scsi_bufflen(scmd); - /* request result TF */ - qc->flags |= ATA_QCFLAG_RESULT_TF; + /* request result TF and be quiet about device error */ + qc->flags |= ATA_QCFLAG_RESULT_TF | ATA_QCFLAG_QUIET; return 0; @@ -2818,7 +2899,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; @@ -3248,10 +3330,9 @@ static void ata_scsi_handle_link_detach(struct ata_link *link) */ void ata_scsi_media_change_notify(struct ata_device *dev) { -#ifdef OTHER_AN_PATCHES_HAVE_BEEN_APPLIED if (dev->sdev) - scsi_device_event_notify(dev->sdev, SDEV_MEDIA_CHANGE); -#endif + sdev_evt_send_simple(dev->sdev, SDEV_EVT_MEDIA_CHANGE, + GFP_ATOMIC); } /** diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 48acc09dab9..b7ac80b4b1f 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -806,7 +806,10 @@ int ata_pci_init_one(struct pci_dev *pdev, if (rc) goto err_out; - if (!legacy_mode) { + if (!legacy_mode && pdev->irq) { + /* We may have no IRQ assigned in which case we can poll. This + shouldn't happen on a sane system but robustness is cheap + in this case */ rc = devm_request_irq(dev, pdev->irq, pi->port_ops->irq_handler, IRQF_SHARED, DRV_NAME, host); if (rc) @@ -814,7 +817,7 @@ int ata_pci_init_one(struct pci_dev *pdev, ata_port_desc(host->ports[0], "irq %d", pdev->irq); ata_port_desc(host->ports[1], "irq %d", pdev->irq); - } else { + } else if (legacy_mode) { if (!ata_port_is_dummy(host->ports[0])) { rc = devm_request_irq(dev, ATA_PRIMARY_IRQ(pdev), pi->port_ops->irq_handler, diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 90df58a3edc..bbe59c2fd1e 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -101,20 +101,26 @@ extern int sata_link_init_spd(struct ata_link *link); extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg); extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg); extern struct ata_port *ata_port_alloc(struct ata_host *host); +extern void ata_dev_enable_pm(struct ata_device *dev, enum link_pm policy); +extern void ata_lpm_schedule(struct ata_port *ap, enum link_pm); /* libata-acpi.c */ #ifdef CONFIG_ATA_ACPI extern void ata_acpi_associate_sata_port(struct ata_port *ap); extern void ata_acpi_associate(struct ata_host *host); +extern void ata_acpi_dissociate(struct ata_host *host); extern int ata_acpi_on_suspend(struct ata_port *ap); extern void ata_acpi_on_resume(struct ata_port *ap); -extern int ata_acpi_on_devcfg(struct ata_device *adev); +extern int ata_acpi_on_devcfg(struct ata_device *dev); +extern void ata_acpi_on_disable(struct ata_device *dev); #else static inline void ata_acpi_associate_sata_port(struct ata_port *ap) { } static inline void ata_acpi_associate(struct ata_host *host) { } +static inline void ata_acpi_dissociate(struct ata_host *host) { } static inline int ata_acpi_on_suspend(struct ata_port *ap) { return 0; } static inline void ata_acpi_on_resume(struct ata_port *ap) { } -static inline int ata_acpi_on_devcfg(struct ata_device *adev) { return 0; } +static inline int ata_acpi_on_devcfg(struct ata_device *dev) { return 0; } +static inline void ata_acpi_on_disable(struct ata_device *dev) { } #endif /* libata-scsi.c */ diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c index 0f6f7bcc3de..e4542ab9c7f 100644 --- a/drivers/ata/pata_acpi.c +++ b/drivers/ata/pata_acpi.c @@ -181,7 +181,7 @@ static void pacpi_set_piomode(struct ata_port *ap, struct ata_device *adev) int unit = adev->devno; struct pata_acpi *acpi = ap->private_data; - if(!(acpi->gtm.flags & 0x10)) + if (!(acpi->gtm.flags & 0x10)) unit = 0; /* Now stuff the nS values into the structure */ @@ -202,7 +202,7 @@ static void pacpi_set_dmamode(struct ata_port *ap, struct ata_device *adev) int unit = adev->devno; struct pata_acpi *acpi = ap->private_data; - if(!(acpi->gtm.flags & 0x10)) + if (!(acpi->gtm.flags & 0x10)) unit = 0; /* Now stuff the nS values into the structure */ diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c index 364534e7aff..8caf9afc8b9 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_amd.c b/drivers/ata/pata_amd.c index c5779ad4abc..3cc27b51465 100644 --- a/drivers/ata/pata_amd.c +++ b/drivers/ata/pata_amd.c @@ -25,7 +25,7 @@ #include <linux/libata.h> #define DRV_NAME "pata_amd" -#define DRV_VERSION "0.3.9" +#define DRV_VERSION "0.3.10" /** * timing_setup - shared timing computation and load @@ -115,7 +115,8 @@ static void timing_setup(struct ata_port *ap, struct ata_device *adev, int offse } /* UDMA timing */ - pci_write_config_byte(pdev, offset + 0x10 + (3 - dn), t); + if (at.udma) + pci_write_config_byte(pdev, offset + 0x10 + (3 - dn), t); } /** diff --git a/drivers/ata/pata_at32.c b/drivers/ata/pata_at32.c index bb250a48e27..67e574de31e 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 b5e38426b81..7842cc48735 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,12 @@ 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 e61cb1fd57b..c79f066c2bc 100644 --- a/drivers/ata/pata_hpt37x.c +++ b/drivers/ata/pata_hpt37x.c @@ -295,7 +295,7 @@ static unsigned long hpt370_filter(struct ata_device *adev, unsigned long mask) static unsigned long hpt370a_filter(struct ata_device *adev, unsigned long mask) { - if (adev->class != ATA_DEV_ATA) { + if (adev->class == ATA_DEV_ATA) { if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5)) mask &= ~ (0x1F << ATA_SHIFT_UDMA); } @@ -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; @@ -359,28 +359,25 @@ static int hpt374_pre_reset(struct ata_link *link, unsigned long deadline) { 0x50, 1, 0x04, 0x04 }, { 0x54, 1, 0x04, 0x04 } }; - u16 mcr3, mcr6; + u16 mcr3; u8 ata66; struct ata_port *ap = link->ap; struct pci_dev *pdev = to_pci_dev(ap->host->dev); + unsigned int mcrbase = 0x50 + 4 * ap->port_no; if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no])) return -ENOENT; /* Do the extra channel work */ - pci_read_config_word(pdev, 0x52, &mcr3); - pci_read_config_word(pdev, 0x56, &mcr6); + pci_read_config_word(pdev, mcrbase + 2, &mcr3); /* Set bit 15 of 0x52 to enable TCBLID as input - Set bit 15 of 0x56 to enable FCBLID as input */ - pci_write_config_word(pdev, 0x52, mcr3 | 0x8000); - pci_write_config_word(pdev, 0x56, mcr6 | 0x8000); + pci_write_config_word(pdev, mcrbase + 2, mcr3 | 0x8000); pci_read_config_byte(pdev, 0x5A, &ata66); /* Reset TCBLID/FCBLID to output */ - pci_write_config_word(pdev, 0x52, mcr3); - pci_write_config_word(pdev, 0x56, mcr6); + pci_write_config_word(pdev, mcrbase + 2, mcr3); - if (ata66 & (1 << ap->port_no)) + if (ata66 & (2 >> ap->port_no)) ap->cbl = ATA_CBL_PATA40; else ap->cbl = ATA_CBL_PATA80; @@ -844,6 +841,25 @@ static int hpt37x_calibrate_dpll(struct pci_dev *dev) /* Never went stable */ return 0; } + +static u32 hpt374_read_freq(struct pci_dev *pdev) +{ + u32 freq; + unsigned long io_base = pci_resource_start(pdev, 4); + if (PCI_FUNC(pdev->devfn) & 1) { + struct pci_dev *pdev_0 = pci_get_slot(pdev->bus, pdev->devfn - 1); + /* Someone hot plugged the controller on us ? */ + if (pdev_0 == NULL) + return 0; + io_base = pci_resource_start(pdev_0, 4); + freq = inl(io_base + 0x90); + pci_dev_put(pdev_0); + } + else + freq = inl(io_base + 0x90); + return freq; +} + /** * hpt37x_init_one - Initialise an HPT37X/302 * @dev: PCI device @@ -902,7 +918,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) .flags = ATA_FLAG_SLAVE_POSS, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = 0x0f, + .udma_mask = ATA_UDMA5, .port_ops = &hpt370_port_ops }; /* HPT370A - UDMA100 */ @@ -911,7 +927,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) .flags = ATA_FLAG_SLAVE_POSS, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = 0x0f, + .udma_mask = ATA_UDMA5, .port_ops = &hpt370a_port_ops }; /* HPT371, 372 and friends - UDMA133 */ @@ -1047,9 +1063,16 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) outb(0x0e, iobase + 0x9c); /* Some devices do not let this value be accessed via PCI space - according to the old driver */ + according to the old driver. In addition we must use the value + from FN 0 on the HPT374 */ + + if (chip_table == &hpt374) { + freq = hpt374_read_freq(dev); + if (freq == 0) + return -ENODEV; + } else + freq = inl(iobase + 0x90); - freq = inl(iobase + 0x90); if ((freq >> 12) != 0xABCDE) { int i; u8 sr; diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c index 88ab0e1d353..4320e798632 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_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c index fcd532afbf2..120b5bfa7ce 100644 --- a/drivers/ata/pata_ixp4xx_cf.c +++ b/drivers/ata/pata_ixp4xx_cf.c @@ -130,10 +130,11 @@ static struct ata_port_operations ixp4xx_port_ops = { .port_start = ata_port_start, }; -static void ixp4xx_setup_port(struct ata_ioports *ioaddr, +static void ixp4xx_setup_port(struct ata_port *ap, struct ixp4xx_pata_data *data, unsigned long raw_cs0, unsigned long raw_cs1) { + struct ata_ioports *ioaddr = &ap->ioaddr; unsigned long raw_cmd = raw_cs0; unsigned long raw_ctl = raw_cs1 + 0x06; diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c index 225a7223a72..5b8174d9406 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_legacy.c b/drivers/ata/pata_legacy.c index 7bed8d80638..17159b5e1e4 100644 --- a/drivers/ata/pata_legacy.c +++ b/drivers/ata/pata_legacy.c @@ -271,14 +271,12 @@ static void pdc_data_xfer_vlb(struct ata_device *adev, unsigned char *buf, unsig ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); if (unlikely(slop)) { - u32 pad; + __le32 pad = 0; if (write_data) { memcpy(&pad, buf + buflen - slop, slop); - pad = le32_to_cpu(pad); - iowrite32(pad, ap->ioaddr.data_addr); + iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr); } else { - pad = ioread32(ap->ioaddr.data_addr); - pad = cpu_to_le16(pad); + pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr)); memcpy(buf + buflen - slop, &pad, slop); } } diff --git a/drivers/ata/pata_ns87415.c b/drivers/ata/pata_ns87415.c index b9a17eb100d..d0e2e50823b 100644 --- a/drivers/ata/pata_ns87415.c +++ b/drivers/ata/pata_ns87415.c @@ -215,6 +215,8 @@ static int ns87415_check_atapi_dma(struct ata_queued_cmd *qc) #include <asm/superio.h> +#define SUPERIO_IDE_MAX_RETRIES 25 + /** * ns87560_read_buggy - workaround buggy Super I/O chip * @port: Port to read diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c index 6b07b5b4853..f9b485a487a 100644 --- a/drivers/ata/pata_optidma.c +++ b/drivers/ata/pata_optidma.c @@ -449,7 +449,7 @@ static int optiplus_with_udma(struct pci_dev *pdev) /* Find function 1 */ dev1 = pci_get_device(0x1045, 0xC701, NULL); - if(dev1 == NULL) + if (dev1 == NULL) return 0; /* Rev must be >= 0x10 */ diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index 5db2013230b..fd36099428a 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c @@ -74,8 +74,7 @@ static int pcmcia_set_mode(struct ata_link *link, struct ata_device **r_failed_d return ata_do_set_mode(link, r_failed_dev); if (memcmp(master->id + ATA_ID_FW_REV, slave->id + ATA_ID_FW_REV, - ATA_ID_FW_REV_LEN + ATA_ID_PROD_LEN) == 0) - { + ATA_ID_FW_REV_LEN + ATA_ID_PROD_LEN) == 0) { /* Suspicious match, but could be two cards from the same vendor - check serial */ if (memcmp(master->id + ATA_ID_SERNO, slave->id + ATA_ID_SERNO, @@ -248,7 +247,8 @@ static int pcmcia_init_one(struct pcmcia_device *pdev) goto next_entry; io_base = pdev->io.BasePort1; ctl_base = pdev->io.BasePort1 + 0x0e; - } else goto next_entry; + } else + goto next_entry; /* If we've got this far, we're done */ break; } @@ -285,8 +285,8 @@ next_entry: printk(KERN_WARNING DRV_NAME ": second channel not yet supported.\n"); /* - * Having done the PCMCIA plumbing the ATA side is relatively - * sane. + * Having done the PCMCIA plumbing the ATA side is relatively + * sane. */ ret = -ENOMEM; host = ata_host_alloc(&pdev->dev, 1); @@ -363,7 +363,7 @@ static struct pcmcia_device_id pcmcia_devices[] = { PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */ PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d), PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000), /* Samsung */ - PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000), /* Hitachi */ + PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000), /* Hitachi */ PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001), PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0100), /* Viking CFA */ PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200), /* Lexar, Viking CFA */ diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c index 3d3f1558cde..2622577521a 100644 --- a/drivers/ata/pata_pdc2027x.c +++ b/drivers/ata/pata_pdc2027x.c @@ -348,7 +348,7 @@ static unsigned long pdc2027x_mode_filter(struct ata_device *adev, unsigned long ata_id_c_string(pair->id, model_num, ATA_ID_PROD, ATA_ID_PROD_LEN + 1); /* If the master is a maxtor in UDMA6 then the slave should not use UDMA 6 */ - if(strstr(model_num, "Maxtor") == 0 && pair->dma_mode == XFER_UDMA_6) + if (strstr(model_num, "Maxtor") == 0 && pair->dma_mode == XFER_UDMA_6) mask &= ~ (1 << (6 + ATA_SHIFT_UDMA)); return ata_pci_default_filter(adev, mask); diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c index 65d951618c6..8f281560179 100644 --- a/drivers/ata/pata_pdc202xx_old.c +++ b/drivers/ata/pata_pdc202xx_old.c @@ -215,8 +215,8 @@ static void pdc2026x_bmdma_stop(struct ata_queued_cmd *qc) /* Flip back to 33Mhz for PIO */ if (adev->dma_mode >= XFER_UDMA_2) iowrite8(ioread8(clock) & ~sel66, clock); - ata_bmdma_stop(qc); + pdc202xx_set_piomode(ap, adev); } /** @@ -233,6 +233,17 @@ static void pdc2026x_dev_config(struct ata_device *adev) adev->max_sectors = 256; } +static int pdc2026x_port_start(struct ata_port *ap) +{ + void __iomem *bmdma = ap->ioaddr.bmdma_addr; + if (bmdma) { + /* Enable burst mode */ + u8 burst = ioread8(bmdma + 0x1f); + iowrite8(burst | 0x01, bmdma + 0x1f); + } + return ata_sff_port_start(ap); +} + static struct scsi_host_template pdc202xx_sht = { .module = THIS_MODULE, .name = DRV_NAME, @@ -313,7 +324,7 @@ static struct ata_port_operations pdc2026x_port_ops = { .irq_clear = ata_bmdma_irq_clear, .irq_on = ata_irq_on, - .port_start = ata_sff_port_start, + .port_start = pdc2026x_port_start, }; static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id) @@ -351,9 +362,9 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id struct pci_dev *bridge = dev->bus->self; /* Don't grab anything behind a Promise I2O RAID */ if (bridge && bridge->vendor == PCI_VENDOR_ID_INTEL) { - if( bridge->device == PCI_DEVICE_ID_INTEL_I960) + if (bridge->device == PCI_DEVICE_ID_INTEL_I960) return -ENODEV; - if( bridge->device == PCI_DEVICE_ID_INTEL_I960RM) + if (bridge->device == PCI_DEVICE_ID_INTEL_I960RM) return -ENODEV; } } diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c index fc72a965643..ac03a90a616 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_qdi.c b/drivers/ata/pata_qdi.c index 7d4c696c4cb..a4c0e502cb4 100644 --- a/drivers/ata/pata_qdi.c +++ b/drivers/ata/pata_qdi.c @@ -136,14 +136,12 @@ static void qdi_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); if (unlikely(slop)) { - u32 pad; + __le32 pad = 0; if (write_data) { memcpy(&pad, buf + buflen - slop, slop); - pad = le32_to_cpu(pad); - iowrite32(pad, ap->ioaddr.data_addr); + iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr); } else { - pad = ioread32(ap->ioaddr.data_addr); - pad = cpu_to_le32(pad); + pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr)); memcpy(buf + buflen - slop, &pad, slop); } } diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c index 55576138fae..ea2ef9fc15b 100644 --- a/drivers/ata/pata_scc.c +++ b/drivers/ata/pata_scc.c @@ -570,17 +570,8 @@ static unsigned int scc_bus_softreset(struct ata_port *ap, unsigned int devmask, udelay(20); out_be32(ioaddr->ctl_addr, ap->ctl); - /* spec mandates ">= 2ms" before checking status. - * We wait 150ms, because that was the magic delay used for - * ATAPI devices in Hale Landis's ATADRVR, for the period of time - * between when the ATA command register is written, and then - * status is checked. Because waiting for "a while" before - * checking status is fine, post SRST, we perform this magic - * delay here as well. - * - * Old drivers/ide uses the 2mS rule and then waits for ready - */ - msleep(150); + /* wait a while before checking status */ + ata_wait_after_reset(ap, deadline); /* Before we perform post reset processing we want to see if * the bus shows 0xFF because the odd clown forgets the D7 diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c index df68806df4b..8bed8887372 100644 --- a/drivers/ata/pata_serverworks.c +++ b/drivers/ata/pata_serverworks.c @@ -274,28 +274,27 @@ static void serverworks_set_dmamode(struct ata_port *ap, struct ata_device *adev { static const u8 dma_mode[] = { 0x77, 0x21, 0x20 }; int offset = 1 + 2 * ap->port_no - adev->devno; - int devbits = (2 * ap->port_no + adev->devno); + int devbits = 2 * ap->port_no + adev->devno; u8 ultra; u8 ultra_cfg; struct pci_dev *pdev = to_pci_dev(ap->host->dev); pci_read_config_byte(pdev, 0x54, &ultra_cfg); + pci_read_config_byte(pdev, 0x56 + ap->port_no, &ultra); + ultra &= ~(0x0F << (adev->devno * 4)); if (adev->dma_mode >= XFER_UDMA_0) { pci_write_config_byte(pdev, 0x44 + offset, 0x20); - pci_read_config_byte(pdev, 0x56 + ap->port_no, &ultra); - ultra &= ~(0x0F << (ap->port_no * 4)); ultra |= (adev->dma_mode - XFER_UDMA_0) - << (ap->port_no * 4); - pci_write_config_byte(pdev, 0x56 + ap->port_no, ultra); - + << (adev->devno * 4); ultra_cfg |= (1 << devbits); } else { pci_write_config_byte(pdev, 0x44 + offset, dma_mode[adev->dma_mode - XFER_MW_DMA_0]); ultra_cfg &= ~(1 << devbits); } + pci_write_config_byte(pdev, 0x56 + ap->port_no, ultra); pci_write_config_byte(pdev, 0x54, ultra_cfg); } diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c index 5c1e9cb59ec..503245a1eaf 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 3b5be77e861..87546d9f1ca 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/pata_via.c b/drivers/ata/pata_via.c index ea7a9a652e6..453d72bf259 100644 --- a/drivers/ata/pata_via.c +++ b/drivers/ata/pata_via.c @@ -63,7 +63,7 @@ #include <linux/dmi.h> #define DRV_NAME "pata_via" -#define DRV_VERSION "0.3.2" +#define DRV_VERSION "0.3.3" /* * The following comes directly from Vojtech Pavlik's ide/pci/via82cxxx @@ -176,7 +176,7 @@ static int via_cable_detect(struct ata_port *ap) { if ((config->flags & VIA_UDMA) < VIA_UDMA_66) return ATA_CBL_PATA40; /* UDMA 66 chips have only drive side logic */ - else if((config->flags & VIA_UDMA) < VIA_UDMA_100) + else if ((config->flags & VIA_UDMA) < VIA_UDMA_100) return ATA_CBL_PATA_UNK; /* UDMA 100 or later */ pci_read_config_dword(pdev, 0x50, &ata66); @@ -296,7 +296,7 @@ static void via_do_set_mode(struct ata_port *ap, struct ata_device *adev, int mo } /* Set UDMA unless device is not UDMA capable */ - if (udma_type) { + if (udma_type && t.udma) { u8 cable80_status; /* Get 80-wire cable detection bit */ diff --git a/drivers/ata/pata_winbond.c b/drivers/ata/pata_winbond.c index 549cbbe9fd0..7116a9e7a8b 100644 --- a/drivers/ata/pata_winbond.c +++ b/drivers/ata/pata_winbond.c @@ -104,14 +104,12 @@ static void winbond_data_xfer(struct ata_device *adev, unsigned char *buf, unsig ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); if (unlikely(slop)) { - u32 pad; + __le32 pad = 0; if (write_data) { memcpy(&pad, buf + buflen - slop, slop); - pad = le32_to_cpu(pad); - iowrite32(pad, ap->ioaddr.data_addr); + iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr); } else { - pad = ioread32(ap->ioaddr.data_addr); - pad = cpu_to_le16(pad); + pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr)); memcpy(buf + buflen - slop, &pad, slop); } } @@ -279,7 +277,7 @@ static __init int winbond_init(void) if (request_region(port, 2, "pata_winbond")) { ret = winbond_init_one(port); - if(ret <= 0) + if (ret <= 0) release_region(port, 2); else ct+= ret; } diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c index 199f7e150eb..bd4c2a3c88d 100644 --- a/drivers/ata/pdc_adma.c +++ b/drivers/ata/pdc_adma.c @@ -47,10 +47,10 @@ #define DRV_VERSION "1.0" /* macro to calculate base address for ATA regs */ -#define ADMA_ATA_REGS(base,port_no) ((base) + ((port_no) * 0x40)) +#define ADMA_ATA_REGS(base, port_no) ((base) + ((port_no) * 0x40)) /* macro to calculate base address for ADMA regs */ -#define ADMA_REGS(base,port_no) ((base) + 0x80 + ((port_no) * 0x20)) +#define ADMA_REGS(base, port_no) ((base) + 0x80 + ((port_no) * 0x20)) /* macro to obtain addresses from ata_port */ #define ADMA_PORT_REGS(ap) \ @@ -128,7 +128,7 @@ struct adma_port_priv { adma_state_t state; }; -static int adma_ata_init_one (struct pci_dev *pdev, +static int adma_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); static int adma_port_start(struct ata_port *ap); static void adma_host_stop(struct ata_host *host); @@ -340,8 +340,8 @@ static int adma_fill_sg(struct ata_queued_cmd *qc) buf[i++] = 0; /* pPKLW */ buf[i++] = 0; /* reserved */ - *(__le32 *)(buf + i) - = (pFLAGS & pEND) ? 0 : cpu_to_le32(pp->pkt_dma + i + 4); + *(__le32 *)(buf + i) = + (pFLAGS & pEND) ? 0 : cpu_to_le32(pp->pkt_dma + i + 4); i += 4; VPRINTK("PRD[%u] = (0x%lX, 0x%X)\n", i/4, @@ -617,7 +617,7 @@ static int adma_port_start(struct ata_port *ap) return -ENOMEM; /* paranoia? */ if ((pp->pkt_dma & 7) != 0) { - printk("bad alignment for pp->pkt_dma: %08x\n", + printk(KERN_ERR "bad alignment for pp->pkt_dma: %08x\n", (u32)pp->pkt_dma); return -ENOMEM; } diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index b4c37b9e413..d015b4adcfe 100644 --- a/drivers/ata/sata_fsl.c +++ b/drivers/ata/sata_fsl.c @@ -34,7 +34,8 @@ enum { SATA_FSL_HOST_FLAGS = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | - ATA_FLAG_NCQ | ATA_FLAG_SKIP_D2H_BSY), + ATA_FLAG_NCQ), + SATA_FSL_HOST_LFLAGS = ATA_LFLAG_SKIP_D2H_BSY, SATA_FSL_MAX_CMDS = SATA_FSL_QUEUE_DEPTH, SATA_FSL_CMD_HDR_SIZE = 16, /* 4 DWORDS */ @@ -264,10 +265,11 @@ struct sata_fsl_host_priv { void __iomem *hcr_base; void __iomem *ssr_base; void __iomem *csr_base; + int irq; }; static inline unsigned int sata_fsl_tag(unsigned int tag, - void __iomem * hcr_base) + void __iomem *hcr_base) { /* We let libATA core do actual (queue) tag allocation */ @@ -306,7 +308,7 @@ static void sata_fsl_setup_cmd_hdr_entry(struct sata_fsl_port_priv *pp, pp->cmdslot[tag].prde_fis_len = cpu_to_le32((num_prde << 16) | (fis_len << 2)); pp->cmdslot[tag].ttl = cpu_to_le32(data_xfer_len & ~0x03); - pp->cmdslot[tag].desc_info = cpu_to_le32((desc_info | (tag & 0x1F))); + pp->cmdslot[tag].desc_info = cpu_to_le32(desc_info | (tag & 0x1F)); VPRINTK("cda=0x%x, prde_fis_len=0x%x, ttl=0x%x, di=0x%x\n", pp->cmdslot[tag].cda, @@ -316,7 +318,7 @@ static void sata_fsl_setup_cmd_hdr_entry(struct sata_fsl_port_priv *pp, } static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc, - u32 * ttl, dma_addr_t cmd_desc_paddr) + u32 *ttl, dma_addr_t cmd_desc_paddr) { struct scatterlist *sg; unsigned int num_prde = 0; @@ -353,7 +355,7 @@ static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc, "s/g len unaligned : 0x%x\n", sg_len); if ((num_prde == (SATA_FSL_MAX_PRD_DIRECT - 1)) && - !ata_sg_is_last(sg, qc)) { + (qc->n_iter + 1 != qc->n_elem)) { VPRINTK("setting indirect prde\n"); prd_ptr_to_indirect_ext = prd; prd->dba = cpu_to_le32(indirect_ext_segment_paddr); @@ -404,7 +406,7 @@ static void sata_fsl_qc_prep(struct ata_queued_cmd *qc) cd = (struct command_desc *)pp->cmdentry + tag; cd_paddr = pp->cmdentry_paddr + tag * SATA_FSL_CMD_DESC_SIZE; - ata_tf_to_fis(&qc->tf, 0, 1, (u8 *) & cd->cfis); + ata_tf_to_fis(&qc->tf, 0, 1, (u8 *) &cd->cfis); VPRINTK("Dumping cfis : 0x%x, 0x%x, 0x%x\n", cd->cfis[0], cd->cfis[1], cd->cfis[2]); @@ -470,16 +472,10 @@ static int sata_fsl_scr_write(struct ata_port *ap, unsigned int sc_reg_in, switch (sc_reg_in) { case SCR_STATUS: - sc_reg = 0; - break; case SCR_ERROR: - sc_reg = 1; - break; case SCR_CONTROL: - sc_reg = 2; - break; case SCR_ACTIVE: - sc_reg = 3; + sc_reg = sc_reg_in; break; default: return -EINVAL; @@ -487,7 +483,7 @@ static int sata_fsl_scr_write(struct ata_port *ap, unsigned int sc_reg_in, VPRINTK("xx_scr_write, reg_in = %d\n", sc_reg); - iowrite32(val, (void __iomem *)ssr_base + (sc_reg * 4)); + iowrite32(val, ssr_base + (sc_reg * 4)); return 0; } @@ -500,16 +496,10 @@ static int sata_fsl_scr_read(struct ata_port *ap, unsigned int sc_reg_in, switch (sc_reg_in) { case SCR_STATUS: - sc_reg = 0; - break; case SCR_ERROR: - sc_reg = 1; - break; case SCR_CONTROL: - sc_reg = 2; - break; case SCR_ACTIVE: - sc_reg = 3; + sc_reg = sc_reg_in; break; default: return -EINVAL; @@ -517,7 +507,7 @@ static int sata_fsl_scr_read(struct ata_port *ap, unsigned int sc_reg_in, VPRINTK("xx_scr_read, reg_in = %d\n", sc_reg); - *val = ioread32((void __iomem *)ssr_base + (sc_reg * 4)); + *val = ioread32(ssr_base + (sc_reg * 4)); return 0; } @@ -571,7 +561,6 @@ static inline void sata_fsl_cache_taskfile_from_d2h_fis(struct ata_queued_cmd struct ata_port *ap) { struct sata_fsl_port_priv *pp = ap->private_data; - u8 fis[6 * 4]; struct sata_fsl_host_priv *host_priv = ap->host->private_data; void __iomem *hcr_base = host_priv->hcr_base; unsigned int tag = sata_fsl_tag(qc->tag, hcr_base); @@ -579,8 +568,7 @@ static inline void sata_fsl_cache_taskfile_from_d2h_fis(struct ata_queued_cmd cd = pp->cmdentry + tag; - memcpy(fis, &cd->sfis, 6 * 4); /* should we use memcpy_from_io() */ - ata_tf_from_fis(fis, &pp->tf); + ata_tf_from_fis(cd->sfis, &pp->tf); } static u8 sata_fsl_check_status(struct ata_port *ap) @@ -664,6 +652,7 @@ static int sata_fsl_port_start(struct ata_port *ap) VPRINTK("HControl = 0x%x\n", ioread32(hcr_base + HCONTROL)); VPRINTK("CHBA = 0x%x\n", ioread32(hcr_base + CHBA)); +#ifdef CONFIG_MPC8315_DS /* * Workaround for 8315DS board 3gbps link-up issue, * currently limit SATA port to GEN1 speed @@ -676,6 +665,7 @@ static int sata_fsl_port_start(struct ata_port *ap) sata_fsl_scr_read(ap, SCR_CONTROL, &temp); dev_printk(KERN_WARNING, dev, "scr_control, speed limited to %x\n", temp); +#endif return 0; } @@ -728,9 +718,10 @@ static unsigned int sata_fsl_dev_classify(struct ata_port *ap) return ata_dev_classify(&tf); } -static int sata_fsl_softreset(struct ata_port *ap, unsigned int *class, +static int sata_fsl_softreset(struct ata_link *link, unsigned int *class, unsigned long deadline) { + struct ata_port *ap = link->ap; struct sata_fsl_port_priv *pp = ap->private_data; struct sata_fsl_host_priv *host_priv = ap->host->private_data; void __iomem *hcr_base = host_priv->hcr_base; @@ -739,10 +730,6 @@ static int sata_fsl_softreset(struct ata_port *ap, unsigned int *class, u8 *cfis; u32 Serror; int i = 0; - struct ata_queued_cmd qc; - u8 *buf; - dma_addr_t dma_address; - struct scatterlist *sg; unsigned long start_jiffies; DPRINTK("in xx_softreset\n"); @@ -811,7 +798,7 @@ try_offline_again: */ temp = ata_wait_register(hcr_base + HSTATUS, 0xFF, 0, 1, 500); - if ((!(temp & 0x10)) || ata_port_offline(ap)) { + if ((!(temp & 0x10)) || ata_link_offline(link)) { ata_port_printk(ap, KERN_WARNING, "No Device OR PHYRDY change,Hstatus = 0x%x\n", ioread32(hcr_base + HSTATUS)); @@ -842,13 +829,10 @@ try_offline_again: * reached here, we can send a command to the target device */ - if (ap->sactive) - goto skip_srst_do_ncq_error_handling; - DPRINTK("Sending SRST/device reset\n"); - ata_tf_init(ap->device, &tf); - cfis = (u8 *) & pp->cmdentry->cfis; + ata_tf_init(link->device, &tf); + cfis = (u8 *) &pp->cmdentry->cfis; /* device reset/SRST is a control register update FIS, uses tag0 */ sata_fsl_setup_cmd_hdr_entry(pp, 0, @@ -912,76 +896,13 @@ try_offline_again: * command bit of the CCreg */ iowrite32(0x01, CC + hcr_base); /* We know it will be cmd#0 always */ - goto check_device_signature; - -skip_srst_do_ncq_error_handling: - - VPRINTK("Sending read log ext(10h) command\n"); - - memset(&qc, 0, sizeof(struct ata_queued_cmd)); - ata_tf_init(ap->device, &tf); - - tf.command = ATA_CMD_READ_LOG_EXT; - tf.lbal = ATA_LOG_SATA_NCQ; - tf.nsect = 1; - tf.hob_nsect = 0; - tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_LBA48 | ATA_TFLAG_DEVICE; - tf.protocol = ATA_PROT_PIO; - - qc.tag = ATA_TAG_INTERNAL; - qc.scsicmd = NULL; - qc.ap = ap; - qc.dev = ap->device; - - qc.tf = tf; - qc.flags |= ATA_QCFLAG_RESULT_TF; - qc.dma_dir = DMA_FROM_DEVICE; - - buf = ap->sector_buf; - ata_sg_init_one(&qc, buf, 1 * ATA_SECT_SIZE); - - /* - * Need to DMA-map the memory buffer associated with the command - */ - - sg = qc.__sg; - dma_address = dma_map_single(ap->dev, qc.buf_virt, - sg->length, DMA_FROM_DEVICE); - - sg_dma_address(sg) = dma_address; - sg_dma_len(sg) = sg->length; - - VPRINTK("EH, addr = 0x%x, len = 0x%x\n", dma_address, sg->length); - - sata_fsl_qc_prep(&qc); - sata_fsl_qc_issue(&qc); - - temp = ata_wait_register(CQ + hcr_base, 0x1, 0x1, 1, 5000); - if (temp & 0x1) { - VPRINTK("READ_LOG_EXT_10H issue failed\n"); - - VPRINTK("READ_LOG@5000,CQ=0x%x,CA=0x%x,CC=0x%x\n", - ioread32(CQ + hcr_base), - ioread32(CA + hcr_base), ioread32(CC + hcr_base)); - - sata_fsl_scr_read(ap, SCR_ERROR, &Serror); - - VPRINTK("HStatus = 0x%x\n", ioread32(hcr_base + HSTATUS)); - VPRINTK("HControl = 0x%x\n", ioread32(hcr_base + HCONTROL)); - VPRINTK("Serror = 0x%x\n", Serror); - goto err; - } - - iowrite32(0x01, CC + hcr_base); /* We know it will be cmd#0 always */ - - check_device_signature: DPRINTK("SATA FSL : Now checking device signature\n"); *class = ATA_DEV_NONE; /* Verify if SStatus indicates device presence */ - if (ata_port_online(ap)) { + if (ata_link_online(link)) { /* * if we are here, device presence has been detected, * 1st D2H FIS would have been received, but sfis in @@ -1002,25 +923,13 @@ err: return -EIO; } -static int sata_fsl_hardreset(struct ata_port *ap, unsigned int *class, - unsigned long deadline) -{ - int retval; - - retval = sata_std_hardreset(ap, class, deadline); - - DPRINTK("SATA FSL : in xx_hardreset, retval = 0x%d\n", retval); - - return retval; -} - static void sata_fsl_error_handler(struct ata_port *ap) { DPRINTK("in xx_error_handler\n"); /* perform recovery */ - ata_do_eh(ap, ata_std_prereset, sata_fsl_softreset, sata_fsl_hardreset, + ata_do_eh(ap, ata_std_prereset, sata_fsl_softreset, sata_std_hardreset, ata_std_postreset); } @@ -1042,7 +951,8 @@ static void sata_fsl_irq_clear(struct ata_port *ap) static void sata_fsl_error_intr(struct ata_port *ap) { - struct ata_eh_info *ehi = &ap->eh_info; + struct ata_link *link = &ap->link; + struct ata_eh_info *ehi = &link->eh_info; struct sata_fsl_host_priv *host_priv = ap->host->private_data; void __iomem *hcr_base = host_priv->hcr_base; u32 hstatus, dereg, cereg = 0, SError = 0; @@ -1111,7 +1021,7 @@ static void sata_fsl_error_intr(struct ata_port *ap) } /* record error info */ - qc = ata_qc_from_tag(ap, ap->active_tag); + qc = ata_qc_from_tag(ap, link->active_tag); if (qc) { sata_fsl_cache_taskfile_from_d2h_fis(qc, qc->ap); @@ -1139,6 +1049,7 @@ static void sata_fsl_qc_complete(struct ata_queued_cmd *qc) static void sata_fsl_host_intr(struct ata_port *ap) { + struct ata_link *link = &ap->link; struct sata_fsl_host_priv *host_priv = ap->host->private_data; void __iomem *hcr_base = host_priv->hcr_base; u32 hstatus, qc_active = 0; @@ -1161,7 +1072,7 @@ static void sata_fsl_host_intr(struct ata_port *ap) return; } - if (ap->sactive) { /* only true for NCQ commands */ + if (link->sactive) { /* only true for NCQ commands */ int i; /* Read command completed register */ qc_active = ioread32(hcr_base + CC); @@ -1190,10 +1101,10 @@ static void sata_fsl_host_intr(struct ata_port *ap) } else if (ap->qc_active) { iowrite32(1, hcr_base + CC); - qc = ata_qc_from_tag(ap, ap->active_tag); + qc = ata_qc_from_tag(ap, link->active_tag); DPRINTK("completing non-ncq cmd, tag=%d,CC=0x%x\n", - ap->active_tag, ioread32(hcr_base + CC)); + link->active_tag, ioread32(hcr_base + CC)); if (qc) { sata_fsl_qc_complete(qc); @@ -1312,15 +1223,9 @@ static struct scsi_host_template sata_fsl_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .suspend = ata_scsi_device_suspend, - .resume = ata_scsi_device_resume, -#endif }; static const struct ata_port_operations sata_fsl_ops = { - .port_disable = ata_port_disable, - .check_status = sata_fsl_check_status, .check_altstatus = sata_fsl_check_status, .dev_select = ata_noop_dev_select, @@ -1330,8 +1235,6 @@ static const struct ata_port_operations sata_fsl_ops = { .qc_prep = sata_fsl_qc_prep, .qc_issue = sata_fsl_qc_issue, .irq_clear = sata_fsl_irq_clear, - .irq_on = ata_dummy_irq_on, - .irq_ack = ata_dummy_irq_ack, .scr_read = sata_fsl_scr_read, .scr_write = sata_fsl_scr_write, @@ -1348,6 +1251,7 @@ static const struct ata_port_operations sata_fsl_ops = { static const struct ata_port_info sata_fsl_port_info[] = { { .flags = SATA_FSL_HOST_FLAGS, + .link_flags = SATA_FSL_HOST_LFLAGS, .pio_mask = 0x1f, /* pio 0-4 */ .udma_mask = 0x7f, /* udma 0-6 */ .port_ops = &sata_fsl_ops, @@ -1398,6 +1302,7 @@ static int sata_fsl_probe(struct of_device *ofdev, dev_printk(KERN_ERR, &ofdev->dev, "invalid irq from platform\n"); goto error_exit_with_cleanup; } + host_priv->irq = irq; /* allocate host structure */ host = ata_host_alloc_pinfo(&ofdev->dev, ppi, SATA_FSL_MAX_PORTS); @@ -1444,7 +1349,7 @@ static int sata_fsl_remove(struct of_device *ofdev) dev_set_drvdata(&ofdev->dev, NULL); - irq_dispose_mapping(host->irq); + irq_dispose_mapping(host_priv->irq); iounmap(host_priv->hcr_base); kfree(host_priv); diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c index 08595f34b3e..323c087e8cc 100644 --- a/drivers/ata/sata_inic162x.c +++ b/drivers/ata/sata_inic162x.c @@ -143,7 +143,7 @@ static const int scr_map[] = { [SCR_CONTROL] = 2, }; -static void __iomem * inic_port_base(struct ata_port *ap) +static void __iomem *inic_port_base(struct ata_port *ap) { return ap->host->iomap[MMIO_BAR] + ap->port_no * PORT_SIZE; } @@ -448,7 +448,7 @@ static int inic_hardreset(struct ata_link *link, unsigned int *class, struct ata_taskfile tf; /* wait a while before checking status */ - msleep(150); + ata_wait_after_reset(ap, deadline); rc = ata_wait_ready(ap, deadline); /* link occupied, -ENODEV too is an error */ diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index b39648f0914..37b850ae084 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 */ }; @@ -1156,7 +1165,7 @@ static void mv_fill_sg(struct ata_queued_cmd *qc) last_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL); } -static inline void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last) +static void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last) { u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS | (last ? CRQB_CMD_LAST : 0); @@ -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 @@ -2429,7 +2441,7 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx) struct mv_host_priv *hpriv = host->private_data; u32 hp_flags = hpriv->hp_flags; - switch(board_idx) { + switch (board_idx) { case chip_5080: hpriv->ops = &mv5xxx_ops; hp_flags |= MV_HP_GEN_I; @@ -2490,6 +2502,36 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx) break; case chip_7042: + hp_flags |= MV_HP_PCIE; + if (pdev->vendor == PCI_VENDOR_ID_TTI && + (pdev->device == 0x2300 || pdev->device == 0x2310)) + { + /* + * Highpoint RocketRAID PCIe 23xx series cards: + * + * Unconfigured drives are treated as "Legacy" + * by the BIOS, and it overwrites sector 8 with + * a "Lgcy" metadata block prior to Linux boot. + * + * Configured drives (RAID or JBOD) leave sector 8 + * alone, but instead overwrite a high numbered + * sector for the RAID metadata. This sector can + * be determined exactly, by truncating the physical + * drive capacity to a nice even GB value. + * + * RAID metadata is at: (dev->n_sectors & ~0xfffff) + * + * Warn the user, lest they think we're just buggy. + */ + printk(KERN_WARNING DRV_NAME ": Highpoint RocketRAID" + " BIOS CORRUPTS DATA on all attached drives," + " regardless of if/how they are configured." + " BEWARE!\n"); + printk(KERN_WARNING DRV_NAME ": For data safety, do not" + " use sectors 8-9 on \"Legacy\" drives," + " and avoid the final two gigabytes on" + " all RocketRAID BIOS initialized drives.\n"); + } case chip_6042: hpriv->ops = &mv6xxx_ops; hp_flags |= MV_HP_GEN_IIE; @@ -2510,11 +2552,21 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx) break; default: - printk(KERN_ERR DRV_NAME ": BUG: invalid board index %u\n", board_idx); + dev_printk(KERN_ERR, &pdev->dev, + "BUG: invalid board index %u\n", board_idx); return 1; } 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; } @@ -2594,10 +2646,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); @@ -2608,8 +2660,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 f1b422f7c74..ed5dc7cb50c 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -291,7 +291,7 @@ struct nv_swncq_port_priv { }; -#define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & ( 1 << (19 + (12 * (PORT))))) +#define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & (1 << (19 + (12 * (PORT))))) static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); #ifdef CONFIG_PM @@ -791,11 +791,13 @@ static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc) static void nv_adma_tf_read(struct ata_port *ap, struct ata_taskfile *tf) { - /* Since commands where a result TF is requested are not - executed in ADMA mode, the only time this function will be called - in ADMA mode will be if a command fails. In this case we - don't care about going into register mode with ADMA commands - pending, as the commands will all shortly be aborted anyway. */ + /* Other than when internal or pass-through commands are executed, + the only time this function will be called in ADMA mode will be + if a command fails. In the failure case we don't care about going + into register mode with ADMA commands pending, as the commands will + all shortly be aborted anyway. We assume that NCQ commands are not + issued via passthrough, which is the only way that switching into + ADMA mode could abort outstanding commands. */ nv_adma_register_mode(ap); ata_tf_read(ap, tf); @@ -884,8 +886,9 @@ static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err) /* Notifier bits set without a command may indicate the drive is misbehaving. Raise host state machine violation on this condition. */ - ata_port_printk(ap, KERN_ERR, "notifier for tag %d with no command?\n", - cpb_num); + ata_port_printk(ap, KERN_ERR, + "notifier for tag %d with no cmd?\n", + cpb_num); ehi->err_mask |= AC_ERR_HSM; ehi->action |= ATA_EH_SOFTRESET; ata_port_freeze(ap); @@ -1012,7 +1015,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) u32 check_commands; int pos, error = 0; - if(ata_tag_valid(ap->link.active_tag)) + if (ata_tag_valid(ap->link.active_tag)) check_commands = 1 << ap->link.active_tag; else check_commands = ap->link.sactive; @@ -1021,14 +1024,14 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) while ((pos = ffs(check_commands)) && !error) { pos--; error = nv_adma_check_cpb(ap, pos, - notifier_error & (1 << pos) ); - check_commands &= ~(1 << pos ); + notifier_error & (1 << pos)); + check_commands &= ~(1 << pos); } } } } - if(notifier_clears[0] || notifier_clears[1]) { + if (notifier_clears[0] || notifier_clears[1]) { /* Note: Both notifier clear registers must be written if either is set, even if one is zero, according to NVIDIA. */ struct nv_adma_port_priv *pp = host->ports[0]->private_data; @@ -1061,7 +1064,7 @@ static void nv_adma_freeze(struct ata_port *ap) tmp = readw(mmio + NV_ADMA_CTL); writew(tmp & ~(NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN), mmio + NV_ADMA_CTL); - readw(mmio + NV_ADMA_CTL ); /* flush posted write */ + readw(mmio + NV_ADMA_CTL); /* flush posted write */ } static void nv_adma_thaw(struct ata_port *ap) @@ -1079,7 +1082,7 @@ static void nv_adma_thaw(struct ata_port *ap) tmp = readw(mmio + NV_ADMA_CTL); writew(tmp | (NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN), mmio + NV_ADMA_CTL); - readw(mmio + NV_ADMA_CTL ); /* flush posted write */ + readw(mmio + NV_ADMA_CTL); /* flush posted write */ } static void nv_adma_irq_clear(struct ata_port *ap) @@ -1119,7 +1122,7 @@ static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc) { struct nv_adma_port_priv *pp = qc->ap->private_data; - if(pp->flags & NV_ADMA_PORT_REGISTER_MODE) + if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) ata_bmdma_post_internal_cmd(qc); } @@ -1165,7 +1168,7 @@ static int nv_adma_port_start(struct ata_port *ap) pp->cpb_dma = mem_dma; writel(mem_dma & 0xFFFFFFFF, mmio + NV_ADMA_CPB_BASE_LOW); - writel((mem_dma >> 16 ) >> 16, mmio + NV_ADMA_CPB_BASE_HIGH); + writel((mem_dma >> 16) >> 16, mmio + NV_ADMA_CPB_BASE_HIGH); mem += NV_ADMA_MAX_CPBS * NV_ADMA_CPB_SZ; mem_dma += NV_ADMA_MAX_CPBS * NV_ADMA_CPB_SZ; @@ -1189,15 +1192,15 @@ static int nv_adma_port_start(struct ata_port *ap) /* clear GO for register mode, enable interrupt */ tmp = readw(mmio + NV_ADMA_CTL); - writew( (tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN | - NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL); + writew((tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN | + NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL); tmp = readw(mmio + NV_ADMA_CTL); writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); - readw( mmio + NV_ADMA_CTL ); /* flush posted write */ + readw(mmio + NV_ADMA_CTL); /* flush posted write */ udelay(1); writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); - readw( mmio + NV_ADMA_CTL ); /* flush posted write */ + readw(mmio + NV_ADMA_CTL); /* flush posted write */ return 0; } @@ -1237,7 +1240,7 @@ static int nv_adma_port_resume(struct ata_port *ap) /* set CPB block location */ writel(pp->cpb_dma & 0xFFFFFFFF, mmio + NV_ADMA_CPB_BASE_LOW); - writel((pp->cpb_dma >> 16 ) >> 16, mmio + NV_ADMA_CPB_BASE_HIGH); + writel((pp->cpb_dma >> 16) >> 16, mmio + NV_ADMA_CPB_BASE_HIGH); /* clear any outstanding interrupt conditions */ writew(0xffff, mmio + NV_ADMA_STAT); @@ -1250,15 +1253,15 @@ static int nv_adma_port_resume(struct ata_port *ap) /* clear GO for register mode, enable interrupt */ tmp = readw(mmio + NV_ADMA_CTL); - writew( (tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN | - NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL); + writew((tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN | + NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL); tmp = readw(mmio + NV_ADMA_CTL); writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); - readw( mmio + NV_ADMA_CTL ); /* flush posted write */ + readw(mmio + NV_ADMA_CTL); /* flush posted write */ udelay(1); writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); - readw( mmio + NV_ADMA_CTL ); /* flush posted write */ + readw(mmio + NV_ADMA_CTL); /* flush posted write */ return 0; } @@ -1342,7 +1345,8 @@ static void nv_adma_fill_sg(struct ata_queued_cmd *qc, struct nv_adma_cpb *cpb) idx = 0; ata_for_each_sg(sg, qc) { - aprd = (idx < 5) ? &cpb->aprd[idx] : &pp->aprd[NV_ADMA_SGTBL_LEN * qc->tag + (idx-5)]; + aprd = (idx < 5) ? &cpb->aprd[idx] : + &pp->aprd[NV_ADMA_SGTBL_LEN * qc->tag + (idx-5)]; nv_adma_fill_aprd(qc, sg, idx, aprd); idx++; } @@ -1357,14 +1361,12 @@ static int nv_adma_use_reg_mode(struct ata_queued_cmd *qc) struct nv_adma_port_priv *pp = qc->ap->private_data; /* ADMA engine can only be used for non-ATAPI DMA commands, - or interrupt-driven no-data commands, where a result taskfile - is not required. */ - if((pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) || - (qc->tf.flags & ATA_TFLAG_POLLING) || - (qc->flags & ATA_QCFLAG_RESULT_TF)) + or interrupt-driven no-data commands. */ + if ((pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) || + (qc->tf.flags & ATA_TFLAG_POLLING)) return 1; - if((qc->flags & ATA_QCFLAG_DMAMAP) || + if ((qc->flags & ATA_QCFLAG_DMAMAP) || (qc->tf.protocol == ATA_PROT_NODATA)) return 0; @@ -1379,6 +1381,8 @@ static void nv_adma_qc_prep(struct ata_queued_cmd *qc) NV_CPB_CTL_IEN; if (nv_adma_use_reg_mode(qc)) { + BUG_ON(!(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) && + (qc->flags & ATA_QCFLAG_DMAMAP)); nv_adma_register_mode(qc->ap); ata_qc_prep(qc); return; @@ -1401,14 +1405,14 @@ static void nv_adma_qc_prep(struct ata_queued_cmd *qc) nv_adma_tf_to_cpb(&qc->tf, cpb->tf); - if(qc->flags & ATA_QCFLAG_DMAMAP) { + if (qc->flags & ATA_QCFLAG_DMAMAP) { nv_adma_fill_sg(qc, cpb); ctl_flags |= NV_CPB_CTL_APRD_VALID; } else memset(&cpb->aprd[0], 0, sizeof(struct nv_adma_prd) * 5); - /* Be paranoid and don't let the device see NV_CPB_CTL_CPB_VALID until we are - finished filling in all of the contents */ + /* Be paranoid and don't let the device see NV_CPB_CTL_CPB_VALID + until we are finished filling in all of the contents */ wmb(); cpb->ctl_flags = ctl_flags; wmb(); @@ -1423,9 +1427,21 @@ static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc) VPRINTK("ENTER\n"); + /* We can't handle result taskfile with NCQ commands, since + retrieving the taskfile switches us out of ADMA mode and would abort + existing commands. */ + if (unlikely(qc->tf.protocol == ATA_PROT_NCQ && + (qc->flags & ATA_QCFLAG_RESULT_TF))) { + ata_dev_printk(qc->dev, KERN_ERR, + "NCQ w/ RESULT_TF not allowed\n"); + return AC_ERR_SYSTEM; + } + if (nv_adma_use_reg_mode(qc)) { /* use ATA register mode */ VPRINTK("using ATA register mode: 0x%lx\n", qc->flags); + BUG_ON(!(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) && + (qc->flags & ATA_QCFLAG_DMAMAP)); nv_adma_register_mode(qc->ap); return ata_qc_issue_prot(qc); } else @@ -1435,16 +1451,16 @@ static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc) and (number of cpbs to append -1) in top 8 bits */ wmb(); - if(curr_ncq != pp->last_issue_ncq) { - /* Seems to need some delay before switching between NCQ and non-NCQ - commands, else we get command timeouts and such. */ + if (curr_ncq != pp->last_issue_ncq) { + /* Seems to need some delay before switching between NCQ and + non-NCQ commands, else we get command timeouts and such. */ udelay(20); pp->last_issue_ncq = curr_ncq; } writew(qc->tag, mmio + NV_ADMA_APPEND); - DPRINTK("Issued tag %u\n",qc->tag); + DPRINTK("Issued tag %u\n", qc->tag); return 0; } @@ -1627,7 +1643,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); } @@ -1641,12 +1657,12 @@ static void nv_error_handler(struct ata_port *ap) static void nv_adma_error_handler(struct ata_port *ap) { struct nv_adma_port_priv *pp = ap->private_data; - if(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) { + if (!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) { void __iomem *mmio = pp->ctl_block; int i; u16 tmp; - if(ata_tag_valid(ap->link.active_tag) || ap->link.sactive) { + if (ata_tag_valid(ap->link.active_tag) || ap->link.sactive) { u32 notifier = readl(mmio + NV_ADMA_NOTIFIER); u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR); u32 gen_ctl = readl(pp->gen_block + NV_ADMA_GEN_CTL); @@ -1654,16 +1670,17 @@ static void nv_adma_error_handler(struct ata_port *ap) u8 cpb_count = readb(mmio + NV_ADMA_CPB_COUNT); u8 next_cpb_idx = readb(mmio + NV_ADMA_NEXT_CPB_IDX); - ata_port_printk(ap, KERN_ERR, "EH in ADMA mode, notifier 0x%X " + ata_port_printk(ap, KERN_ERR, + "EH in ADMA mode, notifier 0x%X " "notifier_error 0x%X gen_ctl 0x%X status 0x%X " "next cpb count 0x%X next cpb idx 0x%x\n", notifier, notifier_error, gen_ctl, status, cpb_count, next_cpb_idx); - for( i=0;i<NV_ADMA_MAX_CPBS;i++) { + for (i = 0; i < NV_ADMA_MAX_CPBS; i++) { struct nv_adma_cpb *cpb = &pp->cpb[i]; - if( (ata_tag_valid(ap->link.active_tag) && i == ap->link.active_tag) || - ap->link.sactive & (1 << i) ) + if ((ata_tag_valid(ap->link.active_tag) && i == ap->link.active_tag) || + ap->link.sactive & (1 << i)) ata_port_printk(ap, KERN_ERR, "CPB %d: ctl_flags 0x%x, resp_flags 0x%x\n", i, cpb->ctl_flags, cpb->resp_flags); @@ -1673,8 +1690,9 @@ static void nv_adma_error_handler(struct ata_port *ap) /* Push us back into port register mode for error handling. */ nv_adma_register_mode(ap); - /* Mark all of the CPBs as invalid to prevent them from being executed */ - for( i=0;i<NV_ADMA_MAX_CPBS;i++) + /* Mark all of the CPBs as invalid to prevent them from + being executed */ + for (i = 0; i < NV_ADMA_MAX_CPBS; i++) pp->cpb[i].ctl_flags &= ~NV_CPB_CTL_CPB_VALID; /* clear CPB fetch count */ @@ -1683,10 +1701,10 @@ static void nv_adma_error_handler(struct ata_port *ap) /* Reset channel */ tmp = readw(mmio + NV_ADMA_CTL); writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); - readw( mmio + NV_ADMA_CTL ); /* flush posted write */ + readw(mmio + NV_ADMA_CTL); /* flush posted write */ udelay(1); writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); - readw( mmio + NV_ADMA_CTL ); /* flush posted write */ + readw(mmio + NV_ADMA_CTL); /* flush posted write */ } ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, @@ -2350,9 +2368,9 @@ static irqreturn_t nv_swncq_interrupt(int irq, void *dev_instance) return IRQ_RETVAL(handled); } -static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - static int printed_version = 0; + static int printed_version; const struct ata_port_info *ppi[] = { NULL, NULL }; struct ata_host *host; struct nv_host_priv *hpriv; @@ -2364,7 +2382,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) // Make sure this is a SATA controller by counting the number of bars // (NVIDIA SATA controllers will always have six bars). Otherwise, // it's an IDE controller and we ignore it. - for (bar=0; bar<6; bar++) + for (bar = 0; bar < 6; bar++) if (pci_resource_start(pdev, bar) == 0) return -ENODEV; @@ -2381,6 +2399,14 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) type = ADMA; } + if (type == SWNCQ) { + if (swncq_enabled) + dev_printk(KERN_NOTICE, &pdev->dev, + "Using SWNCQ mode\n"); + else + type = GENERIC; + } + ppi[0] = &nv_port_info[type]; rc = ata_pci_prepare_sff_host(pdev, ppi, &host); if (rc) @@ -2422,10 +2448,8 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) rc = nv_adma_host_init(host); if (rc) return rc; - } else if (type == SWNCQ && swncq_enabled) { - dev_printk(KERN_NOTICE, &pdev->dev, "Using SWNCQ mode\n"); + } else if (type == SWNCQ) nv_swncq_host_init(host); - } pci_set_master(pdev); return ata_host_activate(host, pdev->irq, ppi[0]->irq_handler, @@ -2440,37 +2464,37 @@ static int nv_pci_device_resume(struct pci_dev *pdev) int rc; rc = ata_pci_device_do_resume(pdev); - if(rc) + if (rc) return rc; if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { - if(hpriv->type >= CK804) { + if (hpriv->type >= CK804) { u8 regval; pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val); regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN; pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval); } - if(hpriv->type == ADMA) { + if (hpriv->type == ADMA) { u32 tmp32; struct nv_adma_port_priv *pp; /* enable/disable ADMA on the ports appropriately */ pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &tmp32); pp = host->ports[0]->private_data; - if(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) + if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT0_EN | - NV_MCP_SATA_CFG_20_PORT0_PWB_EN); + NV_MCP_SATA_CFG_20_PORT0_PWB_EN); else tmp32 |= (NV_MCP_SATA_CFG_20_PORT0_EN | - NV_MCP_SATA_CFG_20_PORT0_PWB_EN); + NV_MCP_SATA_CFG_20_PORT0_PWB_EN); pp = host->ports[1]->private_data; - if(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) + if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT1_EN | - NV_MCP_SATA_CFG_20_PORT1_PWB_EN); + NV_MCP_SATA_CFG_20_PORT1_PWB_EN); else tmp32 |= (NV_MCP_SATA_CFG_20_PORT1_EN | - NV_MCP_SATA_CFG_20_PORT1_PWB_EN); + NV_MCP_SATA_CFG_20_PORT1_PWB_EN); pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, tmp32); } diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index 903213153b5..7914def54fa 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -2,6 +2,7 @@ * sata_promise.c - Promise SATA * * Maintained by: Jeff Garzik <jgarzik@pobox.com> + * Mikael Pettersson <mikpe@it.uu.se> * Please ALWAYS copy linux-ide@vger.kernel.org * on emails. * @@ -45,11 +46,12 @@ #include "sata_promise.h" #define DRV_NAME "sata_promise" -#define DRV_VERSION "2.10" +#define DRV_VERSION "2.11" enum { PDC_MAX_PORTS = 4, PDC_MMIO_BAR = 3, + PDC_MAX_PRD = LIBATA_MAX_PRD - 1, /* -1 for ASIC PRD bug workaround */ /* register offsets */ PDC_FEATURE = 0x04, /* Feature/Error reg (per port) */ @@ -83,10 +85,12 @@ enum { PDC_PCI_SYS_ERR = (1 << 22), /* PCI system error */ PDC1_PCI_PARITY_ERR = (1 << 23), /* PCI parity error (from SATA150 driver) */ PDC1_ERR_MASK = PDC1_PCI_PARITY_ERR, - PDC2_ERR_MASK = PDC2_HTO_ERR | PDC2_ATA_HBA_ERR | PDC2_ATA_DMA_CNT_ERR, - PDC_ERR_MASK = (PDC_PH_ERR | PDC_SH_ERR | PDC_DH_ERR | PDC_OVERRUN_ERR - | PDC_UNDERRUN_ERR | PDC_DRIVE_ERR | PDC_PCI_SYS_ERR - | PDC1_ERR_MASK | PDC2_ERR_MASK), + PDC2_ERR_MASK = PDC2_HTO_ERR | PDC2_ATA_HBA_ERR | + PDC2_ATA_DMA_CNT_ERR, + PDC_ERR_MASK = PDC_PH_ERR | PDC_SH_ERR | PDC_DH_ERR | + PDC_OVERRUN_ERR | PDC_UNDERRUN_ERR | + PDC_DRIVE_ERR | PDC_PCI_SYS_ERR | + PDC1_ERR_MASK | PDC2_ERR_MASK, board_2037x = 0, /* FastTrak S150 TX2plus */ board_2037x_pata = 1, /* FastTrak S150 TX2plus PATA port */ @@ -155,7 +159,7 @@ static struct scsi_host_template pdc_ata_sht = { .queuecommand = ata_scsi_queuecmd, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, + .sg_tablesize = PDC_MAX_PRD, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, .use_clustering = ATA_SHT_USE_CLUSTERING, @@ -238,7 +242,7 @@ static const struct ata_port_operations pdc_pata_ops = { }; static const struct ata_port_info pdc_port_info[] = { - /* board_2037x */ + [board_2037x] = { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | PDC_FLAG_SATA_PATA, @@ -248,7 +252,7 @@ static const struct ata_port_info pdc_port_info[] = { .port_ops = &pdc_old_sata_ops, }, - /* board_2037x_pata */ + [board_2037x_pata] = { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS, .pio_mask = 0x1f, /* pio0-4 */ @@ -257,7 +261,7 @@ static const struct ata_port_info pdc_port_info[] = { .port_ops = &pdc_pata_ops, }, - /* board_20319 */ + [board_20319] = { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | PDC_FLAG_4_PORTS, @@ -267,7 +271,7 @@ static const struct ata_port_info pdc_port_info[] = { .port_ops = &pdc_old_sata_ops, }, - /* board_20619 */ + [board_20619] = { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS | PDC_FLAG_4_PORTS, @@ -277,7 +281,7 @@ static const struct ata_port_info pdc_port_info[] = { .port_ops = &pdc_pata_ops, }, - /* board_2057x */ + [board_2057x] = { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | PDC_FLAG_GEN_II | PDC_FLAG_SATA_PATA, @@ -287,7 +291,7 @@ static const struct ata_port_info pdc_port_info[] = { .port_ops = &pdc_sata_ops, }, - /* board_2057x_pata */ + [board_2057x_pata] = { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS | PDC_FLAG_GEN_II, @@ -297,7 +301,7 @@ static const struct ata_port_info pdc_port_info[] = { .port_ops = &pdc_pata_ops, }, - /* board_40518 */ + [board_40518] = { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS, @@ -521,6 +525,84 @@ static void pdc_atapi_pkt(struct ata_queued_cmd *qc) memcpy(buf+31, cdb, cdb_len); } +/** + * pdc_fill_sg - Fill PCI IDE PRD table + * @qc: Metadata associated with taskfile to be transferred + * + * Fill PCI IDE PRD (scatter-gather) table with segments + * associated with the current disk command. + * Make sure hardware does not choke on it. + * + * LOCKING: + * spin_lock_irqsave(host lock) + * + */ +static void pdc_fill_sg(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct scatterlist *sg; + unsigned int idx; + const u32 SG_COUNT_ASIC_BUG = 41*4; + + if (!(qc->flags & ATA_QCFLAG_DMAMAP)) + return; + + WARN_ON(qc->__sg == NULL); + WARN_ON(qc->n_elem == 0 && qc->pad_len == 0); + + idx = 0; + ata_for_each_sg(sg, qc) { + u32 addr, offset; + u32 sg_len, len; + + /* determine if physical DMA addr spans 64K boundary. + * Note h/w doesn't support 64-bit, so we unconditionally + * truncate dma_addr_t to u32. + */ + addr = (u32) sg_dma_address(sg); + sg_len = sg_dma_len(sg); + + while (sg_len) { + offset = addr & 0xffff; + len = sg_len; + if ((offset + sg_len) > 0x10000) + len = 0x10000 - offset; + + ap->prd[idx].addr = cpu_to_le32(addr); + ap->prd[idx].flags_len = cpu_to_le32(len & 0xffff); + VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len); + + idx++; + sg_len -= len; + addr += len; + } + } + + if (idx) { + u32 len = le32_to_cpu(ap->prd[idx - 1].flags_len); + + if (len > SG_COUNT_ASIC_BUG) { + u32 addr; + + VPRINTK("Splitting last PRD.\n"); + + addr = le32_to_cpu(ap->prd[idx - 1].addr); + ap->prd[idx - 1].flags_len = cpu_to_le32(len - SG_COUNT_ASIC_BUG); + VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx - 1, addr, SG_COUNT_ASIC_BUG); + + addr = addr + len - SG_COUNT_ASIC_BUG; + len = SG_COUNT_ASIC_BUG; + ap->prd[idx].addr = cpu_to_le32(addr); + ap->prd[idx].flags_len = cpu_to_le32(len); + VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len); + + idx++; + } + + ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT); + } +} + static void pdc_qc_prep(struct ata_queued_cmd *qc) { struct pdc_port_priv *pp = qc->ap->private_data; @@ -530,7 +612,7 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc) switch (qc->tf.protocol) { case ATA_PROT_DMA: - ata_qc_prep(qc); + pdc_fill_sg(qc); /* fall through */ case ATA_PROT_NODATA: @@ -546,11 +628,11 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc) break; case ATA_PROT_ATAPI: - ata_qc_prep(qc); + pdc_fill_sg(qc); break; case ATA_PROT_ATAPI_DMA: - ata_qc_prep(qc); + pdc_fill_sg(qc); /*FALLTHROUGH*/ case ATA_PROT_ATAPI_NODATA: pdc_atapi_pkt(qc); @@ -695,19 +777,20 @@ static void pdc_irq_clear(struct ata_port *ap) readl(mmio + PDC_INT_SEQMASK); } -static inline int pdc_is_sataii_tx4(unsigned long flags) +static int pdc_is_sataii_tx4(unsigned long flags) { const unsigned long mask = PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS; return (flags & mask) == mask; } -static inline unsigned int pdc_port_no_to_ata_no(unsigned int port_no, int is_sataii_tx4) +static unsigned int pdc_port_no_to_ata_no(unsigned int port_no, + int is_sataii_tx4) { static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2}; return is_sataii_tx4 ? sataii_tx4_port_remap[port_no] : port_no; } -static irqreturn_t pdc_interrupt (int irq, void *dev_instance) +static irqreturn_t pdc_interrupt(int irq, void *dev_instance) { struct ata_host *host = dev_instance; struct ata_port *ap; @@ -839,15 +922,16 @@ static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc) static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf) { - WARN_ON (tf->protocol == ATA_PROT_DMA || - tf->protocol == ATA_PROT_ATAPI_DMA); + WARN_ON(tf->protocol == ATA_PROT_DMA || + tf->protocol == ATA_PROT_ATAPI_DMA); ata_tf_load(ap, tf); } -static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf) +static void pdc_exec_command_mmio(struct ata_port *ap, + const struct ata_taskfile *tf) { - WARN_ON (tf->protocol == ATA_PROT_DMA || - tf->protocol == ATA_PROT_ATAPI_DMA); + WARN_ON(tf->protocol == ATA_PROT_DMA || + tf->protocol == ATA_PROT_ATAPI_DMA); ata_exec_command(ap, tf); } @@ -870,8 +954,11 @@ static int pdc_check_atapi_dma(struct ata_queued_cmd *qc) } /* -45150 (FFFF4FA2) to -1 (FFFFFFFF) shall use PIO mode */ if (scsicmd[0] == WRITE_10) { - unsigned int lba; - lba = (scsicmd[2] << 24) | (scsicmd[3] << 16) | (scsicmd[4] << 8) | scsicmd[5]; + unsigned int lba = + (scsicmd[2] << 24) | + (scsicmd[3] << 16) | + (scsicmd[4] << 8) | + scsicmd[5]; if (lba >= 0xFFFF4FA2) pio = 1; } @@ -956,7 +1043,8 @@ static void pdc_host_init(struct ata_host *host) writel(tmp, mmio + PDC_SLEW_CTL); } -static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +static int pdc_ata_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { static int printed_version; const struct ata_port_info *pi = &pdc_port_info[ent->driver_data]; diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c index c4c4cd29eeb..c68b241805f 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; @@ -113,17 +113,18 @@ struct qs_port_priv { static int qs_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val); 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_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, @@ -135,7 +136,6 @@ static struct scsi_host_template qs_ata_sht = { .sg_tablesize = QS_MAX_PRD, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, - //FIXME .use_clustering = ATA_SHT_USE_CLUSTERING, .use_clustering = ENABLE_CLUSTERING, .proc_name = DRV_NAME, .dma_boundary = QS_DMA_BOUNDARY, @@ -151,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, @@ -170,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, @@ -220,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 */ } @@ -234,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) @@ -261,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, NULL, sata_std_hardreset, + ata_std_postreset); +} + static int qs_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val) { if (sc_reg > SCR_CONTROL) @@ -359,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; @@ -376,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; @@ -407,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; @@ -432,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; @@ -460,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"); @@ -502,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; @@ -513,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_sil.c b/drivers/ata/sata_sil.c index ea3a0ab7e02..f5119bf40c2 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -111,7 +111,7 @@ enum { SIL_QUIRK_UDMA5MAX = (1 << 1), }; -static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); +static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); #ifdef CONFIG_PM static int sil_pci_device_resume(struct pci_dev *pdev); #endif @@ -138,7 +138,7 @@ static const struct pci_device_id sil_pci_tbl[] = { /* TODO firmware versions should be added - eric */ static const struct sil_drivelist { - const char * product; + const char *product; unsigned int quirk; } sil_blacklist [] = { { "ST320012AS", SIL_QUIRK_MOD15WRITE }, @@ -279,7 +279,7 @@ MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, sil_pci_tbl); MODULE_VERSION(DRV_VERSION); -static int slow_down = 0; +static int slow_down; module_param(slow_down, int, 0444); MODULE_PARM_DESC(slow_down, "Sledgehammer used to work around random problems, by limiting commands to 15 sectors (0=off, 1=on)"); @@ -332,7 +332,8 @@ static int sil_set_mode(struct ata_link *link, struct ata_device **r_failed) return 0; } -static inline void __iomem *sil_scr_addr(struct ata_port *ap, unsigned int sc_reg) +static inline void __iomem *sil_scr_addr(struct ata_port *ap, + unsigned int sc_reg) { void __iomem *offset = ap->ioaddr.scr_addr; @@ -389,23 +390,19 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2) sil_scr_read(ap, SCR_ERROR, &serror); sil_scr_write(ap, SCR_ERROR, serror); - /* Trigger hotplug and accumulate SError only if the - * port isn't already frozen. Otherwise, PHY events - * during hardreset makes controllers with broken SIEN - * repeat probing needlessly. + /* Sometimes spurious interrupts occur, double check + * it's PHYRDY CHG. */ - if (!(ap->pflags & ATA_PFLAG_FROZEN)) { - ata_ehi_hotplugged(&ap->link.eh_info); + if (serror & SERR_PHYRDY_CHG) { ap->link.eh_info.serror |= serror; + goto freeze; } - goto freeze; + if (!(bmdma2 & SIL_DMA_COMPLETE)) + return; } - if (unlikely(!qc)) - goto freeze; - - if (unlikely(qc->tf.flags & ATA_TFLAG_POLLING)) { + if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) { /* this sometimes happens, just clear IRQ */ ata_chk_status(ap); return; @@ -643,7 +640,7 @@ static void sil_init_controller(struct ata_host *host) } } -static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; int board_id = ent->driver_data; diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 26ebffc10f3..864c1c1b851 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 { @@ -265,11 +280,11 @@ static struct sil24_cerr_info { unsigned int err_mask, action; const char *desc; } sil24_cerr_db[] = { - [0] = { AC_ERR_DEV, ATA_EH_REVALIDATE, + [0] = { AC_ERR_DEV, 0, "device error" }, - [PORT_CERR_DEV] = { AC_ERR_DEV, ATA_EH_REVALIDATE, + [PORT_CERR_DEV] = { AC_ERR_DEV, 0, "device error via D2H FIS" }, - [PORT_CERR_SDB] = { AC_ERR_DEV, ATA_EH_REVALIDATE, + [PORT_CERR_SDB] = { AC_ERR_DEV, 0, "device error via SDB FIS" }, [PORT_CERR_DATA] = { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET, "error in data FIS" }, @@ -286,7 +301,7 @@ static struct sil24_cerr_info { [PORT_CERR_PKT_PROT] = { AC_ERR_HSM, ATA_EH_SOFTRESET, "invalid data directon for ATAPI CDB" }, [PORT_CERR_SGT_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_SOFTRESET, - "SGT no on qword boundary" }, + "SGT not on qword boundary" }, [PORT_CERR_SGT_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, "PCI target abort while fetching SGT" }, [PORT_CERR_SGT_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, @@ -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, @@ -674,7 +689,7 @@ static int sil24_do_softreset(struct ata_link *link, unsigned int *class, /* put the port into known state */ if (sil24_init_port(ap)) { - reason ="port not ready"; + reason = "port not ready"; goto err; } @@ -756,7 +771,8 @@ static int sil24_hardreset(struct ata_link *link, unsigned int *class, writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT); tmp = ata_wait_register(port + PORT_CTRL_STAT, - PORT_CS_DEV_RST, PORT_CS_DEV_RST, 10, tout_msec); + PORT_CS_DEV_RST, PORT_CS_DEV_RST, 10, + tout_msec); /* SStatus oscillates between zero and valid status after * DEV_RST, debounce it. @@ -816,16 +832,31 @@ static int sil24_qc_defer(struct ata_queued_cmd *qc) struct ata_link *link = qc->dev->link; struct ata_port *ap = link->ap; u8 prot = qc->tf.protocol; - int is_atapi = (prot == ATA_PROT_ATAPI || - prot == ATA_PROT_ATAPI_NODATA || - prot == ATA_PROT_ATAPI_DMA); - - /* ATAPI commands completing with CHECK_SENSE cause various - * weird problems if other commands are active. PMP DMA CS - * errata doesn't cover all and HSM violation occurs even with - * only one other device active. Always run an ATAPI command - * by itself. - */ + + /* + * There is a bug in the chip: + * Port LRAM Causes the PRB/SGT Data to be Corrupted + * If the host issues a read request for LRAM and SActive registers + * while active commands are available in the port, PRB/SGT data in + * the LRAM can become corrupted. This issue applies only when + * reading from, but not writing to, the LRAM. + * + * Therefore, reading LRAM when there is no particular error [and + * other commands may be outstanding] is prohibited. + * + * To avoid this bug there are two situations where a command must run + * exclusive of any other commands on the port: + * + * - ATAPI commands which check the sense data + * - Passthrough ATA commands which always have ATA_QCFLAG_RESULT_TF + * set. + * + */ + int is_excl = (prot == ATA_PROT_ATAPI || + prot == ATA_PROT_ATAPI_NODATA || + prot == ATA_PROT_ATAPI_DMA || + (qc->flags & ATA_QCFLAG_RESULT_TF)); + if (unlikely(ap->excl_link)) { if (link == ap->excl_link) { if (ap->nr_active_links) @@ -833,7 +864,7 @@ static int sil24_qc_defer(struct ata_queued_cmd *qc) qc->flags |= ATA_QCFLAG_CLEAR_EXCL; } else return ATA_DEFER_PORT; - } else if (unlikely(is_atapi)) { + } else if (unlikely(is_excl)) { ap->excl_link = link; if (ap->nr_active_links) return ATA_DEFER_PORT; @@ -1063,10 +1094,13 @@ static void sil24_error_intr(struct ata_port *ap) if (ci && ci->desc) { err_mask |= ci->err_mask; action |= ci->action; + if (action & ATA_EH_RESET_MASK) + freeze = 1; ata_ehi_push_desc(ehi, "%s", ci->desc); } else { err_mask |= AC_ERR_OTHER; action |= ATA_EH_SOFTRESET; + freeze = 1; ata_ehi_push_desc(ehi, "unknown command error %d", cerr); } @@ -1270,7 +1304,7 @@ static void sil24_init_controller(struct ata_host *host) PORT_CS_PORT_RST, 10, 100); if (tmp & PORT_CS_PORT_RST) dev_printk(KERN_ERR, host->dev, - "failed to clear port RST\n"); + "failed to clear port RST\n"); } /* configure port */ @@ -1283,7 +1317,8 @@ static void sil24_init_controller(struct ata_host *host) static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - static int printed_version = 0; + 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 }; void __iomem * const *iomap; @@ -1291,6 +1326,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/ata/sata_sis.c b/drivers/ata/sata_sis.c index f147dc7bf46..a01260a5643 100644 --- a/drivers/ata/sata_sis.c +++ b/drivers/ata/sata_sis.c @@ -63,17 +63,17 @@ enum { GENCTL_IOMAPPED_SCR = (1 << 26), /* if set, SCRs are in IO space */ }; -static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); -static int sis_scr_read (struct ata_port *ap, unsigned int sc_reg, u32 *val); -static int sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); +static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); +static int sis_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val); +static int sis_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val); static const struct pci_device_id sis_pci_tbl[] = { - { PCI_VDEVICE(SI, 0x0180), sis_180 }, /* SiS 964/180 */ - { PCI_VDEVICE(SI, 0x0181), sis_180 }, /* SiS 964/180 */ - { PCI_VDEVICE(SI, 0x0182), sis_180 }, /* SiS 965/965L */ - { PCI_VDEVICE(SI, 0x0183), sis_180 }, /* SiS 965/965L */ - { PCI_VDEVICE(SI, 0x1182), sis_180 }, /* SiS 966/680 */ - { PCI_VDEVICE(SI, 0x1183), sis_180 }, /* SiS 966/966L/968/680 */ + { PCI_VDEVICE(SI, 0x0180), sis_180 }, /* SiS 964/180 */ + { PCI_VDEVICE(SI, 0x0181), sis_180 }, /* SiS 964/180 */ + { PCI_VDEVICE(SI, 0x0182), sis_180 }, /* SiS 965/965L */ + { PCI_VDEVICE(SI, 0x0183), sis_180 }, /* SiS 965/965L */ + { PCI_VDEVICE(SI, 0x1182), sis_180 }, /* SiS 966/680 */ + { PCI_VDEVICE(SI, 0x1183), sis_180 }, /* SiS 966/966L/968/680 */ { } /* terminate list */ }; @@ -149,24 +149,24 @@ static unsigned int get_scr_cfg_addr(struct ata_port *ap, unsigned int sc_reg) if (ap->port_no) { switch (pdev->device) { - case 0x0180: - case 0x0181: - pci_read_config_byte(pdev, SIS_PMR, &pmr); - if ((pmr & SIS_PMR_COMBINED) == 0) - addr += SIS180_SATA1_OFS; - break; - - case 0x0182: - case 0x0183: - case 0x1182: - addr += SIS182_SATA1_OFS; - break; + case 0x0180: + case 0x0181: + pci_read_config_byte(pdev, SIS_PMR, &pmr); + if ((pmr & SIS_PMR_COMBINED) == 0) + addr += SIS180_SATA1_OFS; + break; + + case 0x0182: + case 0x0183: + case 0x1182: + addr += SIS182_SATA1_OFS; + break; } } return addr; } -static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg, u32 *val) +static u32 sis_scr_cfg_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); unsigned int cfg_addr = get_scr_cfg_addr(ap, sc_reg); @@ -190,7 +190,7 @@ static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg, u32 *val) return 0; } -static void sis_scr_cfg_write (struct ata_port *ap, unsigned int sc_reg, u32 val) +static void sis_scr_cfg_write(struct ata_port *ap, unsigned int sc_reg, u32 val) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); unsigned int cfg_addr = get_scr_cfg_addr(ap, sc_reg); @@ -253,7 +253,7 @@ static int sis_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val) return 0; } -static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; struct ata_port_info pi = sis_port_info; @@ -309,29 +309,33 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) } else { dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 180/181 chipset in combined mode\n"); - port2_start=0; + port2_start = 0; pi.flags |= ATA_FLAG_SLAVE_POSS; } break; case 0x0182: case 0x0183: - pci_read_config_dword ( pdev, 0x6C, &val); + pci_read_config_dword(pdev, 0x6C, &val); if (val & (1L << 31)) { - dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 182/965 chipset\n"); + dev_printk(KERN_INFO, &pdev->dev, + "Detected SiS 182/965 chipset\n"); pi.flags |= ATA_FLAG_SLAVE_POSS; } else { - dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 182/965L chipset\n"); + dev_printk(KERN_INFO, &pdev->dev, + "Detected SiS 182/965L chipset\n"); } break; case 0x1182: - dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 1182/966/680 SATA controller\n"); + dev_printk(KERN_INFO, &pdev->dev, + "Detected SiS 1182/966/680 SATA controller\n"); pi.flags |= ATA_FLAG_SLAVE_POSS; break; case 0x1183: - dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 1183/966/966L/968/680 controller in PATA mode\n"); + dev_printk(KERN_INFO, &pdev->dev, + "Detected SiS 1183/966/966L/968/680 controller in PATA mode\n"); ppi[0] = &sis_info133_for_sata; ppi[1] = &sis_info133_for_sata; break; diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c index 12d613c48c1..69f651e0bc9 100644 --- a/drivers/ata/sata_svw.c +++ b/drivers/ata/sata_svw.c @@ -182,7 +182,7 @@ static void k2_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) tf->hob_lbal = lbal >> 8; tf->hob_lbam = lbam >> 8; tf->hob_lbah = lbah >> 8; - } + } } /** @@ -193,7 +193,7 @@ static void k2_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) * spin_lock_irqsave(host lock) */ -static void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc) +static void k2_bmdma_setup_mmio(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); @@ -224,7 +224,7 @@ static void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc) * spin_lock_irqsave(host lock) */ -static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc) +static void k2_bmdma_start_mmio(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; void __iomem *mmio = ap->ioaddr.bmdma_addr; @@ -255,7 +255,7 @@ static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc) static u8 k2_stat_check_status(struct ata_port *ap) { - return readl(ap->ioaddr.status_addr); + return readl(ap->ioaddr.status_addr); } #ifdef CONFIG_PPC_OF @@ -395,7 +395,7 @@ static void k2_sata_setup_port(struct ata_ioports *port, void __iomem *base) } -static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +static int k2_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; const struct ata_port_info *ppi[] = diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c index b6026bceccd..4d857185f33 100644 --- a/drivers/ata/sata_sx4.c +++ b/drivers/ata/sata_sx4.c @@ -212,9 +212,9 @@ struct pdc_host_priv { }; -static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); +static int pdc_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); static void pdc_eng_timeout(struct ata_port *ap); -static void pdc_20621_phy_reset (struct ata_port *ap); +static void pdc_20621_phy_reset(struct ata_port *ap); static int pdc_port_start(struct ata_port *ap); static void pdc20621_qc_prep(struct ata_queued_cmd *qc); static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf); @@ -320,16 +320,16 @@ static int pdc_port_start(struct ata_port *ap) return 0; } -static void pdc_20621_phy_reset (struct ata_port *ap) +static void pdc_20621_phy_reset(struct ata_port *ap) { VPRINTK("ENTER\n"); - ap->cbl = ATA_CBL_SATA; - ata_port_probe(ap); - ata_bus_reset(ap); + ap->cbl = ATA_CBL_SATA; + ata_port_probe(ap); + ata_bus_reset(ap); } static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf, - unsigned int portno, + unsigned int portno, unsigned int total_len) { u32 addr; @@ -351,7 +351,7 @@ static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf, } static inline void pdc20621_host_sg(struct ata_taskfile *tf, u8 *buf, - unsigned int portno, + unsigned int portno, unsigned int total_len) { u32 addr; @@ -711,8 +711,8 @@ static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc) return ata_qc_issue_prot(qc); } -static inline unsigned int pdc20621_host_intr( struct ata_port *ap, - struct ata_queued_cmd *qc, +static inline unsigned int pdc20621_host_intr(struct ata_port *ap, + struct ata_queued_cmd *qc, unsigned int doing_hdma, void __iomem *mmio) { @@ -803,7 +803,7 @@ static void pdc20621_irq_clear(struct ata_port *ap) readl(mmio + PDC_20621_SEQMASK); } -static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance) +static irqreturn_t pdc20621_interrupt(int irq, void *dev_instance) { struct ata_host *host = dev_instance; struct ata_port *ap; @@ -836,9 +836,9 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance) return IRQ_NONE; } - spin_lock(&host->lock); + spin_lock(&host->lock); - for (i = 1; i < 9; i++) { + for (i = 1; i < 9; i++) { port_no = i - 1; if (port_no > 3) port_no -= 4; @@ -859,7 +859,7 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance) } } - spin_unlock(&host->lock); + spin_unlock(&host->lock); VPRINTK("mask == 0x%x\n", mask); @@ -906,16 +906,16 @@ static void pdc_eng_timeout(struct ata_port *ap) static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf) { - WARN_ON (tf->protocol == ATA_PROT_DMA || - tf->protocol == ATA_PROT_NODATA); + WARN_ON(tf->protocol == ATA_PROT_DMA || + tf->protocol == ATA_PROT_NODATA); ata_tf_load(ap, tf); } static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf) { - WARN_ON (tf->protocol == ATA_PROT_DMA || - tf->protocol == ATA_PROT_NODATA); + WARN_ON(tf->protocol == ATA_PROT_DMA || + tf->protocol == ATA_PROT_NODATA); ata_exec_command(ap, tf); } @@ -953,7 +953,7 @@ static void pdc20621_get_from_dimm(struct ata_host *host, void *psource, mmio += PDC_CHIP0_OFS; page_mask = 0x00; - window_size = 0x2000 * 4; /* 32K byte uchar size */ + window_size = 0x2000 * 4; /* 32K byte uchar size */ idx = (u16) (offset / window_size); writel(0x01, mmio + PDC_GENERAL_CTLR); @@ -979,7 +979,7 @@ static void pdc20621_get_from_dimm(struct ata_host *host, void *psource, window_size / 4); psource += window_size; size -= window_size; - idx ++; + idx++; } if (size) { @@ -1008,7 +1008,7 @@ static void pdc20621_put_to_dimm(struct ata_host *host, void *psource, mmio += PDC_CHIP0_OFS; page_mask = 0x00; - window_size = 0x2000 * 4; /* 32K byte uchar size */ + window_size = 0x2000 * 4; /* 32K byte uchar size */ idx = (u16) (offset / window_size); writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); @@ -1031,7 +1031,7 @@ static void pdc20621_put_to_dimm(struct ata_host *host, void *psource, readl(mmio + PDC_GENERAL_CTLR); psource += window_size; size -= window_size; - idx ++; + idx++; } if (size) { @@ -1050,7 +1050,7 @@ static unsigned int pdc20621_i2c_read(struct ata_host *host, u32 device, void __iomem *mmio = host->iomap[PDC_MMIO_BAR]; u32 i2creg = 0; u32 status; - u32 count =0; + u32 count = 0; /* hard-code chip #0 */ mmio += PDC_CHIP0_OFS; @@ -1082,21 +1082,21 @@ static unsigned int pdc20621_i2c_read(struct ata_host *host, u32 device, static int pdc20621_detect_dimm(struct ata_host *host) { - u32 data=0 ; + u32 data = 0; if (pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS, PDC_DIMM_SPD_SYSTEM_FREQ, &data)) { - if (data == 100) + if (data == 100) return 100; - } else + } else return 0; if (pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS, 9, &data)) { - if(data <= 0x75) + if (data <= 0x75) return 133; - } else + } else return 0; - return 0; + return 0; } @@ -1104,8 +1104,8 @@ static int pdc20621_prog_dimm0(struct ata_host *host) { u32 spd0[50]; u32 data = 0; - int size, i; - u8 bdimmsize; + int size, i; + u8 bdimmsize; void __iomem *mmio = host->iomap[PDC_MMIO_BAR]; static const struct { unsigned int reg; @@ -1128,40 +1128,40 @@ static int pdc20621_prog_dimm0(struct ata_host *host) /* hard-code chip #0 */ mmio += PDC_CHIP0_OFS; - for(i=0; i<ARRAY_SIZE(pdc_i2c_read_data); i++) + for (i = 0; i < ARRAY_SIZE(pdc_i2c_read_data); i++) pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS, pdc_i2c_read_data[i].reg, &spd0[pdc_i2c_read_data[i].ofs]); - data |= (spd0[4] - 8) | ((spd0[21] != 0) << 3) | ((spd0[3]-11) << 4); - data |= ((spd0[17] / 4) << 6) | ((spd0[5] / 2) << 7) | + data |= (spd0[4] - 8) | ((spd0[21] != 0) << 3) | ((spd0[3]-11) << 4); + data |= ((spd0[17] / 4) << 6) | ((spd0[5] / 2) << 7) | ((((spd0[27] + 9) / 10) - 1) << 8) ; - data |= (((((spd0[29] > spd0[28]) + data |= (((((spd0[29] > spd0[28]) ? spd0[29] : spd0[28]) + 9) / 10) - 1) << 10; - data |= ((spd0[30] - spd0[29] + 9) / 10 - 2) << 12; + data |= ((spd0[30] - spd0[29] + 9) / 10 - 2) << 12; - if (spd0[18] & 0x08) + if (spd0[18] & 0x08) data |= ((0x03) << 14); - else if (spd0[18] & 0x04) + else if (spd0[18] & 0x04) data |= ((0x02) << 14); - else if (spd0[18] & 0x01) + else if (spd0[18] & 0x01) data |= ((0x01) << 14); - else + else data |= (0 << 14); - /* + /* Calculate the size of bDIMMSize (power of 2) and merge the DIMM size by program start/end address. */ - bdimmsize = spd0[4] + (spd0[5] / 2) + spd0[3] + (spd0[17] / 2) + 3; - size = (1 << bdimmsize) >> 20; /* size = xxx(MB) */ - data |= (((size / 16) - 1) << 16); - data |= (0 << 23); + bdimmsize = spd0[4] + (spd0[5] / 2) + spd0[3] + (spd0[17] / 2) + 3; + size = (1 << bdimmsize) >> 20; /* size = xxx(MB) */ + data |= (((size / 16) - 1) << 16); + data |= (0 << 23); data |= 8; - writel(data, mmio + PDC_DIMM0_CONTROL); + writel(data, mmio + PDC_DIMM0_CONTROL); readl(mmio + PDC_DIMM0_CONTROL); - return size; + return size; } @@ -1172,9 +1172,9 @@ static unsigned int pdc20621_prog_dimm_global(struct ata_host *host) void __iomem *mmio = host->iomap[PDC_MMIO_BAR]; /* hard-code chip #0 */ - mmio += PDC_CHIP0_OFS; + mmio += PDC_CHIP0_OFS; - /* + /* Set To Default : DIMM Module Global Control Register (0x022259F1) DIMM Arbitration Disable (bit 20) DIMM Data/Control Output Driving Selection (bit12 - bit15) @@ -1193,40 +1193,40 @@ static unsigned int pdc20621_prog_dimm_global(struct ata_host *host) writel(data, mmio + PDC_SDRAM_CONTROL); readl(mmio + PDC_SDRAM_CONTROL); printk(KERN_ERR "Local DIMM ECC Enabled\n"); - } + } - /* DIMM Initialization Select/Enable (bit 18/19) */ - data &= (~(1<<18)); - data |= (1<<19); - writel(data, mmio + PDC_SDRAM_CONTROL); + /* DIMM Initialization Select/Enable (bit 18/19) */ + data &= (~(1<<18)); + data |= (1<<19); + writel(data, mmio + PDC_SDRAM_CONTROL); - error = 1; - for (i = 1; i <= 10; i++) { /* polling ~5 secs */ + error = 1; + for (i = 1; i <= 10; i++) { /* polling ~5 secs */ data = readl(mmio + PDC_SDRAM_CONTROL); if (!(data & (1<<19))) { - error = 0; - break; + error = 0; + break; } msleep(i*100); - } - return error; + } + return error; } static unsigned int pdc20621_dimm_init(struct ata_host *host) { int speed, size, length; - u32 addr,spd0,pci_status; - u32 tmp=0; - u32 time_period=0; - u32 tcount=0; - u32 ticks=0; - u32 clock=0; - u32 fparam=0; + u32 addr, spd0, pci_status; + u32 tmp = 0; + u32 time_period = 0; + u32 tcount = 0; + u32 ticks = 0; + u32 clock = 0; + u32 fparam = 0; void __iomem *mmio = host->iomap[PDC_MMIO_BAR]; /* hard-code chip #0 */ - mmio += PDC_CHIP0_OFS; + mmio += PDC_CHIP0_OFS; /* Initialize PLL based upon PCI Bus Frequency */ @@ -1254,7 +1254,7 @@ static unsigned int pdc20621_dimm_init(struct ata_host *host) If SX4 is on PCI-X bus, after 3 seconds, the timer counter register should be >= (0xffffffff - 3x10^8). */ - if(tcount >= PCI_X_TCOUNT) { + if (tcount >= PCI_X_TCOUNT) { ticks = (time_period - tcount); VPRINTK("Num counters 0x%x (%d)\n", ticks, ticks); @@ -1285,41 +1285,43 @@ static unsigned int pdc20621_dimm_init(struct ata_host *host) if (!(speed = pdc20621_detect_dimm(host))) { printk(KERN_ERR "Detect Local DIMM Fail\n"); return 1; /* DIMM error */ - } - VPRINTK("Local DIMM Speed = %d\n", speed); + } + VPRINTK("Local DIMM Speed = %d\n", speed); - /* Programming DIMM0 Module Control Register (index_CID0:80h) */ + /* Programming DIMM0 Module Control Register (index_CID0:80h) */ size = pdc20621_prog_dimm0(host); - VPRINTK("Local DIMM Size = %dMB\n",size); + VPRINTK("Local DIMM Size = %dMB\n", size); - /* Programming DIMM Module Global Control Register (index_CID0:88h) */ + /* Programming DIMM Module Global Control Register (index_CID0:88h) */ if (pdc20621_prog_dimm_global(host)) { printk(KERN_ERR "Programming DIMM Module Global Control Register Fail\n"); return 1; - } + } #ifdef ATA_VERBOSE_DEBUG { - u8 test_parttern1[40] = {0x55,0xAA,'P','r','o','m','i','s','e',' ', - 'N','o','t',' ','Y','e','t',' ','D','e','f','i','n','e','d',' ', - '1','.','1','0', - '9','8','0','3','1','6','1','2',0,0}; + u8 test_parttern1[40] = + {0x55,0xAA,'P','r','o','m','i','s','e',' ', + 'N','o','t',' ','Y','e','t',' ', + 'D','e','f','i','n','e','d',' ', + '1','.','1','0', + '9','8','0','3','1','6','1','2',0,0}; u8 test_parttern2[40] = {0}; - pdc20621_put_to_dimm(host, (void *) test_parttern2, 0x10040, 40); - pdc20621_put_to_dimm(host, (void *) test_parttern2, 0x40, 40); + pdc20621_put_to_dimm(host, test_parttern2, 0x10040, 40); + pdc20621_put_to_dimm(host, test_parttern2, 0x40, 40); - pdc20621_put_to_dimm(host, (void *) test_parttern1, 0x10040, 40); - pdc20621_get_from_dimm(host, (void *) test_parttern2, 0x40, 40); + pdc20621_put_to_dimm(host, test_parttern1, 0x10040, 40); + pdc20621_get_from_dimm(host, test_parttern2, 0x40, 40); printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], test_parttern2[1], &(test_parttern2[2])); - pdc20621_get_from_dimm(host, (void *) test_parttern2, 0x10040, + pdc20621_get_from_dimm(host, test_parttern2, 0x10040, 40); printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], test_parttern2[1], &(test_parttern2[2])); - pdc20621_put_to_dimm(host, (void *) test_parttern1, 0x40, 40); - pdc20621_get_from_dimm(host, (void *) test_parttern2, 0x40, 40); + pdc20621_put_to_dimm(host, test_parttern1, 0x40, 40); + pdc20621_get_from_dimm(host, test_parttern2, 0x40, 40); printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], test_parttern2[1], &(test_parttern2[2])); } @@ -1375,7 +1377,8 @@ static void pdc_20621_init(struct ata_host *host) readl(mmio + PDC_HDMA_CTLSTAT); /* flush */ } -static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +static int pdc_sata_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { static int printed_version; const struct ata_port_info *ppi[] = diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c index d394da085ae..e710e71b7b9 100644 --- a/drivers/ata/sata_uli.c +++ b/drivers/ata/sata_uli.c @@ -56,9 +56,9 @@ struct uli_priv { unsigned int scr_cfg_addr[uli_max_ports]; }; -static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); -static int uli_scr_read (struct ata_port *ap, unsigned int sc_reg, u32 *val); -static int uli_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); +static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); +static int uli_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val); +static int uli_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val); static const struct pci_device_id uli_pci_tbl[] = { { PCI_VDEVICE(AL, 0x5289), uli_5289 }, @@ -143,7 +143,7 @@ static unsigned int get_scr_cfg_addr(struct ata_port *ap, unsigned int sc_reg) return hpriv->scr_cfg_addr[ap->port_no] + (4 * sc_reg); } -static u32 uli_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg) +static u32 uli_scr_cfg_read(struct ata_port *ap, unsigned int sc_reg) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); unsigned int cfg_addr = get_scr_cfg_addr(ap, sc_reg); @@ -153,7 +153,7 @@ static u32 uli_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg) return val; } -static void uli_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val) +static void uli_scr_cfg_write(struct ata_port *ap, unsigned int scr, u32 val) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); unsigned int cfg_addr = get_scr_cfg_addr(ap, scr); @@ -161,7 +161,7 @@ static void uli_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val) pci_write_config_dword(pdev, cfg_addr, val); } -static int uli_scr_read (struct ata_port *ap, unsigned int sc_reg, u32 *val) +static int uli_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) { if (sc_reg > SCR_CONTROL) return -EINVAL; @@ -170,16 +170,16 @@ static int uli_scr_read (struct ata_port *ap, unsigned int sc_reg, u32 *val) return 0; } -static int uli_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) +static int uli_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val) { - if (sc_reg > SCR_CONTROL) //SCR_CONTROL=2, SCR_ERROR=1, SCR_STATUS=0 + if (sc_reg > SCR_CONTROL) //SCR_CONTROL=2, SCR_ERROR=1, SCR_STATUS=0 return -EINVAL; uli_scr_cfg_write(ap, sc_reg, val); return 0; } -static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; const struct ata_port_info *ppi[] = { &uli_port_info, NULL }; diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index cc6ee0890f5..3ef072ff319 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -3,7 +3,7 @@ * * Maintained by: Jeff Garzik <jgarzik@pobox.com> * Please ALWAYS copy linux-ide@vger.kernel.org - on emails. + * on emails. * * Copyright 2003-2004 Red Hat, Inc. All rights reserved. * Copyright 2003-2004 Jeff Garzik @@ -69,7 +69,7 @@ enum { SATA_EXT_PHY = (1 << 6), /* 0==use PATA, 1==ext phy */ }; -static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); +static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); static int svia_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val); static int svia_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val); static void svia_noop_freeze(struct ata_port *ap); @@ -372,12 +372,12 @@ static const unsigned int vt6421_bar_sizes[] = { 16, 16, 16, 16, 32, 128 }; -static void __iomem * svia_scr_addr(void __iomem *addr, unsigned int port) +static void __iomem *svia_scr_addr(void __iomem *addr, unsigned int port) { return addr + (port * 128); } -static void __iomem * vt6421_scr_addr(void __iomem *addr, unsigned int port) +static void __iomem *vt6421_scr_addr(void __iomem *addr, unsigned int port) { return addr + (port * 64); } @@ -472,7 +472,7 @@ static void svia_configure(struct pci_dev *pdev) if ((tmp8 & ALL_PORTS) != ALL_PORTS) { dev_printk(KERN_DEBUG, &pdev->dev, "enabling SATA channels (0x%x)\n", - (int) tmp8); + (int) tmp8); tmp8 |= ALL_PORTS; pci_write_config_byte(pdev, SATA_CHAN_ENAB, tmp8); } @@ -482,7 +482,7 @@ static void svia_configure(struct pci_dev *pdev) if ((tmp8 & ALL_PORTS) != ALL_PORTS) { dev_printk(KERN_DEBUG, &pdev->dev, "enabling SATA channel interrupts (0x%x)\n", - (int) tmp8); + (int) tmp8); tmp8 |= ALL_PORTS; pci_write_config_byte(pdev, SATA_INT_GATE, tmp8); } @@ -492,13 +492,13 @@ static void svia_configure(struct pci_dev *pdev) if ((tmp8 & NATIVE_MODE_ALL) != NATIVE_MODE_ALL) { dev_printk(KERN_DEBUG, &pdev->dev, "enabling SATA channel native mode (0x%x)\n", - (int) tmp8); + (int) tmp8); tmp8 |= NATIVE_MODE_ALL; pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8); } } -static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; unsigned int i; @@ -525,8 +525,8 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) dev_printk(KERN_ERR, &pdev->dev, "invalid PCI BAR %u (sz 0x%llx, val 0x%llx)\n", i, - (unsigned long long)pci_resource_start(pdev, i), - (unsigned long long)pci_resource_len(pdev, i)); + (unsigned long long)pci_resource_start(pdev, i), + (unsigned long long)pci_resource_len(pdev, i)); return -ENODEV; } diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c index 0d9be168487..95ae3ed24a9 100644 --- a/drivers/ata/sata_vsc.c +++ b/drivers/ata/sata_vsc.c @@ -162,7 +162,8 @@ static void vsc_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) /* * The only thing the ctl register is used for is SRST. * That is not enabled or disabled via tf_load. - * However, if ATA_NIEN is changed, then we need to change the interrupt register. + * However, if ATA_NIEN is changed, then we need to change + * the interrupt register. */ if ((tf->ctl & ATA_NIEN) != (ap->last_ctl & ATA_NIEN)) { ap->last_ctl = tf->ctl; @@ -219,7 +220,7 @@ static void vsc_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) tf->hob_lbal = lbal >> 8; tf->hob_lbam = lbam >> 8; tf->hob_lbah = lbah >> 8; - } + } } static inline void vsc_error_intr(u8 port_status, struct ata_port *ap) @@ -256,9 +257,10 @@ static void vsc_port_intr(u8 port_status, struct ata_port *ap) /* * vsc_sata_interrupt * - * Read the interrupt register and process for the devices that have them pending. + * Read the interrupt register and process for the devices that have + * them pending. */ -static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance) +static irqreturn_t vsc_sata_interrupt(int irq, void *dev_instance) { struct ata_host *host = dev_instance; unsigned int i; @@ -287,7 +289,7 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance) handled++; } else dev_printk(KERN_ERR, host->dev, - ": interrupt from disabled port %d\n", i); + "interrupt from disabled port %d\n", i); } } @@ -363,7 +365,8 @@ static void __devinit vsc_sata_setup_port(struct ata_ioports *port, } -static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +static int __devinit vsc_sata_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { static const struct ata_port_info pi = { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c index f8f7139c07c..c662d686154 100644 --- a/drivers/atm/firestream.c +++ b/drivers/atm/firestream.c @@ -171,8 +171,8 @@ static char *res_strings[] = { "packet purged", "packet ageing timeout", "channel ageing timeout", - "calculated lenght error", - "programmed lenght limit error", + "calculated length error", + "programmed length limit error", "aal5 crc32 error", "oam transp or transpc crc10 error", "reserved 25", diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index 8b12925fe7a..f97e050338f 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -2689,7 +2689,7 @@ fore200e_init(struct fore200e* fore200e) return 0; } - +#ifdef CONFIG_ATM_FORE200E_PCA static int __devinit fore200e_pca_detect(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent) { @@ -2756,7 +2756,6 @@ static void __devexit fore200e_pca_remove_one(struct pci_dev *pci_dev) } -#ifdef CONFIG_ATM_FORE200E_PCA static struct pci_device_id fore200e_pca_tbl[] = { { PCI_VENDOR_ID_FORE, PCI_DEVICE_ID_FORE_PCA200E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &fore200e_bus[0] }, diff --git a/drivers/atm/he.c b/drivers/atm/he.c index d33aba6864c..3b64a99772e 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/atm/nicstar.c b/drivers/atm/nicstar.c index 14ced85b3f5..0c205b000e8 100644 --- a/drivers/atm/nicstar.c +++ b/drivers/atm/nicstar.c @@ -625,14 +625,6 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev) if (mac[i] == NULL) nicstar_init_eprom(card->membase); - if (request_irq(pcidev->irq, &ns_irq_handler, IRQF_DISABLED | IRQF_SHARED, "nicstar", card) != 0) - { - printk("nicstar%d: can't allocate IRQ %d.\n", i, pcidev->irq); - error = 9; - ns_init_card_error(card, error); - return error; - } - /* Set the VPI/VCI MSb mask to zero so we can receive OAM cells */ writel(0x00000000, card->membase + VPM); @@ -858,8 +850,6 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev) card->iovpool.count++; } - card->intcnt = 0; - /* Configure NICStAR */ if (card->rct_size == 4096) ns_cfg_rctsize = NS_CFG_RCTSIZE_4096_ENTRIES; @@ -868,6 +858,15 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev) card->efbie = 1; + card->intcnt = 0; + if (request_irq(pcidev->irq, &ns_irq_handler, IRQF_DISABLED | IRQF_SHARED, "nicstar", card) != 0) + { + printk("nicstar%d: can't allocate IRQ %d.\n", i, pcidev->irq); + error = 9; + ns_init_card_error(card, error); + return error; + } + /* Register device */ card->atmdev = atm_dev_register("nicstar", &atm_ops, -1, NULL); if (card->atmdev == NULL) diff --git a/drivers/base/core.c b/drivers/base/core.c index c1343414d28..2683eac30c6 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, @@ -1228,18 +1230,18 @@ int device_rename(struct device *dev, char *new_name) sysfs_remove_link(&dev->parent->kobj, old_class_name); } } -#endif - +#else if (dev->class) { sysfs_remove_link(&dev->class->subsys.kobj, old_device_name); error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj, dev->bus_id); if (error) { - /* Uh... how to unravel this if restoring can fail? */ dev_err(dev, "%s: sysfs_create_symlink failed (%d)\n", __FUNCTION__, error); } } +#endif + out: put_device(dev); diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c index 5beddc322e6..b5034dc72a0 100644 --- a/drivers/base/dmapool.c +++ b/drivers/base/dmapool.c @@ -2,7 +2,6 @@ #include <linux/device.h> #include <linux/mm.h> #include <asm/io.h> /* Needed for i386 to build */ -#include <asm/scatterlist.h> /* Needed for i386 to build */ #include <linux/dma-mapping.h> #include <linux/dmapool.h> #include <linux/slab.h> diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile index a803733c839..44504e6618f 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 0ab4ab21f56..691ffb64cc3 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 5c4efd493fa..379da4e958e 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/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index b1d00ef6659..ad00b3d9471 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -6,6 +6,7 @@ #include <linux/hdreg.h> #include <linux/blkdev.h> +#include <linux/backing-dev.h> #include <linux/fs.h> #include <linux/ioctl.h> #include <linux/genhd.h> @@ -210,25 +211,20 @@ aoeblk_gdalloc(void *vp) if (gd == NULL) { printk(KERN_ERR "aoe: cannot allocate disk structure for %ld.%ld\n", d->aoemajor, d->aoeminor); - spin_lock_irqsave(&d->lock, flags); - d->flags &= ~DEVFL_GDALLOC; - spin_unlock_irqrestore(&d->lock, flags); - return; + goto err; } d->bufpool = mempool_create_slab_pool(MIN_BUFS, buf_pool_cache); if (d->bufpool == NULL) { printk(KERN_ERR "aoe: cannot allocate bufpool for %ld.%ld\n", d->aoemajor, d->aoeminor); - put_disk(gd); - spin_lock_irqsave(&d->lock, flags); - d->flags &= ~DEVFL_GDALLOC; - spin_unlock_irqrestore(&d->lock, flags); - return; + goto err_disk; } - spin_lock_irqsave(&d->lock, flags); blk_queue_make_request(&d->blkq, aoeblk_make_request); + if (bdi_init(&d->blkq.backing_dev_info)) + goto err_mempool; + spin_lock_irqsave(&d->lock, flags); gd->major = AOE_MAJOR; gd->first_minor = d->sysminor * AOE_PARTITIONS; gd->fops = &aoe_bdops; @@ -246,6 +242,16 @@ aoeblk_gdalloc(void *vp) add_disk(gd); aoedisk_add_sysfs(d); + return; + +err_mempool: + mempool_destroy(d->bufpool); +err_disk: + put_disk(gd); +err: + spin_lock_irqsave(&d->lock, flags); + d->flags &= ~DEVFL_GDALLOC; + spin_unlock_irqrestore(&d->lock, flags); } void diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 5a6fe17fc63..509b6490413 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -1,20 +1,20 @@ /* - * Disk Array driver for HP SA 5xxx and 6xxx Controllers - * Copyright 2000, 2006 Hewlett-Packard Development Company, L.P. + * Disk Array driver for HP Smart Array controllers. + * (C) Copyright 2000, 2007 Hewlett-Packard Development Company, L.P. * * 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. + * the Free Software Foundation; version 2 of the License. * * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more details. + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA. * * Questions/Comments/Bugfixes to iss_storagedev@hp.com * @@ -2927,7 +2927,7 @@ default_int_mode: return; } -static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) +static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) { ushort subsystem_vendor_id, subsystem_device_id, command; __u32 board_id, scratchpad = 0; diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index 4aca7ddfddd..63ee6c076cb 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -1,20 +1,20 @@ /* - * Disk Array driver for Compaq SA53xx Controllers, SCSI Tape module - * Copyright 2001 Compaq Computer Corporation + * Disk Array driver for HP Smart Array controllers, SCSI Tape module. + * (C) Copyright 2001, 2007 Hewlett-Packard Development Company, L.P. * * 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. + * the Free Software Foundation; version 2 of the License. * * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more details. + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 59 Temple Place, Suite 300, Boston, MA + * 02111-1307, USA. * * Questions/Comments/Bugfixes to iss_storagedev@hp.com * diff --git a/drivers/block/cciss_scsi.h b/drivers/block/cciss_scsi.h index 5e7e06c07d6..d9c2c586502 100644 --- a/drivers/block/cciss_scsi.h +++ b/drivers/block/cciss_scsi.h @@ -1,20 +1,20 @@ /* - * Disk Array driver for Compaq SA53xx Controllers, SCSI Tape module - * Copyright 2001 Compaq Computer Corporation + * Disk Array driver for HP Smart Array controllers, SCSI Tape module. + * (C) Copyright 2001, 2007 Hewlett-Packard Development Company, L.P. * * 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. + * the Free Software Foundation; version 2 of the License. * * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more details. + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 59 Temple Place, Suite 300, Boston, MA + * 02111-1307, USA. * * Questions/Comments/Bugfixes to iss_storagedev@hp.com * diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 56e23042728..b8af22e610d 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -610,7 +610,7 @@ static int loop_thread(void *data) static int loop_switch(struct loop_device *lo, struct file *file) { struct switch_request w; - struct bio *bio = bio_alloc(GFP_KERNEL, 1); + struct bio *bio = bio_alloc(GFP_KERNEL, 0); if (!bio) return -ENOMEM; init_completion(&w.wait); diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 6332acad078..b4c0888aedc 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 ceffa6034e2..e7fe6ca97dd 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/paride/pt.c b/drivers/block/paride/pt.c index 9f4e67ee1eb..b91accf1265 100644 --- a/drivers/block/paride/pt.c +++ b/drivers/block/paride/pt.c @@ -664,7 +664,7 @@ static int pt_open(struct inode *inode, struct file *file) goto out; err = -EROFS; - if ((!tape->flags & PT_WRITE_OK) && (file->f_mode & 2)) + if ((!(tape->flags & PT_WRITE_OK)) && (file->f_mode & 2)) goto out; if (!(iminor(inode) & 128)) diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index a8130a4ad6d..3535ef89667 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -117,8 +117,10 @@ static struct pktcdvd_kobj* pkt_kobj_create(struct pktcdvd_device *pd, p->kobj.parent = parent; p->kobj.ktype = ktype; p->pd = pd; - if (kobject_register(&p->kobj) != 0) + if (kobject_register(&p->kobj) != 0) { + kobject_put(&p->kobj); return NULL; + } return p; } /* @@ -358,10 +360,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 47f8ac6cce5..82f4eecc869 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/umem.c b/drivers/block/umem.c index 99806f9ee4c..c24e1bdbad4 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -34,7 +34,7 @@ * - set initialised bit then. */ -//#define DEBUG /* uncomment if you want debugging info (pr_debug) */ +#undef DEBUG /* #define DEBUG if you want debugging info (pr_debug) */ #include <linux/fs.h> #include <linux/bio.h> #include <linux/kernel.h> @@ -143,17 +143,12 @@ static struct cardinfo cards[MM_MAXCARDS]; static struct block_device_operations mm_fops; static struct timer_list battery_timer; -static int num_cards = 0; +static int num_cards; static struct gendisk *mm_gendisk[MM_MAXCARDS]; static void check_batteries(struct cardinfo *card); -/* ------------------------------------------------------------------------------------ --- get_userbit ------------------------------------------------------------------------------------ -*/ static int get_userbit(struct cardinfo *card, int bit) { unsigned char led; @@ -161,11 +156,7 @@ static int get_userbit(struct cardinfo *card, int bit) led = readb(card->csr_remap + MEMCTRLCMD_LEDCTRL); return led & bit; } -/* ------------------------------------------------------------------------------------ --- set_userbit ------------------------------------------------------------------------------------ -*/ + static int set_userbit(struct cardinfo *card, int bit, unsigned char state) { unsigned char led; @@ -179,11 +170,7 @@ static int set_userbit(struct cardinfo *card, int bit, unsigned char state) return 0; } -/* ------------------------------------------------------------------------------------ --- set_led ------------------------------------------------------------------------------------ -*/ + /* * NOTE: For the power LED, use the LED_POWER_* macros since they differ */ @@ -203,11 +190,6 @@ static void set_led(struct cardinfo *card, int shift, unsigned char state) } #ifdef MM_DIAG -/* ------------------------------------------------------------------------------------ --- dump_regs ------------------------------------------------------------------------------------ -*/ static void dump_regs(struct cardinfo *card) { unsigned char *p; @@ -224,32 +206,28 @@ static void dump_regs(struct cardinfo *card) } } #endif -/* ------------------------------------------------------------------------------------ --- dump_dmastat ------------------------------------------------------------------------------------ -*/ + static void dump_dmastat(struct cardinfo *card, unsigned int dmastat) { dev_printk(KERN_DEBUG, &card->dev->dev, "DMAstat - "); if (dmastat & DMASCR_ANY_ERR) - printk("ANY_ERR "); + printk(KERN_CONT "ANY_ERR "); if (dmastat & DMASCR_MBE_ERR) - printk("MBE_ERR "); + printk(KERN_CONT "MBE_ERR "); if (dmastat & DMASCR_PARITY_ERR_REP) - printk("PARITY_ERR_REP "); + printk(KERN_CONT "PARITY_ERR_REP "); if (dmastat & DMASCR_PARITY_ERR_DET) - printk("PARITY_ERR_DET "); + printk(KERN_CONT "PARITY_ERR_DET "); if (dmastat & DMASCR_SYSTEM_ERR_SIG) - printk("SYSTEM_ERR_SIG "); + printk(KERN_CONT "SYSTEM_ERR_SIG "); if (dmastat & DMASCR_TARGET_ABT) - printk("TARGET_ABT "); + printk(KERN_CONT "TARGET_ABT "); if (dmastat & DMASCR_MASTER_ABT) - printk("MASTER_ABT "); + printk(KERN_CONT "MASTER_ABT "); if (dmastat & DMASCR_CHAIN_COMPLETE) - printk("CHAIN_COMPLETE "); + printk(KERN_CONT "CHAIN_COMPLETE "); if (dmastat & DMASCR_DMA_COMPLETE) - printk("DMA_COMPLETE "); + printk(KERN_CONT "DMA_COMPLETE "); printk("\n"); } @@ -286,7 +264,8 @@ static void mm_start_io(struct cardinfo *card) /* make the last descriptor end the chain */ page = &card->mm_pages[card->Active]; - pr_debug("start_io: %d %d->%d\n", card->Active, page->headcnt, page->cnt-1); + pr_debug("start_io: %d %d->%d\n", + card->Active, page->headcnt, page->cnt - 1); desc = &page->desc[page->cnt-1]; desc->control_bits |= cpu_to_le32(DMASCR_CHAIN_COMP_EN); @@ -310,8 +289,8 @@ static void mm_start_io(struct cardinfo *card) writel(0, card->csr_remap + DMA_SEMAPHORE_ADDR); writel(0, card->csr_remap + DMA_SEMAPHORE_ADDR + 4); - offset = ((char*)desc) - ((char*)page->desc); - writel(cpu_to_le32((page->page_dma+offset)&0xffffffff), + offset = ((char *)desc) - ((char *)page->desc); + writel(cpu_to_le32((page->page_dma+offset) & 0xffffffff), card->csr_remap + DMA_DESCRIPTOR_ADDR); /* Force the value to u64 before shifting otherwise >> 32 is undefined C * and on some ports will do nothing ! */ @@ -352,7 +331,7 @@ static inline void reset_page(struct mm_page *page) page->cnt = 0; page->headcnt = 0; page->bio = NULL; - page->biotail = & page->bio; + page->biotail = &page->bio; } static void mm_unplug_device(struct request_queue *q) @@ -408,7 +387,7 @@ static int add_bio(struct cardinfo *card) vec->bv_page, vec->bv_offset, len, - (rw==READ) ? + (rw == READ) ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); p = &card->mm_pages[card->Ready]; @@ -427,10 +406,10 @@ static int add_bio(struct cardinfo *card) desc->pci_addr = cpu_to_le64((u64)desc->data_dma_handle); desc->local_addr = cpu_to_le64(card->current_sector << 9); desc->transfer_size = cpu_to_le32(len); - offset = ( ((char*)&desc->sem_control_bits) - ((char*)p->desc)); + offset = (((char *)&desc->sem_control_bits) - ((char *)p->desc)); desc->sem_addr = cpu_to_le64((u64)(p->page_dma+offset)); desc->zero1 = desc->zero2 = 0; - offset = ( ((char*)(desc+1)) - ((char*)p->desc)); + offset = (((char *)(desc+1)) - ((char *)p->desc)); desc->next_desc_addr = cpu_to_le64(p->page_dma+offset); desc->control_bits = cpu_to_le32(DMASCR_GO|DMASCR_ERR_INT_EN| DMASCR_PARITY_INT_EN| @@ -455,11 +434,11 @@ static void process_page(unsigned long data) /* check if any of the requests in the page are DMA_COMPLETE, * and deal with them appropriately. * If we find a descriptor without DMA_COMPLETE in the semaphore, then - * dma must have hit an error on that descriptor, so use dma_status instead - * and assume that all following descriptors must be re-tried. + * dma must have hit an error on that descriptor, so use dma_status + * instead and assume that all following descriptors must be re-tried. */ struct mm_page *page; - struct bio *return_bio=NULL; + struct bio *return_bio = NULL; struct cardinfo *card = (struct cardinfo *)data; unsigned int dma_status = card->dma_status; @@ -472,24 +451,25 @@ static void process_page(unsigned long data) struct bio *bio = page->bio; struct mm_dma_desc *desc = &page->desc[page->headcnt]; int control = le32_to_cpu(desc->sem_control_bits); - int last=0; + int last = 0; int idx; if (!(control & DMASCR_DMA_COMPLETE)) { control = dma_status; - last=1; + last = 1; } page->headcnt++; idx = page->idx; page->idx++; if (page->idx >= bio->bi_vcnt) { page->bio = bio->bi_next; - page->idx = page->bio->bi_idx; + if (page->bio) + page->idx = page->bio->bi_idx; } pci_unmap_page(card->dev, desc->data_dma_handle, - bio_iovec_idx(bio,idx)->bv_len, - (control& DMASCR_TRANSFER_READ) ? + bio_iovec_idx(bio, idx)->bv_len, + (control & DMASCR_TRANSFER_READ) ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); if (control & DMASCR_HARD_ERROR) { /* error */ @@ -500,9 +480,10 @@ static void process_page(unsigned long data) le32_to_cpu(desc->transfer_size)); dump_dmastat(card, control); } else if (test_bit(BIO_RW, &bio->bi_rw) && - le32_to_cpu(desc->local_addr)>>9 == card->init_size) { - card->init_size += le32_to_cpu(desc->transfer_size)>>9; - if (card->init_size>>1 >= card->mm_size) { + le32_to_cpu(desc->local_addr) >> 9 == + card->init_size) { + card->init_size += le32_to_cpu(desc->transfer_size) >> 9; + if (card->init_size >> 1 >= card->mm_size) { dev_printk(KERN_INFO, &card->dev->dev, "memory now initialised\n"); set_userbit(card, MEMORY_INITIALIZED, 1); @@ -513,7 +494,8 @@ static void process_page(unsigned long data) return_bio = bio; } - if (last) break; + if (last) + break; } if (debug & DEBUG_LED_ON_TRANSFER) @@ -535,7 +517,7 @@ static void process_page(unsigned long data) out_unlock: spin_unlock_bh(&card->lock); - while(return_bio) { + while (return_bio) { struct bio *bio = return_bio; return_bio = bio->bi_next; @@ -544,11 +526,6 @@ static void process_page(unsigned long data) } } -/* ------------------------------------------------------------------------------------ --- mm_make_request ------------------------------------------------------------------------------------ -*/ static int mm_make_request(struct request_queue *q, struct bio *bio) { struct cardinfo *card = q->queuedata; @@ -565,11 +542,6 @@ static int mm_make_request(struct request_queue *q, struct bio *bio) return 0; } -/* ------------------------------------------------------------------------------------ --- mm_interrupt ------------------------------------------------------------------------------------ -*/ static irqreturn_t mm_interrupt(int irq, void *__card) { struct cardinfo *card = (struct cardinfo *) __card; @@ -583,15 +555,15 @@ HW_TRACE(0x30); if (!(dma_status & (DMASCR_ERROR_MASK | DMASCR_CHAIN_COMPLETE))) { /* interrupt wasn't for me ... */ return IRQ_NONE; - } + } /* clear COMPLETION interrupts */ if (card->flags & UM_FLAG_NO_BYTE_STATUS) writel(cpu_to_le32(DMASCR_DMA_COMPLETE|DMASCR_CHAIN_COMPLETE), - card->csr_remap+ DMA_STATUS_CTRL); + card->csr_remap + DMA_STATUS_CTRL); else writeb((DMASCR_DMA_COMPLETE|DMASCR_CHAIN_COMPLETE) >> 16, - card->csr_remap+ DMA_STATUS_CTRL + 2); + card->csr_remap + DMA_STATUS_CTRL + 2); /* log errors and clear interrupt status */ if (dma_status & DMASCR_ANY_ERR) { @@ -601,9 +573,12 @@ HW_TRACE(0x30); stat = readb(card->csr_remap + MEMCTRLCMD_ERRSTATUS); - data_log1 = le32_to_cpu(readl(card->csr_remap + ERROR_DATA_LOG)); - data_log2 = le32_to_cpu(readl(card->csr_remap + ERROR_DATA_LOG + 4)); - addr_log1 = le32_to_cpu(readl(card->csr_remap + ERROR_ADDR_LOG)); + data_log1 = le32_to_cpu(readl(card->csr_remap + + ERROR_DATA_LOG)); + data_log2 = le32_to_cpu(readl(card->csr_remap + + ERROR_DATA_LOG + 4)); + addr_log1 = le32_to_cpu(readl(card->csr_remap + + ERROR_ADDR_LOG)); addr_log2 = readb(card->csr_remap + ERROR_ADDR_LOG + 4); count = readb(card->csr_remap + ERROR_COUNT); @@ -670,11 +645,7 @@ HW_TRACE(0x36); return IRQ_HANDLED; } -/* ------------------------------------------------------------------------------------ --- set_fault_to_battery_status ------------------------------------------------------------------------------------ -*/ + /* * If both batteries are good, no LED * If either battery has been warned, solid LED @@ -695,12 +666,6 @@ static void set_fault_to_battery_status(struct cardinfo *card) static void init_battery_timer(void); - -/* ------------------------------------------------------------------------------------ --- check_battery ------------------------------------------------------------------------------------ -*/ static int check_battery(struct cardinfo *card, int battery, int status) { if (status != card->battery[battery].good) { @@ -729,11 +694,7 @@ static int check_battery(struct cardinfo *card, int battery, int status) return 0; } -/* ------------------------------------------------------------------------------------ --- check_batteries ------------------------------------------------------------------------------------ -*/ + static void check_batteries(struct cardinfo *card) { /* NOTE: this must *never* be called while the card @@ -774,11 +735,7 @@ static void check_all_batteries(unsigned long ptr) init_battery_timer(); } -/* ------------------------------------------------------------------------------------ --- init_battery_timer ------------------------------------------------------------------------------------ -*/ + static void init_battery_timer(void) { init_timer(&battery_timer); @@ -786,20 +743,12 @@ static void init_battery_timer(void) battery_timer.expires = jiffies + (HZ * 60); add_timer(&battery_timer); } -/* ------------------------------------------------------------------------------------ --- del_battery_timer ------------------------------------------------------------------------------------ -*/ + static void del_battery_timer(void) { del_timer(&battery_timer); } -/* ------------------------------------------------------------------------------------ --- mm_revalidate ------------------------------------------------------------------------------------ -*/ + /* * Note no locks taken out here. In a worst case scenario, we could drop * a chunk of system memory. But that should never happen, since validation @@ -832,33 +781,23 @@ static int mm_getgeo(struct block_device *bdev, struct hd_geometry *geo) } /* ------------------------------------------------------------------------------------ --- mm_check_change ------------------------------------------------------------------------------------ - Future support for removable devices -*/ + * Future support for removable devices + */ static int mm_check_change(struct gendisk *disk) { /* struct cardinfo *dev = disk->private_data; */ return 0; } -/* ------------------------------------------------------------------------------------ --- mm_fops ------------------------------------------------------------------------------------ -*/ + static struct block_device_operations mm_fops = { .owner = THIS_MODULE, .getgeo = mm_getgeo, - .revalidate_disk= mm_revalidate, + .revalidate_disk = mm_revalidate, .media_changed = mm_check_change, }; -/* ------------------------------------------------------------------------------------ --- mm_pci_probe ------------------------------------------------------------------------------------ -*/ -static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) + +static int __devinit mm_pci_probe(struct pci_dev *dev, + const struct pci_device_id *id) { int ret = -ENODEV; struct cardinfo *card = &cards[num_cards]; @@ -888,7 +827,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i return -ENODEV; dev_printk(KERN_INFO, &dev->dev, - "Micro Memory(tm) controller found (PCI Mem Module (Battery Backup))\n"); + "Micro Memory(tm) controller found (PCI Mem Module (Battery Backup))\n"); if (pci_set_dma_mask(dev, DMA_64BIT_MASK) && pci_set_dma_mask(dev, DMA_32BIT_MASK)) { @@ -916,7 +855,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i "CSR 0x%08lx -> 0x%p (0x%lx)\n", csr_base, card->csr_remap, csr_len); - switch(card->dev->device) { + switch (card->dev->device) { case 0x5415: card->flags |= UM_FLAG_NO_BYTE_STATUS | UM_FLAG_NO_BATTREG; magic_number = 0x59; @@ -928,7 +867,8 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i break; case 0x6155: - card->flags |= UM_FLAG_NO_BYTE_STATUS | UM_FLAG_NO_BATTREG | UM_FLAG_NO_BATT; + card->flags |= UM_FLAG_NO_BYTE_STATUS | + UM_FLAG_NO_BATTREG | UM_FLAG_NO_BATT; magic_number = 0x99; break; @@ -944,11 +884,11 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i } card->mm_pages[0].desc = pci_alloc_consistent(card->dev, - PAGE_SIZE*2, - &card->mm_pages[0].page_dma); + PAGE_SIZE * 2, + &card->mm_pages[0].page_dma); card->mm_pages[1].desc = pci_alloc_consistent(card->dev, - PAGE_SIZE*2, - &card->mm_pages[1].page_dma); + PAGE_SIZE * 2, + &card->mm_pages[1].page_dma); if (card->mm_pages[0].desc == NULL || card->mm_pages[1].desc == NULL) { dev_printk(KERN_ERR, &card->dev->dev, "alloc failed\n"); @@ -1012,9 +952,9 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i dev_printk(KERN_INFO, &card->dev->dev, "Size %d KB, Battery 1 %s (%s), Battery 2 %s (%s)\n", card->mm_size, - (batt_status & BATTERY_1_DISABLED ? "Disabled" : "Enabled"), + batt_status & BATTERY_1_DISABLED ? "Disabled" : "Enabled", card->battery[0].good ? "OK" : "FAILURE", - (batt_status & BATTERY_2_DISABLED ? "Disabled" : "Enabled"), + batt_status & BATTERY_2_DISABLED ? "Disabled" : "Enabled", card->battery[1].good ? "OK" : "FAILURE"); set_fault_to_battery_status(card); @@ -1029,18 +969,18 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i data = ~data; data += 1; - if (request_irq(dev->irq, mm_interrupt, IRQF_SHARED, DRIVER_NAME, card)) { + if (request_irq(dev->irq, mm_interrupt, IRQF_SHARED, DRIVER_NAME, + card)) { dev_printk(KERN_ERR, &card->dev->dev, "Unable to allocate IRQ\n"); ret = -ENODEV; - goto failed_req_irq; } dev_printk(KERN_INFO, &card->dev->dev, "Window size %d bytes, IRQ %d\n", data, dev->irq); - spin_lock_init(&card->lock); + spin_lock_init(&card->lock); pci_set_drvdata(dev, card); @@ -1059,7 +999,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i if (!get_userbit(card, MEMORY_INITIALIZED)) { dev_printk(KERN_INFO, &card->dev->dev, - "memory NOT initialized. Consider over-writing whole device.\n"); + "memory NOT initialized. Consider over-writing whole device.\n"); card->init_size = 0; } else { dev_printk(KERN_INFO, &card->dev->dev, @@ -1090,11 +1030,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i return ret; } -/* ------------------------------------------------------------------------------------ --- mm_pci_remove ------------------------------------------------------------------------------------ -*/ + static void mm_pci_remove(struct pci_dev *dev) { struct cardinfo *card = pci_get_drvdata(dev); @@ -1118,16 +1054,16 @@ static void mm_pci_remove(struct pci_dev *dev) } static const struct pci_device_id mm_pci_ids[] = { - {PCI_DEVICE(PCI_VENDOR_ID_MICRO_MEMORY,PCI_DEVICE_ID_MICRO_MEMORY_5415CN)}, - {PCI_DEVICE(PCI_VENDOR_ID_MICRO_MEMORY,PCI_DEVICE_ID_MICRO_MEMORY_5425CN)}, - {PCI_DEVICE(PCI_VENDOR_ID_MICRO_MEMORY,PCI_DEVICE_ID_MICRO_MEMORY_6155)}, + {PCI_DEVICE(PCI_VENDOR_ID_MICRO_MEMORY, PCI_DEVICE_ID_MICRO_MEMORY_5415CN)}, + {PCI_DEVICE(PCI_VENDOR_ID_MICRO_MEMORY, PCI_DEVICE_ID_MICRO_MEMORY_5425CN)}, + {PCI_DEVICE(PCI_VENDOR_ID_MICRO_MEMORY, PCI_DEVICE_ID_MICRO_MEMORY_6155)}, { .vendor = 0x8086, .device = 0xB555, - .subvendor= 0x1332, - .subdevice= 0x5460, - .class = 0x050000, - .class_mask= 0, + .subvendor = 0x1332, + .subdevice = 0x5460, + .class = 0x050000, + .class_mask = 0, }, { /* end: all zeroes */ } }; @@ -1140,12 +1076,6 @@ static struct pci_driver mm_pci_driver = { .remove = mm_pci_remove, }; -/* ------------------------------------------------------------------------------------ --- mm_init ------------------------------------------------------------------------------------ -*/ - static int __init mm_init(void) { int retval, i; @@ -1192,18 +1122,14 @@ out: put_disk(mm_gendisk[i]); return -ENOMEM; } -/* ------------------------------------------------------------------------------------ --- mm_cleanup ------------------------------------------------------------------------------------ -*/ + static void __exit mm_cleanup(void) { int i; del_battery_timer(); - for (i=0; i < num_cards ; i++) { + for (i = 0; i < num_cards ; i++) { del_gendisk(mm_gendisk[i]); put_disk(mm_gendisk[i]); } diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 3cf7129d83e..924ddd8bccd 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/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index 8c3e62a17b4..b91d45a41b2 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -204,6 +204,19 @@ static void ll_device_want_to_wakeup(struct hci_uart *hu) spin_lock_irqsave(&ll->hcill_lock, flags); switch (ll->hcill_state) { + case HCILL_ASLEEP_TO_AWAKE: + /* + * This state means that both the host and the BRF chip + * have simultaneously sent a wake-up-indication packet. + * Traditionaly, in this case, receiving a wake-up-indication + * was enough and an additional wake-up-ack wasn't needed. + * This has changed with the BRF6350, which does require an + * explicit wake-up-ack. Other BRF versions, which do not + * require an explicit ack here, do accept it, thus it is + * perfectly safe to always send one. + */ + BT_DBG("dual wake-up-indication"); + /* deliberate fall-through - do not add break */ case HCILL_ASLEEP: /* acknowledge device wake up */ if (send_hcill_cmd(HCILL_WAKE_UP_ACK, hu) < 0) { @@ -211,16 +224,8 @@ static void ll_device_want_to_wakeup(struct hci_uart *hu) goto out; } break; - case HCILL_ASLEEP_TO_AWAKE: - /* - * this state means that a wake-up-indication - * is already on its way to the device, - * and will serve as the required wake-up-ack - */ - BT_DBG("dual wake-up-indication"); - break; default: - /* any other state are illegal */ + /* any other state is illegal */ BT_ERR("received HCILL_WAKE_UP_IND in state %ld", ll->hcill_state); break; } diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index bf18d757b87..ef1ed5d7012 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. @@ -543,28 +543,6 @@ config PPDEV If unsure, say N. -config TIPAR - tristate "Texas Instruments parallel link cable support" - depends on PARPORT - ---help--- - If you own a Texas Instruments graphing calculator and use a - parallel link cable, then you might be interested in this driver. - - If you enable this driver, you will be able to communicate with - your calculator through a set of device nodes under /dev. The - main advantage of this driver is that you don't have to be root - to use this precise link cable (depending on the permissions on - the device nodes, though). - - To compile this driver as a module, choose M here: the - module will be called tipar. - - If you don't know what a parallel link cable is or what a Texas - Instruments graphing calculator is, then you probably don't need this - driver. - - If unsure, say N. - config HVC_DRIVER bool help diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index f22c253bc09..ccb1fa89de2 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig @@ -56,9 +56,9 @@ config AGP_AMD X on AMD Irongate, 761, and 762 chipsets. config AGP_AMD64 - tristate "AMD Opteron/Athlon64 on-CPU GART support" if !IOMMU + tristate "AMD Opteron/Athlon64 on-CPU GART support" if !GART_IOMMU depends on AGP && X86 - default y if IOMMU + default y if GART_IOMMU help This option gives you AGP support for the GLX component of X using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs. diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index d95662e9632..d8200ac8f8c 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -787,7 +787,7 @@ static void __exit agp_amd64_cleanup(void) /* On AMD64 the PCI driver needs to initialize this driver early for the IOMMU, so it has to be called via a backdoor. */ -#ifndef CONFIG_IOMMU +#ifndef CONFIG_GART_IOMMU module_init(agp_amd64_init); module_exit(agp_amd64_cleanup); #endif diff --git a/drivers/char/apm-emulation.c b/drivers/char/apm-emulation.c index c99e43b837f..17d54315e14 100644 --- a/drivers/char/apm-emulation.c +++ b/drivers/char/apm-emulation.c @@ -295,7 +295,6 @@ static int apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) { struct apm_user *as = filp->private_data; - unsigned long flags; int err = -EINVAL; if (!as->suser || !as->writer) @@ -331,10 +330,16 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) * Wait for the suspend/resume to complete. If there * are pending acknowledges, we wait here for them. */ - flags = current->flags; + freezer_do_not_count(); wait_event(apm_suspend_waitqueue, as->suspend_state == SUSPEND_DONE); + + /* + * Since we are waiting until the suspend is done, the + * try_to_freeze() in freezer_count() will not trigger + */ + freezer_count(); } else { as->suspend_state = SUSPEND_WAIT; mutex_unlock(&state_lock); @@ -362,14 +367,10 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) * Wait for the suspend/resume to complete. If there * are pending acknowledges, we wait here for them. */ - flags = current->flags; - - wait_event_interruptible(apm_suspend_waitqueue, + wait_event_freezable(apm_suspend_waitqueue, as->suspend_state == SUSPEND_DONE); } - current->flags = flags; - mutex_lock(&state_lock); err = as->suspend_result; as->suspend_state = SUSPEND_NONE; diff --git a/drivers/char/cs5535_gpio.c b/drivers/char/cs5535_gpio.c index fe6d2407bae..c2d23cae951 100644 --- a/drivers/char/cs5535_gpio.c +++ b/drivers/char/cs5535_gpio.c @@ -104,6 +104,11 @@ static ssize_t cs5535_gpio_write(struct file *file, const char __user *data, for (j = 0; j < ARRAY_SIZE(rm); j++) { if (c == rm[j].on) { outl(m1, base + rm[j].wr_offset); + /* If enabling output, turn off AUX 1 and AUX 2 */ + if (c == 'O') { + outl(m0, base + 0x10); + outl(m0, base + 0x14); + } break; } else if (c == rm[j].off) { outl(m0, base + rm[j].wr_offset); diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 9dd0760dd87..dde02a15fa5 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -559,8 +559,6 @@ struct drm_mm { * a family of cards. There will one drm_device for each card present * in this family */ -struct drm_device; - struct drm_driver { int (*load) (struct drm_device *, unsigned long flags); int (*firstopen) (struct drm_device *); diff --git a/drivers/char/drm/drm_ioctl.c b/drivers/char/drm/drm_ioctl.c index d9be1462452..3cbebf868e6 100644 --- a/drivers/char/drm/drm_ioctl.c +++ b/drivers/char/drm/drm_ioctl.c @@ -272,7 +272,7 @@ int drm_getstats(struct drm_device *dev, void *data, struct drm_stats *stats = data; int i; - memset(stats, 0, sizeof(stats)); + memset(stats, 0, sizeof(*stats)); mutex_lock(&dev->struct_mutex); diff --git a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h index 76e44ac94fb..daa69c9d897 100644 --- a/drivers/char/drm/drm_os_linux.h +++ b/drivers/char/drm/drm_os_linux.h @@ -62,14 +62,6 @@ static __inline__ int mtrr_del(int reg, unsigned long base, unsigned long size) #endif -/** For data going into the kernel through the ioctl argument */ -#define DRM_COPY_FROM_USER_IOCTL(arg1, arg2, arg3) \ - if ( copy_from_user(&arg1, arg2, arg3) ) \ - return -EFAULT -/** For data going from the kernel through the ioctl argument */ -#define DRM_COPY_TO_USER_IOCTL(arg1, arg2, arg3) \ - if ( copy_to_user(arg1, &arg2, arg3) ) \ - return -EFAULT /** Other copying of data to kernel space */ #define DRM_COPY_FROM_USER(arg1, arg2, arg3) \ copy_from_user(arg1, arg2, arg3) diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c index 335423c5c18..24fca8ec137 100644 --- a/drivers/char/drm/radeon_cp.c +++ b/drivers/char/drm/radeon_cp.c @@ -1679,7 +1679,7 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) dev_priv->gart_info.bus_addr = dev_priv->pcigart_offset + dev_priv->fb_location; dev_priv->gart_info.mapping.offset = - dev_priv->gart_info.bus_addr; + dev_priv->pcigart_offset + dev_priv->fb_aper_offset; dev_priv->gart_info.mapping.size = dev_priv->gart_info.table_size; @@ -2275,7 +2275,8 @@ int radeon_driver_firstopen(struct drm_device *dev) if (ret != 0) return ret; - ret = drm_addmap(dev, drm_get_resource_start(dev, 0), + dev_priv->fb_aper_offset = drm_get_resource_start(dev, 0); + ret = drm_addmap(dev, dev_priv->fb_aper_offset, drm_get_resource_len(dev, 0), _DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING, &map); if (ret != 0) diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h index e4077bc212b..bfbb60a9298 100644 --- a/drivers/char/drm/radeon_drv.h +++ b/drivers/char/drm/radeon_drv.h @@ -293,6 +293,7 @@ typedef struct drm_radeon_private { /* starting from here on, data is preserved accross an open */ uint32_t flags; /* see radeon_chip_flags */ + unsigned long fb_aper_offset; } drm_radeon_private_t; typedef struct drm_radeon_buf_priv { diff --git a/drivers/char/drm/savage_bci.c b/drivers/char/drm/savage_bci.c index 59484d56b33..d465b2f9c1c 100644 --- a/drivers/char/drm/savage_bci.c +++ b/drivers/char/drm/savage_bci.c @@ -968,9 +968,6 @@ static int savage_bci_event_wait(struct drm_device *dev, void *data, struct drm_ DRM_DEBUG("\n"); - DRM_COPY_FROM_USER_IOCTL(event, (drm_savage_event_wait_t __user *) data, - sizeof(event)); - UPDATE_EVENT_COUNTER(); if (dev_priv->status_ptr) hw_e = dev_priv->status_ptr[1] & 0xffff; diff --git a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c index 6be1c575758..a6b7ccdaf73 100644 --- a/drivers/char/drm/sis_mm.c +++ b/drivers/char/drm/sis_mm.c @@ -134,6 +134,7 @@ static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file_priv, dev_priv->agp_initialized)) { DRM_ERROR ("Attempt to allocate from uninitialized memory manager.\n"); + mutex_unlock(&dev->struct_mutex); return -EINVAL; } diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index e686fc92516..8f45ca9235a 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -669,6 +669,7 @@ static int ipmi_ioctl(struct inode *inode, struct file *file, return 0; case WDIOC_SET_PRETIMEOUT: + case WDIOC_SETPRETIMEOUT: i = copy_from_user(&val, argp, sizeof(int)); if (i) return -EFAULT; @@ -676,6 +677,7 @@ static int ipmi_ioctl(struct inode *inode, struct file *file, return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); case WDIOC_GET_PRETIMEOUT: + case WDIOC_GETPRETIMEOUT: i = copy_to_user(argp, &pretimeout, sizeof(pretimeout)); if (i) return -EFAULT; diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 0e937f64a78..20070b7c573 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -41,7 +41,7 @@ */ static inline int uncached_access(struct file *file, unsigned long addr) { -#if defined(__i386__) +#if defined(__i386__) && !defined(__arch_um__) /* * On the PPro and successors, the MTRRs are used to set * memory types for physical addresses outside main memory, @@ -57,7 +57,7 @@ static inline int uncached_access(struct file *file, unsigned long addr) test_bit(X86_FEATURE_CYRIX_ARR, boot_cpu_data.x86_capability) || test_bit(X86_FEATURE_CENTAUR_MCR, boot_cpu_data.x86_capability) ) && addr >= __pa(high_memory); -#elif defined(__x86_64__) +#elif defined(__x86_64__) && !defined(__arch_um__) /* * This is broken because it can generate memory type aliases, * which can cause cache corruptions diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index cc5d77797de..02518da6a38 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 a0b9c8728d5..5f291bf739a 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 1756b1f7cb7..5fee0566182 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 ec6b65ec69e..0c66b802736 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/tipar.c b/drivers/char/tipar.c deleted file mode 100644 index cef55c40654..00000000000 --- a/drivers/char/tipar.c +++ /dev/null @@ -1,557 +0,0 @@ -/* Hey EMACS -*- linux-c -*- - * - * tipar - low level driver for handling a parallel link cable designed - * for Texas Instruments graphing calculators (http://lpg.ticalc.org). - * A part of the TiLP project. - * - * Copyright (C) 2000-2002, Romain Lievin <roms@lpg.ticalc.org> - * under the terms of the GNU General Public License. - * - * Various fixes & clean-up from the Linux Kernel Mailing List - * (Alan Cox, Richard B. Johnson, Christoph Hellwig). - */ - -/* This driver should, in theory, work with any parallel port that has an - * appropriate low-level driver; all I/O is done through the parport - * abstraction layer. - * - * If this driver is built into the kernel, you can configure it using the - * kernel command-line. For example: - * - * tipar=timeout,delay (set timeout and delay) - * - * If the driver is loaded as a module, similar functionality is available - * using module parameters. The equivalent of the above commands would be: - * - * # insmod tipar timeout=15 delay=10 - */ - -/* COMPATIBILITY WITH OLD KERNELS - * - * Usually, parallel cables were bound to ports at - * particular I/O addresses, as follows: - * - * tipar0 0x378 - * tipar1 0x278 - * tipar2 0x3bc - * - * - * This driver, by default, binds tipar devices according to parport and - * the minor number. - * - */ -#undef DEBUG /* change to #define to get debugging - * output - for pr_debug() */ -#include <linux/module.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/delay.h> -#include <linux/fcntl.h> -#include <linux/fs.h> -#include <linux/init.h> -#include <asm/uaccess.h> -#include <linux/ioport.h> -#include <asm/io.h> -#include <linux/bitops.h> -#include <linux/parport.h> /* Our code depend on parport */ -#include <linux/device.h> - -/* - * TI definitions - */ -#include <linux/ticable.h> - -/* - * Version Information - */ -#define DRIVER_VERSION "1.19" -#define DRIVER_AUTHOR "Romain Lievin <roms@lpg.ticalc.org>" -#define DRIVER_DESC "Device driver for TI/PC parallel link cables" -#define DRIVER_LICENSE "GPL" - -#define VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq)) - -/* ----- global variables --------------------------------------------- */ - -struct tipar_struct { - struct pardevice *dev; /* Parport device entry */ -}; - -#define PP_NO 3 -static struct tipar_struct table[PP_NO]; - -static int delay = IO_DELAY; /* inter-bit delay in microseconds */ -static int timeout = TIMAXTIME; /* timeout in tenth of seconds */ - -static unsigned int tp_count; /* tipar count */ -static unsigned long opened; /* opened devices */ - -static struct class *tipar_class; - -/* --- macros for parport access -------------------------------------- */ - -#define r_dtr(x) (parport_read_data(table[(x)].dev->port)) -#define r_str(x) (parport_read_status(table[(x)].dev->port)) -#define w_ctr(x,y) (parport_write_control(table[(x)].dev->port, (y))) -#define w_dtr(x,y) (parport_write_data(table[(x)].dev->port, (y))) - -/* --- setting states on the D-bus with the right timing: ------------- */ - -static inline void -outbyte(int value, int minor) -{ - w_dtr(minor, value); -} - -static inline int -inbyte(int minor) -{ - return (r_str(minor)); -} - -static inline void -init_ti_parallel(int minor) -{ - outbyte(3, minor); -} - -/* ----- global defines ----------------------------------------------- */ - -#define START(x) { x = jiffies + (HZ * timeout) / 10; } -#define WAIT(x) { \ - if (time_before((x), jiffies)) return -1; \ - if (need_resched()) schedule(); } - -/* ----- D-bus bit-banging functions ---------------------------------- */ - -/* D-bus protocol (45kbit/s max): - 1 0 0 - _______ ______|______ __________|________ __________ -Red : ________ | ____ | ____ - _ ____________|________ ______|__________ _____ -White: ________ | ______ | _______ -*/ - -/* Try to transmit a byte on the specified port (-1 if error). */ -static int -put_ti_parallel(int minor, unsigned char data) -{ - unsigned int bit; - unsigned long max; - - for (bit = 0; bit < 8; bit++) { - if (data & 1) { - outbyte(2, minor); - START(max); - do { - WAIT(max); - } while (inbyte(minor) & 0x10); - - outbyte(3, minor); - START(max); - do { - WAIT(max); - } while (!(inbyte(minor) & 0x10)); - } else { - outbyte(1, minor); - START(max); - do { - WAIT(max); - } while (inbyte(minor) & 0x20); - - outbyte(3, minor); - START(max); - do { - WAIT(max); - } while (!(inbyte(minor) & 0x20)); - } - - data >>= 1; - udelay(delay); - - if (need_resched()) - schedule(); - } - - return 0; -} - -/* Receive a byte on the specified port or -1 if error. */ -static int -get_ti_parallel(int minor) -{ - unsigned int bit; - unsigned char v, data = 0; - unsigned long max; - - for (bit = 0; bit < 8; bit++) { - START(max); - do { - WAIT(max); - } while ((v = inbyte(minor) & 0x30) == 0x30); - - if (v == 0x10) { - data = (data >> 1) | 0x80; - outbyte(1, minor); - START(max); - do { - WAIT(max); - } while (!(inbyte(minor) & 0x20)); - outbyte(3, minor); - } else { - data = data >> 1; - outbyte(2, minor); - START(max); - do { - WAIT(max); - } while (!(inbyte(minor) & 0x10)); - outbyte(3, minor); - } - - udelay(delay); - if (need_resched()) - schedule(); - } - - return (int) data; -} - -/* Try to detect a parallel link cable on the specified port */ -static int -probe_ti_parallel(int minor) -{ - int i; - int seq[] = { 0x00, 0x20, 0x10, 0x30 }; - int data; - - for (i = 3; i >= 0; i--) { - outbyte(3, minor); - outbyte(i, minor); - udelay(delay); - data = inbyte(minor) & 0x30; - pr_debug("tipar: Probing -> %i: 0x%02x 0x%02x\n", i, - data, seq[i]); - if (data != seq[i]) { - outbyte(3, minor); - return -1; - } - } - - outbyte(3, minor); - return 0; -} - -/* ----- kernel module functions--------------------------------------- */ - -static int -tipar_open(struct inode *inode, struct file *file) -{ - unsigned int minor = iminor(inode) - TIPAR_MINOR; - - if (tp_count == 0 || minor > tp_count - 1) - return -ENXIO; - - if (test_and_set_bit(minor, &opened)) - return -EBUSY; - - if (!table[minor].dev) { - printk(KERN_ERR "%s: NULL device for minor %u\n", - __FUNCTION__, minor); - return -ENXIO; - } - parport_claim_or_block(table[minor].dev); - init_ti_parallel(minor); - parport_release(table[minor].dev); - - return nonseekable_open(inode, file); -} - -static int -tipar_close(struct inode *inode, struct file *file) -{ - unsigned int minor = iminor(inode) - TIPAR_MINOR; - - if (minor > tp_count - 1) - return -ENXIO; - - clear_bit(minor, &opened); - - return 0; -} - -static ssize_t -tipar_write (struct file *file, const char __user *buf, size_t count, - loff_t * ppos) -{ - unsigned int minor = iminor(file->f_path.dentry->d_inode) - TIPAR_MINOR; - ssize_t n; - - parport_claim_or_block(table[minor].dev); - - for (n = 0; n < count; n++) { - unsigned char b; - - if (get_user(b, buf + n)) { - n = -EFAULT; - goto out; - } - - if (put_ti_parallel(minor, b) == -1) { - init_ti_parallel(minor); - n = -ETIMEDOUT; - goto out; - } - } - out: - parport_release(table[minor].dev); - return n; -} - -static ssize_t -tipar_read(struct file *file, char __user *buf, size_t count, loff_t * ppos) -{ - int b = 0; - unsigned int minor = iminor(file->f_path.dentry->d_inode) - TIPAR_MINOR; - ssize_t retval = 0; - ssize_t n = 0; - - if (count == 0) - return 0; - - parport_claim_or_block(table[minor].dev); - - while (n < count) { - b = get_ti_parallel(minor); - if (b == -1) { - init_ti_parallel(minor); - retval = -ETIMEDOUT; - goto out; - } else { - if (put_user(b, buf + n)) { - retval = -EFAULT; - break; - } else - retval = ++n; - } - - /* Non-blocking mode : try again ! */ - if (file->f_flags & O_NONBLOCK) { - retval = -EAGAIN; - goto out; - } - - /* Signal pending, try again ! */ - if (signal_pending(current)) { - retval = -ERESTARTSYS; - goto out; - } - - if (need_resched()) - schedule(); - } - - out: - parport_release(table[minor].dev); - return retval; -} - -static int -tipar_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int retval = 0; - - switch (cmd) { - case IOCTL_TIPAR_DELAY: - delay = (int)arg; //get_user(delay, &arg); - break; - case IOCTL_TIPAR_TIMEOUT: - if (arg != 0) - timeout = (int)arg; - else - retval = -EINVAL; - break; - default: - retval = -ENOTTY; - break; - } - - return retval; -} - -/* ----- kernel module registering ------------------------------------ */ - -static const struct file_operations tipar_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = tipar_read, - .write = tipar_write, - .ioctl = tipar_ioctl, - .open = tipar_open, - .release = tipar_close, -}; - -/* --- initialisation code ------------------------------------- */ - -#ifndef MODULE -/* You must set these - there is no sane way to probe for this cable. - * You can use 'tipar=timeout,delay' to set these now. */ -static int __init -tipar_setup(char *str) -{ - int ints[3]; - - str = get_options(str, ARRAY_SIZE(ints), ints); - - if (ints[0] > 0) { - if (ints[1] != 0) - timeout = ints[1]; - else - printk(KERN_WARNING "tipar: bad timeout value (0), " - "using default value instead"); - if (ints[0] > 1) { - delay = ints[2]; - } - } - - return 1; -} -#endif - -/* - * Register our module into parport. - * Pass also 2 callbacks functions to parport: a pre-emptive function and an - * interrupt handler function (unused). - * Display a message such "tipar0: using parport0 (polling)". - */ -static int -tipar_register(int nr, struct parport *port) -{ - int err = 0; - - /* Register our module into parport */ - table[nr].dev = parport_register_device(port, "tipar", - NULL, NULL, NULL, 0, - (void *) &table[nr]); - - if (table[nr].dev == NULL) { - err = 1; - goto out; - } - - device_create(tipar_class, port->dev, MKDEV(TIPAR_MAJOR, - TIPAR_MINOR + nr), "par%d", nr); - - /* Display informations */ - pr_info("tipar%d: using %s (%s)\n", nr, port->name, (port->irq == - PARPORT_IRQ_NONE) ? "polling" : "interrupt-driven"); - - if (probe_ti_parallel(nr) != -1) - pr_info("tipar%d: link cable found\n", nr); - else - pr_info("tipar%d: link cable not found\n", nr); - - err = 0; - -out: - return err; -} - -static void -tipar_attach(struct parport *port) -{ - if (tp_count == PP_NO) { - pr_info("tipar: ignoring parallel port (max. %d)\n", PP_NO); - return; - } - - if (!tipar_register(tp_count, port)) - tp_count++; -} - -static void -tipar_detach(struct parport *port) -{ - /* Nothing to do */ -} - -static struct parport_driver tipar_driver = { - .name = "tipar", - .attach = tipar_attach, - .detach = tipar_detach, -}; - -static int __init -tipar_init_module(void) -{ - int err = 0; - - pr_info("tipar: parallel link cable driver, version %s\n", - DRIVER_VERSION); - - if (register_chrdev(TIPAR_MAJOR, "tipar", &tipar_fops)) { - printk(KERN_ERR "tipar: unable to get major %d\n", TIPAR_MAJOR); - err = -EIO; - goto out; - } - - tipar_class = class_create(THIS_MODULE, "ticables"); - if (IS_ERR(tipar_class)) { - err = PTR_ERR(tipar_class); - goto out_chrdev; - } - if (parport_register_driver(&tipar_driver)) { - printk(KERN_ERR "tipar: unable to register with parport\n"); - err = -EIO; - goto out_class; - } - - err = 0; - goto out; - -out_class: - class_destroy(tipar_class); - -out_chrdev: - unregister_chrdev(TIPAR_MAJOR, "tipar"); -out: - return err; -} - -static void __exit -tipar_cleanup_module(void) -{ - unsigned int i; - - /* Unregistering module */ - parport_unregister_driver(&tipar_driver); - - unregister_chrdev(TIPAR_MAJOR, "tipar"); - - for (i = 0; i < PP_NO; i++) { - if (table[i].dev == NULL) - continue; - parport_unregister_device(table[i].dev); - device_destroy(tipar_class, MKDEV(TIPAR_MAJOR, i)); - } - class_destroy(tipar_class); - - pr_info("tipar: module unloaded\n"); -} - -/* --------------------------------------------------------------------- */ - -__setup("tipar=", tipar_setup); -module_init(tipar_init_module); -module_exit(tipar_cleanup_module); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE(DRIVER_LICENSE); - -module_param(timeout, int, 0); -MODULE_PARM_DESC(timeout, "Timeout (default=1.5 seconds)"); -module_param(delay, int, 0); -MODULE_PARM_DESC(delay, "Inter-bit delay (default=10 microseconds)"); diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 39564b76d4a..c88424a0c89 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -1046,12 +1046,6 @@ void tpm_remove_hardware(struct device *dev) } EXPORT_SYMBOL_GPL(tpm_remove_hardware); -static u8 savestate[] = { - 0, 193, /* TPM_TAG_RQU_COMMAND */ - 0, 0, 0, 10, /* blob length (in bytes) */ - 0, 0, 0, 152 /* TPM_ORD_SaveState */ -}; - /* * We are about to suspend. Save the TPM state * so that it can be restored. @@ -1059,6 +1053,12 @@ static u8 savestate[] = { int tpm_pm_suspend(struct device *dev, pm_message_t pm_state) { struct tpm_chip *chip = dev_get_drvdata(dev); + u8 savestate[] = { + 0, 193, /* TPM_TAG_RQU_COMMAND */ + 0, 0, 0, 10, /* blob length (in bytes) */ + 0, 0, 0, 152 /* TPM_ORD_SaveState */ + }; + if (chip == NULL) return -ENODEV; diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index fd771a4d6d1..81503d94fec 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 7a003504c26..d4b6d64e858 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c @@ -62,7 +62,7 @@ void tty_wait_until_sent(struct tty_struct * tty, long timeout) if (!timeout) timeout = MAX_SCHEDULE_TIMEOUT; if (wait_event_interruptible_timeout(tty->write_wait, - !tty->driver->chars_in_buffer(tty), timeout)) + !tty->driver->chars_in_buffer(tty), timeout) < 0) return; if (tty->driver->wait_until_sent) tty->driver->wait_until_sent(tty, timeout); @@ -365,6 +365,25 @@ void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old) EXPORT_SYMBOL(tty_termios_copy_hw); /** + * tty_termios_hw_change - check for setting change + * @a: termios + * @b: termios to compare + * + * Check if any of the bits that affect a dumb device have changed + * between the two termios structures, or a speed change is needed. + */ + +int tty_termios_hw_change(struct ktermios *a, struct ktermios *b) +{ + if (a->c_ispeed != b->c_ispeed || a->c_ospeed != b->c_ospeed) + return 1; + if ((a->c_cflag ^ b->c_cflag) & ~(HUPCL | CREAD | CLOCAL)) + return 1; + return 0; +} +EXPORT_SYMBOL(tty_termios_hw_change); + +/** * change_termios - update termios values * @tty: tty to update * @new_termios: desired new value @@ -730,13 +749,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 +828,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 +945,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 +955,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 +973,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/char/virtio_console.c b/drivers/char/virtio_console.c index 100e8a201e3..e34da5c9719 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -141,7 +141,7 @@ int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)) * never remove the console device we never need this pointer again. * * Finally we put our input buffer in the input queue, ready to receive. */ -static int virtcons_probe(struct virtio_device *dev) +static int __devinit virtcons_probe(struct virtio_device *dev) { int err; struct hvc_struct *hvc; diff --git a/drivers/connector/cn_queue.c b/drivers/connector/cn_queue.c index 296f51002b5..12ceed54ab1 100644 --- a/drivers/connector/cn_queue.c +++ b/drivers/connector/cn_queue.c @@ -99,8 +99,8 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id spin_unlock_bh(&dev->queue_lock); if (found) { - atomic_dec(&dev->refcnt); cn_queue_free_callback(cbq); + atomic_dec(&dev->refcnt); return -EINVAL; } diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index 0e328d387af..bf9716b7551 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -145,6 +145,8 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v if (queue_work(dev->cbdev->cn_queue, &__cbq->work)) err = 0; + else + err = -EINVAL; } else { struct cn_callback_data *d; @@ -218,7 +220,7 @@ static void cn_rx_skb(struct sk_buff *__skb) skb->len < nlh->nlmsg_len || nlh->nlmsg_len > CONNECTOR_MAX_MSG_SIZE) { kfree_skb(skb); - goto out; + return; } len = NLMSG_ALIGN(nlh->nlmsg_len); @@ -229,9 +231,6 @@ static void cn_rx_skb(struct sk_buff *__skb) if (err < 0) kfree_skb(skb); } - -out: - kfree_skb(__skb); } /* diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 5e626b12b97..79581fab82d 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -841,19 +841,25 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) drv_attr = cpufreq_driver->attr; while ((drv_attr) && (*drv_attr)) { ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr)); - if (ret) + if (ret) { + unlock_policy_rwsem_write(cpu); goto err_out_driver_exit; + } drv_attr++; } if (cpufreq_driver->get){ ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr); - if (ret) + if (ret) { + unlock_policy_rwsem_write(cpu); goto err_out_driver_exit; + } } if (cpufreq_driver->target){ ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr); - if (ret) + if (ret) { + unlock_policy_rwsem_write(cpu); goto err_out_driver_exit; + } } spin_lock_irqsave(&cpufreq_driver_lock, flags); diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 4bd33ce8a6f..5d3a04ba6ad 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; } @@ -576,5 +603,9 @@ MODULE_DESCRIPTION ("'cpufreq_conservative' - A dynamic cpufreq governor for " "optimised for use in a battery environment"); MODULE_LICENSE ("GPL"); +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE +fs_initcall(cpufreq_gov_dbs_init); +#else module_init(cpufreq_gov_dbs_init); +#endif module_exit(cpufreq_gov_dbs_exit); diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 369f4459515..d2af20dda38 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -610,6 +610,9 @@ MODULE_DESCRIPTION("'cpufreq_ondemand' - A dynamic cpufreq governor for " "Low Latency Frequency Transition capable processors"); MODULE_LICENSE("GPL"); +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND +fs_initcall(cpufreq_gov_dbs_init); +#else module_init(cpufreq_gov_dbs_init); +#endif module_exit(cpufreq_gov_dbs_exit); - diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 8a45d0f93e2..1b8312b0200 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -164,7 +164,7 @@ freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq) return -1; } -static void __cpuexit cpufreq_stats_free_table(unsigned int cpu) +static void cpufreq_stats_free_table(unsigned int cpu) { struct cpufreq_stats *stat = cpufreq_stats_table[cpu]; struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c index 51bedab6c80..f8cdde4bf6c 100644 --- a/drivers/cpufreq/cpufreq_userspace.c +++ b/drivers/cpufreq/cpufreq_userspace.c @@ -231,5 +231,9 @@ MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>, Russell King <rmk@arm.linux. MODULE_DESCRIPTION ("CPUfreq policy governor 'userspace'"); MODULE_LICENSE ("GPL"); +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE fs_initcall(cpufreq_gov_userspace_init); +#else +module_init(cpufreq_gov_userspace_init); +#endif module_exit(cpufreq_gov_userspace_exit); diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index fdf4106b817..d2fabe7863a 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -19,7 +19,6 @@ #include "cpuidle.h" DEFINE_PER_CPU(struct cpuidle_device *, cpuidle_devices); -EXPORT_PER_CPU_SYMBOL_GPL(cpuidle_devices); DEFINE_MUTEX(cpuidle_lock); LIST_HEAD(cpuidle_detected_devices); diff --git a/drivers/cpuidle/governor.c b/drivers/cpuidle/governor.c index bb699cb2dc5..70b59642a70 100644 --- a/drivers/cpuidle/governor.c +++ b/drivers/cpuidle/governor.c @@ -94,8 +94,6 @@ int cpuidle_register_governor(struct cpuidle_governor *gov) return ret; } -EXPORT_SYMBOL_GPL(cpuidle_register_governor); - /** * cpuidle_replace_governor - find a replacement governor * @exclude_rating: the rating that will be skipped while looking for @@ -138,4 +136,3 @@ void cpuidle_unregister_governor(struct cpuidle_governor *gov) mutex_unlock(&cpuidle_lock); } -EXPORT_SYMBOL_GPL(cpuidle_unregister_governor); diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 5fd6688a444..ddd3a259cea 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 f9a34abbf4f..711e246e1ef 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/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c index abbcff0762b..5f7e7181048 100644 --- a/drivers/crypto/padlock-aes.c +++ b/drivers/crypto/padlock-aes.c @@ -419,13 +419,58 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, /* ====== Encryption/decryption routines ====== */ /* These are the real call to PadLock. */ +static inline void padlock_xcrypt(const u8 *input, u8 *output, void *key, + void *control_word) +{ + asm volatile (".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */ + : "+S"(input), "+D"(output) + : "d"(control_word), "b"(key), "c"(1)); +} + +static void aes_crypt_copy(const u8 *in, u8 *out, u32 *key, struct cword *cword) +{ + u8 buf[AES_BLOCK_SIZE * 2 + PADLOCK_ALIGNMENT - 1]; + u8 *tmp = PTR_ALIGN(&buf[0], PADLOCK_ALIGNMENT); + + memcpy(tmp, in, AES_BLOCK_SIZE); + padlock_xcrypt(tmp, out, key, cword); +} + +static inline void aes_crypt(const u8 *in, u8 *out, u32 *key, + struct cword *cword) +{ + asm volatile ("pushfl; popfl"); + + /* padlock_xcrypt requires at least two blocks of data. */ + if (unlikely(!(((unsigned long)in ^ (PAGE_SIZE - AES_BLOCK_SIZE)) & + (PAGE_SIZE - 1)))) { + aes_crypt_copy(in, out, key, cword); + return; + } + + padlock_xcrypt(in, out, key, cword); +} + static inline void padlock_xcrypt_ecb(const u8 *input, u8 *output, void *key, void *control_word, u32 count) { + if (count == 1) { + aes_crypt(input, output, key, control_word); + return; + } + asm volatile ("pushfl; popfl"); /* enforce key reload. */ - asm volatile (".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */ + asm volatile ("test $1, %%cl;" + "je 1f;" + "lea -1(%%ecx), %%eax;" + "mov $1, %%ecx;" + ".byte 0xf3,0x0f,0xa7,0xc8;" /* rep xcryptecb */ + "mov %%eax, %%ecx;" + "1:" + ".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */ : "+S"(input), "+D"(output) - : "d"(control_word), "b"(key), "c"(count)); + : "d"(control_word), "b"(key), "c"(count) + : "ax"); } static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key, @@ -443,13 +488,13 @@ static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key, static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { struct aes_ctx *ctx = aes_ctx(tfm); - padlock_xcrypt_ecb(in, out, ctx->E, &ctx->cword.encrypt, 1); + aes_crypt(in, out, ctx->E, &ctx->cword.encrypt); } static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { struct aes_ctx *ctx = aes_ctx(tfm); - padlock_xcrypt_ecb(in, out, ctx->D, &ctx->cword.decrypt, 1); + aes_crypt(in, out, ctx->D, &ctx->cword.decrypt); } static struct crypto_alg aes_alg = { diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 9c91b0fd134..c46b7c219ee 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 @@ -43,7 +45,6 @@ comment "DMA Clients" config NET_DMA bool "Network: TCP receive copy offload" depends on DMA_ENGINE && NET - default y help This enables the use of DMA engines in the network stack to offload receive copy-to-user operations, freeing CPU cycles. diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 82489923af0..d59b2f41730 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 f204c39fb41..16e0fd8facf 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 ba985715b80..0fa8a98051a 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 7e4a785c2df..45e7b4666c7 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,54 @@ 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) +/** + * ioat_dma_memcpy_issue_pending - push potentially unrecognized appended + * descriptors to hw + * @chan: DMA channel handle + */ +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) { + 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); + } +} + +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; @@ -187,7 +240,7 @@ static dma_cookie_t ioat_tx_submit(struct dma_async_tx_descriptor *tx) prev = to_ioat_desc(ioat_chan->used_desc.prev); prefetch(prev->hw); do { - copy = min((u32) len, ioat_chan->xfercap); + copy = min_t(size_t, len, ioat_chan->xfercap); new->async_tx.ack = 1; @@ -209,7 +262,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 +299,100 @@ 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 + * it gets unlocked at end of this function + */ + do { + copy = min_t(size_t, 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,19 +417,61 @@ 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); - struct ioat_desc_sw *desc = NULL; + struct ioat_desc_sw *desc; u16 chanctrl; u32 chanerr; int i; @@ -304,7 +479,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 +495,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 +505,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 +525,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 +546,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 +600,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,9 +612,9 @@ 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; + struct ioat_desc_sw *new; if (!list_empty(&ioat_chan->free_desc)) { new = to_ioat_desc(ioat_chan->free_desc.next); @@ -416,16 +622,97 @@ ioat_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan) } else { /* try to get another desc */ new = ioat_dma_alloc_descriptor(ioat_chan, GFP_ATOMIC); - /* will this ever happen? */ - /* TODO add upper limit on these */ - BUG_ON(!new); + if (!new) { + dev_err(&ioat_chan->device->pdev->dev, + "alloc failed\n"); + return NULL; + } } prefetch(new->hw); 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; + + /* + * 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; + struct ioat_desc_sw *noop_desc; + 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++; + + /* try to get a few more descriptors */ + for (i = 16; i; i--) { + desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_ATOMIC); + if (!desc) { + dev_err(&ioat_chan->device->pdev->dev, + "alloc failed\n"); + break; + } + 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) @@ -435,26 +722,36 @@ static struct dma_async_tx_descriptor *ioat_dma_prep_memcpy( spin_lock_bh(&ioat_chan->desc_lock); new = ioat_dma_get_next_descriptor(ioat_chan); - new->len = len; spin_unlock_bh(&ioat_chan->desc_lock); - return new ? &new->async_tx : NULL; + if (new) { + new->len = len; + return &new->async_tx; + } else + return 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 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; - 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); + new = ioat2_dma_get_next_descriptor(ioat_chan); + + /* + * leave ioat_chan->desc_lock set in ioat 2 path + * it will get unlocked at end of tx_submit + */ + + if (new) { + new->len = len; + return &new->async_tx; + } else + return NULL; } static void ioat_dma_cleanup_tasklet(unsigned long data) @@ -465,11 +762,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 +810,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 +983,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 +993,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); } /* @@ -658,7 +1031,7 @@ static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan) static void ioat_dma_test_callback(void *dma_async_param) { printk(KERN_ERR "ioatdma: ioat_dma_test_callback(%p)\n", - dma_async_param); + dma_async_param); } /** @@ -671,7 +1044,7 @@ static int ioat_dma_self_test(struct ioatdma_device *device) u8 *src; u8 *dest; struct dma_chan *dma_chan; - struct dma_async_tx_descriptor *tx = NULL; + struct dma_async_tx_descriptor *tx; dma_addr_t addr; dma_cookie_t cookie; int err = 0; @@ -693,14 +1066,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 +1083,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 +1115,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 +1315,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", @@ -977,7 +1363,7 @@ err_completion_pool: err_dma_pool: kfree(device); err_kzalloc: - dev_err(&device->pdev->dev, + dev_err(&pdev->dev, "Intel(R) I/OAT DMA Engine initialization failed\n"); return NULL; } diff --git a/drivers/dma/ioatdma.h b/drivers/dma/ioatdma.h index 5f9881e7b0e..f2c7fedbf00 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; @@ -87,7 +76,7 @@ struct ioat_dma_chan { dma_cookie_t completed_cookie; unsigned long last_completion; - u32 xfercap; /* XFERCAP register value expanded out */ + size_t xfercap; /* XFERCAP register value expanded out */ spinlock_t cleanup_lock; spinlock_t desc_lock; @@ -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 9e7434e1551..dd470fa91d8 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 baaab5ea146..9832d7ebd93 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 96f7e63e399..a1f24c42d5f 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-ohci.c b/drivers/firewire/fw-ohci.c index 67588326ae5..436a855a4c6 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -437,6 +437,21 @@ static void ar_context_run(struct ar_context *ctx) flush_writes(ctx->ohci); } +static struct descriptor * +find_branch_descriptor(struct descriptor *d, int z) +{ + int b, key; + + b = (le16_to_cpu(d->control) & DESCRIPTOR_BRANCH_ALWAYS) >> 2; + key = (le16_to_cpu(d->control) & DESCRIPTOR_KEY_IMMEDIATE) >> 8; + + /* figure out which descriptor the branch address goes in */ + if (z == 2 && (b == 3 || key == 2)) + return d; + else + return d + z - 1; +} + static void context_tasklet(unsigned long data) { struct context *ctx = (struct context *) data; @@ -455,7 +470,7 @@ static void context_tasklet(unsigned long data) address = le32_to_cpu(last->branch_address); z = address & 0xf; d = ctx->buffer + (address - ctx->buffer_bus) / sizeof(*d); - last = (z == 2) ? d : d + z - 1; + last = find_branch_descriptor(d, z); if (!ctx->callback(ctx, d, last)) break; @@ -566,7 +581,7 @@ static void context_append(struct context *ctx, ctx->head_descriptor = d + z + extra; ctx->prev_descriptor->branch_address = cpu_to_le32(d_bus | z); - ctx->prev_descriptor = z == 2 ? d : d + z - 1; + ctx->prev_descriptor = find_branch_descriptor(d, z); dma_sync_single_for_device(ctx->ohci->card.device, ctx->buffer_bus, ctx->buffer_size, DMA_TO_DEVICE); @@ -655,7 +670,7 @@ at_context_queue_packet(struct context *ctx, struct fw_packet *packet) driver_data = (struct driver_data *) &d[3]; driver_data->packet = packet; packet->driver_data = driver_data; - + if (packet->payload_length > 0) { payload_bus = dma_map_single(ohci->card.device, packet->payload, @@ -903,7 +918,7 @@ at_context_transmit(struct context *ctx, struct fw_packet *packet) if (retval < 0) packet->callback(packet, &ctx->ohci->card, packet->ack); - + } static void bus_reset_tasklet(unsigned long data) @@ -984,8 +999,10 @@ static void bus_reset_tasklet(unsigned long data) */ if (ohci->next_config_rom != NULL) { - free_rom = ohci->config_rom; - free_rom_bus = ohci->config_rom_bus; + if (ohci->next_config_rom != ohci->config_rom) { + free_rom = ohci->config_rom; + free_rom_bus = ohci->config_rom_bus; + } ohci->config_rom = ohci->next_config_rom; ohci->config_rom_bus = ohci->next_config_rom_bus; ohci->next_config_rom = NULL; @@ -1161,19 +1178,30 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length) * the right values in the bus reset tasklet. */ - ohci->next_config_rom = - dma_alloc_coherent(ohci->card.device, CONFIG_ROM_SIZE, - &ohci->next_config_rom_bus, GFP_KERNEL); - if (ohci->next_config_rom == NULL) - return -ENOMEM; + if (config_rom) { + ohci->next_config_rom = + dma_alloc_coherent(ohci->card.device, CONFIG_ROM_SIZE, + &ohci->next_config_rom_bus, + GFP_KERNEL); + if (ohci->next_config_rom == NULL) + return -ENOMEM; - memset(ohci->next_config_rom, 0, CONFIG_ROM_SIZE); - fw_memcpy_to_be32(ohci->next_config_rom, config_rom, length * 4); + memset(ohci->next_config_rom, 0, CONFIG_ROM_SIZE); + fw_memcpy_to_be32(ohci->next_config_rom, config_rom, length * 4); + } else { + /* + * In the suspend case, config_rom is NULL, which + * means that we just reuse the old config rom. + */ + ohci->next_config_rom = ohci->config_rom; + ohci->next_config_rom_bus = ohci->config_rom_bus; + } - ohci->next_header = config_rom[0]; + ohci->next_header = be32_to_cpu(ohci->next_config_rom[0]); ohci->next_config_rom[0] = 0; reg_write(ohci, OHCI1394_ConfigROMhdr, 0); - reg_write(ohci, OHCI1394_BusOptions, config_rom[2]); + reg_write(ohci, OHCI1394_BusOptions, + be32_to_cpu(ohci->next_config_rom[2])); reg_write(ohci, OHCI1394_ConfigROMmap, ohci->next_config_rom_bus); reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000); @@ -1418,6 +1446,57 @@ static int handle_ir_dualbuffer_packet(struct context *context, return 1; } +static int handle_ir_packet_per_buffer(struct context *context, + struct descriptor *d, + struct descriptor *last) +{ + struct iso_context *ctx = + container_of(context, struct iso_context, context); + struct descriptor *pd = d + 1; + __le32 *ir_header; + size_t header_length; + void *p, *end; + int i, z; + + if (pd->res_count == pd->req_count) + /* Descriptor(s) not done yet, stop iteration */ + return 0; + + header_length = le16_to_cpu(d->req_count); + + i = ctx->header_length; + z = le32_to_cpu(pd->branch_address) & 0xf; + p = d + z; + end = p + header_length; + + while (p < end && i + ctx->base.header_size <= PAGE_SIZE) { + /* + * The iso header is byteswapped to little endian by + * the controller, but the remaining header quadlets + * are big endian. We want to present all the headers + * as big endian, so we have to swap the first quadlet. + */ + *(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4)); + memcpy(ctx->header + i + 4, p + 8, ctx->base.header_size - 4); + i += ctx->base.header_size; + p += ctx->base.header_size + 4; + } + + ctx->header_length = i; + + if (le16_to_cpu(pd->control) & DESCRIPTOR_IRQ_ALWAYS) { + ir_header = (__le32 *) (d + z); + ctx->base.callback(&ctx->base, + le32_to_cpu(ir_header[0]) & 0xffff, + ctx->header_length, ctx->header, + ctx->base.callback_data); + ctx->header_length = 0; + } + + + return 1; +} + static int handle_it_packet(struct context *context, struct descriptor *d, struct descriptor *last) @@ -1453,14 +1532,12 @@ ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size) } else { mask = &ohci->ir_context_mask; list = ohci->ir_context_list; - callback = handle_ir_dualbuffer_packet; + if (ohci->version >= OHCI_VERSION_1_1) + callback = handle_ir_dualbuffer_packet; + else + callback = handle_ir_packet_per_buffer; } - /* FIXME: We need a fallback for pre 1.1 OHCI. */ - if (callback == handle_ir_dualbuffer_packet && - ohci->version < OHCI_VERSION_1_1) - return ERR_PTR(-ENOSYS); - spin_lock_irqsave(&ohci->lock, flags); index = ffs(*mask) - 1; if (index >= 0) @@ -1519,7 +1596,9 @@ static int ohci_start_iso(struct fw_iso_context *base, context_run(&ctx->context, match); } else { index = ctx - ohci->ir_context_list; - control = IR_CONTEXT_DUAL_BUFFER_MODE | IR_CONTEXT_ISOCH_HEADER; + control = IR_CONTEXT_ISOCH_HEADER; + if (ohci->version >= OHCI_VERSION_1_1) + control |= IR_CONTEXT_DUAL_BUFFER_MODE; match = (tags << 28) | (sync << 8) | ctx->base.channel; if (cycle >= 0) { match |= (cycle & 0x07fff) << 12; @@ -1725,7 +1804,6 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, offset = payload & ~PAGE_MASK; rest = p->payload_length; - /* FIXME: OHCI 1.0 doesn't support dual buffer receive */ /* FIXME: make packet-per-buffer/dual-buffer a context option */ while (rest > 0) { d = context_get_descriptors(&ctx->context, @@ -1764,6 +1842,81 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, } static int +ohci_queue_iso_receive_packet_per_buffer(struct fw_iso_context *base, + struct fw_iso_packet *packet, + struct fw_iso_buffer *buffer, + unsigned long payload) +{ + struct iso_context *ctx = container_of(base, struct iso_context, base); + struct descriptor *d = NULL, *pd = NULL; + struct fw_iso_packet *p; + dma_addr_t d_bus, page_bus; + u32 z, header_z, rest; + int i, page, offset, packet_count, header_size; + + if (packet->skip) { + d = context_get_descriptors(&ctx->context, 1, &d_bus); + if (d == NULL) + return -ENOMEM; + + d->control = cpu_to_le16(DESCRIPTOR_STATUS | + DESCRIPTOR_INPUT_LAST | + DESCRIPTOR_BRANCH_ALWAYS | + DESCRIPTOR_WAIT); + context_append(&ctx->context, d, 1, 0); + } + + /* one descriptor for header, one for payload */ + /* FIXME: handle cases where we need multiple desc. for payload */ + z = 2; + p = packet; + + /* + * The OHCI controller puts the status word in the + * buffer too, so we need 4 extra bytes per packet. + */ + packet_count = p->header_length / ctx->base.header_size; + header_size = packet_count * (ctx->base.header_size + 4); + + /* Get header size in number of descriptors. */ + header_z = DIV_ROUND_UP(header_size, sizeof(*d)); + page = payload >> PAGE_SHIFT; + offset = payload & ~PAGE_MASK; + rest = p->payload_length; + + for (i = 0; i < packet_count; i++) { + /* d points to the header descriptor */ + d = context_get_descriptors(&ctx->context, + z + header_z, &d_bus); + if (d == NULL) + return -ENOMEM; + + d->control = cpu_to_le16(DESCRIPTOR_INPUT_MORE); + d->req_count = cpu_to_le16(header_size); + d->res_count = d->req_count; + d->data_address = cpu_to_le32(d_bus + (z * sizeof(*d))); + + /* pd points to the payload descriptor */ + pd = d + 1; + pd->control = cpu_to_le16(DESCRIPTOR_STATUS | + DESCRIPTOR_INPUT_LAST | + DESCRIPTOR_BRANCH_ALWAYS); + if (p->interrupt) + pd->control |= cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS); + + pd->req_count = cpu_to_le16(rest); + pd->res_count = pd->req_count; + + page_bus = page_private(buffer->pages[page]); + pd->data_address = cpu_to_le32(page_bus + offset); + + context_append(&ctx->context, d, z, header_z); + } + + return 0; +} + +static int ohci_queue_iso(struct fw_iso_context *base, struct fw_iso_packet *packet, struct fw_iso_buffer *buffer, @@ -1777,8 +1930,9 @@ ohci_queue_iso(struct fw_iso_context *base, return ohci_queue_iso_receive_dualbuffer(base, packet, buffer, payload); else - /* FIXME: Implement fallback for OHCI 1.0 controllers. */ - return -ENOSYS; + return ohci_queue_iso_receive_packet_per_buffer(base, packet, + buffer, + payload); } static const struct fw_card_driver ohci_driver = { @@ -1898,12 +2052,6 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) ohci->version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff; fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n", dev->dev.bus_id, ohci->version >> 16, ohci->version & 0xff); - if (ohci->version < OHCI_VERSION_1_1) { - fw_notify(" Isochronous I/O is not yet implemented for " - "OHCI 1.0 chips.\n"); - fw_notify(" Cameras, audio devices etc. won't work on " - "this controller with this driver version.\n"); - } return 0; fail_self_id: @@ -1984,7 +2132,7 @@ static int pci_resume(struct pci_dev *pdev) return err; } - return ohci_enable(&ohci->card, ohci->config_rom, CONFIG_ROM_SIZE); + return ohci_enable(&ohci->card, NULL, 0); } #endif diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index 5596df65c8e..624ff3e082f 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/firmware/dmi-id.c b/drivers/firmware/dmi-id.c index b6e1eb77d14..bc132d8f79c 100644 --- a/drivers/firmware/dmi-id.c +++ b/drivers/firmware/dmi-id.c @@ -175,12 +175,11 @@ static struct device *dmi_dev; extern int dmi_available; -static int __init dmi_id_init(void) +/* In a separate function to keep gcc 3.2 happy - do NOT merge this in + dmi_id_init! */ +static void __init dmi_id_init_attr_table(void) { - int ret, i; - - if (!dmi_available) - return -ENODEV; + int i; /* Not necessarily all DMI fields are available on all * systems, hence let's built an attribute table of just @@ -205,6 +204,16 @@ static int __init dmi_id_init(void) ADD_DMI_ATTR(chassis_serial, DMI_CHASSIS_SERIAL); ADD_DMI_ATTR(chassis_asset_tag, DMI_CHASSIS_ASSET_TAG); sys_dmi_attributes[i++] = &sys_dmi_modalias_attr.attr; +} + +static int __init dmi_id_init(void) +{ + int ret; + + if (!dmi_available) + return -ENODEV; + + dmi_id_init_attr_table(); ret = class_register(&dmi_class); if (ret) diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index dd332f28e08..0b27da7d749 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -297,7 +297,7 @@ static struct hid_usage *hidinput_find_key(struct hid_device *hid, static int hidinput_getkeycode(struct input_dev *dev, int scancode, int *keycode) { - struct hid_device *hid = dev->private; + struct hid_device *hid = input_get_drvdata(dev); struct hid_usage *usage; usage = hidinput_find_key(hid, scancode, 0); @@ -311,7 +311,7 @@ static int hidinput_getkeycode(struct input_dev *dev, int scancode, static int hidinput_setkeycode(struct input_dev *dev, int scancode, int keycode) { - struct hid_device *hid = dev->private; + struct hid_device *hid = input_get_drvdata(dev); struct hid_usage *usage; int old_keycode; @@ -1152,7 +1152,7 @@ int hidinput_connect(struct hid_device *hid) kfree(hidinput); input_free_device(input_dev); err_hid("Out of memory during hid input probe"); - return -1; + goto out_unwind; } input_set_drvdata(input_dev, hid); @@ -1186,15 +1186,25 @@ int hidinput_connect(struct hid_device *hid) * UGCI) cram a lot of unrelated inputs into the * same interface. */ hidinput->report = report; - input_register_device(hidinput->input); + if (input_register_device(hidinput->input)) + goto out_cleanup; hidinput = NULL; } } - if (hidinput) - input_register_device(hidinput->input); + if (hidinput && input_register_device(hidinput->input)) + goto out_cleanup; return 0; + +out_cleanup: + input_free_device(hidinput->input); + kfree(hidinput); +out_unwind: + /* unwind the ones we already registered */ + hidinput_disconnect(hid); + + return -1; } EXPORT_SYMBOL_GPL(hidinput_connect); diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 41a59a80e7e..a2552856476 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -129,6 +129,11 @@ #define USB_DEVICE_ID_0_8_8_IF_KIT 0x0053 #define USB_DEVICE_ID_PHIDGET_MOTORCONTROL 0x0058 +#define USB_VENDOR_ID_GOTOP 0x08f2 +#define USB_DEVICE_ID_SUPER_Q2 0x007f +#define USB_DEVICE_ID_GOGOPEN 0x00ce +#define USB_DEVICE_ID_PENPOWER 0x00f4 + #define USB_VENDOR_ID_GRIFFIN 0x077d #define USB_DEVICE_ID_POWERMATE 0x0410 #define USB_DEVICE_ID_SOUNDKNOB 0x04AA @@ -415,6 +420,9 @@ static const struct hid_blacklist { { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_7_IF_KIT, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_PHIDGET_MOTORCONTROL, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_SUPER_Q2, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_GOGOPEN, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_PENPOWER, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90, HID_QUIRK_IGNORE }, diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 9837adcb17e..5fc4019956b 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -743,7 +743,7 @@ inval: static long hiddev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct inode *inode = file->f_path.dentry->d_inode; - return hiddev_ioctl(inode, file, cmd, compat_ptr(arg)); + return hiddev_ioctl(inode, file, cmd, (unsigned long)compat_ptr(arg)); } #endif diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 700a1657554..a0445bea9f7 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 6da3eef9430..55595f6e1aa 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 cb2331bfd9d..d9f04ce9032 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 1001d2e122a..86c66c345f8 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/coretemp.c b/drivers/hwmon/coretemp.c index 5c82ec7f8bb..3ee60d26e3a 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -337,11 +337,10 @@ static int coretemp_cpu_callback(struct notifier_block *nfb, switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: + case CPU_DOWN_FAILED: coretemp_device_add(cpu); break; - case CPU_DEAD: - case CPU_DEAD_FROZEN: + case CPU_DOWN_PREPARE: coretemp_device_remove(cpu); break; } diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c index 13a041326a0..6892f76fc18 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 00000000000..6ac5c6f5358 --- /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 c462824ffcc..9c9cdb0685e 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 dd366889ce9..d435f003292 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 7e2d9787bab..a276806f3d5 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/w83627ehf.c b/drivers/hwmon/w83627ehf.c index b15c6a998b7..d5aa25ce5db 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -1276,23 +1276,31 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) data->vrm = vid_which_vrm(); superio_enter(sio_data->sioreg); - /* Set VID input sensibility if needed. In theory the BIOS should - have set it, but in practice it's not always the case. */ - en_vrm10 = superio_inb(sio_data->sioreg, SIO_REG_EN_VRM10); - if ((en_vrm10 & 0x08) && data->vrm != 100) { - dev_warn(dev, "Setting VID input voltage to TTL\n"); - superio_outb(sio_data->sioreg, SIO_REG_EN_VRM10, - en_vrm10 & ~0x08); - } else if (!(en_vrm10 & 0x08) && data->vrm == 100) { - dev_warn(dev, "Setting VID input voltage to VRM10\n"); - superio_outb(sio_data->sioreg, SIO_REG_EN_VRM10, - en_vrm10 | 0x08); - } /* Read VID value */ superio_select(sio_data->sioreg, W83627EHF_LD_HWM); - if (superio_inb(sio_data->sioreg, SIO_REG_VID_CTRL) & 0x80) + if (superio_inb(sio_data->sioreg, SIO_REG_VID_CTRL) & 0x80) { + /* Set VID input sensibility if needed. In theory the BIOS + should have set it, but in practice it's not always the + case. We only do it for the W83627EHF/EHG because the + W83627DHG is more complex in this respect. */ + if (sio_data->kind == w83627ehf) { + en_vrm10 = superio_inb(sio_data->sioreg, + SIO_REG_EN_VRM10); + if ((en_vrm10 & 0x08) && data->vrm == 90) { + dev_warn(dev, "Setting VID input voltage to " + "TTL\n"); + superio_outb(sio_data->sioreg, SIO_REG_EN_VRM10, + en_vrm10 & ~0x08); + } else if (!(en_vrm10 & 0x08) && data->vrm == 100) { + dev_warn(dev, "Setting VID input voltage to " + "VRM10\n"); + superio_outb(sio_data->sioreg, SIO_REG_EN_VRM10, + en_vrm10 | 0x08); + } + } + data->vid = superio_inb(sio_data->sioreg, SIO_REG_VID_DATA) & 0x3f; - else { + } else { dev_info(dev, "VID pins in output mode, CPU VID not " "available\n"); data->vid = 0x3f; diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 20ae425a198..879d0a6544c 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 a6a1edfe761..e0fa7520400 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-at91.c b/drivers/i2c/busses/i2c-at91.c index 9c8b6d5eaec..c09b036913b 100644 --- a/drivers/i2c/busses/i2c-at91.c +++ b/drivers/i2c/busses/i2c-at91.c @@ -135,7 +135,7 @@ static int xfer_write(struct i2c_adapter *adap, unsigned char *buf, int length) * Generic i2c master transfer entrypoint. * * Note: We do not use Atmel's feature of storing the "internal device address". - * Instead the "internal device address" has to be written using a seperate + * Instead the "internal device address" has to be written using a separate * i2c message. * http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2004-September/024411.html */ diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index bd7aaff3524..67679882ebe 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -404,7 +404,7 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id) DAVINCI_I2C_STR_REG, w); } else - dev_err(dev->dev, "RDR IRQ while no" + dev_err(dev->dev, "RDR IRQ while no " "data requested\n"); break; @@ -423,7 +423,7 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id) DAVINCI_I2C_IMR_REG, w); } else - dev_err(dev->dev, "TDR IRQ while no data to" + dev_err(dev->dev, "TDR IRQ while no data to " "send\n"); break; diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index 44e1cd21bb0..3ca19fc234f 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -140,6 +140,7 @@ static int __init i2c_gpio_probe(struct platform_device *pdev) adap->owner = THIS_MODULE; snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id); adap->algo_data = bit_data; + adap->class = I2C_CLASS_HWMON; adap->dev.parent = &pdev->dev; /* diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 89a30028ddb..f2552b19ea6 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -203,7 +203,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) while (!(omap_i2c_read_reg(dev, OMAP_I2C_SYSS_REG) & OMAP_I2C_SYSS_RDONE)) { if (time_after(jiffies, timeout)) { - dev_warn(dev->dev, "timeout waiting" + dev_warn(dev->dev, "timeout waiting " "for controller reset\n"); return -ETIMEDOUT; } @@ -483,7 +483,7 @@ omap_i2c_isr(int this_irq, void *dev_id) dev->buf_len--; } } else - dev_err(dev->dev, "RRDY IRQ while no data" + dev_err(dev->dev, "RRDY IRQ while no data " "requested\n"); omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RRDY); continue; @@ -498,7 +498,7 @@ omap_i2c_isr(int this_irq, void *dev_id) dev->buf_len--; } } else - dev_err(dev->dev, "XRDY IRQ while no" + dev_err(dev->dev, "XRDY IRQ while no " "data to send\n"); omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w); omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XRDY); @@ -619,13 +619,13 @@ omap_i2c_probe(struct platform_device *pdev) err_free_irq: free_irq(dev->irq, dev); err_unuse_clocks: + omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); omap_i2c_disable_clocks(dev); omap_i2c_put_clocks(dev); err_free_mem: platform_set_drvdata(pdev, NULL); kfree(dev); err_release_region: - omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); release_mem_region(mem->start, (mem->end - mem->start) + 1); return r; diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c index 58e32714afb..ca18e0be490 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/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c index 0ab4f2627c2..7813127649a 100644 --- a/drivers/i2c/busses/i2c-powermac.c +++ b/drivers/i2c/busses/i2c-powermac.c @@ -94,7 +94,7 @@ static s32 i2c_powermac_smbus_xfer( struct i2c_adapter* adap, break; /* Note that these are broken vs. the expected smbus API where - * on reads, the lenght is actually returned from the function, + * on reads, the length is actually returned from the function, * but I think the current API makes no sense and I don't want * any driver that I haven't verified for correctness to go * anywhere near a pmac i2c bus anyway ... diff --git a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c index 0ca599d3b40..503a134ec80 100644 --- a/drivers/i2c/busses/i2c-sibyte.c +++ b/drivers/i2c/busses/i2c-sibyte.c @@ -200,11 +200,14 @@ static struct i2c_adapter sibyte_board_adapter[2] = { static int __init i2c_sibyte_init(void) { - printk("i2c-swarm.o: i2c SMBus adapter module for SiByte board\n"); + pr_info("i2c-sibyte: i2c SMBus adapter module for SiByte board\n"); if (i2c_sibyte_add_bus(&sibyte_board_adapter[0], K_SMB_FREQ_100KHZ) < 0) return -ENODEV; - if (i2c_sibyte_add_bus(&sibyte_board_adapter[1], K_SMB_FREQ_400KHZ) < 0) + if (i2c_sibyte_add_bus(&sibyte_board_adapter[1], + K_SMB_FREQ_400KHZ) < 0) { + i2c_del_adapter(&sibyte_board_adapter[0]); return -ENODEV; + } return 0; } diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c index d3da1fb05b9..1a7eeebac50 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/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c index fe04e46991a..b767603a07b 100644 --- a/drivers/i2c/chips/isp1301_omap.c +++ b/drivers/i2c/chips/isp1301_omap.c @@ -26,7 +26,7 @@ #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/usb/ch9.h> -#include <linux/usb_gadget.h> +#include <linux/usb/gadget.h> #include <linux/usb.h> #include <linux/usb/otg.h> #include <linux/i2c.h> diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 1a4e8dc03b3..b5e13e405e7 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 5a15e50748d..df540d5dfaf 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 + bound 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 6eaece96524..fb06555708a 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -152,9 +152,22 @@ config BLK_DEV_IDEDISK If unsure, say Y. config IDEDISK_MULTI_MODE - bool "Use multi-mode by default" - help - If you get this error, try to say Y here: + bool "Use multiple sector mode for Programmed Input/Output by default" + help + This setting is irrelevant for most IDE disks, with direct memory + access, to which multiple sector mode does not apply. Multiple sector + mode is a feature of most modern IDE hard drives, permitting the + transfer of multiple sectors per Programmed Input/Output interrupt, + rather than the usual one sector per interrupt. When this feature is + enabled, it can reduce operating system overhead for disk Programmed + Input/Output. On some systems, it also can increase the data + throughput of Programmed Input/Output. Some drives, however, seemed + to run slower with multiple sector mode enabled. Some drives claimed + to support multiple sector mode, but lost data at some settings. + Under rare circumstances, such failures could result in massive + filesystem corruption. + + If you get the following error, try to say Y here: hda: set_multmode: status=0x51 { DriveReady SeekComplete Error } hda: set_multmode: error=0x04 { DriveStatusError } @@ -190,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. @@ -304,7 +313,6 @@ comment "IDE chipset support/bugfixes" config IDE_GENERIC tristate "generic/default IDE chipset support" - default H8300 help If unsure, say N. @@ -380,9 +388,10 @@ config IDEPCI_SHARE_IRQ config IDEPCI_PCIBUS_ORDER def_bool BLK_DEV_IDE=y && BLK_DEV_IDEPCI +# TODO: split it on per host driver config options (or module parameters) config BLK_DEV_OFFBOARD - bool "Boot off-board chipsets first support" - depends on BLK_DEV_IDEPCI + bool "Boot off-board chipsets first support (DEPRECATED)" + depends on BLK_DEV_IDEPCI && (BLK_DEV_AEC62XX || BLK_DEV_GENERIC || BLK_DEV_HPT34X || BLK_DEV_HPT366 || BLK_DEV_PDC202XX_NEW || BLK_DEV_PDC202XX_OLD || BLK_DEV_TC86C001) help Normally, IDE controllers built into the motherboard (on-board controllers) are assigned to ide0 and ide1 while those on add-in PCI @@ -401,6 +410,10 @@ config BLK_DEV_OFFBOARD Note that, if you do this, the order of the hd* devices will be rearranged which may require modification of fstab and other files. + Please also note that this method of assuring stable naming of + IDE devices is unreliable and use other means for achieving it + (i.e. udev). + If in doubt, say N. config BLK_DEV_GENERIC @@ -474,6 +487,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 @@ -873,6 +887,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 @@ -953,7 +1010,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 75dc6969e0a..b181fc67205 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/arm/icside.c b/drivers/ide/arm/icside.c index 410a0d13e35..93f71fcfc04 100644 --- a/drivers/ide/arm/icside.c +++ b/drivers/ide/arm/icside.c @@ -316,13 +316,13 @@ static int icside_dma_end(ide_drive_t *drive) drive->waiting_for_dma = 0; - disable_dma(state->dev->dma); + disable_dma(ECARD_DEV(state->dev)->dma); /* Teardown mappings after DMA has completed. */ dma_unmap_sg(state->dev, hwif->sg_table, hwif->sg_nents, hwif->sg_dma_direction); - return get_dma_residue(state->dev->dma) != 0; + return get_dma_residue(ECARD_DEV(state->dev)->dma) != 0; } static void icside_dma_start(ide_drive_t *drive) @@ -331,8 +331,8 @@ static void icside_dma_start(ide_drive_t *drive) struct icside_state *state = hwif->hwif_data; /* We can not enable DMA on both channels simultaneously. */ - BUG_ON(dma_channel_active(state->dev->dma)); - enable_dma(state->dev->dma); + BUG_ON(dma_channel_active(ECARD_DEV(state->dev)->dma)); + enable_dma(ECARD_DEV(state->dev)->dma); } static int icside_dma_setup(ide_drive_t *drive) @@ -350,7 +350,7 @@ static int icside_dma_setup(ide_drive_t *drive) /* * We can not enable DMA on both channels. */ - BUG_ON(dma_channel_active(state->dev->dma)); + BUG_ON(dma_channel_active(ECARD_DEV(state->dev)->dma)); icside_build_sglist(drive, rq); @@ -367,14 +367,14 @@ static int icside_dma_setup(ide_drive_t *drive) /* * Select the correct timing for this drive. */ - set_dma_speed(state->dev->dma, drive->drive_data); + set_dma_speed(ECARD_DEV(state->dev)->dma, drive->drive_data); /* * Tell the DMA engine about the SG table and * data direction. */ - set_dma_sg(state->dev->dma, hwif->sg_table, hwif->sg_nents); - set_dma_mode(state->dev->dma, dma_mode); + set_dma_sg(ECARD_DEV(state->dev)->dma, hwif->sg_table, hwif->sg_nents); + set_dma_mode(ECARD_DEV(state->dev)->dma, dma_mode); drive->waiting_for_dma = 1; diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c index e196aefa207..476e0d65ed4 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-acpi.c b/drivers/ide/ide-acpi.c index 89df48fdc69..899d56536e8 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -16,6 +16,7 @@ #include <acpi/acpi.h> #include <linux/ide.h> #include <linux/pci.h> +#include <linux/dmi.h> #include <acpi/acpi_bus.h> #include <acpi/acnames.h> @@ -65,6 +66,39 @@ extern int ide_noacpi; extern int ide_noacpitfs; extern int ide_noacpionboot; +static bool ide_noacpi_psx; +static int no_acpi_psx(const struct dmi_system_id *id) +{ + ide_noacpi_psx = true; + printk(KERN_NOTICE"%s detected - disable ACPI _PSx.\n", id->ident); + return 0; +} + +static const struct dmi_system_id ide_acpi_dmi_table[] = { + /* Bug 9673. */ + /* We should check if this is because ACPI NVS isn't save/restored. */ + { + .callback = no_acpi_psx, + .ident = "HP nx9005", + .matches = { + DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies Ltd."), + DMI_MATCH(DMI_BIOS_VERSION, "KAM1.60") + }, + }, + + { } /* terminate list */ +}; + +static int ide_acpi_blacklist(void) +{ + static int done; + if (done) + return 0; + done = 1; + dmi_check_system(ide_acpi_dmi_table); + return 0; +} + /** * ide_get_dev_handle - finds acpi_handle and PCI device.function * @dev: device to locate @@ -623,7 +657,7 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on) { int unit; - if (ide_noacpi) + if (ide_noacpi || ide_noacpi_psx) return; DEBPRINT("ENTER:\n"); @@ -668,6 +702,8 @@ void ide_acpi_init(ide_hwif_t *hwif) struct ide_acpi_drive_link *master; struct ide_acpi_drive_link *slave; + ide_acpi_blacklist(); + hwif->acpidata = kzalloc(sizeof(struct ide_acpi_hwif_link), GFP_KERNEL); if (!hwif->acpidata) return; diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 57a5f63d6ae..c7d77f0ad89 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -1068,8 +1068,8 @@ int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason) return 0; else if (ireason == 0) { /* Whoops... The drive is expecting to receive data from us! */ - printk(KERN_ERR "%s: read_intr: Drive wants to transfer data the " - "wrong way!\n", drive->name); + printk(KERN_ERR "%s: %s: wrong transfer direction!\n", + drive->name, __FUNCTION__); /* Throw some data at the drive so it doesn't hang and quit this request. */ @@ -1086,8 +1086,8 @@ int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason) return 0; } else { /* Drive wants a command packet, or invalid ireason... */ - printk(KERN_ERR "%s: read_intr: bad interrupt reason %x\n", drive->name, - ireason); + printk(KERN_ERR "%s: %s: bad interrupt reason 0x%02x\n", + drive->name, __FUNCTION__, ireason); } cdrom_end_request(drive, 0); @@ -1112,8 +1112,11 @@ static ide_startstop_t cdrom_read_intr (ide_drive_t *drive) */ if (dma) { info->dma = 0; - if ((dma_error = HWIF(drive)->ide_dma_end(drive))) + dma_error = HWIF(drive)->ide_dma_end(drive); + if (dma_error) { + printk(KERN_ERR "%s: DMA read error\n", drive->name); ide_dma_off(drive); + } } if (cdrom_decode_status(drive, 0, &stat)) @@ -1443,7 +1446,7 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive) return ide_stopped; /* Read the interrupt reason and the transfer length. */ - ireason = HWIF(drive)->INB(IDE_IREASON_REG); + ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3; lowcyl = HWIF(drive)->INB(IDE_BCOUNTL_REG); highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG); @@ -1484,7 +1487,7 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive) if (thislen > len) thislen = len; /* The drive wants to be written to. */ - if ((ireason & 3) == 0) { + if (ireason == 0) { if (!rq->data) { blk_dump_rq_flags(rq, "cdrom_pc_intr, write"); goto confused; @@ -1506,9 +1509,9 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive) } /* Same drill for reading. */ - else if ((ireason & 3) == 2) { + else if (ireason == 2) { if (!rq->data) { - blk_dump_rq_flags(rq, "cdrom_pc_intr, write"); + blk_dump_rq_flags(rq, "cdrom_pc_intr, read"); goto confused; } /* Transfer the data. */ @@ -1632,8 +1635,8 @@ static int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason) return 0; else if (ireason == 2) { /* Whoops... The drive wants to send data. */ - printk(KERN_ERR "%s: write_intr: wrong transfer direction!\n", - drive->name); + printk(KERN_ERR "%s: %s: wrong transfer direction!\n", + drive->name, __FUNCTION__); while (len > 0) { int dum = 0; @@ -1642,39 +1645,14 @@ static int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason) } } else { /* Drive wants a command packet, or invalid ireason... */ - printk(KERN_ERR "%s: write_intr: bad interrupt reason %x\n", - drive->name, ireason); + printk(KERN_ERR "%s: %s: bad interrupt reason 0x%02x\n", + drive->name, __FUNCTION__, ireason); } cdrom_end_request(drive, 0); return 1; } -static void post_transform_command(struct request *req) -{ - u8 *c = req->cmd; - char *ibuf; - - if (!blk_pc_request(req)) - return; - - if (req->bio) - ibuf = bio_data(req->bio); - else - ibuf = req->data; - - if (!ibuf) - return; - - /* - * set ansi-revision and response data as atapi - */ - if (c[0] == GPCMD_INQUIRY) { - ibuf[2] |= 2; - ibuf[3] = (ibuf[3] & 0xf0) | 2; - } -} - typedef void (xfer_func_t)(ide_drive_t *, void *, u32); /* @@ -1810,9 +1788,6 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) return ide_started; end_request: - if (!rq->data_len) - post_transform_command(rq); - spin_lock_irqsave(&ide_lock, flags); blkdev_dequeue_request(rq); end_that_request_last(rq, 1); @@ -1833,8 +1808,9 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive) /* Check for errors. */ if (dma) { info->dma = 0; - if ((dma_error = HWIF(drive)->ide_dma_end(drive))) { - printk(KERN_ERR "ide-cd: write dma error\n"); + dma_error = HWIF(drive)->ide_dma_end(drive); + if (dma_error) { + printk(KERN_ERR "%s: DMA write error\n", drive->name); ide_dma_off(drive); } } @@ -1854,7 +1830,7 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive) } /* Read the interrupt reason and the transfer length. */ - ireason = HWIF(drive)->INB(IDE_IREASON_REG); + ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3; lowcyl = HWIF(drive)->INB(IDE_BCOUNTL_REG); highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG); @@ -1867,8 +1843,9 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive) */ uptodate = 1; if (rq->current_nr_sectors > 0) { - printk(KERN_ERR "%s: write_intr: data underrun (%d blocks)\n", - drive->name, rq->current_nr_sectors); + printk(KERN_ERR "%s: %s: data underrun (%d blocks)\n", + drive->name, __FUNCTION__, + rq->current_nr_sectors); uptodate = 0; } cdrom_end_request(drive, uptodate); @@ -1888,7 +1865,8 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive) int this_transfer; if (!rq->current_nr_sectors) { - printk(KERN_ERR "ide-cd: write_intr: oops\n"); + printk(KERN_ERR "%s: %s: confused, missing data\n", + drive->name, __FUNCTION__); break; } @@ -2716,14 +2694,14 @@ void ide_cdrom_update_speed (ide_drive_t *drive, struct atapi_capabilities_page if (!drive->id->model[0] && !strncmp(drive->id->fw_rev, "241N", 4)) { CDROM_STATE_FLAGS(drive)->current_speed = - (((unsigned int)cap->curspeed) + (176/2)) / 176; + (le16_to_cpu(cap->curspeed) + (176/2)) / 176; CDROM_CONFIG_FLAGS(drive)->max_speed = - (((unsigned int)cap->maxspeed) + (176/2)) / 176; + (le16_to_cpu(cap->maxspeed) + (176/2)) / 176; } else { CDROM_STATE_FLAGS(drive)->current_speed = - (ntohs(cap->curspeed) + (176/2)) / 176; + (be16_to_cpu(cap->curspeed) + (176/2)) / 176; CDROM_CONFIG_FLAGS(drive)->max_speed = - (ntohs(cap->maxspeed) + (176/2)) / 176; + (be16_to_cpu(cap->maxspeed) + (176/2)) / 176; } } @@ -2937,6 +2915,9 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots) if (!CDROM_CONFIG_FLAGS(drive)->ram) devinfo->mask |= CDC_RAM; + if (CDROM_CONFIG_FLAGS(drive)->no_speed_select) + devinfo->mask |= CDC_SELECT_SPEED; + devinfo->disk = info->disk; return register_cdrom(devinfo); } @@ -3049,12 +3030,7 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) else printk(" drive"); - printk(", %dkB Cache", be16_to_cpu(cap.buffer_size)); - - if (drive->using_dma) - ide_dma_verbose(drive); - - printk("\n"); + printk(KERN_CONT ", %dkB Cache\n", be16_to_cpu(cap.buffer_size)); return nslots; } @@ -3194,7 +3170,7 @@ int ide_cdrom_setup (ide_drive_t *drive) CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1; /* the 3231 model does not support the SET_CD_SPEED command */ else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-3231")) - cdi->mask |= CDC_SELECT_SPEED; + CDROM_CONFIG_FLAGS(drive)->no_speed_select = 1; #if ! STANDARD_ATAPI /* by default Sanyo 3 CD changer support is turned off and @@ -3537,15 +3513,8 @@ static int ide_cd_probe(ide_drive_t *drive) g->driverfs_dev = &drive->gendev; g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE; if (ide_cdrom_setup(drive)) { - struct cdrom_device_info *devinfo = &info->devinfo; ide_proc_unregister_driver(drive, &ide_cdrom_driver); - kfree(info->buffer); - kfree(info->toc); - kfree(info->changer_info); - if (devinfo->handle == drive && unregister_cdrom(devinfo)) - printk (KERN_ERR "%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name); - kfree(info); - drive->driver_data = NULL; + ide_cd_release(&info->kref); goto failed; } diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h index 228b29c5d2e..1b302fe2724 100644 --- a/drivers/ide/ide-cd.h +++ b/drivers/ide/ide-cd.h @@ -91,7 +91,8 @@ struct ide_cd_config_flags { __u8 close_tray : 1; /* can close the tray */ __u8 writing : 1; /* pseudo write in progress */ __u8 mo_drive : 1; /* drive is an MO device */ - __u8 reserved : 2; + __u8 no_speed_select : 1; /* SET_CD_SPEED command is unsupported. */ + __u8 reserved : 1; byte max_speed; /* Max speed of the drive */ }; #define CDROM_CONFIG_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->config_flags)) diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 00123d99527..b1781908e1f 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -13,32 +13,6 @@ * and Andre Hedrick <andre@linux-ide.org> * * This is the IDE/ATA disk driver, as evolved from hd.c and ide.c. - * - * Version 1.00 move disk only code from ide.c to ide-disk.c - * support optional byte-swapping of all data - * Version 1.01 fix previous byte-swapping code - * Version 1.02 remove ", LBA" from drive identification msgs - * Version 1.03 fix display of id->buf_size for big-endian - * Version 1.04 add /proc configurable settings and S.M.A.R.T support - * Version 1.05 add capacity support for ATA3 >= 8GB - * Version 1.06 get boot-up messages to show full cyl count - * Version 1.07 disable door-locking if it fails - * Version 1.08 fixed CHS/LBA translations for ATA4 > 8GB, - * process of adding new ATA4 compliance. - * fixed problems in allowing fdisk to see - * the entire disk. - * Version 1.09 added increment of rq->sector in ide_multwrite - * added UDMA 3/4 reporting - * Version 1.10 request queue changes, Ultra DMA 100 - * Version 1.11 added 48-bit lba - * Version 1.12 adding taskfile io access method - * Version 1.13 added standby and flush-cache for notifier - * Version 1.14 added acoustic-wcache - * Version 1.15 convert all calls to ide_raw_taskfile - * since args will return register content. - * Version 1.16 added suspend-resume-checkpower - * Version 1.17 do flush on standby, do flush on ATA < ATA6 - * fix wcache setup. */ #define IDEDISK_VERSION "1.18" @@ -961,11 +935,8 @@ static void idedisk_setup (ide_drive_t *drive) if (id->buf_size) printk (" w/%dKiB Cache", id->buf_size/2); - printk(", CHS=%d/%d/%d", - drive->bios_cyl, drive->bios_head, drive->bios_sect); - if (drive->using_dma) - ide_dma_verbose(drive); - printk("\n"); + printk(KERN_CONT ", CHS=%d/%d/%d\n", + drive->bios_cyl, drive->bios_head, drive->bios_sect); /* write cache enabled? */ if ((id->csfo & 1) || (id->cfs_enable_1 & (1 << 5))) diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 428f7a8a00b..4703837bf1f 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 } }; @@ -340,7 +341,7 @@ static int config_drive_for_dma (ide_drive_t *drive) if (drive->media != ide_disk) { if (hwif->host_flags & IDE_HFLAG_NO_ATAPI_DMA) - return -1; + return 0; } /* @@ -610,12 +611,6 @@ static int __ide_dma_test_irq(ide_drive_t *drive) ide_hwif_t *hwif = HWIF(drive); u8 dma_stat = hwif->INB(hwif->dma_status); -#if 0 /* do not set unless you know what you are doing */ - if (dma_stat & 4) { - u8 stat = hwif->INB(IDE_STATUS_REG); - hwif->OUTB(hwif->dma_status, dma_stat & 0xE4); - } -#endif /* return 1 if INTR asserted */ if ((dma_stat & 4) == 4) return 1; @@ -752,9 +747,12 @@ u8 ide_find_dma_mode(ide_drive_t *drive, u8 req_mode) mode = XFER_MW_DMA_1; } - printk(KERN_DEBUG "%s: selected mode 0x%x\n", drive->name, mode); + mode = min(mode, req_mode); - return min(mode, req_mode); + printk(KERN_INFO "%s: %s mode selected\n", drive->name, + mode ? ide_xfer_verbose(mode) : "no DMA"); + + return mode; } EXPORT_SYMBOL_GPL(ide_find_dma_mode); @@ -770,6 +768,9 @@ static int ide_tune_dma(ide_drive_t *drive) if (__ide_dma_bad_drive(drive)) return 0; + if (ide_id_dma_bug(drive)) + return 0; + if (drive->hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA) return config_drive_for_dma(drive); @@ -804,58 +805,23 @@ static int ide_dma_check(ide_drive_t *drive) return vdma ? 0 : -1; } -void ide_dma_verbose(ide_drive_t *drive) +int ide_id_dma_bug(ide_drive_t *drive) { - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); + struct hd_driveid *id = drive->id; if (id->field_valid & 4) { if ((id->dma_ultra >> 8) && (id->dma_mword >> 8)) - goto bug_dma_off; - if (id->dma_ultra & ((id->dma_ultra >> 8) & hwif->ultra_mask)) { - if (((id->dma_ultra >> 11) & 0x1F) && - eighty_ninty_three(drive)) { - if ((id->dma_ultra >> 15) & 1) { - printk(", UDMA(mode 7)"); - } else if ((id->dma_ultra >> 14) & 1) { - printk(", UDMA(133)"); - } else if ((id->dma_ultra >> 13) & 1) { - printk(", UDMA(100)"); - } else if ((id->dma_ultra >> 12) & 1) { - printk(", UDMA(66)"); - } else if ((id->dma_ultra >> 11) & 1) { - printk(", UDMA(44)"); - } else - goto mode_two; - } else { - mode_two: - if ((id->dma_ultra >> 10) & 1) { - printk(", UDMA(33)"); - } else if ((id->dma_ultra >> 9) & 1) { - printk(", UDMA(25)"); - } else if ((id->dma_ultra >> 8) & 1) { - printk(", UDMA(16)"); - } - } - } else { - printk(", (U)DMA"); /* Can be BIOS-enabled! */ - } + goto err_out; } else if (id->field_valid & 2) { if ((id->dma_mword >> 8) && (id->dma_1word >> 8)) - goto bug_dma_off; - printk(", DMA"); - } else if (id->field_valid & 1) { - goto bug_dma_off; + goto err_out; } - return; -bug_dma_off: - printk(", BUG DMA OFF"); - hwif->dma_off_quietly(drive); - return; + return 0; +err_out: + printk(KERN_ERR "%s: bad DMA info in identify block\n", drive->name); + return 1; } -EXPORT_SYMBOL(ide_dma_verbose); - int ide_set_dma(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index c89f0d3058e..bef781fec50 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -340,6 +340,8 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) if (args) { args[0] = stat; args[1] = err; + /* be sure we're looking at the low order bits */ + hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG); args[2] = hwif->INB(IDE_NSECTOR_REG); args[3] = hwif->INB(IDE_SECTOR_REG); args[4] = hwif->INB(IDE_LCYL_REG); @@ -654,7 +656,8 @@ static ide_startstop_t drive_cmd_intr (ide_drive_t *drive) int retries = 10; local_irq_enable_in_hardirq(); - if ((stat & DRQ_STAT) && args && args[3]) { + if (rq->cmd_type == REQ_TYPE_ATA_CMD && + (stat & DRQ_STAT) && args && args[3]) { u8 io_32bit = drive->io_32bit; drive->io_32bit = 0; hwif->ata_input_data(drive, &args[4], args[3] * SECTOR_WORDS); @@ -882,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; @@ -900,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) { @@ -971,7 +970,8 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq) if (rc) printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name); SELECT_DRIVE(drive); - HWIF(drive)->OUTB(8, HWIF(drive)->io_ports[IDE_CONTROL_OFFSET]); + if (IDE_CONTROL_REG) + HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG); rc = ide_wait_not_busy(HWIF(drive), 100000); if (rc) printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name); diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 95168833d06..bb9693dabe4 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 @@ -403,8 +400,12 @@ void ide_fix_driveid (struct hd_driveid *id) #endif } -/* FIXME: exported for use by the USB storage (isd200.c) code only */ -EXPORT_SYMBOL(ide_fix_driveid); +/* + * ide_fixstring() cleans up and (optionally) byte-swaps a text string, + * removing leading/trailing blanks and compressing internal blanks. + * It is primarily used to tidy up the model name/number fields as + * returned by the WIN_[P]IDENTIFY commands. + */ void ide_fixstring (u8 *s, const int bytecount, const int byteswap) { @@ -582,9 +583,15 @@ EXPORT_SYMBOL_GPL(ide_in_drive_list); /* * Early UDMA66 devices don't set bit14 to 1, only bit13 is valid. * We list them here and depend on the device side cable detection for them. + * + * Some optical devices with the buggy firmwares have the same problem. */ 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 } }; @@ -605,12 +612,12 @@ u8 eighty_ninty_three (ide_drive_t *drive) printk(KERN_DEBUG "%s: skipping word 93 validity check\n", drive->name); + if (ide_dev_is_sata(id) && !ivb) + return 1; + if (hwif->cbl != ATA_CBL_PATA80 && !ivb) goto no_80w; - if (ide_dev_is_sata(id)) - return 1; - /* * FIXME: * - force bit13 (80c cable present) check also for !ivb devices @@ -741,6 +748,9 @@ int ide_driveid_update(ide_drive_t *drive) drive->id->dma_1word = id->dma_1word; /* anything more ? */ kfree(id); + + if (drive->using_dma && ide_id_dma_bug(drive)) + ide_dma_off(drive); } return 1; @@ -749,7 +759,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) @@ -760,6 +770,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, @@ -807,6 +821,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 af86433baed..062d3bcb247 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -29,41 +29,44 @@ * Add common non I/O op stuff here. Make sure it has proper * kernel-doc function headers or your patch will be rejected */ - + +static const char *udma_str[] = + { "UDMA/16", "UDMA/25", "UDMA/33", "UDMA/44", + "UDMA/66", "UDMA/100", "UDMA/133", "UDMA7" }; +static const char *mwdma_str[] = + { "MWDMA0", "MWDMA1", "MWDMA2" }; +static const char *swdma_str[] = + { "SWDMA0", "SWDMA1", "SWDMA2" }; +static const char *pio_str[] = + { "PIO0", "PIO1", "PIO2", "PIO3", "PIO4", "PIO5" }; /** * ide_xfer_verbose - return IDE mode names - * @xfer_rate: rate to name + * @mode: transfer mode * * Returns a constant string giving the name of the mode * requested. */ -char *ide_xfer_verbose (u8 xfer_rate) +const char *ide_xfer_verbose(u8 mode) { - switch(xfer_rate) { - case XFER_UDMA_7: return("UDMA 7"); - case XFER_UDMA_6: return("UDMA 6"); - case XFER_UDMA_5: return("UDMA 5"); - case XFER_UDMA_4: return("UDMA 4"); - case XFER_UDMA_3: return("UDMA 3"); - case XFER_UDMA_2: return("UDMA 2"); - case XFER_UDMA_1: return("UDMA 1"); - case XFER_UDMA_0: return("UDMA 0"); - case XFER_MW_DMA_2: return("MW DMA 2"); - case XFER_MW_DMA_1: return("MW DMA 1"); - case XFER_MW_DMA_0: return("MW DMA 0"); - case XFER_SW_DMA_2: return("SW DMA 2"); - case XFER_SW_DMA_1: return("SW DMA 1"); - case XFER_SW_DMA_0: return("SW DMA 0"); - case XFER_PIO_4: return("PIO 4"); - case XFER_PIO_3: return("PIO 3"); - case XFER_PIO_2: return("PIO 2"); - case XFER_PIO_1: return("PIO 1"); - case XFER_PIO_0: return("PIO 0"); - case XFER_PIO_SLOW: return("PIO SLOW"); - default: return("XFER ERROR"); - } + const char *s; + u8 i = mode & 0xf; + + if (mode >= XFER_UDMA_0 && mode <= XFER_UDMA_7) + s = udma_str[i]; + else if (mode >= XFER_MW_DMA_0 && mode <= XFER_MW_DMA_2) + s = mwdma_str[i]; + else if (mode >= XFER_SW_DMA_0 && mode <= XFER_SW_DMA_2) + s = swdma_str[i]; + else if (mode >= XFER_PIO_0 && mode <= XFER_PIO_5) + s = pio_str[i & 0x7]; + else if (mode == XFER_PIO_SLOW) + s = "PIO SLOW"; + else + s = "XFER ERROR"; + + return s; } EXPORT_SYMBOL(ide_xfer_verbose); @@ -514,6 +517,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 6a6f2e066b4..2994523be7b 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -13,22 +13,8 @@ * * This is the IDE probe module, as evolved from hd.c and ide.c. * - * Version 1.00 move drive probing code from ide.c to ide-probe.c - * Version 1.01 fix compilation problem for m68k - * Version 1.02 increase WAIT_PIDENTIFY to avoid CD-ROM locking at boot - * by Andrea Arcangeli - * Version 1.03 fix for (hwif->chipset == ide_4drives) - * Version 1.04 fixed buggy treatments of known flash memory cards - * - * Version 1.05 fix for (hwif->chipset == ide_pdc4030) - * added ide6/7/8/9 - * allowed for secondary flash card to be detectable - * with new flag : drive->ata_flash : 1; - * Version 1.06 stream line request queue and prep for cascade project. - * Version 1.07 max_sect <= 255; slower disks would get behind and - * then fall over when they get to 256. Paul G. - * Version 1.10 Update set for new IDE. drive->id is now always - * valid after probe time even with noprobe + * -- increase WAIT_PIDENTIFY to avoid CD-ROM locking at boot + * by Andrea Arcangeli */ #include <linux/module.h> @@ -172,11 +158,12 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) ide_fixstring(id->fw_rev, sizeof(id->fw_rev), bswap); ide_fixstring(id->serial_no, sizeof(id->serial_no), bswap); + /* we depend on this a lot! */ + id->model[sizeof(id->model)-1] = '\0'; + if (strstr(id->model, "E X A B Y T E N E S T")) goto err_misc; - /* we depend on this a lot! */ - id->model[sizeof(id->model)-1] = '\0'; printk("%s: %s, ", drive->name, id->model); drive->present = 1; drive->dead = 0; @@ -643,7 +630,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); @@ -660,20 +647,27 @@ 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); + if (IDE_CONTROL_REG) + hwif->OUTB(drive->ctl, IDE_CONTROL_REG); + 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/ide-taskfile.c b/drivers/ide/ide-taskfile.c index d066546f283..2b60f1b0437 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -471,6 +471,7 @@ static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long struct request rq; memset(&rq, 0, sizeof(rq)); + rq.ref_count = 1; rq.cmd_type = REQ_TYPE_ATA_TASKFILE; rq.buffer = buf; @@ -511,6 +512,7 @@ int ide_raw_taskfile (ide_drive_t *drive, ide_task_t *args, u8 *buf) EXPORT_SYMBOL(ide_raw_taskfile); +#ifdef CONFIG_IDE_TASK_IOCTL int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) { ide_task_request_t *req_task; @@ -660,6 +662,7 @@ abort: return err; } +#endif int ide_wait_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, u8 feature, u8 sectors, u8 *buf) { diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 674a65c1a13..54943da6e4e 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -800,11 +800,17 @@ int set_io_32bit(ide_drive_t *drive, int arg) if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1)) return -EINVAL; + if (ide_spin_wait_hwgroup(drive)) + return -EBUSY; + drive->io_32bit = arg; #ifdef CONFIG_BLK_DEV_DTC2278 if (HWIF(drive)->chipset == ide_dtc2278) HWIF(drive)->drives[!drive->select.b.unit].io_32bit = arg; #endif /* CONFIG_BLK_DEV_DTC2278 */ + + spin_unlock_irq(&ide_lock); + return 0; } @@ -1670,10 +1676,34 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, return sprintf(buf, "ide:m-%s\n", media_string(drive)); } +static ssize_t model_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + ide_drive_t *drive = to_ide_device(dev); + return sprintf(buf, "%s\n", drive->id->model); +} + +static ssize_t firmware_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + ide_drive_t *drive = to_ide_device(dev); + return sprintf(buf, "%s\n", drive->id->fw_rev); +} + +static ssize_t serial_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + ide_drive_t *drive = to_ide_device(dev); + return sprintf(buf, "%s\n", drive->id->serial_no); +} + static struct device_attribute ide_dev_attrs[] = { __ATTR_RO(media), __ATTR_RO(drivename), __ATTR_RO(modalias), + __ATTR_RO(model), + __ATTR_RO(firmware), + __ATTR(serial, 0400, serial_show, NULL), __ATTR_NULL }; diff --git a/drivers/ide/legacy/ali14xx.c b/drivers/ide/legacy/ali14xx.c index 10311ecc674..38c3a6d63f3 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 e87cd2f1643..5c6aa77c237 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 a73db1bd482..6ea46a6723e 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 19ec421f7b9..44268504ae4 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 a607dd31a64..ce293936af4 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 ea0143ef5fe..bc553337b1b 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.52 Dec 24, 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; } @@ -563,6 +564,7 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = { .init_chipset = init_chipset_cmd64x, .init_hwif = init_hwif_cmd64x, .enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}}, + .chipset = ide_cmd646, .host_flags = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE, .pio_mask = ATA_PIO5, .mwdma_mask = ATA_MWDMA2, @@ -572,7 +574,6 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = { .init_chipset = init_chipset_cmd64x, .init_hwif = init_hwif_cmd64x, .enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}}, - .chipset = ide_cmd646, .host_flags = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE, .pio_mask = ATA_PIO5, .mwdma_mask = ATA_MWDMA2, diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c index 599408952bd..547690395ee 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/cs5535.c b/drivers/ide/pci/cs5535.c index 9094916e378..ddcbeba671e 100644 --- a/drivers/ide/pci/cs5535.c +++ b/drivers/ide/pci/cs5535.c @@ -49,7 +49,7 @@ #define ATAC_BM0_PRD 0x04 #define CS5535_CABLE_DETECT 0x48 -/* Format I PIO settings. We seperate out cmd and data for safer timings */ +/* Format I PIO settings. We separate out cmd and data for safer timings */ static unsigned int cs5535_pio_cmd_timings[5] = { 0xF7F4, 0x53F3, 0x13F1, 0x5131, 0x1131 }; diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c index 3ef4fc10fe2..1cd4e9cb052 100644 --- a/drivers/ide/pci/cy82c693.c +++ b/drivers/ide/pci/cy82c693.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/cy82c693.c Version 0.41 Aug 27, 2007 + * linux/drivers/ide/pci/cy82c693.c Version 0.42 Oct 23, 2007 * * Copyright (C) 1998-2000 Andreas S. Krebs (akrebs@altavista.net), Maintainer * Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org>, Integrator @@ -436,10 +436,10 @@ static void __devinit init_hwif_cy82c693(ide_hwif_t *hwif) hwif->ide_dma_on = &cy82c693_ide_dma_on; } -static __devinitdata ide_hwif_t *primary; - static void __devinit init_iops_cy82c693(ide_hwif_t *hwif) { + static ide_hwif_t *primary; + if (PCI_FUNC(hwif->pci_dev->devfn) == 1) primary = hwif; else { diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c index f44d70852c3..06885697ed7 100644 --- a/drivers/ide/pci/generic.c +++ b/drivers/ide/pci/generic.c @@ -49,7 +49,7 @@ static int __init ide_generic_all_on(char *unused) printk(KERN_INFO "IDE generic will claim all unknown PCI IDE storage controllers.\n"); return 1; } -__setup("all-generic-ide", ide_generic_all_on); +const __setup("all-generic-ide", ide_generic_all_on); #endif module_param_named(all_generic_ide, ide_generic_all, bool, 0444); MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE storage controllers."); diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 612b795241b..9fce25bdec8 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/hpt366.c Version 1.20 Oct 1, 2007 + * linux/drivers/ide/pci/hpt366.c Version 1.22 Dec 4, 2007 * * Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org> * Portions Copyright (C) 2001 Sun Microsystems, Inc. @@ -310,6 +310,8 @@ static u32 twenty_five_base_hpt36x[] = { /* XFER_PIO_0 */ 0xc0d08585 }; +#if 0 +/* These are the timing tables from the HighPoint open source drivers... */ static u32 thirty_three_base_hpt37x[] = { /* XFER_UDMA_6 */ 0x12446231, /* 0x12646231 ?? */ /* XFER_UDMA_5 */ 0x12446231, @@ -369,6 +371,73 @@ static u32 sixty_six_base_hpt37x[] = { /* XFER_PIO_1 */ 0x0d029d26, /* XFER_PIO_0 */ 0x0d029d5e }; +#else +/* + * The following are the new timing tables with PIO mode data/taskfile transfer + * overclocking fixed... + */ + +/* This table is taken from the HPT370 data manual rev. 1.02 */ +static u32 thirty_three_base_hpt37x[] = { + /* XFER_UDMA_6 */ 0x16455031, /* 0x16655031 ?? */ + /* XFER_UDMA_5 */ 0x16455031, + /* XFER_UDMA_4 */ 0x16455031, + /* XFER_UDMA_3 */ 0x166d5031, + /* XFER_UDMA_2 */ 0x16495031, + /* XFER_UDMA_1 */ 0x164d5033, + /* XFER_UDMA_0 */ 0x16515097, + + /* XFER_MW_DMA_2 */ 0x26515031, + /* XFER_MW_DMA_1 */ 0x26515033, + /* XFER_MW_DMA_0 */ 0x26515097, + + /* XFER_PIO_4 */ 0x06515021, + /* XFER_PIO_3 */ 0x06515022, + /* XFER_PIO_2 */ 0x06515033, + /* XFER_PIO_1 */ 0x06915065, + /* XFER_PIO_0 */ 0x06d1508a +}; + +static u32 fifty_base_hpt37x[] = { + /* XFER_UDMA_6 */ 0x1a861842, + /* XFER_UDMA_5 */ 0x1a861842, + /* XFER_UDMA_4 */ 0x1aae1842, + /* XFER_UDMA_3 */ 0x1a8e1842, + /* XFER_UDMA_2 */ 0x1a0e1842, + /* XFER_UDMA_1 */ 0x1a161854, + /* XFER_UDMA_0 */ 0x1a1a18ea, + + /* XFER_MW_DMA_2 */ 0x2a821842, + /* XFER_MW_DMA_1 */ 0x2a821854, + /* XFER_MW_DMA_0 */ 0x2a8218ea, + + /* XFER_PIO_4 */ 0x0a821842, + /* XFER_PIO_3 */ 0x0a821843, + /* XFER_PIO_2 */ 0x0a821855, + /* XFER_PIO_1 */ 0x0ac218a8, + /* XFER_PIO_0 */ 0x0b02190c +}; + +static u32 sixty_six_base_hpt37x[] = { + /* XFER_UDMA_6 */ 0x1c86fe62, + /* XFER_UDMA_5 */ 0x1caefe62, /* 0x1c8afe62 */ + /* XFER_UDMA_4 */ 0x1c8afe62, + /* XFER_UDMA_3 */ 0x1c8efe62, + /* XFER_UDMA_2 */ 0x1c92fe62, + /* XFER_UDMA_1 */ 0x1c9afe62, + /* XFER_UDMA_0 */ 0x1c82fe62, + + /* XFER_MW_DMA_2 */ 0x2c82fe62, + /* XFER_MW_DMA_1 */ 0x2c82fe66, + /* XFER_MW_DMA_0 */ 0x2c82ff2e, + + /* XFER_PIO_4 */ 0x0c82fe62, + /* XFER_PIO_3 */ 0x0c82fe84, + /* XFER_PIO_2 */ 0x0c82fea6, + /* XFER_PIO_1 */ 0x0d02ff26, + /* XFER_PIO_0 */ 0x0d42ff7f +}; +#endif #define HPT366_DEBUG_DRIVE_INFO 0 #define HPT371_ALLOW_ATA133_6 1 @@ -433,7 +502,7 @@ static u32 *hpt37x_settings[NUM_ATA_CLOCKS] = { sixty_six_base_hpt37x }; -static struct hpt_info hpt36x __devinitdata = { +static const struct hpt_info hpt36x __devinitdata = { .chip_name = "HPT36x", .chip_type = HPT36x, .udma_mask = HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ? ATA_UDMA4 : ATA_UDMA3) : ATA_UDMA2, @@ -441,7 +510,7 @@ static struct hpt_info hpt36x __devinitdata = { .settings = hpt36x_settings }; -static struct hpt_info hpt370 __devinitdata = { +static const struct hpt_info hpt370 __devinitdata = { .chip_name = "HPT370", .chip_type = HPT370, .udma_mask = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4, @@ -449,7 +518,7 @@ static struct hpt_info hpt370 __devinitdata = { .settings = hpt37x_settings }; -static struct hpt_info hpt370a __devinitdata = { +static const struct hpt_info hpt370a __devinitdata = { .chip_name = "HPT370A", .chip_type = HPT370A, .udma_mask = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4, @@ -457,7 +526,7 @@ static struct hpt_info hpt370a __devinitdata = { .settings = hpt37x_settings }; -static struct hpt_info hpt374 __devinitdata = { +static const struct hpt_info hpt374 __devinitdata = { .chip_name = "HPT374", .chip_type = HPT374, .udma_mask = ATA_UDMA5, @@ -465,7 +534,7 @@ static struct hpt_info hpt374 __devinitdata = { .settings = hpt37x_settings }; -static struct hpt_info hpt372 __devinitdata = { +static const struct hpt_info hpt372 __devinitdata = { .chip_name = "HPT372", .chip_type = HPT372, .udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, @@ -473,7 +542,7 @@ static struct hpt_info hpt372 __devinitdata = { .settings = hpt37x_settings }; -static struct hpt_info hpt372a __devinitdata = { +static const struct hpt_info hpt372a __devinitdata = { .chip_name = "HPT372A", .chip_type = HPT372A, .udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, @@ -481,7 +550,7 @@ static struct hpt_info hpt372a __devinitdata = { .settings = hpt37x_settings }; -static struct hpt_info hpt302 __devinitdata = { +static const struct hpt_info hpt302 __devinitdata = { .chip_name = "HPT302", .chip_type = HPT302, .udma_mask = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, @@ -489,7 +558,7 @@ static struct hpt_info hpt302 __devinitdata = { .settings = hpt37x_settings }; -static struct hpt_info hpt371 __devinitdata = { +static const struct hpt_info hpt371 __devinitdata = { .chip_name = "HPT371", .chip_type = HPT371, .udma_mask = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, @@ -497,7 +566,7 @@ static struct hpt_info hpt371 __devinitdata = { .settings = hpt37x_settings }; -static struct hpt_info hpt372n __devinitdata = { +static const struct hpt_info hpt372n __devinitdata = { .chip_name = "HPT372N", .chip_type = HPT372N, .udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, @@ -505,7 +574,7 @@ static struct hpt_info hpt372n __devinitdata = { .settings = hpt37x_settings }; -static struct hpt_info hpt302n __devinitdata = { +static const struct hpt_info hpt302n __devinitdata = { .chip_name = "HPT302N", .chip_type = HPT302N, .udma_mask = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, @@ -513,7 +582,7 @@ static struct hpt_info hpt302n __devinitdata = { .settings = hpt37x_settings }; -static struct hpt_info hpt371n __devinitdata = { +static const struct hpt_info hpt371n __devinitdata = { .chip_name = "HPT371N", .chip_type = HPT371N, .udma_mask = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, @@ -1508,7 +1577,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = { */ static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - struct hpt_info *info = NULL; + const struct hpt_info *info = NULL; struct pci_dev *dev2 = NULL; struct ide_port_info d; u8 idx = id->driver_data; @@ -1522,7 +1591,7 @@ static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_devic if (rev < 3) info = &hpt36x; else { - static struct hpt_info *hpt37x_info[] = + static const struct hpt_info *hpt37x_info[] = { &hpt370, &hpt370a, &hpt372, &hpt372n }; info = hpt37x_info[min_t(u8, rev, 6) - 3]; @@ -1552,7 +1621,7 @@ static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_devic d.name = info->chip_name; d.udma_mask = info->udma_mask; - pci_set_drvdata(dev, info); + pci_set_drvdata(dev, (void *)info); if (info == &hpt36x || info == &hpt374) dev2 = pci_get_slot(dev->bus, dev->devfn + 1); @@ -1560,7 +1629,7 @@ static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_devic if (dev2) { int ret; - pci_set_drvdata(dev2, info); + pci_set_drvdata(dev2, (void *)info); if (info == &hpt374) hpt374_init(dev, dev2); diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c index 5c997543531..99b7d763b6c 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 bdf64d99770..0083eaf89c7 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/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c index 4234efeba60..2b4f44e45a1 100644 --- a/drivers/ide/pci/pdc202xx_new.c +++ b/drivers/ide/pci/pdc202xx_new.c @@ -482,8 +482,9 @@ static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev) { struct pci_dev *dev2; - dev2 = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn) + 2, + dev2 = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn) + 1, PCI_FUNC(dev->devfn))); + if (dev2 && dev2->vendor == dev->vendor && dev2->device == dev->device) { diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c index 9329d4a810e..27781d294ce 100644 --- a/drivers/ide/pci/piix.c +++ b/drivers/ide/pci/piix.c @@ -302,9 +302,11 @@ struct ich_laptop { static const struct ich_laptop ich_laptop[] = { /* devid, subvendor, subdev */ + { 0x27DF, 0x1025, 0x0102 }, /* ICH7 on Acer 5602aWLMi */ { 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 d2c8b5524f2..707d5ff66b0 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? */ @@ -324,17 +323,18 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) pci_disable_device(dev); pci_set_power_state(dev, pci_choose_state(dev, state)); - dev->current_state = state.event; return 0; } static int sc1200_resume (struct pci_dev *dev) { ide_hwif_t *hwif = NULL; + int i; + + i = pci_enable_device(dev); + if (i) + return i; - pci_set_power_state(dev, PCI_D0); // bring chip back from sleep state - dev->current_state = PM_EVENT_ON; - pci_enable_device(dev); // // loop over all interfaces that are part of this pci device: // diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c index 6d99441c605..5709c252543 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 6b7bb53acef..d90b4291777 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 5011ba22e36..0151d7fdfb8 100644 --- a/drivers/ide/pci/trm290.c +++ b/drivers/ide/pci/trm290.c @@ -1,7 +1,8 @@ /* - * linux/drivers/ide/pci/trm290.c Version 1.02 Mar. 18, 2000 + * linux/drivers/ide/pci/trm290.c Version 1.05 Dec. 26, 2007 * * Copyright (c) 1997-1998 Mark Lord + * Copyright (c) 2007 MontaVista Software, Inc. <source@mvista.com> * May be copied or modified under the terms of the GNU General Public License * * June 22, 2004 - get rid of check_region @@ -177,7 +178,7 @@ static void trm290_selectproc (ide_drive_t *drive) trm290_prepare_drive(drive, drive->using_dma); } -static void trm290_ide_dma_exec_cmd(ide_drive_t *drive, u8 command) +static void trm290_dma_exec_cmd(ide_drive_t *drive, u8 command) { BUG_ON(HWGROUP(drive)->handler != NULL); /* paranoia check */ ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); @@ -185,7 +186,7 @@ static void trm290_ide_dma_exec_cmd(ide_drive_t *drive, u8 command) outb(command, IDE_COMMAND_REG); } -static int trm290_ide_dma_setup(ide_drive_t *drive) +static int trm290_dma_setup(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; struct request *rq = hwif->hwgroup->rq; @@ -215,7 +216,7 @@ static int trm290_ide_dma_setup(ide_drive_t *drive) return 0; } -static void trm290_ide_dma_start(ide_drive_t *drive) +static void trm290_dma_start(ide_drive_t *drive) { } @@ -240,9 +241,14 @@ static int trm290_ide_dma_test_irq (ide_drive_t *drive) return (status == 0x00ff); } -/* - * Invoked from ide-dma.c at boot time. - */ +static void trm290_dma_host_on(ide_drive_t *drive) +{ +} + +static void trm290_dma_host_off(ide_drive_t *drive) +{ +} + static void __devinit init_hwif_trm290(ide_hwif_t *hwif) { unsigned int cfgbase = 0; @@ -283,11 +289,13 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif) ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 3); - hwif->dma_setup = &trm290_ide_dma_setup; - hwif->dma_exec_cmd = &trm290_ide_dma_exec_cmd; - hwif->dma_start = &trm290_ide_dma_start; - hwif->ide_dma_end = &trm290_ide_dma_end; - hwif->ide_dma_test_irq = &trm290_ide_dma_test_irq; + hwif->dma_host_off = &trm290_dma_host_off; + hwif->dma_host_on = &trm290_dma_host_on; + hwif->dma_setup = &trm290_dma_setup; + hwif->dma_exec_cmd = &trm290_dma_exec_cmd; + hwif->dma_start = &trm290_dma_start; + hwif->ide_dma_end = &trm290_ide_dma_end; + hwif->ide_dma_test_irq = &trm290_ide_dma_test_irq; hwif->selectproc = &trm290_selectproc; #if 1 diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index 816b5311dad..7f7a5988577 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 02d14bf85ab..d2cd5a3d38f 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> @@ -709,7 +704,7 @@ EXPORT_SYMBOL_GPL(ide_setup_pci_devices); /* * Module interfaces */ - + static int pre_init = 1; /* Before first ordered IDE scan */ static LIST_HEAD(ide_pci_drivers); @@ -719,7 +714,7 @@ static LIST_HEAD(ide_pci_drivers); * @module: owner module of the driver * * Registers a driver with the IDE layer. The IDE layer arranges that - * boot time setup is done in the expected device order and then + * boot time setup is done in the expected device order and then * hands the controllers off to the core PCI code to do the rest of * the work. * @@ -729,13 +724,12 @@ static LIST_HEAD(ide_pci_drivers); int __ide_pci_register_driver(struct pci_driver *driver, struct module *module, const char *mod_name) { - if(!pre_init) + if (!pre_init) return __pci_register_driver(driver, module, mod_name); driver->driver.owner = module; list_add_tail(&driver->node, &ide_pci_drivers); return 0; } - EXPORT_SYMBOL_GPL(__ide_pci_register_driver); /** @@ -746,17 +740,18 @@ EXPORT_SYMBOL_GPL(__ide_pci_register_driver); * This is only used during boot up to get the ordering correct. After * boot up the pci layer takes over the job. */ - + static int __init ide_scan_pcidev(struct pci_dev *dev) { struct list_head *l; struct pci_driver *d; - + list_for_each(l, &ide_pci_drivers) { d = list_entry(l, struct pci_driver, node); if (d->id_table) { - const struct pci_device_id *id = pci_match_id(d->id_table, - dev); + const struct pci_device_id *id = + pci_match_id(d->id_table, dev); + if (id != NULL && d->probe(dev, id) >= 0) { dev->driver = d; pci_dev_get(dev); @@ -784,13 +779,13 @@ void __init ide_scan_pcibus (int scan_direction) pre_init = 0; if (!scan_direction) - while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) + while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev))) ide_scan_pcidev(dev); else - while ((dev = pci_get_device_reverse(PCI_ANY_ID, PCI_ANY_ID, dev)) - != NULL) + while ((dev = pci_get_device_reverse(PCI_ANY_ID, PCI_ANY_ID, + dev))) ide_scan_pcidev(dev); - + /* * Hand the drivers over to the PCI layer now we * are post init. @@ -799,9 +794,10 @@ void __init ide_scan_pcibus (int scan_direction) list_for_each_safe(l, n, &ide_pci_drivers) { list_del(l); d = list_entry(l, struct pci_driver, node); - if (__pci_register_driver(d, d->driver.owner, d->driver.mod_name)) - printk(KERN_ERR "%s: failed to register driver for %s\n", - __FUNCTION__, d->driver.mod_name); + if (__pci_register_driver(d, d->driver.owner, + d->driver.mod_name)) + printk(KERN_ERR "%s: failed to register %s driver\n", + __FUNCTION__, d->driver.mod_name); } } #endif diff --git a/drivers/ieee1394/dma.c b/drivers/ieee1394/dma.c index f5f4983dfbf..7c4eb39b702 100644 --- a/drivers/ieee1394/dma.c +++ b/drivers/ieee1394/dma.c @@ -103,8 +103,7 @@ int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, goto err; } - /* just to be safe - this will become unnecessary once sglist->address goes away */ - memset(dma->sglist, 0, dma->n_pages * sizeof(*dma->sglist)); + sg_init_table(dma->sglist, dma->n_pages); /* fill scatter/gather list with pages */ for (i = 0; i < dma->n_pages; i++) { diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c index c39c70a8aa9..67798932095 100644 --- a/drivers/ieee1394/ieee1394_transactions.c +++ b/drivers/ieee1394/ieee1394_transactions.c @@ -235,7 +235,6 @@ int hpsb_packet_success(struct hpsb_packet *packet) packet->node_id); return -EAGAIN; } - BUG(); case ACK_BUSY_X: case ACK_BUSY_A: @@ -282,7 +281,6 @@ int hpsb_packet_success(struct hpsb_packet *packet) packet->ack_code, packet->node_id, packet->tcode); return -EAGAIN; } - BUG(); } struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node, diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index d5dfe11aa5c..b83d254bc86 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -71,11 +71,11 @@ #include <linux/types.h> #include <linux/wait.h> #include <linux/workqueue.h> +#include <linux/scatterlist.h> #include <asm/byteorder.h> #include <asm/errno.h> #include <asm/param.h> -#include <asm/scatterlist.h> #include <asm/system.h> #include <asm/types.h> diff --git a/drivers/infiniband/core/fmr_pool.c b/drivers/infiniband/core/fmr_pool.c index d7f64525469..e8d5f6b6499 100644 --- a/drivers/infiniband/core/fmr_pool.c +++ b/drivers/infiniband/core/fmr_pool.c @@ -291,10 +291,10 @@ struct ib_fmr_pool *ib_create_fmr_pool(struct ib_pd *pd, atomic_set(&pool->flush_ser, 0); init_waitqueue_head(&pool->force_wait); - pool->thread = kthread_create(ib_fmr_cleanup_thread, - pool, - "ib_fmr(%s)", - device->name); + pool->thread = kthread_run(ib_fmr_cleanup_thread, + pool, + "ib_fmr(%s)", + device->name); if (IS_ERR(pool->thread)) { printk(KERN_WARNING PFX "couldn't start cleanup thread\n"); ret = PTR_ERR(pool->thread); diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c index f0c77758937..b5436ca92e6 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 97d108634c5..f7782c882ab 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 2d660ae189e..74d2b72a11d 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; }; @@ -323,6 +322,7 @@ extern int ehca_static_rate; extern int ehca_port_act_time; extern int ehca_use_hp_mr; extern int ehca_scaling_code; +extern int ehca_lock_hcalls; struct ipzu_queue_resp { u32 qe_size; /* queue entry size */ diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c index 15806d14046..5bd7b591987 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 dce503bb7d6..5485799cdc8 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 c6cd38c5321..6a56d86a295 100644 --- a/drivers/infiniband/hw/ehca/ehca_main.c +++ b/drivers/infiniband/hw/ehca/ehca_main.c @@ -43,13 +43,14 @@ #ifdef CONFIG_PPC_64K_PAGES #include <linux/slab.h> #endif + #include "ehca_classes.h" #include "ehca_iverbs.h" #include "ehca_mrmw.h" #include "ehca_tools.h" #include "hcp_if.h" -#define HCAD_VERSION "0024" +#define HCAD_VERSION "0025" MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>"); @@ -66,6 +67,7 @@ int ehca_poll_all_eqs = 1; int ehca_static_rate = -1; int ehca_scaling_code = 0; int ehca_mr_largepage = 1; +int ehca_lock_hcalls = -1; module_param_named(open_aqp1, ehca_open_aqp1, int, S_IRUGO); module_param_named(debug_level, ehca_debug_level, int, S_IRUGO); @@ -77,6 +79,7 @@ module_param_named(poll_all_eqs, ehca_poll_all_eqs, int, S_IRUGO); module_param_named(static_rate, ehca_static_rate, int, S_IRUGO); module_param_named(scaling_code, ehca_scaling_code, int, S_IRUGO); module_param_named(mr_largepage, ehca_mr_largepage, int, S_IRUGO); +module_param_named(lock_hcalls, ehca_lock_hcalls, bool, S_IRUGO); MODULE_PARM_DESC(open_aqp1, "AQP1 on startup (0: no (default), 1: yes)"); @@ -102,6 +105,9 @@ MODULE_PARM_DESC(scaling_code, MODULE_PARM_DESC(mr_largepage, "use large page for MR (0: use PAGE_SIZE (default), " "1: use large page depending on MR size"); +MODULE_PARM_DESC(lock_hcalls, + "serialize all hCalls made by the driver " + "(default: autodetect)"); DEFINE_RWLOCK(ehca_qp_idr_lock); DEFINE_RWLOCK(ehca_cq_idr_lock); @@ -258,6 +264,7 @@ static struct cap_descr { { HCA_CAP_UD_LL_QP, "HCA_CAP_UD_LL_QP" }, { HCA_CAP_RESIZE_MR, "HCA_CAP_RESIZE_MR" }, { HCA_CAP_MINI_QP, "HCA_CAP_MINI_QP" }, + { HCA_CAP_H_ALLOC_RES_SYNC, "HCA_CAP_H_ALLOC_RES_SYNC" }, }; static int ehca_sense_attributes(struct ehca_shca *shca) @@ -327,15 +334,18 @@ 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++) if (EHCA_BMASK_GET(hca_cap_descr[i].mask, shca->hca_cap)) ehca_gen_dbg(" %s", hca_cap_descr[i].descr); + /* Autodetect hCall locking -- the "H_ALLOC_RESOURCE synced" flag is + * a firmware property, so it's valid across all adapters + */ + if (ehca_lock_hcalls == -1) + ehca_lock_hcalls = !(shca->hca_cap & HCA_CAP_H_ALLOC_RES_SYNC); + /* translate supported MR page sizes; always support 4K */ shca->hca_cap_mr_pgsize = EHCA_PAGESIZE; if (ehca_mr_largepage) { /* support extra sizes only if enabled */ diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c index de182648b28..eff5fb55604 100644 --- a/drivers/infiniband/hw/ehca/ehca_qp.c +++ b/drivers/infiniband/hw/ehca/ehca_qp.c @@ -838,7 +838,7 @@ struct ib_srq *ehca_create_srq(struct ib_pd *pd, /* copy back return values */ srq_init_attr->attr.max_wr = qp_init_attr.cap.max_recv_wr; - srq_init_attr->attr.max_sge = qp_init_attr.cap.max_recv_sge; + srq_init_attr->attr.max_sge = 3; /* drive SRQ into RTR state */ mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL); @@ -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; @@ -1755,7 +1750,7 @@ int ehca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr) } srq_attr->max_wr = qpcb->max_nr_outst_recv_wr - 1; - srq_attr->max_sge = qpcb->actual_nr_sges_in_rq_wqe; + srq_attr->max_sge = 3; srq_attr->srq_limit = EHCA_BMASK_GET( MQPCB_CURR_SRQ_LIMIT, qpcb->curr_srq_limit); diff --git a/drivers/infiniband/hw/ehca/hcp_if.c b/drivers/infiniband/hw/ehca/hcp_if.c index c16a21374bb..7029aa65375 100644 --- a/drivers/infiniband/hw/ehca/hcp_if.c +++ b/drivers/infiniband/hw/ehca/hcp_if.c @@ -120,26 +120,21 @@ static long ehca_plpar_hcall_norets(unsigned long opcode, unsigned long arg7) { long ret; - int i, sleep_msecs, do_lock; - unsigned long flags; + int i, sleep_msecs; + unsigned long flags = 0; ehca_gen_dbg("opcode=%lx " HCALL7_REGS_FORMAT, opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7); - /* lock H_FREE_RESOURCE(MR) against itself and H_ALLOC_RESOURCE(MR) */ - if ((opcode == H_FREE_RESOURCE) && (arg7 == 5)) { - arg7 = 0; /* better not upset firmware */ - do_lock = 1; - } - for (i = 0; i < 5; i++) { - if (do_lock) + /* serialize hCalls to work around firmware issue */ + if (ehca_lock_hcalls) spin_lock_irqsave(&hcall_lock, flags); ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7); - if (do_lock) + if (ehca_lock_hcalls) spin_unlock_irqrestore(&hcall_lock, flags); if (H_IS_LONG_BUSY(ret)) { @@ -174,24 +169,22 @@ static long ehca_plpar_hcall9(unsigned long opcode, unsigned long arg9) { long ret; - int i, sleep_msecs, do_lock; + int i, sleep_msecs; unsigned long flags = 0; ehca_gen_dbg("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT, opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); - /* lock H_ALLOC_RESOURCE(MR) against itself and H_FREE_RESOURCE(MR) */ - do_lock = ((opcode == H_ALLOC_RESOURCE) && (arg2 == 5)); - for (i = 0; i < 5; i++) { - if (do_lock) + /* serialize hCalls to work around firmware issue */ + if (ehca_lock_hcalls) spin_lock_irqsave(&hcall_lock, flags); ret = plpar_hcall9(opcode, outs, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); - if (do_lock) + if (ehca_lock_hcalls) spin_unlock_irqrestore(&hcall_lock, flags); if (H_IS_LONG_BUSY(ret)) { @@ -821,7 +814,7 @@ u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle, return ehca_plpar_hcall_norets(H_FREE_RESOURCE, adapter_handle.handle, /* r4 */ mr->ipz_mr_handle.handle, /* r5 */ - 0, 0, 0, 0, 5); + 0, 0, 0, 0, 0); } u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle, diff --git a/drivers/infiniband/hw/ehca/hipz_hw.h b/drivers/infiniband/hw/ehca/hipz_hw.h index d9739e55451..bf996c7acc4 100644 --- a/drivers/infiniband/hw/ehca/hipz_hw.h +++ b/drivers/infiniband/hw/ehca/hipz_hw.h @@ -378,6 +378,7 @@ struct hipz_query_hca { #define HCA_CAP_UD_LL_QP EHCA_BMASK_IBM(16, 16) #define HCA_CAP_RESIZE_MR EHCA_BMASK_IBM(17, 17) #define HCA_CAP_MINI_QP EHCA_BMASK_IBM(18, 18) +#define HCA_CAP_H_ALLOC_RES_SYNC EHCA_BMASK_IBM(19, 19) /* query port response block */ struct hipz_query_port { @@ -402,7 +403,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 645ed71fd79..d1380c7a170 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_eeprom.c b/drivers/infiniband/hw/ipath/ipath_eeprom.c index bcfa3ccb555..e7c25dbbcdc 100644 --- a/drivers/infiniband/hw/ipath/ipath_eeprom.c +++ b/drivers/infiniband/hw/ipath/ipath_eeprom.c @@ -538,7 +538,15 @@ static u8 flash_csum(struct ipath_flash *ifp, int adjust) u8 *ip = (u8 *) ifp; u8 csum = 0, len; - for (len = 0; len < ifp->if_length; len++) + /* + * Limit length checksummed to max length of actual data. + * Checksum of erased eeprom will still be bad, but we avoid + * reading past the end of the buffer we were passed. + */ + len = ifp->if_length; + if (len > sizeof(struct ipath_flash)) + len = sizeof(struct ipath_flash); + while (len--) csum += *ip++; csum -= ifp->if_csum; csum = ~csum; diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c index 6a5dd5cd773..c61f9da2964 100644 --- a/drivers/infiniband/hw/ipath/ipath_intr.c +++ b/drivers/infiniband/hw/ipath/ipath_intr.c @@ -453,7 +453,7 @@ skip_ibchange: } static void handle_supp_msgs(struct ipath_devdata *dd, - unsigned supp_msgs, char msg[512]) + unsigned supp_msgs, char *msg, int msgsz) { /* * Print the message unless it's ibc status change only, which @@ -461,9 +461,9 @@ static void handle_supp_msgs(struct ipath_devdata *dd, */ if (dd->ipath_lasterror & ~INFINIPATH_E_IBSTATUSCHANGED) { int iserr; - iserr = ipath_decode_err(msg, sizeof msg, - dd->ipath_lasterror & - ~INFINIPATH_E_IBSTATUSCHANGED); + iserr = ipath_decode_err(msg, msgsz, + dd->ipath_lasterror & + ~INFINIPATH_E_IBSTATUSCHANGED); if (dd->ipath_lasterror & ~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL | INFINIPATH_E_PKTERRS)) @@ -492,8 +492,8 @@ static void handle_supp_msgs(struct ipath_devdata *dd, } static unsigned handle_frequent_errors(struct ipath_devdata *dd, - ipath_err_t errs, char msg[512], - int *noprint) + ipath_err_t errs, char *msg, + int msgsz, int *noprint) { unsigned long nc; static unsigned long nextmsg_time; @@ -512,7 +512,7 @@ static unsigned handle_frequent_errors(struct ipath_devdata *dd, nextmsg_time = nc + HZ * 3; } else if (supp_msgs) { - handle_supp_msgs(dd, supp_msgs, msg); + handle_supp_msgs(dd, supp_msgs, msg, msgsz); supp_msgs = 0; nmsgs = 0; } @@ -525,14 +525,14 @@ static unsigned handle_frequent_errors(struct ipath_devdata *dd, static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs) { - char msg[512]; + char msg[128]; u64 ignore_this_time = 0; int i, iserr = 0; int chkerrpkts = 0, noprint = 0; unsigned supp_msgs; int log_idx; - supp_msgs = handle_frequent_errors(dd, errs, msg, &noprint); + supp_msgs = handle_frequent_errors(dd, errs, msg, sizeof msg, &noprint); /* don't report errors that are masked */ errs &= ~dd->ipath_maskederrs; diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c index 6a41fdbc8e5..b997ff88401 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 5c29b2bfea1..120a61b03bc 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_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c index 4b6b7ee8e5c..54c61a972de 100644 --- a/drivers/infiniband/hw/ipath/ipath_ruc.c +++ b/drivers/infiniband/hw/ipath/ipath_ruc.c @@ -630,11 +630,8 @@ bail:; void ipath_send_complete(struct ipath_qp *qp, struct ipath_swqe *wqe, enum ib_wc_status status) { - u32 last = qp->s_last; - - if (++last == qp->s_size) - last = 0; - qp->s_last = last; + unsigned long flags; + u32 last; /* See ch. 11.2.4.1 and 10.7.3.1 */ if (!(qp->s_flags & IPATH_S_SIGNAL_REQ_WR) || @@ -658,4 +655,11 @@ void ipath_send_complete(struct ipath_qp *qp, struct ipath_swqe *wqe, wc.port_num = 0; ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 0); } + + spin_lock_irqsave(&qp->s_lock, flags); + last = qp->s_last; + if (++last >= qp->s_size) + last = 0; + qp->s_last = last; + spin_unlock_irqrestore(&qp->s_lock, flags); } diff --git a/drivers/infiniband/hw/ipath/ipath_srq.c b/drivers/infiniband/hw/ipath/ipath_srq.c index 40c36ec1901..2fef36f4b67 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 74f77e7c2c1..c4c998446c7 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/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c index 8bf44daf45e..9d32c49cc65 100644 --- a/drivers/infiniband/hw/mlx4/cq.c +++ b/drivers/infiniband/hw/mlx4/cq.c @@ -430,7 +430,7 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq, wc->dlid_path_bits = (be32_to_cpu(cqe->g_mlpath_rqpn) >> 24) & 0x7f; wc->wc_flags |= be32_to_cpu(cqe->g_mlpath_rqpn) & 0x80000000 ? IB_WC_GRH : 0; - wc->pkey_index = be32_to_cpu(cqe->immed_rss_invalid) >> 16; + wc->pkey_index = be32_to_cpu(cqe->immed_rss_invalid) & 0x7f; } return 0; diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index 6b3322486b5..8cba9c532e6 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c @@ -1282,7 +1282,7 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, int size; int i; - spin_lock_irqsave(&qp->rq.lock, flags); + spin_lock_irqsave(&qp->sq.lock, flags); ind = qp->sq.head; @@ -1448,7 +1448,7 @@ out: (qp->sq.wqe_cnt - 1)); } - spin_unlock_irqrestore(&qp->rq.lock, flags); + spin_unlock_irqrestore(&qp->sq.lock, flags); return err; } diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 87610772a97..059cf92b60a 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c @@ -60,7 +60,7 @@ static struct ib_qp_attr ipoib_cm_err_attr = { .qp_state = IB_QPS_ERR }; -#define IPOIB_CM_RX_DRAIN_WRID 0x7fffffff +#define IPOIB_CM_RX_DRAIN_WRID 0xffffffff static struct ib_send_wr ipoib_cm_rx_drain_wr = { .wr_id = IPOIB_CM_RX_DRAIN_WRID, diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index a03a65ebcf0..c9f6077b615 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 d6879806179..4a17743a639 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/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 950228fb009..bdb6f851740 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -2053,6 +2053,7 @@ static void srp_remove_one(struct ib_device *device) list_for_each_entry_safe(target, tmp_target, &host->target_list, list) { + srp_remove_host(target->scsi_host); scsi_remove_host(target->scsi_host); srp_disconnect_target(target); ib_destroy_cm_id(target->cm_id); diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c index 4941a9e61e9..43aaa5cebd1 100644 --- a/drivers/input/misc/pcspkr.c +++ b/drivers/input/misc/pcspkr.c @@ -24,7 +24,7 @@ MODULE_DESCRIPTION("PC Speaker beeper driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:pcspkr"); -#ifdef CONFIG_X86 +#if defined(CONFIG_MIPS) || defined(CONFIG_X86) /* Use the global PIT lock ! */ #include <asm/i8253.h> #else diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index 5ce632ca681..b88569e21d6 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/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index f59aecf5ec1..fd9c5d51870 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -267,13 +267,12 @@ static int ads7846_read12_ser(struct device *dev, unsigned command) ts->irq_disabled = 0; enable_irq(spi->irq); - if (req->msg.status) - status = req->msg.status; - - /* on-wire is a must-ignore bit, a BE12 value, then padding */ - sample = be16_to_cpu(req->sample); - sample = sample >> 3; - sample &= 0x0fff; + if (status == 0) { + /* on-wire is a must-ignore bit, a BE12 value, then padding */ + sample = be16_to_cpu(req->sample); + sample = sample >> 3; + sample &= 0x0fff; + } kfree(req); return status ? status : sample; diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c index 476012b6dfa..48c1775ef5b 100644 --- a/drivers/isdn/capi/capidrv.c +++ b/drivers/isdn/capi/capidrv.c @@ -1843,6 +1843,7 @@ static int if_sendbuf(int id, int channel, int doack, struct sk_buff *skb) int msglen; u16 errcode; u16 datahandle; + u32 data; if (!card) { printk(KERN_ERR "capidrv: if_sendbuf called with invalid driverId %d!\n", @@ -1860,9 +1861,26 @@ static int if_sendbuf(int id, int channel, int doack, struct sk_buff *skb) return 0; } datahandle = nccip->datahandle; + + /* + * Here we copy pointer skb->data into the 32-bit 'Data' field. + * The 'Data' field is not used in practice in linux kernel + * (neither in 32 or 64 bit), but should have some value, + * since a CAPI message trace will display it. + * + * The correct value in the 32 bit case is the address of the + * data, in 64 bit it makes no sense, we use 0 there. + */ + +#ifdef CONFIG_64BIT + data = 0; +#else + data = (unsigned long) skb->data; +#endif + capi_fill_DATA_B3_REQ(&sendcmsg, global.ap.applid, card->msgid++, nccip->ncci, /* adr */ - (u32) skb->data, /* Data */ + data, /* Data */ skb->len, /* DataLength */ datahandle, /* DataHandle */ 0 /* Flags */ @@ -2123,7 +2141,10 @@ static int capidrv_delcontr(u16 contr) printk(KERN_ERR "capidrv: delcontr: no contr %u\n", contr); return -1; } - #warning FIXME: maybe a race condition the card should be removed here from global list /kkeil + + /* FIXME: maybe a race condition the card should be removed + * here from global list /kkeil + */ spin_unlock_irqrestore(&global_lock, flags); del_timer(&card->listentimer); diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig index a3b945ac325..7832d8ba8e4 100644 --- a/drivers/isdn/hisax/Kconfig +++ b/drivers/isdn/hisax/Kconfig @@ -109,7 +109,7 @@ config HISAX_16_3 config HISAX_TELESPCI bool "Teles PCI" - depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) + depends on PCI && PCI_LEGACY && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) help This enables HiSax support for the Teles PCI. See <file:Documentation/isdn/README.HiSax> on how to configure it. @@ -237,7 +237,7 @@ config HISAX_MIC config HISAX_NETJET bool "NETjet card" - depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) + depends on PCI && PCI_LEGACY && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) help This enables HiSax support for the NetJet from Traverse Technologies. @@ -248,7 +248,7 @@ config HISAX_NETJET config HISAX_NETJET_U bool "NETspider U card" - depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) + depends on PCI && PCI_LEGACY && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) help This enables HiSax support for the Netspider U interface ISDN card from Traverse Technologies. @@ -287,7 +287,7 @@ config HISAX_HSTSAPHIR config HISAX_BKM_A4T bool "Telekom A4T card" - depends on PCI + depends on PCI && PCI_LEGACY help This enables HiSax support for the Telekom A4T card. @@ -297,7 +297,7 @@ config HISAX_BKM_A4T config HISAX_SCT_QUADRO bool "Scitel Quadro card" - depends on PCI + depends on PCI && PCI_LEGACY help This enables HiSax support for the Scitel Quadro card. @@ -316,7 +316,7 @@ config HISAX_GAZEL config HISAX_HFC_PCI bool "HFC PCI-Bus cards" - depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) + depends on PCI && PCI_LEGACY && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) help This enables HiSax support for the HFC-S PCI 2BDS0 based cards. @@ -325,7 +325,7 @@ config HISAX_HFC_PCI config HISAX_W6692 bool "Winbond W6692 based cards" - depends on PCI + depends on PCI && PCI_LEGACY help This enables HiSax support for Winbond W6692 based PCI ISDN cards. @@ -341,7 +341,7 @@ config HISAX_HFC_SX config HISAX_ENTERNOW_PCI bool "Formula-n enter:now PCI card" - depends on HISAX_NETJET && PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) + depends on HISAX_NETJET && PCI && PCI_LEGACY && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) help This enables HiSax support for the Formula-n enter:now PCI ISDN card. @@ -411,7 +411,7 @@ config HISAX_HFC4S8S config HISAX_FRITZ_PCIPNP tristate "AVM Fritz!Card PCI/PCIv2/PnP support (EXPERIMENTAL)" - depends on PCI && EXPERIMENTAL + depends on PCI && PCI_LEGACY && EXPERIMENTAL help This enables the driver for the AVM Fritz!Card PCI, Fritz!Card PCI v2 and Fritz!Card PnP. diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c index f8b79783c8b..035d158779d 100644 --- a/drivers/isdn/hisax/avm_pci.c +++ b/drivers/isdn/hisax/avm_pci.c @@ -830,7 +830,7 @@ static int __devinit avm_pnp_setup(struct IsdnCardState *cs) #endif /* __ISAPNP__ */ -#ifndef CONFIG_PCI +#ifndef CONFIG_PCI_LEGACY static int __devinit avm_pci_setup(struct IsdnCardState *cs) { @@ -872,7 +872,7 @@ static int __devinit avm_pci_setup(struct IsdnCardState *cs) return (1); } -#endif /* CONFIG_PCI */ +#endif /* CONFIG_PCI_LEGACY */ int __devinit setup_avm_pcipnp(struct IsdnCard *card) diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c index 82674507874..2d670856d14 100644 --- a/drivers/isdn/hisax/diva.c +++ b/drivers/isdn/hisax/diva.c @@ -1148,7 +1148,7 @@ static int __devinit setup_diva_isapnp(struct IsdnCard *card) #endif /* ISAPNP */ -#ifdef CONFIG_PCI +#ifdef CONFIG_PCI_LEGACY static struct pci_dev *dev_diva __devinitdata = NULL; static struct pci_dev *dev_diva_u __devinitdata = NULL; static struct pci_dev *dev_diva201 __devinitdata = NULL; @@ -1229,14 +1229,14 @@ static int __devinit setup_diva_pci(struct IsdnCard *card) return (1); /* card found */ } -#else /* if !CONFIG_PCI */ +#else /* if !CONFIG_PCI_LEGACY */ static int __devinit setup_diva_pci(struct IsdnCard *card) { return (-1); /* card not found; continue search */ } -#endif /* CONFIG_PCI */ +#endif /* CONFIG_PCI_LEGACY */ int __devinit setup_diva(struct IsdnCard *card) diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c index 948a9b290fd..d272d8ce653 100644 --- a/drivers/isdn/hisax/elsa.c +++ b/drivers/isdn/hisax/elsa.c @@ -883,7 +883,7 @@ setup_elsa_isa(struct IsdnCard *card) val += 'A' - 3; if (val == 'B' || val == 'C') val ^= 1; - if ((cs->subtyp == ELSA_PCFPRO) && (val = 'G')) + if ((cs->subtyp == ELSA_PCFPRO) && (val == 'G')) val = 'C'; printk(KERN_INFO "Elsa: %s found at %#lx Rev.:%c IRQ %d\n", @@ -1025,7 +1025,7 @@ setup_elsa_pcmcia(struct IsdnCard *card) cs->irq); } -#ifdef CONFIG_PCI +#ifdef CONFIG_PCI_LEGACY static struct pci_dev *dev_qs1000 __devinitdata = NULL; static struct pci_dev *dev_qs3000 __devinitdata = NULL; @@ -1093,7 +1093,7 @@ setup_elsa_pci(struct IsdnCard *card) { return (1); } -#endif /* CONFIG_PCI */ +#endif /* CONFIG_PCI_LEGACY */ static int __devinit setup_elsa_common(struct IsdnCard *card) diff --git a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c index 3efa719b6d2..f66620ad8e7 100644 --- a/drivers/isdn/hisax/gazel.c +++ b/drivers/isdn/hisax/gazel.c @@ -532,6 +532,7 @@ setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs) return (0); } +#ifdef CONFIG_PCI_LEGACY static struct pci_dev *dev_tel __devinitdata = NULL; static int __devinit @@ -620,6 +621,7 @@ setup_gazelpci(struct IsdnCardState *cs) return (0); } +#endif /* CONFIG_PCI_LEGACY */ int __devinit setup_gazel(struct IsdnCard *card) @@ -639,7 +641,7 @@ setup_gazel(struct IsdnCard *card) return (0); } else { -#ifdef CONFIG_PCI +#ifdef CONFIG_PCI_LEGACY if (setup_gazelpci(cs)) return (0); #else diff --git a/drivers/isdn/hisax/hfcscard.c b/drivers/isdn/hisax/hfcscard.c index 57670dc5034..909d6709ec1 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/hisax/niccy.c b/drivers/isdn/hisax/niccy.c index e5918c6fe73..bd9921128aa 100644 --- a/drivers/isdn/hisax/niccy.c +++ b/drivers/isdn/hisax/niccy.c @@ -223,7 +223,6 @@ static int niccy_card_msg(struct IsdnCardState *cs, int mt, void *arg) return 0; } -static struct pci_dev *niccy_dev __devinitdata = NULL; #ifdef __ISAPNP__ static struct pnp_card *pnp_c __devinitdata = NULL; #endif @@ -299,7 +298,9 @@ int __devinit setup_niccy(struct IsdnCard *card) return 0; } } else { -#ifdef CONFIG_PCI +#ifdef CONFIG_PCI_LEGACY + static struct pci_dev *niccy_dev __devinitdata; + u_int pci_ioaddr; cs->subtyp = 0; if ((niccy_dev = pci_find_device(PCI_VENDOR_ID_SATSAGEM, @@ -356,7 +357,7 @@ int __devinit setup_niccy(struct IsdnCard *card) printk(KERN_WARNING "Niccy: io0 0 and NO_PCI_BIOS\n"); printk(KERN_WARNING "Niccy: unable to config NICCY PCI\n"); return 0; -#endif /* CONFIG_PCI */ +#endif /* CONFIG_PCI_LEGACY */ } printk(KERN_INFO "HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n", CardType[cs->typ], (cs->subtyp == 1) ? "PnP" : "PCI", diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c index 03dfc32166a..95425f3d222 100644 --- a/drivers/isdn/hisax/sedlbauer.c +++ b/drivers/isdn/hisax/sedlbauer.c @@ -600,7 +600,7 @@ setup_sedlbauer_isapnp(struct IsdnCard *card, int *bytecnt) } #endif /* __ISAPNP__ */ -#ifdef CONFIG_PCI +#ifdef CONFIG_PCI_LEGACY static struct pci_dev *dev_sedl __devinitdata = NULL; static int __devinit @@ -675,7 +675,7 @@ setup_sedlbauer_pci(struct IsdnCard *card) return (1); } -#endif /* CONFIG_PCI */ +#endif /* CONFIG_PCI_LEGACY */ int __devinit setup_sedlbauer(struct IsdnCard *card) diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index c6df2925ebd..9cef6fcf587 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -914,6 +914,9 @@ isdn_readbchan_tty(int di, int channel, struct tty_struct *tty, int cisco_hack) dflag = 0; count_pull = count_put = 0; while ((count_pull < skb->len) && (len > 0)) { + /* push every character but the last to the tty buffer directly */ + if ( count_put ) + tty_insert_flip_char(tty, last, TTY_NORMAL); len--; if (dev->drv[di]->DLEflag & DLEmask) { last = DLE; @@ -1515,6 +1518,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 +1603,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 +1648,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 +1678,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 b39d1f5b378..ced83c202ca 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/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 4e5f87c1e71..9cb6e5021ad 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -85,6 +85,8 @@ isdn_tty_try_read(modem_info * info, struct sk_buff *skb) tty_insert_flip_char(tty, DLE, 0); tty_insert_flip_char(tty, *dp++, 0); } + if (*dp == DLE) + tty_insert_flip_char(tty, DLE, 0); last = *dp; } else { #endif @@ -2645,7 +2647,12 @@ isdn_tty_modem_result(int code, modem_info * info) if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) { return; } +#ifdef CONFIG_ISDN_AUDIO + if ( !info->vonline ) + tty_ldisc_flush(info->tty); +#else tty_ldisc_flush(info->tty); +#endif if ((info->flags & ISDN_ASYNC_CHECK_CD) && (!((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) && (info->flags & ISDN_ASYNC_CALLOUT_NOHUP)))) { diff --git a/drivers/isdn/sc/card.h b/drivers/isdn/sc/card.h index 5992f63c383..0120bcf8831 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 92016a2608e..5ff6ae86844 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 e0331e0094f..712220cef13 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 07ae280e8fe..47c10b8f89b 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 729f1cd9360..4e04e49a2f1 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 a6ace302e0c..bd46de6bf89 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/leds/led-class.c b/drivers/leds/led-class.c index 4211293ce86..64c66b3769c 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -106,12 +106,12 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) goto err_out; /* add to the list of leds */ - write_lock(&leds_list_lock); + down_write(&leds_list_lock); list_add_tail(&led_cdev->node, &leds_list); - write_unlock(&leds_list_lock); + up_write(&leds_list_lock); #ifdef CONFIG_LEDS_TRIGGERS - rwlock_init(&led_cdev->trigger_lock); + init_rwsem(&led_cdev->trigger_lock); rc = device_create_file(led_cdev->dev, &dev_attr_trigger); if (rc) @@ -147,17 +147,17 @@ void led_classdev_unregister(struct led_classdev *led_cdev) device_remove_file(led_cdev->dev, &dev_attr_brightness); #ifdef CONFIG_LEDS_TRIGGERS device_remove_file(led_cdev->dev, &dev_attr_trigger); - write_lock(&led_cdev->trigger_lock); + down_write(&led_cdev->trigger_lock); if (led_cdev->trigger) led_trigger_set(led_cdev, NULL); - write_unlock(&led_cdev->trigger_lock); + up_write(&led_cdev->trigger_lock); #endif device_unregister(led_cdev->dev); - write_lock(&leds_list_lock); + down_write(&leds_list_lock); list_del(&led_cdev->node); - write_unlock(&leds_list_lock); + up_write(&leds_list_lock); } EXPORT_SYMBOL_GPL(led_classdev_unregister); diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c index 9b015f9af35..5d1ca10524b 100644 --- a/drivers/leds/led-core.c +++ b/drivers/leds/led-core.c @@ -14,11 +14,11 @@ #include <linux/kernel.h> #include <linux/list.h> #include <linux/module.h> -#include <linux/spinlock.h> +#include <linux/rwsem.h> #include <linux/leds.h> #include "leds.h" -DEFINE_RWLOCK(leds_list_lock); +DECLARE_RWSEM(leds_list_lock); LIST_HEAD(leds_list); EXPORT_SYMBOL_GPL(leds_list); diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c index 575368c2b10..13c9026d68a 100644 --- a/drivers/leds/led-triggers.c +++ b/drivers/leds/led-triggers.c @@ -19,13 +19,14 @@ #include <linux/device.h> #include <linux/sysdev.h> #include <linux/timer.h> +#include <linux/rwsem.h> #include <linux/leds.h> #include "leds.h" /* * Nests outside led_cdev->trigger_lock */ -static DEFINE_RWLOCK(triggers_list_lock); +static DECLARE_RWSEM(triggers_list_lock); static LIST_HEAD(trigger_list); ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr, @@ -44,24 +45,24 @@ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr, trigger_name[len - 1] = '\0'; if (!strcmp(trigger_name, "none")) { - write_lock(&led_cdev->trigger_lock); + down_write(&led_cdev->trigger_lock); led_trigger_set(led_cdev, NULL); - write_unlock(&led_cdev->trigger_lock); + up_write(&led_cdev->trigger_lock); return count; } - read_lock(&triggers_list_lock); + down_read(&triggers_list_lock); list_for_each_entry(trig, &trigger_list, next_trig) { if (!strcmp(trigger_name, trig->name)) { - write_lock(&led_cdev->trigger_lock); + down_write(&led_cdev->trigger_lock); led_trigger_set(led_cdev, trig); - write_unlock(&led_cdev->trigger_lock); + up_write(&led_cdev->trigger_lock); - read_unlock(&triggers_list_lock); + up_read(&triggers_list_lock); return count; } } - read_unlock(&triggers_list_lock); + up_read(&triggers_list_lock); return -EINVAL; } @@ -74,8 +75,8 @@ ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr, struct led_trigger *trig; int len = 0; - read_lock(&triggers_list_lock); - read_lock(&led_cdev->trigger_lock); + down_read(&triggers_list_lock); + down_read(&led_cdev->trigger_lock); if (!led_cdev->trigger) len += sprintf(buf+len, "[none] "); @@ -89,8 +90,8 @@ ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr, else len += sprintf(buf+len, "%s ", trig->name); } - read_unlock(&led_cdev->trigger_lock); - read_unlock(&triggers_list_lock); + up_read(&led_cdev->trigger_lock); + up_read(&triggers_list_lock); len += sprintf(len+buf, "\n"); return len; @@ -145,14 +146,14 @@ void led_trigger_set_default(struct led_classdev *led_cdev) if (!led_cdev->default_trigger) return; - read_lock(&triggers_list_lock); - write_lock(&led_cdev->trigger_lock); + down_read(&triggers_list_lock); + down_write(&led_cdev->trigger_lock); list_for_each_entry(trig, &trigger_list, next_trig) { if (!strcmp(led_cdev->default_trigger, trig->name)) led_trigger_set(led_cdev, trig); } - write_unlock(&led_cdev->trigger_lock); - read_unlock(&triggers_list_lock); + up_write(&led_cdev->trigger_lock); + up_read(&triggers_list_lock); } int led_trigger_register(struct led_trigger *trigger) @@ -163,20 +164,20 @@ int led_trigger_register(struct led_trigger *trigger) INIT_LIST_HEAD(&trigger->led_cdevs); /* Add to the list of led triggers */ - write_lock(&triggers_list_lock); + down_write(&triggers_list_lock); list_add_tail(&trigger->next_trig, &trigger_list); - write_unlock(&triggers_list_lock); + up_write(&triggers_list_lock); /* Register with any LEDs that have this as a default trigger */ - read_lock(&leds_list_lock); + down_read(&leds_list_lock); list_for_each_entry(led_cdev, &leds_list, node) { - write_lock(&led_cdev->trigger_lock); + down_write(&led_cdev->trigger_lock); if (!led_cdev->trigger && led_cdev->default_trigger && !strcmp(led_cdev->default_trigger, trigger->name)) led_trigger_set(led_cdev, trigger); - write_unlock(&led_cdev->trigger_lock); + up_write(&led_cdev->trigger_lock); } - read_unlock(&leds_list_lock); + up_read(&leds_list_lock); return 0; } @@ -206,19 +207,19 @@ void led_trigger_unregister(struct led_trigger *trigger) struct led_classdev *led_cdev; /* Remove from the list of led triggers */ - write_lock(&triggers_list_lock); + down_write(&triggers_list_lock); list_del(&trigger->next_trig); - write_unlock(&triggers_list_lock); + up_write(&triggers_list_lock); /* Remove anyone actively using this trigger */ - read_lock(&leds_list_lock); + down_read(&leds_list_lock); list_for_each_entry(led_cdev, &leds_list, node) { - write_lock(&led_cdev->trigger_lock); + down_write(&led_cdev->trigger_lock); if (led_cdev->trigger == trigger) led_trigger_set(led_cdev, NULL); - write_unlock(&led_cdev->trigger_lock); + up_write(&led_cdev->trigger_lock); } - read_unlock(&leds_list_lock); + up_read(&leds_list_lock); } void led_trigger_unregister_simple(struct led_trigger *trigger) diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index 47d90db280c..99bc50059d3 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -60,7 +60,7 @@ static void gpio_led_set(struct led_classdev *led_cdev, gpio_set_value(led_dat->gpio, level); } -static int __init gpio_led_probe(struct platform_device *pdev) +static int gpio_led_probe(struct platform_device *pdev) { struct gpio_led_platform_data *pdata = pdev->dev.platform_data; struct gpio_led *cur_led; @@ -93,13 +93,13 @@ static int __init gpio_led_probe(struct platform_device *pdev) gpio_direction_output(led_dat->gpio, led_dat->active_low); + INIT_WORK(&led_dat->work, gpio_led_work); + ret = led_classdev_register(&pdev->dev, &led_dat->cdev); if (ret < 0) { gpio_free(led_dat->gpio); goto err; } - - INIT_WORK(&led_dat->work, gpio_led_work); } platform_set_drvdata(pdev, leds_data); @@ -110,17 +110,17 @@ err: if (i > 0) { for (i = i - 1; i >= 0; i--) { led_classdev_unregister(&leds_data[i].cdev); + cancel_work_sync(&leds_data[i].work); gpio_free(leds_data[i].gpio); } } - flush_scheduled_work(); kfree(leds_data); return ret; } -static int __exit gpio_led_remove(struct platform_device *pdev) +static int __devexit gpio_led_remove(struct platform_device *pdev) { int i; struct gpio_led_platform_data *pdata = pdev->dev.platform_data; @@ -130,9 +130,10 @@ static int __exit gpio_led_remove(struct platform_device *pdev) for (i = 0; i < pdata->num_leds; i++) { led_classdev_unregister(&leds_data[i].cdev); + cancel_work_sync(&leds_data[i].work); gpio_free(leds_data[i].gpio); } - + kfree(leds_data); return 0; @@ -144,7 +145,7 @@ static int gpio_led_suspend(struct platform_device *pdev, pm_message_t state) struct gpio_led_platform_data *pdata = pdev->dev.platform_data; struct gpio_led_data *leds_data; int i; - + leds_data = platform_get_drvdata(pdev); for (i = 0; i < pdata->num_leds; i++) @@ -172,7 +173,8 @@ static int gpio_led_resume(struct platform_device *pdev) #endif static struct platform_driver gpio_led_driver = { - .remove = __exit_p(gpio_led_remove), + .probe = gpio_led_probe, + .remove = __devexit_p(gpio_led_remove), .suspend = gpio_led_suspend, .resume = gpio_led_resume, .driver = { @@ -183,7 +185,7 @@ static struct platform_driver gpio_led_driver = { static int __init gpio_led_init(void) { - return platform_driver_probe(&gpio_led_driver, gpio_led_probe); + return platform_driver_register(&gpio_led_driver); } static void __exit gpio_led_exit(void) diff --git a/drivers/leds/leds-locomo.c b/drivers/leds/leds-locomo.c index bfac499f325..2207335e921 100644 --- a/drivers/leds/leds-locomo.c +++ b/drivers/leds/leds-locomo.c @@ -19,7 +19,7 @@ static void locomoled_brightness_set(struct led_classdev *led_cdev, enum led_brightness value, int offset) { - struct locomo_dev *locomo_dev = LOCOMO_DEV(led_cdev->dev); + struct locomo_dev *locomo_dev = LOCOMO_DEV(led_cdev->dev->parent); unsigned long flags; local_irq_save(flags); diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h index f2f3884fe06..12b6fe93b13 100644 --- a/drivers/leds/leds.h +++ b/drivers/leds/leds.h @@ -14,6 +14,7 @@ #define __LEDS_H_INCLUDED #include <linux/device.h> +#include <linux/rwsem.h> #include <linux/leds.h> static inline void led_set_brightness(struct led_classdev *led_cdev, @@ -26,7 +27,7 @@ static inline void led_set_brightness(struct led_classdev *led_cdev, led_cdev->brightness_set(led_cdev, value); } -extern rwlock_t leds_list_lock; +extern struct rw_semaphore leds_list_lock; extern struct list_head leds_list; #ifdef CONFIG_LEDS_TRIGGERS diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c index 8904f72f97c..e2eec38c83c 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 9d716fa42ca..3b92a61ba8d 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/adbhid.c b/drivers/macintosh/adbhid.c index 883da72b536..ef4c117ea35 100644 --- a/drivers/macintosh/adbhid.c +++ b/drivers/macintosh/adbhid.c @@ -322,8 +322,9 @@ adbhid_input_keycode(int id, int scancode, int repeat) input_sync(ahid->input); input_report_key(ahid->input, KEY_CAPSLOCK, 0); input_sync(ahid->input); + return; } - return; + break; #ifdef CONFIG_PPC_PMAC case ADB_KEY_POWER_OLD: /* Power key on PBook 3400 needs remapping */ switch(pmac_call_feature(PMAC_FTR_GET_MB_INFO, diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index dc741d3a453..6123c70153d 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -2336,6 +2336,7 @@ powerbook_sleep_3400(void) ret = pmac_suspend_devices(); if (ret) { pbook_free_pci_save(); + iounmap(mem_ctrl); printk(KERN_ERR "Sleep rejected by devices\n"); return ret; } diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c index 516d943227e..075b4d99e35 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/Kconfig b/drivers/md/Kconfig index 9b6fbf044fd..3fa7c77d9bd 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig @@ -269,7 +269,7 @@ config DM_MULTIPATH_RDAC config DM_MULTIPATH_HP tristate "HP MSA multipath support (EXPERIMENTAL)" - depends on DM_MULTIPATH && BLK_DEV_DM && EXPERIMENTAL + depends on DM_MULTIPATH && BLK_DEV_DM && SCSI && EXPERIMENTAL ---help--- Multipath support for HP MSA (Active/Passive) series hardware. diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 7c426d07a55..1b1ef3130e6 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-crypt.c b/drivers/md/dm-crypt.c index 28c6ae095c5..6b66ee46b87 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -398,7 +398,8 @@ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size) struct bio *clone; unsigned int nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; gfp_t gfp_mask = GFP_NOIO | __GFP_HIGHMEM; - unsigned int i; + unsigned i, len; + struct page *page; clone = bio_alloc_bioset(GFP_NOIO, nr_iovecs, cc->bs); if (!clone) @@ -407,10 +408,8 @@ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size) clone_init(io, clone); for (i = 0; i < nr_iovecs; i++) { - struct bio_vec *bv = bio_iovec_idx(clone, i); - - bv->bv_page = mempool_alloc(cc->page_pool, gfp_mask); - if (!bv->bv_page) + page = mempool_alloc(cc->page_pool, gfp_mask); + if (!page) break; /* @@ -421,15 +420,14 @@ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size) if (i == (MIN_BIO_PAGES - 1)) gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT; - bv->bv_offset = 0; - if (size > PAGE_SIZE) - bv->bv_len = PAGE_SIZE; - else - bv->bv_len = size; + len = (size > PAGE_SIZE) ? PAGE_SIZE : size; + + if (!bio_add_page(clone, page, len, 0)) { + mempool_free(page, cc->page_pool); + break; + } - clone->bi_size += bv->bv_len; - clone->bi_vcnt++; - size -= bv->bv_len; + size -= len; } if (!clone->bi_size) { @@ -511,6 +509,9 @@ static void crypt_endio(struct bio *clone, int error) struct crypt_config *cc = io->target->private; unsigned read_io = bio_data_dir(clone) == READ; + if (unlikely(!bio_flagged(clone, BIO_UPTODATE) && !error)) + error = -EIO; + /* * free the processed pages */ @@ -519,10 +520,8 @@ static void crypt_endio(struct bio *clone, int error) goto out; } - if (unlikely(!bio_flagged(clone, BIO_UPTODATE))) { - error = -EIO; + if (unlikely(error)) goto out; - } bio_put(clone); kcryptd_queue_crypt(io); diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 138200bf5e0..9627fa0f947 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -332,6 +332,8 @@ static int dm_hash_rename(const char *old, const char *new) dm_table_put(table); } + dm_kobject_uevent(hc->md); + dm_put(hc->md); up_write(&_hash_lock); kfree(old_name); @@ -1250,21 +1252,17 @@ static int target_message(struct dm_ioctl *param, size_t param_size) if (!table) goto out_argv; - if (tmsg->sector >= dm_table_get_size(table)) { + ti = dm_table_find_target(table, tmsg->sector); + if (!dm_target_is_valid(ti)) { DMWARN("Target message sector outside device."); r = -EINVAL; - goto out_table; - } - - ti = dm_table_find_target(table, tmsg->sector); - if (ti->type->message) + } else if (ti->type->message) r = ti->type->message(ti, argc, argv); else { DMWARN("Target type does not support messages"); r = -EINVAL; } - out_table: dm_table_put(table); out_argv: kfree(argv); diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 8939e610508..47818d8249c 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -99,9 +99,14 @@ static void combine_restrictions_low(struct io_restrictions *lhs, lhs->max_segment_size = min_not_zero(lhs->max_segment_size, rhs->max_segment_size); + lhs->max_hw_sectors = + min_not_zero(lhs->max_hw_sectors, rhs->max_hw_sectors); + lhs->seg_boundary_mask = min_not_zero(lhs->seg_boundary_mask, rhs->seg_boundary_mask); + lhs->bounce_pfn = min_not_zero(lhs->bounce_pfn, rhs->bounce_pfn); + lhs->no_cluster |= rhs->no_cluster; } @@ -187,8 +192,10 @@ static int alloc_targets(struct dm_table *t, unsigned int num) /* * Allocate both the target array and offset array at once. + * Append an empty entry to catch sectors beyond the end of + * the device. */ - n_highs = (sector_t *) dm_vcalloc(num, sizeof(struct dm_target) + + n_highs = (sector_t *) dm_vcalloc(num + 1, sizeof(struct dm_target) + sizeof(sector_t)); if (!n_highs) return -ENOMEM; @@ -562,10 +569,15 @@ void dm_set_device_limits(struct dm_target *ti, struct block_device *bdev) rs->max_segment_size = min_not_zero(rs->max_segment_size, q->max_segment_size); + rs->max_hw_sectors = + min_not_zero(rs->max_hw_sectors, q->max_hw_sectors); + rs->seg_boundary_mask = min_not_zero(rs->seg_boundary_mask, q->seg_boundary_mask); + rs->bounce_pfn = min_not_zero(rs->bounce_pfn, q->bounce_pfn); + rs->no_cluster |= !test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); } EXPORT_SYMBOL_GPL(dm_set_device_limits); @@ -697,6 +709,8 @@ static void check_for_valid_limits(struct io_restrictions *rs) { if (!rs->max_sectors) rs->max_sectors = SAFE_MAX_SECTORS; + if (!rs->max_hw_sectors) + rs->max_hw_sectors = SAFE_MAX_SECTORS; if (!rs->max_phys_segments) rs->max_phys_segments = MAX_PHYS_SEGMENTS; if (!rs->max_hw_segments) @@ -707,6 +721,8 @@ static void check_for_valid_limits(struct io_restrictions *rs) rs->max_segment_size = MAX_SEGMENT_SIZE; if (!rs->seg_boundary_mask) rs->seg_boundary_mask = -1; + if (!rs->bounce_pfn) + rs->bounce_pfn = -1; } int dm_table_add_target(struct dm_table *t, const char *type, @@ -861,6 +877,9 @@ struct dm_target *dm_table_get_target(struct dm_table *t, unsigned int index) /* * Search the btree for the correct target. + * + * Caller should check returned pointer with dm_target_is_valid() + * to trap I/O beyond end of device. */ struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector) { @@ -890,7 +909,9 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q) q->max_hw_segments = t->limits.max_hw_segments; q->hardsect_size = t->limits.hardsect_size; q->max_segment_size = t->limits.max_segment_size; + q->max_hw_sectors = t->limits.max_hw_sectors; q->seg_boundary_mask = t->limits.seg_boundary_mask; + q->bounce_pfn = t->limits.bounce_pfn; if (t->limits.no_cluster) q->queue_flags &= ~(1 << QUEUE_FLAG_CLUSTER); else @@ -993,8 +1014,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/dm.c b/drivers/md/dm.c index 07cbbb8eb3e..88c0fd65782 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -672,13 +672,19 @@ static struct bio *clone_bio(struct bio *bio, sector_t sector, return clone; } -static void __clone_and_map(struct clone_info *ci) +static int __clone_and_map(struct clone_info *ci) { struct bio *clone, *bio = ci->bio; - struct dm_target *ti = dm_table_find_target(ci->map, ci->sector); - sector_t len = 0, max = max_io_len(ci->md, ci->sector, ti); + struct dm_target *ti; + sector_t len = 0, max; struct dm_target_io *tio; + ti = dm_table_find_target(ci->map, ci->sector); + if (!dm_target_is_valid(ti)) + return -EIO; + + max = max_io_len(ci->md, ci->sector, ti); + /* * Allocate a target io object. */ @@ -736,6 +742,9 @@ static void __clone_and_map(struct clone_info *ci) do { if (offset) { ti = dm_table_find_target(ci->map, ci->sector); + if (!dm_target_is_valid(ti)) + return -EIO; + max = max_io_len(ci->md, ci->sector, ti); tio = alloc_tio(ci->md); @@ -759,6 +768,8 @@ static void __clone_and_map(struct clone_info *ci) ci->idx++; } + + return 0; } /* @@ -767,6 +778,7 @@ static void __clone_and_map(struct clone_info *ci) static int __split_bio(struct mapped_device *md, struct bio *bio) { struct clone_info ci; + int error = 0; ci.map = dm_get_table(md); if (unlikely(!ci.map)) @@ -784,11 +796,11 @@ static int __split_bio(struct mapped_device *md, struct bio *bio) ci.idx = bio->bi_idx; start_io_acct(ci.io); - while (ci.sector_count) - __clone_and_map(&ci); + while (ci.sector_count && !error) + error = __clone_and_map(&ci); /* drop the extra reference count */ - dec_pending(ci.io, 0); + dec_pending(ci.io, error); dm_table_put(ci.map); return 0; @@ -1502,7 +1514,7 @@ int dm_resume(struct mapped_device *md) dm_table_unplug_all(map); - kobject_uevent(&md->disk->kobj, KOBJ_CHANGE); + dm_kobject_uevent(md); r = 0; @@ -1516,6 +1528,11 @@ out: /*----------------------------------------------------------------- * Event notification. *---------------------------------------------------------------*/ +void dm_kobject_uevent(struct mapped_device *md) +{ + kobject_uevent(&md->disk->kobj, KOBJ_CHANGE); +} + uint32_t dm_next_uevent_seq(struct mapped_device *md) { return atomic_add_return(1, &md->uevent_seq); diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 4b3faa45277..b4584a39383 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -112,6 +112,11 @@ int dm_table_resume_targets(struct dm_table *t); int dm_table_any_congested(struct dm_table *t, int bdi_bits); void dm_table_unplug_all(struct dm_table *t); +/* + * To check the return value from dm_table_find_target(). + */ +#define dm_target_is_valid(t) ((t)->table) + /*----------------------------------------------------------------- * A registry of target types. *---------------------------------------------------------------*/ @@ -182,4 +187,6 @@ union map_info *dm_get_mapinfo(struct bio *bio); int dm_open_count(struct mapped_device *md); int dm_lock_for_deletion(struct mapped_device *md); +void dm_kobject_uevent(struct mapped_device *md); + #endif diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 56a11f6c127..3dac1cfb818 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 808cd954945..cef9ebd5a04 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 b35731cceac..eb631ebed68 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 c111105fc2d..f8e591708d1 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 85478d6a9c1..4a69c416e04 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 fc6607acb6e..5cdcc938620 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 80a67d789b7..e8c8157b02f 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); @@ -2624,6 +2626,13 @@ static void handle_stripe5(struct stripe_head *sh) s.expanded = test_bit(STRIPE_EXPAND_READY, &sh->state); /* Now to look around and see what can be done */ + /* clean-up completed biofill operations */ + if (test_bit(STRIPE_OP_BIOFILL, &sh->ops.complete)) { + clear_bit(STRIPE_OP_BIOFILL, &sh->ops.pending); + clear_bit(STRIPE_OP_BIOFILL, &sh->ops.ack); + clear_bit(STRIPE_OP_BIOFILL, &sh->ops.complete); + } + rcu_read_lock(); for (i=disks; i--; ) { mdk_rdev_t *rdev; @@ -2856,7 +2865,8 @@ static void handle_stripe5(struct stripe_head *sh) md_done_sync(conf->mddev, STRIPE_SECTORS, 1); } - if (s.expanding && s.locked == 0) + if (s.expanding && s.locked == 0 && + !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending)) handle_stripe_expansion(conf, sh, NULL); if (sh->ops.count) @@ -2897,13 +2907,6 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) s.expanded = test_bit(STRIPE_EXPAND_READY, &sh->state); /* Now to look around and see what can be done */ - /* clean-up completed biofill operations */ - if (test_bit(STRIPE_OP_BIOFILL, &sh->ops.complete)) { - clear_bit(STRIPE_OP_BIOFILL, &sh->ops.pending); - clear_bit(STRIPE_OP_BIOFILL, &sh->ops.ack); - clear_bit(STRIPE_OP_BIOFILL, &sh->ops.complete); - } - rcu_read_lock(); for (i=disks; i--; ) { mdk_rdev_t *rdev; @@ -3065,7 +3068,8 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) md_done_sync(conf->mddev, STRIPE_SECTORS, 1); } - if (s.expanding && s.locked == 0) + if (s.expanding && s.locked == 0 && + !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending)) handle_stripe_expansion(conf, sh, &r6s); spin_unlock(&sh->lock); @@ -3186,8 +3190,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/raid6algos.c b/drivers/md/raid6algos.c index 92657615657..77a6e4bf503 100644 --- a/drivers/md/raid6algos.c +++ b/drivers/md/raid6algos.c @@ -52,7 +52,7 @@ const struct raid6_calls * const raid6_algos[] = { &raid6_intx16, &raid6_intx32, #endif -#if defined(__i386__) +#if defined(__i386__) && !defined(__arch_um__) &raid6_mmxx1, &raid6_mmxx2, &raid6_sse1x1, @@ -60,7 +60,7 @@ const struct raid6_calls * const raid6_algos[] = { &raid6_sse2x1, &raid6_sse2x2, #endif -#if defined(__x86_64__) +#if defined(__x86_64__) && !defined(__arch_um__) &raid6_sse2x1, &raid6_sse2x2, &raid6_sse2x4, diff --git a/drivers/md/raid6mmx.c b/drivers/md/raid6mmx.c index 6181a5a3365..d4e4a1bd70a 100644 --- a/drivers/md/raid6mmx.c +++ b/drivers/md/raid6mmx.c @@ -16,7 +16,7 @@ * MMX implementation of RAID-6 syndrome functions */ -#if defined(__i386__) +#if defined(__i386__) && !defined(__arch_um__) #include "raid6.h" #include "raid6x86.h" diff --git a/drivers/md/raid6sse1.c b/drivers/md/raid6sse1.c index f0a1ba8f40b..0666237276f 100644 --- a/drivers/md/raid6sse1.c +++ b/drivers/md/raid6sse1.c @@ -21,7 +21,7 @@ * worthwhile as a separate implementation. */ -#if defined(__i386__) +#if defined(__i386__) && !defined(__arch_um__) #include "raid6.h" #include "raid6x86.h" diff --git a/drivers/md/raid6sse2.c b/drivers/md/raid6sse2.c index 0f019762a7c..b034ad86803 100644 --- a/drivers/md/raid6sse2.c +++ b/drivers/md/raid6sse2.c @@ -17,7 +17,7 @@ * */ -#if defined(__i386__) || defined(__x86_64__) +#if (defined(__i386__) || defined(__x86_64__)) && !defined(__arch_um__) #include "raid6.h" #include "raid6x86.h" @@ -161,7 +161,7 @@ const struct raid6_calls raid6_sse2x2 = { #endif -#ifdef __x86_64__ +#if defined(__x86_64__) && !defined(__arch_um__) /* * Unrolled-by-4 SSE2 implementation diff --git a/drivers/md/raid6x86.h b/drivers/md/raid6x86.h index 9111950414f..99fea7a70ca 100644 --- a/drivers/md/raid6x86.h +++ b/drivers/md/raid6x86.h @@ -19,7 +19,7 @@ #ifndef LINUX_RAID_RAID6X86_H #define LINUX_RAID_RAID6X86_H -#if defined(__i386__) || defined(__x86_64__) +#if (defined(__i386__) || defined(__x86_64__)) && !defined(__arch_um__) #ifdef __KERNEL__ /* Real code */ diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index dd9bd4310c8..1604f049040 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -151,6 +151,7 @@ config VIDEO_IR_I2C config VIDEO_IR tristate + depends on INPUT select VIDEO_IR_I2C if I2C config VIDEO_TVEEPROM diff --git a/drivers/media/Makefile b/drivers/media/Makefile index 8fa19939c2b..8cf91353b56 100644 --- a/drivers/media/Makefile +++ b/drivers/media/Makefile @@ -3,6 +3,6 @@ # obj-y := common/ -obj-$(CONFIG_VIDEO_DEV) += video/ +obj-y += video/ obj-$(CONFIG_VIDEO_DEV) += radio/ obj-$(CONFIG_DVB_CORE) += dvb/ diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c index cb034ead95a..7d04a6fd1ac 100644 --- a/drivers/media/common/saa7146_core.c +++ b/drivers/media/common/saa7146_core.c @@ -59,43 +59,89 @@ void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data) } /* This DEBI code is based on the saa7146 Stradis driver by Nathan Laredo */ -int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop) +static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev, + unsigned long us1, unsigned long us2) { - unsigned long start; + unsigned long timeout; int err; /* wait for registers to be programmed */ - start = jiffies; + timeout = jiffies + usecs_to_jiffies(us1); while (1) { - err = time_after(jiffies, start + HZ/20); + err = time_after(jiffies, timeout); if (saa7146_read(dev, MC2) & 2) break; if (err) { - DEB_S(("timed out while waiting for registers getting programmed\n")); + printk(KERN_ERR "%s: %s timed out while waiting for " + "registers getting programmed\n", + dev->name, __FUNCTION__); return -ETIMEDOUT; } - if (nobusyloop) - msleep(1); + msleep(1); } /* wait for transfer to complete */ - start = jiffies; + timeout = jiffies + usecs_to_jiffies(us2); while (1) { - err = time_after(jiffies, start + HZ/4); + err = time_after(jiffies, timeout); if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S)) break; saa7146_read(dev, MC2); if (err) { - DEB_S(("timed out while waiting for transfer completion\n")); + DEB_S(("%s: %s timed out while waiting for transfer " + "completion\n", dev->name, __FUNCTION__)); return -ETIMEDOUT; } - if (nobusyloop) - msleep(1); + msleep(1); } return 0; } +static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev, + unsigned long us1, unsigned long us2) +{ + unsigned long loops; + + /* wait for registers to be programmed */ + loops = us1; + while (1) { + if (saa7146_read(dev, MC2) & 2) + break; + if (!loops--) { + printk(KERN_ERR "%s: %s timed out while waiting for " + "registers getting programmed\n", + dev->name, __FUNCTION__); + return -ETIMEDOUT; + } + udelay(1); + } + + /* wait for transfer to complete */ + loops = us2 / 5; + while (1) { + if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S)) + break; + saa7146_read(dev, MC2); + if (!loops--) { + DEB_S(("%s: %s timed out while waiting for transfer " + "completion\n", dev->name, __FUNCTION__)); + return -ETIMEDOUT; + } + udelay(5); + } + + return 0; +} + +int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop) +{ + if (nobusyloop) + return saa7146_wait_for_debi_done_sleep(dev, 50000, 250000); + else + return saa7146_wait_for_debi_done_busyloop(dev, 50000, 250000); +} + /**************************************************************************** * general helper functions ****************************************************************************/ diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index f245a3b2ef4..ae36d101006 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c @@ -1205,13 +1205,10 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int DEB_D(("VIDIOCGMBUF \n")); q = &fh->video_q; - mutex_lock(&q->lock); err = videobuf_mmap_setup(q,gbuffers,gbufsize, V4L2_MEMORY_MMAP); - if (err < 0) { - mutex_unlock(&q->lock); + if (err < 0) return err; - } gbuffers = err; memset(mbuf,0,sizeof(*mbuf)); @@ -1219,7 +1216,6 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int mbuf->size = gbuffers * gbufsize; for (i = 0; i < gbuffers; i++) mbuf->offsets[i] = i * gbufsize; - mutex_unlock(&q->lock); return 0; } #endif @@ -1440,10 +1436,7 @@ static void video_close(struct saa7146_dev *dev, struct file *file) err = saa7146_stop_preview(fh); } - // release all capture buffers - mutex_lock(&q->lock); - videobuf_read_stop(q); - mutex_unlock(&q->lock); + videobuf_stop(q); /* hmm, why is this function declared void? */ /* return err */ diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile index 73ac0a93fde..60a910052c1 100644 --- a/drivers/media/dvb/dvb-usb/Makefile +++ b/drivers/media/dvb/dvb-usb/Makefile @@ -62,3 +62,6 @@ dvb-usb-af9005-remote-objs = af9005-remote.o obj-$(CONFIG_DVB_USB_AF9005_REMOTE) += dvb-usb-af9005-remote.o EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ +# due to tuner-xc3028 +EXTRA_CFLAGS += -Idrivers/media/video + diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c index 9a184da01c4..8ee6cd4da9e 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-common.c +++ b/drivers/media/dvb/dvb-usb/dibusb-common.c @@ -223,6 +223,9 @@ static struct dibx000_agc_config dib3000p_panasonic_agc_config = { .agc2_slope2 = 0x1e, }; +#if defined(CONFIG_DVB_DIB3000MC) || \ + (defined(CONFIG_DVB_DIB3000MC_MODULE) && defined(MODULE)) + static struct dib3000mc_config mod3000p_dib3000p_config = { &dib3000p_panasonic_agc_config, @@ -305,6 +308,7 @@ int dibusb_dib3000mc_tuner_attach(struct dvb_usb_adapter *adap) return 0; } EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach); +#endif /* * common remote control stuff diff --git a/drivers/media/dvb/frontends/mt2131.c b/drivers/media/dvb/frontends/mt2131.c index 4b93931de4e..13cf1666817 100644 --- a/drivers/media/dvb/frontends/mt2131.c +++ b/drivers/media/dvb/frontends/mt2131.c @@ -116,7 +116,7 @@ static int mt2131_set_params(struct dvb_frontend *fe, f_lo1 = (f_lo1 / 250) * 250; f_lo2 = f_lo1 - freq - MT2131_IF2; - priv->frequency = (f_lo1 - f_lo2 - MT2131_IF2) * 1000, + priv->frequency = (f_lo1 - f_lo2 - MT2131_IF2) * 1000; /* Frequency LO1 = 16MHz * (DIV1 + NUM1/8192 ) */ num1 = f_lo1 * 64 / (MT2131_FREF / 128); diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c index 30e8a705fad..562d9208857 100644 --- a/drivers/media/dvb/frontends/s5h1409.c +++ b/drivers/media/dvb/frontends/s5h1409.c @@ -42,6 +42,9 @@ struct s5h1409_state { fe_modulation_t current_modulation; u32 current_frequency; + + u32 is_qam_locked; + u32 qam_state; }; static int debug = 0; @@ -94,6 +97,7 @@ static struct init_tab { { 0xac, 0x1003, }, { 0xad, 0x103f, }, { 0xe2, 0x0100, }, + { 0xe3, 0x0000, }, { 0x28, 0x1010, }, { 0xb1, 0x000e, }, }; @@ -103,7 +107,7 @@ static struct vsb_snr_tab { u16 val; u16 data; } vsb_snr_tab[] = { - { 1023, 770, }, + { 924, 300, }, { 923, 300, }, { 918, 295, }, { 915, 290, }, @@ -150,6 +154,7 @@ static struct qam64_snr_tab { u16 val; u16 data; } qam64_snr_tab[] = { + { 1, 0, }, { 12, 300, }, { 15, 290, }, { 18, 280, }, @@ -213,6 +218,7 @@ static struct qam64_snr_tab { { 95, 202, }, { 96, 201, }, { 104, 200, }, + { 255, 0, }, }; /* QAM256 SNR lookup table */ @@ -220,6 +226,7 @@ static struct qam256_snr_tab { u16 val; u16 data; } qam256_snr_tab[] = { + { 1, 0, }, { 12, 400, }, { 13, 390, }, { 15, 380, }, @@ -288,6 +295,7 @@ static struct qam256_snr_tab { { 105, 262, }, { 106, 261, }, { 110, 260, }, + { 255, 0, }, }; /* 8 bit registers, 16 bit values */ @@ -335,6 +343,8 @@ static int s5h1409_softreset(struct dvb_frontend* fe) s5h1409_writereg(state, 0xf5, 0); s5h1409_writereg(state, 0xf5, 1); + state->is_qam_locked = 0; + state->qam_state = 0; return 0; } @@ -349,6 +359,11 @@ static int s5h1409_set_if_freq(struct dvb_frontend* fe, int KHz) s5h1409_writereg(state, 0x87, 0x01be); s5h1409_writereg(state, 0x88, 0x0436); s5h1409_writereg(state, 0x89, 0x054d); + } else + if (KHz == 4000) { + s5h1409_writereg(state, 0x87, 0x014b); + s5h1409_writereg(state, 0x88, 0x0cb5); + s5h1409_writereg(state, 0x89, 0x03e2); } else { printk("%s() Invalid arg = %d KHz\n", __FUNCTION__, KHz); ret = -1; @@ -361,7 +376,7 @@ static int s5h1409_set_spectralinversion(struct dvb_frontend* fe, int inverted) { struct s5h1409_state* state = fe->demodulator_priv; - dprintk("%s()\n", __FUNCTION__); + dprintk("%s(%d)\n", __FUNCTION__, inverted); if(inverted == 1) return s5h1409_writereg(state, 0x1b, 0x1101); /* Inverted */ @@ -382,14 +397,10 @@ static int s5h1409_enable_modulation(struct dvb_frontend* fe, s5h1409_writereg(state, 0xf4, 0); break; case QAM_64: - dprintk("%s() QAM_64\n", __FUNCTION__); - s5h1409_writereg(state, 0xf4, 1); - s5h1409_writereg(state, 0x85, 0x100); - break; case QAM_256: - dprintk("%s() QAM_256\n", __FUNCTION__); + dprintk("%s() QAM_AUTO (64/256)\n", __FUNCTION__); s5h1409_writereg(state, 0xf4, 1); - s5h1409_writereg(state, 0x85, 0x101); + s5h1409_writereg(state, 0x85, 0x110); break; default: dprintk("%s() Invalid modulation\n", __FUNCTION__); @@ -423,7 +434,7 @@ static int s5h1409_set_gpio(struct dvb_frontend* fe, int enable) if (enable) return s5h1409_writereg(state, 0xe3, 0x1100); else - return s5h1409_writereg(state, 0xe3, 0); + return s5h1409_writereg(state, 0xe3, 0x1000); } static int s5h1409_sleep(struct dvb_frontend* fe, int enable) @@ -444,6 +455,66 @@ static int s5h1409_register_reset(struct dvb_frontend* fe) return s5h1409_writereg(state, 0xfa, 0); } +static void s5h1409_set_qam_amhum_mode(struct dvb_frontend *fe) +{ + struct s5h1409_state *state = fe->demodulator_priv; + u16 reg; + + if (state->is_qam_locked) + return; + + /* QAM EQ lock check */ + reg = s5h1409_readreg(state, 0xf0); + + if ((reg >> 13) & 0x1) { + + state->is_qam_locked = 1; + reg &= 0xff; + + s5h1409_writereg(state, 0x96, 0x00c); + if ((reg < 0x38) || (reg > 0x68) ) { + s5h1409_writereg(state, 0x93, 0x3332); + s5h1409_writereg(state, 0x9e, 0x2c37); + } else { + s5h1409_writereg(state, 0x93, 0x3130); + s5h1409_writereg(state, 0x9e, 0x2836); + } + + } else { + s5h1409_writereg(state, 0x96, 0x0008); + s5h1409_writereg(state, 0x93, 0x3332); + s5h1409_writereg(state, 0x9e, 0x2c37); + } +} + +static void s5h1409_set_qam_interleave_mode(struct dvb_frontend *fe) +{ + struct s5h1409_state *state = fe->demodulator_priv; + u16 reg, reg1, reg2; + + reg = s5h1409_readreg(state, 0xf1); + + /* Master lock */ + if ((reg >> 15) & 0x1) { + if (state->qam_state != 2) { + state->qam_state = 2; + reg1 = s5h1409_readreg(state, 0xb2); + reg2 = s5h1409_readreg(state, 0xad); + + s5h1409_writereg(state, 0x96, 0x20); + s5h1409_writereg(state, 0xad, + ( ((reg1 & 0xf000) >> 4) | (reg2 & 0xf0ff)) ); + s5h1409_writereg(state, 0xab, 0x1100); + } + } else { + if (state->qam_state != 1) { + state->qam_state = 1; + s5h1409_writereg(state, 0x96, 0x08); + s5h1409_writereg(state, 0xab, 0x1101); + } + } +} + /* Talk to the demod, set the FEC, GUARD, QAM settings etc */ static int s5h1409_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_parameters *p) @@ -458,12 +529,21 @@ static int s5h1409_set_frontend (struct dvb_frontend* fe, s5h1409_enable_modulation(fe, p->u.vsb.modulation); + /* Allow the demod to settle */ + msleep(100); + if (fe->ops.tuner_ops.set_params) { if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); fe->ops.tuner_ops.set_params(fe, p); if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); } + /* Optimize the demod for QAM */ + if (p->u.vsb.modulation != VSB_8) { + s5h1409_set_qam_amhum_mode(fe); + s5h1409_set_qam_interleave_mode(fe); + } + return 0; } @@ -495,8 +575,8 @@ static int s5h1409_init (struct dvb_frontend* fe) s5h1409_set_gpio(fe, state->config->gpio); s5h1409_softreset(fe); - /* Note: Leaving the I2C gate open here. */ - s5h1409_i2c_gate_ctrl(fe, 1); + /* Note: Leaving the I2C gate closed. */ + s5h1409_i2c_gate_ctrl(fe, 0); return 0; } @@ -594,14 +674,15 @@ static int s5h1409_read_snr(struct dvb_frontend* fe, u16* snr) u16 reg; dprintk("%s()\n", __FUNCTION__); - reg = s5h1409_readreg(state, 0xf1) & 0x1ff; - switch(state->current_modulation) { case QAM_64: + reg = s5h1409_readreg(state, 0xf0) & 0xff; return s5h1409_qam64_lookup_snr(fe, snr, reg); case QAM_256: + reg = s5h1409_readreg(state, 0xf0) & 0xff; return s5h1409_qam256_lookup_snr(fe, snr, reg); case VSB_8: + reg = s5h1409_readreg(state, 0xf1) & 0x3ff; return s5h1409_vsb_lookup_snr(fe, snr, reg); default: break; diff --git a/drivers/media/dvb/frontends/stv0297.c b/drivers/media/dvb/frontends/stv0297.c index 17e5cb561cd..7c23775f77d 100644 --- a/drivers/media/dvb/frontends/stv0297.c +++ b/drivers/media/dvb/frontends/stv0297.c @@ -358,11 +358,23 @@ static int stv0297_read_ber(struct dvb_frontend *fe, u32 * ber) static int stv0297_read_signal_strength(struct dvb_frontend *fe, u16 * strength) { struct stv0297_state *state = fe->demodulator_priv; - u8 STRENGTH[2]; - - stv0297_readregs(state, 0x41, STRENGTH, 2); - *strength = (STRENGTH[1] & 0x03) << 8 | STRENGTH[0]; - + u8 STRENGTH[3]; + u16 tmp; + + stv0297_readregs(state, 0x41, STRENGTH, 3); + tmp = (STRENGTH[1] & 0x03) << 8 | STRENGTH[0]; + if (STRENGTH[2] & 0x20) { + if (tmp < 0x200) + tmp = 0; + else + tmp = tmp - 0x200; + } else { + if (tmp > 0x1ff) + tmp = 0; + else + tmp = 0x1ff - tmp; + } + *strength = (tmp << 7) | (tmp >> 2); return 0; } diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c index 4cd9e82c466..45137d2ebfb 100644 --- a/drivers/media/dvb/frontends/tda10021.c +++ b/drivers/media/dvb/frontends/tda10021.c @@ -301,6 +301,8 @@ static int tda10021_read_ber(struct dvb_frontend* fe, u32* ber) u32 _ber = tda10021_readreg(state, 0x14) | (tda10021_readreg(state, 0x15) << 8) | ((tda10021_readreg(state, 0x16) & 0x0f) << 16); + _tda10021_writereg(state, 0x10, (tda10021_readreg(state, 0x10) & ~0xc0) + | (tda10021_inittab[0x10] & 0xc0)); *ber = 10 * _ber; return 0; @@ -310,7 +312,11 @@ static int tda10021_read_signal_strength(struct dvb_frontend* fe, u16* strength) { struct tda10021_state* state = fe->demodulator_priv; + u8 config = tda10021_readreg(state, 0x02); u8 gain = tda10021_readreg(state, 0x17); + if (config & 0x02) + /* the agc value is inverted */ + gain = ~gain; *strength = (gain << 8) | gain; return 0; diff --git a/drivers/media/dvb/frontends/tda10086.c b/drivers/media/dvb/frontends/tda10086.c index 9a8ddc537f8..9d26ace6515 100644 --- a/drivers/media/dvb/frontends/tda10086.c +++ b/drivers/media/dvb/frontends/tda10086.c @@ -158,7 +158,7 @@ static int tda10086_init(struct dvb_frontend* fe) tda10086_write_byte(state, 0x3d, 0x80); // setup SEC - tda10086_write_byte(state, 0x36, 0x00); // all SEC off + tda10086_write_byte(state, 0x36, 0x80); // all SEC off, no 22k tone tda10086_write_byte(state, 0x34, (((1<<19) * (22000/1000)) / (SACLK/1000))); // } tone frequency tda10086_write_byte(state, 0x35, (((1<<19) * (22000/1000)) / (SACLK/1000)) >> 8); // } @@ -183,13 +183,13 @@ static int tda10086_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone) dprintk ("%s\n", __FUNCTION__); - switch(tone) { + switch (tone) { case SEC_TONE_OFF: - tda10086_write_byte(state, 0x36, 0x00); + tda10086_write_byte(state, 0x36, 0x80); break; case SEC_TONE_ON: - tda10086_write_byte(state, 0x36, 0x01); + tda10086_write_byte(state, 0x36, 0x81); break; } @@ -212,7 +212,7 @@ static int tda10086_send_master_cmd (struct dvb_frontend* fe, for(i=0; i< cmd->msg_len; i++) { tda10086_write_byte(state, 0x48+i, cmd->msg[i]); } - tda10086_write_byte(state, 0x36, 0x08 | ((cmd->msg_len - 1) << 4)); + tda10086_write_byte(state, 0x36, 0x88 | ((cmd->msg_len - 1) << 4)); tda10086_diseqc_wait(state); @@ -230,11 +230,11 @@ static int tda10086_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minic switch(minicmd) { case SEC_MINI_A: - tda10086_write_byte(state, 0x36, 0x04); + tda10086_write_byte(state, 0x36, 0x84); break; case SEC_MINI_B: - tda10086_write_byte(state, 0x36, 0x06); + tda10086_write_byte(state, 0x36, 0x86); break; } diff --git a/drivers/media/dvb/frontends/ves1820.c b/drivers/media/dvb/frontends/ves1820.c index 066b73b7569..60433b5011f 100644 --- a/drivers/media/dvb/frontends/ves1820.c +++ b/drivers/media/dvb/frontends/ves1820.c @@ -47,7 +47,7 @@ struct ves1820_state { static int verbose; static u8 ves1820_inittab[] = { - 0x69, 0x6A, 0x93, 0x12, 0x12, 0x46, 0x26, 0x1A, + 0x69, 0x6A, 0x93, 0x1A, 0x12, 0x46, 0x26, 0x1A, 0x43, 0x6A, 0xAA, 0xAA, 0x1E, 0x85, 0x43, 0x20, 0xE0, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c index a97a7fd2c89..0106df4c55e 100644 --- a/drivers/media/dvb/frontends/zl10353.c +++ b/drivers/media/dvb/frontends/zl10353.c @@ -122,7 +122,7 @@ static void zl10353_calc_nominal_rate(struct dvb_frontend *fe, enum fe_bandwidth bandwidth, u16 *nominal_rate) { - u32 adc_clock = 22528; /* 20.480 MHz on the board(!?) */ + u32 adc_clock = 45056; /* 45.056 MHz */ u8 bw; struct zl10353_state *state = fe->demodulator_priv; @@ -142,7 +142,7 @@ static void zl10353_calc_nominal_rate(struct dvb_frontend *fe, break; } - *nominal_rate = (64 * bw * (1<<16) / (7 * 8) * 4000 / adc_clock + 2) / 4; + *nominal_rate = (bw * (1 << 23) / 7 * 125 + adc_clock / 2) / adc_clock; dprintk("%s: bw %d, adc_clock %d => 0x%x\n", __FUNCTION__, bw, adc_clock, *nominal_rate); diff --git a/drivers/media/dvb/frontends/zl10353.h b/drivers/media/dvb/frontends/zl10353.h index cb274dc12b8..1c3d494a6da 100644 --- a/drivers/media/dvb/frontends/zl10353.h +++ b/drivers/media/dvb/frontends/zl10353.h @@ -30,7 +30,7 @@ struct zl10353_config u8 demod_address; /* frequencies in kHz */ - int adc_clock; // default: 22528 + int adc_clock; /* default: 45056 */ /* set if no pll is connected to the secondary i2c bus */ int no_tuner; diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index 6d53289b327..54b91f26ca6 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig @@ -84,7 +84,7 @@ config DVB_BUDGET config DVB_BUDGET_CI tristate "Budget cards with onboard CI connector" - depends on DVB_CORE && PCI && I2C && VIDEO_V4L1 + depends on DVB_CORE && PCI && I2C && VIDEO_V4L1 && INPUT select VIDEO_SAA7146 select DVB_STV0297 if !DVB_FE_CUSTOMISE select DVB_STV0299 if !DVB_FE_CUSTOMISE diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 8b8144f77a7..0d36c155695 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -2800,12 +2800,12 @@ static void av7110_irq(struct saa7146_dev* dev, u32 *isr) } -static struct saa7146_extension av7110_extension; +static struct saa7146_extension av7110_extension_driver; #define MAKE_AV7110_INFO(x_var,x_name) \ static struct saa7146_pci_extension_data x_var = { \ .ext_priv = x_name, \ - .ext = &av7110_extension } + .ext = &av7110_extension_driver } MAKE_AV7110_INFO(tts_1_X_fsc,"Technotrend/Hauppauge WinTV DVB-S rev1.X or Fujitsu Siemens DVB-C"); MAKE_AV7110_INFO(ttt_1_X, "Technotrend/Hauppauge WinTV DVB-T rev1.X"); @@ -2843,7 +2843,7 @@ static struct pci_device_id pci_tbl[] = { MODULE_DEVICE_TABLE(pci, pci_tbl); -static struct saa7146_extension av7110_extension = { +static struct saa7146_extension av7110_extension_driver = { .name = "dvb", .flags = SAA7146_USE_I2C_IRQ, @@ -2860,14 +2860,14 @@ static struct saa7146_extension av7110_extension = { static int __init av7110_init(void) { int retval; - retval = saa7146_register_extension(&av7110_extension); + retval = saa7146_register_extension(&av7110_extension_driver); return retval; } static void __exit av7110_exit(void) { - saa7146_unregister_extension(&av7110_extension); + saa7146_unregister_extension(&av7110_extension_driver); } module_init(av7110_init); diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 2e571eb9313..c9f14bfc854 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -363,7 +363,7 @@ endmenu # encoder / decoder chips config VIDEO_VIVI tristate "Virtual Video Driver" - depends on VIDEO_V4L2 && !SPARC32 && !SPARC64 && PCI + depends on VIDEO_V4L2 && !SPARC32 && !SPARC64 select VIDEOBUF_VMALLOC default n ---help--- diff --git a/drivers/media/video/bt866.c b/drivers/media/video/bt866.c index b767b098d14..96b415576f0 100644 --- a/drivers/media/video/bt866.c +++ b/drivers/media/video/bt866.c @@ -300,7 +300,6 @@ static struct i2c_client bt866_client_tmpl = .addr = 0, .adapter = NULL, .driver = &i2c_driver_bt866, - .usage_count = 0 }; static int bt866_found_proc(struct i2c_adapter *adapter, diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 3abd9fa54d2..585d1ef95af 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -5080,7 +5080,7 @@ static void PXC200_muxsel(struct bttv *btv, unsigned int input) /* ----------------------------------------------------------------------- */ /* motherboard chipset specific stuff */ -void __devinit bttv_check_chipset(void) +void __init bttv_check_chipset(void) { int pcipci_fail = 0; struct pci_dev *dev = NULL; diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 9feeb636ff9..581a3c95573 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -2881,10 +2881,6 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, if (NULL == fmt) return -EINVAL; mutex_lock(&fh->cap.lock); - if (fmt->depth != pic->depth) { - retval = -EINVAL; - goto fh_unlock_and_return; - } if (fmt->flags & FORMAT_FLAGS_RAW) { /* VIDIOCMCAPTURE uses gbufsize, not RAW_BPL * RAW_LINES * 2. F1 is stored at offset 0, F2 @@ -3067,11 +3063,10 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, struct video_mbuf *mbuf = arg; unsigned int i; - mutex_lock(&fh->cap.lock); retval = videobuf_mmap_setup(&fh->cap,gbuffers,gbufsize, V4L2_MEMORY_MMAP); if (retval < 0) - goto fh_unlock_and_return; + return retval; gbuffers = retval; memset(mbuf,0,sizeof(*mbuf)); @@ -3079,7 +3074,6 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, mbuf->size = gbuffers * gbufsize; for (i = 0; i < gbuffers; i++) mbuf->offsets[i] = i * gbufsize; - mutex_unlock(&fh->cap.lock); return 0; } case VIDIOCMCAPTURE: @@ -3117,6 +3111,8 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, vm->width,vm->height,field); if (0 != retval) goto fh_unlock_and_return; + btv->init.width = vm->width; + btv->init.height = vm->height; spin_lock_irqsave(&btv->s_lock,flags); buffer_queue(&fh->cap,&buf->vb); spin_unlock_irqrestore(&btv->s_lock,flags); @@ -3829,10 +3825,7 @@ static int bttv_release(struct inode *inode, struct file *file) /* stop vbi capture */ if (check_btres(fh, RESOURCE_VBI)) { - if (fh->vbi.streaming) - videobuf_streamoff(&fh->vbi); - if (fh->vbi.reading) - videobuf_read_stop(&fh->vbi); + videobuf_stop(&fh->vbi); free_btres(btv,fh,RESOURCE_VBI); } @@ -4990,7 +4983,7 @@ static struct pci_driver bttv_pci_driver = { #endif }; -static int bttv_init_module(void) +static int __init bttv_init_module(void) { int ret; @@ -5023,7 +5016,7 @@ static int bttv_init_module(void) return pci_register_driver(&bttv_pci_driver); } -static void bttv_cleanup_module(void) +static void __exit bttv_cleanup_module(void) { pci_unregister_driver(&bttv_pci_driver); bus_unregister(&bttv_sub_bus_type); diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h index 0b92c35a843..d4ac4c4b49b 100644 --- a/drivers/media/video/bt8xx/bttvp.h +++ b/drivers/media/video/bt8xx/bttvp.h @@ -36,7 +36,7 @@ #include <linux/pci.h> #include <linux/input.h> #include <linux/mutex.h> -#include <asm/scatterlist.h> +#include <linux/scatterlist.h> #include <asm/io.h> #include <media/v4l2-common.h> diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index b63cab33692..7ae499c9c54 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c @@ -3,6 +3,9 @@ * multifunction chip. Currently works with the Omnivision OV7670 * sensor. * + * The data sheet for this device can be found at: + * http://www.marvell.com/products/pcconn/88ALP01.jsp + * * Copyright 2006 One Laptop Per Child Association, Inc. * Copyright 2006-7 Jonathan Corbet <corbet@lwn.net> * @@ -2232,13 +2235,16 @@ static int cafe_pci_suspend(struct pci_dev *pdev, pm_message_t state) { struct cafe_camera *cam = cafe_find_by_pdev(pdev); int ret; + enum cafe_state cstate; ret = pci_save_state(pdev); if (ret) return ret; + cstate = cam->state; /* HACK - stop_dma sets to idle */ cafe_ctlr_stop_dma(cam); cafe_ctlr_power_down(cam); pci_disable_device(pdev); + cam->state = cstate; return 0; } diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig index 72004a07b2d..081ee6e1536 100644 --- a/drivers/media/video/cx23885/Kconfig +++ b/drivers/media/video/cx23885/Kconfig @@ -1,6 +1,6 @@ config VIDEO_CX23885 tristate "Conexant cx23885 (2388x successor) support" - depends on DVB_CORE && VIDEO_DEV && PCI && I2C + depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT select I2C_ALGOBIT select FW_LOADER select VIDEO_BTCX @@ -10,6 +10,7 @@ config VIDEO_CX23885 select VIDEOBUF_DVB select DVB_TUNER_MT2131 if !DVB_FE_CUSTOMISE select DVB_S5H1409 if !DVB_FE_CUSTOMISE + select DVB_LGDT330X if !DVB_FE_CUSTOMISE select DVB_PLL if !DVB_FE_CUSTOMISE ---help--- This is a video4linux driver for Conexant 23885 based diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index eeb5224ca10..ceb31d4a251 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -1,6 +1,6 @@ config VIDEO_CX88 tristate "Conexant 2388x (bt878 successor) support" - depends on VIDEO_DEV && PCI && I2C + depends on VIDEO_DEV && PCI && I2C && INPUT select I2C_ALGOBIT select FW_LOADER select VIDEO_BTCX diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index f33f0b47142..f802b565356 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -1085,10 +1085,7 @@ static int mpeg_release(struct inode *inode, struct file *file) cx8802_cancel_buffers(fh->dev); /* stop mpeg capture */ - if (fh->mpegq.streaming) - videobuf_streamoff(&fh->mpegq); - if (fh->mpegq.reading) - videobuf_read_stop(&fh->mpegq); + videobuf_stop(&fh->mpegq); videobuf_mmap_free(&fh->mpegq); file->private_data = NULL; diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 5ee05f8f3fa..c84dafbdb99 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -851,10 +851,7 @@ static int video_release(struct inode *inode, struct file *file) /* stop vbi capture */ if (res_check(fh, RESOURCE_VBI)) { - if (fh->vbiq.streaming) - videobuf_streamoff(&fh->vbiq); - if (fh->vbiq.reading) - videobuf_read_stop(&fh->vbiq); + videobuf_stop(&fh->vbiq); res_free(dev,fh,RESOURCE_VBI); } diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig index 5b6a4037160..c1127802ad9 100644 --- a/drivers/media/video/em28xx/Kconfig +++ b/drivers/media/video/em28xx/Kconfig @@ -1,6 +1,6 @@ config VIDEO_EM28XX tristate "Empia EM2800/2820/2840 USB video capture support" - depends on VIDEO_V4L1 && I2C + depends on VIDEO_V4L1 && I2C && INPUT select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_IR diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 997d067e32e..e3a4aa7a9df 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -416,8 +416,10 @@ static int attach_inform(struct i2c_client *client) struct em28xx *dev = client->adapter->algo_data; switch (client->addr << 1) { - case 0x43: - case 0x4b: + case 0x86: + case 0x84: + case 0x96: + case 0x94: { struct tuner_setup tun_setup; diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index a4c2a907124..0906bc5766c 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -32,6 +32,7 @@ #include <linux/usb.h> #include <linux/i2c.h> #include <linux/version.h> +#include <linux/mm.h> #include <linux/video_decoder.h> #include <linux/mutex.h> @@ -143,7 +144,8 @@ static int em28xx_config(struct em28xx *dev) { /* Sets I2C speed to 100 KHz */ - em28xx_write_regs_req(dev, 0x00, 0x06, "\x40", 1); + if (!dev->is_em2800) + em28xx_write_regs_req(dev, 0x00, 0x06, "\x40", 1); /* enable vbi capturing */ @@ -569,7 +571,9 @@ static void em28xx_vm_close(struct vm_area_struct *vma) { /* NOTE: buffers are not freed here */ struct em28xx_frame_t *f = vma->vm_private_data; - f->vma_use_count--; + + if (f->vma_use_count) + f->vma_use_count--; } static struct vm_operations_struct em28xx_vm_ops = { diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index 285fca676a6..36e54f78aa2 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c @@ -541,7 +541,7 @@ static const struct i2c_algo_bit_data ivtv_i2c_algo_template = { .setscl = ivtv_setscl_old, .getsda = ivtv_getsda_old, .getscl = ivtv_getscl_old, - .udelay = 5, + .udelay = 10, .timeout = 200, }; @@ -706,7 +706,7 @@ void ivtv_call_i2c_clients(struct ivtv *itv, unsigned int cmd, void *arg) } /* init + register i2c algo-bit adapter */ -int __devinit init_ivtv_i2c(struct ivtv *itv) +int init_ivtv_i2c(struct ivtv *itv) { IVTV_DEBUG_I2C("i2c init\n"); @@ -741,7 +741,7 @@ int __devinit init_ivtv_i2c(struct ivtv *itv) return i2c_bit_add_bus(&itv->i2c_adap); } -void __devexit exit_ivtv_i2c(struct ivtv *itv) +void exit_ivtv_i2c(struct ivtv *itv) { IVTV_DEBUG_I2C("i2c exit\n"); diff --git a/drivers/media/video/ivtv/ivtv-i2c.h b/drivers/media/video/ivtv/ivtv-i2c.h index 677c3292855..987042c09b6 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.h +++ b/drivers/media/video/ivtv/ivtv-i2c.h @@ -35,7 +35,7 @@ int ivtv_call_i2c_client(struct ivtv *itv, int addr, unsigned int cmd, void *arg void ivtv_call_i2c_clients(struct ivtv *itv, unsigned int cmd, void *arg); /* init + register i2c algo-bit adapter */ -int __devinit init_ivtv_i2c(struct ivtv *itv); -void __devexit exit_ivtv_i2c(struct ivtv *itv); +int init_ivtv_i2c(struct ivtv *itv); +void exit_ivtv_i2c(struct ivtv *itv); #endif diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index aa03e61ef31..74fb0e02197 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c @@ -76,7 +76,7 @@ static struct { int minor_offset; int dma, pio; enum v4l2_buf_type buf_type; - struct file_operations *fops; + const struct file_operations *fops; } ivtv_stream_info[] = { { /* IVTV_ENC_STREAM_TYPE_MPG */ "encoder MPG", diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c index ce4b2f9791e..36047d4e70f 100644 --- a/drivers/media/video/planb.c +++ b/drivers/media/video/planb.c @@ -91,7 +91,6 @@ static void planb_close(struct video_device *); static int planb_ioctl(struct video_device *, unsigned int, void *); static int planb_init_done(struct video_device *); static int planb_mmap(struct video_device *, const char *, unsigned long); -static void planb_irq(int, void *); static void release_planb(void); int init_planbs(struct video_init *); @@ -1315,7 +1314,7 @@ cmd_tab_data_end: return c1; } -static void planb_irq(int irq, void *dev_id) +static irqreturn_t planb_irq(int irq, void *dev_id) { unsigned int stat, astat; struct planb *pb = (struct planb *)dev_id; @@ -1358,13 +1357,14 @@ static void planb_irq(int irq, void *dev_id) pb->frame_stat[fr] = GBUFFER_DONE; pb->grabbing--; wake_up_interruptible(&pb->capq); - return; + return IRQ_HANDLED; } /* incorrect interrupts? */ pb->intr_mask = PLANB_CLR_IRQ; out_le32(&pb->planb_base->intr_stat, PLANB_CLR_IRQ); printk(KERN_ERR "PlanB: IRQ lockup, cleared intrrupts" " unconditionally\n"); + return IRQ_HANDLED; } /******************************* @@ -2090,7 +2090,7 @@ static int init_planb(struct planb *pb) /* clear interrupt mask */ pb->intr_mask = PLANB_CLR_IRQ; - result = request_irq(pb->irq, planb_irq, 0, "PlanB", (void *)pb); + result = request_irq(pb->irq, planb_irq, 0, "PlanB", pb); if (result < 0) { if (result==-EINVAL) printk(KERN_ERR "PlanB: Bad irq number (%d) " diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c index f569b00201d..46f156fb108 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c +++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c @@ -410,7 +410,7 @@ static int parse_mtoken(const char *ptr,unsigned int len, int msk; *valptr = 0; for (idx = 0, msk = 1; valid_bits; idx++, msk <<= 1) { - if (!msk & valid_bits) continue; + if (!(msk & valid_bits)) continue; valid_bits &= ~msk; if (!names[idx]) continue; slen = strlen(names[idx]); diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c index ca9e2789c8c..11b3b2e84b9 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-main.c +++ b/drivers/media/video/pvrusb2/pvrusb2-main.c @@ -136,14 +136,13 @@ static int __init pvr_init(void) static void __exit pvr_exit(void) { - pvr2_trace(PVR2_TRACE_INIT,"pvr_exit"); + usb_deregister(&pvr_driver); + #ifdef CONFIG_VIDEO_PVRUSB2_SYSFS pvr2_sysfs_class_destroy(class_ptr); #endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */ - - usb_deregister(&pvr_driver); } module_init(pvr_init); diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index 2ee3c3049e8..3c57a7d8200 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -905,13 +905,6 @@ struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *mp, } -static int pvr2_sysfs_hotplug(struct device *d, - struct kobj_uevent_env *env) -{ - /* Even though we don't do anything here, we still need this function - because sysfs will still try to call it. */ - return 0; -} struct pvr2_sysfs_class *pvr2_sysfs_class_create(void) { @@ -922,7 +915,6 @@ struct pvr2_sysfs_class *pvr2_sysfs_class_create(void) clp->class.name = "pvrusb2"; clp->class.class_release = pvr2_sysfs_class_release; clp->class.dev_release = pvr2_sysfs_release; - clp->class.dev_uevent = pvr2_sysfs_hotplug; if (class_register(&clp->class)) { pvr2_sysfs_trace( "Registration failed for pvr2_sysfs_class id=%p",clp); diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c index ad0232935df..996b49491f5 100644 --- a/drivers/media/video/saa5246a.c +++ b/drivers/media/video/saa5246a.c @@ -187,12 +187,14 @@ static int i2c_senddata(struct saa5246a_device *t, ...) { unsigned char buf[64]; int v; - int ct=0; + int ct = 0; va_list argp; - va_start(argp,t); + va_start(argp, t); - while((v=va_arg(argp,int))!=-1) - buf[ct++]=v; + while ((v = va_arg(argp, int)) != -1) + buf[ct++] = v; + + va_end(argp); return i2c_sendbuf(t, buf[0], ct-1, buf+1); } diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c index 94bb59a32b1..f55d6e85f20 100644 --- a/drivers/media/video/saa5249.c +++ b/drivers/media/video/saa5249.c @@ -282,12 +282,14 @@ static int i2c_senddata(struct saa5249_device *t, ...) { unsigned char buf[64]; int v; - int ct=0; + int ct = 0; va_list argp; va_start(argp,t); - while((v=va_arg(argp,int))!=-1) - buf[ct++]=v; + while ((v = va_arg(argp, int)) != -1) + buf[ct++] = v; + + va_end(argp); return i2c_sendbuf(t, buf[0], ct-1, buf+1); } diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig index d6d8d660196..3aa8cb2b860 100644 --- a/drivers/media/video/saa7134/Kconfig +++ b/drivers/media/video/saa7134/Kconfig @@ -1,6 +1,6 @@ config VIDEO_SAA7134 tristate "Philips SAA7134 support" - depends on VIDEO_DEV && PCI && I2C + depends on VIDEO_DEV && PCI && I2C && INPUT select VIDEOBUF_DMA_SG select VIDEO_IR select VIDEO_TUNER diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index c6f7279669c..4878f306778 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -222,7 +222,8 @@ static irqreturn_t saa7134_alsa_irq(int irq, void *dev_id) if (report & SAA7134_IRQ_REPORT_DONE_RA3) { handled = 1; - saa_writel(SAA7134_IRQ_REPORT,report); + saa_writel(SAA7134_IRQ_REPORT, + SAA7134_IRQ_REPORT_DONE_RA3); saa7134_irq_alsa_done(dev, status); } else { goto out; @@ -457,7 +458,7 @@ static struct snd_pcm_hardware snd_card_saa7134_capture = .buffer_bytes_max = (256*1024), .period_bytes_min = 64, .period_bytes_max = (256*1024), - .periods_min = 2, + .periods_min = 4, .periods_max = 1024, }; @@ -491,7 +492,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream, snd_assert(period_size >= 0x100 && period_size <= 0x10000, return -EINVAL); - snd_assert(periods >= 2, return -EINVAL); + snd_assert(periods >= 4, return -EINVAL); snd_assert(period_size * periods <= 1024 * 1024, return -EINVAL); dev = saa7134->dev; @@ -543,8 +544,10 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream, V4L functions, and force ALSA to use that as the DMA area */ substream->runtime->dma_area = dev->dmasound.dma.vmalloc; + substream->runtime->dma_bytes = dev->dmasound.bufsize; + substream->runtime->dma_addr = 0; - return 1; + return 0; } @@ -645,13 +648,31 @@ static int snd_card_saa7134_capture_open(struct snd_pcm_substream * substream) saa7134_tvaudio_setmute(dev); } - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) + err = snd_pcm_hw_constraint_integer(runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) + return err; + + err = snd_pcm_hw_constraint_step(runtime, 0, + SNDRV_PCM_HW_PARAM_PERIODS, 2); + if (err < 0) return err; return 0; } /* + * page callback (needed for mmap) + */ + +static struct page *snd_card_saa7134_page(struct snd_pcm_substream *substream, + unsigned long offset) +{ + void *pageptr = substream->runtime->dma_area + offset; + return vmalloc_to_page(pageptr); +} + +/* * ALSA capture callbacks definition */ @@ -664,6 +685,7 @@ static struct snd_pcm_ops snd_card_saa7134_capture_ops = { .prepare = snd_card_saa7134_capture_prepare, .trigger = snd_card_saa7134_capture_trigger, .pointer = snd_card_saa7134_capture_pointer, + .page = snd_card_saa7134_page, }; /* diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index a4c192fb4e4..98c1b084a71 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -334,7 +334,7 @@ struct saa7134_board saa7134_boards[] = { .tv = 1, },{ .name = name_comp1, - .vmux = 2, + .vmux = 0, .amux = LINE1, },{ .name = name_comp2, @@ -2996,11 +2996,11 @@ struct saa7134_board saa7134_boards[] = { },{ .name = name_comp1, .vmux = 0, - .amux = LINE2, + .amux = LINE1, },{ .name = name_svideo, .vmux = 8, - .amux = LINE2, + .amux = LINE1, }}, }, [SAA7134_BOARD_FLYDVBS_LR300] = { @@ -3221,6 +3221,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .tuner_config = 1, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ .name = name_tv, diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index a499eea379e..4f0a9157ecb 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -569,21 +569,22 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id) for (loop = 0; loop < 10; loop++) { report = saa_readl(SAA7134_IRQ_REPORT); status = saa_readl(SAA7134_IRQ_STATUS); - if (0 == report) { - if (irq_debug > 1) - printk(KERN_DEBUG "%s/irq: no (more) work\n", - dev->name); - goto out; - } - - /* If dmasound support is active and we get a sound report, exit - and let the saa7134-alsa/oss module deal with it */ + /* If dmasound support is active and we get a sound report, + * mask out the report and let the saa7134-alsa module deal + * with it */ if ((report & SAA7134_IRQ_REPORT_DONE_RA3) && (dev->dmasound.priv_data != NULL) ) { if (irq_debug > 1) - printk(KERN_DEBUG "%s/irq: ignoring interrupt for DMA sound\n", + printk(KERN_DEBUG "%s/irq: preserving DMA sound interrupt\n", + dev->name); + report &= ~SAA7134_IRQ_REPORT_DONE_RA3; + } + + if (0 == report) { + if (irq_debug > 1) + printk(KERN_DEBUG "%s/irq: no (more) work\n", dev->name); goto out; } @@ -1201,9 +1202,8 @@ static int saa7134_suspend(struct pci_dev *pci_dev , pm_message_t state) static int saa7134_resume(struct pci_dev *pci_dev) { - struct saa7134_dev *dev = pci_get_drvdata(pci_dev); - unsigned int flags; + unsigned long flags; pci_restore_state(pci_dev); pci_set_power_state(pci_dev, PCI_D0); diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 38d87332cc5..e1ab099ec4c 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -662,6 +662,7 @@ static struct tda1004x_config hauppauge_hvr_1110_config = { .if_freq = TDA10046_FREQ_045, .i2c_gate = 0x4b, .tuner_address = 0x61, + .tuner_config = 1, .request_firmware = philips_tda1004x_request_firmware }; diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index 75d0c5bf46d..9322f44865b 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -110,11 +110,8 @@ static int ts_release(struct inode *inode, struct file *file) { struct saa7134_dev *dev = file->private_data; - if (dev->empress_tsq.streaming) - videobuf_streamoff(&dev->empress_tsq); mutex_lock(&dev->empress_tsq.lock); - if (dev->empress_tsq.reading) - videobuf_read_stop(&dev->empress_tsq); + videobuf_stop(&dev->empress_tsq); videobuf_mmap_free(&dev->empress_tsq); dev->empress_users--; diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 3b9ffb4b648..6396d9b5c06 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -1445,10 +1445,7 @@ static int video_release(struct inode *inode, struct file *file) /* stop vbi capture */ if (res_check(fh, RESOURCE_VBI)) { - if (fh->vbi.streaming) - videobuf_streamoff(&fh->vbi); - if (fh->vbi.reading) - videobuf_read_stop(&fh->vbi); + videobuf_stop(&fh->vbi); res_free(dev,fh,RESOURCE_VBI); } diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 6a777604f07..9e99f3636d3 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -30,7 +30,7 @@ /* standard i2c insmod options */ static unsigned short normal_i2c[] = { -#ifdef CONFIG_TUNER_TEA5761 +#if defined(CONFIG_TUNER_TEA5761) || (defined(CONFIG_TUNER_TEA5761_MODULE) && defined(MODULE)) 0x10, #endif 0x42, 0x43, 0x4a, 0x4b, /* tda8290 */ @@ -292,7 +292,6 @@ static void set_type(struct i2c_client *c, unsigned int type, } t->mode_mask = T_RADIO; break; -#ifdef CONFIG_TUNER_TEA5761 case TUNER_TEA5761: if (tea5761_attach(&t->fe, t->i2c.adapter, t->i2c.addr) == NULL) { t->type = TUNER_ABSENT; @@ -301,7 +300,6 @@ static void set_type(struct i2c_client *c, unsigned int type, } t->mode_mask = T_RADIO; break; -#endif case TUNER_PHILIPS_FMD1216ME_MK3: buffer[0] = 0x0b; buffer[1] = 0xdc; @@ -594,7 +592,6 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) /* autodetection code based on the i2c addr */ if (!no_autodetect) { switch (addr) { -#ifdef CONFIG_TUNER_TEA5761 case 0x10: if (tea5761_autodetection(t->i2c.adapter, t->i2c.addr) != EINVAL) { t->type = TUNER_TEA5761; @@ -606,7 +603,6 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) goto register_client; } break; -#endif case 0x42: case 0x43: case 0x4a: diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index e2f1c972754..445eba4174d 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -290,6 +290,7 @@ static inline void tvp5150_selmux(struct i2c_client *c) int opmode=0; struct tvp5150 *decoder = i2c_get_clientdata(c); int input = 0; + unsigned char val; if ((decoder->route.output & TVP5150_BLACK_SCREEN) || !decoder->enable) input = 8; @@ -315,6 +316,16 @@ static inline void tvp5150_selmux(struct i2c_client *c) tvp5150_write(c, TVP5150_OP_MODE_CTL, opmode); tvp5150_write(c, TVP5150_VD_IN_SRC_SEL_1, input); + + /* Svideo should enable YCrCb output and disable GPCL output + * For Composite and TV, it should be the reverse + */ + val = tvp5150_read(c, TVP5150_MISC_CTL); + if (decoder->route.input == TVP5150_SVIDEO) + val = (val & ~0x40) | 0x10; + else + val = (val & ~0x10) | 0x40; + tvp5150_write(c, TVP5150_MISC_CTL, val); }; struct i2c_reg_value { @@ -799,10 +810,10 @@ static inline void tvp5150_reset(struct i2c_client *c) tvp5150_write_inittab(c, tvp5150_init_enable); /* Initialize image preferences */ - tvp5150_write(c, TVP5150_BRIGHT_CTL, decoder->bright >> 8); - tvp5150_write(c, TVP5150_CONTRAST_CTL, decoder->contrast >> 8); - tvp5150_write(c, TVP5150_SATURATION_CTL, decoder->contrast >> 8); - tvp5150_write(c, TVP5150_HUE_CTL, (decoder->hue - 32768) >> 8); + tvp5150_write(c, TVP5150_BRIGHT_CTL, decoder->bright); + tvp5150_write(c, TVP5150_CONTRAST_CTL, decoder->contrast); + tvp5150_write(c, TVP5150_SATURATION_CTL, decoder->contrast); + tvp5150_write(c, TVP5150_HUE_CTL, decoder->hue); tvp5150_set_std(c, decoder->norm); }; @@ -1077,10 +1088,10 @@ static int tvp5150_detect_client(struct i2c_adapter *adapter, core->norm = V4L2_STD_ALL; /* Default is autodetect */ core->route.input = TVP5150_COMPOSITE1; core->enable = 1; - core->bright = 32768; - core->contrast = 32768; - core->hue = 32768; - core->sat = 32768; + core->bright = 128; + core->contrast = 128; + core->hue = 0; + core->sat = 128; if (rv) { kfree(c); diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 89a44f16f0b..c8a5cb57963 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -141,6 +141,7 @@ void videobuf_queue_core_init(struct videobuf_queue* q, INIT_LIST_HEAD(&q->stream); } +/* Locking: Only usage in bttv unsafe find way to remove */ int videobuf_queue_is_busy(struct videobuf_queue *q) { int i; @@ -178,6 +179,7 @@ int videobuf_queue_is_busy(struct videobuf_queue *q) return 0; } +/* Locking: Caller holds q->lock */ void videobuf_queue_cancel(struct videobuf_queue *q) { unsigned long flags=0; @@ -208,6 +210,7 @@ void videobuf_queue_cancel(struct videobuf_queue *q) /* --------------------------------------------------------------------- */ +/* Locking: Caller holds q->lock */ enum v4l2_field videobuf_next_field(struct videobuf_queue *q) { enum v4l2_field field = q->field; @@ -226,6 +229,7 @@ enum v4l2_field videobuf_next_field(struct videobuf_queue *q) return field; } +/* Locking: Caller holds q->lock */ static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b, struct videobuf_buffer *vb, enum v4l2_buf_type type) { @@ -281,20 +285,108 @@ static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b, b->sequence = vb->field_count >> 1; } +/* Locking: Caller holds q->lock */ +static int __videobuf_mmap_free(struct videobuf_queue *q) +{ + int i; + int rc; + + if (!q) + return 0; + + MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); + + rc = CALL(q,mmap_free,q); + if (rc<0) + return rc; + + for (i = 0; i < VIDEO_MAX_FRAME; i++) { + if (NULL == q->bufs[i]) + continue; + q->ops->buf_release(q,q->bufs[i]); + kfree(q->bufs[i]); + q->bufs[i] = NULL; + } + + return rc; +} + +int videobuf_mmap_free(struct videobuf_queue *q) +{ + int ret; + mutex_lock(&q->lock); + ret = __videobuf_mmap_free(q); + mutex_unlock(&q->lock); + return ret; +} + +/* Locking: Caller holds q->lock */ +static int __videobuf_mmap_setup(struct videobuf_queue *q, + unsigned int bcount, unsigned int bsize, + enum v4l2_memory memory) +{ + unsigned int i; + int err; + + MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); + + err = __videobuf_mmap_free(q); + if (0 != err) + return err; + + /* Allocate and initialize buffers */ + for (i = 0; i < bcount; i++) { + q->bufs[i] = videobuf_alloc(q); + + if (q->bufs[i] == NULL) + break; + + q->bufs[i]->i = i; + q->bufs[i]->input = UNSET; + q->bufs[i]->memory = memory; + q->bufs[i]->bsize = bsize; + switch (memory) { + case V4L2_MEMORY_MMAP: + q->bufs[i]->boff = bsize * i; + break; + case V4L2_MEMORY_USERPTR: + case V4L2_MEMORY_OVERLAY: + /* nothing */ + break; + } + } + + if (!i) + return -ENOMEM; + + dprintk(1,"mmap setup: %d buffers, %d bytes each\n", + i, bsize); + + return i; +} + +int videobuf_mmap_setup(struct videobuf_queue *q, + unsigned int bcount, unsigned int bsize, + enum v4l2_memory memory) +{ + int ret; + mutex_lock(&q->lock); + ret = __videobuf_mmap_setup(q, bcount, bsize, memory); + mutex_unlock(&q->lock); + return ret; +} + int videobuf_reqbufs(struct videobuf_queue *q, struct v4l2_requestbuffers *req) { unsigned int size,count; int retval; - if (req->type != q->type) { - dprintk(1,"reqbufs: queue type invalid\n"); - return -EINVAL; - } if (req->count < 1) { dprintk(1,"reqbufs: count invalid (%d)\n",req->count); return -EINVAL; } + if (req->memory != V4L2_MEMORY_MMAP && req->memory != V4L2_MEMORY_USERPTR && req->memory != V4L2_MEMORY_OVERLAY) { @@ -303,6 +395,12 @@ int videobuf_reqbufs(struct videobuf_queue *q, } mutex_lock(&q->lock); + if (req->type != q->type) { + dprintk(1,"reqbufs: queue type invalid\n"); + retval = -EINVAL; + goto done; + } + if (q->streaming) { dprintk(1,"reqbufs: streaming already exists\n"); retval = -EBUSY; @@ -323,7 +421,7 @@ int videobuf_reqbufs(struct videobuf_queue *q, dprintk(1,"reqbufs: bufs=%d, size=0x%x [%d pages total]\n", count, size, (count*size)>>PAGE_SHIFT); - retval = videobuf_mmap_setup(q,count,size,req->memory); + retval = __videobuf_mmap_setup(q,count,size,req->memory); if (retval < 0) { dprintk(1,"reqbufs: mmap setup returned %d\n",retval); goto done; @@ -338,20 +436,28 @@ int videobuf_reqbufs(struct videobuf_queue *q, int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b) { + int ret = -EINVAL; + + mutex_lock(&q->lock); if (unlikely(b->type != q->type)) { dprintk(1,"querybuf: Wrong type.\n"); - return -EINVAL; + goto done; } if (unlikely(b->index < 0 || b->index >= VIDEO_MAX_FRAME)) { dprintk(1,"querybuf: index out of range.\n"); - return -EINVAL; + goto done; } if (unlikely(NULL == q->bufs[b->index])) { dprintk(1,"querybuf: buffer is null.\n"); - return -EINVAL; + goto done; } + videobuf_status(q,b,q->bufs[b->index],q->type); - return 0; + + ret = 0; +done: + mutex_unlock(&q->lock); + return ret; } int videobuf_qbuf(struct videobuf_queue *q, @@ -541,22 +647,30 @@ int videobuf_streamon(struct videobuf_queue *q) return retval; } -int videobuf_streamoff(struct videobuf_queue *q) +/* Locking: Caller holds q->lock */ +static int __videobuf_streamoff(struct videobuf_queue *q) { - int retval = -EINVAL; - - mutex_lock(&q->lock); if (!q->streaming) - goto done; + return -EINVAL; + videobuf_queue_cancel(q); q->streaming = 0; - retval = 0; - done: + return 0; +} + +int videobuf_streamoff(struct videobuf_queue *q) +{ + int retval; + + mutex_lock(&q->lock); + retval = __videobuf_streamoff(q); mutex_unlock(&q->lock); + return retval; } +/* Locking: Caller holds q->lock */ static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q, char __user *data, size_t count, loff_t *ppos) @@ -691,7 +805,8 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, return retval; } -int videobuf_read_start(struct videobuf_queue *q) +/* Locking: Caller holds q->lock */ +int __videobuf_read_start(struct videobuf_queue *q) { enum v4l2_field field; unsigned long flags=0; @@ -705,7 +820,7 @@ int videobuf_read_start(struct videobuf_queue *q) count = VIDEO_MAX_FRAME; size = PAGE_ALIGN(size); - err = videobuf_mmap_setup(q, count, size, V4L2_MEMORY_USERPTR); + err = __videobuf_mmap_setup(q, count, size, V4L2_MEMORY_USERPTR); if (err < 0) return err; @@ -728,12 +843,13 @@ int videobuf_read_start(struct videobuf_queue *q) return 0; } -void videobuf_read_stop(struct videobuf_queue *q) +static void __videobuf_read_stop(struct videobuf_queue *q) { int i; + videobuf_queue_cancel(q); - videobuf_mmap_free(q); + __videobuf_mmap_free(q); INIT_LIST_HEAD(&q->stream); for (i = 0; i < VIDEO_MAX_FRAME; i++) { if (NULL == q->bufs[i]) @@ -743,8 +859,41 @@ void videobuf_read_stop(struct videobuf_queue *q) } q->read_buf = NULL; q->reading = 0; + } +int videobuf_read_start(struct videobuf_queue *q) +{ + int rc; + + mutex_lock(&q->lock); + rc = __videobuf_read_start(q); + mutex_unlock(&q->lock); + + return rc; +} + +void videobuf_read_stop(struct videobuf_queue *q) +{ + mutex_lock(&q->lock); + __videobuf_read_stop(q); + mutex_unlock(&q->lock); +} + +void videobuf_stop(struct videobuf_queue *q) +{ + mutex_lock(&q->lock); + + if (q->streaming) + __videobuf_streamoff(q); + + if (q->reading) + __videobuf_read_stop(q); + + mutex_unlock(&q->lock); +} + + ssize_t videobuf_read_stream(struct videobuf_queue *q, char __user *data, size_t count, loff_t *ppos, int vbihack, int nonblocking) @@ -760,7 +909,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, if (q->streaming) goto done; if (!q->reading) { - retval = videobuf_read_start(q); + retval = __videobuf_read_start(q); if (retval < 0) goto done; } @@ -833,7 +982,7 @@ unsigned int videobuf_poll_stream(struct file *file, struct videobuf_buffer, stream); } else { if (!q->reading) - videobuf_read_start(q); + __videobuf_read_start(q); if (!q->reading) { rc = POLLERR; } else if (NULL == q->read_buf) { @@ -858,75 +1007,6 @@ unsigned int videobuf_poll_stream(struct file *file, return rc; } -int videobuf_mmap_setup(struct videobuf_queue *q, - unsigned int bcount, unsigned int bsize, - enum v4l2_memory memory) -{ - unsigned int i; - int err; - - MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); - - err = videobuf_mmap_free(q); - if (0 != err) - return err; - - /* Allocate and initialize buffers */ - for (i = 0; i < bcount; i++) { - q->bufs[i] = videobuf_alloc(q); - - if (q->bufs[i] == NULL) - break; - - q->bufs[i]->i = i; - q->bufs[i]->input = UNSET; - q->bufs[i]->memory = memory; - q->bufs[i]->bsize = bsize; - switch (memory) { - case V4L2_MEMORY_MMAP: - q->bufs[i]->boff = bsize * i; - break; - case V4L2_MEMORY_USERPTR: - case V4L2_MEMORY_OVERLAY: - /* nothing */ - break; - } - } - - if (!i) - return -ENOMEM; - - dprintk(1,"mmap setup: %d buffers, %d bytes each\n", - i, bsize); - - return i; -} - -int videobuf_mmap_free(struct videobuf_queue *q) -{ - int i; - int rc; - - if (!q) - return 0; - - MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS); - - rc = CALL(q,mmap_free,q); - if (rc<0) - return rc; - - for (i = 0; i < VIDEO_MAX_FRAME; i++) { - if (NULL == q->bufs[i]) - continue; - q->ops->buf_release(q,q->bufs[i]); - kfree(q->bufs[i]); - q->bufs[i] = NULL; - } - - return rc; -} - int videobuf_mmap_mapper(struct videobuf_queue *q, struct vm_area_struct *vma) { @@ -991,6 +1071,7 @@ EXPORT_SYMBOL_GPL(videobuf_streamoff); EXPORT_SYMBOL_GPL(videobuf_read_start); EXPORT_SYMBOL_GPL(videobuf_read_stop); +EXPORT_SYMBOL_GPL(videobuf_stop); EXPORT_SYMBOL_GPL(videobuf_read_stream); EXPORT_SYMBOL_GPL(videobuf_read_one); EXPORT_SYMBOL_GPL(videobuf_poll_stream); diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index cd74341c984..e01259438bb 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c @@ -51,7 +51,7 @@ videobuf_vm_open(struct vm_area_struct *vma) { struct videobuf_mapping *map = vma->vm_private_data; - dprintk(2,"vm_open %p [count=%d,vma=%08lx-%08lx]\n",map, + dprintk(2,"vm_open %p [count=%u,vma=%08lx-%08lx]\n",map, map->count,vma->vm_start,vma->vm_end); map->count++; @@ -64,7 +64,7 @@ videobuf_vm_close(struct vm_area_struct *vma) struct videobuf_queue *q = map->q; int i; - dprintk(2,"vm_close %p [count=%d,vma=%08lx-%08lx]\n",map, + dprintk(2,"vm_close %p [count=%u,vma=%08lx-%08lx]\n",map, map->count,vma->vm_start,vma->vm_end); map->count--; @@ -221,7 +221,7 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, } /* create mapping + update buffer list */ - map = q->bufs[first]->map = kmalloc(sizeof(struct videobuf_mapping),GFP_KERNEL); + map = q->bufs[first]->map = kzalloc(sizeof(struct videobuf_mapping),GFP_KERNEL); if (NULL == map) return -ENOMEM; diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index ee73dc75131..9b54ff9d2e3 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -1076,6 +1076,7 @@ static int vivi_release(struct inode *inode, struct file *file) int minor = iminor(inode); vivi_stop_thread(vidq); + videobuf_stop(&fh->vb_vidq); videobuf_mmap_free(&fh->vb_vidq); kfree (fh); diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index 682406168de..e4ad7a1c4fb 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -1077,8 +1077,8 @@ static int i2o_block_probe(struct device *dev) blk_queue_max_sectors(queue, max_sectors); blk_queue_max_hw_segments(queue, i2o_sg_tablesize(c, body_size)); - osm_debug("max sectors = %d\n", queue->max_phys_segments); - osm_debug("phys segments = %d\n", queue->max_sectors); + osm_debug("max sectors = %d\n", queue->max_sectors); + osm_debug("phys segments = %d\n", queue->max_phys_segments); osm_debug("max hw segments = %d\n", queue->max_hw_segments); /* diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index 8135e4c3bf4..afd82966f9a 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/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c index d366a6cc1fd..c8d62c268b1 100644 --- a/drivers/misc/fujitsu-laptop.c +++ b/drivers/misc/fujitsu-laptop.c @@ -122,9 +122,6 @@ static int get_lcd_level(void) else fujitsu->brightness_changed = 0; - if (status < 0) - return status; - return fujitsu->brightness_level; } @@ -198,7 +195,7 @@ static struct platform_driver fujitsupf_driver = { /* ACPI device */ -int acpi_fujitsu_add(struct acpi_device *device) +static int acpi_fujitsu_add(struct acpi_device *device) { int result = 0; int state = 0; @@ -229,7 +226,7 @@ int acpi_fujitsu_add(struct acpi_device *device) return result; } -int acpi_fujitsu_remove(struct acpi_device *device, int type) +static int acpi_fujitsu_remove(struct acpi_device *device, int type) { ACPI_FUNCTION_TRACE("acpi_fujitsu_remove"); diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c index 6a5a05d1f39..05172d2613d 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/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index e953276664a..cf56647a6ca 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, @@ -987,15 +987,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, @@ -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 3abcc812063..8fba2bbe345 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 e38d5a3b2a8..aeb32a93f6a 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 9203a0b221b..30cd13b13ac 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 d552de68311..eeea84c309e 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/core/core.c b/drivers/mmc/core/core.c index 09435e0ec68..b96667448eb 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -19,7 +19,6 @@ #include <linux/pagemap.h> #include <linux/err.h> #include <linux/leds.h> -#include <asm/scatterlist.h> #include <linux/scatterlist.h> #include <linux/mmc/card.h> diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 7471d49909b..64b05c6270f 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -10,7 +10,6 @@ */ #include <linux/types.h> -#include <asm/scatterlist.h> #include <linux/scatterlist.h> #include <linux/mmc/host.h> diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c index a6dafe62b99..0d96080d44b 100644 --- a/drivers/mmc/core/sd_ops.c +++ b/drivers/mmc/core/sd_ops.c @@ -10,7 +10,6 @@ */ #include <linux/types.h> -#include <asm/scatterlist.h> #include <linux/scatterlist.h> #include <linux/mmc/host.h> diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c index 4d289b27503..e1fca588e38 100644 --- a/drivers/mmc/core/sdio_ops.c +++ b/drivers/mmc/core/sdio_ops.c @@ -9,7 +9,6 @@ * your option) any later version. */ -#include <asm/scatterlist.h> #include <linux/scatterlist.h> #include <linux/mmc/host.h> diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c index b2104d4f87a..c3926eb3bf4 100644 --- a/drivers/mmc/host/au1xmmc.c +++ b/drivers/mmc/host/au1xmmc.c @@ -40,7 +40,7 @@ #include <linux/mm.h> #include <linux/interrupt.h> #include <linux/dma-mapping.h> -#include <scatterlist/scatterlist.h> +#include <linux/scatterlist.h> #include <linux/mmc/host.h> #include <asm/io.h> diff --git a/drivers/mmc/host/imxmmc.c b/drivers/mmc/host/imxmmc.c index fc72e1fadb6..f2070a19cfa 100644 --- a/drivers/mmc/host/imxmmc.c +++ b/drivers/mmc/host/imxmmc.c @@ -262,7 +262,7 @@ static void imxmci_setup_data(struct imxmci_host *host, struct mmc_data *data) } /* Convert back to virtual address */ - host->data_ptr = (u16*)sg_virt(sg); + host->data_ptr = (u16*)sg_virt(data->sg); host->data_cnt = 0; clear_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events); diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index a6469218f19..365024b83d3 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c @@ -176,8 +176,6 @@ mmc_spi_readbytes(struct mmc_spi_host *host, unsigned len) DMA_FROM_DEVICE); status = spi_sync(host->spi, &host->readback); - if (status == 0) - status = host->readback.status; if (host->dma_dev) dma_sync_single_for_cpu(host->dma_dev, @@ -480,8 +478,6 @@ mmc_spi_command_send(struct mmc_spi_host *host, DMA_BIDIRECTIONAL); } status = spi_sync(host->spi, &host->m); - if (status == 0) - status = host->m.status; if (host->dma_dev) dma_sync_single_for_cpu(host->dma_dev, @@ -624,8 +620,6 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t) DMA_BIDIRECTIONAL); status = spi_sync(spi, &host->m); - if (status == 0) - status = host->m.status; if (status != 0) { dev_dbg(&spi->dev, "write error (%d)\n", status); @@ -726,8 +720,6 @@ mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t) } status = spi_sync(spi, &host->m); - if (status == 0) - status = host->m.status; if (host->dma_dev) { dma_sync_single_for_cpu(host->dma_dev, @@ -905,8 +897,6 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd, DMA_BIDIRECTIONAL); tmp = spi_sync(spi, &host->m); - if (tmp == 0) - tmp = host->m.status; if (host->dma_dev) dma_sync_single_for_cpu(host->dma_dev, diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index a25ee71998a..1654a333034 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -39,6 +39,7 @@ #define DRIVER_NAME "pxa2xx-mci" #define NR_SG 1 +#define CLKRT_OFF (~0) struct pxamci_host { struct mmc_host *mmc; @@ -371,6 +372,9 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) unsigned long rate = host->clkrate; unsigned int clk = rate / ios->clock; + if (host->clkrt == CLKRT_OFF) + clk_enable(host->clk); + /* * clk might result in a lower divisor than we * desire. check for that condition and adjust @@ -379,14 +383,16 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) if (rate / clk > ios->clock) clk <<= 1; host->clkrt = fls(clk) - 1; - clk_enable(host->clk); /* * we write clkrt on the next command */ } else { pxamci_stop_clock(host); - clk_disable(host->clk); + if (host->clkrt != CLKRT_OFF) { + host->clkrt = CLKRT_OFF; + clk_disable(host->clk); + } } if (host->power_mode != ios->power_mode) { @@ -498,6 +504,7 @@ static int pxamci_probe(struct platform_device *pdev) host->mmc = mmc; host->dma = -1; host->pdata = pdev->dev.platform_data; + host->clkrt = CLKRT_OFF; host->clk = clk_get(&pdev->dev, "MMCCLK"); if (IS_ERR(host->clk)) { diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 6b80bf77a4e..785bbdcf4a5 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -7,6 +7,10 @@ * 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. + * + * Thanks to the following companies for their support: + * + * - JMicron (hardware and technical support) */ #include <linux/delay.h> @@ -26,13 +30,29 @@ static unsigned int debug_quirks = 0; +/* + * Different quirks to handle when the hardware deviates from a strict + * interpretation of the SDHCI specification. + */ + +/* Controller doesn't honor resets unless we touch the clock register */ #define SDHCI_QUIRK_CLOCK_BEFORE_RESET (1<<0) +/* Controller has bad caps bits, but really supports DMA */ #define SDHCI_QUIRK_FORCE_DMA (1<<1) /* Controller doesn't like some resets when there is no card inserted. */ #define SDHCI_QUIRK_NO_CARD_NO_RESET (1<<2) +/* Controller doesn't like clearing the power reg before a change */ #define SDHCI_QUIRK_SINGLE_POWER_WRITE (1<<3) +/* Controller has flaky internal state so reset it on each ios change */ #define SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS (1<<4) +/* Controller has an unusable DMA engine */ #define SDHCI_QUIRK_BROKEN_DMA (1<<5) +/* Controller can only DMA from 32-bit aligned addresses */ +#define SDHCI_QUIRK_32BIT_DMA_ADDR (1<<6) +/* Controller can only DMA chunk sizes that are a multiple of 32 bits */ +#define SDHCI_QUIRK_32BIT_DMA_SIZE (1<<7) +/* Controller needs to be reset after each request to stay stable */ +#define SDHCI_QUIRK_RESET_AFTER_REQUEST (1<<8) static const struct pci_device_id pci_ids[] __devinitdata = { { @@ -97,6 +117,16 @@ static const struct pci_device_id pci_ids[] __devinitdata = { SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS, }, + { + .vendor = PCI_VENDOR_ID_JMICRON, + .device = PCI_DEVICE_ID_JMICRON_JMB38X_SD, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = SDHCI_QUIRK_32BIT_DMA_ADDR | + SDHCI_QUIRK_32BIT_DMA_SIZE | + SDHCI_QUIRK_RESET_AFTER_REQUEST, + }, + { /* Generic SD host controller */ PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00) }, @@ -419,7 +449,29 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) writeb(count, host->ioaddr + SDHCI_TIMEOUT_CONTROL); - if (host->flags & SDHCI_USE_DMA) { + if (host->flags & SDHCI_USE_DMA) + host->flags |= SDHCI_REQ_USE_DMA; + + if (unlikely((host->flags & SDHCI_REQ_USE_DMA) && + (host->chip->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE) && + ((data->blksz * data->blocks) & 0x3))) { + DBG("Reverting to PIO because of transfer size (%d)\n", + data->blksz * data->blocks); + host->flags &= ~SDHCI_REQ_USE_DMA; + } + + /* + * The assumption here being that alignment is the same after + * translation to device address space. + */ + if (unlikely((host->flags & SDHCI_REQ_USE_DMA) && + (host->chip->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) && + (data->sg->offset & 0x3))) { + DBG("Reverting to PIO because of bad alignment\n"); + host->flags &= ~SDHCI_REQ_USE_DMA; + } + + if (host->flags & SDHCI_REQ_USE_DMA) { int count; count = pci_map_sg(host->chip->pdev, data->sg, data->sg_len, @@ -456,7 +508,7 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, mode |= SDHCI_TRNS_MULTI; if (data->flags & MMC_DATA_READ) mode |= SDHCI_TRNS_READ; - if (host->flags & SDHCI_USE_DMA) + if (host->flags & SDHCI_REQ_USE_DMA) mode |= SDHCI_TRNS_DMA; writew(mode, host->ioaddr + SDHCI_TRANSFER_MODE); @@ -472,7 +524,7 @@ static void sdhci_finish_data(struct sdhci_host *host) data = host->data; host->data = NULL; - if (host->flags & SDHCI_USE_DMA) { + if (host->flags & SDHCI_REQ_USE_DMA) { pci_unmap_sg(host->chip->pdev, data->sg, data->sg_len, (data->flags & MMC_DATA_READ)?PCI_DMA_FROMDEVICE:PCI_DMA_TODEVICE); } @@ -886,7 +938,8 @@ static void sdhci_tasklet_finish(unsigned long param) */ if (mrq->cmd->error || (mrq->data && (mrq->data->error || - (mrq->data->stop && mrq->data->stop->error)))) { + (mrq->data->stop && mrq->data->stop->error))) || + (host->chip->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST)) { /* Some controllers need this kick or reset won't work here */ if (host->chip->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) { @@ -1284,7 +1337,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) version = readw(host->ioaddr + SDHCI_HOST_VERSION); version = (version & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT; - if (version != 0) { + if (version > 1) { printk(KERN_ERR "%s: Unknown controller version (%d). " "You may experience problems.\n", host->slot_descr, version); @@ -1301,7 +1354,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/sdhci.h b/drivers/mmc/host/sdhci.h index 05195ea900f..e4d77b038bf 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -171,7 +171,8 @@ struct sdhci_host { spinlock_t lock; /* Mutex */ int flags; /* Host attributes */ -#define SDHCI_USE_DMA (1<<0) +#define SDHCI_USE_DMA (1<<0) /* Host is DMA capable */ +#define SDHCI_REQ_USE_DMA (1<<1) /* Use DMA for this req. */ unsigned int max_clk; /* Max possible freq (MHz) */ unsigned int timeout_clk; /* Timeout freq (KHz) */ diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c index c11a3d25605..20d5c7bd940 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/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index a9eb1c51624..1707f98c322 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -1504,9 +1504,12 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, int ret, wbufsize, word_gap, words; const struct kvec *vec; unsigned long vec_seek; + unsigned long initial_adr; + int initial_len = len; wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; adr += chip->start; + initial_adr = adr; cmd_adr = adr & ~(wbufsize-1); /* Let's determine this according to the interleave only once */ @@ -1519,7 +1522,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, return ret; } - XIP_INVAL_CACHED_RANGE(map, adr, len); + XIP_INVAL_CACHED_RANGE(map, initial_adr, initial_len); ENABLE_VPP(map); xip_disable(map, chip, cmd_adr); @@ -1610,7 +1613,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, chip->state = FL_WRITING; ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, - adr, len, + initial_adr, initial_len, chip->buffer_write_time); if (ret) { map_write(map, CMD(0x70), cmd_adr); diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index edda6e10ebe..8fafac987e0 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -385,6 +385,7 @@ static int __init el3_probe(int card_idx) #if defined(__ISAPNP__) static int pnp_cards; struct pnp_dev *idev = NULL; + int pnp_found = 0; if (nopnp == 1) goto no_pnp; @@ -430,6 +431,7 @@ __again: pnp_cards++; netdev_boot_setup_check(dev); + pnp_found = 1; goto found; } } @@ -560,6 +562,8 @@ no_pnp: lp = netdev_priv(dev); #if defined(__ISAPNP__) lp->dev = &idev->dev; + if (pnp_found) + lp->type = EL3_PNP; #endif err = el3_common_init(dev); diff --git a/drivers/net/82596.c b/drivers/net/82596.c index bb30d5be782..2797da7eeee 100644 --- a/drivers/net/82596.c +++ b/drivers/net/82596.c @@ -1192,6 +1192,8 @@ struct net_device * __init i82596_probe(int unit) goto out; } + dev->base_addr = ioaddr; + for (i = 0; i < 8; i++) { eth_addr[i] = inb(ioaddr + 8 + i); checksum += eth_addr[i]; @@ -1209,7 +1211,6 @@ struct net_device * __init i82596_probe(int unit) goto out1; } - dev->base_addr = ioaddr; dev->irq = 10; } #endif diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 86b8641b466..114771a2a13 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" @@ -165,15 +166,6 @@ config NET_SB1000 If you don't have this card, of course say N. -config IP1000 - tristate "IP1000 Gigabit Ethernet support" - depends on PCI && EXPERIMENTAL - ---help--- - This driver supports IP1000 gigabit Ethernet cards. - - To compile this driver as a module, choose M here: the module - will be called ipg. This is recommended. - source "drivers/net/arcnet/Kconfig" source "drivers/net/phy/Kconfig" @@ -233,7 +225,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 @@ -364,8 +356,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 @@ -378,8 +369,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 @@ -617,8 +607,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 @@ -630,8 +619,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 @@ -643,8 +631,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 @@ -655,8 +642,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 @@ -671,8 +657,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 @@ -683,8 +668,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 @@ -695,8 +679,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 @@ -707,8 +690,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 @@ -731,8 +713,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" @@ -749,8 +730,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 @@ -787,8 +767,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 @@ -800,8 +779,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 @@ -820,8 +798,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 @@ -833,8 +810,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 @@ -895,15 +871,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 @@ -914,8 +889,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" @@ -924,8 +898,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 @@ -936,15 +909,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. @@ -978,8 +950,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 @@ -990,8 +961,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 @@ -1002,8 +972,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" @@ -1017,8 +986,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 @@ -1031,8 +999,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 @@ -1043,8 +1010,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 @@ -1073,8 +1039,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 @@ -1088,8 +1053,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 @@ -1103,8 +1067,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 @@ -1117,8 +1080,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 @@ -1130,8 +1092,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 @@ -1143,8 +1104,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 @@ -1163,8 +1123,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 @@ -1184,8 +1143,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 @@ -1206,8 +1164,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 @@ -1219,8 +1176,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 @@ -1231,8 +1187,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 @@ -1246,8 +1201,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" @@ -1277,8 +1231,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 @@ -1305,8 +1258,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 @@ -1360,8 +1312,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 @@ -1372,9 +1323,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" @@ -1386,9 +1336,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 @@ -1417,9 +1366,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)" @@ -1445,9 +1393,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" @@ -1463,8 +1410,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. @@ -1491,8 +1437,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 @@ -1504,8 +1449,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 @@ -1545,8 +1489,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 @@ -1559,8 +1502,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 @@ -1572,8 +1514,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 @@ -1703,8 +1644,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>. @@ -1880,6 +1820,28 @@ config FEC2 Say Y here if you want to use the second built-in 10/100 Fast ethernet controller on some Motorola ColdFire processors. +config FEC_MPC52xx + tristate "MPC52xx FEC driver" + depends on PPC_MERGE && PPC_MPC52xx && PPC_BESTCOMM_FEC + select CRC32 + select PHYLIB + ---help--- + This option enables support for the MPC5200's on-chip + Fast Ethernet Controller + If compiled as module, it will be called 'fec_mpc52xx.ko'. + +config FEC_MPC52xx_MDIO + bool "MPC52xx FEC MDIO bus driver" + depends on FEC_MPC52xx + default y + ---help--- + The MPC5200's FEC can connect to the Ethernet either with + an external MII PHY chip or 10 Mbps 7-wire interface + (Motorola? industry standard). + If your board uses an external PHY connected to FEC, enable this. + If not sure, enable. + If compiled as module, it will be called 'fec_mpc52xx_phy.ko'. + config NE_H8300 tristate "NE2000 compatible support for H8/300" depends on H8300 @@ -1972,8 +1934,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 @@ -2018,10 +1979,19 @@ 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. +config IP1000 + tristate "IP1000 Gigabit Ethernet support" + depends on PCI && EXPERIMENTAL + select MII + ---help--- + This driver supports IP1000 gigabit Ethernet cards. + + To compile this driver as a module, choose M here: the module + will be called ipg. This is recommended. + source "drivers/net/ixp2000/Kconfig" config MYRI_SBUS @@ -2052,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 @@ -2502,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 @@ -2525,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 @@ -2579,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 @@ -2804,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" @@ -2837,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)" @@ -2999,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/Makefile b/drivers/net/Makefile index 593262065c9..0e5fde4a1b2 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -96,6 +96,10 @@ obj-$(CONFIG_SHAPER) += shaper.o obj-$(CONFIG_HP100) += hp100.o obj-$(CONFIG_SMC9194) += smc9194.o obj-$(CONFIG_FEC) += fec.o +obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o +ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y) + obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o +endif obj-$(CONFIG_68360_ENET) += 68360enet.o obj-$(CONFIG_WD80x3) += wd.o 8390.o obj-$(CONFIG_EL2) += 3c503.o 8390.o diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index eebf5bb2b03..e7fdd81919b 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 4030274fe78..3b2f7f11546 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 7f016f3d5bf..91a6590d107 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 53fe7ded5d5..eb971755a3f 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -371,7 +371,6 @@ static void bf537_adjust_link(struct net_device *dev) if (phydev->speed != lp->old_speed) { #if defined(CONFIG_BFIN_MAC_RMII) u32 opmode = bfin_read_EMAC_OPMODE(); - bf537mac_disable(); switch (phydev->speed) { case 10: opmode |= RMII_10; @@ -386,7 +385,6 @@ static void bf537_adjust_link(struct net_device *dev) break; } bfin_write_EMAC_OPMODE(opmode); - bf537mac_enable(); #endif new_state = 1; @@ -678,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); @@ -926,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 3a107ad7538..5970ea7142c 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/bnx2.c b/drivers/net/bnx2.c index da767d3d5af..4e7b46e4487 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -56,8 +56,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.6.8" -#define DRV_MODULE_RELDATE "October 17, 2007" +#define DRV_MODULE_VERSION "1.6.9" +#define DRV_MODULE_RELDATE "December 8, 2007" #define RUN_AT(x) (jiffies + (x)) @@ -2387,18 +2387,24 @@ bnx2_reuse_rx_skb(struct bnx2 *bp, struct sk_buff *skb, prod_bd->rx_bd_haddr_lo = cons_bd->rx_bd_haddr_lo; } +static inline u16 +bnx2_get_hw_rx_cons(struct bnx2 *bp) +{ + u16 cons = bp->status_blk->status_rx_quick_consumer_index0; + + if (unlikely((cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT)) + cons++; + return cons; +} + static int bnx2_rx_int(struct bnx2 *bp, int budget) { - struct status_block *sblk = bp->status_blk; u16 hw_cons, sw_cons, sw_ring_cons, sw_prod, sw_ring_prod; struct l2_fhdr *rx_hdr; int rx_pkt = 0; - hw_cons = bp->hw_rx_cons = sblk->status_rx_quick_consumer_index0; - if ((hw_cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT) { - hw_cons++; - } + hw_cons = bnx2_get_hw_rx_cons(bp); sw_cons = bp->rx_cons; sw_prod = bp->rx_prod; @@ -2515,10 +2521,7 @@ next_rx: /* Refresh hw_cons to see if there is new work */ if (sw_cons == hw_cons) { - hw_cons = bp->hw_rx_cons = - sblk->status_rx_quick_consumer_index0; - if ((hw_cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT) - hw_cons++; + hw_cons = bnx2_get_hw_rx_cons(bp); rmb(); } } @@ -2622,7 +2625,7 @@ bnx2_has_work(struct bnx2 *bp) { struct status_block *sblk = bp->status_blk; - if ((sblk->status_rx_quick_consumer_index0 != bp->hw_rx_cons) || + if ((bnx2_get_hw_rx_cons(bp) != bp->rx_cons) || (sblk->status_tx_quick_consumer_index0 != bp->hw_tx_cons)) return 1; @@ -2655,7 +2658,7 @@ static int bnx2_poll_work(struct bnx2 *bp, int work_done, int budget) if (sblk->status_tx_quick_consumer_index0 != bp->hw_tx_cons) bnx2_tx_int(bp); - if (sblk->status_rx_quick_consumer_index0 != bp->hw_rx_cons) + if (bnx2_get_hw_rx_cons(bp) != bp->rx_cons) work_done += bnx2_rx_int(bp, budget - work_done); return work_done; @@ -4177,7 +4180,6 @@ bnx2_init_rx_ring(struct bnx2 *bp) ring_prod = prod = bp->rx_prod = 0; bp->rx_cons = 0; - bp->hw_rx_cons = 0; bp->rx_prod_bseq = 0; for (i = 0; i < bp->rx_max_ring; i++) { @@ -6685,8 +6687,9 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) } else if (CHIP_NUM(bp) == CHIP_NUM_5706 || CHIP_NUM(bp) == CHIP_NUM_5708) bp->phy_flags |= PHY_CRC_FIX_FLAG; - else if (CHIP_ID(bp) == CHIP_ID_5709_A0 || - CHIP_ID(bp) == CHIP_ID_5709_A1) + else if (CHIP_NUM(bp) == CHIP_NUM_5709 && + (CHIP_REV(bp) == CHIP_REV_Ax || + CHIP_REV(bp) == CHIP_REV_Bx)) bp->phy_flags |= PHY_DIS_EARLY_DAC_FLAG; if ((CHIP_ID(bp) == CHIP_ID_5708_A0) || diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 1dce0d1a258..30ba366608b 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -6513,7 +6513,6 @@ struct bnx2 { u32 rx_prod_bseq; u16 rx_prod; u16 rx_cons; - u16 hw_rx_cons; u32 rx_csum; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 6937ef0e727..b0b26036266 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -74,6 +74,7 @@ #include <linux/ethtool.h> #include <linux/if_vlan.h> #include <linux/if_bonding.h> +#include <linux/jiffies.h> #include <net/route.h> #include <net/net_namespace.h> #include "bonding.h" @@ -174,6 +175,7 @@ struct bond_parm_tbl bond_mode_tbl[] = { struct bond_parm_tbl xmit_hashtype_tbl[] = { { "layer2", BOND_XMIT_POLICY_LAYER2}, { "layer3+4", BOND_XMIT_POLICY_LAYER34}, +{ "layer2+3", BOND_XMIT_POLICY_LAYER23}, { NULL, -1}, }; @@ -1847,9 +1849,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); } /* @@ -2722,8 +2724,8 @@ void bond_loadbalance_arp_mon(struct work_struct *work) */ bond_for_each_slave(bond, slave, i) { if (slave->link != BOND_LINK_UP) { - if (((jiffies - slave->dev->trans_start) <= delta_in_ticks) && - ((jiffies - slave->dev->last_rx) <= delta_in_ticks)) { + if (time_before_eq(jiffies, slave->dev->trans_start + delta_in_ticks) && + time_before_eq(jiffies, slave->dev->last_rx + delta_in_ticks)) { slave->link = BOND_LINK_UP; slave->state = BOND_STATE_ACTIVE; @@ -2754,8 +2756,8 @@ void bond_loadbalance_arp_mon(struct work_struct *work) * when the source ip is 0, so don't take the link down * if we don't know our ip yet */ - if (((jiffies - slave->dev->trans_start) >= (2*delta_in_ticks)) || - (((jiffies - slave->dev->last_rx) >= (2*delta_in_ticks)) && + if (time_after_eq(jiffies, slave->dev->trans_start + 2*delta_in_ticks) || + (time_after_eq(jiffies, slave->dev->last_rx + 2*delta_in_ticks) && bond_has_ip(bond))) { slave->link = BOND_LINK_DOWN; @@ -2848,8 +2850,8 @@ void bond_activebackup_arp_mon(struct work_struct *work) */ bond_for_each_slave(bond, slave, i) { if (slave->link != BOND_LINK_UP) { - if ((jiffies - slave_last_rx(bond, slave)) <= - delta_in_ticks) { + if (time_before_eq(jiffies, + slave_last_rx(bond, slave) + delta_in_ticks)) { slave->link = BOND_LINK_UP; @@ -2858,7 +2860,7 @@ void bond_activebackup_arp_mon(struct work_struct *work) write_lock_bh(&bond->curr_slave_lock); if ((!bond->curr_active_slave) && - ((jiffies - slave->dev->trans_start) <= delta_in_ticks)) { + time_before_eq(jiffies, slave->dev->trans_start + delta_in_ticks)) { bond_change_active_slave(bond, slave); bond->current_arp_slave = NULL; } else if (bond->curr_active_slave != slave) { @@ -2897,7 +2899,7 @@ void bond_activebackup_arp_mon(struct work_struct *work) if ((slave != bond->curr_active_slave) && (!bond->current_arp_slave) && - (((jiffies - slave_last_rx(bond, slave)) >= 3*delta_in_ticks) && + (time_after_eq(jiffies, slave_last_rx(bond, slave) + 3*delta_in_ticks) && bond_has_ip(bond))) { /* a backup slave has gone down; three times * the delta allows the current slave to be @@ -2943,10 +2945,10 @@ void bond_activebackup_arp_mon(struct work_struct *work) * before being taken out. if a primary is being used, check * if it is up and needs to take over as the curr_active_slave */ - if ((((jiffies - slave->dev->trans_start) >= (2*delta_in_ticks)) || - (((jiffies - slave_last_rx(bond, slave)) >= (2*delta_in_ticks)) && - bond_has_ip(bond))) && - ((jiffies - slave->jiffies) >= 2*delta_in_ticks)) { + if ((time_after_eq(jiffies, slave->dev->trans_start + 2*delta_in_ticks) || + (time_after_eq(jiffies, slave_last_rx(bond, slave) + 2*delta_in_ticks) && + bond_has_ip(bond))) && + time_after_eq(jiffies, slave->jiffies + 2*delta_in_ticks)) { slave->link = BOND_LINK_DOWN; @@ -3604,6 +3606,24 @@ void bond_unregister_arp(struct bonding *bond) /*---------------------------- Hashing Policies -----------------------------*/ /* + * Hash for the output device based upon layer 2 and layer 3 data. If + * the packet is not IP mimic bond_xmit_hash_policy_l2() + */ +static int bond_xmit_hash_policy_l23(struct sk_buff *skb, + struct net_device *bond_dev, int count) +{ + struct ethhdr *data = (struct ethhdr *)skb->data; + struct iphdr *iph = ip_hdr(skb); + + if (skb->protocol == __constant_htons(ETH_P_IP)) { + return ((ntohl(iph->saddr ^ iph->daddr) & 0xffff) ^ + (data->h_dest[5] ^ bond_dev->dev_addr[5])) % count; + } + + return (data->h_dest[5] ^ bond_dev->dev_addr[5]) % count; +} + +/* * Hash for the output device based upon layer 3 and layer 4 data. If * the packet is a frag or not TCP or UDP, just use layer 3 data. If it is * altogether not IP, mimic bond_xmit_hash_policy_l2() @@ -4305,6 +4325,22 @@ out: /*------------------------- Device initialization ---------------------------*/ +static void bond_set_xmit_hash_policy(struct bonding *bond) +{ + switch (bond->params.xmit_policy) { + case BOND_XMIT_POLICY_LAYER23: + bond->xmit_hash_policy = bond_xmit_hash_policy_l23; + break; + case BOND_XMIT_POLICY_LAYER34: + bond->xmit_hash_policy = bond_xmit_hash_policy_l34; + break; + case BOND_XMIT_POLICY_LAYER2: + default: + bond->xmit_hash_policy = bond_xmit_hash_policy_l2; + break; + } +} + /* * set bond mode specific net device operations */ @@ -4321,10 +4357,7 @@ void bond_set_mode_ops(struct bonding *bond, int mode) break; case BOND_MODE_XOR: bond_dev->hard_start_xmit = bond_xmit_xor; - if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER34) - bond->xmit_hash_policy = bond_xmit_hash_policy_l34; - else - bond->xmit_hash_policy = bond_xmit_hash_policy_l2; + bond_set_xmit_hash_policy(bond); break; case BOND_MODE_BROADCAST: bond_dev->hard_start_xmit = bond_xmit_broadcast; @@ -4332,10 +4365,7 @@ void bond_set_mode_ops(struct bonding *bond, int mode) case BOND_MODE_8023AD: bond_set_master_3ad_flags(bond); bond_dev->hard_start_xmit = bond_3ad_xmit_xor; - if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER34) - bond->xmit_hash_policy = bond_xmit_hash_policy_l34; - else - bond->xmit_hash_policy = bond_xmit_hash_policy_l2; + bond_set_xmit_hash_policy(bond); break; case BOND_MODE_ALB: bond_set_master_alb_flags(bond); @@ -4405,6 +4435,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); @@ -4461,6 +4492,27 @@ static void bond_deinit(struct net_device *bond_dev) #endif } +static void bond_work_cancel_all(struct bonding *bond) +{ + write_lock_bh(&bond->lock); + bond->kill_timers = 1; + write_unlock_bh(&bond->lock); + + if (bond->params.miimon && delayed_work_pending(&bond->mii_work)) + cancel_delayed_work(&bond->mii_work); + + if (bond->params.arp_interval && delayed_work_pending(&bond->arp_work)) + cancel_delayed_work(&bond->arp_work); + + if (bond->params.mode == BOND_MODE_ALB && + delayed_work_pending(&bond->alb_work)) + cancel_delayed_work(&bond->alb_work); + + if (bond->params.mode == BOND_MODE_8023AD && + delayed_work_pending(&bond->ad_work)) + cancel_delayed_work(&bond->ad_work); +} + /* Unregister and free all bond devices. * Caller must hold rtnl_lock. */ @@ -4471,11 +4523,12 @@ static void bond_free_all(void) list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list) { struct net_device *bond_dev = bond->dev; + bond_work_cancel_all(bond); 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 @@ -4496,8 +4549,7 @@ int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl) for (i = 0; tbl[i].modename; i++) { if ((isdigit(*mode_arg) && tbl[i].mode == simple_strtol(mode_arg, NULL, 0)) || - (strncmp(mode_arg, tbl[i].modename, - strlen(tbl[i].modename)) == 0)) { + (strcmp(mode_arg, tbl[i].modename) == 0)) { return tbl[i].mode; } } @@ -4872,27 +4924,6 @@ out_rtnl: return res; } -static void bond_work_cancel_all(struct bonding *bond) -{ - write_lock_bh(&bond->lock); - bond->kill_timers = 1; - write_unlock_bh(&bond->lock); - - if (bond->params.miimon && delayed_work_pending(&bond->mii_work)) - cancel_delayed_work(&bond->mii_work); - - if (bond->params.arp_interval && delayed_work_pending(&bond->arp_work)) - cancel_delayed_work(&bond->arp_work); - - if (bond->params.mode == BOND_MODE_ALB && - delayed_work_pending(&bond->alb_work)) - cancel_delayed_work(&bond->alb_work); - - if (bond->params.mode == BOND_MODE_8023AD && - delayed_work_pending(&bond->ad_work)) - cancel_delayed_work(&bond->ad_work); -} - static int __init bonding_init(void) { int i; diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 7a06ade85b0..11b76b35241 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -74,7 +74,7 @@ struct rw_semaphore bonding_rwsem; * "show" function for the bond_masters attribute. * The class parameter is ignored. */ -static ssize_t bonding_show_bonds(struct class *cls, char *buffer) +static ssize_t bonding_show_bonds(struct class *cls, char *buf) { int res = 0; struct bonding *bond; @@ -86,14 +86,13 @@ static ssize_t bonding_show_bonds(struct class *cls, char *buffer) /* not enough space for another interface name */ if ((PAGE_SIZE - res) > 10) res = PAGE_SIZE - 10; - res += sprintf(buffer + res, "++more++"); + res += sprintf(buf + res, "++more++ "); break; } - res += sprintf(buffer + res, "%s ", - bond->dev->name); + res += sprintf(buf + res, "%s ", bond->dev->name); } - res += sprintf(buffer + res, "\n"); - res++; + if (res) + buf[res-1] = '\n'; /* eat the leftover space */ up_read(&(bonding_rwsem)); return res; } @@ -235,14 +234,14 @@ static ssize_t bonding_show_slaves(struct device *d, /* not enough space for another interface name */ if ((PAGE_SIZE - res) > 10) res = PAGE_SIZE - 10; - res += sprintf(buf + res, "++more++"); + res += sprintf(buf + res, "++more++ "); break; } res += sprintf(buf + res, "%s ", slave->dev->name); } read_unlock(&bond->lock); - res += sprintf(buf + res, "\n"); - res++; + if (res) + buf[res-1] = '\n'; /* eat the leftover space */ return res; } @@ -406,7 +405,7 @@ static ssize_t bonding_show_mode(struct device *d, return sprintf(buf, "%s %d\n", bond_mode_tbl[bond->params.mode].modename, - bond->params.mode) + 1; + bond->params.mode); } static ssize_t bonding_store_mode(struct device *d, @@ -457,20 +456,11 @@ static ssize_t bonding_show_xmit_hash(struct device *d, struct device_attribute *attr, char *buf) { - int count; struct bonding *bond = to_bond(d); - if ((bond->params.mode != BOND_MODE_XOR) && - (bond->params.mode != BOND_MODE_8023AD)) { - // Not Applicable - count = sprintf(buf, "NA\n") + 1; - } else { - count = sprintf(buf, "%s %d\n", - xmit_hashtype_tbl[bond->params.xmit_policy].modename, - bond->params.xmit_policy) + 1; - } - - return count; + return sprintf(buf, "%s %d\n", + xmit_hashtype_tbl[bond->params.xmit_policy].modename, + bond->params.xmit_policy); } static ssize_t bonding_store_xmit_hash(struct device *d, @@ -488,15 +478,6 @@ static ssize_t bonding_store_xmit_hash(struct device *d, goto out; } - if ((bond->params.mode != BOND_MODE_XOR) && - (bond->params.mode != BOND_MODE_8023AD)) { - printk(KERN_ERR DRV_NAME - "%s: Transmit hash policy is irrelevant in this mode.\n", - bond->dev->name); - ret = -EPERM; - goto out; - } - new_value = bond_parse_parm((char *)buf, xmit_hashtype_tbl); if (new_value < 0) { printk(KERN_ERR DRV_NAME @@ -527,7 +508,7 @@ static ssize_t bonding_show_arp_validate(struct device *d, return sprintf(buf, "%s %d\n", arp_validate_tbl[bond->params.arp_validate].modename, - bond->params.arp_validate) + 1; + bond->params.arp_validate); } static ssize_t bonding_store_arp_validate(struct device *d, @@ -627,7 +608,7 @@ static ssize_t bonding_show_arp_interval(struct device *d, { struct bonding *bond = to_bond(d); - return sprintf(buf, "%d\n", bond->params.arp_interval) + 1; + return sprintf(buf, "%d\n", bond->params.arp_interval); } static ssize_t bonding_store_arp_interval(struct device *d, @@ -712,9 +693,7 @@ static ssize_t bonding_show_arp_targets(struct device *d, NIPQUAD(bond->params.arp_targets[i])); } if (res) - res--; /* eat the leftover space */ - res += sprintf(buf + res, "\n"); - res++; + buf[res-1] = '\n'; /* eat the leftover space */ return res; } @@ -815,7 +794,7 @@ static ssize_t bonding_show_downdelay(struct device *d, { struct bonding *bond = to_bond(d); - return sprintf(buf, "%d\n", bond->params.downdelay * bond->params.miimon) + 1; + return sprintf(buf, "%d\n", bond->params.downdelay * bond->params.miimon); } static ssize_t bonding_store_downdelay(struct device *d, @@ -872,7 +851,7 @@ static ssize_t bonding_show_updelay(struct device *d, { struct bonding *bond = to_bond(d); - return sprintf(buf, "%d\n", bond->params.updelay * bond->params.miimon) + 1; + return sprintf(buf, "%d\n", bond->params.updelay * bond->params.miimon); } @@ -936,7 +915,7 @@ static ssize_t bonding_show_lacp(struct device *d, return sprintf(buf, "%s %d\n", bond_lacp_tbl[bond->params.lacp_fast].modename, - bond->params.lacp_fast) + 1; + bond->params.lacp_fast); } static ssize_t bonding_store_lacp(struct device *d, @@ -992,7 +971,7 @@ static ssize_t bonding_show_miimon(struct device *d, { struct bonding *bond = to_bond(d); - return sprintf(buf, "%d\n", bond->params.miimon) + 1; + return sprintf(buf, "%d\n", bond->params.miimon); } static ssize_t bonding_store_miimon(struct device *d, @@ -1083,9 +1062,7 @@ static ssize_t bonding_show_primary(struct device *d, struct bonding *bond = to_bond(d); if (bond->primary_slave) - count = sprintf(buf, "%s\n", bond->primary_slave->dev->name) + 1; - else - count = sprintf(buf, "\n") + 1; + count = sprintf(buf, "%s\n", bond->primary_slave->dev->name); return count; } @@ -1149,7 +1126,7 @@ static ssize_t bonding_show_carrier(struct device *d, { struct bonding *bond = to_bond(d); - return sprintf(buf, "%d\n", bond->params.use_carrier) + 1; + return sprintf(buf, "%d\n", bond->params.use_carrier); } static ssize_t bonding_store_carrier(struct device *d, @@ -1191,18 +1168,14 @@ static ssize_t bonding_show_active_slave(struct device *d, { struct slave *curr; struct bonding *bond = to_bond(d); - int count; - - rtnl_lock(); + int count = 0; read_lock(&bond->curr_slave_lock); curr = bond->curr_active_slave; read_unlock(&bond->curr_slave_lock); if (USES_PRIMARY(bond->params.mode) && curr) - count = sprintf(buf, "%s\n", curr->dev->name) + 1; - else - count = sprintf(buf, "\n") + 1; + count = sprintf(buf, "%s\n", curr->dev->name); return count; } @@ -1216,7 +1189,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", @@ -1295,7 +1270,7 @@ static ssize_t bonding_show_mii_status(struct device *d, curr = bond->curr_active_slave; read_unlock(&bond->curr_slave_lock); - return sprintf(buf, "%s\n", (curr) ? "up" : "down") + 1; + return sprintf(buf, "%s\n", (curr) ? "up" : "down"); } static DEVICE_ATTR(mii_status, S_IRUGO, bonding_show_mii_status, NULL); @@ -1312,10 +1287,8 @@ static ssize_t bonding_show_ad_aggregator(struct device *d, if (bond->params.mode == BOND_MODE_8023AD) { struct ad_info ad_info; - count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0 : ad_info.aggregator_id) + 1; + count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0 : ad_info.aggregator_id); } - else - count = sprintf(buf, "\n") + 1; return count; } @@ -1334,10 +1307,8 @@ static ssize_t bonding_show_ad_num_ports(struct device *d, if (bond->params.mode == BOND_MODE_8023AD) { struct ad_info ad_info; - count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0: ad_info.ports) + 1; + count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0: ad_info.ports); } - else - count = sprintf(buf, "\n") + 1; return count; } @@ -1356,10 +1327,8 @@ static ssize_t bonding_show_ad_actor_key(struct device *d, if (bond->params.mode == BOND_MODE_8023AD) { struct ad_info ad_info; - count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0 : ad_info.actor_key) + 1; + count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0 : ad_info.actor_key); } - else - count = sprintf(buf, "\n") + 1; return count; } @@ -1378,10 +1347,8 @@ static ssize_t bonding_show_ad_partner_key(struct device *d, if (bond->params.mode == BOND_MODE_8023AD) { struct ad_info ad_info; - count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0 : ad_info.partner_key) + 1; + count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0 : ad_info.partner_key); } - else - count = sprintf(buf, "\n") + 1; return count; } @@ -1403,12 +1370,9 @@ static ssize_t bonding_show_ad_partner_mac(struct device *d, struct ad_info ad_info; if (!bond_3ad_get_active_agg_info(bond, &ad_info)) { count = sprintf(buf,"%s\n", - print_mac(mac, ad_info.partner_system)) - + 1; + print_mac(mac, ad_info.partner_system)); } } - else - count = sprintf(buf, "\n") + 1; return count; } diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 61c1b4536d3..e1e4734e23c 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -22,8 +22,8 @@ #include "bond_3ad.h" #include "bond_alb.h" -#define DRV_VERSION "3.2.1" -#define DRV_RELDATE "October 15, 2007" +#define DRV_VERSION "3.2.3" +#define DRV_RELDATE "December 6, 2007" #define DRV_NAME "bonding" #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 7df31b5561c..d66915d82b2 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -142,8 +142,8 @@ #define DRV_MODULE_NAME "cassini" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.4" -#define DRV_MODULE_RELDATE "1 July 2004" +#define DRV_MODULE_VERSION "1.5" +#define DRV_MODULE_RELDATE "4 Jan 2008" #define CAS_DEF_MSG_ENABLE \ (NETIF_MSG_DRV | \ @@ -336,30 +336,6 @@ static inline void cas_mask_intr(struct cas *cp) cas_disable_irq(cp, i); } -static inline void cas_buffer_init(cas_page_t *cp) -{ - struct page *page = cp->buffer; - atomic_set((atomic_t *)&page->lru.next, 1); -} - -static inline int cas_buffer_count(cas_page_t *cp) -{ - struct page *page = cp->buffer; - return atomic_read((atomic_t *)&page->lru.next); -} - -static inline void cas_buffer_inc(cas_page_t *cp) -{ - struct page *page = cp->buffer; - atomic_inc((atomic_t *)&page->lru.next); -} - -static inline void cas_buffer_dec(cas_page_t *cp) -{ - struct page *page = cp->buffer; - atomic_dec((atomic_t *)&page->lru.next); -} - static void cas_enable_irq(struct cas *cp, const int ring) { if (ring == 0) { /* all but TX_DONE */ @@ -497,7 +473,6 @@ static int cas_page_free(struct cas *cp, cas_page_t *page) { pci_unmap_page(cp->pdev, page->dma_addr, cp->page_size, PCI_DMA_FROMDEVICE); - cas_buffer_dec(page); __free_pages(page->buffer, cp->page_order); kfree(page); return 0; @@ -527,7 +502,6 @@ static cas_page_t *cas_page_alloc(struct cas *cp, const gfp_t flags) page->buffer = alloc_pages(flags, cp->page_order); if (!page->buffer) goto page_err; - cas_buffer_init(page); page->dma_addr = pci_map_page(cp->pdev, page->buffer, 0, cp->page_size, PCI_DMA_FROMDEVICE); return page; @@ -606,7 +580,7 @@ static void cas_spare_recover(struct cas *cp, const gfp_t flags) list_for_each_safe(elem, tmp, &list) { cas_page_t *page = list_entry(elem, cas_page_t, list); - if (cas_buffer_count(page) > 1) + if (page_count(page->buffer) > 1) continue; list_del(elem); @@ -1374,7 +1348,7 @@ static inline cas_page_t *cas_page_spare(struct cas *cp, const int index) cas_page_t *page = cp->rx_pages[1][index]; cas_page_t *new; - if (cas_buffer_count(page) == 1) + if (page_count(page->buffer) == 1) return page; new = cas_page_dequeue(cp); @@ -1394,7 +1368,7 @@ static cas_page_t *cas_page_swap(struct cas *cp, const int ring, cas_page_t **page1 = cp->rx_pages[1]; /* swap if buffer is in use */ - if (cas_buffer_count(page0[index]) > 1) { + if (page_count(page0[index]->buffer) > 1) { cas_page_t *new = cas_page_spare(cp, index); if (new) { page1[index] = page0[index]; @@ -1979,6 +1953,7 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc, struct cas_page *page; struct sk_buff *skb; void *addr, *crcaddr; + __sum16 csum; char *p; hlen = CAS_VAL(RX_COMP2_HDR_SIZE, words[1]); @@ -2062,10 +2037,10 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc, skb_shinfo(skb)->nr_frags++; skb->data_len += hlen - swivel; + skb->truesize += hlen - swivel; skb->len += hlen - swivel; get_page(page->buffer); - cas_buffer_inc(page); frag->page = page->buffer; frag->page_offset = off; frag->size = hlen - swivel; @@ -2090,7 +2065,6 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc, frag++; get_page(page->buffer); - cas_buffer_inc(page); frag->page = page->buffer; frag->page_offset = 0; frag->size = hlen; @@ -2158,14 +2132,15 @@ end_copy_pkt: skb_put(skb, alloclen); } - i = CAS_VAL(RX_COMP4_TCP_CSUM, words[3]); + csum = (__force __sum16)htons(CAS_VAL(RX_COMP4_TCP_CSUM, words[3])); if (cp->crc_size) { /* checksum includes FCS. strip it out. */ - i = csum_fold(csum_partial(crcaddr, cp->crc_size, i)); + csum = csum_fold(csum_partial(crcaddr, cp->crc_size, + csum_unfold(csum))); if (addr) cas_page_unmap(addr); } - skb->csum = ntohs(i ^ 0xffff); + skb->csum = csum_unfold(~csum); skb->ip_summed = CHECKSUM_COMPLETE; skb->protocol = eth_type_trans(skb, cp->dev); return len; @@ -2253,7 +2228,7 @@ static int cas_post_rxds_ringN(struct cas *cp, int ring, int num) released = 0; while (entry != last) { /* make a new buffer if it's still in use */ - if (cas_buffer_count(page[entry]) > 1) { + if (page_count(page[entry]->buffer) > 1) { cas_page_t *new = cas_page_dequeue(cp); if (!new) { /* let the timer know that we need to @@ -2611,7 +2586,7 @@ static int cas_poll(struct napi_struct *napi, int budget) { struct cas *cp = container_of(napi, struct cas, napi); struct net_device *dev = cp->dev; - int i, enable_intr, todo, credits; + int i, enable_intr, credits; u32 status = readl(cp->regs + REG_INTR_STATUS); unsigned long flags; @@ -4375,7 +4350,7 @@ static int cas_close(struct net_device *dev) struct cas *cp = netdev_priv(dev); #ifdef USE_NAPI - napi_enable(&cp->napi); + napi_disable(&cp->napi); #endif /* Make sure we don't get distracted by suspend/resume */ mutex_lock(&cp->pm_mutex); @@ -4872,6 +4847,90 @@ static int cas_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return rc; } +/* When this chip sits underneath an Intel 31154 bridge, it is the + * only subordinate device and we can tweak the bridge settings to + * reflect that fact. + */ +static void __devinit cas_program_bridge(struct pci_dev *cas_pdev) +{ + struct pci_dev *pdev = cas_pdev->bus->self; + u32 val; + + if (!pdev) + return; + + if (pdev->vendor != 0x8086 || pdev->device != 0x537c) + return; + + /* Clear bit 10 (Bus Parking Control) in the Secondary + * Arbiter Control/Status Register which lives at offset + * 0x41. Using a 32-bit word read/modify/write at 0x40 + * is much simpler so that's how we do this. + */ + pci_read_config_dword(pdev, 0x40, &val); + val &= ~0x00040000; + pci_write_config_dword(pdev, 0x40, val); + + /* Max out the Multi-Transaction Timer settings since + * Cassini is the only device present. + * + * The register is 16-bit and lives at 0x50. When the + * settings are enabled, it extends the GRANT# signal + * for a requestor after a transaction is complete. This + * allows the next request to run without first needing + * to negotiate the GRANT# signal back. + * + * Bits 12:10 define the grant duration: + * + * 1 -- 16 clocks + * 2 -- 32 clocks + * 3 -- 64 clocks + * 4 -- 128 clocks + * 5 -- 256 clocks + * + * All other values are illegal. + * + * Bits 09:00 define which REQ/GNT signal pairs get the + * GRANT# signal treatment. We set them all. + */ + pci_write_config_word(pdev, 0x50, (5 << 10) | 0x3ff); + + /* The Read Prefecth Policy register is 16-bit and sits at + * offset 0x52. It enables a "smart" pre-fetch policy. We + * enable it and max out all of the settings since only one + * device is sitting underneath and thus bandwidth sharing is + * not an issue. + * + * The register has several 3 bit fields, which indicates a + * multiplier applied to the base amount of prefetching the + * chip would do. These fields are at: + * + * 15:13 --- ReRead Primary Bus + * 12:10 --- FirstRead Primary Bus + * 09:07 --- ReRead Secondary Bus + * 06:04 --- FirstRead Secondary Bus + * + * Bits 03:00 control which REQ/GNT pairs the prefetch settings + * get enabled on. Bit 3 is a grouped enabler which controls + * all of the REQ/GNT pairs from [8:3]. Bits 2 to 0 control + * the individual REQ/GNT pairs [2:0]. + */ + pci_write_config_word(pdev, 0x52, + (0x7 << 13) | + (0x7 << 10) | + (0x7 << 7) | + (0x7 << 4) | + (0xf << 0)); + + /* Force cacheline size to 0x8 */ + pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); + + /* Force latency timer to maximum setting so Cassini can + * sit on the bus as long as it likes. + */ + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xff); +} + static int __devinit cas_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -4927,6 +4986,8 @@ static int __devinit cas_init_one(struct pci_dev *pdev, printk(KERN_WARNING PFX "Could not enable MWI for %s\n", pci_name(pdev)); + cas_program_bridge(pdev); + /* * On some architectures, the default cache line size set * by pci_try_set_mwi reduces perforamnce. We have to increase diff --git a/drivers/net/cassini.h b/drivers/net/cassini.h index 2f93f83342d..552af89ca1c 100644 --- a/drivers/net/cassini.h +++ b/drivers/net/cassini.h @@ -4122,8 +4122,8 @@ cas_saturn_patch_t cas_saturn_patch[] = { inserted into outgoing frame. */ struct cas_tx_desc { - u64 control; - u64 buffer; + __le64 control; + __le64 buffer; }; /* descriptor ring for free buffers contains page-sized buffers. the index @@ -4131,8 +4131,8 @@ struct cas_tx_desc { * the completion ring. */ struct cas_rx_desc { - u64 index; - u64 buffer; + __le64 index; + __le64 buffer; }; /* received packets are put on the completion ring. */ @@ -4210,10 +4210,10 @@ struct cas_rx_desc { #define RX_INDEX_RELEASE 0x0000000000002000ULL struct cas_rx_comp { - u64 word1; - u64 word2; - u64 word3; - u64 word4; + __le64 word1; + __le64 word2; + __le64 word3; + __le64 word4; }; enum link_state { @@ -4252,7 +4252,7 @@ struct cas_init_block { struct cas_rx_comp rxcs[N_RX_COMP_RINGS][INIT_BLOCK_RX_COMP]; struct cas_rx_desc rxds[N_RX_DESC_RINGS][INIT_BLOCK_RX_DESC]; struct cas_tx_desc txds[N_TX_RINGS][INIT_BLOCK_TX]; - u64 tx_compwb; + __le64 tx_compwb; }; /* tiny buffers to deal with target abort issue. we allocate a bit diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index 2dbf8dc116c..c5975047c89 100644 --- 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 678778a8d13..2117c4fbb10 100644 --- 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 ffa7e649a6e..b301c0428ae 100644 --- 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 713d9c55f24..cced9dff91c 100644 --- 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 edd6828f0a7..917b7b46f1a 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/cxgb3/regs.h b/drivers/net/cxgb3/regs.h index 5e1bc0dec5f..6e12bf4bc6c 100644 --- a/drivers/net/cxgb3/regs.h +++ b/drivers/net/cxgb3/regs.h @@ -1937,6 +1937,10 @@ #define A_XGM_RXFIFO_CFG 0x884 +#define S_RXFIFO_EMPTY 31 +#define V_RXFIFO_EMPTY(x) ((x) << S_RXFIFO_EMPTY) +#define F_RXFIFO_EMPTY V_RXFIFO_EMPTY(1U) + #define S_RXFIFOPAUSEHWM 17 #define M_RXFIFOPAUSEHWM 0xfff @@ -1961,6 +1965,10 @@ #define A_XGM_TXFIFO_CFG 0x888 +#define S_UNDERUNFIX 22 +#define V_UNDERUNFIX(x) ((x) << S_UNDERUNFIX) +#define F_UNDERUNFIX V_UNDERUNFIX(1U) + #define S_TXIPG 13 #define M_TXIPG 0xff #define V_TXIPG(x) ((x) << S_TXIPG) @@ -2034,10 +2042,27 @@ #define V_XAUIIMP(x) ((x) << S_XAUIIMP) #define A_XGM_RX_MAX_PKT_SIZE 0x8a8 -#define A_XGM_RX_MAX_PKT_SIZE_ERR_CNT 0x9a4 + +#define S_RXMAXFRAMERSIZE 17 +#define M_RXMAXFRAMERSIZE 0x3fff +#define V_RXMAXFRAMERSIZE(x) ((x) << S_RXMAXFRAMERSIZE) +#define G_RXMAXFRAMERSIZE(x) (((x) >> S_RXMAXFRAMERSIZE) & M_RXMAXFRAMERSIZE) + +#define S_RXENFRAMER 14 +#define V_RXENFRAMER(x) ((x) << S_RXENFRAMER) +#define F_RXENFRAMER V_RXENFRAMER(1U) + +#define S_RXMAXPKTSIZE 0 +#define M_RXMAXPKTSIZE 0x3fff +#define V_RXMAXPKTSIZE(x) ((x) << S_RXMAXPKTSIZE) +#define G_RXMAXPKTSIZE(x) (((x) >> S_RXMAXPKTSIZE) & M_RXMAXPKTSIZE) #define A_XGM_RESET_CTRL 0x8ac +#define S_XGMAC_STOP_EN 4 +#define V_XGMAC_STOP_EN(x) ((x) << S_XGMAC_STOP_EN) +#define F_XGMAC_STOP_EN V_XGMAC_STOP_EN(1U) + #define S_XG2G_RESET_ 3 #define V_XG2G_RESET_(x) ((x) << S_XG2G_RESET_) #define F_XG2G_RESET_ V_XG2G_RESET_(1U) diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c index d4ee00d3221..522834c42ae 100644 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c @@ -447,8 +447,8 @@ static const struct adapter_info t3_adap_info[] = { &mi1_mdio_ops, "Chelsio T302"}, {1, 0, 0, 0, F_GPIO1_OEN | F_GPIO6_OEN | F_GPIO7_OEN | F_GPIO10_OEN | - F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, 0, - SUPPORTED_10000baseT_Full | SUPPORTED_AUI, + F_GPIO11_OEN | F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, + 0, SUPPORTED_10000baseT_Full | SUPPORTED_AUI, &mi1_mdio_ext_ops, "Chelsio T310"}, {2, 0, 0, 0, F_GPIO1_OEN | F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO5_OEN | F_GPIO6_OEN | @@ -2613,7 +2613,7 @@ static void __devinit init_mtus(unsigned short mtus[]) * it can accomodate max size TCP/IP headers when SACK and timestamps * are enabled and still have at least 8 bytes of payload. */ - mtus[1] = 88; + mtus[0] = 88; mtus[1] = 88; mtus[2] = 256; mtus[3] = 512; diff --git a/drivers/net/cxgb3/xgmac.c b/drivers/net/cxgb3/xgmac.c index eeb766aeced..efcf09a709c 100644 --- a/drivers/net/cxgb3/xgmac.c +++ b/drivers/net/cxgb3/xgmac.c @@ -106,6 +106,7 @@ int t3_mac_reset(struct cmac *mac) t3_set_reg_field(adap, A_XGM_RXFIFO_CFG + oft, F_RXSTRFRWRD | F_DISERRFRAMES, uses_xaui(adap) ? 0 : F_RXSTRFRWRD); + t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + oft, 0, F_UNDERUNFIX); if (uses_xaui(adap)) { if (adap->params.rev == 0) { @@ -124,7 +125,11 @@ int t3_mac_reset(struct cmac *mac) xaui_serdes_reset(mac); } - val = F_MAC_RESET_; + t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + oft, + V_RXMAXFRAMERSIZE(M_RXMAXFRAMERSIZE), + V_RXMAXFRAMERSIZE(MAX_FRAME_SIZE) | F_RXENFRAMER); + val = F_MAC_RESET_ | F_XGMAC_STOP_EN; + if (is_10G(adap)) val |= F_PCS_RESET_; else if (uses_xaui(adap)) @@ -313,8 +318,9 @@ static int rx_fifo_hwm(int mtu) int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu) { - int hwm, lwm; - unsigned int thres, v; + int hwm, lwm, divisor; + int ipg; + unsigned int thres, v, reg; struct adapter *adap = mac->adapter; /* @@ -335,27 +341,32 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu) hwm = min(hwm, MAC_RXFIFO_SIZE - 8192); lwm = min(3 * (int)mtu, MAC_RXFIFO_SIZE / 4); - if (adap->params.rev == T3_REV_B2 && + if (adap->params.rev >= T3_REV_B2 && (t3_read_reg(adap, A_XGM_RX_CTRL + mac->offset) & F_RXEN)) { disable_exact_filters(mac); v = t3_read_reg(adap, A_XGM_RX_CFG + mac->offset); t3_set_reg_field(adap, A_XGM_RX_CFG + mac->offset, F_ENHASHMCAST | F_COPYALLFRAMES, F_DISBCAST); - /* drain rx FIFO */ - if (t3_wait_op_done(adap, - A_XGM_RX_MAX_PKT_SIZE_ERR_CNT + - mac->offset, - 1 << 31, 1, 20, 5)) { + reg = adap->params.rev == T3_REV_B2 ? + A_XGM_RX_MAX_PKT_SIZE_ERR_CNT : A_XGM_RXFIFO_CFG; + + /* drain RX FIFO */ + if (t3_wait_op_done(adap, reg + mac->offset, + F_RXFIFO_EMPTY, 1, 20, 5)) { t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v); enable_exact_filters(mac); return -EIO; } - t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, mtu); + t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, + V_RXMAXPKTSIZE(M_RXMAXPKTSIZE), + V_RXMAXPKTSIZE(mtu)); t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v); enable_exact_filters(mac); } else - t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, mtu); + t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, + V_RXMAXPKTSIZE(M_RXMAXPKTSIZE), + V_RXMAXPKTSIZE(mtu)); /* * Adjust the PAUSE frame watermarks. We always set the LWM, and the @@ -379,13 +390,16 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu) thres /= 10; thres = mtu > thres ? (mtu - thres + 7) / 8 : 0; thres = max(thres, 8U); /* need at least 8 */ + ipg = (adap->params.rev == T3_REV_C) ? 0 : 1; t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + mac->offset, V_TXFIFOTHRESH(M_TXFIFOTHRESH) | V_TXIPG(M_TXIPG), - V_TXFIFOTHRESH(thres) | V_TXIPG(1)); + V_TXFIFOTHRESH(thres) | V_TXIPG(ipg)); - if (adap->params.rev > 0) + if (adap->params.rev > 0) { + divisor = (adap->params.rev == T3_REV_C) ? 64 : 8; t3_write_reg(adap, A_XGM_PAUSE_TIMER + mac->offset, - (hwm - lwm) * 4 / 8); + (hwm - lwm) * 4 / divisor); + } t3_write_reg(adap, A_XGM_TX_PAUSE_QUANTA + mac->offset, MAC_RXFIFO_SIZE * 4 * 8 / 512); return 0; @@ -522,7 +536,7 @@ int t3b2_mac_watchdog_task(struct cmac *mac) goto rxcheck; } - if ((tx_tcnt != mac->tx_tcnt) && (mac->tx_xcnt == 0)) { + if ((tx_tcnt != mac->tx_tcnt) && (mac->tx_xcnt == 0)) { if (mac->toggle_cnt > 4) { status = 2; goto out; diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c index 5066beb2e7b..47cce9cad30 100644 --- a/drivers/net/dl2k.c +++ b/drivers/net/dl2k.c @@ -332,7 +332,7 @@ parse_eeprom (struct net_device *dev) #endif /* Read eeprom */ for (i = 0; i < 128; i++) { - ((u16 *) sromdata)[i] = le16_to_cpu (read_eeprom (ioaddr, i)); + ((__le16 *) sromdata)[i] = cpu_to_le16(read_eeprom (ioaddr, i)); } #ifdef MEM_MAPPING ioaddr = dev->base_addr; @@ -516,7 +516,7 @@ rio_timer (unsigned long data) PCI_DMA_FROMDEVICE)); } np->rx_ring[entry].fraginfo |= - cpu_to_le64 (np->rx_buf_sz) << 48; + cpu_to_le64((u64)np->rx_buf_sz << 48); np->rx_ring[entry].status = 0; } /* end for */ } /* end if */ @@ -584,11 +584,11 @@ alloc_list (struct net_device *dev) cpu_to_le64 ( pci_map_single ( np->pdev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE)); - np->rx_ring[i].fraginfo |= cpu_to_le64 (np->rx_buf_sz) << 48; + np->rx_ring[i].fraginfo |= cpu_to_le64((u64)np->rx_buf_sz << 48); } /* Set RFDListPtr */ - writel (cpu_to_le32 (np->rx_ring_dma), dev->base_addr + RFDListPtr0); + writel (np->rx_ring_dma, dev->base_addr + RFDListPtr0); writel (0, dev->base_addr + RFDListPtr1); return; @@ -620,15 +620,14 @@ start_xmit (struct sk_buff *skb, struct net_device *dev) } #endif if (np->vlan) { - tfc_vlan_tag = - cpu_to_le64 (VLANTagInsert) | - (cpu_to_le64 (np->vlan) << 32) | - (cpu_to_le64 (skb->priority) << 45); + tfc_vlan_tag = VLANTagInsert | + ((u64)np->vlan << 32) | + ((u64)skb->priority << 45); } txdesc->fraginfo = cpu_to_le64 (pci_map_single (np->pdev, skb->data, skb->len, PCI_DMA_TODEVICE)); - txdesc->fraginfo |= cpu_to_le64 (skb->len) << 48; + txdesc->fraginfo |= cpu_to_le64((u64)skb->len << 48); /* DL2K bug: DMA fails to get next descriptor ptr in 10Mbps mode * Work around: Always use 1 descriptor in 10Mbps mode */ @@ -708,6 +707,11 @@ rio_interrupt (int irq, void *dev_instance) return IRQ_RETVAL(handled); } +static inline dma_addr_t desc_to_dma(struct netdev_desc *desc) +{ + return le64_to_cpu(desc->fraginfo) & DMA_48BIT_MASK; +} + static void rio_free_tx (struct net_device *dev, int irq) { @@ -725,11 +729,11 @@ rio_free_tx (struct net_device *dev, int irq) while (entry != np->cur_tx) { struct sk_buff *skb; - if (!(np->tx_ring[entry].status & TFDDone)) + if (!(np->tx_ring[entry].status & cpu_to_le64(TFDDone))) break; skb = np->tx_skbuff[entry]; pci_unmap_single (np->pdev, - np->tx_ring[entry].fraginfo & DMA_48BIT_MASK, + desc_to_dma(&np->tx_ring[entry]), skb->len, PCI_DMA_TODEVICE); if (irq) dev_kfree_skb_irq (skb); @@ -831,13 +835,14 @@ receive_packet (struct net_device *dev) int pkt_len; u64 frame_status; - if (!(desc->status & RFDDone) || - !(desc->status & FrameStart) || !(desc->status & FrameEnd)) + if (!(desc->status & cpu_to_le64(RFDDone)) || + !(desc->status & cpu_to_le64(FrameStart)) || + !(desc->status & cpu_to_le64(FrameEnd))) break; /* Chip omits the CRC. */ - pkt_len = le64_to_cpu (desc->status & 0xffff); - frame_status = le64_to_cpu (desc->status); + frame_status = le64_to_cpu(desc->status); + pkt_len = frame_status & 0xffff; if (--cnt < 0) break; /* Update rx error statistics, drop packet. */ @@ -857,15 +862,14 @@ receive_packet (struct net_device *dev) /* Small skbuffs for short packets */ if (pkt_len > copy_thresh) { pci_unmap_single (np->pdev, - desc->fraginfo & DMA_48BIT_MASK, + desc_to_dma(desc), np->rx_buf_sz, PCI_DMA_FROMDEVICE); skb_put (skb = np->rx_skbuff[entry], pkt_len); np->rx_skbuff[entry] = NULL; } else if ((skb = dev_alloc_skb (pkt_len + 2)) != NULL) { pci_dma_sync_single_for_cpu(np->pdev, - desc->fraginfo & - DMA_48BIT_MASK, + desc_to_dma(desc), np->rx_buf_sz, PCI_DMA_FROMDEVICE); /* 16 byte align the IP header */ @@ -875,8 +879,7 @@ receive_packet (struct net_device *dev) pkt_len); skb_put (skb, pkt_len); pci_dma_sync_single_for_device(np->pdev, - desc->fraginfo & - DMA_48BIT_MASK, + desc_to_dma(desc), np->rx_buf_sz, PCI_DMA_FROMDEVICE); } @@ -919,7 +922,7 @@ receive_packet (struct net_device *dev) PCI_DMA_FROMDEVICE)); } np->rx_ring[entry].fraginfo |= - cpu_to_le64 (np->rx_buf_sz) << 48; + cpu_to_le64((u64)np->rx_buf_sz << 48); np->rx_ring[entry].status = 0; entry = (entry + 1) % RX_RING_SIZE; } @@ -1121,7 +1124,7 @@ set_multicast (struct net_device *dev) hash_table[0] = hash_table[1] = 0; /* RxFlowcontrol DA: 01-80-C2-00-00-01. Hash index=0x39 */ - hash_table[1] |= cpu_to_le32(0x02000000); + hash_table[1] |= 0x02000000; if (dev->flags & IFF_PROMISC) { /* Receive all frames promiscuously. */ rx_mode = ReceiveAllFrames; @@ -1762,7 +1765,7 @@ rio_close (struct net_device *dev) skb = np->rx_skbuff[i]; if (skb) { pci_unmap_single(np->pdev, - np->rx_ring[i].fraginfo & DMA_48BIT_MASK, + desc_to_dma(&np->rx_ring[i]), skb->len, PCI_DMA_FROMDEVICE); dev_kfree_skb (skb); np->rx_skbuff[i] = NULL; @@ -1772,7 +1775,7 @@ rio_close (struct net_device *dev) skb = np->tx_skbuff[i]; if (skb) { pci_unmap_single(np->pdev, - np->tx_ring[i].fraginfo & DMA_48BIT_MASK, + desc_to_dma(&np->tx_ring[i]), skb->len, PCI_DMA_TODEVICE); dev_kfree_skb (skb); np->tx_skbuff[i] = NULL; diff --git a/drivers/net/dl2k.h b/drivers/net/dl2k.h index 5b801775f42..014b77ce96d 100644 --- a/drivers/net/dl2k.h +++ b/drivers/net/dl2k.h @@ -633,9 +633,9 @@ struct mii_data { /* The Rx and Tx buffer descriptors. */ struct netdev_desc { - u64 next_desc; - u64 status; - u64 fraginfo; + __le64 next_desc; + __le64 status; + __le64 fraginfo; }; #define PRIV_ALIGN 15 /* Required alignment mask */ diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 3dbaec680b4..b87402bc830 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1991,13 +1991,12 @@ static int e100_poll(struct napi_struct *napi, int budget) struct nic *nic = container_of(napi, struct nic, napi); struct net_device *netdev = nic->netdev; unsigned int work_done = 0; - int tx_cleaned; e100_rx_clean(nic, &work_done, budget); - tx_cleaned = e100_tx_clean(nic); + e100_tx_clean(nic); - /* If no Rx and Tx cleanup work was done, exit polling mode. */ - if((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) { + /* If budget not fully consumed, exit the polling mode */ + if (work_done < budget) { netif_rx_complete(netdev, napi); e100_enable_irq(nic); } @@ -2214,13 +2213,11 @@ static void e100_get_drvinfo(struct net_device *netdev, strcpy(info->bus_info, pci_name(nic->pdev)); } +#define E100_PHY_REGS 0x1C static int e100_get_regs_len(struct net_device *netdev) { struct nic *nic = netdev_priv(netdev); -#define E100_PHY_REGS 0x1C -#define E100_REGS_LEN 1 + E100_PHY_REGS + \ - sizeof(nic->mem->dump_buf) / sizeof(u32) - return E100_REGS_LEN * sizeof(u32); + return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf); } static void e100_get_regs(struct net_device *netdev, @@ -2739,8 +2736,9 @@ static int e100_suspend(struct pci_dev *pdev, pm_message_t state) pci_enable_wake(pdev, PCI_D3cold, 0); } - pci_disable_device(pdev); free_irq(pdev->irq, netdev); + + pci_disable_device(pdev); pci_set_power_state(pdev, PCI_D3hot); return 0; @@ -2782,6 +2780,8 @@ static void e100_shutdown(struct pci_dev *pdev) pci_enable_wake(pdev, PCI_D3cold, 0); } + free_irq(pdev->irq, netdev); + pci_disable_device(pdev); pci_set_power_state(pdev, PCI_D3hot); } diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 781ed996848..3b840283a9c 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -351,4 +351,12 @@ enum e1000_state_t { __E1000_DOWN }; +extern char e1000_driver_name[]; +extern const char e1000_driver_version[]; + +extern void e1000_power_up_phy(struct e1000_adapter *); +extern void e1000_set_ethtool_ops(struct net_device *netdev); +extern void e1000_check_options(struct e1000_adapter *adapter); + + #endif /* _E1000_H_ */ diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 6c9a643426f..b83ccce8a9b 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -32,9 +32,6 @@ #include <asm/uaccess.h> -extern char e1000_driver_name[]; -extern char e1000_driver_version[]; - extern int e1000_up(struct e1000_adapter *adapter); extern void e1000_down(struct e1000_adapter *adapter); extern void e1000_reinit_locked(struct e1000_adapter *adapter); @@ -733,16 +730,16 @@ err_setup: #define REG_PATTERN_TEST(R, M, W) \ { \ - uint32_t pat, value; \ - uint32_t test[] = \ + uint32_t pat, val; \ + const uint32_t test[] = \ {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; \ - for (pat = 0; pat < ARRAY_SIZE(test); pat++) { \ + for (pat = 0; pat < ARRAY_SIZE(test); pat++) { \ E1000_WRITE_REG(&adapter->hw, R, (test[pat] & W)); \ - value = E1000_READ_REG(&adapter->hw, R); \ - if (value != (test[pat] & W & M)) { \ + val = E1000_READ_REG(&adapter->hw, R); \ + if (val != (test[pat] & W & M)) { \ DPRINTK(DRV, ERR, "pattern test reg %04X failed: got " \ "0x%08X expected 0x%08X\n", \ - E1000_##R, value, (test[pat] & W & M)); \ + E1000_##R, val, (test[pat] & W & M)); \ *data = (adapter->hw.mac_type < e1000_82543) ? \ E1000_82542_##R : E1000_##R; \ return 1; \ @@ -752,12 +749,12 @@ err_setup: #define REG_SET_AND_CHECK(R, M, W) \ { \ - uint32_t value; \ + uint32_t val; \ E1000_WRITE_REG(&adapter->hw, R, W & M); \ - value = E1000_READ_REG(&adapter->hw, R); \ - if ((W & M) != (value & M)) { \ + val = E1000_READ_REG(&adapter->hw, R); \ + if ((W & M) != (val & M)) { \ DPRINTK(DRV, ERR, "set/check reg %04X test failed: got 0x%08X "\ - "expected 0x%08X\n", E1000_##R, (value & M), (W & M)); \ + "expected 0x%08X\n", E1000_##R, (val & M), (W & M)); \ *data = (adapter->hw.mac_type < e1000_82543) ? \ E1000_82542_##R : E1000_##R; \ return 1; \ @@ -1621,8 +1618,6 @@ e1000_get_sset_count(struct net_device *netdev, int sset) } } -extern void e1000_power_up_phy(struct e1000_adapter *); - static void e1000_diag_test(struct net_device *netdev, struct ethtool_test *eth_test, uint64_t *data) @@ -1859,8 +1854,8 @@ e1000_phys_id(struct net_device *netdev, uint32_t data) { struct e1000_adapter *adapter = netdev_priv(netdev); - if (!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ); + if (!data) + data = INT_MAX; if (adapter->hw.mac_type < e1000_82571) { if (!adapter->blink_timer.function) { @@ -1928,7 +1923,7 @@ e1000_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data) switch (stringset) { case ETH_SS_TEST: memcpy(data, *e1000_gstrings_test, - E1000_TEST_LEN*ETH_GSTRING_LEN); + sizeof(e1000_gstrings_test)); break; case ETH_SS_STATS: for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 8fa0fe4009d..7c6888c58c2 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -8607,7 +8607,7 @@ e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index, DEBUGFUNC("e1000_read_ich8_data"); - if (size < 1 || size > 2 || data == 0x0 || + if (size < 1 || size > 2 || data == NULL || index > ICH_FLASH_LINEAR_ADDR_MASK) return error; @@ -8841,7 +8841,7 @@ e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t *data) * amount of NVM used in each bank is a *minimum* of 4 KBytes, but in fact the * bank size may be 4, 8 or 64 KBytes *****************************************************************************/ -int32_t +static int32_t e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t bank) { union ich8_hws_flash_status hsfsts; diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index f1ce348470c..0c9a6f7104d 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -37,8 +37,8 @@ static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; #define DRIVERNAPI "-NAPI" #endif #define DRV_VERSION "7.3.20-k2"DRIVERNAPI -char e1000_driver_version[] = DRV_VERSION; -static char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation."; +const char e1000_driver_version[] = DRV_VERSION; +static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation."; /* e1000_pci_tbl - PCI Device ID Table * @@ -188,7 +188,6 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); -void e1000_set_ethtool_ops(struct net_device *netdev); static void e1000_enter_82542_rst(struct e1000_adapter *adapter); static void e1000_leave_82542_rst(struct e1000_adapter *adapter); static void e1000_tx_timeout(struct net_device *dev); @@ -213,8 +212,6 @@ static void e1000_shutdown(struct pci_dev *pdev); static void e1000_netpoll (struct net_device *netdev); #endif -extern void e1000_check_options(struct e1000_adapter *adapter); - #define COPYBREAK_DEFAULT 256 static unsigned int copybreak __read_mostly = COPYBREAK_DEFAULT; module_param(copybreak, uint, 0644); @@ -3927,27 +3924,24 @@ e1000_clean(struct napi_struct *napi, int budget) /* Must NOT use netdev_priv macro here. */ adapter = poll_dev->priv; - /* Keep link state information with original netdev */ - if (!netif_carrier_ok(poll_dev)) - goto quit_polling; - /* e1000_clean is called per-cpu. This lock protects * tx_ring[0] from being cleaned by multiple cpus * simultaneously. A failure obtaining the lock means * tx_ring[0] is currently being cleaned anyway. */ if (spin_trylock(&adapter->tx_queue_lock)) { tx_cleaned = e1000_clean_tx_irq(adapter, - &adapter->tx_ring[0]); + &adapter->tx_ring[0]); spin_unlock(&adapter->tx_queue_lock); } adapter->clean_rx(adapter, &adapter->rx_ring[0], &work_done, budget); - /* If no Tx and not enough Rx work done, exit the polling mode */ - if ((!tx_cleaned && (work_done < budget)) || - !netif_running(poll_dev)) { -quit_polling: + if (tx_cleaned) + work_done = budget; + + /* If budget not fully consumed, exit the polling mode */ + if (work_done < budget) { if (likely(adapter->itr_setting & 3)) e1000_set_itr(adapter); netif_rx_complete(poll_dev, napi); @@ -4807,6 +4801,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: @@ -4827,12 +4822,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); @@ -4841,11 +4832,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 { @@ -4860,7 +4848,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/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c index f485874a63f..e6565ce686b 100644 --- a/drivers/net/e1000/e1000_param.c +++ b/drivers/net/e1000/e1000_param.c @@ -46,7 +46,7 @@ #define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET } #define E1000_PARAM(X, desc) \ static int __devinitdata X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \ - static int num_##X = 0; \ + static unsigned int num_##X; \ module_param_array_named(X, X, int, &num_##X, 0); \ MODULE_PARM_DESC(X, desc); @@ -198,9 +198,9 @@ E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround"); struct e1000_option { enum { enable_option, range_option, list_option } type; - char *name; - char *err; - int def; + const char *name; + const char *err; + int def; union { struct { /* range_option info */ int min; @@ -214,8 +214,9 @@ struct e1000_option { }; static int __devinit -e1000_validate_option(int *value, struct e1000_option *opt, - struct e1000_adapter *adapter) +e1000_validate_option(unsigned int *value, + const struct e1000_option *opt, + struct e1000_adapter *adapter) { if (*value == OPTION_UNSET) { *value = opt->def; @@ -348,7 +349,7 @@ e1000_check_options(struct e1000_adapter *adapter) }; if (num_XsumRX > bd) { - int rx_csum = XsumRX[bd]; + unsigned int rx_csum = XsumRX[bd]; e1000_validate_option(&rx_csum, &opt, adapter); adapter->rx_csum = rx_csum; } else { @@ -374,7 +375,7 @@ e1000_check_options(struct e1000_adapter *adapter) }; if (num_FlowControl > bd) { - int fc = FlowControl[bd]; + unsigned int fc = FlowControl[bd]; e1000_validate_option(&fc, &opt, adapter); adapter->hw.fc = adapter->hw.original_fc = fc; } else { @@ -506,7 +507,7 @@ e1000_check_options(struct e1000_adapter *adapter) }; if (num_SmartPowerDownEnable > bd) { - int spd = SmartPowerDownEnable[bd]; + unsigned int spd = SmartPowerDownEnable[bd]; e1000_validate_option(&spd, &opt, adapter); adapter->smart_power_down = spd; } else { @@ -522,7 +523,7 @@ e1000_check_options(struct e1000_adapter *adapter) }; if (num_KumeranLockLoss > bd) { - int kmrn_lock_loss = KumeranLockLoss[bd]; + unsigned int kmrn_lock_loss = KumeranLockLoss[bd]; e1000_validate_option(&kmrn_lock_loss, &opt, adapter); adapter->hw.kmrn_lock_loss_workaround_disabled = !kmrn_lock_loss; } else { @@ -581,7 +582,7 @@ e1000_check_fiber_options(struct e1000_adapter *adapter) static void __devinit e1000_check_copper_options(struct e1000_adapter *adapter) { - int speed, dplx, an; + unsigned int speed, dplx, an; int bd = adapter->bd_number; { /* Speed */ diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index cf70522fc85..14141a55eaa 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -283,7 +283,7 @@ static s32 e1000_get_invariants_82571(struct e1000_adapter *adapter) adapter->flags &= ~FLAG_HAS_WOL; /* quad ports only support WoL on port A */ if (adapter->flags & FLAG_IS_QUAD_PORT && - (!adapter->flags & FLAG_IS_QUAD_PORT_A)) + (!(adapter->flags & FLAG_IS_QUAD_PORT_A))) adapter->flags &= ~FLAG_HAS_WOL; break; diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index d2499bb07c1..473f78de4be 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -122,7 +122,8 @@ struct e1000_buffer { u16 next_to_watch; }; /* RX */ - struct page *page; + /* arrays of page information for packet split */ + struct e1000_ps_page *ps_pages; }; }; @@ -142,8 +143,6 @@ struct e1000_ring { /* array of buffer information structs */ struct e1000_buffer *buffer_info; - /* arrays of page information for packet split */ - struct e1000_ps_page *ps_pages; struct sk_buff *rx_skb_top; struct e1000_queue_stats stats; diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index 0666e62e9ad..87f9da1b6b4 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -1680,8 +1680,8 @@ static int e1000_phys_id(struct net_device *netdev, u32 data) { struct e1000_adapter *adapter = netdev_priv(netdev); - if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); + if (!data) + data = INT_MAX; if (adapter->hw.phy.type == e1000_phy_ife) { if (!adapter->blink_timer.function) { @@ -1739,7 +1739,7 @@ static void e1000_get_strings(struct net_device *netdev, u32 stringset, switch (stringset) { case ETH_SS_TEST: memcpy(data, *e1000_gstrings_test, - E1000_TEST_LEN*ETH_GSTRING_LEN); + sizeof(e1000_gstrings_test)); break; case ETH_SS_STATS: for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 033e124d1c1..2ab3bfbb8a6 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -245,37 +245,36 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, rx_desc = E1000_RX_DESC_PS(*rx_ring, i); for (j = 0; j < PS_PAGE_BUFFERS; j++) { - ps_page = &rx_ring->ps_pages[(i * PS_PAGE_BUFFERS) - + j]; - if (j < adapter->rx_ps_pages) { + ps_page = &buffer_info->ps_pages[j]; + if (j >= adapter->rx_ps_pages) { + /* all unused desc entries get hw null ptr */ + rx_desc->read.buffer_addr[j+1] = ~0; + continue; + } + if (!ps_page->page) { + ps_page->page = alloc_page(GFP_ATOMIC); if (!ps_page->page) { - ps_page->page = alloc_page(GFP_ATOMIC); - if (!ps_page->page) { - adapter->alloc_rx_buff_failed++; - goto no_buffers; - } - ps_page->dma = pci_map_page(pdev, - ps_page->page, - 0, PAGE_SIZE, - PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error( - ps_page->dma)) { - dev_err(&adapter->pdev->dev, - "RX DMA page map failed\n"); - adapter->rx_dma_failed++; - goto no_buffers; - } + adapter->alloc_rx_buff_failed++; + goto no_buffers; + } + ps_page->dma = pci_map_page(pdev, + ps_page->page, + 0, PAGE_SIZE, + PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(ps_page->dma)) { + dev_err(&adapter->pdev->dev, + "RX DMA page map failed\n"); + adapter->rx_dma_failed++; + goto no_buffers; } - /* - * Refresh the desc even if buffer_addrs - * didn't change because each write-back - * erases this info. - */ - rx_desc->read.buffer_addr[j+1] = - cpu_to_le64(ps_page->dma); - } else { - rx_desc->read.buffer_addr[j+1] = ~0; } + /* + * Refresh the desc even if buffer_addrs + * didn't change because each write-back + * erases this info. + */ + rx_desc->read.buffer_addr[j+1] = + cpu_to_le64(ps_page->dma); } skb = netdev_alloc_skb(netdev, @@ -334,94 +333,6 @@ no_buffers: } /** - * e1000_alloc_rx_buffers_jumbo - Replace used jumbo receive buffers - * - * @adapter: address of board private structure - * @cleaned_count: number of buffers to allocate this pass - **/ -static void e1000_alloc_rx_buffers_jumbo(struct e1000_adapter *adapter, - int cleaned_count) -{ - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - struct e1000_ring *rx_ring = adapter->rx_ring; - struct e1000_rx_desc *rx_desc; - struct e1000_buffer *buffer_info; - struct sk_buff *skb; - unsigned int i; - unsigned int bufsz = 256 - - 16 /*for skb_reserve */ - - NET_IP_ALIGN; - - i = rx_ring->next_to_use; - buffer_info = &rx_ring->buffer_info[i]; - - while (cleaned_count--) { - skb = buffer_info->skb; - if (skb) { - skb_trim(skb, 0); - goto check_page; - } - - skb = netdev_alloc_skb(netdev, bufsz); - if (!skb) { - /* Better luck next round */ - adapter->alloc_rx_buff_failed++; - break; - } - - /* Make buffer alignment 2 beyond a 16 byte boundary - * this will result in a 16 byte aligned IP header after - * the 14 byte MAC header is removed - */ - skb_reserve(skb, NET_IP_ALIGN); - - buffer_info->skb = skb; -check_page: - /* allocate a new page if necessary */ - if (!buffer_info->page) { - buffer_info->page = alloc_page(GFP_ATOMIC); - if (!buffer_info->page) { - adapter->alloc_rx_buff_failed++; - break; - } - } - - if (!buffer_info->dma) - buffer_info->dma = pci_map_page(pdev, - buffer_info->page, 0, - PAGE_SIZE, - PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(buffer_info->dma)) { - dev_err(&adapter->pdev->dev, "RX DMA page map failed\n"); - adapter->rx_dma_failed++; - break; - } - - rx_desc = E1000_RX_DESC(*rx_ring, i); - rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); - - i++; - if (i == rx_ring->count) - i = 0; - buffer_info = &rx_ring->buffer_info[i]; - } - - if (rx_ring->next_to_use != i) { - rx_ring->next_to_use = i; - if (i-- == 0) - i = (rx_ring->count - 1); - - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). */ - wmb(); - writel(i, adapter->hw.hw_addr + rx_ring->tail); - } -} - -/** * e1000_clean_rx_irq - Send received data up the network stack; legacy * @adapter: board private structure * @@ -495,10 +406,6 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, goto next_desc; } - /* adjust length to remove Ethernet CRC */ - length -= 4; - - /* probably a little skewed due to removing CRC */ total_rx_bytes += length; total_rx_packets++; @@ -554,15 +461,6 @@ next_desc: return cleaned; } -static void e1000_consume_page(struct e1000_buffer *bi, struct sk_buff *skb, - u16 length) -{ - bi->page = NULL; - skb->len += length; - skb->data_len += length; - skb->truesize += length; -} - static void e1000_put_txbuf(struct e1000_adapter *adapter, struct e1000_buffer *buffer_info) { @@ -699,174 +597,6 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) } /** - * e1000_clean_rx_irq_jumbo - Send received data up the network stack; legacy - * @adapter: board private structure - * - * the return value indicates whether actual cleaning was done, there - * is no guarantee that everything was cleaned - **/ -static bool e1000_clean_rx_irq_jumbo(struct e1000_adapter *adapter, - int *work_done, int work_to_do) -{ - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - struct e1000_ring *rx_ring = adapter->rx_ring; - struct e1000_rx_desc *rx_desc, *next_rxd; - struct e1000_buffer *buffer_info, *next_buffer; - u32 length; - unsigned int i; - int cleaned_count = 0; - bool cleaned = 0; - unsigned int total_rx_bytes = 0, total_rx_packets = 0; - - i = rx_ring->next_to_clean; - rx_desc = E1000_RX_DESC(*rx_ring, i); - buffer_info = &rx_ring->buffer_info[i]; - - while (rx_desc->status & E1000_RXD_STAT_DD) { - struct sk_buff *skb; - u8 status; - - if (*work_done >= work_to_do) - break; - (*work_done)++; - - status = rx_desc->status; - skb = buffer_info->skb; - buffer_info->skb = NULL; - - i++; - if (i == rx_ring->count) - i = 0; - next_rxd = E1000_RX_DESC(*rx_ring, i); - prefetch(next_rxd); - - next_buffer = &rx_ring->buffer_info[i]; - - cleaned = 1; - cleaned_count++; - pci_unmap_page(pdev, - buffer_info->dma, - PAGE_SIZE, - PCI_DMA_FROMDEVICE); - buffer_info->dma = 0; - - length = le16_to_cpu(rx_desc->length); - - /* errors is only valid for DD + EOP descriptors */ - if ((status & E1000_RXD_STAT_EOP) && - (rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) { - /* recycle both page and skb */ - buffer_info->skb = skb; - /* an error means any chain goes out the window too */ - if (rx_ring->rx_skb_top) - dev_kfree_skb(rx_ring->rx_skb_top); - rx_ring->rx_skb_top = NULL; - goto next_desc; - } - -#define rxtop rx_ring->rx_skb_top - if (!(status & E1000_RXD_STAT_EOP)) { - /* this descriptor is only the beginning (or middle) */ - if (!rxtop) { - /* this is the beginning of a chain */ - rxtop = skb; - skb_fill_page_desc(rxtop, 0, buffer_info->page, - 0, length); - } else { - /* this is the middle of a chain */ - skb_fill_page_desc(rxtop, - skb_shinfo(rxtop)->nr_frags, - buffer_info->page, 0, - length); - /* re-use the skb, only consumed the page */ - buffer_info->skb = skb; - } - e1000_consume_page(buffer_info, rxtop, length); - goto next_desc; - } else { - if (rxtop) { - /* end of the chain */ - skb_fill_page_desc(rxtop, - skb_shinfo(rxtop)->nr_frags, - buffer_info->page, 0, length); - /* re-use the current skb, we only consumed the - * page */ - buffer_info->skb = skb; - skb = rxtop; - rxtop = NULL; - e1000_consume_page(buffer_info, skb, length); - } else { - /* no chain, got EOP, this buf is the packet - * copybreak to save the put_page/alloc_page */ - if (length <= copybreak && - skb_tailroom(skb) >= length) { - u8 *vaddr; - vaddr = kmap_atomic(buffer_info->page, - KM_SKB_DATA_SOFTIRQ); - memcpy(skb_tail_pointer(skb), - vaddr, length); - kunmap_atomic(vaddr, - KM_SKB_DATA_SOFTIRQ); - /* re-use the page, so don't erase - * buffer_info->page */ - skb_put(skb, length); - } else { - skb_fill_page_desc(skb, 0, - buffer_info->page, 0, - length); - e1000_consume_page(buffer_info, skb, - length); - } - } - } - - /* Receive Checksum Offload XXX recompute due to CRC strip? */ - e1000_rx_checksum(adapter, - (u32)(status) | - ((u32)(rx_desc->errors) << 24), - le16_to_cpu(rx_desc->csum), skb); - - pskb_trim(skb, skb->len - 4); - - /* probably a little skewed due to removing CRC */ - total_rx_bytes += skb->len; - total_rx_packets++; - - /* eth type trans needs skb->data to point to something */ - if (!pskb_may_pull(skb, ETH_HLEN)) { - ndev_err(netdev, "__pskb_pull_tail failed.\n"); - dev_kfree_skb(skb); - goto next_desc; - } - - e1000_receive_skb(adapter, netdev, skb,status,rx_desc->special); - -next_desc: - rx_desc->status = 0; - - /* return some buffers to hardware, one at a time is too slow */ - if (cleaned_count >= E1000_RX_BUFFER_WRITE) { - adapter->alloc_rx_buf(adapter, cleaned_count); - cleaned_count = 0; - } - - /* use prefetched values */ - rx_desc = next_rxd; - buffer_info = next_buffer; - } - rx_ring->next_to_clean = i; - - cleaned_count = e1000_desc_unused(rx_ring); - if (cleaned_count) - adapter->alloc_rx_buf(adapter, cleaned_count); - - adapter->total_rx_packets += total_rx_packets; - adapter->total_rx_bytes += total_rx_bytes; - return cleaned; -} - -/** * e1000_clean_rx_irq_ps - Send received data up the network stack; packet split * @adapter: board private structure * @@ -953,7 +683,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, ((length + l1) <= adapter->rx_ps_bsize0)) { u8 *vaddr; - ps_page = &rx_ring->ps_pages[i * PS_PAGE_BUFFERS]; + ps_page = &buffer_info->ps_pages[0]; /* there is no documentation about how to call * kmap_atomic, so we can't hold the mapping @@ -965,8 +695,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, kunmap_atomic(vaddr, KM_SKB_DATA_SOFTIRQ); pci_dma_sync_single_for_device(pdev, ps_page->dma, PAGE_SIZE, PCI_DMA_FROMDEVICE); - /* remove the CRC */ - l1 -= 4; + skb_put(skb, l1); goto copydone; } /* if */ @@ -977,7 +706,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, if (!length) break; - ps_page = &rx_ring->ps_pages[(i * PS_PAGE_BUFFERS) + j]; + ps_page = &buffer_info->ps_pages[j]; pci_unmap_page(pdev, ps_page->dma, PAGE_SIZE, PCI_DMA_FROMDEVICE); ps_page->dma = 0; @@ -988,10 +717,6 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, skb->truesize += length; } - /* strip the ethernet crc, problem is we're using pages now so - * this whole operation can get a little cpu intensive */ - pskb_trim(skb, skb->len - 4); - copydone: total_rx_bytes += skb->len; total_rx_packets++; @@ -1043,7 +768,6 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter) struct e1000_buffer *buffer_info; struct e1000_ps_page *ps_page; struct pci_dev *pdev = adapter->pdev; - unsigned long size; unsigned int i, j; /* Free all the Rx ring sk_buffs */ @@ -1054,9 +778,6 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter) pci_unmap_single(pdev, buffer_info->dma, adapter->rx_buffer_len, PCI_DMA_FROMDEVICE); - else if (adapter->clean_rx == e1000_clean_rx_irq_jumbo) - pci_unmap_page(pdev, buffer_info->dma, - PAGE_SIZE, PCI_DMA_FROMDEVICE); else if (adapter->clean_rx == e1000_clean_rx_irq_ps) pci_unmap_single(pdev, buffer_info->dma, adapter->rx_ps_bsize0, @@ -1064,19 +785,13 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter) buffer_info->dma = 0; } - if (buffer_info->page) { - put_page(buffer_info->page); - buffer_info->page = NULL; - } - if (buffer_info->skb) { dev_kfree_skb(buffer_info->skb); buffer_info->skb = NULL; } for (j = 0; j < PS_PAGE_BUFFERS; j++) { - ps_page = &rx_ring->ps_pages[(i * PS_PAGE_BUFFERS) - + j]; + ps_page = &buffer_info->ps_pages[j]; if (!ps_page->page) break; pci_unmap_page(pdev, ps_page->dma, PAGE_SIZE, @@ -1093,12 +808,6 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter) rx_ring->rx_skb_top = NULL; } - size = sizeof(struct e1000_buffer) * rx_ring->count; - memset(rx_ring->buffer_info, 0, size); - size = sizeof(struct e1000_ps_page) - * (rx_ring->count * PS_PAGE_BUFFERS); - memset(rx_ring->ps_pages, 0, size); - /* Zero out the descriptor ring */ memset(rx_ring->desc, 0, rx_ring->size); @@ -1421,7 +1130,8 @@ err: int e1000e_setup_rx_resources(struct e1000_adapter *adapter) { struct e1000_ring *rx_ring = adapter->rx_ring; - int size, desc_len, err = -ENOMEM; + struct e1000_buffer *buffer_info; + int i, size, desc_len, err = -ENOMEM; size = sizeof(struct e1000_buffer) * rx_ring->count; rx_ring->buffer_info = vmalloc(size); @@ -1429,11 +1139,14 @@ int e1000e_setup_rx_resources(struct e1000_adapter *adapter) goto err; memset(rx_ring->buffer_info, 0, size); - rx_ring->ps_pages = kcalloc(rx_ring->count * PS_PAGE_BUFFERS, - sizeof(struct e1000_ps_page), - GFP_KERNEL); - if (!rx_ring->ps_pages) - goto err; + for (i = 0; i < rx_ring->count; i++) { + buffer_info = &rx_ring->buffer_info[i]; + buffer_info->ps_pages = kcalloc(PS_PAGE_BUFFERS, + sizeof(struct e1000_ps_page), + GFP_KERNEL); + if (!buffer_info->ps_pages) + goto err_pages; + } desc_len = sizeof(union e1000_rx_desc_packet_split); @@ -1443,16 +1156,21 @@ int e1000e_setup_rx_resources(struct e1000_adapter *adapter) err = e1000_alloc_ring_dma(adapter, rx_ring); if (err) - goto err; + goto err_pages; rx_ring->next_to_clean = 0; rx_ring->next_to_use = 0; rx_ring->rx_skb_top = NULL; return 0; + +err_pages: + for (i = 0; i < rx_ring->count; i++) { + buffer_info = &rx_ring->buffer_info[i]; + kfree(buffer_info->ps_pages); + } err: vfree(rx_ring->buffer_info); - kfree(rx_ring->ps_pages); ndev_err(adapter->netdev, "Unable to allocate memory for the transmit descriptor ring\n"); return err; @@ -1518,15 +1236,17 @@ void e1000e_free_rx_resources(struct e1000_adapter *adapter) { struct pci_dev *pdev = adapter->pdev; struct e1000_ring *rx_ring = adapter->rx_ring; + int i; e1000_clean_rx_ring(adapter); + for (i = 0; i < rx_ring->count; i++) { + kfree(rx_ring->buffer_info[i].ps_pages); + } + vfree(rx_ring->buffer_info); rx_ring->buffer_info = NULL; - kfree(rx_ring->ps_pages); - rx_ring->ps_pages = NULL; - dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc, rx_ring->dma); rx_ring->desc = NULL; @@ -1669,10 +1389,6 @@ static int e1000_clean(struct napi_struct *napi, int budget) /* Must NOT use netdev_priv macro here. */ adapter = poll_dev->priv; - /* Keep link state information with original netdev */ - if (!netif_carrier_ok(poll_dev)) - goto quit_polling; - /* e1000_clean is called per-cpu. This lock protects * tx_ring from being cleaned by multiple cpus * simultaneously. A failure obtaining the lock means @@ -1684,10 +1400,11 @@ static int e1000_clean(struct napi_struct *napi, int budget) adapter->clean_rx(adapter, &work_done, budget); - /* If no Tx and not enough Rx work done, exit the polling mode */ - if ((!tx_cleaned && (work_done < budget)) || - !netif_running(poll_dev)) { -quit_polling: + if (tx_cleaned) + work_done = budget; + + /* If budget not fully consumed, exit the polling mode */ + if (work_done < budget) { if (adapter->itr_setting & 3) e1000_set_itr(adapter); netif_rx_complete(poll_dev, napi); @@ -2032,9 +1749,11 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) ew32(RFCTL, rfctl); - /* disable the stripping of CRC because it breaks - * BMC firmware connected over SMBUS */ - rctl |= E1000_RCTL_DTYP_PS /* | E1000_RCTL_SECRC */; + /* Enable Packet split descriptors */ + rctl |= E1000_RCTL_DTYP_PS; + + /* Enable hardware CRC frame stripping */ + rctl |= E1000_RCTL_SECRC; psrctl |= adapter->rx_ps_bsize0 >> E1000_PSRCTL_BSIZE0_SHIFT; @@ -2077,11 +1796,6 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) sizeof(union e1000_rx_desc_packet_split); adapter->clean_rx = e1000_clean_rx_irq_ps; adapter->alloc_rx_buf = e1000_alloc_rx_buffers_ps; - } else if (adapter->netdev->mtu > ETH_FRAME_LEN + VLAN_HLEN + 4) { - rdlen = rx_ring->count * - sizeof(struct e1000_rx_desc); - adapter->clean_rx = e1000_clean_rx_irq_jumbo; - adapter->alloc_rx_buf = e1000_alloc_rx_buffers_jumbo; } else { rdlen = rx_ring->count * sizeof(struct e1000_rx_desc); @@ -2326,8 +2040,11 @@ void e1000e_reset(struct e1000_adapter *adapter) struct e1000_mac_info *mac = &adapter->hw.mac; struct e1000_hw *hw = &adapter->hw; u32 tx_space, min_tx_space, min_rx_space; + u32 pba; u16 hwm; + ew32(PBA, adapter->pba); + if (mac->max_frame_size > ETH_FRAME_LEN + ETH_FCS_LEN ) { /* To maintain wire speed transmits, the Tx FIFO should be * large enough to accommodate two full transmit packets, @@ -2335,11 +2052,11 @@ void e1000e_reset(struct e1000_adapter *adapter) * the Rx FIFO should be large enough to accommodate at least * one full receive packet and is similarly rounded up and * expressed in KB. */ - adapter->pba = er32(PBA); + pba = er32(PBA); /* upper 16 bits has Tx packet buffer allocation size in KB */ - tx_space = adapter->pba >> 16; + tx_space = pba >> 16; /* lower 16 bits has Rx packet buffer allocation size in KB */ - adapter->pba &= 0xffff; + pba &= 0xffff; /* the tx fifo also stores 16 bytes of information about the tx * but don't include ethernet FCS because hardware appends it */ min_tx_space = (mac->max_frame_size + @@ -2355,20 +2072,21 @@ void e1000e_reset(struct e1000_adapter *adapter) /* If current Tx allocation is less than the min Tx FIFO size, * and the min Tx FIFO size is less than the current Rx FIFO * allocation, take space away from current Rx allocation */ - if (tx_space < min_tx_space && - ((min_tx_space - tx_space) < adapter->pba)) { - adapter->pba -= - (min_tx_space - tx_space); + if ((tx_space < min_tx_space) && + ((min_tx_space - tx_space) < pba)) { + pba -= min_tx_space - tx_space; /* if short on rx space, rx wins and must trump tx * adjustment or use Early Receive if available */ - if ((adapter->pba < min_rx_space) && + if ((pba < min_rx_space) && (!(adapter->flags & FLAG_HAS_ERT))) /* ERT enabled in e1000_configure_rx */ - adapter->pba = min_rx_space; + pba = min_rx_space; } + + ew32(PBA, pba); } - ew32(PBA, adapter->pba); /* flow control settings */ /* The high water mark must be low enough to fit one full frame @@ -3624,9 +3342,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) /* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN * means we reserve 2 more, this pushes us to allocate from the next * larger slab size. - * i.e. RXBUFFER_2048 --> size-4096 slab - * however with the new *_jumbo* routines, jumbo receives will use - * fragmented skbs */ + * i.e. RXBUFFER_2048 --> size-4096 slab */ if (max_frame <= 256) adapter->rx_buffer_len = 256; diff --git a/drivers/net/e1000e/param.c b/drivers/net/e1000e/param.c index e4e655efb23..332789238b9 100644 --- a/drivers/net/e1000e/param.c +++ b/drivers/net/e1000e/param.c @@ -52,10 +52,11 @@ MODULE_PARM_DESC(copybreak, */ #define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET } -#define E1000_PARAM(X, desc) \ - static int __devinitdata X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \ - static int num_##X; \ - module_param_array_named(X, X, int, &num_##X, 0); \ +#define E1000_PARAM(X, desc) \ + static int __devinitdata X[E1000_MAX_NIC+1] \ + = E1000_PARAM_INIT; \ + static unsigned int num_##X; \ + module_param_array_named(X, X, int, &num_##X, 0); \ MODULE_PARM_DESC(X, desc); @@ -124,9 +125,9 @@ E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround"); struct e1000_option { enum { enable_option, range_option, list_option } type; - char *name; - char *err; - int def; + const char *name; + const char *err; + int def; union { struct { /* range_option info */ int min; @@ -139,8 +140,8 @@ struct e1000_option { } arg; }; -static int __devinit e1000_validate_option(int *value, - struct e1000_option *opt, +static int __devinit e1000_validate_option(unsigned int *value, + const struct e1000_option *opt, struct e1000_adapter *adapter) { if (*value == OPTION_UNSET) { @@ -213,7 +214,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) } { /* Transmit Interrupt Delay */ - struct e1000_option opt = { + const struct e1000_option opt = { .type = range_option, .name = "Transmit Interrupt Delay", .err = "using default of " @@ -232,7 +233,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) } } { /* Transmit Absolute Interrupt Delay */ - struct e1000_option opt = { + const struct e1000_option opt = { .type = range_option, .name = "Transmit Absolute Interrupt Delay", .err = "using default of " @@ -277,7 +278,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) } } { /* Receive Absolute Interrupt Delay */ - struct e1000_option opt = { + const struct e1000_option opt = { .type = range_option, .name = "Receive Absolute Interrupt Delay", .err = "using default of " @@ -296,7 +297,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) } } { /* Interrupt Throttling Rate */ - struct e1000_option opt = { + const struct e1000_option opt = { .type = range_option, .name = "Interrupt Throttling Rate (ints/sec)", .err = "using default of " @@ -344,7 +345,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) } } { /* Smart Power Down */ - struct e1000_option opt = { + const struct e1000_option opt = { .type = enable_option, .name = "PHY Smart Power Down", .err = "defaulting to Disabled", @@ -352,7 +353,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) }; if (num_SmartPowerDownEnable > bd) { - int spd = SmartPowerDownEnable[bd]; + unsigned int spd = SmartPowerDownEnable[bd]; e1000_validate_option(&spd, &opt, adapter); if ((adapter->flags & FLAG_HAS_SMART_POWER_DOWN) && spd) @@ -360,7 +361,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) } } { /* Kumeran Lock Loss Workaround */ - struct e1000_option opt = { + const struct e1000_option opt = { .type = enable_option, .name = "Kumeran Lock Loss Workaround", .err = "defaulting to Enabled", @@ -368,7 +369,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) }; if (num_KumeranLockLoss > bd) { - int kmrn_lock_loss = KumeranLockLoss[bd]; + unsigned int kmrn_lock_loss = KumeranLockLoss[bd]; e1000_validate_option(&kmrn_lock_loss, &opt, adapter); if (hw->mac.type == e1000_ich8lan) e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index 4b4b74e47a6..5f82a4647ee 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_0079" +#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 0a7e7892554..869e1604b16 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -33,6 +33,9 @@ #include <linux/if.h> #include <linux/list.h> #include <linux/if_ether.h> +#include <linux/notifier.h> +#include <linux/reboot.h> + #include <net/ip.h> #include "ehea.h" @@ -133,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)); @@ -159,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; @@ -403,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); @@ -419,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; } @@ -1997,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); @@ -3295,6 +3302,20 @@ static int __devexit ehea_remove(struct of_device *dev) return 0; } +static int ehea_reboot_notifier(struct notifier_block *nb, + unsigned long action, void *unused) +{ + if (action == SYS_RESTART) { + ehea_info("Reboot: freeing all eHEA resources"); + ibmebus_unregister_driver(&ehea_driver); + } + return NOTIFY_DONE; +} + +static struct notifier_block ehea_reboot_nb = { + .notifier_call = ehea_reboot_notifier, +}; + static int check_module_parm(void) { int ret = 0; @@ -3351,6 +3372,8 @@ int __init ehea_module_init(void) if (ret) goto out; + register_reboot_notifier(&ehea_reboot_nb); + ret = ibmebus_register_driver(&ehea_driver); if (ret) { ehea_error("failed registering eHEA device driver on ebus"); @@ -3362,6 +3385,7 @@ int __init ehea_module_init(void) if (ret) { ehea_error("failed to register capabilities attribute, ret=%d", ret); + unregister_reboot_notifier(&ehea_reboot_nb); ibmebus_unregister_driver(&ehea_driver); goto out; } @@ -3375,6 +3399,7 @@ static void __exit ehea_module_exit(void) flush_scheduled_work(); driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities); ibmebus_unregister_driver(&ehea_driver); + unregister_reboot_notifier(&ehea_reboot_nb); ehea_destroy_busmap(); } diff --git a/drivers/net/ehea/ehea_qmr.h b/drivers/net/ehea/ehea_qmr.h index 562de0ebdd8..bc62d389c16 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/epic100.c b/drivers/net/epic100.c index ecdd3fc8d70..0b365b8d947 100644 --- a/drivers/net/epic100.c +++ b/drivers/net/epic100.c @@ -1273,7 +1273,7 @@ rx_action: epic_rx_err(dev, ep); - if (netif_running(dev) && (work_done < budget)) { + if (work_done < budget) { unsigned long flags; int more; diff --git a/drivers/net/fec_8xx/fec_main.c b/drivers/net/fec_8xx/fec_main.c index 8d2904fa578..ab9637ab3a8 100644 --- a/drivers/net/fec_8xx/fec_main.c +++ b/drivers/net/fec_8xx/fec_main.c @@ -476,11 +476,6 @@ static int fec_enet_rx_common(struct fec_enet_private *ep, __u16 pkt_len, sc; int curidx; - if (fpi->use_napi) { - if (!netif_running(dev)) - return 0; - } - /* * First, grab all of the stats for the incoming packet. * These get messed up if we get called due to a busy condition. diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c new file mode 100644 index 00000000000..f91ee700e60 --- /dev/null +++ b/drivers/net/fec_mpc52xx.c @@ -0,0 +1,1115 @@ +/* + * Driver for the MPC5200 Fast Ethernet Controller + * + * Originally written by Dale Farnsworth <dfarnsworth@mvista.com> and + * now maintained by Sylvain Munaut <tnt@246tNt.com> + * + * Copyright (C) 2007 Domen Puncer, Telargo, Inc. + * Copyright (C) 2007 Sylvain Munaut <tnt@246tNt.com> + * Copyright (C) 2003-2004 MontaVista, Software, Inc. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + * + */ + +#include <linux/module.h> + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/spinlock.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/crc32.h> +#include <linux/hardirq.h> +#include <linux/delay.h> +#include <linux/of_device.h> +#include <linux/of_platform.h> + +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/ethtool.h> +#include <linux/skbuff.h> + +#include <asm/io.h> +#include <asm/delay.h> +#include <asm/mpc52xx.h> + +#include <sysdev/bestcomm/bestcomm.h> +#include <sysdev/bestcomm/fec.h> + +#include "fec_mpc52xx.h" + +#define DRIVER_NAME "mpc52xx-fec" + +static irqreturn_t mpc52xx_fec_interrupt(int, void *); +static irqreturn_t mpc52xx_fec_rx_interrupt(int, void *); +static irqreturn_t mpc52xx_fec_tx_interrupt(int, void *); +static void mpc52xx_fec_stop(struct net_device *dev); +static void mpc52xx_fec_start(struct net_device *dev); +static void mpc52xx_fec_reset(struct net_device *dev); + +static u8 mpc52xx_fec_mac_addr[6]; +module_param_array_named(mac, mpc52xx_fec_mac_addr, byte, NULL, 0); +MODULE_PARM_DESC(mac, "six hex digits, ie. 0x1,0x2,0xc0,0x01,0xba,0xbe"); + +#define MPC52xx_MESSAGES_DEFAULT ( NETIF_MSG_DRV | NETIF_MSG_PROBE | \ + NETIF_MSG_LINK | NETIF_MSG_IFDOWN | NETIF_MSG_IFDOWN ) +static int debug = -1; /* the above default */ +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "debugging messages level"); + +static void mpc52xx_fec_tx_timeout(struct net_device *dev) +{ + dev_warn(&dev->dev, "transmit timed out\n"); + + mpc52xx_fec_reset(dev); + + dev->stats.tx_errors++; + + netif_wake_queue(dev); +} + +static void mpc52xx_fec_set_paddr(struct net_device *dev, u8 *mac) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct mpc52xx_fec __iomem *fec = priv->fec; + + out_be32(&fec->paddr1, *(u32 *)(&mac[0])); + out_be32(&fec->paddr2, (*(u16 *)(&mac[4]) << 16) | FEC_PADDR2_TYPE); +} + +static void mpc52xx_fec_get_paddr(struct net_device *dev, u8 *mac) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct mpc52xx_fec __iomem *fec = priv->fec; + + *(u32 *)(&mac[0]) = in_be32(&fec->paddr1); + *(u16 *)(&mac[4]) = in_be32(&fec->paddr2) >> 16; +} + +static int mpc52xx_fec_set_mac_address(struct net_device *dev, void *addr) +{ + struct sockaddr *sock = addr; + + memcpy(dev->dev_addr, sock->sa_data, dev->addr_len); + + mpc52xx_fec_set_paddr(dev, sock->sa_data); + return 0; +} + +static void mpc52xx_fec_free_rx_buffers(struct net_device *dev, struct bcom_task *s) +{ + while (!bcom_queue_empty(s)) { + struct bcom_fec_bd *bd; + struct sk_buff *skb; + + skb = bcom_retrieve_buffer(s, NULL, (struct bcom_bd **)&bd); + dma_unmap_single(&dev->dev, bd->skb_pa, skb->len, DMA_FROM_DEVICE); + kfree_skb(skb); + } +} + +static int mpc52xx_fec_alloc_rx_buffers(struct net_device *dev, struct bcom_task *rxtsk) +{ + while (!bcom_queue_full(rxtsk)) { + struct sk_buff *skb; + struct bcom_fec_bd *bd; + + skb = dev_alloc_skb(FEC_RX_BUFFER_SIZE); + if (skb == NULL) + return -EAGAIN; + + /* zero out the initial receive buffers to aid debugging */ + memset(skb->data, 0, FEC_RX_BUFFER_SIZE); + + bd = (struct bcom_fec_bd *)bcom_prepare_next_buffer(rxtsk); + + bd->status = FEC_RX_BUFFER_SIZE; + bd->skb_pa = dma_map_single(&dev->dev, skb->data, + FEC_RX_BUFFER_SIZE, DMA_FROM_DEVICE); + + bcom_submit_next_buffer(rxtsk, skb); + } + + return 0; +} + +/* based on generic_adjust_link from fs_enet-main.c */ +static void mpc52xx_fec_adjust_link(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct phy_device *phydev = priv->phydev; + int new_state = 0; + + if (phydev->link != PHY_DOWN) { + if (phydev->duplex != priv->duplex) { + struct mpc52xx_fec __iomem *fec = priv->fec; + u32 rcntrl; + u32 tcntrl; + + new_state = 1; + priv->duplex = phydev->duplex; + + rcntrl = in_be32(&fec->r_cntrl); + tcntrl = in_be32(&fec->x_cntrl); + + rcntrl &= ~FEC_RCNTRL_DRT; + tcntrl &= ~FEC_TCNTRL_FDEN; + if (phydev->duplex == DUPLEX_FULL) + tcntrl |= FEC_TCNTRL_FDEN; /* FD enable */ + else + rcntrl |= FEC_RCNTRL_DRT; /* disable Rx on Tx (HD) */ + + out_be32(&fec->r_cntrl, rcntrl); + out_be32(&fec->x_cntrl, tcntrl); + } + + if (phydev->speed != priv->speed) { + new_state = 1; + priv->speed = phydev->speed; + } + + if (priv->link == PHY_DOWN) { + new_state = 1; + priv->link = phydev->link; + netif_schedule(dev); + netif_carrier_on(dev); + netif_start_queue(dev); + } + + } else if (priv->link) { + new_state = 1; + priv->link = PHY_DOWN; + priv->speed = 0; + priv->duplex = -1; + netif_stop_queue(dev); + netif_carrier_off(dev); + } + + if (new_state && netif_msg_link(priv)) + phy_print_status(phydev); +} + +static int mpc52xx_fec_init_phy(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct phy_device *phydev; + char phy_id[BUS_ID_SIZE]; + + snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, + (unsigned int)dev->base_addr, priv->phy_addr); + + priv->link = PHY_DOWN; + priv->speed = 0; + priv->duplex = -1; + + phydev = phy_connect(dev, phy_id, &mpc52xx_fec_adjust_link, 0, PHY_INTERFACE_MODE_MII); + if (IS_ERR(phydev)) { + dev_err(&dev->dev, "phy_connect failed\n"); + return PTR_ERR(phydev); + } + dev_info(&dev->dev, "attached phy %i to driver %s\n", + phydev->addr, phydev->drv->name); + + priv->phydev = phydev; + + return 0; +} + +static int mpc52xx_fec_phy_start(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + int err; + + if (!priv->has_phy) + return 0; + + err = mpc52xx_fec_init_phy(dev); + if (err) { + dev_err(&dev->dev, "mpc52xx_fec_init_phy failed\n"); + return err; + } + + /* reset phy - this also wakes it from PDOWN */ + phy_write(priv->phydev, MII_BMCR, BMCR_RESET); + phy_start(priv->phydev); + + return 0; +} + +static void mpc52xx_fec_phy_stop(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + + if (!priv->has_phy) + return; + + phy_disconnect(priv->phydev); + /* power down phy */ + phy_stop(priv->phydev); + phy_write(priv->phydev, MII_BMCR, BMCR_PDOWN); +} + +static int mpc52xx_fec_phy_mii_ioctl(struct mpc52xx_fec_priv *priv, + struct mii_ioctl_data *mii_data, int cmd) +{ + if (!priv->has_phy) + return -ENOTSUPP; + + return phy_mii_ioctl(priv->phydev, mii_data, cmd); +} + +static void mpc52xx_fec_phy_hw_init(struct mpc52xx_fec_priv *priv) +{ + struct mpc52xx_fec __iomem *fec = priv->fec; + + if (!priv->has_phy) + return; + + out_be32(&fec->mii_speed, priv->phy_speed); +} + +static int mpc52xx_fec_open(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + int err = -EBUSY; + + if (request_irq(dev->irq, &mpc52xx_fec_interrupt, IRQF_SHARED, + DRIVER_NAME "_ctrl", dev)) { + dev_err(&dev->dev, "ctrl interrupt request failed\n"); + goto out; + } + if (request_irq(priv->r_irq, &mpc52xx_fec_rx_interrupt, 0, + DRIVER_NAME "_rx", dev)) { + dev_err(&dev->dev, "rx interrupt request failed\n"); + goto free_ctrl_irq; + } + if (request_irq(priv->t_irq, &mpc52xx_fec_tx_interrupt, 0, + DRIVER_NAME "_tx", dev)) { + dev_err(&dev->dev, "tx interrupt request failed\n"); + goto free_2irqs; + } + + bcom_fec_rx_reset(priv->rx_dmatsk); + bcom_fec_tx_reset(priv->tx_dmatsk); + + err = mpc52xx_fec_alloc_rx_buffers(dev, priv->rx_dmatsk); + if (err) { + dev_err(&dev->dev, "mpc52xx_fec_alloc_rx_buffers failed\n"); + goto free_irqs; + } + + err = mpc52xx_fec_phy_start(dev); + if (err) + goto free_skbs; + + bcom_enable(priv->rx_dmatsk); + bcom_enable(priv->tx_dmatsk); + + mpc52xx_fec_start(dev); + + netif_start_queue(dev); + + return 0; + + free_skbs: + mpc52xx_fec_free_rx_buffers(dev, priv->rx_dmatsk); + + free_irqs: + free_irq(priv->t_irq, dev); + free_2irqs: + free_irq(priv->r_irq, dev); + free_ctrl_irq: + free_irq(dev->irq, dev); + out: + + return err; +} + +static int mpc52xx_fec_close(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + + netif_stop_queue(dev); + + mpc52xx_fec_stop(dev); + + mpc52xx_fec_free_rx_buffers(dev, priv->rx_dmatsk); + + free_irq(dev->irq, dev); + free_irq(priv->r_irq, dev); + free_irq(priv->t_irq, dev); + + mpc52xx_fec_phy_stop(dev); + + return 0; +} + +/* This will only be invoked if your driver is _not_ in XOFF state. + * What this means is that you need not check it, and that this + * invariant will hold if you make sure that the netif_*_queue() + * calls are done at the proper times. + */ +static int mpc52xx_fec_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct bcom_fec_bd *bd; + + if (bcom_queue_full(priv->tx_dmatsk)) { + if (net_ratelimit()) + dev_err(&dev->dev, "transmit queue overrun\n"); + return 1; + } + + spin_lock_irq(&priv->lock); + dev->trans_start = jiffies; + + bd = (struct bcom_fec_bd *) + bcom_prepare_next_buffer(priv->tx_dmatsk); + + bd->status = skb->len | BCOM_FEC_TX_BD_TFD | BCOM_FEC_TX_BD_TC; + bd->skb_pa = dma_map_single(&dev->dev, skb->data, skb->len, DMA_TO_DEVICE); + + bcom_submit_next_buffer(priv->tx_dmatsk, skb); + + if (bcom_queue_full(priv->tx_dmatsk)) { + netif_stop_queue(dev); + } + + spin_unlock_irq(&priv->lock); + + return 0; +} + +/* This handles BestComm transmit task interrupts + */ +static irqreturn_t mpc52xx_fec_tx_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + + spin_lock(&priv->lock); + + while (bcom_buffer_done(priv->tx_dmatsk)) { + struct sk_buff *skb; + struct bcom_fec_bd *bd; + skb = bcom_retrieve_buffer(priv->tx_dmatsk, NULL, + (struct bcom_bd **)&bd); + dma_unmap_single(&dev->dev, bd->skb_pa, skb->len, DMA_TO_DEVICE); + + dev_kfree_skb_irq(skb); + } + + netif_wake_queue(dev); + + spin_unlock(&priv->lock); + + return IRQ_HANDLED; +} + +static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + + while (bcom_buffer_done(priv->rx_dmatsk)) { + struct sk_buff *skb; + struct sk_buff *rskb; + struct bcom_fec_bd *bd; + u32 status; + + rskb = bcom_retrieve_buffer(priv->rx_dmatsk, &status, + (struct bcom_bd **)&bd); + dma_unmap_single(&dev->dev, bd->skb_pa, rskb->len, DMA_FROM_DEVICE); + + /* Test for errors in received frame */ + if (status & BCOM_FEC_RX_BD_ERRORS) { + /* Drop packet and reuse the buffer */ + bd = (struct bcom_fec_bd *) + bcom_prepare_next_buffer(priv->rx_dmatsk); + + bd->status = FEC_RX_BUFFER_SIZE; + bd->skb_pa = dma_map_single(&dev->dev, rskb->data, + FEC_RX_BUFFER_SIZE, DMA_FROM_DEVICE); + + bcom_submit_next_buffer(priv->rx_dmatsk, rskb); + + dev->stats.rx_dropped++; + + continue; + } + + /* skbs are allocated on open, so now we allocate a new one, + * and remove the old (with the packet) */ + skb = dev_alloc_skb(FEC_RX_BUFFER_SIZE); + if (skb) { + /* Process the received skb */ + int length = status & BCOM_FEC_RX_BD_LEN_MASK; + + skb_put(rskb, length - 4); /* length without CRC32 */ + + rskb->dev = dev; + rskb->protocol = eth_type_trans(rskb, dev); + + netif_rx(rskb); + dev->last_rx = jiffies; + } else { + /* Can't get a new one : reuse the same & drop pkt */ + dev_notice(&dev->dev, "Memory squeeze, dropping packet.\n"); + dev->stats.rx_dropped++; + + skb = rskb; + } + + bd = (struct bcom_fec_bd *) + bcom_prepare_next_buffer(priv->rx_dmatsk); + + bd->status = FEC_RX_BUFFER_SIZE; + bd->skb_pa = dma_map_single(&dev->dev, skb->data, + FEC_RX_BUFFER_SIZE, DMA_FROM_DEVICE); + + bcom_submit_next_buffer(priv->rx_dmatsk, skb); + } + + return IRQ_HANDLED; +} + +static irqreturn_t mpc52xx_fec_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct mpc52xx_fec __iomem *fec = priv->fec; + u32 ievent; + + ievent = in_be32(&fec->ievent); + + ievent &= ~FEC_IEVENT_MII; /* mii is handled separately */ + if (!ievent) + return IRQ_NONE; + + out_be32(&fec->ievent, ievent); /* clear pending events */ + + if (ievent & ~(FEC_IEVENT_RFIFO_ERROR | FEC_IEVENT_XFIFO_ERROR)) { + if (ievent & ~FEC_IEVENT_TFINT) + dev_dbg(&dev->dev, "ievent: %08x\n", ievent); + return IRQ_HANDLED; + } + + if (net_ratelimit() && (ievent & FEC_IEVENT_RFIFO_ERROR)) + dev_warn(&dev->dev, "FEC_IEVENT_RFIFO_ERROR\n"); + if (net_ratelimit() && (ievent & FEC_IEVENT_XFIFO_ERROR)) + dev_warn(&dev->dev, "FEC_IEVENT_XFIFO_ERROR\n"); + + mpc52xx_fec_reset(dev); + + netif_wake_queue(dev); + return IRQ_HANDLED; +} + +/* + * Get the current statistics. + * This may be called with the card open or closed. + */ +static struct net_device_stats *mpc52xx_fec_get_stats(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct net_device_stats *stats = &dev->stats; + struct mpc52xx_fec __iomem *fec = priv->fec; + + stats->rx_bytes = in_be32(&fec->rmon_r_octets); + stats->rx_packets = in_be32(&fec->rmon_r_packets); + stats->rx_errors = in_be32(&fec->rmon_r_crc_align) + + in_be32(&fec->rmon_r_undersize) + + in_be32(&fec->rmon_r_oversize) + + in_be32(&fec->rmon_r_frag) + + in_be32(&fec->rmon_r_jab); + + stats->tx_bytes = in_be32(&fec->rmon_t_octets); + stats->tx_packets = in_be32(&fec->rmon_t_packets); + stats->tx_errors = in_be32(&fec->rmon_t_crc_align) + + in_be32(&fec->rmon_t_undersize) + + in_be32(&fec->rmon_t_oversize) + + in_be32(&fec->rmon_t_frag) + + in_be32(&fec->rmon_t_jab); + + stats->multicast = in_be32(&fec->rmon_r_mc_pkt); + stats->collisions = in_be32(&fec->rmon_t_col); + + /* detailed rx_errors: */ + stats->rx_length_errors = in_be32(&fec->rmon_r_undersize) + + in_be32(&fec->rmon_r_oversize) + + in_be32(&fec->rmon_r_frag) + + in_be32(&fec->rmon_r_jab); + stats->rx_over_errors = in_be32(&fec->r_macerr); + stats->rx_crc_errors = in_be32(&fec->ieee_r_crc); + stats->rx_frame_errors = in_be32(&fec->ieee_r_align); + stats->rx_fifo_errors = in_be32(&fec->rmon_r_drop); + stats->rx_missed_errors = in_be32(&fec->rmon_r_drop); + + /* detailed tx_errors: */ + stats->tx_aborted_errors = 0; + stats->tx_carrier_errors = in_be32(&fec->ieee_t_cserr); + stats->tx_fifo_errors = in_be32(&fec->rmon_t_drop); + stats->tx_heartbeat_errors = in_be32(&fec->ieee_t_sqe); + stats->tx_window_errors = in_be32(&fec->ieee_t_lcol); + + return stats; +} + +/* + * Read MIB counters in order to reset them, + * then zero all the stats fields in memory + */ +static void mpc52xx_fec_reset_stats(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct mpc52xx_fec __iomem *fec = priv->fec; + + out_be32(&fec->mib_control, FEC_MIB_DISABLE); + memset_io(&fec->rmon_t_drop, 0, + offsetof(struct mpc52xx_fec, reserved10) - + offsetof(struct mpc52xx_fec, rmon_t_drop)); + out_be32(&fec->mib_control, 0); + + memset(&dev->stats, 0, sizeof(dev->stats)); +} + +/* + * Set or clear the multicast filter for this adaptor. + */ +static void mpc52xx_fec_set_multicast_list(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct mpc52xx_fec __iomem *fec = priv->fec; + u32 rx_control; + + rx_control = in_be32(&fec->r_cntrl); + + if (dev->flags & IFF_PROMISC) { + rx_control |= FEC_RCNTRL_PROM; + out_be32(&fec->r_cntrl, rx_control); + } else { + rx_control &= ~FEC_RCNTRL_PROM; + out_be32(&fec->r_cntrl, rx_control); + + if (dev->flags & IFF_ALLMULTI) { + out_be32(&fec->gaddr1, 0xffffffff); + out_be32(&fec->gaddr2, 0xffffffff); + } else { + u32 crc; + int i; + struct dev_mc_list *dmi; + u32 gaddr1 = 0x00000000; + u32 gaddr2 = 0x00000000; + + dmi = dev->mc_list; + for (i=0; i<dev->mc_count; i++) { + crc = ether_crc_le(6, dmi->dmi_addr) >> 26; + if (crc >= 32) + gaddr1 |= 1 << (crc-32); + else + gaddr2 |= 1 << crc; + dmi = dmi->next; + } + out_be32(&fec->gaddr1, gaddr1); + out_be32(&fec->gaddr2, gaddr2); + } + } +} + +/** + * mpc52xx_fec_hw_init + * @dev: network device + * + * Setup various hardware setting, only needed once on start + */ +static void mpc52xx_fec_hw_init(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct mpc52xx_fec __iomem *fec = priv->fec; + int i; + + /* Whack a reset. We should wait for this. */ + out_be32(&fec->ecntrl, FEC_ECNTRL_RESET); + for (i = 0; i < FEC_RESET_DELAY; ++i) { + if ((in_be32(&fec->ecntrl) & FEC_ECNTRL_RESET) == 0) + break; + udelay(1); + } + if (i == FEC_RESET_DELAY) + dev_err(&dev->dev, "FEC Reset timeout!\n"); + + /* set pause to 0x20 frames */ + out_be32(&fec->op_pause, FEC_OP_PAUSE_OPCODE | 0x20); + + /* high service request will be deasserted when there's < 7 bytes in fifo + * low service request will be deasserted when there's < 4*7 bytes in fifo + */ + out_be32(&fec->rfifo_cntrl, FEC_FIFO_CNTRL_FRAME | FEC_FIFO_CNTRL_LTG_7); + out_be32(&fec->tfifo_cntrl, FEC_FIFO_CNTRL_FRAME | FEC_FIFO_CNTRL_LTG_7); + + /* alarm when <= x bytes in FIFO */ + out_be32(&fec->rfifo_alarm, 0x0000030c); + out_be32(&fec->tfifo_alarm, 0x00000100); + + /* begin transmittion when 256 bytes are in FIFO (or EOF or FIFO full) */ + out_be32(&fec->x_wmrk, FEC_FIFO_WMRK_256B); + + /* enable crc generation */ + out_be32(&fec->xmit_fsm, FEC_XMIT_FSM_APPEND_CRC | FEC_XMIT_FSM_ENABLE_CRC); + out_be32(&fec->iaddr1, 0x00000000); /* No individual filter */ + out_be32(&fec->iaddr2, 0x00000000); /* No individual filter */ + + /* set phy speed. + * this can't be done in phy driver, since it needs to be called + * before fec stuff (even on resume) */ + mpc52xx_fec_phy_hw_init(priv); +} + +/** + * mpc52xx_fec_start + * @dev: network device + * + * This function is called to start or restart the FEC during a link + * change. This happens on fifo errors or when switching between half + * and full duplex. + */ +static void mpc52xx_fec_start(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct mpc52xx_fec __iomem *fec = priv->fec; + u32 rcntrl; + u32 tcntrl; + u32 tmp; + + /* clear sticky error bits */ + tmp = FEC_FIFO_STATUS_ERR | FEC_FIFO_STATUS_UF | FEC_FIFO_STATUS_OF; + out_be32(&fec->rfifo_status, in_be32(&fec->rfifo_status) & tmp); + out_be32(&fec->tfifo_status, in_be32(&fec->tfifo_status) & tmp); + + /* FIFOs will reset on mpc52xx_fec_enable */ + out_be32(&fec->reset_cntrl, FEC_RESET_CNTRL_ENABLE_IS_RESET); + + /* Set station address. */ + mpc52xx_fec_set_paddr(dev, dev->dev_addr); + + mpc52xx_fec_set_multicast_list(dev); + + /* set max frame len, enable flow control, select mii mode */ + rcntrl = FEC_RX_BUFFER_SIZE << 16; /* max frame length */ + rcntrl |= FEC_RCNTRL_FCE; + + if (priv->has_phy) + rcntrl |= FEC_RCNTRL_MII_MODE; + + if (priv->duplex == DUPLEX_FULL) + tcntrl = FEC_TCNTRL_FDEN; /* FD enable */ + else { + rcntrl |= FEC_RCNTRL_DRT; /* disable Rx on Tx (HD) */ + tcntrl = 0; + } + out_be32(&fec->r_cntrl, rcntrl); + out_be32(&fec->x_cntrl, tcntrl); + + /* Clear any outstanding interrupt. */ + out_be32(&fec->ievent, 0xffffffff); + + /* Enable interrupts we wish to service. */ + out_be32(&fec->imask, FEC_IMASK_ENABLE); + + /* And last, enable the transmit and receive processing. */ + out_be32(&fec->ecntrl, FEC_ECNTRL_ETHER_EN); + out_be32(&fec->r_des_active, 0x01000000); +} + +/** + * mpc52xx_fec_stop + * @dev: network device + * + * stop all activity on fec and empty dma buffers + */ +static void mpc52xx_fec_stop(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct mpc52xx_fec __iomem *fec = priv->fec; + unsigned long timeout; + + /* disable all interrupts */ + out_be32(&fec->imask, 0); + + /* Disable the rx task. */ + bcom_disable(priv->rx_dmatsk); + + /* Wait for tx queue to drain, but only if we're in process context */ + if (!in_interrupt()) { + timeout = jiffies + msecs_to_jiffies(2000); + while (time_before(jiffies, timeout) && + !bcom_queue_empty(priv->tx_dmatsk)) + msleep(100); + + if (time_after_eq(jiffies, timeout)) + dev_err(&dev->dev, "queues didn't drain\n"); +#if 1 + if (time_after_eq(jiffies, timeout)) { + dev_err(&dev->dev, " tx: index: %i, outdex: %i\n", + priv->tx_dmatsk->index, + priv->tx_dmatsk->outdex); + dev_err(&dev->dev, " rx: index: %i, outdex: %i\n", + priv->rx_dmatsk->index, + priv->rx_dmatsk->outdex); + } +#endif + } + + bcom_disable(priv->tx_dmatsk); + + /* Stop FEC */ + out_be32(&fec->ecntrl, in_be32(&fec->ecntrl) & ~FEC_ECNTRL_ETHER_EN); + + return; +} + +/* reset fec and bestcomm tasks */ +static void mpc52xx_fec_reset(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + struct mpc52xx_fec __iomem *fec = priv->fec; + + mpc52xx_fec_stop(dev); + + out_be32(&fec->rfifo_status, in_be32(&fec->rfifo_status)); + out_be32(&fec->reset_cntrl, FEC_RESET_CNTRL_RESET_FIFO); + + mpc52xx_fec_free_rx_buffers(dev, priv->rx_dmatsk); + + mpc52xx_fec_hw_init(dev); + + phy_stop(priv->phydev); + phy_write(priv->phydev, MII_BMCR, BMCR_RESET); + phy_start(priv->phydev); + + bcom_fec_rx_reset(priv->rx_dmatsk); + bcom_fec_tx_reset(priv->tx_dmatsk); + + mpc52xx_fec_alloc_rx_buffers(dev, priv->rx_dmatsk); + + bcom_enable(priv->rx_dmatsk); + bcom_enable(priv->tx_dmatsk); + + mpc52xx_fec_start(dev); +} + + +/* ethtool interface */ +static void mpc52xx_fec_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + strcpy(info->driver, DRIVER_NAME); +} + +static int mpc52xx_fec_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + return phy_ethtool_gset(priv->phydev, cmd); +} + +static int mpc52xx_fec_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + return phy_ethtool_sset(priv->phydev, cmd); +} + +static u32 mpc52xx_fec_get_msglevel(struct net_device *dev) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + return priv->msg_enable; +} + +static void mpc52xx_fec_set_msglevel(struct net_device *dev, u32 level) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + priv->msg_enable = level; +} + +static const struct ethtool_ops mpc52xx_fec_ethtool_ops = { + .get_drvinfo = mpc52xx_fec_get_drvinfo, + .get_settings = mpc52xx_fec_get_settings, + .set_settings = mpc52xx_fec_set_settings, + .get_link = ethtool_op_get_link, + .get_msglevel = mpc52xx_fec_get_msglevel, + .set_msglevel = mpc52xx_fec_set_msglevel, +}; + + +static int mpc52xx_fec_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + + return mpc52xx_fec_phy_mii_ioctl(priv, if_mii(rq), cmd); +} + +/* ======================================================================== */ +/* OF Driver */ +/* ======================================================================== */ + +static int __devinit +mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match) +{ + int rv; + struct net_device *ndev; + struct mpc52xx_fec_priv *priv = NULL; + struct resource mem; + const phandle *ph; + + phys_addr_t rx_fifo; + phys_addr_t tx_fifo; + + /* Get the ether ndev & it's private zone */ + ndev = alloc_etherdev(sizeof(struct mpc52xx_fec_priv)); + if (!ndev) + return -ENOMEM; + + priv = netdev_priv(ndev); + + /* Reserve FEC control zone */ + rv = of_address_to_resource(op->node, 0, &mem); + if (rv) { + printk(KERN_ERR DRIVER_NAME ": " + "Error while parsing device node resource\n" ); + return rv; + } + if ((mem.end - mem.start + 1) < sizeof(struct mpc52xx_fec)) { + printk(KERN_ERR DRIVER_NAME + " - invalid resource size (%lx < %x), check mpc52xx_devices.c\n", + (unsigned long)(mem.end - mem.start + 1), sizeof(struct mpc52xx_fec)); + return -EINVAL; + } + + if (!request_mem_region(mem.start, sizeof(struct mpc52xx_fec), DRIVER_NAME)) + return -EBUSY; + + /* Init ether ndev with what we have */ + ndev->open = mpc52xx_fec_open; + ndev->stop = mpc52xx_fec_close; + ndev->hard_start_xmit = mpc52xx_fec_hard_start_xmit; + ndev->do_ioctl = mpc52xx_fec_ioctl; + ndev->ethtool_ops = &mpc52xx_fec_ethtool_ops; + ndev->get_stats = mpc52xx_fec_get_stats; + ndev->set_mac_address = mpc52xx_fec_set_mac_address; + ndev->set_multicast_list = mpc52xx_fec_set_multicast_list; + ndev->tx_timeout = mpc52xx_fec_tx_timeout; + ndev->watchdog_timeo = FEC_WATCHDOG_TIMEOUT; + ndev->base_addr = mem.start; + + priv->t_irq = priv->r_irq = ndev->irq = NO_IRQ; /* IRQ are free for now */ + + spin_lock_init(&priv->lock); + + /* ioremap the zones */ + priv->fec = ioremap(mem.start, sizeof(struct mpc52xx_fec)); + + if (!priv->fec) { + rv = -ENOMEM; + goto probe_error; + } + + /* Bestcomm init */ + rx_fifo = ndev->base_addr + offsetof(struct mpc52xx_fec, rfifo_data); + tx_fifo = ndev->base_addr + offsetof(struct mpc52xx_fec, tfifo_data); + + priv->rx_dmatsk = bcom_fec_rx_init(FEC_RX_NUM_BD, rx_fifo, FEC_RX_BUFFER_SIZE); + priv->tx_dmatsk = bcom_fec_tx_init(FEC_TX_NUM_BD, tx_fifo); + + if (!priv->rx_dmatsk || !priv->tx_dmatsk) { + printk(KERN_ERR DRIVER_NAME ": Can not init SDMA tasks\n" ); + rv = -ENOMEM; + goto probe_error; + } + + /* Get the IRQ we need one by one */ + /* Control */ + ndev->irq = irq_of_parse_and_map(op->node, 0); + + /* RX */ + priv->r_irq = bcom_get_task_irq(priv->rx_dmatsk); + + /* TX */ + priv->t_irq = bcom_get_task_irq(priv->tx_dmatsk); + + /* MAC address init */ + if (!is_zero_ether_addr(mpc52xx_fec_mac_addr)) + memcpy(ndev->dev_addr, mpc52xx_fec_mac_addr, 6); + else + mpc52xx_fec_get_paddr(ndev, ndev->dev_addr); + + priv->msg_enable = netif_msg_init(debug, MPC52xx_MESSAGES_DEFAULT); + priv->duplex = DUPLEX_FULL; + + /* is the phy present in device tree? */ + ph = of_get_property(op->node, "phy-handle", NULL); + if (ph) { + const unsigned int *prop; + struct device_node *phy_dn; + priv->has_phy = 1; + + phy_dn = of_find_node_by_phandle(*ph); + prop = of_get_property(phy_dn, "reg", NULL); + priv->phy_addr = *prop; + + of_node_put(phy_dn); + + /* Phy speed */ + priv->phy_speed = ((mpc52xx_find_ipb_freq(op->node) >> 20) / 5) << 1; + } else { + dev_info(&ndev->dev, "can't find \"phy-handle\" in device" + " tree, using 7-wire mode\n"); + } + + /* Hardware init */ + mpc52xx_fec_hw_init(ndev); + + mpc52xx_fec_reset_stats(ndev); + + SET_NETDEV_DEV(ndev, &op->dev); + + /* Register the new network device */ + rv = register_netdev(ndev); + if (rv < 0) + goto probe_error; + + /* We're done ! */ + dev_set_drvdata(&op->dev, ndev); + + return 0; + + + /* Error handling - free everything that might be allocated */ +probe_error: + + irq_dispose_mapping(ndev->irq); + + if (priv->rx_dmatsk) + bcom_fec_rx_release(priv->rx_dmatsk); + if (priv->tx_dmatsk) + bcom_fec_tx_release(priv->tx_dmatsk); + + if (priv->fec) + iounmap(priv->fec); + + release_mem_region(mem.start, sizeof(struct mpc52xx_fec)); + + free_netdev(ndev); + + return rv; +} + +static int +mpc52xx_fec_remove(struct of_device *op) +{ + struct net_device *ndev; + struct mpc52xx_fec_priv *priv; + + ndev = dev_get_drvdata(&op->dev); + priv = netdev_priv(ndev); + + unregister_netdev(ndev); + + irq_dispose_mapping(ndev->irq); + + bcom_fec_rx_release(priv->rx_dmatsk); + bcom_fec_tx_release(priv->tx_dmatsk); + + iounmap(priv->fec); + + release_mem_region(ndev->base_addr, sizeof(struct mpc52xx_fec)); + + free_netdev(ndev); + + dev_set_drvdata(&op->dev, NULL); + return 0; +} + +#ifdef CONFIG_PM +static int mpc52xx_fec_of_suspend(struct of_device *op, pm_message_t state) +{ + struct net_device *dev = dev_get_drvdata(&op->dev); + + if (netif_running(dev)) + mpc52xx_fec_close(dev); + + return 0; +} + +static int mpc52xx_fec_of_resume(struct of_device *op) +{ + struct net_device *dev = dev_get_drvdata(&op->dev); + + mpc52xx_fec_hw_init(dev); + mpc52xx_fec_reset_stats(dev); + + if (netif_running(dev)) + mpc52xx_fec_open(dev); + + return 0; +} +#endif + +static struct of_device_id mpc52xx_fec_match[] = { + { + .type = "network", + .compatible = "mpc5200-fec", + }, + { } +}; + +MODULE_DEVICE_TABLE(of, mpc52xx_fec_match); + +static struct of_platform_driver mpc52xx_fec_driver = { + .owner = THIS_MODULE, + .name = DRIVER_NAME, + .match_table = mpc52xx_fec_match, + .probe = mpc52xx_fec_probe, + .remove = mpc52xx_fec_remove, +#ifdef CONFIG_PM + .suspend = mpc52xx_fec_of_suspend, + .resume = mpc52xx_fec_of_resume, +#endif +}; + + +/* ======================================================================== */ +/* Module */ +/* ======================================================================== */ + +static int __init +mpc52xx_fec_init(void) +{ +#ifdef CONFIG_FEC_MPC52xx_MDIO + int ret; + ret = of_register_platform_driver(&mpc52xx_fec_mdio_driver); + if (ret) { + printk(KERN_ERR DRIVER_NAME ": failed to register mdio driver\n"); + return ret; + } +#endif + return of_register_platform_driver(&mpc52xx_fec_driver); +} + +static void __exit +mpc52xx_fec_exit(void) +{ + of_unregister_platform_driver(&mpc52xx_fec_driver); +#ifdef CONFIG_FEC_MPC52xx_MDIO + of_unregister_platform_driver(&mpc52xx_fec_mdio_driver); +#endif +} + + +module_init(mpc52xx_fec_init); +module_exit(mpc52xx_fec_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Dale Farnsworth"); +MODULE_DESCRIPTION("Ethernet driver for the Freescale MPC52xx FEC"); diff --git a/drivers/net/fec_mpc52xx.h b/drivers/net/fec_mpc52xx.h new file mode 100644 index 00000000000..8b1f75397b9 --- /dev/null +++ b/drivers/net/fec_mpc52xx.h @@ -0,0 +1,313 @@ +/* + * drivers/drivers/net/fec_mpc52xx/fec.h + * + * Driver for the MPC5200 Fast Ethernet Controller + * + * Author: Dale Farnsworth <dfarnsworth@mvista.com> + * + * 2003-2004 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#ifndef __DRIVERS_NET_MPC52XX_FEC_H__ +#define __DRIVERS_NET_MPC52XX_FEC_H__ + +#include <linux/phy.h> + +/* Tunable constant */ +/* FEC_RX_BUFFER_SIZE includes 4 bytes for CRC32 */ +#define FEC_RX_BUFFER_SIZE 1522 /* max receive packet size */ +#define FEC_RX_NUM_BD 256 +#define FEC_TX_NUM_BD 64 + +#define FEC_RESET_DELAY 50 /* uS */ + +#define FEC_WATCHDOG_TIMEOUT ((400*HZ)/1000) + +struct mpc52xx_fec_priv { + int duplex; + int r_irq; + int t_irq; + struct mpc52xx_fec __iomem *fec; + struct bcom_task *rx_dmatsk; + struct bcom_task *tx_dmatsk; + spinlock_t lock; + int msg_enable; + + int has_phy; + unsigned int phy_speed; + unsigned int phy_addr; + struct phy_device *phydev; + enum phy_state link; + int speed; +}; + + +/* ======================================================================== */ +/* Hardware register sets & bits */ +/* ======================================================================== */ + +struct mpc52xx_fec { + u32 fec_id; /* FEC + 0x000 */ + u32 ievent; /* FEC + 0x004 */ + u32 imask; /* FEC + 0x008 */ + + u32 reserved0[1]; /* FEC + 0x00C */ + u32 r_des_active; /* FEC + 0x010 */ + u32 x_des_active; /* FEC + 0x014 */ + u32 r_des_active_cl; /* FEC + 0x018 */ + u32 x_des_active_cl; /* FEC + 0x01C */ + u32 ivent_set; /* FEC + 0x020 */ + u32 ecntrl; /* FEC + 0x024 */ + + u32 reserved1[6]; /* FEC + 0x028-03C */ + u32 mii_data; /* FEC + 0x040 */ + u32 mii_speed; /* FEC + 0x044 */ + u32 mii_status; /* FEC + 0x048 */ + + u32 reserved2[5]; /* FEC + 0x04C-05C */ + u32 mib_data; /* FEC + 0x060 */ + u32 mib_control; /* FEC + 0x064 */ + + u32 reserved3[6]; /* FEC + 0x068-7C */ + u32 r_activate; /* FEC + 0x080 */ + u32 r_cntrl; /* FEC + 0x084 */ + u32 r_hash; /* FEC + 0x088 */ + u32 r_data; /* FEC + 0x08C */ + u32 ar_done; /* FEC + 0x090 */ + u32 r_test; /* FEC + 0x094 */ + u32 r_mib; /* FEC + 0x098 */ + u32 r_da_low; /* FEC + 0x09C */ + u32 r_da_high; /* FEC + 0x0A0 */ + + u32 reserved4[7]; /* FEC + 0x0A4-0BC */ + u32 x_activate; /* FEC + 0x0C0 */ + u32 x_cntrl; /* FEC + 0x0C4 */ + u32 backoff; /* FEC + 0x0C8 */ + u32 x_data; /* FEC + 0x0CC */ + u32 x_status; /* FEC + 0x0D0 */ + u32 x_mib; /* FEC + 0x0D4 */ + u32 x_test; /* FEC + 0x0D8 */ + u32 fdxfc_da1; /* FEC + 0x0DC */ + u32 fdxfc_da2; /* FEC + 0x0E0 */ + u32 paddr1; /* FEC + 0x0E4 */ + u32 paddr2; /* FEC + 0x0E8 */ + u32 op_pause; /* FEC + 0x0EC */ + + u32 reserved5[4]; /* FEC + 0x0F0-0FC */ + u32 instr_reg; /* FEC + 0x100 */ + u32 context_reg; /* FEC + 0x104 */ + u32 test_cntrl; /* FEC + 0x108 */ + u32 acc_reg; /* FEC + 0x10C */ + u32 ones; /* FEC + 0x110 */ + u32 zeros; /* FEC + 0x114 */ + u32 iaddr1; /* FEC + 0x118 */ + u32 iaddr2; /* FEC + 0x11C */ + u32 gaddr1; /* FEC + 0x120 */ + u32 gaddr2; /* FEC + 0x124 */ + u32 random; /* FEC + 0x128 */ + u32 rand1; /* FEC + 0x12C */ + u32 tmp; /* FEC + 0x130 */ + + u32 reserved6[3]; /* FEC + 0x134-13C */ + u32 fifo_id; /* FEC + 0x140 */ + u32 x_wmrk; /* FEC + 0x144 */ + u32 fcntrl; /* FEC + 0x148 */ + u32 r_bound; /* FEC + 0x14C */ + u32 r_fstart; /* FEC + 0x150 */ + u32 r_count; /* FEC + 0x154 */ + u32 r_lag; /* FEC + 0x158 */ + u32 r_read; /* FEC + 0x15C */ + u32 r_write; /* FEC + 0x160 */ + u32 x_count; /* FEC + 0x164 */ + u32 x_lag; /* FEC + 0x168 */ + u32 x_retry; /* FEC + 0x16C */ + u32 x_write; /* FEC + 0x170 */ + u32 x_read; /* FEC + 0x174 */ + + u32 reserved7[2]; /* FEC + 0x178-17C */ + u32 fm_cntrl; /* FEC + 0x180 */ + u32 rfifo_data; /* FEC + 0x184 */ + u32 rfifo_status; /* FEC + 0x188 */ + u32 rfifo_cntrl; /* FEC + 0x18C */ + u32 rfifo_lrf_ptr; /* FEC + 0x190 */ + u32 rfifo_lwf_ptr; /* FEC + 0x194 */ + u32 rfifo_alarm; /* FEC + 0x198 */ + u32 rfifo_rdptr; /* FEC + 0x19C */ + u32 rfifo_wrptr; /* FEC + 0x1A0 */ + u32 tfifo_data; /* FEC + 0x1A4 */ + u32 tfifo_status; /* FEC + 0x1A8 */ + u32 tfifo_cntrl; /* FEC + 0x1AC */ + u32 tfifo_lrf_ptr; /* FEC + 0x1B0 */ + u32 tfifo_lwf_ptr; /* FEC + 0x1B4 */ + u32 tfifo_alarm; /* FEC + 0x1B8 */ + u32 tfifo_rdptr; /* FEC + 0x1BC */ + u32 tfifo_wrptr; /* FEC + 0x1C0 */ + + u32 reset_cntrl; /* FEC + 0x1C4 */ + u32 xmit_fsm; /* FEC + 0x1C8 */ + + u32 reserved8[3]; /* FEC + 0x1CC-1D4 */ + u32 rdes_data0; /* FEC + 0x1D8 */ + u32 rdes_data1; /* FEC + 0x1DC */ + u32 r_length; /* FEC + 0x1E0 */ + u32 x_length; /* FEC + 0x1E4 */ + u32 x_addr; /* FEC + 0x1E8 */ + u32 cdes_data; /* FEC + 0x1EC */ + u32 status; /* FEC + 0x1F0 */ + u32 dma_control; /* FEC + 0x1F4 */ + u32 des_cmnd; /* FEC + 0x1F8 */ + u32 data; /* FEC + 0x1FC */ + + u32 rmon_t_drop; /* FEC + 0x200 */ + u32 rmon_t_packets; /* FEC + 0x204 */ + u32 rmon_t_bc_pkt; /* FEC + 0x208 */ + u32 rmon_t_mc_pkt; /* FEC + 0x20C */ + u32 rmon_t_crc_align; /* FEC + 0x210 */ + u32 rmon_t_undersize; /* FEC + 0x214 */ + u32 rmon_t_oversize; /* FEC + 0x218 */ + u32 rmon_t_frag; /* FEC + 0x21C */ + u32 rmon_t_jab; /* FEC + 0x220 */ + u32 rmon_t_col; /* FEC + 0x224 */ + u32 rmon_t_p64; /* FEC + 0x228 */ + u32 rmon_t_p65to127; /* FEC + 0x22C */ + u32 rmon_t_p128to255; /* FEC + 0x230 */ + u32 rmon_t_p256to511; /* FEC + 0x234 */ + u32 rmon_t_p512to1023; /* FEC + 0x238 */ + u32 rmon_t_p1024to2047; /* FEC + 0x23C */ + u32 rmon_t_p_gte2048; /* FEC + 0x240 */ + u32 rmon_t_octets; /* FEC + 0x244 */ + u32 ieee_t_drop; /* FEC + 0x248 */ + u32 ieee_t_frame_ok; /* FEC + 0x24C */ + u32 ieee_t_1col; /* FEC + 0x250 */ + u32 ieee_t_mcol; /* FEC + 0x254 */ + u32 ieee_t_def; /* FEC + 0x258 */ + u32 ieee_t_lcol; /* FEC + 0x25C */ + u32 ieee_t_excol; /* FEC + 0x260 */ + u32 ieee_t_macerr; /* FEC + 0x264 */ + u32 ieee_t_cserr; /* FEC + 0x268 */ + u32 ieee_t_sqe; /* FEC + 0x26C */ + u32 t_fdxfc; /* FEC + 0x270 */ + u32 ieee_t_octets_ok; /* FEC + 0x274 */ + + u32 reserved9[2]; /* FEC + 0x278-27C */ + u32 rmon_r_drop; /* FEC + 0x280 */ + u32 rmon_r_packets; /* FEC + 0x284 */ + u32 rmon_r_bc_pkt; /* FEC + 0x288 */ + u32 rmon_r_mc_pkt; /* FEC + 0x28C */ + u32 rmon_r_crc_align; /* FEC + 0x290 */ + u32 rmon_r_undersize; /* FEC + 0x294 */ + u32 rmon_r_oversize; /* FEC + 0x298 */ + u32 rmon_r_frag; /* FEC + 0x29C */ + u32 rmon_r_jab; /* FEC + 0x2A0 */ + + u32 rmon_r_resvd_0; /* FEC + 0x2A4 */ + + u32 rmon_r_p64; /* FEC + 0x2A8 */ + u32 rmon_r_p65to127; /* FEC + 0x2AC */ + u32 rmon_r_p128to255; /* FEC + 0x2B0 */ + u32 rmon_r_p256to511; /* FEC + 0x2B4 */ + u32 rmon_r_p512to1023; /* FEC + 0x2B8 */ + u32 rmon_r_p1024to2047; /* FEC + 0x2BC */ + u32 rmon_r_p_gte2048; /* FEC + 0x2C0 */ + u32 rmon_r_octets; /* FEC + 0x2C4 */ + u32 ieee_r_drop; /* FEC + 0x2C8 */ + u32 ieee_r_frame_ok; /* FEC + 0x2CC */ + u32 ieee_r_crc; /* FEC + 0x2D0 */ + u32 ieee_r_align; /* FEC + 0x2D4 */ + u32 r_macerr; /* FEC + 0x2D8 */ + u32 r_fdxfc; /* FEC + 0x2DC */ + u32 ieee_r_octets_ok; /* FEC + 0x2E0 */ + + u32 reserved10[7]; /* FEC + 0x2E4-2FC */ + + u32 reserved11[64]; /* FEC + 0x300-3FF */ +}; + +#define FEC_MIB_DISABLE 0x80000000 + +#define FEC_IEVENT_HBERR 0x80000000 +#define FEC_IEVENT_BABR 0x40000000 +#define FEC_IEVENT_BABT 0x20000000 +#define FEC_IEVENT_GRA 0x10000000 +#define FEC_IEVENT_TFINT 0x08000000 +#define FEC_IEVENT_MII 0x00800000 +#define FEC_IEVENT_LATE_COL 0x00200000 +#define FEC_IEVENT_COL_RETRY_LIM 0x00100000 +#define FEC_IEVENT_XFIFO_UN 0x00080000 +#define FEC_IEVENT_XFIFO_ERROR 0x00040000 +#define FEC_IEVENT_RFIFO_ERROR 0x00020000 + +#define FEC_IMASK_HBERR 0x80000000 +#define FEC_IMASK_BABR 0x40000000 +#define FEC_IMASK_BABT 0x20000000 +#define FEC_IMASK_GRA 0x10000000 +#define FEC_IMASK_MII 0x00800000 +#define FEC_IMASK_LATE_COL 0x00200000 +#define FEC_IMASK_COL_RETRY_LIM 0x00100000 +#define FEC_IMASK_XFIFO_UN 0x00080000 +#define FEC_IMASK_XFIFO_ERROR 0x00040000 +#define FEC_IMASK_RFIFO_ERROR 0x00020000 + +/* all but MII, which is enabled separately */ +#define FEC_IMASK_ENABLE (FEC_IMASK_HBERR | FEC_IMASK_BABR | \ + FEC_IMASK_BABT | FEC_IMASK_GRA | FEC_IMASK_LATE_COL | \ + FEC_IMASK_COL_RETRY_LIM | FEC_IMASK_XFIFO_UN | \ + FEC_IMASK_XFIFO_ERROR | FEC_IMASK_RFIFO_ERROR) + +#define FEC_RCNTRL_MAX_FL_SHIFT 16 +#define FEC_RCNTRL_LOOP 0x01 +#define FEC_RCNTRL_DRT 0x02 +#define FEC_RCNTRL_MII_MODE 0x04 +#define FEC_RCNTRL_PROM 0x08 +#define FEC_RCNTRL_BC_REJ 0x10 +#define FEC_RCNTRL_FCE 0x20 + +#define FEC_TCNTRL_GTS 0x00000001 +#define FEC_TCNTRL_HBC 0x00000002 +#define FEC_TCNTRL_FDEN 0x00000004 +#define FEC_TCNTRL_TFC_PAUSE 0x00000008 +#define FEC_TCNTRL_RFC_PAUSE 0x00000010 + +#define FEC_ECNTRL_RESET 0x00000001 +#define FEC_ECNTRL_ETHER_EN 0x00000002 + +#define FEC_MII_DATA_ST 0x40000000 /* Start frame */ +#define FEC_MII_DATA_OP_RD 0x20000000 /* Perform read */ +#define FEC_MII_DATA_OP_WR 0x10000000 /* Perform write */ +#define FEC_MII_DATA_PA_MSK 0x0f800000 /* PHY Address mask */ +#define FEC_MII_DATA_RA_MSK 0x007c0000 /* PHY Register mask */ +#define FEC_MII_DATA_TA 0x00020000 /* Turnaround */ +#define FEC_MII_DATA_DATAMSK 0x0000ffff /* PHY data mask */ + +#define FEC_MII_READ_FRAME (FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA) +#define FEC_MII_WRITE_FRAME (FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR | FEC_MII_DATA_TA) + +#define FEC_MII_DATA_RA_SHIFT 0x12 /* MII reg addr bits */ +#define FEC_MII_DATA_PA_SHIFT 0x17 /* MII PHY addr bits */ + +#define FEC_PADDR2_TYPE 0x8808 + +#define FEC_OP_PAUSE_OPCODE 0x00010000 + +#define FEC_FIFO_WMRK_256B 0x3 + +#define FEC_FIFO_STATUS_ERR 0x00400000 +#define FEC_FIFO_STATUS_UF 0x00200000 +#define FEC_FIFO_STATUS_OF 0x00100000 + +#define FEC_FIFO_CNTRL_FRAME 0x08000000 +#define FEC_FIFO_CNTRL_LTG_7 0x07000000 + +#define FEC_RESET_CNTRL_RESET_FIFO 0x02000000 +#define FEC_RESET_CNTRL_ENABLE_IS_RESET 0x01000000 + +#define FEC_XMIT_FSM_APPEND_CRC 0x02000000 +#define FEC_XMIT_FSM_ENABLE_CRC 0x01000000 + + +extern struct of_platform_driver mpc52xx_fec_mdio_driver; + +#endif /* __DRIVERS_NET_MPC52XX_FEC_H__ */ diff --git a/drivers/net/fec_mpc52xx_phy.c b/drivers/net/fec_mpc52xx_phy.c new file mode 100644 index 00000000000..ba6e8b218e0 --- /dev/null +++ b/drivers/net/fec_mpc52xx_phy.c @@ -0,0 +1,198 @@ +/* + * Driver for the MPC5200 Fast Ethernet Controller - MDIO bus driver + * + * Copyright (C) 2007 Domen Puncer, Telargo, Inc. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/netdevice.h> +#include <linux/phy.h> +#include <linux/of_platform.h> +#include <asm/io.h> +#include <asm/mpc52xx.h> +#include "fec_mpc52xx.h" + +struct mpc52xx_fec_mdio_priv { + struct mpc52xx_fec __iomem *regs; +}; + +static int mpc52xx_fec_mdio_read(struct mii_bus *bus, int phy_id, int reg) +{ + struct mpc52xx_fec_mdio_priv *priv = bus->priv; + struct mpc52xx_fec __iomem *fec; + int tries = 100; + u32 request = FEC_MII_READ_FRAME; + + fec = priv->regs; + out_be32(&fec->ievent, FEC_IEVENT_MII); + + request |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK; + request |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK; + + out_be32(&priv->regs->mii_data, request); + + /* wait for it to finish, this takes about 23 us on lite5200b */ + while (!(in_be32(&fec->ievent) & FEC_IEVENT_MII) && --tries) + udelay(5); + + if (tries == 0) + return -ETIMEDOUT; + + return in_be32(&priv->regs->mii_data) & FEC_MII_DATA_DATAMSK; +} + +static int mpc52xx_fec_mdio_write(struct mii_bus *bus, int phy_id, int reg, u16 data) +{ + struct mpc52xx_fec_mdio_priv *priv = bus->priv; + struct mpc52xx_fec __iomem *fec; + u32 value = data; + int tries = 100; + + fec = priv->regs; + out_be32(&fec->ievent, FEC_IEVENT_MII); + + value |= FEC_MII_WRITE_FRAME; + value |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK; + value |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK; + + out_be32(&priv->regs->mii_data, value); + + /* wait for request to finish */ + while (!(in_be32(&fec->ievent) & FEC_IEVENT_MII) && --tries) + udelay(5); + + if (tries == 0) + return -ETIMEDOUT; + + return 0; +} + +static int mpc52xx_fec_mdio_probe(struct of_device *of, const struct of_device_id *match) +{ + struct device *dev = &of->dev; + struct device_node *np = of->node; + struct device_node *child = NULL; + struct mii_bus *bus; + struct mpc52xx_fec_mdio_priv *priv; + struct resource res = {}; + int err; + int i; + + bus = kzalloc(sizeof(*bus), GFP_KERNEL); + if (bus == NULL) + return -ENOMEM; + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (priv == NULL) { + err = -ENOMEM; + goto out_free; + } + + bus->name = "mpc52xx MII bus"; + bus->read = mpc52xx_fec_mdio_read; + bus->write = mpc52xx_fec_mdio_write; + + /* setup irqs */ + bus->irq = kmalloc(sizeof(bus->irq[0]) * PHY_MAX_ADDR, GFP_KERNEL); + if (bus->irq == NULL) { + err = -ENOMEM; + goto out_free; + } + for (i=0; i<PHY_MAX_ADDR; i++) + bus->irq[i] = PHY_POLL; + + while ((child = of_get_next_child(np, child)) != NULL) { + int irq = irq_of_parse_and_map(child, 0); + if (irq != NO_IRQ) { + const u32 *id = of_get_property(child, "reg", NULL); + bus->irq[*id] = irq; + } + } + + /* setup registers */ + err = of_address_to_resource(np, 0, &res); + if (err) + goto out_free; + priv->regs = ioremap(res.start, res.end - res.start + 1); + if (priv->regs == NULL) { + err = -ENOMEM; + goto out_free; + } + + bus->id = res.start; + bus->priv = priv; + + bus->dev = dev; + dev_set_drvdata(dev, bus); + + /* set MII speed */ + out_be32(&priv->regs->mii_speed, ((mpc52xx_find_ipb_freq(of->node) >> 20) / 5) << 1); + + /* enable MII interrupt */ + out_be32(&priv->regs->imask, in_be32(&priv->regs->imask) | FEC_IMASK_MII); + + err = mdiobus_register(bus); + if (err) + goto out_unmap; + + return 0; + + out_unmap: + iounmap(priv->regs); + out_free: + for (i=0; i<PHY_MAX_ADDR; i++) + if (bus->irq[i] != PHY_POLL) + irq_dispose_mapping(bus->irq[i]); + kfree(bus->irq); + kfree(priv); + kfree(bus); + + return err; +} + +static int mpc52xx_fec_mdio_remove(struct of_device *of) +{ + struct device *dev = &of->dev; + struct mii_bus *bus = dev_get_drvdata(dev); + struct mpc52xx_fec_mdio_priv *priv = bus->priv; + int i; + + mdiobus_unregister(bus); + dev_set_drvdata(dev, NULL); + + iounmap(priv->regs); + for (i=0; i<PHY_MAX_ADDR; i++) + if (bus->irq[i]) + irq_dispose_mapping(bus->irq[i]); + kfree(priv); + kfree(bus->irq); + kfree(bus); + + return 0; +} + + +static struct of_device_id mpc52xx_fec_mdio_match[] = { + { + .type = "mdio", + .compatible = "mpc5200b-fec-phy", + }, + {}, +}; + +struct of_platform_driver mpc52xx_fec_mdio_driver = { + .name = "mpc5200b-fec-phy", + .probe = mpc52xx_fec_mdio_probe, + .remove = mpc52xx_fec_mdio_remove, + .match_table = mpc52xx_fec_mdio_match, +}; + +/* let fec driver call it, since this has to be registered before it */ +EXPORT_SYMBOL_GPL(mpc52xx_fec_mdio_driver); + + +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 92ce2e38f0d..f84c752997a 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -5199,10 +5199,6 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i dev->dev_addr[3] = (np->orig_mac[0] >> 16) & 0xff; dev->dev_addr[4] = (np->orig_mac[0] >> 8) & 0xff; dev->dev_addr[5] = (np->orig_mac[0] >> 0) & 0xff; - /* set permanent address to be correct aswell */ - np->orig_mac[0] = (dev->dev_addr[0] << 0) + (dev->dev_addr[1] << 8) + - (dev->dev_addr[2] << 16) + (dev->dev_addr[3] << 24); - np->orig_mac[1] = (dev->dev_addr[4] << 0) + (dev->dev_addr[5] << 8); writel(txreg|NVREG_TRANSMITPOLL_MAC_ADDR_REV, base + NvRegTransmitPoll); } memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); @@ -5286,19 +5282,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 */ } } } @@ -5418,6 +5410,8 @@ static void __devexit nv_remove(struct pci_dev *pci_dev) */ writel(np->orig_mac[0], base + NvRegMacAddrA); writel(np->orig_mac[1], base + NvRegMacAddrB); + writel(readl(base + NvRegTransmitPoll) & ~NVREG_TRANSMITPOLL_MAC_ADDR_REV, + base + NvRegTransmitPoll); /* free all structures */ free_rings(dev); @@ -5613,6 +5607,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 2765e49e07d..562ea68ed99 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 02d4dc18ba6..1ffbe0756a0 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/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index f2a4d399a6e..c83bd656008 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c @@ -96,9 +96,6 @@ static int fs_enet_rx_napi(struct napi_struct *napi, int budget) u16 pkt_len, sc; int curidx; - if (!netif_running(dev)) - return 0; - /* * First, grab all of the stats for the incoming packet. * These get messed up if we get called due to a busy condition. @@ -897,14 +894,21 @@ static void fs_get_regs(struct net_device *dev, struct ethtool_regs *regs, static int fs_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct fs_enet_private *fep = netdev_priv(dev); + + if (!fep->phydev) + return -ENODEV; + return phy_ethtool_gset(fep->phydev, cmd); } static int fs_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct fs_enet_private *fep = netdev_priv(dev); - phy_ethtool_sset(fep->phydev, cmd); - return 0; + + if (!fep->phydev) + return -ENODEV; + + return phy_ethtool_sset(fep->phydev, cmd); } static int fs_nway_reset(struct net_device *dev) diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c index 03134f47a4e..48f2f300593 100644 --- a/drivers/net/fs_enet/mac-scc.c +++ b/drivers/net/fs_enet/mac-scc.c @@ -158,7 +158,7 @@ static int setup_data(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); -#ifdef CONFIG_PPC_CPM_NEW_BINDING +#ifndef CONFIG_PPC_CPM_NEW_BINDING struct fs_platform_info *fpi = fep->fpi; fep->scc.idx = fs_get_scc_index(fpi->fs_no); diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 38268d7335a..0431e9ed0fa 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -696,7 +696,7 @@ int startup_gfar(struct net_device *dev) { struct txbd8 *txbdp; struct rxbd8 *rxbdp; - dma_addr_t addr; + dma_addr_t addr = 0; unsigned long vaddr; int i; struct gfar_private *priv = netdev_priv(dev); diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c index ed407c85708..b53f6b6491b 100644 --- a/drivers/net/hamachi.c +++ b/drivers/net/hamachi.c @@ -204,8 +204,10 @@ KERN_INFO " Further modifications by Keith Underwood <keithu@parl.clemson.edu> /* Condensed bus+endian portability operations. */ #if ADDRLEN == 64 #define cpu_to_leXX(addr) cpu_to_le64(addr) +#define leXX_to_cpu(addr) le64_to_cpu(addr) #else #define cpu_to_leXX(addr) cpu_to_le32(addr) +#define leXX_to_cpu(addr) le32_to_cpu(addr) #endif @@ -465,12 +467,12 @@ enum intr_status_bits { /* The Hamachi Rx and Tx buffer descriptors. */ struct hamachi_desc { - u32 status_n_length; + __le32 status_n_length; #if ADDRLEN == 64 u32 pad; - u64 addr; + __le64 addr; #else - u32 addr; + __le32 addr; #endif }; @@ -874,13 +876,13 @@ static int hamachi_open(struct net_device *dev) #if ADDRLEN == 64 /* writellll anyone ? */ - writel(cpu_to_le64(hmp->rx_ring_dma), ioaddr + RxPtr); - writel(cpu_to_le64(hmp->rx_ring_dma) >> 32, ioaddr + RxPtr + 4); - writel(cpu_to_le64(hmp->tx_ring_dma), ioaddr + TxPtr); - writel(cpu_to_le64(hmp->tx_ring_dma) >> 32, ioaddr + TxPtr + 4); + writel(hmp->rx_ring_dma, ioaddr + RxPtr); + writel(hmp->rx_ring_dma >> 32, ioaddr + RxPtr + 4); + writel(hmp->tx_ring_dma, ioaddr + TxPtr); + writel(hmp->tx_ring_dma >> 32, ioaddr + TxPtr + 4); #else - writel(cpu_to_le32(hmp->rx_ring_dma), ioaddr + RxPtr); - writel(cpu_to_le32(hmp->tx_ring_dma), ioaddr + TxPtr); + writel(hmp->rx_ring_dma, ioaddr + RxPtr); + writel(hmp->tx_ring_dma, ioaddr + TxPtr); #endif /* TODO: It would make sense to organize this as words since the card @@ -1019,8 +1021,8 @@ static inline int hamachi_tx(struct net_device *dev) skb = hmp->tx_skbuff[entry]; if (skb) { pci_unmap_single(hmp->pci_dev, - hmp->tx_ring[entry].addr, skb->len, - PCI_DMA_TODEVICE); + leXX_to_cpu(hmp->tx_ring[entry].addr), + skb->len, PCI_DMA_TODEVICE); dev_kfree_skb(skb); hmp->tx_skbuff[entry] = NULL; } @@ -1071,10 +1073,10 @@ static void hamachi_tx_timeout(struct net_device *dev) { printk(KERN_DEBUG " Rx ring %p: ", hmp->rx_ring); for (i = 0; i < RX_RING_SIZE; i++) - printk(" %8.8x", (unsigned int)hmp->rx_ring[i].status_n_length); + printk(" %8.8x", le32_to_cpu(hmp->rx_ring[i].status_n_length)); printk("\n"KERN_DEBUG" Tx ring %p: ", hmp->tx_ring); for (i = 0; i < TX_RING_SIZE; i++) - printk(" %4.4x", hmp->tx_ring[i].status_n_length); + printk(" %4.4x", le32_to_cpu(hmp->tx_ring[i].status_n_length)); printk("\n"); } @@ -1099,14 +1101,15 @@ static void hamachi_tx_timeout(struct net_device *dev) struct sk_buff *skb; if (i >= TX_RING_SIZE - 1) - hmp->tx_ring[i].status_n_length = cpu_to_le32( - DescEndRing | - (hmp->tx_ring[i].status_n_length & 0x0000FFFF)); + hmp->tx_ring[i].status_n_length = + cpu_to_le32(DescEndRing) | + (hmp->tx_ring[i].status_n_length & + cpu_to_le32(0x0000ffff)); else - hmp->tx_ring[i].status_n_length &= 0x0000ffff; + hmp->tx_ring[i].status_n_length &= cpu_to_le32(0x0000ffff); skb = hmp->tx_skbuff[i]; if (skb){ - pci_unmap_single(hmp->pci_dev, hmp->tx_ring[i].addr, + pci_unmap_single(hmp->pci_dev, leXX_to_cpu(hmp->tx_ring[i].addr), skb->len, PCI_DMA_TODEVICE); dev_kfree_skb(skb); hmp->tx_skbuff[i] = NULL; @@ -1128,7 +1131,8 @@ static void hamachi_tx_timeout(struct net_device *dev) struct sk_buff *skb = hmp->rx_skbuff[i]; if (skb){ - pci_unmap_single(hmp->pci_dev, hmp->rx_ring[i].addr, + pci_unmap_single(hmp->pci_dev, + leXX_to_cpu(hmp->rx_ring[i].addr), hmp->rx_buf_sz, PCI_DMA_FROMDEVICE); dev_kfree_skb(skb); hmp->rx_skbuff[i] = NULL; @@ -1420,7 +1424,7 @@ static irqreturn_t hamachi_interrupt(int irq, void *dev_instance) /* Free the original skb. */ if (skb){ pci_unmap_single(hmp->pci_dev, - hmp->tx_ring[entry].addr, + leXX_to_cpu(hmp->tx_ring[entry].addr), skb->len, PCI_DMA_TODEVICE); dev_kfree_skb_irq(skb); @@ -1500,11 +1504,11 @@ static int hamachi_rx(struct net_device *dev) if (desc_status & DescOwn) break; pci_dma_sync_single_for_cpu(hmp->pci_dev, - desc->addr, + leXX_to_cpu(desc->addr), hmp->rx_buf_sz, PCI_DMA_FROMDEVICE); buf_addr = (u8 *) hmp->rx_skbuff[entry]->data; - frame_status = le32_to_cpu(get_unaligned((s32*)&(buf_addr[data_size - 12]))); + frame_status = le32_to_cpu(get_unaligned((__le32*)&(buf_addr[data_size - 12]))); if (hamachi_debug > 4) printk(KERN_DEBUG " hamachi_rx() status was %8.8x.\n", frame_status); @@ -1518,9 +1522,9 @@ static int hamachi_rx(struct net_device *dev) dev->name, desc, &hmp->rx_ring[hmp->cur_rx % RX_RING_SIZE]); printk(KERN_WARNING "%s: Oversized Ethernet frame -- next status %x/%x last status %x.\n", dev->name, - hmp->rx_ring[(hmp->cur_rx+1) % RX_RING_SIZE].status_n_length & 0xffff0000, - hmp->rx_ring[(hmp->cur_rx+1) % RX_RING_SIZE].status_n_length & 0x0000ffff, - hmp->rx_ring[(hmp->cur_rx-1) % RX_RING_SIZE].status_n_length); + le32_to_cpu(hmp->rx_ring[(hmp->cur_rx+1) % RX_RING_SIZE].status_n_length) & 0xffff0000, + le32_to_cpu(hmp->rx_ring[(hmp->cur_rx+1) % RX_RING_SIZE].status_n_length) & 0x0000ffff, + le32_to_cpu(hmp->rx_ring[(hmp->cur_rx-1) % RX_RING_SIZE].status_n_length)); hmp->stats.rx_length_errors++; } /* else Omit for prototype errata??? */ if (frame_status & 0x00380000) { @@ -1566,7 +1570,7 @@ static int hamachi_rx(struct net_device *dev) #endif skb_reserve(skb, 2); /* 16 byte align the IP header */ pci_dma_sync_single_for_cpu(hmp->pci_dev, - hmp->rx_ring[entry].addr, + leXX_to_cpu(hmp->rx_ring[entry].addr), hmp->rx_buf_sz, PCI_DMA_FROMDEVICE); /* Call copy + cksum if available. */ @@ -1579,12 +1583,12 @@ static int hamachi_rx(struct net_device *dev) + entry*sizeof(*desc), pkt_len); #endif pci_dma_sync_single_for_device(hmp->pci_dev, - hmp->rx_ring[entry].addr, + leXX_to_cpu(hmp->rx_ring[entry].addr), hmp->rx_buf_sz, PCI_DMA_FROMDEVICE); } else { pci_unmap_single(hmp->pci_dev, - hmp->rx_ring[entry].addr, + leXX_to_cpu(hmp->rx_ring[entry].addr), hmp->rx_buf_sz, PCI_DMA_FROMDEVICE); skb_put(skb = hmp->rx_skbuff[entry], pkt_len); hmp->rx_skbuff[entry] = NULL; @@ -1787,21 +1791,21 @@ static int hamachi_close(struct net_device *dev) for (i = 0; i < RX_RING_SIZE; i++) { skb = hmp->rx_skbuff[i]; hmp->rx_ring[i].status_n_length = 0; - hmp->rx_ring[i].addr = 0xBADF00D0; /* An invalid address. */ if (skb) { pci_unmap_single(hmp->pci_dev, - hmp->rx_ring[i].addr, hmp->rx_buf_sz, - PCI_DMA_FROMDEVICE); + leXX_to_cpu(hmp->rx_ring[i].addr), + hmp->rx_buf_sz, PCI_DMA_FROMDEVICE); dev_kfree_skb(skb); hmp->rx_skbuff[i] = NULL; } + hmp->rx_ring[i].addr = cpu_to_leXX(0xBADF00D0); /* An invalid address. */ } for (i = 0; i < TX_RING_SIZE; i++) { skb = hmp->tx_skbuff[i]; if (skb) { pci_unmap_single(hmp->pci_dev, - hmp->tx_ring[i].addr, skb->len, - PCI_DMA_TODEVICE); + leXX_to_cpu(hmp->tx_ring[i].addr), + skb->len, PCI_DMA_TODEVICE); dev_kfree_skb(skb); hmp->tx_skbuff[i] = NULL; } diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index e0119f6a331..580cb4ab2af 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 0de3aa2a2e4..cb06280dced 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c @@ -3,6 +3,11 @@ * * Driver for PowerPC 4xx on-chip ethernet controller. * + * Copyright 2007 Benjamin Herrenschmidt, IBM Corp. + * <benh@kernel.crashing.org> + * + * Based on the arch/ppc version of the driver: + * * Copyright (c) 2004, 2005 Zultys Technologies. * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> * @@ -402,7 +407,7 @@ static u32 __emac_calc_base_mr1(struct emac_instance *dev, int tx_size, int rx_s static u32 __emac4_calc_base_mr1(struct emac_instance *dev, int tx_size, int rx_size) { u32 ret = EMAC_MR1_VLE | EMAC_MR1_IST | EMAC4_MR1_TR | - EMAC4_MR1_OBCI(dev->opb_bus_freq); + EMAC4_MR1_OBCI(dev->opb_bus_freq / 1000000); DBG2(dev, "__emac4_calc_base_mr1" NL); @@ -464,26 +469,34 @@ static int emac_configure(struct emac_instance *dev) { struct emac_regs __iomem *p = dev->emacp; struct net_device *ndev = dev->ndev; - int tx_size, rx_size; + int tx_size, rx_size, link = netif_carrier_ok(dev->ndev); u32 r, mr1 = 0; DBG(dev, "configure" NL); - if (emac_reset(dev) < 0) + if (!link) { + out_be32(&p->mr1, in_be32(&p->mr1) + | EMAC_MR1_FDE | EMAC_MR1_ILE); + udelay(100); + } else if (emac_reset(dev) < 0) return -ETIMEDOUT; if (emac_has_feature(dev, EMAC_FTR_HAS_TAH)) tah_reset(dev->tah_dev); - DBG(dev, " duplex = %d, pause = %d, asym_pause = %d\n", - dev->phy.duplex, dev->phy.pause, dev->phy.asym_pause); + DBG(dev, " link = %d duplex = %d, pause = %d, asym_pause = %d\n", + link, dev->phy.duplex, dev->phy.pause, dev->phy.asym_pause); /* Default fifo sizes */ tx_size = dev->tx_fifo_size; rx_size = dev->rx_fifo_size; + /* No link, force loopback */ + if (!link) + mr1 = EMAC_MR1_FDE | EMAC_MR1_ILE; + /* Check for full duplex */ - if (dev->phy.duplex == DUPLEX_FULL) + else if (dev->phy.duplex == DUPLEX_FULL) mr1 |= EMAC_MR1_FDE | EMAC_MR1_MWSW_001; /* Adjust fifo sizes, mr1 and timeouts based on link speed */ @@ -642,9 +655,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); } @@ -701,7 +716,7 @@ static int __emac_mdio_read(struct emac_instance *dev, u8 id, u8 reg) r = EMAC_STACR_BASE(dev->opb_bus_freq); if (emac_has_feature(dev, EMAC_FTR_STACR_OC_INVERT)) r |= EMAC_STACR_OC; - if (emac_has_feature(dev, EMAC_FTR_HAS_AXON_STACR)) + if (emac_has_feature(dev, EMAC_FTR_HAS_NEW_STACR)) r |= EMACX_STACR_STAC_READ; else r |= EMAC_STACR_STAC_READ; @@ -773,7 +788,7 @@ static void __emac_mdio_write(struct emac_instance *dev, u8 id, u8 reg, r = EMAC_STACR_BASE(dev->opb_bus_freq); if (emac_has_feature(dev, EMAC_FTR_STACR_OC_INVERT)) r |= EMAC_STACR_OC; - if (emac_has_feature(dev, EMAC_FTR_HAS_AXON_STACR)) + if (emac_has_feature(dev, EMAC_FTR_HAS_NEW_STACR)) r |= EMACX_STACR_STAC_WRITE; else r |= EMAC_STACR_STAC_WRITE; @@ -1063,10 +1078,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 +1159,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 */ @@ -1162,21 +1178,22 @@ static void emac_link_timer(struct work_struct *work) link_poll_interval = PHY_POLL_LINK_ON; } else { if (netif_carrier_ok(dev->ndev)) { - emac_reinitialize(dev); netif_carrier_off(dev->ndev); netif_tx_disable(dev->ndev); + emac_reinitialize(dev); emac_print_link_status(dev); } 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 +1208,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); @@ -2427,7 +2447,7 @@ static int __devinit emac_init_config(struct emac_instance *dev) if (emac_read_uint_prop(np, "tah-device", &dev->tah_ph, 0)) dev->tah_ph = 0; if (emac_read_uint_prop(np, "tah-channel", &dev->tah_port, 0)) - dev->tah_ph = 0; + dev->tah_port = 0; if (emac_read_uint_prop(np, "mdio-device", &dev->mdio_ph, 0)) dev->mdio_ph = 0; if (emac_read_uint_prop(np, "zmii-device", &dev->zmii_ph, 0)) @@ -2465,16 +2485,19 @@ static int __devinit emac_init_config(struct emac_instance *dev) /* Check EMAC version */ if (of_device_is_compatible(np, "ibm,emac4")) dev->features |= EMAC_FTR_EMAC4; - if (of_device_is_compatible(np, "ibm,emac-axon") - || of_device_is_compatible(np, "ibm,emac-440epx")) - dev->features |= EMAC_FTR_HAS_AXON_STACR - | EMAC_FTR_STACR_OC_INVERT; - if (of_device_is_compatible(np, "ibm,emac-440spe")) + + /* Fixup some feature bits based on the device tree */ + if (of_get_property(np, "has-inverted-stacr-oc", NULL)) dev->features |= EMAC_FTR_STACR_OC_INVERT; + if (of_get_property(np, "has-new-stacr-staopc", NULL)) + dev->features |= EMAC_FTR_HAS_NEW_STACR; - /* Fixup some feature bits based on the device tree and verify - * we have support for them compiled in - */ + /* CAB lacks the appropriate properties */ + if (of_device_is_compatible(np, "ibm,emac-axon")) + dev->features |= EMAC_FTR_HAS_NEW_STACR | + EMAC_FTR_STACR_OC_INVERT; + + /* Enable TAH/ZMII/RGMII features as found */ if (dev->tah_ph != 0) { #ifdef CONFIG_IBM_NEW_EMAC_TAH dev->features |= EMAC_FTR_HAS_TAH; @@ -2532,6 +2555,10 @@ static int __devinit emac_probe(struct of_device *ofdev, struct device_node **blist = NULL; int err, i; + /* Skip unused/unwired EMACS */ + if (of_get_property(np, "unused", NULL)) + return -ENODEV; + /* Find ourselves in the bootlist if we are there */ for (i = 0; i < EMAC_BOOT_LIST_SIZE; i++) if (emac_boot_list[i] == np) @@ -2756,6 +2783,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 4011803117c..4e74d8287c6 100644 --- a/drivers/net/ibm_newemac/core.h +++ b/drivers/net/ibm_newemac/core.h @@ -3,6 +3,11 @@ * * Driver for PowerPC 4xx on-chip ethernet controller. * + * Copyright 2007 Benjamin Herrenschmidt, IBM Corp. + * <benh@kernel.crashing.org> + * + * Based on the arch/ppc version of the driver: + * * Copyright (c) 2004, 2005 Zultys Technologies. * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> * @@ -258,6 +263,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; }; @@ -292,9 +298,9 @@ struct emac_instance { */ #define EMAC_FTR_HAS_RGMII 0x00000020 /* - * Set if we have axon-type STACR + * Set if we have new type STACR with STAOPC */ -#define EMAC_FTR_HAS_AXON_STACR 0x00000040 +#define EMAC_FTR_HAS_NEW_STACR 0x00000040 /* Right now, we don't quite handle the always/possible masks on the @@ -306,7 +312,7 @@ enum { EMAC_FTRS_POSSIBLE = #ifdef CONFIG_IBM_NEW_EMAC_EMAC4 - EMAC_FTR_EMAC4 | EMAC_FTR_HAS_AXON_STACR | + EMAC_FTR_EMAC4 | EMAC_FTR_HAS_NEW_STACR | EMAC_FTR_STACR_OC_INVERT | #endif #ifdef CONFIG_IBM_NEW_EMAC_TAH diff --git a/drivers/net/ibm_newemac/debug.c b/drivers/net/ibm_newemac/debug.c index 170524ee0f1..86b756a3078 100644 --- a/drivers/net/ibm_newemac/debug.c +++ b/drivers/net/ibm_newemac/debug.c @@ -3,6 +3,11 @@ * * Driver for PowerPC 4xx on-chip ethernet controller, debug print routines. * + * Copyright 2007 Benjamin Herrenschmidt, IBM Corp. + * <benh@kernel.crashing.org> + * + * Based on the arch/ppc version of the driver: + * * Copyright (c) 2004, 2005 Zultys Technologies * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> * @@ -21,7 +26,7 @@ #include "core.h" -static spinlock_t emac_dbg_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(emac_dbg_lock); static void emac_desc_dump(struct emac_instance *p) { diff --git a/drivers/net/ibm_newemac/debug.h b/drivers/net/ibm_newemac/debug.h index 1dd2dcbc157..b631842ec8d 100644 --- a/drivers/net/ibm_newemac/debug.h +++ b/drivers/net/ibm_newemac/debug.h @@ -3,6 +3,11 @@ * * Driver for PowerPC 4xx on-chip ethernet controller, debug print routines. * + * Copyright 2007 Benjamin Herrenschmidt, IBM Corp. + * <benh@kernel.crashing.org> + * + * Based on the arch/ppc version of the driver: + * * Copyright (c) 2004, 2005 Zultys Technologies * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> * diff --git a/drivers/net/ibm_newemac/emac.h b/drivers/net/ibm_newemac/emac.h index bef92efeead..91cb096ab40 100644 --- a/drivers/net/ibm_newemac/emac.h +++ b/drivers/net/ibm_newemac/emac.h @@ -3,6 +3,11 @@ * * Register definitions for PowerPC 4xx on-chip ethernet contoller * + * Copyright 2007 Benjamin Herrenschmidt, IBM Corp. + * <benh@kernel.crashing.org> + * + * Based on the arch/ppc version of the driver: + * * Copyright (c) 2004, 2005 Zultys Technologies. * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> * diff --git a/drivers/net/ibm_newemac/mal.c b/drivers/net/ibm_newemac/mal.c index 9a88f71db00..6869f08c9dc 100644 --- a/drivers/net/ibm_newemac/mal.c +++ b/drivers/net/ibm_newemac/mal.c @@ -3,6 +3,11 @@ * * Memory Access Layer (MAL) support * + * Copyright 2007 Benjamin Herrenschmidt, IBM Corp. + * <benh@kernel.crashing.org> + * + * Based on the arch/ppc version of the driver: + * * Copyright (c) 2004, 2005 Zultys Technologies. * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> * diff --git a/drivers/net/ibm_newemac/mal.h b/drivers/net/ibm_newemac/mal.h index 784edb8ea82..eaa7262dc07 100644 --- a/drivers/net/ibm_newemac/mal.h +++ b/drivers/net/ibm_newemac/mal.h @@ -3,6 +3,11 @@ * * Memory Access Layer (MAL) support * + * Copyright 2007 Benjamin Herrenschmidt, IBM Corp. + * <benh@kernel.crashing.org> + * + * Based on the arch/ppc version of the driver: + * * Copyright (c) 2004, 2005 Zultys Technologies. * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> * diff --git a/drivers/net/ibm_newemac/phy.c b/drivers/net/ibm_newemac/phy.c index aa1f0ddf1e3..37bfeea8788 100644 --- a/drivers/net/ibm_newemac/phy.c +++ b/drivers/net/ibm_newemac/phy.c @@ -8,6 +8,11 @@ * This file should be shared with other drivers or eventually * merged as the "low level" part of miilib * + * Copyright 2007 Benjamin Herrenschmidt, IBM Corp. + * <benh@kernel.crashing.org> + * + * Based on the arch/ppc version of the driver: + * * (c) 2003, Benjamin Herrenscmidt (benh@kernel.crashing.org) * (c) 2004-2005, Eugene Surovegin <ebs@ebshome.net> * @@ -306,8 +311,84 @@ static struct mii_phy_def cis8201_phy_def = { .ops = &cis8201_phy_ops }; +static struct mii_phy_def bcm5248_phy_def = { + + .phy_id = 0x0143bc00, + .phy_id_mask = 0x0ffffff0, + .name = "BCM5248 10/100 SMII Ethernet", + .ops = &generic_phy_ops +}; + +static int m88e1111_init(struct mii_phy *phy) +{ + pr_debug("%s: Marvell 88E1111 Ethernet\n", __FUNCTION__); + phy_write(phy, 0x14, 0x0ce3); + phy_write(phy, 0x18, 0x4101); + phy_write(phy, 0x09, 0x0e00); + phy_write(phy, 0x04, 0x01e1); + phy_write(phy, 0x00, 0x9140); + phy_write(phy, 0x00, 0x1140); + + return 0; +} + +static int et1011c_init(struct mii_phy *phy) +{ + u16 reg_short; + + reg_short = (u16)(phy_read(phy, 0x16)); + reg_short &= ~(0x7); + reg_short |= 0x6; /* RGMII Trace Delay*/ + phy_write(phy, 0x16, reg_short); + + reg_short = (u16)(phy_read(phy, 0x17)); + reg_short &= ~(0x40); + phy_write(phy, 0x17, reg_short); + + phy_write(phy, 0x1c, 0x74f0); + return 0; +} + +static struct mii_phy_ops et1011c_phy_ops = { + .init = et1011c_init, + .setup_aneg = genmii_setup_aneg, + .setup_forced = genmii_setup_forced, + .poll_link = genmii_poll_link, + .read_link = genmii_read_link +}; + +static struct mii_phy_def et1011c_phy_def = { + .phy_id = 0x0282f000, + .phy_id_mask = 0x0fffff00, + .name = "ET1011C Gigabit Ethernet", + .ops = &et1011c_phy_ops +}; + + + + + +static struct mii_phy_ops m88e1111_phy_ops = { + .init = m88e1111_init, + .setup_aneg = genmii_setup_aneg, + .setup_forced = genmii_setup_forced, + .poll_link = genmii_poll_link, + .read_link = genmii_read_link +}; + +static struct mii_phy_def m88e1111_phy_def = { + + .phy_id = 0x01410CC0, + .phy_id_mask = 0x0ffffff0, + .name = "Marvell 88E1111 Ethernet", + .ops = &m88e1111_phy_ops, +}; + static struct mii_phy_def *mii_phy_table[] = { + &et1011c_phy_def, &cis8201_phy_def, + &bcm5248_phy_def, + &m88e1111_phy_def, &genmii_phy_def, NULL }; diff --git a/drivers/net/ibm_newemac/phy.h b/drivers/net/ibm_newemac/phy.h index 6feca26afed..1b65c81f655 100644 --- a/drivers/net/ibm_newemac/phy.h +++ b/drivers/net/ibm_newemac/phy.h @@ -3,6 +3,11 @@ * * Driver for PowerPC 4xx on-chip ethernet controller, PHY support * + * Copyright 2007 Benjamin Herrenschmidt, IBM Corp. + * <benh@kernel.crashing.org> + * + * Based on the arch/ppc version of the driver: + * * Benjamin Herrenschmidt <benh@kernel.crashing.org> * February 2003 * diff --git a/drivers/net/ibm_newemac/rgmii.c b/drivers/net/ibm_newemac/rgmii.c index de416951a43..9bc1132fa78 100644 --- a/drivers/net/ibm_newemac/rgmii.c +++ b/drivers/net/ibm_newemac/rgmii.c @@ -3,6 +3,11 @@ * * Driver for PowerPC 4xx on-chip ethernet controller, RGMII bridge support. * + * Copyright 2007 Benjamin Herrenschmidt, IBM Corp. + * <benh@kernel.crashing.org> + * + * Based on the arch/ppc version of the driver: + * * Copyright (c) 2004, 2005 Zultys Technologies. * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> * @@ -140,7 +145,7 @@ void rgmii_get_mdio(struct of_device *ofdev, int input) RGMII_DBG2(dev, "get_mdio(%d)" NL, input); - if (dev->type != RGMII_AXON) + if (!(dev->flags & EMAC_RGMII_FLAG_HAS_MDIO)) return; mutex_lock(&dev->lock); @@ -161,7 +166,7 @@ void rgmii_put_mdio(struct of_device *ofdev, int input) RGMII_DBG2(dev, "put_mdio(%d)" NL, input); - if (dev->type != RGMII_AXON) + if (!(dev->flags & EMAC_RGMII_FLAG_HAS_MDIO)) return; fer = in_be32(&p->fer); @@ -250,11 +255,13 @@ static int __devinit rgmii_probe(struct of_device *ofdev, goto err_free; } - /* Check for RGMII type */ + /* Check for RGMII flags */ + if (of_get_property(ofdev->node, "has-mdio", NULL)) + dev->flags |= EMAC_RGMII_FLAG_HAS_MDIO; + + /* CAB lacks the right properties, fix this up */ if (of_device_is_compatible(ofdev->node, "ibm,rgmii-axon")) - dev->type = RGMII_AXON; - else - dev->type = RGMII_STANDARD; + dev->flags |= EMAC_RGMII_FLAG_HAS_MDIO; DBG2(dev, " Boot FER = 0x%08x, SSR = 0x%08x\n", in_be32(&dev->base->fer), in_be32(&dev->base->ssr)); @@ -263,9 +270,9 @@ static int __devinit rgmii_probe(struct of_device *ofdev, out_be32(&dev->base->fer, 0); printk(KERN_INFO - "RGMII %s %s initialized\n", - dev->type == RGMII_STANDARD ? "standard" : "axon", - ofdev->node->full_name); + "RGMII %s initialized with%s MDIO support\n", + ofdev->node->full_name, + (dev->flags & EMAC_RGMII_FLAG_HAS_MDIO) ? "" : "out"); wmb(); dev_set_drvdata(&ofdev->dev, dev); diff --git a/drivers/net/ibm_newemac/rgmii.h b/drivers/net/ibm_newemac/rgmii.h index 57806833121..c4a4b358a27 100644 --- a/drivers/net/ibm_newemac/rgmii.h +++ b/drivers/net/ibm_newemac/rgmii.h @@ -3,6 +3,11 @@ * * Driver for PowerPC 4xx on-chip ethernet controller, RGMII bridge support. * + * Copyright 2007 Benjamin Herrenschmidt, IBM Corp. + * <benh@kernel.crashing.org> + * + * Based on the arch/ppc version of the driver: + * * Based on ocp_zmii.h/ibm_emac_zmii.h * Armin Kuster akuster@mvista.com * @@ -35,8 +40,9 @@ struct rgmii_regs { struct rgmii_instance { struct rgmii_regs __iomem *base; - /* Type of RGMII bridge */ - int type; + /* RGMII bridge flags */ + int flags; +#define EMAC_RGMII_FLAG_HAS_MDIO 0x00000001 /* Only one EMAC whacks us at a time */ struct mutex lock; diff --git a/drivers/net/ibm_newemac/tah.c b/drivers/net/ibm_newemac/tah.c index f161fb100e8..96417adec32 100644 --- a/drivers/net/ibm_newemac/tah.c +++ b/drivers/net/ibm_newemac/tah.c @@ -3,6 +3,11 @@ * * Driver for PowerPC 4xx on-chip ethernet controller, TAH support. * + * Copyright 2007 Benjamin Herrenschmidt, IBM Corp. + * <benh@kernel.crashing.org> + * + * Based on the arch/ppc version of the driver: + * * Copyright 2004 MontaVista Software, Inc. * Matt Porter <mporter@kernel.crashing.org> * @@ -116,13 +121,14 @@ static int __devinit tah_probe(struct of_device *ofdev, goto err_free; } + dev_set_drvdata(&ofdev->dev, dev); + /* Initialize TAH and enable IPv4 checksum verification, no TSO yet */ tah_reset(ofdev); printk(KERN_INFO "TAH %s initialized\n", ofdev->node->full_name); wmb(); - dev_set_drvdata(&ofdev->dev, dev); return 0; diff --git a/drivers/net/ibm_newemac/tah.h b/drivers/net/ibm_newemac/tah.h index bc41853b6e2..a068b5658da 100644 --- a/drivers/net/ibm_newemac/tah.h +++ b/drivers/net/ibm_newemac/tah.h @@ -3,6 +3,11 @@ * * Driver for PowerPC 4xx on-chip ethernet controller, TAH support. * + * Copyright 2007 Benjamin Herrenschmidt, IBM Corp. + * <benh@kernel.crashing.org> + * + * Based on the arch/ppc version of the driver: + * * Copyright 2004 MontaVista Software, Inc. * Matt Porter <mporter@kernel.crashing.org> * diff --git a/drivers/net/ibm_newemac/zmii.c b/drivers/net/ibm_newemac/zmii.c index 2219ec2740e..2ea472aeab0 100644 --- a/drivers/net/ibm_newemac/zmii.c +++ b/drivers/net/ibm_newemac/zmii.c @@ -3,6 +3,11 @@ * * Driver for PowerPC 4xx on-chip ethernet controller, ZMII bridge support. * + * Copyright 2007 Benjamin Herrenschmidt, IBM Corp. + * <benh@kernel.crashing.org> + * + * Based on the arch/ppc version of the driver: + * * Copyright (c) 2004, 2005 Zultys Technologies. * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> * @@ -83,12 +88,14 @@ int __devinit zmii_attach(struct of_device *ofdev, int input, int *mode) ZMII_DBG(dev, "init(%d, %d)" NL, input, *mode); - if (!zmii_valid_mode(*mode)) + if (!zmii_valid_mode(*mode)) { /* Probably an EMAC connected to RGMII, * but it still may need ZMII for MDIO so * we don't fail here. */ + dev->users++; return 0; + } mutex_lock(&dev->lock); diff --git a/drivers/net/ibm_newemac/zmii.h b/drivers/net/ibm_newemac/zmii.h index 82a9968b1f7..6c9beba0c4b 100644 --- a/drivers/net/ibm_newemac/zmii.h +++ b/drivers/net/ibm_newemac/zmii.h @@ -3,6 +3,11 @@ * * Driver for PowerPC 4xx on-chip ethernet controller, ZMII bridge support. * + * Copyright 2007 Benjamin Herrenschmidt, IBM Corp. + * <benh@kernel.crashing.org> + * + * Based on the arch/ppc version of the driver: + * * Copyright (c) 2004, 2005 Zultys Technologies. * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> * diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c index 4dbdfaaf37b..a1e4508717c 100644 --- a/drivers/net/irda/au1k_ir.c +++ b/drivers/net/irda/au1k_ir.c @@ -627,19 +627,16 @@ static int au1k_irda_rx(struct net_device *dev) } -void au1k_irda_interrupt(int irq, void *dev_id) +static irqreturn_t au1k_irda_interrupt(int dummy, void *dev_id) { - struct net_device *dev = (struct net_device *) dev_id; - - if (dev == NULL) { - printk(KERN_ERR "%s: isr: null dev ptr\n", dev->name); - return; - } + struct net_device *dev = dev_id; writel(0, IR_INT_CLEAR); /* ack irda interrupts */ au1k_irda_rx(dev); au1k_tx_ack(dev); + + return IRQ_HANDLED; } diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index c6355c00fd7..9081234ab45 100644 --- a/drivers/net/irda/irda-usb.c +++ b/drivers/net/irda/irda-usb.c @@ -1168,6 +1168,7 @@ static int stir421x_patch_device(struct irda_usb_cb *self) static int irda_usb_net_open(struct net_device *netdev) { struct irda_usb_cb *self; + unsigned long flags; char hwname[16]; int i; @@ -1177,13 +1178,16 @@ static int irda_usb_net_open(struct net_device *netdev) self = (struct irda_usb_cb *) netdev->priv; IRDA_ASSERT(self != NULL, return -1;); + spin_lock_irqsave(&self->lock, flags); /* Can only open the device if it's there */ if(!self->present) { + spin_unlock_irqrestore(&self->lock, flags); IRDA_WARNING("%s(), device not present!\n", __FUNCTION__); return -1; } if(self->needspatch) { + spin_unlock_irqrestore(&self->lock, flags); IRDA_WARNING("%s(), device needs patch\n", __FUNCTION__) ; return -EIO ; } @@ -1198,6 +1202,7 @@ static int irda_usb_net_open(struct net_device *netdev) /* To do *before* submitting Rx urbs and starting net Tx queue * Jean II */ self->netopen = 1; + spin_unlock_irqrestore(&self->lock, flags); /* * Now that everything should be initialized properly, diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c index 2c6f7be36e8..fc753d7f674 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/irda/mcs7780.c b/drivers/net/irda/mcs7780.c index 0b769192d4c..93916cf33f2 100644 --- a/drivers/net/irda/mcs7780.c +++ b/drivers/net/irda/mcs7780.c @@ -677,6 +677,8 @@ static int mcs_net_close(struct net_device *netdev) /* Stop transmit processing */ netif_stop_queue(netdev); + kfree_skb(mcs->rx_buff.skb); + /* kill and free the receive and transmit URBs */ usb_kill_urb(mcs->rx_urb); usb_free_urb(mcs->rx_urb); diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c index 042bc2f0417..e59c485bc49 100644 --- a/drivers/net/irda/stir4200.c +++ b/drivers/net/irda/stir4200.c @@ -142,9 +142,6 @@ enum StirCtrl2Mask { }; enum StirFifoCtlMask { - FIFOCTL_EOF = 0x80, - FIFOCTL_UNDER = 0x40, - FIFOCTL_OVER = 0x20, FIFOCTL_DIR = 0x10, FIFOCTL_CLR = 0x08, FIFOCTL_EMPTY = 0x04, @@ -594,9 +591,10 @@ static int fifo_txwait(struct stir_cb *stir, int space) { int err; unsigned long count, status; + unsigned long prev_count = 0x1fff; /* Read FIFO status and count */ - for(;;) { + for (;; prev_count = count) { err = read_reg(stir, REG_FIFOCTL, stir->fifo_status, FIFO_REGS_SIZE); if (unlikely(err != FIFO_REGS_SIZE)) { @@ -629,6 +627,10 @@ static int fifo_txwait(struct stir_cb *stir, int space) if (space >= 0 && STIR_FIFO_SIZE - 4 > space + count) return 0; + /* queue confused */ + if (prev_count < count) + break; + /* estimate transfer time for remaining chars */ msleep((count * 8000) / stir->speed); } diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h index 1eee8894c73..3d2e7217e9a 100644 --- a/drivers/net/ixgb/ixgb.h +++ b/drivers/net/ixgb/ixgb.h @@ -196,4 +196,11 @@ struct ixgb_adapter { uint32_t alloc_rx_buff_failed; boolean_t have_msi; }; + +/* Exported from other modules */ +extern void ixgb_check_options(struct ixgb_adapter *adapter); +extern void ixgb_set_ethtool_ops(struct net_device *netdev); +extern char ixgb_driver_name[]; +extern const char ixgb_driver_version[]; + #endif /* _IXGB_H_ */ diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c index fddd5844168..a267dd86252 100644 --- a/drivers/net/ixgb/ixgb_ethtool.c +++ b/drivers/net/ixgb/ixgb_ethtool.c @@ -32,9 +32,6 @@ #include <asm/uaccess.h> -extern char ixgb_driver_name[]; -extern char ixgb_driver_version[]; - extern int ixgb_up(struct ixgb_adapter *adapter); extern void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog); extern void ixgb_reset(struct ixgb_adapter *adapter); @@ -639,8 +636,8 @@ ixgb_phys_id(struct net_device *netdev, uint32_t data) { struct ixgb_adapter *adapter = netdev_priv(netdev); - if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ); + if (!data) + data = INT_MAX; if(!adapter->blink_timer.function) { init_timer(&adapter->blink_timer); diff --git a/drivers/net/ixgb/ixgb_hw.c b/drivers/net/ixgb/ixgb_hw.c index ecbf45861c6..2c6367ace3c 100644 --- a/drivers/net/ixgb/ixgb_hw.c +++ b/drivers/net/ixgb/ixgb_hw.c @@ -1174,7 +1174,7 @@ mac_addr_valid(uint8_t *mac_addr) * * hw - Struct containing variables accessed by shared code *****************************************************************************/ -boolean_t +static boolean_t ixgb_link_reset(struct ixgb_hw *hw) { boolean_t link_status = FALSE; @@ -1205,7 +1205,7 @@ ixgb_link_reset(struct ixgb_hw *hw) * * hw - Struct containing variables accessed by shared code *****************************************************************************/ -void +static void ixgb_optics_reset(struct ixgb_hw *hw) { if (hw->phy_type == ixgb_phy_type_txn17401) { diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index d444de58ba3..d2fb88d5cda 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -37,8 +37,8 @@ static char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver"; #define DRIVERNAPI "-NAPI" #endif #define DRV_VERSION "1.0.126-k2"DRIVERNAPI -char ixgb_driver_version[] = DRV_VERSION; -static char ixgb_copyright[] = "Copyright (c) 1999-2006 Intel Corporation."; +const char ixgb_driver_version[] = DRV_VERSION; +static const char ixgb_copyright[] = "Copyright (c) 1999-2006 Intel Corporation."; /* ixgb_pci_tbl - PCI Device ID Table * @@ -104,7 +104,6 @@ static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter, static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter); #endif static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter); -void ixgb_set_ethtool_ops(struct net_device *netdev); static void ixgb_tx_timeout(struct net_device *dev); static void ixgb_tx_timeout_task(struct work_struct *work); static void ixgb_vlan_rx_register(struct net_device *netdev, @@ -123,9 +122,6 @@ static pci_ers_result_t ixgb_io_error_detected (struct pci_dev *pdev, static pci_ers_result_t ixgb_io_slot_reset (struct pci_dev *pdev); static void ixgb_io_resume (struct pci_dev *pdev); -/* Exported from other modules */ -extern void ixgb_check_options(struct ixgb_adapter *adapter); - static struct pci_error_handlers ixgb_err_handler = { .error_detected = ixgb_io_error_detected, .slot_reset = ixgb_io_slot_reset, @@ -324,10 +320,22 @@ ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog) void ixgb_reset(struct ixgb_adapter *adapter) { + struct ixgb_hw *hw = &adapter->hw; - ixgb_adapter_stop(&adapter->hw); - if(!ixgb_init_hw(&adapter->hw)) + ixgb_adapter_stop(hw); + if (!ixgb_init_hw(hw)) DPRINTK(PROBE, ERR, "ixgb_init_hw failed.\n"); + + /* restore frame size information */ + IXGB_WRITE_REG(hw, MFS, hw->max_frame_size << IXGB_MFS_SHIFT); + if (hw->max_frame_size > + IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH) { + u32 ctrl0 = IXGB_READ_REG(hw, CTRL0); + if (!(ctrl0 & IXGB_CTRL0_JFE)) { + ctrl0 |= IXGB_CTRL0_JFE; + IXGB_WRITE_REG(hw, CTRL0, ctrl0); + } + } } /** @@ -1085,7 +1093,8 @@ ixgb_set_multi(struct net_device *netdev) rctl |= IXGB_RCTL_MPE; IXGB_WRITE_REG(hw, RCTL, rctl); } else { - uint8_t mta[netdev->mc_count * IXGB_ETH_LENGTH_OF_ADDRESS]; + uint8_t mta[IXGB_MAX_NUM_MULTICAST_ADDRESSES * + IXGB_ETH_LENGTH_OF_ADDRESS]; IXGB_WRITE_REG(hw, RCTL, rctl); @@ -1324,8 +1333,8 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb, /* Workaround for premature desc write-backs * in TSO mode. Append 4-byte sentinel desc */ - if (unlikely(mss && !nr_frags && size == len - && size > 8)) + if (unlikely(mss && (f == (nr_frags - 1)) + && size == len && size > 8)) size -= 4; buffer_info->length = size; @@ -1778,14 +1787,13 @@ ixgb_clean(struct napi_struct *napi, int budget) { struct ixgb_adapter *adapter = container_of(napi, struct ixgb_adapter, napi); struct net_device *netdev = adapter->netdev; - int tx_cleaned; int work_done = 0; - tx_cleaned = ixgb_clean_tx_irq(adapter); + ixgb_clean_tx_irq(adapter); ixgb_clean_rx_irq(adapter, &work_done, budget); - /* if no Tx and not enough Rx work done, exit the polling mode */ - if((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) { + /* If budget not fully consumed, exit the polling mode */ + if (work_done < budget) { netif_rx_complete(netdev, napi); ixgb_irq_enable(adapter); } diff --git a/drivers/net/ixgb/ixgb_param.c b/drivers/net/ixgb/ixgb_param.c index 5d5ddabf436..865d14d6e5a 100644 --- a/drivers/net/ixgb/ixgb_param.c +++ b/drivers/net/ixgb/ixgb_param.c @@ -44,10 +44,11 @@ */ #define IXGB_PARAM_INIT { [0 ... IXGB_MAX_NIC] = OPTION_UNSET } -#define IXGB_PARAM(X, desc) \ - static int __devinitdata X[IXGB_MAX_NIC+1] = IXGB_PARAM_INIT; \ - static int num_##X = 0; \ - module_param_array_named(X, X, int, &num_##X, 0); \ +#define IXGB_PARAM(X, desc) \ + static int __devinitdata X[IXGB_MAX_NIC+1] \ + = IXGB_PARAM_INIT; \ + static unsigned int num_##X = 0; \ + module_param_array_named(X, X, int, &num_##X, 0); \ MODULE_PARM_DESC(X, desc); /* Transmit Descriptor Count @@ -178,8 +179,8 @@ IXGB_PARAM(IntDelayEnable, "Transmit Interrupt Delay Enable"); struct ixgb_option { enum { enable_option, range_option, list_option } type; - char *name; - char *err; + const char *name; + const char *err; int def; union { struct { /* range_option info */ @@ -197,7 +198,7 @@ struct ixgb_option { }; static int __devinit -ixgb_validate_option(int *value, struct ixgb_option *opt) +ixgb_validate_option(unsigned int *value, const struct ixgb_option *opt) { if(*value == OPTION_UNSET) { *value = opt->def; @@ -266,7 +267,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) } { /* Transmit Descriptor Count */ - struct ixgb_option opt = { + const struct ixgb_option opt = { .type = range_option, .name = "Transmit Descriptors", .err = "using default of " __MODULE_STRING(DEFAULT_TXD), @@ -285,7 +286,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) tx_ring->count = ALIGN(tx_ring->count, IXGB_REQ_TX_DESCRIPTOR_MULTIPLE); } { /* Receive Descriptor Count */ - struct ixgb_option opt = { + const struct ixgb_option opt = { .type = range_option, .name = "Receive Descriptors", .err = "using default of " __MODULE_STRING(DEFAULT_RXD), @@ -304,7 +305,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) rx_ring->count = ALIGN(rx_ring->count, IXGB_REQ_RX_DESCRIPTOR_MULTIPLE); } { /* Receive Checksum Offload Enable */ - struct ixgb_option opt = { + const struct ixgb_option opt = { .type = enable_option, .name = "Receive Checksum Offload", .err = "defaulting to Enabled", @@ -312,7 +313,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) }; if(num_XsumRX > bd) { - int rx_csum = XsumRX[bd]; + unsigned int rx_csum = XsumRX[bd]; ixgb_validate_option(&rx_csum, &opt); adapter->rx_csum = rx_csum; } else { @@ -328,7 +329,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) { ixgb_fc_full, "Flow Control Enabled" }, { ixgb_fc_default, "Flow Control Hardware Default" }}; - struct ixgb_option opt = { + const struct ixgb_option opt = { .type = list_option, .name = "Flow Control", .err = "reading default settings from EEPROM", @@ -338,7 +339,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) }; if(num_FlowControl > bd) { - int fc = FlowControl[bd]; + unsigned int fc = FlowControl[bd]; ixgb_validate_option(&fc, &opt); adapter->hw.fc.type = fc; } else { @@ -346,7 +347,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) } } { /* Receive Flow Control High Threshold */ - struct ixgb_option opt = { + const struct ixgb_option opt = { .type = range_option, .name = "Rx Flow Control High Threshold", .err = "using default of " __MODULE_STRING(DEFAULT_FCRTH), @@ -366,7 +367,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) "Ignoring RxFCHighThresh when no RxFC\n"); } { /* Receive Flow Control Low Threshold */ - struct ixgb_option opt = { + const struct ixgb_option opt = { .type = range_option, .name = "Rx Flow Control Low Threshold", .err = "using default of " __MODULE_STRING(DEFAULT_FCRTL), @@ -386,7 +387,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) "Ignoring RxFCLowThresh when no RxFC\n"); } { /* Flow Control Pause Time Request*/ - struct ixgb_option opt = { + const struct ixgb_option opt = { .type = range_option, .name = "Flow Control Pause Time Request", .err = "using default of "__MODULE_STRING(DEFAULT_FCPAUSE), @@ -396,7 +397,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) }; if(num_FCReqTimeout > bd) { - int pause_time = FCReqTimeout[bd]; + unsigned int pause_time = FCReqTimeout[bd]; ixgb_validate_option(&pause_time, &opt); adapter->hw.fc.pause_time = pause_time; } else { @@ -419,7 +420,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) } } { /* Receive Interrupt Delay */ - struct ixgb_option opt = { + const struct ixgb_option opt = { .type = range_option, .name = "Receive Interrupt Delay", .err = "using default of " __MODULE_STRING(DEFAULT_RDTR), @@ -436,7 +437,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) } } { /* Transmit Interrupt Delay */ - struct ixgb_option opt = { + const struct ixgb_option opt = { .type = range_option, .name = "Transmit Interrupt Delay", .err = "using default of " __MODULE_STRING(DEFAULT_TIDV), @@ -454,7 +455,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) } { /* Transmit Interrupt Delay Enable */ - struct ixgb_option opt = { + const struct ixgb_option opt = { .type = enable_option, .name = "Tx Interrupt Delay Enable", .err = "defaulting to Enabled", @@ -462,7 +463,7 @@ ixgb_check_options(struct ixgb_adapter *adapter) }; if(num_IntDelayEnable > bd) { - int ide = IntDelayEnable[bd]; + unsigned int ide = IntDelayEnable[bd]; ixgb_validate_option(&ide, &opt); adapter->tx_int_delay_enable = ide; } else { diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index c160a7d91e2..bc51432b8d2 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -244,7 +244,7 @@ extern struct ixgbe_info ixgbe_82598EB_info; extern struct ixgbe_info ixgbe_82598AT_info; extern char ixgbe_driver_name[]; -extern char ixgbe_driver_version[]; +extern const char ixgbe_driver_version[]; extern int ixgbe_up(struct ixgbe_adapter *adapter); extern void ixgbe_down(struct ixgbe_adapter *adapter); diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index 00ee20125ca..4d64673164c 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -30,8 +30,7 @@ #include <linux/delay.h> #include <linux/sched.h> -#include "ixgbe_type.h" -#include "ixgbe_common.h" +#include "ixgbe.h" #include "ixgbe_phy.h" #define IXGBE_82598_MAX_TX_QUEUES 32 diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index b75f1c6efc4..de3f45e4c5a 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -45,12 +45,13 @@ #include "ixgbe_common.h" char ixgbe_driver_name[] = "ixgbe"; -static char ixgbe_driver_string[] = - "Intel(R) 10 Gigabit PCI Express Network Driver"; +static const char ixgbe_driver_string[] = + "Intel(R) 10 Gigabit PCI Express Network Driver"; #define DRV_VERSION "1.1.18" -char ixgbe_driver_version[] = DRV_VERSION; -static char ixgbe_copyright[] = "Copyright (c) 1999-2007 Intel Corporation."; +const char ixgbe_driver_version[] = DRV_VERSION; +static const char ixgbe_copyright[] = + "Copyright (c) 1999-2007 Intel Corporation."; static const struct ixgbe_info *ixgbe_info_tbl[] = { [board_82598AF] = &ixgbe_82598AF_info, @@ -1469,19 +1470,16 @@ static int ixgbe_clean(struct napi_struct *napi, int budget) struct net_device *netdev = adapter->netdev; int tx_cleaned = 0, work_done = 0; - /* Keep link state information with original netdev */ - if (!netif_carrier_ok(adapter->netdev)) - goto quit_polling; - /* In non-MSIX case, there is no multi-Tx/Rx queue */ tx_cleaned = ixgbe_clean_tx_irq(adapter, adapter->tx_ring); ixgbe_clean_rx_irq(adapter, &adapter->rx_ring[0], &work_done, budget); - /* If no Tx and not enough Rx work done, exit the polling mode */ - if ((!tx_cleaned && (work_done < budget)) || - !netif_running(adapter->netdev)) { -quit_polling: + if (tx_cleaned) + work_done = budget; + + /* If budget not fully consumed, exit the polling mode */ + if (work_done < budget) { netif_rx_complete(netdev, napi); ixgbe_irq_enable(adapter); } diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c index 6c0dd49149d..484cb2ba717 100644 --- a/drivers/net/ixp2000/ixpdev.c +++ b/drivers/net/ixp2000/ixpdev.c @@ -135,8 +135,6 @@ static int ixpdev_poll(struct napi_struct *napi, int budget) struct net_device *dev = ip->dev; int rx; - /* @@@ Have to stop polling when nds[0] is administratively - * downed while we are polling. */ rx = 0; do { ixp2000_reg_write(IXP2000_IRQ_THD_RAW_STATUS_A_0, 0x00ff); diff --git a/drivers/net/lib82596.c b/drivers/net/lib82596.c index 9a855e51214..b59f442bbf3 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 45f30a2974b..fa147cd5d68 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -242,7 +242,7 @@ static void loopback_setup(struct net_device *dev) | NETIF_F_NO_CSUM | NETIF_F_HIGHDMA | NETIF_F_LLTX - | NETIF_F_NETNS_LOCAL, + | NETIF_F_NETNS_LOCAL; dev->ethtool_ops = &loopback_ethtool_ops; dev->header_ops = ð_header_ops; dev->init = loopback_dev_init; @@ -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/macb.c b/drivers/net/macb.c index 047ea7be485..e10528ed908 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -307,8 +307,31 @@ static void macb_tx(struct macb *bp) (unsigned long)status); if (status & MACB_BIT(UND)) { + int i; printk(KERN_ERR "%s: TX underrun, resetting buffers\n", - bp->dev->name); + bp->dev->name); + + head = bp->tx_head; + + /*Mark all the buffer as used to avoid sending a lost buffer*/ + for (i = 0; i < TX_RING_SIZE; i++) + bp->tx_ring[i].ctrl = MACB_BIT(TX_USED); + + /* free transmit buffer in upper layer*/ + for (tail = bp->tx_tail; tail != head; tail = NEXT_TX(tail)) { + struct ring_info *rp = &bp->tx_skb[tail]; + struct sk_buff *skb = rp->skb; + + BUG_ON(skb == NULL); + + rmb(); + + dma_unmap_single(&bp->pdev->dev, rp->mapping, skb->len, + DMA_TO_DEVICE); + rp->skb = NULL; + dev_kfree_skb_irq(skb); + } + bp->tx_head = bp->tx_tail = 0; } diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 2e4bcd5654c..e8dc2f44fec 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -384,6 +384,13 @@ static int macvlan_newlink(struct net_device *dev, if (lowerdev == NULL) return -ENODEV; + /* Don't allow macvlans on top of other macvlans - its not really + * wrong, but lockdep can't handle it and its not useful for anything + * you couldn't do directly on top of the real device. + */ + if (lowerdev->rtnl_link_ops == dev->rtnl_link_ops) + return -ENODEV; + if (!tb[IFLA_MTU]) dev->mtu = lowerdev->mtu; else if (dev->mtu > lowerdev->mtu) diff --git a/drivers/net/meth.c b/drivers/net/meth.c index e25dbab6736..cdaa8fc2180 100644 --- a/drivers/net/meth.c +++ b/drivers/net/meth.c @@ -33,7 +33,6 @@ #include <asm/ip32/ip32_ints.h> #include <asm/io.h> -#include <asm/scatterlist.h> #include "meth.h" @@ -96,11 +95,14 @@ static inline void load_eaddr(struct net_device *dev) { int i; DECLARE_MAC_BUF(mac); + u64 macaddr; - for (i = 0; i < 6; i++) - dev->dev_addr[i] = o2meth_eaddr[i]; DPRINTK("Loading MAC Address: %s\n", print_mac(mac, dev->dev_addr)); - mace->eth.mac_addr = (*(unsigned long*)o2meth_eaddr) >> 16; + macaddr = 0; + for (i = 0; i < 6; i++) + macaddr |= dev->dev_addr[i] << ((5 - i) * 8); + + mace->eth.mac_addr = macaddr; } /* @@ -795,6 +797,7 @@ static int __init meth_probe(struct platform_device *pdev) #endif dev->irq = MACE_ETHERNET_IRQ; dev->base_addr = (unsigned long)&mace->eth; + memcpy(dev->dev_addr, o2meth_eaddr, 6); priv = netdev_priv(dev); spin_lock_init(&priv->meth_lock); diff --git a/drivers/net/mlx4/alloc.c b/drivers/net/mlx4/alloc.c index f8d63d39f59..b226e019bc8 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 cc4b1be1821..fa24e659759 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/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 366e62a2b1e..c90958f6d3f 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -1151,7 +1151,7 @@ static inline int myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int budget) u16 length; __wsum checksum; - while (rx_done->entry[idx].length != 0 && work_done++ < budget) { + while (rx_done->entry[idx].length != 0 && work_done < budget) { length = ntohs(rx_done->entry[idx].length); rx_done->entry[idx].length = 0; checksum = csum_unfold(rx_done->entry[idx].checksum); @@ -1167,6 +1167,7 @@ static inline int myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int budget) rx_bytes += rx_ok * (unsigned long)length; cnt++; idx = cnt & (myri10ge_max_intr_slots - 1); + work_done++; } rx_done->idx = idx; rx_done->cnt = cnt; @@ -1233,13 +1234,12 @@ static int myri10ge_poll(struct napi_struct *napi, int budget) struct myri10ge_priv *mgp = container_of(napi, struct myri10ge_priv, napi); struct net_device *netdev = mgp->dev; - struct myri10ge_rx_done *rx_done = &mgp->rx_done; int work_done; /* process as many rx events as NAPI will allow */ work_done = myri10ge_clean_rx_done(mgp, budget); - if (rx_done->entry[rx_done->idx].length == 0 || !netif_running(netdev)) { + if (work_done < budget) { netif_rx_complete(netdev, napi); put_be32(htonl(3), mgp->irq_claim); } @@ -1979,6 +1979,7 @@ static int myri10ge_open(struct net_device *dev) lro_mgr->lro_arr = mgp->rx_done.lro_desc; lro_mgr->get_frag_header = myri10ge_get_frag_header; lro_mgr->max_aggr = myri10ge_lro_max_pkts; + lro_mgr->frag_align_pad = 2; if (lro_mgr->max_aggr > MAX_SKB_FRAGS) lro_mgr->max_aggr = MAX_SKB_FRAGS; diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index 8d29319cc5c..656a260fc95 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/natsemi.c b/drivers/net/natsemi.c index 87cde062fd6..c329a4f5840 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -2266,7 +2266,7 @@ static int natsemi_poll(struct napi_struct *napi, int budget) /* Reenable interrupts providing nothing is trying to shut * the chip down. */ spin_lock(&np->lock); - if (!np->hands_off && netif_running(dev)) + if (!np->hands_off) natsemi_irq_enable(dev); spin_unlock(&np->lock); diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c index eb0aff787df..78d34af13a1 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; } @@ -169,8 +169,8 @@ static void netx_eth_receive(struct net_device *ndev) ndev->last_rx = jiffies; skb->protocol = eth_type_trans(skb, ndev); netif_rx(skb); - dev->stats.rx_packets++; - dev->stats.rx_bytes += len; + ndev->stats.rx_packets++; + ndev->stats.rx_bytes += len; } static irqreturn_t diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index fbc2553275d..a8f63c47b3c 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -65,8 +65,8 @@ #define _NETXEN_NIC_LINUX_MAJOR 3 #define _NETXEN_NIC_LINUX_MINOR 4 -#define _NETXEN_NIC_LINUX_SUBVERSION 2 -#define NETXEN_NIC_LINUX_VERSIONID "3.4.2" +#define _NETXEN_NIC_LINUX_SUBVERSION 18 +#define NETXEN_NIC_LINUX_VERSIONID "3.4.18" #define NETXEN_NUM_FLASH_SECTORS (64) #define NETXEN_FLASH_SECTOR_SIZE (64 * 1024) @@ -309,23 +309,26 @@ struct netxen_ring_ctx { ((cmd_desc)->port_ctxid |= ((var) & 0xF0)) #define netxen_set_cmd_desc_flags(cmd_desc, val) \ - ((cmd_desc)->flags_opcode &= ~cpu_to_le16(0x7f), \ - (cmd_desc)->flags_opcode |= cpu_to_le16((val) & 0x7f)) + (cmd_desc)->flags_opcode = ((cmd_desc)->flags_opcode & \ + ~cpu_to_le16(0x7f)) | cpu_to_le16((val) & 0x7f) #define netxen_set_cmd_desc_opcode(cmd_desc, val) \ - ((cmd_desc)->flags_opcode &= ~cpu_to_le16(0x3f<<7), \ - (cmd_desc)->flags_opcode |= cpu_to_le16(((val & 0x3f)<<7))) + (cmd_desc)->flags_opcode = ((cmd_desc)->flags_opcode & \ + ~cpu_to_le16((u16)0x3f << 7)) | cpu_to_le16(((val) & 0x3f) << 7) #define netxen_set_cmd_desc_num_of_buff(cmd_desc, val) \ - ((cmd_desc)->num_of_buffers_total_length &= ~cpu_to_le32(0xff), \ - (cmd_desc)->num_of_buffers_total_length |= cpu_to_le32((val) & 0xff)) + (cmd_desc)->num_of_buffers_total_length = \ + ((cmd_desc)->num_of_buffers_total_length & \ + ~cpu_to_le32(0xff)) | cpu_to_le32((val) & 0xff) #define netxen_set_cmd_desc_totallength(cmd_desc, val) \ - ((cmd_desc)->num_of_buffers_total_length &= ~cpu_to_le32(0xffffff00), \ - (cmd_desc)->num_of_buffers_total_length |= cpu_to_le32(val << 8)) + (cmd_desc)->num_of_buffers_total_length = \ + ((cmd_desc)->num_of_buffers_total_length & \ + ~cpu_to_le32((u32)0xffffff << 8)) | \ + cpu_to_le32(((val) & 0xffffff) << 8) #define netxen_get_cmd_desc_opcode(cmd_desc) \ - ((le16_to_cpu((cmd_desc)->flags_opcode) >> 7) & 0x003F) + ((le16_to_cpu((cmd_desc)->flags_opcode) >> 7) & 0x003f) #define netxen_get_cmd_desc_totallength(cmd_desc) \ - (le32_to_cpu((cmd_desc)->num_of_buffers_total_length) >> 8) + ((le32_to_cpu((cmd_desc)->num_of_buffers_total_length) >> 8) & 0xffffff) struct cmd_desc_type0 { u8 tcp_hdr_offset; /* For LSO only */ @@ -412,29 +415,29 @@ struct rcv_desc { #define netxen_get_sts_desc_lro_last_frag(status_desc) \ (((status_desc)->lro & 0x80) >> 7) -#define netxen_get_sts_port(status_desc) \ - (le64_to_cpu((status_desc)->status_desc_data) & 0x0F) -#define netxen_get_sts_status(status_desc) \ - ((le64_to_cpu((status_desc)->status_desc_data) >> 4) & 0x0F) -#define netxen_get_sts_type(status_desc) \ - ((le64_to_cpu((status_desc)->status_desc_data) >> 8) & 0x0F) -#define netxen_get_sts_totallength(status_desc) \ - ((le64_to_cpu((status_desc)->status_desc_data) >> 12) & 0xFFFF) -#define netxen_get_sts_refhandle(status_desc) \ - ((le64_to_cpu((status_desc)->status_desc_data) >> 28) & 0xFFFF) -#define netxen_get_sts_prot(status_desc) \ - ((le64_to_cpu((status_desc)->status_desc_data) >> 44) & 0x0F) +#define netxen_get_sts_port(sts_data) \ + ((sts_data) & 0x0F) +#define netxen_get_sts_status(sts_data) \ + (((sts_data) >> 4) & 0x0F) +#define netxen_get_sts_type(sts_data) \ + (((sts_data) >> 8) & 0x0F) +#define netxen_get_sts_totallength(sts_data) \ + (((sts_data) >> 12) & 0xFFFF) +#define netxen_get_sts_refhandle(sts_data) \ + (((sts_data) >> 28) & 0xFFFF) +#define netxen_get_sts_prot(sts_data) \ + (((sts_data) >> 44) & 0x0F) +#define netxen_get_sts_opcode(sts_data) \ + (((sts_data) >> 58) & 0x03F) + #define netxen_get_sts_owner(status_desc) \ ((le64_to_cpu((status_desc)->status_desc_data) >> 56) & 0x03) -#define netxen_get_sts_opcode(status_desc) \ - ((le64_to_cpu((status_desc)->status_desc_data) >> 58) & 0x03F) - -#define netxen_clear_sts_owner(status_desc) \ - ((status_desc)->status_desc_data &= \ - ~cpu_to_le64(((unsigned long long)3) << 56 )) -#define netxen_set_sts_owner(status_desc, val) \ - ((status_desc)->status_desc_data |= \ - cpu_to_le64(((unsigned long long)((val) & 0x3)) << 56 )) +#define netxen_set_sts_owner(status_desc, val) { \ + (status_desc)->status_desc_data = \ + ((status_desc)->status_desc_data & \ + ~cpu_to_le64(0x3ULL << 56)) | \ + cpu_to_le64((u64)((val) & 0x3) << 56); \ +} struct status_desc { /* Bit pattern: 0-3 port, 4-7 status, 8-11 type, 12-27 total_length diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 37589265297..485ff939891 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -1070,16 +1070,17 @@ netxen_process_rcv(struct netxen_adapter *adapter, int ctxid, { struct pci_dev *pdev = adapter->pdev; struct net_device *netdev = adapter->netdev; - int index = netxen_get_sts_refhandle(desc); + u64 sts_data = le64_to_cpu(desc->status_desc_data); + int index = netxen_get_sts_refhandle(sts_data); struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctxid]); struct netxen_rx_buffer *buffer; struct sk_buff *skb; - u32 length = netxen_get_sts_totallength(desc); + u32 length = netxen_get_sts_totallength(sts_data); u32 desc_ctx; struct netxen_rcv_desc_ctx *rcv_desc; int ret; - desc_ctx = netxen_get_sts_type(desc); + desc_ctx = netxen_get_sts_type(sts_data); if (unlikely(desc_ctx >= NUM_RCV_DESC_RINGS)) { printk("%s: %s Bad Rcv descriptor ring\n", netxen_nic_driver_name, netdev->name); @@ -1119,7 +1120,7 @@ netxen_process_rcv(struct netxen_adapter *adapter, int ctxid, skb = (struct sk_buff *)buffer->skb; if (likely(adapter->rx_csum && - netxen_get_sts_status(desc) == STATUS_CKSUM_OK)) { + netxen_get_sts_status(sts_data) == STATUS_CKSUM_OK)) { adapter->stats.csummed++; skb->ip_summed = CHECKSUM_UNNECESSARY; } else @@ -1209,7 +1210,6 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max) break; } netxen_process_rcv(adapter, ctxid, desc); - netxen_clear_sts_owner(desc); netxen_set_sts_owner(desc, STATUS_OWNER_PHANTOM); consumer = (consumer + 1) & (adapter->max_rx_desc_count - 1); count++; @@ -1248,7 +1248,6 @@ int netxen_process_cmd_ring(unsigned long data) struct pci_dev *pdev; struct netxen_skb_frag *frag; u32 i; - struct sk_buff *skb = NULL; int done; spin_lock(&adapter->tx_lock); @@ -1278,9 +1277,8 @@ int netxen_process_cmd_ring(unsigned long data) while ((last_consumer != consumer) && (count1 < MAX_STATUS_HANDLE)) { buffer = &adapter->cmd_buf_arr[last_consumer]; pdev = adapter->pdev; - frag = &buffer->frag_array[0]; - skb = buffer->skb; - if (skb && (cmpxchg(&buffer->skb, skb, 0) == skb)) { + if (buffer->skb) { + frag = &buffer->frag_array[0]; pci_unmap_single(pdev, frag->dma, frag->length, PCI_DMA_TODEVICE); frag->dma = 0ULL; @@ -1293,8 +1291,8 @@ int netxen_process_cmd_ring(unsigned long data) } adapter->stats.skbfreed++; - dev_kfree_skb_any(skb); - skb = NULL; + dev_kfree_skb_any(buffer->skb); + buffer->skb = NULL; } else if (adapter->proc_cmd_buf_counter == 1) { adapter->stats.txnullskb++; } diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index a80f0cd6b52..263b55e36c7 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -732,11 +732,6 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) unregister_netdev(netdev); - if (adapter->stop_port) - adapter->stop_port(adapter); - - netxen_nic_disable_int(adapter); - if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) { init_firmware_done++; netxen_free_hw_resources(adapter); @@ -919,6 +914,9 @@ static int netxen_nic_close(struct net_device *netdev) netif_stop_queue(netdev); napi_disable(&adapter->napi); + if (adapter->stop_port) + adapter->stop_port(adapter); + netxen_nic_disable_int(adapter); cmd_buff = adapter->cmd_buf_arr; @@ -996,28 +994,6 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) return NETDEV_TX_OK; } - /* - * Everything is set up. Now, we just need to transmit it out. - * Note that we have to copy the contents of buffer over to - * right place. Later on, this can be optimized out by de-coupling the - * producer index from the buffer index. - */ - retry_getting_window: - spin_lock_bh(&adapter->tx_lock); - if (adapter->total_threads >= MAX_XMIT_PRODUCERS) { - spin_unlock_bh(&adapter->tx_lock); - /* - * Yield CPU - */ - if (!in_atomic()) - schedule(); - else { - for (i = 0; i < 20; i++) - cpu_relax(); /*This a nop instr on i386 */ - } - goto retry_getting_window; - } - local_producer = adapter->cmd_producer; /* There 4 fragments per descriptor */ no_of_desc = (frag_count + 3) >> 2; if (netdev->features & NETIF_F_TSO) { @@ -1031,16 +1007,19 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) } } } + + spin_lock_bh(&adapter->tx_lock); + if (adapter->total_threads >= MAX_XMIT_PRODUCERS) { + goto out_requeue; + } + local_producer = adapter->cmd_producer; k = adapter->cmd_producer; max_tx_desc_count = adapter->max_tx_desc_count; last_cmd_consumer = adapter->last_cmd_consumer; if ((k + no_of_desc) >= ((last_cmd_consumer <= k) ? last_cmd_consumer + max_tx_desc_count : last_cmd_consumer)) { - netif_stop_queue(netdev); - adapter->flags |= NETXEN_NETDEV_STATUS; - spin_unlock_bh(&adapter->tx_lock); - return NETDEV_TX_BUSY; + goto out_requeue; } k = get_index_range(k, max_tx_desc_count, no_of_desc); adapter->cmd_producer = k; @@ -1093,6 +1072,8 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) adapter->max_tx_desc_count); hwdesc = &hw->cmd_desc_head[producer]; memset(hwdesc, 0, sizeof(struct cmd_desc_type0)); + pbuf = &adapter->cmd_buf_arr[producer]; + pbuf->skb = NULL; } frag = &skb_shinfo(skb)->frags[i - 1]; len = frag->size; @@ -1148,6 +1129,8 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) } /* copy the MAC/IP/TCP headers to the cmd descriptor list */ hwdesc = &hw->cmd_desc_head[producer]; + pbuf = &adapter->cmd_buf_arr[producer]; + pbuf->skb = NULL; /* copy the first 64 bytes */ memcpy(((void *)hwdesc) + 2, @@ -1156,6 +1139,8 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) if (more_hdr) { hwdesc = &hw->cmd_desc_head[producer]; + pbuf = &adapter->cmd_buf_arr[producer]; + pbuf->skb = NULL; /* copy the next 64 bytes - should be enough except * for pathological case */ @@ -1167,16 +1152,8 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) } } - i = netxen_get_cmd_desc_totallength(&hw->cmd_desc_head[saved_producer]); - - hw->cmd_desc_head[saved_producer].flags_opcode = - cpu_to_le16(hw->cmd_desc_head[saved_producer].flags_opcode); - hw->cmd_desc_head[saved_producer].num_of_buffers_total_length = - cpu_to_le32(hw->cmd_desc_head[saved_producer]. - num_of_buffers_total_length); - spin_lock_bh(&adapter->tx_lock); - adapter->stats.txbytes += i; + adapter->stats.txbytes += skb->len; /* Code to update the adapter considering how many producer threads are currently working */ @@ -1189,14 +1166,17 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) } adapter->stats.xmitfinished++; - spin_unlock_bh(&adapter->tx_lock); - netdev->trans_start = jiffies; - DPRINTK(INFO, "wrote CMD producer %x to phantom\n", producer); - - DPRINTK(INFO, "Done. Send\n"); + spin_unlock_bh(&adapter->tx_lock); return NETDEV_TX_OK; + +out_requeue: + netif_stop_queue(netdev); + adapter->flags |= NETXEN_NETDEV_STATUS; + + spin_unlock_bh(&adapter->tx_lock); + return NETDEV_TX_BUSY; } static void netxen_watchdog(unsigned long v) @@ -1321,7 +1301,7 @@ static int netxen_nic_poll(struct napi_struct *napi, int budget) budget / MAX_RCV_CTX); } - if (work_done >= budget && netxen_nic_rx_has_work(adapter) != 0) + if (work_done >= budget) done = 0; if (netxen_process_cmd_ring((unsigned long)adapter) == 0) diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c index 5b9e1b300fa..d04ecb77d08 100644 --- a/drivers/net/netxen/netxen_nic_niu.c +++ b/drivers/net/netxen/netxen_nic_niu.c @@ -736,12 +736,12 @@ int netxen_niu_disable_xg_port(struct netxen_adapter *adapter) __u32 mac_cfg; u32 port = physical_port[adapter->portnum]; - if (port != 0) + if (port > NETXEN_NIU_MAX_XG_PORTS) return -EINVAL; + mac_cfg = 0; - netxen_xg_soft_reset(mac_cfg); - if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_CONFIG_0, - &mac_cfg, 4)) + if (netxen_nic_hw_write_wx(adapter, + NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), &mac_cfg, 4)) return -EIO; return 0; } diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 112ab079ce7..5f6beabf2d1 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -33,8 +33,8 @@ #define DRV_MODULE_NAME "niu" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "0.5" -#define DRV_MODULE_RELDATE "October 5, 2007" +#define DRV_MODULE_VERSION "0.6" +#define DRV_MODULE_RELDATE "January 5, 2008" static char version[] __devinitdata = DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; @@ -801,22 +801,90 @@ static int bcm8704_init_user_dev3(struct niu *np) return 0; } -static int xcvr_init_10g(struct niu *np) +static int mrvl88x2011_act_led(struct niu *np, int val) +{ + int err; + + err = mdio_read(np, np->phy_addr, MRVL88X2011_USER_DEV2_ADDR, + MRVL88X2011_LED_8_TO_11_CTL); + if (err < 0) + return err; + + err &= ~MRVL88X2011_LED(MRVL88X2011_LED_ACT,MRVL88X2011_LED_CTL_MASK); + err |= MRVL88X2011_LED(MRVL88X2011_LED_ACT,val); + + return mdio_write(np, np->phy_addr, MRVL88X2011_USER_DEV2_ADDR, + MRVL88X2011_LED_8_TO_11_CTL, err); +} + +static int mrvl88x2011_led_blink_rate(struct niu *np, int rate) +{ + int err; + + err = mdio_read(np, np->phy_addr, MRVL88X2011_USER_DEV2_ADDR, + MRVL88X2011_LED_BLINK_CTL); + if (err >= 0) { + err &= ~MRVL88X2011_LED_BLKRATE_MASK; + err |= (rate << 4); + + err = mdio_write(np, np->phy_addr, MRVL88X2011_USER_DEV2_ADDR, + MRVL88X2011_LED_BLINK_CTL, err); + } + + return err; +} + +static int xcvr_init_10g_mrvl88x2011(struct niu *np) +{ + int err; + + /* Set LED functions */ + err = mrvl88x2011_led_blink_rate(np, MRVL88X2011_LED_BLKRATE_134MS); + if (err) + return err; + + /* led activity */ + err = mrvl88x2011_act_led(np, MRVL88X2011_LED_CTL_OFF); + if (err) + return err; + + err = mdio_read(np, np->phy_addr, MRVL88X2011_USER_DEV3_ADDR, + MRVL88X2011_GENERAL_CTL); + if (err < 0) + return err; + + err |= MRVL88X2011_ENA_XFPREFCLK; + + err = mdio_write(np, np->phy_addr, MRVL88X2011_USER_DEV3_ADDR, + MRVL88X2011_GENERAL_CTL, err); + if (err < 0) + return err; + + err = mdio_read(np, np->phy_addr, MRVL88X2011_USER_DEV1_ADDR, + MRVL88X2011_PMA_PMD_CTL_1); + if (err < 0) + return err; + + if (np->link_config.loopback_mode == LOOPBACK_MAC) + err |= MRVL88X2011_LOOPBACK; + else + err &= ~MRVL88X2011_LOOPBACK; + + err = mdio_write(np, np->phy_addr, MRVL88X2011_USER_DEV1_ADDR, + MRVL88X2011_PMA_PMD_CTL_1, err); + if (err < 0) + return err; + + /* Enable PMD */ + return mdio_write(np, np->phy_addr, MRVL88X2011_USER_DEV1_ADDR, + MRVL88X2011_10G_PMD_TX_DIS, MRVL88X2011_ENA_PMDTX); +} + +static int xcvr_init_10g_bcm8704(struct niu *np) { struct niu_link_config *lp = &np->link_config; u16 analog_stat0, tx_alarm_status; int err; - u64 val; - - val = nr64_mac(XMAC_CONFIG); - val &= ~XMAC_CONFIG_LED_POLARITY; - val |= XMAC_CONFIG_FORCE_LED_ON; - nw64_mac(XMAC_CONFIG, val); - - /* XXX shared resource, lock parent XXX */ - val = nr64(MIF_CONFIG); - val |= MIF_CONFIG_INDIRECT_MODE; - nw64(MIF_CONFIG, val); err = bcm8704_reset(np); if (err) @@ -896,6 +964,38 @@ static int xcvr_init_10g(struct niu *np) return 0; } +static int xcvr_init_10g(struct niu *np) +{ + int phy_id, err; + u64 val; + + val = nr64_mac(XMAC_CONFIG); + val &= ~XMAC_CONFIG_LED_POLARITY; + val |= XMAC_CONFIG_FORCE_LED_ON; + nw64_mac(XMAC_CONFIG, val); + + /* XXX shared resource, lock parent XXX */ + val = nr64(MIF_CONFIG); + val |= MIF_CONFIG_INDIRECT_MODE; + nw64(MIF_CONFIG, val); + + phy_id = phy_decode(np->parent->port_phy, np->port); + phy_id = np->parent->phy_probe_info.phy_id[phy_id][np->port]; + + /* handle different phy types */ + switch (phy_id & NIU_PHY_ID_MASK) { + case NIU_PHY_ID_MRVL88X2011: + err = xcvr_init_10g_mrvl88x2011(np); + break; + + default: /* bcom 8704 */ + err = xcvr_init_10g_bcm8704(np); + break; + } + + return 0; +} + static int mii_reset(struct niu *np) { int limit, err; @@ -1045,6 +1145,7 @@ static int niu_serdes_init(struct niu *np) } static void niu_init_xif(struct niu *); +static void niu_handle_led(struct niu *, int status); static int niu_link_status_common(struct niu *np, int link_up) { @@ -1066,30 +1167,83 @@ static int niu_link_status_common(struct niu *np, int link_up) spin_lock_irqsave(&np->lock, flags); niu_init_xif(np); + niu_handle_led(np, 1); spin_unlock_irqrestore(&np->lock, flags); netif_carrier_on(dev); } else if (netif_carrier_ok(dev) && !link_up) { niuwarn(LINK, "%s: Link is down\n", dev->name); + spin_lock_irqsave(&np->lock, flags); + niu_handle_led(np, 0); + spin_unlock_irqrestore(&np->lock, flags); netif_carrier_off(dev); } return 0; } -static int link_status_10g(struct niu *np, int *link_up_p) +static int link_status_10g_mrvl(struct niu *np, int *link_up_p) { - unsigned long flags; - int err, link_up; + int err, link_up, pma_status, pcs_status; link_up = 0; - spin_lock_irqsave(&np->lock, flags); + err = mdio_read(np, np->phy_addr, MRVL88X2011_USER_DEV1_ADDR, + MRVL88X2011_10G_PMD_STATUS_2); + if (err < 0) + goto out; - err = -EINVAL; - if (np->link_config.loopback_mode != LOOPBACK_DISABLED) + /* Check PMA/PMD Register: 1.0001.2 == 1 */ + err = mdio_read(np, np->phy_addr, MRVL88X2011_USER_DEV1_ADDR, + MRVL88X2011_PMA_PMD_STATUS_1); + if (err < 0) + goto out; + + pma_status = ((err & MRVL88X2011_LNK_STATUS_OK) ? 1 : 0); + + /* Check PMC Register : 3.0001.2 == 1: read twice */ + err = mdio_read(np, np->phy_addr, MRVL88X2011_USER_DEV3_ADDR, + MRVL88X2011_PMA_PMD_STATUS_1); + if (err < 0) goto out; + err = mdio_read(np, np->phy_addr, MRVL88X2011_USER_DEV3_ADDR, + MRVL88X2011_PMA_PMD_STATUS_1); + if (err < 0) + goto out; + + pcs_status = ((err & MRVL88X2011_LNK_STATUS_OK) ? 1 : 0); + + /* Check XGXS Register : 4.0018.[0-3,12] */ + err = mdio_read(np, np->phy_addr, MRVL88X2011_USER_DEV4_ADDR, + MRVL88X2011_10G_XGXS_LANE_STAT); + if (err < 0) + goto out; + + if (err == (PHYXS_XGXS_LANE_STAT_ALINGED | PHYXS_XGXS_LANE_STAT_LANE3 | + PHYXS_XGXS_LANE_STAT_LANE2 | PHYXS_XGXS_LANE_STAT_LANE1 | + PHYXS_XGXS_LANE_STAT_LANE0 | PHYXS_XGXS_LANE_STAT_MAGIC | + 0x800)) + link_up = (pma_status && pcs_status) ? 1 : 0; + + np->link_config.active_speed = SPEED_10000; + np->link_config.active_duplex = DUPLEX_FULL; + err = 0; +out: + mrvl88x2011_act_led(np, (link_up ? + MRVL88X2011_LED_CTL_PCS_ACT : + MRVL88X2011_LED_CTL_OFF)); + + *link_up_p = link_up; + return err; +} + +static int link_status_10g_bcom(struct niu *np, int *link_up_p) +{ + int err, link_up; + + link_up = 0; + err = mdio_read(np, np->phy_addr, BCM8704_PMA_PMD_DEV_ADDR, BCM8704_PMD_RCV_SIGDET); if (err < 0) @@ -1129,14 +1283,43 @@ static int link_status_10g(struct niu *np, int *link_up_p) err = 0; out: + *link_up_p = link_up; + return err; +} + +static int link_status_10g(struct niu *np, int *link_up_p) +{ + unsigned long flags; + int err = -EINVAL; + + spin_lock_irqsave(&np->lock, flags); + + if (np->link_config.loopback_mode == LOOPBACK_DISABLED) { + int phy_id; + + phy_id = phy_decode(np->parent->port_phy, np->port); + phy_id = np->parent->phy_probe_info.phy_id[phy_id][np->port]; + + /* handle different phy types */ + switch (phy_id & NIU_PHY_ID_MASK) { + case NIU_PHY_ID_MRVL88X2011: + err = link_status_10g_mrvl(np, link_up_p); + break; + + default: /* bcom 8704 */ + err = link_status_10g_bcom(np, link_up_p); + break; + } + } + spin_unlock_irqrestore(&np->lock, flags); - *link_up_p = link_up; return err; } static int link_status_1g(struct niu *np, int *link_up_p) { + struct niu_link_config *lp = &np->link_config; u16 current_speed, bmsr; unsigned long flags; u8 current_duplex; @@ -1204,6 +1387,8 @@ static int link_status_1g(struct niu *np, int *link_up_p) link_up = 0; } } + lp->active_speed = current_speed; + lp->active_duplex = current_duplex; err = 0; out: @@ -2236,6 +2421,8 @@ static int niu_process_rx_pkt(struct niu *np, struct rx_ring_info *rp) skb->protocol = eth_type_trans(skb, np->dev); netif_receive_skb(skb); + np->dev->last_rx = jiffies; + return num_rcr; } @@ -2503,15 +2690,19 @@ static int niu_rx_error(struct niu *np, struct rx_ring_info *rp) u64 stat = nr64(RX_DMA_CTL_STAT(rp->rx_channel)); int err = 0; - dev_err(np->device, PFX "%s: RX channel %u error, stat[%llx]\n", - np->dev->name, rp->rx_channel, (unsigned long long) stat); - - niu_log_rxchan_errors(np, rp, stat); if (stat & (RX_DMA_CTL_STAT_CHAN_FATAL | RX_DMA_CTL_STAT_PORT_FATAL)) err = -EINVAL; + if (err) { + dev_err(np->device, PFX "%s: RX channel %u error, stat[%llx]\n", + np->dev->name, rp->rx_channel, + (unsigned long long) stat); + + niu_log_rxchan_errors(np, rp, stat); + } + nw64(RX_DMA_CTL_STAT(rp->rx_channel), stat & RX_DMA_CTL_WRITE_CLEAR_ERRS); @@ -2744,13 +2935,16 @@ static int niu_device_error(struct niu *np) return -ENODEV; } -static int niu_slowpath_interrupt(struct niu *np, struct niu_ldg *lp) +static int niu_slowpath_interrupt(struct niu *np, struct niu_ldg *lp, + u64 v0, u64 v1, u64 v2) { - u64 v0 = lp->v0; - u64 v1 = lp->v1; - u64 v2 = lp->v2; + int i, err = 0; + lp->v0 = v0; + lp->v1 = v1; + lp->v2 = v2; + if (v1 & 0x00000000ffffffffULL) { u32 rx_vec = (v1 & 0xffffffff); @@ -2759,8 +2953,13 @@ static int niu_slowpath_interrupt(struct niu *np, struct niu_ldg *lp) if (rx_vec & (1 << rp->rx_channel)) { int r = niu_rx_error(np, rp); - if (r) + if (r) { err = r; + } else { + if (!v0) + nw64(RX_DMA_CTL_STAT(rp->rx_channel), + RX_DMA_CTL_STAT_MEX); + } } } } @@ -2798,7 +2997,7 @@ static int niu_slowpath_interrupt(struct niu *np, struct niu_ldg *lp) if (err) niu_enable_interrupts(np, 0); - return -EINVAL; + return err; } static void niu_rxchan_intr(struct niu *np, struct rx_ring_info *rp, @@ -2900,7 +3099,7 @@ static irqreturn_t niu_interrupt(int irq, void *dev_id) } if (unlikely((v0 & ((u64)1 << LDN_MIF)) || v1 || v2)) { - int err = niu_slowpath_interrupt(np, lp); + int err = niu_slowpath_interrupt(np, lp, v0, v1, v2); if (err) goto out; } @@ -3915,16 +4114,14 @@ static int niu_init_ipp(struct niu *np) return 0; } -static void niu_init_xif_xmac(struct niu *np) +static void niu_handle_led(struct niu *np, int status) { - struct niu_link_config *lp = &np->link_config; u64 val; - val = nr64_mac(XMAC_CONFIG); if ((np->flags & NIU_FLAGS_10G) != 0 && (np->flags & NIU_FLAGS_FIBER) != 0) { - if (netif_carrier_ok(np->dev)) { + if (status) { val |= XMAC_CONFIG_LED_POLARITY; val &= ~XMAC_CONFIG_FORCE_LED_ON; } else { @@ -3933,6 +4130,15 @@ static void niu_init_xif_xmac(struct niu *np) } } + nw64_mac(XMAC_CONFIG, val); +} + +static void niu_init_xif_xmac(struct niu *np) +{ + struct niu_link_config *lp = &np->link_config; + u64 val; + + val = nr64_mac(XMAC_CONFIG); val &= ~XMAC_CONFIG_SEL_POR_CLK_SRC; val |= XMAC_CONFIG_TX_OUTPUT_EN; @@ -4776,6 +4982,8 @@ static int niu_close(struct net_device *dev) niu_free_channels(np); + niu_handle_led(np, 0); + return 0; } @@ -5180,7 +5388,8 @@ static int niu_start_xmit(struct sk_buff *skb, struct net_device *dev) } kfree_skb(skb); skb = skb_new; - } + } else + skb_orphan(skb); align = ((unsigned long) skb->data & (16 - 1)); headroom = align + sizeof(struct tx_pkt_hdr); @@ -6268,7 +6477,8 @@ static int __devinit phy_record(struct niu_parent *parent, if (dev_id_1 < 0 || dev_id_2 < 0) return 0; if (type == PHY_TYPE_PMA_PMD || type == PHY_TYPE_PCS) { - if ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM8704) + if (((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM8704) && + ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_MRVL88X2011)) return 0; } else { if ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM5464R) diff --git a/drivers/net/niu.h b/drivers/net/niu.h index 10e3f111b6d..0e8626adc57 100644 --- a/drivers/net/niu.h +++ b/drivers/net/niu.h @@ -2538,6 +2538,39 @@ struct fcram_hash_ipv6 { #define NIU_PHY_ID_MASK 0xfffff0f0 #define NIU_PHY_ID_BCM8704 0x00206030 #define NIU_PHY_ID_BCM5464R 0x002060b0 +#define NIU_PHY_ID_MRVL88X2011 0x01410020 + +/* MRVL88X2011 register addresses */ +#define MRVL88X2011_USER_DEV1_ADDR 1 +#define MRVL88X2011_USER_DEV2_ADDR 2 +#define MRVL88X2011_USER_DEV3_ADDR 3 +#define MRVL88X2011_USER_DEV4_ADDR 4 +#define MRVL88X2011_PMA_PMD_CTL_1 0x0000 +#define MRVL88X2011_PMA_PMD_STATUS_1 0x0001 +#define MRVL88X2011_10G_PMD_STATUS_2 0x0008 +#define MRVL88X2011_10G_PMD_TX_DIS 0x0009 +#define MRVL88X2011_10G_XGXS_LANE_STAT 0x0018 +#define MRVL88X2011_GENERAL_CTL 0x8300 +#define MRVL88X2011_LED_BLINK_CTL 0x8303 +#define MRVL88X2011_LED_8_TO_11_CTL 0x8306 + +/* MRVL88X2011 register control */ +#define MRVL88X2011_ENA_XFPREFCLK 0x0001 +#define MRVL88X2011_ENA_PMDTX 0x0000 +#define MRVL88X2011_LOOPBACK 0x1 +#define MRVL88X2011_LED_ACT 0x1 +#define MRVL88X2011_LNK_STATUS_OK 0x4 +#define MRVL88X2011_LED_BLKRATE_MASK 0x70 +#define MRVL88X2011_LED_BLKRATE_034MS 0x0 +#define MRVL88X2011_LED_BLKRATE_067MS 0x1 +#define MRVL88X2011_LED_BLKRATE_134MS 0x2 +#define MRVL88X2011_LED_BLKRATE_269MS 0x3 +#define MRVL88X2011_LED_BLKRATE_538MS 0x4 +#define MRVL88X2011_LED_CTL_OFF 0x0 +#define MRVL88X2011_LED_CTL_PCS_ACT 0x5 +#define MRVL88X2011_LED_CTL_MASK 0x7 +#define MRVL88X2011_LED(n,v) ((v)<<((n)*4)) +#define MRVL88X2011_LED_STAT(n,v) ((v)>>((n)*4)) #define BCM8704_PMA_PMD_DEV_ADDR 1 #define BCM8704_PCS_DEV_ADDR 2 diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c index ab4d309a858..816a59e801b 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++; + /* No need to free skb, it'll be reused */ + 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); @@ -1352,7 +1362,7 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netif_napi_add(dev, &mac->napi, pasemi_mac_poll, 64); - dev->features = NETIF_F_HW_CSUM | NETIF_F_LLTX | NETIF_F_SG; + dev->features = NETIF_F_IP_CSUM | NETIF_F_LLTX | NETIF_F_SG; /* These should come out of the device tree eventually */ mac->dma_txch = index; diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 73dcbb7296d..288177716a4 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -274,7 +274,7 @@ static int tc574_probe(struct pcmcia_device *link) spin_lock_init(&lp->window_lock); link->io.NumPorts1 = 32; link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_HANDLE_PRESENT; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->irq.Handler = &el3_interrupt; link->irq.Instance = dev; @@ -337,15 +337,15 @@ static int tc574_config(struct pcmcia_device *link) struct net_device *dev = link->priv; struct el3_private *lp = netdev_priv(dev); tuple_t tuple; - unsigned short buf[32]; + __le16 buf[32]; int last_fn, last_ret, i, j; kio_addr_t ioaddr; - u16 *phys_addr; + __be16 *phys_addr; char *cardname; union wn3_config config; DECLARE_MAC_BUF(mac); - phys_addr = (u16 *)dev->dev_addr; + phys_addr = (__be16 *)dev->dev_addr; DEBUG(0, "3c574_config(0x%p)\n", link); @@ -378,12 +378,12 @@ static int tc574_config(struct pcmcia_device *link) if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) { pcmcia_get_tuple_data(link, &tuple); for (i = 0; i < 3; i++) - phys_addr[i] = htons(buf[i]); + phys_addr[i] = htons(le16_to_cpu(buf[i])); } else { EL3WINDOW(0); for (i = 0; i < 3; i++) phys_addr[i] = htons(read_eeprom(ioaddr, i + 10)); - if (phys_addr[0] == 0x6060) { + if (phys_addr[0] == htons(0x6060)) { printk(KERN_NOTICE "3c574_cs: IO port conflict at 0x%03lx" "-0x%03lx\n", dev->base_addr, dev->base_addr+15); goto failed; diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 32076ca6a9e..e862d14ece7 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -188,7 +188,7 @@ static int tc589_probe(struct pcmcia_device *link) spin_lock_init(&lp->lock); link->io.NumPorts1 = 16; link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_HANDLE_PRESENT; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->irq.Handler = &el3_interrupt; link->irq.Instance = dev; @@ -251,7 +251,8 @@ static int tc589_config(struct pcmcia_device *link) struct net_device *dev = link->priv; struct el3_private *lp = netdev_priv(dev); tuple_t tuple; - u16 buf[32], *phys_addr; + __le16 buf[32]; + __be16 *phys_addr; int last_fn, last_ret, i, j, multi = 0, fifo; kio_addr_t ioaddr; char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; @@ -259,7 +260,7 @@ static int tc589_config(struct pcmcia_device *link) DEBUG(0, "3c589_config(0x%p)\n", link); - phys_addr = (u16 *)dev->dev_addr; + phys_addr = (__be16 *)dev->dev_addr; tuple.Attributes = 0; tuple.TupleData = (cisdata_t *)buf; tuple.TupleDataMax = sizeof(buf); @@ -298,11 +299,11 @@ static int tc589_config(struct pcmcia_device *link) if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) { pcmcia_get_tuple_data(link, &tuple); for (i = 0; i < 3; i++) - phys_addr[i] = htons(buf[i]); + phys_addr[i] = htons(le16_to_cpu(buf[i])); } else { for (i = 0; i < 3; i++) phys_addr[i] = htons(read_eeprom(ioaddr, i)); - if (phys_addr[0] == 0x6060) { + if (phys_addr[0] == htons(0x6060)) { printk(KERN_ERR "3c589_cs: IO port conflict at 0x%03lx" "-0x%03lx\n", dev->base_addr, dev->base_addr+15); goto failed; diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index a95a2cae6b2..8d910a372f8 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -158,7 +158,7 @@ static int axnet_probe(struct pcmcia_device *link) info = PRIV(dev); info->p_dev = link; link->priv = dev; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 62844677c78..8c719b4df54 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -249,7 +249,7 @@ static int fmvj18x_probe(struct pcmcia_device *link) link->io.IOAddrLines = 5; /* Interrupt setup */ - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_HANDLE_PRESENT; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->irq.Handler = &fjn_interrupt; link->irq.Instance = dev; diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 9d45e9696e1..51bbd582f16 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -254,7 +254,7 @@ static int pcnet_probe(struct pcmcia_device *link) info->p_dev = link; link->priv = dev; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; @@ -1746,6 +1746,7 @@ static struct pcmcia_device_id pcnet_ids[] = { PCMCIA_DEVICE_CIS_PROD_ID12("NDC", "Ethernet", 0x01c43ae1, 0x00b2e941, "NE2K.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("PMX ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "PE-200.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("TAMARACK", "Ethernet", 0xcf434fba, 0x00b2e941, "tamarack.cis"), + PCMCIA_DEVICE_PROD_ID12("Ethernet", "CF Size PC Card", 0x00b2e941, 0x43ac239b), PCMCIA_DEVICE_PROD_ID123("Fast Ethernet", "CF Size PC Card", "1.0", 0xb4be14e3, 0x43ac239b, 0x0877b627), PCMCIA_DEVICE_NULL diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 58d716fd17c..c9868e9dac4 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -328,7 +328,7 @@ static int smc91c92_probe(struct pcmcia_device *link) link->io.NumPorts1 = 16; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; link->io.IOAddrLines = 4; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_HANDLE_PRESENT; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->irq.Handler = &smc_interrupt; link->irq.Instance = dev; diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index c3b69602e27..1f09bea6db5 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -886,7 +886,7 @@ xirc2ps_config(struct pcmcia_device * link) } printk(KNOT_XIRC "no ports available\n"); } else { - link->irq.Attributes |= IRQ_TYPE_EXCLUSIVE; + link->irq.Attributes |= IRQ_TYPE_DYNAMIC_SHARING; link->io.NumPorts1 = 16; for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { link->io.BasePort1 = ioaddr; diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index ff92aca0a7b..90498ffe26f 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -455,9 +455,14 @@ static void pcnet32_netif_start(struct net_device *dev) { #ifdef CONFIG_PCNET32_NAPI struct pcnet32_private *lp = netdev_priv(dev); + ulong ioaddr = dev->base_addr; + u16 val; #endif netif_wake_queue(dev); #ifdef CONFIG_PCNET32_NAPI + val = lp->a.read_csr(ioaddr, CSR3); + val &= 0x00ff; + lp->a.write_csr(ioaddr, CSR3, val); napi_enable(&lp->napi); #endif } diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index d2ede5ff9ff..f0574073a2a 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; @@ -265,7 +273,7 @@ static struct phy_driver marvell_drivers[] = { .read_status = &genphy_read_status, .ack_interrupt = &marvell_ack_interrupt, .config_intr = &marvell_config_intr, - .driver = {.owner = THIS_MODULE,}, + .driver = { .owner = THIS_MODULE }, }, { .phy_id = 0x01410c90, @@ -278,7 +286,7 @@ static struct phy_driver marvell_drivers[] = { .read_status = &genphy_read_status, .ack_interrupt = &marvell_ack_interrupt, .config_intr = &marvell_config_intr, - .driver = {.owner = THIS_MODULE,}, + .driver = { .owner = THIS_MODULE }, }, { .phy_id = 0x01410cc0, @@ -291,7 +299,7 @@ static struct phy_driver marvell_drivers[] = { .read_status = &genphy_read_status, .ack_interrupt = &marvell_ack_interrupt, .config_intr = &marvell_config_intr, - .driver = {.owner = THIS_MODULE,}, + .driver = { .owner = THIS_MODULE }, }, { .phy_id = 0x01410cd0, @@ -304,8 +312,21 @@ static struct phy_driver marvell_drivers[] = { .read_status = &genphy_read_status, .ack_interrupt = &marvell_ack_interrupt, .config_intr = &marvell_config_intr, - .driver = {.owner = THIS_MODULE,}, - } + .driver = { .owner = THIS_MODULE }, + }, + { + .phy_id = 0x01410e30, + .phy_id_mask = 0xfffffff0, + .name = "Marvell 88E1240", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_init = &m88e1111_config_init, + .config_aneg = &marvell_config_aneg, + .read_status = &genphy_read_status, + .ack_interrupt = &marvell_ack_interrupt, + .config_intr = &marvell_config_intr, + .driver = { .owner = THIS_MODULE }, + }, }; static int __init marvell_init(void) diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index fc2f0e695a1..c30196d0ad1 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -91,9 +91,12 @@ int mdiobus_register(struct mii_bus *bus) err = device_register(&phydev->dev); - if (err) + if (err) { printk(KERN_ERR "phy %d failed to register\n", i); + phy_device_free(phydev); + phydev = NULL; + } } bus->phy_map[i] = phydev; @@ -110,10 +113,8 @@ void mdiobus_unregister(struct mii_bus *bus) int i; for (i = 0; i < PHY_MAX_ADDR; i++) { - if (bus->phy_map[i]) { + if (bus->phy_map[i]) device_unregister(&bus->phy_map[i]->dev); - kfree(bus->phy_map[i]); - } } } EXPORT_SYMBOL(mdiobus_unregister); diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 9bc11773705..7c9e6e34950 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/phy/phy_device.c b/drivers/net/phy/phy_device.c index c0461217b10..5b9e1751e1b 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -44,6 +44,16 @@ static struct phy_driver genphy_driver; extern int mdio_bus_init(void); extern void mdio_bus_exit(void); +void phy_device_free(struct phy_device *phydev) +{ + kfree(phydev); +} + +static void phy_device_release(struct device *dev) +{ + phy_device_free(to_phy_device(dev)); +} + struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id) { struct phy_device *dev; @@ -54,6 +64,8 @@ struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id) if (NULL == dev) return (struct phy_device*) PTR_ERR((void*)-ENOMEM); + dev->dev.release = phy_device_release; + dev->speed = 0; dev->duplex = -1; dev->pause = dev->asym_pause = 0; @@ -706,7 +718,7 @@ int phy_driver_register(struct phy_driver *new_driver) return retval; } - pr_info("%s: Registered new driver\n", new_driver->name); + pr_debug("%s: Registered new driver\n", new_driver->name); return 0; } diff --git a/drivers/net/plip.c b/drivers/net/plip.c index 5071fcd8a0b..57c98669984 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 27f5b904f48..f023d5b67e6 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 4b49d0e8c7e..4f690378bb7 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 ce64032a465..f0c6a1926a0 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/pppoe.c b/drivers/net/pppoe.c index 8936ed3469c..a005d8f4c38 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -491,7 +491,7 @@ static int pppoe_create(struct net *net, struct socket *sock) int error = -ENOMEM; struct sock *sk; - sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pppoe_sk_proto, 1); + sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pppoe_sk_proto); if (!sk) goto out; diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c index 921d4ef6d14..a7556cd2df7 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; @@ -1416,7 +1427,7 @@ static int pppol2tp_create(struct net *net, struct socket *sock) int error = -ENOMEM; struct sock *sk; - sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pppol2tp_sk_proto, 1); + sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pppol2tp_sk_proto); if (!sk) goto out; diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index 30adf726743..cf0774de6c4 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); } /* @@ -2315,14 +2320,9 @@ static int ql_poll(struct napi_struct *napi, int budget) unsigned long hw_flags; struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; - if (!netif_carrier_ok(ndev)) - goto quit_polling; - ql_tx_rx_clean(qdev, &tx_cleaned, &rx_cleaned, budget); - if (tx_cleaned + rx_cleaned != budget || - !netif_running(ndev)) { -quit_polling: + if (tx_cleaned + rx_cleaned != budget) { spin_lock_irqsave(&qdev->hw_lock, hw_flags); __netif_rx_complete(ndev, napi); ql_update_small_bufq_prod_index(qdev); @@ -3941,19 +3941,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 +4091,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 fbcb0b94963..d0ffb30ef37 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 e8960f294a6..3acfeeabdee 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,}, }; @@ -392,7 +394,9 @@ struct rtl8169_private { void __iomem *mmio_addr; /* memory map physical address */ struct pci_dev *pci_dev; /* Index of PCI device */ struct net_device *dev; +#ifdef CONFIG_R8169_NAPI struct napi_struct napi; +#endif spinlock_t lock; /* spin lock flag */ u32 msg_enable; int chipset; @@ -466,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--) { /* @@ -483,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--) { /* @@ -491,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); @@ -1243,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) { @@ -1322,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; @@ -1737,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; @@ -2012,7 +2002,7 @@ static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) u32 clk; clk = RTL_R8(Config2) & PCI_Clock_66MHz; - for (i = 0; i < ARRAY_SIZE(cfg2_info); i++) { + for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) { if ((p->mac_version == mac_version) && (p->clk == clk)) { RTL_W32(0x7c, p->val); break; @@ -2221,7 +2211,7 @@ out: static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) { - desc->addr = 0x0badbadbadbadbadull; + desc->addr = cpu_to_le64(0x0badbadbadbadbadull); desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); } @@ -2408,6 +2398,8 @@ static void rtl8169_wait_for_quiescence(struct net_device *dev) rtl8169_irq_mask_and_ack(ioaddr); #ifdef CONFIG_R8169_NAPI + tp->intr_mask = 0xffff; + RTL_W16(IntrMask, tp->intr_event); napi_enable(&tp->napi); #endif } @@ -2845,7 +2837,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev, } /* Work around for AMD plateform. */ - if ((desc->opts2 & 0xfffe000) && + if ((desc->opts2 & cpu_to_le32(0xfffe000)) && (tp->mac_version == RTL_GIGA_MAC_VER_05)) { desc->opts2 = 0; cur_rx++; @@ -2989,13 +2981,16 @@ static void rtl8169_down(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; - unsigned int poll_locked = 0; unsigned int intrmask; rtl8169_delete_timer(dev); netif_stop_queue(dev); +#ifdef CONFIG_R8169_NAPI + napi_disable(&tp->napi); +#endif + core_down: spin_lock_irq(&tp->lock); @@ -3009,11 +3004,6 @@ core_down: synchronize_irq(dev->irq); - if (!poll_locked) { - napi_disable(&tp->napi); - poll_locked++; - } - /* Give a racing hard_start_xmit a few cycles to complete. */ synchronize_sched(); /* FIXME: should this be synchronize_irq()? */ diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c index b822859c8de..55a590ab1e1 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) { @@ -300,7 +294,6 @@ static int rr_reset(struct net_device *dev) { struct rr_private *rrpriv; struct rr_regs __iomem *regs; - struct eeprom *hw = NULL; u32 start_pc; int i; @@ -387,7 +380,8 @@ static int rr_reset(struct net_device *dev) writel(RBURST_64|WBURST_64, ®s->PciState); wmb(); - start_pc = rr_read_eeprom_word(rrpriv, &hw->rncd_info.FwStart); + start_pc = rr_read_eeprom_word(rrpriv, + offsetof(struct eeprom, rncd_info.FwStart)); #if (DEBUG > 1) printk("%s: Executing firmware at address 0x%06x\n", @@ -444,12 +438,12 @@ static unsigned int rr_read_eeprom(struct rr_private *rrpriv, * it to our CPU byte-order. */ static u32 rr_read_eeprom_word(struct rr_private *rrpriv, - void * offset) + size_t offset) { - u32 word; + __be32 word; - if ((rr_read_eeprom(rrpriv, (unsigned long)offset, - (char *)&word, 4) == 4)) + if ((rr_read_eeprom(rrpriv, offset, + (unsigned char *)&word, 4) == 4)) return be32_to_cpu(word); return 0; } @@ -516,7 +510,6 @@ static int __devinit rr_init(struct net_device *dev) { struct rr_private *rrpriv; struct rr_regs __iomem *regs; - struct eeprom *hw = NULL; u32 sram_size, rev; DECLARE_MAC_BUF(mac); @@ -551,28 +544,16 @@ static int __devinit rr_init(struct net_device *dev) * other method I've seen. -VAL */ - *(u16 *)(dev->dev_addr) = - htons(rr_read_eeprom_word(rrpriv, &hw->manf.BoardULA)); - *(u32 *)(dev->dev_addr+2) = - htonl(rr_read_eeprom_word(rrpriv, &hw->manf.BoardULA[4])); + *(__be16 *)(dev->dev_addr) = + htons(rr_read_eeprom_word(rrpriv, offsetof(struct eeprom, manf.BoardULA))); + *(__be32 *)(dev->dev_addr+2) = + htonl(rr_read_eeprom_word(rrpriv, offsetof(struct eeprom, manf.BoardULA[4]))); printk(" MAC: %s\n", print_mac(mac, dev->dev_addr)); - sram_size = rr_read_eeprom_word(rrpriv, (void *)8); + sram_size = rr_read_eeprom_word(rrpriv, 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; } @@ -1495,11 +1476,10 @@ static int rr_load_firmware(struct net_device *dev) { struct rr_private *rrpriv; struct rr_regs __iomem *regs; - unsigned long eptr, segptr; + size_t eptr, segptr; int i, j; u32 localctrl, sptr, len, tmp; u32 p2len, p2size, nr_seg, revision, io, sram_size; - struct eeprom *hw = NULL; rrpriv = netdev_priv(dev); regs = rrpriv->regs; @@ -1527,7 +1507,7 @@ static int rr_load_firmware(struct net_device *dev) */ io = readl(®s->ExtIo); writel(0, ®s->ExtIo); - sram_size = rr_read_eeprom_word(rrpriv, (void *)8); + sram_size = rr_read_eeprom_word(rrpriv, 8); for (i = 200; i < sram_size / 4; i++){ writel(i * 4, ®s->WinBase); @@ -1538,13 +1518,13 @@ static int rr_load_firmware(struct net_device *dev) writel(io, ®s->ExtIo); mb(); - eptr = (unsigned long)rr_read_eeprom_word(rrpriv, - &hw->rncd_info.AddrRunCodeSegs); + eptr = rr_read_eeprom_word(rrpriv, + offsetof(struct eeprom, rncd_info.AddrRunCodeSegs)); eptr = ((eptr & 0x1fffff) >> 3); - p2len = rr_read_eeprom_word(rrpriv, (void *)(0x83*4)); + p2len = rr_read_eeprom_word(rrpriv, 0x83*4); p2len = (p2len << 2); - p2size = rr_read_eeprom_word(rrpriv, (void *)(0x84*4)); + p2size = rr_read_eeprom_word(rrpriv, 0x84*4); p2size = ((p2size & 0x1fffff) >> 3); if ((eptr < p2size) || (eptr > (p2size + p2len))){ @@ -1552,7 +1532,8 @@ static int rr_load_firmware(struct net_device *dev) goto out; } - revision = rr_read_eeprom_word(rrpriv, &hw->manf.HeaderFmt); + revision = rr_read_eeprom_word(rrpriv, + offsetof(struct eeprom, manf.HeaderFmt)); if (revision != 1){ printk("%s: invalid firmware format (%i)\n", @@ -1560,18 +1541,18 @@ static int rr_load_firmware(struct net_device *dev) goto out; } - nr_seg = rr_read_eeprom_word(rrpriv, (void *)eptr); + nr_seg = rr_read_eeprom_word(rrpriv, eptr); eptr +=4; #if (DEBUG > 1) printk("%s: nr_seg %i\n", dev->name, nr_seg); #endif for (i = 0; i < nr_seg; i++){ - sptr = rr_read_eeprom_word(rrpriv, (void *)eptr); + sptr = rr_read_eeprom_word(rrpriv, eptr); eptr += 4; - len = rr_read_eeprom_word(rrpriv, (void *)eptr); + len = rr_read_eeprom_word(rrpriv, eptr); eptr += 4; - segptr = (unsigned long)rr_read_eeprom_word(rrpriv, (void *)eptr); + segptr = rr_read_eeprom_word(rrpriv, eptr); segptr = ((segptr & 0x1fffff) >> 3); eptr += 4; #if (DEBUG > 1) @@ -1579,7 +1560,7 @@ static int rr_load_firmware(struct net_device *dev) dev->name, i, sptr, len, segptr); #endif for (j = 0; j < len; j++){ - tmp = rr_read_eeprom_word(rrpriv, (void *)segptr); + tmp = rr_read_eeprom_word(rrpriv, segptr); writel(sptr, ®s->WinBase); mb(); writel(tmp, ®s->WinData); diff --git a/drivers/net/rrunner.h b/drivers/net/rrunner.h index 6a79825bc8c..6173f11218d 100644 --- a/drivers/net/rrunner.h +++ b/drivers/net/rrunner.h @@ -838,7 +838,7 @@ static unsigned int rr_read_eeprom(struct rr_private *rrpriv, unsigned long offset, unsigned char *buf, unsigned long length); -static u32 rr_read_eeprom_word(struct rr_private *rrpriv, void * offset); +static u32 rr_read_eeprom_word(struct rr_private *rrpriv, size_t offset); static int rr_load_firmware(struct net_device *dev); static inline void rr_raz_tx(struct rr_private *, struct net_device *); static inline void rr_raz_rx(struct rr_private *, struct net_device *); diff --git a/drivers/net/s2io-regs.h b/drivers/net/s2io-regs.h index 01f08d726ac..f25264f2638 100644 --- a/drivers/net/s2io-regs.h +++ b/drivers/net/s2io-regs.h @@ -66,6 +66,7 @@ struct XENA_dev_config { #define ADAPTER_STATUS_RC_PRC_QUIESCENT vBIT(0xFF,16,8) #define ADAPTER_STATUS_MC_DRAM_READY s2BIT(24) #define ADAPTER_STATUS_MC_QUEUES_READY s2BIT(25) +#define ADAPTER_STATUS_RIC_RUNNING s2BIT(26) #define ADAPTER_STATUS_M_PLL_LOCK s2BIT(30) #define ADAPTER_STATUS_P_PLL_LOCK s2BIT(31) diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index b8c0e7b4ca1..fa57c49c0c5 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.10" /* 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; } /* @@ -1100,6 +1100,20 @@ static int init_nic(struct s2io_nic *nic) msleep(500); val64 = readq(&bar0->sw_reset); + /* Ensure that it's safe to access registers by checking + * RIC_RUNNING bit is reset. Check is valid only for XframeII. + */ + if (nic->device_type == XFRAME_II_DEVICE) { + for (i = 0; i < 50; i++) { + val64 = readq(&bar0->adapter_status); + if (!(val64 & ADAPTER_STATUS_RIC_RUNNING)) + break; + msleep(10); + } + if (i == 50) + return -ENODEV; + } + /* Enable Receiving broadcasts */ add = &bar0->mac_cfg; val64 = readq(&bar0->mac_cfg); @@ -1503,7 +1517,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 +1584,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 +1637,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); @@ -2690,9 +2704,6 @@ static int s2io_poll(struct napi_struct *napi, int budget) struct XENA_dev_config __iomem *bar0 = nic->bar0; int i; - if (!is_s2io_card_up(nic)) - return 0; - mac_control = &nic->mac_control; config = &nic->config; @@ -3723,7 +3734,7 @@ static int s2io_enable_msi_x(struct s2io_nic *nic) } /* Handle software interrupt used during MSI(X) test */ -static irqreturn_t __devinit s2io_test_intr(int irq, void *dev_id) +static irqreturn_t s2io_test_intr(int irq, void *dev_id) { struct s2io_nic *sp = dev_id; @@ -3734,7 +3745,7 @@ static irqreturn_t __devinit s2io_test_intr(int irq, void *dev_id) } /* Test interrupt path by forcing a a software IRQ */ -static int __devinit s2io_test_msi(struct s2io_nic *sp) +static int s2io_test_msi(struct s2io_nic *sp) { struct pci_dev *pdev = sp->pdev; struct XENA_dev_config __iomem *bar0 = sp->bar0; @@ -3775,6 +3786,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 +3854,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 +3925,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 +6372,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 +6384,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 +6399,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 +6754,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 +6784,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 +6797,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 +6873,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/sis190.c b/drivers/net/sis190.c index 720088396bb..7eab072ae79 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -474,7 +474,7 @@ static inline void sis190_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, static inline void sis190_make_unusable_by_asic(struct RxDesc *desc) { desc->PSize = 0x0; - desc->addr = 0xdeadbeef; + desc->addr = cpu_to_le32(0xdeadbeef); desc->size &= cpu_to_le32(RingEnd); wmb(); desc->status = 0x0; @@ -580,7 +580,7 @@ static int sis190_rx_interrupt(struct net_device *dev, struct RxDesc *desc = tp->RxDescRing + entry; u32 status; - if (desc->status & OWNbit) + if (le32_to_cpu(desc->status) & OWNbit) break; status = le32_to_cpu(desc->PSize); @@ -1381,7 +1381,7 @@ out: return rc; } -static void __devexit sis190_mii_remove(struct net_device *dev) +static void sis190_mii_remove(struct net_device *dev) { struct sis190_private *tp = netdev_priv(dev); @@ -1538,9 +1538,9 @@ static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev, /* Get MAC address from EEPROM */ for (i = 0; i < MAC_ADDR_LEN / 2; i++) { - __le16 w = sis190_read_eeprom(ioaddr, EEPROMMACAddr + i); + u16 w = sis190_read_eeprom(ioaddr, EEPROMMACAddr + i); - ((u16 *)dev->dev_addr)[i] = le16_to_cpu(w); + ((__le16 *)dev->dev_addr)[i] = cpu_to_le16(w); } sis190_set_rgmii(tp, sis190_read_eeprom(ioaddr, EEPROMInfo)); diff --git a/drivers/net/skge.c b/drivers/net/skge.c index b9961dc4760..186eb8ebfda 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 c27c7d63b6a..7023bbe545e 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); @@ -810,8 +822,13 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), rx_reg); - /* Flush Rx MAC FIFO on any flow control or error */ - sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR); + if (hw->chip_id == CHIP_ID_YUKON_XL) { + /* Hardware errata - clear flush mask */ + sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), 0); + } else { + /* Flush Rx MAC FIFO on any flow control or error */ + sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR); + } /* Set threshold to 0xa (64 bytes) + 1 to workaround pause bug */ reg = RX_GMF_FL_THR_DEF + 1; @@ -833,6 +850,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 */ @@ -920,7 +944,6 @@ static void tx_init(struct sky2_port *sky2) le = get_tx_le(sky2); le->addr = 0; le->opcode = OP_ADDR64 | HW_OWNER; - sky2->tx_addr64 = 0; } static inline struct tx_ring_info *tx_le_re(struct sky2_port *sky2, @@ -954,13 +977,11 @@ static void sky2_rx_add(struct sky2_port *sky2, u8 op, dma_addr_t map, unsigned len) { struct sky2_rx_le *le; - u32 hi = upper_32_bits(map); - if (sky2->rx_addr64 != hi) { + if (sizeof(dma_addr_t) > sizeof(u32)) { le = sky2_next_rx(sky2); - le->addr = cpu_to_le32(hi); + le->addr = cpu_to_le32(upper_32_bits(map)); le->opcode = OP_ADDR64 | HW_OWNER; - sky2->rx_addr64 = upper_32_bits(map + len); } le = sky2_next_rx(sky2); @@ -1144,6 +1165,7 @@ static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp TX_VLAN_TAG_OFF); } + sky2_read32(hw, B0_Y2_SP_LISR); napi_enable(&hw->napi); netif_tx_unlock_bh(dev); } @@ -1305,15 +1327,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)) @@ -1458,7 +1477,6 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) struct tx_ring_info *re; unsigned i, len; dma_addr_t mapping; - u32 addr64; u16 mss; u8 ctrl; @@ -1471,15 +1489,12 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) len = skb_headlen(skb); mapping = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE); - addr64 = upper_32_bits(mapping); - /* Send high bits if changed or crosses boundary */ - if (addr64 != sky2->tx_addr64 || - upper_32_bits(mapping + len) != sky2->tx_addr64) { + /* Send high bits if needed */ + if (sizeof(dma_addr_t) > sizeof(u32)) { le = get_tx_le(sky2); - le->addr = cpu_to_le32(addr64); + le->addr = cpu_to_le32(upper_32_bits(mapping)); le->opcode = OP_ADDR64 | HW_OWNER; - sky2->tx_addr64 = upper_32_bits(mapping + len); } /* Check for TCP Segmentation Offload */ @@ -1560,13 +1575,12 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) mapping = pci_map_page(hw->pdev, frag->page, frag->page_offset, frag->size, PCI_DMA_TODEVICE); - addr64 = upper_32_bits(mapping); - if (addr64 != sky2->tx_addr64) { + + if (sizeof(dma_addr_t) > sizeof(u32)) { le = get_tx_le(sky2); - le->addr = cpu_to_le32(addr64); + le->addr = cpu_to_le32(upper_32_bits(mapping)); le->ctrl = 0; le->opcode = OP_ADDR64 | HW_OWNER; - sky2->tx_addr64 = addr64; } le = get_tx_le(sky2); @@ -1805,29 +1819,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", @@ -2045,6 +2036,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) err = sky2_rx_start(sky2); sky2_write32(hw, B0_IMSK, imask); + sky2_read32(hw, B0_Y2_SP_LISR); napi_enable(&hw->napi); if (err) @@ -2247,20 +2239,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 +2351,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 +2426,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 +2692,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 +2788,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; } @@ -2907,16 +2905,14 @@ static void sky2_restart(struct work_struct *work) int i, err; rtnl_lock(); - sky2_write32(hw, B0_IMSK, 0); - sky2_read32(hw, B0_IMSK); - napi_disable(&hw->napi); - for (i = 0; i < hw->ports; i++) { dev = hw->dev[i]; if (netif_running(dev)) sky2_down(dev); } + napi_disable(&hw->napi); + sky2_write32(hw, B0_IMSK, 0); sky2_reset(hw); sky2_write32(hw, B0_IMSK, Y2_IS_BASE); napi_enable(&hw->napi); @@ -3649,32 +3645,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 +3689,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 +3719,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; @@ -3858,6 +3855,7 @@ static int sky2_debug_show(struct seq_file *seq, void *v) last = sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_PUT_IDX)), sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_LAST_IDX))); + sky2_read32(hw, B0_Y2_SP_LISR); napi_enable(&hw->napi); return 0; } @@ -3951,7 +3949,7 @@ static __exit void sky2_debug_cleanup(void) /* Initialize network device */ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port, - int highmem, int wol) + int highmem) { struct sky2_port *sky2; struct net_device *dev = alloc_etherdev(sizeof(*sky2)); @@ -3974,7 +3972,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,8 +3988,8 @@ 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->wol = wol; + sky2->rx_csum = (hw->chip_id != CHIP_ID_YUKON_XL); + sky2->wol = sky2_wol_supported(hw) & WAKE_MAGIC; spin_lock_init(&sky2->phy_lock); sky2->tx_pending = TX_DEF_PENDING; @@ -4087,24 +4086,12 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw) return err; } -static int __devinit pci_wake_enabled(struct pci_dev *dev) -{ - int pm = pci_find_capability(dev, PCI_CAP_ID_PM); - u16 value; - - if (!pm) - return 0; - if (pci_read_config_word(dev, pm + PCI_PM_CTRL, &value)) - return 0; - return value & PCI_PM_CTRL_PME_ENABLE; -} - static int __devinit sky2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *dev; struct sky2_hw *hw; - int err, using_dac = 0, wol_default; + int err, using_dac = 0; err = pci_enable_device(pdev); if (err) { @@ -4137,8 +4124,6 @@ static int __devinit sky2_probe(struct pci_dev *pdev, } } - wol_default = pci_wake_enabled(pdev) ? WAKE_MAGIC : 0; - err = -ENOMEM; hw = kzalloc(sizeof(*hw), GFP_KERNEL); if (!hw) { @@ -4160,9 +4145,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 @@ -4182,7 +4167,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev, sky2_reset(hw); - dev = sky2_init_netdev(hw, 0, using_dac, wol_default); + dev = sky2_init_netdev(hw, 0, using_dac); if (!dev) { err = -ENOMEM; goto err_out_free_pci; @@ -4219,7 +4204,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev, if (hw->ports > 1) { struct net_device *dev1; - dev1 = sky2_init_netdev(hw, 1, using_dac, wol_default); + dev1 = sky2_init_netdev(hw, 1, using_dac); if (!dev1) dev_warn(&pdev->dev, "allocation for second device failed\n"); else if ((err = register_netdev(dev1))) { @@ -4353,7 +4338,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 49ee264064a..ffe9b8a50a1 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 */ @@ -1990,14 +1991,14 @@ struct sky2_port { u16 tx_cons; /* next le to check */ u16 tx_prod; /* next le to use */ u16 tx_next; /* debug only */ - u32 tx_addr64; + u16 tx_pending; u16 tx_last_mss; u32 tx_tcpsum; struct rx_ring_info *rx_ring ____cacheline_aligned_in_smp; struct sky2_rx_le *rx_le; - u32 rx_addr64; + u16 rx_next; /* next re to check */ u16 rx_put; /* next le index to use */ u16 rx_pending; @@ -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 335b7cc80eb..251a3ce376a 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 dd18af0ce67..76cc1d3adf7 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(); @@ -1299,9 +1299,9 @@ smc911x_rx_dma_irq(int dma, void *data) PRINT_PKT(skb->data, skb->len); dev->last_rx = jiffies; skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); dev->stats.rx_packets++; dev->stats.rx_bytes += skb->len; + netif_rx(skb); spin_lock_irqsave(&lp->lock, flags); pkts = (SMC_GET_RX_FIFO_INF() & RX_FIFO_INF_RXSUSED_) >> 16; @@ -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 16a0edc078f..7defa63b9c7 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 @@ -76,7 +76,7 @@ -#if SMC_USE_PXA_DMA +#ifdef SMC_USE_PXA_DMA #define SMC_USE_DMA /* diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index 729fd28c08b..07b7f7120e3 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/starfire.c b/drivers/net/starfire.c index bcc430bd9e4..6e00dc857af 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -1742,7 +1742,7 @@ static void set_rx_mode(struct net_device *dev) if (vlan_group_get_device(np->vlgrp, i)) { if (vlan_count >= 32) break; - writew(cpu_to_be16(i), filter_addr); + writew(i, filter_addr); filter_addr += 16; vlan_count++; } diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index ff98f5d597f..0a6186d4a48 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -340,9 +340,9 @@ enum mac_ctrl1_bits { /* Note that using only 32 bit fields simplifies conversion to big-endian architectures. */ struct netdev_desc { - u32 next_desc; - u32 status; - struct desc_frag { u32 addr, length; } frag[1]; + __le32 next_desc; + __le32 status; + struct desc_frag { __le32 addr, length; } frag[1]; }; /* Bits in netdev_desc.status */ @@ -495,8 +495,8 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev, goto err_out_res; for (i = 0; i < 3; i++) - ((u16 *)dev->dev_addr)[i] = - le16_to_cpu(eeprom_read(ioaddr, i + EEPROM_SA_OFFSET)); + ((__le16 *)dev->dev_addr)[i] = + cpu_to_le16(eeprom_read(ioaddr, i + EEPROM_SA_OFFSET)); memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); dev->base_addr = (unsigned long)ioaddr; @@ -1090,8 +1090,8 @@ reset_tx (struct net_device *dev) skb = np->tx_skbuff[i]; if (skb) { pci_unmap_single(np->pci_dev, - np->tx_ring[i].frag[0].addr, skb->len, - PCI_DMA_TODEVICE); + le32_to_cpu(np->tx_ring[i].frag[0].addr), + skb->len, PCI_DMA_TODEVICE); if (irq) dev_kfree_skb_irq (skb); else @@ -1214,7 +1214,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance) skb = np->tx_skbuff[entry]; /* Free the original skb. */ pci_unmap_single(np->pci_dev, - np->tx_ring[entry].frag[0].addr, + le32_to_cpu(np->tx_ring[entry].frag[0].addr), skb->len, PCI_DMA_TODEVICE); dev_kfree_skb_irq (np->tx_skbuff[entry]); np->tx_skbuff[entry] = NULL; @@ -1233,7 +1233,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance) skb = np->tx_skbuff[entry]; /* Free the original skb. */ pci_unmap_single(np->pci_dev, - np->tx_ring[entry].frag[0].addr, + le32_to_cpu(np->tx_ring[entry].frag[0].addr), skb->len, PCI_DMA_TODEVICE); dev_kfree_skb_irq (np->tx_skbuff[entry]); np->tx_skbuff[entry] = NULL; @@ -1311,19 +1311,19 @@ static void rx_poll(unsigned long data) && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) { skb_reserve(skb, 2); /* 16 byte align the IP header */ pci_dma_sync_single_for_cpu(np->pci_dev, - desc->frag[0].addr, + le32_to_cpu(desc->frag[0].addr), np->rx_buf_sz, PCI_DMA_FROMDEVICE); skb_copy_to_linear_data(skb, np->rx_skbuff[entry]->data, pkt_len); pci_dma_sync_single_for_device(np->pci_dev, - desc->frag[0].addr, + le32_to_cpu(desc->frag[0].addr), np->rx_buf_sz, PCI_DMA_FROMDEVICE); skb_put(skb, pkt_len); } else { pci_unmap_single(np->pci_dev, - desc->frag[0].addr, + le32_to_cpu(desc->frag[0].addr), np->rx_buf_sz, PCI_DMA_FROMDEVICE); skb_put(skb = np->rx_skbuff[entry], pkt_len); @@ -1709,23 +1709,23 @@ static int netdev_close(struct net_device *dev) /* Free all the skbuffs in the Rx queue. */ for (i = 0; i < RX_RING_SIZE; i++) { np->rx_ring[i].status = 0; - np->rx_ring[i].frag[0].addr = 0xBADF00D0; /* An invalid address. */ skb = np->rx_skbuff[i]; if (skb) { pci_unmap_single(np->pci_dev, - np->rx_ring[i].frag[0].addr, np->rx_buf_sz, - PCI_DMA_FROMDEVICE); + le32_to_cpu(np->rx_ring[i].frag[0].addr), + np->rx_buf_sz, PCI_DMA_FROMDEVICE); dev_kfree_skb(skb); np->rx_skbuff[i] = NULL; } + np->rx_ring[i].frag[0].addr = cpu_to_le32(0xBADF00D0); /* poison */ } for (i = 0; i < TX_RING_SIZE; i++) { np->tx_ring[i].next_desc = 0; skb = np->tx_skbuff[i]; if (skb) { pci_unmap_single(np->pci_dev, - np->tx_ring[i].frag[0].addr, skb->len, - PCI_DMA_TODEVICE); + le32_to_cpu(np->tx_ring[i].frag[0].addr), + skb->len, PCI_DMA_TODEVICE); dev_kfree_skb(skb); np->tx_skbuff[i] = NULL; } diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 53b8344a68e..68872142530 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 120c8affe83..9cc13dd8a82 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]; diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c index 4e1b84e6d66..21230c97b2a 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 09440d783e6..22eb7c8c1a2 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 @@ -7365,10 +7427,6 @@ static int tg3_open(struct net_device *dev) } else if (pci_enable_msi(tp->pdev) == 0) { u32 msi_mode; - /* Hardware bug - MSI won't work if INTX disabled. */ - if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) - pci_intx(tp->pdev, 1); - msi_mode = tr32(MSGINT_MODE); tw32(MSGINT_MODE, msi_mode | MSGINT_MODE_ENABLE); tp->tg3_flags2 |= TG3_FLG2_USING_MSI; @@ -8131,6 +8189,7 @@ static int tg3_get_eeprom_len(struct net_device *dev) } static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val); +static int tg3_nvram_read_le(struct tg3 *tp, u32 offset, __le32 *val); static int tg3_nvram_read_swab(struct tg3 *tp, u32 offset, u32 *val); static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) @@ -8138,7 +8197,8 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, struct tg3 *tp = netdev_priv(dev); int ret; u8 *pd; - u32 i, offset, len, val, b_offset, b_count; + u32 i, offset, len, b_offset, b_count; + __le32 val; if (tp->link_config.phy_is_low_power) return -EAGAIN; @@ -8157,10 +8217,9 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, /* i.e. offset=1 len=2 */ b_count = len; } - ret = tg3_nvram_read(tp, offset-b_offset, &val); + ret = tg3_nvram_read_le(tp, offset-b_offset, &val); if (ret) return ret; - val = cpu_to_le32(val); memcpy(data, ((char*)&val) + b_offset, b_count); len -= b_count; offset += b_count; @@ -8170,12 +8229,11 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, /* read bytes upto the last 4 byte boundary */ pd = &data[eeprom->len]; for (i = 0; i < (len - (len & 3)); i += 4) { - ret = tg3_nvram_read(tp, offset + i, &val); + ret = tg3_nvram_read_le(tp, offset + i, &val); if (ret) { eeprom->len += i; return ret; } - val = cpu_to_le32(val); memcpy(pd + i, &val, 4); } eeprom->len += i; @@ -8185,11 +8243,10 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, pd = &data[eeprom->len]; b_count = len & 3; b_offset = offset + len - b_count; - ret = tg3_nvram_read(tp, b_offset, &val); + ret = tg3_nvram_read_le(tp, b_offset, &val); if (ret) return ret; - val = cpu_to_le32(val); - memcpy(pd, ((char*)&val), b_count); + memcpy(pd, &val, b_count); eeprom->len += b_count; } return 0; @@ -8201,8 +8258,9 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, { struct tg3 *tp = netdev_priv(dev); int ret; - u32 offset, len, b_offset, odd_len, start, end; + u32 offset, len, b_offset, odd_len; u8 *buf; + __le32 start, end; if (tp->link_config.phy_is_low_power) return -EAGAIN; @@ -8215,10 +8273,9 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, if ((b_offset = (offset & 3))) { /* adjustments to start on required 4 byte boundary */ - ret = tg3_nvram_read(tp, offset-b_offset, &start); + ret = tg3_nvram_read_le(tp, offset-b_offset, &start); if (ret) return ret; - start = cpu_to_le32(start); len += b_offset; offset &= ~3; if (len < 4) @@ -8230,10 +8287,9 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, /* adjustments to end on required 4 byte boundary */ odd_len = 1; len = (len + 3) & ~3; - ret = tg3_nvram_read(tp, offset+len-4, &end); + ret = tg3_nvram_read_le(tp, offset+len-4, &end); if (ret) return ret; - end = cpu_to_le32(end); } buf = data; @@ -8271,7 +8327,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; @@ -8668,13 +8724,16 @@ 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 static int tg3_test_nvram(struct tg3 *tp) { - u32 *buf, csum, magic; + u32 csum, magic; + __le32 *buf; int i, j, k, err = 0, size; if (tg3_nvram_read_swab(tp, 0, &magic) != 0) @@ -8683,9 +8742,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; @@ -8698,22 +8770,29 @@ static int tg3_test_nvram(struct tg3 *tp) err = -EIO; for (i = 0, j = 0; i < size; i += 4, j++) { - u32 val; - - if ((err = tg3_nvram_read(tp, i, &val)) != 0) + if ((err = tg3_nvram_read_le(tp, i, &buf[j])) != 0) break; - buf[j] = cpu_to_le32(val); } if (i < size) goto out; /* Selfboot format */ - if ((cpu_to_be32(buf[0]) & TG3_EEPROM_MAGIC_FW_MSK) == + magic = swab32(le32_to_cpu(buf[0])); + if ((magic & TG3_EEPROM_MAGIC_FW_MSK) == TG3_EEPROM_MAGIC_FW) { u8 *buf8 = (u8 *) buf, csum8 = 0; - for (i = 0; i < size; i++) - csum8 += buf8[i]; + if ((magic & 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; @@ -8724,7 +8803,7 @@ static int tg3_test_nvram(struct tg3 *tp) goto out; } - if ((cpu_to_be32(buf[0]) & TG3_EEPROM_MAGIC_HW_MSK) == + if ((magic & TG3_EEPROM_MAGIC_HW_MSK) == TG3_EEPROM_MAGIC_HW) { u8 data[NVRAM_SELFBOOT_DATA_SIZE]; u8 parity[NVRAM_SELFBOOT_DATA_SIZE]; @@ -8770,12 +8849,12 @@ static int tg3_test_nvram(struct tg3 *tp) /* Bootstrap checksum at offset 0x10 */ csum = calc_crc((unsigned char *) buf, 0x10); - if(csum != cpu_to_le32(buf[0x10/4])) + if(csum != le32_to_cpu(buf[0x10/4])) goto out; /* Manufacturing block starts at offset 0x74, checksum at 0xfc */ csum = calc_crc((unsigned char *) &buf[0x74/4], 0x88); - if (csum != cpu_to_le32(buf[0xfc/4])) + if (csum != le32_to_cpu(buf[0xfc/4])) goto out; err = 0; @@ -9297,7 +9376,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; @@ -9314,17 +9393,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 */ @@ -10089,6 +10168,15 @@ static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val) return ret; } +static int tg3_nvram_read_le(struct tg3 *tp, u32 offset, __le32 *val) +{ + u32 v; + int res = tg3_nvram_read(tp, offset, &v); + if (!res) + *val = cpu_to_le32(v); + return res; +} + static int tg3_nvram_read_swab(struct tg3 *tp, u32 offset, u32 *val) { int err; @@ -10106,13 +10194,14 @@ static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp, u32 val; for (i = 0; i < len; i += 4) { - u32 addr, data; + u32 addr; + __le32 data; addr = offset + i; memcpy(&data, buf + i, 4); - tw32(GRC_EEPROM_DATA, cpu_to_le32(data)); + tw32(GRC_EEPROM_DATA, le32_to_cpu(data)); val = tr32(GRC_EEPROM_ADDR); tw32(GRC_EEPROM_ADDR, val | EEPROM_ADDR_COMPLETE); @@ -10162,8 +10251,8 @@ static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len, phy_addr = offset & ~pagemask; for (j = 0; j < pagesize; j += 4) { - if ((ret = tg3_nvram_read(tp, phy_addr + j, - (u32 *) (tmp + j)))) + if ((ret = tg3_nvram_read_le(tp, phy_addr + j, + (__le32 *) (tmp + j)))) break; } if (ret) @@ -10207,10 +10296,11 @@ static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len, break; for (j = 0; j < pagesize; j += 4) { - u32 data; + __be32 data; - data = *((u32 *) (tmp + j)); - tw32(NVRAM_WRDATA, cpu_to_be32(data)); + data = *((__be32 *) (tmp + j)); + /* swab32(le32_to_cpu(data)), actually */ + tw32(NVRAM_WRDATA, be32_to_cpu(data)); tw32(NVRAM_ADDR, phy_addr + j); @@ -10244,10 +10334,11 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len, int i, ret = 0; for (i = 0; i < len; i += 4, offset += 4) { - u32 data, page_off, phy_addr, nvram_cmd; + u32 page_off, phy_addr, nvram_cmd; + __be32 data; memcpy(&data, buf + i, 4); - tw32(NVRAM_WRDATA, cpu_to_be32(data)); + tw32(NVRAM_WRDATA, be32_to_cpu(data)); page_off = offset % tp->nvram_pagesize; @@ -10545,6 +10636,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 == @@ -10745,6 +10840,7 @@ static void __devinit tg3_read_partno(struct tg3 *tp) vpd_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_VPD); for (i = 0; i < 256; i += 4) { u32 tmp, j = 0; + __le32 v; u16 tmp16; pci_write_config_word(tp->pdev, vpd_cap + PCI_VPD_ADDR, @@ -10761,8 +10857,8 @@ static void __devinit tg3_read_partno(struct tg3 *tp) pci_read_config_dword(tp->pdev, vpd_cap + PCI_VPD_DATA, &tmp); - tmp = cpu_to_le32(tmp); - memcpy(&vpd_data[i], &tmp, 4); + v = cpu_to_le32(tmp); + memcpy(&vpd_data[i], &v, 4); } } @@ -10855,15 +10951,15 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp) offset = offset + ver_offset - start; for (i = 0; i < 16; i += 4) { - if (tg3_nvram_read(tp, offset + i, &val)) + __le32 v; + if (tg3_nvram_read_le(tp, offset + i, &v)) return; - val = le32_to_cpu(val); - memcpy(tp->fw_ver + i, &val, 4); + memcpy(tp->fw_ver + i, &v, 4); } 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; @@ -10897,19 +10993,19 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp) tp->fw_ver[bcnt++] = ' '; for (i = 0; i < 4; i++) { - if (tg3_nvram_read(tp, offset, &val)) + __le32 v; + if (tg3_nvram_read_le(tp, offset, &v)) return; - val = le32_to_cpu(val); - offset += sizeof(val); + offset += sizeof(v); - if (bcnt > TG3_VER_SIZE - sizeof(val)) { - memcpy(&tp->fw_ver[bcnt], &val, TG3_VER_SIZE - bcnt); + if (bcnt > TG3_VER_SIZE - sizeof(v)) { + memcpy(&tp->fw_ver[bcnt], &v, TG3_VER_SIZE - bcnt); break; } - memcpy(&tp->fw_ver[bcnt], &val, sizeof(val)); - bcnt += sizeof(val); + memcpy(&tp->fw_ver[bcnt], &v, sizeof(v)); + bcnt += sizeof(v); } tp->fw_ver[TG3_VER_SIZE - 1] = 0; @@ -11131,6 +11227,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; @@ -11311,9 +11410,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. @@ -12468,6 +12574,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) @@ -12482,7 +12610,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 @@ -12505,28 +12633,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); @@ -12681,11 +12787,6 @@ static int tg3_resume(struct pci_dev *pdev) if (err) return err; - /* Hardware bug - MSI won't work if INTX disabled. */ - if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) && - (tp->tg3_flags2 & TG3_FLG2_USING_MSI)) - pci_intx(tp->pdev, 1); - netif_device_attach(dev); tg3_full_lock(tp, 0); diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 1d5b2a3dd29..da18fb22071 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/tokenring/3c359.c b/drivers/net/tokenring/3c359.c index 5d31519a6c6..44a06f8b588 100644 --- a/drivers/net/tokenring/3c359.c +++ b/drivers/net/tokenring/3c359.c @@ -570,7 +570,7 @@ static int xl_open(struct net_device *dev) struct xl_private *xl_priv=netdev_priv(dev); u8 __iomem *xl_mmio = xl_priv->xl_mmio ; u8 i ; - u16 hwaddr[3] ; /* Should be u8[6] but we get word return values */ + __le16 hwaddr[3] ; /* Should be u8[6] but we get word return values */ int open_err ; u16 switchsettings, switchsettings_eeprom ; @@ -580,15 +580,12 @@ static int xl_open(struct net_device *dev) } /* - * Read the information from the EEPROM that we need. I know we - * should use ntohs, but the word gets stored reversed in the 16 - * bit field anyway and it all works its self out when we memcpy - * it into dev->dev_addr. + * Read the information from the EEPROM that we need. */ - hwaddr[0] = xl_ee_read(dev,0x10) ; - hwaddr[1] = xl_ee_read(dev,0x11) ; - hwaddr[2] = xl_ee_read(dev,0x12) ; + hwaddr[0] = cpu_to_le16(xl_ee_read(dev,0x10)); + hwaddr[1] = cpu_to_le16(xl_ee_read(dev,0x11)); + hwaddr[2] = cpu_to_le16(xl_ee_read(dev,0x12)); /* Ring speed */ @@ -665,8 +662,8 @@ static int xl_open(struct net_device *dev) break ; skb->dev = dev ; - xl_priv->xl_rx_ring[i].upfragaddr = pci_map_single(xl_priv->pdev, skb->data,xl_priv->pkt_buf_sz, PCI_DMA_FROMDEVICE) ; - xl_priv->xl_rx_ring[i].upfraglen = xl_priv->pkt_buf_sz | RXUPLASTFRAG; + xl_priv->xl_rx_ring[i].upfragaddr = cpu_to_le32(pci_map_single(xl_priv->pdev, skb->data,xl_priv->pkt_buf_sz, PCI_DMA_FROMDEVICE)); + xl_priv->xl_rx_ring[i].upfraglen = cpu_to_le32(xl_priv->pkt_buf_sz) | RXUPLASTFRAG; xl_priv->rx_ring_skb[i] = skb ; } @@ -680,7 +677,7 @@ static int xl_open(struct net_device *dev) xl_priv->rx_ring_tail = 0 ; xl_priv->rx_ring_dma_addr = pci_map_single(xl_priv->pdev,xl_priv->xl_rx_ring, sizeof(struct xl_rx_desc) * XL_RX_RING_SIZE, PCI_DMA_TODEVICE) ; for (i=0;i<(xl_priv->rx_ring_no-1);i++) { - xl_priv->xl_rx_ring[i].upnextptr = xl_priv->rx_ring_dma_addr + (sizeof (struct xl_rx_desc) * (i+1)) ; + xl_priv->xl_rx_ring[i].upnextptr = cpu_to_le32(xl_priv->rx_ring_dma_addr + (sizeof (struct xl_rx_desc) * (i+1))); } xl_priv->xl_rx_ring[i].upnextptr = 0 ; @@ -698,7 +695,7 @@ static int xl_open(struct net_device *dev) * Setup the first dummy DPD entry for polling to start working. */ - xl_priv->xl_tx_ring[0].framestartheader = TXDPDEMPTY ; + xl_priv->xl_tx_ring[0].framestartheader = TXDPDEMPTY; xl_priv->xl_tx_ring[0].buffer = 0 ; xl_priv->xl_tx_ring[0].buffer_length = 0 ; xl_priv->xl_tx_ring[0].dnnextptr = 0 ; @@ -811,17 +808,17 @@ static int xl_open_hw(struct net_device *dev) return open_err ; } else { writel( (MEM_WORD_READ | 0xD0000 | xl_priv->srb) + 8, xl_mmio + MMIO_MAC_ACCESS_CMD) ; - xl_priv->asb = ntohs(readw(xl_mmio + MMIO_MACDATA)) ; + xl_priv->asb = swab16(readw(xl_mmio + MMIO_MACDATA)) ; printk(KERN_INFO "%s: Adapter Opened Details: ",dev->name) ; printk("ASB: %04x",xl_priv->asb ) ; writel( (MEM_WORD_READ | 0xD0000 | xl_priv->srb) + 10, xl_mmio + MMIO_MAC_ACCESS_CMD) ; - printk(", SRB: %04x",ntohs(readw(xl_mmio + MMIO_MACDATA)) ) ; + printk(", SRB: %04x",swab16(readw(xl_mmio + MMIO_MACDATA)) ) ; writel( (MEM_WORD_READ | 0xD0000 | xl_priv->srb) + 12, xl_mmio + MMIO_MAC_ACCESS_CMD) ; - xl_priv->arb = ntohs(readw(xl_mmio + MMIO_MACDATA)) ; + xl_priv->arb = swab16(readw(xl_mmio + MMIO_MACDATA)) ; printk(", ARB: %04x \n",xl_priv->arb ) ; writel( (MEM_WORD_READ | 0xD0000 | xl_priv->srb) + 14, xl_mmio + MMIO_MAC_ACCESS_CMD) ; - vsoff = ntohs(readw(xl_mmio + MMIO_MACDATA)) ; + vsoff = swab16(readw(xl_mmio + MMIO_MACDATA)) ; /* * Interesting, sending the individual characters directly to printk was causing klogd to use @@ -873,16 +870,15 @@ static int xl_open_hw(struct net_device *dev) static void adv_rx_ring(struct net_device *dev) /* Advance rx_ring, cut down on bloat in xl_rx */ { struct xl_private *xl_priv=netdev_priv(dev); - int prev_ring_loc ; - - prev_ring_loc = (xl_priv->rx_ring_tail + XL_RX_RING_SIZE - 1) & (XL_RX_RING_SIZE - 1); - xl_priv->xl_rx_ring[prev_ring_loc].upnextptr = xl_priv->rx_ring_dma_addr + (sizeof (struct xl_rx_desc) * xl_priv->rx_ring_tail) ; - xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].framestatus = 0 ; - xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upnextptr = 0 ; - xl_priv->rx_ring_tail++ ; - xl_priv->rx_ring_tail &= (XL_RX_RING_SIZE-1) ; - - return ; + int n = xl_priv->rx_ring_tail; + int prev_ring_loc; + + prev_ring_loc = (n + XL_RX_RING_SIZE - 1) & (XL_RX_RING_SIZE - 1); + xl_priv->xl_rx_ring[prev_ring_loc].upnextptr = cpu_to_le32(xl_priv->rx_ring_dma_addr + (sizeof (struct xl_rx_desc) * n)); + xl_priv->xl_rx_ring[n].framestatus = 0; + xl_priv->xl_rx_ring[n].upnextptr = 0; + xl_priv->rx_ring_tail++; + xl_priv->rx_ring_tail &= (XL_RX_RING_SIZE-1); } static void xl_rx(struct net_device *dev) @@ -914,7 +910,7 @@ static void xl_rx(struct net_device *dev) temp_ring_loc &= (XL_RX_RING_SIZE-1) ; } - frame_length = xl_priv->xl_rx_ring[temp_ring_loc].framestatus & 0x7FFF ; + frame_length = le32_to_cpu(xl_priv->xl_rx_ring[temp_ring_loc].framestatus) & 0x7FFF; skb = dev_alloc_skb(frame_length) ; @@ -931,29 +927,29 @@ static void xl_rx(struct net_device *dev) } while (xl_priv->rx_ring_tail != temp_ring_loc) { - copy_len = xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfraglen & 0x7FFF ; + copy_len = le32_to_cpu(xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfraglen) & 0x7FFF; frame_length -= copy_len ; - pci_dma_sync_single_for_cpu(xl_priv->pdev,xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr,xl_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ; + pci_dma_sync_single_for_cpu(xl_priv->pdev,le32_to_cpu(xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr),xl_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE); skb_copy_from_linear_data(xl_priv->rx_ring_skb[xl_priv->rx_ring_tail], skb_put(skb, copy_len), copy_len); - pci_dma_sync_single_for_device(xl_priv->pdev,xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr,xl_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ; + pci_dma_sync_single_for_device(xl_priv->pdev,le32_to_cpu(xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr),xl_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE); adv_rx_ring(dev) ; } /* Now we have found the last fragment */ - pci_dma_sync_single_for_cpu(xl_priv->pdev,xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr,xl_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ; + pci_dma_sync_single_for_cpu(xl_priv->pdev,le32_to_cpu(xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr),xl_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE); skb_copy_from_linear_data(xl_priv->rx_ring_skb[xl_priv->rx_ring_tail], skb_put(skb,copy_len), frame_length); /* memcpy(skb_put(skb,frame_length), bus_to_virt(xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr), frame_length) ; */ - pci_dma_sync_single_for_device(xl_priv->pdev,xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr,xl_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ; + pci_dma_sync_single_for_device(xl_priv->pdev,le32_to_cpu(xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr),xl_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE); adv_rx_ring(dev) ; skb->protocol = tr_type_trans(skb,dev) ; netif_rx(skb) ; } else { /* Single Descriptor Used, simply swap buffers over, fast path */ - frame_length = xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].framestatus & 0x7FFF ; + frame_length = le32_to_cpu(xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].framestatus) & 0x7FFF; skb = dev_alloc_skb(xl_priv->pkt_buf_sz) ; @@ -966,13 +962,13 @@ static void xl_rx(struct net_device *dev) } skb2 = xl_priv->rx_ring_skb[xl_priv->rx_ring_tail] ; - pci_unmap_single(xl_priv->pdev, xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr, xl_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ; + pci_unmap_single(xl_priv->pdev, le32_to_cpu(xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr), xl_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ; skb_put(skb2, frame_length) ; skb2->protocol = tr_type_trans(skb2,dev) ; xl_priv->rx_ring_skb[xl_priv->rx_ring_tail] = skb ; - xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr = pci_map_single(xl_priv->pdev,skb->data,xl_priv->pkt_buf_sz, PCI_DMA_FROMDEVICE) ; - xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfraglen = xl_priv->pkt_buf_sz | RXUPLASTFRAG ; + xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr = cpu_to_le32(pci_map_single(xl_priv->pdev,skb->data,xl_priv->pkt_buf_sz, PCI_DMA_FROMDEVICE)); + xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfraglen = cpu_to_le32(xl_priv->pkt_buf_sz) | RXUPLASTFRAG; adv_rx_ring(dev) ; xl_priv->xl_stats.rx_packets++ ; xl_priv->xl_stats.rx_bytes += frame_length ; @@ -1022,7 +1018,7 @@ static void xl_freemem(struct net_device *dev) for (i=0;i<XL_RX_RING_SIZE;i++) { dev_kfree_skb_irq(xl_priv->rx_ring_skb[xl_priv->rx_ring_tail]) ; - pci_unmap_single(xl_priv->pdev,xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr,xl_priv->pkt_buf_sz, PCI_DMA_FROMDEVICE) ; + pci_unmap_single(xl_priv->pdev,le32_to_cpu(xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr),xl_priv->pkt_buf_sz, PCI_DMA_FROMDEVICE); xl_priv->rx_ring_tail++ ; xl_priv->rx_ring_tail &= XL_RX_RING_SIZE-1; } @@ -1181,9 +1177,9 @@ static int xl_xmit(struct sk_buff *skb, struct net_device *dev) txd = &(xl_priv->xl_tx_ring[tx_head]) ; txd->dnnextptr = 0 ; - txd->framestartheader = skb->len | TXDNINDICATE ; - txd->buffer = pci_map_single(xl_priv->pdev, skb->data, skb->len, PCI_DMA_TODEVICE) ; - txd->buffer_length = skb->len | TXDNFRAGLAST ; + txd->framestartheader = cpu_to_le32(skb->len) | TXDNINDICATE; + txd->buffer = cpu_to_le32(pci_map_single(xl_priv->pdev, skb->data, skb->len, PCI_DMA_TODEVICE)); + txd->buffer_length = cpu_to_le32(skb->len) | TXDNFRAGLAST; xl_priv->tx_ring_skb[tx_head] = skb ; xl_priv->xl_stats.tx_packets++ ; xl_priv->xl_stats.tx_bytes += skb->len ; @@ -1199,7 +1195,7 @@ static int xl_xmit(struct sk_buff *skb, struct net_device *dev) xl_priv->tx_ring_head &= (XL_TX_RING_SIZE - 1) ; xl_priv->free_ring_entries-- ; - xl_priv->xl_tx_ring[tx_prev].dnnextptr = xl_priv->tx_ring_dma_addr + (sizeof (struct xl_tx_desc) * tx_head) ; + xl_priv->xl_tx_ring[tx_prev].dnnextptr = cpu_to_le32(xl_priv->tx_ring_dma_addr + (sizeof (struct xl_tx_desc) * tx_head)); /* Sneaky, by doing a read on DnListPtr we can force the card to poll on the DnNextPtr */ /* readl(xl_mmio + MMIO_DNLISTPTR) ; */ @@ -1237,9 +1233,9 @@ static void xl_dn_comp(struct net_device *dev) while (xl_priv->xl_tx_ring[xl_priv->tx_ring_tail].framestartheader & TXDNCOMPLETE ) { txd = &(xl_priv->xl_tx_ring[xl_priv->tx_ring_tail]) ; - pci_unmap_single(xl_priv->pdev,txd->buffer, xl_priv->tx_ring_skb[xl_priv->tx_ring_tail]->len, PCI_DMA_TODEVICE) ; + pci_unmap_single(xl_priv->pdev, le32_to_cpu(txd->buffer), xl_priv->tx_ring_skb[xl_priv->tx_ring_tail]->len, PCI_DMA_TODEVICE); txd->framestartheader = 0 ; - txd->buffer = 0xdeadbeef ; + txd->buffer = cpu_to_le32(0xdeadbeef); txd->buffer_length = 0 ; dev_kfree_skb_irq(xl_priv->tx_ring_skb[xl_priv->tx_ring_tail]) ; xl_priv->tx_ring_tail++ ; @@ -1507,9 +1503,9 @@ static void xl_arb_cmd(struct net_device *dev) if (arb_cmd == RING_STATUS_CHANGE) { /* Ring.Status.Change */ writel( ( (MEM_WORD_READ | 0xD0000 | xl_priv->arb) + 6), xl_mmio + MMIO_MAC_ACCESS_CMD) ; - printk(KERN_INFO "%s: Ring Status Change: New Status = %04x\n", dev->name, ntohs(readw(xl_mmio + MMIO_MACDATA) )) ; + printk(KERN_INFO "%s: Ring Status Change: New Status = %04x\n", dev->name, swab16(readw(xl_mmio + MMIO_MACDATA) )) ; - lan_status = ntohs(readw(xl_mmio + MMIO_MACDATA)); + lan_status = swab16(readw(xl_mmio + MMIO_MACDATA)); /* Acknowledge interrupt, this tells nic we are done with the arb */ writel(ACK_INTERRUPT | ARBCACK | LATCH_ACK, xl_mmio + MMIO_COMMAND) ; @@ -1573,7 +1569,7 @@ static void xl_arb_cmd(struct net_device *dev) printk(KERN_INFO "Received.Data \n") ; #endif writel( ((MEM_WORD_READ | 0xD0000 | xl_priv->arb) + 6), xl_mmio + MMIO_MAC_ACCESS_CMD) ; - xl_priv->mac_buffer = ntohs(readw(xl_mmio + MMIO_MACDATA)) ; + xl_priv->mac_buffer = swab16(readw(xl_mmio + MMIO_MACDATA)) ; /* Now we are going to be really basic here and not do anything * with the data at all. The tech docs do not give me enough @@ -1634,7 +1630,7 @@ static void xl_asb_cmd(struct net_device *dev) writeb(0x81, xl_mmio + MMIO_MACDATA) ; writel(MEM_WORD_WRITE | 0xd0000 | xl_priv->asb | 6, xl_mmio + MMIO_MAC_ACCESS_CMD) ; - writew(ntohs(xl_priv->mac_buffer), xl_mmio + MMIO_MACDATA) ; + writew(swab16(xl_priv->mac_buffer), xl_mmio + MMIO_MACDATA) ; xl_wait_misr_flags(dev) ; diff --git a/drivers/net/tokenring/3c359.h b/drivers/net/tokenring/3c359.h index 05c86036885..b880cba0f6f 100644 --- a/drivers/net/tokenring/3c359.h +++ b/drivers/net/tokenring/3c359.h @@ -156,19 +156,19 @@ #define HOSTERRINT (1<<1) /* Receive descriptor bits */ -#define RXOVERRUN (1<<19) -#define RXFC (1<<21) -#define RXAR (1<<22) -#define RXUPDCOMPLETE (1<<23) -#define RXUPDFULL (1<<24) -#define RXUPLASTFRAG (1<<31) +#define RXOVERRUN cpu_to_le32(1<<19) +#define RXFC cpu_to_le32(1<<21) +#define RXAR cpu_to_le32(1<<22) +#define RXUPDCOMPLETE cpu_to_le32(1<<23) +#define RXUPDFULL cpu_to_le32(1<<24) +#define RXUPLASTFRAG cpu_to_le32(1<<31) /* Transmit descriptor bits */ -#define TXDNCOMPLETE (1<<16) -#define TXTXINDICATE (1<<27) -#define TXDPDEMPTY (1<<29) -#define TXDNINDICATE (1<<31) -#define TXDNFRAGLAST (1<<31) +#define TXDNCOMPLETE cpu_to_le32(1<<16) +#define TXTXINDICATE cpu_to_le32(1<<27) +#define TXDPDEMPTY cpu_to_le32(1<<29) +#define TXDNINDICATE cpu_to_le32(1<<31) +#define TXDNFRAGLAST cpu_to_le32(1<<31) /* Interrupts to Acknowledge */ #define LATCH_ACK 1 @@ -232,17 +232,17 @@ /* 3c359 data structures */ struct xl_tx_desc { - u32 dnnextptr ; - u32 framestartheader ; - u32 buffer ; - u32 buffer_length ; + __le32 dnnextptr; + __le32 framestartheader; + __le32 buffer; + __le32 buffer_length; }; struct xl_rx_desc { - u32 upnextptr ; - u32 framestatus ; - u32 upfragaddr ; - u32 upfraglen ; + __le32 upnextptr; + __le32 framestatus; + __le32 upfragaddr; + __le32 upfraglen; }; struct xl_private { diff --git a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig index 49d7a290dbb..20ac1503021 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/de4x5.c b/drivers/net/tulip/de4x5.c index 41f34bb91ca..6e8b18a3b3c 100644 --- a/drivers/net/tulip/de4x5.c +++ b/drivers/net/tulip/de4x5.c @@ -911,7 +911,7 @@ static int de4x5_init(struct net_device *dev); static int de4x5_sw_reset(struct net_device *dev); static int de4x5_rx(struct net_device *dev); static int de4x5_tx(struct net_device *dev); -static int de4x5_ast(struct net_device *dev); +static void de4x5_ast(struct net_device *dev); static int de4x5_txur(struct net_device *dev); static int de4x5_rx_ovfc(struct net_device *dev); @@ -984,11 +984,9 @@ static int test_bad_enet(struct net_device *dev, int status); static int an_exception(struct de4x5_private *lp); static char *build_setup_frame(struct net_device *dev, int mode); static void disable_ast(struct net_device *dev); -static void enable_ast(struct net_device *dev, u32 time_out); static long de4x5_switch_mac_port(struct net_device *dev); static int gep_rd(struct net_device *dev); static void gep_wr(s32 data, struct net_device *dev); -static void timeout(struct net_device *dev, void (*fn)(u_long data), u_long data, u_long msec); static void yawn(struct net_device *dev, int state); static void de4x5_parse_params(struct net_device *dev); static void de4x5_dbg_open(struct net_device *dev); @@ -1139,6 +1137,8 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev) lp->gendev = gendev; spin_lock_init(&lp->lock); init_timer(&lp->timer); + lp->timer.function = (void (*)(unsigned long))de4x5_ast; + lp->timer.data = (unsigned long)dev; de4x5_parse_params(dev); /* @@ -1311,7 +1311,7 @@ de4x5_open(struct net_device *dev) lp->state = OPEN; de4x5_dbg_open(dev); - if (request_irq(dev->irq, (void *)de4x5_interrupt, IRQF_SHARED, + if (request_irq(dev->irq, de4x5_interrupt, IRQF_SHARED, lp->adapter_name, dev)) { printk("de4x5_open(): Requested IRQ%d is busy - attemping FAST/SHARE...", dev->irq); if (request_irq(dev->irq, de4x5_interrupt, IRQF_DISABLED | IRQF_SHARED, @@ -1737,27 +1737,29 @@ de4x5_tx(struct net_device *dev) return 0; } -static int +static void de4x5_ast(struct net_device *dev) { - struct de4x5_private *lp = netdev_priv(dev); - int next_tick = DE4X5_AUTOSENSE_MS; + struct de4x5_private *lp = netdev_priv(dev); + int next_tick = DE4X5_AUTOSENSE_MS; + int dt; - disable_ast(dev); + if (lp->useSROM) + next_tick = srom_autoconf(dev); + else if (lp->chipset == DC21140) + next_tick = dc21140m_autoconf(dev); + else if (lp->chipset == DC21041) + next_tick = dc21041_autoconf(dev); + else if (lp->chipset == DC21040) + next_tick = dc21040_autoconf(dev); + lp->linkOK = 0; - if (lp->useSROM) { - next_tick = srom_autoconf(dev); - } else if (lp->chipset == DC21140) { - next_tick = dc21140m_autoconf(dev); - } else if (lp->chipset == DC21041) { - next_tick = dc21041_autoconf(dev); - } else if (lp->chipset == DC21040) { - next_tick = dc21040_autoconf(dev); - } - lp->linkOK = 0; - enable_ast(dev, next_tick); + dt = (next_tick * HZ) / 1000; - return 0; + if (!dt) + dt = 1; + + mod_timer(&lp->timer, jiffies + dt); } static int @@ -2174,7 +2176,7 @@ srom_search(struct net_device *dev, struct pci_dev *pdev) for (j=0, i=0; i<ETH_ALEN; i++) { j += (u_char) *((u_char *)&lp->srom + SROM_HWADD + i); } - if ((j != 0) && (j != 0x5fa)) { + if (j != 0 && j != 6 * 0xff) { last.chipset = device; last.bus = pb; last.irq = irq; @@ -2371,30 +2373,19 @@ static struct pci_driver de4x5_pci_driver = { static int autoconf_media(struct net_device *dev) { - struct de4x5_private *lp = netdev_priv(dev); - u_long iobase = dev->base_addr; - int next_tick = DE4X5_AUTOSENSE_MS; + struct de4x5_private *lp = netdev_priv(dev); + u_long iobase = dev->base_addr; - lp->linkOK = 0; - lp->c_media = AUTO; /* Bogus last media */ - disable_ast(dev); - inl(DE4X5_MFC); /* Zero the lost frames counter */ - lp->media = INIT; - lp->tcount = 0; + disable_ast(dev); - if (lp->useSROM) { - next_tick = srom_autoconf(dev); - } else if (lp->chipset == DC21040) { - next_tick = dc21040_autoconf(dev); - } else if (lp->chipset == DC21041) { - next_tick = dc21041_autoconf(dev); - } else if (lp->chipset == DC21140) { - next_tick = dc21140m_autoconf(dev); - } + lp->c_media = AUTO; /* Bogus last media */ + inl(DE4X5_MFC); /* Zero the lost frames counter */ + lp->media = INIT; + lp->tcount = 0; - enable_ast(dev, next_tick); + de4x5_ast(dev); - return (lp->media); + return lp->media; } /* @@ -4018,20 +4009,22 @@ DevicePresent(struct net_device *dev, u_long aprom_addr) outl(0, aprom_addr); /* Reset Ethernet Address ROM Pointer */ } } else { /* Read new srom */ - u_short tmp, *p = (short *)((char *)&lp->srom + SROM_HWADD); + u_short tmp; + __le16 *p = (__le16 *)((char *)&lp->srom + SROM_HWADD); for (i=0; i<(ETH_ALEN>>1); i++) { tmp = srom_rd(aprom_addr, (SROM_HWADD>>1) + i); - *p = le16_to_cpu(tmp); - j += *p++; + j += tmp; /* for check for 0:0:0:0:0:0 or ff:ff:ff:ff:ff:ff */ + *p = cpu_to_le16(tmp); } - if ((j == 0) || (j == 0x2fffd)) { - return; + if (j == 0 || j == 3 * 0xffff) { + /* could get 0 only from all-0 and 3 * 0xffff only from all-1 */ + return; } - p=(short *)&lp->srom; + p = (__le16 *)&lp->srom; for (i=0; i<(sizeof(struct de4x5_srom)>>1); i++) { tmp = srom_rd(aprom_addr, i); - *p++ = le16_to_cpu(tmp); + *p++ = cpu_to_le16(tmp); } de4x5_dbg_srom((struct de4x5_srom *)&lp->srom); } @@ -5161,21 +5154,10 @@ build_setup_frame(struct net_device *dev, int mode) } static void -enable_ast(struct net_device *dev, u32 time_out) -{ - timeout(dev, (void *)&de4x5_ast, (u_long)dev, time_out); - - return; -} - -static void disable_ast(struct net_device *dev) { - struct de4x5_private *lp = netdev_priv(dev); - - del_timer(&lp->timer); - - return; + struct de4x5_private *lp = netdev_priv(dev); + del_timer_sync(&lp->timer); } static long @@ -5245,29 +5227,6 @@ gep_rd(struct net_device *dev) } static void -timeout(struct net_device *dev, void (*fn)(u_long data), u_long data, u_long msec) -{ - struct de4x5_private *lp = netdev_priv(dev); - int dt; - - /* First, cancel any pending timer events */ - del_timer(&lp->timer); - - /* Convert msec to ticks */ - dt = (msec * HZ) / 1000; - if (dt==0) dt=1; - - /* Set up timer */ - init_timer(&lp->timer); - lp->timer.expires = jiffies + dt; - lp->timer.function = fn; - lp->timer.data = data; - add_timer(&lp->timer); - - return; -} - -static void yawn(struct net_device *dev, int state) { struct de4x5_private *lp = netdev_priv(dev); diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c index ca90566d5bc..b4891caeae5 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/tulip/interrupt.c b/drivers/net/tulip/interrupt.c index 36533144638..6284afd14bb 100644 --- a/drivers/net/tulip/interrupt.c +++ b/drivers/net/tulip/interrupt.c @@ -117,9 +117,6 @@ int tulip_poll(struct napi_struct *napi, int budget) int received = 0; #endif - if (!netif_running(dev)) - goto done; - #ifdef CONFIG_TULIP_NAPI_HW_MITIGATION /* that one buffer is needed for mit activation; or might be a @@ -151,7 +148,8 @@ int tulip_poll(struct napi_struct *napi, int budget) if (tulip_debug > 5) printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %8.8x.\n", dev->name, entry, status); - if (work_done++ >= budget) + + if (++work_done >= budget) goto not_done; if ((status & 0x38008300) != 0x0300) { @@ -260,8 +258,6 @@ int tulip_poll(struct napi_struct *napi, int budget) * finally: amount of IO did not increase at all. */ } while ((ioread32(tp->base_addr + CSR5) & RxIntr)); -done: - #ifdef CONFIG_TULIP_NAPI_HW_MITIGATION /* We use this simplistic scheme for IM. It's proven by diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index e5e2c9c4ebf..ed600bf56e7 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -797,7 +797,8 @@ static int tulip_close (struct net_device *dev) tp->rx_ring[i].status = 0; /* Not owned by Tulip chip. */ tp->rx_ring[i].length = 0; - tp->rx_ring[i].buffer1 = 0xBADF00D0; /* An invalid address. */ + /* An invalid address. */ + tp->rx_ring[i].buffer1 = cpu_to_le32(0xBADF00D0); if (skb) { pci_unmap_single(tp->pdev, mapping, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c index 70befe33e45..8fc7274642e 100644 --- a/drivers/net/tulip/xircom_cb.c +++ b/drivers/net/tulip/xircom_cb.c @@ -83,8 +83,8 @@ static int bufferoffsets[NUMDESCRIPTORS] = {128,2048,4096,6144}; struct xircom_private { /* Send and receive buffers, kernel-addressable and dma addressable forms */ - unsigned int *rx_buffer; - unsigned int *tx_buffer; + __le32 *rx_buffer; + __le32 *tx_buffer; dma_addr_t rx_dma_handle; dma_addr_t tx_dma_handle; @@ -412,19 +412,20 @@ static int xircom_start_xmit(struct sk_buff *skb, struct net_device *dev) /* FIXME: The specification tells us that the length we send HAS to be a multiple of 4 bytes. */ - card->tx_buffer[4*desc+1] = skb->len; - if (desc == NUMDESCRIPTORS-1) - card->tx_buffer[4*desc+1] |= (1<<25); /* bit 25: last descriptor of the ring */ + card->tx_buffer[4*desc+1] = cpu_to_le32(skb->len); + if (desc == NUMDESCRIPTORS - 1) /* bit 25: last descriptor of the ring */ + card->tx_buffer[4*desc+1] |= cpu_to_le32(1<<25); - card->tx_buffer[4*desc+1] |= 0xF0000000; + card->tx_buffer[4*desc+1] |= cpu_to_le32(0xF0000000); /* 0xF0... means want interrupts*/ card->tx_skb[desc] = skb; wmb(); /* This gives the descriptor to the card */ - card->tx_buffer[4*desc] = 0x80000000; + card->tx_buffer[4*desc] = cpu_to_le32(0x80000000); trigger_transmit(card); - if (((int)card->tx_buffer[nextdescriptor*4])<0) { /* next descriptor is occupied... */ + if (card->tx_buffer[nextdescriptor*4] & cpu_to_le32(0x8000000)) { + /* next descriptor is occupied... */ netif_stop_queue(dev); } card->transmit_used = nextdescriptor; @@ -590,8 +591,7 @@ descriptors and programs the addresses into the card. */ static void setup_descriptors(struct xircom_private *card) { - unsigned int val; - unsigned int address; + u32 address; int i; enter("setup_descriptors"); @@ -604,16 +604,16 @@ static void setup_descriptors(struct xircom_private *card) for (i=0;i<NUMDESCRIPTORS;i++ ) { /* Rx Descr0: It's empty, let the card own it, no errors -> 0x80000000 */ - card->rx_buffer[i*4 + 0] = 0x80000000; + card->rx_buffer[i*4 + 0] = cpu_to_le32(0x80000000); /* Rx Descr1: buffer 1 is 1536 bytes, buffer 2 is 0 bytes */ - card->rx_buffer[i*4 + 1] = 1536; - if (i==NUMDESCRIPTORS-1) - card->rx_buffer[i*4 + 1] |= (1 << 25); /* bit 25 is "last descriptor" */ + card->rx_buffer[i*4 + 1] = cpu_to_le32(1536); + if (i == NUMDESCRIPTORS - 1) /* bit 25 is "last descriptor" */ + card->rx_buffer[i*4 + 1] |= cpu_to_le32(1 << 25); /* Rx Descr2: address of the buffer we store the buffer at the 2nd half of the page */ - address = (unsigned long) card->rx_dma_handle; + address = card->rx_dma_handle; card->rx_buffer[i*4 + 2] = cpu_to_le32(address + bufferoffsets[i]); /* Rx Desc3: address of 2nd buffer -> 0 */ card->rx_buffer[i*4 + 3] = 0; @@ -621,9 +621,8 @@ static void setup_descriptors(struct xircom_private *card) wmb(); /* Write the receive descriptor ring address to the card */ - address = (unsigned long) card->rx_dma_handle; - val = cpu_to_le32(address); - outl(val, card->io_port + CSR3); /* Receive descr list address */ + address = card->rx_dma_handle; + outl(address, card->io_port + CSR3); /* Receive descr list address */ /* transmit descriptors */ @@ -633,13 +632,13 @@ static void setup_descriptors(struct xircom_private *card) /* Tx Descr0: Empty, we own it, no errors -> 0x00000000 */ card->tx_buffer[i*4 + 0] = 0x00000000; /* Tx Descr1: buffer 1 is 1536 bytes, buffer 2 is 0 bytes */ - card->tx_buffer[i*4 + 1] = 1536; - if (i==NUMDESCRIPTORS-1) - card->tx_buffer[i*4 + 1] |= (1 << 25); /* bit 25 is "last descriptor" */ + card->tx_buffer[i*4 + 1] = cpu_to_le32(1536); + if (i == NUMDESCRIPTORS - 1) /* bit 25 is "last descriptor" */ + card->tx_buffer[i*4 + 1] |= cpu_to_le32(1 << 25); /* Tx Descr2: address of the buffer we store the buffer at the 2nd half of the page */ - address = (unsigned long) card->tx_dma_handle; + address = card->tx_dma_handle; card->tx_buffer[i*4 + 2] = cpu_to_le32(address + bufferoffsets[i]); /* Tx Desc3: address of 2nd buffer -> 0 */ card->tx_buffer[i*4 + 3] = 0; @@ -647,9 +646,8 @@ static void setup_descriptors(struct xircom_private *card) wmb(); /* wite the transmit descriptor ring to the card */ - address = (unsigned long) card->tx_dma_handle; - val =cpu_to_le32(address); - outl(val, card->io_port + CSR4); /* xmit descr list address */ + address = card->tx_dma_handle; + outl(address, card->io_port + CSR4); /* xmit descr list address */ leave("setup_descriptors"); } @@ -1180,7 +1178,7 @@ static void investigate_read_descriptor(struct net_device *dev,struct xircom_pri int status; enter("investigate_read_descriptor"); - status = card->rx_buffer[4*descnr]; + status = le32_to_cpu(card->rx_buffer[4*descnr]); if ((status > 0)) { /* packet received */ @@ -1210,7 +1208,7 @@ static void investigate_read_descriptor(struct net_device *dev,struct xircom_pri out: /* give the buffer back to the card */ - card->rx_buffer[4*descnr] = 0x80000000; + card->rx_buffer[4*descnr] = cpu_to_le32(0x80000000); trigger_receive(card); } @@ -1226,7 +1224,7 @@ static void investigate_write_descriptor(struct net_device *dev, struct xircom_p enter("investigate_write_descriptor"); - status = card->tx_buffer[4*descnr]; + status = le32_to_cpu(card->tx_buffer[4*descnr]); #if 0 if (status & 0x8000) { /* Major error */ printk(KERN_ERR "Major transmit error status %x \n", status); diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 1f764469597..f8b8c71187a 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -610,7 +610,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, tun->flags &= ~TUN_PERSIST; DBG(KERN_INFO "%s: persist %s\n", - tun->dev->name, arg ? "disabled" : "enabled"); + tun->dev->name, arg ? "enabled" : "disabled"); break; case TUNSETOWNER: diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index 94ac5869bb1..f50cb520dff 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -813,8 +813,7 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev) first_txd->flags = TYPHOON_TX_DESC | TYPHOON_DESC_VALID; first_txd->numDesc = 0; first_txd->len = 0; - first_txd->addr = (u64)((unsigned long) skb) & 0xffffffff; - first_txd->addrHi = (u64)((unsigned long) skb) >> 32; + first_txd->tx_addr = (u64)((unsigned long) skb); first_txd->processFlags = 0; if(skb->ip_summed == CHECKSUM_PARTIAL) { @@ -850,8 +849,8 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev) PCI_DMA_TODEVICE); txd->flags = TYPHOON_FRAG_DESC | TYPHOON_DESC_VALID; txd->len = cpu_to_le16(skb->len); - txd->addr = cpu_to_le32(skb_dma); - txd->addrHi = 0; + txd->frag.addr = cpu_to_le32(skb_dma); + txd->frag.addrHi = 0; first_txd->numDesc++; } else { int i, len; @@ -861,8 +860,8 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev) PCI_DMA_TODEVICE); txd->flags = TYPHOON_FRAG_DESC | TYPHOON_DESC_VALID; txd->len = cpu_to_le16(len); - txd->addr = cpu_to_le32(skb_dma); - txd->addrHi = 0; + txd->frag.addr = cpu_to_le32(skb_dma); + txd->frag.addrHi = 0; first_txd->numDesc++; for(i = 0; i < skb_shinfo(skb)->nr_frags; i++) { @@ -880,8 +879,8 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev) PCI_DMA_TODEVICE); txd->flags = TYPHOON_FRAG_DESC | TYPHOON_DESC_VALID; txd->len = cpu_to_le16(len); - txd->addr = cpu_to_le32(skb_dma); - txd->addrHi = 0; + txd->frag.addr = cpu_to_le32(skb_dma); + txd->frag.addrHi = 0; first_txd->numDesc++; } } @@ -977,12 +976,12 @@ typhoon_do_get_stats(struct typhoon *tp) * ethtool_ops->get_{strings,stats}() */ stats->tx_packets = le32_to_cpu(s->txPackets); - stats->tx_bytes = le32_to_cpu(s->txBytes); + stats->tx_bytes = le64_to_cpu(s->txBytes); stats->tx_errors = le32_to_cpu(s->txCarrierLost); stats->tx_carrier_errors = le32_to_cpu(s->txCarrierLost); stats->collisions = le32_to_cpu(s->txMultipleCollisions); stats->rx_packets = le32_to_cpu(s->rxPacketsGood); - stats->rx_bytes = le32_to_cpu(s->rxBytesGood); + stats->rx_bytes = le64_to_cpu(s->rxBytesGood); stats->rx_fifo_errors = le32_to_cpu(s->rxFifoOverruns); stats->rx_errors = le32_to_cpu(s->rxFifoOverruns) + le32_to_cpu(s->BadSSD) + le32_to_cpu(s->rxCrcErrors); @@ -1056,7 +1055,7 @@ typhoon_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) if(typhoon_issue_command(tp, 1, &xp_cmd, 3, xp_resp) < 0) { strcpy(info->fw_version, "Unknown runtime"); } else { - u32 sleep_ver = xp_resp[0].parm2; + u32 sleep_ver = le32_to_cpu(xp_resp[0].parm2); snprintf(info->fw_version, 32, "%02x.%03x.%03x", sleep_ver >> 24, (sleep_ver >> 12) & 0xfff, sleep_ver & 0xfff); @@ -1157,7 +1156,7 @@ typhoon_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) } INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_XCVR_SELECT); - xp_cmd.parm1 = cpu_to_le16(xcvr); + xp_cmd.parm1 = xcvr; err = typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL); if(err < 0) goto out; @@ -1320,7 +1319,7 @@ typhoon_init_interface(struct typhoon *tp) tp->txLoRing.writeRegister = TYPHOON_REG_TX_LO_READY; tp->txHiRing.writeRegister = TYPHOON_REG_TX_HI_READY; - tp->txlo_dma_addr = iface->txLoAddr; + tp->txlo_dma_addr = le32_to_cpu(iface->txLoAddr); tp->card_state = Sleeping; smp_wmb(); @@ -1358,7 +1357,7 @@ typhoon_download_firmware(struct typhoon *tp) u8 *image_data; void *dpage; dma_addr_t dpage_dma; - unsigned int csum; + __sum16 csum; u32 irqEnabled; u32 irqMasked; u32 numSections; @@ -1450,13 +1449,13 @@ typhoon_download_firmware(struct typhoon *tp) * summing. Fortunately, due to the properties of * the checksum, we can do this once, at the end. */ - csum = csum_partial_copy_nocheck(image_data, dpage, - len, 0); - csum = csum_fold(csum); - csum = le16_to_cpu(csum); + csum = csum_fold(csum_partial_copy_nocheck(image_data, + dpage, len, + 0)); iowrite32(len, ioaddr + TYPHOON_REG_BOOT_LENGTH); - iowrite32(csum, ioaddr + TYPHOON_REG_BOOT_CHECKSUM); + iowrite32(le16_to_cpu((__force __le16)csum), + ioaddr + TYPHOON_REG_BOOT_CHECKSUM); iowrite32(load_addr, ioaddr + TYPHOON_REG_BOOT_DEST_ADDR); iowrite32(0, ioaddr + TYPHOON_REG_BOOT_DATA_HI); @@ -1551,13 +1550,13 @@ typhoon_clean_tx(struct typhoon *tp, struct transmit_ring *txRing, if(type == TYPHOON_TX_DESC) { /* This tx_desc describes a packet. */ - unsigned long ptr = tx->addr | ((u64)tx->addrHi << 32); + unsigned long ptr = tx->tx_addr; struct sk_buff *skb = (struct sk_buff *) ptr; dev_kfree_skb_irq(skb); } else if(type == TYPHOON_FRAG_DESC) { /* This tx_desc describes a memory mapping. Free it. */ - skb_dma = (dma_addr_t) le32_to_cpu(tx->addr); + skb_dma = (dma_addr_t) le32_to_cpu(tx->frag.addr); dma_len = le16_to_cpu(tx->len); pci_unmap_single(tp->pdev, skb_dma, dma_len, PCI_DMA_TODEVICE); @@ -1596,7 +1595,7 @@ typhoon_recycle_rx_skb(struct typhoon *tp, u32 idx) struct rx_free *r; if((ring->lastWrite + sizeof(*r)) % (RXFREE_ENTRIES * sizeof(*r)) == - indexes->rxBuffCleared) { + le32_to_cpu(indexes->rxBuffCleared)) { /* no room in ring, just drop the skb */ dev_kfree_skb_any(rxb->skb); @@ -1627,7 +1626,7 @@ typhoon_alloc_rx_skb(struct typhoon *tp, u32 idx) rxb->skb = NULL; if((ring->lastWrite + sizeof(*r)) % (RXFREE_ENTRIES * sizeof(*r)) == - indexes->rxBuffCleared) + le32_to_cpu(indexes->rxBuffCleared)) return -ENOMEM; skb = dev_alloc_skb(PKT_BUF_SZ); diff --git a/drivers/net/typhoon.h b/drivers/net/typhoon.h index 19df20889b8..dd7022ca735 100644 --- a/drivers/net/typhoon.h +++ b/drivers/net/typhoon.h @@ -73,7 +73,7 @@ struct typhoon_indexes { volatile __le32 txLoCleared; volatile __le32 txHiCleared; volatile __le32 rxLoReady; - volatile __u32 rxBuffCleared; /* AV: really? */ + volatile __le32 rxBuffCleared; volatile __le32 cmdCleared; volatile __le32 respReady; volatile __le32 rxHiReady; @@ -166,8 +166,13 @@ struct tx_desc { #define TYPHOON_DESC_VALID 0x80 u8 numDesc; __le16 len; - u32 addr; - u32 addrHi; + union { + struct { + __le32 addr; + __le32 addrHi; + } frag; + u64 tx_addr; /* opaque for hardware, for TX_DESC */ + }; __le32 processFlags; #define TYPHOON_TX_PF_NO_CRC __constant_cpu_to_le32(0x00000001) #define TYPHOON_TX_PF_IP_CHKSUM __constant_cpu_to_le32(0x00000002) @@ -240,8 +245,8 @@ struct rx_desc { u8 flags; u8 numDesc; __le16 frameLen; - u32 addr; - u32 addrHi; + u32 addr; /* opaque, comes from virtAddr */ + u32 addrHi; /* opaque, comes from virtAddrHi */ __le32 rxStatus; #define TYPHOON_RX_ERR_INTERNAL __constant_cpu_to_le32(0x00000000) #define TYPHOON_RX_ERR_FIFO_UNDERRUN __constant_cpu_to_le32(0x00000001) diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 9741d613ba6..abac7db3819 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; @@ -2214,9 +2218,7 @@ static void ucc_geth_set_multi(struct net_device *dev) struct dev_mc_list *dmi; struct ucc_fast *uf_regs; struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt; - u8 tempaddr[6]; - u8 *mcptr, *tdptr; - int i, j; + int i; ugeth = netdev_priv(dev); @@ -2255,19 +2257,10 @@ static void ucc_geth_set_multi(struct net_device *dev) if (!(dmi->dmi_addr[0] & 1)) continue; - /* The address in dmi_addr is LSB first, - * and taddr is MSB first. We have to - * copy bytes MSB first from dmi_addr. - */ - mcptr = (u8 *) dmi->dmi_addr + 5; - tdptr = (u8 *) tempaddr; - for (j = 0; j < 6; j++) - *tdptr++ = *mcptr--; - /* Ask CPM to run CRC and set bit in * filter mask. */ - hw_add_addr_in_hash(ugeth, tempaddr); + hw_add_addr_in_hash(ugeth, dmi->dmi_addr); } } } @@ -3454,7 +3447,7 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit u16 length, howmany = 0; u32 bd_status; u8 *bdBuffer; - struct net_device * dev; + struct net_device *dev; ugeth_vdbg("%s: IN", __FUNCTION__); @@ -3806,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; @@ -3900,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/ucc_geth_mii.h b/drivers/net/ucc_geth_mii.h index d8343703991..1e45b2028a5 100644 --- a/drivers/net/ucc_geth_mii.h +++ b/drivers/net/ucc_geth_mii.h @@ -96,5 +96,5 @@ enum enet_tbi_mii_reg { int uec_mdio_read(struct mii_bus *bus, int mii_id, int regnum); int uec_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value); int __init uec_mdio_init(void); -void __exit uec_mdio_exit(void); +void uec_mdio_exit(void); #endif /* __UEC_MII_H */ diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 5a96d74e4ce..a12c9c41b21 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/asix.c b/drivers/net/usb/asix.c index 61daa096de6..569028b2baf 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -172,45 +172,76 @@ struct asix_data { }; struct ax88172_int_data { - u16 res1; + __le16 res1; u8 link; - u16 res2; + __le16 res2; u8 status; - u16 res3; + __le16 res3; } __attribute__ ((packed)); static int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, u16 size, void *data) { + void *buf; + int err = -ENOMEM; + devdbg(dev,"asix_read_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d", cmd, value, index, size); - return usb_control_msg( + + buf = kmalloc(size, GFP_KERNEL); + if (!buf) + goto out; + + err = usb_control_msg( dev->udev, usb_rcvctrlpipe(dev->udev, 0), cmd, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, index, - data, + buf, size, USB_CTRL_GET_TIMEOUT); + if (err == size) + memcpy(data, buf, size); + else if (err >= 0) + err = -EINVAL; + kfree(buf); + +out: + return err; } static int asix_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, u16 size, void *data) { + void *buf = NULL; + int err = -ENOMEM; + devdbg(dev,"asix_write_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d", cmd, value, index, size); - return usb_control_msg( + + if (data) { + buf = kmalloc(size, GFP_KERNEL); + if (!buf) + goto out; + memcpy(buf, data, size); + } + + err = usb_control_msg( dev->udev, usb_sndctrlpipe(dev->udev, 0), cmd, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, index, - data, + buf, size, USB_CTRL_SET_TIMEOUT); + kfree(buf); + +out: + return err; } static void asix_async_cmd_callback(struct urb *urb) @@ -402,25 +433,19 @@ static inline int asix_set_hw_mii(struct usbnet *dev) static inline int asix_get_phy_addr(struct usbnet *dev) { - int ret = 0; - void *buf; + u8 buf[2]; + int ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf); devdbg(dev, "asix_get_phy_addr()"); - buf = kmalloc(2, GFP_KERNEL); - if (!buf) - goto out1; - - if ((ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID, - 0, 0, 2, buf)) < 2) { + if (ret < 0) { deverr(dev, "Error reading PHYID register: %02x", ret); - goto out2; + goto out; } - devdbg(dev, "asix_get_phy_addr() returning 0x%04x", *((u16 *)buf)); - ret = *((u8 *)buf + 1); -out2: - kfree(buf); -out1: + devdbg(dev, "asix_get_phy_addr() returning 0x%04x", *((__le16 *)buf)); + ret = buf[1]; + +out: return ret; } @@ -437,22 +462,15 @@ static int asix_sw_reset(struct usbnet *dev, u8 flags) static u16 asix_read_rx_ctl(struct usbnet *dev) { - u16 ret = 0; - void *buf; - - buf = kmalloc(2, GFP_KERNEL); - if (!buf) - goto out1; + __le16 v; + int ret = asix_read_cmd(dev, AX_CMD_READ_RX_CTL, 0, 0, 2, &v); - if ((ret = asix_read_cmd(dev, AX_CMD_READ_RX_CTL, - 0, 0, 2, buf)) < 2) { + if (ret < 0) { deverr(dev, "Error reading RX_CTL register: %02x", ret); - goto out2; + goto out; } - ret = le16_to_cpu(*((u16 *)buf)); -out2: - kfree(buf); -out1: + ret = le16_to_cpu(v); +out: return ret; } @@ -471,22 +489,15 @@ static int asix_write_rx_ctl(struct usbnet *dev, u16 mode) static u16 asix_read_medium_status(struct usbnet *dev) { - u16 ret = 0; - void *buf; + __le16 v; + int ret = asix_read_cmd(dev, AX_CMD_READ_MEDIUM_STATUS, 0, 0, 2, &v); - buf = kmalloc(2, GFP_KERNEL); - if (!buf) - goto out1; - - if ((ret = asix_read_cmd(dev, AX_CMD_READ_MEDIUM_STATUS, - 0, 0, 2, buf)) < 2) { + if (ret < 0) { deverr(dev, "Error reading Medium Status register: %02x", ret); - goto out2; + goto out; } - ret = le16_to_cpu(*((u16 *)buf)); -out2: - kfree(buf); -out1: + ret = le16_to_cpu(v); +out: return ret; } @@ -568,31 +579,30 @@ static void asix_set_multicast(struct net_device *net) static int asix_mdio_read(struct net_device *netdev, int phy_id, int loc) { struct usbnet *dev = netdev_priv(netdev); - u16 res; + __le16 res; mutex_lock(&dev->phy_mutex); asix_set_sw_mii(dev); asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id, - (__u16)loc, 2, (u16 *)&res); + (__u16)loc, 2, &res); asix_set_hw_mii(dev); mutex_unlock(&dev->phy_mutex); - devdbg(dev, "asix_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x", phy_id, loc, le16_to_cpu(res & 0xffff)); + devdbg(dev, "asix_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x", phy_id, loc, le16_to_cpu(res)); - return le16_to_cpu(res & 0xffff); + return le16_to_cpu(res); } static void asix_mdio_write(struct net_device *netdev, int phy_id, int loc, int val) { struct usbnet *dev = netdev_priv(netdev); - u16 res = cpu_to_le16(val); + __le16 res = cpu_to_le16(val); devdbg(dev, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x", phy_id, loc, val); mutex_lock(&dev->phy_mutex); asix_set_sw_mii(dev); - asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, - (__u16)loc, 2, (u16 *)&res); + asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, (__u16)loc, 2, &res); asix_set_hw_mii(dev); mutex_unlock(&dev->phy_mutex); } @@ -644,7 +654,6 @@ asix_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) { struct usbnet *dev = netdev_priv(net); u8 opt = 0; - u8 buf[1]; if (wolinfo->wolopts & WAKE_PHY) opt |= AX_MONITOR_LINK; @@ -654,7 +663,7 @@ asix_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) opt |= AX_MONITOR_MODE; if (asix_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE, - opt, 0, 0, &buf) < 0) + opt, 0, 0, NULL) < 0) return -EINVAL; return 0; @@ -672,7 +681,7 @@ static int asix_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom, u8 *data) { struct usbnet *dev = netdev_priv(net); - u16 *ebuf = (u16 *)data; + __le16 *ebuf = (__le16 *)data; int i; /* Crude hack to ensure that we don't overwrite memory @@ -801,7 +810,7 @@ static int ax88172_link_reset(struct usbnet *dev) static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf) { int ret = 0; - void *buf; + u8 buf[ETH_ALEN]; int i; unsigned long gpio_bits = dev->driver_info->data; struct asix_data *data = (struct asix_data *)&dev->data; @@ -810,30 +819,23 @@ static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf) usbnet_get_endpoints(dev,intf); - buf = kmalloc(ETH_ALEN, GFP_KERNEL); - if(!buf) { - ret = -ENOMEM; - goto out1; - } - /* Toggle the GPIOs in a manufacturer/model specific way */ for (i = 2; i >= 0; i--) { if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS, (gpio_bits >> (i * 8)) & 0xff, 0, 0, - buf)) < 0) - goto out2; + NULL)) < 0) + goto out; msleep(5); } if ((ret = asix_write_rx_ctl(dev, 0x80)) < 0) - goto out2; + goto out; /* Get the MAC address */ - memset(buf, 0, ETH_ALEN); if ((ret = asix_read_cmd(dev, AX88172_CMD_READ_NODE_ID, - 0, 0, 6, buf)) < 0) { + 0, 0, ETH_ALEN, buf)) < 0) { dbg("read AX_CMD_READ_NODE_ID failed: %d", ret); - goto out2; + goto out; } memcpy(dev->net->dev_addr, buf, ETH_ALEN); @@ -855,9 +857,8 @@ static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf) mii_nway_restart(&dev->mii); return 0; -out2: - kfree(buf); -out1: + +out: return ret; } @@ -900,66 +901,58 @@ static int ax88772_link_reset(struct usbnet *dev) static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) { int ret, embd_phy; - void *buf; u16 rx_ctl; struct asix_data *data = (struct asix_data *)&dev->data; + u8 buf[ETH_ALEN]; u32 phyid; data->eeprom_len = AX88772_EEPROM_LEN; usbnet_get_endpoints(dev,intf); - buf = kmalloc(6, GFP_KERNEL); - if(!buf) { - dbg ("Cannot allocate memory for buffer"); - ret = -ENOMEM; - goto out1; - } - if ((ret = asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5)) < 0) - goto out2; + goto out; /* 0x10 is the phy id of the embedded 10/100 ethernet phy */ embd_phy = ((asix_get_phy_addr(dev) & 0x1f) == 0x10 ? 1 : 0); if ((ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, - embd_phy, 0, 0, buf)) < 0) { + embd_phy, 0, 0, NULL)) < 0) { dbg("Select PHY #1 failed: %d", ret); - goto out2; + goto out; } if ((ret = asix_sw_reset(dev, AX_SWRESET_IPPD | AX_SWRESET_PRL)) < 0) - goto out2; + goto out; msleep(150); if ((ret = asix_sw_reset(dev, AX_SWRESET_CLEAR)) < 0) - goto out2; + goto out; msleep(150); if (embd_phy) { if ((ret = asix_sw_reset(dev, AX_SWRESET_IPRL)) < 0) - goto out2; + goto out; } else { if ((ret = asix_sw_reset(dev, AX_SWRESET_PRTE)) < 0) - goto out2; + goto out; } msleep(150); rx_ctl = asix_read_rx_ctl(dev); dbg("RX_CTL is 0x%04x after software reset", rx_ctl); if ((ret = asix_write_rx_ctl(dev, 0x0000)) < 0) - goto out2; + goto out; rx_ctl = asix_read_rx_ctl(dev); dbg("RX_CTL is 0x%04x setting to 0x0000", rx_ctl); /* Get the MAC address */ - memset(buf, 0, ETH_ALEN); if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf)) < 0) { dbg("Failed to read MAC address: %d", ret); - goto out2; + goto out; } memcpy(dev->net->dev_addr, buf, ETH_ALEN); @@ -976,12 +969,12 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) dbg("PHYID=0x%08x", phyid); if ((ret = asix_sw_reset(dev, AX_SWRESET_PRL)) < 0) - goto out2; + goto out; msleep(150); if ((ret = asix_sw_reset(dev, AX_SWRESET_IPRL | AX_SWRESET_PRL)) < 0) - goto out2; + goto out; msleep(150); @@ -994,18 +987,18 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) mii_nway_restart(&dev->mii); if ((ret = asix_write_medium_mode(dev, AX88772_MEDIUM_DEFAULT)) < 0) - goto out2; + goto out; if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_IPG0, AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT, - AX88772_IPG2_DEFAULT, 0, buf)) < 0) { + AX88772_IPG2_DEFAULT, 0, NULL)) < 0) { dbg("Write IPG,IPG1,IPG2 failed: %d", ret); - goto out2; + goto out; } /* Set RX_CTL to default values with 2k buffer, and enable cactus */ if ((ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL)) < 0) - goto out2; + goto out; rx_ctl = asix_read_rx_ctl(dev); dbg("RX_CTL is 0x%04x after all initializations", rx_ctl); @@ -1013,20 +1006,15 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) rx_ctl = asix_read_medium_status(dev); dbg("Medium Status is 0x%04x after all initializations", rx_ctl); - kfree(buf); - /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */ if (dev->driver_info->flags & FLAG_FRAMING_AX) { /* hard_mtu is still the default - the device does not support jumbo eth frames */ dev->rx_urb_size = 2048; } - return 0; -out2: - kfree(buf); -out1: +out: return ret; } @@ -1195,23 +1183,16 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf) { struct asix_data *data = (struct asix_data *)&dev->data; int ret; - void *buf; - u16 eeprom; + u8 buf[ETH_ALEN]; + __le16 eeprom; + u8 status; int gpio0 = 0; u32 phyid; usbnet_get_endpoints(dev,intf); - buf = kmalloc(6, GFP_KERNEL); - if(!buf) { - dbg ("Cannot allocate memory for buffer"); - ret = -ENOMEM; - goto out1; - } - - eeprom = 0; - asix_read_cmd(dev, AX_CMD_READ_GPIOS, 0, 0, 1, &eeprom); - dbg("GPIO Status: 0x%04x", eeprom); + asix_read_cmd(dev, AX_CMD_READ_GPIOS, 0, 0, 1, &status); + dbg("GPIO Status: 0x%04x", status); asix_write_cmd(dev, AX_CMD_WRITE_ENABLE, 0, 0, 0, NULL); asix_read_cmd(dev, AX_CMD_READ_EEPROM, 0x0017, 0, 2, &eeprom); @@ -1219,19 +1200,19 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf) dbg("EEPROM index 0x17 is 0x%04x", eeprom); - if (eeprom == 0xffff) { + if (eeprom == cpu_to_le16(0xffff)) { data->phymode = PHY_MODE_MARVELL; data->ledmode = 0; gpio0 = 1; } else { - data->phymode = eeprom & 7; - data->ledmode = eeprom >> 8; - gpio0 = (eeprom & 0x80) ? 0 : 1; + data->phymode = le16_to_cpu(eeprom) & 7; + data->ledmode = le16_to_cpu(eeprom) >> 8; + gpio0 = (le16_to_cpu(eeprom) & 0x80) ? 0 : 1; } dbg("GPIO0: %d, PhyMode: %d", gpio0, data->phymode); asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_1 | AX_GPIO_GPO1EN, 40); - if ((eeprom >> 8) != 1) { + if ((le16_to_cpu(eeprom) >> 8) != 1) { asix_write_gpio(dev, 0x003c, 30); asix_write_gpio(dev, 0x001c, 300); asix_write_gpio(dev, 0x003c, 30); @@ -1250,11 +1231,10 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf) asix_write_rx_ctl(dev, 0); /* Get the MAC address */ - memset(buf, 0, ETH_ALEN); if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf)) < 0) { dbg("Failed to read MAC address: %d", ret); - goto out2; + goto out; } memcpy(dev->net->dev_addr, buf, ETH_ALEN); @@ -1289,12 +1269,10 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf) mii_nway_restart(&dev->mii); if ((ret = asix_write_medium_mode(dev, AX88178_MEDIUM_DEFAULT)) < 0) - goto out2; + goto out; if ((ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL)) < 0) - goto out2; - - kfree(buf); + goto out; /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */ if (dev->driver_info->flags & FLAG_FRAMING_AX) { @@ -1302,12 +1280,9 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf) jumbo eth frames */ dev->rx_urb_size = 2048; } - return 0; -out2: - kfree(buf); -out1: +out: return ret; } diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index a2de32fabc1..1ffdd106f4c 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); @@ -586,6 +586,10 @@ static const struct usb_device_id products[] = { USB_DEVICE(0x0a46, 0x0268), /* ShanTou ST268 USB NIC */ .driver_info = (unsigned long)&dm9601_info, }, + { + USB_DEVICE(0x0a46, 0x8515), /* ADMtek ADM8515 USB NIC */ + .driver_info = (unsigned long)&dm9601_info, + }, {}, // END }; diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index 58a53a64175..569ad8bfd38 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c @@ -70,7 +70,7 @@ #define KAWETH_TX_TIMEOUT (5 * HZ) #define KAWETH_SCRATCH_SIZE 32 #define KAWETH_FIRMWARE_BUF_SIZE 4096 -#define KAWETH_CONTROL_TIMEOUT (30 * HZ) +#define KAWETH_CONTROL_TIMEOUT (30000) #define KAWETH_STATUS_BROKEN 0x0000001 #define KAWETH_STATUS_CLOSING 0x0000002 diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c index f55a5951733..5ea7411e133 100644 --- a/drivers/net/usb/mcs7830.c +++ b/drivers/net/usb/mcs7830.c @@ -94,7 +94,7 @@ static int mcs7830_get_reg(struct usbnet *dev, u16 index, u16 size, void *data) ret = usb_control_msg(xdev, usb_rcvctrlpipe(xdev, 0), MCS7830_RD_BREQ, MCS7830_RD_BMREQ, 0x0000, index, data, - size, msecs_to_jiffies(MCS7830_CTRL_TIMEOUT)); + size, MCS7830_CTRL_TIMEOUT); return ret; } @@ -105,7 +105,7 @@ static int mcs7830_set_reg(struct usbnet *dev, u16 index, u16 size, void *data) ret = usb_control_msg(xdev, usb_sndctrlpipe(xdev, 0), MCS7830_WR_BREQ, MCS7830_WR_BMREQ, 0x0000, index, data, - size, msecs_to_jiffies(MCS7830_CTRL_TIMEOUT)); + size, MCS7830_CTRL_TIMEOUT); return ret; } diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index acd5f1c0e63..8ed1fc5cbc7 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/veth.c b/drivers/net/veth.c index fdd1e034569..43af9e9b265 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -15,7 +15,7 @@ #include <net/dst.h> #include <net/xfrm.h> -#include <net/veth.h> +#include <linux/veth.h> #define DRV_NAME "veth" #define DRV_VERSION "1.0" diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 5c4a92de9a0..35cd65d6b9e 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 e396c9d2af8..5413dbf3d4a 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/cycx_x25.c b/drivers/net/wan/cycx_x25.c index 8a1778cf98d..d3b28b01b9f 100644 --- a/drivers/net/wan/cycx_x25.c +++ b/drivers/net/wan/cycx_x25.c @@ -503,7 +503,7 @@ static int cycx_netdevice_init(struct net_device *dev) dev->addr_len = 0; /* hardware address length */ if (!chan->svc) - *(u16*)dev->dev_addr = htons(chan->lcn); + *(__be16*)dev->dev_addr = htons(chan->lcn); /* Initialize hardware parameters (just for reference) */ dev->irq = wandev->irq; @@ -565,7 +565,7 @@ static int cycx_netdevice_hard_header(struct sk_buff *skb, const void *daddr, const void *saddr, unsigned len) { - skb->protocol = type; + skb->protocol = htons(type); return dev->hard_header_len; } @@ -600,15 +600,15 @@ static int cycx_netdevice_hard_start_xmit(struct sk_buff *skb, struct cycx_device *card = chan->card; if (!chan->svc) - chan->protocol = skb->protocol; + chan->protocol = ntohs(skb->protocol); if (card->wandev.state != WAN_CONNECTED) ++chan->ifstats.tx_dropped; else if (chan->svc && chan->protocol && - chan->protocol != skb->protocol) { + chan->protocol != ntohs(skb->protocol)) { printk(KERN_INFO "%s: unsupported Ethertype 0x%04X on interface %s!\n", - card->devname, skb->protocol, dev->name); + card->devname, ntohs(skb->protocol), dev->name); ++chan->ifstats.tx_errors; } else if (chan->protocol == ETH_P_IP) { switch (chan->state) { @@ -1401,7 +1401,7 @@ static void cycx_x25_set_chan_state(struct net_device *dev, u8 state) switch (state) { case WAN_CONNECTED: string_state = "connected!"; - *(u16*)dev->dev_addr = htons(chan->lcn); + *(__be16*)dev->dev_addr = htons(chan->lcn); netif_wake_queue(dev); reset_timer(dev); diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c index 5ea877221f4..37c52e13175 100644 --- a/drivers/net/wan/lmc/lmc_main.c +++ b/drivers/net/wan/lmc/lmc_main.c @@ -142,9 +142,10 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ * To date internally, just copy this out to the user. */ case LMCIOCGINFO: /*fold01*/ - if (copy_to_user(ifr->ifr_data, &sc->ictl, sizeof (lmc_ctl_t))) - return -EFAULT; - ret = 0; + if (copy_to_user(ifr->ifr_data, &sc->ictl, sizeof(lmc_ctl_t))) + ret = -EFAULT; + else + ret = 0; break; case LMCIOCSINFO: /*fold01*/ @@ -159,8 +160,10 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ break; } - if (copy_from_user(&ctl, ifr->ifr_data, sizeof (lmc_ctl_t))) - return -EFAULT; + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(lmc_ctl_t))) { + ret = -EFAULT; + break; + } sc->lmc_media->set_status (sc, &ctl); @@ -190,8 +193,10 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ break; } - if (copy_from_user(&new_type, ifr->ifr_data, sizeof(u_int16_t))) - return -EFAULT; + if (copy_from_user(&new_type, ifr->ifr_data, sizeof(u_int16_t))) { + ret = -EFAULT; + break; + } if (new_type == old_type) @@ -229,9 +234,10 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ sc->lmc_xinfo.Magic1 = 0xDEADBEEF; if (copy_to_user(ifr->ifr_data, &sc->lmc_xinfo, - sizeof (struct lmc_xinfo))) - return -EFAULT; - ret = 0; + sizeof(struct lmc_xinfo))) + ret = -EFAULT; + else + ret = 0; break; @@ -262,9 +268,9 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ if (copy_to_user(ifr->ifr_data, &sc->stats, sizeof (struct lmc_statistics))) - return -EFAULT; - - ret = 0; + ret = -EFAULT; + else + ret = 0; break; case LMCIOCCLEARLMCSTATS: /*fold01*/ @@ -292,8 +298,10 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ break; } - if (copy_from_user(&ctl, ifr->ifr_data, sizeof (lmc_ctl_t))) - return -EFAULT; + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(lmc_ctl_t))) { + ret = -EFAULT; + break; + } sc->lmc_media->set_circuit_type(sc, ctl.circuit_type); sc->ictl.circuit_type = ctl.circuit_type; ret = 0; @@ -318,12 +326,15 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ #ifdef DEBUG case LMCIOCDUMPEVENTLOG: - if (copy_to_user(ifr->ifr_data, &lmcEventLogIndex, sizeof (u32))) - return -EFAULT; + if (copy_to_user(ifr->ifr_data, &lmcEventLogIndex, sizeof(u32))) { + ret = -EFAULT; + break; + } if (copy_to_user(ifr->ifr_data + sizeof (u32), lmcEventLogBuf, sizeof (lmcEventLogBuf))) - return -EFAULT; + ret = -EFAULT; + else + ret = 0; - ret = 0; break; #endif /* end ifdef _DBG_EVENTLOG */ case LMCIOCT1CONTROL: /*fold01*/ @@ -346,8 +357,10 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ */ netif_stop_queue(dev); - if (copy_from_user(&xc, ifr->ifr_data, sizeof (struct lmc_xilinx_control))) - return -EFAULT; + if (copy_from_user(&xc, ifr->ifr_data, sizeof(struct lmc_xilinx_control))) { + ret = -EFAULT; + break; + } switch(xc.command){ case lmc_xilinx_reset: /*fold02*/ { diff --git a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c index 232ecba5340..61e24b7a45a 100644 --- a/drivers/net/wan/syncppp.c +++ b/drivers/net/wan/syncppp.c @@ -107,24 +107,24 @@ struct ppp_header { u8 address; u8 control; - u16 protocol; + __be16 protocol; }; #define PPP_HEADER_LEN sizeof (struct ppp_header) struct lcp_header { u8 type; u8 ident; - u16 len; + __be16 len; }; #define LCP_HEADER_LEN sizeof (struct lcp_header) struct cisco_packet { - u32 type; - u32 par1; - u32 par2; - u16 rel; - u16 time0; - u16 time1; + __be32 type; + __be32 par1; + __be32 par2; + __be16 rel; + __be16 time0; + __be16 time1; }; #define CISCO_PACKET_LEN 18 #define CISCO_BIG_PACKET_LEN 20 @@ -139,7 +139,7 @@ static struct sk_buff_head tx_queue; static void sppp_keepalive (unsigned long dummy); static void sppp_cp_send (struct sppp *sp, u16 proto, u8 type, u8 ident, u16 len, void *data); -static void sppp_cisco_send (struct sppp *sp, int type, long par1, long par2); +static void sppp_cisco_send (struct sppp *sp, int type, u32 par1, u32 par2); static void sppp_lcp_input (struct sppp *sp, struct sk_buff *m); static void sppp_cisco_input (struct sppp *sp, struct sk_buff *m); static void sppp_ipcp_input (struct sppp *sp, struct sk_buff *m); @@ -447,7 +447,7 @@ static void sppp_keepalive (unsigned long dummy) sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, ++sp->pp_seq, sp->pp_rseq); else if (sp->lcp.state == LCP_STATE_OPENED) { - long nmagic = htonl (sp->lcp.magic); + __be32 nmagic = htonl (sp->lcp.magic); sp->lcp.echoid = ++sp->pp_seq; sppp_cp_send (sp, PPP_LCP, LCP_ECHO_REQ, sp->lcp.echoid, 4, &nmagic); @@ -667,7 +667,7 @@ badreq: dev->name, len); break; } - if (ntohl (*(long*)(h+1)) == sp->lcp.magic) { + if (ntohl (*(__be32*)(h+1)) == sp->lcp.magic) { /* Line loopback mode detected. */ printk (KERN_WARNING "%s: loopback\n", dev->name); if_down (dev); @@ -680,7 +680,7 @@ badreq: sppp_lcp_open (sp); break; } - *(long*)(h+1) = htonl (sp->lcp.magic); + *(__be32 *)(h+1) = htonl (sp->lcp.magic); sppp_cp_send (sp, PPP_LCP, LCP_ECHO_REPLY, h->ident, len-4, h+1); break; case LCP_ECHO_REPLY: @@ -692,7 +692,7 @@ badreq: dev->name, len); break; } - if (ntohl (*(long*)(h+1)) != sp->lcp.magic) + if (ntohl(*(__be32 *)(h+1)) != sp->lcp.magic) sp->pp_alivecnt = 0; break; } @@ -765,7 +765,7 @@ static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb) { struct in_device *in_dev; struct in_ifaddr *ifa; - __be32 addr = 0, mask = ~0; /* FIXME: is the mask correct? */ + __be32 addr = 0, mask = htonl(~0U); /* FIXME: is the mask correct? */ #ifdef CONFIG_INET rcu_read_lock(); if ((in_dev = __in_dev_get_rcu(dev)) != NULL) @@ -782,8 +782,7 @@ static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb) } rcu_read_unlock(); #endif - /* I hope both addr and mask are in the net order */ - sppp_cisco_send (sp, CISCO_ADDR_REPLY, addr, mask); + sppp_cisco_send (sp, CISCO_ADDR_REPLY, ntohl(addr), ntohl(mask)); break; } } @@ -844,7 +843,7 @@ static void sppp_cp_send (struct sppp *sp, u16 proto, u8 type, * Send Cisco keepalive packet. */ -static void sppp_cisco_send (struct sppp *sp, int type, long par1, long par2) +static void sppp_cisco_send (struct sppp *sp, int type, u32 par1, u32 par2) { struct ppp_header *h; struct cisco_packet *ch; @@ -868,7 +867,7 @@ static void sppp_cisco_send (struct sppp *sp, int type, long par1, long par2) ch->type = htonl (type); ch->par1 = htonl (par1); ch->par2 = htonl (par2); - ch->rel = -1; + ch->rel = htons(0xffff); ch->time0 = htons ((u16) (t >> 16)); ch->time1 = htons ((u16) t); diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index c48b1cc63fd..1e89d4de1bb 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 dae5c8d5a31..c98fc62a3e6 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -264,6 +264,7 @@ config IPW2200_DEBUG config LIBERTAS tristate "Marvell 8xxx Libertas WLAN driver support" depends on WLAN_80211 + select WIRELESS_EXT select IEEE80211 select FW_LOADER ---help--- @@ -325,7 +326,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 @@ -586,15 +587,66 @@ config ADM8211 config P54_COMMON tristate "Softmac Prism54 support" depends on MAC80211 && WLAN_80211 && FW_LOADER && EXPERIMENTAL + ---help--- + This is common code for isl38xx based cards. + This module does nothing by itself - the USB/PCI frontends + also need to be enabled in order to support any devices. + + These devices require softmac firmware which can be found at + http://prism54.org/ + + If you choose to build a module, it'll be called p54common. config P54_USB tristate "Prism54 USB support" depends on P54_COMMON && USB select CRC32 + ---help--- + This driver is for USB isl38xx based wireless cards. + These are USB based adapters found in devices such as: + + 3COM 3CRWE254G72 + SMC 2862W-G + Accton 802.11g WN4501 USB + Siemens Gigaset USB + Netgear WG121 + Netgear WG111 + Medion 40900, Roper Europe + Shuttle PN15, Airvast WM168g, IOGear GWU513 + Linksys WUSB54G + Linksys WUSB54G Portable + DLink DWL-G120 Spinnaker + DLink DWL-G122 + Belkin F5D7050 ver 1000 + Cohiba Proto board + SMC 2862W-G version 2 + U.S. Robotics U5 802.11g Adapter + FUJITSU E-5400 USB D1700 + Sagem XG703A + DLink DWL-G120 Cohiba + Spinnaker Proto board + Linksys WUSB54AG + Inventel UR054G + Spinnaker DUT + + These devices require softmac firmware which can be found at + http://prism54.org/ + + If you choose to build a module, it'll be called p54usb. config P54_PCI tristate "Prism54 PCI support" depends on P54_COMMON && PCI + ---help--- + This driver is for PCI isl38xx based wireless cards. + This driver supports most devices that are supported by the + fullmac prism54 driver plus many devices which are not + supported by the fullmac driver/firmware. + + This driver requires softmac firmware which can be found at + http://prism54.org/ + + If you choose to build a module, it'll be called p54pci. source "drivers/net/wireless/iwlwifi/Kconfig" source "drivers/net/wireless/hostap/Kconfig" diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index e3c573e56b6..fdbc351ac33 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/b43.h b/drivers/net/wireless/b43/b43.h index a28ad230d63..7b6fc1ab2b9 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -273,6 +273,8 @@ enum { #define B43_PHYTYPE_A 0x00 #define B43_PHYTYPE_B 0x01 #define B43_PHYTYPE_G 0x02 +#define B43_PHYTYPE_N 0x04 +#define B43_PHYTYPE_LP 0x05 /* PHYRegisters */ #define B43_PHY_ILT_A_CTRL 0x0072 diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c index 734e70e1a06..ef0075d9f9c 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/leds.c b/drivers/net/wireless/b43/leds.c index 19e588582c7..6c0e2b9f776 100644 --- a/drivers/net/wireless/b43/leds.c +++ b/drivers/net/wireless/b43/leds.c @@ -163,6 +163,9 @@ static void b43_map_led(struct b43_wldev *dev, b43_register_led(dev, &dev->led_radio, name, b43_rfkill_led_name(dev), led_index, activelow); + /* Sync the RF-kill LED state with the switch state. */ + if (dev->radio_hw_enable) + b43_led_turn_on(dev, led_index, activelow); break; case B43_LED_WEIRD: case B43_LED_ASSOC: @@ -232,4 +235,5 @@ void b43_leds_exit(struct b43_wldev *dev) b43_unregister_led(&dev->led_tx); b43_unregister_led(&dev->led_rx); b43_unregister_led(&dev->led_assoc); + b43_unregister_led(&dev->led_radio); } diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 9d9ff76a9bc..1c93b4f4bfe 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"); } @@ -2163,7 +2163,6 @@ static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna) static void b43_chip_exit(struct b43_wldev *dev) { b43_radio_turn_off(dev, 1); - b43_leds_exit(dev); b43_gpio_cleanup(dev); /* firmware is released later */ } @@ -2191,11 +2190,10 @@ static int b43_chip_init(struct b43_wldev *dev) err = b43_gpio_init(dev); if (err) goto out; /* firmware is released later */ - b43_leds_init(dev); err = b43_upload_initvals(dev); if (err) - goto err_leds_exit; + goto err_gpio_clean; b43_radio_turn_on(dev); b43_write16(dev, 0x03E6, 0x0000); @@ -2271,8 +2269,7 @@ out: err_radio_off: b43_radio_turn_off(dev, 1); -err_leds_exit: - b43_leds_exit(dev); +err_gpio_clean: b43_gpio_cleanup(dev); return err; } @@ -2391,7 +2388,7 @@ out_requeue: if (b43_debug(dev, B43_DBG_PWORK_FAST)) delay = msecs_to_jiffies(50); else - delay = round_jiffies(HZ * 15); + delay = round_jiffies_relative(HZ * 15); queue_delayed_work(wl->hw->workqueue, &dev->periodic_work, delay); out: mutex_unlock(&wl->mutex); @@ -2985,6 +2982,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 +3002,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"); @@ -3270,10 +3270,7 @@ static void b43_wireless_core_exit(struct b43_wldev *dev) return; b43_set_status(dev, B43_STAT_UNINIT); - mutex_unlock(&dev->wl->mutex); - b43_rfkill_exit(dev); - mutex_lock(&dev->wl->mutex); - + b43_leds_exit(dev); b43_rng_exit(dev->wl); b43_pio_free(dev); b43_dma_free(dev); @@ -3402,12 +3399,12 @@ static int b43_wireless_core_init(struct b43_wldev *dev) memset(wl->mac_addr, 0, ETH_ALEN); b43_upload_card_macaddress(dev); b43_security_init(dev); - b43_rfkill_init(dev); b43_rng_init(wl); b43_set_status(dev, B43_STAT_INITIALIZED); - out: + b43_leds_init(dev); +out: return err; err_chip_exit: @@ -3496,6 +3493,10 @@ static int b43_start(struct ieee80211_hw *hw) int did_init = 0; int err = 0; + /* First register RFkill. + * LEDs that are registered later depend on it. */ + b43_rfkill_init(dev); + mutex_lock(&wl->mutex); if (b43_status(dev) < B43_STAT_INITIALIZED) { @@ -3525,6 +3526,8 @@ static void b43_stop(struct ieee80211_hw *hw) struct b43_wl *wl = hw_to_b43_wl(hw); struct b43_wldev *dev = wl->current_dev; + b43_rfkill_exit(dev); + mutex_lock(&wl->mutex); if (b43_status(dev) >= B43_STAT_STARTED) b43_wireless_core_stop(dev); @@ -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/main.h b/drivers/net/wireless/b43/main.h index 284d17da17d..08e2e56e48f 100644 --- a/drivers/net/wireless/b43/main.h +++ b/drivers/net/wireless/b43/main.h @@ -39,11 +39,11 @@ #define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes)) /* Lightweight function to convert a frequency (in Mhz) to a channel number. */ -static inline u8 b43_freq_to_channel_a(int freq) +static inline u8 b43_freq_to_channel_5ghz(int freq) { return ((freq - 5000) / 5); } -static inline u8 b43_freq_to_channel_bg(int freq) +static inline u8 b43_freq_to_channel_2ghz(int freq) { u8 channel; @@ -54,19 +54,13 @@ static inline u8 b43_freq_to_channel_bg(int freq) return channel; } -static inline u8 b43_freq_to_channel(struct b43_wldev *dev, int freq) -{ - if (dev->phy.type == B43_PHYTYPE_A) - return b43_freq_to_channel_a(freq); - return b43_freq_to_channel_bg(freq); -} /* Lightweight function to convert a channel number to a frequency (in Mhz). */ -static inline int b43_channel_to_freq_a(u8 channel) +static inline int b43_channel_to_freq_5ghz(u8 channel) { return (5000 + (5 * channel)); } -static inline int b43_channel_to_freq_bg(u8 channel) +static inline int b43_channel_to_freq_2ghz(u8 channel) { int freq; @@ -77,12 +71,6 @@ static inline int b43_channel_to_freq_bg(u8 channel) return freq; } -static inline int b43_channel_to_freq(struct b43_wldev *dev, u8 channel) -{ - if (dev->phy.type == B43_PHYTYPE_A) - return b43_channel_to_freq_a(channel); - return b43_channel_to_freq_bg(channel); -} static inline int b43_is_cck_rate(int rate) { diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c index b242a9a90dd..b79a6bd5396 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 3d4ed647c31..7ff091e69f0 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 800e0a61a7f..98cf70c5fd4 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c @@ -25,6 +25,8 @@ #include "rfkill.h" #include "b43.h" +#include <linux/kmod.h> + /* Returns TRUE, if the radio is enabled in hardware. */ static bool b43_is_hw_radio_enabled(struct b43_wldev *dev) @@ -47,32 +49,44 @@ 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); + if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) { + mutex_unlock(&wl->mutex); + return; + } 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); - input_report_key(poll_dev->input, KEY_WLAN, enabled); - } else - mutex_unlock(&wl->mutex); + } + mutex_unlock(&wl->mutex); + + /* send the radio switch event to the system - note both a key press + * and a release are required */ + if (unlikely(report_change)) { + input_report_key(poll_dev->input, KEY_WLAN, 1); + input_report_key(poll_dev->input, KEY_WLAN, 0); + } } -/* 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; + int err = -EBUSY; + + if (!wl->rfkill.registered) + return 0; mutex_lock(&wl->mutex); if (b43_status(dev) < B43_STAT_INITIALIZED) goto out_unlock; - + err = 0; switch (state) { case RFKILL_STATE_ON: if (!dev->radio_hw_enable) { @@ -89,7 +103,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 +111,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 +124,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 +138,61 @@ 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 */ + + rfk->poll_dev->input->name = rfk->name; + rfk->poll_dev->input->id.bustype = BUS_HOST; + rfk->poll_dev->input->id.vendor = dev->dev->bus->boardinfo.vendor; + rfk->poll_dev->input->evbit[0] = BIT(EV_KEY); + set_bit(KEY_WLAN, rfk->poll_dev->input->keybit); + + err = rfkill_register(rfk->rfkill); + if (err) + goto err_free_polldev; + +#ifdef CONFIG_RFKILL_INPUT_MODULE + /* B43 RF-kill isn't useful without the rfkill-input subsystem. + * Try to load the module. */ + err = request_module("rfkill-input"); + if (err) + b43warn(wl, "Failed to load the rfkill-input module. " + "The built-in radio LED will not work.\n"); +#endif /* CONFIG_RFKILL_INPUT */ + + 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 29544e8c9e5..adacf936d81 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/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 0bd6f8a348a..3307ba1856b 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -531,21 +531,32 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) switch (chanstat & B43_RX_CHAN_PHYTYPE) { case B43_PHYTYPE_A: status.phymode = MODE_IEEE80211A; - status.freq = chanid; - status.channel = b43_freq_to_channel_a(chanid); - break; - case B43_PHYTYPE_B: - status.phymode = MODE_IEEE80211B; - status.freq = chanid + 2400; - status.channel = b43_freq_to_channel_bg(chanid + 2400); + B43_WARN_ON(1); + /* FIXME: We don't really know which value the "chanid" contains. + * So the following assignment might be wrong. */ + status.channel = chanid; + status.freq = b43_channel_to_freq_5ghz(status.channel); break; case B43_PHYTYPE_G: status.phymode = MODE_IEEE80211G; + /* chanid is the radio channel cookie value as used + * to tune the radio. */ status.freq = chanid + 2400; - status.channel = b43_freq_to_channel_bg(chanid + 2400); + status.channel = b43_freq_to_channel_2ghz(status.freq); + break; + case B43_PHYTYPE_N: + status.phymode = 0xDEAD /*FIXME MODE_IEEE80211N*/; + /* chanid is the SHM channel cookie. Which is the plain + * channel number in b43. */ + status.channel = chanid; + if (chanstat & B43_RX_CHAN_5GHZ) + status.freq = b43_freq_to_channel_5ghz(status.freq); + else + status.freq = b43_freq_to_channel_2ghz(status.freq); break; default: B43_WARN_ON(1); + goto drop; } dev->stats.last_rx = jiffies; diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h index 03bddd25161..6dc079382f7 100644 --- a/drivers/net/wireless/b43/xmit.h +++ b/drivers/net/wireless/b43/xmit.h @@ -142,49 +142,56 @@ struct b43_rxhdr_fw4 { } __attribute__ ((__packed__)); /* PHY RX Status 0 */ -#define B43_RX_PHYST0_GAINCTL 0x4000 /* Gain Control */ -#define B43_RX_PHYST0_PLCPHCF 0x0200 -#define B43_RX_PHYST0_PLCPFV 0x0100 -#define B43_RX_PHYST0_SHORTPRMBL 0x0080 /* Received with Short Preamble */ +#define B43_RX_PHYST0_GAINCTL 0x4000 /* Gain Control */ +#define B43_RX_PHYST0_PLCPHCF 0x0200 +#define B43_RX_PHYST0_PLCPFV 0x0100 +#define B43_RX_PHYST0_SHORTPRMBL 0x0080 /* Received with Short Preamble */ #define B43_RX_PHYST0_LCRS 0x0040 -#define B43_RX_PHYST0_ANT 0x0020 /* Antenna */ -#define B43_RX_PHYST0_UNSRATE 0x0010 +#define B43_RX_PHYST0_ANT 0x0020 /* Antenna */ +#define B43_RX_PHYST0_UNSRATE 0x0010 #define B43_RX_PHYST0_CLIP 0x000C #define B43_RX_PHYST0_CLIP_SHIFT 2 -#define B43_RX_PHYST0_FTYPE 0x0003 /* Frame type */ -#define B43_RX_PHYST0_CCK 0x0000 /* Frame type: CCK */ -#define B43_RX_PHYST0_OFDM 0x0001 /* Frame type: OFDM */ -#define B43_RX_PHYST0_PRE_N 0x0002 /* Pre-standard N-PHY frame */ -#define B43_RX_PHYST0_STD_N 0x0003 /* Standard N-PHY frame */ +#define B43_RX_PHYST0_FTYPE 0x0003 /* Frame type */ +#define B43_RX_PHYST0_CCK 0x0000 /* Frame type: CCK */ +#define B43_RX_PHYST0_OFDM 0x0001 /* Frame type: OFDM */ +#define B43_RX_PHYST0_PRE_N 0x0002 /* Pre-standard N-PHY frame */ +#define B43_RX_PHYST0_STD_N 0x0003 /* Standard N-PHY frame */ /* PHY RX Status 2 */ -#define B43_RX_PHYST2_LNAG 0xC000 /* LNA Gain */ +#define B43_RX_PHYST2_LNAG 0xC000 /* LNA Gain */ #define B43_RX_PHYST2_LNAG_SHIFT 14 -#define B43_RX_PHYST2_PNAG 0x3C00 /* PNA Gain */ +#define B43_RX_PHYST2_PNAG 0x3C00 /* PNA Gain */ #define B43_RX_PHYST2_PNAG_SHIFT 10 -#define B43_RX_PHYST2_FOFF 0x03FF /* F offset */ +#define B43_RX_PHYST2_FOFF 0x03FF /* F offset */ /* PHY RX Status 3 */ -#define B43_RX_PHYST3_DIGG 0x1800 /* DIG Gain */ +#define B43_RX_PHYST3_DIGG 0x1800 /* DIG Gain */ #define B43_RX_PHYST3_DIGG_SHIFT 11 -#define B43_RX_PHYST3_TRSTATE 0x0400 /* TR state */ +#define B43_RX_PHYST3_TRSTATE 0x0400 /* TR state */ /* MAC RX Status */ -#define B43_RX_MAC_BEACONSENT 0x00008000 /* Beacon send flag */ -#define B43_RX_MAC_KEYIDX 0x000007E0 /* Key index */ -#define B43_RX_MAC_KEYIDX_SHIFT 5 -#define B43_RX_MAC_DECERR 0x00000010 /* Decrypt error */ -#define B43_RX_MAC_DEC 0x00000008 /* Decryption attempted */ -#define B43_RX_MAC_PADDING 0x00000004 /* Pad bytes present */ -#define B43_RX_MAC_RESP 0x00000002 /* Response frame transmitted */ -#define B43_RX_MAC_FCSERR 0x00000001 /* FCS error */ +#define B43_RX_MAC_RXST_VALID 0x01000000 /* PHY RXST valid */ +#define B43_RX_MAC_TKIP_MICERR 0x00100000 /* TKIP MIC error */ +#define B43_RX_MAC_TKIP_MICATT 0x00080000 /* TKIP MIC attempted */ +#define B43_RX_MAC_AGGTYPE 0x00060000 /* Aggregation type */ +#define B43_RX_MAC_AGGTYPE_SHIFT 17 +#define B43_RX_MAC_AMSDU 0x00010000 /* A-MSDU mask */ +#define B43_RX_MAC_BEACONSENT 0x00008000 /* Beacon sent flag */ +#define B43_RX_MAC_KEYIDX 0x000007E0 /* Key index */ +#define B43_RX_MAC_KEYIDX_SHIFT 5 +#define B43_RX_MAC_DECERR 0x00000010 /* Decrypt error */ +#define B43_RX_MAC_DEC 0x00000008 /* Decryption attempted */ +#define B43_RX_MAC_PADDING 0x00000004 /* Pad bytes present */ +#define B43_RX_MAC_RESP 0x00000002 /* Response frame transmitted */ +#define B43_RX_MAC_FCSERR 0x00000001 /* FCS error */ /* RX channel */ -#define B43_RX_CHAN_GAIN 0xFC00 /* Gain */ -#define B43_RX_CHAN_GAIN_SHIFT 10 -#define B43_RX_CHAN_ID 0x03FC /* Channel ID */ -#define B43_RX_CHAN_ID_SHIFT 2 -#define B43_RX_CHAN_PHYTYPE 0x0003 /* PHY type */ +#define B43_RX_CHAN_40MHZ 0x1000 /* 40 Mhz channel width */ +#define B43_RX_CHAN_5GHZ 0x0800 /* 5 Ghz band */ +#define B43_RX_CHAN_ID 0x07F8 /* Channel ID */ +#define B43_RX_CHAN_ID_SHIFT 3 +#define B43_RX_CHAN_PHYTYPE 0x0007 /* PHY type */ + u8 b43_plcp_get_ratecode_cck(const u8 bitrate); u8 b43_plcp_get_ratecode_ofdm(const u8 bitrate); diff --git a/drivers/net/wireless/b43legacy/debugfs.c b/drivers/net/wireless/b43legacy/debugfs.c index eefa6fb7968..619b4534ef0 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 8cb3dc4c474..83161d9af81 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 d09479e816c..32d5e1785bd 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"); } @@ -2260,7 +2260,7 @@ out_requeue: if (b43legacy_debug(dev, B43legacy_DBG_PWORK_FAST)) delay = msecs_to_jiffies(50); else - delay = round_jiffies(HZ); + delay = round_jiffies_relative(HZ); queue_delayed_work(dev->wl->hw->workqueue, &dev->periodic_work, delay); out: @@ -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 22a4b3d0186..491e518e4ae 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_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c index 35dbe455451..76e9dd843fa 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c @@ -219,7 +219,7 @@ static ssize_t tsf_write_file(struct file *file, const char __user *user_buf, ssize_t buf_size; ssize_t res; unsigned long flags; - u64 tsf; + unsigned long long tsf; buf_size = min(count, sizeof (really_big_buffer) - 1); down(&big_buffer_sem); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index b37f1e34870..af3de334365 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 7da3664b851..fc876ba1857 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 a6c7904de28..fc6cdd8086c 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; @@ -1769,7 +1769,7 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred) if (priv->stop_rf_kill) { priv->stop_rf_kill = 0; queue_delayed_work(priv->workqueue, &priv->rf_kill, - round_jiffies(HZ)); + round_jiffies_relative(HZ)); } deferred = 1; @@ -2086,7 +2086,8 @@ static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status) /* Make sure the RF Kill check timer is running */ priv->stop_rf_kill = 0; cancel_delayed_work(&priv->rf_kill); - queue_delayed_work(priv->workqueue, &priv->rf_kill, round_jiffies(HZ)); + queue_delayed_work(priv->workqueue, &priv->rf_kill, + round_jiffies_relative(HZ)); } static void send_scan_event(void *data) @@ -2123,7 +2124,7 @@ static void isr_scan_complete(struct ipw2100_priv *priv, u32 status) if (!delayed_work_pending(&priv->scan_event_later)) queue_delayed_work(priv->workqueue, &priv->scan_event_later, - round_jiffies(msecs_to_jiffies(4000))); + round_jiffies_relative(msecs_to_jiffies(4000))); } else { priv->user_requested_scan = 0; cancel_delayed_work(&priv->scan_event_later); @@ -4242,7 +4243,7 @@ static int ipw_radio_kill_sw(struct ipw2100_priv *priv, int disable_radio) priv->stop_rf_kill = 0; cancel_delayed_work(&priv->rf_kill); queue_delayed_work(priv->workqueue, &priv->rf_kill, - round_jiffies(HZ)); + round_jiffies_relative(HZ)); } else schedule_reset(priv); } @@ -5981,7 +5982,7 @@ static void ipw2100_rf_kill(struct work_struct *work) IPW_DEBUG_RF_KILL("RF Kill active, rescheduling GPIO check\n"); if (!priv->stop_rf_kill) queue_delayed_work(priv->workqueue, &priv->rf_kill, - round_jiffies(HZ)); + round_jiffies_relative(HZ)); goto exit_unlock; } diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index e3c828401b9..88062c1318a 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -1233,9 +1233,19 @@ static ssize_t show_event_log(struct device *d, { struct ipw_priv *priv = dev_get_drvdata(d); u32 log_len = ipw_get_event_log_len(priv); - struct ipw_event log[log_len]; + u32 log_size; + struct ipw_event *log; u32 len = 0, i; + /* not using min() because of its strict type checking */ + log_size = PAGE_SIZE / sizeof(*log) > log_len ? + sizeof(*log) * log_len : PAGE_SIZE; + log = kzalloc(log_size, GFP_KERNEL); + if (!log) { + IPW_ERROR("Unable to allocate memory for log\n"); + return 0; + } + log_len = log_size / sizeof(*log); ipw_capture_event_log(priv, log_len, log); len += snprintf(buf + len, PAGE_SIZE - len, "%08X", log_len); @@ -1244,6 +1254,7 @@ static ssize_t show_event_log(struct device *d, "\n%08X%08X%08X", log[i].time, log[i].event, log[i].data); len += snprintf(buf + len, PAGE_SIZE - len, "\n"); + kfree(log); return len; } @@ -1753,7 +1764,7 @@ static int ipw_radio_kill_sw(struct ipw_priv *priv, int disable_radio) /* Make sure the RF_KILL check timer is running */ cancel_delayed_work(&priv->rf_kill); queue_delayed_work(priv->workqueue, &priv->rf_kill, - round_jiffies(2 * HZ)); + round_jiffies_relative(2 * HZ)); } else queue_work(priv->workqueue, &priv->up); } @@ -4364,7 +4375,7 @@ static void handle_scan_event(struct ipw_priv *priv) if (!priv->user_requested_scan) { if (!delayed_work_pending(&priv->scan_event)) queue_delayed_work(priv->workqueue, &priv->scan_event, - round_jiffies(msecs_to_jiffies(4000))); + round_jiffies_relative(msecs_to_jiffies(4000))); } else { union iwreq_data wrqu; @@ -4728,7 +4739,7 @@ static void ipw_rx_notification(struct ipw_priv *priv, && priv->status & STATUS_ASSOCIATED) queue_delayed_work(priv->workqueue, &priv->request_scan, - round_jiffies(HZ)); + round_jiffies_relative(HZ)); /* Send an empty event to user space. * We don't send the received data on the event because @@ -10751,7 +10762,7 @@ static void ipw_bg_link_down(struct work_struct *work) mutex_unlock(&priv->mutex); } -static int ipw_setup_deferred_work(struct ipw_priv *priv) +static int __devinit ipw_setup_deferred_work(struct ipw_priv *priv) { int ret = 0; @@ -11600,7 +11611,8 @@ static void ipw_prom_free(struct ipw_priv *priv) #endif -static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +static int __devinit ipw_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { int err = 0; struct net_device *net_dev; @@ -11767,7 +11779,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return err; } -static void ipw_pci_remove(struct pci_dev *pdev) +static void __devexit ipw_pci_remove(struct pci_dev *pdev) { struct ipw_priv *priv = pci_get_drvdata(pdev); struct list_head *p, *q; diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 25cfc6c3250..8d52a26c248 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -96,8 +96,8 @@ config IWL4965 If you want to compile the driver as a module ( = code which can be inserted in and remvoed from the running kernel whenever you want), - say M here and read <file:Documentation/modules.txt>. The module - will be called iwl4965.ko. + say M here and read <file:Documentation/kbuild/modules.txt>. The + module will be called iwl4965.ko. config IWL3945 tristate "Intel PRO/Wireless 3945ABG/BG Network Connection" @@ -124,5 +124,5 @@ config IWL3945 If you want to compile the driver as a module ( = code which can be inserted in and remvoed from the running kernel whenever you want), - say M here and read <file:Documentation/modules.txt>. The module - will be called iwl3945.ko. + say M here and read <file:Documentation/kbuild/modules.txt>. The + module will be called iwl3945.ko. diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 262ab0b5582..c48b1b537d2 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 b926738e0ea..bec4d3ffca1 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 19bcb01e278..3a45fe99a83 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/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 557deebca1b..891f90d2f01 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -3232,9 +3232,7 @@ int iwl4965_tx_cmd(struct iwl_priv *priv, struct iwl_cmd *out_cmd, tx->rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[rate_index].plcp, rate_flags); - if (ieee80211_is_probe_request(fc)) - tx->tx_flags |= TX_CMD_FLG_TSF_MSK; - else if (ieee80211_is_back_request(fc)) + if (ieee80211_is_back_request(fc)) tx->tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK; #ifdef CONFIG_IWLWIFI_HT @@ -3872,7 +3870,7 @@ static void iwl4965_rx_reply_rx(struct iwl_priv *priv, */ case IEEE80211_STYPE_ASSOC_RESP: case IEEE80211_STYPE_REASSOC_RESP: - if (network_packet && iwl_is_associated(priv)) { + if (network_packet) { #ifdef CONFIG_IWLWIFI_HT u8 *pos = NULL; struct ieee802_11_elems elems; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 83019d1d7cc..1a6b0e0edf6 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; @@ -4739,8 +4743,10 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) * when we loaded driver, and is now set to "enable". * After we're Alive, RF_KILL gets handled by * iwl_rx_card_state_notif() */ - if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status)) + if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status)) { + clear_bit(STATUS_RF_KILL_HW, &priv->status); queue_work(priv->workqueue, &priv->restart); + } handled |= CSR_INT_BIT_RF_KILL; } @@ -4850,7 +4856,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 +4864,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 +5338,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; @@ -6166,6 +6173,7 @@ static void iwl_alive_start(struct iwl_priv *priv) mutex_lock(&priv->mutex); if (rc) { + iwl_rate_control_unregister(priv->hw); IWL_ERROR("Failed to register network " "device (error %d)\n", rc); return; @@ -6238,8 +6246,6 @@ static void __iwl_down(struct iwl_priv *priv) /* Unblock any waiting calls */ wake_up_interruptible_all(&priv->wait_command_queue); - iwl_cancel_deferred_work(priv); - /* Wipe out the EXIT_PENDING status bit if we are not actually * exiting the module */ if (!exit_pending) @@ -6314,6 +6320,8 @@ static void iwl_down(struct iwl_priv *priv) mutex_lock(&priv->mutex); __iwl_down(priv); mutex_unlock(&priv->mutex); + + iwl_cancel_deferred_work(priv); } #define MAX_HW_RESTARTS 5 @@ -6478,8 +6486,9 @@ static void iwl_bg_scan_check(struct work_struct *data) IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN, "Scan completion watchdog resetting adapter (%dms)\n", jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG)); + if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) - queue_work(priv->workqueue, &priv->restart); + iwl_send_scan_abort(priv); } mutex_unlock(&priv->mutex); } @@ -6575,7 +6584,7 @@ static void iwl_bg_request_scan(struct work_struct *data) spin_unlock_irqrestore(&priv->lock, flags); scan->suspend_time = 0; - scan->max_out_time = cpu_to_le32(600 * 1024); + scan->max_out_time = cpu_to_le32(200 * 1024); if (!interval) interval = suspend_time; /* @@ -6605,7 +6614,7 @@ static void iwl_bg_request_scan(struct work_struct *data) memcpy(scan->direct_scan[0].ssid, priv->direct_ssid, priv->direct_ssid_len); direct_mask = 1; - } else if (!iwl_is_associated(priv)) { + } else if (!iwl_is_associated(priv) && priv->essid_len) { scan->direct_scan[0].id = WLAN_EID_SSID; scan->direct_scan[0].len = priv->essid_len; memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len); @@ -6744,6 +6753,12 @@ static void iwl_bg_post_associate(struct work_struct *data) mutex_lock(&priv->mutex); + if (!priv->interface_id || !priv->is_open) { + mutex_unlock(&priv->mutex); + return; + } + iwl_scan_cancel_timeout(priv, 200); + conf = ieee80211_get_hw_conf(priv->hw); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; @@ -6882,9 +6897,19 @@ static void iwl_mac_stop(struct ieee80211_hw *hw) struct iwl_priv *priv = hw->priv; IWL_DEBUG_MAC80211("enter\n"); + + + mutex_lock(&priv->mutex); + /* stop mac, cancel any scan request and clear + * RXON_FILTER_ASSOC_MSK BIT + */ priv->is_open = 0; - /*netif_stop_queue(dev); */ - flush_workqueue(priv->workqueue); + iwl_scan_cancel_timeout(priv, 100); + cancel_delayed_work(&priv->post_associate); + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwl_commit_rxon(priv); + mutex_unlock(&priv->mutex); + IWL_DEBUG_MAC80211("leave\n"); } @@ -6918,13 +6943,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); @@ -6933,6 +6955,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"); @@ -7169,8 +7197,6 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id, if (priv->iw_mode == IEEE80211_IF_TYPE_AP) iwl_config_ap(priv); else { - priv->staging_rxon.filter_flags |= - RXON_FILTER_ASSOC_MSK; rc = iwl_commit_rxon(priv); if ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && rc) iwl_add_station(priv, @@ -7178,6 +7204,7 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id, } } else { + iwl_scan_cancel_timeout(priv, 100); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl_commit_rxon(priv); } @@ -7217,6 +7244,12 @@ static void iwl_mac_remove_interface(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211("enter\n"); mutex_lock(&priv->mutex); + + iwl_scan_cancel_timeout(priv, 100); + cancel_delayed_work(&priv->post_associate); + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwl_commit_rxon(priv); + if (priv->interface_id == conf->if_id) { priv->interface_id = 0; memset(priv->bssid, 0, ETH_ALEN); @@ -7238,6 +7271,7 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) IWL_DEBUG_MAC80211("enter\n"); + mutex_lock(&priv->mutex); spin_lock_irqsave(&priv->lock, flags); if (!iwl_is_ready_rf(priv)) { @@ -7268,7 +7302,8 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) priv->direct_ssid_len = (u8) min((u8) len, (u8) IW_ESSID_MAX_SIZE); memcpy(priv->direct_ssid, ssid, priv->direct_ssid_len); - } + } else + priv->one_direct_scan = 0; rc = iwl_scan_initiate(priv); @@ -7276,6 +7311,7 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) out_unlock: spin_unlock_irqrestore(&priv->lock, flags); + mutex_unlock(&priv->mutex); return rc; } @@ -7310,6 +7346,8 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, mutex_lock(&priv->mutex); + iwl_scan_cancel_timeout(priv, 100); + switch (cmd) { case SET_KEY: rc = iwl_update_sta_key_info(priv, key, sta_id); @@ -7479,8 +7517,18 @@ static void iwl_mac_reset_tsf(struct ieee80211_hw *hw) spin_unlock_irqrestore(&priv->lock, flags); + /* we are restarting association process + * clear RXON_FILTER_ASSOC_MSK bit + */ + if (priv->iw_mode != IEEE80211_IF_TYPE_AP) { + iwl_scan_cancel_timeout(priv, 100); + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwl_commit_rxon(priv); + } + /* Per mac80211.h: This is only used in IBSS mode... */ if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) { + IWL_DEBUG_MAC80211("leave - not in IBSS\n"); mutex_unlock(&priv->mutex); return; @@ -8232,6 +8280,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); @@ -8317,6 +8366,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; @@ -8529,10 +8580,9 @@ static void iwl_pci_remove(struct pci_dev *pdev) IWL_DEBUG_INFO("*** UNLOAD DRIVER ***\n"); - mutex_lock(&priv->mutex); set_bit(STATUS_EXIT_PENDING, &priv->status); - __iwl_down(priv); - mutex_unlock(&priv->mutex); + + iwl_down(priv); /* Free MAC hash list for ADHOC */ for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) { @@ -8558,6 +8608,9 @@ static void iwl_pci_remove(struct pci_dev *pdev) iwl_rate_control_unregister(priv->hw); } + /*netif_stop_queue(dev); */ + flush_workqueue(priv->workqueue); + /* ieee80211_unregister_hw calls iwl_mac_stop, which flushes * priv->workqueue... so we can't take down the workqueue * until now... */ @@ -8588,12 +8641,10 @@ static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) { struct iwl_priv *priv = pci_get_drvdata(pdev); - mutex_lock(&priv->mutex); - set_bit(STATUS_IN_SUSPEND, &priv->status); /* Take down the device; powers it off, etc. */ - __iwl_down(priv); + iwl_down(priv); if (priv->mac80211_registered) ieee80211_stop_queues(priv->hw); @@ -8602,8 +8653,6 @@ static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) pci_disable_device(pdev); pci_set_power_state(pdev, PCI_D3hot); - mutex_unlock(&priv->mutex); - return 0; } @@ -8661,8 +8710,6 @@ static int iwl_pci_resume(struct pci_dev *pdev) printk(KERN_INFO "Coming out of suspend...\n"); - mutex_lock(&priv->mutex); - pci_set_power_state(pdev, PCI_D0); err = pci_enable_device(pdev); pci_restore_state(pdev); @@ -8676,7 +8723,6 @@ static int iwl_pci_resume(struct pci_dev *pdev) pci_write_config_byte(pdev, 0x41, 0x00); iwl_resume(priv); - mutex_unlock(&priv->mutex); return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 5e1279263b2..6cd57c22063 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; @@ -5055,8 +5059,10 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) * when we loaded driver, and is now set to "enable". * After we're Alive, RF_KILL gets handled by * iwl_rx_card_state_notif() */ - if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status)) + if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status)) { + clear_bit(STATUS_RF_KILL_HW, &priv->status); queue_work(priv->workqueue, &priv->restart); + } handled |= CSR_INT_BIT_RF_KILL; } @@ -5156,9 +5162,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 +5173,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: @@ -6521,6 +6529,7 @@ static void iwl_alive_start(struct iwl_priv *priv) mutex_lock(&priv->mutex); if (rc) { + iwl_rate_control_unregister(priv->hw); IWL_ERROR("Failed to register network " "device (error %d)\n", rc); return; @@ -6592,8 +6601,6 @@ static void __iwl_down(struct iwl_priv *priv) /* Unblock any waiting calls */ wake_up_interruptible_all(&priv->wait_command_queue); - iwl_cancel_deferred_work(priv); - /* Wipe out the EXIT_PENDING status bit if we are not actually * exiting the module */ if (!exit_pending) @@ -6668,6 +6675,8 @@ static void iwl_down(struct iwl_priv *priv) mutex_lock(&priv->mutex); __iwl_down(priv); mutex_unlock(&priv->mutex); + + iwl_cancel_deferred_work(priv); } #define MAX_HW_RESTARTS 5 @@ -6845,8 +6854,9 @@ static void iwl_bg_scan_check(struct work_struct *data) IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN, "Scan completion watchdog resetting adapter (%dms)\n", jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG)); + if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) - queue_work(priv->workqueue, &priv->restart); + iwl_send_scan_abort(priv); } mutex_unlock(&priv->mutex); } @@ -6942,7 +6952,7 @@ static void iwl_bg_request_scan(struct work_struct *data) spin_unlock_irqrestore(&priv->lock, flags); scan->suspend_time = 0; - scan->max_out_time = cpu_to_le32(600 * 1024); + scan->max_out_time = cpu_to_le32(200 * 1024); if (!interval) interval = suspend_time; @@ -6965,7 +6975,7 @@ static void iwl_bg_request_scan(struct work_struct *data) memcpy(scan->direct_scan[0].ssid, priv->direct_ssid, priv->direct_ssid_len); direct_mask = 1; - } else if (!iwl_is_associated(priv)) { + } else if (!iwl_is_associated(priv) && priv->essid_len) { scan->direct_scan[0].id = WLAN_EID_SSID; scan->direct_scan[0].len = priv->essid_len; memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len); @@ -7118,6 +7128,12 @@ static void iwl_bg_post_associate(struct work_struct *data) mutex_lock(&priv->mutex); + if (!priv->interface_id || !priv->is_open) { + mutex_unlock(&priv->mutex); + return; + } + iwl_scan_cancel_timeout(priv, 200); + conf = ieee80211_get_hw_conf(priv->hw); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; @@ -7271,9 +7287,19 @@ static void iwl_mac_stop(struct ieee80211_hw *hw) struct iwl_priv *priv = hw->priv; IWL_DEBUG_MAC80211("enter\n"); + + + mutex_lock(&priv->mutex); + /* stop mac, cancel any scan request and clear + * RXON_FILTER_ASSOC_MSK BIT + */ priv->is_open = 0; - /*netif_stop_queue(dev); */ - flush_workqueue(priv->workqueue); + iwl_scan_cancel_timeout(priv, 100); + cancel_delayed_work(&priv->post_associate); + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwl_commit_rxon(priv); + mutex_unlock(&priv->mutex); + IWL_DEBUG_MAC80211("leave\n"); } @@ -7307,9 +7333,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"); @@ -7322,6 +7345,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"); @@ -7573,8 +7601,6 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id, if (priv->iw_mode == IEEE80211_IF_TYPE_AP) iwl_config_ap(priv); else { - priv->staging_rxon.filter_flags |= - RXON_FILTER_ASSOC_MSK; rc = iwl_commit_rxon(priv); if ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && rc) iwl_rxon_add_station( @@ -7582,6 +7608,7 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id, } } else { + iwl_scan_cancel_timeout(priv, 100); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl_commit_rxon(priv); } @@ -7621,6 +7648,12 @@ static void iwl_mac_remove_interface(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211("enter\n"); mutex_lock(&priv->mutex); + + iwl_scan_cancel_timeout(priv, 100); + cancel_delayed_work(&priv->post_associate); + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwl_commit_rxon(priv); + if (priv->interface_id == conf->if_id) { priv->interface_id = 0; memset(priv->bssid, 0, ETH_ALEN); @@ -7642,6 +7675,7 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) IWL_DEBUG_MAC80211("enter\n"); + mutex_lock(&priv->mutex); spin_lock_irqsave(&priv->lock, flags); if (!iwl_is_ready_rf(priv)) { @@ -7672,7 +7706,8 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) priv->direct_ssid_len = (u8) min((u8) len, (u8) IW_ESSID_MAX_SIZE); memcpy(priv->direct_ssid, ssid, priv->direct_ssid_len); - } + } else + priv->one_direct_scan = 0; rc = iwl_scan_initiate(priv); @@ -7680,6 +7715,7 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) out_unlock: spin_unlock_irqrestore(&priv->lock, flags); + mutex_unlock(&priv->mutex); return rc; } @@ -7713,6 +7749,8 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, mutex_lock(&priv->mutex); + iwl_scan_cancel_timeout(priv, 100); + switch (cmd) { case SET_KEY: rc = iwl_update_sta_key_info(priv, key, sta_id); @@ -7903,8 +7941,18 @@ static void iwl_mac_reset_tsf(struct ieee80211_hw *hw) spin_unlock_irqrestore(&priv->lock, flags); + /* we are restarting association process + * clear RXON_FILTER_ASSOC_MSK bit + */ + if (priv->iw_mode != IEEE80211_IF_TYPE_AP) { + iwl_scan_cancel_timeout(priv, 100); + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwl_commit_rxon(priv); + } + /* Per mac80211.h: This is only used in IBSS mode... */ if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) { + IWL_DEBUG_MAC80211("leave - not in IBSS\n"); mutex_unlock(&priv->mutex); return; @@ -8825,6 +8873,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); @@ -8918,6 +8967,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; @@ -9123,10 +9174,9 @@ static void iwl_pci_remove(struct pci_dev *pdev) IWL_DEBUG_INFO("*** UNLOAD DRIVER ***\n"); - mutex_lock(&priv->mutex); set_bit(STATUS_EXIT_PENDING, &priv->status); - __iwl_down(priv); - mutex_unlock(&priv->mutex); + + iwl_down(priv); /* Free MAC hash list for ADHOC */ for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) { @@ -9152,6 +9202,9 @@ static void iwl_pci_remove(struct pci_dev *pdev) iwl_rate_control_unregister(priv->hw); } + /*netif_stop_queue(dev); */ + flush_workqueue(priv->workqueue); + /* ieee80211_unregister_hw calls iwl_mac_stop, which flushes * priv->workqueue... so we can't take down the workqueue * until now... */ @@ -9182,12 +9235,10 @@ static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) { struct iwl_priv *priv = pci_get_drvdata(pdev); - mutex_lock(&priv->mutex); - set_bit(STATUS_IN_SUSPEND, &priv->status); /* Take down the device; powers it off, etc. */ - __iwl_down(priv); + iwl_down(priv); if (priv->mac80211_registered) ieee80211_stop_queues(priv->hw); @@ -9196,8 +9247,6 @@ static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) pci_disable_device(pdev); pci_set_power_state(pdev, PCI_D3hot); - mutex_unlock(&priv->mutex); - return 0; } @@ -9255,8 +9304,6 @@ static int iwl_pci_resume(struct pci_dev *pdev) printk(KERN_INFO "Coming out of suspend...\n"); - mutex_lock(&priv->mutex); - pci_set_power_state(pdev, PCI_D0); err = pci_enable_device(pdev); pci_restore_state(pdev); @@ -9270,7 +9317,6 @@ static int iwl_pci_resume(struct pci_dev *pdev) pci_write_config_byte(pdev, 0x41, 0x00); iwl_resume(priv); - mutex_unlock(&priv->mutex); return 0; } diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 1cbbd96fdbd..be5cfd8402c 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 0360cad363a..ba4fc2b3bf0 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 a8e17076e7d..b24425f7488 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 5ead08312e1..1823b48a8ba 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 c6f5aa3cb46..395b7882d4d 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 2402cb8dd32..d2fa079fbc4 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 755482a5a93..60d286eb0b8 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 ff2d63267b1..702321c3016 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 7cdc80a122b..18b1f914538 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -257,7 +257,7 @@ static const struct rt2x00debug rt2500usb_rt2x00debug = { static void rt2500usb_config_mac_addr(struct rt2x00_dev *rt2x00dev, __le32 *mac) { - rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR2, &mac, + rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR2, mac, (3 * sizeof(__le16))); } @@ -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 9845e584b73..c8f16f161c2 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/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 298faa9d3f6..06d9bc0015c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -30,7 +30,7 @@ * Interval defines * Both the link tuner as the rfkill will be called once per second. */ -#define LINK_TUNE_INTERVAL ( round_jiffies(HZ) ) +#define LINK_TUNE_INTERVAL ( round_jiffies_relative(HZ) ) #define RFKILL_POLL_INTERVAL ( 1000 ) /* diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 4a6a0bd01ff..85ea8a8e658 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/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 2780df00623..6d5d9aba0b7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -124,7 +124,10 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) struct data_entry *entry; struct data_desc *rxd; struct sk_buff *skb; + struct ieee80211_hdr *hdr; struct rxdata_entry_desc desc; + int header_size; + int align; u32 word; while (1) { @@ -138,17 +141,26 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) memset(&desc, 0x00, sizeof(desc)); rt2x00dev->ops->lib->fill_rxdone(entry, &desc); + hdr = (struct ieee80211_hdr *)entry->data_addr; + header_size = + ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control)); + + /* + * The data behind the ieee80211 header must be + * aligned on a 4 byte boundary. + */ + align = NET_IP_ALIGN + (2 * (header_size % 4 == 0)); + /* * Allocate the sk_buffer, initialize it and copy * all data into it. */ - skb = dev_alloc_skb(desc.size + NET_IP_ALIGN); + skb = dev_alloc_skb(desc.size + align); if (!skb) return; - skb_reserve(skb, NET_IP_ALIGN); - skb_put(skb, desc.size); - memcpy(skb->data, entry->data_addr, desc.size); + skb_reserve(skb, align); + memcpy(skb_put(skb, desc.size), entry->data_addr, desc.size); /* * Send the frame to rt2x00lib for further processing. diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 73cc726c404..ab4797ed94c 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. @@ -223,7 +221,9 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) struct data_ring *ring = entry->ring; struct rt2x00_dev *rt2x00dev = ring->rt2x00dev; struct sk_buff *skb; + struct ieee80211_hdr *hdr; struct rxdata_entry_desc desc; + int header_size; int frame_size; if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || @@ -255,9 +255,20 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) skb_put(skb, frame_size); /* - * Trim the skb_buffer to only contain the valid - * frame data (so ignore the device's descriptor). + * The data behind the ieee80211 header must be + * aligned on a 4 byte boundary. + * After that trim the entire buffer down to only + * contain the valid frame data excluding the device + * descriptor. */ + hdr = (struct ieee80211_hdr *)entry->skb->data; + header_size = + ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control)); + + if (header_size % 4 == 0) { + skb_push(entry->skb, 2); + memmove(entry->skb->data, entry->skb->data + 2, skb->len - 2); + } skb_trim(entry->skb, desc.size); /* @@ -490,6 +501,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/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 01dbef19d65..ecae968ce09 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1738,6 +1738,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) { struct data_ring *ring; struct data_entry *entry; + struct data_entry *entry_done; struct data_desc *txd; u32 word; u32 reg; @@ -1791,6 +1792,17 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) !rt2x00_get_field32(word, TXD_W0_VALID)) return; + entry_done = rt2x00_get_data_entry_done(ring); + while (entry != entry_done) { + /* Catch up. Just report any entries we missed as + * failed. */ + WARNING(rt2x00dev, + "TX status report missed for entry %p\n", + entry_done); + rt2x00lib_txdone(entry_done, TX_FAIL_OTHER, 0); + entry_done = rt2x00_get_data_entry_done(ring); + } + /* * Obtain the status about this packet. */ diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 46c8c0840a6..c0671c2e6e7 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/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index de61c8fe649..bd1ab3b3afc 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -38,6 +38,8 @@ static struct usb_device_id rtl8187_table[] __devinitdata = { {USB_DEVICE(0x0846, 0x6a00)}, /* HP */ {USB_DEVICE(0x03f0, 0xca02)}, + /* Sitecom */ + {USB_DEVICE(0x0df6, 0x000d)}, {} }; @@ -433,6 +435,9 @@ static int rtl8187_start(struct ieee80211_hw *dev) rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF); + rtl818x_iowrite32(priv, &priv->map->MAR[0], ~0); + rtl818x_iowrite32(priv, &priv->map->MAR[1], ~0); + rtl8187_init_urbs(dev); reg = RTL818X_RX_CONF_ONLYERLPKT | @@ -582,32 +587,31 @@ static int rtl8187_config_interface(struct ieee80211_hw *dev, int if_id, static void rtl8187_configure_filter(struct ieee80211_hw *dev, unsigned int changed_flags, unsigned int *total_flags, - int mc_count, struct dev_addr_list *mc_list) + int mc_count, struct dev_addr_list *mclist) { struct rtl8187_priv *priv = dev->priv; - *total_flags = 0; - - if (changed_flags & FIF_ALLMULTI) - priv->rx_conf ^= RTL818X_RX_CONF_MULTICAST; if (changed_flags & FIF_FCSFAIL) priv->rx_conf ^= RTL818X_RX_CONF_FCS; if (changed_flags & FIF_CONTROL) priv->rx_conf ^= RTL818X_RX_CONF_CTRL; if (changed_flags & FIF_OTHER_BSS) priv->rx_conf ^= RTL818X_RX_CONF_MONITOR; - - if (mc_count > 0) + if (*total_flags & FIF_ALLMULTI || mc_count > 0) priv->rx_conf |= RTL818X_RX_CONF_MULTICAST; + else + priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST; + + *total_flags = 0; - if (priv->rx_conf & RTL818X_RX_CONF_MULTICAST) - *total_flags |= FIF_ALLMULTI; if (priv->rx_conf & RTL818X_RX_CONF_FCS) *total_flags |= FIF_FCSFAIL; if (priv->rx_conf & RTL818X_RX_CONF_CTRL) *total_flags |= FIF_CONTROL; if (priv->rx_conf & RTL818X_RX_CONF_MONITOR) *total_flags |= FIF_OTHER_BSS; + if (priv->rx_conf & RTL818X_RX_CONF_MULTICAST) + *total_flags |= FIF_ALLMULTI; rtl818x_iowrite32_async(priv, &priv->map->RX_CONF, priv->rx_conf); } diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c index 4bd14b33186..88efe1bae58 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/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index a903645e157..5298a8bf112 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -1130,6 +1130,8 @@ static void zd_mac_rx(struct zd_mac *mac, struct sk_buff *skb) __skb_trim(skb, skb->len - (IEEE80211_FCS_LEN + sizeof(struct rx_status))); + ZD_ASSERT(IS_ALIGNED((unsigned long)skb->data, 4)); + update_qual_rssi(mac, skb->data, skb->len, stats.signal, status->signal_strength); @@ -1166,15 +1168,19 @@ static void do_rx(unsigned long mac_ptr) int zd_mac_rx_irq(struct zd_mac *mac, const u8 *buffer, unsigned int length) { struct sk_buff *skb; + unsigned int reserved = + ALIGN(max_t(unsigned int, + sizeof(struct zd_rt_hdr), ZD_PLCP_HEADER_SIZE), 4) - + ZD_PLCP_HEADER_SIZE; - skb = dev_alloc_skb(sizeof(struct zd_rt_hdr) + length); + skb = dev_alloc_skb(reserved + length); if (!skb) { struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac); dev_warn(zd_mac_dev(mac), "Could not allocate skb.\n"); ieee->stats.rx_dropped++; return -ENOMEM; } - skb_reserve(skb, sizeof(struct zd_rt_hdr)); + skb_reserve(skb, reserved); memcpy(__skb_put(skb, length), buffer, length); skb_queue_tail(&mac->rx_queue, skb); tasklet_schedule(&mac->rx_tasklet); diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 2a8fc431099..bca37bf0f54 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -852,11 +852,6 @@ static int xennet_poll(struct napi_struct *napi, int budget) spin_lock(&np->rx_lock); - if (unlikely(!netif_carrier_ok(dev))) { - spin_unlock(&np->rx_lock); - return 0; - } - skb_queue_head_init(&rxq); skb_queue_head_init(&errq); skb_queue_head_init(&tmpq); diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index 87f002ade53..fe6ff3e3d52 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c @@ -265,10 +265,10 @@ enum yellowfin_offsets { /* The Yellowfin Rx and Tx buffer descriptors. Elements are written as 32 bit for endian portability. */ struct yellowfin_desc { - u32 dbdma_cmd; - u32 addr; - u32 branch_addr; - u32 result_status; + __le32 dbdma_cmd; + __le32 addr; + __le32 branch_addr; + __le32 result_status; }; struct tx_status_words { @@ -922,7 +922,7 @@ static irqreturn_t yellowfin_interrupt(int irq, void *dev_instance) dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; /* Free the original skb. */ - pci_unmap_single(yp->pci_dev, yp->tx_ring[entry].addr, + pci_unmap_single(yp->pci_dev, le32_to_cpu(yp->tx_ring[entry].addr), skb->len, PCI_DMA_TODEVICE); dev_kfree_skb_irq(skb); yp->tx_skbuff[entry] = NULL; @@ -1056,13 +1056,13 @@ static int yellowfin_rx(struct net_device *dev) if(!desc->result_status) break; - pci_dma_sync_single_for_cpu(yp->pci_dev, desc->addr, + pci_dma_sync_single_for_cpu(yp->pci_dev, le32_to_cpu(desc->addr), yp->rx_buf_sz, PCI_DMA_FROMDEVICE); desc_status = le32_to_cpu(desc->result_status) >> 16; buf_addr = rx_skb->data; data_size = (le32_to_cpu(desc->dbdma_cmd) - le32_to_cpu(desc->result_status)) & 0xffff; - frame_status = le16_to_cpu(get_unaligned((s16*)&(buf_addr[data_size - 2]))); + frame_status = le16_to_cpu(get_unaligned((__le16*)&(buf_addr[data_size - 2]))); if (yellowfin_debug > 4) printk(KERN_DEBUG " yellowfin_rx() status was %4.4x.\n", frame_status); @@ -1123,7 +1123,7 @@ static int yellowfin_rx(struct net_device *dev) if (pkt_len > rx_copybreak) { skb_put(skb = rx_skb, pkt_len); pci_unmap_single(yp->pci_dev, - yp->rx_ring[entry].addr, + le32_to_cpu(yp->rx_ring[entry].addr), yp->rx_buf_sz, PCI_DMA_FROMDEVICE); yp->rx_skbuff[entry] = NULL; @@ -1134,9 +1134,10 @@ static int yellowfin_rx(struct net_device *dev) skb_reserve(skb, 2); /* 16 byte align the IP header */ skb_copy_to_linear_data(skb, rx_skb->data, pkt_len); skb_put(skb, pkt_len); - pci_dma_sync_single_for_device(yp->pci_dev, desc->addr, - yp->rx_buf_sz, - PCI_DMA_FROMDEVICE); + pci_dma_sync_single_for_device(yp->pci_dev, + le32_to_cpu(desc->addr), + yp->rx_buf_sz, + PCI_DMA_FROMDEVICE); } skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); @@ -1252,7 +1253,7 @@ static int yellowfin_close(struct net_device *dev) /* Free all the skbuffs in the Rx queue. */ for (i = 0; i < RX_RING_SIZE; i++) { yp->rx_ring[i].dbdma_cmd = cpu_to_le32(CMD_STOP); - yp->rx_ring[i].addr = 0xBADF00D0; /* An invalid address. */ + yp->rx_ring[i].addr = cpu_to_le32(0xBADF00D0); /* An invalid address. */ if (yp->rx_skbuff[i]) { dev_kfree_skb(yp->rx_skbuff[i]); } diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index a83c3db7d18..c93d3d2640a 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 49900d9e323..c66c025abe7 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 f0acb661c25..d1f6d776e9e 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/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index 5eace9e66e1..66ce6104836 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -768,9 +768,13 @@ lba_fixup_bus(struct pci_bus *bus) DBG("lba_fixup_bus() WTF? 0x%lx [%lx/%lx] XXX", res->flags, res->start, res->end); } - if ((i != PCI_ROM_RESOURCE) || - (res->flags & IORESOURCE_ROM_ENABLE)) - pci_claim_resource(dev, i); + + /* + ** FIXME: this will result in whinging for devices + ** that share expansion ROMs (think quad tulip), but + ** isn't harmful. + */ + pci_claim_resource(dev, i); } #ifdef FBB_SUPPORT diff --git a/drivers/parport/procfs.c b/drivers/parport/procfs.c index ed82e41210d..d950fc34320 100644 --- a/drivers/parport/procfs.c +++ b/drivers/parport/procfs.c @@ -384,7 +384,7 @@ parport_device_sysctl_template = { { .procname = "timeslice", .data = NULL, - .maxlen = sizeof(int), + .maxlen = sizeof(unsigned long), .mode = 0644, .proc_handler = &proc_doulongvec_ms_jiffies_minmax, .extra1 = (void*) &parport_min_timeslice_value, diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 7a1d6d51283..e1ca42591ac 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -21,6 +21,17 @@ config PCI_MSI If you don't know what to do here, say N. +config PCI_LEGACY + bool "Enable deprecated pci_find_* API" + depends on PCI + default y + help + Say Y here if you want to include support for the deprecated + pci_find_slot() and pci_find_device() APIs. Most drivers have + been converted over to using the proper hotplug APIs, so this + option serves to include/exclude only a few drivers that are + still using this API. + config PCI_DEBUG bool "PCI Debugging" depends on PCI && DEBUG_KERNEL diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig index 63d62752fb9..a64449d489d 100644 --- a/drivers/pci/hotplug/Kconfig +++ b/drivers/pci/hotplug/Kconfig @@ -41,7 +41,7 @@ config HOTPLUG_PCI_FAKE config HOTPLUG_PCI_COMPAQ tristate "Compaq PCI Hotplug driver" - depends on X86 && PCI_BIOS + depends on X86 && PCI_BIOS && PCI_LEGACY help Say Y here if you have a motherboard with a Compaq PCI Hotplug controller. @@ -63,7 +63,7 @@ config HOTPLUG_PCI_COMPAQ_NVRAM config HOTPLUG_PCI_IBM tristate "IBM PCI Hotplug driver" - depends on X86_IO_APIC && X86 && PCI_BIOS + depends on X86_IO_APIC && X86 && PCI_BIOS && PCI_LEGACY help Say Y here if you have a motherboard with a IBM PCI Hotplug controller. @@ -119,7 +119,7 @@ config HOTPLUG_PCI_CPCI_ZT5550 config HOTPLUG_PCI_CPCI_GENERIC tristate "Generic port I/O CompactPCI Hotplug driver" - depends on HOTPLUG_PCI_CPCI && X86 + depends on HOTPLUG_PCI_CPCI && X86 && PCI_LEGACY help Say Y here if you have a CompactPCI system card that exposes the #ENUM hotswap signal as a bit in a system register that can be read through diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index f6cc0c5b565..1ef417cca2d 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 a0ca63adad5..c8c263875c2 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 1e125b56c9a..ff1b1c71291 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 56829f82be4..47d26b65e99 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 a96b739b2d3..74178875b94 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 3ef0a4875a6..4018420c6f9 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) { @@ -1931,16 +1932,14 @@ void cpqhp_pushbutton_thread(unsigned long slot) return ; } - if (func != NULL && ctrl != NULL) { - if (cpqhp_process_SS(ctrl, func) != 0) { - amber_LED_on (ctrl, hp_slot); - green_LED_on (ctrl, hp_slot); - - set_SOGO(ctrl); + if (cpqhp_process_SS(ctrl, func) != 0) { + amber_LED_on(ctrl, hp_slot); + green_LED_on(ctrl, hp_slot); - /* Wait for SOBS to be unset */ - wait_for_ctrl_irq (ctrl); - } + set_SOGO(ctrl); + + /* Wait for SOBS to be unset */ + wait_for_ctrl_irq(ctrl); } p_slot->state = STATIC_STATE; @@ -2139,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, @@ -2167,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) { @@ -2251,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) @@ -2348,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 027f6865d7e..d7a293e3faf 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 c8cb49c5a75..f1e0966cee9 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 deb6b5e35fe..b169b0e2647 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 458c08ef265..58f1a992770 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 54ca8650d51..0de84533cd8 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 d2fc35598cd..eb5cac6f08a 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/intel-iommu.c b/drivers/pci/intel-iommu.c index 0c4ab3b0727..e079a5237c9 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -34,7 +34,7 @@ #include "intel-iommu.h" #include <asm/proto.h> /* force_iommu in this header in x86-64*/ #include <asm/cacheflush.h> -#include <asm/iommu.h> +#include <asm/gart.h> #include "pci.h" #define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) @@ -745,12 +745,12 @@ static char *fault_reason_strings[] = "non-zero reserved fields in PTE", "Unknown" }; -#define MAX_FAULT_REASON_IDX ARRAY_SIZE(fault_reason_strings) +#define MAX_FAULT_REASON_IDX ARRAY_SIZE(fault_reason_strings) - 1 char *dmar_get_fault_reason(u8 fault_reason) { - if (fault_reason > MAX_FAULT_REASON_IDX) - return fault_reason_strings[MAX_FAULT_REASON_IDX]; + if (fault_reason >= MAX_FAULT_REASON_IDX) + return fault_reason_strings[MAX_FAULT_REASON_IDX - 1]; else return fault_reason_strings[fault_reason]; } @@ -995,7 +995,6 @@ static struct intel_iommu *alloc_iommu(struct dmar_drhd_unit *drhd) return iommu; error_unmap: iounmap(iommu->reg); - iommu->reg = 0; error: kfree(iommu); return NULL; @@ -1808,7 +1807,7 @@ get_valid_domain_for_dev(struct pci_dev *pdev) if (!domain) { printk(KERN_ERR "Allocating domain for %s failed", pci_name(pdev)); - return 0; + return NULL; } /* make sure context mapping is ok */ @@ -1818,7 +1817,7 @@ get_valid_domain_for_dev(struct pci_dev *pdev) printk(KERN_ERR "Domain context map for %s failed", pci_name(pdev)); - return 0; + return NULL; } } diff --git a/drivers/pci/intel-iommu.h b/drivers/pci/intel-iommu.h index ee88dd2400c..459ad1f9dc5 100644 --- a/drivers/pci/intel-iommu.h +++ b/drivers/pci/intel-iommu.h @@ -58,7 +58,7 @@ hi = readl(dmar + reg + 4); \ (((u64) hi) << 32) + lo; }) */ -static inline u64 dmar_readq(void *addr) +static inline u64 dmar_readq(void __iomem *addr) { u32 lo, hi; lo = readl(addr); diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 87e01615053..07c9f09c856 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -224,6 +224,12 @@ static struct msi_desc* alloc_msi_entry(void) return entry; } +static void pci_intx_for_msi(struct pci_dev *dev, int enable) +{ + if (!(dev->dev_flags & PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG)) + pci_intx(dev, enable); +} + #ifdef CONFIG_PM static void __pci_restore_msi_state(struct pci_dev *dev) { @@ -237,7 +243,7 @@ static void __pci_restore_msi_state(struct pci_dev *dev) entry = get_irq_msi(dev->irq); pos = entry->msi_attrib.pos; - pci_intx(dev, 0); /* disable intx */ + pci_intx_for_msi(dev, 0); msi_set_enable(dev, 0); write_msi_msg(dev->irq, &entry->msg); if (entry->msi_attrib.maskbit) @@ -260,7 +266,7 @@ static void __pci_restore_msix_state(struct pci_dev *dev) return; /* route the table */ - pci_intx(dev, 0); /* disable intx */ + pci_intx_for_msi(dev, 0); msix_set_enable(dev, 0); list_for_each_entry(entry, &dev->msi_list, list) { @@ -343,7 +349,7 @@ static int msi_capability_init(struct pci_dev *dev) } /* Set MSI enabled bits */ - pci_intx(dev, 0); /* disable intx */ + pci_intx_for_msi(dev, 0); msi_set_enable(dev, 1); dev->msi_enabled = 1; @@ -433,7 +439,7 @@ static int msix_capability_init(struct pci_dev *dev, i++; } /* Set MSI-X enabled bits */ - pci_intx(dev, 0); /* disable intx */ + pci_intx_for_msi(dev, 0); msix_set_enable(dev, 1); dev->msix_enabled = 1; @@ -528,7 +534,7 @@ void pci_disable_msi(struct pci_dev* dev) return; msi_set_enable(dev, 0); - pci_intx(dev, 1); /* enable intx */ + pci_intx_for_msi(dev, 1); dev->msi_enabled = 0; BUG_ON(list_empty(&dev->msi_list)); @@ -640,7 +646,7 @@ void pci_disable_msix(struct pci_dev* dev) return; msix_set_enable(dev, 0); - pci_intx(dev, 1); /* enable intx */ + pci_intx_for_msi(dev, 1); dev->msix_enabled = 0; msix_free_all_irqs(dev); diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 6e2760b6c20..6d1a2161181 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -143,8 +143,8 @@ const struct pci_device_id *pci_match_id(const struct pci_device_id *ids, * system is in its list of supported devices. Returns the matching * pci_device_id structure or %NULL if there is no match. */ -const struct pci_device_id *pci_match_device(struct pci_driver *drv, - struct pci_dev *dev) +static const struct pci_device_id *pci_match_device(struct pci_driver *drv, + struct pci_dev *dev) { struct pci_dynid *dynid; @@ -559,7 +559,6 @@ static int __init pci_driver_init(void) postcore_initcall(pci_driver_init); EXPORT_SYMBOL(pci_match_id); -EXPORT_SYMBOL(pci_match_device); EXPORT_SYMBOL(__pci_register_driver); EXPORT_SYMBOL(pci_unregister_driver); EXPORT_SYMBOL(pci_dev_driver); diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 1b7b2812bf2..7d1877341aa 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 92a8469b21b..3c0d8d138f5 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 df383645e36..26057f98f72 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/pci/probe.c b/drivers/pci/probe.c index 463a5a9d583..c5ca3134513 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -276,7 +276,8 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) sz = pci_size(l, sz, (u32)PCI_ROM_ADDRESS_MASK); if (sz) { res->flags = (l & IORESOURCE_ROM_ENABLE) | - IORESOURCE_MEM | IORESOURCE_READONLY; + IORESOURCE_MEM | IORESOURCE_PREFETCH | + IORESOURCE_READONLY | IORESOURCE_CACHEABLE; res->start = l & PCI_ROM_ADDRESS_MASK; res->end = res->start + (unsigned long) sz; } @@ -454,22 +455,6 @@ struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int return child; } -static void pci_enable_crs(struct pci_dev *dev) -{ - u16 cap, rpctl; - int rpcap = pci_find_capability(dev, PCI_CAP_ID_EXP); - if (!rpcap) - return; - - pci_read_config_word(dev, rpcap + PCI_CAP_FLAGS, &cap); - if (((cap & PCI_EXP_FLAGS_TYPE) >> 4) != PCI_EXP_TYPE_ROOT_PORT) - return; - - pci_read_config_word(dev, rpcap + PCI_EXP_RTCTL, &rpctl); - rpctl |= PCI_EXP_RTCTL_CRSSVE; - pci_write_config_word(dev, rpcap + PCI_EXP_RTCTL, rpctl); -} - static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max) { struct pci_bus *parent = child->parent; @@ -516,8 +501,6 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bctl & ~PCI_BRIDGE_CTL_MASTER_ABORT); - pci_enable_crs(dev); - if ((buses & 0xffff00) && !pcibios_assign_all_busses() && !is_cardbus) { unsigned int cmax, busnr; /* @@ -743,46 +726,22 @@ static int pci_setup_device(struct pci_dev * dev) */ if (class == PCI_CLASS_STORAGE_IDE) { u8 progif; - struct pci_bus_region region; - pci_read_config_byte(dev, PCI_CLASS_PROG, &progif); if ((progif & 1) == 0) { - struct resource resource = { - .start = 0x1F0, - .end = 0x1F7, - .flags = LEGACY_IO_RESOURCE, - }; - - pcibios_resource_to_bus(dev, ®ion, &resource); - dev->resource[0].start = region.start; - dev->resource[0].end = region.end; - dev->resource[0].flags = resource.flags; - resource.start = 0x3F6; - resource.end = 0x3F6; - resource.flags = LEGACY_IO_RESOURCE; - pcibios_resource_to_bus(dev, ®ion, &resource); - dev->resource[1].start = region.start; - dev->resource[1].end = region.end; - dev->resource[1].flags = resource.flags; + dev->resource[0].start = 0x1F0; + dev->resource[0].end = 0x1F7; + dev->resource[0].flags = LEGACY_IO_RESOURCE; + dev->resource[1].start = 0x3F6; + dev->resource[1].end = 0x3F6; + dev->resource[1].flags = LEGACY_IO_RESOURCE; } if ((progif & 4) == 0) { - struct resource resource = { - .start = 0x170, - .end = 0x177, - .flags = LEGACY_IO_RESOURCE, - }; - - pcibios_resource_to_bus(dev, ®ion, &resource); - dev->resource[2].start = region.start; - dev->resource[2].end = region.end; - dev->resource[2].flags = resource.flags; - resource.start = 0x376; - resource.end = 0x376; - resource.flags = LEGACY_IO_RESOURCE; - pcibios_resource_to_bus(dev, ®ion, &resource); - dev->resource[3].start = region.start; - dev->resource[3].end = region.end; - dev->resource[3].flags = resource.flags; + dev->resource[2].start = 0x170; + dev->resource[2].end = 0x177; + dev->resource[2].flags = LEGACY_IO_RESOURCE; + dev->resource[3].start = 0x376; + dev->resource[3].end = 0x376; + dev->resource[3].flags = LEGACY_IO_RESOURCE; } } break; diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index d0bb5b9d212..72e0bd5d80a 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -465,6 +465,12 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, quirk DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_0, quirk_ich6_lpc_acpi ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_2, quirk_ich6_lpc_acpi ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_3, quirk_ich6_lpc_acpi ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_1, quirk_ich6_lpc_acpi ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_4, quirk_ich6_lpc_acpi ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_2, quirk_ich6_lpc_acpi ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_4, quirk_ich6_lpc_acpi ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_7, quirk_ich6_lpc_acpi ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_8, quirk_ich6_lpc_acpi ); /* * VIA ACPI: One IO region pointed to by longword at @@ -1621,12 +1627,8 @@ static void __init quirk_disable_all_msi(struct pci_dev *dev) printk(KERN_WARNING "PCI: MSI quirk detected. MSI deactivated.\n"); } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_GCNB_LE, quirk_disable_all_msi); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000_PCIX, quirk_disable_all_msi); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS400_200, quirk_disable_all_msi); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS480, quirk_disable_all_msi); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RD580, quirk_disable_all_msi); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RX790, quirk_disable_all_msi); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS690, quirk_disable_all_msi); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3351, quirk_disable_all_msi); /* Disable MSI on chipsets that are known to not support it */ @@ -1678,6 +1680,9 @@ static void __devinit quirk_msi_ht_cap(struct pci_dev *dev) } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE, quirk_msi_ht_cap); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, + PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB, + quirk_msi_ht_cap); /* The nVidia CK804 chipset may have 2 HT MSI mappings. * MSI are supported if the MSI capability set in any of these mappings. @@ -1705,4 +1710,48 @@ static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev) } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, quirk_nvidia_ck804_msi_ht_cap); + +static void __devinit quirk_msi_intx_disable_bug(struct pci_dev *dev) +{ + dev->dev_flags |= PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG; +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, + PCI_DEVICE_ID_TIGON3_5780, + quirk_msi_intx_disable_bug); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, + PCI_DEVICE_ID_TIGON3_5780S, + quirk_msi_intx_disable_bug); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, + PCI_DEVICE_ID_TIGON3_5714, + quirk_msi_intx_disable_bug); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, + PCI_DEVICE_ID_TIGON3_5714S, + quirk_msi_intx_disable_bug); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, + PCI_DEVICE_ID_TIGON3_5715, + quirk_msi_intx_disable_bug); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, + PCI_DEVICE_ID_TIGON3_5715S, + quirk_msi_intx_disable_bug); + +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4390, + quirk_msi_intx_disable_bug); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4391, + quirk_msi_intx_disable_bug); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4392, + quirk_msi_intx_disable_bug); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4393, + quirk_msi_intx_disable_bug); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4394, + quirk_msi_intx_disable_bug); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4395, + quirk_msi_intx_disable_bug); + +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4373, + quirk_msi_intx_disable_bug); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4374, + quirk_msi_intx_disable_bug); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4375, + quirk_msi_intx_disable_bug); + #endif /* CONFIG_PCI_MSI */ diff --git a/drivers/pci/search.c b/drivers/pci/search.c index b001b5922e3..8541034021f 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -113,6 +113,8 @@ pci_find_next_bus(const struct pci_bus *from) return b; } +#ifdef CONFIG_PCI_LEGACY + /** * pci_find_slot - locate PCI device from a given PCI slot * @bus: number of PCI bus on which desired PCI device resides @@ -137,6 +139,8 @@ pci_find_slot(unsigned int bus, unsigned int devfn) return NULL; } +#endif /* CONFIG_PCI_LEGACY */ + /** * pci_get_slot - locate PCI device for a given PCI slot * @bus: PCI bus on which desired PCI device resides @@ -200,6 +204,7 @@ struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn) return NULL; } +#ifdef CONFIG_PCI_LEGACY /** * pci_find_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids @@ -278,6 +283,7 @@ pci_find_device(unsigned int vendor, unsigned int device, const struct pci_dev * { return pci_find_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from); } +#endif /* CONFIG_PCI_LEGACY */ /** * pci_get_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id @@ -468,8 +474,11 @@ int pci_dev_present(const struct pci_device_id *ids) EXPORT_SYMBOL(pci_dev_present); EXPORT_SYMBOL(pci_find_present); +#ifdef CONFIG_PCI_LEGACY EXPORT_SYMBOL(pci_find_device); EXPORT_SYMBOL(pci_find_slot); +#endif /* CONFIG_PCI_LEGACY */ + /* For boot time work */ EXPORT_SYMBOL(pci_find_bus); EXPORT_SYMBOL(pci_find_next_bus); diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index a0aca46ce87..56230dbd347 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -89,7 +89,7 @@ DECLARE_RWSEM(pcmcia_socket_list_rwsem); EXPORT_SYMBOL(pcmcia_socket_list_rwsem); -/** +/* * Low-level PCMCIA socket drivers need to register with the PCCard * core using pcmcia_register_socket. * @@ -174,6 +174,7 @@ static int pccardd(void *__skt); /** * pcmcia_register_socket - add a new pcmcia socket device + * @socket: the &socket to register */ int pcmcia_register_socket(struct pcmcia_socket *socket) { @@ -268,6 +269,7 @@ EXPORT_SYMBOL(pcmcia_register_socket); /** * pcmcia_unregister_socket - remove a pcmcia socket device + * @socket: the &socket to unregister */ void pcmcia_unregister_socket(struct pcmcia_socket *socket) { @@ -311,7 +313,7 @@ struct pcmcia_socket * pcmcia_get_socket_by_nr(unsigned int nr) } EXPORT_SYMBOL(pcmcia_get_socket_by_nr); -/** +/* * The central event handler. Send_event() sends an event to the * 16-bit subsystem, which then calls the relevant device drivers. * Parse_events() interprets the event bits from @@ -380,7 +382,7 @@ static int socket_reset(struct pcmcia_socket *skt) return CS_GENERAL_FAILURE; } -/** +/* * socket_setup() and socket_shutdown() are called by the main event handler * when card insertion and removal events are received. * socket_setup() turns on socket power and resets the socket, in two stages. diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 7bf78c12789..5cf89a91da1 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -320,6 +320,7 @@ pcmcia_create_newid_file(struct pcmcia_driver *drv) /** * pcmcia_register_driver - register a PCMCIA driver with the bus core + * @driver: the &driver being registered * * Registers a PCMCIA driver with the PCMCIA bus core. */ @@ -354,6 +355,7 @@ EXPORT_SYMBOL(pcmcia_register_driver); /** * pcmcia_unregister_driver - unregister a PCMCIA driver with the bus core + * @driver: the &driver being unregistered */ void pcmcia_unregister_driver(struct pcmcia_driver *driver) { @@ -840,8 +842,8 @@ static void pcmcia_bus_rescan(struct pcmcia_socket *skt, int new_cis) /** * pcmcia_load_firmware - load CIS from userspace if device-provided is broken - * @dev - the pcmcia device which needs a CIS override - * @filename - requested filename in /lib/firmware/ + * @dev: the pcmcia device which needs a CIS override + * @filename: requested filename in /lib/firmware/ * * This uses the in-kernel firmware loading mechanism to use a "fake CIS" if * the one provided by the card is broken. The firmware files reside in diff --git a/drivers/pcmcia/pxa2xx_lubbock.c b/drivers/pcmcia/pxa2xx_lubbock.c index 1510d6cde3e..4a05802213c 100644 --- a/drivers/pcmcia/pxa2xx_lubbock.c +++ b/drivers/pcmcia/pxa2xx_lubbock.c @@ -213,7 +213,7 @@ static struct pcmcia_low_level lubbock_pcmcia_ops = { #include "pxa2xx_base.h" -int __init pcmcia_lubbock_init(struct sa1111_dev *sadev) +int pcmcia_lubbock_init(struct sa1111_dev *sadev) { int ret = -ENODEV; diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h index 62e9ebf967f..d29657bf1b4 100644 --- a/drivers/pcmcia/ti113x.h +++ b/drivers/pcmcia/ti113x.h @@ -874,7 +874,7 @@ static int ti1250_override(struct yenta_socket *socket) */ #ifdef CONFIG_YENTA_ENE_TUNE -/** +/* * set/clear various test bits: * Defaults to clear the bit. * - mask (u8) defines what bits to change diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 20853a03202..0ab1fb65cdc 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -48,7 +48,7 @@ MODULE_PARM_DESC(pwr_irqs_off, "Force IRQs off during power-on of slot. Use only #define to_cycles(ns) ((ns)/120) #define to_ns(cycles) ((cycles)*120) -/** +/* * yenta PCI irq probing. * currently only used in the TI/EnE initialization code */ @@ -888,7 +888,7 @@ static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mas } -/** +/* * yenta PCI irq probing. * currently only used in the TI/EnE initialization code */ @@ -1012,7 +1012,7 @@ static void yenta_config_init(struct yenta_socket *socket) * invisible during PCI scans because of a misconfigured subordinate number * of the parent brige - some BIOSes seem to be too lazy to set it right. * Does the fixup carefully by checking how far it can go without conflicts. - * See http://bugzilla.kernel.org/show_bug.cgi?id=2944 for more information. + * See http\://bugzilla.kernel.org/show_bug.cgi?id=2944 for more information. */ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge) { diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index cd0a204d96d..6b9840cce0f 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -75,6 +75,8 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, { int i = 0; int irq; + int p, t; + static unsigned char warned; if (!valid_IRQ(gsi)) return; @@ -82,18 +84,28 @@ 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 && !warned) { + printk(KERN_ERR "pnpacpi: exceeded the max number of IRQ " + "resources: %d \n", PNP_MAX_IRQ); + warned = 1; 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); @@ -159,6 +171,7 @@ static void pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, int bus_master, int transfer) { int i = 0; + static unsigned char warned; while (i < PNP_MAX_DMA && !(res->dma_resource[i].flags & IORESOURCE_UNSET)) @@ -173,6 +186,10 @@ static void pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, } res->dma_resource[i].start = dma; res->dma_resource[i].end = dma; + } else if (!warned) { + printk(KERN_ERR "pnpacpi: exceeded the max number of DMA " + "resources: %d \n", PNP_MAX_DMA); + warned = 1; } } @@ -180,6 +197,7 @@ static void pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res, u64 io, u64 len, int io_decode) { int i = 0; + static unsigned char warned; while (!(res->port_resource[i].flags & IORESOURCE_UNSET) && i < PNP_MAX_PORT) @@ -194,6 +212,10 @@ 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 if (!warned) { + printk(KERN_ERR "pnpacpi: exceeded the max number of IO " + "resources: %d \n", PNP_MAX_PORT); + warned = 1; } } @@ -202,6 +224,7 @@ static void pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res, int write_protect) { int i = 0; + static unsigned char warned; while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) && (i < PNP_MAX_MEM)) @@ -217,6 +240,10 @@ 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 if (!warned) { + printk(KERN_ERR "pnpacpi: exceeded the max number of mem " + "resources: %d\n", PNP_MAX_MEM); + warned = 1; } } diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index 41d73a5e931..e50ebcffb96 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 746031de219..1f5a2d33bf5 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 8461b08ab9f..8461b08ab9f 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 9dea585ef80..bb8d5b1eec9 100644 --- a/drivers/ps3/vuart.c +++ b/drivers/ps3/ps3-vuart.c @@ -1074,7 +1074,6 @@ static int ps3_vuart_probe(struct ps3_system_bus_device *dev) if (result) { dev_dbg(&dev->core, "%s:%d: drv->probe failed\n", __func__, __LINE__); - down(&vuart_bus_priv.probe_mutex); goto fail_probe; } diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index cbde770eb12..1e6715ec51e 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 178527252c6..33c0e98243e 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 de0da545c7a..f1e00ff54ce 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_lock(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_unlock(RTC_DEV_BUSY, &rtc->flags); return retval; } diff --git a/drivers/rtc/rtc-at32ap700x.c b/drivers/rtc/rtc-at32ap700x.c index 2999214ca53..d3b9b14267a 100644 --- a/drivers/rtc/rtc-at32ap700x.c +++ b/drivers/rtc/rtc-at32ap700x.c @@ -225,18 +225,12 @@ static int __init at32_rtc_probe(struct platform_device *pdev) goto out; } - ret = request_irq(irq, at32_rtc_interrupt, IRQF_SHARED, "rtc", rtc); - if (ret) { - dev_dbg(&pdev->dev, "could not request irq %d\n", irq); - goto out; - } - rtc->irq = irq; rtc->regs = ioremap(regs->start, regs->end - regs->start + 1); if (!rtc->regs) { ret = -ENOMEM; dev_dbg(&pdev->dev, "could not map I/O memory\n"); - goto out_free_irq; + goto out; } spin_lock_init(&rtc->lock); @@ -253,12 +247,18 @@ static int __init at32_rtc_probe(struct platform_device *pdev) | RTC_BIT(CTRL_EN)); } + ret = request_irq(irq, at32_rtc_interrupt, IRQF_SHARED, "rtc", rtc); + if (ret) { + dev_dbg(&pdev->dev, "could not request irq %d\n", irq); + goto out_iounmap; + } + rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, &at32_rtc_ops, THIS_MODULE); if (IS_ERR(rtc->rtc)) { dev_dbg(&pdev->dev, "could not register rtc device\n"); ret = PTR_ERR(rtc->rtc); - goto out_iounmap; + goto out_free_irq; } platform_set_drvdata(pdev, rtc); @@ -268,10 +268,10 @@ static int __init at32_rtc_probe(struct platform_device *pdev) return 0; -out_iounmap: - iounmap(rtc->regs); out_free_irq: free_irq(irq, rtc); +out_iounmap: + iounmap(rtc->regs); out: kfree(rtc); return ret; diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index e3fe83a23cf..29cf1457ca1 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -120,7 +120,8 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t) t->time.tm_hour = CMOS_READ(RTC_HOURS_ALARM); if (cmos->day_alrm) { - t->time.tm_mday = CMOS_READ(cmos->day_alrm); + /* ignore upper bits on readback per ACPI spec */ + t->time.tm_mday = CMOS_READ(cmos->day_alrm) & 0x3f; if (!t->time.tm_mday) t->time.tm_mday = -1; diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 814583bd2fe..025c60a17a4 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_lock(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_unlock(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_unlock(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 db6f3f0d898..bc1c7fe94ad 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 bb53c09bad1..d9e848dcd45 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 c535b78698e..2e73f0b183b 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 bf60d35f580..cd0bbc0e803 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) @@ -464,7 +465,7 @@ static int __devexit m48t59_rtc_remove(struct platform_device *pdev) return 0; } -static struct platform_driver m48t59_rtc_platdrv = { +static struct platform_driver m48t59_rtc_driver = { .driver = { .name = "rtc-m48t59", .owner = THIS_MODULE, @@ -475,12 +476,12 @@ static struct platform_driver m48t59_rtc_platdrv = { static int __init m48t59_rtc_init(void) { - return platform_driver_register(&m48t59_rtc_platdrv); + return platform_driver_register(&m48t59_rtc_driver); } static void __exit m48t59_rtc_exit(void) { - platform_driver_unregister(&m48t59_rtc_platdrv); + platform_driver_unregister(&m48t59_rtc_driver); } module_init(m48t59_rtc_init); diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c index 3e183cfee10..1f956dc5d56 100644 --- a/drivers/rtc/rtc-max6902.c +++ b/drivers/rtc/rtc-max6902.c @@ -89,13 +89,9 @@ static int max6902_get_reg(struct device *dev, unsigned char address, /* do the i/o */ status = spi_sync(spi, &message); - if (status == 0) - status = message.status; - else - return status; - - *data = chip->rx_buf[1]; + if (status == 0) + *data = chip->rx_buf[1]; return status; } @@ -125,9 +121,7 @@ static int max6902_get_datetime(struct device *dev, struct rtc_time *dt) /* do the i/o */ status = spi_sync(spi, &message); - if (status == 0) - status = message.status; - else + if (status) return status; /* The chip sends data in this order: diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 8c1012b432b..e2041b4d0c8 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -542,8 +542,6 @@ static int s3c_rtc_probe(struct platform_device *pdev) /* RTC Power management control */ -static struct timespec s3c_rtc_delta; - static int ticnt_save; static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index 78277a118b6..8e8c8b8e81e 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 8288b6b2bf2..a265da7c6ff 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/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 859f870552e..15a5789b773 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -193,6 +193,12 @@ dcssblk_segment_warn(int rc, char* seg_name) } } +static void dcssblk_unregister_callback(struct device *dev) +{ + device_unregister(dev); + put_device(dev); +} + /* * device attribute for switching shared/nonshared (exclusive) * operation (show + store) @@ -276,8 +282,7 @@ removeseg: blk_cleanup_queue(dev_info->dcssblk_queue); dev_info->gd->queue = NULL; put_disk(dev_info->gd); - device_unregister(dev); - put_device(dev); + rc = device_schedule_callback(dev, dcssblk_unregister_callback); out: up_write(&dcssblk_devices_sem); return rc; @@ -467,11 +472,11 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char if (rc) goto unregister_dev; - add_disk(dev_info->gd); - blk_queue_make_request(dev_info->dcssblk_queue, dcssblk_make_request); blk_queue_hardsect_size(dev_info->dcssblk_queue, 4096); + add_disk(dev_info->gd); + switch (dev_info->segment_type) { case SEG_TYPE_SR: case SEG_TYPE_ER: diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c index 725b0dd1426..f4c132ab39e 100644 --- a/drivers/s390/cio/cmf.c +++ b/drivers/s390/cio/cmf.c @@ -343,10 +343,10 @@ static int cmf_copy_block(struct ccw_device *cdev) if (sch->schib.scsw.fctl & SCSW_FCTL_START_FUNC) { /* Don't copy if a start function is in progress. */ - if ((!sch->schib.scsw.actl & SCSW_ACTL_SUSPENDED) && + if ((!(sch->schib.scsw.actl & SCSW_ACTL_SUSPENDED)) && (sch->schib.scsw.actl & (SCSW_ACTL_DEVACT | SCSW_ACTL_SCHACT)) && - (!sch->schib.scsw.stctl & SCSW_STCTL_SEC_STATUS)) + (!(sch->schib.scsw.stctl & SCSW_STCTL_SEC_STATUS))) return -EBUSY; } cmb_data = cdev->private->cmb; diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 838f7ac0dc3..c3df2cd009a 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -451,6 +451,7 @@ static int reprobe_subchannel(struct subchannel_id schid, void *data) break; case -ENXIO: case -ENOMEM: + case -EIO: /* These should abort looping */ break; default: @@ -483,7 +484,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.c b/drivers/s390/cio/device.c index 7ee57f084a8..74f6b539974 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -738,7 +738,7 @@ static int io_subchannel_initialize_dev(struct subchannel *sch, atomic_set(&cdev->private->onoff, 0); cdev->dev.parent = &sch->dev; cdev->dev.release = ccw_device_release; - INIT_LIST_HEAD(&cdev->private->kick_work.entry); + INIT_WORK(&cdev->private->kick_work, NULL); cdev->dev.groups = ccwdev_attr_groups; /* Do first half of device_register. */ device_initialize(&cdev->dev); diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 8867443b806..bfad421cda6 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 f232832f2b2..156f3f9786b 100644 --- a/drivers/s390/cio/device_id.c +++ b/drivers/s390/cio/device_id.c @@ -118,14 +118,6 @@ __ccw_device_sense_id_start(struct ccw_device *cdev) 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); diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c index 6bf3ebbe985..77a503139e3 100644 --- a/drivers/s390/net/ctcmain.c +++ b/drivers/s390/net/ctcmain.c @@ -478,14 +478,14 @@ ctc_unpack_skb(struct channel *ch, struct sk_buff *pskb) skb->dev = pskb->dev; skb->protocol = pskb->protocol; pskb->ip_summed = CHECKSUM_UNNECESSARY; - netif_rx_ni(skb); /** - * Successful rx; reset logflags + * reset logflags */ ch->logflags = 0; - dev->last_rx = jiffies; privptr->stats.rx_packets++; privptr->stats.rx_bytes += skb->len; + netif_rx_ni(skb); + dev->last_rx = jiffies; if (len > 0) { skb_pull(pskb, header->length); if (skb_tailroom(pskb) < LL_HEADER_LENGTH) { @@ -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,6 @@ 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; } @@ -2879,14 +2857,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/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index 4d18d6419dd..c7ea9381db9 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -639,14 +639,14 @@ static void netiucv_unpack_skb(struct iucv_connection *conn, skb->dev = pskb->dev; skb->protocol = pskb->protocol; pskb->ip_summed = CHECKSUM_UNNECESSARY; + privptr->stats.rx_packets++; + privptr->stats.rx_bytes += skb->len; /* * Since receiving is always initiated from a tasklet (in iucv.c), * we must use netif_rx_ni() instead of netif_rx() */ netif_rx_ni(skb); dev->last_rx = jiffies; - privptr->stats.rx_packets++; - privptr->stats.rx_bytes += skb->len; skb_pull(pskb, header->next); skb_put(pskb, NETIUCV_HDRLEN); } diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c index 3ccca5871fd..47bb47b4858 100644 --- a/drivers/s390/net/smsgiucv.c +++ b/drivers/s390/net/smsgiucv.c @@ -148,6 +148,10 @@ static int __init smsg_init(void) { int rc; + if (!MACHINE_IS_VM) { + rc = -EPROTONOSUPPORT; + goto out; + } rc = driver_register(&smsg_driver); if (rc != 0) goto out; diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 0754542978b..e268f79bdbd 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -70,11 +70,12 @@ zfcp_sg_to_address(struct scatterlist *list) * zfcp_address_to_sg - set up struct scatterlist from kernel address * @address: kernel address * @list: struct scatterlist + * @size: buffer size */ static inline void -zfcp_address_to_sg(void *address, struct scatterlist *list) +zfcp_address_to_sg(void *address, struct scatterlist *list, unsigned int size) { - sg_set_buf(list, address, 0); + sg_set_buf(list, address, size); } #define REQUEST_LIST_SIZE 128 diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 5552b755c08..07fa824d179 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -977,7 +977,9 @@ static void zfcp_erp_action_dismiss(struct zfcp_erp_action *erp_action) debug_text_event(adapter->erp_dbf, 2, "a_adis"); debug_event(adapter->erp_dbf, 2, &erp_action->action, sizeof (int)); - zfcp_erp_async_handler_nolock(erp_action, ZFCP_STATUS_ERP_DISMISSED); + erp_action->status |= ZFCP_STATUS_ERP_DISMISSED; + if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) + zfcp_erp_action_ready(erp_action); } int @@ -1063,7 +1065,7 @@ zfcp_erp_thread(void *data) &adapter->status)) { write_lock_irqsave(&adapter->erp_lock, flags); - next = adapter->erp_ready_head.prev; + next = adapter->erp_ready_head.next; write_unlock_irqrestore(&adapter->erp_lock, flags); if (next != &adapter->erp_ready_head) { @@ -1153,15 +1155,13 @@ zfcp_erp_strategy(struct zfcp_erp_action *erp_action) /* * check for dismissed status again to avoid follow-up actions, - * failing of targets and so on for dismissed actions + * failing of targets and so on for dismissed actions, + * we go through down() here because there has been an up() */ - retval = zfcp_erp_strategy_check_action(erp_action, retval); + if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) + retval = ZFCP_ERP_CONTINUES; switch (retval) { - case ZFCP_ERP_DISMISSED: - /* leave since this action has ridden to its ancestors */ - debug_text_event(adapter->erp_dbf, 6, "a_st_dis2"); - goto unlock; case ZFCP_ERP_NOMEM: /* no memory to continue immediately, let it sleep */ if (!(erp_action->status & ZFCP_STATUS_ERP_LOWMEM)) { @@ -3089,7 +3089,7 @@ zfcp_erp_action_enqueue(int action, ++adapter->erp_total_count; /* finally put it into 'ready' queue and kick erp thread */ - list_add(&erp_action->list, &adapter->erp_ready_head); + list_add_tail(&erp_action->list, &adapter->erp_ready_head); up(&adapter->erp_ready_sem); retval = 0; out: diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c index 7b5773d8821..a4e75814366 100644 --- a/drivers/sbus/char/cpwatchdog.c +++ b/drivers/sbus/char/cpwatchdog.c @@ -154,7 +154,7 @@ struct wd_device { }; static struct wd_device wd_dev = { - 0, SPIN_LOCK_UNLOCKED, 0, 0, 0, 0, + 0, __SPIN_LOCK_UNLOCKED(wd_dev.lock), 0, 0, 0, 0, }; static struct timer_list wd_timer; diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index a5763c6e936..a6676be8784 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -172,12 +172,12 @@ config CHR_DEV_SCH don't need this for those tiny 6-slot cdrom changers. Media changers are listed as "Type: Medium Changer" in /proc/scsi/scsi. If you have such hardware and want to use it with linux, say Y - here. Check <file:Documentation/scsi-changer.txt> for details. + here. Check <file:Documentation/scsi/scsi-changer.txt> for details. If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read <file:Documentation/kbuild/modules.txt> and - <file:Documentation/scsi.txt>. The module will be called ch.o. + <file:Documentation/scsi/scsi.txt>. The module will be called ch.o. If unsure, say N. @@ -725,7 +725,7 @@ config SCSI_FD_MCS config SCSI_GDTH tristate "Intel/ICP (former GDT SCSI Disk Array) RAID Controller support" - depends on (ISA || EISA || PCI) && SCSI && ISA_DMA_API + depends on (ISA || EISA || PCI) && SCSI && ISA_DMA_API && PCI_LEGACY ---help--- Formerly called GDT SCSI Disk Array Controller Support. diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index 72b0393b459..1e6d7a9c75b 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c @@ -391,7 +391,7 @@ static int close_getadapter_fib(struct aac_dev * dev, void __user *arg) /* * Extract the fibctx from the input parameters */ - if (fibctx->unique == (u32)(ptrdiff_t)arg) /* We found a winner */ + if (fibctx->unique == (u32)(uintptr_t)arg) /* We found a winner */ break; entry = entry->next; fibctx = NULL; @@ -590,7 +590,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) } addr = (u64)upsg->sg[i].addr[0]; addr += ((u64)upsg->sg[i].addr[1]) << 32; - sg_user[i] = (void __user *)(ptrdiff_t)addr; + sg_user[i] = (void __user *)(uintptr_t)addr; sg_list[i] = p; // save so we can clean up later sg_indx = i; @@ -633,7 +633,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) rcode = -ENOMEM; goto cleanup; } - sg_user[i] = (void __user *)(ptrdiff_t)usg->sg[i].addr; + sg_user[i] = (void __user *)(uintptr_t)usg->sg[i].addr; sg_list[i] = p; // save so we can clean up later sg_indx = i; @@ -664,7 +664,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) if (actual_fibsize64 == fibsize) { struct user_sgmap64* usg = (struct user_sgmap64 *)upsg; for (i = 0; i < upsg->count; i++) { - u64 addr; + uintptr_t addr; void* p; /* Does this really need to be GFP_DMA? */ p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA); @@ -676,7 +676,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) } addr = (u64)usg->sg[i].addr[0]; addr += ((u64)usg->sg[i].addr[1]) << 32; - sg_user[i] = (void __user *)(ptrdiff_t)addr; + sg_user[i] = (void __user *)addr; sg_list[i] = p; // save so we can clean up later sg_indx = i; @@ -704,7 +704,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) rcode = -ENOMEM; goto cleanup; } - sg_user[i] = (void __user *)(ptrdiff_t)upsg->sg[i].addr; + sg_user[i] = (void __user *)(uintptr_t)upsg->sg[i].addr; sg_list[i] = p; // save so we can clean up later sg_indx = i; diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 3009ad8c407..8736813a029 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c @@ -110,7 +110,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co /* * Align the beginning of Headers to commalign */ - align = (commalign - ((ptrdiff_t)(base) & (commalign - 1))); + align = (commalign - ((uintptr_t)(base) & (commalign - 1))); base = base + align; phys = phys + align; /* diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 240a0bb8986..abce48ccc85 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -1339,10 +1339,10 @@ int aac_check_health(struct aac_dev * aac) aif = (struct aac_aifcmd *)hw_fib->data; aif->command = cpu_to_le32(AifCmdEventNotify); aif->seqnum = cpu_to_le32(0xFFFFFFFF); - aif->data[0] = cpu_to_le32(AifEnExpEvent); - aif->data[1] = cpu_to_le32(AifExeFirmwarePanic); - aif->data[2] = cpu_to_le32(AifHighPriority); - aif->data[3] = cpu_to_le32(BlinkLED); + aif->data[0] = AifEnExpEvent; + aif->data[1] = AifExeFirmwarePanic; + aif->data[2] = AifHighPriority; + aif->data[3] = BlinkLED; /* * Put the FIB onto the diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c index fcd25f7d0bc..e6032ffc66a 100644 --- a/drivers/scsi/aacraid/dpcsup.c +++ b/drivers/scsi/aacraid/dpcsup.c @@ -254,7 +254,7 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index) kfree (fib); return 1; } - memcpy(hw_fib, (struct hw_fib *)(((ptrdiff_t)(dev->regs.sa)) + + memcpy(hw_fib, (struct hw_fib *)(((uintptr_t)(dev->regs.sa)) + (index & ~0x00000002L)), sizeof(struct hw_fib)); INIT_LIST_HEAD(&fib->fiblink); fib->type = FSAFS_NTC_FIB_CONTEXT; diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 038980be763..9dd331bc29b 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -636,7 +636,7 @@ static int aac_cfg_open(struct inode *inode, struct file *file) static int aac_cfg_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - if (!capable(CAP_SYS_ADMIN)) + if (!capable(CAP_SYS_RAWIO)) return -EPERM; return aac_do_ioctl(file->private_data, cmd, (void __user *)arg); } @@ -691,7 +691,7 @@ static int aac_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) static long aac_compat_cfg_ioctl(struct file *file, unsigned cmd, unsigned long arg) { - if (!capable(CAP_SYS_ADMIN)) + if (!capable(CAP_SYS_RAWIO)) return -EPERM; return aac_compat_do_ioctl((struct aac_dev *)file->private_data, cmd, arg); } @@ -950,7 +950,8 @@ static struct scsi_host_template aac_driver_template = { static void __aac_shutdown(struct aac_dev * aac) { - kthread_stop(aac->thread); + if (aac->aif_thread) + kthread_stop(aac->thread); aac_send_shutdown(aac); aac_adapter_disable_int(aac); free_irq(aac->pdev->irq, aac); diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index 9dd3952516c..38a1ee2eacd 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -13906,7 +13906,7 @@ static int advansys_release(struct Scsi_Host *shost) #define ASC_IOADR_TABLE_MAX_IX 11 -static PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] __devinitdata = { +static PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] = { 0x100, 0x0110, 0x120, 0x0130, 0x140, 0x0150, 0x0190, 0x0210, 0x0230, 0x0250, 0x0330 }; diff --git a/drivers/scsi/aic94xx/aic94xx_sds.c b/drivers/scsi/aic94xx/aic94xx_sds.c index 5b0932f6147..06509bff71f 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/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h index ace7a15b413..a67e29f83ae 100644 --- a/drivers/scsi/arcmsr/arcmsr.h +++ b/drivers/scsi/arcmsr/arcmsr.h @@ -141,14 +141,14 @@ struct CMD_MESSAGE_FIELD #define IS_SG64_ADDR 0x01000000 /* bit24 */ struct SG32ENTRY { - uint32_t length; - uint32_t address; + __le32 length; + __le32 address; }; struct SG64ENTRY { - uint32_t length; - uint32_t address; - uint32_t addresshigh; + __le32 length; + __le32 address; + __le32 addresshigh; }; struct SGENTRY_UNION { @@ -339,23 +339,15 @@ struct MessageUnit_B uint32_t done_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE]; uint32_t postq_index; uint32_t doneq_index; - uint32_t *drv2iop_doorbell_reg; - uint32_t *drv2iop_doorbell_mask_reg; - uint32_t *iop2drv_doorbell_reg; - uint32_t *iop2drv_doorbell_mask_reg; - uint32_t *msgcode_rwbuffer_reg; - uint32_t *ioctl_wbuffer_reg; - uint32_t *ioctl_rbuffer_reg; + uint32_t __iomem *drv2iop_doorbell_reg; + uint32_t __iomem *drv2iop_doorbell_mask_reg; + uint32_t __iomem *iop2drv_doorbell_reg; + uint32_t __iomem *iop2drv_doorbell_mask_reg; + uint32_t __iomem *msgcode_rwbuffer_reg; + uint32_t __iomem *ioctl_wbuffer_reg; + uint32_t __iomem *ioctl_rbuffer_reg; }; -struct MessageUnit -{ - union - { - struct MessageUnit_A pmu_A; - struct MessageUnit_B pmu_B; - } u; -}; /* ******************************************************************************* ** Adapter Control Block @@ -374,7 +366,10 @@ struct AdapterControlBlock /* Offset is used in making arc cdb physical to virtual calculations */ uint32_t outbound_int_enable; - struct MessageUnit * pmu; + union { + struct MessageUnit_A __iomem * pmuA; + struct MessageUnit_B * pmuB; + }; /* message unit ATU inbound base address0 */ uint32_t acb_flags; @@ -558,7 +553,7 @@ struct SENSE_DATA extern void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *); extern void arcmsr_iop_message_read(struct AdapterControlBlock *); -extern struct QBUFFER *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *); +extern struct QBUFFER __iomem *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *); extern struct class_device_attribute *arcmsr_host_attrs[]; extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *); void arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb); diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c index d04d1aa28fa..7d7b0a55427 100644 --- a/drivers/scsi/arcmsr/arcmsr_attr.c +++ b/drivers/scsi/arcmsr/arcmsr_attr.c @@ -85,13 +85,13 @@ static ssize_t arcmsr_sysfs_iop_message_read(struct kobject *kobj, allxfer_len++; } if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { - struct QBUFFER *prbuffer; - uint8_t *iop_data; + struct QBUFFER __iomem *prbuffer; + uint8_t __iomem *iop_data; int32_t iop_len; acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; prbuffer = arcmsr_get_iop_rqbuffer(acb); - iop_data = (uint8_t *)prbuffer->data; + iop_data = prbuffer->data; iop_len = readl(&prbuffer->data_len); while (iop_len > 0) { acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data); diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index f7a252885a5..d466a2dac1d 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -236,18 +236,22 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) uint32_t intmask_org; int i, j; - acb->pmu = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); - if (!acb->pmu) { + acb->pmuA = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); + if (!acb->pmuA) { printk(KERN_NOTICE "arcmsr%d: memory mapping region fail \n", acb->host->host_no); + return -ENOMEM; } dma_coherent = dma_alloc_coherent(&pdev->dev, ARCMSR_MAX_FREECCB_NUM * sizeof (struct CommandControlBlock) + 0x20, &dma_coherent_handle, GFP_KERNEL); - if (!dma_coherent) + + if (!dma_coherent) { + iounmap(acb->pmuA); return -ENOMEM; + } acb->dma_coherent = dma_coherent; acb->dma_coherent_handle = dma_coherent_handle; @@ -287,7 +291,7 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) struct pci_dev *pdev = acb->pdev; struct MessageUnit_B *reg; - void *mem_base0, *mem_base1; + void __iomem *mem_base0, *mem_base1; void *dma_coherent; dma_addr_t dma_coherent_handle, dma_addr; uint32_t intmask_org; @@ -328,25 +332,28 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) reg = (struct MessageUnit_B *)(dma_coherent + ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock)); - acb->pmu = (struct MessageUnit *)reg; + acb->pmuB = reg; mem_base0 = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); + if (!mem_base0) + goto out; + mem_base1 = ioremap(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2)); - reg->drv2iop_doorbell_reg = (uint32_t *)((char *)mem_base0 + - ARCMSR_DRV2IOP_DOORBELL); - reg->drv2iop_doorbell_mask_reg = (uint32_t *)((char *)mem_base0 + - ARCMSR_DRV2IOP_DOORBELL_MASK); - reg->iop2drv_doorbell_reg = (uint32_t *)((char *)mem_base0 + - ARCMSR_IOP2DRV_DOORBELL); - reg->iop2drv_doorbell_mask_reg = (uint32_t *)((char *)mem_base0 + - ARCMSR_IOP2DRV_DOORBELL_MASK); - reg->ioctl_wbuffer_reg = (uint32_t *)((char *)mem_base1 + - ARCMSR_IOCTL_WBUFFER); - reg->ioctl_rbuffer_reg = (uint32_t *)((char *)mem_base1 + - ARCMSR_IOCTL_RBUFFER); - reg->msgcode_rwbuffer_reg = (uint32_t *)((char *)mem_base1 + - ARCMSR_MSGCODE_RWBUFFER); + if (!mem_base1) { + iounmap(mem_base0); + goto out; + } + + reg->drv2iop_doorbell_reg = mem_base0 + ARCMSR_DRV2IOP_DOORBELL; + reg->drv2iop_doorbell_mask_reg = mem_base0 + + ARCMSR_DRV2IOP_DOORBELL_MASK; + reg->iop2drv_doorbell_reg = mem_base0 + ARCMSR_IOP2DRV_DOORBELL; + reg->iop2drv_doorbell_mask_reg = mem_base0 + + ARCMSR_IOP2DRV_DOORBELL_MASK; + reg->ioctl_wbuffer_reg = mem_base1 + ARCMSR_IOCTL_WBUFFER; + reg->ioctl_rbuffer_reg = mem_base1 + ARCMSR_IOCTL_RBUFFER; + reg->msgcode_rwbuffer_reg = mem_base1 + ARCMSR_MSGCODE_RWBUFFER; acb->vir2phy_offset = (unsigned long)ccb_tmp -(unsigned long)dma_addr; for (i = 0; i < ARCMSR_MAX_TARGETID; i++) @@ -362,6 +369,12 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) break; } return 0; + +out: + dma_free_coherent(&acb->pdev->dev, + ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock) + 0x20, + acb->dma_coherent, acb->dma_coherent_handle); + return -ENOMEM; } static int arcmsr_probe(struct pci_dev *pdev, @@ -454,7 +467,6 @@ static int arcmsr_probe(struct pci_dev *pdev, free_irq(pdev->irq, acb); out_free_ccb_pool: arcmsr_free_ccb_pool(acb); - iounmap(acb->pmu); out_release_regions: pci_release_regions(pdev); out_host_put: @@ -467,7 +479,7 @@ static int arcmsr_probe(struct pci_dev *pdev, static uint8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb) { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; uint32_t Index; uint8_t Retries = 0x00; @@ -488,7 +500,7 @@ static uint8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb) static uint8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; uint32_t Index; uint8_t Retries = 0x00; @@ -509,7 +521,7 @@ static uint8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, ®->inbound_msgaddr0); if (arcmsr_hba_wait_msgint_ready(acb)) @@ -520,7 +532,7 @@ static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb) { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; writel(ARCMSR_MESSAGE_ABORT_CMD, reg->drv2iop_doorbell_reg); if (arcmsr_hbb_wait_msgint_ready(acb)) @@ -566,7 +578,7 @@ static void arcmsr_ccb_complete(struct CommandControlBlock *ccb, int stand_flag) static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb) { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; int retry_count = 30; writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, ®->inbound_msgaddr0); @@ -583,7 +595,7 @@ static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb) static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb) { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; int retry_count = 30; writel(ARCMSR_MESSAGE_FLUSH_CACHE, reg->drv2iop_doorbell_reg); @@ -637,7 +649,7 @@ static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb) switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A : { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; orig_mask = readl(®->outbound_intmask)|\ ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE; writel(orig_mask|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, \ @@ -646,7 +658,7 @@ static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb) break; case ACB_ADAPTER_TYPE_B : { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; orig_mask = readl(reg->iop2drv_doorbell_mask_reg) & \ (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); writel(0, reg->iop2drv_doorbell_mask_reg); @@ -748,14 +760,13 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { - struct MessageUnit_A __iomem *reg = \ - (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; uint32_t outbound_intstatus; - outbound_intstatus = readl(®->outbound_intstatus) & \ + outbound_intstatus = readl(®->outbound_intstatus) & acb->outbound_int_enable; /*clear and abort all outbound posted Q*/ writel(outbound_intstatus, ®->outbound_intstatus);/*clear interrupt*/ - while (((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) \ + while (((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { arcmsr_drain_donequeue(acb, flag_ccb); } @@ -763,7 +774,7 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) break; case ACB_ADAPTER_TYPE_B: { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; /*clear all outbound posted Q*/ for (i = 0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) { if ((flag_ccb = readl(®->done_qbuffer[i])) != 0) { @@ -816,7 +827,6 @@ static void arcmsr_remove(struct pci_dev *pdev) } free_irq(pdev->irq, acb); - iounmap(acb->pmu); arcmsr_free_ccb_pool(acb); pci_release_regions(pdev); @@ -859,7 +869,7 @@ static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, \ switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A : { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; mask = intmask_org & ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE | ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); writel(mask, ®->outbound_intmask); @@ -868,7 +878,7 @@ static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, \ break; case ACB_ADAPTER_TYPE_B : { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; mask = intmask_org | (ARCMSR_IOP2DRV_DATA_WRITE_OK | \ ARCMSR_IOP2DRV_DATA_READ_OK | ARCMSR_IOP2DRV_CDB_DONE); writel(mask, reg->iop2drv_doorbell_mask_reg); @@ -882,7 +892,7 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb, { struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb; int8_t *psge = (int8_t *)&arcmsr_cdb->u; - uint32_t address_lo, address_hi; + __le32 address_lo, address_hi; int arccdbsize = 0x30; int nseg; @@ -900,7 +910,8 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb, BUG_ON(nseg < 0); if (nseg) { - int length, i, cdb_sgcount = 0; + __le32 length; + int i, cdb_sgcount = 0; struct scatterlist *sg; /* map stor port SG list to our iop SG List. */ @@ -921,7 +932,7 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb, pdma_sg->addresshigh = address_hi; pdma_sg->address = address_lo; - pdma_sg->length = length|IS_SG64_ADDR; + pdma_sg->length = length|cpu_to_le32(IS_SG64_ADDR); psge += sizeof (struct SG64ENTRY); arccdbsize += sizeof (struct SG64ENTRY); } @@ -947,7 +958,7 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { - struct MessageUnit_A *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) writel(cdb_shifted_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE, @@ -959,7 +970,7 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr break; case ACB_ADAPTER_TYPE_B: { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; uint32_t ending_index, index = reg->postq_index; ending_index = ((index + 1) % ARCMSR_MAX_HBB_POSTQUEUE); @@ -982,7 +993,7 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb) { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; acb->acb_flags &= ~ACB_F_MSG_START_BGRB; writel(ARCMSR_INBOUND_MESG0_STOP_BGRB, ®->inbound_msgaddr0); @@ -995,7 +1006,7 @@ static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb) static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb) { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; acb->acb_flags &= ~ACB_F_MSG_START_BGRB; writel(ARCMSR_MESSAGE_STOP_BGRB, reg->drv2iop_doorbell_reg); @@ -1023,6 +1034,17 @@ static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb) { + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + iounmap(acb->pmuA); + break; + } + case ACB_ADAPTER_TYPE_B: { + struct MessageUnit_B *reg = acb->pmuB; + iounmap(reg->drv2iop_doorbell_reg - ARCMSR_DRV2IOP_DOORBELL); + iounmap(reg->ioctl_wbuffer_reg - ARCMSR_IOCTL_WBUFFER); + } + } dma_free_coherent(&acb->pdev->dev, ARCMSR_MAX_FREECCB_NUM * sizeof (struct CommandControlBlock) + 0x20, acb->dma_coherent, @@ -1033,13 +1055,13 @@ void arcmsr_iop_message_read(struct AdapterControlBlock *acb) { switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, ®->inbound_doorbell); } break; case ACB_ADAPTER_TYPE_B: { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; writel(ARCMSR_DRV2IOP_DATA_READ_OK, reg->drv2iop_doorbell_reg); } break; @@ -1050,7 +1072,7 @@ static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb) { switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; /* ** push inbound doorbell tell iop, driver data write ok ** and wait reply on next hwinterrupt for next Qbuffer post @@ -1060,7 +1082,7 @@ static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb) break; case ACB_ADAPTER_TYPE_B: { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; /* ** push inbound doorbell tell iop, driver data write ok ** and wait reply on next hwinterrupt for next Qbuffer post @@ -1071,41 +1093,41 @@ static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb) } } -struct QBUFFER *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *acb) +struct QBUFFER __iomem *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *acb) { - static struct QBUFFER *qbuffer; + struct QBUFFER __iomem *qbuffer = NULL; switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; - qbuffer = (struct QBUFFER __iomem *) ®->message_rbuffer; + struct MessageUnit_A __iomem *reg = acb->pmuA; + qbuffer = (struct QBUFFER __iomem *)®->message_rbuffer; } break; case ACB_ADAPTER_TYPE_B: { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; - qbuffer = (struct QBUFFER __iomem *) reg->ioctl_rbuffer_reg; + struct MessageUnit_B *reg = acb->pmuB; + qbuffer = (struct QBUFFER __iomem *)reg->ioctl_rbuffer_reg; } break; } return qbuffer; } -static struct QBUFFER *arcmsr_get_iop_wqbuffer(struct AdapterControlBlock *acb) +static struct QBUFFER __iomem *arcmsr_get_iop_wqbuffer(struct AdapterControlBlock *acb) { - static struct QBUFFER *pqbuffer; + struct QBUFFER __iomem *pqbuffer = NULL; switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; - pqbuffer = (struct QBUFFER *) ®->message_wbuffer; + struct MessageUnit_A __iomem *reg = acb->pmuA; + pqbuffer = (struct QBUFFER __iomem *) ®->message_wbuffer; } break; case ACB_ADAPTER_TYPE_B: { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; pqbuffer = (struct QBUFFER __iomem *)reg->ioctl_wbuffer_reg; } break; @@ -1115,15 +1137,15 @@ static struct QBUFFER *arcmsr_get_iop_wqbuffer(struct AdapterControlBlock *acb) static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) { - struct QBUFFER *prbuffer; + struct QBUFFER __iomem *prbuffer; struct QBUFFER *pQbuffer; - uint8_t *iop_data; + uint8_t __iomem *iop_data; int32_t my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex; rqbuf_lastindex = acb->rqbuf_lastindex; rqbuf_firstindex = acb->rqbuf_firstindex; prbuffer = arcmsr_get_iop_rqbuffer(acb); - iop_data = (uint8_t *)prbuffer->data; + iop_data = (uint8_t __iomem *)prbuffer->data; iop_len = prbuffer->data_len; my_empty_len = (rqbuf_firstindex - rqbuf_lastindex -1)&(ARCMSR_MAX_QBUFFER -1); @@ -1151,8 +1173,8 @@ static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED; if (acb->wqbuf_firstindex != acb->wqbuf_lastindex) { uint8_t *pQbuffer; - struct QBUFFER *pwbuffer; - uint8_t *iop_data; + struct QBUFFER __iomem *pwbuffer; + uint8_t __iomem *iop_data; int32_t allxfer_len = 0; acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); @@ -1181,7 +1203,7 @@ static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) { uint32_t outbound_doorbell; - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; outbound_doorbell = readl(®->outbound_doorbell); writel(outbound_doorbell, ®->outbound_doorbell); @@ -1197,7 +1219,7 @@ static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb) { uint32_t flag_ccb; - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; while ((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) { arcmsr_drain_donequeue(acb, flag_ccb); @@ -1208,7 +1230,7 @@ static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb) { uint32_t index; uint32_t flag_ccb; - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; index = reg->doneq_index; @@ -1224,7 +1246,7 @@ static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb) static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb) { uint32_t outbound_intstatus; - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; outbound_intstatus = readl(®->outbound_intstatus) & \ acb->outbound_int_enable; @@ -1244,7 +1266,7 @@ static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb) static int arcmsr_handle_hbb_isr(struct AdapterControlBlock *acb) { uint32_t outbound_doorbell; - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; outbound_doorbell = readl(reg->iop2drv_doorbell_reg) & \ acb->outbound_int_enable; @@ -1305,8 +1327,8 @@ void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb) { int32_t wqbuf_firstindex, wqbuf_lastindex; uint8_t *pQbuffer; - struct QBUFFER *pwbuffer; - uint8_t *iop_data; + struct QBUFFER __iomem *pwbuffer; + uint8_t __iomem *iop_data; int32_t allxfer_len = 0; pwbuffer = arcmsr_get_iop_wqbuffer(acb); @@ -1380,13 +1402,13 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ } if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { - struct QBUFFER *prbuffer; - uint8_t *iop_data; + struct QBUFFER __iomem *prbuffer; + uint8_t __iomem *iop_data; int32_t iop_len; acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; prbuffer = arcmsr_get_iop_rqbuffer(acb); - iop_data = (uint8_t *)prbuffer->data; + iop_data = prbuffer->data; iop_len = readl(&prbuffer->data_len); while (iop_len > 0) { acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data); @@ -1669,11 +1691,11 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd, static void arcmsr_get_hba_config(struct AdapterControlBlock *acb) { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; char *acb_firm_model = acb->firm_model; char *acb_firm_version = acb->firm_version; - char *iop_firm_model = (char *) (®->message_rwbuffer[15]); - char *iop_firm_version = (char *) (®->message_rwbuffer[17]); + char __iomem *iop_firm_model = (char __iomem *)(®->message_rwbuffer[15]); + char __iomem *iop_firm_version = (char __iomem *)(®->message_rwbuffer[17]); int count; writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0); @@ -1710,13 +1732,13 @@ static void arcmsr_get_hba_config(struct AdapterControlBlock *acb) static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb) { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; - uint32_t *lrwbuffer = reg->msgcode_rwbuffer_reg; + struct MessageUnit_B *reg = acb->pmuB; + uint32_t __iomem *lrwbuffer = reg->msgcode_rwbuffer_reg; char *acb_firm_model = acb->firm_model; char *acb_firm_version = acb->firm_version; - char *iop_firm_model = (char *) (&lrwbuffer[15]); + char __iomem *iop_firm_model = (char __iomem *)(&lrwbuffer[15]); /*firm_model,15,60-67*/ - char *iop_firm_version = (char *) (&lrwbuffer[17]); + char __iomem *iop_firm_version = (char __iomem *)(&lrwbuffer[17]); /*firm_version,17,68-83*/ int count; @@ -1777,7 +1799,7 @@ static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) static void arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_ccb) { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; struct CommandControlBlock *ccb; uint32_t flag_ccb, outbound_intstatus, poll_ccb_done = 0, poll_count = 0; @@ -1826,7 +1848,7 @@ static void arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb, static void arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, \ struct CommandControlBlock *poll_ccb) { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; struct CommandControlBlock *ccb; uint32_t flag_ccb, poll_ccb_done = 0, poll_count = 0; int index; @@ -1918,8 +1940,7 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) case ACB_ADAPTER_TYPE_A: { if (ccb_phyaddr_hi32 != 0) { - struct MessageUnit_A __iomem *reg = \ - (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; uint32_t intmask_org; intmask_org = arcmsr_disable_outbound_ints(acb); writel(ARCMSR_SIGNATURE_SET_CONFIG, \ @@ -1940,9 +1961,9 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) case ACB_ADAPTER_TYPE_B: { unsigned long post_queue_phyaddr; - uint32_t *rwbuffer; + uint32_t __iomem *rwbuffer; - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; uint32_t intmask_org; intmask_org = arcmsr_disable_outbound_ints(acb); reg->postq_index = 0; @@ -1994,7 +2015,7 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb) switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; do { firmware_state = readl(®->outbound_msgaddr1); } while ((firmware_state & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0); @@ -2002,7 +2023,7 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb) break; case ACB_ADAPTER_TYPE_B: { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; do { firmware_state = readl(reg->iop2drv_doorbell_reg); } while ((firmware_state & ARCMSR_MESSAGE_FIRMWARE_OK) == 0); @@ -2013,7 +2034,7 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb) static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb) { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; acb->acb_flags |= ACB_F_MSG_START_BGRB; writel(ARCMSR_INBOUND_MESG0_START_BGRB, ®->inbound_msgaddr0); if (arcmsr_hba_wait_msgint_ready(acb)) { @@ -2024,7 +2045,7 @@ static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb) static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb) { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; acb->acb_flags |= ACB_F_MSG_START_BGRB; writel(ARCMSR_MESSAGE_START_BGRB, reg->drv2iop_doorbell_reg); if (arcmsr_hbb_wait_msgint_ready(acb)) { @@ -2049,7 +2070,7 @@ static void arcmsr_clear_doorbell_queue_buffer(struct AdapterControlBlock *acb) { switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { - struct MessageUnit_A *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit_A __iomem *reg = acb->pmuA; uint32_t outbound_doorbell; /* empty doorbell Qbuffer if door bell ringed */ outbound_doorbell = readl(®->outbound_doorbell); @@ -2060,7 +2081,7 @@ static void arcmsr_clear_doorbell_queue_buffer(struct AdapterControlBlock *acb) break; case ACB_ADAPTER_TYPE_B: { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct MessageUnit_B *reg = acb->pmuB; /*clear interrupt and message state*/ writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN, reg->iop2drv_doorbell_reg); writel(ARCMSR_DRV2IOP_DATA_READ_OK, reg->drv2iop_doorbell_reg); diff --git a/drivers/scsi/arm/scsi.h b/drivers/scsi/arm/scsi.h index 21ba57155be..bb6550e3192 100644 --- a/drivers/scsi/arm/scsi.h +++ b/drivers/scsi/arm/scsi.h @@ -38,9 +38,7 @@ static inline int next_SCp(struct scsi_pointer *SCp) if (ret) { SCp->buffer++; SCp->buffers_residual--; - SCp->ptr = (char *) - (page_address(SCp->buffer->page) + - SCp->buffer->offset); + SCp->ptr = sg_virt(SCp->buffer); SCp->this_residual = SCp->buffer->length; } else { SCp->ptr = NULL; @@ -76,9 +74,7 @@ static inline void init_SCp(struct scsi_cmnd *SCpnt) SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer; SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1; - SCpnt->SCp.ptr = (char *) - (page_address(SCpnt->SCp.buffer->page) + - SCpnt->SCp.buffer->offset); + SCpnt->SCp.ptr = sg_virt(SCpnt->SCp.buffer); SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length; SCpnt->SCp.phase = SCpnt->request_bufflen; diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index 6f8403b82ba..f5732d8f67f 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -393,7 +393,7 @@ static irqreturn_t scsi_tt_intr(int irq, void *dummy) #endif /* REAL_DMA */ - NCR5380_intr(0, 0); + NCR5380_intr(irq, dummy); #if 0 /* To be sure the int is not masked */ @@ -458,7 +458,7 @@ static irqreturn_t scsi_falcon_intr(int irq, void *dummy) #endif /* REAL_DMA */ - NCR5380_intr(0, 0); + NCR5380_intr(irq, dummy); return IRQ_HANDLED; } @@ -684,7 +684,7 @@ int atari_scsi_detect(struct scsi_host_template *host) * interrupt after having cleared the pending flag for the DMA * interrupt. */ if (request_irq(IRQ_TT_MFP_SCSI, scsi_tt_intr, IRQ_TYPE_SLOW, - "SCSI NCR5380", scsi_tt_intr)) { + "SCSI NCR5380", instance)) { printk(KERN_ERR "atari_scsi_detect: cannot allocate irq %d, aborting",IRQ_TT_MFP_SCSI); scsi_unregister(atari_scsi_host); atari_stram_free(atari_dma_buffer); @@ -701,7 +701,7 @@ int atari_scsi_detect(struct scsi_host_template *host) IRQ_TYPE_PRIO, "Hades DMA emulator", hades_dma_emulator)) { printk(KERN_ERR "atari_scsi_detect: cannot allocate irq %d, aborting (MACH_IS_HADES)",IRQ_AUTO_2); - free_irq(IRQ_TT_MFP_SCSI, scsi_tt_intr); + free_irq(IRQ_TT_MFP_SCSI, instance); scsi_unregister(atari_scsi_host); atari_stram_free(atari_dma_buffer); atari_dma_buffer = 0; @@ -761,7 +761,7 @@ int atari_scsi_detect(struct scsi_host_template *host) int atari_scsi_release(struct Scsi_Host *sh) { if (IS_A_TT()) - free_irq(IRQ_TT_MFP_SCSI, scsi_tt_intr); + free_irq(IRQ_TT_MFP_SCSI, sh); if (atari_dma_buffer) atari_stram_free(atari_dma_buffer); return 1; diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index 8258506ba7d..b31d1c95c9f 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -173,20 +173,20 @@ static struct pci_device_id dptids[] = { }; MODULE_DEVICE_TABLE(pci,dptids); -static void adpt_exit(void); - -static int adpt_detect(void) +static int adpt_detect(struct scsi_host_template* sht) { struct pci_dev *pDev = NULL; adpt_hba* pHba; + adpt_init(); + PINFO("Detecting Adaptec I2O RAID controllers...\n"); /* search for all Adatpec I2O RAID cards */ while ((pDev = pci_get_device( PCI_DPT_VENDOR_ID, PCI_ANY_ID, pDev))) { if(pDev->device == PCI_DPT_DEVICE_ID || pDev->device == PCI_DPT_RAPTOR_DEVICE_ID){ - if(adpt_install_hba(pDev) ){ + if(adpt_install_hba(sht, pDev) ){ PERROR("Could not Init an I2O RAID device\n"); PERROR("Will not try to detect others.\n"); return hba_count-1; @@ -248,33 +248,34 @@ rebuild_sys_tab: } for (pHba = hba_chain; pHba; pHba = pHba->next) { - if (adpt_scsi_register(pHba) < 0) { + if( adpt_scsi_register(pHba,sht) < 0){ adpt_i2o_delete_hba(pHba); continue; } pHba->initialized = TRUE; pHba->state &= ~DPTI_STATE_RESET; - scsi_scan_host(pHba->host); } // Register our control device node // nodes will need to be created in /dev to access this // the nodes can not be created from within the driver if (hba_count && register_chrdev(DPTI_I2O_MAJOR, DPT_DRIVER, &adpt_fops)) { - adpt_exit(); + adpt_i2o_sys_shutdown(); return 0; } return hba_count; } -static int adpt_release(adpt_hba *pHba) +/* + * scsi_unregister will be called AFTER we return. + */ +static int adpt_release(struct Scsi_Host *host) { - struct Scsi_Host *shost = pHba->host; - scsi_remove_host(shost); + adpt_hba* pHba = (adpt_hba*) host->hostdata[0]; // adpt_i2o_quiesce_hba(pHba); adpt_i2o_delete_hba(pHba); - scsi_host_put(shost); + scsi_unregister(host); return 0; } @@ -881,7 +882,7 @@ static int adpt_reboot_event(struct notifier_block *n, ulong code, void *p) #endif -static int adpt_install_hba(struct pci_dev* pDev) +static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev) { adpt_hba* pHba = NULL; @@ -905,8 +906,7 @@ static int adpt_install_hba(struct pci_dev* pDev) } pci_set_master(pDev); - if (pci_set_dma_mask(pDev, DMA_64BIT_MASK) && - pci_set_dma_mask(pDev, DMA_32BIT_MASK)) + if (pci_set_dma_mask(pDev, DMA_32BIT_MASK)) return -EINVAL; base_addr0_phys = pci_resource_start(pDev,0); @@ -1028,6 +1028,8 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba) mutex_lock(&adpt_configuration_lock); + // scsi_unregister calls our adpt_release which + // does a quiese if(pHba->host){ free_irq(pHba->host->irq, pHba); } @@ -1079,6 +1081,17 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba) } +static int adpt_init(void) +{ + printk("Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n"); +#ifdef REBOOT_NOTIFIER + register_reboot_notifier(&adpt_reboot_notifier); +#endif + + return 0; +} + + static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u32 lun) { struct adpt_device* d; @@ -2164,6 +2177,37 @@ static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_d } +static s32 adpt_scsi_register(adpt_hba* pHba,struct scsi_host_template * sht) +{ + struct Scsi_Host *host = NULL; + + host = scsi_register(sht, sizeof(adpt_hba*)); + if (host == NULL) { + printk ("%s: scsi_register returned NULL\n",pHba->name); + return -1; + } + host->hostdata[0] = (unsigned long)pHba; + pHba->host = host; + + host->irq = pHba->pDev->irq; + /* no IO ports, so don't have to set host->io_port and + * host->n_io_port + */ + host->io_port = 0; + host->n_io_port = 0; + /* see comments in scsi_host.h */ + host->max_id = 16; + host->max_lun = 256; + host->max_channel = pHba->top_scsi_channel + 1; + host->cmd_per_lun = 1; + host->unique_id = (uint) pHba; + host->sg_tablesize = pHba->sg_tablesize; + host->can_queue = pHba->post_fifo_size; + + return 0; +} + + static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd) { adpt_hba* pHba; @@ -3279,10 +3323,12 @@ static static void adpt_delay(int millisec) #endif -static struct scsi_host_template adpt_template = { +static struct scsi_host_template driver_template = { .name = "dpt_i2o", .proc_name = "dpt_i2o", .proc_info = adpt_proc_info, + .detect = adpt_detect, + .release = adpt_release, .info = adpt_info, .queuecommand = adpt_queue, .eh_abort_handler = adpt_abort, @@ -3297,62 +3343,5 @@ static struct scsi_host_template adpt_template = { .use_clustering = ENABLE_CLUSTERING, .use_sg_chaining = ENABLE_SG_CHAINING, }; - -static s32 adpt_scsi_register(adpt_hba* pHba) -{ - struct Scsi_Host *host; - - host = scsi_host_alloc(&adpt_template, sizeof(adpt_hba*)); - if (host == NULL) { - printk ("%s: scsi_host_alloc returned NULL\n",pHba->name); - return -1; - } - host->hostdata[0] = (unsigned long)pHba; - pHba->host = host; - - host->irq = pHba->pDev->irq; - /* no IO ports, so don't have to set host->io_port and - * host->n_io_port - */ - host->io_port = 0; - host->n_io_port = 0; - /* see comments in scsi_host.h */ - host->max_id = 16; - host->max_lun = 256; - host->max_channel = pHba->top_scsi_channel + 1; - host->cmd_per_lun = 1; - host->unique_id = (uint) pHba; - host->sg_tablesize = pHba->sg_tablesize; - host->can_queue = pHba->post_fifo_size; - - if (scsi_add_host(host, &pHba->pDev->dev)) { - scsi_host_put(host); - return -1; - } - - return 0; -} - -static int __init adpt_init(void) -{ - int count; - - printk("Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n"); -#ifdef REBOOT_NOTIFIER - register_reboot_notifier(&adpt_reboot_notifier); -#endif - - count = adpt_detect(); - - return count > 0 ? 0 : -ENODEV; -} - -static void adpt_exit(void) -{ - while (hba_chain) - adpt_release(hba_chain); -} - -module_init(adpt_init); -module_exit(adpt_exit); +#include "scsi_module.c" MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h index 0892f6c7031..fd79068c586 100644 --- a/drivers/scsi/dpti.h +++ b/drivers/scsi/dpti.h @@ -28,9 +28,11 @@ * SCSI interface function Prototypes */ +static int adpt_detect(struct scsi_host_template * sht); static int adpt_queue(struct scsi_cmnd * cmd, void (*cmdcomplete) (struct scsi_cmnd *)); static int adpt_abort(struct scsi_cmnd * cmd); static int adpt_reset(struct scsi_cmnd* cmd); +static int adpt_release(struct Scsi_Host *host); static int adpt_slave_configure(struct scsi_device *); static const char *adpt_info(struct Scsi_Host *pSHost); @@ -47,6 +49,8 @@ static int adpt_device_reset(struct scsi_cmnd* cmd); #define DPT_DRIVER_NAME "Adaptec I2O RAID" +#ifndef HOSTS_C + #include "dpt/sys_info.h" #include <linux/wait.h> #include "dpt/dpti_i2o.h" @@ -285,7 +289,7 @@ static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba); static s32 adpt_i2o_hrt_get(adpt_hba* pHba); static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_device* dptdevice); static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd); -static s32 adpt_scsi_register(adpt_hba* pHba); +static s32 adpt_scsi_register(adpt_hba* pHba,struct scsi_host_template * sht); static s32 adpt_hba_reset(adpt_hba* pHba); static s32 adpt_i2o_reset_hba(adpt_hba* pHba); static s32 adpt_rescan(adpt_hba* pHba); @@ -295,7 +299,7 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba); static void adpt_inquiry(adpt_hba* pHba); static void adpt_fail_posted_scbs(adpt_hba* pHba); static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u32 lun); -static int adpt_install_hba(struct pci_dev* pDev) ; +static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev) ; static int adpt_i2o_online_hba(adpt_hba* pHba); static void adpt_i2o_post_wait_complete(u32, int); static int adpt_i2o_systab_send(adpt_hba* pHba); @@ -339,4 +343,5 @@ static void adpt_i386_info(sysInfo_S* si); #define FW_DEBUG_BLED_OFFSET 8 #define FW_DEBUG_FLAGS_NO_HEADERS_B 0x01 +#endif /* !HOSTS_C */ #endif /* _DPT_H */ diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index 2596165096d..c2677ba29c7 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -277,7 +277,8 @@ found: /* With interrupts enabled, it will sometimes hang when doing heavy * reads. So better not enable them until I finger it out. */ if (instance->irq != SCSI_IRQ_NONE) - if (request_irq(instance->irq, dtc_intr, IRQF_DISABLED, "dtc", instance)) { + if (request_irq(instance->irq, dtc_intr, IRQF_DISABLED, + "dtc", instance)) { printk(KERN_ERR "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); instance->irq = SCSI_IRQ_NONE; } @@ -459,7 +460,7 @@ static int dtc_release(struct Scsi_Host *shost) NCR5380_local_declare(); NCR5380_setup(shost); if (shost->irq) - free_irq(shost->irq, NULL); + free_irq(shost->irq, shost); NCR5380_exit(shost); if (shost->io_port && shost->n_io_port) release_region(shost->io_port, shost->n_io_port); diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c index 4ed3a529706..bfdee596889 100644 --- a/drivers/scsi/esp_scsi.c +++ b/drivers/scsi/esp_scsi.c @@ -2026,8 +2026,8 @@ static void esp_reset_cleanup(struct esp *esp) tp->flags |= ESP_TGT_CHECK_NEGO; if (tp->starget) - starget_for_each_device(tp->starget, NULL, - esp_clear_hold); + __starget_for_each_device(tp->starget, NULL, + esp_clear_hold); } esp->flags &= ~ESP_FLAG_RESETTING; } diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 607336f56d5..75585a52c88 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -460,7 +460,8 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt) instance->irq = NCR5380_probe_irq(instance, 0xffff); if (instance->irq != SCSI_IRQ_NONE) - if (request_irq(instance->irq, generic_NCR5380_intr, IRQF_DISABLED, "NCR5380", instance)) { + if (request_irq(instance->irq, generic_NCR5380_intr, + IRQF_DISABLED, "NCR5380", instance)) { printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); instance->irq = SCSI_IRQ_NONE; } @@ -513,7 +514,7 @@ int generic_NCR5380_release_resources(struct Scsi_Host *instance) NCR5380_setup(instance); if (instance->irq != SCSI_IRQ_NONE) - free_irq(instance->irq, NULL); + free_irq(instance->irq, instance); NCR5380_exit(instance); #ifndef CONFIG_SCSI_G_NCR5380_MEM diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 22d91ee173c..5f2396c0395 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -556,7 +556,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, unsigned long timeout) { u64 *crq_as_u64 = (u64 *) &evt_struct->crq; - int request_status; + int request_status = 0; int rc; /* If we have exhausted our request limit, just fail this request, @@ -574,6 +574,13 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, if (request_status < -1) goto send_error; /* Otherwise, we may have run out of requests. */ + /* If request limit was 0 when we started the adapter is in the + * process of performing a login with the server adapter, or + * we may have run out of requests. + */ + else if (request_status == -1 && + evt_struct->iu.srp.login_req.opcode != SRP_LOGIN_REQ) + goto send_busy; /* Abort and reset calls should make it through. * Nothing except abort and reset should use the last two * slots unless we had two or less to begin with. @@ -633,7 +640,8 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev); free_event_struct(&hostdata->pool, evt_struct); - atomic_inc(&hostdata->request_limit); + if (request_status != -1) + atomic_inc(&hostdata->request_limit); return SCSI_MLQUEUE_HOST_BUSY; send_error: @@ -927,10 +935,11 @@ static int send_srp_login(struct ibmvscsi_host_data *hostdata) login->req_buf_fmt = SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT; spin_lock_irqsave(hostdata->host->host_lock, flags); - /* Start out with a request limit of 1, since this is negotiated in - * the login request we are just sending + /* Start out with a request limit of 0, since this is negotiated in + * the login request we are just sending and login requests always + * get sent by the driver regardless of request_limit. */ - atomic_set(&hostdata->request_limit, 1); + atomic_set(&hostdata->request_limit, 0); rc = ibmvscsi_send_srp_event(evt_struct, hostdata, init_timeout * 2); spin_unlock_irqrestore(hostdata->host->host_lock, flags); diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 8d0244c2e7d..9706de9d98d 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -242,14 +242,9 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign } } -static void hexdump(u8 *x, int len) +static void ide_scsi_hex_dump(u8 *data, int len) { - int i; - - printk("[ "); - for (i = 0; i < len; i++) - printk("%x ", x[i]); - printk("]\n"); + print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1, data, len, 0); } static int idescsi_check_condition(ide_drive_t *drive, struct request *failed_command) @@ -282,7 +277,7 @@ 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); + ide_scsi_hex_dump(pc->c, 6); } rq->rq_disk = scsi->disk; return ide_do_drive_cmd(drive, rq, ide_preempt); @@ -337,7 +332,7 @@ 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); + ide_scsi_hex_dump(pc->buffer, 16); } memcpy((void *) opc->scsi_cmd->sense_buffer, pc->buffer, SCSI_SENSE_BUFFERSIZE); kfree(pc->buffer); @@ -816,10 +811,10 @@ 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); + ide_scsi_hex_dump(cmd->cmnd, cmd->cmd_len); 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); + ide_scsi_hex_dump(pc->c, 12); } } diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c index 4c4465d39a1..01bf0189367 100644 --- a/drivers/scsi/initio.c +++ b/drivers/scsi/initio.c @@ -2616,6 +2616,7 @@ static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * c scsi_for_each_sg(cmnd, sglist, cblk->sglen, i) { sg->data = cpu_to_le32((u32)sg_dma_address(sglist)); total_len += sg->len = cpu_to_le32((u32)sg_dma_len(sglist)); + ++sg; } cblk->buflen = (scsi_bufflen(cmnd) > total_len) ? @@ -2867,6 +2868,7 @@ static int initio_probe_one(struct pci_dev *pdev, } host = (struct initio_host *)shost->hostdata; memset(host, 0, sizeof(struct initio_host)); + host->addr = pci_resource_start(pdev, 0); if (!request_region(host->addr, 256, "i91u")) { printk(KERN_WARNING "initio: I/O port range 0x%x is busy.\n", host->addr); diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 4bcf916c21a..57ce2251abc 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -197,7 +197,7 @@ iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) if (unlikely(!sc)) return; - tcp_ctask->xmstate = XMSTATE_IDLE; + tcp_ctask->xmstate = XMSTATE_VALUE_IDLE; tcp_ctask->r2t = NULL; } @@ -409,7 +409,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) tcp_ctask->exp_datasn = r2tsn + 1; __kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*)); - tcp_ctask->xmstate |= XMSTATE_SOL_HDR_INIT; + set_bit(XMSTATE_BIT_SOL_HDR_INIT, &tcp_ctask->xmstate); list_move_tail(&ctask->running, &conn->xmitqueue); scsi_queue_work(session->host, &conn->xmitwork); @@ -1254,7 +1254,7 @@ static void iscsi_set_padding(struct iscsi_tcp_cmd_task *tcp_ctask, tcp_ctask->pad_count = ISCSI_PAD_LEN - tcp_ctask->pad_count; debug_scsi("write padding %d bytes\n", tcp_ctask->pad_count); - tcp_ctask->xmstate |= XMSTATE_W_PAD; + set_bit(XMSTATE_BIT_W_PAD, &tcp_ctask->xmstate); } /** @@ -1269,7 +1269,7 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask) struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; BUG_ON(__kfifo_len(tcp_ctask->r2tqueue)); - tcp_ctask->xmstate = XMSTATE_CMD_HDR_INIT; + tcp_ctask->xmstate = 1 << XMSTATE_BIT_CMD_HDR_INIT; } /** @@ -1283,10 +1283,10 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask) * xmit. * * Management xmit state machine consists of these states: - * XMSTATE_IMM_HDR_INIT - calculate digest of PDU Header - * XMSTATE_IMM_HDR - PDU Header xmit in progress - * XMSTATE_IMM_DATA - PDU Data xmit in progress - * XMSTATE_IDLE - management PDU is done + * XMSTATE_BIT_IMM_HDR_INIT - calculate digest of PDU Header + * XMSTATE_BIT_IMM_HDR - PDU Header xmit in progress + * XMSTATE_BIT_IMM_DATA - PDU Data xmit in progress + * XMSTATE_VALUE_IDLE - management PDU is done **/ static int iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) @@ -1297,12 +1297,12 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) debug_scsi("mtask deq [cid %d state %x itt 0x%x]\n", conn->id, tcp_mtask->xmstate, mtask->itt); - if (tcp_mtask->xmstate & XMSTATE_IMM_HDR_INIT) { + if (test_bit(XMSTATE_BIT_IMM_HDR_INIT, &tcp_mtask->xmstate)) { iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr, sizeof(struct iscsi_hdr)); if (mtask->data_count) { - tcp_mtask->xmstate |= XMSTATE_IMM_DATA; + set_bit(XMSTATE_BIT_IMM_DATA, &tcp_mtask->xmstate); iscsi_buf_init_iov(&tcp_mtask->sendbuf, (char*)mtask->data, mtask->data_count); @@ -1315,21 +1315,20 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) (u8*)tcp_mtask->hdrext); tcp_mtask->sent = 0; - tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR_INIT; - tcp_mtask->xmstate |= XMSTATE_IMM_HDR; + clear_bit(XMSTATE_BIT_IMM_HDR_INIT, &tcp_mtask->xmstate); + set_bit(XMSTATE_BIT_IMM_HDR, &tcp_mtask->xmstate); } - if (tcp_mtask->xmstate & XMSTATE_IMM_HDR) { + if (test_bit(XMSTATE_BIT_IMM_HDR, &tcp_mtask->xmstate)) { rc = iscsi_sendhdr(conn, &tcp_mtask->headbuf, mtask->data_count); if (rc) return rc; - tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR; + clear_bit(XMSTATE_BIT_IMM_HDR, &tcp_mtask->xmstate); } - if (tcp_mtask->xmstate & XMSTATE_IMM_DATA) { + if (test_and_clear_bit(XMSTATE_BIT_IMM_DATA, &tcp_mtask->xmstate)) { BUG_ON(!mtask->data_count); - tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA; /* FIXME: implement. * Virtual buffer could be spreaded across multiple pages... */ @@ -1339,13 +1338,13 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) rc = iscsi_sendpage(conn, &tcp_mtask->sendbuf, &mtask->data_count, &tcp_mtask->sent); if (rc) { - tcp_mtask->xmstate |= XMSTATE_IMM_DATA; + set_bit(XMSTATE_BIT_IMM_DATA, &tcp_mtask->xmstate); return rc; } } while (mtask->data_count); } - BUG_ON(tcp_mtask->xmstate != XMSTATE_IDLE); + BUG_ON(tcp_mtask->xmstate != XMSTATE_VALUE_IDLE); if (mtask->hdr->itt == RESERVED_ITT) { struct iscsi_session *session = conn->session; @@ -1365,7 +1364,7 @@ iscsi_send_cmd_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; int rc = 0; - if (tcp_ctask->xmstate & XMSTATE_CMD_HDR_INIT) { + if (test_bit(XMSTATE_BIT_CMD_HDR_INIT, &tcp_ctask->xmstate)) { tcp_ctask->sent = 0; tcp_ctask->sg_count = 0; tcp_ctask->exp_datasn = 0; @@ -1390,21 +1389,21 @@ iscsi_send_cmd_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) if (conn->hdrdgst_en) iscsi_hdr_digest(conn, &tcp_ctask->headbuf, (u8*)tcp_ctask->hdrext); - tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_INIT; - tcp_ctask->xmstate |= XMSTATE_CMD_HDR_XMIT; + clear_bit(XMSTATE_BIT_CMD_HDR_INIT, &tcp_ctask->xmstate); + set_bit(XMSTATE_BIT_CMD_HDR_XMIT, &tcp_ctask->xmstate); } - if (tcp_ctask->xmstate & XMSTATE_CMD_HDR_XMIT) { + if (test_bit(XMSTATE_BIT_CMD_HDR_XMIT, &tcp_ctask->xmstate)) { rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count); if (rc) return rc; - tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_XMIT; + clear_bit(XMSTATE_BIT_CMD_HDR_XMIT, &tcp_ctask->xmstate); if (sc->sc_data_direction != DMA_TO_DEVICE) return 0; if (ctask->imm_count) { - tcp_ctask->xmstate |= XMSTATE_IMM_DATA; + set_bit(XMSTATE_BIT_IMM_DATA, &tcp_ctask->xmstate); iscsi_set_padding(tcp_ctask, ctask->imm_count); if (ctask->conn->datadgst_en) { @@ -1414,9 +1413,10 @@ iscsi_send_cmd_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) } } - if (ctask->unsol_count) - tcp_ctask->xmstate |= - XMSTATE_UNS_HDR | XMSTATE_UNS_INIT; + if (ctask->unsol_count) { + set_bit(XMSTATE_BIT_UNS_HDR, &tcp_ctask->xmstate); + set_bit(XMSTATE_BIT_UNS_INIT, &tcp_ctask->xmstate); + } } return rc; } @@ -1428,25 +1428,25 @@ iscsi_send_padding(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) struct iscsi_tcp_conn *tcp_conn = conn->dd_data; int sent = 0, rc; - if (tcp_ctask->xmstate & XMSTATE_W_PAD) { + if (test_bit(XMSTATE_BIT_W_PAD, &tcp_ctask->xmstate)) { iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad, tcp_ctask->pad_count); if (conn->datadgst_en) crypto_hash_update(&tcp_conn->tx_hash, &tcp_ctask->sendbuf.sg, tcp_ctask->sendbuf.sg.length); - } else if (!(tcp_ctask->xmstate & XMSTATE_W_RESEND_PAD)) + } else if (!test_bit(XMSTATE_BIT_W_RESEND_PAD, &tcp_ctask->xmstate)) return 0; - tcp_ctask->xmstate &= ~XMSTATE_W_PAD; - tcp_ctask->xmstate &= ~XMSTATE_W_RESEND_PAD; + clear_bit(XMSTATE_BIT_W_PAD, &tcp_ctask->xmstate); + clear_bit(XMSTATE_BIT_W_RESEND_PAD, &tcp_ctask->xmstate); debug_scsi("sending %d pad bytes for itt 0x%x\n", tcp_ctask->pad_count, ctask->itt); rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count, &sent); if (rc) { debug_scsi("padding send failed %d\n", rc); - tcp_ctask->xmstate |= XMSTATE_W_RESEND_PAD; + set_bit(XMSTATE_BIT_W_RESEND_PAD, &tcp_ctask->xmstate); } return rc; } @@ -1465,11 +1465,11 @@ iscsi_send_digest(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, tcp_ctask = ctask->dd_data; tcp_conn = conn->dd_data; - if (!(tcp_ctask->xmstate & XMSTATE_W_RESEND_DATA_DIGEST)) { + if (!test_bit(XMSTATE_BIT_W_RESEND_DATA_DIGEST, &tcp_ctask->xmstate)) { crypto_hash_final(&tcp_conn->tx_hash, (u8*)digest); iscsi_buf_init_iov(buf, (char*)digest, 4); } - tcp_ctask->xmstate &= ~XMSTATE_W_RESEND_DATA_DIGEST; + clear_bit(XMSTATE_BIT_W_RESEND_DATA_DIGEST, &tcp_ctask->xmstate); rc = iscsi_sendpage(conn, buf, &tcp_ctask->digest_count, &sent); if (!rc) @@ -1478,7 +1478,7 @@ iscsi_send_digest(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, else { debug_scsi("sending digest 0x%x failed for itt 0x%x!\n", *digest, ctask->itt); - tcp_ctask->xmstate |= XMSTATE_W_RESEND_DATA_DIGEST; + set_bit(XMSTATE_BIT_W_RESEND_DATA_DIGEST, &tcp_ctask->xmstate); } return rc; } @@ -1526,8 +1526,8 @@ iscsi_send_unsol_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) struct iscsi_data_task *dtask; int rc; - tcp_ctask->xmstate |= XMSTATE_UNS_DATA; - if (tcp_ctask->xmstate & XMSTATE_UNS_INIT) { + set_bit(XMSTATE_BIT_UNS_DATA, &tcp_ctask->xmstate); + if (test_bit(XMSTATE_BIT_UNS_INIT, &tcp_ctask->xmstate)) { dtask = &tcp_ctask->unsol_dtask; iscsi_prep_unsolicit_data_pdu(ctask, &dtask->hdr); @@ -1537,14 +1537,14 @@ iscsi_send_unsol_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) iscsi_hdr_digest(conn, &tcp_ctask->headbuf, (u8*)dtask->hdrext); - tcp_ctask->xmstate &= ~XMSTATE_UNS_INIT; + clear_bit(XMSTATE_BIT_UNS_INIT, &tcp_ctask->xmstate); iscsi_set_padding(tcp_ctask, ctask->data_count); } rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->data_count); if (rc) { - tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA; - tcp_ctask->xmstate |= XMSTATE_UNS_HDR; + clear_bit(XMSTATE_BIT_UNS_DATA, &tcp_ctask->xmstate); + set_bit(XMSTATE_BIT_UNS_HDR, &tcp_ctask->xmstate); return rc; } @@ -1565,16 +1565,15 @@ iscsi_send_unsol_pdu(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; int rc; - if (tcp_ctask->xmstate & XMSTATE_UNS_HDR) { + if (test_and_clear_bit(XMSTATE_BIT_UNS_HDR, &tcp_ctask->xmstate)) { BUG_ON(!ctask->unsol_count); - tcp_ctask->xmstate &= ~XMSTATE_UNS_HDR; send_hdr: rc = iscsi_send_unsol_hdr(conn, ctask); if (rc) return rc; } - if (tcp_ctask->xmstate & XMSTATE_UNS_DATA) { + if (test_bit(XMSTATE_BIT_UNS_DATA, &tcp_ctask->xmstate)) { struct iscsi_data_task *dtask = &tcp_ctask->unsol_dtask; int start = tcp_ctask->sent; @@ -1584,14 +1583,14 @@ send_hdr: ctask->unsol_count -= tcp_ctask->sent - start; if (rc) return rc; - tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA; + clear_bit(XMSTATE_BIT_UNS_DATA, &tcp_ctask->xmstate); /* * Done with the Data-Out. Next, check if we need * to send another unsolicited Data-Out. */ if (ctask->unsol_count) { debug_scsi("sending more uns\n"); - tcp_ctask->xmstate |= XMSTATE_UNS_INIT; + set_bit(XMSTATE_BIT_UNS_INIT, &tcp_ctask->xmstate); goto send_hdr; } } @@ -1607,7 +1606,7 @@ static int iscsi_send_sol_pdu(struct iscsi_conn *conn, struct iscsi_data_task *dtask; int left, rc; - if (tcp_ctask->xmstate & XMSTATE_SOL_HDR_INIT) { + if (test_bit(XMSTATE_BIT_SOL_HDR_INIT, &tcp_ctask->xmstate)) { if (!tcp_ctask->r2t) { spin_lock_bh(&session->lock); __kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t, @@ -1621,19 +1620,19 @@ send_hdr: if (conn->hdrdgst_en) iscsi_hdr_digest(conn, &r2t->headbuf, (u8*)dtask->hdrext); - tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR_INIT; - tcp_ctask->xmstate |= XMSTATE_SOL_HDR; + clear_bit(XMSTATE_BIT_SOL_HDR_INIT, &tcp_ctask->xmstate); + set_bit(XMSTATE_BIT_SOL_HDR, &tcp_ctask->xmstate); } - if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) { + if (test_bit(XMSTATE_BIT_SOL_HDR, &tcp_ctask->xmstate)) { r2t = tcp_ctask->r2t; dtask = &r2t->dtask; rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count); if (rc) return rc; - tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR; - tcp_ctask->xmstate |= XMSTATE_SOL_DATA; + clear_bit(XMSTATE_BIT_SOL_HDR, &tcp_ctask->xmstate); + set_bit(XMSTATE_BIT_SOL_DATA, &tcp_ctask->xmstate); if (conn->datadgst_en) { iscsi_data_digest_init(conn->dd_data, tcp_ctask); @@ -1646,7 +1645,7 @@ send_hdr: r2t->sent); } - if (tcp_ctask->xmstate & XMSTATE_SOL_DATA) { + if (test_bit(XMSTATE_BIT_SOL_DATA, &tcp_ctask->xmstate)) { r2t = tcp_ctask->r2t; dtask = &r2t->dtask; @@ -1655,7 +1654,7 @@ send_hdr: &dtask->digestbuf, &dtask->digest); if (rc) return rc; - tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA; + clear_bit(XMSTATE_BIT_SOL_DATA, &tcp_ctask->xmstate); /* * Done with this Data-Out. Next, check if we have @@ -1700,32 +1699,32 @@ send_hdr: * xmit stages. * *iscsi_send_cmd_hdr() - * XMSTATE_CMD_HDR_INIT - prepare Header and Data buffers Calculate - * Header Digest - * XMSTATE_CMD_HDR_XMIT - Transmit header in progress + * XMSTATE_BIT_CMD_HDR_INIT - prepare Header and Data buffers Calculate + * Header Digest + * XMSTATE_BIT_CMD_HDR_XMIT - Transmit header in progress * *iscsi_send_padding - * XMSTATE_W_PAD - Prepare and send pading - * XMSTATE_W_RESEND_PAD - retry send pading + * XMSTATE_BIT_W_PAD - Prepare and send pading + * XMSTATE_BIT_W_RESEND_PAD - retry send pading * *iscsi_send_digest - * XMSTATE_W_RESEND_DATA_DIGEST - Finalize and send Data Digest - * XMSTATE_W_RESEND_DATA_DIGEST - retry sending digest + * XMSTATE_BIT_W_RESEND_DATA_DIGEST - Finalize and send Data Digest + * XMSTATE_BIT_W_RESEND_DATA_DIGEST - retry sending digest * *iscsi_send_unsol_hdr - * XMSTATE_UNS_INIT - prepare un-solicit data header and digest - * XMSTATE_UNS_HDR - send un-solicit header + * XMSTATE_BIT_UNS_INIT - prepare un-solicit data header and digest + * XMSTATE_BIT_UNS_HDR - send un-solicit header * *iscsi_send_unsol_pdu - * XMSTATE_UNS_DATA - send un-solicit data in progress + * XMSTATE_BIT_UNS_DATA - send un-solicit data in progress * *iscsi_send_sol_pdu - * XMSTATE_SOL_HDR_INIT - solicit data header and digest initialize - * XMSTATE_SOL_HDR - send solicit header - * XMSTATE_SOL_DATA - send solicit data + * XMSTATE_BIT_SOL_HDR_INIT - solicit data header and digest initialize + * XMSTATE_BIT_SOL_HDR - send solicit header + * XMSTATE_BIT_SOL_DATA - send solicit data * *iscsi_tcp_ctask_xmit - * XMSTATE_IMM_DATA - xmit managment data (??) + * XMSTATE_BIT_IMM_DATA - xmit managment data (??) **/ static int iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) @@ -1742,13 +1741,13 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) if (ctask->sc->sc_data_direction != DMA_TO_DEVICE) return 0; - if (tcp_ctask->xmstate & XMSTATE_IMM_DATA) { + if (test_bit(XMSTATE_BIT_IMM_DATA, &tcp_ctask->xmstate)) { rc = iscsi_send_data(ctask, &tcp_ctask->sendbuf, &tcp_ctask->sg, &tcp_ctask->sent, &ctask->imm_count, &tcp_ctask->immbuf, &tcp_ctask->immdigest); if (rc) return rc; - tcp_ctask->xmstate &= ~XMSTATE_IMM_DATA; + clear_bit(XMSTATE_BIT_IMM_DATA, &tcp_ctask->xmstate); } rc = iscsi_send_unsol_pdu(conn, ctask); @@ -1981,7 +1980,7 @@ static void iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) { struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data; - tcp_mtask->xmstate = XMSTATE_IMM_HDR_INIT; + tcp_mtask->xmstate = 1 << XMSTATE_BIT_IMM_HDR_INIT; } static int diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h index 7eba44df0a7..68c36cc8997 100644 --- a/drivers/scsi/iscsi_tcp.h +++ b/drivers/scsi/iscsi_tcp.h @@ -32,21 +32,21 @@ #define IN_PROGRESS_PAD_RECV 0x4 /* xmit state machine */ -#define XMSTATE_IDLE 0x0 -#define XMSTATE_CMD_HDR_INIT 0x1 -#define XMSTATE_CMD_HDR_XMIT 0x2 -#define XMSTATE_IMM_HDR 0x4 -#define XMSTATE_IMM_DATA 0x8 -#define XMSTATE_UNS_INIT 0x10 -#define XMSTATE_UNS_HDR 0x20 -#define XMSTATE_UNS_DATA 0x40 -#define XMSTATE_SOL_HDR 0x80 -#define XMSTATE_SOL_DATA 0x100 -#define XMSTATE_W_PAD 0x200 -#define XMSTATE_W_RESEND_PAD 0x400 -#define XMSTATE_W_RESEND_DATA_DIGEST 0x800 -#define XMSTATE_IMM_HDR_INIT 0x1000 -#define XMSTATE_SOL_HDR_INIT 0x2000 +#define XMSTATE_VALUE_IDLE 0 +#define XMSTATE_BIT_CMD_HDR_INIT 0 +#define XMSTATE_BIT_CMD_HDR_XMIT 1 +#define XMSTATE_BIT_IMM_HDR 2 +#define XMSTATE_BIT_IMM_DATA 3 +#define XMSTATE_BIT_UNS_INIT 4 +#define XMSTATE_BIT_UNS_HDR 5 +#define XMSTATE_BIT_UNS_DATA 6 +#define XMSTATE_BIT_SOL_HDR 7 +#define XMSTATE_BIT_SOL_DATA 8 +#define XMSTATE_BIT_W_PAD 9 +#define XMSTATE_BIT_W_RESEND_PAD 10 +#define XMSTATE_BIT_W_RESEND_DATA_DIGEST 11 +#define XMSTATE_BIT_IMM_HDR_INIT 12 +#define XMSTATE_BIT_SOL_HDR_INIT 13 #define ISCSI_PAD_LEN 4 #define ISCSI_SG_TABLESIZE SG_ALL @@ -122,7 +122,7 @@ struct iscsi_data_task { struct iscsi_tcp_mgmt_task { struct iscsi_hdr hdr; char hdrext[sizeof(__u32)]; /* Header-Digest */ - int xmstate; /* mgmt xmit progress */ + unsigned long xmstate; /* mgmt xmit progress */ struct iscsi_buf headbuf; /* header buffer */ struct iscsi_buf sendbuf; /* in progress buffer */ int sent; @@ -150,7 +150,7 @@ struct iscsi_tcp_cmd_task { int pad_count; /* padded bytes */ struct iscsi_buf headbuf; /* header buf (xmit) */ struct iscsi_buf sendbuf; /* in progress buffer*/ - int xmstate; /* xmit xtate machine */ + unsigned long xmstate; /* xmit xtate machine */ int sent; struct scatterlist *sg; /* per-cmd SG list */ struct scatterlist *bad_sg; /* assert statement */ diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index efceed451b4..8b57af5baae 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -291,9 +291,6 @@ invalid_datalen: min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE)); } - if (sc->sc_data_direction == DMA_TO_DEVICE) - goto out; - if (rhdr->flags & ISCSI_FLAG_CMD_UNDERFLOW) { int res_count = be32_to_cpu(rhdr->residual_count); diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index c0755565fae..4e46045dea6 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -682,6 +682,7 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb; struct lpfc_iocbq *piocbq = &(lpfc_cmd->cur_iocbq); int datadir = scsi_cmnd->sc_data_direction; + char tag[2]; lpfc_cmd->fcp_rsp->rspSnsLen = 0; /* clear task management bits */ @@ -692,8 +693,8 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, memcpy(&fcp_cmnd->fcpCdb[0], scsi_cmnd->cmnd, 16); - if (scsi_cmnd->device->tagged_supported) { - switch (scsi_cmnd->tag) { + if (scsi_populate_tag_msg(scsi_cmnd, tag)) { + switch (tag[0]) { case HEAD_OF_QUEUE_TAG: fcp_cmnd->fcpCntl1 = HEAD_OF_Q; break; diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index abe2bda6ac3..3b09ab21d70 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -303,7 +303,7 @@ int macscsi_detect(struct scsi_host_template * tpnt) if (instance->irq != SCSI_IRQ_NONE) if (request_irq(instance->irq, NCR5380_intr, IRQ_FLG_SLOW, - "ncr5380", instance)) { + "ncr5380", instance)) { printk(KERN_WARNING "scsi%d: IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); instance->irq = SCSI_IRQ_NONE; @@ -326,7 +326,7 @@ int macscsi_detect(struct scsi_host_template * tpnt) int macscsi_release (struct Scsi_Host *shpnt) { if (shpnt->irq != SCSI_IRQ_NONE) - free_irq (shpnt->irq, NCR5380_intr); + free_irq(shpnt->irq, shpnt); NCR5380_exit(shpnt); return 0; diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 4652ad22516..abef7048f25 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -593,10 +593,11 @@ static int osst_verify_frame(struct osst_tape * STp, int frame_seq_number, int q if (aux->frame_type != OS_FRAME_TYPE_DATA && aux->frame_type != OS_FRAME_TYPE_EOD && aux->frame_type != OS_FRAME_TYPE_MARKER) { - if (!quiet) + if (!quiet) { #if DEBUG printk(OSST_DEB_MSG "%s:D: Skipping frame, frame type %x\n", name, aux->frame_type); #endif + } goto err_out; } if (aux->frame_type == OS_FRAME_TYPE_EOD && @@ -606,11 +607,12 @@ static int osst_verify_frame(struct osst_tape * STp, int frame_seq_number, int q goto err_out; } if (frame_seq_number != -1 && ntohl(aux->frame_seq_num) != frame_seq_number) { - if (!quiet) + if (!quiet) { #if DEBUG printk(OSST_DEB_MSG "%s:D: Skipping frame, sequence number %u (expected %d)\n", name, ntohl(aux->frame_seq_num), frame_seq_number); #endif + } goto err_out; } if (aux->frame_type == OS_FRAME_TYPE_MARKER) { diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index ee596565997..f2018b46f49 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -453,7 +453,8 @@ int __init pas16_detect(struct scsi_host_template * tpnt) instance->irq = NCR5380_probe_irq(instance, PAS16_IRQS); if (instance->irq != SCSI_IRQ_NONE) - if (request_irq(instance->irq, pas16_intr, IRQF_DISABLED, "pas16", instance)) { + if (request_irq(instance->irq, pas16_intr, IRQF_DISABLED, + "pas16", instance)) { printk("scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); instance->irq = SCSI_IRQ_NONE; @@ -604,7 +605,7 @@ static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src static int pas16_release(struct Scsi_Host *shost) { if (shost->irq) - free_irq(shost->irq, NULL); + free_irq(shost->irq, shost); NCR5380_exit(shost); if (shost->dma_channel != 0xff) free_dma(shost->dma_channel); diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 3aeb68bcb7a..28864075609 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -1310,14 +1310,7 @@ qla1280_done(struct scsi_qla_host *ha) } /* Release memory used for this I/O */ - if (cmd->use_sg) { - pci_unmap_sg(ha->pdev, cmd->request_buffer, - cmd->use_sg, cmd->sc_data_direction); - } else if (cmd->request_bufflen) { - pci_unmap_single(ha->pdev, sp->saved_dma_handle, - cmd->request_bufflen, - cmd->sc_data_direction); - } + scsi_dma_unmap(cmd); /* Call the mid-level driver interrupt handler */ CMD_HANDLE(sp->cmd) = (unsigned char *)INVALID_HANDLE; @@ -1406,14 +1399,14 @@ qla1280_return_status(struct response * sts, struct scsi_cmnd *cp) break; case CS_DATA_UNDERRUN: - if ((cp->request_bufflen - residual_length) < + if ((scsi_bufflen(cp) - residual_length) < cp->underflow) { printk(KERN_WARNING "scsi: Underflow detected - retrying " "command.\n"); host_status = DID_ERROR; } else { - cp->resid = residual_length; + scsi_set_resid(cp, residual_length); host_status = DID_OK; } break; @@ -2775,33 +2768,28 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) struct device_reg __iomem *reg = ha->iobase; struct scsi_cmnd *cmd = sp->cmd; cmd_a64_entry_t *pkt; - struct scatterlist *sg = NULL, *s; __le32 *dword_ptr; dma_addr_t dma_handle; int status = 0; int cnt; int req_cnt; - u16 seg_cnt; + int seg_cnt; u8 dir; ENTER("qla1280_64bit_start_scsi:"); /* Calculate number of entries and segments required. */ req_cnt = 1; - if (cmd->use_sg) { - sg = (struct scatterlist *) cmd->request_buffer; - seg_cnt = pci_map_sg(ha->pdev, sg, cmd->use_sg, - cmd->sc_data_direction); - + seg_cnt = scsi_dma_map(cmd); + if (seg_cnt > 0) { if (seg_cnt > 2) { req_cnt += (seg_cnt - 2) / 5; if ((seg_cnt - 2) % 5) req_cnt++; } - } else if (cmd->request_bufflen) { /* If data transfer. */ - seg_cnt = 1; - } else { - seg_cnt = 0; + } else if (seg_cnt < 0) { + status = 1; + goto out; } if ((req_cnt + 2) >= ha->req_q_cnt) { @@ -2889,124 +2877,104 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) * Load data segments. */ if (seg_cnt) { /* If data transfer. */ + struct scatterlist *sg, *s; int remseg = seg_cnt; + + sg = scsi_sglist(cmd); + /* Setup packet address segment pointer. */ dword_ptr = (u32 *)&pkt->dseg_0_address; - if (cmd->use_sg) { /* If scatter gather */ - /* Load command entry data segments. */ - for_each_sg(sg, s, seg_cnt, cnt) { - if (cnt == 2) + /* Load command entry data segments. */ + for_each_sg(sg, s, seg_cnt, cnt) { + if (cnt == 2) + break; + + dma_handle = sg_dma_address(s); +#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) + if (ha->flags.use_pci_vchannel) + sn_pci_set_vchan(ha->pdev, + (unsigned long *)&dma_handle, + SCSI_BUS_32(cmd)); +#endif + *dword_ptr++ = + cpu_to_le32(pci_dma_lo32(dma_handle)); + *dword_ptr++ = + cpu_to_le32(pci_dma_hi32(dma_handle)); + *dword_ptr++ = cpu_to_le32(sg_dma_len(s)); + dprintk(3, "S/G Segment phys_addr=%x %x, len=0x%x\n", + cpu_to_le32(pci_dma_hi32(dma_handle)), + cpu_to_le32(pci_dma_lo32(dma_handle)), + cpu_to_le32(sg_dma_len(sg_next(s)))); + remseg--; + } + dprintk(5, "qla1280_64bit_start_scsi: Scatter/gather " + "command packet data - b %i, t %i, l %i \n", + SCSI_BUS_32(cmd), SCSI_TCN_32(cmd), + SCSI_LUN_32(cmd)); + qla1280_dump_buffer(5, (char *)pkt, + REQUEST_ENTRY_SIZE); + + /* + * Build continuation packets. + */ + dprintk(3, "S/G Building Continuation...seg_cnt=0x%x " + "remains\n", seg_cnt); + + while (remseg > 0) { + /* Update sg start */ + sg = s; + /* Adjust ring index. */ + ha->req_ring_index++; + if (ha->req_ring_index == REQUEST_ENTRY_CNT) { + ha->req_ring_index = 0; + ha->request_ring_ptr = + ha->request_ring; + } else + ha->request_ring_ptr++; + + pkt = (cmd_a64_entry_t *)ha->request_ring_ptr; + + /* Zero out packet. */ + memset(pkt, 0, REQUEST_ENTRY_SIZE); + + /* Load packet defaults. */ + ((struct cont_a64_entry *) pkt)->entry_type = + CONTINUE_A64_TYPE; + ((struct cont_a64_entry *) pkt)->entry_count = 1; + ((struct cont_a64_entry *) pkt)->sys_define = + (uint8_t)ha->req_ring_index; + /* Setup packet address segment pointer. */ + dword_ptr = + (u32 *)&((struct cont_a64_entry *) pkt)->dseg_0_address; + + /* Load continuation entry data segments. */ + for_each_sg(sg, s, remseg, cnt) { + if (cnt == 5) break; dma_handle = sg_dma_address(s); #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) if (ha->flags.use_pci_vchannel) sn_pci_set_vchan(ha->pdev, - (unsigned long *)&dma_handle, + (unsigned long *)&dma_handle, SCSI_BUS_32(cmd)); #endif *dword_ptr++ = cpu_to_le32(pci_dma_lo32(dma_handle)); *dword_ptr++ = cpu_to_le32(pci_dma_hi32(dma_handle)); - *dword_ptr++ = cpu_to_le32(sg_dma_len(s)); - dprintk(3, "S/G Segment phys_addr=%x %x, len=0x%x\n", + *dword_ptr++ = + cpu_to_le32(sg_dma_len(s)); + dprintk(3, "S/G Segment Cont. phys_addr=%x %x, len=0x%x\n", cpu_to_le32(pci_dma_hi32(dma_handle)), cpu_to_le32(pci_dma_lo32(dma_handle)), - cpu_to_le32(sg_dma_len(sg_next(s)))); - remseg--; + cpu_to_le32(sg_dma_len(s))); } - dprintk(5, "qla1280_64bit_start_scsi: Scatter/gather " - "command packet data - b %i, t %i, l %i \n", - SCSI_BUS_32(cmd), SCSI_TCN_32(cmd), - SCSI_LUN_32(cmd)); - qla1280_dump_buffer(5, (char *)pkt, - REQUEST_ENTRY_SIZE); - - /* - * Build continuation packets. - */ - dprintk(3, "S/G Building Continuation...seg_cnt=0x%x " - "remains\n", seg_cnt); - - while (remseg > 0) { - /* Update sg start */ - sg = s; - /* Adjust ring index. */ - ha->req_ring_index++; - if (ha->req_ring_index == REQUEST_ENTRY_CNT) { - ha->req_ring_index = 0; - ha->request_ring_ptr = - ha->request_ring; - } else - ha->request_ring_ptr++; - - pkt = (cmd_a64_entry_t *)ha->request_ring_ptr; - - /* Zero out packet. */ - memset(pkt, 0, REQUEST_ENTRY_SIZE); - - /* Load packet defaults. */ - ((struct cont_a64_entry *) pkt)->entry_type = - CONTINUE_A64_TYPE; - ((struct cont_a64_entry *) pkt)->entry_count = 1; - ((struct cont_a64_entry *) pkt)->sys_define = - (uint8_t)ha->req_ring_index; - /* Setup packet address segment pointer. */ - dword_ptr = - (u32 *)&((struct cont_a64_entry *) pkt)->dseg_0_address; - - /* Load continuation entry data segments. */ - for_each_sg(sg, s, remseg, cnt) { - if (cnt == 5) - break; - dma_handle = sg_dma_address(s); -#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) - if (ha->flags.use_pci_vchannel) - sn_pci_set_vchan(ha->pdev, - (unsigned long *)&dma_handle, - SCSI_BUS_32(cmd)); -#endif - *dword_ptr++ = - cpu_to_le32(pci_dma_lo32(dma_handle)); - *dword_ptr++ = - cpu_to_le32(pci_dma_hi32(dma_handle)); - *dword_ptr++ = - cpu_to_le32(sg_dma_len(s)); - dprintk(3, "S/G Segment Cont. phys_addr=%x %x, len=0x%x\n", - cpu_to_le32(pci_dma_hi32(dma_handle)), - cpu_to_le32(pci_dma_lo32(dma_handle)), - cpu_to_le32(sg_dma_len(s))); - } - remseg -= cnt; - dprintk(5, "qla1280_64bit_start_scsi: " - "continuation packet data - b %i, t " - "%i, l %i \n", SCSI_BUS_32(cmd), - SCSI_TCN_32(cmd), SCSI_LUN_32(cmd)); - qla1280_dump_buffer(5, (char *)pkt, - REQUEST_ENTRY_SIZE); - } - } else { /* No scatter gather data transfer */ - dma_handle = pci_map_single(ha->pdev, - cmd->request_buffer, - cmd->request_bufflen, - cmd->sc_data_direction); - - sp->saved_dma_handle = dma_handle; -#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) - if (ha->flags.use_pci_vchannel) - sn_pci_set_vchan(ha->pdev, - (unsigned long *)&dma_handle, - SCSI_BUS_32(cmd)); -#endif - *dword_ptr++ = cpu_to_le32(pci_dma_lo32(dma_handle)); - *dword_ptr++ = cpu_to_le32(pci_dma_hi32(dma_handle)); - *dword_ptr = cpu_to_le32(cmd->request_bufflen); - - dprintk(5, "qla1280_64bit_start_scsi: No scatter/" - "gather command packet data - b %i, t %i, " - "l %i \n", SCSI_BUS_32(cmd), SCSI_TCN_32(cmd), - SCSI_LUN_32(cmd)); + remseg -= cnt; + dprintk(5, "qla1280_64bit_start_scsi: " + "continuation packet data - b %i, t " + "%i, l %i \n", SCSI_BUS_32(cmd), + SCSI_TCN_32(cmd), SCSI_LUN_32(cmd)); qla1280_dump_buffer(5, (char *)pkt, REQUEST_ENTRY_SIZE); } @@ -3068,13 +3036,11 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) struct device_reg __iomem *reg = ha->iobase; struct scsi_cmnd *cmd = sp->cmd; struct cmd_entry *pkt; - struct scatterlist *sg = NULL, *s; __le32 *dword_ptr; int status = 0; int cnt; int req_cnt; - uint16_t seg_cnt; - dma_addr_t dma_handle; + int seg_cnt; u8 dir; ENTER("qla1280_32bit_start_scsi"); @@ -3084,17 +3050,8 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) /* Calculate number of entries and segments required. */ req_cnt = 1; - if (cmd->use_sg) { - /* - * We must build an SG list in adapter format, as the kernel's - * SG list cannot be used directly because of data field size - * (__alpha__) differences and the kernel SG list uses virtual - * addresses where we need physical addresses. - */ - sg = (struct scatterlist *) cmd->request_buffer; - seg_cnt = pci_map_sg(ha->pdev, sg, cmd->use_sg, - cmd->sc_data_direction); - + seg_cnt = scsi_dma_map(cmd); + if (seg_cnt) { /* * if greater than four sg entries then we need to allocate * continuation entries @@ -3106,14 +3063,9 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) } dprintk(3, "S/G Transfer cmd=%p seg_cnt=0x%x, req_cnt=%x\n", cmd, seg_cnt, req_cnt); - } else if (cmd->request_bufflen) { /* If data transfer. */ - dprintk(3, "No S/G transfer t=%x cmd=%p len=%x CDB=%x\n", - SCSI_TCN_32(cmd), cmd, cmd->request_bufflen, - cmd->cmnd[0]); - seg_cnt = 1; - } else { - /* dprintk(1, "No data transfer \n"); */ - seg_cnt = 0; + } else if (seg_cnt < 0) { + status = 1; + goto out; } if ((req_cnt + 2) >= ha->req_q_cnt) { @@ -3194,91 +3146,84 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) * Load data segments. */ if (seg_cnt) { + struct scatterlist *sg, *s; int remseg = seg_cnt; + + sg = scsi_sglist(cmd); + /* Setup packet address segment pointer. */ dword_ptr = &pkt->dseg_0_address; - if (cmd->use_sg) { /* If scatter gather */ - dprintk(3, "Building S/G data segments..\n"); - qla1280_dump_buffer(1, (char *)sg, 4 * 16); + dprintk(3, "Building S/G data segments..\n"); + qla1280_dump_buffer(1, (char *)sg, 4 * 16); + + /* Load command entry data segments. */ + for_each_sg(sg, s, seg_cnt, cnt) { + if (cnt == 4) + break; + *dword_ptr++ = + cpu_to_le32(pci_dma_lo32(sg_dma_address(s))); + *dword_ptr++ = cpu_to_le32(sg_dma_len(s)); + dprintk(3, "S/G Segment phys_addr=0x%lx, len=0x%x\n", + (pci_dma_lo32(sg_dma_address(s))), + (sg_dma_len(s))); + remseg--; + } + /* + * Build continuation packets. + */ + dprintk(3, "S/G Building Continuation" + "...seg_cnt=0x%x remains\n", seg_cnt); + while (remseg > 0) { + /* Continue from end point */ + sg = s; + /* Adjust ring index. */ + ha->req_ring_index++; + if (ha->req_ring_index == REQUEST_ENTRY_CNT) { + ha->req_ring_index = 0; + ha->request_ring_ptr = + ha->request_ring; + } else + ha->request_ring_ptr++; + + pkt = (struct cmd_entry *)ha->request_ring_ptr; + + /* Zero out packet. */ + memset(pkt, 0, REQUEST_ENTRY_SIZE); + + /* Load packet defaults. */ + ((struct cont_entry *) pkt)-> + entry_type = CONTINUE_TYPE; + ((struct cont_entry *) pkt)->entry_count = 1; - /* Load command entry data segments. */ - for_each_sg(sg, s, seg_cnt, cnt) { - if (cnt == 4) + ((struct cont_entry *) pkt)->sys_define = + (uint8_t) ha->req_ring_index; + + /* Setup packet address segment pointer. */ + dword_ptr = + &((struct cont_entry *) pkt)->dseg_0_address; + + /* Load continuation entry data segments. */ + for_each_sg(sg, s, remseg, cnt) { + if (cnt == 7) break; *dword_ptr++ = cpu_to_le32(pci_dma_lo32(sg_dma_address(s))); - *dword_ptr++ = cpu_to_le32(sg_dma_len(s)); - dprintk(3, "S/G Segment phys_addr=0x%lx, len=0x%x\n", - (pci_dma_lo32(sg_dma_address(s))), - (sg_dma_len(s))); - remseg--; - } - /* - * Build continuation packets. - */ - dprintk(3, "S/G Building Continuation" - "...seg_cnt=0x%x remains\n", seg_cnt); - while (remseg > 0) { - /* Continue from end point */ - sg = s; - /* Adjust ring index. */ - ha->req_ring_index++; - if (ha->req_ring_index == REQUEST_ENTRY_CNT) { - ha->req_ring_index = 0; - ha->request_ring_ptr = - ha->request_ring; - } else - ha->request_ring_ptr++; - - pkt = (struct cmd_entry *)ha->request_ring_ptr; - - /* Zero out packet. */ - memset(pkt, 0, REQUEST_ENTRY_SIZE); - - /* Load packet defaults. */ - ((struct cont_entry *) pkt)-> - entry_type = CONTINUE_TYPE; - ((struct cont_entry *) pkt)->entry_count = 1; - - ((struct cont_entry *) pkt)->sys_define = - (uint8_t) ha->req_ring_index; - - /* Setup packet address segment pointer. */ - dword_ptr = - &((struct cont_entry *) pkt)->dseg_0_address; - - /* Load continuation entry data segments. */ - for_each_sg(sg, s, remseg, cnt) { - if (cnt == 7) - break; - *dword_ptr++ = - cpu_to_le32(pci_dma_lo32(sg_dma_address(s))); - *dword_ptr++ = - cpu_to_le32(sg_dma_len(s)); - dprintk(1, - "S/G Segment Cont. phys_addr=0x%x, " - "len=0x%x\n", - cpu_to_le32(pci_dma_lo32(sg_dma_address(s))), - cpu_to_le32(sg_dma_len(s))); - } - remseg -= cnt; - dprintk(5, "qla1280_32bit_start_scsi: " - "continuation packet data - " - "scsi(%i:%i:%i)\n", SCSI_BUS_32(cmd), - SCSI_TCN_32(cmd), SCSI_LUN_32(cmd)); - qla1280_dump_buffer(5, (char *)pkt, - REQUEST_ENTRY_SIZE); + *dword_ptr++ = + cpu_to_le32(sg_dma_len(s)); + dprintk(1, + "S/G Segment Cont. phys_addr=0x%x, " + "len=0x%x\n", + cpu_to_le32(pci_dma_lo32(sg_dma_address(s))), + cpu_to_le32(sg_dma_len(s))); } - } else { /* No S/G data transfer */ - dma_handle = pci_map_single(ha->pdev, - cmd->request_buffer, - cmd->request_bufflen, - cmd->sc_data_direction); - sp->saved_dma_handle = dma_handle; - - *dword_ptr++ = cpu_to_le32(pci_dma_lo32(dma_handle)); - *dword_ptr = cpu_to_le32(cmd->request_bufflen); + remseg -= cnt; + dprintk(5, "qla1280_32bit_start_scsi: " + "continuation packet data - " + "scsi(%i:%i:%i)\n", SCSI_BUS_32(cmd), + SCSI_TCN_32(cmd), SCSI_LUN_32(cmd)); + qla1280_dump_buffer(5, (char *)pkt, + REQUEST_ENTRY_SIZE); } } else { /* No data transfer at all */ dprintk(5, "qla1280_32bit_start_scsi: No data, command " @@ -4086,9 +4031,9 @@ __qla1280_print_scsi_cmd(struct scsi_cmnd *cmd) for (i = 0; i < cmd->cmd_len; i++) { printk("0x%02x ", cmd->cmnd[i]); } - printk(" seg_cnt =%d\n", cmd->use_sg); + printk(" seg_cnt =%d\n", scsi_sg_count(cmd)); printk(" request buffer=0x%p, request buffer len=0x%x\n", - cmd->request_buffer, cmd->request_bufflen); + scsi_sglist(cmd), scsi_bufflen(cmd)); /* if (cmd->use_sg) { sg = (struct scatterlist *) cmd->request_buffer; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index a5bcf1f390b..8ecc0470b8f 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1831,7 +1831,7 @@ probe_out: return ret; } -static void __devexit +static void qla2x00_remove_one(struct pci_dev *pdev) { scsi_qla_host_t *ha; @@ -2965,7 +2965,7 @@ static struct pci_driver qla2xxx_pci_driver = { }, .id_table = qla2xxx_pci_tbl, .probe = qla2x00_probe_one, - .remove = __devexit_p(qla2x00_remove_one), + .remove = qla2x00_remove_one, .err_handler = &qla2xxx_err_handler, }; diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 19294882245..0fb1709ce5e 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -896,11 +896,11 @@ EXPORT_SYMBOL(__scsi_iterate_devices); * starget_for_each_device - helper to walk all devices of a target * @starget: target whose devices we want to iterate over. * - * This traverses over each devices of @shost. The devices have + * This traverses over each device of @starget. The devices have * a reference that must be released by scsi_host_put when breaking * out of the loop. */ -void starget_for_each_device(struct scsi_target *starget, void * data, +void starget_for_each_device(struct scsi_target *starget, void *data, void (*fn)(struct scsi_device *, void *)) { struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); @@ -915,6 +915,33 @@ void starget_for_each_device(struct scsi_target *starget, void * data, EXPORT_SYMBOL(starget_for_each_device); /** + * __starget_for_each_device - helper to walk all devices of a target + * (UNLOCKED) + * @starget: target whose devices we want to iterate over. + * + * This traverses over each device of @starget. It does _not_ + * take a reference on the scsi_device, so the whole loop must be + * protected by shost->host_lock. + * + * Note: The only reason why drivers would want to use this is because + * they need to access the device list in irq context. Otherwise you + * really want to use starget_for_each_device instead. + **/ +void __starget_for_each_device(struct scsi_target *starget, void *data, + void (*fn)(struct scsi_device *, void *)) +{ + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct scsi_device *sdev; + + __shost_for_each_device(sdev, shost) { + if ((sdev->channel == starget->channel) && + (sdev->id == starget->id)) + fn(sdev, data); + } +} +EXPORT_SYMBOL(__starget_for_each_device); + +/** * __scsi_device_lookup_by_target - find a device given the target (UNLOCKED) * @starget: SCSI target pointer * @lun: SCSI Logical Unit Number diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 61fdaf02f25..a9ac5b1b166 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -785,7 +785,7 @@ struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask) * end-of-list */ if (!left) - sg_mark_end(sgl, this); + sg_mark_end(&sgl[this - 1]); /* * don't allow subsequent mempool allocs to sleep, it would @@ -1332,7 +1332,7 @@ int scsi_prep_return(struct request_queue *q, struct request *req, int ret) } EXPORT_SYMBOL(scsi_prep_return); -static int scsi_prep_fn(struct request_queue *q, struct request *req) +int scsi_prep_fn(struct request_queue *q, struct request *req) { struct scsi_device *sdev = q->queuedata; int ret = BLKPREP_KILL; @@ -2115,6 +2115,142 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state) EXPORT_SYMBOL(scsi_device_set_state); /** + * sdev_evt_emit - emit a single SCSI device uevent + * @sdev: associated SCSI device + * @evt: event to emit + * + * Send a single uevent (scsi_event) to the associated scsi_device. + */ +static void scsi_evt_emit(struct scsi_device *sdev, struct scsi_event *evt) +{ + int idx = 0; + char *envp[3]; + + switch (evt->evt_type) { + case SDEV_EVT_MEDIA_CHANGE: + envp[idx++] = "SDEV_MEDIA_CHANGE=1"; + break; + + default: + /* do nothing */ + break; + } + + envp[idx++] = NULL; + + kobject_uevent_env(&sdev->sdev_gendev.kobj, KOBJ_CHANGE, envp); +} + +/** + * sdev_evt_thread - send a uevent for each scsi event + * @work: work struct for scsi_device + * + * Dispatch queued events to their associated scsi_device kobjects + * as uevents. + */ +void scsi_evt_thread(struct work_struct *work) +{ + struct scsi_device *sdev; + LIST_HEAD(event_list); + + sdev = container_of(work, struct scsi_device, event_work); + + while (1) { + struct scsi_event *evt; + struct list_head *this, *tmp; + unsigned long flags; + + spin_lock_irqsave(&sdev->list_lock, flags); + list_splice_init(&sdev->event_list, &event_list); + spin_unlock_irqrestore(&sdev->list_lock, flags); + + if (list_empty(&event_list)) + break; + + list_for_each_safe(this, tmp, &event_list) { + evt = list_entry(this, struct scsi_event, node); + list_del(&evt->node); + scsi_evt_emit(sdev, evt); + kfree(evt); + } + } +} + +/** + * sdev_evt_send - send asserted event to uevent thread + * @sdev: scsi_device event occurred on + * @evt: event to send + * + * Assert scsi device event asynchronously. + */ +void sdev_evt_send(struct scsi_device *sdev, struct scsi_event *evt) +{ + unsigned long flags; + + if (!test_bit(evt->evt_type, sdev->supported_events)) { + kfree(evt); + return; + } + + spin_lock_irqsave(&sdev->list_lock, flags); + list_add_tail(&evt->node, &sdev->event_list); + schedule_work(&sdev->event_work); + spin_unlock_irqrestore(&sdev->list_lock, flags); +} +EXPORT_SYMBOL_GPL(sdev_evt_send); + +/** + * sdev_evt_alloc - allocate a new scsi event + * @evt_type: type of event to allocate + * @gfpflags: GFP flags for allocation + * + * Allocates and returns a new scsi_event. + */ +struct scsi_event *sdev_evt_alloc(enum scsi_device_event evt_type, + gfp_t gfpflags) +{ + struct scsi_event *evt = kzalloc(sizeof(struct scsi_event), gfpflags); + if (!evt) + return NULL; + + evt->evt_type = evt_type; + INIT_LIST_HEAD(&evt->node); + + /* evt_type-specific initialization, if any */ + switch (evt_type) { + case SDEV_EVT_MEDIA_CHANGE: + default: + /* do nothing */ + break; + } + + return evt; +} +EXPORT_SYMBOL_GPL(sdev_evt_alloc); + +/** + * sdev_evt_send_simple - send asserted event to uevent thread + * @sdev: scsi_device event occurred on + * @evt_type: type of event to send + * @gfpflags: GFP flags for allocation + * + * Assert scsi device event asynchronously, given an event type. + */ +void sdev_evt_send_simple(struct scsi_device *sdev, + enum scsi_device_event evt_type, gfp_t gfpflags) +{ + struct scsi_event *evt = sdev_evt_alloc(evt_type, gfpflags); + if (!evt) { + sdev_printk(KERN_ERR, sdev, "event %d eaten due to OOM\n", + evt_type); + return; + } + + sdev_evt_send(sdev, evt); +} +EXPORT_SYMBOL_GPL(sdev_evt_send_simple); + +/** * scsi_device_quiesce - Block user issued commands. * @sdev: scsi device to quiesce. * diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index eff00595189..3f34e9376b0 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -74,6 +74,9 @@ extern struct request_queue *scsi_alloc_queue(struct scsi_device *sdev); extern void scsi_free_queue(struct request_queue *q); extern int scsi_init_queue(void); extern void scsi_exit_queue(void); +struct request_queue; +struct request; +extern int scsi_prep_fn(struct request_queue *, struct request *); /* scsi_proc.c */ #ifdef CONFIG_SCSI_PROC_FS diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index b53c5f67e37..40ea71cd2ca 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -236,6 +236,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, struct scsi_device *sdev; int display_failure_msg = 1, ret; struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + extern void scsi_evt_thread(struct work_struct *work); sdev = kzalloc(sizeof(*sdev) + shost->transportt->device_size, GFP_ATOMIC); @@ -254,7 +255,9 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, INIT_LIST_HEAD(&sdev->same_target_siblings); INIT_LIST_HEAD(&sdev->cmd_list); INIT_LIST_HEAD(&sdev->starved_entry); + INIT_LIST_HEAD(&sdev->event_list); spin_lock_init(&sdev->list_lock); + INIT_WORK(&sdev->event_work, scsi_evt_thread); sdev->sdev_gendev.parent = get_device(&starget->dev); sdev->sdev_target = starget; diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index d531ceeb0d8..00b38667739 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -268,6 +268,7 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work) struct scsi_device *sdev; struct device *parent; struct scsi_target *starget; + struct list_head *this, *tmp; unsigned long flags; sdev = container_of(work, struct scsi_device, ew.work); @@ -282,6 +283,16 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work) list_del(&sdev->starved_entry); spin_unlock_irqrestore(sdev->host->host_lock, flags); + cancel_work_sync(&sdev->event_work); + + list_for_each_safe(this, tmp, &sdev->event_list) { + struct scsi_event *evt; + + evt = list_entry(this, struct scsi_event, node); + list_del(&evt->node); + kfree(evt); + } + if (sdev->request_queue) { sdev->request_queue->queuedata = NULL; /* user context needed to free queue */ @@ -362,12 +373,29 @@ static int scsi_bus_resume(struct device * dev) return err; } +static int scsi_bus_remove(struct device *dev) +{ + struct device_driver *drv = dev->driver; + struct scsi_device *sdev = to_scsi_device(dev); + int err = 0; + + /* reset the prep_fn back to the default since the + * driver may have altered it and it's being removed */ + blk_queue_prep_rq(sdev->request_queue, scsi_prep_fn); + + if (drv && drv->remove) + err = drv->remove(dev); + + return 0; +} + struct bus_type scsi_bus_type = { .name = "scsi", .match = scsi_bus_match, .uevent = scsi_bus_uevent, .suspend = scsi_bus_suspend, .resume = scsi_bus_resume, + .remove = scsi_bus_remove, }; int scsi_sysfs_register(void) @@ -614,6 +642,41 @@ sdev_show_modalias(struct device *dev, struct device_attribute *attr, char *buf) } static DEVICE_ATTR(modalias, S_IRUGO, sdev_show_modalias, NULL); +#define DECLARE_EVT_SHOW(name, Cap_name) \ +static ssize_t \ +sdev_show_evt_##name(struct device *dev, struct device_attribute *attr, \ + char *buf) \ +{ \ + struct scsi_device *sdev = to_scsi_device(dev); \ + int val = test_bit(SDEV_EVT_##Cap_name, sdev->supported_events);\ + return snprintf(buf, 20, "%d\n", val); \ +} + +#define DECLARE_EVT_STORE(name, Cap_name) \ +static ssize_t \ +sdev_store_evt_##name(struct device *dev, struct device_attribute *attr, \ + const char *buf, size_t count) \ +{ \ + struct scsi_device *sdev = to_scsi_device(dev); \ + int val = simple_strtoul(buf, NULL, 0); \ + if (val == 0) \ + clear_bit(SDEV_EVT_##Cap_name, sdev->supported_events); \ + else if (val == 1) \ + set_bit(SDEV_EVT_##Cap_name, sdev->supported_events); \ + else \ + return -EINVAL; \ + return count; \ +} + +#define DECLARE_EVT(name, Cap_name) \ + DECLARE_EVT_SHOW(name, Cap_name) \ + DECLARE_EVT_STORE(name, Cap_name) \ + static DEVICE_ATTR(evt_##name, S_IRUGO, sdev_show_evt_##name, \ + sdev_store_evt_##name); +#define REF_EVT(name) &dev_attr_evt_##name.attr + +DECLARE_EVT(media_change, MEDIA_CHANGE) + /* Default template for device attributes. May NOT be modified */ static struct attribute *scsi_sdev_attrs[] = { &dev_attr_device_blocked.attr, @@ -631,6 +694,7 @@ static struct attribute *scsi_sdev_attrs[] = { &dev_attr_iodone_cnt.attr, &dev_attr_ioerr_cnt.attr, &dev_attr_modalias.attr, + REF_EVT(media_change), NULL }; diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c index 44a340bd937..65c584db33b 100644 --- a/drivers/scsi/scsi_transport_srp.c +++ b/drivers/scsi/scsi_transport_srp.c @@ -265,7 +265,8 @@ EXPORT_SYMBOL_GPL(srp_rport_del); static int do_srp_rport_del(struct device *dev, void *data) { - srp_rport_del(dev_to_rport(dev)); + if (scsi_is_srp_rport(dev)) + srp_rport_del(dev_to_rport(dev)); return 0; } diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index b5fa4f09138..f1871ea0404 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1652,6 +1652,7 @@ sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, int tablesize) schp->buffer = kzalloc(sg_bufflen, gfp_flags); if (!schp->buffer) return -ENOMEM; + sg_init_table(schp->buffer, tablesize); schp->sglist_len = sg_bufflen; return tablesize; /* number of scat_gath elements allocated */ } diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 98dfd6ea209..328c47c6aeb 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -3611,6 +3611,7 @@ static struct st_buffer * tb->dma = need_dma; tb->buffer_size = got; + sg_init_table(tb->sg, max_sg); return tb; } diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index 5e46d842c6f..e606cf0a2eb 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -268,7 +268,7 @@ int sun3scsi_detect(struct scsi_host_template * tpnt) ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0; if (request_irq(instance->irq, scsi_sun3_intr, - 0, "Sun3SCSI-5380", NULL)) { + 0, "Sun3SCSI-5380", instance)) { #ifndef REAL_DMA printk("scsi%d: IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); @@ -310,7 +310,7 @@ int sun3scsi_detect(struct scsi_host_template * tpnt) int sun3scsi_release (struct Scsi_Host *shpnt) { if (shpnt->irq != SCSI_IRQ_NONE) - free_irq (shpnt->irq, NULL); + free_irq(shpnt->irq, shpnt); iounmap((void *)sun3_scsi_regp); diff --git a/drivers/scsi/sun3_scsi_vme.c b/drivers/scsi/sun3_scsi_vme.c index 7cb4a31453e..02d9727f017 100644 --- a/drivers/scsi/sun3_scsi_vme.c +++ b/drivers/scsi/sun3_scsi_vme.c @@ -230,7 +230,7 @@ static int sun3scsi_detect(struct scsi_host_template * tpnt) ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0; if (request_irq(instance->irq, scsi_sun3_intr, - 0, "Sun3SCSI-5380VME", NULL)) { + 0, "Sun3SCSI-5380VME", instance)) { #ifndef REAL_DMA printk("scsi%d: IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); @@ -279,7 +279,7 @@ static int sun3scsi_detect(struct scsi_host_template * tpnt) int sun3scsi_release (struct Scsi_Host *shpnt) { if (shpnt->irq != SCSI_IRQ_NONE) - free_irq (shpnt->irq, NULL); + free_irq(shpnt->irq, shpnt); iounmap((void *)sun3_scsi_regp); diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 0f74aba5b23..9e0908d1981 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -1243,7 +1243,7 @@ static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev) * Free O/S specific resources. */ if (pdev->irq) - free_irq(pdev->irq, np); + free_irq(pdev->irq, np->s.host); if (np->s.ioaddr) pci_iounmap(pdev, np->s.ioaddr); if (np->s.ramaddr) diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index 463f119f20e..254bdaeb35f 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -2791,7 +2791,7 @@ irqreturn_t sym_interrupt(struct Scsi_Host *shost) istat = INB(np, nc_istat); if (istat & INTF) { OUTB(np, nc_istat, (istat & SIGP) | INTF | np->istat_sem); - istat = INB(np, nc_istat); /* DUMMY READ */ + istat |= INB(np, nc_istat); /* DUMMY READ */ if (DEBUG_FLAGS & DEBUG_TINY) printf ("F "); sym_wakeup_done(np); } diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c index 248d60b8d89..041eaaace2c 100644 --- a/drivers/scsi/t128.c +++ b/drivers/scsi/t128.c @@ -259,7 +259,8 @@ found: instance->irq = NCR5380_probe_irq(instance, T128_IRQS); if (instance->irq != SCSI_IRQ_NONE) - if (request_irq(instance->irq, t128_intr, IRQF_DISABLED, "t128", instance)) { + if (request_irq(instance->irq, t128_intr, IRQF_DISABLED, "t128", + instance)) { printk("scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); instance->irq = SCSI_IRQ_NONE; @@ -295,7 +296,7 @@ static int t128_release(struct Scsi_Host *shost) NCR5380_local_declare(); NCR5380_setup(shost); if (shost->irq) - free_irq(shost->irq, NULL); + free_irq(shost->irq, shost); NCR5380_exit(shost); if (shost->io_port && shost->n_io_port) release_region(shost->io_port, shost->n_io_port); diff --git a/drivers/scsi/zorro7xx.c b/drivers/scsi/zorro7xx.c index ac67394c737..64d40a2d4d4 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_early.c b/drivers/serial/8250_early.c index 4d4c9f01be8..1f16de71996 100644 --- a/drivers/serial/8250_early.c +++ b/drivers/serial/8250_early.c @@ -76,7 +76,7 @@ static void __init wait_for_xmitr(struct uart_port *port) } } -static void __init putc(struct uart_port *port, int c) +static void __init serial_putc(struct uart_port *port, int c) { wait_for_xmitr(port); serial_out(port, UART_TX, c); @@ -91,7 +91,7 @@ static void __init early_serial8250_write(struct console *console, const char *s ier = serial_in(port, UART_IER); serial_out(port, UART_IER, 0); - uart_console_write(port, s, count, putc); + uart_console_write(port, s, count, serial_putc); /* Wait for transmitter to become empty and restore the IER */ wait_for_xmitr(port); diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index 0e357562ce9..ceb03c9e749 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c @@ -1986,6 +1986,7 @@ static int pciserial_suspend_one(struct pci_dev *dev, pm_message_t state) static int pciserial_resume_one(struct pci_dev *dev) { + int err; struct serial_private *priv = pci_get_drvdata(dev); pci_set_power_state(dev, PCI_D0); @@ -1995,7 +1996,9 @@ static int pciserial_resume_one(struct pci_dev *dev) /* * The device may have been disabled. Re-enable it. */ - pci_enable_device(dev); + err = pci_enable_device(dev); + if (err) + return err; pciserial_resume_ports(priv); } diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c index 926f58a674a..1de098e7549 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 ed438bc7e98..d7e1996e2fe 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 4d6b3c56d20..111da57f533 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 f523cdf4b02..a4e23cf4790 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 00000000000..ccd0f32b737 --- /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 f3257f708ef..9c95bc0398a 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 af3a011b2b2..352fcb8926a 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/serial_cs.c b/drivers/serial/serial_cs.c index 5afcb2fa7cd..d8b660061c1 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -345,7 +345,7 @@ static int serial_probe(struct pcmcia_device *link) link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; link->io.NumPorts1 = 8; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->conf.Attributes = CONF_ENABLE_IRQ; if (do_sound) { diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c index 6846a6c38b6..7ad21925869 100644 --- a/drivers/serial/serial_txx9.c +++ b/drivers/serial/serial_txx9.c @@ -657,7 +657,15 @@ static void serial_txx9_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) { - if (state == 0) + /* + * If oldstate was -1 this is called from + * uart_configure_port(). In this case do not initialize the + * port now, because the port was already initialized (for + * non-console port) or should not be initialized here (for + * console port). If we initialized the port here we lose + * serial console settings. + */ + if (state == 0 && oldstate != -1) serial_txx9_initialize(port); } diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index e89ae29645d..d24621ce799 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/suncore.c b/drivers/serial/suncore.c index 70a09a3d5af..a2d4a19550a 100644 --- a/drivers/serial/suncore.c +++ b/drivers/serial/suncore.c @@ -23,9 +23,34 @@ #include "suncore.h" -int sunserial_current_minor = 64; +static int sunserial_current_minor = 64; -EXPORT_SYMBOL(sunserial_current_minor); +int sunserial_register_minors(struct uart_driver *drv, int count) +{ + int err = 0; + + drv->minor = sunserial_current_minor; + drv->nr += count; + /* Register the driver on the first call */ + if (drv->nr == count) + err = uart_register_driver(drv); + if (err == 0) { + sunserial_current_minor += count; + drv->tty_driver->name_base = drv->minor - 64; + } + return err; +} +EXPORT_SYMBOL(sunserial_register_minors); + +void sunserial_unregister_minors(struct uart_driver *drv, int count) +{ + drv->nr -= count; + sunserial_current_minor -= count; + + if (drv->nr == 0) + uart_unregister_driver(drv); +} +EXPORT_SYMBOL(sunserial_unregister_minors); int sunserial_console_match(struct console *con, struct device_node *dp, struct uart_driver *drv, int line) @@ -133,8 +158,6 @@ sunserial_console_termios(struct console *con) con->cflag = cflag; } -EXPORT_SYMBOL(sunserial_console_termios); - /* Sun serial MOUSE auto baud rate detection. */ static struct mouse_baud_cflag { int baud; diff --git a/drivers/serial/suncore.h b/drivers/serial/suncore.h index 829d7d65d6d..042668aa602 100644 --- a/drivers/serial/suncore.h +++ b/drivers/serial/suncore.h @@ -22,7 +22,8 @@ extern unsigned int suncore_mouse_baud_cflag_next(unsigned int, int *); extern int suncore_mouse_baud_detection(unsigned char, int); -extern int sunserial_current_minor; +extern int sunserial_register_minors(struct uart_driver *, int); +extern void sunserial_unregister_minors(struct uart_driver *, int); extern int sunserial_console_match(struct console *, struct device_node *, struct uart_driver *, int); diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index 8ff900b0981..be0fe152891 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c @@ -562,16 +562,10 @@ static int __devinit hv_probe(struct of_device *op, const struct of_device_id *m port->dev = &op->dev; - sunhv_reg.minor = sunserial_current_minor; - sunhv_reg.nr = 1; - - err = uart_register_driver(&sunhv_reg); + err = sunserial_register_minors(&sunhv_reg, 1); if (err) goto out_free_con_read_page; - sunhv_reg.tty_driver->name_base = sunhv_reg.minor - 64; - sunserial_current_minor += 1; - sunserial_console_match(&sunhv_console, op->node, &sunhv_reg, port->line); @@ -591,8 +585,7 @@ out_remove_port: uart_remove_one_port(&sunhv_reg, port); out_unregister_driver: - sunserial_current_minor -= 1; - uart_unregister_driver(&sunhv_reg); + sunserial_unregister_minors(&sunhv_reg, 1); out_free_con_read_page: kfree(con_read_page); @@ -614,8 +607,7 @@ static int __devexit hv_remove(struct of_device *dev) uart_remove_one_port(&sunhv_reg, port); - sunserial_current_minor -= 1; - uart_unregister_driver(&sunhv_reg); + sunserial_unregister_minors(&sunhv_reg, 1); kfree(port); sunhv_port = NULL; diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index ff610c23314..543f93741e6 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -832,7 +832,6 @@ static struct uart_driver sunsab_reg = { }; static struct uart_sunsab_port *sunsab_ports; -static int num_channels; #ifdef CONFIG_SERIAL_SUNSAB_CONSOLE @@ -1102,8 +1101,8 @@ static int __init sunsab_init(void) { struct device_node *dp; int err; + int num_channels = 0; - num_channels = 0; for_each_node_by_name(dp, "se") num_channels += 2; for_each_node_by_name(dp, "serial") { @@ -1117,20 +1116,14 @@ static int __init sunsab_init(void) if (!sunsab_ports) return -ENOMEM; - sunsab_reg.minor = sunserial_current_minor; - sunsab_reg.nr = num_channels; sunsab_reg.cons = SUNSAB_CONSOLE(); - - err = uart_register_driver(&sunsab_reg); + err = sunserial_register_minors(&sunsab_reg, num_channels); if (err) { kfree(sunsab_ports); sunsab_ports = NULL; return err; } - - sunsab_reg.tty_driver->name_base = sunsab_reg.minor - 64; - sunserial_current_minor += num_channels; } return of_register_driver(&sab_driver, &of_bus_type); @@ -1139,9 +1132,8 @@ static int __init sunsab_init(void) static void __exit sunsab_exit(void) { of_unregister_driver(&sab_driver); - if (num_channels) { - sunserial_current_minor -= num_channels; - uart_unregister_driver(&sunsab_reg); + if (sunsab_reg.nr) { + sunserial_unregister_minors(&sunsab_reg, sunsab_reg.nr); } kfree(sunsab_ports); diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index e074943feff..4e2302d43ab 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -1528,14 +1528,12 @@ static struct of_platform_driver su_driver = { .remove = __devexit_p(su_remove), }; -static int num_uart; - static int __init sunsu_init(void) { struct device_node *dp; int err; + int num_uart = 0; - num_uart = 0; for_each_node_by_name(dp, "su") { if (su_get_type(dp) == SU_PORT_PORT) num_uart++; @@ -1552,26 +1550,22 @@ static int __init sunsu_init(void) } if (num_uart) { - sunsu_reg.minor = sunserial_current_minor; - sunsu_reg.nr = num_uart; - err = uart_register_driver(&sunsu_reg); + err = sunserial_register_minors(&sunsu_reg, num_uart); if (err) return err; - sunsu_reg.tty_driver->name_base = sunsu_reg.minor - 64; - sunserial_current_minor += num_uart; } err = of_register_driver(&su_driver, &of_bus_type); if (err && num_uart) - uart_unregister_driver(&sunsu_reg); + sunserial_unregister_minors(&sunsu_reg, num_uart); return err; } static void __exit sunsu_exit(void) { - if (num_uart) - uart_unregister_driver(&sunsu_reg); + if (sunsu_reg.nr) + sunserial_unregister_minors(&sunsu_reg, sunsu_reg.nr); } module_init(sunsu_init); diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index 283bef0d24c..cb2e4050637 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -63,10 +63,6 @@ readb(&((__channel)->control)) #endif -static int num_sunzilog; -#define NUM_SUNZILOG num_sunzilog -#define NUM_CHANNELS (NUM_SUNZILOG * 2) - #define ZS_CLOCK 4915200 /* Zilog input clock rate. */ #define ZS_CLOCK_DIVISOR 16 /* Divisor this driver uses. */ @@ -1031,18 +1027,19 @@ static struct uart_driver sunzilog_reg = { .major = TTY_MAJOR, }; -static int __init sunzilog_alloc_tables(void) +static int __init sunzilog_alloc_tables(int num_sunzilog) { struct uart_sunzilog_port *up; unsigned long size; + int num_channels = num_sunzilog * 2; int i; - size = NUM_CHANNELS * sizeof(struct uart_sunzilog_port); + size = num_channels * sizeof(struct uart_sunzilog_port); sunzilog_port_table = kzalloc(size, GFP_KERNEL); if (!sunzilog_port_table) return -ENOMEM; - for (i = 0; i < NUM_CHANNELS; i++) { + for (i = 0; i < num_channels; i++) { up = &sunzilog_port_table[i]; spin_lock_init(&up->port.lock); @@ -1050,13 +1047,13 @@ static int __init sunzilog_alloc_tables(void) if (i == 0) sunzilog_irq_chain = up; - if (i < NUM_CHANNELS - 1) + if (i < num_channels - 1) up->next = up + 1; else up->next = NULL; } - size = NUM_SUNZILOG * sizeof(struct zilog_layout __iomem *); + size = num_sunzilog * sizeof(struct zilog_layout __iomem *); sunzilog_chip_regs = kzalloc(size, GFP_KERNEL); if (!sunzilog_chip_regs) { kfree(sunzilog_port_table); @@ -1496,34 +1493,28 @@ static int __init sunzilog_init(void) struct device_node *dp; int err, uart_count; int num_keybms; + int num_sunzilog = 0; - NUM_SUNZILOG = 0; num_keybms = 0; for_each_node_by_name(dp, "zs") { - NUM_SUNZILOG++; + num_sunzilog++; if (of_find_property(dp, "keyboard", NULL)) num_keybms++; } uart_count = 0; - if (NUM_SUNZILOG) { + if (num_sunzilog) { int uart_count; - err = sunzilog_alloc_tables(); + err = sunzilog_alloc_tables(num_sunzilog); if (err) goto out; - uart_count = (NUM_SUNZILOG * 2) - (2 * num_keybms); + uart_count = (num_sunzilog * 2) - (2 * num_keybms); - sunzilog_reg.nr = uart_count; - sunzilog_reg.minor = sunserial_current_minor; - err = uart_register_driver(&sunzilog_reg); + err = sunserial_register_minors(&sunzilog_reg, uart_count); if (err) goto out_free_tables; - - sunzilog_reg.tty_driver->name_base = sunzilog_reg.minor - 64; - - sunserial_current_minor += uart_count; } err = of_register_driver(&zs_driver, &of_bus_type); @@ -1557,8 +1548,8 @@ out_unregister_driver: of_unregister_driver(&zs_driver); out_unregister_uart: - if (NUM_SUNZILOG) { - uart_unregister_driver(&sunzilog_reg); + if (num_sunzilog) { + sunserial_unregister_minors(&sunzilog_reg, num_sunzilog); sunzilog_reg.cons = NULL; } @@ -1590,8 +1581,8 @@ static void __exit sunzilog_exit(void) zilog_irq = -1; } - if (NUM_SUNZILOG) { - uart_unregister_driver(&sunzilog_reg); + if (sunzilog_reg.nr) { + sunserial_unregister_minors(&sunzilog_reg, sunzilog_reg.nr); sunzilog_free_tables(); } } diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c index dfef83f1496..3f593247c41 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(); } } @@ -391,6 +393,7 @@ static inline void __init ulite_console_of_find_device(int id) continue; ulite_ports[id].mapbase = res.start; + of_node_put(np); return; } } diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c index 161d1021b7e..e52a6296ca4 100644 --- a/drivers/sh/maple/maple.c +++ b/drivers/sh/maple/maple.c @@ -601,8 +601,7 @@ static int match_maple_bus_driver(struct device *devptr, return 0; } -static int maple_bus_uevent(struct device *dev, char **envp, - int num_envp, char *buffer, int buffer_size) +static int maple_bus_uevent(struct device *dev, struct kobj_uevent_env *env) { return 0; } diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c index 7d873b3b051..4d0282b821b 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 a77ede598d3..abf05048c63 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/at25.c b/drivers/spi/at25.c index e007833cca5..290dbe99647 100644 --- a/drivers/spi/at25.c +++ b/drivers/spi/at25.c @@ -21,6 +21,13 @@ #include <linux/spi/eeprom.h> +/* + * NOTE: this is an *EEPROM* driver. The vagaries of product naming + * mean that some AT25 products are EEPROMs, and others are FLASH. + * Handle FLASH chips with the drivers/mtd/devices/m25p80.c driver, + * not this one! + */ + struct at25_data { struct spi_device *spi; struct mutex lock; diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c index 0d342dcdd30..ff10808183a 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c @@ -195,8 +195,8 @@ static void atmel_spi_next_xfer(struct spi_master *master, xfer, xfer->len, xfer->tx_buf, xfer->tx_dma, xfer->rx_buf, xfer->rx_dma, spi_readl(as, IMR)); - spi_writel(as, TCR, len); spi_writel(as, RCR, len); + spi_writel(as, TCR, len); spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN)); } @@ -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/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index 5f3d808cbc2..1c2ab541d37 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c @@ -39,7 +39,7 @@ #include <asm/arch/pxa2xx_spi.h> MODULE_AUTHOR("Stephen Street"); -MODULE_DESCRIPTION("PXA2xx SSP SPI Contoller"); +MODULE_DESCRIPTION("PXA2xx SSP SPI Controller"); MODULE_LICENSE("GPL"); #define MAX_BUSES 3 diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 89769ce16f8..93e9de46977 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); @@ -539,10 +541,7 @@ static void spi_complete(void *arg) * Also, the caller is guaranteeing that the memory associated with the * message will not be freed before this call returns. * - * The return value is a negative error code if the message could not be - * submitted, else zero. When the value is zero, then message->status is - * also defined; it's the completion code for the transfer, either zero - * or a negative error code from the controller driver. + * It returns zero on success, else a negative error code. */ int spi_sync(struct spi_device *spi, struct spi_message *message) { @@ -552,8 +551,10 @@ int spi_sync(struct spi_device *spi, struct spi_message *message) message->complete = spi_complete; message->context = &done; status = spi_async(spi, message); - if (status == 0) + if (status == 0) { wait_for_completion(&done); + status = message->status; + } message->context = NULL; return status; } @@ -587,7 +588,7 @@ int spi_write_then_read(struct spi_device *spi, const u8 *txbuf, unsigned n_tx, u8 *rxbuf, unsigned n_rx) { - static DECLARE_MUTEX(lock); + static DEFINE_MUTEX(lock); int status; struct spi_message message; @@ -613,7 +614,7 @@ int spi_write_then_read(struct spi_device *spi, } /* ... unless someone else is using the pre-allocated buffer */ - if (down_trylock(&lock)) { + if (!mutex_trylock(&lock)) { local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL); if (!local_buf) return -ENOMEM; @@ -626,13 +627,11 @@ int spi_write_then_read(struct spi_device *spi, /* do the i/o */ status = spi_sync(spi, &message); - if (status == 0) { + if (status == 0) memcpy(rxbuf, x[1].rx_buf, n_rx); - status = message.status; - } if (x[0].tx_buf == buf) - up(&lock); + mutex_unlock(&lock); else kfree(local_buf); diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c index 2ef11bb70b2..7ef39a6e8c0 100644 --- a/drivers/spi/spi_bfin5xx.c +++ b/drivers/spi/spi_bfin5xx.c @@ -1,17 +1,22 @@ /* - * File: drivers/spi/bfin5xx_spi.c - * Based on: N/A - * Author: Luke Yang (Analog Devices Inc.) + * File: drivers/spi/bfin5xx_spi.c + * Maintainer: + * Bryan Wu <bryan.wu@analog.com> + * Original Author: + * Luke Yang (Analog Devices Inc.) * - * Created: March. 10th 2006 - * Description: SPI controller driver for Blackfin 5xx - * Bugs: Enter bugs at http://blackfin.uclinux.org/ + * Created: March. 10th 2006 + * Description: SPI controller driver for Blackfin BF5xx + * Bugs: Enter bugs at http://blackfin.uclinux.org/ * * Modified: * March 10, 2006 bfin5xx_spi.c Created. (Luke Yang) * August 7, 2006 added full duplex mode (Axel Weiss & Luke Yang) + * July 17, 2007 add support for BF54x SPI0 controller (Bryan Wu) + * July 30, 2007 add platfrom_resource interface to support multi-port + * SPI controller (Bryan Wu) * - * Copyright 2004-2006 Analog Devices Inc. + * Copyright 2004-2007 Analog Devices Inc. * * 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 @@ -31,50 +36,39 @@ #include <linux/init.h> #include <linux/module.h> +#include <linux/delay.h> #include <linux/device.h> +#include <linux/io.h> #include <linux/ioport.h> +#include <linux/irq.h> #include <linux/errno.h> #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/dma-mapping.h> #include <linux/spi/spi.h> #include <linux/workqueue.h> -#include <linux/delay.h> -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/delay.h> #include <asm/dma.h> - +#include <asm/portmux.h> #include <asm/bfin5xx_spi.h> -MODULE_AUTHOR("Luke Yang"); -MODULE_DESCRIPTION("Blackfin 5xx SPI Contoller"); -MODULE_LICENSE("GPL"); +#define DRV_NAME "bfin-spi" +#define DRV_AUTHOR "Bryan Wu, Luke Yang" +#define DRV_DESC "Blackfin BF5xx on-chip SPI Controller Driver" +#define DRV_VERSION "1.0" -#define IS_DMA_ALIGNED(x) (((u32)(x)&0x07)==0) +MODULE_AUTHOR(DRV_AUTHOR); +MODULE_DESCRIPTION(DRV_DESC); +MODULE_LICENSE("GPL"); -#define DEFINE_SPI_REG(reg, off) \ -static inline u16 read_##reg(void) \ - { return *(volatile unsigned short*)(SPI0_REGBASE + off); } \ -static inline void write_##reg(u16 v) \ - {*(volatile unsigned short*)(SPI0_REGBASE + off) = v;\ - SSYNC();} +#define IS_DMA_ALIGNED(x) (((u32)(x)&0x07) == 0) -DEFINE_SPI_REG(CTRL, 0x00) -DEFINE_SPI_REG(FLAG, 0x04) -DEFINE_SPI_REG(STAT, 0x08) -DEFINE_SPI_REG(TDBR, 0x0C) -DEFINE_SPI_REG(RDBR, 0x10) -DEFINE_SPI_REG(BAUD, 0x14) -DEFINE_SPI_REG(SHAW, 0x18) -#define START_STATE ((void*)0) -#define RUNNING_STATE ((void*)1) -#define DONE_STATE ((void*)2) -#define ERROR_STATE ((void*)-1) -#define QUEUE_RUNNING 0 -#define QUEUE_STOPPED 1 -int dma_requested; +#define START_STATE ((void *)0) +#define RUNNING_STATE ((void *)1) +#define DONE_STATE ((void *)2) +#define ERROR_STATE ((void *)-1) +#define QUEUE_RUNNING 0 +#define QUEUE_STOPPED 1 struct driver_data { /* Driver model hookup */ @@ -83,6 +77,12 @@ struct driver_data { /* SPI framework hookup */ struct spi_master *master; + /* Regs base of SPI controller */ + void __iomem *regs_base; + + /* Pin request list */ + u16 *pin_req; + /* BFIN hookup */ struct bfin5xx_spi_master *master_info; @@ -107,12 +107,18 @@ struct driver_data { void *tx_end; void *rx; void *rx_end; + + /* DMA stuffs */ + int dma_channel; int dma_mapped; + int dma_requested; dma_addr_t rx_dma; dma_addr_t tx_dma; + size_t rx_map_len; size_t tx_map_len; u8 n_bytes; + int cs_change; void (*write) (struct driver_data *); void (*read) (struct driver_data *); void (*duplex) (struct driver_data *); @@ -129,28 +135,40 @@ struct chip_data { u8 enable_dma; u8 bits_per_word; /* 8 or 16 */ u8 cs_change_per_word; - u8 cs_chg_udelay; + u16 cs_chg_udelay; /* Some devices require > 255usec delay */ void (*write) (struct driver_data *); void (*read) (struct driver_data *); void (*duplex) (struct driver_data *); }; +#define DEFINE_SPI_REG(reg, off) \ +static inline u16 read_##reg(struct driver_data *drv_data) \ + { return bfin_read16(drv_data->regs_base + off); } \ +static inline void write_##reg(struct driver_data *drv_data, u16 v) \ + { bfin_write16(drv_data->regs_base + off, v); } + +DEFINE_SPI_REG(CTRL, 0x00) +DEFINE_SPI_REG(FLAG, 0x04) +DEFINE_SPI_REG(STAT, 0x08) +DEFINE_SPI_REG(TDBR, 0x0C) +DEFINE_SPI_REG(RDBR, 0x10) +DEFINE_SPI_REG(BAUD, 0x14) +DEFINE_SPI_REG(SHAW, 0x18) + static void bfin_spi_enable(struct driver_data *drv_data) { u16 cr; - cr = read_CTRL(); - write_CTRL(cr | BIT_CTL_ENABLE); - SSYNC(); + cr = read_CTRL(drv_data); + write_CTRL(drv_data, (cr | BIT_CTL_ENABLE)); } static void bfin_spi_disable(struct driver_data *drv_data) { u16 cr; - cr = read_CTRL(); - write_CTRL(cr & (~BIT_CTL_ENABLE)); - SSYNC(); + cr = read_CTRL(drv_data); + write_CTRL(drv_data, (cr & (~BIT_CTL_ENABLE))); } /* Caculate the SPI_BAUD register value based on input HZ */ @@ -170,83 +188,71 @@ static int flush(struct driver_data *drv_data) unsigned long limit = loops_per_jiffy << 1; /* wait for stop and clear stat */ - while (!(read_STAT() & BIT_STAT_SPIF) && limit--) - continue; + while (!(read_STAT(drv_data) & BIT_STAT_SPIF) && limit--) + cpu_relax(); - write_STAT(BIT_STAT_CLR); + write_STAT(drv_data, BIT_STAT_CLR); return limit; } +/* Chip select operation functions for cs_change flag */ +static void cs_active(struct driver_data *drv_data, struct chip_data *chip) +{ + u16 flag = read_FLAG(drv_data); + + flag |= chip->flag; + flag &= ~(chip->flag << 8); + + write_FLAG(drv_data, flag); +} + +static void cs_deactive(struct driver_data *drv_data, struct chip_data *chip) +{ + u16 flag = read_FLAG(drv_data); + + flag |= (chip->flag << 8); + + write_FLAG(drv_data, flag); + + /* Move delay here for consistency */ + if (chip->cs_chg_udelay) + udelay(chip->cs_chg_udelay); +} + +#define MAX_SPI_SSEL 7 + /* stop controller and re-config current chip*/ -static void restore_state(struct driver_data *drv_data) +static int restore_state(struct driver_data *drv_data) { struct chip_data *chip = drv_data->cur_chip; + int ret = 0; /* Clear status and disable clock */ - write_STAT(BIT_STAT_CLR); + write_STAT(drv_data, BIT_STAT_CLR); bfin_spi_disable(drv_data); dev_dbg(&drv_data->pdev->dev, "restoring spi ctl state\n"); -#if defined(CONFIG_BF534) || defined(CONFIG_BF536) || defined(CONFIG_BF537) - dev_dbg(&drv_data->pdev->dev, - "chip select number is %d\n", chip->chip_select_num); - - switch (chip->chip_select_num) { - case 1: - bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3c00); - SSYNC(); - break; - - case 2: - case 3: - bfin_write_PORT_MUX(bfin_read_PORT_MUX() | PJSE_SPI); - SSYNC(); - bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3800); - SSYNC(); - break; - - case 4: - bfin_write_PORT_MUX(bfin_read_PORT_MUX() | PFS4E_SPI); - SSYNC(); - bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3840); - SSYNC(); - break; + /* Load the registers */ + write_CTRL(drv_data, chip->ctl_reg); + write_BAUD(drv_data, chip->baud); - case 5: - bfin_write_PORT_MUX(bfin_read_PORT_MUX() | PFS5E_SPI); - SSYNC(); - bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3820); - SSYNC(); - break; + bfin_spi_enable(drv_data); + cs_active(drv_data, chip); - case 6: - bfin_write_PORT_MUX(bfin_read_PORT_MUX() | PFS6E_SPI); - SSYNC(); - bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3810); - SSYNC(); - break; + if (ret) + dev_dbg(&drv_data->pdev->dev, + ": request chip select number %d failed\n", + chip->chip_select_num); - case 7: - bfin_write_PORT_MUX(bfin_read_PORT_MUX() | PJCE_SPI); - SSYNC(); - bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3800); - SSYNC(); - break; - } -#endif - - /* Load the registers */ - write_CTRL(chip->ctl_reg); - write_BAUD(chip->baud); - write_FLAG(chip->flag); + return ret; } /* used to kick off transfer in rx mode */ -static unsigned short dummy_read(void) +static unsigned short dummy_read(struct driver_data *drv_data) { unsigned short tmp; - tmp = read_RDBR(); + tmp = read_RDBR(drv_data); return tmp; } @@ -255,9 +261,9 @@ static void null_writer(struct driver_data *drv_data) u8 n_bytes = drv_data->n_bytes; while (drv_data->tx < drv_data->tx_end) { - write_TDBR(0); - while ((read_STAT() & BIT_STAT_TXS)) - continue; + write_TDBR(drv_data, 0); + while ((read_STAT(drv_data) & BIT_STAT_TXS)) + cpu_relax(); drv_data->tx += n_bytes; } } @@ -265,75 +271,78 @@ static void null_writer(struct driver_data *drv_data) static void null_reader(struct driver_data *drv_data) { u8 n_bytes = drv_data->n_bytes; - dummy_read(); + dummy_read(drv_data); while (drv_data->rx < drv_data->rx_end) { - while (!(read_STAT() & BIT_STAT_RXS)) - continue; - dummy_read(); + while (!(read_STAT(drv_data) & BIT_STAT_RXS)) + cpu_relax(); + dummy_read(drv_data); drv_data->rx += n_bytes; } } static void u8_writer(struct driver_data *drv_data) { - dev_dbg(&drv_data->pdev->dev, - "cr8-s is 0x%x\n", read_STAT()); + dev_dbg(&drv_data->pdev->dev, + "cr8-s is 0x%x\n", read_STAT(drv_data)); + + /* poll for SPI completion before start */ + while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) + cpu_relax(); + while (drv_data->tx < drv_data->tx_end) { - write_TDBR(*(u8 *) (drv_data->tx)); - while (read_STAT() & BIT_STAT_TXS) - continue; + write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); + while (read_STAT(drv_data) & BIT_STAT_TXS) + cpu_relax(); ++drv_data->tx; } - - /* poll for SPI completion before returning */ - while (!(read_STAT() & BIT_STAT_SPIF)) - continue; } static void u8_cs_chg_writer(struct driver_data *drv_data) { struct chip_data *chip = drv_data->cur_chip; + /* poll for SPI completion before start */ + while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) + cpu_relax(); + while (drv_data->tx < drv_data->tx_end) { - write_FLAG(chip->flag); - SSYNC(); - - write_TDBR(*(u8 *) (drv_data->tx)); - while (read_STAT() & BIT_STAT_TXS) - continue; - while (!(read_STAT() & BIT_STAT_SPIF)) - continue; - write_FLAG(0xFF00 | chip->flag); - SSYNC(); - if (chip->cs_chg_udelay) - udelay(chip->cs_chg_udelay); + cs_active(drv_data, chip); + + write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); + while (read_STAT(drv_data) & BIT_STAT_TXS) + cpu_relax(); + + cs_deactive(drv_data, chip); + ++drv_data->tx; } - write_FLAG(0xFF00); - SSYNC(); } static void u8_reader(struct driver_data *drv_data) { - dev_dbg(&drv_data->pdev->dev, - "cr-8 is 0x%x\n", read_STAT()); + dev_dbg(&drv_data->pdev->dev, + "cr-8 is 0x%x\n", read_STAT(drv_data)); + + /* poll for SPI completion before start */ + while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) + cpu_relax(); /* clear TDBR buffer before read(else it will be shifted out) */ - write_TDBR(0xFFFF); + write_TDBR(drv_data, 0xFFFF); - dummy_read(); + dummy_read(drv_data); while (drv_data->rx < drv_data->rx_end - 1) { - while (!(read_STAT() & BIT_STAT_RXS)) - continue; - *(u8 *) (drv_data->rx) = read_RDBR(); + while (!(read_STAT(drv_data) & BIT_STAT_RXS)) + cpu_relax(); + *(u8 *) (drv_data->rx) = read_RDBR(drv_data); ++drv_data->rx; } - while (!(read_STAT() & BIT_STAT_RXS)) - continue; - *(u8 *) (drv_data->rx) = read_SHAW(); + while (!(read_STAT(drv_data) & BIT_STAT_RXS)) + cpu_relax(); + *(u8 *) (drv_data->rx) = read_SHAW(drv_data); ++drv_data->rx; } @@ -341,36 +350,47 @@ static void u8_cs_chg_reader(struct driver_data *drv_data) { struct chip_data *chip = drv_data->cur_chip; - while (drv_data->rx < drv_data->rx_end) { - write_FLAG(chip->flag); - SSYNC(); - - read_RDBR(); /* kick off */ - while (!(read_STAT() & BIT_STAT_RXS)) - continue; - while (!(read_STAT() & BIT_STAT_SPIF)) - continue; - *(u8 *) (drv_data->rx) = read_SHAW(); - write_FLAG(0xFF00 | chip->flag); - SSYNC(); - if (chip->cs_chg_udelay) - udelay(chip->cs_chg_udelay); + /* poll for SPI completion before start */ + while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) + cpu_relax(); + + /* clear TDBR buffer before read(else it will be shifted out) */ + write_TDBR(drv_data, 0xFFFF); + + cs_active(drv_data, chip); + dummy_read(drv_data); + + while (drv_data->rx < drv_data->rx_end - 1) { + cs_deactive(drv_data, chip); + + while (!(read_STAT(drv_data) & BIT_STAT_RXS)) + cpu_relax(); + cs_active(drv_data, chip); + *(u8 *) (drv_data->rx) = read_RDBR(drv_data); ++drv_data->rx; } - write_FLAG(0xFF00); - SSYNC(); + cs_deactive(drv_data, chip); + + while (!(read_STAT(drv_data) & BIT_STAT_RXS)) + cpu_relax(); + *(u8 *) (drv_data->rx) = read_SHAW(drv_data); + ++drv_data->rx; } static void u8_duplex(struct driver_data *drv_data) { + /* poll for SPI completion before start */ + while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) + cpu_relax(); + /* in duplex mode, clk is triggered by writing of TDBR */ while (drv_data->rx < drv_data->rx_end) { - write_TDBR(*(u8 *) (drv_data->tx)); - while (!(read_STAT() & BIT_STAT_SPIF)) - continue; - while (!(read_STAT() & BIT_STAT_RXS)) - continue; - *(u8 *) (drv_data->rx) = read_RDBR(); + write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); + while (read_STAT(drv_data) & BIT_STAT_TXS) + cpu_relax(); + while (!(read_STAT(drv_data) & BIT_STAT_RXS)) + cpu_relax(); + *(u8 *) (drv_data->rx) = read_RDBR(drv_data); ++drv_data->rx; ++drv_data->tx; } @@ -380,83 +400,89 @@ static void u8_cs_chg_duplex(struct driver_data *drv_data) { struct chip_data *chip = drv_data->cur_chip; + /* poll for SPI completion before start */ + while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) + cpu_relax(); + while (drv_data->rx < drv_data->rx_end) { - write_FLAG(chip->flag); - SSYNC(); - - write_TDBR(*(u8 *) (drv_data->tx)); - while (!(read_STAT() & BIT_STAT_SPIF)) - continue; - while (!(read_STAT() & BIT_STAT_RXS)) - continue; - *(u8 *) (drv_data->rx) = read_RDBR(); - write_FLAG(0xFF00 | chip->flag); - SSYNC(); - if (chip->cs_chg_udelay) - udelay(chip->cs_chg_udelay); + cs_active(drv_data, chip); + + write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); + while (read_STAT(drv_data) & BIT_STAT_TXS) + cpu_relax(); + while (!(read_STAT(drv_data) & BIT_STAT_RXS)) + cpu_relax(); + *(u8 *) (drv_data->rx) = read_RDBR(drv_data); + + cs_deactive(drv_data, chip); + ++drv_data->rx; ++drv_data->tx; } - write_FLAG(0xFF00); - SSYNC(); } static void u16_writer(struct driver_data *drv_data) { - dev_dbg(&drv_data->pdev->dev, - "cr16 is 0x%x\n", read_STAT()); + dev_dbg(&drv_data->pdev->dev, + "cr16 is 0x%x\n", read_STAT(drv_data)); + + /* poll for SPI completion before start */ + while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) + cpu_relax(); while (drv_data->tx < drv_data->tx_end) { - write_TDBR(*(u16 *) (drv_data->tx)); - while ((read_STAT() & BIT_STAT_TXS)) - continue; + write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); + while ((read_STAT(drv_data) & BIT_STAT_TXS)) + cpu_relax(); drv_data->tx += 2; } - - /* poll for SPI completion before returning */ - while (!(read_STAT() & BIT_STAT_SPIF)) - continue; } static void u16_cs_chg_writer(struct driver_data *drv_data) { struct chip_data *chip = drv_data->cur_chip; + /* poll for SPI completion before start */ + while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) + cpu_relax(); + while (drv_data->tx < drv_data->tx_end) { - write_FLAG(chip->flag); - SSYNC(); - - write_TDBR(*(u16 *) (drv_data->tx)); - while ((read_STAT() & BIT_STAT_TXS)) - continue; - while (!(read_STAT() & BIT_STAT_SPIF)) - continue; - write_FLAG(0xFF00 | chip->flag); - SSYNC(); - if (chip->cs_chg_udelay) - udelay(chip->cs_chg_udelay); + cs_active(drv_data, chip); + + write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); + while ((read_STAT(drv_data) & BIT_STAT_TXS)) + cpu_relax(); + + cs_deactive(drv_data, chip); + drv_data->tx += 2; } - write_FLAG(0xFF00); - SSYNC(); } static void u16_reader(struct driver_data *drv_data) { dev_dbg(&drv_data->pdev->dev, - "cr-16 is 0x%x\n", read_STAT()); - dummy_read(); + "cr-16 is 0x%x\n", read_STAT(drv_data)); + + /* poll for SPI completion before start */ + while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) + cpu_relax(); + + /* clear TDBR buffer before read(else it will be shifted out) */ + write_TDBR(drv_data, 0xFFFF); + + dummy_read(drv_data); while (drv_data->rx < (drv_data->rx_end - 2)) { - while (!(read_STAT() & BIT_STAT_RXS)) - continue; - *(u16 *) (drv_data->rx) = read_RDBR(); + while (!(read_STAT(drv_data) & BIT_STAT_RXS)) + cpu_relax(); + *(u16 *) (drv_data->rx) = read_RDBR(drv_data); drv_data->rx += 2; } - while (!(read_STAT() & BIT_STAT_RXS)) - continue; - *(u16 *) (drv_data->rx) = read_SHAW(); + while (!(read_STAT(drv_data) & BIT_STAT_RXS)) + cpu_relax(); + *(u16 *) (drv_data->rx) = read_SHAW(drv_data); drv_data->rx += 2; } @@ -464,36 +490,47 @@ static void u16_cs_chg_reader(struct driver_data *drv_data) { struct chip_data *chip = drv_data->cur_chip; - while (drv_data->rx < drv_data->rx_end) { - write_FLAG(chip->flag); - SSYNC(); - - read_RDBR(); /* kick off */ - while (!(read_STAT() & BIT_STAT_RXS)) - continue; - while (!(read_STAT() & BIT_STAT_SPIF)) - continue; - *(u16 *) (drv_data->rx) = read_SHAW(); - write_FLAG(0xFF00 | chip->flag); - SSYNC(); - if (chip->cs_chg_udelay) - udelay(chip->cs_chg_udelay); + /* poll for SPI completion before start */ + while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) + cpu_relax(); + + /* clear TDBR buffer before read(else it will be shifted out) */ + write_TDBR(drv_data, 0xFFFF); + + cs_active(drv_data, chip); + dummy_read(drv_data); + + while (drv_data->rx < drv_data->rx_end - 2) { + cs_deactive(drv_data, chip); + + while (!(read_STAT(drv_data) & BIT_STAT_RXS)) + cpu_relax(); + cs_active(drv_data, chip); + *(u16 *) (drv_data->rx) = read_RDBR(drv_data); drv_data->rx += 2; } - write_FLAG(0xFF00); - SSYNC(); + cs_deactive(drv_data, chip); + + while (!(read_STAT(drv_data) & BIT_STAT_RXS)) + cpu_relax(); + *(u16 *) (drv_data->rx) = read_SHAW(drv_data); + drv_data->rx += 2; } static void u16_duplex(struct driver_data *drv_data) { + /* poll for SPI completion before start */ + while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) + cpu_relax(); + /* in duplex mode, clk is triggered by writing of TDBR */ while (drv_data->tx < drv_data->tx_end) { - write_TDBR(*(u16 *) (drv_data->tx)); - while (!(read_STAT() & BIT_STAT_SPIF)) - continue; - while (!(read_STAT() & BIT_STAT_RXS)) - continue; - *(u16 *) (drv_data->rx) = read_RDBR(); + write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); + while (read_STAT(drv_data) & BIT_STAT_TXS) + cpu_relax(); + while (!(read_STAT(drv_data) & BIT_STAT_RXS)) + cpu_relax(); + *(u16 *) (drv_data->rx) = read_RDBR(drv_data); drv_data->rx += 2; drv_data->tx += 2; } @@ -503,25 +540,25 @@ static void u16_cs_chg_duplex(struct driver_data *drv_data) { struct chip_data *chip = drv_data->cur_chip; + /* poll for SPI completion before start */ + while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) + cpu_relax(); + while (drv_data->tx < drv_data->tx_end) { - write_FLAG(chip->flag); - SSYNC(); - - write_TDBR(*(u16 *) (drv_data->tx)); - while (!(read_STAT() & BIT_STAT_SPIF)) - continue; - while (!(read_STAT() & BIT_STAT_RXS)) - continue; - *(u16 *) (drv_data->rx) = read_RDBR(); - write_FLAG(0xFF00 | chip->flag); - SSYNC(); - if (chip->cs_chg_udelay) - udelay(chip->cs_chg_udelay); + cs_active(drv_data, chip); + + write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); + while (read_STAT(drv_data) & BIT_STAT_TXS) + cpu_relax(); + while (!(read_STAT(drv_data) & BIT_STAT_RXS)) + cpu_relax(); + *(u16 *) (drv_data->rx) = read_RDBR(drv_data); + + cs_deactive(drv_data, chip); + drv_data->rx += 2; drv_data->tx += 2; } - write_FLAG(0xFF00); - SSYNC(); } /* test if ther is more transfer to be done */ @@ -546,6 +583,7 @@ static void *next_transfer(struct driver_data *drv_data) */ static void giveback(struct driver_data *drv_data) { + struct chip_data *chip = drv_data->cur_chip; struct spi_transfer *last_transfer; unsigned long flags; struct spi_message *msg; @@ -565,10 +603,13 @@ static void giveback(struct driver_data *drv_data) /* disable chip select signal. And not stop spi in autobuffer mode */ if (drv_data->tx_dma != 0xFFFF) { - write_FLAG(0xFF00); + cs_deactive(drv_data, chip); bfin_spi_disable(drv_data); } + if (!drv_data->cs_change) + cs_deactive(drv_data, chip); + if (msg->complete) msg->complete(msg->context); } @@ -576,14 +617,15 @@ static void giveback(struct driver_data *drv_data) static irqreturn_t dma_irq_handler(int irq, void *dev_id) { struct driver_data *drv_data = (struct driver_data *)dev_id; + struct chip_data *chip = drv_data->cur_chip; struct spi_message *msg = drv_data->cur_msg; dev_dbg(&drv_data->pdev->dev, "in dma_irq_handler\n"); - clear_dma_irqstat(CH_SPI); + clear_dma_irqstat(drv_data->dma_channel); /* Wait for DMA to complete */ - while (get_dma_curr_irqstat(CH_SPI) & DMA_RUN) - continue; + while (get_dma_curr_irqstat(drv_data->dma_channel) & DMA_RUN) + cpu_relax(); /* * wait for the last transaction shifted out. HRM states: @@ -592,18 +634,19 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id) * register until it goes low for 2 successive reads */ if (drv_data->tx != NULL) { - while ((bfin_read_SPI_STAT() & TXS) || - (bfin_read_SPI_STAT() & TXS)) - continue; + while ((read_STAT(drv_data) & TXS) || + (read_STAT(drv_data) & TXS)) + cpu_relax(); } - while (!(bfin_read_SPI_STAT() & SPIF)) - continue; - - bfin_spi_disable(drv_data); + while (!(read_STAT(drv_data) & SPIF)) + cpu_relax(); msg->actual_length += drv_data->len_in_bytes; + if (drv_data->cs_change) + cs_deactive(drv_data, chip); + /* Move to next transfer */ msg->state = next_transfer(drv_data); @@ -613,8 +656,8 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id) /* free the irq handler before next transfer */ dev_dbg(&drv_data->pdev->dev, "disable dma channel irq%d\n", - CH_SPI); - dma_disable_irq(CH_SPI); + drv_data->dma_channel); + dma_disable_irq(drv_data->dma_channel); return IRQ_HANDLED; } @@ -690,31 +733,67 @@ static void pump_transfers(unsigned long data) drv_data->rx_dma = transfer->rx_dma; drv_data->tx_dma = transfer->tx_dma; drv_data->len_in_bytes = transfer->len; + drv_data->cs_change = transfer->cs_change; + + /* Bits per word setup */ + switch (transfer->bits_per_word) { + case 8: + drv_data->n_bytes = 1; + width = CFG_SPI_WORDSIZE8; + drv_data->read = chip->cs_change_per_word ? + u8_cs_chg_reader : u8_reader; + drv_data->write = chip->cs_change_per_word ? + u8_cs_chg_writer : u8_writer; + drv_data->duplex = chip->cs_change_per_word ? + u8_cs_chg_duplex : u8_duplex; + break; + + case 16: + drv_data->n_bytes = 2; + width = CFG_SPI_WORDSIZE16; + drv_data->read = chip->cs_change_per_word ? + u16_cs_chg_reader : u16_reader; + drv_data->write = chip->cs_change_per_word ? + u16_cs_chg_writer : u16_writer; + drv_data->duplex = chip->cs_change_per_word ? + u16_cs_chg_duplex : u16_duplex; + break; + + default: + /* No change, the same as default setting */ + drv_data->n_bytes = chip->n_bytes; + width = chip->width; + drv_data->write = drv_data->tx ? chip->write : null_writer; + drv_data->read = drv_data->rx ? chip->read : null_reader; + drv_data->duplex = chip->duplex ? chip->duplex : null_writer; + break; + } + cr = (read_CTRL(drv_data) & (~BIT_CTL_TIMOD)); + cr |= (width << 8); + write_CTRL(drv_data, cr); - width = chip->width; if (width == CFG_SPI_WORDSIZE16) { drv_data->len = (transfer->len) >> 1; } else { drv_data->len = transfer->len; } - drv_data->write = drv_data->tx ? chip->write : null_writer; - drv_data->read = drv_data->rx ? chip->read : null_reader; - drv_data->duplex = chip->duplex ? chip->duplex : null_writer; - dev_dbg(&drv_data->pdev->dev, - "transfer: drv_data->write is %p, chip->write is %p, null_wr is %p\n", - drv_data->write, chip->write, null_writer); + dev_dbg(&drv_data->pdev->dev, "transfer: ", + "drv_data->write is %p, chip->write is %p, null_wr is %p\n", + drv_data->write, chip->write, null_writer); /* speed and width has been set on per message */ message->state = RUNNING_STATE; dma_config = 0; - /* restore spi status for each spi transfer */ - if (transfer->speed_hz) { - write_BAUD(hz_to_spi_baud(transfer->speed_hz)); - } else { - write_BAUD(chip->baud); - } - write_FLAG(chip->flag); + /* Speed setup (surely valid because already checked) */ + if (transfer->speed_hz) + write_BAUD(drv_data, hz_to_spi_baud(transfer->speed_hz)); + else + write_BAUD(drv_data, chip->baud); + + write_STAT(drv_data, BIT_STAT_CLR); + cr = (read_CTRL(drv_data) & (~BIT_CTL_TIMOD)); + cs_active(drv_data, chip); dev_dbg(&drv_data->pdev->dev, "now pumping a transfer: width is %d, len is %d\n", @@ -727,25 +806,25 @@ static void pump_transfers(unsigned long data) */ if (drv_data->cur_chip->enable_dma && drv_data->len > 6) { - write_STAT(BIT_STAT_CLR); - disable_dma(CH_SPI); - clear_dma_irqstat(CH_SPI); + disable_dma(drv_data->dma_channel); + clear_dma_irqstat(drv_data->dma_channel); bfin_spi_disable(drv_data); /* config dma channel */ dev_dbg(&drv_data->pdev->dev, "doing dma transfer\n"); if (width == CFG_SPI_WORDSIZE16) { - set_dma_x_count(CH_SPI, drv_data->len); - set_dma_x_modify(CH_SPI, 2); + set_dma_x_count(drv_data->dma_channel, drv_data->len); + set_dma_x_modify(drv_data->dma_channel, 2); dma_width = WDSIZE_16; } else { - set_dma_x_count(CH_SPI, drv_data->len); - set_dma_x_modify(CH_SPI, 1); + set_dma_x_count(drv_data->dma_channel, drv_data->len); + set_dma_x_modify(drv_data->dma_channel, 1); dma_width = WDSIZE_8; } - /* set transfer width,direction. And enable spi */ - cr = (read_CTRL() & (~BIT_CTL_TIMOD)); + /* poll for SPI completion before start */ + while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) + cpu_relax(); /* dirty hack for autobuffer DMA mode */ if (drv_data->tx_dma == 0xFFFF) { @@ -755,13 +834,18 @@ static void pump_transfers(unsigned long data) /* no irq in autobuffer mode */ dma_config = (DMAFLOW_AUTO | RESTART | dma_width | DI_EN); - set_dma_config(CH_SPI, dma_config); - set_dma_start_addr(CH_SPI, (unsigned long)drv_data->tx); - enable_dma(CH_SPI); - write_CTRL(cr | CFG_SPI_DMAWRITE | (width << 8) | - (CFG_SPI_ENABLE << 14)); - - /* just return here, there can only be one transfer in this mode */ + set_dma_config(drv_data->dma_channel, dma_config); + set_dma_start_addr(drv_data->dma_channel, + (unsigned long)drv_data->tx); + enable_dma(drv_data->dma_channel); + + /* start SPI transfer */ + write_CTRL(drv_data, + (cr | CFG_SPI_DMAWRITE | BIT_CTL_ENABLE)); + + /* just return here, there can only be one transfer + * in this mode + */ message->status = 0; giveback(drv_data); return; @@ -772,58 +856,51 @@ static void pump_transfers(unsigned long data) /* set transfer mode, and enable SPI */ dev_dbg(&drv_data->pdev->dev, "doing DMA in.\n"); - /* disable SPI before write to TDBR */ - write_CTRL(cr & ~BIT_CTL_ENABLE); - /* clear tx reg soformer data is not shifted out */ - write_TDBR(0xFF); + write_TDBR(drv_data, 0xFFFF); - set_dma_x_count(CH_SPI, drv_data->len); + set_dma_x_count(drv_data->dma_channel, drv_data->len); /* start dma */ - dma_enable_irq(CH_SPI); + dma_enable_irq(drv_data->dma_channel); dma_config = (WNR | RESTART | dma_width | DI_EN); - set_dma_config(CH_SPI, dma_config); - set_dma_start_addr(CH_SPI, (unsigned long)drv_data->rx); - enable_dma(CH_SPI); + set_dma_config(drv_data->dma_channel, dma_config); + set_dma_start_addr(drv_data->dma_channel, + (unsigned long)drv_data->rx); + enable_dma(drv_data->dma_channel); + + /* start SPI transfer */ + write_CTRL(drv_data, + (cr | CFG_SPI_DMAREAD | BIT_CTL_ENABLE)); - cr |= - CFG_SPI_DMAREAD | (width << 8) | (CFG_SPI_ENABLE << - 14); - /* set transfer mode, and enable SPI */ - write_CTRL(cr); } else if (drv_data->tx != NULL) { dev_dbg(&drv_data->pdev->dev, "doing DMA out.\n"); /* start dma */ - dma_enable_irq(CH_SPI); + dma_enable_irq(drv_data->dma_channel); dma_config = (RESTART | dma_width | DI_EN); - set_dma_config(CH_SPI, dma_config); - set_dma_start_addr(CH_SPI, (unsigned long)drv_data->tx); - enable_dma(CH_SPI); - - write_CTRL(cr | CFG_SPI_DMAWRITE | (width << 8) | - (CFG_SPI_ENABLE << 14)); - + set_dma_config(drv_data->dma_channel, dma_config); + set_dma_start_addr(drv_data->dma_channel, + (unsigned long)drv_data->tx); + enable_dma(drv_data->dma_channel); + + /* start SPI transfer */ + write_CTRL(drv_data, + (cr | CFG_SPI_DMAWRITE | BIT_CTL_ENABLE)); } } else { /* IO mode write then read */ dev_dbg(&drv_data->pdev->dev, "doing IO transfer\n"); - write_STAT(BIT_STAT_CLR); - if (drv_data->tx != NULL && drv_data->rx != NULL) { /* full duplex mode */ BUG_ON((drv_data->tx_end - drv_data->tx) != (drv_data->rx_end - drv_data->rx)); - cr = (read_CTRL() & (~BIT_CTL_TIMOD)); - cr |= CFG_SPI_WRITE | (width << 8) | - (CFG_SPI_ENABLE << 14); dev_dbg(&drv_data->pdev->dev, "IO duplex: cr is 0x%x\n", cr); - write_CTRL(cr); - SSYNC(); + /* set SPI transfer mode */ + write_CTRL(drv_data, (cr | CFG_SPI_WRITE)); drv_data->duplex(drv_data); @@ -831,14 +908,11 @@ static void pump_transfers(unsigned long data) tranf_success = 0; } else if (drv_data->tx != NULL) { /* write only half duplex */ - cr = (read_CTRL() & (~BIT_CTL_TIMOD)); - cr |= CFG_SPI_WRITE | (width << 8) | - (CFG_SPI_ENABLE << 14); - dev_dbg(&drv_data->pdev->dev, + dev_dbg(&drv_data->pdev->dev, "IO write: cr is 0x%x\n", cr); - write_CTRL(cr); - SSYNC(); + /* set SPI transfer mode */ + write_CTRL(drv_data, (cr | CFG_SPI_WRITE)); drv_data->write(drv_data); @@ -846,14 +920,11 @@ static void pump_transfers(unsigned long data) tranf_success = 0; } else if (drv_data->rx != NULL) { /* read only half duplex */ - cr = (read_CTRL() & (~BIT_CTL_TIMOD)); - cr |= CFG_SPI_READ | (width << 8) | - (CFG_SPI_ENABLE << 14); - dev_dbg(&drv_data->pdev->dev, + dev_dbg(&drv_data->pdev->dev, "IO read: cr is 0x%x\n", cr); - write_CTRL(cr); - SSYNC(); + /* set SPI transfer mode */ + write_CTRL(drv_data, (cr | CFG_SPI_READ)); drv_data->read(drv_data); if (drv_data->rx != drv_data->rx_end) @@ -861,7 +932,7 @@ static void pump_transfers(unsigned long data) } if (!tranf_success) { - dev_dbg(&drv_data->pdev->dev, + dev_dbg(&drv_data->pdev->dev, "IO write error!\n"); message->state = ERROR_STATE; } else { @@ -881,9 +952,11 @@ static void pump_transfers(unsigned long data) /* pop a msg from queue and kick off real transfer */ static void pump_messages(struct work_struct *work) { - struct driver_data *drv_data = container_of(work, struct driver_data, pump_messages); + struct driver_data *drv_data; unsigned long flags; + drv_data = container_of(work, struct driver_data, pump_messages); + /* Lock queue and check for queue work */ spin_lock_irqsave(&drv_data->lock, flags); if (list_empty(&drv_data->queue) || drv_data->run == QUEUE_STOPPED) { @@ -902,6 +975,14 @@ static void pump_messages(struct work_struct *work) /* Extract head of queue */ drv_data->cur_msg = list_entry(drv_data->queue.next, struct spi_message, queue); + + /* Setup the SSP using the per chip configuration */ + drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi); + if (restore_state(drv_data)) { + spin_unlock_irqrestore(&drv_data->lock, flags); + return; + }; + list_del_init(&drv_data->cur_msg->queue); /* Initial message state */ @@ -909,15 +990,12 @@ static void pump_messages(struct work_struct *work) drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next, struct spi_transfer, transfer_list); - /* Setup the SSP using the per chip configuration */ - drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi); - restore_state(drv_data); + dev_dbg(&drv_data->pdev->dev, "got a message to pump, " + "state is set to: baud %d, flag 0x%x, ctl 0x%x\n", + drv_data->cur_chip->baud, drv_data->cur_chip->flag, + drv_data->cur_chip->ctl_reg); + dev_dbg(&drv_data->pdev->dev, - "got a message to pump, state is set to: baud %d, flag 0x%x, ctl 0x%x\n", - drv_data->cur_chip->baud, drv_data->cur_chip->flag, - drv_data->cur_chip->ctl_reg); - - dev_dbg(&drv_data->pdev->dev, "the first transfer len is %d\n", drv_data->cur_transfer->len); @@ -959,6 +1037,22 @@ static int transfer(struct spi_device *spi, struct spi_message *msg) return 0; } +#define MAX_SPI_SSEL 7 + +static u16 ssel[3][MAX_SPI_SSEL] = { + {P_SPI0_SSEL1, P_SPI0_SSEL2, P_SPI0_SSEL3, + P_SPI0_SSEL4, P_SPI0_SSEL5, + P_SPI0_SSEL6, P_SPI0_SSEL7}, + + {P_SPI1_SSEL1, P_SPI1_SSEL2, P_SPI1_SSEL3, + P_SPI1_SSEL4, P_SPI1_SSEL5, + P_SPI1_SSEL6, P_SPI1_SSEL7}, + + {P_SPI2_SSEL1, P_SPI2_SSEL2, P_SPI2_SSEL3, + P_SPI2_SSEL4, P_SPI2_SSEL5, + P_SPI2_SSEL6, P_SPI2_SSEL7}, +}; + /* first setup for new devices */ static int setup(struct spi_device *spi) { @@ -993,6 +1087,18 @@ static int setup(struct spi_device *spi) /* chip_info isn't always needed */ if (chip_info) { + /* Make sure people stop trying to set fields via ctl_reg + * when they should actually be using common SPI framework. + * Currently we let through: WOM EMISO PSSE GM SZ TIMOD. + * Not sure if a user actually needs/uses any of these, + * but let's assume (for now) they do. + */ + if (chip_info->ctl_reg & (SPE|MSTR|CPOL|CPHA|LSBF|SIZE)) { + dev_err(&spi->dev, "do not set bits in ctl_reg " + "that the SPI framework manages\n"); + return -EINVAL; + } + chip->enable_dma = chip_info->enable_dma != 0 && drv_data->master_info->enable_dma; chip->ctl_reg = chip_info->ctl_reg; @@ -1015,20 +1121,20 @@ static int setup(struct spi_device *spi) * if any one SPI chip is registered and wants DMA, request the * DMA channel for it */ - if (chip->enable_dma && !dma_requested) { + if (chip->enable_dma && !drv_data->dma_requested) { /* register dma irq handler */ - if (request_dma(CH_SPI, "BF53x_SPI_DMA") < 0) { + if (request_dma(drv_data->dma_channel, "BF53x_SPI_DMA") < 0) { dev_dbg(&spi->dev, "Unable to request BlackFin SPI DMA channel\n"); return -ENODEV; } - if (set_dma_callback(CH_SPI, (void *)dma_irq_handler, drv_data) - < 0) { + if (set_dma_callback(drv_data->dma_channel, + (void *)dma_irq_handler, drv_data) < 0) { dev_dbg(&spi->dev, "Unable to set dma callback\n"); return -EPERM; } - dma_disable_irq(CH_SPI); - dma_requested = 1; + dma_disable_irq(drv_data->dma_channel); + drv_data->dma_requested = 1; } /* @@ -1077,6 +1183,14 @@ static int setup(struct spi_device *spi) spi_set_ctldata(spi, chip); + dev_dbg(&spi->dev, "chip select number is %d\n", chip->chip_select_num); + if ((chip->chip_select_num > 0) + && (chip->chip_select_num <= spi->master->num_chipselect)) + peripheral_request(ssel[spi->master->bus_num] + [chip->chip_select_num-1], DRV_NAME); + + cs_deactive(drv_data, chip); + return 0; } @@ -1088,6 +1202,11 @@ static void cleanup(struct spi_device *spi) { struct chip_data *chip = spi_get_ctldata(spi); + if ((chip->chip_select_num > 0) + && (chip->chip_select_num <= spi->master->num_chipselect)) + peripheral_free(ssel[spi->master->bus_num] + [chip->chip_select_num-1]); + kfree(chip); } @@ -1183,6 +1302,7 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev) struct bfin5xx_spi_master *platform_info; struct spi_master *master; struct driver_data *drv_data = 0; + struct resource *res; int status = 0; platform_info = dev->platform_data; @@ -1193,10 +1313,12 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev) dev_err(&pdev->dev, "can not alloc spi_master\n"); return -ENOMEM; } + drv_data = spi_master_get_devdata(master); drv_data->master = master; drv_data->master_info = platform_info; drv_data->pdev = pdev; + drv_data->pin_req = platform_info->pin_req; master->bus_num = pdev->id; master->num_chipselect = platform_info->num_chipselect; @@ -1204,15 +1326,38 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev) master->setup = setup; master->transfer = transfer; + /* Find and map our resources */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(dev, "Cannot get IORESOURCE_MEM\n"); + status = -ENOENT; + goto out_error_get_res; + } + + drv_data->regs_base = ioremap(res->start, (res->end - res->start + 1)); + if (drv_data->regs_base == NULL) { + dev_err(dev, "Cannot map IO\n"); + status = -ENXIO; + goto out_error_ioremap; + } + + drv_data->dma_channel = platform_get_irq(pdev, 0); + if (drv_data->dma_channel < 0) { + dev_err(dev, "No DMA channel specified\n"); + status = -ENOENT; + goto out_error_no_dma_ch; + } + /* Initial and start queue */ status = init_queue(drv_data); if (status != 0) { - dev_err(&pdev->dev, "problem initializing queue\n"); + dev_err(dev, "problem initializing queue\n"); goto out_error_queue_alloc; } + status = start_queue(drv_data); if (status != 0) { - dev_err(&pdev->dev, "problem starting queue\n"); + dev_err(dev, "problem starting queue\n"); goto out_error_queue_alloc; } @@ -1220,15 +1365,30 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, drv_data); status = spi_register_master(master); if (status != 0) { - dev_err(&pdev->dev, "problem registering spi master\n"); + dev_err(dev, "problem registering spi master\n"); goto out_error_queue_alloc; } - dev_dbg(&pdev->dev, "controller probe successfully\n"); + + status = peripheral_request_list(drv_data->pin_req, DRV_NAME); + if (status != 0) { + dev_err(&pdev->dev, ": Requesting Peripherals failed\n"); + goto out_error; + } + + dev_info(dev, "%s, Version %s, regs_base@%p, dma channel@%d\n", + DRV_DESC, DRV_VERSION, drv_data->regs_base, + drv_data->dma_channel); return status; - out_error_queue_alloc: +out_error_queue_alloc: destroy_queue(drv_data); +out_error_no_dma_ch: + iounmap((void *) drv_data->regs_base); +out_error_ioremap: +out_error_get_res: +out_error: spi_master_put(master); + return status; } @@ -1251,13 +1411,15 @@ static int __devexit bfin5xx_spi_remove(struct platform_device *pdev) /* Release DMA */ if (drv_data->master_info->enable_dma) { - if (dma_channel_active(CH_SPI)) - free_dma(CH_SPI); + if (dma_channel_active(drv_data->dma_channel)) + free_dma(drv_data->dma_channel); } /* Disconnect from the SPI framework */ spi_unregister_master(drv_data->master); + peripheral_free_list(drv_data->pin_req); + /* Prevent double remove */ platform_set_drvdata(pdev, NULL); @@ -1305,7 +1467,7 @@ static int bfin5xx_spi_resume(struct platform_device *pdev) MODULE_ALIAS("bfin-spi-master"); /* for platform bus hotplug */ static struct platform_driver bfin5xx_spi_driver = { .driver = { - .name = "bfin-spi-master", + .name = DRV_NAME, .owner = THIS_MODULE, }, .suspend = bfin5xx_spi_suspend, diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c index 81639c6be1c..f7f8580edad 100644 --- a/drivers/spi/spi_bitbang.c +++ b/drivers/spi/spi_bitbang.c @@ -184,6 +184,7 @@ int spi_bitbang_setup(struct spi_device *spi) struct spi_bitbang_cs *cs = spi->controller_state; struct spi_bitbang *bitbang; int retval; + unsigned long flags; bitbang = spi_master_get_devdata(spi->master); @@ -222,12 +223,12 @@ int spi_bitbang_setup(struct spi_device *spi) */ /* deselect chip (low or high) */ - spin_lock(&bitbang->lock); + spin_lock_irqsave(&bitbang->lock, flags); if (!bitbang->busy) { bitbang->chipselect(spi, BITBANG_CS_INACTIVE); ndelay(cs->nsecs); } - spin_unlock(&bitbang->lock); + spin_unlock_irqrestore(&bitbang->lock, flags); return 0; } diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c index 7686ba34430..2cd8573fb09 100644 --- a/drivers/spi/spi_imx.c +++ b/drivers/spi/spi_imx.c @@ -1758,5 +1758,5 @@ static void __exit spi_imx_exit(void) module_exit(spi_imx_exit); MODULE_AUTHOR("Andrea Paterniani, <a.paterniani@swapp-eng.it>"); -MODULE_DESCRIPTION("iMX SPI Contoller Driver"); +MODULE_DESCRIPTION("iMX SPI Controller Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c index 0fa25e2e80f..109d82c1abc 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 cc5094f37dd..363ac8e6882 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/spidev.c b/drivers/spi/spidev.c index c55459c592b..b3518ca9f04 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -184,14 +184,14 @@ static int spidev_message(struct spidev_data *spidev, if (u_tmp->rx_buf) { k_tmp->rx_buf = buf; if (!access_ok(VERIFY_WRITE, (u8 __user *) - (ptrdiff_t) u_tmp->rx_buf, + (uintptr_t) u_tmp->rx_buf, u_tmp->len)) goto done; } if (u_tmp->tx_buf) { k_tmp->tx_buf = buf; if (copy_from_user(buf, (const u8 __user *) - (ptrdiff_t) u_tmp->tx_buf, + (uintptr_t) u_tmp->tx_buf, u_tmp->len)) goto done; } @@ -224,7 +224,7 @@ static int spidev_message(struct spidev_data *spidev, for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) { if (u_tmp->rx_buf) { if (__copy_to_user((u8 __user *) - (ptrdiff_t) u_tmp->rx_buf, buf, + (uintptr_t) u_tmp->rx_buf, buf, u_tmp->len)) { status = -EFAULT; goto done; diff --git a/drivers/spi/tle62x0.c b/drivers/spi/tle62x0.c index 6da58ca48b3..455991fbe28 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 c12a741b557..85a20546e82 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 b6abee846f0..bb44a76b3eb 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/ssb/scan.c b/drivers/ssb/scan.c index 96258c60919..63ee5cfbefb 100644 --- a/drivers/ssb/scan.c +++ b/drivers/ssb/scan.c @@ -388,6 +388,17 @@ int ssb_bus_scan(struct ssb_bus *bus, case SSB_DEV_PCI: case SSB_DEV_PCIE: #ifdef CONFIG_SSB_DRIVER_PCICORE + if (bus->bustype == SSB_BUSTYPE_PCI) { + /* Ignore PCI cores on PCI-E cards. + * Ignore PCI-E cores on PCI cards. */ + if (dev->id.coreid == SSB_DEV_PCI) { + if (bus->host_pci->is_pcie) + continue; + } else { + if (!bus->host_pci->is_pcie) + continue; + } + } if (bus->pcicore.dev) { ssb_printk(KERN_WARNING PFX "WARNING: Multiple PCI(E) cores found\n"); diff --git a/drivers/telephony/phonedev.c b/drivers/telephony/phonedev.c index 4d8c2a5b329..bcea8d9b718 100644 --- a/drivers/telephony/phonedev.c +++ b/drivers/telephony/phonedev.c @@ -120,9 +120,8 @@ int phone_register_device(struct phone_device *p, int unit) void phone_unregister_device(struct phone_device *pfd) { mutex_lock(&phone_lock); - if (phone_device[pfd->minor] != pfd) - panic("phone: bad unregister"); - phone_device[pfd->minor] = NULL; + if (likely(phone_device[pfd->minor] == pfd)) + phone_device[pfd->minor] = NULL; mutex_unlock(&phone_lock); } diff --git a/drivers/usb/README b/drivers/usb/README index 3c843412855..284f46b3e1c 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/buffer.c b/drivers/usb/core/buffer.c index ead2475406b..28d4972f7ad 100644 --- a/drivers/usb/core/buffer.c +++ b/drivers/usb/core/buffer.c @@ -11,7 +11,6 @@ #include <linux/device.h> #include <linux/mm.h> #include <asm/io.h> -#include <asm/scatterlist.h> #include <linux/dma-mapping.h> #include <linux/dmapool.h> #include <linux/usb.h> diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 8586817698a..c51f8e9312e 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-pci.c b/drivers/usb/core/hcd-pci.c index 5cf6d5f9acb..3fb9af80cbf 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -125,7 +125,7 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) pci_set_master (dev); - retval = usb_add_hcd (hcd, dev->irq, IRQF_SHARED); + retval = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED); if (retval != 0) goto err4; return retval; diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 3dd997df850..d5ed3fa9e30 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -30,7 +30,6 @@ #include <linux/utsname.h> #include <linux/mm.h> #include <asm/io.h> -#include <asm/scatterlist.h> #include <linux/device.h> #include <linux/dma-mapping.h> #include <linux/mutex.h> @@ -1312,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; @@ -1346,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 036c3dea855..b04d232d4c6 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); } @@ -522,9 +522,9 @@ static void hub_quiesce(struct usb_hub *hub) /* (blocking) stop khubd and related activity */ usb_kill_urb(hub->urb); if (hub->has_indicators) - cancel_delayed_work(&hub->leds); - if (hub->has_indicators || hub->tt.hub) - flush_scheduled_work(); + cancel_delayed_work_sync(&hub->leds); + if (hub->tt.hub) + cancel_work_sync(&hub->tt.kevent); } static void hub_activate(struct usb_hub *hub) diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index eb4ac47612a..fcd40ecbeec 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -434,7 +434,7 @@ int usb_sg_init ( if (dma) { io->urbs [i]->transfer_dma = sg_dma_address (sg + i); len = sg_dma_len (sg + i); -#if defined(CONFIG_HIGHMEM) || defined(CONFIG_IOMMU) +#if defined(CONFIG_HIGHMEM) || defined(CONFIG_GART_IOMMU) io->urbs[i]->transfer_buffer = NULL; #else io->urbs[i]->transfer_buffer = sg_virt(&sg[i]); @@ -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 b04afd06e50..32bd130b1ee 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 69aa68287d3..8f142370103 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -36,7 +36,7 @@ #include <linux/workqueue.h> #include <asm/io.h> -#include <asm/scatterlist.h> +#include <linux/scatterlist.h> #include <linux/mm.h> #include <linux/dma-mapping.h> @@ -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/at91_udc.c b/drivers/usb/gadget/at91_udc.c index a6adf7e0f6f..cd62b029d17 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -887,6 +887,7 @@ static void pullup(struct at91_udc *udc, int is_on) if (is_on) { clk_on(udc); + at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM); at91_udp_write(udc, AT91_UDP_TXVC, 0); if (cpu_is_at91rm9200()) at91_set_gpio_value(udc->board.pullup_pin, 1); @@ -904,6 +905,7 @@ static void pullup(struct at91_udc *udc, int is_on) } } else { stop_activity(udc); + at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM); at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); if (cpu_is_at91rm9200()) at91_set_gpio_value(udc->board.pullup_pin, 0); diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c index 9bb7f64a85c..038e7d7b4da 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.c +++ b/drivers/usb/gadget/fsl_usb2_udc.c @@ -1318,7 +1318,7 @@ static void setup_received_irq(struct fsl_udc *udc, | USB_TYPE_STANDARD)) { /* Note: The driver has not include OTG support yet. * This will be set when OTG support is added */ - if (!gadget_is_otg(udc->gadget)) + if (!gadget_is_otg(&udc->gadget)) break; else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE) udc->gadget.b_hnp_enable = 1; diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 87c4f50dfb6..d377154658b 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 e3e90f8a75e..4ce050c3d13 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 177e78ed241..49a91c5ee51 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-fsl.c b/drivers/usb/host/ehci-fsl.c index b7b7bfbce52..430821cb95c 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -122,7 +122,7 @@ int usb_hcd_fsl_probe(const struct hc_driver *driver, temp = in_le32(hcd->regs + 0x1a8); out_le32(hcd->regs + 0x1a8, temp | 0x3); - retval = usb_add_hcd(hcd, irq, IRQF_SHARED); + retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); if (retval != 0) goto err4; return retval; diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index c1514442883..5f2d74ed5ad 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/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 704f33fdd2f..ecfe800fd72 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -732,24 +732,27 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd) struct ohci_regs __iomem *regs = ohci->regs; int ints; - /* we can eliminate a (slow) ohci_readl() - * if _only_ WDH caused this irq + /* Read interrupt status (and flush pending writes). We ignore the + * optimization of checking the LSB of hcca->done_head; it doesn't + * work on all systems (edge triggering for OHCI can be a factor). */ - if ((ohci->hcca->done_head != 0) - && ! (hc32_to_cpup (ohci, &ohci->hcca->done_head) - & 0x01)) { - ints = OHCI_INTR_WDH; + ints = ohci_readl(ohci, ®s->intrstatus); - /* cardbus/... hardware gone before remove() */ - } else if ((ints = ohci_readl (ohci, ®s->intrstatus)) == ~(u32)0) { + /* Check for an all 1's result which is a typical consequence + * of dead, unclocked, or unplugged (CardBus...) devices + */ + if (ints == ~(u32)0) { disable (ohci); ohci_dbg (ohci, "device removed!\n"); return IRQ_HANDLED; + } + + /* We only care about interrupts that are enabled */ + ints &= ohci_readl(ohci, ®s->intrenable); /* interrupt for some other device? */ - } else if ((ints &= ohci_readl (ohci, ®s->intrenable)) == 0) { + if (ints == 0) return IRQ_NOTMINE; - } if (ints & OHCI_INTR_UE) { // e.g. due to PCI Master/Target Abort diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c index 0a742692015..0c3e6b790b7 100644 --- a/drivers/usb/host/ohci-ppc-of.c +++ b/drivers/usb/host/ohci-ppc-of.c @@ -142,7 +142,7 @@ ohci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match) ohci_hcd_init(ohci); - rv = usb_add_hcd(hcd, irq, 0); + rv = usb_add_hcd(hcd, irq, IRQF_DISABLED); if (rv == 0) return 0; diff --git a/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c index fe70e72340d..6e9c2d6db88 100644 --- a/drivers/usb/host/ohci-ssb.c +++ b/drivers/usb/host/ohci-ssb.c @@ -160,7 +160,7 @@ static int ssb_ohci_attach(struct ssb_device *dev) hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) goto err_put_hcd; - err = usb_add_hcd(hcd, dev->irq, IRQF_SHARED); + err = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED); if (err) goto err_iounmap; diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index ae8ec4474eb..0ce2fc5e396 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -2197,7 +2197,7 @@ static int __init r8a66597_probe(struct platform_device *pdev) INIT_LIST_HEAD(&r8a66597->child_device); hcd->rsrc_start = res->start; - ret = usb_add_hcd(hcd, irq, 0); + ret = usb_add_hcd(hcd, irq, IRQF_DISABLED); if (ret != 0) { err("Failed to add hcd"); goto clean_up; diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 4db17f75f4f..ec987897b8e 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -378,7 +378,6 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) { struct uhci_hcd *uhci = hcd_to_uhci(hcd); unsigned short status; - unsigned long flags; /* * Read the interrupt status, and write it back to clear the @@ -398,7 +397,7 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) dev_err(uhci_dev(uhci), "host controller process " "error, something bad happened!\n"); if (status & USBSTS_HCH) { - spin_lock_irqsave(&uhci->lock, flags); + spin_lock(&uhci->lock); if (uhci->rh_state >= UHCI_RH_RUNNING) { dev_err(uhci_dev(uhci), "host controller halted, " @@ -415,16 +414,16 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) * pending unlinks */ mod_timer(&hcd->rh_timer, jiffies); } - spin_unlock_irqrestore(&uhci->lock, flags); + spin_unlock(&uhci->lock); } } if (status & USBSTS_RD) usb_hcd_poll_rh_status(hcd); else { - spin_lock_irqsave(&uhci->lock, flags); + spin_lock(&uhci->lock); uhci_scan_schedule(uhci); - spin_unlock_irqrestore(&uhci->lock, flags); + spin_unlock(&uhci->lock); } return IRQ_HANDLED; diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c index 91e999c9f68..bc207e3c21f 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 c567aa7a41e..5a2c44e4c1f 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 49c5c5c4c43..06cb71942dc 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/cp2101.c b/drivers/usb/serial/cp2101.c index 3a83cb4c4bc..22833589c4b 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -55,6 +55,7 @@ static int debug; static struct usb_device_id id_table [] = { { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */ { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */ + { USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */ { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */ { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */ @@ -71,6 +72,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */ { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */ + { USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */ { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ @@ -98,8 +100,8 @@ static struct usb_serial_driver cp2101_device = { .usb_driver = &cp2101_driver, .id_table = id_table, .num_interrupt_in = 0, - .num_bulk_in = 0, - .num_bulk_out = 0, + .num_bulk_in = NUM_DONT_CARE, + .num_bulk_out = NUM_DONT_CARE, .num_ports = 1, .open = cp2101_open, .close = cp2101_close, diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 9eb4a65ee4d..d41531139c5 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 6bfdba6a213..feba9679ace 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 a5ced7e08cb..c29c9127113 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/option.c b/drivers/usb/serial/option.c index 4590124cf88..d1185f53447 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -158,8 +158,8 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_MODEM) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_NETWORK) }, { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, - { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) }, - { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1100) }, /* Novatel Merlin XS620/S640 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1110) }, /* Novatel Merlin S620 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1120) }, /* Novatel Merlin EX720 */ diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 2cd3f1d4b68..0da1df9c79b 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 */ }; @@ -482,6 +483,13 @@ static void pl2303_set_termios(struct usb_serial_port *port, } spin_unlock_irqrestore(&priv->lock, flags); + /* The PL2303 is reported to lose bytes if you change + serial settings even to the same values as before. Thus + we actually need to filter in this specific case */ + + if (!tty_termios_hw_change(port->tty->termios, old_termios)) + return; + cflag = port->tty->termios->c_cflag; buf = kzalloc(7, GFP_KERNEL); diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index ed603e3decd..d31f5d29998 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 833f6e1e372..c295d0495f9 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -100,6 +100,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x0f30, 0x1b1d) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x1199, 0x0020) }, /* 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 */ @@ -108,6 +109,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */ { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 & AC 875U */ + { USB_DEVICE(0x1199, 0x6813) }, /* Sierra Wireless MC8775 (Thinkpad internal) */ { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */ { USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780*/ { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781*/ @@ -136,6 +138,7 @@ 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, 0x0019) }, /* Sierra Wireless AirCard 595 */ { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */ { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U*/ @@ -144,6 +147,7 @@ static struct usb_device_id id_table_3port [] = { { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */ { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 & AC 875U */ + { USB_DEVICE(0x1199, 0x6813) }, /* Sierra Wireless MC8775 (Thinkpad internal) */ { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */ { USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780*/ { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781*/ diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 1ba19eaa197..7c9593b7b04 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -114,9 +114,15 @@ static int slave_configure(struct scsi_device *sdev) * while others have trouble with more than 64K. At this time we * are limiting both to 32K (64 sectores). */ - if ((us->flags & US_FL_MAX_SECTORS_64) && - sdev->request_queue->max_sectors > 64) - blk_queue_max_sectors(sdev->request_queue, 64); + if (us->flags & (US_FL_MAX_SECTORS_64 | US_FL_MAX_SECTORS_MIN)) { + unsigned int max_sectors = 64; + + if (us->flags & US_FL_MAX_SECTORS_MIN) + max_sectors = PAGE_CACHE_SIZE >> 9; + if (sdev->request_queue->max_sectors > max_sectors) + blk_queue_max_sectors(sdev->request_queue, + max_sectors); + } /* We can't put these settings in slave_alloc() because that gets * called before the device type is known. Consequently these @@ -177,6 +183,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 22ab2380367..6d6108b3993 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, @@ -376,6 +376,13 @@ UNUSUAL_DEV( 0x04b0, 0x0417, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), +/* Reported by Doug Maxey (dwm@austin.ibm.com) */ +UNUSUAL_DEV( 0x04b3, 0x4001, 0x0110, 0x0110, + "IBM", + "IBM RSA2", + US_SC_DEVICE, US_PR_CB, NULL, + US_FL_MAX_SECTORS_MIN), + /* BENQ DC5330 * Reported by Manuel Fombuena <mfombuena@ya.com> and * Frank Copeland <fjc@thingy.apana.org.au> */ @@ -731,6 +738,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", @@ -1251,14 +1265,6 @@ UNUSUAL_DEV( 0x0ace, 0x20ff, 0x0101, 0x0101, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_DEVICE ), -/* SanDisk that has a second LUN for a driver ISO, reported by - * Ben Collins <bcollins@ubuntu.com> */ -UNUSUAL_DEV( 0x0781, 0x5406, 0x0000, 0xffff, - "SanDisk", - "U3 Cruzer Micro driver ISO", - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_SINGLE_LUN ), - #ifdef CONFIG_USB_STORAGE_ISD200 UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110, "ATI", diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index fb9d8d0b2c0..5b3dbcfcda4 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 @@ -1509,7 +1520,7 @@ config FB_VOODOO1 WARNING: Do not use any application that uses the 3D engine (namely glide) while using this driver. - Please read the <file:Documentation/fb/README-sstfb.txt> for supported + Please read the <file:Documentation/fb/sstfb.txt> for supported options and other important info support. config FB_VT8623 @@ -1807,7 +1818,7 @@ config FB_SM501 This driver is also available as a module ( = code which can be inserted and removed from the running kernel whenever you want). The module will be called sm501fb. If you want to compile it as a module, - say M here and read <file:Documentation/modules.txt>. + say M here and read <file:Documentation/kbuild/modules.txt>. If unsure, say N. @@ -1892,9 +1903,7 @@ config FB_VIRTUAL If unsure, say N. -if ARCH_OMAP - source "drivers/video/omap/Kconfig" -endif +source "drivers/video/omap/Kconfig" source "drivers/video/backlight/Kconfig" source "drivers/video/display/Kconfig" diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 59d6c45a910..83e02b3429b 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 235b618b411..7c30cc8df71 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) @@ -797,5 +801,5 @@ module_init(atmel_lcdfb_init); module_exit(atmel_lcdfb_exit); MODULE_DESCRIPTION("AT91/AT32 LCD Controller framebuffer driver"); -MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@rfo.atmel.com>"); +MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@atmel.com>"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 1e32b3d13f2..62867cb63fe 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/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index be1d57bf9dc..83ee3e75386 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c @@ -27,8 +27,6 @@ #include "ati_ids.h" -static void radeon_reinitialize_M10(struct radeonfb_info *rinfo); - /* * Workarounds for bugs in PC laptops: * - enable D2 sleep in some IBM Thinkpads @@ -39,6 +37,8 @@ static void radeon_reinitialize_M10(struct radeonfb_info *rinfo); */ #if defined(CONFIG_PM) && defined(CONFIG_X86) +static void radeon_reinitialize_M10(struct radeonfb_info *rinfo); + struct radeon_device_id { const char *ident; /* (arbitrary) Name */ const unsigned short subsystem_vendor; /* Subsystem Vendor ID */ diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index f99cb77e7b4..f7e2d5add83 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -2509,8 +2509,7 @@ static int cirrusfb_zorro_register(struct zorro_dev *z, cinfo = info->par; cinfo->btype = btype; - assert(z > 0); - assert(z2 >= 0); + assert(z); assert(btype != BT_NONE); cinfo->zdev = z; diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index 267422f6625..b87ed37ac0c 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 5fb8675e0d6..d0e4cb61826 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 00000000000..bd779ae44b1 --- /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 f836137a0ed..a0df63289b5 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 b9b572b293d..2e552d5bbb5 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 6c227f9592a..ca13c48d19b 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 6455fd2a39f..9366ef2bb5f 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/modedb.c b/drivers/video/modedb.c index 8d81ef019c6..08d07255223 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c @@ -259,6 +259,10 @@ static const struct fb_videomode modedb[] = { /* 1366x768, 60 Hz, 47.403 kHz hsync, WXGA 16:9 aspect ratio */ NULL, 60, 1366, 768, 13806, 120, 10, 14, 3, 32, 5, 0, FB_VMODE_NONINTERLACED + }, { + /* 1280x800, 60 Hz, 47.403 kHz hsync, WXGA 16:10 aspect ratio */ + NULL, 60, 1280, 800, 12048, 200, 64, 24, 1, 136, 3, + 0, FB_VMODE_NONINTERLACED }, }; diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig index f4fcf11b290..44408850e2e 100644 --- a/drivers/video/omap/Kconfig +++ b/drivers/video/omap/Kconfig @@ -1,6 +1,6 @@ config FB_OMAP tristate "OMAP frame buffer support (EXPERIMENTAL)" - depends on FB + depends on FB && ARCH_OMAP select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c index b3463ddcfd6..044a423a72c 100644 --- a/drivers/video/ps3fb.c +++ b/drivers/video/ps3fb.c @@ -51,8 +51,8 @@ #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_CMD_BUF_SIZE (2 * 1024 * 1024) +#define GPU_FB_START (64 * 1024) #define GPU_IOIF (0x0d000000UL) #define GPU_ALIGN_UP(x) _ALIGN_UP((x), 64) #define GPU_MAX_LINE_LENGTH (65536 - 64) @@ -407,6 +407,7 @@ static void ps3fb_sync_image(struct device *dev, u64 frame_offset, if (src_line_length != dst_line_length) line_length |= (u64)src_line_length << 32; + src_offset += GPU_FB_START; status = lv1_gpu_context_attribute(ps3fb.context_handle, L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, dst_offset, GPU_IOIF + src_offset, @@ -442,8 +443,6 @@ static int ps3fb_sync(struct fb_info *info, u32 frame) u32 ddr_line_length, xdr_line_length; u64 ddr_base, xdr_base; - acquire_console_sem(); - if (frame > par->num_frames - 1) { dev_dbg(info->device, "%s: invalid frame number (%u)\n", __func__, frame); @@ -463,7 +462,6 @@ static int ps3fb_sync(struct fb_info *info, u32 frame) xdr_line_length); out: - release_console_sem(); return error; } @@ -478,7 +476,10 @@ static int ps3fb_release(struct fb_info *info, int user) if (atomic_dec_and_test(&ps3fb.f_count)) { if (atomic_read(&ps3fb.ext_flip)) { atomic_set(&ps3fb.ext_flip, 0); - ps3fb_sync(info, 0); /* single buffer */ + if (!try_acquire_console_sem()) { + ps3fb_sync(info, 0); /* single buffer */ + release_console_sem(); + } } } return 0; @@ -727,7 +728,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; } @@ -864,7 +865,9 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd, break; dev_dbg(info->device, "PS3FB_IOCTL_FSEL:%d\n", val); + acquire_console_sem(); retval = ps3fb_sync(info, val); + release_console_sem(); break; default: @@ -884,7 +887,9 @@ static int ps3fbd(void *arg) set_current_state(TASK_INTERRUPTIBLE); if (ps3fb.is_kicked) { ps3fb.is_kicked = 0; + acquire_console_sem(); ps3fb_sync(info, 0); /* single buffer */ + release_console_sem(); } schedule(); } @@ -977,9 +982,8 @@ static int ps3fb_xdr_settings(u64 xdr_lpar, struct device *dev) status = lv1_gpu_context_attribute(ps3fb.context_handle, L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP, - xdr_lpar + ps3fb.xdr_size, - GPU_CMD_BUF_SIZE, - GPU_IOIF + ps3fb.xdr_size, 0); + xdr_lpar, GPU_CMD_BUF_SIZE, + GPU_IOIF, 0); if (status) { dev_err(dev, "%s: lv1_gpu_context_attribute FB_SETUP failed: %d\n", @@ -1060,6 +1064,12 @@ 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; + + if (ps3fb_videomemory.size < GPU_CMD_BUF_SIZE) { + dev_err(&dev->core, "%s: Not enough video memory\n", __func__); + return -ENOMEM; + } status = ps3_open_hv_device(dev); if (status) { @@ -1085,8 +1095,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", @@ -1124,8 +1141,14 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) /* Clear memory to prevent kernel info leakage into userspace */ memset(ps3fb.xdr_ea, 0, ps3fb_videomemory.size); - /* The GPU command buffer is at the end of video memory */ - ps3fb.xdr_size = ps3fb_videomemory.size - GPU_CMD_BUF_SIZE; + /* + * The GPU command buffer is at the start of video memory + * As we don't use the full command buffer, we can put the actual + * frame buffer at offset GPU_FB_START and save some precious XDR + * memory + */ + ps3fb.xdr_ea += GPU_FB_START; + ps3fb.xdr_size = ps3fb_videomemory.size - GPU_FB_START; retval = ps3fb_xdr_settings(xdr_lpar, &dev->core); if (retval) @@ -1193,7 +1216,7 @@ err_fb_dealloc: err_framebuffer_release: framebuffer_release(info); err_free_irq: - free_irq(ps3fb.irq_no, dev); + free_irq(ps3fb.irq_no, &dev->core); ps3_irq_plug_destroy(ps3fb.irq_no); err_iounmap_dinfo: iounmap((u8 __iomem *)ps3fb.dinfo); @@ -1215,12 +1238,6 @@ static int ps3fb_shutdown(struct ps3_system_bus_device *dev) ps3fb_flip_ctl(0, &ps3fb); /* flip off */ ps3fb.dinfo->irq.mask = 0; - if (info) { - unregister_framebuffer(info); - fb_dealloc_cmap(&info->cmap); - framebuffer_release(info); - } - ps3av_register_flip_ctl(NULL, NULL); if (ps3fb.task) { struct task_struct *task = ps3fb.task; @@ -1228,9 +1245,15 @@ static int ps3fb_shutdown(struct ps3_system_bus_device *dev) kthread_stop(task); } if (ps3fb.irq_no) { - free_irq(ps3fb.irq_no, dev); + free_irq(ps3fb.irq_no, &dev->core); ps3_irq_plug_destroy(ps3fb.irq_no); } + if (info) { + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); + framebuffer_release(info); + info = dev->core.driver_data = NULL; + } iounmap((u8 __iomem *)ps3fb.dinfo); status = lv1_gpu_context_free(ps3fb.context_handle); diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c index a5333c19078..b829dc7c5ed 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/s3c2410fb.c b/drivers/video/s3c2410fb.c index 5857ccf5f6b..ad35033f1a4 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c @@ -1026,7 +1026,7 @@ static int s3c2410fb_resume(struct platform_device *dev) clk_enable(info->clk); msleep(1); - s3c2410fb_init_registers(info); + s3c2410fb_init_registers(fbinfo); return 0; } diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index bc7d2368373..37bd24b8d83 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 b983d262ab7..a14ef894d57 100644 --- a/drivers/video/uvesafb.c +++ b/drivers/video/uvesafb.c @@ -43,7 +43,7 @@ static struct fb_fix_screeninfo uvesafb_fix __devinitdata = { }; static int mtrr __devinitdata = 3; /* enable mtrr by default */ -static int blank __devinitdata = 1; /* enable blanking by default */ +static int blank = 1; /* enable blanking by default */ static int ypan __devinitdata = 1; /* 0: scroll, 1: ypan, 2: ywrap */ static int pmi_setpal __devinitdata = 1; /* use PMI for palette changes */ static int nocrtc __devinitdata; /* ignore CRTC settings */ @@ -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; @@ -1547,7 +1549,7 @@ static void __devinit uvesafb_init_info(struct fb_info *info, info->fbops->fb_pan_display = NULL; } -static void uvesafb_init_mtrr(struct fb_info *info) +static void __devinit uvesafb_init_mtrr(struct fb_info *info) { #ifdef CONFIG_MTRR if (mtrr && !(info->fix.smem_start & (PAGE_SIZE - 1))) { diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 15d7787dea8..69d7ea02cd4 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 0e4baca21b8..1dc04b6684e 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/Kconfig b/drivers/w1/Kconfig index 6854fd6b971..9adbb4f9047 100644 --- a/drivers/w1/Kconfig +++ b/drivers/w1/Kconfig @@ -17,7 +17,8 @@ config W1_CON bool "Userspace communication over connector" default y --- help --- - This allows to communicate with userspace using connector [Documentation/connector]. + This allows to communicate with userspace using connector. For more + information see <file:Documentation/connector/connector.txt>. There are three types of messages between w1 core and userspace: 1. Events. They are generated each time new master or slave device found either due to automatic or requested search. diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c index 299e274d241..b63b5e044a4 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/w1/w1.c b/drivers/w1/w1.c index 070217322c9..33e50310e9e 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -869,11 +869,9 @@ void w1_search_process(struct w1_master *dev, u8 search_type) w1_search_devices(dev, search_type, w1_slave_found); list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { - if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) { + if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) w1_slave_detach(sl); - - dev->slave_count--; - } else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags)) + else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags)) sl->ttl = dev->slave_ttl; } diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 81db48f07ca..52dff40ec19 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -15,8 +15,8 @@ menuconfig WATCHDOG implementation entirely in software (which can sometimes fail to reboot the machine) and a driver for hardware watchdog boards, which are more robust and can also keep track of the temperature inside - your computer. For details, read <file:Documentation/watchdog/watchdog.txt> - in the kernel source. + your computer. For details, read + <file:Documentation/watchdog/watchdog-api.txt> in the kernel source. The watchdog is usually used together with the watchdog daemon which is available from @@ -392,6 +392,16 @@ config ITCO_VENDOR_SUPPORT devices. At this moment we only have additional support for some SuperMicro Inc. motherboards. +config IT8712F_WDT + tristate "IT8712F (Smart Guardian) Watchdog Timer" + depends on X86 + ---help--- + This is the driver for the built-in watchdog timer on the IT8712F + Super I/0 chipset used on many motherboards. + + To compile this driver as a module, choose M here: the + module will be called it8712f_wdt. + config SC1200_WDT tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog" depends on X86 @@ -456,6 +466,19 @@ config SBC8360_WDT Most people will say N. +config SBC7240_WDT + tristate "SBC Nano 7240 Watchdog Timer" + depends on X86_32 + ---help--- + This is the driver for the hardware watchdog found on the IEI + single board computers EPIC Nano 7240 (and likely others). This + watchdog simply watches your kernel to make sure it doesn't freeze, + and if it does, it reboots your computer after a certain amount of + time. + + To compile this driver as a module, choose M here: the + module will be called sbc7240_wdt. + config CPU5_WDT tristate "SMA CPU5 Watchdog" depends on X86 diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 7d9e5734f8b..87483cc6325 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -66,11 +66,13 @@ obj-$(CONFIG_IBMASR) += ibmasr.o obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o obj-$(CONFIG_I6300ESB_WDT) += i6300esb.o obj-$(CONFIG_ITCO_WDT) += iTCO_wdt.o iTCO_vendor_support.o +obj-$(CONFIG_IT8712F_WDT) += it8712f_wdt.o obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o obj-$(CONFIG_PC87413_WDT) += pc87413_wdt.o obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o obj-$(CONFIG_SBC8360_WDT) += sbc8360.o +obj-$(CONFIG_SBC7240_WDT) += sbc7240_wdt.o obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o obj-$(CONFIG_SMSC37B787_WDT) += smsc37b787_wdt.o obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o diff --git a/drivers/watchdog/alim1535_wdt.c b/drivers/watchdog/alim1535_wdt.c index c404fc69e7e..b481cc0e32e 100644 --- a/drivers/watchdog/alim1535_wdt.c +++ b/drivers/watchdog/alim1535_wdt.c @@ -31,7 +31,7 @@ static unsigned long ali_is_open; static char ali_expect_release; static struct pci_dev *ali_pci; static u32 ali_timeout_bits; /* stores the computed timeout */ -static spinlock_t ali_lock; /* Guards the hardware */ +static DEFINE_SPINLOCK(ali_lock); /* Guards the hardware */ /* module parameters */ static int timeout = WATCHDOG_TIMEOUT; @@ -398,8 +398,6 @@ static int __init watchdog_init(void) { int ret; - spin_lock_init(&ali_lock); - /* Check whether or not the hardware watchdog is there */ if (ali_find_watchdog() != 0) { return -ENODEV; diff --git a/drivers/watchdog/at32ap700x_wdt.c b/drivers/watchdog/at32ap700x_wdt.c index 54a516169d0..fb5ed6478f7 100644 --- a/drivers/watchdog/at32ap700x_wdt.c +++ b/drivers/watchdog/at32ap700x_wdt.c @@ -6,6 +6,19 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * + * Errata: WDT Clear is blocked after WDT Reset + * + * A watchdog timer event will, after reset, block writes to the WDT_CLEAR + * register, preventing the program to clear the next Watchdog Timer Reset. + * + * If you still want to use the WDT after a WDT reset a small code can be + * insterted at the startup checking the AVR32_PM.rcause register for WDT reset + * and use a GPIO pin to reset the system. This method requires that one of the + * GPIO pins are available and connected externally to the RESET_N pin. After + * the GPIO pin has pulled down the reset line the GPIO will be reset and leave + * the pin tristated with pullup. */ #include <linux/init.h> @@ -44,6 +57,13 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" #define WDT_CLR 0x04 +#define WDT_RCAUSE 0x10 +#define WDT_RCAUSE_POR 0 +#define WDT_RCAUSE_EXT 2 +#define WDT_RCAUSE_WDT 3 +#define WDT_RCAUSE_JTAG 4 +#define WDT_RCAUSE_SERP 5 + #define WDT_BIT(name) (1 << WDT_##name) #define WDT_BF(name, value) ((value) << WDT_##name) @@ -56,6 +76,7 @@ struct wdt_at32ap700x { void __iomem *regs; spinlock_t io_lock; int timeout; + int boot_status; unsigned long users; struct miscdevice miscdev; }; @@ -126,7 +147,7 @@ static int at32_wdt_close(struct inode *inode, struct file *file) at32_wdt_stop(); } else { dev_dbg(wdt->miscdev.parent, - "Unexpected close, not stopping watchdog!\n"); + "unexpected close, not stopping watchdog!\n"); at32_wdt_pat(); } clear_bit(1, &wdt->users); @@ -154,6 +175,33 @@ static int at32_wdt_settimeout(int time) return 0; } +/* + * Get the watchdog status. + */ +static int at32_wdt_get_status(void) +{ + int rcause; + int status = 0; + + rcause = wdt_readl(wdt, RCAUSE); + + switch (rcause) { + case WDT_BIT(RCAUSE_EXT): + status = WDIOF_EXTERN1; + break; + case WDT_BIT(RCAUSE_WDT): + status = WDIOF_CARDRESET; + break; + case WDT_BIT(RCAUSE_POR): /* fall through */ + case WDT_BIT(RCAUSE_JTAG): /* fall through */ + case WDT_BIT(RCAUSE_SERP): /* fall through */ + default: + break; + } + + return status; +} + static struct watchdog_info at32_wdt_info = { .identity = "at32ap700x watchdog", .options = WDIOF_SETTIMEOUT | @@ -194,10 +242,12 @@ static int at32_wdt_ioctl(struct inode *inode, struct file *file, case WDIOC_GETTIMEOUT: ret = put_user(wdt->timeout, p); break; - case WDIOC_GETSTATUS: /* fall through */ - case WDIOC_GETBOOTSTATUS: + case WDIOC_GETSTATUS: ret = put_user(0, p); break; + case WDIOC_GETBOOTSTATUS: + ret = put_user(wdt->boot_status, p); + break; case WDIOC_SETOPTIONS: ret = get_user(time, p); if (ret) @@ -282,8 +332,19 @@ static int __init at32_wdt_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "could not map I/O memory\n"); goto err_free; } + spin_lock_init(&wdt->io_lock); - wdt->users = 0; + wdt->boot_status = at32_wdt_get_status(); + + /* Work-around for watchdog silicon errata. */ + if (wdt->boot_status & WDIOF_CARDRESET) { + dev_info(&pdev->dev, "CPU must be reset with external " + "reset or POR due to silicon errata.\n"); + ret = -EIO; + goto err_iounmap; + } else { + wdt->users = 0; + } wdt->miscdev.minor = WATCHDOG_MINOR; wdt->miscdev.name = "watchdog"; wdt->miscdev.fops = &at32_wdt_fops; diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c index 309d27913fc..31dc7a69e90 100644 --- a/drivers/watchdog/bfin_wdt.c +++ b/drivers/watchdog/bfin_wdt.c @@ -71,7 +71,7 @@ static int nowayout = WATCHDOG_NOWAYOUT; static struct watchdog_info bfin_wdt_info; static unsigned long open_check; static char expect_close; -static spinlock_t bfin_wdt_spinlock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(bfin_wdt_spinlock); /** * bfin_wdt_keepalive - Keep the Userspace Watchdog Alive diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c index 19db5302ba6..a61cbd48dc0 100644 --- a/drivers/watchdog/davinci_wdt.c +++ b/drivers/watchdog/davinci_wdt.c @@ -61,7 +61,7 @@ static int heartbeat = DEFAULT_HEARTBEAT; -static spinlock_t io_lock; +static DEFINE_SPINLOCK(io_lock); static unsigned long wdt_status; #define WDT_IN_USE 0 #define WDT_OK_TO_CLOSE 1 @@ -200,8 +200,6 @@ static int davinci_wdt_probe(struct platform_device *pdev) int ret = 0, size; struct resource *res; - spin_lock_init(&io_lock); - if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT) heartbeat = DEFAULT_HEARTBEAT; @@ -262,7 +260,7 @@ static int __init davinci_wdt_init(void) static void __exit davinci_wdt_exit(void) { - return platform_driver_unregister(&platform_wdt_driver); + platform_driver_unregister(&platform_wdt_driver); } module_init(davinci_wdt_init); diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c index f236954d253..ca44fd9b19b 100644 --- a/drivers/watchdog/i6300esb.c +++ b/drivers/watchdog/i6300esb.c @@ -77,7 +77,7 @@ /* internal variables */ static void __iomem *BASEADDR; -static spinlock_t esb_lock; /* Guards the hardware */ +static DEFINE_SPINLOCK(esb_lock); /* Guards the hardware */ static unsigned long timer_alive; static struct pci_dev *esb_pci; static unsigned short triggered; /* The status of the watchdog upon boot */ @@ -456,8 +456,6 @@ static int __init watchdog_init (void) { int ret; - spin_lock_init(&esb_lock); - /* Check whether or not the hardware watchdog is there */ if (!esb_getdevice () || esb_pci == NULL) return -ENODEV; diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index cd5a565bc3a..a0e6809e369 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -35,10 +35,12 @@ * 82801GDH (ICH7DH) : document number 307013-002, 307014-009, * 82801GBM (ICH7-M) : document number 307013-002, 307014-009, * 82801GHM (ICH7-M DH) : document number 307013-002, 307014-009, - * 82801HB (ICH8) : document number 313056-002, 313057-004, - * 82801HR (ICH8R) : document number 313056-002, 313057-004, - * 82801HH (ICH8DH) : document number 313056-002, 313057-004, - * 82801HO (ICH8DO) : document number 313056-002, 313057-004, + * 82801HB (ICH8) : document number 313056-003, 313057-009, + * 82801HR (ICH8R) : document number 313056-003, 313057-009, + * 82801HBM (ICH8M) : document number 313056-003, 313057-009, + * 82801HH (ICH8DH) : document number 313056-003, 313057-009, + * 82801HO (ICH8DO) : document number 313056-003, 313057-009, + * 82801HEM (ICH8M-E) : document number 313056-003, 313057-009, * 82801IB (ICH9) : document number 316972-001, 316973-001, * 82801IR (ICH9R) : document number 316972-001, 316973-001, * 82801IH (ICH9DH) : document number 316972-001, 316973-001, @@ -95,8 +97,10 @@ enum iTCO_chipsets { TCO_ICH7M, /* ICH7-M */ TCO_ICH7MDH, /* ICH7-M DH */ TCO_ICH8, /* ICH8 & ICH8R */ + TCO_ICH8ME, /* ICH8M-E */ TCO_ICH8DH, /* ICH8DH */ TCO_ICH8DO, /* ICH8DO */ + TCO_ICH8M, /* ICH8M */ TCO_ICH9, /* ICH9 */ TCO_ICH9R, /* ICH9R */ TCO_ICH9DH, /* ICH9DH */ @@ -125,8 +129,10 @@ static struct { {"ICH7-M", 2}, {"ICH7-M DH", 2}, {"ICH8 or ICH8R", 2}, + {"ICH8M-E", 2}, {"ICH8DH", 2}, {"ICH8DO", 2}, + {"ICH8M", 2}, {"ICH9", 2}, {"ICH9R", 2}, {"ICH9DH", 2}, @@ -134,6 +140,15 @@ static struct { {NULL,0} }; +#define ITCO_PCI_DEVICE(dev, data) \ + .vendor = PCI_VENDOR_ID_INTEL, \ + .device = dev, \ + .subvendor = PCI_ANY_ID, \ + .subdevice = PCI_ANY_ID, \ + .class = 0, \ + .class_mask = 0, \ + .driver_data = data + /* * This data only exists for exporting the supported PCI ids * via MODULE_DEVICE_TABLE. We do not actually register a @@ -141,45 +156,47 @@ static struct { * functions that probably will be registered by other drivers. */ static struct pci_device_id iTCO_wdt_pci_tbl[] = { - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH0 }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH2 }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH2M }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH3 }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH3M }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH4 }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH4M }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_CICH }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH5 }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_6300ESB }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH6 }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH6M }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH6W }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7 }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7M }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7MDH }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8 }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DH }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DO }, - { PCI_VENDOR_ID_INTEL, 0x2918, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH9 }, - { PCI_VENDOR_ID_INTEL, 0x2916, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH9R }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH9DH }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, - { PCI_VENDOR_ID_INTEL, 0x2671, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, - { PCI_VENDOR_ID_INTEL, 0x2672, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, - { PCI_VENDOR_ID_INTEL, 0x2673, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, - { PCI_VENDOR_ID_INTEL, 0x2674, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, - { PCI_VENDOR_ID_INTEL, 0x2675, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, - { PCI_VENDOR_ID_INTEL, 0x2676, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, - { PCI_VENDOR_ID_INTEL, 0x2677, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, - { PCI_VENDOR_ID_INTEL, 0x2678, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, - { PCI_VENDOR_ID_INTEL, 0x2679, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, - { PCI_VENDOR_ID_INTEL, 0x267a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, - { PCI_VENDOR_ID_INTEL, 0x267b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, - { PCI_VENDOR_ID_INTEL, 0x267c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, - { PCI_VENDOR_ID_INTEL, 0x267d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, - { PCI_VENDOR_ID_INTEL, 0x267e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, - { PCI_VENDOR_ID_INTEL, 0x267f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AA_0, TCO_ICH )}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AB_0, TCO_ICH0 )}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801BA_0, TCO_ICH2 )}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801BA_10, TCO_ICH2M )}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801CA_0, TCO_ICH3 )}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801CA_12, TCO_ICH3M )}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801DB_0, TCO_ICH4 )}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801DB_12, TCO_ICH4M )}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801E_0, TCO_CICH )}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801EB_0, TCO_ICH5 )}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ESB_1, TCO_6300ESB)}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_0, TCO_ICH6 )}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_1, TCO_ICH6M )}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_2, TCO_ICH6W )}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_0, TCO_ICH7 )}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_1, TCO_ICH7M )}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_31, TCO_ICH7MDH)}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_0, TCO_ICH8 )}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_1, TCO_ICH8ME )}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_2, TCO_ICH8DH )}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_3, TCO_ICH8DO )}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_4, TCO_ICH8M )}, + { ITCO_PCI_DEVICE(0x2918, TCO_ICH9 )}, + { ITCO_PCI_DEVICE(0x2916, TCO_ICH9R )}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_2, TCO_ICH9DH )}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ESB2_0, TCO_631XESB)}, + { ITCO_PCI_DEVICE(0x2671, TCO_631XESB)}, + { ITCO_PCI_DEVICE(0x2672, TCO_631XESB)}, + { ITCO_PCI_DEVICE(0x2673, TCO_631XESB)}, + { ITCO_PCI_DEVICE(0x2674, TCO_631XESB)}, + { ITCO_PCI_DEVICE(0x2675, TCO_631XESB)}, + { ITCO_PCI_DEVICE(0x2676, TCO_631XESB)}, + { ITCO_PCI_DEVICE(0x2677, TCO_631XESB)}, + { ITCO_PCI_DEVICE(0x2678, TCO_631XESB)}, + { ITCO_PCI_DEVICE(0x2679, TCO_631XESB)}, + { ITCO_PCI_DEVICE(0x267a, TCO_631XESB)}, + { ITCO_PCI_DEVICE(0x267b, TCO_631XESB)}, + { ITCO_PCI_DEVICE(0x267c, TCO_631XESB)}, + { ITCO_PCI_DEVICE(0x267d, TCO_631XESB)}, + { ITCO_PCI_DEVICE(0x267e, TCO_631XESB)}, + { ITCO_PCI_DEVICE(0x267f, TCO_631XESB)}, { 0, }, /* End of list */ }; MODULE_DEVICE_TABLE (pci, iTCO_wdt_pci_tbl); @@ -300,6 +317,7 @@ static int iTCO_wdt_start(void) /* disable chipset's NO_REBOOT bit */ if (iTCO_wdt_unset_NO_REBOOT_bit()) { + spin_unlock(&iTCO_wdt_private.io_lock); printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n"); return -EIO; } @@ -590,7 +608,7 @@ static struct miscdevice iTCO_wdt_miscdev = { * Init & exit routines */ -static int iTCO_wdt_init(struct pci_dev *pdev, const struct pci_device_id *ent, struct platform_device *dev) +static int __devinit iTCO_wdt_init(struct pci_dev *pdev, const struct pci_device_id *ent, struct platform_device *dev) { int ret; u32 base_address; @@ -694,7 +712,7 @@ out: return ret; } -static void iTCO_wdt_cleanup(void) +static void __devexit iTCO_wdt_cleanup(void) { /* Stop the timer before we leave */ if (!nowayout) @@ -709,7 +727,7 @@ static void iTCO_wdt_cleanup(void) iTCO_wdt_private.ACPIBASE = 0; } -static int iTCO_wdt_probe(struct platform_device *dev) +static int __devinit iTCO_wdt_probe(struct platform_device *dev) { int found = 0; struct pci_dev *pdev = NULL; @@ -735,7 +753,7 @@ static int iTCO_wdt_probe(struct platform_device *dev) return 0; } -static int iTCO_wdt_remove(struct platform_device *dev) +static int __devexit iTCO_wdt_remove(struct platform_device *dev) { if (iTCO_wdt_private.ACPIBASE) iTCO_wdt_cleanup(); @@ -753,7 +771,7 @@ static void iTCO_wdt_shutdown(struct platform_device *dev) static struct platform_driver iTCO_wdt_driver = { .probe = iTCO_wdt_probe, - .remove = iTCO_wdt_remove, + .remove = __devexit_p(iTCO_wdt_remove), .shutdown = iTCO_wdt_shutdown, .suspend = iTCO_wdt_suspend, .resume = iTCO_wdt_resume, diff --git a/drivers/watchdog/ib700wdt.c b/drivers/watchdog/ib700wdt.c index c3a60f52ccb..4b89f401691 100644 --- a/drivers/watchdog/ib700wdt.c +++ b/drivers/watchdog/ib700wdt.c @@ -48,7 +48,7 @@ static struct platform_device *ibwdt_platform_device; static unsigned long ibwdt_is_open; -static spinlock_t ibwdt_lock; +static DEFINE_SPINLOCK(ibwdt_lock); static char expect_close; /* Module information */ @@ -308,8 +308,6 @@ static int __devinit ibwdt_probe(struct platform_device *dev) { int res; - spin_lock_init(&ibwdt_lock); - #if WDT_START != WDT_STOP if (!request_region(WDT_STOP, 1, "IB700 WDT")) { printk (KERN_ERR PFX "STOP method I/O %X is not available.\n", WDT_STOP); diff --git a/drivers/watchdog/it8712f_wdt.c b/drivers/watchdog/it8712f_wdt.c new file mode 100644 index 00000000000..6330fc02464 --- /dev/null +++ b/drivers/watchdog/it8712f_wdt.c @@ -0,0 +1,400 @@ +/* + * IT8712F "Smart Guardian" Watchdog support + * + * Copyright (c) 2006-2007 Jorge Boncompte - DTI2 <jorge@dti2.net> + * + * Based on info and code taken from: + * + * drivers/char/watchdog/scx200_wdt.c + * drivers/hwmon/it87.c + * IT8712F EC-LPC I/O Preliminary Specification 0.9.2.pdf + * + * 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. + * + * The author(s) of this software shall not be held liable for damages + * of any nature resulting due to the use of this software. This + * software is provided AS-IS with no warranties. + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/init.h> +#include <linux/miscdevice.h> +#include <linux/watchdog.h> +#include <linux/notifier.h> +#include <linux/reboot.h> +#include <linux/fs.h> +#include <linux/pci.h> +#include <linux/spinlock.h> + +#include <asm/uaccess.h> +#include <asm/io.h> + +#define NAME "it8712f_wdt" + +MODULE_AUTHOR("Jorge Boncompte - DTI2 <jorge@dti2.net>"); +MODULE_DESCRIPTION("IT8712F Watchdog Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); + +static int margin = 60; /* in seconds */ +module_param(margin, int, 0); +MODULE_PARM_DESC(margin, "Watchdog margin in seconds"); + +static int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); + +static struct semaphore it8712f_wdt_sem; +static unsigned expect_close; +static spinlock_t io_lock; + +/* Dog Food address - We use the game port address */ +static unsigned short address; + +#define REG 0x2e /* The register to read/write */ +#define VAL 0x2f /* The value to read/write */ + +#define LDN 0x07 /* Register: Logical device select */ +#define DEVID 0x20 /* Register: Device ID */ +#define DEVREV 0x22 /* Register: Device Revision */ +#define ACT_REG 0x30 /* LDN Register: Activation */ +#define BASE_REG 0x60 /* LDN Register: Base address */ + +#define IT8712F_DEVID 0x8712 + +#define LDN_GPIO 0x07 /* GPIO and Watch Dog Timer */ +#define LDN_GAME 0x09 /* Game Port */ + +#define WDT_CONTROL 0x71 /* WDT Register: Control */ +#define WDT_CONFIG 0x72 /* WDT Register: Configuration */ +#define WDT_TIMEOUT 0x73 /* WDT Register: Timeout Value */ + +#define WDT_RESET_GAME 0x10 +#define WDT_RESET_KBD 0x20 +#define WDT_RESET_MOUSE 0x40 +#define WDT_RESET_CIR 0x80 + +#define WDT_UNIT_SEC 0x80 /* If 0 in MINUTES */ + +#define WDT_OUT_PWROK 0x10 +#define WDT_OUT_KRST 0x40 + +static int +superio_inb(int reg) +{ + outb(reg, REG); + return inb(VAL); +} + +static void +superio_outb(int val, int reg) +{ + outb(reg, REG); + outb(val, VAL); +} + +static int +superio_inw(int reg) +{ + int val; + outb(reg++, REG); + val = inb(VAL) << 8; + outb(reg, REG); + val |= inb(VAL); + return val; +} + +static inline void +superio_select(int ldn) +{ + outb(LDN, REG); + outb(ldn, VAL); +} + +static inline void +superio_enter(void) +{ + spin_lock(&io_lock); + outb(0x87, REG); + outb(0x01, REG); + outb(0x55, REG); + outb(0x55, REG); +} + +static inline void +superio_exit(void) +{ + outb(0x02, REG); + outb(0x02, VAL); + spin_unlock(&io_lock); +} + +static inline void +it8712f_wdt_ping(void) +{ + inb(address); +} + +static void +it8712f_wdt_update_margin(void) +{ + int config = WDT_OUT_KRST | WDT_OUT_PWROK; + + printk(KERN_INFO NAME ": timer margin %d seconds\n", margin); + + /* The timeout register only has 8bits wide */ + if (margin < 256) + config |= WDT_UNIT_SEC; /* else UNIT are MINUTES */ + superio_outb(config, WDT_CONFIG); + + superio_outb((margin > 255) ? (margin / 60) : margin, WDT_TIMEOUT); +} + +static void +it8712f_wdt_enable(void) +{ + printk(KERN_DEBUG NAME ": enabling watchdog timer\n"); + superio_enter(); + superio_select(LDN_GPIO); + + superio_outb(WDT_RESET_GAME, WDT_CONTROL); + + it8712f_wdt_update_margin(); + + superio_exit(); + + it8712f_wdt_ping(); +} + +static void +it8712f_wdt_disable(void) +{ + printk(KERN_DEBUG NAME ": disabling watchdog timer\n"); + + superio_enter(); + superio_select(LDN_GPIO); + + superio_outb(0, WDT_CONFIG); + superio_outb(0, WDT_CONTROL); + superio_outb(0, WDT_TIMEOUT); + + superio_exit(); +} + +static int +it8712f_wdt_notify(struct notifier_block *this, + unsigned long code, void *unused) +{ + if (code == SYS_HALT || code == SYS_POWER_OFF) + if (!nowayout) + it8712f_wdt_disable(); + + return NOTIFY_DONE; +} + +static struct notifier_block it8712f_wdt_notifier = { + .notifier_call = it8712f_wdt_notify, +}; + +static ssize_t +it8712f_wdt_write(struct file *file, const char __user *data, + size_t len, loff_t *ppos) +{ + /* check for a magic close character */ + if (len) { + size_t i; + + it8712f_wdt_ping(); + + expect_close = 0; + for (i = 0; i < len; ++i) { + char c; + if (get_user(c, data+i)) + return -EFAULT; + if (c == 'V') + expect_close = 42; + } + } + + return len; +} + +static int +it8712f_wdt_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + void __user *argp = (void __user *)arg; + int __user *p = argp; + static struct watchdog_info ident = { + .identity = "IT8712F Watchdog", + .firmware_version = 1, + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, + }; + int new_margin; + + switch (cmd) { + default: + return -ENOTTY; + case WDIOC_GETSUPPORT: + if (copy_to_user(argp, &ident, sizeof(ident))) + return -EFAULT; + return 0; + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0, p); + case WDIOC_KEEPALIVE: + it8712f_wdt_ping(); + return 0; + case WDIOC_SETTIMEOUT: + if (get_user(new_margin, p)) + return -EFAULT; + if (new_margin < 1) + return -EINVAL; + margin = new_margin; + superio_enter(); + superio_select(LDN_GPIO); + + it8712f_wdt_update_margin(); + + superio_exit(); + it8712f_wdt_ping(); + case WDIOC_GETTIMEOUT: + if (put_user(margin, p)) + return -EFAULT; + return 0; + } +} + +static int +it8712f_wdt_open(struct inode *inode, struct file *file) +{ + /* only allow one at a time */ + if (down_trylock(&it8712f_wdt_sem)) + return -EBUSY; + it8712f_wdt_enable(); + + return nonseekable_open(inode, file); +} + +static int +it8712f_wdt_release(struct inode *inode, struct file *file) +{ + if (expect_close != 42) { + printk(KERN_WARNING NAME + ": watchdog device closed unexpectedly, will not" + " disable the watchdog timer\n"); + } else if (!nowayout) { + it8712f_wdt_disable(); + } + expect_close = 0; + up(&it8712f_wdt_sem); + + return 0; +} + +static struct file_operations it8712f_wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = it8712f_wdt_write, + .ioctl = it8712f_wdt_ioctl, + .open = it8712f_wdt_open, + .release = it8712f_wdt_release, +}; + +static struct miscdevice it8712f_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &it8712f_wdt_fops, +}; + +static int __init +it8712f_wdt_find(unsigned short *address) +{ + int err = -ENODEV; + int chip_type; + + superio_enter(); + chip_type = superio_inw(DEVID); + if (chip_type != IT8712F_DEVID) + goto exit; + + superio_select(LDN_GAME); + superio_outb(1, ACT_REG); + if (!(superio_inb(ACT_REG) & 0x01)) { + printk(KERN_ERR NAME ": Device not activated, skipping\n"); + goto exit; + } + + *address = superio_inw(BASE_REG); + if (*address == 0) { + printk(KERN_ERR NAME ": Base address not set, skipping\n"); + goto exit; + } + + err = 0; + printk(KERN_DEBUG NAME ": Found IT%04xF chip revision %d - " + "using DogFood address 0x%x\n", + chip_type, superio_inb(DEVREV) & 0x0f, *address); + +exit: + superio_exit(); + return err; +} + +static int __init +it8712f_wdt_init(void) +{ + int err = 0; + + spin_lock_init(&io_lock); + + if (it8712f_wdt_find(&address)) + return -ENODEV; + + if (!request_region(address, 1, "IT8712F Watchdog")) { + printk(KERN_WARNING NAME ": watchdog I/O region busy\n"); + return -EBUSY; + } + + it8712f_wdt_disable(); + + sema_init(&it8712f_wdt_sem, 1); + + err = register_reboot_notifier(&it8712f_wdt_notifier); + if (err) { + printk(KERN_ERR NAME ": unable to register reboot notifier\n"); + goto out; + } + + err = misc_register(&it8712f_wdt_miscdev); + if (err) { + printk(KERN_ERR NAME + ": cannot register miscdev on minor=%d (err=%d)\n", + WATCHDOG_MINOR, err); + goto reboot_out; + } + + return 0; + + +reboot_out: + unregister_reboot_notifier(&it8712f_wdt_notifier); +out: + release_region(address, 1); + return err; +} + +static void __exit +it8712f_wdt_exit(void) +{ + misc_deregister(&it8712f_wdt_miscdev); + unregister_reboot_notifier(&it8712f_wdt_notifier); + release_region(address, 1); +} + +module_init(it8712f_wdt_init); +module_exit(it8712f_wdt_exit); diff --git a/drivers/watchdog/machzwd.c b/drivers/watchdog/machzwd.c index 6d35bb112a5..e6e07b4575e 100644 --- a/drivers/watchdog/machzwd.c +++ b/drivers/watchdog/machzwd.c @@ -123,8 +123,8 @@ static void zf_ping(unsigned long data); static int zf_action = GEN_RESET; static unsigned long zf_is_open; static char zf_expect_close; -static spinlock_t zf_lock; -static spinlock_t zf_port_lock; +static DEFINE_SPINLOCK(zf_lock); +static DEFINE_SPINLOCK(zf_port_lock); static DEFINE_TIMER(zf_timer, zf_ping, 0, 0); static unsigned long next_heartbeat = 0; @@ -438,9 +438,6 @@ static int __init zf_init(void) zf_show_action(action); - spin_lock_init(&zf_lock); - spin_lock_init(&zf_port_lock); - if(!request_region(ZF_IOBASE, 3, "MachZ ZFL WDT")){ printk(KERN_ERR "cannot reserve I/O ports at %d\n", ZF_IOBASE); diff --git a/drivers/watchdog/mpc83xx_wdt.c b/drivers/watchdog/mpc83xx_wdt.c index a0bf95fb976..6369f569517 100644 --- a/drivers/watchdog/mpc83xx_wdt.c +++ b/drivers/watchdog/mpc83xx_wdt.c @@ -56,7 +56,7 @@ static int prescale = 1; static unsigned int timeout_sec; static unsigned long wdt_is_open; -static spinlock_t wdt_spinlock; +static DEFINE_SPINLOCK(wdt_spinlock); static void mpc83xx_wdt_keepalive(void) { @@ -185,9 +185,6 @@ static int __devinit mpc83xx_wdt_probe(struct platform_device *dev) printk(KERN_INFO "WDT driver for MPC83xx initialized. " "mode:%s timeout=%d (%d seconds)\n", reset ? "reset":"interrupt", timeout, timeout_sec); - - spin_lock_init(&wdt_spinlock); - return 0; err_unmap: diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c index 3d3deae0d64..15e4f8887a9 100644 --- a/drivers/watchdog/pc87413_wdt.c +++ b/drivers/watchdog/pc87413_wdt.c @@ -61,7 +61,7 @@ static unsigned long timer_enabled = 0; /* is the timer enabled? */ static char expect_close; /* is the close expected? */ -static spinlock_t io_lock; /* to guard the watchdog from io races */ +static DEFINE_SPINLOCK(io_lock);/* to guard the watchdog from io races */ static int nowayout = WATCHDOG_NOWAYOUT; @@ -561,8 +561,6 @@ static int __init pc87413_init(void) { int ret; - spin_lock_init(&io_lock); - printk(KERN_INFO PFX "Version " VERSION " at io 0x%X\n", WDT_INDEX_IO_PORT); /* request_region(io, 2, "pc87413"); */ diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c index 22f8873dd09..b04aa096a10 100644 --- a/drivers/watchdog/pnx4008_wdt.c +++ b/drivers/watchdog/pnx4008_wdt.c @@ -80,7 +80,7 @@ static int nowayout = WATCHDOG_NOWAYOUT; static int heartbeat = DEFAULT_HEARTBEAT; -static spinlock_t io_lock; +static DEFINE_SPINLOCK(io_lock); static unsigned long wdt_status; #define WDT_IN_USE 0 #define WDT_OK_TO_CLOSE 1 @@ -254,8 +254,6 @@ static int pnx4008_wdt_probe(struct platform_device *pdev) int ret = 0, size; struct resource *res; - spin_lock_init(&io_lock); - if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT) heartbeat = DEFAULT_HEARTBEAT; @@ -335,7 +333,7 @@ static int __init pnx4008_wdt_init(void) static void __exit pnx4008_wdt_exit(void) { - return platform_driver_unregister(&platform_wdt_driver); + platform_driver_unregister(&platform_wdt_driver); } module_init(pnx4008_wdt_init); diff --git a/drivers/watchdog/sbc7240_wdt.c b/drivers/watchdog/sbc7240_wdt.c new file mode 100644 index 00000000000..4c8cefbd862 --- /dev/null +++ b/drivers/watchdog/sbc7240_wdt.c @@ -0,0 +1,324 @@ +/* + * NANO7240 SBC Watchdog device driver + * + * Based on w83877f.c by Scott Jennings, + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * (c) Copyright 2007 Gilles GIGAN <gilles.gigan@jcu.edu.au> + * + */ + +#include <linux/fs.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/jiffies.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/miscdevice.h> +#include <linux/notifier.h> +#include <linux/reboot.h> +#include <linux/types.h> +#include <linux/watchdog.h> +#include <asm/atomic.h> +#include <asm/io.h> +#include <asm/system.h> +#include <asm/uaccess.h> + +#define SBC7240_PREFIX "sbc7240_wdt: " + +#define SBC7240_ENABLE_PORT 0x443 +#define SBC7240_DISABLE_PORT 0x043 +#define SBC7240_SET_TIMEOUT_PORT SBC7240_ENABLE_PORT +#define SBC7240_MAGIC_CHAR 'V' + +#define SBC7240_TIMEOUT 30 +#define SBC7240_MAX_TIMEOUT 255 +static int timeout = SBC7240_TIMEOUT; /* in seconds */ +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=" + __MODULE_STRING(SBC7240_MAX_TIMEOUT) ", default=" + __MODULE_STRING(SBC7240_TIMEOUT) ")"); + +static int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Disable watchdog when closing device file"); + +#define SBC7240_OPEN_STATUS_BIT 0 +#define SBC7240_ENABLED_STATUS_BIT 1 +#define SBC7240_EXPECT_CLOSE_STATUS_BIT 2 +static unsigned long wdt_status; + +/* + * Utility routines + */ + +static void wdt_disable(void) +{ + /* disable the watchdog */ + if (test_and_clear_bit(SBC7240_ENABLED_STATUS_BIT, &wdt_status)) { + inb_p(SBC7240_DISABLE_PORT); + printk(KERN_INFO SBC7240_PREFIX + "Watchdog timer is now disabled.\n"); + } +} + +static void wdt_enable(void) +{ + /* enable the watchdog */ + if (!test_and_set_bit(SBC7240_ENABLED_STATUS_BIT, &wdt_status)) { + inb_p(SBC7240_ENABLE_PORT); + printk(KERN_INFO SBC7240_PREFIX + "Watchdog timer is now enabled.\n"); + } +} + +static int wdt_set_timeout(int t) +{ + if (t < 1 || t > SBC7240_MAX_TIMEOUT) { + printk(KERN_ERR SBC7240_PREFIX + "timeout value must be 1<=x<=%d\n", + SBC7240_MAX_TIMEOUT); + return -1; + } + /* set the timeout */ + outb_p((unsigned)t, SBC7240_SET_TIMEOUT_PORT); + timeout = t; + printk(KERN_INFO SBC7240_PREFIX "timeout set to %d seconds\n", t); + return 0; +} + +/* Whack the dog */ +static inline void wdt_keepalive(void) +{ + if (test_bit(SBC7240_ENABLED_STATUS_BIT, &wdt_status)) + inb_p(SBC7240_ENABLE_PORT); +} + +/* + * /dev/watchdog handling + */ +static ssize_t fop_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + size_t i; + char c; + + if (count) { + if (!nowayout) { + clear_bit(SBC7240_EXPECT_CLOSE_STATUS_BIT, + &wdt_status); + + /* is there a magic char ? */ + for (i = 0; i != count; i++) { + if (get_user(c, buf + i)) + return -EFAULT; + if (c == SBC7240_MAGIC_CHAR) { + set_bit(SBC7240_EXPECT_CLOSE_STATUS_BIT, + &wdt_status); + break; + } + } + } + + wdt_keepalive(); + } + + return count; +} + +static int fop_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit(SBC7240_OPEN_STATUS_BIT, &wdt_status)) + return -EBUSY; + + wdt_enable(); + + return nonseekable_open(inode, file); +} + +static int fop_close(struct inode *inode, struct file *file) +{ + if (test_and_clear_bit(SBC7240_EXPECT_CLOSE_STATUS_BIT, &wdt_status) + || !nowayout) { + wdt_disable(); + } else { + printk(KERN_CRIT SBC7240_PREFIX + "Unexpected close, not stopping watchdog!\n"); + wdt_keepalive(); + } + + clear_bit(SBC7240_OPEN_STATUS_BIT, &wdt_status); + return 0; +} + +static struct watchdog_info ident = { + .options = WDIOF_KEEPALIVEPING| + WDIOF_SETTIMEOUT| + WDIOF_MAGICCLOSE, + .firmware_version = 1, + .identity = "SBC7240", +}; + + +static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user + ((void __user *)arg, &ident, sizeof(ident)) + ? -EFAULT : 0; + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0, (int __user *)arg); + case WDIOC_KEEPALIVE: + wdt_keepalive(); + return 0; + case WDIOC_SETOPTIONS:{ + int options; + int retval = -EINVAL; + + if (get_user(options, (int __user *)arg)) + return -EFAULT; + + if (options & WDIOS_DISABLECARD) { + wdt_disable(); + retval = 0; + } + + if (options & WDIOS_ENABLECARD) { + wdt_enable(); + retval = 0; + } + + return retval; + } + case WDIOC_SETTIMEOUT:{ + int new_timeout; + + if (get_user(new_timeout, (int __user *)arg)) + return -EFAULT; + + if (wdt_set_timeout(new_timeout)) + return -EINVAL; + + /* Fall through */ + } + case WDIOC_GETTIMEOUT: + return put_user(timeout, (int __user *)arg); + default: + return -ENOTTY; + } +} + +static const struct file_operations wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = fop_write, + .open = fop_open, + .release = fop_close, + .ioctl = fop_ioctl, +}; + +static struct miscdevice wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &wdt_fops, +}; + +/* + * Notifier for system down + */ + +static int wdt_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if (code == SYS_DOWN || code == SYS_HALT) + wdt_disable(); + return NOTIFY_DONE; +} + +static struct notifier_block wdt_notifier = { + .notifier_call = wdt_notify_sys, +}; + +static void __exit sbc7240_wdt_unload(void) +{ + printk(KERN_INFO SBC7240_PREFIX "Removing watchdog\n"); + misc_deregister(&wdt_miscdev); + + unregister_reboot_notifier(&wdt_notifier); + release_region(SBC7240_ENABLE_PORT, 1); +} + +static int __init sbc7240_wdt_init(void) +{ + int rc = -EBUSY; + + if (!request_region(SBC7240_ENABLE_PORT, 1, "SBC7240 WDT")) { + printk(KERN_ERR SBC7240_PREFIX + "I/O address 0x%04x already in use\n", + SBC7240_ENABLE_PORT); + rc = -EIO; + goto err_out; + } + + /* The IO port 0x043 used to disable the watchdog + * is already claimed by the system timer, so we + * cant request_region() it ...*/ + + if (timeout < 1 || timeout > SBC7240_MAX_TIMEOUT) { + timeout = SBC7240_TIMEOUT; + printk(KERN_INFO SBC7240_PREFIX + "timeout value must be 1<=x<=%d, using %d\n", + SBC7240_MAX_TIMEOUT, timeout); + } + wdt_set_timeout(timeout); + wdt_disable(); + + rc = register_reboot_notifier(&wdt_notifier); + if (rc) { + printk(KERN_ERR SBC7240_PREFIX + "cannot register reboot notifier (err=%d)\n", rc); + goto err_out_region; + } + + rc = misc_register(&wdt_miscdev); + if (rc) { + printk(KERN_ERR SBC7240_PREFIX + "cannot register miscdev on minor=%d (err=%d)\n", + wdt_miscdev.minor, rc); + goto err_out_reboot_notifier; + } + + printk(KERN_INFO SBC7240_PREFIX + "Watchdog driver for SBC7240 initialised (nowayout=%d)\n", + nowayout); + + return 0; + +err_out_reboot_notifier: + unregister_reboot_notifier(&wdt_notifier); +err_out_region: + release_region(SBC7240_ENABLE_PORT, 1); +err_out: + return rc; +} + +module_init(sbc7240_wdt_init); +module_exit(sbc7240_wdt_unload); + +MODULE_AUTHOR("Gilles Gigan"); +MODULE_DESCRIPTION("Watchdog device driver for single board" + " computers EPIC Nano 7240 from iEi"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); + diff --git a/drivers/watchdog/sbc8360.c b/drivers/watchdog/sbc8360.c index 285d8528953..2ee2677f364 100644 --- a/drivers/watchdog/sbc8360.c +++ b/drivers/watchdog/sbc8360.c @@ -54,7 +54,7 @@ #include <asm/system.h> static unsigned long sbc8360_is_open; -static spinlock_t sbc8360_lock; +static DEFINE_SPINLOCK(sbc8360_lock); static char expect_close; #define PFX "sbc8360: " @@ -359,7 +359,6 @@ static int __init sbc8360_init(void) goto out_noreboot; } - spin_lock_init(&sbc8360_lock); res = misc_register(&sbc8360_miscdev); if (res) { printk(KERN_ERR PFX "failed to register misc device\n"); diff --git a/drivers/watchdog/sc1200wdt.c b/drivers/watchdog/sc1200wdt.c index 9670d47190d..32ccd7c89c7 100644 --- a/drivers/watchdog/sc1200wdt.c +++ b/drivers/watchdog/sc1200wdt.c @@ -74,7 +74,7 @@ static int io = -1; static int io_len = 2; /* for non plug and play */ static struct semaphore open_sem; static char expect_close; -static spinlock_t sc1200wdt_lock; /* io port access serialisation */ +static DEFINE_SPINLOCK(sc1200wdt_lock); /* io port access serialisation */ #if defined CONFIG_PNP static int isapnp = 1; @@ -375,7 +375,6 @@ static int __init sc1200wdt_init(void) printk("%s\n", banner); - spin_lock_init(&sc1200wdt_lock); sema_init(&open_sem, 1); #if defined CONFIG_PNP diff --git a/drivers/watchdog/sc520_wdt.c b/drivers/watchdog/sc520_wdt.c index e8594c64d1e..2847324a2be 100644 --- a/drivers/watchdog/sc520_wdt.c +++ b/drivers/watchdog/sc520_wdt.c @@ -125,7 +125,7 @@ static DEFINE_TIMER(timer, wdt_timer_ping, 0, 0); static unsigned long next_heartbeat; static unsigned long wdt_is_open; static char wdt_expect_close; -static spinlock_t wdt_spinlock; +static DEFINE_SPINLOCK(wdt_spinlock); /* * Whack the dog @@ -383,8 +383,6 @@ static int __init sc520_wdt_init(void) { int rc = -EBUSY; - spin_lock_init(&wdt_spinlock); - /* Check that the timeout value is within it's range ; if not reset to the default */ if (wdt_set_heartbeat(timeout)) { wdt_set_heartbeat(WATCHDOG_TIMEOUT); diff --git a/drivers/watchdog/smsc37b787_wdt.c b/drivers/watchdog/smsc37b787_wdt.c index d3cb0a76602..5d2b5ba6141 100644 --- a/drivers/watchdog/smsc37b787_wdt.c +++ b/drivers/watchdog/smsc37b787_wdt.c @@ -83,7 +83,7 @@ static unsigned long timer_enabled = 0; /* is the timer enabled? */ static char expect_close; /* is the close expected? */ -static spinlock_t io_lock; /* to guard the watchdog from io races */ +static DEFINE_SPINLOCK(io_lock);/* to guard the watchdog from io races */ static int nowayout = WATCHDOG_NOWAYOUT; @@ -540,8 +540,6 @@ static int __init wb_smsc_wdt_init(void) { int ret; - spin_lock_init(&io_lock); - printk("SMsC 37B787 watchdog component driver " VERSION " initialising...\n"); if (!request_region(IOPORT, IOPORT_SIZE, "SMsC 37B787 watchdog")) { diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c index df33b3b5a53..386492821fc 100644 --- a/drivers/watchdog/w83627hf_wdt.c +++ b/drivers/watchdog/w83627hf_wdt.c @@ -48,7 +48,7 @@ static unsigned long wdt_is_open; static char expect_close; -static spinlock_t io_lock; +static DEFINE_SPINLOCK(io_lock); /* You must set this - there is no sane way to probe for this board. */ static int wdt_io = 0x2E; @@ -328,8 +328,6 @@ wdt_init(void) { int ret; - spin_lock_init(&io_lock); - printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF/THF/HG Super I/O chip initialising.\n"); if (wdt_set_heartbeat(timeout)) { diff --git a/drivers/watchdog/w83697hf_wdt.c b/drivers/watchdog/w83697hf_wdt.c index 51826c216d6..6ea125eabea 100644 --- a/drivers/watchdog/w83697hf_wdt.c +++ b/drivers/watchdog/w83697hf_wdt.c @@ -47,7 +47,7 @@ static unsigned long wdt_is_open; static char expect_close; -static spinlock_t io_lock; +static DEFINE_SPINLOCK(io_lock); /* You must set this - there is no sane way to probe for this board. */ static int wdt_io = 0x2e; @@ -376,16 +376,16 @@ wdt_init(void) { int ret, i, found = 0; - spin_lock_init(&io_lock); - printk (KERN_INFO PFX "WDT driver for W83697HF/HG initializing\n"); if (wdt_io == 0) { /* we will autodetect the W83697HF/HG watchdog */ for (i = 0; ((!found) && (w83697hf_ioports[i] != 0)); i++) { wdt_io = w83697hf_ioports[i]; - if (!w83697hf_check_wdt()) + if (!w83697hf_check_wdt()) { found++; + break; + } } } else { if (!w83697hf_check_wdt()) diff --git a/drivers/watchdog/w83877f_wdt.c b/drivers/watchdog/w83877f_wdt.c index 3c88fe18f4f..bcc9d48955d 100644 --- a/drivers/watchdog/w83877f_wdt.c +++ b/drivers/watchdog/w83877f_wdt.c @@ -94,7 +94,7 @@ static DEFINE_TIMER(timer, wdt_timer_ping, 0, 0); static unsigned long next_heartbeat; static unsigned long wdt_is_open; static char wdt_expect_close; -static spinlock_t wdt_spinlock; +static DEFINE_SPINLOCK(wdt_spinlock); /* * Whack the dog @@ -350,8 +350,6 @@ static int __init w83877f_wdt_init(void) { int rc = -EBUSY; - spin_lock_init(&wdt_spinlock); - if(timeout < 1 || timeout > 3600) /* arbitrary upper limit */ { timeout = WATCHDOG_TIMEOUT; diff --git a/drivers/watchdog/w83977f_wdt.c b/drivers/watchdog/w83977f_wdt.c index 15796844289..b475529d247 100644 --- a/drivers/watchdog/w83977f_wdt.c +++ b/drivers/watchdog/w83977f_wdt.c @@ -50,7 +50,7 @@ static int timeoutW; /* timeout in watchdog counter units */ static unsigned long timer_alive; static int testmode; static char expect_close; -static spinlock_t spinlock; +static DEFINE_SPINLOCK(spinlock); module_param(timeout, int, 0); MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (15..7635), default=" __MODULE_STRING(DEFAULT_TIMEOUT) ")"); @@ -476,8 +476,6 @@ static int __init w83977f_wdt_init(void) printk(KERN_INFO PFX DRIVER_VERSION); - spin_lock_init(&spinlock); - /* * Check that the timeout value is within it's range ; * if not reset to the default diff --git a/drivers/watchdog/wafer5823wdt.c b/drivers/watchdog/wafer5823wdt.c index 950905d3c39..9e368091f79 100644 --- a/drivers/watchdog/wafer5823wdt.c +++ b/drivers/watchdog/wafer5823wdt.c @@ -45,7 +45,7 @@ static unsigned long wafwdt_is_open; static char expect_close; -static spinlock_t wafwdt_lock; +static DEFINE_SPINLOCK(wafwdt_lock); /* * You must set these - there is no sane way to probe for this board. @@ -252,8 +252,6 @@ static int __init wafwdt_init(void) printk(KERN_INFO "WDT driver for Wafer 5823 single board computer initialising.\n"); - spin_lock_init(&wafwdt_lock); - if (timeout < 1 || timeout > 255) { timeout = WD_TIMO; printk (KERN_INFO PFX "timeout value must be 1<=x<=255, using %d\n", diff --git a/drivers/watchdog/wdt.c b/drivers/watchdog/wdt.c index 0a3de6a0244..53d0bb410df 100644 --- a/drivers/watchdog/wdt.c +++ b/drivers/watchdog/wdt.c @@ -253,7 +253,7 @@ static irqreturn_t wdt_interrupt(int irq, void *dev_id) printk(KERN_CRIT "Possible fan fault.\n"); } #endif /* CONFIG_WDT_501 */ - if (!(status & WDC_SR_WCCR)) + if (!(status & WDC_SR_WCCR)) { #ifdef SOFTWARE_REBOOT #ifdef ONLY_TESTING printk(KERN_CRIT "Would Reboot.\n"); @@ -264,6 +264,7 @@ static irqreturn_t wdt_interrupt(int irq, void *dev_id) #else printk(KERN_CRIT "Reset in 5ms.\n"); #endif + } return IRQ_HANDLED; } diff --git a/drivers/watchdog/wdt977.c b/drivers/watchdog/wdt977.c index 7d300ff7ab0..9b7f6b6edef 100644 --- a/drivers/watchdog/wdt977.c +++ b/drivers/watchdog/wdt977.c @@ -59,7 +59,7 @@ static int timeoutM; /* timeout in minutes */ static unsigned long timer_alive; static int testmode; static char expect_close; -static spinlock_t spinlock; +static DEFINE_SPINLOCK(spinlock); module_param(timeout, int, 0); MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (60..15300), default=" __MODULE_STRING(DEFAULT_TIMEOUT) ")"); @@ -448,8 +448,6 @@ static int __init wd977_init(void) printk(KERN_INFO PFX DRIVER_VERSION); - spin_lock_init(&spinlock); - /* Check that the timeout value is within it's range ; if not reset to the default */ if (wdt977_set_timeout(timeout)) { diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c index 6baf4ae42c9..1355608683e 100644 --- a/drivers/watchdog/wdt_pci.c +++ b/drivers/watchdog/wdt_pci.c @@ -74,7 +74,7 @@ static int dev_count; static struct semaphore open_sem; -static spinlock_t wdtpci_lock; +static DEFINE_SPINLOCK(wdtpci_lock); static char expect_close; static int io; @@ -298,7 +298,7 @@ static irqreturn_t wdtpci_interrupt(int irq, void *dev_id) printk(KERN_CRIT PFX "Possible fan fault.\n"); } #endif /* CONFIG_WDT_501_PCI */ - if (!(status&WDC_SR_WCCR)) + if (!(status&WDC_SR_WCCR)) { #ifdef SOFTWARE_REBOOT #ifdef ONLY_TESTING printk(KERN_CRIT PFX "Would Reboot.\n"); @@ -309,6 +309,7 @@ static irqreturn_t wdtpci_interrupt(int irq, void *dev_id) #else printk(KERN_CRIT PFX "Reset in 5ms.\n"); #endif + } return IRQ_HANDLED; } @@ -606,7 +607,6 @@ static int __devinit wdtpci_init_one (struct pci_dev *dev, } sema_init(&open_sem, 1); - spin_lock_init(&wdtpci_lock); irq = dev->irq; io = pci_resource_start (dev, 2); diff --git a/drivers/zorro/zorro-driver.c b/drivers/zorro/zorro-driver.c index 067c07be928..e6c4390d8bd 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, }; |