diff options
Diffstat (limited to 'drivers')
43 files changed, 480 insertions, 300 deletions
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 84e0f3c0744..2cc4b303387 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -1151,6 +1151,9 @@ static int __init acpi_processor_init(void) { int result = 0; + if (acpi_disabled) + return 0; + memset(&errata, 0, sizeof(errata)); #ifdef CONFIG_SMP @@ -1197,6 +1200,9 @@ out_proc: static void __exit acpi_processor_exit(void) { + if (acpi_disabled) + return; + acpi_processor_ppc_exit(); acpi_thermal_cpufreq_exit(); diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 0efa59e7e3a..66393d5c4c7 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -162,8 +162,9 @@ static void lapic_timer_check_state(int state, struct acpi_processor *pr, pr->power.timer_broadcast_on_state = state; } -static void lapic_timer_propagate_broadcast(struct acpi_processor *pr) +static void lapic_timer_propagate_broadcast(void *arg) { + struct acpi_processor *pr = (struct acpi_processor *) arg; unsigned long reason; reason = pr->power.timer_broadcast_on_state < INT_MAX ? @@ -635,7 +636,8 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) working++; } - lapic_timer_propagate_broadcast(pr); + smp_call_function_single(pr->id, lapic_timer_propagate_broadcast, + pr, 1); return (working); } diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index 39838c66603..31adda1099e 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c @@ -66,7 +66,7 @@ static int acpi_processor_apply_limit(struct acpi_processor *pr) if (pr->limit.thermal.tx > tx) tx = pr->limit.thermal.tx; - result = acpi_processor_set_throttling(pr, tx); + result = acpi_processor_set_throttling(pr, tx, false); if (result) goto end; } @@ -421,12 +421,12 @@ processor_set_cur_state(struct thermal_cooling_device *cdev, if (state <= max_pstate) { if (pr->flags.throttling && pr->throttling.state) - result = acpi_processor_set_throttling(pr, 0); + result = acpi_processor_set_throttling(pr, 0, false); cpufreq_set_cur_state(pr->id, state); } else { cpufreq_set_cur_state(pr->id, max_pstate); result = acpi_processor_set_throttling(pr, - state - max_pstate); + state - max_pstate, false); } return result; } diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 227543789ba..ae39797aab5 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -62,7 +62,8 @@ struct throttling_tstate { #define THROTTLING_POSTCHANGE (2) static int acpi_processor_get_throttling(struct acpi_processor *pr); -int acpi_processor_set_throttling(struct acpi_processor *pr, int state); +int acpi_processor_set_throttling(struct acpi_processor *pr, + int state, bool force); static int acpi_processor_update_tsd_coord(void) { @@ -361,7 +362,7 @@ int acpi_processor_tstate_has_changed(struct acpi_processor *pr) */ target_state = throttling_limit; } - return acpi_processor_set_throttling(pr, target_state); + return acpi_processor_set_throttling(pr, target_state, false); } /* @@ -839,10 +840,10 @@ static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr) if (ret >= 0) { state = acpi_get_throttling_state(pr, value); if (state == -1) { - ACPI_WARNING((AE_INFO, - "Invalid throttling state, reset")); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Invalid throttling state, reset\n")); state = 0; - ret = acpi_processor_set_throttling(pr, state); + ret = acpi_processor_set_throttling(pr, state, true); if (ret) return ret; } @@ -915,7 +916,7 @@ static int acpi_processor_get_fadt_info(struct acpi_processor *pr) } static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr, - int state) + int state, bool force) { u32 value = 0; u32 duty_mask = 0; @@ -930,7 +931,7 @@ static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr, if (!pr->flags.throttling) return -ENODEV; - if (state == pr->throttling.state) + if (!force && (state == pr->throttling.state)) return 0; if (state < pr->throttling_platform_limit) @@ -988,7 +989,7 @@ static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr, } static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr, - int state) + int state, bool force) { int ret; acpi_integer value; @@ -1002,7 +1003,7 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr, if (!pr->flags.throttling) return -ENODEV; - if (state == pr->throttling.state) + if (!force && (state == pr->throttling.state)) return 0; if (state < pr->throttling_platform_limit) @@ -1018,7 +1019,8 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr, return 0; } -int acpi_processor_set_throttling(struct acpi_processor *pr, int state) +int acpi_processor_set_throttling(struct acpi_processor *pr, + int state, bool force) { cpumask_var_t saved_mask; int ret = 0; @@ -1070,7 +1072,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state) /* FIXME: use work_on_cpu() */ set_cpus_allowed_ptr(current, cpumask_of(pr->id)); ret = p_throttling->acpi_processor_set_throttling(pr, - t_state.target_state); + t_state.target_state, force); } else { /* * When the T-state coordination is SW_ALL or HW_ALL, @@ -1103,7 +1105,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state) set_cpus_allowed_ptr(current, cpumask_of(i)); ret = match_pr->throttling. acpi_processor_set_throttling( - match_pr, t_state.target_state); + match_pr, t_state.target_state, force); } } /* @@ -1201,7 +1203,7 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabling throttling (was T%d)\n", pr->throttling.state)); - result = acpi_processor_set_throttling(pr, 0); + result = acpi_processor_set_throttling(pr, 0, false); if (result) goto end; } @@ -1307,7 +1309,7 @@ static ssize_t acpi_processor_write_throttling(struct file *file, if (strcmp(tmpbuf, charp) != 0) return -EINVAL; - result = acpi_processor_set_throttling(pr, state_val); + result = acpi_processor_set_throttling(pr, state_val, false); if (result) return result; diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index 1733d3439ad..e48af9f7921 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c @@ -508,8 +508,9 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) * be obtained while the delayed work queue halt ensures that no more * data is fed to the ldisc. * - * In order to wait for any existing references to complete see - * tty_ldisc_wait_idle. + * You need to do a 'flush_scheduled_work()' (outside the ldisc_mutex) + * in order to make sure any currently executing ldisc work is also + * flushed. */ static int tty_ldisc_halt(struct tty_struct *tty) @@ -753,11 +754,14 @@ void tty_ldisc_hangup(struct tty_struct *tty) * N_TTY. */ if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) { + /* Make sure the old ldisc is quiescent */ + tty_ldisc_halt(tty); + flush_scheduled_work(); + /* Avoid racing set_ldisc or tty_ldisc_release */ mutex_lock(&tty->ldisc_mutex); if (tty->ldisc) { /* Not yet closed */ /* Switch back to N_TTY */ - tty_ldisc_halt(tty); tty_ldisc_reinit(tty); /* At this point we have a closed ldisc and we want to reopen it. We could defer this to the next open but diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index 14c19980292..d880edf254d 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -274,12 +274,18 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, } robj = gobj->driver_private; r = radeon_object_busy_domain(robj, &cur_placement); - if (cur_placement == TTM_PL_VRAM) + switch (cur_placement) { + case TTM_PL_VRAM: args->domain = RADEON_GEM_DOMAIN_VRAM; - if (cur_placement == TTM_PL_FLAG_TT) + break; + case TTM_PL_TT: args->domain = RADEON_GEM_DOMAIN_GTT; - if (cur_placement == TTM_PL_FLAG_SYSTEM) + break; + case TTM_PL_SYSTEM: args->domain = RADEON_GEM_DOMAIN_CPU; + default: + break; + } mutex_lock(&dev->struct_mutex); drm_gem_object_unreference(gobj); mutex_unlock(&dev->struct_mutex); diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 4cfd084fa89..9a1d55b74d7 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -456,8 +456,11 @@ static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __user *argp) { struct input_dev *dev = joydev->handle.dev; + size_t len; int i, j; + const char *name; + /* Process fixed-sized commands. */ switch (cmd) { case JS_SET_CAL: @@ -499,9 +502,22 @@ static int joydev_ioctl_common(struct joydev *joydev, return copy_to_user(argp, joydev->corr, sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0; - case JSIOCSAXMAP: - if (copy_from_user(joydev->abspam, argp, - sizeof(__u8) * (ABS_MAX + 1))) + } + + /* + * Process variable-sized commands (the axis and button map commands + * are considered variable-sized to decouple them from the values of + * ABS_MAX and KEY_MAX). + */ + switch (cmd & ~IOCSIZE_MASK) { + + case (JSIOCSAXMAP & ~IOCSIZE_MASK): + len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam)); + /* + * FIXME: we should not copy into our axis map before + * validating the data. + */ + if (copy_from_user(joydev->abspam, argp, len)) return -EFAULT; for (i = 0; i < joydev->nabs; i++) { @@ -511,13 +527,17 @@ static int joydev_ioctl_common(struct joydev *joydev, } return 0; - case JSIOCGAXMAP: - return copy_to_user(argp, joydev->abspam, - sizeof(__u8) * (ABS_MAX + 1)) ? -EFAULT : 0; - - case JSIOCSBTNMAP: - if (copy_from_user(joydev->keypam, argp, - sizeof(__u16) * (KEY_MAX - BTN_MISC + 1))) + case (JSIOCGAXMAP & ~IOCSIZE_MASK): + len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam)); + return copy_to_user(argp, joydev->abspam, len) ? -EFAULT : 0; + + case (JSIOCSBTNMAP & ~IOCSIZE_MASK): + len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam)); + /* + * FIXME: we should not copy into our keymap before + * validating the data. + */ + if (copy_from_user(joydev->keypam, argp, len)) return -EFAULT; for (i = 0; i < joydev->nkey; i++) { @@ -529,25 +549,19 @@ static int joydev_ioctl_common(struct joydev *joydev, return 0; - case JSIOCGBTNMAP: - return copy_to_user(argp, joydev->keypam, - sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)) ? -EFAULT : 0; + case (JSIOCGBTNMAP & ~IOCSIZE_MASK): + len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam)); + return copy_to_user(argp, joydev->keypam, len) ? -EFAULT : 0; - default: - if ((cmd & ~IOCSIZE_MASK) == JSIOCGNAME(0)) { - int len; - const char *name = dev->name; - - if (!name) - return 0; - len = strlen(name) + 1; - if (len > _IOC_SIZE(cmd)) - len = _IOC_SIZE(cmd); - if (copy_to_user(argp, name, len)) - return -EFAULT; - return len; - } + case JSIOCGNAME(0): + name = dev->name; + if (!name) + return 0; + + len = min_t(size_t, _IOC_SIZE(cmd), strlen(name) + 1); + return copy_to_user(argp, name, len) ? -EFAULT : len; } + return -EINVAL; } diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index baabf830264..f6c688cae33 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -74,6 +74,7 @@ static struct iforce_device iforce_device[] = { { 0x05ef, 0x8884, "AVB Mag Turbo Force", btn_avb_wheel, abs_wheel, ff_iforce }, { 0x05ef, 0x8888, "AVB Top Shot Force Feedback Racing Wheel", btn_avb_tw, abs_wheel, ff_iforce }, //? { 0x061c, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //? + { 0x061c, 0xc084, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, { 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //? { 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //? { 0x06f8, 0x0004, "Gullemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //? diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index f83185aeb51..9f289d8f52c 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c @@ -223,6 +223,7 @@ static struct usb_device_id iforce_usb_ids [] = { { USB_DEVICE(0x05ef, 0x8884) }, /* AVB Mag Turbo Force */ { USB_DEVICE(0x05ef, 0x8888) }, /* AVB Top Shot FFB Racing Wheel */ { USB_DEVICE(0x061c, 0xc0a4) }, /* ACT LABS Force RS */ + { USB_DEVICE(0x061c, 0xc084) }, /* ACT LABS Force RS */ { USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */ { USB_DEVICE(0x06f8, 0x0004) }, /* Guillemot Force Feedback Racing Wheel */ { USB_DEVICE(0x06f8, 0xa302) }, /* Guillemot Jet Leader 3D */ diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index a9d5031b855..ea30c983a33 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -388,6 +388,32 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi return result; } +static int wacom_query_tablet_data(struct usb_interface *intf) +{ + unsigned char *rep_data; + int limit = 0; + int error; + + rep_data = kmalloc(2, GFP_KERNEL); + if (!rep_data) + return -ENOMEM; + + do { + rep_data[0] = 2; + rep_data[1] = 2; + error = usb_set_report(intf, WAC_HID_FEATURE_REPORT, + 2, rep_data, 2); + if (error >= 0) + error = usb_get_report(intf, + WAC_HID_FEATURE_REPORT, 2, + rep_data, 2); + } while ((error < 0 || rep_data[1] != 2) && limit++ < 5); + + kfree(rep_data); + + return error < 0 ? error : 0; +} + static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *dev = interface_to_usbdev(intf); @@ -398,7 +424,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i struct wacom_features *features; struct input_dev *input_dev; int error = -ENOMEM; - char rep_data[2], limit = 0; struct hid_descriptor *hid_desc; wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); @@ -489,20 +514,10 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i /* * Ask the tablet to report tablet data if it is not a Tablet PC. - * Repeat until it succeeds + * Note that if query fails it is not a hard failure. */ - if (wacom_wac->features->type != TABLETPC) { - do { - rep_data[0] = 2; - rep_data[1] = 2; - error = usb_set_report(intf, WAC_HID_FEATURE_REPORT, - 2, rep_data, 2); - if (error >= 0) - error = usb_get_report(intf, - WAC_HID_FEATURE_REPORT, 2, - rep_data, 2); - } while ((error < 0 || rep_data[1] != 2) && limit++ < 5); - } + if (wacom_wac->features->type != TABLETPC) + wacom_query_tablet_data(intf); usb_set_intfdata(intf, wacom); return 0; diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index 6954f550010..3a7a58222f8 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c @@ -170,11 +170,11 @@ static void ucb1400_handle_pending_irq(struct ucb1400_ts *ucb) ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, isr); ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, 0); - if (isr & UCB_IE_TSPX) { + if (isr & UCB_IE_TSPX) ucb1400_ts_irq_disable(ucb->ac97); - enable_irq(ucb->irq); - } else - printk(KERN_ERR "ucb1400: unexpected IE_STATUS = %#x\n", isr); + else + dev_dbg(&ucb->ts_idev->dev, "ucb1400: unexpected IE_STATUS = %#x\n", isr); + enable_irq(ucb->irq); } static int ucb1400_ts_thread(void *_ucb) @@ -345,6 +345,7 @@ static int ucb1400_ts_detect_irq(struct ucb1400_ts *ucb) static int ucb1400_ts_probe(struct platform_device *dev) { int error, x_res, y_res; + u16 fcsr; struct ucb1400_ts *ucb = dev->dev.platform_data; ucb->ts_idev = input_allocate_device(); @@ -382,6 +383,14 @@ static int ucb1400_ts_probe(struct platform_device *dev) ucb->ts_idev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY); ucb->ts_idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); + /* + * Enable ADC filter to prevent horrible jitter on Colibri. + * This also further reduces jitter on boards where ADCSYNC + * pin is connected. + */ + fcsr = ucb1400_reg_read(ucb->ac97, UCB_FCSR); + ucb1400_reg_write(ucb->ac97, UCB_FCSR, fcsr | UCB_FCSR_AVE); + ucb1400_adc_enable(ucb->ac97); x_res = ucb1400_ts_read_xres(ucb); y_res = ucb1400_ts_read_yres(ucb); diff --git a/drivers/leds/ledtrig-gpio.c b/drivers/leds/ledtrig-gpio.c index a247ae63374..1bc5db4ece0 100644 --- a/drivers/leds/ledtrig-gpio.c +++ b/drivers/leds/ledtrig-gpio.c @@ -117,6 +117,9 @@ static ssize_t gpio_trig_inverted_store(struct device *dev, gpio_data->inverted = !!inverted; + /* After inverting, we need to update the LED. */ + schedule_work(&gpio_data->work); + return n; } static DEVICE_ATTR(inverted, 0644, gpio_trig_inverted_show, @@ -146,20 +149,26 @@ static ssize_t gpio_trig_gpio_store(struct device *dev, return -EINVAL; } + if (gpio_data->gpio == gpio) + return n; + if (!gpio) { - free_irq(gpio_to_irq(gpio_data->gpio), led); + if (gpio_data->gpio != 0) + free_irq(gpio_to_irq(gpio_data->gpio), led); + gpio_data->gpio = 0; return n; } - if (gpio_data->gpio > 0 && gpio_data->gpio != gpio) - free_irq(gpio_to_irq(gpio_data->gpio), led); - - gpio_data->gpio = gpio; ret = request_irq(gpio_to_irq(gpio), gpio_trig_irq, IRQF_SHARED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "ledtrig-gpio", led); - if (ret) + if (ret) { dev_err(dev, "request_irq failed with error %d\n", ret); + } else { + if (gpio_data->gpio != 0) + free_irq(gpio_to_irq(gpio_data->gpio), led); + gpio_data->gpio = gpio; + } return ret ? ret : n; } @@ -211,7 +220,8 @@ static void gpio_trig_deactivate(struct led_classdev *led) device_remove_file(led->dev, &dev_attr_inverted); device_remove_file(led->dev, &dev_attr_desired_brightness); flush_work(&gpio_data->work); - free_irq(gpio_to_irq(gpio_data->gpio),led); + if (gpio_data->gpio != 0) + free_irq(gpio_to_irq(gpio_data->gpio), led); kfree(gpio_data); } } diff --git a/drivers/macintosh/via-maciisi.c b/drivers/macintosh/via-maciisi.c index 4d686c0bdea..9ab5b0c34f0 100644 --- a/drivers/macintosh/via-maciisi.c +++ b/drivers/macintosh/via-maciisi.c @@ -288,7 +288,7 @@ static void maciisi_sync(struct adb_request *req) } /* This could be BAD... when the ADB controller doesn't respond * for this long, it's probably not coming back :-( */ - if(count >= 50) /* Hopefully shouldn't happen */ + if (count > 50) /* Hopefully shouldn't happen */ printk(KERN_ERR "maciisi_send_request: poll timed out!\n"); } diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index 7ad972229db..0d9d4bc9c76 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c @@ -61,7 +61,7 @@ static void orion_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) buf64 = (uint64_t *)buf; while (i < len/8) { uint64_t x; - asm ("ldrd\t%0, [%1]" : "=r" (x) : "r" (io_base)); + asm volatile ("ldrd\t%0, [%1]" : "=&r" (x) : "r" (io_base)); buf64[i++] = x; } i *= 8; diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 5f6509a5f64..5ce7cbabd7a 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1727,12 +1727,14 @@ config KS8842 tristate "Micrel KSZ8842" depends on HAS_IOMEM help - This platform driver is for Micrel KSZ8842 chip. + This platform driver is for Micrel KSZ8842 / KS8842 + 2-port ethernet switch chip (managed, VLAN, QoS). config KS8851 tristate "Micrel KS8851 SPI" depends on SPI select MII + select CRC32 help SPI driver for Micrel KS8851 SPI attached network chip. diff --git a/drivers/net/arm/w90p910_ether.c b/drivers/net/arm/w90p910_ether.c index 616fb7985a3..ddd231cb54b 100644 --- a/drivers/net/arm/w90p910_ether.c +++ b/drivers/net/arm/w90p910_ether.c @@ -1080,7 +1080,7 @@ static struct platform_driver w90p910_ether_driver = { .probe = w90p910_ether_probe, .remove = __devexit_p(w90p910_ether_remove), .driver = { - .name = "w90p910-emc", + .name = "nuc900-emc", .owner = THIS_MODULE, }, }; @@ -1101,5 +1101,5 @@ module_exit(w90p910_ether_exit); MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); MODULE_DESCRIPTION("w90p910 MAC driver!"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:w90p910-emc"); +MODULE_ALIAS("platform:nuc900-emc"); diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 41b648a67fe..3a6735dc9f6 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1899,7 +1899,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx, nic->ru_running = RU_SUSPENDED; pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); + PCI_DMA_FROMDEVICE); return -ENODATA; } diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c index cc786333d95..c40113f5896 100644 --- a/drivers/net/fec_mpc52xx.c +++ b/drivers/net/fec_mpc52xx.c @@ -309,6 +309,7 @@ static int mpc52xx_fec_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct mpc52xx_fec_priv *priv = netdev_priv(dev); struct bcom_fec_bd *bd; + unsigned long flags; if (bcom_queue_full(priv->tx_dmatsk)) { if (net_ratelimit()) @@ -316,7 +317,7 @@ static int mpc52xx_fec_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_BUSY; } - spin_lock_irq(&priv->lock); + spin_lock_irqsave(&priv->lock, flags); dev->trans_start = jiffies; bd = (struct bcom_fec_bd *) @@ -332,7 +333,7 @@ static int mpc52xx_fec_start_xmit(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); } - spin_unlock_irq(&priv->lock); + spin_unlock_irqrestore(&priv->lock, flags); return NETDEV_TX_OK; } diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index beb84213b67..f0f89080371 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c @@ -1305,6 +1305,8 @@ static int emac_close(struct net_device *ndev) free_irq(dev->emac_irq, dev); + netif_carrier_off(ndev); + return 0; } diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c index c4361d46659..ee1cff5c9b2 100644 --- a/drivers/net/irda/au1k_ir.c +++ b/drivers/net/irda/au1k_ir.c @@ -23,7 +23,6 @@ #include <linux/init.h> #include <linux/errno.h> #include <linux/netdevice.h> -#include <linux/etherdevice.h> #include <linux/slab.h> #include <linux/rtnetlink.h> #include <linux/interrupt.h> @@ -205,9 +204,6 @@ static const struct net_device_ops au1k_irda_netdev_ops = { .ndo_start_xmit = au1k_irda_hard_xmit, .ndo_tx_timeout = au1k_tx_timeout, .ndo_do_ioctl = au1k_irda_ioctl, - .ndo_change_mtu = eth_change_mtu, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = eth_mac_addr, }; static int au1k_irda_net_init(struct net_device *dev) diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c index 3376a4f39e0..77d10edefd2 100644 --- a/drivers/net/irda/pxaficp_ir.c +++ b/drivers/net/irda/pxaficp_ir.c @@ -803,9 +803,6 @@ static const struct net_device_ops pxa_irda_netdev_ops = { .ndo_stop = pxa_irda_stop, .ndo_start_xmit = pxa_irda_hard_xmit, .ndo_do_ioctl = pxa_irda_ioctl, - .ndo_change_mtu = eth_change_mtu, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = eth_mac_addr, }; static int pxa_irda_probe(struct platform_device *pdev) @@ -830,6 +827,7 @@ static int pxa_irda_probe(struct platform_device *pdev) if (!dev) goto err_mem_3; + SET_NETDEV_DEV(dev, &pdev->dev); si = netdev_priv(dev); si->dev = &pdev->dev; si->pdata = pdev->dev.platform_data; diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c index 2aeb2e6aec1..b039cb081e9 100644 --- a/drivers/net/irda/sa1100_ir.c +++ b/drivers/net/irda/sa1100_ir.c @@ -24,7 +24,6 @@ #include <linux/init.h> #include <linux/errno.h> #include <linux/netdevice.h> -#include <linux/etherdevice.h> #include <linux/slab.h> #include <linux/rtnetlink.h> #include <linux/interrupt.h> @@ -881,9 +880,6 @@ static const struct net_device_ops sa1100_irda_netdev_ops = { .ndo_stop = sa1100_irda_stop, .ndo_start_xmit = sa1100_irda_hard_xmit, .ndo_do_ioctl = sa1100_irda_ioctl, - .ndo_change_mtu = eth_change_mtu, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = eth_mac_addr, }; static int sa1100_irda_probe(struct platform_device *pdev) diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c index 2a0174b62e9..92fb8235c76 100644 --- a/drivers/net/ixp2000/ixpdev.c +++ b/drivers/net/ixp2000/ixpdev.c @@ -41,6 +41,7 @@ static int ixpdev_xmit(struct sk_buff *skb, struct net_device *dev) struct ixpdev_priv *ip = netdev_priv(dev); struct ixpdev_tx_desc *desc; int entry; + unsigned long flags; if (unlikely(skb->len > PAGE_SIZE)) { /* @@@ Count drops. */ @@ -63,11 +64,11 @@ static int ixpdev_xmit(struct sk_buff *skb, struct net_device *dev) dev->trans_start = jiffies; - local_irq_disable(); + local_irq_save(flags); ip->tx_queue_entries++; if (ip->tx_queue_entries == TX_BUF_COUNT_PER_CHAN) netif_stop_queue(dev); - local_irq_enable(); + local_irq_restore(flags); return 0; } diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 5b5c25368d1..e3601cf3f93 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -620,6 +620,7 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) dma_addr_t mapping; unsigned int len, entry; u32 ctrl; + unsigned long flags; #ifdef DEBUG int i; @@ -635,12 +636,12 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) #endif len = skb->len; - spin_lock_irq(&bp->lock); + spin_lock_irqsave(&bp->lock, flags); /* This is a hard error, log it. */ if (TX_BUFFS_AVAIL(bp) < 1) { netif_stop_queue(dev); - spin_unlock_irq(&bp->lock); + spin_unlock_irqrestore(&bp->lock, flags); dev_err(&bp->pdev->dev, "BUG! Tx Ring full when queue awake!\n"); dev_dbg(&bp->pdev->dev, "tx_head = %u, tx_tail = %u\n", @@ -674,7 +675,7 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) if (TX_BUFFS_AVAIL(bp) < 1) netif_stop_queue(dev); - spin_unlock_irq(&bp->lock); + spin_unlock_irqrestore(&bp->lock, flags); dev->trans_start = jiffies; diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c index 5a88b3f5769..62208401c4d 100644 --- a/drivers/net/mlx4/en_tx.c +++ b/drivers/net/mlx4/en_tx.c @@ -437,6 +437,7 @@ static inline void mlx4_en_xmit_poll(struct mlx4_en_priv *priv, int tx_ind) { struct mlx4_en_cq *cq = &priv->tx_cq[tx_ind]; struct mlx4_en_tx_ring *ring = &priv->tx_ring[tx_ind]; + unsigned long flags; /* If we don't have a pending timer, set one up to catch our recent post in case the interface becomes idle */ @@ -445,9 +446,9 @@ static inline void mlx4_en_xmit_poll(struct mlx4_en_priv *priv, int tx_ind) /* Poll the CQ every mlx4_en_TX_MODER_POLL packets */ if ((++ring->poll_cnt & (MLX4_EN_TX_POLL_MODER - 1)) == 0) - if (spin_trylock_irq(&ring->comp_lock)) { + if (spin_trylock_irqsave(&ring->comp_lock, flags)) { mlx4_en_process_tx_cq(priv->dev, cq); - spin_unlock_irq(&ring->comp_lock); + spin_unlock_irqrestore(&ring->comp_lock, flags); } } diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index 1c70e999cc5..7567f510eff 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -196,21 +196,23 @@ static void PRINT_PKT(u_char *buf, int length) /* this enables an interrupt in the interrupt mask register */ #define SMC_ENABLE_INT(lp, x) do { \ unsigned char mask; \ - spin_lock_irq(&lp->lock); \ + unsigned long smc_enable_flags; \ + spin_lock_irqsave(&lp->lock, smc_enable_flags); \ mask = SMC_GET_INT_MASK(lp); \ mask |= (x); \ SMC_SET_INT_MASK(lp, mask); \ - spin_unlock_irq(&lp->lock); \ + spin_unlock_irqrestore(&lp->lock, smc_enable_flags); \ } while (0) /* this disables an interrupt from the interrupt mask register */ #define SMC_DISABLE_INT(lp, x) do { \ unsigned char mask; \ - spin_lock_irq(&lp->lock); \ + unsigned long smc_disable_flags; \ + spin_lock_irqsave(&lp->lock, smc_disable_flags); \ mask = SMC_GET_INT_MASK(lp); \ mask &= ~(x); \ SMC_SET_INT_MASK(lp, mask); \ - spin_unlock_irq(&lp->lock); \ + spin_unlock_irqrestore(&lp->lock, smc_disable_flags); \ } while (0) /* @@ -520,21 +522,21 @@ static inline void smc_rcv(struct net_device *dev) * any other concurrent access and C would always interrupt B. But life * isn't that easy in a SMP world... */ -#define smc_special_trylock(lock) \ +#define smc_special_trylock(lock, flags) \ ({ \ int __ret; \ - local_irq_disable(); \ + local_irq_save(flags); \ __ret = spin_trylock(lock); \ if (!__ret) \ - local_irq_enable(); \ + local_irq_restore(flags); \ __ret; \ }) -#define smc_special_lock(lock) spin_lock_irq(lock) -#define smc_special_unlock(lock) spin_unlock_irq(lock) +#define smc_special_lock(lock, flags) spin_lock_irqsave(lock, flags) +#define smc_special_unlock(lock, flags) spin_unlock_irqrestore(lock, flags) #else -#define smc_special_trylock(lock) (1) -#define smc_special_lock(lock) do { } while (0) -#define smc_special_unlock(lock) do { } while (0) +#define smc_special_trylock(lock, flags) (1) +#define smc_special_lock(lock, flags) do { } while (0) +#define smc_special_unlock(lock, flags) do { } while (0) #endif /* @@ -548,10 +550,11 @@ static void smc_hardware_send_pkt(unsigned long data) struct sk_buff *skb; unsigned int packet_no, len; unsigned char *buf; + unsigned long flags; DBG(3, "%s: %s\n", dev->name, __func__); - if (!smc_special_trylock(&lp->lock)) { + if (!smc_special_trylock(&lp->lock, flags)) { netif_stop_queue(dev); tasklet_schedule(&lp->tx_task); return; @@ -559,7 +562,7 @@ static void smc_hardware_send_pkt(unsigned long data) skb = lp->pending_tx_skb; if (unlikely(!skb)) { - smc_special_unlock(&lp->lock); + smc_special_unlock(&lp->lock, flags); return; } lp->pending_tx_skb = NULL; @@ -569,7 +572,7 @@ static void smc_hardware_send_pkt(unsigned long data) printk("%s: Memory allocation failed.\n", dev->name); dev->stats.tx_errors++; dev->stats.tx_fifo_errors++; - smc_special_unlock(&lp->lock); + smc_special_unlock(&lp->lock, flags); goto done; } @@ -608,7 +611,7 @@ static void smc_hardware_send_pkt(unsigned long data) /* queue the packet for TX */ SMC_SET_MMU_CMD(lp, MC_ENQUEUE); - smc_special_unlock(&lp->lock); + smc_special_unlock(&lp->lock, flags); dev->trans_start = jiffies; dev->stats.tx_packets++; @@ -633,6 +636,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) struct smc_local *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; unsigned int numPages, poll_count, status; + unsigned long flags; DBG(3, "%s: %s\n", dev->name, __func__); @@ -658,7 +662,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } - smc_special_lock(&lp->lock); + smc_special_lock(&lp->lock, flags); /* now, try to allocate the memory */ SMC_SET_MMU_CMD(lp, MC_ALLOC | numPages); @@ -676,7 +680,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) } } while (--poll_count); - smc_special_unlock(&lp->lock); + smc_special_unlock(&lp->lock, flags); lp->pending_tx_skb = skb; if (!poll_count) { diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 2a6e81d5b57..bbedf03a212 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -70,6 +70,9 @@ struct virtnet_info struct sk_buff_head recv; struct sk_buff_head send; + /* Work struct for refilling if we run low on memory. */ + struct delayed_work refill; + /* Chain pages by the private ptr. */ struct page *pages; }; @@ -273,19 +276,22 @@ drop: dev_kfree_skb(skb); } -static void try_fill_recv_maxbufs(struct virtnet_info *vi) +static bool try_fill_recv_maxbufs(struct virtnet_info *vi, gfp_t gfp) { struct sk_buff *skb; struct scatterlist sg[2+MAX_SKB_FRAGS]; int num, err, i; + bool oom = false; sg_init_table(sg, 2+MAX_SKB_FRAGS); for (;;) { struct virtio_net_hdr *hdr; skb = netdev_alloc_skb(vi->dev, MAX_PACKET_LEN + NET_IP_ALIGN); - if (unlikely(!skb)) + if (unlikely(!skb)) { + oom = true; break; + } skb_reserve(skb, NET_IP_ALIGN); skb_put(skb, MAX_PACKET_LEN); @@ -296,7 +302,7 @@ static void try_fill_recv_maxbufs(struct virtnet_info *vi) if (vi->big_packets) { for (i = 0; i < MAX_SKB_FRAGS; i++) { skb_frag_t *f = &skb_shinfo(skb)->frags[i]; - f->page = get_a_page(vi, GFP_ATOMIC); + f->page = get_a_page(vi, gfp); if (!f->page) break; @@ -325,31 +331,35 @@ static void try_fill_recv_maxbufs(struct virtnet_info *vi) if (unlikely(vi->num > vi->max)) vi->max = vi->num; vi->rvq->vq_ops->kick(vi->rvq); + return !oom; } -static void try_fill_recv(struct virtnet_info *vi) +/* Returns false if we couldn't fill entirely (OOM). */ +static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp) { struct sk_buff *skb; struct scatterlist sg[1]; int err; + bool oom = false; - if (!vi->mergeable_rx_bufs) { - try_fill_recv_maxbufs(vi); - return; - } + if (!vi->mergeable_rx_bufs) + return try_fill_recv_maxbufs(vi, gfp); for (;;) { skb_frag_t *f; skb = netdev_alloc_skb(vi->dev, GOOD_COPY_LEN + NET_IP_ALIGN); - if (unlikely(!skb)) + if (unlikely(!skb)) { + oom = true; break; + } skb_reserve(skb, NET_IP_ALIGN); f = &skb_shinfo(skb)->frags[0]; - f->page = get_a_page(vi, GFP_ATOMIC); + f->page = get_a_page(vi, gfp); if (!f->page) { + oom = true; kfree_skb(skb); break; } @@ -373,6 +383,7 @@ static void try_fill_recv(struct virtnet_info *vi) if (unlikely(vi->num > vi->max)) vi->max = vi->num; vi->rvq->vq_ops->kick(vi->rvq); + return !oom; } static void skb_recv_done(struct virtqueue *rvq) @@ -385,6 +396,23 @@ static void skb_recv_done(struct virtqueue *rvq) } } +static void refill_work(struct work_struct *work) +{ + struct virtnet_info *vi; + bool still_empty; + + vi = container_of(work, struct virtnet_info, refill.work); + napi_disable(&vi->napi); + try_fill_recv(vi, GFP_KERNEL); + still_empty = (vi->num == 0); + napi_enable(&vi->napi); + + /* In theory, this can happen: if we don't get any buffers in + * we will *never* try to fill again. */ + if (still_empty) + schedule_delayed_work(&vi->refill, HZ/2); +} + static int virtnet_poll(struct napi_struct *napi, int budget) { struct virtnet_info *vi = container_of(napi, struct virtnet_info, napi); @@ -400,10 +428,10 @@ again: received++; } - /* FIXME: If we oom and completely run out of inbufs, we need - * to start a timer trying to fill more. */ - if (vi->num < vi->max / 2) - try_fill_recv(vi); + if (vi->num < vi->max / 2) { + if (!try_fill_recv(vi, GFP_ATOMIC)) + schedule_delayed_work(&vi->refill, 0); + } /* Out of packets? */ if (received < budget) { @@ -893,6 +921,7 @@ static int virtnet_probe(struct virtio_device *vdev) vi->vdev = vdev; vdev->priv = vi; vi->pages = NULL; + INIT_DELAYED_WORK(&vi->refill, refill_work); /* If they give us a callback when all buffers are done, we don't need * the timer. */ @@ -941,7 +970,7 @@ static int virtnet_probe(struct virtio_device *vdev) } /* Last of all, set up some receive buffers. */ - try_fill_recv(vi); + try_fill_recv(vi, GFP_KERNEL); /* If we didn't even get one input buffer, we're useless. */ if (vi->num == 0) { @@ -958,6 +987,7 @@ static int virtnet_probe(struct virtio_device *vdev) unregister: unregister_netdev(dev); + cancel_delayed_work_sync(&vi->refill); free_vqs: vdev->config->del_vqs(vdev); free: @@ -986,6 +1016,7 @@ static void virtnet_remove(struct virtio_device *vdev) BUG_ON(vi->num != 0); unregister_netdev(vi->dev); + cancel_delayed_work_sync(&vi->refill); vdev->config->del_vqs(vi->vdev); diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c index 632fac86a30..b3946272c72 100644 --- a/drivers/net/wireless/orinoco/hw.c +++ b/drivers/net/wireless/orinoco/hw.c @@ -70,7 +70,7 @@ int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc) int err = 0; u8 tsc_arr[4][IW_ENCODE_SEQ_MAX_SIZE]; - if ((key < 0) || (key > 4)) + if ((key < 0) || (key >= 4)) return -EINVAL; err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV, diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 294250e294d..87a95588a8e 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -869,6 +869,9 @@ static int rtl8187b_init_hw(struct ieee80211_hw *dev) priv->aifsn[3] = 3; /* AIFSN[AC_BE] */ rtl818x_iowrite8(priv, &priv->map->ACM_CONTROL, 0); + /* ENEDCA flag must always be set, transmit issues? */ + rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_ENEDCA); + return 0; } @@ -1173,13 +1176,16 @@ static void rtl8187_bss_info_changed(struct ieee80211_hw *dev, rtl818x_iowrite8(priv, &priv->map->BSSID[i], info->bssid[i]); + if (priv->is_rtl8187b) + reg = RTL818X_MSR_ENEDCA; + else + reg = 0; + if (is_valid_ether_addr(info->bssid)) { - reg = RTL818X_MSR_INFRA; - if (priv->is_rtl8187b) - reg |= RTL818X_MSR_ENEDCA; + reg |= RTL818X_MSR_INFRA; rtl818x_iowrite8(priv, &priv->map->MSR, reg); } else { - reg = RTL818X_MSR_NO_LINK; + reg |= RTL818X_MSR_NO_LINK; rtl818x_iowrite8(priv, &priv->map->MSR, reg); } diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index a07580138e8..c2fd6187773 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c @@ -346,7 +346,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int yellowfin_open(struct net_device *dev); static void yellowfin_timer(unsigned long data); static void yellowfin_tx_timeout(struct net_device *dev); -static void yellowfin_init_ring(struct net_device *dev); +static int yellowfin_init_ring(struct net_device *dev); static int yellowfin_start_xmit(struct sk_buff *skb, struct net_device *dev); static irqreturn_t yellowfin_interrupt(int irq, void *dev_instance); static int yellowfin_rx(struct net_device *dev); @@ -573,19 +573,24 @@ static int yellowfin_open(struct net_device *dev) { struct yellowfin_private *yp = netdev_priv(dev); void __iomem *ioaddr = yp->base; - int i; + int i, ret; /* Reset the chip. */ iowrite32(0x80000000, ioaddr + DMACtrl); - i = request_irq(dev->irq, &yellowfin_interrupt, IRQF_SHARED, dev->name, dev); - if (i) return i; + ret = request_irq(dev->irq, &yellowfin_interrupt, IRQF_SHARED, dev->name, dev); + if (ret) + return ret; if (yellowfin_debug > 1) printk(KERN_DEBUG "%s: yellowfin_open() irq %d.\n", dev->name, dev->irq); - yellowfin_init_ring(dev); + ret = yellowfin_init_ring(dev); + if (ret) { + free_irq(dev->irq, dev); + return ret; + } iowrite32(yp->rx_ring_dma, ioaddr + RxPtr); iowrite32(yp->tx_ring_dma, ioaddr + TxPtr); @@ -725,10 +730,10 @@ static void yellowfin_tx_timeout(struct net_device *dev) } /* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void yellowfin_init_ring(struct net_device *dev) +static int yellowfin_init_ring(struct net_device *dev) { struct yellowfin_private *yp = netdev_priv(dev); - int i; + int i, j; yp->tx_full = 0; yp->cur_rx = yp->cur_tx = 0; @@ -753,6 +758,11 @@ static void yellowfin_init_ring(struct net_device *dev) yp->rx_ring[i].addr = cpu_to_le32(pci_map_single(yp->pci_dev, skb->data, yp->rx_buf_sz, PCI_DMA_FROMDEVICE)); } + if (i != RX_RING_SIZE) { + for (j = 0; j < i; j++) + dev_kfree_skb(yp->rx_skbuff[j]); + return -ENOMEM; + } yp->rx_ring[i-1].dbdma_cmd = cpu_to_le32(CMD_STOP); yp->dirty_rx = (unsigned int)(i - RX_RING_SIZE); @@ -769,8 +779,6 @@ static void yellowfin_init_ring(struct net_device *dev) yp->tx_ring[--i].dbdma_cmd = cpu_to_le32(CMD_STOP | BRANCH_ALWAYS); #else { - int j; - /* Tx ring needs a pair of descriptors, the second for the status. */ for (i = 0; i < TX_RING_SIZE; i++) { j = 2*i; @@ -805,7 +813,7 @@ static void yellowfin_init_ring(struct net_device *dev) } #endif yp->tx_tail_desc = &yp->tx_status[0]; - return; + return 0; } static int yellowfin_start_xmit(struct sk_buff *skb, struct net_device *dev) diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index d76c4c85367..f99bc7f089f 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -508,7 +508,7 @@ static int pci_restore_standard_config(struct pci_dev *pci_dev) return error; } - return pci_dev->state_saved ? pci_restore_state(pci_dev) : 0; + return pci_restore_state(pci_dev); } static void pci_pm_default_resume_noirq(struct pci_dev *pci_dev) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index dbd0f947f49..7b70312181d 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -846,6 +846,8 @@ pci_restore_state(struct pci_dev *dev) int i; u32 val; + if (!dev->state_saved) + return 0; /* PCI Express register must be restored first */ pci_restore_pcie_state(dev); diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 043b208d971..f215a591919 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -270,7 +270,7 @@ u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out) acpi_status status; struct acpi_object_list input; union acpi_object params[3]; - char method[4] = "WM"; + char method[5] = "WM"; if (!find_guid(guid_string, &wblock)) return AE_ERROR; @@ -328,8 +328,8 @@ struct acpi_buffer *out) acpi_status status, wc_status = AE_ERROR; struct acpi_object_list input, wc_input; union acpi_object wc_params[1], wq_params[1]; - char method[4]; - char wc_method[4] = "WC"; + char method[5]; + char wc_method[5] = "WC"; if (!guid_string || !out) return AE_BAD_PARAMETER; @@ -410,7 +410,7 @@ const struct acpi_buffer *in) acpi_handle handle; struct acpi_object_list input; union acpi_object params[2]; - char method[4] = "WS"; + char method[5] = "WS"; if (!guid_string || !in) return AE_BAD_DATA; diff --git a/drivers/pps/pps.c b/drivers/pps/pps.c index ac8cc8cea1e..fea17e7805e 100644 --- a/drivers/pps/pps.c +++ b/drivers/pps/pps.c @@ -244,7 +244,7 @@ int pps_register_cdev(struct pps_device *pps) } pps->dev = device_create(pps_class, pps->info.dev, pps->devno, NULL, "pps%d", pps->id); - if (err) + if (IS_ERR(pps->dev)) goto del_cdev; dev_set_drvdata(pps->dev, pps); diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 74983666865..3f62dd50bbb 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -2135,9 +2135,9 @@ static int dasd_getgeo(struct block_device *bdev, struct hd_geometry *geo) struct dasd_device *base; block = bdev->bd_disk->private_data; - base = block->base; if (!block) return -ENODEV; + base = block->base; if (!base->discipline || !base->discipline->fill_geometry) diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 3c57c1a18bb..d593bc76afe 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -772,10 +772,8 @@ static struct ccw_device * io_subchannel_create_ccwdev(struct subchannel *sch) cdev = io_subchannel_allocate_dev(sch); if (!IS_ERR(cdev)) { ret = io_subchannel_initialize_dev(sch, cdev); - if (ret) { - kfree(cdev); + if (ret) cdev = ERR_PTR(ret); - } } return cdev; } diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c index 15dab96d05e..7c815d3327f 100644 --- a/drivers/sbus/char/bbc_envctrl.c +++ b/drivers/sbus/char/bbc_envctrl.c @@ -537,8 +537,12 @@ int bbc_envctrl_init(struct bbc_i2c_bus *bp) } if (temp_index != 0 && fan_index != 0) { kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld"); - if (IS_ERR(kenvctrld_task)) - return PTR_ERR(kenvctrld_task); + if (IS_ERR(kenvctrld_task)) { + int err = PTR_ERR(kenvctrld_task); + + kenvctrld_task = NULL; + return err; + } } return 0; @@ -561,7 +565,8 @@ void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp) struct bbc_cpu_temperature *tp, *tpos; struct bbc_fan_control *fp, *fpos; - kthread_stop(kenvctrld_task); + if (kenvctrld_task) + kthread_stop(kenvctrld_task); list_for_each_entry_safe(tp, tpos, &bp->temps, bp_list) { list_del(&tp->bp_list); diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index f3da592f7bc..35a13867495 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -119,6 +119,64 @@ _base_fault_reset_work(struct work_struct *work) spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); } +/** + * mpt2sas_base_start_watchdog - start the fault_reset_work_q + * @ioc: pointer to scsi command object + * Context: sleep. + * + * Return nothing. + */ +void +mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc) +{ + unsigned long flags; + + if (ioc->fault_reset_work_q) + return; + + /* initialize fault polling */ + INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work); + snprintf(ioc->fault_reset_work_q_name, + sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id); + ioc->fault_reset_work_q = + create_singlethread_workqueue(ioc->fault_reset_work_q_name); + if (!ioc->fault_reset_work_q) { + printk(MPT2SAS_ERR_FMT "%s: failed (line=%d)\n", + ioc->name, __func__, __LINE__); + return; + } + spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); + if (ioc->fault_reset_work_q) + queue_delayed_work(ioc->fault_reset_work_q, + &ioc->fault_reset_work, + msecs_to_jiffies(FAULT_POLLING_INTERVAL)); + spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); +} + +/** + * mpt2sas_base_stop_watchdog - stop the fault_reset_work_q + * @ioc: pointer to scsi command object + * Context: sleep. + * + * Return nothing. + */ +void +mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc) +{ + unsigned long flags; + struct workqueue_struct *wq; + + spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); + wq = ioc->fault_reset_work_q; + ioc->fault_reset_work_q = NULL; + spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); + if (wq) { + if (!cancel_delayed_work(&ioc->fault_reset_work)) + flush_workqueue(wq); + destroy_workqueue(wq); + } +} + #ifdef CONFIG_SCSI_MPT2SAS_LOGGING /** * _base_sas_ioc_info - verbose translation of the ioc status @@ -440,6 +498,10 @@ _base_sas_log_info(struct MPT2SAS_ADAPTER *ioc , u32 log_info) if (sas_loginfo.dw.bus_type != 3 /*SAS*/) return; + /* each nexus loss loginfo */ + if (log_info == 0x31170000) + return; + /* eat the loginfos associated with task aborts */ if (ioc->ignore_loginfos && (log_info == 30050000 || log_info == 0x31140000 || log_info == 0x31130000)) @@ -1109,7 +1171,6 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc) } } - pci_set_drvdata(pdev, ioc->shost); _base_mask_interrupts(ioc); r = _base_enable_msix(ioc); if (r) @@ -1132,7 +1193,6 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc) ioc->pci_irq = -1; pci_release_selected_regions(ioc->pdev, ioc->bars); pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); return r; } @@ -3191,7 +3251,6 @@ mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc) ioc->chip_phys = 0; pci_release_selected_regions(ioc->pdev, ioc->bars); pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); return; } @@ -3205,7 +3264,6 @@ int mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) { int r, i; - unsigned long flags; dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, __func__)); @@ -3214,6 +3272,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) if (r) return r; + pci_set_drvdata(ioc->pdev, ioc->shost); r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); if (r) goto out_free_resources; @@ -3288,23 +3347,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) if (r) goto out_free_resources; - /* initialize fault polling */ - INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work); - snprintf(ioc->fault_reset_work_q_name, - sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id); - ioc->fault_reset_work_q = - create_singlethread_workqueue(ioc->fault_reset_work_q_name); - if (!ioc->fault_reset_work_q) { - printk(MPT2SAS_ERR_FMT "%s: failed (line=%d)\n", - ioc->name, __func__, __LINE__); - goto out_free_resources; - } - spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); - if (ioc->fault_reset_work_q) - queue_delayed_work(ioc->fault_reset_work_q, - &ioc->fault_reset_work, - msecs_to_jiffies(FAULT_POLLING_INTERVAL)); - spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); + mpt2sas_base_start_watchdog(ioc); return 0; out_free_resources: @@ -3312,6 +3355,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) ioc->remove_host = 1; mpt2sas_base_free_resources(ioc); _base_release_memory_pools(ioc); + pci_set_drvdata(ioc->pdev, NULL); kfree(ioc->tm_cmds.reply); kfree(ioc->transport_cmds.reply); kfree(ioc->config_cmds.reply); @@ -3337,22 +3381,14 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) void mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc) { - unsigned long flags; - struct workqueue_struct *wq; dexitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, __func__)); - spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); - wq = ioc->fault_reset_work_q; - ioc->fault_reset_work_q = NULL; - spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); - if (!cancel_delayed_work(&ioc->fault_reset_work)) - flush_workqueue(wq); - destroy_workqueue(wq); - + mpt2sas_base_stop_watchdog(ioc); mpt2sas_base_free_resources(ioc); _base_release_memory_pools(ioc); + pci_set_drvdata(ioc->pdev, NULL); kfree(ioc->pfacts); kfree(ioc->ctl_cmds.reply); kfree(ioc->base_cmds.reply); diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index 286c185fa9e..acdcff150a3 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -69,10 +69,10 @@ #define MPT2SAS_DRIVER_NAME "mpt2sas" #define MPT2SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>" #define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver" -#define MPT2SAS_DRIVER_VERSION "01.100.03.00" +#define MPT2SAS_DRIVER_VERSION "01.100.04.00" #define MPT2SAS_MAJOR_VERSION 01 #define MPT2SAS_MINOR_VERSION 100 -#define MPT2SAS_BUILD_VERSION 03 +#define MPT2SAS_BUILD_VERSION 04 #define MPT2SAS_RELEASE_VERSION 00 /* @@ -673,6 +673,8 @@ typedef void (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, /* base shared API */ extern struct list_head mpt2sas_ioc_list; +void mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc); +void mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc); int mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc); void mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc); diff --git a/drivers/scsi/mpt2sas/mpt2sas_config.c b/drivers/scsi/mpt2sas/mpt2sas_config.c index 58cfb97846f..6ddee161beb 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_config.c +++ b/drivers/scsi/mpt2sas/mpt2sas_config.c @@ -236,17 +236,25 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t Mpi2ConfigRequest_t *config_request; int r; u8 retry_count; - u8 issue_reset; + u8 issue_host_reset = 0; u16 wait_state_count; + mutex_lock(&ioc->config_cmds.mutex); if (ioc->config_cmds.status != MPT2_CMD_NOT_USED) { printk(MPT2SAS_ERR_FMT "%s: config_cmd in use\n", ioc->name, __func__); + mutex_unlock(&ioc->config_cmds.mutex); return -EAGAIN; } retry_count = 0; retry_config: + if (retry_count) { + if (retry_count > 2) /* attempt only 2 retries */ + return -EFAULT; + printk(MPT2SAS_INFO_FMT "%s: attempting retry (%d)\n", + ioc->name, __func__, retry_count); + } wait_state_count = 0; ioc_state = mpt2sas_base_get_iocstate(ioc, 1); while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { @@ -254,8 +262,8 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t printk(MPT2SAS_ERR_FMT "%s: failed due to ioc not operational\n", ioc->name, __func__); - ioc->config_cmds.status = MPT2_CMD_NOT_USED; - return -EFAULT; + r = -EFAULT; + goto out; } ssleep(1); ioc_state = mpt2sas_base_get_iocstate(ioc, 1); @@ -271,8 +279,8 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t if (!smid) { printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", ioc->name, __func__); - ioc->config_cmds.status = MPT2_CMD_NOT_USED; - return -EAGAIN; + r = -EAGAIN; + goto out; } r = 0; @@ -292,9 +300,15 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t ioc->name, __func__); _debug_dump_mf(mpi_request, sizeof(Mpi2ConfigRequest_t)/4); - if (!(ioc->config_cmds.status & MPT2_CMD_RESET)) - issue_reset = 1; - goto issue_host_reset; + retry_count++; + if (ioc->config_cmds.smid == smid) + mpt2sas_base_free_smid(ioc, smid); + if ((ioc->shost_recovery) || + (ioc->config_cmds.status & MPT2_CMD_RESET)) + goto retry_config; + issue_host_reset = 1; + r = -EFAULT; + goto out; } if (ioc->config_cmds.status & MPT2_CMD_REPLY_VALID) memcpy(mpi_reply, ioc->config_cmds.reply, @@ -302,21 +316,13 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t if (retry_count) printk(MPT2SAS_INFO_FMT "%s: retry completed!!\n", ioc->name, __func__); +out: ioc->config_cmds.status = MPT2_CMD_NOT_USED; - return r; - - issue_host_reset: - if (issue_reset) + mutex_unlock(&ioc->config_cmds.mutex); + if (issue_host_reset) mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, FORCE_BIG_HAMMER); - ioc->config_cmds.status = MPT2_CMD_NOT_USED; - if (!retry_count) { - printk(MPT2SAS_INFO_FMT "%s: attempting retry\n", - ioc->name, __func__); - retry_count++; - goto retry_config; - } - return -EFAULT; + return r; } /** @@ -375,7 +381,6 @@ mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc, int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2ManufacturingPage0_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -417,7 +422,6 @@ mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc, _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -438,7 +442,6 @@ mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc, int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2BiosPage2_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -480,7 +483,6 @@ mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc, _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -501,7 +503,6 @@ mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2BiosPage3_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -543,7 +544,6 @@ mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -564,7 +564,6 @@ mpt2sas_config_get_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2IOUnitPage0_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -606,7 +605,6 @@ mpt2sas_config_get_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -627,7 +625,6 @@ mpt2sas_config_get_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2IOUnitPage1_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -669,7 +666,6 @@ mpt2sas_config_get_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -690,7 +686,6 @@ mpt2sas_config_set_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; @@ -732,7 +727,6 @@ mpt2sas_config_set_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -753,7 +747,6 @@ mpt2sas_config_get_ioc_pg8(struct MPT2SAS_ADAPTER *ioc, int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2IOCPage8_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -795,7 +788,6 @@ mpt2sas_config_get_ioc_pg8(struct MPT2SAS_ADAPTER *ioc, _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -818,7 +810,6 @@ mpt2sas_config_get_sas_device_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2SasDevicePage0_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -863,7 +854,6 @@ mpt2sas_config_get_sas_device_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -886,7 +876,6 @@ mpt2sas_config_get_sas_device_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2SasDevicePage1_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -931,7 +920,6 @@ mpt2sas_config_get_sas_device_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -953,7 +941,6 @@ mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys) Mpi2ConfigReply_t mpi_reply; Mpi2SasIOUnitPage0_t config_page; - mutex_lock(&ioc->config_cmds.mutex); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; @@ -1002,7 +989,6 @@ mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys) _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -1026,8 +1012,6 @@ mpt2sas_config_get_sas_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t Mpi2ConfigRequest_t mpi_request; int r; struct config_request mem; - - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sz); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -1070,7 +1054,6 @@ mpt2sas_config_get_sas_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -1095,7 +1078,6 @@ mpt2sas_config_get_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sz); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -1138,7 +1120,6 @@ mpt2sas_config_get_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -1161,7 +1142,6 @@ mpt2sas_config_get_expander_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2ExpanderPage0_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -1206,7 +1186,6 @@ mpt2sas_config_get_expander_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -1230,7 +1209,6 @@ mpt2sas_config_get_expander_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2ExpanderPage1_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -1277,7 +1255,6 @@ mpt2sas_config_get_expander_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -1300,7 +1277,6 @@ mpt2sas_config_get_enclosure_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2SasEnclosurePage0_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -1345,7 +1321,6 @@ mpt2sas_config_get_enclosure_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -1367,7 +1342,6 @@ mpt2sas_config_get_phy_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2SasPhyPage0_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -1413,7 +1387,6 @@ mpt2sas_config_get_phy_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -1435,7 +1408,6 @@ mpt2sas_config_get_phy_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2SasPhyPage1_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -1481,7 +1453,6 @@ mpt2sas_config_get_phy_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -1505,7 +1476,6 @@ mpt2sas_config_get_raid_volume_pg1(struct MPT2SAS_ADAPTER *ioc, int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2RaidVolPage1_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -1548,7 +1518,6 @@ mpt2sas_config_get_raid_volume_pg1(struct MPT2SAS_ADAPTER *ioc, _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -1572,7 +1541,6 @@ mpt2sas_config_get_number_pds(struct MPT2SAS_ADAPTER *ioc, u16 handle, struct config_request mem; u16 ioc_status; - mutex_lock(&ioc->config_cmds.mutex); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); *num_pds = 0; mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -1620,7 +1588,6 @@ mpt2sas_config_get_number_pds(struct MPT2SAS_ADAPTER *ioc, u16 handle, _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -1645,7 +1612,6 @@ mpt2sas_config_get_raid_volume_pg0(struct MPT2SAS_ADAPTER *ioc, int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); memset(config_page, 0, sz); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -1687,7 +1653,6 @@ mpt2sas_config_get_raid_volume_pg0(struct MPT2SAS_ADAPTER *ioc, _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -1711,7 +1676,6 @@ mpt2sas_config_get_phys_disk_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); memset(config_page, 0, sizeof(Mpi2RaidPhysDiskPage0_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -1754,7 +1718,6 @@ mpt2sas_config_get_phys_disk_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -1778,7 +1741,6 @@ mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle, struct config_request mem; u16 ioc_status; - mutex_lock(&ioc->config_cmds.mutex); *volume_handle = 0; memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -1842,7 +1804,6 @@ mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle, _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 2a01a5f2a84..2e9a4445596 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -2767,6 +2767,10 @@ _scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, char *desc_ioc_state = NULL; char *desc_scsi_status = NULL; char *desc_scsi_state = ioc->tmp_string; + u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo); + + if (log_info == 0x31170000) + return; switch (ioc_status) { case MPI2_IOCSTATUS_SUCCESS: @@ -3426,7 +3430,7 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle) __le64 sas_address; int i; unsigned long flags; - struct _sas_port *mpt2sas_port; + struct _sas_port *mpt2sas_port = NULL; int rc = 0; if (!handle) @@ -3518,12 +3522,20 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle) &expander_pg1, i, handle))) { printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__, __func__); - continue; + rc = -1; + goto out_fail; } sas_expander->phy[i].handle = handle; sas_expander->phy[i].phy_id = i; - mpt2sas_transport_add_expander_phy(ioc, &sas_expander->phy[i], - expander_pg1, sas_expander->parent_dev); + + if ((mpt2sas_transport_add_expander_phy(ioc, + &sas_expander->phy[i], expander_pg1, + sas_expander->parent_dev))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + rc = -1; + goto out_fail; + } } if (sas_expander->enclosure_handle) { @@ -3540,8 +3552,9 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle) out_fail: - if (sas_expander) - kfree(sas_expander->phy); + if (mpt2sas_port) + mpt2sas_transport_port_remove(ioc, sas_expander->sas_address, + sas_expander->parent_handle); kfree(sas_expander); return rc; } @@ -3663,12 +3676,11 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd) sas_device->hidden_raid_component = is_pd; /* get enclosure_logical_id */ - if (!(mpt2sas_config_get_enclosure_pg0(ioc, &mpi_reply, &enclosure_pg0, - MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE, - sas_device->enclosure_handle))) { + if (sas_device->enclosure_handle && !(mpt2sas_config_get_enclosure_pg0( + ioc, &mpi_reply, &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE, + sas_device->enclosure_handle))) sas_device->enclosure_logical_id = le64_to_cpu(enclosure_pg0.EnclosureLogicalID); - } /* get device name */ sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName); @@ -4250,12 +4262,6 @@ _scsih_sas_volume_add(struct MPT2SAS_ADAPTER *ioc, u16 handle = le16_to_cpu(element->VolDevHandle); int rc; -#if 0 /* RAID_HACKS */ - if (le32_to_cpu(event_data->Flags) & - MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) - return; -#endif - mpt2sas_config_get_volume_wwid(ioc, handle, &wwid); if (!wwid) { printk(MPT2SAS_ERR_FMT @@ -4310,12 +4316,6 @@ _scsih_sas_volume_delete(struct MPT2SAS_ADAPTER *ioc, unsigned long flags; struct MPT2SAS_TARGET *sas_target_priv_data; -#if 0 /* RAID_HACKS */ - if (le32_to_cpu(event_data->Flags) & - MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) - return; -#endif - spin_lock_irqsave(&ioc->raid_device_lock, flags); raid_device = _scsih_raid_device_find_by_handle(ioc, handle); spin_unlock_irqrestore(&ioc->raid_device_lock, flags); @@ -4428,14 +4428,38 @@ _scsih_sas_pd_add(struct MPT2SAS_ADAPTER *ioc, struct _sas_device *sas_device; unsigned long flags; u16 handle = le16_to_cpu(element->PhysDiskDevHandle); + Mpi2ConfigReply_t mpi_reply; + Mpi2SasDevicePage0_t sas_device_pg0; + u32 ioc_status; spin_lock_irqsave(&ioc->sas_device_lock, flags); sas_device = _scsih_sas_device_find_by_handle(ioc, handle); spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - if (sas_device) + if (sas_device) { sas_device->hidden_raid_component = 1; - else - _scsih_add_device(ioc, handle, 0, 1); + return; + } + + if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, + MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return; + } + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return; + } + + _scsih_link_change(ioc, + le16_to_cpu(sas_device_pg0.ParentDevHandle), + handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); + + _scsih_add_device(ioc, handle, 0, 1); } #ifdef CONFIG_SCSI_MPT2SAS_LOGGING @@ -4535,12 +4559,15 @@ _scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, { Mpi2EventIrConfigElement_t *element; int i; + u8 foreign_config; #ifdef CONFIG_SCSI_MPT2SAS_LOGGING if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) _scsih_sas_ir_config_change_event_debug(ioc, event_data); #endif + foreign_config = (le32_to_cpu(event_data->Flags) & + MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0; element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; for (i = 0; i < event_data->NumElements; i++, element++) { @@ -4548,11 +4575,13 @@ _scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, switch (element->ReasonCode) { case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED: case MPI2_EVENT_IR_CHANGE_RC_ADDED: - _scsih_sas_volume_add(ioc, element); + if (!foreign_config) + _scsih_sas_volume_add(ioc, element); break; case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED: case MPI2_EVENT_IR_CHANGE_RC_REMOVED: - _scsih_sas_volume_delete(ioc, element); + if (!foreign_config) + _scsih_sas_volume_delete(ioc, element); break; case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED: _scsih_sas_pd_hide(ioc, element); @@ -4671,6 +4700,9 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 state; struct _sas_device *sas_device; unsigned long flags; + Mpi2ConfigReply_t mpi_reply; + Mpi2SasDevicePage0_t sas_device_pg0; + u32 ioc_status; if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED) return; @@ -4687,22 +4719,40 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, spin_unlock_irqrestore(&ioc->sas_device_lock, flags); switch (state) { -#if 0 - case MPI2_RAID_PD_STATE_OFFLINE: - if (sas_device) - _scsih_remove_device(ioc, handle); - break; -#endif case MPI2_RAID_PD_STATE_ONLINE: case MPI2_RAID_PD_STATE_DEGRADED: case MPI2_RAID_PD_STATE_REBUILDING: case MPI2_RAID_PD_STATE_OPTIMAL: - if (sas_device) + if (sas_device) { sas_device->hidden_raid_component = 1; - else - _scsih_add_device(ioc, handle, 0, 1); + return; + } + + if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, + &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, + handle))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return; + } + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return; + } + + _scsih_link_change(ioc, + le16_to_cpu(sas_device_pg0.ParentDevHandle), + handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); + + _scsih_add_device(ioc, handle, 0, 1); + break; + case MPI2_RAID_PD_STATE_OFFLINE: case MPI2_RAID_PD_STATE_NOT_CONFIGURED: case MPI2_RAID_PD_STATE_NOT_COMPATIBLE: case MPI2_RAID_PD_STATE_HOT_SPARE: @@ -5774,6 +5824,7 @@ _scsih_suspend(struct pci_dev *pdev, pm_message_t state) struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); u32 device_state; + mpt2sas_base_stop_watchdog(ioc); flush_scheduled_work(); scsi_block_requests(shost); device_state = pci_choose_state(pdev, state); @@ -5816,6 +5867,7 @@ _scsih_resume(struct pci_dev *pdev) mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, SOFT_RESET); scsi_unblock_requests(shost); + mpt2sas_base_start_watchdog(ioc); return 0; } #endif /* CONFIG_PM */ diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index 0a69672097a..4e83c297ec9 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c @@ -953,7 +953,12 @@ void thermal_zone_device_update(struct thermal_zone_device *tz) mutex_lock(&tz->lock); - tz->ops->get_temp(tz, &temp); + if (tz->ops->get_temp(tz, &temp)) { + /* get_temp failed - retry it later */ + printk(KERN_WARNING PREFIX "failed to read out thermal zone " + "%d\n", tz->id); + goto leave; + } for (count = 0; count < tz->trips; count++) { tz->ops->get_trip_type(tz, count, &trip_type); @@ -1005,6 +1010,8 @@ void thermal_zone_device_update(struct thermal_zone_device *tz) THERMAL_TRIPS_NONE); tz->last_temperature = temp; + + leave: if (tz->passive) thermal_zone_device_set_polling(tz, tz->passive_delay); else if (tz->polling_delay) diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c index 3fe9742c23c..2f8643efe92 100644 --- a/drivers/watchdog/ar7_wdt.c +++ b/drivers/watchdog/ar7_wdt.c @@ -37,7 +37,7 @@ #include <linux/uaccess.h> #include <asm/addrspace.h> -#include <asm/ar7/ar7.h> +#include <asm/mach-ar7/ar7.h> #define DRVNAME "ar7_wdt" #define LONGNAME "TI AR7 Watchdog Timer" |