diff options
Diffstat (limited to 'drivers')
268 files changed, 5107 insertions, 2613 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 5d0e26a5c34..da3a08fa9e4 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 @@ -88,7 +88,8 @@ config ACPI_PROC_EVENT config ACPI_AC tristate "AC Adapter" - depends on X86 && POWER_SUPPLY + depends on X86 + select POWER_SUPPLY default y help This driver adds support for the AC Adapter object, which indicates @@ -97,7 +98,8 @@ config ACPI_AC config ACPI_BATTERY tristate "Battery" - depends on X86 && POWER_SUPPLY + depends on X86 + select POWER_SUPPLY default y help This driver adds support for battery information through @@ -352,7 +354,7 @@ config ACPI_HOTPLUG_MEMORY config ACPI_SBS tristate "Smart Battery System" depends on X86 - depends on POWER_SUPPLY + select 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/battery.c b/drivers/acpi/battery.c index 681e26b56b1..c2ce0ad2169 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -125,11 +125,15 @@ 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 (!strcasecmp("LI-ION", battery->type)) + return POWER_SUPPLY_TECHNOLOGY_LION; if (!strcasecmp("LiP", battery->type)) return POWER_SUPPLY_TECHNOLOGY_LIPO; return POWER_SUPPLY_TECHNOLOGY_UNKNOWN; } +static int acpi_battery_update(struct acpi_battery *battery); + static int acpi_battery_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) @@ -139,6 +143,7 @@ static int acpi_battery_get_property(struct power_supply *psy, if ((!acpi_battery_present(battery)) && psp != POWER_SUPPLY_PROP_PRESENT) return -ENODEV; + acpi_battery_update(battery); switch (psp) { case POWER_SUPPLY_PROP_STATUS: if (battery->state & 0x01) @@ -257,7 +262,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 +271,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 +395,81 @@ static int acpi_battery_init_alarm(struct acpi_battery *battery) return acpi_battery_set_alarm(battery); } +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; + + battery->update_time = 0; + result = acpi_battery_get_info(battery); + acpi_battery_init_alarm(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); + } + + 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); +} + 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)) + if (result) return result; - if (saved_present != acpi_battery_present(battery) || - !battery->update_time) { - battery->update_time = 0; - 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); + if (!acpi_battery_present(battery)) { + sysfs_remove_battery(battery); + return 0; } + if (!battery->bat.dev) + sysfs_add_battery(battery); return acpi_battery_get_state(battery); } @@ -554,10 +616,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 +746,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 +763,9 @@ 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); + /* acpi_batter_update could remove power_supply object */ + if (battery->bat.dev) + kobject_uevent(&battery->bat.dev->kobj, KOBJ_CHANGE); } static int acpi_battery_add(struct acpi_device *device) @@ -756,11 +789,6 @@ static int acpi_battery_add(struct acpi_device *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); @@ -796,10 +824,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type) #ifdef CONFIG_ACPI_PROCFS acpi_battery_remove_fs(device); #endif - if (battery->bat.dev) { - device_remove_file(battery->bat.dev, &alarm_attr); - power_supply_unregister(&battery->bat); - } + sysfs_remove_battery(battery); mutex_destroy(&battery->lock); kfree(battery); return 0; @@ -813,6 +838,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; } diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index fb2cff9a2d2..49d432d0a12 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -198,12 +198,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; 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/ec.c b/drivers/acpi/ec.c index 7b4178393e3..06b78e5e33a 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -65,16 +65,18 @@ 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_ONLY_IBF_GPE, /* Expect GPE only for IBF = 0 event */ +}; static int acpi_ec_remove(struct acpi_device *device, int type); static int acpi_ec_start(struct acpi_device *device); @@ -116,9 +118,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; @@ -148,45 +149,54 @@ static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) outb(data, ec->data_addr); } -static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event, - 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) { + if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) && + likely(!force_poll)) { + if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event), + msecs_to_jiffies(ACPI_EC_DELAY))) + return 0; + clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); + if (acpi_ec_check_status(ec, event)) { + if (event == ACPI_EC_EVENT_OBF_1) { + /* miss OBF = 1 GPE, don't expect it anymore */ + printk(KERN_INFO PREFIX "missing OBF_1 confirmation," + "switching to degraded mode.\n"); + set_bit(EC_FLAGS_ONLY_IBF_GPE, &ec->flags); + } else { + /* missing GPEs, switch back to poll mode */ + printk(KERN_INFO PREFIX "missing IBF_1 confirmations," + "switch off interrupt mode.\n"); + clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); + } + return 0; + } + } 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)) + if (acpi_ec_check_status(ec, event)) return 0; } - } 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," + } + printk(KERN_ERR PREFIX "acpi_ec_wait timeout," " status = %d, expect_event = %d\n", acpi_ec_read_status(ec), event); - } - } - return -ETIME; } @@ -196,39 +206,42 @@ 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); 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 "write_cmd timeout, command = %d\n", command); goto end; } - count = atomic_read(&ec->event_count); + 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); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); if (result) { printk(KERN_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); + if (test_bit(EC_FLAGS_ONLY_IBF_GPE, &ec->flags)) + force_poll = 1; + result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, force_poll); if (result) { printk(KERN_ERR PREFIX "read timeout, command = %d\n", command); 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: @@ -258,10 +271,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, } } - /* Make sure GPE is enabled before doing transaction */ - acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); - - status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 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"); @@ -435,9 +445,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 +486,24 @@ 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) { + 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 */ + printk(KERN_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 +652,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; } @@ -741,6 +749,8 @@ static int acpi_ec_add(struct acpi_device *device) acpi_ec_add_fs(device); printk(KERN_INFO PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", ec->gpe, ec->command_addr, ec->data_addr); + printk(KERN_INFO PREFIX "driver started in %s mode\n", + (test_bit(EC_FLAGS_GPE_MODE, &ec->flags))?"interrupt":"poll"); return 0; } @@ -833,7 +843,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; } @@ -924,20 +934,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/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/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/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/sleep/proc.c b/drivers/acpi/sleep/proc.c index 3839efd5eae..1538355c266 100644 --- a/drivers/acpi/sleep/proc.c +++ b/drivers/acpi/sleep/proc.c @@ -194,6 +194,23 @@ static int get_date_field(char **p, u32 * value) return result; } +/* Read a possibly BCD register, always return binary */ +static u32 cmos_bcd_read(int offset, int rtc_control) +{ + u32 val = CMOS_READ(offset); + if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) + BCD_TO_BIN(val); + return val; +} + +/* Write binary value into possibly BCD register */ +static void cmos_bcd_write(u32 val, int offset, int rtc_control) +{ + if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) + BIN_TO_BCD(val); + CMOS_WRITE(val, offset); +} + static ssize_t acpi_system_write_alarm(struct file *file, const char __user * buffer, size_t count, loff_t * ppos) @@ -258,35 +275,18 @@ acpi_system_write_alarm(struct file *file, spin_lock_irq(&rtc_lock); rtc_control = CMOS_READ(RTC_CONTROL); - if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BIN_TO_BCD(yr); - BIN_TO_BCD(mo); - BIN_TO_BCD(day); - BIN_TO_BCD(hr); - BIN_TO_BCD(min); - BIN_TO_BCD(sec); - } if (adjust) { - yr += CMOS_READ(RTC_YEAR); - mo += CMOS_READ(RTC_MONTH); - day += CMOS_READ(RTC_DAY_OF_MONTH); - hr += CMOS_READ(RTC_HOURS); - min += CMOS_READ(RTC_MINUTES); - sec += CMOS_READ(RTC_SECONDS); + yr += cmos_bcd_read(RTC_YEAR, rtc_control); + mo += cmos_bcd_read(RTC_MONTH, rtc_control); + day += cmos_bcd_read(RTC_DAY_OF_MONTH, rtc_control); + hr += cmos_bcd_read(RTC_HOURS, rtc_control); + min += cmos_bcd_read(RTC_MINUTES, rtc_control); + sec += cmos_bcd_read(RTC_SECONDS, rtc_control); } spin_unlock_irq(&rtc_lock); - if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BCD_TO_BIN(yr); - BCD_TO_BIN(mo); - BCD_TO_BIN(day); - BCD_TO_BIN(hr); - BCD_TO_BIN(min); - BCD_TO_BIN(sec); - } - if (sec > 59) { min++; sec -= 60; @@ -307,14 +307,6 @@ acpi_system_write_alarm(struct file *file, yr++; mo -= 12; } - if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BIN_TO_BCD(yr); - BIN_TO_BCD(mo); - BIN_TO_BCD(day); - BIN_TO_BCD(hr); - BIN_TO_BCD(min); - BIN_TO_BCD(sec); - } spin_lock_irq(&rtc_lock); /* @@ -326,9 +318,9 @@ acpi_system_write_alarm(struct file *file, CMOS_READ(RTC_INTR_FLAGS); /* write the fields the rtc knows about */ - CMOS_WRITE(hr, RTC_HOURS_ALARM); - CMOS_WRITE(min, RTC_MINUTES_ALARM); - CMOS_WRITE(sec, RTC_SECONDS_ALARM); + cmos_bcd_write(hr, RTC_HOURS_ALARM, rtc_control); + cmos_bcd_write(min, RTC_MINUTES_ALARM, rtc_control); + cmos_bcd_write(sec, RTC_SECONDS_ALARM, rtc_control); /* * If the system supports an enhanced alarm it will have non-zero @@ -336,11 +328,11 @@ acpi_system_write_alarm(struct file *file, * to the RTC area of memory. */ if (acpi_gbl_FADT.day_alarm) - CMOS_WRITE(day, acpi_gbl_FADT.day_alarm); + cmos_bcd_write(day, acpi_gbl_FADT.day_alarm, rtc_control); if (acpi_gbl_FADT.month_alarm) - CMOS_WRITE(mo, acpi_gbl_FADT.month_alarm); + cmos_bcd_write(mo, acpi_gbl_FADT.month_alarm, rtc_control); if (acpi_gbl_FADT.century) - CMOS_WRITE(yr / 100, acpi_gbl_FADT.century); + cmos_bcd_write(yr / 100, acpi_gbl_FADT.century, rtc_control); /* enable the rtc alarm interrupt */ rtc_control |= RTC_AIE; CMOS_WRITE(rtc_control, RTC_CONTROL); diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 95229e77bff..ed9b407e42d 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -41,6 +41,7 @@ #include <linux/interrupt.h> #include <linux/dma-mapping.h> #include <linux/device.h> +#include <linux/dmi.h> #include <scsi/scsi_host.h> #include <scsi/scsi_cmnd.h> #include <linux/libata.h> @@ -48,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, @@ -98,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 */ @@ -154,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 */ @@ -177,13 +184,14 @@ 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, }; @@ -241,6 +249,7 @@ static void ahci_pmp_attach(struct ata_port *ap); static void ahci_pmp_detach(struct ata_port *ap); static void ahci_error_handler(struct ata_port *ap); static void ahci_vt8251_error_handler(struct ata_port *ap); +static void ahci_p5wdh_error_handler(struct ata_port *ap); static void ahci_post_internal_cmd(struct ata_queued_cmd *qc); static int ahci_port_resume(struct ata_port *ap); static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl); @@ -252,6 +261,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, @@ -269,6 +283,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 = { @@ -300,6 +315,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, @@ -339,6 +356,40 @@ static const struct ata_port_operations ahci_vt8251_ops = { .port_stop = ahci_port_stop, }; +static const struct ata_port_operations ahci_p5wdh_ops = { + .check_status = ahci_check_status, + .check_altstatus = ahci_check_status, + .dev_select = ata_noop_dev_select, + + .tf_read = ahci_tf_read, + + .qc_defer = sata_pmp_qc_defer_cmd_switch, + .qc_prep = ahci_qc_prep, + .qc_issue = ahci_qc_issue, + + .irq_clear = ahci_irq_clear, + + .scr_read = ahci_scr_read, + .scr_write = ahci_scr_write, + + .freeze = ahci_freeze, + .thaw = ahci_thaw, + + .error_handler = ahci_p5wdh_error_handler, + .post_internal_cmd = ahci_post_internal_cmd, + + .pmp_attach = ahci_pmp_attach, + .pmp_detach = ahci_pmp_detach, + +#ifdef CONFIG_PM + .port_suspend = ahci_port_suspend, + .port_resume = ahci_port_resume, +#endif + + .port_start = ahci_port_start, + .port_stop = ahci_port_stop, +}; + #define AHCI_HFLAGS(flags) .private_data = (void *)(flags) static const struct ata_port_info ahci_port_info[] = { @@ -800,6 +851,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) { @@ -862,8 +1037,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) { @@ -1117,15 +1294,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 */ @@ -1213,6 +1383,53 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, return rc ?: -EAGAIN; } +static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, + unsigned long deadline) +{ + struct ata_port *ap = link->ap; + struct ahci_port_priv *pp = ap->private_data; + u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; + struct ata_taskfile tf; + int rc; + + ahci_stop_engine(ap); + + /* clear D2H reception area to properly wait for D2H FIS */ + ata_tf_init(link->device, &tf); + tf.command = 0x80; + ata_tf_to_fis(&tf, 0, 0, d2h_fis); + + rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), + deadline); + + ahci_start_engine(ap); + + if (rc || ata_link_offline(link)) + return rc; + + /* spec mandates ">= 2ms" before checking status */ + msleep(150); + + /* The pseudo configuration device on SIMG4726 attached to + * ASUS P5W-DH Deluxe doesn't send signature FIS after + * hardreset if no device is attached to the first downstream + * port && the pseudo device locks up on SRST w/ PMP==0. To + * work around this, wait for !BSY only briefly. If BSY isn't + * cleared, perform CLO and proceed to IDENTIFY (achieved by + * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA). + * + * Wait for two seconds. Devices attached to downstream port + * which can't process the following IDENTIFY after this will + * have to be reset again. For most cases, this should + * suffice while making probing snappish enough. + */ + rc = ata_wait_ready(ap, jiffies + 2 * HZ); + if (rc) + ahci_kick_engine(ap, 0); + + return 0; +} + static void ahci_postreset(struct ata_link *link, unsigned int *class) { struct ata_port *ap = link->ap; @@ -1426,6 +1643,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; @@ -1670,6 +1898,19 @@ static void ahci_vt8251_error_handler(struct ata_port *ap) ahci_postreset); } +static void ahci_p5wdh_error_handler(struct ata_port *ap) +{ + if (!(ap->pflags & ATA_PFLAG_FROZEN)) { + /* restart engine */ + ahci_stop_engine(ap); + ahci_start_engine(ap); + } + + /* perform recovery */ + ata_do_eh(ap, ata_std_prereset, ahci_softreset, ahci_p5wdh_hardreset, + ahci_postreset); +} + static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; @@ -1955,6 +2196,51 @@ static void ahci_print_info(struct ata_host *host) ); } +/* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is + * hardwired to on-board SIMG 4726. The chipset is ICH8 and doesn't + * support PMP and the 4726 either directly exports the device + * attached to the first downstream port or acts as a hardware storage + * controller and emulate a single ATA device (can be RAID 0/1 or some + * other configuration). + * + * When there's no device attached to the first downstream port of the + * 4726, "Config Disk" appears, which is a pseudo ATA device to + * configure the 4726. However, ATA emulation of the device is very + * lame. It doesn't send signature D2H Reg FIS after the initial + * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues. + * + * The following function works around the problem by always using + * hardreset on the port and not depending on receiving signature FIS + * afterward. If signature FIS isn't received soon, ATA class is + * assumed without follow-up softreset. + */ +static void ahci_p5wdh_workaround(struct ata_host *host) +{ + static struct dmi_system_id sysids[] = { + { + .ident = "P5W DH Deluxe", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, + "ASUSTEK COMPUTER INC"), + DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"), + }, + }, + { } + }; + struct pci_dev *pdev = to_pci_dev(host->dev); + + if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) && + dmi_check_system(sysids)) { + struct ata_port *ap = host->ports[1]; + + dev_printk(KERN_INFO, &pdev->dev, "enabling ASUS P5W DH " + "Deluxe on-board SIMG4726 workaround\n"); + + ap->ops = &ahci_p5wdh_ops; + ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA; + } +} + static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; @@ -2015,6 +2301,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; @@ -2024,6 +2313,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ap->ops = &ata_dummy_port_ops; } + /* apply workaround for ASUS P5W DH Deluxe mainboard */ + ahci_p5wdh_workaround(host); + /* initialize adapter */ rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64); if (rc) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 2d147b51c97..164c7d9514f 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -68,7 +68,8 @@ const unsigned long sata_deb_timing_long[] = { 100, 2000, 5000 }; static unsigned int ata_dev_init_params(struct ata_device *dev, u16 heads, u16 sectors); static unsigned int ata_dev_set_xfermode(struct ata_device *dev); -static unsigned int ata_dev_set_AN(struct ata_device *dev, u8 enable); +static unsigned int ata_dev_set_feature(struct ata_device *dev, + u8 enable, u8 feature); static void ata_dev_xfermask(struct ata_device *dev); static unsigned long ata_dev_blacklisted(const struct ata_device *dev); @@ -619,6 +620,181 @@ void ata_dev_disable(struct ata_device *dev) } } +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; + + /* disable DIPM */ + if (ata_dev_enabled(dev) && (dev->flags & ATA_DFLAG_DIPM)) + err_mask = ata_dev_set_feature(dev, + SETFEATURES_SATA_DISABLE, SATA_DIPM); + 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; + + /* disable DIPM */ + if (ata_dev_enabled(dev) && (dev->flags & ATA_DFLAG_DIPM)) + err_mask = ata_dev_set_feature(dev, + SETFEATURES_SATA_DISABLE, SATA_DIPM); + 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 @@ -1799,13 +1975,7 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, * SET_FEATURES spin-up subcommand before it will accept * anything other than the original IDENTIFY command. */ - ata_tf_init(dev, &tf); - tf.command = ATA_CMD_SET_FEATURES; - tf.feature = SETFEATURES_SPINUP; - tf.protocol = ATA_PROT_NODATA; - tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; - err_mask = ata_exec_internal(dev, &tf, NULL, - DMA_NONE, NULL, 0, 0); + err_mask = ata_dev_set_feature(dev, SETFEATURES_SPINUP, 0); if (err_mask && id[2] != 0x738c) { rc = -EIO; reason = "SPINUP failed"; @@ -2075,7 +2245,8 @@ int ata_dev_configure(struct ata_device *dev) unsigned int err_mask; /* issue SET feature command to turn this on */ - err_mask = ata_dev_set_AN(dev, SETFEATURES_SATA_ENABLE); + err_mask = ata_dev_set_feature(dev, + SETFEATURES_SATA_ENABLE, SATA_AN); if (err_mask) ata_dev_printk(dev, KERN_ERR, "failed to enable ATAPI AN " @@ -2105,6 +2276,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 @@ -2126,10 +2304,21 @@ 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; + 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); @@ -2223,6 +2412,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); @@ -2238,12 +2446,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 */ @@ -2549,17 +2751,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; - if (link->sata_spd_limit == UINT_MAX) - limit = 0; + limit = link->sata_spd_limit; + + /* 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; } /** @@ -2582,7 +2794,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); } @@ -2886,6 +3098,13 @@ static int ata_dev_set_mode(struct ata_device *dev) dev->pio_mode <= XFER_PIO_2) err_mask &= ~AC_ERR_DEV; + /* Early MWDMA devices do DMA but don't allow DMA mode setting. + Don't fail an MWDMA0 set IFF the device indicates it is in MWDMA0 */ + if (dev->xfer_shift == ATA_SHIFT_MWDMA && + dev->dma_mode == XFER_MW_DMA_0 && + (dev->id[63] >> 8) & 1) + err_mask &= ~AC_ERR_DEV; + if (err_mask) { ata_dev_printk(dev, KERN_ERR, "failed to set xfermode " "(err_mask=0x%x)\n", err_mask); @@ -3115,6 +3334,55 @@ 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. + */ + 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 @@ -3220,8 +3488,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); @@ -3232,36 +3498,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 @@ -3688,8 +3926,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 @@ -3947,9 +4185,6 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "_NEC DV5800A", NULL, ATA_HORKAGE_NODMA }, { "SAMSUNG CD-ROM SN-124", "N001", ATA_HORKAGE_NODMA }, { "Seagate STT20000A", NULL, ATA_HORKAGE_NODMA }, - { "IOMEGA ZIP 250 ATAPI", NULL, ATA_HORKAGE_NODMA }, /* temporary fix */ - { "IOMEGA ZIP 250 ATAPI Floppy", - NULL, ATA_HORKAGE_NODMA }, /* Odd clown on sil3726/4726 PMPs */ { "Config Disk", NULL, ATA_HORKAGE_NODMA | ATA_HORKAGE_SKIP_PM }, @@ -3992,6 +4227,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "ST3160812AS", "3.ADJ", ATA_HORKAGE_NONCQ, }, { "ST980813AS", "3.ADB", ATA_HORKAGE_NONCQ, }, { "SAMSUNG HD401LJ", "ZZ100-15", ATA_HORKAGE_NONCQ, }, + { "Maxtor 7V300F0", "VA111900", ATA_HORKAGE_NONCQ, }, /* devices which puke on READ_NATIVE_MAX */ { "HDS724040KLSA80", "KFAOA20N", ATA_HORKAGE_BROKEN_HPA, }, @@ -4007,7 +4243,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { } }; -int strn_pattern_cmp(const char *patt, const char *name, int wildchar) +static int strn_pattern_cmp(const char *patt, const char *name, int wildchar) { const char *p; int len; @@ -4181,15 +4417,14 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev) DPRINTK("EXIT, err_mask=%x\n", err_mask); return err_mask; } - /** - * ata_dev_set_AN - Issue SET FEATURES - SATA FEATURES + * ata_dev_set_feature - Issue SET FEATURES - SATA FEATURES * @dev: Device to which command will be sent * @enable: Whether to enable or disable the feature + * @feature: The sector count represents the feature to set * * Issue SET FEATURES - SATA FEATURES command to device @dev - * on port @ap with sector count set to indicate Asynchronous - * Notification feature + * on port @ap with sector count * * LOCKING: * PCI/etc. bus probe sem. @@ -4197,7 +4432,8 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev) * RETURNS: * 0 on success, AC_ERR_* mask otherwise. */ -static unsigned int ata_dev_set_AN(struct ata_device *dev, u8 enable) +static unsigned int ata_dev_set_feature(struct ata_device *dev, u8 enable, + u8 feature) { struct ata_taskfile tf; unsigned int err_mask; @@ -4210,7 +4446,7 @@ static unsigned int ata_dev_set_AN(struct ata_device *dev, u8 enable) tf.feature = enable; tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; tf.protocol = ATA_PROT_NODATA; - tf.nsect = SATA_AN; + tf.nsect = feature; err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0); @@ -4689,8 +4925,9 @@ 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_set_page(psg, nth_page(sg_page(lsg), offset >> PAGE_SHIFT)); - psg->offset = offset_in_page(offset); + sg_init_table(psg, 1); + sg_set_page(psg, nth_page(sg_page(lsg), offset >> PAGE_SHIFT), + qc->pad_len, offset_in_page(offset)); if (qc->tf.flags & ATA_TFLAG_WRITE) { void *addr = kmap_atomic(sg_page(psg), KM_IRQ0); @@ -5594,6 +5831,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 +5852,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 +6010,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 +6565,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 +6593,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 @@ -6860,6 +7138,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; @@ -6921,7 +7200,7 @@ int ata_host_activate(struct ata_host *host, int irq, * LOCKING: * Kernel thread context (may sleep). */ -void ata_port_detach(struct ata_port *ap) +static void ata_port_detach(struct ata_port *ap) { unsigned long flags; struct ata_link *link; @@ -7256,7 +7535,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); @@ -7326,6 +7604,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); diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 93e2b545b43..ed8813b222a 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1747,6 +1747,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 +1801,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 +1815,28 @@ 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; } + /* 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"); } @@ -1879,7 +1885,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; @@ -2064,16 +2072,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 int action; + unsigned long deadline, now; + unsigned int tmp_action; ata_reset_fn_t reset; unsigned long flags; + u32 sstatus; int rc; /* about to reset */ @@ -2083,17 +2094,36 @@ 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. */ - action = ehc->i.action; - ehc->i.action &= ~ATA_EH_RESET_MASK; - if (softreset && (!hardreset || (!(link->flags & ATA_LFLAG_NO_SRST) && + if (softreset && (!hardreset || (!(lflags & ATA_LFLAG_NO_SRST) && !sata_set_spd_needed(link) && - !(action & ATA_EH_HARDRESET)))) - ehc->i.action |= ATA_EH_SOFTRESET; + !(ehc->i.action & ATA_EH_HARDRESET)))) + tmp_action = ATA_EH_SOFTRESET; else - ehc->i.action |= ATA_EH_HARDRESET; + tmp_action = ATA_EH_HARDRESET; + + ehc->i.action = (ehc->i.action & ~ATA_EH_RESET_MASK) | tmp_action; if (prereset) { rc = prereset(link, jiffies + ATA_EH_PRERESET_TIMEOUT); @@ -2161,80 +2191,64 @@ 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 and convert UNKNOWN to NONE */ + 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 */ + else if (classes[dev->devno] == ATA_DEV_UNKNOWN) + classes[dev->devno] = ATA_DEV_NONE; + } - /* 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 +2258,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 +2452,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 +2643,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 +2712,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-scsi.c b/drivers/ata/libata-scsi.c index f5d5420a1ba..245057df69d 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 *)) { @@ -1040,6 +1108,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 +1432,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 @@ -2719,8 +2767,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; diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 90df58a3edc..0e6cf3a484d 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -101,6 +101,8 @@ 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 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_icside.c b/drivers/ata/pata_icside.c index be30923566c..842fe08a3c1 100644 --- a/drivers/ata/pata_icside.c +++ b/drivers/ata/pata_icside.c @@ -332,12 +332,13 @@ static void ata_dummy_noret(struct ata_port *port) { } -static void pata_icside_postreset(struct ata_port *ap, unsigned int *classes) +static void pata_icside_postreset(struct ata_link *link, unsigned int *classes) { + struct ata_port *ap = link->ap; struct pata_icside_state *state = ap->host->private_data; if (classes[0] != ATA_DEV_NONE || classes[1] != ATA_DEV_NONE) - return ata_std_postreset(ap, classes); + return ata_std_postreset(link, classes); state->port[ap->port_no].disabled = 1; @@ -395,29 +396,30 @@ static struct ata_port_operations pata_icside_port_ops = { static void __devinit pata_icside_setup_ioaddr(struct ata_port *ap, void __iomem *base, - const struct portinfo *info) + struct pata_icside_info *info, + const struct portinfo *port) { struct ata_ioports *ioaddr = &ap->ioaddr; - void __iomem *cmd = base + info->dataoffset; + void __iomem *cmd = base + port->dataoffset; ioaddr->cmd_addr = cmd; - ioaddr->data_addr = cmd + (ATA_REG_DATA << info->stepping); - ioaddr->error_addr = cmd + (ATA_REG_ERR << info->stepping); - ioaddr->feature_addr = cmd + (ATA_REG_FEATURE << info->stepping); - ioaddr->nsect_addr = cmd + (ATA_REG_NSECT << info->stepping); - ioaddr->lbal_addr = cmd + (ATA_REG_LBAL << info->stepping); - ioaddr->lbam_addr = cmd + (ATA_REG_LBAM << info->stepping); - ioaddr->lbah_addr = cmd + (ATA_REG_LBAH << info->stepping); - ioaddr->device_addr = cmd + (ATA_REG_DEVICE << info->stepping); - ioaddr->status_addr = cmd + (ATA_REG_STATUS << info->stepping); - ioaddr->command_addr = cmd + (ATA_REG_CMD << info->stepping); - - ioaddr->ctl_addr = base + info->ctrloffset; + ioaddr->data_addr = cmd + (ATA_REG_DATA << port->stepping); + ioaddr->error_addr = cmd + (ATA_REG_ERR << port->stepping); + ioaddr->feature_addr = cmd + (ATA_REG_FEATURE << port->stepping); + ioaddr->nsect_addr = cmd + (ATA_REG_NSECT << port->stepping); + ioaddr->lbal_addr = cmd + (ATA_REG_LBAL << port->stepping); + ioaddr->lbam_addr = cmd + (ATA_REG_LBAM << port->stepping); + ioaddr->lbah_addr = cmd + (ATA_REG_LBAH << port->stepping); + ioaddr->device_addr = cmd + (ATA_REG_DEVICE << port->stepping); + ioaddr->status_addr = cmd + (ATA_REG_STATUS << port->stepping); + ioaddr->command_addr = cmd + (ATA_REG_CMD << port->stepping); + + ioaddr->ctl_addr = base + port->ctrloffset; ioaddr->altstatus_addr = ioaddr->ctl_addr; ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", - info->raw_base + info->dataoffset, - info->raw_base + info->ctrloffset); + info->raw_base + port->dataoffset, + info->raw_base + port->ctrloffset); if (info->raw_ioc_base) ata_port_desc(ap, "iocbase 0x%lx", info->raw_ioc_base); @@ -441,7 +443,7 @@ static int __devinit pata_icside_register_v5(struct pata_icside_info *info) info->nr_ports = 1; info->port[0] = &pata_icside_portinfo_v5; - info->raw_base = ecard_resource_start(ec, ECARD_RES_MEMC); + info->raw_base = ecard_resource_start(info->ec, ECARD_RES_MEMC); return 0; } @@ -522,7 +524,7 @@ static int __devinit pata_icside_add_ports(struct pata_icside_info *info) ap->flags |= ATA_FLAG_SLAVE_POSS; ap->ops = &pata_icside_port_ops; - pata_icside_setup_ioaddr(ap, info->base, info->port[i]); + pata_icside_setup_ioaddr(ap, info->base, info, info->port[i]); } return ata_host_activate(host, ec->irq, ata_interrupt, 0, 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..bc7c2d5d8d5 100644 --- a/drivers/ata/pata_pdc202xx_old.c +++ b/drivers/ata/pata_pdc202xx_old.c @@ -351,9 +351,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_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_via.c b/drivers/ata/pata_via.c index ea7a9a652e6..a4175fbdd17 100644 --- a/drivers/ata/pata_via.c +++ b/drivers/ata/pata_via.c @@ -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); diff --git a/drivers/ata/pata_winbond.c b/drivers/ata/pata_winbond.c index 549cbbe9fd0..311cdb3a556 100644 --- a/drivers/ata/pata_winbond.c +++ b/drivers/ata/pata_winbond.c @@ -279,7 +279,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..a43f64d2775 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1156,7 +1156,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); @@ -2429,7 +2429,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; @@ -2510,7 +2510,8 @@ 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; } diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 2e0279fdd7a..35b2df29752 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 @@ -365,9 +365,9 @@ static const struct pci_device_id nv_pci_tbl[] = { { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2), SWNCQ }, { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA), SWNCQ }, { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2), SWNCQ }, - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA), SWNCQ }, - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2), SWNCQ }, - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3), SWNCQ }, + { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA), GENERIC }, + { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2), GENERIC }, + { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3), GENERIC }, { } /* terminate list */ }; @@ -884,8 +884,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 +1013,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 +1022,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 +1062,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 +1080,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 +1120,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 +1166,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 +1190,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 +1238,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 +1251,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 +1343,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++; } @@ -1359,12 +1361,12 @@ static int nv_adma_use_reg_mode(struct ata_queued_cmd *qc) /* 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) || + if ((pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) || (qc->tf.flags & ATA_TFLAG_POLLING) || (qc->flags & ATA_QCFLAG_RESULT_TF)) return 1; - if((qc->flags & ATA_QCFLAG_DMAMAP) || + if ((qc->flags & ATA_QCFLAG_DMAMAP) || (qc->tf.protocol == ATA_PROT_NODATA)) return 0; @@ -1401,14 +1403,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(); @@ -1435,16 +1437,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; } @@ -1641,12 +1643,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 +1656,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 +1676,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 +1687,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 +2354,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 +2368,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 +2385,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 +2434,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 +2450,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..6d43ba79e15 100644 --- a/drivers/ata/sata_qstor.c +++ b/drivers/ata/sata_qstor.c @@ -113,7 +113,7 @@ 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); @@ -135,7 +135,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, diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index ea3a0ab7e02..4e6e381279c 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; @@ -643,7 +644,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..187dcb02c68 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -265,11 +265,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" }, @@ -674,7 +674,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 +756,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. @@ -1270,7 +1271,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 +1284,7 @@ static void sil24_init_controller(struct ata_host *host) static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - static int printed_version = 0; + 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; 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/base/core.c b/drivers/base/core.c index c1343414d28..3f4d6aa1399 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1228,18 +1228,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/block/cciss.c b/drivers/block/cciss.c index 5a6fe17fc63..7d704968765 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 * 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/cryptoloop.c b/drivers/block/cryptoloop.c index 1b58b010797..241167878ed 100644 --- a/drivers/block/cryptoloop.c +++ b/drivers/block/cryptoloop.c @@ -150,13 +150,8 @@ cryptoloop_transfer(struct loop_device *lo, int cmd, u32 iv[4] = { 0, }; iv[0] = cpu_to_le32(IV & 0xffffffff); - sg_set_page(&sg_in, in_page); - sg_in.offset = in_offs; - sg_in.length = sz; - - sg_set_page(&sg_out, out_page); - sg_out.offset = out_offs; - sg_out.length = sz; + sg_set_page(&sg_in, in_page, sz, in_offs); + sg_set_page(&sg_out, out_page, sz, out_offs); desc.info = iv; err = encdecfunc(&desc, &sg_out, &sg_in, sz); diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c index 7276f7d207c..fac4c6cd04f 100644 --- a/drivers/block/sunvdc.c +++ b/drivers/block/sunvdc.c @@ -15,6 +15,7 @@ #include <linux/delay.h> #include <linux/init.h> #include <linux/list.h> +#include <linux/scatterlist.h> #include <asm/vio.h> #include <asm/ldc.h> diff --git a/drivers/block/ub.c b/drivers/block/ub.c index 14143f2c484..08e909dc794 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -1428,9 +1428,9 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd) scmd->state = UB_CMDST_INIT; scmd->nsg = 1; sg = &scmd->sgv[0]; - sg_set_page(sg, virt_to_page(sc->top_sense)); - sg->offset = (unsigned long)sc->top_sense & (PAGE_SIZE-1); - sg->length = UB_SENSE_SIZE; + sg_init_table(sg, UB_MAX_REQ_SG); + sg_set_page(sg, virt_to_page(sc->top_sense), UB_SENSE_SIZE, + (unsigned long)sc->top_sense & (PAGE_SIZE-1)); scmd->len = UB_SENSE_SIZE; scmd->lun = cmd->lun; scmd->done = ub_top_sense_done; @@ -1864,9 +1864,8 @@ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun, cmd->state = UB_CMDST_INIT; cmd->nsg = 1; sg = &cmd->sgv[0]; - sg_set_page(sg, virt_to_page(p)); - sg->offset = (unsigned long)p & (PAGE_SIZE-1); - sg->length = 8; + sg_init_table(sg, UB_MAX_REQ_SG); + sg_set_page(sg, virt_to_page(p), 8, (unsigned long)p & (PAGE_SIZE-1)); cmd->len = 8; cmd->lun = lun; cmd->done = ub_probe_done; diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index a901eee64ba..3cf7129d83e 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -4,7 +4,9 @@ #include <linux/hdreg.h> #include <linux/virtio.h> #include <linux/virtio_blk.h> -#include <linux/virtio_blk.h> +#include <linux/scatterlist.h> + +#define VIRTIO_MAX_SG (3+MAX_PHYS_SEGMENTS) static unsigned char virtblk_index = 'a'; struct virtio_blk @@ -23,7 +25,7 @@ struct virtio_blk mempool_t *pool; /* Scatterlist: can be too big for stack. */ - struct scatterlist sg[3+MAX_PHYS_SEGMENTS]; + struct scatterlist sg[VIRTIO_MAX_SG]; }; struct virtblk_req @@ -94,8 +96,8 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk, if (blk_barrier_rq(vbr->req)) vbr->out_hdr.type |= VIRTIO_BLK_T_BARRIER; - /* We have to zero this, otherwise blk_rq_map_sg gets upset. */ - memset(vblk->sg, 0, sizeof(vblk->sg)); + /* This init could be done at vblk creation time */ + sg_init_table(vblk->sg, VIRTIO_MAX_SG); sg_set_buf(&vblk->sg[0], &vbr->out_hdr, sizeof(vbr->out_hdr)); num = blk_rq_map_sg(q, vbr->req, vblk->sg+1); sg_set_buf(&vblk->sg[num+1], &vbr->in_hdr, sizeof(vbr->in_hdr)); diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index 880b5dce3a6..d8bb44b98a6 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -41,9 +41,9 @@ #include <linux/completion.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> +#include <linux/scatterlist.h> #include <asm/vio.h> -#include <asm/scatterlist.h> #include <asm/iseries/hv_types.h> #include <asm/iseries/hv_lp_event.h> #include <asm/iseries/vio.h> @@ -258,6 +258,7 @@ static int send_request(struct request *req) cmd = viomajorsubtype_cdio | viocdwrite; } + sg_init_table(&sg, 1); if (blk_rq_map_sg(req->q, req, &sg) == 0) { printk(VIOCD_KERN_WARNING "error setting up scatter/gather list\n"); 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/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/connector/connector.c b/drivers/connector/connector.c index 0e328d387af..6883fcb79ad 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -218,7 +218,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 +229,6 @@ static void cn_rx_skb(struct sk_buff *__skb) if (err < 0) kfree_skb(skb); } - -out: - kfree_skb(__skb); } /* 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/padlock-sha.c b/drivers/crypto/padlock-sha.c index 4e8de162fc1..c666b4e0933 100644 --- a/drivers/crypto/padlock-sha.c +++ b/drivers/crypto/padlock-sha.c @@ -55,7 +55,7 @@ static void padlock_sha_bypass(struct crypto_tfm *tfm) if (ctx(tfm)->data && ctx(tfm)->used) { struct scatterlist sg; - sg_set_buf(&sg, ctx(tfm)->data, ctx(tfm)->used); + sg_init_one(&sg, ctx(tfm)->data, ctx(tfm)->used); crypto_hash_update(&ctx(tfm)->fallback, &sg, sg.length); } @@ -79,7 +79,7 @@ static void padlock_sha_update(struct crypto_tfm *tfm, if (unlikely(ctx(tfm)->bypass)) { struct scatterlist sg; - sg_set_buf(&sg, (uint8_t *)data, length); + sg_init_one(&sg, (uint8_t *)data, length); crypto_hash_update(&ctx(tfm)->fallback, &sg, length); return; } diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 9c91b0fd134..6a7d25fc247 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -43,7 +43,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/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 67588326ae5..c9b9081831d 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -984,8 +984,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 +1163,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); @@ -1984,7 +1997,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/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/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/ide-iops.c b/drivers/ide/ide-iops.c index 95168833d06..dcda0f109df 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -582,9 +582,12 @@ 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" }, { NULL , NULL } }; 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..5682895d36d 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.21 Oct 23, 2007 * * Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org> * Portions Copyright (C) 2001 Sun Microsystems, Inc. @@ -433,7 +433,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 +441,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 +449,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 +457,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 +465,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 +473,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 +481,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 +489,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 +497,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 +505,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 +513,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 +1508,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 +1522,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 +1552,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 +1560,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/sc1200.c b/drivers/ide/pci/sc1200.c index d2c8b5524f2..0a7b3202066 100644 --- a/drivers/ide/pci/sc1200.c +++ b/drivers/ide/pci/sc1200.c @@ -324,17 +324,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/ieee1394/dma.c b/drivers/ieee1394/dma.c index 3051e312fdc..f5f4983dfbf 100644 --- a/drivers/ieee1394/dma.c +++ b/drivers/ieee1394/dma.c @@ -111,8 +111,8 @@ int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, unsigned long va = (unsigned long)dma->kvirt + (i << PAGE_SHIFT); - sg_set_page(&dma->sglist[i], vmalloc_to_page((void *)va)); - dma->sglist[i].length = PAGE_SIZE; + sg_set_page(&dma->sglist[i], vmalloc_to_page((void *)va), + PAGE_SIZE, 0); } /* map sglist to the IOMMU */ 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/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/core/umem.c b/drivers/infiniband/core/umem.c index 14159ff2940..4e3128ff73c 100644 --- a/drivers/infiniband/core/umem.c +++ b/drivers/infiniband/core/umem.c @@ -171,9 +171,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr, if (vma_list && !is_vm_hugetlb_page(vma_list[i + off])) umem->hugetlb = 0; - sg_set_page(&chunk->page_list[i], page_list[i + off]); - chunk->page_list[i].offset = 0; - chunk->page_list[i].length = PAGE_SIZE; + sg_set_page(&chunk->page_list[i], page_list[i + off], PAGE_SIZE, 0); } chunk->nmap = ib_dma_map_sg(context->device, 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_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/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/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c index 007b38157fc..1f4d27d7c16 100644 --- a/drivers/infiniband/hw/mthca/mthca_memfree.c +++ b/drivers/infiniband/hw/mthca/mthca_memfree.c @@ -113,9 +113,7 @@ static int mthca_alloc_icm_pages(struct scatterlist *mem, int order, gfp_t gfp_m if (!page) return -ENOMEM; - sg_set_page(mem, page); - mem->length = PAGE_SIZE << order; - mem->offset = 0; + sg_set_page(mem, page, PAGE_SIZE << order, 0); return 0; } @@ -481,9 +479,8 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar, if (ret < 0) goto out; - sg_set_page(&db_tab->page[i].mem, pages[0]); - db_tab->page[i].mem.length = MTHCA_ICM_PAGE_SIZE; - db_tab->page[i].mem.offset = uaddr & ~PAGE_MASK; + sg_set_page(&db_tab->page[i].mem, pages[0], MTHCA_ICM_PAGE_SIZE, + uaddr & ~PAGE_MASK); ret = pci_map_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE); if (ret < 0) { 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/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 6dd375825a1..6e9d75bd2b1 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -120,6 +120,7 @@ static const struct xpad_device { { 0x0738, 0x4536, "Mad Catz MicroCON", MAP_DPAD_TO_AXES, XTYPE_XBOX }, { 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, { 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, + { 0x0738, 0x4716, "Mad Catz Wired Xbox 360 Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, { 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, { 0x0c12, 0x8802, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, { 0x0c12, 0x8810, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, @@ -129,6 +130,7 @@ static const struct xpad_device { { 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, { 0x0e6f, 0x0005, "Eclipse wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, { 0x0e6f, 0x0006, "Edge wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, + { 0x0e6f, 0x0006, "Pelican 'TSZ' Wired Xbox 360 Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", MAP_DPAD_TO_AXES, XTYPE_XBOX }, { 0x0f30, 0x0202, "Joytech Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, 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/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index f132702d137..b4423a471f0 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c @@ -129,12 +129,12 @@ MODULE_DEVICE_TABLE (usb, atp_table); */ #define ATP_THRESHOLD 5 -/* MacBook Pro (Geyser 3 & 4) initialization constants */ -#define ATP_GEYSER3_MODE_READ_REQUEST_ID 1 -#define ATP_GEYSER3_MODE_WRITE_REQUEST_ID 9 -#define ATP_GEYSER3_MODE_REQUEST_VALUE 0x300 -#define ATP_GEYSER3_MODE_REQUEST_INDEX 0 -#define ATP_GEYSER3_MODE_VENDOR_VALUE 0x04 +/* Geyser initialization constants */ +#define ATP_GEYSER_MODE_READ_REQUEST_ID 1 +#define ATP_GEYSER_MODE_WRITE_REQUEST_ID 9 +#define ATP_GEYSER_MODE_REQUEST_VALUE 0x300 +#define ATP_GEYSER_MODE_REQUEST_INDEX 0 +#define ATP_GEYSER_MODE_VENDOR_VALUE 0x04 /* Structure to hold all of our device specific stuff */ struct atp { @@ -142,9 +142,11 @@ struct atp { struct usb_device * udev; /* usb device */ struct urb * urb; /* usb request block */ signed char * data; /* transferred data */ - int open; /* non-zero if opened */ - struct input_dev *input; /* input dev */ - int valid; /* are the sensors valid ? */ + struct input_dev * input; /* input dev */ + unsigned char open; /* non-zero if opened */ + unsigned char valid; /* are the sensors valid ? */ + unsigned char size_detect_done; + unsigned char overflowwarn; /* overflow warning printed? */ int x_old; /* last reported x/y, */ int y_old; /* used for smoothing */ /* current value of the sensors */ @@ -153,7 +155,6 @@ struct atp { signed char xy_old[ATP_XSENSORS + ATP_YSENSORS]; /* accumulated sensors */ int xy_acc[ATP_XSENSORS + ATP_YSENSORS]; - int overflowwarn; /* overflow warning printed? */ int datalen; /* size of an USB urb transfer */ int idlecount; /* number of empty packets */ struct work_struct work; @@ -170,7 +171,7 @@ struct atp { #define dprintk(format, a...) \ do { \ - if (debug) printk(format, ##a); \ + if (debug) printk(KERN_DEBUG format, ##a); \ } while (0) MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Michael Hanselmann"); @@ -188,6 +189,15 @@ static int debug = 1; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Activate debugging output"); +static inline int atp_is_fountain(struct atp *dev) +{ + u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct); + + return productId == FOUNTAIN_ANSI_PRODUCT_ID || + productId == FOUNTAIN_ISO_PRODUCT_ID || + productId == FOUNTAIN_TP_ONLY_PRODUCT_ID; +} + /* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */ static inline int atp_is_geyser_2(struct atp *dev) { @@ -211,52 +221,63 @@ static inline int atp_is_geyser_3(struct atp *dev) } /* - * By default Geyser 3 device sends standard USB HID mouse + * By default newer Geyser devices send standard USB HID mouse * packets (Report ID 2). This code changes device mode, so it * sends raw sensor reports (Report ID 5). */ -static int atp_geyser3_init(struct usb_device *udev) +static int atp_geyser_init(struct usb_device *udev) { char data[8]; int size; size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - ATP_GEYSER3_MODE_READ_REQUEST_ID, + ATP_GEYSER_MODE_READ_REQUEST_ID, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - ATP_GEYSER3_MODE_REQUEST_VALUE, - ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000); + ATP_GEYSER_MODE_REQUEST_VALUE, + ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000); if (size != 8) { err("Could not do mode read request from device" - " (Geyser 3 mode)"); + " (Geyser Raw mode)"); return -EIO; } /* Apply the mode switch */ - data[0] = ATP_GEYSER3_MODE_VENDOR_VALUE; + data[0] = ATP_GEYSER_MODE_VENDOR_VALUE; size = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - ATP_GEYSER3_MODE_WRITE_REQUEST_ID, + ATP_GEYSER_MODE_WRITE_REQUEST_ID, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - ATP_GEYSER3_MODE_REQUEST_VALUE, - ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000); + ATP_GEYSER_MODE_REQUEST_VALUE, + ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000); if (size != 8) { err("Could not do mode write request to device" - " (Geyser 3 mode)"); + " (Geyser Raw mode)"); return -EIO; } return 0; } -/* Reinitialise the device if it's a geyser 3 */ +/* + * Reinitialise the device. This usually stops stream of empty packets + * coming from it. + */ static void atp_reinit(struct work_struct *work) { struct atp *dev = container_of(work, struct atp, work); struct usb_device *udev = dev->udev; + int retval; dev->idlecount = 0; - atp_geyser3_init(udev); + + atp_geyser_init(udev); + + retval = usb_submit_urb(dev->urb, GFP_ATOMIC); + if (retval) { + err("%s - usb_submit_urb failed with result %d", + __FUNCTION__, retval); + } } static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, @@ -337,7 +358,7 @@ static void atp_complete(struct urb* urb) break; case -EOVERFLOW: if(!dev->overflowwarn) { - printk("appletouch: OVERFLOW with data " + printk(KERN_WARNING "appletouch: OVERFLOW with data " "length %d, actual length is %d\n", dev->datalen, dev->urb->actual_length); dev->overflowwarn = 1; @@ -426,15 +447,17 @@ static void atp_complete(struct urb* urb) dev->x_old = dev->y_old = -1; memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); - if (atp_is_geyser_3(dev)) /* No 17" Macbooks (yet) */ + if (dev->size_detect_done || + atp_is_geyser_3(dev)) /* No 17" Macbooks (yet) */ goto exit; /* 17" Powerbooks have extra X sensors */ - for (i = (atp_is_geyser_2(dev)?15:16); i < ATP_XSENSORS; i++) { - if (!dev->xy_cur[i]) continue; + for (i = (atp_is_geyser_2(dev) ? 15 : 16); i < ATP_XSENSORS; i++) { + if (!dev->xy_cur[i]) + continue; - printk("appletouch: 17\" model detected.\n"); - if(atp_is_geyser_2(dev)) + printk(KERN_INFO "appletouch: 17\" model detected.\n"); + if (atp_is_geyser_2(dev)) input_set_abs_params(dev->input, ABS_X, 0, (20 - 1) * ATP_XFACT - 1, @@ -444,10 +467,10 @@ static void atp_complete(struct urb* urb) (ATP_XSENSORS - 1) * ATP_XFACT - 1, ATP_FUZZ, 0); - break; } + dev->size_detect_done = 1; goto exit; } @@ -479,7 +502,7 @@ static void atp_complete(struct urb* urb) dev->y_old = y; if (debug > 1) - printk("appletouch: X: %3d Y: %3d " + printk(KERN_DEBUG "appletouch: X: %3d Y: %3d " "Xz: %3d Yz: %3d\n", x, y, x_z, y_z); @@ -507,19 +530,25 @@ static void atp_complete(struct urb* urb) input_report_key(dev->input, BTN_LEFT, key); input_sync(dev->input); - /* Many Geysers will continue to send packets continually after - the first touch unless reinitialised. Do so if it's been - idle for a while in order to avoid waking the kernel up - several hundred times a second */ - - if (!x && !y && !key) { - dev->idlecount++; - if (dev->idlecount == 10) { - dev->valid = 0; - schedule_work(&dev->work); - } - } else - dev->idlecount = 0; + /* + * Many Geysers will continue to send packets continually after + * the first touch unless reinitialised. Do so if it's been + * idle for a while in order to avoid waking the kernel up + * several hundred times a second. Re-initialization does not + * work on Fountain touchpads. + */ + if (!atp_is_fountain(dev)) { + if (!x && !y && !key) { + dev->idlecount++; + if (dev->idlecount == 10) { + dev->valid = 0; + schedule_work(&dev->work); + /* Don't resubmit urb here, wait for reinit */ + return; + } + } else + dev->idlecount = 0; + } exit: retval = usb_submit_urb(dev->urb, GFP_ATOMIC); @@ -593,12 +622,12 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id else dev->datalen = 81; - if (atp_is_geyser_3(dev)) { + if (!atp_is_fountain(dev)) { /* switch to raw sensor mode */ - if (atp_geyser3_init(udev)) + if (atp_geyser_init(udev)) goto err_free_devs; - printk("appletouch Geyser 3 inited.\n"); + printk(KERN_INFO "appletouch: Geyser mode initialized.\n"); } dev->urb = usb_alloc_urb(0, GFP_KERNEL); diff --git a/drivers/input/mouse/inport.c b/drivers/input/mouse/inport.c index 655a3921743..26ec09529b5 100644 --- a/drivers/input/mouse/inport.c +++ b/drivers/input/mouse/inport.c @@ -144,7 +144,7 @@ static int __init inport_init(void) b = inb(INPORT_SIGNATURE_PORT); c = inb(INPORT_SIGNATURE_PORT); if (a == b || a != c) { - printk(KERN_ERR "inport.c: Didn't find InPort mouse at %#x\n", INPORT_BASE); + printk(KERN_INFO "inport.c: Didn't find InPort mouse at %#x\n", INPORT_BASE); err = -ENODEV; goto err_release_region; } diff --git a/drivers/input/mouse/logibm.c b/drivers/input/mouse/logibm.c index b23a4f3ea5c..37e7c75b43b 100644 --- a/drivers/input/mouse/logibm.c +++ b/drivers/input/mouse/logibm.c @@ -134,7 +134,7 @@ static int __init logibm_init(void) udelay(100); if (inb(LOGIBM_SIGNATURE_PORT) != LOGIBM_SIGNATURE_BYTE) { - printk(KERN_ERR "logibm.c: Didn't find Logitech busmouse at %#x\n", LOGIBM_BASE); + printk(KERN_INFO "logibm.c: Didn't find Logitech busmouse at %#x\n", LOGIBM_BASE); err = -ENODEV; goto err_release_region; } diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c index 6af199805ff..02b3ad8c082 100644 --- a/drivers/input/serio/hp_sdc.c +++ b/drivers/input/serio/hp_sdc.c @@ -944,11 +944,7 @@ static int __init hp_sdc_init_hppa(struct parisc_device *d) #endif /* __hppa__ */ -#if !defined(__mc68000__) /* Link error on m68k! */ -static void __exit hp_sdc_exit(void) -#else static void hp_sdc_exit(void) -#endif { write_lock_irq(&hp_sdc.lock); 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/sc/shmem.c b/drivers/isdn/sc/shmem.c index 034d41a61ae..e0331e0094f 100644 --- a/drivers/isdn/sc/shmem.c +++ b/drivers/isdn/sc/shmem.c @@ -28,15 +28,15 @@ void memcpy_toshmem(int card, void *dest, const void *src, size_t n) { unsigned long flags; unsigned char ch; + unsigned long dest_rem = ((unsigned long) dest) % 0x4000; - if(!IS_VALID_CARD(card)) { + if (!IS_VALID_CARD(card)) { pr_debug("Invalid param: %d is not a valid card id\n", card); return; } - if(n > SRAM_PAGESIZE) { + if (n > SRAM_PAGESIZE) return; - } /* * determine the page to load from the address @@ -50,8 +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 + - ((unsigned long) dest % 0x4000), src, n); + memcpy_toio(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/lguest/core.c b/drivers/lguest/core.c index 35d19ae58de..cb4c67025d5 100644 --- a/drivers/lguest/core.c +++ b/drivers/lguest/core.c @@ -128,9 +128,12 @@ static void unmap_switcher(void) __free_pages(switcher_page[i], 0); } -/*L:305 +/*H:032 * Dealing With Guest Memory. * + * Before we go too much further into the Host, we need to grok the routines + * we use to deal with Guest memory. + * * When the Guest gives us (what it thinks is) a physical address, we can use * the normal copy_from_user() & copy_to_user() on the corresponding place in * the memory region allocated by the Launcher. diff --git a/drivers/lguest/hypercalls.c b/drivers/lguest/hypercalls.c index 9d5184c7c14..b478affe8f9 100644 --- a/drivers/lguest/hypercalls.c +++ b/drivers/lguest/hypercalls.c @@ -90,6 +90,7 @@ static void do_hcall(struct lguest *lg, struct hcall_args *args) lg->pending_notify = args->arg1; break; default: + /* It should be an architecture-specific hypercall. */ if (lguest_arch_do_hcall(lg, args)) kill_guest(lg, "Bad hypercall %li\n", args->arg0); } @@ -157,7 +158,6 @@ static void do_async_hcalls(struct lguest *lg) * Guest makes a hypercall, we end up here to set things up: */ static void initialize(struct lguest *lg) { - /* You can't do anything until you're initialized. The Guest knows the * rules, so we're unforgiving here. */ if (lg->hcall->arg0 != LHCALL_LGUEST_INIT) { @@ -174,7 +174,8 @@ static void initialize(struct lguest *lg) || get_user(lg->noirq_end, &lg->lguest_data->noirq_end)) kill_guest(lg, "bad guest page %p", lg->lguest_data); - /* We write the current time into the Guest's data page once now. */ + /* We write the current time into the Guest's data page once so it can + * set its clock. */ write_timestamp(lg); /* page_tables.c will also do some setup. */ @@ -182,8 +183,8 @@ static void initialize(struct lguest *lg) /* This is the one case where the above accesses might have been the * first write to a Guest page. This may have caused a copy-on-write - * fault, but the Guest might be referring to the old (read-only) - * page. */ + * fault, but the old page might be (read-only) in the Guest + * pagetable. */ guest_pagetable_clear_all(lg); } @@ -220,7 +221,7 @@ void do_hypercalls(struct lguest *lg) * Normally it doesn't matter: the Guest will run again and * update the trap number before we come back here. * - * However, if we are signalled or the Guest sends DMA to the + * However, if we are signalled or the Guest sends I/O to the * Launcher, the run_guest() loop will exit without running the * Guest. When it comes back it would try to re-run the * hypercall. */ diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c index 82966982cb3..2b66f79c208 100644 --- a/drivers/lguest/interrupts_and_traps.c +++ b/drivers/lguest/interrupts_and_traps.c @@ -92,8 +92,8 @@ static void set_guest_interrupt(struct lguest *lg, u32 lo, u32 hi, int has_err) /* Remember that we never let the Guest actually disable interrupts, so * the "Interrupt Flag" bit is always set. We copy that bit from the - * Guest's "irq_enabled" field into the eflags word: the Guest copies - * it back in "lguest_iret". */ + * Guest's "irq_enabled" field into the eflags word: we saw the Guest + * copy it back in "lguest_iret". */ eflags = lg->regs->eflags; if (get_user(irq_enable, &lg->lguest_data->irq_enabled) == 0 && !(irq_enable & X86_EFLAGS_IF)) @@ -124,7 +124,7 @@ static void set_guest_interrupt(struct lguest *lg, u32 lo, u32 hi, int has_err) kill_guest(lg, "Disabling interrupts"); } -/*H:200 +/*H:205 * Virtual Interrupts. * * maybe_do_interrupt() gets called before every entry to the Guest, to see if @@ -256,19 +256,21 @@ int deliver_trap(struct lguest *lg, unsigned int num) * bogus one in): if we fail here, the Guest will be killed. */ if (!idt_present(lg->arch.idt[num].a, lg->arch.idt[num].b)) return 0; - set_guest_interrupt(lg, lg->arch.idt[num].a, lg->arch.idt[num].b, has_err(num)); + set_guest_interrupt(lg, lg->arch.idt[num].a, lg->arch.idt[num].b, + has_err(num)); return 1; } /*H:250 Here's the hard part: returning to the Host every time a trap happens * and then calling deliver_trap() and re-entering the Guest is slow. - * Particularly because Guest userspace system calls are traps (trap 128). + * Particularly because Guest userspace system calls are traps (usually trap + * 128). * * So we'd like to set up the IDT to tell the CPU to deliver traps directly * into the Guest. This is possible, but the complexities cause the size of * this file to double! However, 150 lines of code is worth writing for taking * system calls down from 1750ns to 270ns. Plus, if lguest didn't do it, all - * the other hypervisors would tease it. + * the other hypervisors would beat it up at lunchtime. * * This routine indicates if a particular trap number could be delivered * directly. */ @@ -331,7 +333,7 @@ void pin_stack_pages(struct lguest *lg) * change stacks on each context switch. */ void guest_set_stack(struct lguest *lg, u32 seg, u32 esp, unsigned int pages) { - /* You are not allowd have a stack segment with privilege level 0: bad + /* You are not allowed have a stack segment with privilege level 0: bad * Guest! */ if ((seg & 0x3) != GUEST_PL) kill_guest(lg, "bad stack segment %i", seg); @@ -350,7 +352,7 @@ void guest_set_stack(struct lguest *lg, u32 seg, u32 esp, unsigned int pages) * part of the Host: page table handling. */ /*H:235 This is the routine which actually checks the Guest's IDT entry and - * transfers it into our entry in "struct lguest": */ + * transfers it into the entry in "struct lguest": */ static void set_trap(struct lguest *lg, struct desc_struct *trap, unsigned int num, u32 lo, u32 hi) { @@ -456,6 +458,18 @@ void copy_traps(const struct lguest *lg, struct desc_struct *idt, } } +/*H:200 + * The Guest Clock. + * + * There are two sources of virtual interrupts. We saw one in lguest_user.c: + * the Launcher sending interrupts for virtual devices. The other is the Guest + * timer interrupt. + * + * The Guest uses the LHCALL_SET_CLOCKEVENT hypercall to tell us how long to + * the next timer interrupt (in nanoseconds). We use the high-resolution timer + * infrastructure to set a callback at that time. + * + * 0 means "turn off the clock". */ void guest_set_clockevent(struct lguest *lg, unsigned long delta) { ktime_t expires; @@ -466,20 +480,27 @@ void guest_set_clockevent(struct lguest *lg, unsigned long delta) return; } + /* We use wallclock time here, so the Guest might not be running for + * all the time between now and the timer interrupt it asked for. This + * is almost always the right thing to do. */ expires = ktime_add_ns(ktime_get_real(), delta); hrtimer_start(&lg->hrt, expires, HRTIMER_MODE_ABS); } +/* This is the function called when the Guest's timer expires. */ static enum hrtimer_restart clockdev_fn(struct hrtimer *timer) { struct lguest *lg = container_of(timer, struct lguest, hrt); + /* Remember the first interrupt is the timer interrupt. */ set_bit(0, lg->irqs_pending); + /* If the Guest is actually stopped, we need to wake it up. */ if (lg->halted) wake_up_process(lg->tsk); return HRTIMER_NORESTART; } +/* This sets up the timer for this Guest. */ void init_clockdev(struct lguest *lg) { hrtimer_init(&lg->hrt, CLOCK_REALTIME, HRTIMER_MODE_ABS); diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h index d9144beca82..86924891b5e 100644 --- a/drivers/lguest/lg.h +++ b/drivers/lguest/lg.h @@ -74,9 +74,6 @@ struct lguest u32 pgdidx; struct pgdir pgdirs[4]; - /* Cached wakeup: we hold a reference to this task. */ - struct task_struct *wake; - unsigned long noirq_start, noirq_end; unsigned long pending_notify; /* pfn from LHCALL_NOTIFY */ @@ -103,7 +100,7 @@ int lguest_address_ok(const struct lguest *lg, void __lgread(struct lguest *, void *, unsigned long, unsigned); void __lgwrite(struct lguest *, unsigned long, const void *, unsigned); -/*L:306 Using memory-copy operations like that is usually inconvient, so we +/*H:035 Using memory-copy operations like that is usually inconvient, so we * have the following helper macros which read and write a specific type (often * an unsigned long). * @@ -191,7 +188,7 @@ void write_timestamp(struct lguest *lg); * Let's step aside for the moment, to study one important routine that's used * widely in the Host code. * - * There are many cases where the Guest does something invalid, like pass crap + * There are many cases where the Guest can do something invalid, like pass crap * to a hypercall. Since only the Guest kernel can make hypercalls, it's quite * acceptable to simply terminate the Guest and give the Launcher a nicely * formatted reason. It's also simpler for the Guest itself, which doesn't diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c index 71c64837b43..8904f72f97c 100644 --- a/drivers/lguest/lguest_device.c +++ b/drivers/lguest/lguest_device.c @@ -53,7 +53,8 @@ struct lguest_device { * Device configurations * * The configuration information for a device consists of a series of fields. - * The device will look for these fields during setup. + * We don't really care what they are: the Launcher set them up, and the driver + * will look at them during setup. * * For us these fields come immediately after that device's descriptor in the * lguest_devices page. @@ -122,8 +123,8 @@ static void lg_set_status(struct virtio_device *vdev, u8 status) * The other piece of infrastructure virtio needs is a "virtqueue": a way of * the Guest device registering buffers for the other side to read from or * write into (ie. send and receive buffers). Each device can have multiple - * virtqueues: for example the console has one queue for sending and one for - * receiving. + * virtqueues: for example the console driver uses one queue for sending and + * another for receiving. * * Fortunately for us, a very fast shared-memory-plus-descriptors virtqueue * already exists in virtio_ring.c. We just need to connect it up. @@ -158,7 +159,7 @@ static void lg_notify(struct virtqueue *vq) * * This is kind of an ugly duckling. It'd be nicer to have a standard * representation of a virtqueue in the configuration space, but it seems that - * everyone wants to do it differently. The KVM guys want the Guest to + * everyone wants to do it differently. The KVM coders want the Guest to * allocate its own pages and tell the Host where they are, but for lguest it's * simpler for the Host to simply tell us where the pages are. * @@ -284,6 +285,8 @@ static void add_lguest_device(struct lguest_device_desc *d) { struct lguest_device *ldev; + /* Start with zeroed memory; Linux's device layer seems to count on + * it. */ ldev = kzalloc(sizeof(*ldev), GFP_KERNEL); if (!ldev) { printk(KERN_EMERG "Cannot allocate lguest dev %u\n", diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c index ee405b38383..9d716fa42ca 100644 --- a/drivers/lguest/lguest_user.c +++ b/drivers/lguest/lguest_user.c @@ -8,20 +8,22 @@ #include <linux/fs.h> #include "lg.h" -/*L:315 To force the Guest to stop running and return to the Launcher, the - * Waker sets writes LHREQ_BREAK and the value "1" to /dev/lguest. The - * Launcher then writes LHREQ_BREAK and "0" to release the Waker. */ +/*L:055 When something happens, the Waker process needs a way to stop the + * kernel running the Guest and return to the Launcher. So the Waker writes + * LHREQ_BREAK and the value "1" to /dev/lguest to do this. Once the Launcher + * has done whatever needs attention, it writes LHREQ_BREAK and "0" to release + * the Waker. */ static int break_guest_out(struct lguest *lg, const unsigned long __user *input) { unsigned long on; - /* Fetch whether they're turning break on or off.. */ + /* Fetch whether they're turning break on or off. */ if (get_user(on, input) != 0) return -EFAULT; if (on) { lg->break_out = 1; - /* Pop it out (may be running on different CPU) */ + /* Pop it out of the Guest (may be running on different CPU) */ wake_up_process(lg->tsk); /* Wait for them to reset it */ return wait_event_interruptible(lg->break_wq, !lg->break_out); @@ -58,7 +60,7 @@ static ssize_t read(struct file *file, char __user *user, size_t size,loff_t*o) if (!lg) return -EINVAL; - /* If you're not the task which owns the guest, go away. */ + /* If you're not the task which owns the Guest, go away. */ if (current != lg->tsk) return -EPERM; @@ -92,8 +94,8 @@ static ssize_t read(struct file *file, char __user *user, size_t size,loff_t*o) * base: The start of the Guest-physical memory inside the Launcher memory. * * pfnlimit: The highest (Guest-physical) page number the Guest should be - * allowed to access. The Launcher has to live in Guest memory, so it sets - * this to ensure the Guest can't reach it. + * allowed to access. The Guest memory lives inside the Launcher, so it sets + * this to ensure the Guest can only reach its own memory. * * pgdir: The (Guest-physical) address of the top of the initial Guest * pagetables (which are set up by the Launcher). @@ -189,7 +191,7 @@ unlock: } /*L:010 The first operation the Launcher does must be a write. All writes - * start with a 32 bit number: for the first write this must be + * start with an unsigned long number: for the first write this must be * LHREQ_INITIALIZE to set up the Guest. After that the Launcher can use * writes of other values to send interrupts. */ static ssize_t write(struct file *file, const char __user *in, @@ -275,8 +277,7 @@ static int close(struct inode *inode, struct file *file) * The Launcher is the Host userspace program which sets up, runs and services * the Guest. In fact, many comments in the Drivers which refer to "the Host" * doing things are inaccurate: the Launcher does all the device handling for - * the Guest. The Guest can't tell what's done by the the Launcher and what by - * the Host. + * the Guest, but the Guest can't know that. * * Just to confuse you: to the Host kernel, the Launcher *is* the Guest and we * shall see more of that later. diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c index 2a45f0691c9..fffabb32715 100644 --- a/drivers/lguest/page_tables.c +++ b/drivers/lguest/page_tables.c @@ -26,7 +26,8 @@ * * We use two-level page tables for the Guest. If you're not entirely * comfortable with virtual addresses, physical addresses and page tables then - * I recommend you review lguest.c's "Page Table Handling" (with diagrams!). + * I recommend you review arch/x86/lguest/boot.c's "Page Table Handling" (with + * diagrams!). * * The Guest keeps page tables, but we maintain the actual ones here: these are * called "shadow" page tables. Which is a very Guest-centric name: these are @@ -36,11 +37,11 @@ * * Anyway, this is the most complicated part of the Host code. There are seven * parts to this: - * (i) Setting up a page table entry for the Guest when it faults, - * (ii) Setting up the page table entry for the Guest stack, - * (iii) Setting up a page table entry when the Guest tells us it has changed, + * (i) Looking up a page table entry when the Guest faults, + * (ii) Making sure the Guest stack is mapped, + * (iii) Setting up a page table entry when the Guest tells us one has changed, * (iv) Switching page tables, - * (v) Flushing (thowing away) page tables, + * (v) Flushing (throwing away) page tables, * (vi) Mapping the Switcher when the Guest is about to run, * (vii) Setting up the page tables initially. :*/ @@ -57,16 +58,15 @@ static DEFINE_PER_CPU(pte_t *, switcher_pte_pages); #define switcher_pte_page(cpu) per_cpu(switcher_pte_pages, cpu) -/*H:320 With our shadow and Guest types established, we need to deal with - * them: the page table code is curly enough to need helper functions to keep - * it clear and clean. +/*H:320 The page table code is curly enough to need helper functions to keep it + * clear and clean. * * There are two functions which return pointers to the shadow (aka "real") * page tables. * * spgd_addr() takes the virtual address and returns a pointer to the top-level - * page directory entry for that address. Since we keep track of several page - * tables, the "i" argument tells us which one we're interested in (it's + * page directory entry (PGD) for that address. Since we keep track of several + * page tables, the "i" argument tells us which one we're interested in (it's * usually the current one). */ static pgd_t *spgd_addr(struct lguest *lg, u32 i, unsigned long vaddr) { @@ -81,9 +81,9 @@ static pgd_t *spgd_addr(struct lguest *lg, u32 i, unsigned long vaddr) return &lg->pgdirs[i].pgdir[index]; } -/* This routine then takes the PGD entry given above, which contains the - * address of the PTE page. It then returns a pointer to the PTE entry for the - * given address. */ +/* This routine then takes the page directory entry returned above, which + * contains the address of the page table entry (PTE) page. It then returns a + * pointer to the PTE entry for the given address. */ static pte_t *spte_addr(struct lguest *lg, pgd_t spgd, unsigned long vaddr) { pte_t *page = __va(pgd_pfn(spgd) << PAGE_SHIFT); @@ -191,7 +191,7 @@ static void check_gpgd(struct lguest *lg, pgd_t gpgd) } /*H:330 - * (i) Setting up a page table entry for the Guest when it faults + * (i) Looking up a page table entry when the Guest faults. * * We saw this call in run_guest(): when we see a page fault in the Guest, we * come here. That's because we only set up the shadow page tables lazily as @@ -199,7 +199,7 @@ static void check_gpgd(struct lguest *lg, pgd_t gpgd) * and return to the Guest without it knowing. * * If we fixed up the fault (ie. we mapped the address), this routine returns - * true. */ + * true. Otherwise, it was a real fault and we need to tell the Guest. */ int demand_page(struct lguest *lg, unsigned long vaddr, int errcode) { pgd_t gpgd; @@ -246,16 +246,16 @@ int demand_page(struct lguest *lg, unsigned long vaddr, int errcode) if ((errcode & 2) && !(pte_flags(gpte) & _PAGE_RW)) return 0; - /* User access to a kernel page? (bit 3 == user access) */ + /* User access to a kernel-only page? (bit 3 == user access) */ if ((errcode & 4) && !(pte_flags(gpte) & _PAGE_USER)) return 0; /* Check that the Guest PTE flags are OK, and the page number is below * the pfn_limit (ie. not mapping the Launcher binary). */ check_gpte(lg, gpte); + /* Add the _PAGE_ACCESSED and (for a write) _PAGE_DIRTY flag */ gpte = pte_mkyoung(gpte); - if (errcode & 2) gpte = pte_mkdirty(gpte); @@ -272,23 +272,28 @@ int demand_page(struct lguest *lg, unsigned long vaddr, int errcode) else /* If this is a read, don't set the "writable" bit in the page * table entry, even if the Guest says it's writable. That way - * we come back here when a write does actually ocur, so we can - * update the Guest's _PAGE_DIRTY flag. */ + * we will come back here when a write does actually occur, so + * we can update the Guest's _PAGE_DIRTY flag. */ *spte = gpte_to_spte(lg, pte_wrprotect(gpte), 0); /* Finally, we write the Guest PTE entry back: we've set the * _PAGE_ACCESSED and maybe the _PAGE_DIRTY flags. */ lgwrite(lg, gpte_ptr, pte_t, gpte); - /* We succeeded in mapping the page! */ + /* The fault is fixed, the page table is populated, the mapping + * manipulated, the result returned and the code complete. A small + * delay and a trace of alliteration are the only indications the Guest + * has that a page fault occurred at all. */ return 1; } -/*H:360 (ii) Setting up the page table entry for the Guest stack. +/*H:360 + * (ii) Making sure the Guest stack is mapped. * - * Remember pin_stack_pages() which makes sure the stack is mapped? It could - * simply call demand_page(), but as we've seen that logic is quite long, and - * usually the stack pages are already mapped anyway, so it's not required. + * Remember that direct traps into the Guest need a mapped Guest kernel stack. + * pin_stack_pages() calls us here: we could simply call demand_page(), but as + * we've seen that logic is quite long, and usually the stack pages are already + * mapped, so it's overkill. * * This is a quick version which answers the question: is this virtual address * mapped by the shadow page tables, and is it writable? */ @@ -297,7 +302,7 @@ static int page_writable(struct lguest *lg, unsigned long vaddr) pgd_t *spgd; unsigned long flags; - /* Look at the top level entry: is it present? */ + /* Look at the current top level entry: is it present? */ spgd = spgd_addr(lg, lg->pgdidx, vaddr); if (!(pgd_flags(*spgd) & _PAGE_PRESENT)) return 0; @@ -333,15 +338,14 @@ static void release_pgd(struct lguest *lg, pgd_t *spgd) release_pte(ptepage[i]); /* Now we can free the page of PTEs */ free_page((long)ptepage); - /* And zero out the PGD entry we we never release it twice. */ + /* And zero out the PGD entry so we never release it twice. */ *spgd = __pgd(0); } } -/*H:440 (v) Flushing (thowing away) page tables, - * - * We saw flush_user_mappings() called when we re-used a top-level pgdir page. - * It simply releases every PTE page from 0 up to the kernel address. */ +/*H:445 We saw flush_user_mappings() twice: once from the flush_user_mappings() + * hypercall and once in new_pgdir() when we re-used a top-level pgdir page. + * It simply releases every PTE page from 0 up to the Guest's kernel address. */ static void flush_user_mappings(struct lguest *lg, int idx) { unsigned int i; @@ -350,8 +354,10 @@ static void flush_user_mappings(struct lguest *lg, int idx) release_pgd(lg, lg->pgdirs[idx].pgdir + i); } -/* The Guest also has a hypercall to do this manually: it's used when a large - * number of mappings have been changed. */ +/*H:440 (v) Flushing (throwing away) page tables, + * + * The Guest has a hypercall to throw away the page tables: it's used when a + * large number of mappings have been changed. */ void guest_pagetable_flush_user(struct lguest *lg) { /* Drop the userspace part of the current page table. */ @@ -423,8 +429,9 @@ static unsigned int new_pgdir(struct lguest *lg, /*H:430 (iv) Switching page tables * - * This is what happens when the Guest changes page tables (ie. changes the - * top-level pgdir). This happens on almost every context switch. */ + * Now we've seen all the page table setting and manipulation, let's see what + * what happens when the Guest changes page tables (ie. changes the top-level + * pgdir). This occurs on almost every context switch. */ void guest_new_pagetable(struct lguest *lg, unsigned long pgtable) { int newpgdir, repin = 0; @@ -443,7 +450,8 @@ void guest_new_pagetable(struct lguest *lg, unsigned long pgtable) } /*H:470 Finally, a routine which throws away everything: all PGD entries in all - * the shadow page tables. This is used when we destroy the Guest. */ + * the shadow page tables, including the Guest's kernel mappings. This is used + * when we destroy the Guest. */ static void release_all_pagetables(struct lguest *lg) { unsigned int i, j; @@ -458,13 +466,22 @@ static void release_all_pagetables(struct lguest *lg) /* We also throw away everything when a Guest tells us it's changed a kernel * mapping. Since kernel mappings are in every page table, it's easiest to - * throw them all away. This is amazingly slow, but thankfully rare. */ + * throw them all away. This traps the Guest in amber for a while as + * everything faults back in, but it's rare. */ void guest_pagetable_clear_all(struct lguest *lg) { release_all_pagetables(lg); /* We need the Guest kernel stack mapped again. */ pin_stack_pages(lg); } +/*:*/ +/*M:009 Since we throw away all mappings when a kernel mapping changes, our + * performance sucks for guests using highmem. In fact, a guest with + * PAGE_OFFSET 0xc0000000 (the default) and more than about 700MB of RAM is + * usually slower than a Guest with less memory. + * + * This, of course, cannot be fixed. It would take some kind of... well, I + * don't know, but the term "puissant code-fu" comes to mind. :*/ /*H:420 This is the routine which actually sets the page table entry for then * "idx"'th shadow page table. @@ -483,7 +500,7 @@ void guest_pagetable_clear_all(struct lguest *lg) static void do_set_pte(struct lguest *lg, int idx, unsigned long vaddr, pte_t gpte) { - /* Look up the matching shadow page directot entry. */ + /* Look up the matching shadow page directory entry. */ pgd_t *spgd = spgd_addr(lg, idx, vaddr); /* If the top level isn't present, there's no entry to update. */ @@ -500,7 +517,8 @@ static void do_set_pte(struct lguest *lg, int idx, *spte = gpte_to_spte(lg, gpte, pte_flags(gpte) & _PAGE_DIRTY); } else - /* Otherwise we can demand_page() it in later. */ + /* Otherwise kill it and we can demand_page() it in + * later. */ *spte = __pte(0); } } @@ -535,7 +553,7 @@ void guest_set_pte(struct lguest *lg, } /*H:400 - * (iii) Setting up a page table entry when the Guest tells us it has changed. + * (iii) Setting up a page table entry when the Guest tells us one has changed. * * Just like we did in interrupts_and_traps.c, it makes sense for us to deal * with the other side of page tables while we're here: what happens when the @@ -612,9 +630,10 @@ void free_guest_pagetable(struct lguest *lg) /*H:480 (vi) Mapping the Switcher when the Guest is about to run. * - * The Switcher and the two pages for this CPU need to be available to the + * The Switcher and the two pages for this CPU need to be visible in the * Guest (and not the pages for other CPUs). We have the appropriate PTE pages - * for each CPU already set up, we just need to hook them in. */ + * for each CPU already set up, we just need to hook them in now we know which + * Guest is about to run on this CPU. */ void map_switcher_in_guest(struct lguest *lg, struct lguest_pages *pages) { pte_t *switcher_pte_page = __get_cpu_var(switcher_pte_pages); @@ -677,6 +696,18 @@ static __init void populate_switcher_pte_page(unsigned int cpu, __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED)); } +/* We've made it through the page table code. Perhaps our tired brains are + * still processing the details, or perhaps we're simply glad it's over. + * + * If nothing else, note that all this complexity in juggling shadow page + * tables in sync with the Guest's page tables is for one reason: for most + * Guests this page table dance determines how bad performance will be. This + * is why Xen uses exotic direct Guest pagetable manipulation, and why both + * Intel and AMD have implemented shadow page table support directly into + * hardware. + * + * There is just one file remaining in the Host. */ + /*H:510 At boot or module load time, init_pagetables() allocates and populates * the Switcher PTE page for each CPU. */ __init int init_pagetables(struct page **switcher_page, unsigned int pages) diff --git a/drivers/lguest/segments.c b/drivers/lguest/segments.c index c2434ec99f7..9e189cbec7d 100644 --- a/drivers/lguest/segments.c +++ b/drivers/lguest/segments.c @@ -12,8 +12,6 @@ #include "lg.h" /*H:600 - * We've almost completed the Host; there's just one file to go! - * * Segments & The Global Descriptor Table * * (That title sounds like a bad Nerdcore group. Not to suggest that there are @@ -55,7 +53,7 @@ static int ignored_gdt(unsigned int num) || num == GDT_ENTRY_DOUBLEFAULT_TSS); } -/*H:610 Once the GDT has been changed, we fix the new entries up a little. We +/*H:630 Once the Guest gave us new GDT entries, we fix them up a little. We * don't care if they're invalid: the worst that can happen is a General * Protection Fault in the Switcher when it restores a Guest segment register * which tries to use that entry. Then we kill the Guest for causing such a @@ -84,25 +82,33 @@ static void fixup_gdt_table(struct lguest *lg, unsigned start, unsigned end) } } -/* This routine is called at boot or modprobe time for each CPU to set up the - * "constant" GDT entries for Guests running on that CPU. */ +/*H:610 Like the IDT, we never simply use the GDT the Guest gives us. We keep + * a GDT for each CPU, and copy across the Guest's entries each time we want to + * run the Guest on that CPU. + * + * This routine is called at boot or modprobe time for each CPU to set up the + * constant GDT entries: the ones which are the same no matter what Guest we're + * running. */ void setup_default_gdt_entries(struct lguest_ro_state *state) { struct desc_struct *gdt = state->guest_gdt; unsigned long tss = (unsigned long)&state->guest_tss; - /* The hypervisor segments are full 0-4G segments, privilege level 0 */ + /* The Switcher segments are full 0-4G segments, privilege level 0 */ gdt[GDT_ENTRY_LGUEST_CS] = FULL_EXEC_SEGMENT; gdt[GDT_ENTRY_LGUEST_DS] = FULL_SEGMENT; - /* The TSS segment refers to the TSS entry for this CPU, so we cannot - * copy it from the Guest. Forgive the magic flags */ + /* The TSS segment refers to the TSS entry for this particular CPU. + * Forgive the magic flags: the 0x8900 means the entry is Present, it's + * privilege level 0 Available 386 TSS system segment, and the 0x67 + * means Saturn is eclipsed by Mercury in the twelfth house. */ gdt[GDT_ENTRY_TSS].a = 0x00000067 | (tss << 16); gdt[GDT_ENTRY_TSS].b = 0x00008900 | (tss & 0xFF000000) | ((tss >> 16) & 0x000000FF); } -/* This routine is called before the Guest is run for the first time. */ +/* This routine sets up the initial Guest GDT for booting. All entries start + * as 0 (unusable). */ void setup_guest_gdt(struct lguest *lg) { /* Start with full 0-4G segments... */ @@ -114,13 +120,8 @@ void setup_guest_gdt(struct lguest *lg) lg->arch.gdt[GDT_ENTRY_KERNEL_DS].b |= (GUEST_PL << 13); } -/* Like the IDT, we never simply use the GDT the Guest gives us. We set up the - * GDTs for each CPU, then we copy across the entries each time we want to run - * a different Guest on that CPU. */ - -/* A partial GDT load, for the three "thead-local storage" entries. Otherwise - * it's just like load_guest_gdt(). So much, in fact, it would probably be - * neater to have a single hypercall to cover both. */ +/*H:650 An optimization of copy_gdt(), for just the three "thead-local storage" + * entries. */ void copy_gdt_tls(const struct lguest *lg, struct desc_struct *gdt) { unsigned int i; @@ -129,7 +130,9 @@ void copy_gdt_tls(const struct lguest *lg, struct desc_struct *gdt) gdt[i] = lg->arch.gdt[i]; } -/* This is the full version */ +/*H:640 When the Guest is run on a different CPU, or the GDT entries have + * changed, copy_gdt() is called to copy the Guest's GDT entries across to this + * CPU's GDT. */ void copy_gdt(const struct lguest *lg, struct desc_struct *gdt) { unsigned int i; @@ -141,7 +144,8 @@ void copy_gdt(const struct lguest *lg, struct desc_struct *gdt) gdt[i] = lg->arch.gdt[i]; } -/* This is where the Guest asks us to load a new GDT (LHCALL_LOAD_GDT). */ +/*H:620 This is where the Guest asks us to load a new GDT (LHCALL_LOAD_GDT). + * We copy it from the Guest and tweak the entries. */ void load_guest_gdt(struct lguest *lg, unsigned long table, u32 num) { /* We assume the Guest has the same number of GDT entries as the @@ -157,16 +161,22 @@ void load_guest_gdt(struct lguest *lg, unsigned long table, u32 num) lg->changed |= CHANGED_GDT; } +/* This is the fast-track version for just changing the three TLS entries. + * Remember that this happens on every context switch, so it's worth + * optimizing. But wouldn't it be neater to have a single hypercall to cover + * both cases? */ void guest_load_tls(struct lguest *lg, unsigned long gtls) { struct desc_struct *tls = &lg->arch.gdt[GDT_ENTRY_TLS_MIN]; __lgread(lg, tls, gtls, sizeof(*tls)*GDT_ENTRY_TLS_ENTRIES); fixup_gdt_table(lg, GDT_ENTRY_TLS_MIN, GDT_ENTRY_TLS_MAX+1); + /* Note that just the TLS entries have changed. */ lg->changed |= CHANGED_GDT_TLS; } +/*:*/ -/* +/*H:660 * With this, we have finished the Host. * * Five of the seven parts of our task are complete. You have made it through diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index 9eed12d5a39..482aec2a963 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c @@ -63,7 +63,7 @@ static struct lguest_pages *lguest_pages(unsigned int cpu) static DEFINE_PER_CPU(struct lguest *, last_guest); /*S:010 - * We are getting close to the Switcher. + * We approach the Switcher. * * Remember that each CPU has two pages which are visible to the Guest when it * runs on that CPU. This has to contain the state for that Guest: we copy the @@ -134,7 +134,7 @@ static void run_guest_once(struct lguest *lg, struct lguest_pages *pages) * * The lcall also pushes the old code segment (KERNEL_CS) onto the * stack, then the address of this call. This stack layout happens to - * exactly match the stack of an interrupt... */ + * exactly match the stack layout created by an interrupt... */ asm volatile("pushf; lcall *lguest_entry" /* This is how we tell GCC that %eax ("a") and %ebx ("b") * are changed by this routine. The "=" means output. */ @@ -151,40 +151,46 @@ static void run_guest_once(struct lguest *lg, struct lguest_pages *pages) } /*:*/ +/*M:002 There are hooks in the scheduler which we can register to tell when we + * get kicked off the CPU (preempt_notifier_register()). This would allow us + * to lazily disable SYSENTER which would regain some performance, and should + * also simplify copy_in_guest_info(). Note that we'd still need to restore + * things when we exit to Launcher userspace, but that's fairly easy. + * + * The hooks were designed for KVM, but we can also put them to good use. :*/ + /*H:040 This is the i386-specific code to setup and run the Guest. Interrupts * are disabled: we own the CPU. */ void lguest_arch_run_guest(struct lguest *lg) { - /* Remember the awfully-named TS bit? If the Guest has asked - * to set it we set it now, so we can trap and pass that trap - * to the Guest if it uses the FPU. */ + /* Remember the awfully-named TS bit? If the Guest has asked to set it + * we set it now, so we can trap and pass that trap to the Guest if it + * uses the FPU. */ if (lg->ts) lguest_set_ts(); - /* SYSENTER is an optimized way of doing system calls. We - * can't allow it because it always jumps to privilege level 0. - * A normal Guest won't try it because we don't advertise it in - * CPUID, but a malicious Guest (or malicious Guest userspace - * program) could, so we tell the CPU to disable it before - * running the Guest. */ + /* SYSENTER is an optimized way of doing system calls. We can't allow + * it because it always jumps to privilege level 0. A normal Guest + * won't try it because we don't advertise it in CPUID, but a malicious + * Guest (or malicious Guest userspace program) could, so we tell the + * CPU to disable it before running the Guest. */ if (boot_cpu_has(X86_FEATURE_SEP)) wrmsr(MSR_IA32_SYSENTER_CS, 0, 0); - /* Now we actually run the Guest. It will pop back out when - * something interesting happens, and we can examine its - * registers to see what it was doing. */ + /* Now we actually run the Guest. It will return when something + * interesting happens, and we can examine its registers to see what it + * was doing. */ run_guest_once(lg, lguest_pages(raw_smp_processor_id())); - /* The "regs" pointer contains two extra entries which are not - * really registers: a trap number which says what interrupt or - * trap made the switcher code come back, and an error code - * which some traps set. */ + /* Note that the "regs" pointer contains two extra entries which are + * not really registers: a trap number which says what interrupt or + * trap made the switcher code come back, and an error code which some + * traps set. */ - /* If the Guest page faulted, then the cr2 register will tell - * us the bad virtual address. We have to grab this now, - * because once we re-enable interrupts an interrupt could - * fault and thus overwrite cr2, or we could even move off to a - * different CPU. */ + /* If the Guest page faulted, then the cr2 register will tell us the + * bad virtual address. We have to grab this now, because once we + * re-enable interrupts an interrupt could fault and thus overwrite + * cr2, or we could even move off to a different CPU. */ if (lg->regs->trapnum == 14) lg->arch.last_pagefault = read_cr2(); /* Similarly, if we took a trap because the Guest used the FPU, @@ -197,14 +203,15 @@ void lguest_arch_run_guest(struct lguest *lg) wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0); } -/*H:130 Our Guest is usually so well behaved; it never tries to do things it - * isn't allowed to. Unfortunately, Linux's paravirtual infrastructure isn't - * quite complete, because it doesn't contain replacements for the Intel I/O - * instructions. As a result, the Guest sometimes fumbles across one during - * the boot process as it probes for various things which are usually attached - * to a PC. +/*H:130 Now we've examined the hypercall code; our Guest can make requests. + * Our Guest is usually so well behaved; it never tries to do things it isn't + * allowed to, and uses hypercalls instead. Unfortunately, Linux's paravirtual + * infrastructure isn't quite complete, because it doesn't contain replacements + * for the Intel I/O instructions. As a result, the Guest sometimes fumbles + * across one during the boot process as it probes for various things which are + * usually attached to a PC. * - * When the Guest uses one of these instructions, we get trap #13 (General + * When the Guest uses one of these instructions, we get a trap (General * Protection Fault) and come here. We see if it's one of those troublesome * instructions and skip over it. We return true if we did. */ static int emulate_insn(struct lguest *lg) @@ -275,43 +282,43 @@ static int emulate_insn(struct lguest *lg) void lguest_arch_handle_trap(struct lguest *lg) { switch (lg->regs->trapnum) { - case 13: /* We've intercepted a GPF. */ - /* Check if this was one of those annoying IN or OUT - * instructions which we need to emulate. If so, we - * just go back into the Guest after we've done it. */ + case 13: /* We've intercepted a General Protection Fault. */ + /* Check if this was one of those annoying IN or OUT + * instructions which we need to emulate. If so, we just go + * back into the Guest after we've done it. */ if (lg->regs->errcode == 0) { if (emulate_insn(lg)) return; } break; - case 14: /* We've intercepted a page fault. */ - /* The Guest accessed a virtual address that wasn't - * mapped. This happens a lot: we don't actually set - * up most of the page tables for the Guest at all when - * we start: as it runs it asks for more and more, and - * we set them up as required. In this case, we don't - * even tell the Guest that the fault happened. - * - * The errcode tells whether this was a read or a - * write, and whether kernel or userspace code. */ + case 14: /* We've intercepted a Page Fault. */ + /* The Guest accessed a virtual address that wasn't mapped. + * This happens a lot: we don't actually set up most of the + * page tables for the Guest at all when we start: as it runs + * it asks for more and more, and we set them up as + * required. In this case, we don't even tell the Guest that + * the fault happened. + * + * The errcode tells whether this was a read or a write, and + * whether kernel or userspace code. */ if (demand_page(lg, lg->arch.last_pagefault, lg->regs->errcode)) return; - /* OK, it's really not there (or not OK): the Guest - * needs to know. We write out the cr2 value so it - * knows where the fault occurred. - * - * Note that if the Guest were really messed up, this - * could happen before it's done the INITIALIZE - * hypercall, so lg->lguest_data will be NULL */ + /* OK, it's really not there (or not OK): the Guest needs to + * know. We write out the cr2 value so it knows where the + * fault occurred. + * + * Note that if the Guest were really messed up, this could + * happen before it's done the LHCALL_LGUEST_INIT hypercall, so + * lg->lguest_data could be NULL */ if (lg->lguest_data && put_user(lg->arch.last_pagefault, &lg->lguest_data->cr2)) kill_guest(lg, "Writing cr2"); break; case 7: /* We've intercepted a Device Not Available fault. */ - /* If the Guest doesn't want to know, we already - * restored the Floating Point Unit, so we just - * continue without telling it. */ + /* If the Guest doesn't want to know, we already restored the + * Floating Point Unit, so we just continue without telling + * it. */ if (!lg->ts) return; break; @@ -536,9 +543,6 @@ int lguest_arch_init_hypercalls(struct lguest *lg) return 0; } -/* Now we've examined the hypercall code; our Guest can make requests. There - * is one other way we can do things for the Guest, as we see in - * emulate_insn(). :*/ /*L:030 lguest_arch_setup_regs() * @@ -562,7 +566,7 @@ void lguest_arch_setup_regs(struct lguest *lg, unsigned long start) * is supposed to always be "1". Bit 9 (0x200) controls whether * interrupts are enabled. We always leave interrupts enabled while * running the Guest. */ - regs->eflags = 0x202; + regs->eflags = X86_EFLAGS_IF | 0x2; /* The "Extended Instruction Pointer" register says where the Guest is * running. */ @@ -570,8 +574,8 @@ void lguest_arch_setup_regs(struct lguest *lg, unsigned long start) /* %esi points to our boot information, at physical address 0, so don't * touch it. */ + /* There are a couple of GDT entries the Guest expects when first * booting. */ - setup_guest_gdt(lg); } diff --git a/drivers/lguest/x86/switcher_32.S b/drivers/lguest/x86/switcher_32.S index 1010b90b11f..0af8baaa0d4 100644 --- a/drivers/lguest/x86/switcher_32.S +++ b/drivers/lguest/x86/switcher_32.S @@ -6,6 +6,37 @@ * are feeling invigorated and refreshed then the next, more challenging stage * can be found in "make Guest". :*/ +/*M:012 Lguest is meant to be simple: my rule of thumb is that 1% more LOC must + * gain at least 1% more performance. Since neither LOC nor performance can be + * measured beforehand, it generally means implementing a feature then deciding + * if it's worth it. And once it's implemented, who can say no? + * + * This is why I haven't implemented this idea myself. I want to, but I + * haven't. You could, though. + * + * The main place where lguest performance sucks is Guest page faulting. When + * a Guest userspace process hits an unmapped page we switch back to the Host, + * walk the page tables, find it's not mapped, switch back to the Guest page + * fault handler, which calls a hypercall to set the page table entry, then + * finally returns to userspace. That's two round-trips. + * + * If we had a small walker in the Switcher, we could quickly check the Guest + * page table and if the page isn't mapped, immediately reflect the fault back + * into the Guest. This means the Switcher would have to know the top of the + * Guest page table and the page fault handler address. + * + * For simplicity, the Guest should only handle the case where the privilege + * level of the fault is 3 and probably only not present or write faults. It + * should also detect recursive faults, and hand the original fault to the + * Host (which is actually really easy). + * + * Two questions remain. Would the performance gain outweigh the complexity? + * And who would write the verse documenting it? :*/ + +/*M:011 Lguest64 handles NMI. This gave me NMI envy (until I looked at their + * code). It's worth doing though, since it would let us use oprofile in the + * Host when a Guest is running. :*/ + /*S:100 * Welcome to the Switcher itself! * @@ -88,7 +119,7 @@ ENTRY(switch_to_guest) // All saved and there's now five steps before us: // Stack, GDT, IDT, TSS - // And last of all the page tables are flipped. + // Then last of all the page tables are flipped. // Yet beware that our stack pointer must be // Always valid lest an NMI hits @@ -103,25 +134,25 @@ ENTRY(switch_to_guest) lgdt LGUEST_PAGES_guest_gdt_desc(%eax) // The Guest's IDT we did partially - // Move to the "struct lguest_pages" as well. + // Copy to "struct lguest_pages" as well. lidt LGUEST_PAGES_guest_idt_desc(%eax) // The TSS entry which controls traps // Must be loaded up with "ltr" now: + // The GDT entry that TSS uses + // Changes type when we load it: damn Intel! // For after we switch over our page tables - // It (as the rest) will be writable no more. - // (The GDT entry TSS needs - // Changes type when we load it: damn Intel!) + // That entry will be read-only: we'd crash. movl $(GDT_ENTRY_TSS*8), %edx ltr %dx // Look back now, before we take this last step! // The Host's TSS entry was also marked used; - // Let's clear it again, ere we return. + // Let's clear it again for our return. // The GDT descriptor of the Host // Points to the table after two "size" bytes movl (LGUEST_PAGES_host_gdt_desc+2)(%eax), %edx - // Clear the type field of "used" (byte 5, bit 2) + // Clear "used" from type field (byte 5, bit 2) andb $0xFD, (GDT_ENTRY_TSS*8 + 5)(%edx) // Once our page table's switched, the Guest is live! @@ -131,7 +162,7 @@ ENTRY(switch_to_guest) // The page table change did one tricky thing: // The Guest's register page has been mapped - // Writable onto our %esp (stack) -- + // Writable under our %esp (stack) -- // We can simply pop off all Guest regs. popl %eax popl %ebx @@ -152,16 +183,15 @@ ENTRY(switch_to_guest) addl $8, %esp // The last five stack slots hold return address - // And everything needed to change privilege - // Into the Guest privilege level of 1, + // And everything needed to switch privilege + // From Switcher's level 0 to Guest's 1, // And the stack where the Guest had last left it. // Interrupts are turned back on: we are Guest. iret -// There are two paths where we switch to the Host +// We treat two paths to switch back to the Host +// Yet both must save Guest state and restore Host // So we put the routine in a macro. -// We are on our way home, back to the Host -// Interrupted out of the Guest, we come here. #define SWITCH_TO_HOST \ /* We save the Guest state: all registers first \ * Laid out just as "struct lguest_regs" defines */ \ @@ -194,7 +224,7 @@ ENTRY(switch_to_guest) movl %esp, %eax; \ andl $(~(1 << PAGE_SHIFT - 1)), %eax; \ /* Save our trap number: the switch will obscure it \ - * (The Guest regs are not mapped here in the Host) \ + * (In the Host the Guest regs are not mapped here) \ * %ebx holds it safe for deliver_to_host */ \ movl LGUEST_PAGES_regs_trapnum(%eax), %ebx; \ /* The Host GDT, IDT and stack! \ @@ -210,9 +240,9 @@ ENTRY(switch_to_guest) /* Switch to Host's GDT, IDT. */ \ lgdt LGUEST_PAGES_host_gdt_desc(%eax); \ lidt LGUEST_PAGES_host_idt_desc(%eax); \ - /* Restore the Host's stack where it's saved regs lie */ \ + /* Restore the Host's stack where its saved regs lie */ \ movl LGUEST_PAGES_host_sp(%eax), %esp; \ - /* Last the TSS: our Host is complete */ \ + /* Last the TSS: our Host is returned */ \ movl $(GDT_ENTRY_TSS*8), %edx; \ ltr %dx; \ /* Restore now the regs saved right at the first. */ \ @@ -222,14 +252,15 @@ ENTRY(switch_to_guest) popl %ds; \ popl %es -// Here's where we come when the Guest has just trapped: -// (Which trap we'll see has been pushed on the stack). +// The first path is trod when the Guest has trapped: +// (Which trap it was has been pushed on the stack). // We need only switch back, and the Host will decode // Why we came home, and what needs to be done. return_to_host: SWITCH_TO_HOST iret +// We are lead to the second path like so: // An interrupt, with some cause external // Has ajerked us rudely from the Guest's code // Again we must return home to the Host @@ -238,7 +269,7 @@ deliver_to_host: // But now we must go home via that place // Where that interrupt was supposed to go // Had we not been ensconced, running the Guest. - // Here we see the cleverness of our stack: + // Here we see the trickness of run_guest_once(): // The Host stack is formed like an interrupt // With EIP, CS and EFLAGS layered. // Interrupt handlers end with "iret" @@ -263,7 +294,7 @@ deliver_to_host: xorw %ax, %ax orl %eax, %edx // Now the address of the handler's in %edx - // We call it now: its "iret" takes us home. + // We call it now: its "iret" drops us home. jmp *%edx // Every interrupt can come to us here diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index ac54f697c50..28c6ae095c5 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -168,7 +168,7 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, return -ENOMEM; } - sg_set_buf(&sg, cc->key, cc->key_size); + sg_init_one(&sg, cc->key, cc->key_size); desc.tfm = hash_tfm; desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; err = crypto_hash_digest(&desc, &sg, cc->key_size, salt); @@ -351,14 +351,10 @@ static int crypt_convert(struct crypt_config *cc, struct scatterlist sg_in, sg_out; sg_init_table(&sg_in, 1); - sg_set_page(&sg_in, bv_in->bv_page); - sg_in.offset = bv_in->bv_offset + ctx->offset_in; - sg_in.length = 1 << SECTOR_SHIFT; + sg_set_page(&sg_in, bv_in->bv_page, 1 << SECTOR_SHIFT, bv_in->bv_offset + ctx->offset_in); sg_init_table(&sg_out, 1); - sg_set_page(&sg_out, bv_out->bv_page); - sg_out.offset = bv_out->bv_offset + ctx->offset_out; - sg_out.length = 1 << SECTOR_SHIFT; + sg_set_page(&sg_out, bv_out->bv_page, 1 << SECTOR_SHIFT, bv_out->bv_offset + ctx->offset_out); ctx->offset_in += sg_in.length; if (ctx->offset_in >= bv_in->bv_len) { 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/common/saa7146_core.c b/drivers/media/common/saa7146_core.c index 2b1f8b4be00..cb034ead95a 100644 --- a/drivers/media/common/saa7146_core.c +++ b/drivers/media/common/saa7146_core.c @@ -118,8 +118,7 @@ static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages) if (NULL == pg) goto err; BUG_ON(PageHighMem(pg)); - sg_set_page(&sglist[i], pg); - sglist[i].length = PAGE_SIZE; + sg_set_page(&sglist[i], pg, PAGE_SIZE, 0); } return sglist; diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index 285fca676a6..623eea2652c 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c @@ -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..de6a0744229 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.h +++ b/drivers/media/video/ivtv/ivtv-i2c.h @@ -36,6 +36,6 @@ 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); +void exit_ivtv_i2c(struct ivtv *itv); #endif diff --git a/drivers/media/video/ivtv/ivtv-udma.c b/drivers/media/video/ivtv/ivtv-udma.c index 912b424e520..460db03b0ba 100644 --- a/drivers/media/video/ivtv/ivtv-udma.c +++ b/drivers/media/video/ivtv/ivtv-udma.c @@ -49,8 +49,6 @@ int ivtv_udma_fill_sg_list (struct ivtv_user_dma *dma, struct ivtv_dma_page_info unsigned int len = (i == dma_page->page_count - 1) ? dma_page->tail : PAGE_SIZE - offset; - dma->SGlist[map_offset].length = len; - dma->SGlist[map_offset].offset = offset; if (PageHighMem(dma->map[map_offset])) { void *src; @@ -63,10 +61,10 @@ int ivtv_udma_fill_sg_list (struct ivtv_user_dma *dma, struct ivtv_dma_page_info memcpy(page_address(dma->bouncemap[map_offset]) + offset, src, len); kunmap_atomic(src, KM_BOUNCE_READ); local_irq_restore(flags); - sg_set_page(&dma->SGlist[map_offset], dma->bouncemap[map_offset]); + sg_set_page(&dma->SGlist[map_offset], dma->bouncemap[map_offset], len, offset); } else { - sg_set_page(&dma->SGlist[map_offset], dma->map[map_offset]); + sg_set_page(&dma->SGlist[map_offset], dma->map[map_offset], len, offset); } offset = 0; map_offset++; diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index 9ab94a749d8..44ee408e145 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -67,8 +67,7 @@ videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages) if (NULL == pg) goto err; BUG_ON(PageHighMem(pg)); - sg_set_page(&sglist[i], pg); - sglist[i].length = PAGE_SIZE; + sg_set_page(&sglist[i], pg, PAGE_SIZE, 0); } return sglist; @@ -95,16 +94,13 @@ videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset) if (PageHighMem(pages[0])) /* DMA to highmem pages might not work */ goto highmem; - sg_set_page(&sglist[0], pages[0]); - sglist[0].offset = offset; - sglist[0].length = PAGE_SIZE - offset; + sg_set_page(&sglist[0], pages[0], PAGE_SIZE - offset, offset); for (i = 1; i < nr_pages; i++) { if (NULL == pages[i]) goto nopage; if (PageHighMem(pages[i])) goto highmem; - sg_set_page(&sglist[i], pages[i]); - sglist[i].length = PAGE_SIZE; + sg_set_page(&sglist[i], pages[i], PAGE_SIZE, 0); } return sglist; diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index d602ba6d541..682406168de 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -284,6 +284,7 @@ static inline struct i2o_block_request *i2o_block_request_alloc(void) return ERR_PTR(-ENOMEM); INIT_LIST_HEAD(&ireq->queue); + sg_init_table(ireq->sg_table, I2O_MAX_PHYS_SEGMENTS); return ireq; }; 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/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index bf4bc6adcfe..7471d49909b 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -267,15 +267,26 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, int mmc_send_csd(struct mmc_card *card, u32 *csd) { + int ret, i; + if (!mmc_host_is_spi(card->host)) return mmc_send_cxd_native(card->host, card->rca << 16, csd, MMC_SEND_CSD); - return mmc_send_cxd_data(card, card->host, MMC_SEND_CSD, csd, 16); + ret = mmc_send_cxd_data(card, card->host, MMC_SEND_CSD, csd, 16); + if (ret) + return ret; + + for (i = 0;i < 4;i++) + csd[i] = be32_to_cpu(csd[i]); + + return 0; } int mmc_send_cid(struct mmc_host *host, u32 *cid) { + int ret, i; + if (!mmc_host_is_spi(host)) { if (!host->card) return -EINVAL; @@ -283,7 +294,14 @@ int mmc_send_cid(struct mmc_host *host, u32 *cid) cid, MMC_SEND_CID); } - return mmc_send_cxd_data(NULL, host, MMC_SEND_CID, cid, 16); + ret = mmc_send_cxd_data(NULL, host, MMC_SEND_CID, cid, 16); + if (ret) + return ret; + + for (i = 0;i < 4;i++) + cid[i] = be32_to_cpu(cid[i]); + + return 0; } int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd) diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c index ee4029a24ef..a6dafe62b99 100644 --- a/drivers/mmc/core/sd_ops.c +++ b/drivers/mmc/core/sd_ops.c @@ -294,8 +294,8 @@ int mmc_app_send_scr(struct mmc_card *card, u32 *scr) if (data.error) return data.error; - scr[0] = ntohl(scr[0]); - scr[1] = ntohl(scr[1]); + scr[0] = be32_to_cpu(scr[0]); + scr[1] = be32_to_cpu(scr[1]); return 0; } diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c index bcbb6d247bf..c3926eb3bf4 100644 --- a/drivers/mmc/host/au1xmmc.c +++ b/drivers/mmc/host/au1xmmc.c @@ -40,13 +40,13 @@ #include <linux/mm.h> #include <linux/interrupt.h> #include <linux/dma-mapping.h> +#include <linux/scatterlist.h> #include <linux/mmc/host.h> #include <asm/io.h> #include <asm/mach-au1x00/au1000.h> #include <asm/mach-au1x00/au1xxx_dbdma.h> #include <asm/mach-au1x00/au1100_mmc.h> -#include <asm/scatterlist.h> #include <au1xxx.h> #include "au1xmmc.h" @@ -212,12 +212,12 @@ static int au1xmmc_send_command(struct au1xmmc_host *host, int wait, } if (data) { - if (flags & MMC_DATA_READ) { + if (data->flags & MMC_DATA_READ) { if (data->blocks > 1) mmccmd |= SD_CMD_CT_4; else mmccmd |= SD_CMD_CT_2; - } else if (flags & MMC_DATA_WRITE) { + } else if (data->flags & MMC_DATA_WRITE) { if (data->blocks > 1) mmccmd |= SD_CMD_CT_3; else 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 12c2d807c14..a6469218f19 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c @@ -1165,6 +1165,23 @@ mmc_spi_detect_irq(int irq, void *mmc) return IRQ_HANDLED; } +struct count_children { + unsigned n; + struct bus_type *bus; +}; + +static int maybe_count_child(struct device *dev, void *c) +{ + struct count_children *ccp = c; + + if (dev->bus == ccp->bus) { + if (ccp->n) + return -EBUSY; + ccp->n++; + } + return 0; +} + static int mmc_spi_probe(struct spi_device *spi) { void *ones; @@ -1188,33 +1205,30 @@ static int mmc_spi_probe(struct spi_device *spi) return status; } - /* We can use the bus safely iff nobody else will interfere with - * us. That is, either we have the experimental exclusive access - * primitives ... or else there's nobody to share it with. + /* We can use the bus safely iff nobody else will interfere with us. + * Most commands consist of one SPI message to issue a command, then + * several more to collect its response, then possibly more for data + * transfer. Clocking access to other devices during that period will + * corrupt the command execution. + * + * Until we have software primitives which guarantee non-interference, + * we'll aim for a hardware-level guarantee. + * + * REVISIT we can't guarantee another device won't be added later... */ if (spi->master->num_chipselect > 1) { - struct device *parent = spi->dev.parent; + struct count_children cc; - /* If there are multiple devices on this bus, we - * can't proceed. - */ - spin_lock(&parent->klist_children.k_lock); - if (parent->klist_children.k_list.next - != parent->klist_children.k_list.prev) - status = -EMLINK; - else - status = 0; - spin_unlock(&parent->klist_children.k_lock); + cc.n = 0; + cc.bus = spi->dev.bus; + status = device_for_each_child(spi->dev.parent, &cc, + maybe_count_child); if (status < 0) { dev_err(&spi->dev, "can't share SPI bus\n"); return status; } - /* REVISIT we can't guarantee another device won't - * be added later. It's uncommon though ... for now, - * work as if this is safe. - */ - dev_warn(&spi->dev, "ASSUMING unshared SPI bus!\n"); + dev_warn(&spi->dev, "ASSUMING SPI bus stays unshared!\n"); } /* We need a supply of ones to transmit. This is the only time diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index d0eb0a2abf4..95244a7e735 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -20,11 +20,11 @@ #include <linux/mmc/host.h> #include <linux/amba/bus.h> #include <linux/clk.h> +#include <linux/scatterlist.h> #include <asm/cacheflush.h> #include <asm/div64.h> #include <asm/io.h> -#include <asm/scatterlist.h> #include <asm/sizes.h> #include <asm/mach/mmc.h> @@ -167,7 +167,7 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data, * partially written to a page is properly coherent. */ if (host->sg_len && data->flags & MMC_DATA_READ) - flush_dcache_page(host->sg_ptr->page); + flush_dcache_page(sg_page(host->sg_ptr)); } if (status & MCI_DATAEND) { mmci_stop_data(host); @@ -319,7 +319,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id) * page, ensure that the data cache is coherent. */ if (status & MCI_RXACTIVE) - flush_dcache_page(host->sg_ptr->page); + flush_dcache_page(sg_page(host->sg_ptr)); if (!mmci_next_sg(host)) break; diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 0601e01aa2c..1654a333034 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -29,7 +29,6 @@ #include <asm/dma.h> #include <asm/io.h> -#include <asm/scatterlist.h> #include <asm/sizes.h> #include <asm/arch/pxa-regs.h> @@ -40,6 +39,7 @@ #define DRIVER_NAME "pxa2xx-mci" #define NR_SG 1 +#define CLKRT_OFF (~0) struct pxamci_host { struct mmc_host *mmc; @@ -372,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 @@ -380,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) { @@ -499,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 d7c5b94d8c5..6b80bf77a4e 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -17,8 +17,6 @@ #include <linux/mmc/host.h> -#include <asm/scatterlist.h> - #include "sdhci.h" #define DRIVER_NAME "sdhci" diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c index fa4c8c53cc7..4d5f3742187 100644 --- a/drivers/mmc/host/wbsd.c +++ b/drivers/mmc/host/wbsd.c @@ -33,10 +33,10 @@ #include <linux/pnp.h> #include <linux/highmem.h> #include <linux/mmc/host.h> +#include <linux/scatterlist.h> #include <asm/io.h> #include <asm/dma.h> -#include <asm/scatterlist.h> #include "wbsd.h" diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 86b8641b466..5f800a6dd97 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -166,13 +166,14 @@ 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. + 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. + To compile this driver as a module, choose M here: the module + will be called ipg. This is recommended. source "drivers/net/arcnet/Kconfig" @@ -1880,6 +1881,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 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/bfin_mac.c b/drivers/net/bfin_mac.c index 53fe7ded5d5..084acfd6fc5 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; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 6909becb10f..6937ef0e727 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -188,6 +188,7 @@ struct bond_parm_tbl arp_validate_tbl[] = { /*-------------------------- Forward declarations ---------------------------*/ static void bond_send_gratuitous_arp(struct bonding *bond); +static void bond_deinit(struct net_device *bond_dev); /*---------------------------- General routines -----------------------------*/ @@ -3681,7 +3682,7 @@ static int bond_open(struct net_device *bond_dev) } if (bond->params.mode == BOND_MODE_8023AD) { - INIT_DELAYED_WORK(&bond->ad_work, bond_alb_monitor); + INIT_DELAYED_WORK(&bond->ad_work, bond_3ad_state_machine_handler); queue_delayed_work(bond->wq, &bond->ad_work, 0); /* register to receive LACPDUs */ bond_register_lacpdu(bond); @@ -4449,7 +4450,7 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params) /* De-initialize device specific data. * Caller must hold rtnl_lock. */ -void bond_deinit(struct net_device *bond_dev) +static void bond_deinit(struct net_device *bond_dev) { struct bonding *bond = bond_dev->priv; diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index d1ed14bf1cc..61c1b4536d3 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -302,7 +302,6 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_de int bond_create(char *name, struct bond_params *params, struct bonding **newbond); void bond_destroy(struct bonding *bond); int bond_release_and_destroy(struct net_device *bond_dev, struct net_device *slave_dev); -void bond_deinit(struct net_device *bond_dev); int bond_create_sysfs(void); void bond_destroy_sysfs(void); void bond_destroy_sysfs_entry(struct bonding *bond); diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index 57541d2d9e1..6fd95a2c8ce 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c @@ -34,6 +34,7 @@ #include <linux/skbuff.h> #include <linux/mii.h> #include <linux/phy.h> +#include <linux/phy_fixed.h> #include <linux/platform_device.h> #include <linux/dma-mapping.h> #include <asm/gpio.h> @@ -53,12 +54,6 @@ MODULE_PARM_DESC(debug_level, "Number of NETIF_MSG bits to enable"); MODULE_PARM_DESC(dumb_switch, "Assume switch is not connected to MDIO bus"); #define CPMAC_VERSION "0.5.0" -/* stolen from net/ieee80211.h */ -#ifndef MAC_FMT -#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" -#define MAC_ARG(x) ((u8*)(x))[0], ((u8*)(x))[1], ((u8*)(x))[2], \ - ((u8*)(x))[3], ((u8*)(x))[4], ((u8*)(x))[5] -#endif /* frame size + 802.1q tag */ #define CPMAC_SKB_SIZE (ETH_FRAME_LEN + 4) #define CPMAC_QUEUES 8 @@ -211,6 +206,7 @@ struct cpmac_priv { struct net_device *dev; struct work_struct reset_work; struct platform_device *pdev; + struct napi_struct napi; }; static irqreturn_t cpmac_irq(int, void *); @@ -362,47 +358,48 @@ static void cpmac_set_multicast_list(struct net_device *dev) } } -static struct sk_buff *cpmac_rx_one(struct net_device *dev, - struct cpmac_priv *priv, +static struct sk_buff *cpmac_rx_one(struct cpmac_priv *priv, struct cpmac_desc *desc) { struct sk_buff *skb, *result = NULL; if (unlikely(netif_msg_hw(priv))) - cpmac_dump_desc(dev, desc); + cpmac_dump_desc(priv->dev, desc); cpmac_write(priv->regs, CPMAC_RX_ACK(0), (u32)desc->mapping); if (unlikely(!desc->datalen)) { if (netif_msg_rx_err(priv) && net_ratelimit()) printk(KERN_WARNING "%s: rx: spurious interrupt\n", - dev->name); + priv->dev->name); return NULL; } - skb = netdev_alloc_skb(dev, CPMAC_SKB_SIZE); + skb = netdev_alloc_skb(priv->dev, CPMAC_SKB_SIZE); if (likely(skb)) { skb_reserve(skb, 2); skb_put(desc->skb, desc->datalen); - desc->skb->protocol = eth_type_trans(desc->skb, dev); + desc->skb->protocol = eth_type_trans(desc->skb, priv->dev); desc->skb->ip_summed = CHECKSUM_NONE; - dev->stats.rx_packets++; - dev->stats.rx_bytes += desc->datalen; + priv->dev->stats.rx_packets++; + priv->dev->stats.rx_bytes += desc->datalen; result = desc->skb; - dma_unmap_single(&dev->dev, desc->data_mapping, CPMAC_SKB_SIZE, - DMA_FROM_DEVICE); + dma_unmap_single(&priv->dev->dev, desc->data_mapping, + CPMAC_SKB_SIZE, DMA_FROM_DEVICE); desc->skb = skb; - desc->data_mapping = dma_map_single(&dev->dev, skb->data, + desc->data_mapping = dma_map_single(&priv->dev->dev, skb->data, CPMAC_SKB_SIZE, DMA_FROM_DEVICE); desc->hw_data = (u32)desc->data_mapping; if (unlikely(netif_msg_pktdata(priv))) { - printk(KERN_DEBUG "%s: received packet:\n", dev->name); - cpmac_dump_skb(dev, result); + printk(KERN_DEBUG "%s: received packet:\n", + priv->dev->name); + cpmac_dump_skb(priv->dev, result); } } else { if (netif_msg_rx_err(priv) && net_ratelimit()) printk(KERN_WARNING - "%s: low on skbs, dropping packet\n", dev->name); - dev->stats.rx_dropped++; + "%s: low on skbs, dropping packet\n", + priv->dev->name); + priv->dev->stats.rx_dropped++; } desc->buflen = CPMAC_SKB_SIZE; @@ -411,25 +408,25 @@ static struct sk_buff *cpmac_rx_one(struct net_device *dev, return result; } -static int cpmac_poll(struct net_device *dev, int *budget) +static int cpmac_poll(struct napi_struct *napi, int budget) { struct sk_buff *skb; struct cpmac_desc *desc; - int received = 0, quota = min(dev->quota, *budget); - struct cpmac_priv *priv = netdev_priv(dev); + int received = 0; + struct cpmac_priv *priv = container_of(napi, struct cpmac_priv, napi); spin_lock(&priv->rx_lock); if (unlikely(!priv->rx_head)) { if (netif_msg_rx_err(priv) && net_ratelimit()) printk(KERN_WARNING "%s: rx: polling, but no queue\n", - dev->name); - netif_rx_complete(dev); + priv->dev->name); + netif_rx_complete(priv->dev, napi); return 0; } desc = priv->rx_head; - while ((received < quota) && ((desc->dataflags & CPMAC_OWN) == 0)) { - skb = cpmac_rx_one(dev, priv, desc); + while (((desc->dataflags & CPMAC_OWN) == 0) && (received < budget)) { + skb = cpmac_rx_one(priv, desc); if (likely(skb)) { netif_receive_skb(skb); received++; @@ -439,13 +436,11 @@ static int cpmac_poll(struct net_device *dev, int *budget) priv->rx_head = desc; spin_unlock(&priv->rx_lock); - *budget -= received; - dev->quota -= received; if (unlikely(netif_msg_rx_status(priv))) - printk(KERN_DEBUG "%s: poll processed %d packets\n", dev->name, - received); + printk(KERN_DEBUG "%s: poll processed %d packets\n", + priv->dev->name, received); if (desc->dataflags & CPMAC_OWN) { - netif_rx_complete(dev); + netif_rx_complete(priv->dev, napi); cpmac_write(priv->regs, CPMAC_RX_PTR(0), (u32)desc->mapping); cpmac_write(priv->regs, CPMAC_RX_INT_ENABLE, 1); return 0; @@ -655,6 +650,7 @@ static void cpmac_hw_error(struct work_struct *work) spin_unlock(&priv->rx_lock); cpmac_clear_tx(priv->dev); cpmac_hw_start(priv->dev); + napi_enable(&priv->napi); netif_start_queue(priv->dev); } @@ -681,8 +677,10 @@ static irqreturn_t cpmac_irq(int irq, void *dev_id) if (status & MAC_INT_RX) { queue = (status >> 8) & 7; - netif_rx_schedule(dev); - cpmac_write(priv->regs, CPMAC_RX_INT_CLEAR, 1 << queue); + if (netif_rx_schedule_prep(dev, &priv->napi)) { + cpmac_write(priv->regs, CPMAC_RX_INT_CLEAR, 1 << queue); + __netif_rx_schedule(dev, &priv->napi); + } } cpmac_write(priv->regs, CPMAC_MAC_EOI_VECTOR, 0); @@ -692,6 +690,7 @@ static irqreturn_t cpmac_irq(int irq, void *dev_id) printk(KERN_ERR "%s: hw error, resetting...\n", dev->name); netif_stop_queue(dev); + napi_disable(&priv->napi); cpmac_hw_stop(dev); schedule_work(&priv->reset_work); if (unlikely(netif_msg_hw(priv))) @@ -849,6 +848,15 @@ static void cpmac_adjust_link(struct net_device *dev) spin_unlock(&priv->lock); } +static int cpmac_link_update(struct net_device *dev, + struct fixed_phy_status *status) +{ + status->link = 1; + status->speed = 100; + status->duplex = 1; + return 0; +} + static int cpmac_open(struct net_device *dev) { int i, size, res; @@ -857,15 +865,6 @@ static int cpmac_open(struct net_device *dev) struct cpmac_desc *desc; struct sk_buff *skb; - priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, - 0, PHY_INTERFACE_MODE_MII); - if (IS_ERR(priv->phy)) { - if (netif_msg_drv(priv)) - printk(KERN_ERR "%s: Could not attach to PHY\n", - dev->name); - return PTR_ERR(priv->phy); - } - mem = platform_get_resource_byname(priv->pdev, IORESOURCE_MEM, "regs"); if (!request_mem_region(mem->start, mem->end - mem->start, dev->name)) { if (netif_msg_drv(priv)) @@ -927,6 +926,7 @@ static int cpmac_open(struct net_device *dev) INIT_WORK(&priv->reset_work, cpmac_hw_error); cpmac_hw_start(dev); + napi_enable(&priv->napi); priv->phy->state = PHY_CHANGELINK; phy_start(priv->phy); @@ -951,8 +951,6 @@ fail_remap: release_mem_region(mem->start, mem->end - mem->start); fail_reserve: - phy_disconnect(priv->phy); - return res; } @@ -965,9 +963,8 @@ static int cpmac_stop(struct net_device *dev) netif_stop_queue(dev); cancel_work_sync(&priv->reset_work); + napi_disable(&priv->napi); phy_stop(priv->phy); - phy_disconnect(priv->phy); - priv->phy = NULL; cpmac_hw_stop(dev); @@ -1001,11 +998,13 @@ static int external_switch; static int __devinit cpmac_probe(struct platform_device *pdev) { - int rc, phy_id; + int rc, phy_id, i; struct resource *mem; struct cpmac_priv *priv; struct net_device *dev; struct plat_cpmac_data *pdata; + struct fixed_info *fixed_phy; + DECLARE_MAC_BUF(mac); pdata = pdev->dev.platform_data; @@ -1053,21 +1052,51 @@ static int __devinit cpmac_probe(struct platform_device *pdev) dev->set_multicast_list = cpmac_set_multicast_list; dev->tx_timeout = cpmac_tx_timeout; dev->ethtool_ops = &cpmac_ethtool_ops; - dev->poll = cpmac_poll; - dev->weight = 64; dev->features |= NETIF_F_MULTI_QUEUE; + netif_napi_add(dev, &priv->napi, cpmac_poll, 64); + spin_lock_init(&priv->lock); spin_lock_init(&priv->rx_lock); priv->dev = dev; priv->ring_size = 64; priv->msg_enable = netif_msg_init(debug_level, 0xff); memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr)); + if (phy_id == 31) { - snprintf(priv->phy_name, BUS_ID_SIZE, PHY_ID_FMT, - cpmac_mii.id, phy_id); - } else - snprintf(priv->phy_name, BUS_ID_SIZE, "fixed@%d:%d", 100, 1); + snprintf(priv->phy_name, BUS_ID_SIZE, PHY_ID_FMT, cpmac_mii.id, + phy_id); + } else { + /* Let's try to get a free fixed phy... */ + for (i = 0; i < MAX_PHY_AMNT; i++) { + fixed_phy = fixed_mdio_get_phydev(i); + if (!fixed_phy) + continue; + if (!fixed_phy->phydev->attached_dev) { + strncpy(priv->phy_name, + fixed_phy->phydev->dev.bus_id, + BUS_ID_SIZE); + fixed_mdio_set_link_update(fixed_phy->phydev, + &cpmac_link_update); + goto phy_found; + } + } + if (netif_msg_drv(priv)) + printk(KERN_ERR "%s: Could not find fixed PHY\n", + dev->name); + rc = -ENODEV; + goto fail; + } + +phy_found: + priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, 0, + PHY_INTERFACE_MODE_MII); + if (IS_ERR(priv->phy)) { + if (netif_msg_drv(priv)) + printk(KERN_ERR "%s: Could not attach to PHY\n", + dev->name); + return PTR_ERR(priv->phy); + } if ((rc = register_netdev(dev))) { printk(KERN_ERR "cpmac: error %i registering device %s\n", rc, @@ -1077,9 +1106,9 @@ static int __devinit cpmac_probe(struct platform_device *pdev) if (netif_msg_probe(priv)) { printk(KERN_INFO - "cpmac: device %s (regs: %p, irq: %d, phy: %s, mac: " - MAC_FMT ")\n", dev->name, (void *)mem->start, dev->irq, - priv->phy_name, MAC_ARG(dev->dev_addr)); + "cpmac: device %s (regs: %p, irq: %d, phy: %s, " + "mac: %s)\n", dev->name, (void *)mem->start, dev->irq, + priv->phy_name, print_mac(mac, dev->dev_addr)); } return 0; 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..667f18bcc17 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) { 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..72deff0d4d9 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); 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..6a39784e7ee 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) { diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 033e124d1c1..4fd2e23720b 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; @@ -2032,9 +1752,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 +1799,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 +2043,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 +2055,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 +2075,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 +3345,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 b557bb44a36..f78e5bf7cb3 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_0078" +#define DRV_VERSION "EHEA_0080" /* 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 2809c99906e..f0319f1e8e0 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" @@ -2329,7 +2332,7 @@ static void port_napi_disable(struct ehea_port *port) { int i; - for (i = 0; i < port->num_def_qps; i++) + for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) napi_disable(&port->port_res[i].napi); } @@ -2337,7 +2340,7 @@ static void port_napi_enable(struct ehea_port *port) { int i; - for (i = 0; i < port->num_def_qps; i++) + for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) napi_enable(&port->port_res[i].napi); } @@ -2373,8 +2376,6 @@ static int ehea_down(struct net_device *dev) ehea_drop_multicast_list(dev); ehea_free_interrupts(dev); - port_napi_disable(port); - port->state = EHEA_PORT_DOWN; ret = ehea_clean_all_portres(port); @@ -2396,6 +2397,7 @@ static int ehea_stop(struct net_device *dev) flush_scheduled_work(); down(&port->port_lock); netif_stop_queue(dev); + port_napi_disable(port); ret = ehea_down(dev); up(&port->port_lock); return ret; @@ -3296,6 +3298,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; @@ -3352,6 +3368,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"); @@ -3363,6 +3381,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; } @@ -3376,6 +3395,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/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c new file mode 100644 index 00000000000..a8a0ee220da --- /dev/null +++ b/drivers/net/fec_mpc52xx.c @@ -0,0 +1,1112 @@ +/* + * 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, skb->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, rskb->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, (__force u32)&fec->reserved10 - + (__force u32)&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); + + /* 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 70ddf1acfd8..92ce2e38f0d 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -5597,6 +5597,22 @@ static struct pci_device_id pci_tbl[] = { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_31), .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, + { /* MCP77 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_32), + .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, + }, + { /* MCP77 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_33), + .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, + }, + { /* MCP77 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_34), + .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, + }, + { /* MCP77 Ethernet Controller */ + 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, + }, {0,}, }; diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c index 68887235d7e..dbd23bb65d1 100644 --- a/drivers/net/ipg.c +++ b/drivers/net/ipg.c @@ -55,6 +55,26 @@ MODULE_DESCRIPTION("IC Plus IP1000 Gigabit Ethernet Adapter Linux Driver " DrvVer); MODULE_LICENSE("GPL"); +//variable record -- index by leading revision/length +//Revision/Length(=N*4), Address1, Data1, Address2, Data2,...,AddressN,DataN +static unsigned short DefaultPhyParam[] = { + // 11/12/03 IP1000A v1-3 rev=0x40 + /*-------------------------------------------------------------------------- + (0x4000|(15*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 22, 0x85bd, 24, 0xfff2, + 27, 0x0c10, 28, 0x0c10, 29, 0x2c10, 31, 0x0003, 23, 0x92f6, + 31, 0x0000, 23, 0x003d, 30, 0x00de, 20, 0x20e7, 9, 0x0700, + --------------------------------------------------------------------------*/ + // 12/17/03 IP1000A v1-4 rev=0x40 + (0x4000 | (07 * 4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31, + 0x0000, + 30, 0x005e, 9, 0x0700, + // 01/09/04 IP1000A v1-5 rev=0x41 + (0x4100 | (07 * 4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31, + 0x0000, + 30, 0x005e, 9, 0x0700, + 0x0000 +}; + static const char *ipg_brand_name[] = { "IC PLUS IP1000 1000/100/10 based NIC", "Sundance Technology ST2021 based NIC", @@ -990,7 +1010,7 @@ static void ipg_nic_txcleanup(struct net_device *dev) } /* Provides statistical information about the IPG NIC. */ -struct net_device_stats *ipg_nic_get_stats(struct net_device *dev) +static struct net_device_stats *ipg_nic_get_stats(struct net_device *dev) { struct ipg_nic_private *sp = netdev_priv(dev); void __iomem *ioaddr = sp->ioaddr; diff --git a/drivers/net/ipg.h b/drivers/net/ipg.h index e418b9035ca..d5d092c9d0a 100644 --- a/drivers/net/ipg.h +++ b/drivers/net/ipg.h @@ -833,24 +833,4 @@ struct ipg_nic_private { struct delayed_work task; }; -//variable record -- index by leading revision/length -//Revision/Length(=N*4), Address1, Data1, Address2, Data2,...,AddressN,DataN -unsigned short DefaultPhyParam[] = { - // 11/12/03 IP1000A v1-3 rev=0x40 - /*-------------------------------------------------------------------------- - (0x4000|(15*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 22, 0x85bd, 24, 0xfff2, - 27, 0x0c10, 28, 0x0c10, 29, 0x2c10, 31, 0x0003, 23, 0x92f6, - 31, 0x0000, 23, 0x003d, 30, 0x00de, 20, 0x20e7, 9, 0x0700, - --------------------------------------------------------------------------*/ - // 12/17/03 IP1000A v1-4 rev=0x40 - (0x4000 | (07 * 4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31, - 0x0000, - 30, 0x005e, 9, 0x0700, - // 01/09/04 IP1000A v1-5 rev=0x41 - (0x4100 | (07 * 4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31, - 0x0000, - 30, 0x005e, 9, 0x0700, - 0x0000 -}; - #endif /* __LINUX_IPG_H */ 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/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..3021234b1e1 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, @@ -1085,7 +1081,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 +1321,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; 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..00bc525c656 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, diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 662b8d16803..45f30a2974b 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -284,7 +284,7 @@ static __net_exit void loopback_net_exit(struct net *net) unregister_netdev(dev); } -static struct pernet_operations __net_initdata loopback_net_ops = { +static struct pernet_operations loopback_net_ops = { .init = loopback_net_init, .exit = loopback_net_exit, }; diff --git a/drivers/net/mlx4/icm.c b/drivers/net/mlx4/icm.c index 887633b207d..2a5bef6388f 100644 --- a/drivers/net/mlx4/icm.c +++ b/drivers/net/mlx4/icm.c @@ -101,9 +101,7 @@ static int mlx4_alloc_icm_pages(struct scatterlist *mem, int order, gfp_t gfp_ma if (!page) return -ENOMEM; - sg_set_page(mem, page); - mem->length = PAGE_SIZE << order; - mem->offset = 0; + sg_set_page(mem, page, PAGE_SIZE << order, 0); return 0; } diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 366e62a2b1e..0f306ddb563 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_running(netdev)) { netif_rx_complete(netdev, napi); put_be32(htonl(3), mgp->irq_claim); } diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 953117152bb..87cde062fd6 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -864,6 +864,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, np = netdev_priv(dev); netif_napi_add(dev, &np->napi, natsemi_poll, 64); + np->dev = dev; np->pci_dev = pdev; pci_set_drvdata(pdev, dev); diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 73dcbb7296d..ad134a61302 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; diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 32076ca6a9e..a98fe07cce7 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; 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..db6a97d1d7b 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; 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/ppp_mppe.c b/drivers/net/ppp_mppe.c index bcb0885011c..b35d7944950 100644 --- a/drivers/net/ppp_mppe.c +++ b/drivers/net/ppp_mppe.c @@ -68,7 +68,7 @@ MODULE_VERSION("1.0.2"); static unsigned int setup_sg(struct scatterlist *sg, const void *address, unsigned int length) { - sg_init_one(sg, address, length); + sg_set_buf(sg, address, length); return length; } @@ -140,6 +140,8 @@ static void get_new_key_from_sha(struct ppp_mppe_state * state) struct scatterlist sg[4]; unsigned int nbytes; + sg_init_table(sg, 4); + nbytes = setup_sg(&sg[0], state->master_key, state->keylen); nbytes += setup_sg(&sg[1], sha_pad->sha_pad1, sizeof(sha_pad->sha_pad1)); @@ -166,6 +168,8 @@ static void mppe_rekey(struct ppp_mppe_state * state, int initial_key) if (!initial_key) { crypto_blkcipher_setkey(state->arc4, state->sha1_digest, state->keylen); + sg_init_table(sg_in, 1); + sg_init_table(sg_out, 1); setup_sg(sg_in, state->sha1_digest, state->keylen); setup_sg(sg_out, state->session_key, state->keylen); if (crypto_blkcipher_encrypt(&desc, sg_out, sg_in, @@ -421,6 +425,8 @@ mppe_compress(void *arg, unsigned char *ibuf, unsigned char *obuf, isize -= 2; /* Encrypt packet */ + sg_init_table(sg_in, 1); + sg_init_table(sg_out, 1); setup_sg(sg_in, ibuf, isize); setup_sg(sg_out, obuf, osize); if (crypto_blkcipher_encrypt(&desc, sg_out, sg_in, isize) != 0) { @@ -608,6 +614,8 @@ mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf, * Decrypt the first byte in order to check if it is * a compressed or uncompressed protocol field. */ + sg_init_table(sg_in, 1); + sg_init_table(sg_out, 1); setup_sg(sg_in, ibuf, 1); setup_sg(sg_out, obuf, 1); if (crypto_blkcipher_decrypt(&desc, sg_out, sg_in, 1) != 0) { 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..f8904fd9236 100644 --- a/drivers/net/pppol2tp.c +++ b/drivers/net/pppol2tp.c @@ -1416,7 +1416,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/r8169.c b/drivers/net/r8169.c index e8960f294a6..b94fa7ef195 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -392,7 +392,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; @@ -2989,13 +2991,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 +3014,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 19152f54ef2..b822859c8de 100644 --- a/drivers/net/rrunner.c +++ b/drivers/net/rrunner.c @@ -79,12 +79,10 @@ static char version[] __devinitdata = "rrunner.c: v0.50 11/11/2002 Jes Sorensen */ /* - * These 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, + * 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, */ -extern __u32 sysctl_wmem_max; -extern __u32 sysctl_rmem_max; static int __devinit rr_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 9741d613ba6..a3ff270593f 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -2214,9 +2214,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 +2253,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); } } } diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index a2de32fabc1..2c685734b7a 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -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/rndis_host.c b/drivers/net/usb/rndis_host.c index cd991a0f75b..1ebe3259be0 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -512,11 +512,19 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf) } tmp = le32_to_cpu(u.init_c->max_transfer_size); if (tmp < dev->hard_mtu) { - dev_err(&intf->dev, - "dev can't take %u byte packets (max %u)\n", - dev->hard_mtu, tmp); - retval = -EINVAL; - goto fail_and_release; + if (tmp <= net->hard_header_len) { + dev_err(&intf->dev, + "dev can't take %u byte packets (max %u)\n", + dev->hard_mtu, tmp); + retval = -EINVAL; + goto fail_and_release; + } + dev->hard_mtu = tmp; + net->mtu = dev->hard_mtu - net->hard_header_len; + dev_warn(&intf->dev, + "dev can't take %u byte packets (max %u), " + "adjusting MTU to %u\n", + dev->hard_mtu, tmp, net->mtu); } /* REVISIT: peripheral "alignment" request is ignored ... */ 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/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 9d9ff76a9bc..5058e60e570 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2391,7 +2391,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); diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index d09479e816c..f0e56dfc9ec 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -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: diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index a6c7904de28..8d53d08b969 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -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..54f44e5473c 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -1753,7 +1753,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 +4364,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 +4728,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 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-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..4f22a7174ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -6478,8 +6478,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 +6576,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 +6606,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 +6745,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 +6889,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"); } @@ -7169,8 +7186,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 +7193,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 +7233,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 +7260,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 +7291,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 +7300,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 +7335,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 +7506,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; @@ -8558,6 +8595,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... */ diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 5e1279263b2..d60adcb9bd4 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -6845,8 +6845,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 +6943,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 +6966,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 +7119,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 +7278,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"); } @@ -7573,8 +7590,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 +7597,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 +7637,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 +7664,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 +7695,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 +7704,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 +7738,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 +7930,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; @@ -9152,6 +9189,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... */ 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/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index de61c8fe649..e454ae83e97 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -433,6 +433,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 +585,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/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/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/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index fd5d0c1570d..00118499018 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -562,8 +562,6 @@ zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size) sg_init_table(sg_list->sg, sg_list->count); for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++) { - sg->length = min(size, PAGE_SIZE); - sg->offset = 0; address = (void *) get_zeroed_page(GFP_KERNEL); if (address == NULL) { sg_list->count = i; @@ -571,7 +569,7 @@ zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size) retval = -ENOMEM; goto out; } - zfcp_address_to_sg(address, sg); + zfcp_address_to_sg(address, sg, min(size, PAGE_SIZE)); size -= sg->length; } @@ -1518,13 +1516,13 @@ zfcp_gid_pn_buffers_alloc(struct zfcp_gid_pn_data **gid_pn, mempool_t *pool) return -ENOMEM; memset(data, 0, sizeof(*data)); + sg_init_table(&data->req , 1); + sg_init_table(&data->resp , 1); data->ct.req = &data->req; data->ct.resp = &data->resp; data->ct.req_count = data->ct.resp_count = 1; - zfcp_address_to_sg(&data->ct_iu_req, &data->req); - zfcp_address_to_sg(&data->ct_iu_resp, &data->resp); - data->req.length = sizeof(struct ct_iu_gid_pn_req); - data->resp.length = sizeof(struct ct_iu_gid_pn_resp); + zfcp_address_to_sg(&data->ct_iu_req, &data->req, sizeof(struct ct_iu_gid_pn_req)); + zfcp_address_to_sg(&data->ct_iu_resp, &data->resp, sizeof(struct ct_iu_gid_pn_resp)); *gid_pn = data; return 0; diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 326e7ee232c..e268f79bdbd 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -70,12 +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_page(list, virt_to_page(address)); - list->offset = ((unsigned long) address) & (PAGE_SIZE - 1); + 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 9438d0b2879..5552b755c08 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -322,9 +322,9 @@ zfcp_erp_adisc(struct zfcp_port *port) if (address == NULL) goto nomem; - zfcp_address_to_sg(address, send_els->req); + zfcp_address_to_sg(address, send_els->req, sizeof(struct zfcp_ls_adisc)); address += PAGE_SIZE >> 1; - zfcp_address_to_sg(address, send_els->resp); + zfcp_address_to_sg(address, send_els->resp, sizeof(struct zfcp_ls_adisc_acc)); send_els->req_count = send_els->resp_count = 1; send_els->adapter = adapter; @@ -336,9 +336,6 @@ zfcp_erp_adisc(struct zfcp_port *port) adisc = zfcp_sg_to_address(send_els->req); send_els->ls_code = adisc->code = ZFCP_LS_ADISC; - send_els->req->length = sizeof(struct zfcp_ls_adisc); - send_els->resp->length = sizeof(struct zfcp_ls_adisc_acc); - /* acc. to FC-FS, hard_nport_id in ADISC should not be set for ports without FC-AL-2 capability, so we don't set it */ adisc->wwpn = fc_host_port_name(adapter->scsi_host); diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index a5763c6e936..86cf10efb0c 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. 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/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/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_NCR5380.c b/drivers/scsi/atari_NCR5380.c index d1780980fb2..a9680b5e8ac 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -477,10 +477,9 @@ static void merge_contiguous_buffers(Scsi_Cmnd *cmd) for (endaddr = virt_to_phys(cmd->SCp.ptr + cmd->SCp.this_residual - 1) + 1; cmd->SCp.buffers_residual && - virt_to_phys(page_address(cmd->SCp.buffer[1].page) + - cmd->SCp.buffer[1].offset) == endaddr;) { + virt_to_phys(sg_virt(&cmd->SCp.buffer[1])) == endaddr;) { MER_PRINTK("VTOP(%p) == %08lx -> merging\n", - page_address(cmd->SCp.buffer[1].page), endaddr); + page_address(sg_page(&cmd->SCp.buffer[1])), endaddr); #if (NDEBUG & NDEBUG_MERGING) ++cnt; #endif diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 439b97a6a26..0841df01bc1 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -2890,7 +2890,7 @@ static struct ipr_sglist *ipr_alloc_ucode_buffer(int buf_len) return NULL; } - sg_set_page(&scatterlist[i], page); + sg_set_page(&scatterlist[i], page, 0, 0); } return sglist; diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 6ce4109efdf..4bcf916c21a 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -79,9 +79,7 @@ static inline void iscsi_buf_init_sg(struct iscsi_buf *ibuf, struct scatterlist *sg) { sg_init_table(&ibuf->sg, 1); - sg_set_page(&ibuf->sg, sg_page(sg)); - ibuf->sg.offset = sg->offset; - ibuf->sg.length = sg->length; + sg_set_page(&ibuf->sg, sg_page(sg), sg->length, sg->offset); /* * Fastpath: sg element fits into single page */ @@ -676,9 +674,8 @@ partial_sg_digest_update(struct hash_desc *desc, struct scatterlist *sg, { struct scatterlist temp; - memcpy(&temp, sg, sizeof(struct scatterlist)); - temp.offset = offset; - temp.length = length; + sg_init_table(&temp, 1); + sg_set_page(&temp, sg_page(sg), length, offset); crypto_hash_update(desc, &temp, length); } diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 1c5c4b68f20..4652ad22516 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -5256,8 +5256,7 @@ static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma) STbuffer->sg[0].offset = 0; if (page != NULL) { - sg_set_page(&STbuffer->sg[0], page); - STbuffer->sg[0].length = b_size; + sg_set_page(&STbuffer->sg[0], page, b_size, 0); STbuffer->b_data = page_address(page); break; } @@ -5285,8 +5284,7 @@ static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma) normalize_buffer(STbuffer); return 0; } - sg_set_page(&STbuffer->sg[segs], page); - STbuffer->sg[segs].length = (OS_FRAME_SIZE - got <= PAGE_SIZE / 2) ? (OS_FRAME_SIZE - got) : b_size; + sg_set_page(&STbuffer->sg[segs], page, (OS_FRAME_SIZE - got <= PAGE_SIZE / 2) ? (OS_FRAME_SIZE - got) : b_size, 0); got += STbuffer->sg[segs].length; STbuffer->buffer_size = got; STbuffer->sg_segs = ++segs; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index cc197100284..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 */ } @@ -1717,16 +1718,12 @@ st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages, goto out_unlock; */ } - sg_set_page(sgl, pages[0]); - sgl[0].offset = uaddr & ~PAGE_MASK; + sg_set_page(sgl, pages[0], 0, uaddr & ~PAGE_MASK); if (nr_pages > 1) { sgl[0].length = PAGE_SIZE - sgl[0].offset; count -= sgl[0].length; - for (i=1; i < nr_pages ; i++) { - sg_set_page(&sgl[i], pages[i]); - sgl[i].length = count < PAGE_SIZE ? count : PAGE_SIZE; - count -= PAGE_SIZE; - } + for (i=1; i < nr_pages ; i++) + sg_set_page(&sgl[i], pages[i], count < PAGE_SIZE ? count : PAGE_SIZE, 0); } else { sgl[0].length = count; @@ -1854,8 +1851,7 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size) scatter_elem_sz_prev = ret_sz; } } - sg_set_page(sg, p); - sg->length = (ret_sz > num) ? num : ret_sz; + sg_set_page(sg, p, (ret_sz > num) ? num : ret_sz, 0); SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k=%d, num=%d, " "ret_sz=%d\n", k, num, ret_sz)); diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index ce69b9efc10..98dfd6ea209 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -3797,13 +3797,11 @@ static void buf_to_sg(struct st_buffer *STbp, unsigned int length) sg = &(STbp->sg[0]); frp = STbp->frp; for (i=count=0; count < length; i++) { - sg_set_page(&sg[i], frp[i].page); if (length - count > frp[i].length) - sg[i].length = frp[i].length; + sg_set_page(&sg[i], frp[i].page, frp[i].length, 0); else - sg[i].length = length - count; + sg_set_page(&sg[i], frp[i].page, length - count, 0); count += sg[i].length; - sg[i].offset = 0; } STbp->sg_segs = i; STbp->frp_sg_current = length; @@ -4446,15 +4444,13 @@ static int sgl_map_user_pages(struct scatterlist *sgl, const unsigned int max_pa } /* Populate the scatter/gather list */ - sg_set_page(&sgl[0], pages[0]); - sgl[0].offset = uaddr & ~PAGE_MASK; + sg_set_page(&sgl[0], pages[0], 0, uaddr & ~PAGE_MASK); if (nr_pages > 1) { sgl[0].length = PAGE_SIZE - sgl[0].offset; count -= sgl[0].length; for (i=1; i < nr_pages ; i++) { - sg_set_page(&sgl[i], pages[i]);; - sgl[i].offset = 0; - sgl[i].length = count < PAGE_SIZE ? count : PAGE_SIZE; + sg_set_page(&sgl[i], pages[i], + count < PAGE_SIZE ? count : PAGE_SIZE, 0);; count -= PAGE_SIZE; } } diff --git a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c index 80fb3f88af2..1bc41907a03 100644 --- a/drivers/scsi/sun3x_esp.c +++ b/drivers/scsi/sun3x_esp.c @@ -332,8 +332,8 @@ static void dma_mmu_get_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp) struct scatterlist *sg = sp->SCp.buffer; while (sz >= 0) { - sg[sz].dma_address = dvma_map((unsigned long)page_address(sg[sz].page) + - sg[sz].offset, sg[sz].length); + sg[sz].dma_address = dvma_map((unsigned long)sg_virt(&sg[sz]), + sg[sz].length); sz--; } sp->SCp.ptr=(char *)((unsigned long)sp->SCp.buffer->dma_address); diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 103189095c8..3bb5d241dd4 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1875,6 +1875,7 @@ uart_set_options(struct uart_port *port, struct console *co, int baud, int parity, int bits, int flow) { struct ktermios termios; + static struct ktermios dummy; int i; /* @@ -1920,7 +1921,7 @@ uart_set_options(struct uart_port *port, struct console *co, */ port->mctrl |= TIOCM_DTR; - port->ops->set_termios(port, &termios, NULL); + port->ops->set_termios(port, &termios, &dummy); co->cflag = termios.c_cflag; return 0; 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/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/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/usb/core/message.c b/drivers/usb/core/message.c index 8bdaa157ffe..316a746e008 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]); @@ -1641,7 +1641,13 @@ free_interfaces: intf->dev.bus_id, ret); continue; } - usb_create_sysfs_intf_files (intf); + + /* 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); } usb_autosuspend_device(dev); diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index c20c03aaf01..d05ead20081 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -372,7 +372,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) /* enforce simple/standard policy */ allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP | - URB_NO_INTERRUPT | URB_DIR_MASK); + URB_NO_INTERRUPT | URB_DIR_MASK | URB_FREE_BUFFER); switch (xfertype) { case USB_ENDPOINT_XFER_BULK: if (is_out) diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index 1c804060252..c72e9620bf8 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -3289,7 +3289,7 @@ static int udc_pci_probe( dev->chiprev = pdev->revision; pci_set_master(pdev); - pci_set_mwi(pdev); + pci_try_set_mwi(pdev); /* init dma pools */ if (use_dma) { diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index c978d622fa8..177e78ed241 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 && EXPERIMENTAL + depends on USB_OHCI_HCD && (SSB = y || SSB = CONFIG_USB_OHCI_HCD) && EXPERIMENTAL default n ---help--- Support for the Sonics Silicon Backplane (SSB) attached diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 240c7f50754..704f33fdd2f 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -80,7 +80,10 @@ static const char hcd_name [] = "ohci_hcd"; static void ohci_dump (struct ohci_hcd *ohci, int verbose); static int ohci_init (struct ohci_hcd *ohci); static void ohci_stop (struct usb_hcd *hcd); + +#if defined(CONFIG_PM) || defined(CONFIG_PCI) static int ohci_restart (struct ohci_hcd *ohci); +#endif #include "ohci-hub.c" #include "ohci-dbg.c" @@ -396,7 +399,7 @@ static int check_ed(struct ohci_hcd *ohci, struct ed *ed) */ static void unlink_watchdog_func(unsigned long _ohci) { - long flags; + unsigned long flags; unsigned max; unsigned seen_count = 0; unsigned i; @@ -893,6 +896,8 @@ static void ohci_stop (struct usb_hcd *hcd) /*-------------------------------------------------------------------------*/ +#if defined(CONFIG_PM) || defined(CONFIG_PCI) + /* must not be called from interrupt context */ static int ohci_restart (struct ohci_hcd *ohci) { @@ -954,6 +959,8 @@ static int ohci_restart (struct ohci_hcd *ohci) return 0; } +#endif + /*-------------------------------------------------------------------------*/ #define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index e5d60d5b105..60379b17bbc 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -1271,7 +1271,8 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, } else if (qh->period != urb->interval) { return -EINVAL; /* Can't change the period */ - } else { /* Pick up where the last URB leaves off */ + } else { + /* Find the next unused frame */ if (list_empty(&qh->queue)) { frame = qh->iso_frame; } else { @@ -1283,10 +1284,18 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, lurb->number_of_packets * lurb->interval; } - if (urb->transfer_flags & URB_ISO_ASAP) - urb->start_frame = frame; - else if (urb->start_frame != frame) - return -EINVAL; + if (urb->transfer_flags & URB_ISO_ASAP) { + /* Skip some frames if necessary to insure + * the start frame is in the future. + */ + uhci_get_current_frame_number(uhci); + if (uhci_frame_before_eq(frame, uhci->frame_number)) { + frame = uhci->frame_number + 1; + frame += ((qh->phase - frame) & + (qh->period - 1)); + } + } /* Otherwise pick up where the last URB leaves off */ + urb->start_frame = frame; } /* Make sure we won't have to go too far into the future */ diff --git a/drivers/usb/misc/cytherm.c b/drivers/usb/misc/cytherm.c index 2677fea147d..1cd9e7eba93 100644 --- a/drivers/usb/misc/cytherm.c +++ b/drivers/usb/misc/cytherm.c @@ -399,7 +399,6 @@ static void cytherm_disconnect(struct usb_interface *interface) struct usb_cytherm *dev; dev = usb_get_intfdata (interface); - usb_set_intfdata (interface, NULL); device_remove_file(&interface->dev, &dev_attr_brightness); device_remove_file(&interface->dev, &dev_attr_temp); @@ -407,6 +406,9 @@ static void cytherm_disconnect(struct usb_interface *interface) device_remove_file(&interface->dev, &dev_attr_port0); device_remove_file(&interface->dev, &dev_attr_port1); + /* first remove the files, then NULL the pointer */ + usb_set_intfdata (interface, NULL); + usb_put_dev(dev->udev); kfree(dev); diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c index cd137577bb2..4a09b87bdd2 100644 --- a/drivers/usb/misc/emi26.c +++ b/drivers/usb/misc/emi26.c @@ -114,6 +114,10 @@ static int emi26_load_firmware (struct usb_device *dev) /* De-assert reset (let the CPU run) */ err = emi26_set_reset(dev,0); + if (err < 0) { + err("%s - error loading firmware: error = %d", __FUNCTION__, err); + goto wraperr; + } msleep(250); /* let device settle */ /* 2. We upload the FPGA firmware into the EMI diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c index 4758cc5cceb..d1362415922 100644 --- a/drivers/usb/misc/emi62.c +++ b/drivers/usb/misc/emi62.c @@ -123,6 +123,10 @@ static int emi62_load_firmware (struct usb_device *dev) /* De-assert reset (let the CPU run) */ err = emi62_set_reset(dev,0); + if (err < 0) { + err("%s - error loading firmware: error = %d", __FUNCTION__, err); + goto wraperr; + } msleep(250); /* let device settle */ /* 2. We upload the FPGA firmware into the EMI diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index d3d8cd6ff10..148b7fe639b 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -147,7 +147,7 @@ struct u132_target { /* Structure to hold all of our device specific stuff*/ struct usb_ftdi { struct list_head ftdi_list; - struct semaphore u132_lock; + struct mutex u132_lock; int command_next; int command_head; struct u132_command command[COMMAND_SIZE]; @@ -330,39 +330,39 @@ static int ftdi_elan_hcd_init(struct usb_ftdi *ftdi) static void ftdi_elan_abandon_completions(struct usb_ftdi *ftdi) { - down(&ftdi->u132_lock); + mutex_lock(&ftdi->u132_lock); while (ftdi->respond_next > ftdi->respond_head) { struct u132_respond *respond = &ftdi->respond[RESPOND_MASK & ftdi->respond_head++]; *respond->result = -ESHUTDOWN; *respond->value = 0; complete(&respond->wait_completion); - } up(&ftdi->u132_lock); + } mutex_unlock(&ftdi->u132_lock); } static void ftdi_elan_abandon_targets(struct usb_ftdi *ftdi) { int ed_number = 4; - down(&ftdi->u132_lock); + mutex_lock(&ftdi->u132_lock); while (ed_number-- > 0) { struct u132_target *target = &ftdi->target[ed_number]; if (target->active == 1) { target->condition_code = TD_DEVNOTRESP; - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); ftdi_elan_do_callback(ftdi, target, NULL, 0); - down(&ftdi->u132_lock); + mutex_lock(&ftdi->u132_lock); } } ftdi->recieved = 0; ftdi->expected = 4; ftdi->ed_found = 0; - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); } static void ftdi_elan_flush_targets(struct usb_ftdi *ftdi) { int ed_number = 4; - down(&ftdi->u132_lock); + mutex_lock(&ftdi->u132_lock); while (ed_number-- > 0) { struct u132_target *target = &ftdi->target[ed_number]; target->abandoning = 1; @@ -382,9 +382,9 @@ static void ftdi_elan_flush_targets(struct usb_ftdi *ftdi) ftdi->command_next += 1; ftdi_elan_kick_command_queue(ftdi); } else { - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); msleep(100); - down(&ftdi->u132_lock); + mutex_lock(&ftdi->u132_lock); goto wait_1; } } @@ -404,9 +404,9 @@ static void ftdi_elan_flush_targets(struct usb_ftdi *ftdi) ftdi->command_next += 1; ftdi_elan_kick_command_queue(ftdi); } else { - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); msleep(100); - down(&ftdi->u132_lock); + mutex_lock(&ftdi->u132_lock); goto wait_2; } } @@ -414,13 +414,13 @@ static void ftdi_elan_flush_targets(struct usb_ftdi *ftdi) ftdi->recieved = 0; ftdi->expected = 4; ftdi->ed_found = 0; - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); } static void ftdi_elan_cancel_targets(struct usb_ftdi *ftdi) { int ed_number = 4; - down(&ftdi->u132_lock); + mutex_lock(&ftdi->u132_lock); while (ed_number-- > 0) { struct u132_target *target = &ftdi->target[ed_number]; target->abandoning = 1; @@ -440,9 +440,9 @@ static void ftdi_elan_cancel_targets(struct usb_ftdi *ftdi) ftdi->command_next += 1; ftdi_elan_kick_command_queue(ftdi); } else { - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); msleep(100); - down(&ftdi->u132_lock); + mutex_lock(&ftdi->u132_lock); goto wait; } } @@ -450,7 +450,7 @@ static void ftdi_elan_cancel_targets(struct usb_ftdi *ftdi) ftdi->recieved = 0; ftdi->expected = 4; ftdi->ed_found = 0; - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); } static void ftdi_elan_kick_command_queue(struct usb_ftdi *ftdi) @@ -886,14 +886,14 @@ static char *have_ed_set_response(struct usb_ftdi *ftdi, char *b) { int payload = (ed_length >> 0) & 0x07FF; - down(&ftdi->u132_lock); + mutex_lock(&ftdi->u132_lock); target->actual = 0; target->non_null = (ed_length >> 15) & 0x0001; target->repeat_number = (ed_length >> 11) & 0x000F; if (ed_type == 0x02) { if (payload == 0 || target->abandoning > 0) { target->abandoning = 0; - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response, payload); ftdi->recieved = 0; @@ -903,13 +903,13 @@ static char *have_ed_set_response(struct usb_ftdi *ftdi, } else { ftdi->expected = 4 + payload; ftdi->ed_found = 1; - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); return b; } } else if (ed_type == 0x03) { if (payload == 0 || target->abandoning > 0) { target->abandoning = 0; - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response, payload); ftdi->recieved = 0; @@ -919,12 +919,12 @@ static char *have_ed_set_response(struct usb_ftdi *ftdi, } else { ftdi->expected = 4 + payload; ftdi->ed_found = 1; - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); return b; } } else if (ed_type == 0x01) { target->abandoning = 0; - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response, payload); ftdi->recieved = 0; @@ -933,7 +933,7 @@ static char *have_ed_set_response(struct usb_ftdi *ftdi, return ftdi->response; } else { target->abandoning = 0; - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response, payload); ftdi->recieved = 0; @@ -947,12 +947,12 @@ static char *have_ed_get_response(struct usb_ftdi *ftdi, struct u132_target *target, u16 ed_length, int ed_number, int ed_type, char *b) { - down(&ftdi->u132_lock); + mutex_lock(&ftdi->u132_lock); target->condition_code = TD_DEVNOTRESP; target->actual = (ed_length >> 0) & 0x01FF; target->non_null = (ed_length >> 15) & 0x0001; target->repeat_number = (ed_length >> 11) & 0x000F; - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); if (target->active) ftdi_elan_do_callback(ftdi, target, NULL, 0); target->abandoning = 0; @@ -1278,7 +1278,7 @@ static int ftdi_elan_write_reg(struct usb_ftdi *ftdi, u32 data) return -ENODEV; } else { int command_size; - down(&ftdi->u132_lock); + mutex_lock(&ftdi->u132_lock); command_size = ftdi->command_next - ftdi->command_head; if (command_size < COMMAND_SIZE) { struct u132_command *command = &ftdi->command[ @@ -1292,10 +1292,10 @@ static int ftdi_elan_write_reg(struct usb_ftdi *ftdi, u32 data) command->buffer = &command->value; ftdi->command_next += 1; ftdi_elan_kick_command_queue(ftdi); - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); return 0; } else { - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); msleep(100); goto wait; } @@ -1310,7 +1310,7 @@ static int ftdi_elan_write_config(struct usb_ftdi *ftdi, int config_offset, return -ENODEV; } else { int command_size; - down(&ftdi->u132_lock); + mutex_lock(&ftdi->u132_lock); command_size = ftdi->command_next - ftdi->command_head; if (command_size < COMMAND_SIZE) { struct u132_command *command = &ftdi->command[ @@ -1324,10 +1324,10 @@ static int ftdi_elan_write_config(struct usb_ftdi *ftdi, int config_offset, command->buffer = &command->value; ftdi->command_next += 1; ftdi_elan_kick_command_queue(ftdi); - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); return 0; } else { - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); msleep(100); goto wait; } @@ -1342,7 +1342,7 @@ static int ftdi_elan_write_pcimem(struct usb_ftdi *ftdi, int mem_offset, return -ENODEV; } else { int command_size; - down(&ftdi->u132_lock); + mutex_lock(&ftdi->u132_lock); command_size = ftdi->command_next - ftdi->command_head; if (command_size < COMMAND_SIZE) { struct u132_command *command = &ftdi->command[ @@ -1356,10 +1356,10 @@ static int ftdi_elan_write_pcimem(struct usb_ftdi *ftdi, int mem_offset, command->buffer = &command->value; ftdi->command_next += 1; ftdi_elan_kick_command_queue(ftdi); - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); return 0; } else { - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); msleep(100); goto wait; } @@ -1382,7 +1382,7 @@ static int ftdi_elan_read_reg(struct usb_ftdi *ftdi, u32 *data) } else { int command_size; int respond_size; - down(&ftdi->u132_lock); + mutex_lock(&ftdi->u132_lock); command_size = ftdi->command_next - ftdi->command_head; respond_size = ftdi->respond_next - ftdi->respond_head; if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE) @@ -1405,11 +1405,11 @@ static int ftdi_elan_read_reg(struct usb_ftdi *ftdi, u32 *data) ftdi->command_next += 1; ftdi->respond_next += 1; ftdi_elan_kick_command_queue(ftdi); - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); wait_for_completion(&respond->wait_completion); return result; } else { - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); msleep(100); goto wait; } @@ -1425,7 +1425,7 @@ static int ftdi_elan_read_config(struct usb_ftdi *ftdi, int config_offset, } else { int command_size; int respond_size; - down(&ftdi->u132_lock); + mutex_lock(&ftdi->u132_lock); command_size = ftdi->command_next - ftdi->command_head; respond_size = ftdi->respond_next - ftdi->respond_head; if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE) @@ -1449,11 +1449,11 @@ static int ftdi_elan_read_config(struct usb_ftdi *ftdi, int config_offset, ftdi->command_next += 1; ftdi->respond_next += 1; ftdi_elan_kick_command_queue(ftdi); - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); wait_for_completion(&respond->wait_completion); return result; } else { - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); msleep(100); goto wait; } @@ -1469,7 +1469,7 @@ static int ftdi_elan_read_pcimem(struct usb_ftdi *ftdi, int mem_offset, } else { int command_size; int respond_size; - down(&ftdi->u132_lock); + mutex_lock(&ftdi->u132_lock); command_size = ftdi->command_next - ftdi->command_head; respond_size = ftdi->respond_next - ftdi->respond_head; if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE) @@ -1493,11 +1493,11 @@ static int ftdi_elan_read_pcimem(struct usb_ftdi *ftdi, int mem_offset, ftdi->command_next += 1; ftdi->respond_next += 1; ftdi_elan_kick_command_queue(ftdi); - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); wait_for_completion(&respond->wait_completion); return result; } else { - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); msleep(100); goto wait; } @@ -1529,7 +1529,7 @@ static int ftdi_elan_edset_setup(struct usb_ftdi *ftdi, u8 ed_number, return -ENODEV; } else { int command_size; - down(&ftdi->u132_lock); + mutex_lock(&ftdi->u132_lock); command_size = ftdi->command_next - ftdi->command_head; if (command_size < COMMAND_SIZE) { struct u132_target *target = &ftdi->target[ed]; @@ -1550,10 +1550,10 @@ static int ftdi_elan_edset_setup(struct usb_ftdi *ftdi, u8 ed_number, target->active = 1; ftdi->command_next += 1; ftdi_elan_kick_command_queue(ftdi); - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); return 0; } else { - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); msleep(100); goto wait; } @@ -1586,7 +1586,7 @@ static int ftdi_elan_edset_input(struct usb_ftdi *ftdi, u8 ed_number, return -ENODEV; } else { int command_size; - down(&ftdi->u132_lock); + mutex_lock(&ftdi->u132_lock); command_size = ftdi->command_next - ftdi->command_head; if (command_size < COMMAND_SIZE) { struct u132_target *target = &ftdi->target[ed]; @@ -1615,10 +1615,10 @@ static int ftdi_elan_edset_input(struct usb_ftdi *ftdi, u8 ed_number, target->active = 1; ftdi->command_next += 1; ftdi_elan_kick_command_queue(ftdi); - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); return 0; } else { - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); msleep(100); goto wait; } @@ -1651,7 +1651,7 @@ static int ftdi_elan_edset_empty(struct usb_ftdi *ftdi, u8 ed_number, return -ENODEV; } else { int command_size; - down(&ftdi->u132_lock); + mutex_lock(&ftdi->u132_lock); command_size = ftdi->command_next - ftdi->command_head; if (command_size < COMMAND_SIZE) { struct u132_target *target = &ftdi->target[ed]; @@ -1672,10 +1672,10 @@ static int ftdi_elan_edset_empty(struct usb_ftdi *ftdi, u8 ed_number, target->active = 1; ftdi->command_next += 1; ftdi_elan_kick_command_queue(ftdi); - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); return 0; } else { - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); msleep(100); goto wait; } @@ -1708,7 +1708,7 @@ static int ftdi_elan_edset_output(struct usb_ftdi *ftdi, u8 ed_number, return -ENODEV; } else { int command_size; - down(&ftdi->u132_lock); + mutex_lock(&ftdi->u132_lock); command_size = ftdi->command_next - ftdi->command_head; if (command_size < COMMAND_SIZE) { u8 *b; @@ -1751,10 +1751,10 @@ static int ftdi_elan_edset_output(struct usb_ftdi *ftdi, u8 ed_number, target->active = 1; ftdi->command_next += 1; ftdi_elan_kick_command_queue(ftdi); - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); return 0; } else { - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); msleep(100); goto wait; } @@ -1787,7 +1787,7 @@ static int ftdi_elan_edset_single(struct usb_ftdi *ftdi, u8 ed_number, return -ENODEV; } else { int command_size; - down(&ftdi->u132_lock); + mutex_lock(&ftdi->u132_lock); command_size = ftdi->command_next - ftdi->command_head; if (command_size < COMMAND_SIZE) { int remaining_length = urb->transfer_buffer_length - @@ -1816,10 +1816,10 @@ static int ftdi_elan_edset_single(struct usb_ftdi *ftdi, u8 ed_number, target->active = 1; ftdi->command_next += 1; ftdi_elan_kick_command_queue(ftdi); - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); return 0; } else { - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); msleep(100); goto wait; } @@ -1849,9 +1849,9 @@ static int ftdi_elan_edset_flush(struct usb_ftdi *ftdi, u8 ed_number, return -ENODEV; } else { struct u132_target *target = &ftdi->target[ed]; - down(&ftdi->u132_lock); + mutex_lock(&ftdi->u132_lock); if (target->abandoning > 0) { - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); return 0; } else { target->abandoning = 1; @@ -1873,13 +1873,13 @@ static int ftdi_elan_edset_flush(struct usb_ftdi *ftdi, u8 ed_number, ftdi->command_next += 1; ftdi_elan_kick_command_queue(ftdi); } else { - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); msleep(100); - down(&ftdi->u132_lock); + mutex_lock(&ftdi->u132_lock); goto wait_1; } } - up(&ftdi->u132_lock); + mutex_unlock(&ftdi->u132_lock); return 0; } } @@ -2793,7 +2793,7 @@ static int ftdi_elan_probe(struct usb_interface *interface, init_MUTEX(&ftdi->sw_lock); ftdi->udev = usb_get_dev(interface_to_usbdev(interface)); ftdi->interface = interface; - init_MUTEX(&ftdi->u132_lock); + mutex_init(&ftdi->u132_lock); ftdi->expected = 4; iface_desc = interface->cur_altsetting; for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c index e6fd024024f..4bcf7fb4e5d 100644 --- a/drivers/usb/misc/idmouse.c +++ b/drivers/usb/misc/idmouse.c @@ -66,6 +66,7 @@ static struct usb_device_id idmouse_table[] = { USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, value, index, NULL, 0, 1000) MODULE_DEVICE_TABLE(usb, idmouse_table); +static DEFINE_MUTEX(open_disc_mutex); /* structure to hold all of our device specific stuff */ struct usb_idmouse { @@ -80,7 +81,7 @@ struct usb_idmouse { int open; /* if the port is open or not */ int present; /* if the device is not disconnected */ - struct semaphore sem; /* locks this structure */ + struct mutex lock; /* locks this structure */ }; @@ -213,13 +214,17 @@ static int idmouse_open(struct inode *inode, struct file *file) if (!interface) return -ENODEV; + mutex_lock(&open_disc_mutex); /* get the device information block from the interface */ dev = usb_get_intfdata(interface); - if (!dev) + if (!dev) { + mutex_unlock(&open_disc_mutex); return -ENODEV; + } /* lock this device */ - down(&dev->sem); + mutex_lock(&dev->lock); + mutex_unlock(&open_disc_mutex); /* check if already open */ if (dev->open) { @@ -245,7 +250,7 @@ static int idmouse_open(struct inode *inode, struct file *file) error: /* unlock this device */ - up(&dev->sem); + mutex_unlock(&dev->lock); return result; } @@ -258,12 +263,14 @@ static int idmouse_release(struct inode *inode, struct file *file) if (dev == NULL) return -ENODEV; + mutex_lock(&open_disc_mutex); /* lock our device */ - down(&dev->sem); + mutex_lock(&dev->lock); /* are we really open? */ if (dev->open <= 0) { - up(&dev->sem); + mutex_unlock(&dev->lock); + mutex_unlock(&open_disc_mutex); return -ENODEV; } @@ -271,10 +278,12 @@ static int idmouse_release(struct inode *inode, struct file *file) if (!dev->present) { /* the device was unplugged before the file was released */ - up(&dev->sem); + mutex_unlock(&dev->lock); + mutex_unlock(&open_disc_mutex); idmouse_delete(dev); } else { - up(&dev->sem); + mutex_unlock(&dev->lock); + mutex_unlock(&open_disc_mutex); } return 0; } @@ -286,18 +295,18 @@ static ssize_t idmouse_read(struct file *file, char __user *buffer, size_t count int result; /* lock this object */ - down(&dev->sem); + mutex_lock(&dev->lock); /* verify that the device wasn't unplugged */ if (!dev->present) { - up(&dev->sem); + mutex_unlock(&dev->lock); return -ENODEV; } result = simple_read_from_buffer(buffer, count, ppos, dev->bulk_in_buffer, IMGSIZE); /* unlock the device */ - up(&dev->sem); + mutex_unlock(&dev->lock); return result; } @@ -320,7 +329,7 @@ static int idmouse_probe(struct usb_interface *interface, if (dev == NULL) return -ENOMEM; - init_MUTEX(&dev->sem); + mutex_init(&dev->lock); dev->udev = udev; dev->interface = interface; @@ -372,24 +381,26 @@ static void idmouse_disconnect(struct usb_interface *interface) /* get device structure */ dev = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); /* give back our minor */ usb_deregister_dev(interface, &idmouse_class); - /* lock it */ - down(&dev->sem); + mutex_lock(&open_disc_mutex); + usb_set_intfdata(interface, NULL); + /* lock the device */ + mutex_lock(&dev->lock); + mutex_unlock(&open_disc_mutex); /* prevent device read, write and ioctl */ dev->present = 0; /* if the device is opened, idmouse_release will clean this up */ if (!dev->open) { - up(&dev->sem); + mutex_unlock(&dev->lock); idmouse_delete(dev); } else { /* unlock */ - up(&dev->sem); + mutex_unlock(&dev->lock); } info("%s disconnected", DRIVER_DESC); diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index d372fbc4eff..764696ff1e8 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -66,6 +66,7 @@ module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "debug=1 enables debugging messages"); static struct usb_driver iowarrior_driver; +static DEFINE_MUTEX(iowarrior_open_disc_lock); /*--------------*/ /* data */ @@ -351,7 +352,7 @@ static ssize_t iowarrior_write(struct file *file, mutex_lock(&dev->mutex); /* verify that the device wasn't unplugged */ - if (dev == NULL || !dev->present) { + if (!dev->present) { retval = -ENODEV; goto exit; } @@ -608,11 +609,15 @@ static int iowarrior_open(struct inode *inode, struct file *file) return -ENODEV; } + mutex_lock(&iowarrior_open_disc_lock); dev = usb_get_intfdata(interface); - if (!dev) + if (!dev) { + mutex_unlock(&iowarrior_open_disc_lock); return -ENODEV; + } mutex_lock(&dev->mutex); + mutex_unlock(&iowarrior_open_disc_lock); /* Only one process can open each device, no sharing. */ if (dev->opened) { @@ -866,6 +871,7 @@ static void iowarrior_disconnect(struct usb_interface *interface) int minor; dev = usb_get_intfdata(interface); + mutex_lock(&iowarrior_open_disc_lock); usb_set_intfdata(interface, NULL); minor = dev->minor; @@ -879,6 +885,7 @@ static void iowarrior_disconnect(struct usb_interface *interface) dev->present = 0; mutex_unlock(&dev->mutex); + mutex_unlock(&iowarrior_open_disc_lock); if (dev->opened) { /* There is a process that holds a filedescriptor to the device , diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 561970b889a..aab320085eb 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -198,6 +198,7 @@ static struct usb_device_id tower_table [] = { }; MODULE_DEVICE_TABLE (usb, tower_table); +static DEFINE_MUTEX(open_disc_mutex); #define LEGO_USB_TOWER_MINOR_BASE 160 @@ -350,25 +351,31 @@ static int tower_open (struct inode *inode, struct file *file) goto exit; } + mutex_lock(&open_disc_mutex); dev = usb_get_intfdata(interface); if (!dev) { + mutex_unlock(&open_disc_mutex); retval = -ENODEV; goto exit; } /* lock this device */ if (down_interruptible (&dev->sem)) { + mutex_unlock(&open_disc_mutex); retval = -ERESTARTSYS; goto exit; } + /* allow opening only once */ if (dev->open_count) { + mutex_unlock(&open_disc_mutex); retval = -EBUSY; goto unlock_exit; } dev->open_count = 1; + mutex_unlock(&open_disc_mutex); /* reset the tower */ result = usb_control_msg (dev->udev, @@ -437,9 +444,10 @@ static int tower_release (struct inode *inode, struct file *file) if (dev == NULL) { dbg(1, "%s: object is NULL", __FUNCTION__); retval = -ENODEV; - goto exit; + goto exit_nolock; } + mutex_lock(&open_disc_mutex); if (down_interruptible (&dev->sem)) { retval = -ERESTARTSYS; goto exit; @@ -468,6 +476,8 @@ unlock_exit: up (&dev->sem); exit: + mutex_unlock(&open_disc_mutex); +exit_nolock: dbg(2, "%s: leave, return value %d", __FUNCTION__, retval); return retval; } @@ -989,6 +999,7 @@ static void tower_disconnect (struct usb_interface *interface) dbg(2, "%s: enter", __FUNCTION__); dev = usb_get_intfdata (interface); + mutex_lock(&open_disc_mutex); usb_set_intfdata (interface, NULL); minor = dev->minor; @@ -997,6 +1008,7 @@ static void tower_disconnect (struct usb_interface *interface) usb_deregister_dev (interface, &tower_class); down (&dev->sem); + mutex_unlock(&open_disc_mutex); /* if the device is not opened, then we clean up right now */ if (!dev->open_count) { diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c index 88f6abe7362..330c18e390b 100644 --- a/drivers/usb/misc/rio500.c +++ b/drivers/usb/misc/rio500.c @@ -118,10 +118,7 @@ ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd, mutex_lock(&(rio->lock)); /* Sanity check to make sure rio is connected, powered, etc */ - if ( rio == NULL || - rio->present == 0 || - rio->rio_dev == NULL ) - { + if (rio->present == 0 || rio->rio_dev == NULL) { retval = -ENODEV; goto err_out; } @@ -280,10 +277,7 @@ write_rio(struct file *file, const char __user *buffer, if (intr) return -EINTR; /* Sanity check to make sure rio is connected, powered, etc */ - if ( rio == NULL || - rio->present == 0 || - rio->rio_dev == NULL ) - { + if (rio->present == 0 || rio->rio_dev == NULL) { mutex_unlock(&(rio->lock)); return -ENODEV; } @@ -369,10 +363,7 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos) if (intr) return -EINTR; /* Sanity check to make sure rio is connected, powered, etc */ - if ( rio == NULL || - rio->present == 0 || - rio->rio_dev == NULL ) - { + if (rio->present == 0 || rio->rio_dev == NULL) { mutex_unlock(&(rio->lock)); return -ENODEV; } diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c index 71984203271..20777d01db6 100644 --- a/drivers/usb/misc/usblcd.c +++ b/drivers/usb/misc/usblcd.c @@ -17,6 +17,7 @@ #include <linux/init.h> #include <linux/slab.h> #include <linux/errno.h> +#include <linux/mutex.h> #include <asm/uaccess.h> #include <linux/usb.h> @@ -34,6 +35,8 @@ static struct usb_device_id id_table [] = { }; MODULE_DEVICE_TABLE (usb, id_table); +static DEFINE_MUTEX(open_disc_mutex); + struct usb_lcd { struct usb_device * udev; /* init: probe_lcd */ @@ -79,12 +82,16 @@ static int lcd_open(struct inode *inode, struct file *file) return -ENODEV; } + mutex_lock(&open_disc_mutex); dev = usb_get_intfdata(interface); - if (!dev) + if (!dev) { + mutex_unlock(&open_disc_mutex); return -ENODEV; + } /* increment our usage count for the device */ kref_get(&dev->kref); + mutex_unlock(&open_disc_mutex); /* grab a power reference */ r = usb_autopm_get_interface(interface); @@ -393,8 +400,10 @@ static void lcd_disconnect(struct usb_interface *interface) struct usb_lcd *dev; int minor = interface->minor; + mutex_lock(&open_disc_mutex); dev = usb_get_intfdata(interface); usb_set_intfdata(interface, NULL); + mutex_unlock(&open_disc_mutex); /* give back our minor */ usb_deregister_dev(interface, &lcd_class); diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index 2a8e537cb04..ddfee918000 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -161,7 +161,8 @@ static void ark3116_set_termios(struct usb_serial_port *port, { struct usb_serial *serial = port->serial; struct ark3116_private *priv = usb_get_serial_port_data(port); - unsigned int cflag = port->tty->termios->c_cflag; + struct ktermios *termios = port->tty->termios; + unsigned int cflag = termios->c_cflag; unsigned long flags; int baud; int ark3116_baud; @@ -177,11 +178,14 @@ static void ark3116_set_termios(struct usb_serial_port *port, *(port->tty->termios) = tty_std_termios; port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + termios->c_ispeed = 9600; + termios->c_ospeed = 9600; priv->termios_initialized = 1; } spin_unlock_irqrestore(&priv->lock, flags); - cflag = port->tty->termios->c_cflag; + cflag = termios->c_cflag; + termios->c_cflag &= ~(CMSPAR|CRTSCTS); buf = kmalloc(1, GFP_KERNEL); if (!buf) { @@ -254,9 +258,13 @@ static void ark3116_set_termios(struct usb_serial_port *port, case 115200: case 230400: case 460800: + /* Report the resulting rate back to the caller */ + tty_encode_baud_rate(port->tty, baud, baud); break; /* set 9600 as default (if given baudrate is invalid for example) */ default: + tty_encode_baud_rate(port->tty, 9600, 9600); + case 0: baud = 9600; } @@ -302,6 +310,7 @@ static void ark3116_set_termios(struct usb_serial_port *port, /* TEST ARK3116_SND(154, 0xFE, 0x40, 0xFFFF, 0x0006); */ kfree(buf); + return; } diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index 6b252ceb39a..42582d49b69 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -272,9 +272,6 @@ static void ch341_set_termios(struct usb_serial_port *port, dbg("ch341_set_termios()"); - if (!tty || !tty->termios) - return; - baud_rate = tty_get_baud_rate(tty); switch (baud_rate) { @@ -299,6 +296,11 @@ static void ch341_set_termios(struct usb_serial_port *port, * (cflag & PARENB) : parity {NONE, EVEN, ODD} * (cflag & CSTOPB) : stop bits [1, 2] */ + + /* Copy back the old hardware settings */ + tty_termios_copy_hw(tty->termios, old_termios); + /* And re-encode with the new baud */ + tty_encode_baud_rate(tty, baud_rate, baud_rate); } static struct usb_driver ch341_driver = { diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 9386e216d68..0362654d3b5 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -164,6 +164,7 @@ static int usb_console_setup(struct console *co, char *options) } if (serial->type->set_termios) { + struct ktermios dummy; /* build up a fake tty structure so that the open call has something * to look at to get the cflag value */ tty = kzalloc(sizeof(*tty), GFP_KERNEL); @@ -177,12 +178,13 @@ static int usb_console_setup(struct console *co, char *options) kfree (tty); return -ENOMEM; } + memset(&dummy, 0, sizeof(struct ktermios)); termios->c_cflag = cflag; tty->termios = termios; port->tty = tty; /* set up the initial termios settings */ - serial->type->set_termios(port, NULL); + serial->type->set_termios(port, &dummy); port->tty = NULL; kfree (termios); kfree (tty); diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index eb7df1835c1..3a83cb4c4bc 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -361,7 +361,6 @@ static void cp2101_get_termios (struct usb_serial_port *port) dbg("%s - no tty structures", __FUNCTION__); return; } - cflag = port->tty->termios->c_cflag; cp2101_get_config(port, CP2101_BAUDRATE, &baud, 2); /* Convert to baudrate */ @@ -369,40 +368,9 @@ static void cp2101_get_termios (struct usb_serial_port *port) baud = BAUD_RATE_GEN_FREQ / baud; dbg("%s - baud rate = %d", __FUNCTION__, baud); - cflag &= ~CBAUD; - switch (baud) { - /* - * The baud rates which are commented out below - * appear to be supported by the device - * but are non-standard - */ - case 600: cflag |= B600; break; - case 1200: cflag |= B1200; break; - case 1800: cflag |= B1800; break; - case 2400: cflag |= B2400; break; - case 4800: cflag |= B4800; break; - /*case 7200: cflag |= B7200; break;*/ - case 9600: cflag |= B9600; break; - /*case 14400: cflag |= B14400; break;*/ - case 19200: cflag |= B19200; break; - /*case 28800: cflag |= B28800; break;*/ - case 38400: cflag |= B38400; break; - /*case 55854: cflag |= B55054; break;*/ - case 57600: cflag |= B57600; break; - case 115200: cflag |= B115200; break; - /*case 127117: cflag |= B127117; break;*/ - case 230400: cflag |= B230400; break; - case 460800: cflag |= B460800; break; - case 921600: cflag |= B921600; break; - /*case 3686400: cflag |= B3686400; break;*/ - default: - dbg("%s - Baud rate is not supported, " - "using 9600 baud", __FUNCTION__); - cflag |= B9600; - cp2101_set_config_single(port, CP2101_BAUDRATE, - (BAUD_RATE_GEN_FREQ/9600)); - break; - } + + tty_encode_baud_rate(port->tty, baud, baud); + cflag = port->tty->termios->c_cflag; cp2101_get_config(port, CP2101_BITS, &bits, 2); cflag &= ~CSIZE; @@ -516,7 +484,7 @@ static void cp2101_get_termios (struct usb_serial_port *port) static void cp2101_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { - unsigned int cflag, old_cflag=0; + unsigned int cflag, old_cflag; int baud=0, bits; unsigned int modem_ctl[4]; @@ -526,6 +494,8 @@ static void cp2101_set_termios (struct usb_serial_port *port, dbg("%s - no tty structures", __FUNCTION__); return; } + port->tty->termios->c_cflag &= ~CMSPAR; + cflag = port->tty->termios->c_cflag; old_cflag = old_termios->c_cflag; baud = tty_get_baud_rate(port->tty); @@ -563,11 +533,15 @@ static void cp2101_set_termios (struct usb_serial_port *port, dbg("%s - Setting baud rate to %d baud", __FUNCTION__, baud); if (cp2101_set_config_single(port, CP2101_BAUDRATE, - (BAUD_RATE_GEN_FREQ / baud))) + (BAUD_RATE_GEN_FREQ / baud))) { dev_err(&port->dev, "Baud rate requested not " "supported by device\n"); + baud = tty_termios_baud_rate(old_termios); + } } } + /* Report back the resulting baud rate */ + tty_encode_baud_rate(port->tty, baud, baud); /* If the number of data bits is to be updated */ if ((cflag & CSIZE) != (old_cflag & CSIZE)) { diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index dab2e66d111..ae410c4678e 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -973,6 +973,8 @@ static void digi_set_termios(struct usb_serial_port *port, } } /* set parity */ + tty->termios->c_cflag &= ~CMSPAR; + if ((cflag&(PARENB|PARODD)) != (old_cflag&(PARENB|PARODD))) { if (cflag&PARENB) { if (cflag&PARODD) @@ -1054,15 +1056,15 @@ static void digi_set_termios(struct usb_serial_port *port, } /* set output flow control */ - if ((iflag&IXON) != (old_iflag&IXON) - || (cflag&CRTSCTS) != (old_cflag&CRTSCTS)) { + if ((iflag & IXON) != (old_iflag & IXON) + || (cflag & CRTSCTS) != (old_cflag & CRTSCTS)) { arg = 0; - if (iflag&IXON) + if (iflag & IXON) arg |= DIGI_OUTPUT_FLOW_CONTROL_XON_XOFF; else arg &= ~DIGI_OUTPUT_FLOW_CONTROL_XON_XOFF; - if (cflag&CRTSCTS) { + if (cflag & CRTSCTS) { arg |= DIGI_OUTPUT_FLOW_CONTROL_CTS; } else { arg &= ~DIGI_OUTPUT_FLOW_CONTROL_CTS; @@ -1076,8 +1078,8 @@ static void digi_set_termios(struct usb_serial_port *port, } /* set receive enable/disable */ - if ((cflag&CREAD) != (old_cflag&CREAD)) { - if (cflag&CREAD) + if ((cflag & CREAD) != (old_cflag & CREAD)) { + if (cflag & CREAD) arg = DIGI_ENABLE; else arg = DIGI_DISABLE; @@ -1089,7 +1091,7 @@ static void digi_set_termios(struct usb_serial_port *port, } if ((ret = digi_write_oob_command(port, buf, i, 1)) != 0) dbg("digi_set_termios: write oob failed, ret=%d", ret); - + tty_encode_baud_rate(tty, baud, baud); } diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c index 050fcc996f5..a5c8e1e17ea 100644 --- a/drivers/usb/serial/empeg.c +++ b/drivers/usb/serial/empeg.c @@ -449,14 +449,9 @@ static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsign static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { - + struct ktermios *termios = port->tty->termios; dbg("%s - port %d", __FUNCTION__, port->number); - if ((!port->tty) || (!port->tty->termios)) { - dbg("%s - no tty structures", __FUNCTION__); - return; - } - /* * The empeg-car player wants these particular tty settings. * You could, for example, change the baud rate, however the @@ -466,7 +461,7 @@ static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *ol * * The default requirements for this device are: */ - port->tty->termios->c_iflag + termios->c_iflag &= ~(IGNBRK /* disable ignore break */ | BRKINT /* disable break causes interrupt */ | PARMRK /* disable mark parity errors */ @@ -476,24 +471,23 @@ static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *ol | ICRNL /* disable translate CR to NL */ | IXON); /* disable enable XON/XOFF flow control */ - port->tty->termios->c_oflag + termios->c_oflag &= ~OPOST; /* disable postprocess output characters */ - port->tty->termios->c_lflag + termios->c_lflag &= ~(ECHO /* disable echo input characters */ | ECHONL /* disable echo new line */ | ICANON /* disable erase, kill, werase, and rprnt special characters */ | ISIG /* disable interrupt, quit, and suspend special characters */ | IEXTEN); /* disable non-POSIX special characters */ - port->tty->termios->c_cflag + termios->c_cflag &= ~(CSIZE /* no size */ | PARENB /* disable parity bit */ | CBAUD); /* clear current baud rate */ - port->tty->termios->c_cflag - |= (CS8 /* character size 8 bits */ - | B115200); /* baud rate 115200 */ + termios->c_cflag + |= CS8; /* character size 8 bits */ /* * Force low_latency on; otherwise the pushes are scheduled; @@ -501,8 +495,7 @@ static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *ol * on the floor. We don't want to drop bytes on the floor. :) */ port->tty->low_latency = 1; - - return; + tty_encode_baud_rate(port->tty, 115200, 115200); } diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 8a8a6b9fb05..c40e77dccf8 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -294,7 +294,7 @@ struct ftdi_private { __u16 interface; /* FT2232C port interface (0 for FT232/245) */ - int force_baud; /* if non-zero, force the baud rate to this value */ + speed_t force_baud; /* if non-zero, force the baud rate to this value */ int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */ spinlock_t tx_lock; /* spinlock for transmit state */ @@ -878,6 +878,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port) if (div_value == 0) { dbg("%s - Baudrate (%d) requested is not supported", __FUNCTION__, baud); div_value = ftdi_sio_b9600; + baud = 9600; div_okay = 0; } break; @@ -886,6 +887,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port) div_value = ftdi_232am_baud_to_divisor(baud); } else { dbg("%s - Baud rate too high!", __FUNCTION__); + baud = 9600; div_value = ftdi_232am_baud_to_divisor(9600); div_okay = 0; } @@ -899,6 +901,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port) dbg("%s - Baud rate too high!", __FUNCTION__); div_value = ftdi_232bm_baud_to_divisor(9600); div_okay = 0; + baud = 9600; } break; } /* priv->chip_type */ @@ -909,6 +912,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port) ftdi_chip_name[priv->chip_type]); } + tty_encode_baud_rate(port->tty, baud, baud); return(div_value); } @@ -1263,7 +1267,7 @@ static void ftdi_USB_UIRT_setup (struct ftdi_private *priv) priv->flags |= ASYNC_SPD_CUST; priv->custom_divisor = 77; - priv->force_baud = B38400; + priv->force_baud = 38400; } /* ftdi_USB_UIRT_setup */ /* Setup for the HE-TIRA1 device, which requires hardwired @@ -1274,7 +1278,7 @@ static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv) priv->flags |= ASYNC_SPD_CUST; priv->custom_divisor = 240; - priv->force_baud = B38400; + priv->force_baud = 38400; priv->force_rtscts = 1; } /* ftdi_HE_TIRA1_setup */ @@ -1363,7 +1367,7 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp) /* ftdi_set_termios will send usb control messages */ if (port->tty) - ftdi_set_termios(port, NULL); + ftdi_set_termios(port, port->tty->termios); /* FIXME: Flow control might be enabled, so it should be checked - we have no control of defaults! */ @@ -1933,32 +1937,33 @@ static void ftdi_break_ctl( struct usb_serial_port *port, int break_state ) static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { /* ftdi_termios */ struct usb_device *dev = port->serial->dev; - unsigned int cflag = port->tty->termios->c_cflag; struct ftdi_private *priv = usb_get_serial_port_data(port); + struct ktermios *termios = port->tty->termios; + unsigned int cflag = termios->c_cflag; __u16 urb_value; /* will hold the new flags */ char buf[1]; /* Perhaps I should dynamically alloc this? */ // Added for xon/xoff support - unsigned int iflag = port->tty->termios->c_iflag; + unsigned int iflag = termios->c_iflag; unsigned char vstop; unsigned char vstart; dbg("%s", __FUNCTION__); /* Force baud rate if this device requires it, unless it is set to B0. */ - if (priv->force_baud && ((port->tty->termios->c_cflag & CBAUD) != B0)) { + if (priv->force_baud && ((termios->c_cflag & CBAUD) != B0)) { dbg("%s: forcing baud rate for this device", __FUNCTION__); - port->tty->termios->c_cflag &= ~CBAUD; - port->tty->termios->c_cflag |= priv->force_baud; + tty_encode_baud_rate(port->tty, priv->force_baud, + priv->force_baud); } /* Force RTS-CTS if this device requires it. */ if (priv->force_rtscts) { dbg("%s: forcing rtscts for this device", __FUNCTION__); - port->tty->termios->c_cflag |= CRTSCTS; + termios->c_cflag |= CRTSCTS; } - cflag = port->tty->termios->c_cflag; + cflag = termios->c_cflag; /* FIXME -For this cut I don't care if the line is really changing or not - so just do the change regardless - should be able to @@ -1969,6 +1974,8 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old /* Set number of data bits, parity, stop bits */ + termios->c_cflag &= ~CMSPAR; + urb_value = 0; urb_value |= (cflag & CSTOPB ? FTDI_SIO_SET_DATA_STOP_BITS_2 : FTDI_SIO_SET_DATA_STOP_BITS_1); @@ -2048,8 +2055,8 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old // Set the vstart and vstop -- could have been done up above where // a lot of other dereferencing is done but that would be very // inefficient as vstart and vstop are not always needed - vstart=port->tty->termios->c_cc[VSTART]; - vstop=port->tty->termios->c_cc[VSTOP]; + vstart = termios->c_cc[VSTART]; + vstop = termios->c_cc[VSTOP]; urb_value=(vstop << 8) | (vstart); if (usb_control_msg(dev, diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 88a2c7dce33..9eb4a65ee4d 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -208,14 +208,15 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char * /* only do something if we have a bulk out endpoint */ if (serial->num_bulk_out) { - spin_lock_bh(&port->lock); + unsigned long flags; + spin_lock_irqsave(&port->lock, flags); if (port->write_urb_busy) { - spin_unlock_bh(&port->lock); + spin_unlock_irqrestore(&port->lock, flags); dbg("%s - already writing", __FUNCTION__); return 0; } port->write_urb_busy = 1; - spin_unlock_bh(&port->lock); + spin_unlock_irqrestore(&port->lock, flags); count = (count > port->bulk_out_size) ? port->bulk_out_size : count; diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 8dd3abc99d6..a5d2e115e16 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -1503,22 +1503,16 @@ static void edge_unthrottle (struct usb_serial_port *port) *****************************************************************************/ static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { + /* FIXME: This function appears unused ?? */ struct edgeport_port *edge_port = usb_get_serial_port_data(port); struct tty_struct *tty = port->tty; unsigned int cflag; - if (!port->tty || !port->tty->termios) { - dbg ("%s - no tty or termios", __FUNCTION__); - return; - } - cflag = tty->termios->c_cflag; dbg("%s - clfag %08x iflag %08x", __FUNCTION__, tty->termios->c_cflag, tty->termios->c_iflag); - if (old_termios) { - dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__, - old_termios->c_cflag, old_termios->c_iflag); - } + dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__, + old_termios->c_cflag, old_termios->c_iflag); dbg("%s - port %d", __FUNCTION__, port->number); @@ -2653,7 +2647,11 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi dbg("%s - baud rate = %d", __FUNCTION__, baud); status = send_cmd_write_baud_rate (edge_port, baud); - + if (status == -1) { + /* Speed change was not possible - put back the old speed */ + baud = tty_termios_baud_rate(old_termios); + tty_encode_baud_rate(tty, baud, baud); + } return; } diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index 5ab6a0c5ac5..6b803ab9854 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c @@ -504,11 +504,6 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t dbg("%s - port %d", __FUNCTION__, port->number); - if ((!port->tty) || (!port->tty->termios)) { - dbg("%s - no tty structures", __FUNCTION__); - return; - } - baud = tty_get_baud_rate(port->tty); /* @@ -531,8 +526,6 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t default: ir_baud = SPEED_9600; baud = 9600; - /* And once the new tty stuff is all done we need to - call back to correct the baud bits */ } if (xbof == -1) @@ -562,6 +555,10 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t result = usb_submit_urb (port->write_urb, GFP_KERNEL); if (result) dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result); + + /* Only speed changes are supported */ + tty_termios_copy_hw(port->tty->termios, old_termios); + tty_encode_baud_rate(port->tty, baud, baud); } diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index f2a6fce5de1..6bfdba6a213 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -278,29 +278,35 @@ static void keyspan_set_termios (struct usb_serial_port *port, struct keyspan_port_private *p_priv; const struct keyspan_device_details *d_details; unsigned int cflag; + struct tty_struct *tty = port->tty; dbg("%s", __FUNCTION__); p_priv = usb_get_serial_port_data(port); d_details = p_priv->device_details; - cflag = port->tty->termios->c_cflag; + cflag = tty->termios->c_cflag; device_port = port->number - port->serial->minor; /* 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); + baud_rate = tty_get_baud_rate(tty); /* If no match or invalid, don't change */ - if (baud_rate >= 0 - && d_details->calculate_baud_rate(baud_rate, d_details->baudclk, + if (d_details->calculate_baud_rate(baud_rate, d_details->baudclk, NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) { /* FIXME - more to do here to ensure rate changes cleanly */ + /* FIXME - calcuate exact rate from divisor ? */ p_priv->baud = baud_rate; - } + } else + baud_rate = tty_termios_baud_rate(old_termios); + tty_encode_baud_rate(tty, baud_rate, baud_rate); /* set CTS/RTS handshake etc. */ p_priv->cflag = cflag; p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none; + /* Mark/Space not supported */ + tty->termios->c_cflag &= ~CMSPAR; + keyspan_send_setup(port, 0); } diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 6f224195bd2..aee450246bf 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -616,8 +616,9 @@ static void kobil_set_termios(struct usb_serial_port *port, struct ktermios *old case 1200: urb_val = SUSBCR_SBR_1200; break; - case 9600: default: + speed = 9600; + case 9600: urb_val = SUSBCR_SBR_9600; break; } @@ -641,6 +642,8 @@ static void kobil_set_termios(struct usb_serial_port *port, struct ktermios *old urb_val |= SUSBCR_SPASB_NoParity; strcat(settings, "No Parity"); } + port->tty->termios->c_cflag &= ~CMSPAR; + tty_encode_baud_rate(port->tty, speed, speed); result = usb_control_msg( port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0 ), diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index f76480f1455..a5ced7e08cb 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -1977,11 +1977,6 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port, tty = mos7840_port->port->tty; - if ((!tty) || (!tty->termios)) { - dbg("%s - no tty structures", __FUNCTION__); - return; - } - dbg("%s", "Entering .......... \n"); lData = LCR_BITS_8; @@ -2151,11 +2146,6 @@ static void mos7840_set_termios(struct usb_serial_port *port, tty = port->tty; - if (!port->tty || !port->tty->termios) { - dbg("%s - no tty or termios", __FUNCTION__); - return; - } - if (!mos7840_port->open) { dbg("%s - port not opened", __FUNCTION__); return; @@ -2165,19 +2155,10 @@ static void mos7840_set_termios(struct usb_serial_port *port, cflag = tty->termios->c_cflag; - if (!cflag) { - dbg("%s %s\n", __FUNCTION__, "cflag is NULL"); - return; - } - dbg("%s - clfag %08x iflag %08x", __FUNCTION__, tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag)); - - if (old_termios) { - dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__, - old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag)); - } - + dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__, + old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag)); dbg("%s - port %d", __FUNCTION__, port->number); /* change the port settings to the new ones specified */ diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index a18659e0700..4590124cf88 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -172,6 +172,8 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2110) }, /* Novatel Merlin ES620 / Merlin ES720 / Ovation U720 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2130) }, /* Novatel Merlin ES620 SM Bus */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2410) }, /* Novatel EU740 */ + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x4100) }, /* Novatel U727 */ + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x4400) }, /* Novatel MC950 */ { USB_DEVICE(DELL_VENDOR_ID, 0x8114) }, /* Dell Wireless 5700 Mobile Broadband CDMA/EVDO Mini-Card == Novatel Expedite EV620 CDMA/EV-DO */ { USB_DEVICE(DELL_VENDOR_ID, 0x8115) }, /* Dell Wireless 5500 Mobile Broadband HSDPA Mini-Card == Novatel Expedite EU740 HSDPA/3G */ { USB_DEVICE(DELL_VENDOR_ID, 0x8116) }, /* Dell Wireless 5505 Mobile Broadband HSDPA Mini-Card == Novatel Expedite EU740 HSDPA/3G */ @@ -311,7 +313,8 @@ static void option_set_termios(struct usb_serial_port *port, struct ktermios *old_termios) { dbg("%s", __FUNCTION__); - + /* Doesn't support option setting */ + tty_termios_copy_hw(port->tty->termios, old_termios); option_send_setup(port); } diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 1da57fd9ea2..2cd3f1d4b68 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -56,6 +56,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS) }, { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) }, + { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) }, { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) }, { USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) }, { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) }, @@ -470,16 +471,13 @@ static void pl2303_set_termios(struct usb_serial_port *port, dbg("%s - port %d", __FUNCTION__, port->number); - if ((!port->tty) || (!port->tty->termios)) { - dbg("%s - no tty structures", __FUNCTION__); - return; - } - spin_lock_irqsave(&priv->lock, flags); if (!priv->termios_initialized) { *(port->tty->termios) = tty_std_termios; port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + port->tty->termios->c_ispeed = 9600; + port->tty->termios->c_ospeed = 9600; priv->termios_initialized = 1; } spin_unlock_irqrestore(&priv->lock, flags); @@ -596,6 +594,10 @@ static void pl2303_set_termios(struct usb_serial_port *port, dbg ("0x40:0x1:0x0:0x0 %d", i); } + /* FIXME: Need to read back resulting baud rate */ + if (baud) + tty_encode_baud_rate(port->tty, baud, baud); + kfree(buf); } diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index c39bace5cbc..ed603e3decd 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -20,6 +20,7 @@ #define IODATA_VENDOR_ID 0x04bb #define IODATA_PRODUCT_ID 0x0a03 +#define IODATA_PRODUCT_ID_RSAQ5 0x0a0e #define ELCOM_VENDOR_ID 0x056e #define ELCOM_PRODUCT_ID 0x5003 diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 959b3e4e907..833f6e1e372 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -224,7 +224,7 @@ static void sierra_set_termios(struct usb_serial_port *port, struct ktermios *old_termios) { dbg("%s", __FUNCTION__); - + tty_termios_copy_hw(port->tty->termios, old_termios); sierra_send_setup(port); } diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 4b1bd7def4a..497e29a700c 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -429,6 +429,8 @@ static void serial_set_termios (struct tty_struct *tty, struct ktermios * old) /* pass on to the driver specific version of this function if it is available */ if (port->serial->type->set_termios) port->serial->type->set_termios(port, old); + else + tty_termios_copy_hw(tty->termios, old); } static void serial_break (struct tty_struct *tty, int break_state) @@ -1121,7 +1123,9 @@ int usb_serial_resume(struct usb_interface *intf) { struct usb_serial *serial = usb_get_intfdata(intf); - return serial->type->resume(serial); + if (serial->type->resume) + return serial->type->resume(serial); + return 0; } EXPORT_SYMBOL(usb_serial_resume); diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index cc8b44c0871..ee5dd8b5a71 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -885,16 +885,7 @@ static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, un static void whiteheat_set_termios(struct usb_serial_port *port, struct ktermios *old_termios) { dbg("%s -port %d", __FUNCTION__, port->number); - - if ((!port->tty) || (!port->tty->termios)) { - dbg("%s - no tty structures", __FUNCTION__); - goto exit; - } - firm_setup_port(port); - -exit: - return; } @@ -1244,6 +1235,8 @@ static int firm_setup_port(struct usb_serial_port *port) { port_settings.baud = tty_get_baud_rate(port->tty); dbg("%s - baud rate = %d", __FUNCTION__, port_settings.baud); + /* fixme: should set validated settings */ + tty_encode_baud_rate(port->tty, port_settings.baud, port_settings.baud); /* handle any settings that aren't specified in the tty structure */ port_settings.lloop = 0; diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index fe2c4cd53f5..7e53333be01 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -48,7 +48,6 @@ config USB_STORAGE_FREECOM config USB_STORAGE_ISD200 bool "ISD-200 USB/ATA Bridge support" depends on USB_STORAGE - depends on BLK_DEV_IDE=y || BLK_DEV_IDE=USB_STORAGE ---help--- Say Y here if you want to use USB Mass Store devices based on the In-Systems Design ISD-200 USB/ATA bridge. diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index 93a7724e167..49ba6c0ff1e 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -977,6 +977,109 @@ static int isd200_manual_enum(struct us_data *us) return(retStatus); } +/* + * We are the last non IDE user of the legacy IDE ident structures + * and we thus want to keep a private copy of this function so the + * driver can be used without the obsolete drivers/ide layer + */ + +static void isd200_fix_driveid (struct hd_driveid *id) +{ +#ifndef __LITTLE_ENDIAN +# ifdef __BIG_ENDIAN + int i; + u16 *stringcast; + + id->config = __le16_to_cpu(id->config); + id->cyls = __le16_to_cpu(id->cyls); + id->reserved2 = __le16_to_cpu(id->reserved2); + id->heads = __le16_to_cpu(id->heads); + id->track_bytes = __le16_to_cpu(id->track_bytes); + id->sector_bytes = __le16_to_cpu(id->sector_bytes); + id->sectors = __le16_to_cpu(id->sectors); + id->vendor0 = __le16_to_cpu(id->vendor0); + id->vendor1 = __le16_to_cpu(id->vendor1); + id->vendor2 = __le16_to_cpu(id->vendor2); + stringcast = (u16 *)&id->serial_no[0]; + for (i = 0; i < (20/2); i++) + stringcast[i] = __le16_to_cpu(stringcast[i]); + id->buf_type = __le16_to_cpu(id->buf_type); + id->buf_size = __le16_to_cpu(id->buf_size); + id->ecc_bytes = __le16_to_cpu(id->ecc_bytes); + stringcast = (u16 *)&id->fw_rev[0]; + for (i = 0; i < (8/2); i++) + stringcast[i] = __le16_to_cpu(stringcast[i]); + stringcast = (u16 *)&id->model[0]; + for (i = 0; i < (40/2); i++) + stringcast[i] = __le16_to_cpu(stringcast[i]); + id->dword_io = __le16_to_cpu(id->dword_io); + id->reserved50 = __le16_to_cpu(id->reserved50); + id->field_valid = __le16_to_cpu(id->field_valid); + id->cur_cyls = __le16_to_cpu(id->cur_cyls); + id->cur_heads = __le16_to_cpu(id->cur_heads); + id->cur_sectors = __le16_to_cpu(id->cur_sectors); + id->cur_capacity0 = __le16_to_cpu(id->cur_capacity0); + id->cur_capacity1 = __le16_to_cpu(id->cur_capacity1); + id->lba_capacity = __le32_to_cpu(id->lba_capacity); + id->dma_1word = __le16_to_cpu(id->dma_1word); + id->dma_mword = __le16_to_cpu(id->dma_mword); + id->eide_pio_modes = __le16_to_cpu(id->eide_pio_modes); + id->eide_dma_min = __le16_to_cpu(id->eide_dma_min); + id->eide_dma_time = __le16_to_cpu(id->eide_dma_time); + id->eide_pio = __le16_to_cpu(id->eide_pio); + id->eide_pio_iordy = __le16_to_cpu(id->eide_pio_iordy); + for (i = 0; i < 2; ++i) + id->words69_70[i] = __le16_to_cpu(id->words69_70[i]); + for (i = 0; i < 4; ++i) + id->words71_74[i] = __le16_to_cpu(id->words71_74[i]); + id->queue_depth = __le16_to_cpu(id->queue_depth); + for (i = 0; i < 4; ++i) + id->words76_79[i] = __le16_to_cpu(id->words76_79[i]); + id->major_rev_num = __le16_to_cpu(id->major_rev_num); + id->minor_rev_num = __le16_to_cpu(id->minor_rev_num); + id->command_set_1 = __le16_to_cpu(id->command_set_1); + id->command_set_2 = __le16_to_cpu(id->command_set_2); + id->cfsse = __le16_to_cpu(id->cfsse); + id->cfs_enable_1 = __le16_to_cpu(id->cfs_enable_1); + id->cfs_enable_2 = __le16_to_cpu(id->cfs_enable_2); + id->csf_default = __le16_to_cpu(id->csf_default); + id->dma_ultra = __le16_to_cpu(id->dma_ultra); + id->trseuc = __le16_to_cpu(id->trseuc); + id->trsEuc = __le16_to_cpu(id->trsEuc); + id->CurAPMvalues = __le16_to_cpu(id->CurAPMvalues); + id->mprc = __le16_to_cpu(id->mprc); + id->hw_config = __le16_to_cpu(id->hw_config); + id->acoustic = __le16_to_cpu(id->acoustic); + id->msrqs = __le16_to_cpu(id->msrqs); + id->sxfert = __le16_to_cpu(id->sxfert); + id->sal = __le16_to_cpu(id->sal); + id->spg = __le32_to_cpu(id->spg); + id->lba_capacity_2 = __le64_to_cpu(id->lba_capacity_2); + for (i = 0; i < 22; i++) + id->words104_125[i] = __le16_to_cpu(id->words104_125[i]); + id->last_lun = __le16_to_cpu(id->last_lun); + id->word127 = __le16_to_cpu(id->word127); + id->dlf = __le16_to_cpu(id->dlf); + id->csfo = __le16_to_cpu(id->csfo); + for (i = 0; i < 26; i++) + id->words130_155[i] = __le16_to_cpu(id->words130_155[i]); + id->word156 = __le16_to_cpu(id->word156); + for (i = 0; i < 3; i++) + id->words157_159[i] = __le16_to_cpu(id->words157_159[i]); + id->cfa_power = __le16_to_cpu(id->cfa_power); + for (i = 0; i < 14; i++) + id->words161_175[i] = __le16_to_cpu(id->words161_175[i]); + for (i = 0; i < 31; i++) + id->words176_205[i] = __le16_to_cpu(id->words176_205[i]); + for (i = 0; i < 48; i++) + id->words206_254[i] = __le16_to_cpu(id->words206_254[i]); + id->integrity_word = __le16_to_cpu(id->integrity_word); +# else +# error "Please fix <asm/byteorder.h>" +# endif +#endif +} + /************************************************************************** * isd200_get_inquiry_data @@ -1018,7 +1121,7 @@ static int isd200_get_inquiry_data( struct us_data *us ) int i; __be16 *src; __u16 *dest; - ide_fix_driveid(id); + isd200_fix_driveid(id); US_DEBUGP(" Identify Data Structure:\n"); US_DEBUGP(" config = 0x%x\n", id->config); diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index fb9d8d0b2c0..cc4b60f899c 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -1509,7 +1509,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 +1807,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 +1892,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/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/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/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/watchdog/Kconfig b/drivers/watchdog/Kconfig index 81db48f07ca..2792bc1a726 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 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/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/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/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..c622a0e6c9a 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,8 +376,6 @@ 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) { 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); |