diff options
Diffstat (limited to 'drivers')
100 files changed, 1202 insertions, 671 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index cdd01c52c629..5e6e00bc1652 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1912,8 +1912,8 @@ int __dev_printk(const char *level, const struct device *dev, "DEVICE=+%s:%s", subsys, dev_name(dev)); } skip: - if (level[3]) - level_extra = &level[3]; /* skip past "<L>" */ + if (level[2]) + level_extra = &level[2]; /* skip past KERN_SOH "L" */ return printk_emit(0, level[1] - '0', dictlen ? dict : NULL, dictlen, diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 59894873a3b3..7d9c1cb1c39a 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -147,6 +147,8 @@ static int rpm_check_suspend_allowed(struct device *dev) || (dev->power.request_pending && dev->power.request == RPM_REQ_RESUME)) retval = -EAGAIN; + else if (__dev_pm_qos_read_value(dev) < 0) + retval = -EPERM; else if (dev->power.runtime_status == RPM_SUSPENDED) retval = 1; @@ -388,7 +390,6 @@ static int rpm_suspend(struct device *dev, int rpmflags) goto repeat; } - dev->power.deferred_resume = false; if (dev->power.no_callbacks) goto no_callback; /* Assume success. */ @@ -403,12 +404,6 @@ static int rpm_suspend(struct device *dev, int rpmflags) goto out; } - if (__dev_pm_qos_read_value(dev) < 0) { - /* Negative PM QoS constraint means "never suspend". */ - retval = -EPERM; - goto out; - } - __update_runtime_status(dev, RPM_SUSPENDING); if (dev->pm_domain) @@ -440,6 +435,7 @@ static int rpm_suspend(struct device *dev, int rpmflags) wake_up_all(&dev->power.wait_queue); if (dev->power.deferred_resume) { + dev->power.deferred_resume = false; rpm_resume(dev, 0); retval = -EAGAIN; goto out; @@ -584,6 +580,7 @@ static int rpm_resume(struct device *dev, int rpmflags) || dev->parent->power.runtime_status == RPM_ACTIVE) { atomic_inc(&dev->parent->power.child_count); spin_unlock(&dev->parent->power.lock); + retval = 1; goto no_callback; /* Assume success. */ } spin_unlock(&dev->parent->power.lock); @@ -664,7 +661,7 @@ static int rpm_resume(struct device *dev, int rpmflags) } wake_up_all(&dev->power.wait_queue); - if (!retval) + if (retval >= 0) rpm_idle(dev, RPM_ASYNC); out: diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index acda773b3720..38aa6dda6b81 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -763,16 +763,7 @@ static void complete_scsi_command(CommandList_struct *c, int timeout, { case CMD_TARGET_STATUS: /* Pass it up to the upper layers... */ - if( ei->ScsiStatus) - { -#if 0 - printk(KERN_WARNING "cciss: cmd %p " - "has SCSI Status = %x\n", - c, ei->ScsiStatus); -#endif - cmd->result |= (ei->ScsiStatus << 1); - } - else { /* scsi status is zero??? How??? */ + if (!ei->ScsiStatus) { /* Ordinarily, this case should never happen, but there is a bug in some released firmware revisions that allows it to happen diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 10308cd8a7ed..11f36e502136 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -79,6 +79,7 @@ static struct usb_device_id ath3k_table[] = { { USB_DEVICE(0x13d3, 0x3362) }, { USB_DEVICE(0x0CF3, 0xE004) }, { USB_DEVICE(0x0930, 0x0219) }, + { USB_DEVICE(0x0489, 0xe057) }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xE02C) }, @@ -104,6 +105,7 @@ static struct usb_device_id ath3k_blist_tbl[] = { { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, /* Atheros AR5BBU22 with sflash firmware */ { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index e27221411036..cef3bac1a543 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -98,6 +98,7 @@ static struct usb_device_id btusb_table[] = { { USB_DEVICE(0x0a5c, 0x21e6) }, { USB_DEVICE(0x0a5c, 0x21e8) }, { USB_DEVICE(0x0a5c, 0x21f3) }, + { USB_DEVICE(0x0a5c, 0x21f4) }, { USB_DEVICE(0x413c, 0x8197) }, /* Foxconn - Hon Hai */ @@ -133,6 +134,7 @@ static struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, diff --git a/drivers/clocksource/cs5535-clockevt.c b/drivers/clocksource/cs5535-clockevt.c index 540795cd0760..d9279385304d 100644 --- a/drivers/clocksource/cs5535-clockevt.c +++ b/drivers/clocksource/cs5535-clockevt.c @@ -53,7 +53,7 @@ static struct cs5535_mfgpt_timer *cs5535_event_clock; #define MFGPT_PERIODIC (MFGPT_HZ / HZ) /* - * The MFPGT timers on the CS5536 provide us with suitable timers to use + * The MFGPT timers on the CS5536 provide us with suitable timers to use * as clock event sources - not as good as a HPET or APIC, but certainly * better than the PIT. This isn't a general purpose MFGPT driver, but * a simplified one designed specifically to act as a clock event source. @@ -144,7 +144,7 @@ static int __init cs5535_mfgpt_init(void) timer = cs5535_mfgpt_alloc_timer(MFGPT_TIMER_ANY, MFGPT_DOMAIN_WORKING); if (!timer) { - printk(KERN_ERR DRV_NAME ": Could not allocate MFPGT timer\n"); + printk(KERN_ERR DRV_NAME ": Could not allocate MFGPT timer\n"); return -ENODEV; } cs5535_event_clock = timer; diff --git a/drivers/cpuidle/coupled.c b/drivers/cpuidle/coupled.c index 2c9bf2692232..3265844839bf 100644 --- a/drivers/cpuidle/coupled.c +++ b/drivers/cpuidle/coupled.c @@ -678,10 +678,22 @@ static int cpuidle_coupled_cpu_notify(struct notifier_block *nb, int cpu = (unsigned long)hcpu; struct cpuidle_device *dev; + switch (action & ~CPU_TASKS_FROZEN) { + case CPU_UP_PREPARE: + case CPU_DOWN_PREPARE: + case CPU_ONLINE: + case CPU_DEAD: + case CPU_UP_CANCELED: + case CPU_DOWN_FAILED: + break; + default: + return NOTIFY_OK; + } + mutex_lock(&cpuidle_lock); dev = per_cpu(cpuidle_devices, cpu); - if (!dev->coupled) + if (!dev || !dev->coupled) goto out; switch (action & ~CPU_TASKS_FROZEN) { diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 23120c00a881..90e28081712d 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -22,6 +22,7 @@ menuconfig DRM config DRM_USB tristate depends on DRM + depends on USB_ARCH_HAS_HCD select USB config DRM_KMS_HELPER diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index fc841e87b343..26ebffebe710 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -211,11 +211,6 @@ static int nouveau_dsm_power_state(enum vga_switcheroo_client_id id, return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dhandle, state); } -static int nouveau_dsm_init(void) -{ - return 0; -} - static int nouveau_dsm_get_client_id(struct pci_dev *pdev) { /* easy option one - intel vendor ID means Integrated */ @@ -232,7 +227,6 @@ static int nouveau_dsm_get_client_id(struct pci_dev *pdev) static struct vga_switcheroo_handler nouveau_dsm_handler = { .switchto = nouveau_dsm_switchto, .power_state = nouveau_dsm_power_state, - .init = nouveau_dsm_init, .get_client_id = nouveau_dsm_get_client_id, }; diff --git a/drivers/gpu/drm/udl/Kconfig b/drivers/gpu/drm/udl/Kconfig index 0b5e096d39a6..56e0bf31d425 100644 --- a/drivers/gpu/drm/udl/Kconfig +++ b/drivers/gpu/drm/udl/Kconfig @@ -1,6 +1,7 @@ config DRM_UDL tristate "DisplayLink" depends on DRM && EXPERIMENTAL + depends on USB_ARCH_HAS_HCD select DRM_USB select FB_SYS_FILLRECT select FB_SYS_COPYAREA diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c index 5b3c7d135dc9..e25cf31faab2 100644 --- a/drivers/gpu/vga/vga_switcheroo.c +++ b/drivers/gpu/vga/vga_switcheroo.c @@ -70,27 +70,12 @@ static struct vgasr_priv vgasr_priv = { .clients = LIST_HEAD_INIT(vgasr_priv.clients), }; -int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler) -{ - mutex_lock(&vgasr_mutex); - if (vgasr_priv.handler) { - mutex_unlock(&vgasr_mutex); - return -EINVAL; - } - - vgasr_priv.handler = handler; - mutex_unlock(&vgasr_mutex); - return 0; -} -EXPORT_SYMBOL(vga_switcheroo_register_handler); - -void vga_switcheroo_unregister_handler(void) +static bool vga_switcheroo_ready(void) { - mutex_lock(&vgasr_mutex); - vgasr_priv.handler = NULL; - mutex_unlock(&vgasr_mutex); + /* we're ready if we get two clients + handler */ + return !vgasr_priv.active && + vgasr_priv.registered_clients == 2 && vgasr_priv.handler; } -EXPORT_SYMBOL(vga_switcheroo_unregister_handler); static void vga_switcheroo_enable(void) { @@ -98,7 +83,8 @@ static void vga_switcheroo_enable(void) struct vga_switcheroo_client *client; /* call the handler to init */ - vgasr_priv.handler->init(); + if (vgasr_priv.handler->init) + vgasr_priv.handler->init(); list_for_each_entry(client, &vgasr_priv.clients, list) { if (client->id != -1) @@ -113,6 +99,37 @@ static void vga_switcheroo_enable(void) vgasr_priv.active = true; } +int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler) +{ + mutex_lock(&vgasr_mutex); + if (vgasr_priv.handler) { + mutex_unlock(&vgasr_mutex); + return -EINVAL; + } + + vgasr_priv.handler = handler; + if (vga_switcheroo_ready()) { + printk(KERN_INFO "vga_switcheroo: enabled\n"); + vga_switcheroo_enable(); + } + mutex_unlock(&vgasr_mutex); + return 0; +} +EXPORT_SYMBOL(vga_switcheroo_register_handler); + +void vga_switcheroo_unregister_handler(void) +{ + mutex_lock(&vgasr_mutex); + vgasr_priv.handler = NULL; + if (vgasr_priv.active) { + pr_info("vga_switcheroo: disabled\n"); + vga_switcheroo_debugfs_fini(&vgasr_priv); + vgasr_priv.active = false; + } + mutex_unlock(&vgasr_mutex); +} +EXPORT_SYMBOL(vga_switcheroo_unregister_handler); + static int register_client(struct pci_dev *pdev, const struct vga_switcheroo_client_ops *ops, int id, bool active) @@ -134,9 +151,7 @@ static int register_client(struct pci_dev *pdev, if (client_is_vga(client)) vgasr_priv.registered_clients++; - /* if we get two clients + handler */ - if (!vgasr_priv.active && - vgasr_priv.registered_clients == 2 && vgasr_priv.handler) { + if (vga_switcheroo_ready()) { printk(KERN_INFO "vga_switcheroo: enabled\n"); vga_switcheroo_enable(); } diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index faa16f80db9c..0fa356fe82cc 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -196,7 +196,7 @@ struct tjmax { int tjmax; }; -static struct tjmax __cpuinitconst tjmax_table[] = { +static const struct tjmax __cpuinitconst tjmax_table[] = { { "CPU D410", 100000 }, { "CPU D425", 100000 }, { "CPU D510", 100000 }, diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index ab4825205a9d..5b1a6a666441 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -1206,7 +1206,7 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr, int err = -ENODEV; u16 val; - static const __initdata char *names[] = { + static __initconst char *const names[] = { "W83627HF", "W83627THF", "W83697HF", diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index f559088869f6..e8726177d103 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -606,8 +606,9 @@ static int __init intel_idle_init(void) intel_idle_cpuidle_driver_init(); retval = cpuidle_register_driver(&intel_idle_driver); if (retval) { + struct cpuidle_driver *drv = cpuidle_get_driver(); printk(KERN_DEBUG PREFIX "intel_idle yielding to %s", - cpuidle_get_driver()->name); + drv ? drv->name : "none"); return retval; } diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 0a2ea317120a..18a89b760aaa 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -1111,7 +1111,7 @@ static void print_iommu_info(void) if (iommu->cap & (1 << IOMMU_CAP_EFR)) { pr_info("AMD-Vi: Extended features: "); - for (i = 0; ARRAY_SIZE(feat_str); ++i) { + for (i = 0; i < ARRAY_SIZE(feat_str); ++i) { if (iommu_feature(iommu, (1ULL << i))) pr_cont(" %s", feat_str[i]); } diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index e0b18f3ae9a8..af8904de1d44 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -736,6 +736,7 @@ int __init parse_ioapics_under_ir(void) { struct dmar_drhd_unit *drhd; int ir_supported = 0; + int ioapic_idx; for_each_drhd_unit(drhd) { struct intel_iommu *iommu = drhd->iommu; @@ -748,13 +749,20 @@ int __init parse_ioapics_under_ir(void) } } - if (ir_supported && ir_ioapic_num != nr_ioapics) { - printk(KERN_WARNING - "Not all IO-APIC's listed under remapping hardware\n"); - return -1; + if (!ir_supported) + return 0; + + for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) { + int ioapic_id = mpc_ioapic_id(ioapic_idx); + if (!map_ioapic_to_ir(ioapic_id)) { + pr_err(FW_BUG "ioapic %d has no mapping iommu, " + "interrupt remapping will be disabled\n", + ioapic_id); + return -1; + } } - return ir_supported; + return 1; } int __init ir_dev_scope_init(void) diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c index 664e460f247b..aac622200e99 100644 --- a/drivers/media/dvb/siano/smsusb.c +++ b/drivers/media/dvb/siano/smsusb.c @@ -481,7 +481,7 @@ static int smsusb_resume(struct usb_interface *intf) return 0; } -static const struct usb_device_id smsusb_id_table[] __devinitconst = { +static const struct usb_device_id smsusb_id_table[] = { { USB_DEVICE(0x187f, 0x0010), .driver_info = SMS1XXX_BOARD_SIANO_STELLAR }, { USB_DEVICE(0x187f, 0x0100), diff --git a/drivers/media/radio/radio-shark.c b/drivers/media/radio/radio-shark.c index d0b6bb507634..72ded29728bb 100644 --- a/drivers/media/radio/radio-shark.c +++ b/drivers/media/radio/radio-shark.c @@ -35,6 +35,11 @@ #include <media/v4l2-device.h> #include <sound/tea575x-tuner.h> +#if defined(CONFIG_LEDS_CLASS) || \ + (defined(CONFIG_LEDS_CLASS_MODULE) && defined(CONFIG_RADIO_SHARK_MODULE)) +#define SHARK_USE_LEDS 1 +#endif + /* * Version Information */ @@ -56,44 +61,18 @@ MODULE_LICENSE("GPL"); enum { BLUE_LED, BLUE_PULSE_LED, RED_LED, NO_LEDS }; -static void shark_led_set_blue(struct led_classdev *led_cdev, - enum led_brightness value); -static void shark_led_set_blue_pulse(struct led_classdev *led_cdev, - enum led_brightness value); -static void shark_led_set_red(struct led_classdev *led_cdev, - enum led_brightness value); - -static const struct led_classdev shark_led_templates[NO_LEDS] = { - [BLUE_LED] = { - .name = "%s:blue:", - .brightness = LED_OFF, - .max_brightness = 127, - .brightness_set = shark_led_set_blue, - }, - [BLUE_PULSE_LED] = { - .name = "%s:blue-pulse:", - .brightness = LED_OFF, - .max_brightness = 255, - .brightness_set = shark_led_set_blue_pulse, - }, - [RED_LED] = { - .name = "%s:red:", - .brightness = LED_OFF, - .max_brightness = 1, - .brightness_set = shark_led_set_red, - }, -}; - struct shark_device { struct usb_device *usbdev; struct v4l2_device v4l2_dev; struct snd_tea575x tea; +#ifdef SHARK_USE_LEDS struct work_struct led_work; struct led_classdev leds[NO_LEDS]; char led_names[NO_LEDS][32]; atomic_t brightness[NO_LEDS]; unsigned long brightness_new; +#endif u8 *transfer_buffer; u32 last_val; @@ -175,20 +154,13 @@ static struct snd_tea575x_ops shark_tea_ops = { .read_val = shark_read_val, }; +#ifdef SHARK_USE_LEDS static void shark_led_work(struct work_struct *work) { struct shark_device *shark = container_of(work, struct shark_device, led_work); int i, res, brightness, actual_len; - /* - * We use the v4l2_dev lock and registered bit to ensure the device - * does not get unplugged and unreffed while we're running. - */ - mutex_lock(&shark->tea.mutex); - if (!video_is_registered(&shark->tea.vd)) - goto leave; - for (i = 0; i < 3; i++) { if (!test_and_clear_bit(i, &shark->brightness_new)) continue; @@ -208,8 +180,6 @@ static void shark_led_work(struct work_struct *work) v4l2_err(&shark->v4l2_dev, "set LED %s error: %d\n", shark->led_names[i], res); } -leave: - mutex_unlock(&shark->tea.mutex); } static void shark_led_set_blue(struct led_classdev *led_cdev, @@ -245,19 +215,78 @@ static void shark_led_set_red(struct led_classdev *led_cdev, schedule_work(&shark->led_work); } +static const struct led_classdev shark_led_templates[NO_LEDS] = { + [BLUE_LED] = { + .name = "%s:blue:", + .brightness = LED_OFF, + .max_brightness = 127, + .brightness_set = shark_led_set_blue, + }, + [BLUE_PULSE_LED] = { + .name = "%s:blue-pulse:", + .brightness = LED_OFF, + .max_brightness = 255, + .brightness_set = shark_led_set_blue_pulse, + }, + [RED_LED] = { + .name = "%s:red:", + .brightness = LED_OFF, + .max_brightness = 1, + .brightness_set = shark_led_set_red, + }, +}; + +static int shark_register_leds(struct shark_device *shark, struct device *dev) +{ + int i, retval; + + INIT_WORK(&shark->led_work, shark_led_work); + for (i = 0; i < NO_LEDS; i++) { + shark->leds[i] = shark_led_templates[i]; + snprintf(shark->led_names[i], sizeof(shark->led_names[0]), + shark->leds[i].name, shark->v4l2_dev.name); + shark->leds[i].name = shark->led_names[i]; + retval = led_classdev_register(dev, &shark->leds[i]); + if (retval) { + v4l2_err(&shark->v4l2_dev, + "couldn't register led: %s\n", + shark->led_names[i]); + return retval; + } + } + return 0; +} + +static void shark_unregister_leds(struct shark_device *shark) +{ + int i; + + for (i = 0; i < NO_LEDS; i++) + led_classdev_unregister(&shark->leds[i]); + + cancel_work_sync(&shark->led_work); +} +#else +static int shark_register_leds(struct shark_device *shark, struct device *dev) +{ + v4l2_warn(&shark->v4l2_dev, + "CONFIG_LED_CLASS not enabled, LED support disabled\n"); + return 0; +} +static inline void shark_unregister_leds(struct shark_device *shark) { } +#endif + static void usb_shark_disconnect(struct usb_interface *intf) { struct v4l2_device *v4l2_dev = usb_get_intfdata(intf); struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev); - int i; mutex_lock(&shark->tea.mutex); v4l2_device_disconnect(&shark->v4l2_dev); snd_tea575x_exit(&shark->tea); mutex_unlock(&shark->tea.mutex); - for (i = 0; i < NO_LEDS; i++) - led_classdev_unregister(&shark->leds[i]); + shark_unregister_leds(shark); v4l2_device_put(&shark->v4l2_dev); } @@ -266,7 +295,6 @@ static void usb_shark_release(struct v4l2_device *v4l2_dev) { struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev); - cancel_work_sync(&shark->led_work); v4l2_device_unregister(&shark->v4l2_dev); kfree(shark->transfer_buffer); kfree(shark); @@ -276,7 +304,7 @@ static int usb_shark_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct shark_device *shark; - int i, retval = -ENOMEM; + int retval = -ENOMEM; shark = kzalloc(sizeof(struct shark_device), GFP_KERNEL); if (!shark) @@ -286,17 +314,13 @@ static int usb_shark_probe(struct usb_interface *intf, if (!shark->transfer_buffer) goto err_alloc_buffer; - /* - * Work around a bug in usbhid/hid-core.c, where it leaves a dangling - * pointer in intfdata causing v4l2-device.c to not set it. Which - * results in usb_shark_disconnect() referencing the dangling pointer - * - * REMOVE (as soon as the above bug is fixed, patch submitted) - */ - usb_set_intfdata(intf, NULL); + v4l2_device_set_name(&shark->v4l2_dev, DRV_NAME, &shark_instance); + + retval = shark_register_leds(shark, &intf->dev); + if (retval) + goto err_reg_leds; shark->v4l2_dev.release = usb_shark_release; - v4l2_device_set_name(&shark->v4l2_dev, DRV_NAME, &shark_instance); retval = v4l2_device_register(&intf->dev, &shark->v4l2_dev); if (retval) { v4l2_err(&shark->v4l2_dev, "couldn't register v4l2_device\n"); @@ -320,32 +344,13 @@ static int usb_shark_probe(struct usb_interface *intf, goto err_init_tea; } - INIT_WORK(&shark->led_work, shark_led_work); - for (i = 0; i < NO_LEDS; i++) { - shark->leds[i] = shark_led_templates[i]; - snprintf(shark->led_names[i], sizeof(shark->led_names[0]), - shark->leds[i].name, shark->v4l2_dev.name); - shark->leds[i].name = shark->led_names[i]; - /* - * We don't fail the probe if we fail to register the leds, - * because once we've called snd_tea575x_init, the /dev/radio0 - * node may be opened from userspace holding a reference to us! - * - * Note we cannot register the leds first instead as - * shark_led_work depends on the v4l2 mutex and registered bit. - */ - retval = led_classdev_register(&intf->dev, &shark->leds[i]); - if (retval) - v4l2_err(&shark->v4l2_dev, - "couldn't register led: %s\n", - shark->led_names[i]); - } - return 0; err_init_tea: v4l2_device_unregister(&shark->v4l2_dev); err_reg_dev: + shark_unregister_leds(shark); +err_reg_leds: kfree(shark->transfer_buffer); err_alloc_buffer: kfree(shark); diff --git a/drivers/media/radio/radio-shark2.c b/drivers/media/radio/radio-shark2.c index b9575de3e7e8..7b4efdfaae28 100644 --- a/drivers/media/radio/radio-shark2.c +++ b/drivers/media/radio/radio-shark2.c @@ -35,6 +35,11 @@ #include <media/v4l2-device.h> #include "radio-tea5777.h" +#if defined(CONFIG_LEDS_CLASS) || \ + (defined(CONFIG_LEDS_CLASS_MODULE) && defined(CONFIG_RADIO_SHARK2_MODULE)) +#define SHARK_USE_LEDS 1 +#endif + MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); MODULE_DESCRIPTION("Griffin radioSHARK2, USB radio receiver driver"); MODULE_LICENSE("GPL"); @@ -43,7 +48,6 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); - #define SHARK_IN_EP 0x83 #define SHARK_OUT_EP 0x05 @@ -54,36 +58,18 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); enum { BLUE_LED, RED_LED, NO_LEDS }; -static void shark_led_set_blue(struct led_classdev *led_cdev, - enum led_brightness value); -static void shark_led_set_red(struct led_classdev *led_cdev, - enum led_brightness value); - -static const struct led_classdev shark_led_templates[NO_LEDS] = { - [BLUE_LED] = { - .name = "%s:blue:", - .brightness = LED_OFF, - .max_brightness = 127, - .brightness_set = shark_led_set_blue, - }, - [RED_LED] = { - .name = "%s:red:", - .brightness = LED_OFF, - .max_brightness = 1, - .brightness_set = shark_led_set_red, - }, -}; - struct shark_device { struct usb_device *usbdev; struct v4l2_device v4l2_dev; struct radio_tea5777 tea; +#ifdef SHARK_USE_LEDS struct work_struct led_work; struct led_classdev leds[NO_LEDS]; char led_names[NO_LEDS][32]; atomic_t brightness[NO_LEDS]; unsigned long brightness_new; +#endif u8 *transfer_buffer; }; @@ -161,18 +147,12 @@ static struct radio_tea5777_ops shark_tea_ops = { .read_reg = shark_read_reg, }; +#ifdef SHARK_USE_LEDS static void shark_led_work(struct work_struct *work) { struct shark_device *shark = container_of(work, struct shark_device, led_work); int i, res, brightness, actual_len; - /* - * We use the v4l2_dev lock and registered bit to ensure the device - * does not get unplugged and unreffed while we're running. - */ - mutex_lock(&shark->tea.mutex); - if (!video_is_registered(&shark->tea.vd)) - goto leave; for (i = 0; i < 2; i++) { if (!test_and_clear_bit(i, &shark->brightness_new)) @@ -191,8 +171,6 @@ static void shark_led_work(struct work_struct *work) v4l2_err(&shark->v4l2_dev, "set LED %s error: %d\n", shark->led_names[i], res); } -leave: - mutex_unlock(&shark->tea.mutex); } static void shark_led_set_blue(struct led_classdev *led_cdev, @@ -217,19 +195,72 @@ static void shark_led_set_red(struct led_classdev *led_cdev, schedule_work(&shark->led_work); } +static const struct led_classdev shark_led_templates[NO_LEDS] = { + [BLUE_LED] = { + .name = "%s:blue:", + .brightness = LED_OFF, + .max_brightness = 127, + .brightness_set = shark_led_set_blue, + }, + [RED_LED] = { + .name = "%s:red:", + .brightness = LED_OFF, + .max_brightness = 1, + .brightness_set = shark_led_set_red, + }, +}; + +static int shark_register_leds(struct shark_device *shark, struct device *dev) +{ + int i, retval; + + INIT_WORK(&shark->led_work, shark_led_work); + for (i = 0; i < NO_LEDS; i++) { + shark->leds[i] = shark_led_templates[i]; + snprintf(shark->led_names[i], sizeof(shark->led_names[0]), + shark->leds[i].name, shark->v4l2_dev.name); + shark->leds[i].name = shark->led_names[i]; + retval = led_classdev_register(dev, &shark->leds[i]); + if (retval) { + v4l2_err(&shark->v4l2_dev, + "couldn't register led: %s\n", + shark->led_names[i]); + return retval; + } + } + return 0; +} + +static void shark_unregister_leds(struct shark_device *shark) +{ + int i; + + for (i = 0; i < NO_LEDS; i++) + led_classdev_unregister(&shark->leds[i]); + + cancel_work_sync(&shark->led_work); +} +#else +static int shark_register_leds(struct shark_device *shark, struct device *dev) +{ + v4l2_warn(&shark->v4l2_dev, + "CONFIG_LED_CLASS not enabled, LED support disabled\n"); + return 0; +} +static inline void shark_unregister_leds(struct shark_device *shark) { } +#endif + static void usb_shark_disconnect(struct usb_interface *intf) { struct v4l2_device *v4l2_dev = usb_get_intfdata(intf); struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev); - int i; mutex_lock(&shark->tea.mutex); v4l2_device_disconnect(&shark->v4l2_dev); radio_tea5777_exit(&shark->tea); mutex_unlock(&shark->tea.mutex); - for (i = 0; i < NO_LEDS; i++) - led_classdev_unregister(&shark->leds[i]); + shark_unregister_leds(shark); v4l2_device_put(&shark->v4l2_dev); } @@ -238,7 +269,6 @@ static void usb_shark_release(struct v4l2_device *v4l2_dev) { struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev); - cancel_work_sync(&shark->led_work); v4l2_device_unregister(&shark->v4l2_dev); kfree(shark->transfer_buffer); kfree(shark); @@ -248,7 +278,7 @@ static int usb_shark_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct shark_device *shark; - int i, retval = -ENOMEM; + int retval = -ENOMEM; shark = kzalloc(sizeof(struct shark_device), GFP_KERNEL); if (!shark) @@ -258,17 +288,13 @@ static int usb_shark_probe(struct usb_interface *intf, if (!shark->transfer_buffer) goto err_alloc_buffer; - /* - * Work around a bug in usbhid/hid-core.c, where it leaves a dangling - * pointer in intfdata causing v4l2-device.c to not set it. Which - * results in usb_shark_disconnect() referencing the dangling pointer - * - * REMOVE (as soon as the above bug is fixed, patch submitted) - */ - usb_set_intfdata(intf, NULL); + v4l2_device_set_name(&shark->v4l2_dev, DRV_NAME, &shark_instance); + + retval = shark_register_leds(shark, &intf->dev); + if (retval) + goto err_reg_leds; shark->v4l2_dev.release = usb_shark_release; - v4l2_device_set_name(&shark->v4l2_dev, DRV_NAME, &shark_instance); retval = v4l2_device_register(&intf->dev, &shark->v4l2_dev); if (retval) { v4l2_err(&shark->v4l2_dev, "couldn't register v4l2_device\n"); @@ -292,32 +318,13 @@ static int usb_shark_probe(struct usb_interface *intf, goto err_init_tea; } - INIT_WORK(&shark->led_work, shark_led_work); - for (i = 0; i < NO_LEDS; i++) { - shark->leds[i] = shark_led_templates[i]; - snprintf(shark->led_names[i], sizeof(shark->led_names[0]), - shark->leds[i].name, shark->v4l2_dev.name); - shark->leds[i].name = shark->led_names[i]; - /* - * We don't fail the probe if we fail to register the leds, - * because once we've called radio_tea5777_init, the /dev/radio0 - * node may be opened from userspace holding a reference to us! - * - * Note we cannot register the leds first instead as - * shark_led_work depends on the v4l2 mutex and registered bit. - */ - retval = led_classdev_register(&intf->dev, &shark->leds[i]); - if (retval) - v4l2_err(&shark->v4l2_dev, - "couldn't register led: %s\n", - shark->led_names[i]); - } - return 0; err_init_tea: v4l2_device_unregister(&shark->v4l2_dev); err_reg_dev: + shark_unregister_leds(shark); +err_reg_leds: kfree(shark->transfer_buffer); err_alloc_buffer: kfree(shark); diff --git a/drivers/media/radio/si470x/radio-si470x-common.c b/drivers/media/radio/si470x/radio-si470x-common.c index 9e38132afec6..9bb65e170d99 100644 --- a/drivers/media/radio/si470x/radio-si470x-common.c +++ b/drivers/media/radio/si470x/radio-si470x-common.c @@ -151,6 +151,7 @@ static const struct v4l2_frequency_band bands[] = { .index = 0, .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO | + V4L2_TUNER_CAP_FREQ_BANDS | V4L2_TUNER_CAP_HWSEEK_BOUNDED | V4L2_TUNER_CAP_HWSEEK_WRAP, .rangelow = 87500 * 16, @@ -162,6 +163,7 @@ static const struct v4l2_frequency_band bands[] = { .index = 1, .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO | + V4L2_TUNER_CAP_FREQ_BANDS | V4L2_TUNER_CAP_HWSEEK_BOUNDED | V4L2_TUNER_CAP_HWSEEK_WRAP, .rangelow = 76000 * 16, @@ -173,6 +175,7 @@ static const struct v4l2_frequency_band bands[] = { .index = 2, .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO | + V4L2_TUNER_CAP_FREQ_BANDS | V4L2_TUNER_CAP_HWSEEK_BOUNDED | V4L2_TUNER_CAP_HWSEEK_WRAP, .rangelow = 76000 * 16, diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index 643a6ff7c5d0..f867f04cccc9 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -225,8 +225,9 @@ int si470x_vidioc_querycap(struct file *file, void *priv, { strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver)); strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card)); - capability->capabilities = V4L2_CAP_HW_FREQ_SEEK | - V4L2_CAP_TUNER | V4L2_CAP_RADIO; + capability->device_caps = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_READWRITE | + V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE; + capability->capabilities = capability->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c index 146be4263ea1..be076f7181e7 100644 --- a/drivers/media/radio/si470x/radio-si470x-usb.c +++ b/drivers/media/radio/si470x/radio-si470x-usb.c @@ -531,7 +531,7 @@ int si470x_vidioc_querycap(struct file *file, void *priv, strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card)); usb_make_path(radio->usbdev, capability->bus_info, sizeof(capability->bus_info)); - capability->device_caps = V4L2_CAP_HW_FREQ_SEEK | + capability->device_caps = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_READWRITE | V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE; capability->capabilities = capability->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 5180390be7ab..8be57634ba60 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -261,6 +261,7 @@ config IR_WINBOND_CIR config IR_IGUANA tristate "IguanaWorks USB IR Transceiver" + depends on USB_ARCH_HAS_HCD depends on RC_CORE select USB ---help--- diff --git a/drivers/media/video/gspca/jl2005bcd.c b/drivers/media/video/gspca/jl2005bcd.c index cf9d9fca5b84..234777116e5f 100644 --- a/drivers/media/video/gspca/jl2005bcd.c +++ b/drivers/media/video/gspca/jl2005bcd.c @@ -512,7 +512,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x0979, 0x0227)}, {} }; diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c index 969bb5a4cd93..bab01c86c315 100644 --- a/drivers/media/video/gspca/spca506.c +++ b/drivers/media/video/gspca/spca506.c @@ -579,7 +579,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const struct usb_device_id device_table[] __devinitconst = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x06e1, 0xa190)}, /*fixme: may be IntelPCCameraPro BRIDGE_SPCA505 {USB_DEVICE(0x0733, 0x0430)}, */ diff --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/video/mem2mem_testdev.c index 7efe9ad7acc7..0b91a5cd38eb 100644 --- a/drivers/media/video/mem2mem_testdev.c +++ b/drivers/media/video/mem2mem_testdev.c @@ -431,7 +431,7 @@ static int vidioc_querycap(struct file *file, void *priv, strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1); strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1); strlcpy(cap->bus_info, MEM2MEM_NAME, sizeof(cap->bus_info)); - cap->capabilities = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; + cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } diff --git a/drivers/media/video/mx1_camera.c b/drivers/media/video/mx1_camera.c index d2e6f82ecfac..560a65aa7038 100644 --- a/drivers/media/video/mx1_camera.c +++ b/drivers/media/video/mx1_camera.c @@ -403,7 +403,7 @@ static void mx1_camera_activate(struct mx1_camera_dev *pcdev) dev_dbg(pcdev->icd->parent, "Activate device\n"); - clk_enable(pcdev->clk); + clk_prepare_enable(pcdev->clk); /* enable CSI before doing anything else */ __raw_writel(csicr1, pcdev->base + CSICR1); @@ -422,7 +422,7 @@ static void mx1_camera_deactivate(struct mx1_camera_dev *pcdev) /* Disable all CSI interface */ __raw_writel(0x00, pcdev->base + CSICR1); - clk_disable(pcdev->clk); + clk_disable_unprepare(pcdev->clk); } /* diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c index 637bde8aca28..ac175406e582 100644 --- a/drivers/media/video/mx2_camera.c +++ b/drivers/media/video/mx2_camera.c @@ -272,7 +272,7 @@ struct mx2_camera_dev { struct device *dev; struct soc_camera_host soc_host; struct soc_camera_device *icd; - struct clk *clk_csi, *clk_emma; + struct clk *clk_csi, *clk_emma_ahb, *clk_emma_ipg; unsigned int irq_csi, irq_emma; void __iomem *base_csi, *base_emma; @@ -407,7 +407,7 @@ static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev) { unsigned long flags; - clk_disable(pcdev->clk_csi); + clk_disable_unprepare(pcdev->clk_csi); writel(0, pcdev->base_csi + CSICR1); if (cpu_is_mx27()) { writel(0, pcdev->base_emma + PRP_CNTL); @@ -435,7 +435,7 @@ static int mx2_camera_add_device(struct soc_camera_device *icd) if (pcdev->icd) return -EBUSY; - ret = clk_enable(pcdev->clk_csi); + ret = clk_prepare_enable(pcdev->clk_csi); if (ret < 0) return ret; @@ -1633,23 +1633,34 @@ static int __devinit mx27_camera_emma_init(struct mx2_camera_dev *pcdev) goto exit_iounmap; } - pcdev->clk_emma = clk_get(NULL, "emma"); - if (IS_ERR(pcdev->clk_emma)) { - err = PTR_ERR(pcdev->clk_emma); + pcdev->clk_emma_ipg = clk_get(pcdev->dev, "emma-ipg"); + if (IS_ERR(pcdev->clk_emma_ipg)) { + err = PTR_ERR(pcdev->clk_emma_ipg); goto exit_free_irq; } - clk_enable(pcdev->clk_emma); + clk_prepare_enable(pcdev->clk_emma_ipg); + + pcdev->clk_emma_ahb = clk_get(pcdev->dev, "emma-ahb"); + if (IS_ERR(pcdev->clk_emma_ahb)) { + err = PTR_ERR(pcdev->clk_emma_ahb); + goto exit_clk_emma_ipg_put; + } + + clk_prepare_enable(pcdev->clk_emma_ahb); err = mx27_camera_emma_prp_reset(pcdev); if (err) - goto exit_clk_emma_put; + goto exit_clk_emma_ahb_put; return err; -exit_clk_emma_put: - clk_disable(pcdev->clk_emma); - clk_put(pcdev->clk_emma); +exit_clk_emma_ahb_put: + clk_disable_unprepare(pcdev->clk_emma_ahb); + clk_put(pcdev->clk_emma_ahb); +exit_clk_emma_ipg_put: + clk_disable_unprepare(pcdev->clk_emma_ipg); + clk_put(pcdev->clk_emma_ipg); exit_free_irq: free_irq(pcdev->irq_emma, pcdev); exit_iounmap: @@ -1685,7 +1696,7 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev) goto exit; } - pcdev->clk_csi = clk_get(&pdev->dev, NULL); + pcdev->clk_csi = clk_get(&pdev->dev, "ahb"); if (IS_ERR(pcdev->clk_csi)) { dev_err(&pdev->dev, "Could not get csi clock\n"); err = PTR_ERR(pcdev->clk_csi); @@ -1785,8 +1796,10 @@ exit_free_emma: eallocctx: if (cpu_is_mx27()) { free_irq(pcdev->irq_emma, pcdev); - clk_disable(pcdev->clk_emma); - clk_put(pcdev->clk_emma); + clk_disable_unprepare(pcdev->clk_emma_ipg); + clk_put(pcdev->clk_emma_ipg); + clk_disable_unprepare(pcdev->clk_emma_ahb); + clk_put(pcdev->clk_emma_ahb); iounmap(pcdev->base_emma); release_mem_region(pcdev->res_emma->start, resource_size(pcdev->res_emma)); } @@ -1825,8 +1838,10 @@ static int __devexit mx2_camera_remove(struct platform_device *pdev) iounmap(pcdev->base_csi); if (cpu_is_mx27()) { - clk_disable(pcdev->clk_emma); - clk_put(pcdev->clk_emma); + clk_disable_unprepare(pcdev->clk_emma_ipg); + clk_put(pcdev->clk_emma_ipg); + clk_disable_unprepare(pcdev->clk_emma_ahb); + clk_put(pcdev->clk_emma_ahb); iounmap(pcdev->base_emma); res = pcdev->res_emma; release_mem_region(res->start, resource_size(res)); diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c index f13643d31353..af2297dd49c8 100644 --- a/drivers/media/video/mx3_camera.c +++ b/drivers/media/video/mx3_camera.c @@ -61,15 +61,9 @@ #define MAX_VIDEO_MEM 16 -enum csi_buffer_state { - CSI_BUF_NEEDS_INIT, - CSI_BUF_PREPARED, -}; - struct mx3_camera_buffer { /* common v4l buffer stuff -- must be first */ struct vb2_buffer vb; - enum csi_buffer_state state; struct list_head queue; /* One descriptot per scatterlist (per frame) */ @@ -285,7 +279,7 @@ static void mx3_videobuf_queue(struct vb2_buffer *vb) goto error; } - if (buf->state == CSI_BUF_NEEDS_INIT) { + if (!buf->txd) { sg_dma_address(sg) = vb2_dma_contig_plane_dma_addr(vb, 0); sg_dma_len(sg) = new_size; @@ -298,7 +292,6 @@ static void mx3_videobuf_queue(struct vb2_buffer *vb) txd->callback_param = txd; txd->callback = mx3_cam_dma_done; - buf->state = CSI_BUF_PREPARED; buf->txd = txd; } else { txd = buf->txd; @@ -385,7 +378,6 @@ static void mx3_videobuf_release(struct vb2_buffer *vb) /* Doesn't hurt also if the list is empty */ list_del_init(&buf->queue); - buf->state = CSI_BUF_NEEDS_INIT; if (txd) { buf->txd = NULL; @@ -405,13 +397,13 @@ static int mx3_videobuf_init(struct vb2_buffer *vb) struct mx3_camera_dev *mx3_cam = ici->priv; struct mx3_camera_buffer *buf = to_mx3_vb(vb); - /* This is for locking debugging only */ - INIT_LIST_HEAD(&buf->queue); - sg_init_table(&buf->sg, 1); + if (!buf->txd) { + /* This is for locking debugging only */ + INIT_LIST_HEAD(&buf->queue); + sg_init_table(&buf->sg, 1); - buf->state = CSI_BUF_NEEDS_INIT; - - mx3_cam->buf_total += vb2_plane_size(vb, 0); + mx3_cam->buf_total += vb2_plane_size(vb, 0); + } return 0; } diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index b03ffecb7438..1bde255e45df 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -171,7 +171,8 @@ static int soc_camera_try_fmt(struct soc_camera_device *icd, dev_dbg(icd->pdev, "TRY_FMT(%c%c%c%c, %ux%u)\n", pixfmtstr(pix->pixelformat), pix->width, pix->height); - if (!(ici->capabilities & SOCAM_HOST_CAP_STRIDE)) { + if (pix->pixelformat != V4L2_PIX_FMT_JPEG && + !(ici->capabilities & SOCAM_HOST_CAP_STRIDE)) { pix->bytesperline = 0; pix->sizeimage = 0; } diff --git a/drivers/media/video/soc_mediabus.c b/drivers/media/video/soc_mediabus.c index 89dce097a827..a397812635d6 100644 --- a/drivers/media/video/soc_mediabus.c +++ b/drivers/media/video/soc_mediabus.c @@ -378,6 +378,9 @@ EXPORT_SYMBOL(soc_mbus_samples_per_pixel); s32 soc_mbus_bytes_per_line(u32 width, const struct soc_mbus_pixelfmt *mf) { + if (mf->fourcc == V4L2_PIX_FMT_JPEG) + return 0; + if (mf->layout != SOC_MBUS_LAYOUT_PACKED) return width * mf->bits_per_sample / 8; @@ -400,6 +403,9 @@ EXPORT_SYMBOL(soc_mbus_bytes_per_line); s32 soc_mbus_image_size(const struct soc_mbus_pixelfmt *mf, u32 bytes_per_line, u32 height) { + if (mf->fourcc == V4L2_PIX_FMT_JPEG) + return 0; + if (mf->layout == SOC_MBUS_LAYOUT_PACKED) return bytes_per_line * height; diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index 9288fbd5001b..5577381b5bf0 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c @@ -338,6 +338,7 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, if ((queue->flags & UVC_QUEUE_DROP_CORRUPTED) && buf->error) { buf->error = 0; buf->state = UVC_BUF_STATE_QUEUED; + buf->bytesused = 0; vb2_set_plane_payload(&buf->buf, 0, 0); return buf; } diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index c3b7b5f59b32..6bc47fc82fe2 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -402,8 +402,10 @@ static void v4l_print_hw_freq_seek(const void *arg, bool write_only) { const struct v4l2_hw_freq_seek *p = arg; - pr_cont("tuner=%u, type=%u, seek_upward=%u, wrap_around=%u, spacing=%u\n", - p->tuner, p->type, p->seek_upward, p->wrap_around, p->spacing); + pr_cont("tuner=%u, type=%u, seek_upward=%u, wrap_around=%u, spacing=%u, " + "rangelow=%u, rangehigh=%u\n", + p->tuner, p->type, p->seek_upward, p->wrap_around, p->spacing, + p->rangelow, p->rangehigh); } static void v4l_print_requestbuffers(const void *arg, bool write_only) @@ -1853,6 +1855,8 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops, .type = type, }; + if (p->index) + return -EINVAL; err = ops->vidioc_g_tuner(file, fh, &t); if (err) return err; @@ -1870,6 +1874,8 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops, if (type != V4L2_TUNER_RADIO) return -EINVAL; + if (p->index) + return -EINVAL; err = ops->vidioc_g_modulator(file, fh, &m); if (err) return err; diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index d1facef28a60..b1a146205c08 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -395,7 +395,8 @@ config MFD_TC6387XB config MFD_TC6393XB bool "Support Toshiba TC6393XB" - depends on GPIOLIB && ARM && HAVE_CLK + depends on ARM && HAVE_CLK + select GPIOLIB select MFD_CORE select MFD_TMIO help diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c index 87b251ab6ec5..b9e2000969f0 100644 --- a/drivers/misc/sgi-xp/xpc_uv.c +++ b/drivers/misc/sgi-xp/xpc_uv.c @@ -18,6 +18,8 @@ #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/device.h> +#include <linux/cpu.h> +#include <linux/module.h> #include <linux/err.h> #include <linux/slab.h> #include <asm/uv/uv_hub.h> @@ -59,6 +61,8 @@ static struct xpc_heartbeat_uv *xpc_heartbeat_uv; XPC_NOTIFY_MSG_SIZE_UV) #define XPC_NOTIFY_IRQ_NAME "xpc_notify" +static int xpc_mq_node = -1; + static struct xpc_gru_mq_uv *xpc_activate_mq_uv; static struct xpc_gru_mq_uv *xpc_notify_mq_uv; @@ -109,11 +113,8 @@ xpc_get_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq, int cpu, char *irq_name) #if defined CONFIG_X86_64 mq->irq = uv_setup_irq(irq_name, cpu, mq->mmr_blade, mq->mmr_offset, UV_AFFINITY_CPU); - if (mq->irq < 0) { - dev_err(xpc_part, "uv_setup_irq() returned error=%d\n", - -mq->irq); + if (mq->irq < 0) return mq->irq; - } mq->mmr_value = uv_read_global_mmr64(mmr_pnode, mq->mmr_offset); @@ -238,8 +239,9 @@ xpc_create_gru_mq_uv(unsigned int mq_size, int cpu, char *irq_name, mq->mmr_blade = uv_cpu_to_blade_id(cpu); nid = cpu_to_node(cpu); - page = alloc_pages_exact_node(nid, GFP_KERNEL | __GFP_ZERO | GFP_THISNODE, - pg_order); + page = alloc_pages_exact_node(nid, + GFP_KERNEL | __GFP_ZERO | GFP_THISNODE, + pg_order); if (page == NULL) { dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to alloc %d " "bytes of memory on nid=%d for GRU mq\n", mq_size, nid); @@ -1731,9 +1733,50 @@ static struct xpc_arch_operations xpc_arch_ops_uv = { .notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_uv, }; +static int +xpc_init_mq_node(int nid) +{ + int cpu; + + get_online_cpus(); + + for_each_cpu(cpu, cpumask_of_node(nid)) { + xpc_activate_mq_uv = + xpc_create_gru_mq_uv(XPC_ACTIVATE_MQ_SIZE_UV, nid, + XPC_ACTIVATE_IRQ_NAME, + xpc_handle_activate_IRQ_uv); + if (!IS_ERR(xpc_activate_mq_uv)) + break; + } + if (IS_ERR(xpc_activate_mq_uv)) { + put_online_cpus(); + return PTR_ERR(xpc_activate_mq_uv); + } + + for_each_cpu(cpu, cpumask_of_node(nid)) { + xpc_notify_mq_uv = + xpc_create_gru_mq_uv(XPC_NOTIFY_MQ_SIZE_UV, nid, + XPC_NOTIFY_IRQ_NAME, + xpc_handle_notify_IRQ_uv); + if (!IS_ERR(xpc_notify_mq_uv)) + break; + } + if (IS_ERR(xpc_notify_mq_uv)) { + xpc_destroy_gru_mq_uv(xpc_activate_mq_uv); + put_online_cpus(); + return PTR_ERR(xpc_notify_mq_uv); + } + + put_online_cpus(); + return 0; +} + int xpc_init_uv(void) { + int nid; + int ret = 0; + xpc_arch_ops = xpc_arch_ops_uv; if (sizeof(struct xpc_notify_mq_msghdr_uv) > XPC_MSG_HDR_MAX_SIZE) { @@ -1742,21 +1785,21 @@ xpc_init_uv(void) return -E2BIG; } - xpc_activate_mq_uv = xpc_create_gru_mq_uv(XPC_ACTIVATE_MQ_SIZE_UV, 0, - XPC_ACTIVATE_IRQ_NAME, - xpc_handle_activate_IRQ_uv); - if (IS_ERR(xpc_activate_mq_uv)) - return PTR_ERR(xpc_activate_mq_uv); + if (xpc_mq_node < 0) + for_each_online_node(nid) { + ret = xpc_init_mq_node(nid); - xpc_notify_mq_uv = xpc_create_gru_mq_uv(XPC_NOTIFY_MQ_SIZE_UV, 0, - XPC_NOTIFY_IRQ_NAME, - xpc_handle_notify_IRQ_uv); - if (IS_ERR(xpc_notify_mq_uv)) { - xpc_destroy_gru_mq_uv(xpc_activate_mq_uv); - return PTR_ERR(xpc_notify_mq_uv); - } + if (!ret) + break; + } + else + ret = xpc_init_mq_node(xpc_mq_node); - return 0; + if (ret < 0) + dev_err(xpc_part, "xpc_init_mq_node() returned error=%d\n", + -ret); + + return ret; } void @@ -1765,3 +1808,6 @@ xpc_exit_uv(void) xpc_destroy_gru_mq_uv(xpc_notify_mq_uv); xpc_destroy_gru_mq_uv(xpc_activate_mq_uv); } + +module_param(xpc_mq_node, int, 0); +MODULE_PARM_DESC(xpc_mq_node, "Node number on which to allocate message queues."); diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 6fae5f3ec7f6..d688a8af432c 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -398,7 +398,7 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, sizeof(qdisc_skb_cb(skb)->slave_dev_queue_mapping)); skb->queue_mapping = qdisc_skb_cb(skb)->slave_dev_queue_mapping; - if (unlikely(netpoll_tx_running(slave_dev))) + if (unlikely(netpoll_tx_running(bond->dev))) bond_netpoll_send_skb(bond_get_slave_by_dev(bond, slave_dev), skb); else dev_queue_xmit(skb); @@ -1235,12 +1235,12 @@ static inline int slave_enable_netpoll(struct slave *slave) struct netpoll *np; int err = 0; - np = kzalloc(sizeof(*np), GFP_KERNEL); + np = kzalloc(sizeof(*np), GFP_ATOMIC); err = -ENOMEM; if (!np) goto out; - err = __netpoll_setup(np, slave->dev); + err = __netpoll_setup(np, slave->dev, GFP_ATOMIC); if (err) { kfree(np); goto out; @@ -1257,9 +1257,7 @@ static inline void slave_disable_netpoll(struct slave *slave) return; slave->np = NULL; - synchronize_rcu_bh(); - __netpoll_cleanup(np); - kfree(np); + __netpoll_free_rcu(np); } static inline bool slave_dev_support_netpoll(struct net_device *slave_dev) { @@ -1292,7 +1290,7 @@ static void bond_netpoll_cleanup(struct net_device *bond_dev) read_unlock(&bond->lock); } -static int bond_netpoll_setup(struct net_device *dev, struct netpoll_info *ni) +static int bond_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, gfp_t gfp) { struct bonding *bond = netdev_priv(dev); struct slave *slave; diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c index 0f2d1a710909..151453309401 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c +++ b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c @@ -174,8 +174,10 @@ static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev) new_bus->phy_mask = ~0; new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); - if (!new_bus->irq) + if (!new_bus->irq) { + ret = -ENOMEM; goto out_unmap_regs; + } new_bus->parent = &ofdev->dev; dev_set_drvdata(&ofdev->dev, new_bus); diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c index 55bb867258e6..cdf702a59485 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c +++ b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c @@ -137,8 +137,10 @@ static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev) snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", res.start); fec->fecp = ioremap(res.start, resource_size(&res)); - if (!fec->fecp) + if (!fec->fecp) { + ret = -ENOMEM; goto out_fec; + } if (get_bus_freq) { clock = get_bus_freq(ofdev->dev.of_node); @@ -172,8 +174,10 @@ static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev) new_bus->phy_mask = ~0; new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); - if (!new_bus->irq) + if (!new_bus->irq) { + ret = -ENOMEM; goto out_unmap_regs; + } new_bus->parent = &ofdev->dev; dev_set_drvdata(&ofdev->dev, new_bus); diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c index 4ec3835e1bc2..a018ea2a43de 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mcg.c +++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c @@ -432,8 +432,10 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 port, if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn) { /* Entry already exists, add to duplicates */ dqp = kmalloc(sizeof *dqp, GFP_KERNEL); - if (!dqp) + if (!dqp) { + err = -ENOMEM; goto out_mailbox; + } dqp->qpn = qpn; list_add_tail(&dqp->list, &entry->duplicates); found = true; diff --git a/drivers/net/ethernet/renesas/Kconfig b/drivers/net/ethernet/renesas/Kconfig index 46df3a04030c..24c2305d7948 100644 --- a/drivers/net/ethernet/renesas/Kconfig +++ b/drivers/net/ethernet/renesas/Kconfig @@ -8,7 +8,7 @@ config SH_ETH (CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || \ CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7619 || \ CPU_SUBTYPE_SH7724 || CPU_SUBTYPE_SH7734 || \ - CPU_SUBTYPE_SH7757 || ARCH_R8A7740) + CPU_SUBTYPE_SH7757 || ARCH_R8A7740 || ARCH_R8A7779) select CRC32 select NET_CORE select MII @@ -18,4 +18,4 @@ config SH_ETH Renesas SuperH Ethernet device driver. This driver supporting CPUs are: - SH7619, SH7710, SH7712, SH7724, SH7734, SH7763, SH7757, - and R8A7740. + R8A7740 and R8A7779. diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index af0b867a6cf6..bad8f2eec9b4 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -78,7 +78,7 @@ static void sh_eth_select_mii(struct net_device *ndev) #endif /* There is CPU dependent code */ -#if defined(CONFIG_CPU_SUBTYPE_SH7724) +#if defined(CONFIG_CPU_SUBTYPE_SH7724) || defined(CONFIG_ARCH_R8A7779) #define SH_ETH_RESET_DEFAULT 1 static void sh_eth_set_duplex(struct net_device *ndev) { @@ -93,13 +93,18 @@ static void sh_eth_set_duplex(struct net_device *ndev) static void sh_eth_set_rate(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); + unsigned int bits = ECMR_RTM; + +#if defined(CONFIG_ARCH_R8A7779) + bits |= ECMR_ELB; +#endif switch (mdp->speed) { case 10: /* 10BASE */ - sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_RTM, ECMR); + sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~bits, ECMR); break; case 100:/* 100BASE */ - sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_RTM, ECMR); + sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | bits, ECMR); break; default: break; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index fd8882f9602a..c136162e6473 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -2077,7 +2077,7 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device, goto error_netdev_register; } - priv->stmmac_clk = clk_get(priv->device, NULL); + priv->stmmac_clk = clk_get(priv->device, STMMAC_RESOURCE_NAME); if (IS_ERR(priv->stmmac_clk)) { pr_warning("%s: warning: cannot get CSR clock\n", __func__); goto error_clk_get; diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c index 3b5c4571b55e..d15c888e9df8 100644 --- a/drivers/net/ethernet/ti/davinci_cpdma.c +++ b/drivers/net/ethernet/ti/davinci_cpdma.c @@ -538,11 +538,12 @@ EXPORT_SYMBOL_GPL(cpdma_chan_create); int cpdma_chan_destroy(struct cpdma_chan *chan) { - struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_ctlr *ctlr; unsigned long flags; if (!chan) return -EINVAL; + ctlr = chan->ctlr; spin_lock_irqsave(&ctlr->lock, flags); if (chan->state != CPDMA_STATE_IDLE) diff --git a/drivers/net/irda/ks959-sir.c b/drivers/net/irda/ks959-sir.c index 824e2a93fe8a..5f3aeac3f86d 100644 --- a/drivers/net/irda/ks959-sir.c +++ b/drivers/net/irda/ks959-sir.c @@ -542,6 +542,7 @@ static int ks959_net_open(struct net_device *netdev) sprintf(hwname, "usb#%d", kingsun->usbdev->devnum); kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname); if (!kingsun->irlap) { + err = -ENOMEM; dev_err(&kingsun->usbdev->dev, "irlap_open failed\n"); goto free_mem; } diff --git a/drivers/net/irda/ksdazzle-sir.c b/drivers/net/irda/ksdazzle-sir.c index 5a278ab83c2f..2d4b6a1ab202 100644 --- a/drivers/net/irda/ksdazzle-sir.c +++ b/drivers/net/irda/ksdazzle-sir.c @@ -436,6 +436,7 @@ static int ksdazzle_net_open(struct net_device *netdev) sprintf(hwname, "usb#%d", kingsun->usbdev->devnum); kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname); if (!kingsun->irlap) { + err = -ENOMEM; dev_err(&kingsun->usbdev->dev, "irlap_open failed\n"); goto free_mem; } diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index f9347ea3d381..b3321129a83c 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -640,15 +640,9 @@ static int netconsole_netdev_event(struct notifier_block *this, * rtnl_lock already held */ if (nt->np.dev) { - spin_unlock_irqrestore( - &target_list_lock, - flags); __netpoll_cleanup(&nt->np); - spin_lock_irqsave(&target_list_lock, - flags); dev_put(nt->np.dev); nt->np.dev = NULL; - netconsole_target_put(nt); } nt->enabled = 0; stopped = true; diff --git a/drivers/net/phy/mdio-mux.c b/drivers/net/phy/mdio-mux.c index 5c120189ec86..4d4d25efc1e1 100644 --- a/drivers/net/phy/mdio-mux.c +++ b/drivers/net/phy/mdio-mux.c @@ -132,7 +132,7 @@ int mdio_mux_init(struct device *dev, pb->mii_bus = parent_bus; ret_val = -ENODEV; - for_each_child_of_node(dev->of_node, child_bus_node) { + for_each_available_child_of_node(dev->of_node, child_bus_node) { u32 v; r = of_property_read_u32(child_bus_node, "reg", &v); diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 87707ab39430..341b65dbbcd3 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -795,16 +795,17 @@ static void team_port_leave(struct team *team, struct team_port *port) } #ifdef CONFIG_NET_POLL_CONTROLLER -static int team_port_enable_netpoll(struct team *team, struct team_port *port) +static int team_port_enable_netpoll(struct team *team, struct team_port *port, + gfp_t gfp) { struct netpoll *np; int err; - np = kzalloc(sizeof(*np), GFP_KERNEL); + np = kzalloc(sizeof(*np), gfp); if (!np) return -ENOMEM; - err = __netpoll_setup(np, port->dev); + err = __netpoll_setup(np, port->dev, gfp); if (err) { kfree(np); return err; @@ -833,7 +834,8 @@ static struct netpoll_info *team_netpoll_info(struct team *team) } #else -static int team_port_enable_netpoll(struct team *team, struct team_port *port) +static int team_port_enable_netpoll(struct team *team, struct team_port *port, + gfp_t gfp) { return 0; } @@ -913,7 +915,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev) } if (team_netpoll_info(team)) { - err = team_port_enable_netpoll(team, port); + err = team_port_enable_netpoll(team, port, GFP_KERNEL); if (err) { netdev_err(dev, "Failed to enable netpoll on device %s\n", portname); @@ -1443,7 +1445,7 @@ static void team_netpoll_cleanup(struct net_device *dev) } static int team_netpoll_setup(struct net_device *dev, - struct netpoll_info *npifo) + struct netpoll_info *npifo, gfp_t gfp) { struct team *team = netdev_priv(dev); struct team_port *port; @@ -1451,7 +1453,7 @@ static int team_netpoll_setup(struct net_device *dev, mutex_lock(&team->lock); list_for_each_entry(port, &team->port_list, list) { - err = team_port_enable_netpoll(team, port); + err = team_port_enable_netpoll(team, port, gfp); if (err) { __team_netpoll_cleanup(team); break; diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 2ea126a16d79..328397c66730 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -247,30 +247,12 @@ err: */ static int qmi_wwan_bind_shared(struct usbnet *dev, struct usb_interface *intf) { - int rv; struct qmi_wwan_state *info = (void *)&dev->data; - /* ZTE makes devices where the interface descriptors and endpoint - * configurations of two or more interfaces are identical, even - * though the functions are completely different. If set, then - * driver_info->data is a bitmap of acceptable interface numbers - * allowing us to bind to one such interface without binding to - * all of them - */ - if (dev->driver_info->data && - !test_bit(intf->cur_altsetting->desc.bInterfaceNumber, &dev->driver_info->data)) { - dev_info(&intf->dev, "not on our whitelist - ignored"); - rv = -ENODEV; - goto err; - } - /* control and data is shared */ info->control = intf; info->data = intf; - rv = qmi_wwan_register_subdriver(dev); - -err: - return rv; + return qmi_wwan_register_subdriver(dev); } static void qmi_wwan_unbind(struct usbnet *dev, struct usb_interface *intf) @@ -356,214 +338,64 @@ static const struct driver_info qmi_wwan_shared = { .manage_power = qmi_wwan_manage_power, }; -static const struct driver_info qmi_wwan_force_int0 = { - .description = "Qualcomm WWAN/QMI device", - .flags = FLAG_WWAN, - .bind = qmi_wwan_bind_shared, - .unbind = qmi_wwan_unbind, - .manage_power = qmi_wwan_manage_power, - .data = BIT(0), /* interface whitelist bitmap */ -}; - -static const struct driver_info qmi_wwan_force_int1 = { - .description = "Qualcomm WWAN/QMI device", - .flags = FLAG_WWAN, - .bind = qmi_wwan_bind_shared, - .unbind = qmi_wwan_unbind, - .manage_power = qmi_wwan_manage_power, - .data = BIT(1), /* interface whitelist bitmap */ -}; - -static const struct driver_info qmi_wwan_force_int2 = { - .description = "Qualcomm WWAN/QMI device", - .flags = FLAG_WWAN, - .bind = qmi_wwan_bind_shared, - .unbind = qmi_wwan_unbind, - .manage_power = qmi_wwan_manage_power, - .data = BIT(2), /* interface whitelist bitmap */ -}; - -static const struct driver_info qmi_wwan_force_int3 = { - .description = "Qualcomm WWAN/QMI device", - .flags = FLAG_WWAN, - .bind = qmi_wwan_bind_shared, - .unbind = qmi_wwan_unbind, - .manage_power = qmi_wwan_manage_power, - .data = BIT(3), /* interface whitelist bitmap */ -}; - -static const struct driver_info qmi_wwan_force_int4 = { - .description = "Qualcomm WWAN/QMI device", - .flags = FLAG_WWAN, - .bind = qmi_wwan_bind_shared, - .unbind = qmi_wwan_unbind, - .manage_power = qmi_wwan_manage_power, - .data = BIT(4), /* interface whitelist bitmap */ -}; - -/* Sierra Wireless provide equally useless interface descriptors - * Devices in QMI mode can be switched between two different - * configurations: - * a) USB interface #8 is QMI/wwan - * b) USB interfaces #8, #19 and #20 are QMI/wwan - * - * Both configurations provide a number of other interfaces (serial++), - * some of which have the same endpoint configuration as we expect, so - * a whitelist or blacklist is necessary. - * - * FIXME: The below whitelist should include BIT(20). It does not - * because I cannot get it to work... - */ -static const struct driver_info qmi_wwan_sierra = { - .description = "Sierra Wireless wwan/QMI device", - .flags = FLAG_WWAN, - .bind = qmi_wwan_bind_shared, - .unbind = qmi_wwan_unbind, - .manage_power = qmi_wwan_manage_power, - .data = BIT(8) | BIT(19), /* interface whitelist bitmap */ -}; - #define HUAWEI_VENDOR_ID 0x12D1 +/* map QMI/wwan function by a fixed interface number */ +#define QMI_FIXED_INTF(vend, prod, num) \ + USB_DEVICE_INTERFACE_NUMBER(vend, prod, num), \ + .driver_info = (unsigned long)&qmi_wwan_shared + /* Gobi 1000 QMI/wwan interface number is 3 according to qcserial */ #define QMI_GOBI1K_DEVICE(vend, prod) \ - USB_DEVICE(vend, prod), \ - .driver_info = (unsigned long)&qmi_wwan_force_int3 + QMI_FIXED_INTF(vend, prod, 3) -/* Gobi 2000 and Gobi 3000 QMI/wwan interface number is 0 according to qcserial */ +/* Gobi 2000/3000 QMI/wwan interface number is 0 according to qcserial */ #define QMI_GOBI_DEVICE(vend, prod) \ - USB_DEVICE(vend, prod), \ - .driver_info = (unsigned long)&qmi_wwan_force_int0 + QMI_FIXED_INTF(vend, prod, 0) static const struct usb_device_id products[] = { + /* 1. CDC ECM like devices match on the control interface */ { /* Huawei E392, E398 and possibly others sharing both device id and more... */ - .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = HUAWEI_VENDOR_ID, - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 9, /* CDC Ethernet *control* interface */ + USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 9), .driver_info = (unsigned long)&qmi_wwan_info, }, { /* Vodafone/Huawei K5005 (12d1:14c8) and similar modems */ - .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = HUAWEI_VENDOR_ID, - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 57, /* CDC Ethernet *control* interface */ + USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 57), .driver_info = (unsigned long)&qmi_wwan_info, }, - { /* Huawei E392, E398 and possibly others in "Windows mode" - * using a combined control and data interface without any CDC - * functional descriptors - */ - .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = HUAWEI_VENDOR_ID, - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 17, + + /* 2. Combined interface devices matching on class+protocol */ + { /* Huawei E392, E398 and possibly others in "Windows mode" */ + USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 17), .driver_info = (unsigned long)&qmi_wwan_shared, }, { /* Pantech UML290 */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x106c, - .idProduct = 0x3718, - .bInterfaceClass = 0xff, - .bInterfaceSubClass = 0xf0, - .bInterfaceProtocol = 0xff, + USB_DEVICE_AND_INTERFACE_INFO(0x106c, 0x3718, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff), .driver_info = (unsigned long)&qmi_wwan_shared, }, - { /* ZTE MF820D */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x19d2, - .idProduct = 0x0167, - .bInterfaceClass = 0xff, - .bInterfaceSubClass = 0xff, - .bInterfaceProtocol = 0xff, - .driver_info = (unsigned long)&qmi_wwan_force_int4, - }, - { /* ZTE MF821D */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x19d2, - .idProduct = 0x0326, - .bInterfaceClass = 0xff, - .bInterfaceSubClass = 0xff, - .bInterfaceProtocol = 0xff, - .driver_info = (unsigned long)&qmi_wwan_force_int4, - }, - { /* ZTE (Vodafone) K3520-Z */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x19d2, - .idProduct = 0x0055, - .bInterfaceClass = 0xff, - .bInterfaceSubClass = 0xff, - .bInterfaceProtocol = 0xff, - .driver_info = (unsigned long)&qmi_wwan_force_int1, - }, - { /* ZTE (Vodafone) K3565-Z */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x19d2, - .idProduct = 0x0063, - .bInterfaceClass = 0xff, - .bInterfaceSubClass = 0xff, - .bInterfaceProtocol = 0xff, - .driver_info = (unsigned long)&qmi_wwan_force_int4, - }, - { /* ZTE (Vodafone) K3570-Z */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x19d2, - .idProduct = 0x1008, - .bInterfaceClass = 0xff, - .bInterfaceSubClass = 0xff, - .bInterfaceProtocol = 0xff, - .driver_info = (unsigned long)&qmi_wwan_force_int4, - }, - { /* ZTE (Vodafone) K3571-Z */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x19d2, - .idProduct = 0x1010, - .bInterfaceClass = 0xff, - .bInterfaceSubClass = 0xff, - .bInterfaceProtocol = 0xff, - .driver_info = (unsigned long)&qmi_wwan_force_int4, - }, - { /* ZTE (Vodafone) K3765-Z */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x19d2, - .idProduct = 0x2002, - .bInterfaceClass = 0xff, - .bInterfaceSubClass = 0xff, - .bInterfaceProtocol = 0xff, - .driver_info = (unsigned long)&qmi_wwan_force_int4, - }, - { /* ZTE (Vodafone) K4505-Z */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x19d2, - .idProduct = 0x0104, - .bInterfaceClass = 0xff, - .bInterfaceSubClass = 0xff, - .bInterfaceProtocol = 0xff, - .driver_info = (unsigned long)&qmi_wwan_force_int4, - }, - { /* ZTE MF60 */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x19d2, - .idProduct = 0x1402, - .bInterfaceClass = 0xff, - .bInterfaceSubClass = 0xff, - .bInterfaceProtocol = 0xff, - .driver_info = (unsigned long)&qmi_wwan_force_int2, - }, - { /* Sierra Wireless MC77xx in QMI mode */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x1199, - .idProduct = 0x68a2, - .bInterfaceClass = 0xff, - .bInterfaceSubClass = 0xff, - .bInterfaceProtocol = 0xff, - .driver_info = (unsigned long)&qmi_wwan_sierra, + { /* Pantech UML290 - newer firmware */ + USB_DEVICE_AND_INTERFACE_INFO(0x106c, 0x3718, USB_CLASS_VENDOR_SPEC, 0xf1, 0xff), + .driver_info = (unsigned long)&qmi_wwan_shared, }, - /* Gobi 1000 devices */ + /* 3. Combined interface devices matching on interface number */ + {QMI_FIXED_INTF(0x19d2, 0x0055, 1)}, /* ZTE (Vodafone) K3520-Z */ + {QMI_FIXED_INTF(0x19d2, 0x0063, 4)}, /* ZTE (Vodafone) K3565-Z */ + {QMI_FIXED_INTF(0x19d2, 0x0104, 4)}, /* ZTE (Vodafone) K4505-Z */ + {QMI_FIXED_INTF(0x19d2, 0x0167, 4)}, /* ZTE MF820D */ + {QMI_FIXED_INTF(0x19d2, 0x0326, 4)}, /* ZTE MF821D */ + {QMI_FIXED_INTF(0x19d2, 0x1008, 4)}, /* ZTE (Vodafone) K3570-Z */ + {QMI_FIXED_INTF(0x19d2, 0x1010, 4)}, /* ZTE (Vodafone) K3571-Z */ + {QMI_FIXED_INTF(0x19d2, 0x1018, 3)}, /* ZTE (Vodafone) K5006-Z */ + {QMI_FIXED_INTF(0x19d2, 0x1402, 2)}, /* ZTE MF60 */ + {QMI_FIXED_INTF(0x19d2, 0x2002, 4)}, /* ZTE (Vodafone) K3765-Z */ + {QMI_FIXED_INTF(0x0f3d, 0x68a2, 8)}, /* Sierra Wireless MC7700 */ + {QMI_FIXED_INTF(0x114f, 0x68a2, 8)}, /* Sierra Wireless MC7750 */ + {QMI_FIXED_INTF(0x1199, 0x68a2, 8)}, /* Sierra Wireless MC7710 in QMI mode */ + {QMI_FIXED_INTF(0x1199, 0x68a2, 19)}, /* Sierra Wireless MC7710 in QMI mode */ + {QMI_FIXED_INTF(0x1199, 0x901c, 8)}, /* Sierra Wireless EM7700 */ + + /* 4. Gobi 1000 devices */ {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ {QMI_GOBI1K_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ {QMI_GOBI1K_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */ @@ -579,7 +411,7 @@ static const struct usb_device_id products[] = { {QMI_GOBI1K_DEVICE(0x05c6, 0x9222)}, /* Generic Gobi Modem device */ {QMI_GOBI1K_DEVICE(0x05c6, 0x9009)}, /* Generic Gobi Modem device */ - /* Gobi 2000 and 3000 devices */ + /* 5. Gobi 2000 and 3000 devices */ {QMI_GOBI_DEVICE(0x413c, 0x8186)}, /* Dell Gobi 2000 Modem device (N0218, VU936) */ {QMI_GOBI_DEVICE(0x05c6, 0x920b)}, /* Generic Gobi 2000 Modem device */ {QMI_GOBI_DEVICE(0x05c6, 0x9225)}, /* Sony Gobi 2000 Modem device (N0279, VU730) */ @@ -589,6 +421,8 @@ static const struct usb_device_id products[] = { {QMI_GOBI_DEVICE(0x05c6, 0x9265)}, /* Asus Gobi 2000 Modem device (VR305) */ {QMI_GOBI_DEVICE(0x05c6, 0x9235)}, /* Top Global Gobi 2000 Modem device (VR306) */ {QMI_GOBI_DEVICE(0x05c6, 0x9275)}, /* iRex Technologies Gobi 2000 Modem device (VR307) */ + {QMI_GOBI_DEVICE(0x1199, 0x68a5)}, /* Sierra Wireless Modem */ + {QMI_GOBI_DEVICE(0x1199, 0x68a9)}, /* Sierra Wireless Modem */ {QMI_GOBI_DEVICE(0x1199, 0x9001)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ {QMI_GOBI_DEVICE(0x1199, 0x9002)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ {QMI_GOBI_DEVICE(0x1199, 0x9003)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ @@ -600,11 +434,14 @@ static const struct usb_device_id products[] = { {QMI_GOBI_DEVICE(0x1199, 0x9009)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ {QMI_GOBI_DEVICE(0x1199, 0x900a)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ {QMI_GOBI_DEVICE(0x1199, 0x9011)}, /* Sierra Wireless Gobi 2000 Modem device (MC8305) */ + {QMI_FIXED_INTF(0x1199, 0x9011, 5)}, /* alternate interface number!? */ {QMI_GOBI_DEVICE(0x16d8, 0x8002)}, /* CMDTech Gobi 2000 Modem device (VU922) */ {QMI_GOBI_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */ {QMI_GOBI_DEVICE(0x1199, 0x9013)}, /* Sierra Wireless Gobi 3000 Modem device (MC8355) */ {QMI_GOBI_DEVICE(0x1199, 0x9015)}, /* Sierra Wireless Gobi 3000 Modem device */ {QMI_GOBI_DEVICE(0x1199, 0x9019)}, /* Sierra Wireless Gobi 3000 Modem device */ + {QMI_GOBI_DEVICE(0x1199, 0x901b)}, /* Sierra Wireless MC7770 */ + { } /* END */ }; MODULE_DEVICE_TABLE(usb, products); diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c index d75d1f56becf..7be49ea60b6d 100644 --- a/drivers/net/usb/sierra_net.c +++ b/drivers/net/usb/sierra_net.c @@ -68,15 +68,8 @@ static atomic_t iface_counter = ATOMIC_INIT(0); */ #define SIERRA_NET_USBCTL_BUF_LEN 1024 -/* list of interface numbers - used for constructing interface lists */ -struct sierra_net_iface_info { - const u32 infolen; /* number of interface numbers on list */ - const u8 *ifaceinfo; /* pointer to the array holding the numbers */ -}; - struct sierra_net_info_data { u16 rx_urb_size; - struct sierra_net_iface_info whitelist; }; /* Private data structure */ @@ -637,21 +630,6 @@ static int sierra_net_change_mtu(struct net_device *net, int new_mtu) return usbnet_change_mtu(net, new_mtu); } -static int is_whitelisted(const u8 ifnum, - const struct sierra_net_iface_info *whitelist) -{ - if (whitelist) { - const u8 *list = whitelist->ifaceinfo; - int i; - - for (i = 0; i < whitelist->infolen; i++) { - if (list[i] == ifnum) - return 1; - } - } - return 0; -} - static int sierra_net_get_fw_attr(struct usbnet *dev, u16 *datap) { int result = 0; @@ -706,11 +684,6 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf) dev_dbg(&dev->udev->dev, "%s", __func__); ifacenum = intf->cur_altsetting->desc.bInterfaceNumber; - /* We only accept certain interfaces */ - if (!is_whitelisted(ifacenum, &data->whitelist)) { - dev_dbg(&dev->udev->dev, "Ignoring interface: %d", ifacenum); - return -ENODEV; - } numendpoints = intf->cur_altsetting->desc.bNumEndpoints; /* We have three endpoints, bulk in and out, and a status */ if (numendpoints != 3) { @@ -945,13 +918,8 @@ struct sk_buff *sierra_net_tx_fixup(struct usbnet *dev, struct sk_buff *skb, return NULL; } -static const u8 sierra_net_ifnum_list[] = { 7, 10, 11 }; static const struct sierra_net_info_data sierra_net_info_data_direct_ip = { .rx_urb_size = 8 * 1024, - .whitelist = { - .infolen = ARRAY_SIZE(sierra_net_ifnum_list), - .ifaceinfo = sierra_net_ifnum_list - } }; static const struct driver_info sierra_net_info_direct_ip = { @@ -965,15 +933,19 @@ static const struct driver_info sierra_net_info_direct_ip = { .data = (unsigned long)&sierra_net_info_data_direct_ip, }; +#define DIRECT_IP_DEVICE(vend, prod) \ + {USB_DEVICE_INTERFACE_NUMBER(vend, prod, 7), \ + .driver_info = (unsigned long)&sierra_net_info_direct_ip}, \ + {USB_DEVICE_INTERFACE_NUMBER(vend, prod, 10), \ + .driver_info = (unsigned long)&sierra_net_info_direct_ip}, \ + {USB_DEVICE_INTERFACE_NUMBER(vend, prod, 11), \ + .driver_info = (unsigned long)&sierra_net_info_direct_ip} + static const struct usb_device_id products[] = { - {USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless USB-to-WWAN modem */ - .driver_info = (unsigned long) &sierra_net_info_direct_ip}, - {USB_DEVICE(0x0F3D, 0x68A3), /* AT&T Direct IP modem */ - .driver_info = (unsigned long) &sierra_net_info_direct_ip}, - {USB_DEVICE(0x1199, 0x68AA), /* Sierra Wireless Direct IP LTE modem */ - .driver_info = (unsigned long) &sierra_net_info_direct_ip}, - {USB_DEVICE(0x0F3D, 0x68AA), /* AT&T Direct IP LTE modem */ - .driver_info = (unsigned long) &sierra_net_info_direct_ip}, + DIRECT_IP_DEVICE(0x1199, 0x68A3), /* Sierra Wireless USB-to-WWAN modem */ + DIRECT_IP_DEVICE(0x0F3D, 0x68A3), /* AT&T Direct IP modem */ + DIRECT_IP_DEVICE(0x1199, 0x68AA), /* Sierra Wireless Direct IP LTE modem */ + DIRECT_IP_DEVICE(0x0F3D, 0x68AA), /* AT&T Direct IP LTE modem */ {}, /* last item */ }; diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 93e0cfb739b8..ce9d4f2c9776 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -3019,6 +3019,7 @@ vmxnet3_probe_device(struct pci_dev *pdev, netdev->watchdog_timeo = 5 * HZ; INIT_WORK(&adapter->work, vmxnet3_reset_work); + set_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state); if (adapter->intr.type == VMXNET3_IT_MSIX) { int i; @@ -3043,7 +3044,6 @@ vmxnet3_probe_device(struct pci_dev *pdev, goto err_register; } - set_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state); vmxnet3_check_link(adapter, false); atomic_inc(&devices_found); return 0; diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index 9eb6479306d6..ef36cafd44b7 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -774,14 +774,15 @@ static int __devinit dscc4_init_one(struct pci_dev *pdev, } /* Global interrupt queue */ writel((u32)(((IRQ_RING_SIZE >> 5) - 1) << 20), ioaddr + IQLENR1); + + rc = -ENOMEM; + priv->iqcfg = (__le32 *) pci_alloc_consistent(pdev, IRQ_RING_SIZE*sizeof(__le32), &priv->iqcfg_dma); if (!priv->iqcfg) goto err_free_irq_5; writel(priv->iqcfg_dma, ioaddr + IQCFG); - rc = -ENOMEM; - /* * SCC 0-3 private rx/tx irq structures * IQRX/TXi needs to be set soon. Learned it the hard way... diff --git a/drivers/net/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c index 283237f6f074..def12b38cbf7 100644 --- a/drivers/net/wimax/i2400m/fw.c +++ b/drivers/net/wimax/i2400m/fw.c @@ -326,8 +326,10 @@ int i2400m_barker_db_init(const char *_options) unsigned barker; options_orig = kstrdup(_options, GFP_KERNEL); - if (options_orig == NULL) + if (options_orig == NULL) { + result = -ENOMEM; goto error_parse; + } options = options_orig; while ((token = strsep(&options, ",")) != NULL) { diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index efc162e0b511..88b8d64c90f1 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c @@ -342,7 +342,7 @@ static int at76_dfu_get_status(struct usb_device *udev, return ret; } -static u8 at76_dfu_get_state(struct usb_device *udev, u8 *state) +static int at76_dfu_get_state(struct usb_device *udev, u8 *state) { int ret; diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 8c4c040a47b8..2aab20ee9f38 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2056,9 +2056,7 @@ ath5k_beacon_update_timers(struct ath5k_hw *ah, u64 bc_tsf) void ath5k_beacon_config(struct ath5k_hw *ah) { - unsigned long flags; - - spin_lock_irqsave(&ah->block, flags); + spin_lock_bh(&ah->block); ah->bmisscount = 0; ah->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA); @@ -2085,7 +2083,7 @@ ath5k_beacon_config(struct ath5k_hw *ah) ath5k_hw_set_imr(ah, ah->imask); mmiowb(); - spin_unlock_irqrestore(&ah->block, flags); + spin_unlock_bh(&ah->block); } static void ath5k_tasklet_beacon(unsigned long data) diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index 260e7dc7f751..d56453e43d7e 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c @@ -254,7 +254,6 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ath5k_vif *avf = (void *)vif->drv_priv; struct ath5k_hw *ah = hw->priv; struct ath_common *common = ath5k_hw_common(ah); - unsigned long flags; mutex_lock(&ah->lock); @@ -300,9 +299,9 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } if (changes & BSS_CHANGED_BEACON) { - spin_lock_irqsave(&ah->block, flags); + spin_lock_bh(&ah->block); ath5k_beacon_update(hw, vif); - spin_unlock_irqrestore(&ah->block, flags); + spin_unlock_bh(&ah->block); } if (changes & BSS_CHANGED_BEACON_ENABLED) diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 7990cd55599c..b42be910a83d 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -773,15 +773,10 @@ bool ath9k_hw_intrpend(struct ath_hw *ah) } EXPORT_SYMBOL(ath9k_hw_intrpend); -void ath9k_hw_disable_interrupts(struct ath_hw *ah) +void ath9k_hw_kill_interrupts(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); - if (!(ah->imask & ATH9K_INT_GLOBAL)) - atomic_set(&ah->intr_ref_cnt, -1); - else - atomic_dec(&ah->intr_ref_cnt); - ath_dbg(common, INTERRUPT, "disable IER\n"); REG_WRITE(ah, AR_IER, AR_IER_DISABLE); (void) REG_READ(ah, AR_IER); @@ -793,6 +788,17 @@ void ath9k_hw_disable_interrupts(struct ath_hw *ah) (void) REG_READ(ah, AR_INTR_SYNC_ENABLE); } } +EXPORT_SYMBOL(ath9k_hw_kill_interrupts); + +void ath9k_hw_disable_interrupts(struct ath_hw *ah) +{ + if (!(ah->imask & ATH9K_INT_GLOBAL)) + atomic_set(&ah->intr_ref_cnt, -1); + else + atomic_dec(&ah->intr_ref_cnt); + + ath9k_hw_kill_interrupts(ah); +} EXPORT_SYMBOL(ath9k_hw_disable_interrupts); void ath9k_hw_enable_interrupts(struct ath_hw *ah) diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 0eba36dca6f8..4a745e68dd94 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -738,6 +738,7 @@ bool ath9k_hw_intrpend(struct ath_hw *ah); void ath9k_hw_set_interrupts(struct ath_hw *ah); void ath9k_hw_enable_interrupts(struct ath_hw *ah); void ath9k_hw_disable_interrupts(struct ath_hw *ah); +void ath9k_hw_kill_interrupts(struct ath_hw *ah); void ar9002_hw_attach_mac_ops(struct ath_hw *ah); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 6049d8b82855..a22df749b8db 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -462,8 +462,10 @@ irqreturn_t ath_isr(int irq, void *dev) if (!ath9k_hw_intrpend(ah)) return IRQ_NONE; - if(test_bit(SC_OP_HW_RESET, &sc->sc_flags)) + if (test_bit(SC_OP_HW_RESET, &sc->sc_flags)) { + ath9k_hw_kill_interrupts(ah); return IRQ_HANDLED; + } /* * Figure out the reason(s) for the interrupt. Note diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index d455de9162ec..a978984d78a5 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -321,6 +321,7 @@ static int ath_pci_suspend(struct device *device) * Otherwise the chip never moved to full sleep, * when no interface is up. */ + ath9k_stop_btcoex(sc); ath9k_hw_disable(sc->sc_ah); ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 12aca02228c2..4480c0cc655f 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -1044,7 +1044,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) struct ieee80211_hw *hw = sc->hw; struct ieee80211_hdr *hdr; int retval; - bool decrypt_error = false; struct ath_rx_status rs; enum ath9k_rx_qtype qtype; bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA); @@ -1066,6 +1065,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) tsf_lower = tsf & 0xffffffff; do { + bool decrypt_error = false; /* If handling rx interrupt and flush is in progress => exit */ if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags) && (flush == 0)) break; diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 7f207b6e9552..effb044a8a9d 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -42,7 +42,7 @@ MODULE_FIRMWARE("isl3887usb"); * whenever you add a new device. */ -static struct usb_device_id p54u_table[] __devinitdata = { +static struct usb_device_id p54u_table[] = { /* Version 1 devices (pci chip + net2280) */ {USB_DEVICE(0x0411, 0x0050)}, /* Buffalo WLI2-USB2-G54 */ {USB_DEVICE(0x045e, 0x00c2)}, /* Microsoft MN-710 */ diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 241162e8111d..7a4ae9ee1c63 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -1803,6 +1803,7 @@ static struct ndis_80211_pmkid *update_pmkid(struct usbnet *usbdev, struct cfg80211_pmksa *pmksa, int max_pmkids) { + struct ndis_80211_pmkid *new_pmkids; int i, err, newlen; unsigned int count; @@ -1833,11 +1834,12 @@ static struct ndis_80211_pmkid *update_pmkid(struct usbnet *usbdev, /* add new pmkid */ newlen = sizeof(*pmkids) + (count + 1) * sizeof(pmkids->bssid_info[0]); - pmkids = krealloc(pmkids, newlen, GFP_KERNEL); - if (!pmkids) { + new_pmkids = krealloc(pmkids, newlen, GFP_KERNEL); + if (!new_pmkids) { err = -ENOMEM; goto error; } + pmkids = new_pmkids; pmkids->length = cpu_to_le32(newlen); pmkids->bssid_info_count = cpu_to_le32(count + 1); diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c index 71a30b026089..533024095c43 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c @@ -44,7 +44,7 @@ MODULE_AUTHOR("Larry Finger <Larry.Finger@lwfinger.net>"); MODULE_DESCRIPTION("RTL8187/RTL8187B USB wireless driver"); MODULE_LICENSE("GPL"); -static struct usb_device_id rtl8187_table[] __devinitdata = { +static struct usb_device_id rtl8187_table[] = { /* Asus */ {USB_DEVICE(0x0b05, 0x171d), .driver_info = DEVICE_RTL8187}, /* Belkin */ diff --git a/drivers/of/base.c b/drivers/of/base.c index c181b94abc36..d4a1c9a043e1 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -364,6 +364,33 @@ struct device_node *of_get_next_child(const struct device_node *node, EXPORT_SYMBOL(of_get_next_child); /** + * of_get_next_available_child - Find the next available child node + * @node: parent node + * @prev: previous child of the parent node, or NULL to get first + * + * This function is like of_get_next_child(), except that it + * automatically skips any disabled nodes (i.e. status = "disabled"). + */ +struct device_node *of_get_next_available_child(const struct device_node *node, + struct device_node *prev) +{ + struct device_node *next; + + read_lock(&devtree_lock); + next = prev ? prev->sibling : node->child; + for (; next; next = next->sibling) { + if (!of_device_is_available(next)) + continue; + if (of_node_get(next)) + break; + } + of_node_put(prev); + read_unlock(&devtree_lock); + return next; +} +EXPORT_SYMBOL(of_get_next_available_child); + +/** * of_find_node_by_path - Find a node matching a full OF path * @path: The full path to match * diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index fbf7b26c7c8a..c5792d622dc4 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -266,8 +266,8 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) } if (!error) - dev_printk(KERN_INFO, &dev->dev, - "power state changed by ACPI to D%d\n", state); + dev_info(&dev->dev, "power state changed by ACPI to %s\n", + pci_power_name(state)); return error; } diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 185be3703343..5270f1a99328 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -959,6 +959,13 @@ static int pci_pm_poweroff_noirq(struct device *dev) if (!pci_dev->state_saved && !pci_is_bridge(pci_dev)) pci_prepare_to_sleep(pci_dev); + /* + * The reason for doing this here is the same as for the analogous code + * in pci_pm_suspend_noirq(). + */ + if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI) + pci_write_config_word(pci_dev, PCI_COMMAND, 0); + return 0; } diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index fb7f3bebdc69..dc5c126e398a 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -657,11 +657,7 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev) if (p != NULL) return ERR_PTR(-EBUSY); - p = create_pinctrl(dev); - if (IS_ERR(p)) - return p; - - return p; + return create_pinctrl(dev); } /** @@ -738,11 +734,8 @@ static struct pinctrl_state *pinctrl_lookup_state_locked(struct pinctrl *p, dev_dbg(p->dev, "using pinctrl dummy state (%s)\n", name); state = create_state(p, name); - if (IS_ERR(state)) - return state; - } else { - return ERR_PTR(-ENODEV); - } + } else + state = ERR_PTR(-ENODEV); } return state; diff --git a/drivers/pinctrl/pinctrl-imx51.c b/drivers/pinctrl/pinctrl-imx51.c index 689b3c88dd2e..9fd02162a3c2 100644 --- a/drivers/pinctrl/pinctrl-imx51.c +++ b/drivers/pinctrl/pinctrl-imx51.c @@ -974,7 +974,7 @@ static struct imx_pin_reg imx51_pin_regs[] = { IMX_PIN_REG(MX51_PAD_EIM_DA13, NO_PAD, 0x050, 0, 0x000, 0), /* MX51_PAD_EIM_DA13__EIM_DA13 */ IMX_PIN_REG(MX51_PAD_EIM_DA14, NO_PAD, 0x054, 0, 0x000, 0), /* MX51_PAD_EIM_DA14__EIM_DA14 */ IMX_PIN_REG(MX51_PAD_EIM_DA15, NO_PAD, 0x058, 0, 0x000, 0), /* MX51_PAD_EIM_DA15__EIM_DA15 */ - IMX_PIN_REG(MX51_PAD_SD2_CMD, NO_PAD, 0x3b4, 2, 0x91c, 3), /* MX51_PAD_SD2_CMD__CSPI_MOSI */ + IMX_PIN_REG(MX51_PAD_SD2_CMD, 0x7bc, 0x3b4, 2, 0x91c, 3), /* MX51_PAD_SD2_CMD__CSPI_MOSI */ IMX_PIN_REG(MX51_PAD_SD2_CMD, 0x7bc, 0x3b4, 1, 0x9b0, 2), /* MX51_PAD_SD2_CMD__I2C1_SCL */ IMX_PIN_REG(MX51_PAD_SD2_CMD, 0x7bc, 0x3b4, 0, 0x000, 0), /* MX51_PAD_SD2_CMD__SD2_CMD */ IMX_PIN_REG(MX51_PAD_SD2_CLK, 0x7c0, 0x3b8, 2, 0x914, 3), /* MX51_PAD_SD2_CLK__CSPI_SCLK */ diff --git a/drivers/pinctrl/pinctrl-nomadik-db8500.c b/drivers/pinctrl/pinctrl-nomadik-db8500.c index 5f3e9d0221e1..a39fb7a6fc51 100644 --- a/drivers/pinctrl/pinctrl-nomadik-db8500.c +++ b/drivers/pinctrl/pinctrl-nomadik-db8500.c @@ -505,6 +505,8 @@ static const unsigned kp_b_1_pins[] = { DB8500_PIN_F3, DB8500_PIN_F1, DB8500_PIN_J3, DB8500_PIN_H2, DB8500_PIN_J2, DB8500_PIN_H1, DB8500_PIN_F4, DB8500_PIN_E3, DB8500_PIN_E4, DB8500_PIN_D2, DB8500_PIN_C1, DB8500_PIN_D3, DB8500_PIN_C2, DB8500_PIN_D5 }; +static const unsigned kp_b_2_pins[] = { DB8500_PIN_F3, DB8500_PIN_F1, + DB8500_PIN_G3, DB8500_PIN_G2, DB8500_PIN_F4, DB8500_PIN_E3}; static const unsigned sm_b_1_pins[] = { DB8500_PIN_C6, DB8500_PIN_B3, DB8500_PIN_C4, DB8500_PIN_E6, DB8500_PIN_A3, DB8500_PIN_B6, DB8500_PIN_D6, DB8500_PIN_B7, DB8500_PIN_D7, DB8500_PIN_D8, @@ -662,6 +664,7 @@ static const struct nmk_pingroup nmk_db8500_groups[] = { DB8500_PIN_GROUP(spi3_b_1, NMK_GPIO_ALT_B), DB8500_PIN_GROUP(msp1txrx_b_1, NMK_GPIO_ALT_B), DB8500_PIN_GROUP(kp_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(kp_b_2, NMK_GPIO_ALT_B), DB8500_PIN_GROUP(sm_b_1, NMK_GPIO_ALT_B), DB8500_PIN_GROUP(smcs0_b_1, NMK_GPIO_ALT_B), DB8500_PIN_GROUP(smcs1_b_1, NMK_GPIO_ALT_B), @@ -751,7 +754,7 @@ DB8500_FUNC_GROUPS(msp1, "msp1txrx_a_1", "msp1_a_1", "msp1txrx_b_1"); DB8500_FUNC_GROUPS(lcdb, "lcdb_a_1"); DB8500_FUNC_GROUPS(lcd, "lcdvsi0_a_1", "lcdvsi1_a_1", "lcd_d0_d7_a_1", "lcd_d8_d11_a_1", "lcd_d12_d23_a_1", "lcd_b_1"); -DB8500_FUNC_GROUPS(kp, "kp_a_1", "kp_b_1", "kp_c_1", "kp_oc1_1"); +DB8500_FUNC_GROUPS(kp, "kp_a_1", "kp_b_1", "kp_b_2", "kp_c_1", "kp_oc1_1"); DB8500_FUNC_GROUPS(mc2, "mc2_a_1", "mc2rstn_c_1"); DB8500_FUNC_GROUPS(ssp1, "ssp1_a_1"); DB8500_FUNC_GROUPS(ssp0, "ssp0_a_1"); diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index ec6ac501b23a..3dde6537adb8 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c @@ -1292,7 +1292,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) NOMADIK_GPIO_TO_IRQ(pdata->first_gpio), 0, &nmk_gpio_irq_simple_ops, nmk_chip); if (!nmk_chip->domain) { - pr_err("%s: Failed to create irqdomain\n", np->full_name); + dev_err(&dev->dev, "failed to create irqdomain\n"); ret = -ENOSYS; goto out; } diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 2a262f5c5c0c..c86bae828c28 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -289,6 +289,7 @@ config IDEAPAD_LAPTOP tristate "Lenovo IdeaPad Laptop Extras" depends on ACPI depends on RFKILL && INPUT + depends on SERIO_I8042 select INPUT_SPARSEKMAP help This is a driver for the rfkill switches on Lenovo IdeaPad netbooks. @@ -758,8 +759,11 @@ config SAMSUNG_Q10 config APPLE_GMUX tristate "Apple Gmux Driver" + depends on ACPI depends on PNP - select BACKLIGHT_CLASS_DEVICE + depends on BACKLIGHT_CLASS_DEVICE + depends on BACKLIGHT_APPLE=n || BACKLIGHT_APPLE + depends on ACPI_VIDEO=n || ACPI_VIDEO ---help--- This driver provides support for the gmux device found on many Apple laptops, which controls the display mux for the hybrid diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index 905fa01ac8df..dfb1a92ce949 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -2,6 +2,7 @@ * Gmux driver for Apple laptops * * Copyright (C) Canonical Ltd. <seth.forshee@canonical.com> + * Copyright (C) 2010-2012 Andreas Heider <andreas@meetr.de> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -18,16 +19,30 @@ #include <linux/pnp.h> #include <linux/apple_bl.h> #include <linux/slab.h> +#include <linux/delay.h> +#include <linux/pci.h> +#include <linux/vga_switcheroo.h> #include <acpi/video.h> #include <asm/io.h> struct apple_gmux_data { unsigned long iostart; unsigned long iolen; + bool indexed; + struct mutex index_lock; struct backlight_device *bdev; + + /* switcheroo data */ + acpi_handle dhandle; + int gpe; + enum vga_switcheroo_client_id resume_client_id; + enum vga_switcheroo_state power_state; + struct completion powerchange_done; }; +static struct apple_gmux_data *apple_gmux_data; + /* * gmux port offsets. Many of these are not yet used, but may be in the * future, and it's useful to have them documented here anyhow. @@ -45,6 +60,9 @@ struct apple_gmux_data { #define GMUX_PORT_DISCRETE_POWER 0x50 #define GMUX_PORT_MAX_BRIGHTNESS 0x70 #define GMUX_PORT_BRIGHTNESS 0x74 +#define GMUX_PORT_VALUE 0xc2 +#define GMUX_PORT_READ 0xd0 +#define GMUX_PORT_WRITE 0xd4 #define GMUX_MIN_IO_LEN (GMUX_PORT_BRIGHTNESS + 4) @@ -59,22 +77,172 @@ struct apple_gmux_data { #define GMUX_BRIGHTNESS_MASK 0x00ffffff #define GMUX_MAX_BRIGHTNESS GMUX_BRIGHTNESS_MASK -static inline u8 gmux_read8(struct apple_gmux_data *gmux_data, int port) +static u8 gmux_pio_read8(struct apple_gmux_data *gmux_data, int port) { return inb(gmux_data->iostart + port); } -static inline void gmux_write8(struct apple_gmux_data *gmux_data, int port, +static void gmux_pio_write8(struct apple_gmux_data *gmux_data, int port, u8 val) { outb(val, gmux_data->iostart + port); } -static inline u32 gmux_read32(struct apple_gmux_data *gmux_data, int port) +static u32 gmux_pio_read32(struct apple_gmux_data *gmux_data, int port) { return inl(gmux_data->iostart + port); } +static void gmux_pio_write32(struct apple_gmux_data *gmux_data, int port, + u32 val) +{ + int i; + u8 tmpval; + + for (i = 0; i < 4; i++) { + tmpval = (val >> (i * 8)) & 0xff; + outb(tmpval, port + i); + } +} + +static int gmux_index_wait_ready(struct apple_gmux_data *gmux_data) +{ + int i = 200; + u8 gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE); + + while (i && (gwr & 0x01)) { + inb(gmux_data->iostart + GMUX_PORT_READ); + gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE); + udelay(100); + i--; + } + + return !!i; +} + +static int gmux_index_wait_complete(struct apple_gmux_data *gmux_data) +{ + int i = 200; + u8 gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE); + + while (i && !(gwr & 0x01)) { + gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE); + udelay(100); + i--; + } + + if (gwr & 0x01) + inb(gmux_data->iostart + GMUX_PORT_READ); + + return !!i; +} + +static u8 gmux_index_read8(struct apple_gmux_data *gmux_data, int port) +{ + u8 val; + + mutex_lock(&gmux_data->index_lock); + outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ); + gmux_index_wait_ready(gmux_data); + val = inb(gmux_data->iostart + GMUX_PORT_VALUE); + mutex_unlock(&gmux_data->index_lock); + + return val; +} + +static void gmux_index_write8(struct apple_gmux_data *gmux_data, int port, + u8 val) +{ + mutex_lock(&gmux_data->index_lock); + outb(val, gmux_data->iostart + GMUX_PORT_VALUE); + gmux_index_wait_ready(gmux_data); + outb(port & 0xff, gmux_data->iostart + GMUX_PORT_WRITE); + gmux_index_wait_complete(gmux_data); + mutex_unlock(&gmux_data->index_lock); +} + +static u32 gmux_index_read32(struct apple_gmux_data *gmux_data, int port) +{ + u32 val; + + mutex_lock(&gmux_data->index_lock); + outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ); + gmux_index_wait_ready(gmux_data); + val = inl(gmux_data->iostart + GMUX_PORT_VALUE); + mutex_unlock(&gmux_data->index_lock); + + return val; +} + +static void gmux_index_write32(struct apple_gmux_data *gmux_data, int port, + u32 val) +{ + int i; + u8 tmpval; + + mutex_lock(&gmux_data->index_lock); + + for (i = 0; i < 4; i++) { + tmpval = (val >> (i * 8)) & 0xff; + outb(tmpval, gmux_data->iostart + GMUX_PORT_VALUE + i); + } + + gmux_index_wait_ready(gmux_data); + outb(port & 0xff, gmux_data->iostart + GMUX_PORT_WRITE); + gmux_index_wait_complete(gmux_data); + mutex_unlock(&gmux_data->index_lock); +} + +static u8 gmux_read8(struct apple_gmux_data *gmux_data, int port) +{ + if (gmux_data->indexed) + return gmux_index_read8(gmux_data, port); + else + return gmux_pio_read8(gmux_data, port); +} + +static void gmux_write8(struct apple_gmux_data *gmux_data, int port, u8 val) +{ + if (gmux_data->indexed) + gmux_index_write8(gmux_data, port, val); + else + gmux_pio_write8(gmux_data, port, val); +} + +static u32 gmux_read32(struct apple_gmux_data *gmux_data, int port) +{ + if (gmux_data->indexed) + return gmux_index_read32(gmux_data, port); + else + return gmux_pio_read32(gmux_data, port); +} + +static void gmux_write32(struct apple_gmux_data *gmux_data, int port, + u32 val) +{ + if (gmux_data->indexed) + gmux_index_write32(gmux_data, port, val); + else + gmux_pio_write32(gmux_data, port, val); +} + +static bool gmux_is_indexed(struct apple_gmux_data *gmux_data) +{ + u16 val; + + outb(0xaa, gmux_data->iostart + 0xcc); + outb(0x55, gmux_data->iostart + 0xcd); + outb(0x00, gmux_data->iostart + 0xce); + + val = inb(gmux_data->iostart + 0xcc) | + (inb(gmux_data->iostart + 0xcd) << 8); + + if (val == 0x55aa) + return true; + + return false; +} + static int gmux_get_brightness(struct backlight_device *bd) { struct apple_gmux_data *gmux_data = bl_get_data(bd); @@ -90,16 +258,7 @@ static int gmux_update_status(struct backlight_device *bd) if (bd->props.state & BL_CORE_SUSPENDED) return 0; - /* - * Older gmux versions require writing out lower bytes first then - * setting the upper byte to 0 to flush the values. Newer versions - * accept a single u32 write, but the old method also works, so we - * just use the old method for all gmux versions. - */ - gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS, brightness); - gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS + 1, brightness >> 8); - gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS + 2, brightness >> 16); - gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS + 3, 0); + gmux_write32(gmux_data, GMUX_PORT_BRIGHTNESS, brightness); return 0; } @@ -110,6 +269,146 @@ static const struct backlight_ops gmux_bl_ops = { .update_status = gmux_update_status, }; +static int gmux_switchto(enum vga_switcheroo_client_id id) +{ + if (id == VGA_SWITCHEROO_IGD) { + gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 1); + gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DISPLAY, 2); + gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 2); + } else { + gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 2); + gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DISPLAY, 3); + gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 3); + } + + return 0; +} + +static int gmux_set_discrete_state(struct apple_gmux_data *gmux_data, + enum vga_switcheroo_state state) +{ + INIT_COMPLETION(gmux_data->powerchange_done); + + if (state == VGA_SWITCHEROO_ON) { + gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 1); + gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 3); + pr_debug("Discrete card powered up\n"); + } else { + gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 1); + gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 0); + pr_debug("Discrete card powered down\n"); + } + + gmux_data->power_state = state; + + if (gmux_data->gpe >= 0 && + !wait_for_completion_interruptible_timeout(&gmux_data->powerchange_done, + msecs_to_jiffies(200))) + pr_warn("Timeout waiting for gmux switch to complete\n"); + + return 0; +} + +static int gmux_set_power_state(enum vga_switcheroo_client_id id, + enum vga_switcheroo_state state) +{ + if (id == VGA_SWITCHEROO_IGD) + return 0; + + return gmux_set_discrete_state(apple_gmux_data, state); +} + +static int gmux_get_client_id(struct pci_dev *pdev) +{ + /* + * Early Macbook Pros with switchable graphics use nvidia + * integrated graphics. Hardcode that the 9400M is integrated. + */ + if (pdev->vendor == PCI_VENDOR_ID_INTEL) + return VGA_SWITCHEROO_IGD; + else if (pdev->vendor == PCI_VENDOR_ID_NVIDIA && + pdev->device == 0x0863) + return VGA_SWITCHEROO_IGD; + else + return VGA_SWITCHEROO_DIS; +} + +static enum vga_switcheroo_client_id +gmux_active_client(struct apple_gmux_data *gmux_data) +{ + if (gmux_read8(gmux_data, GMUX_PORT_SWITCH_DISPLAY) == 2) + return VGA_SWITCHEROO_IGD; + + return VGA_SWITCHEROO_DIS; +} + +static struct vga_switcheroo_handler gmux_handler = { + .switchto = gmux_switchto, + .power_state = gmux_set_power_state, + .get_client_id = gmux_get_client_id, +}; + +static inline void gmux_disable_interrupts(struct apple_gmux_data *gmux_data) +{ + gmux_write8(gmux_data, GMUX_PORT_INTERRUPT_ENABLE, + GMUX_INTERRUPT_DISABLE); +} + +static inline void gmux_enable_interrupts(struct apple_gmux_data *gmux_data) +{ + gmux_write8(gmux_data, GMUX_PORT_INTERRUPT_ENABLE, + GMUX_INTERRUPT_ENABLE); +} + +static inline u8 gmux_interrupt_get_status(struct apple_gmux_data *gmux_data) +{ + return gmux_read8(gmux_data, GMUX_PORT_INTERRUPT_STATUS); +} + +static void gmux_clear_interrupts(struct apple_gmux_data *gmux_data) +{ + u8 status; + + /* to clear interrupts write back current status */ + status = gmux_interrupt_get_status(gmux_data); + gmux_write8(gmux_data, GMUX_PORT_INTERRUPT_STATUS, status); +} + +static void gmux_notify_handler(acpi_handle device, u32 value, void *context) +{ + u8 status; + struct pnp_dev *pnp = (struct pnp_dev *)context; + struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp); + + status = gmux_interrupt_get_status(gmux_data); + gmux_disable_interrupts(gmux_data); + pr_debug("Notify handler called: status %d\n", status); + + gmux_clear_interrupts(gmux_data); + gmux_enable_interrupts(gmux_data); + + if (status & GMUX_INTERRUPT_STATUS_POWER) + complete(&gmux_data->powerchange_done); +} + +static int gmux_suspend(struct pnp_dev *pnp, pm_message_t state) +{ + struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp); + gmux_data->resume_client_id = gmux_active_client(gmux_data); + gmux_disable_interrupts(gmux_data); + return 0; +} + +static int gmux_resume(struct pnp_dev *pnp) +{ + struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp); + gmux_enable_interrupts(gmux_data); + gmux_switchto(gmux_data->resume_client_id); + if (gmux_data->power_state == VGA_SWITCHEROO_OFF) + gmux_set_discrete_state(gmux_data, gmux_data->power_state); + return 0; +} + static int __devinit gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) { @@ -119,6 +418,11 @@ static int __devinit gmux_probe(struct pnp_dev *pnp, struct backlight_device *bdev; u8 ver_major, ver_minor, ver_release; int ret = -ENXIO; + acpi_status status; + unsigned long long gpe; + + if (apple_gmux_data) + return -EBUSY; gmux_data = kzalloc(sizeof(*gmux_data), GFP_KERNEL); if (!gmux_data) @@ -147,22 +451,29 @@ static int __devinit gmux_probe(struct pnp_dev *pnp, } /* - * On some machines the gmux is in ACPI even thought the machine - * doesn't really have a gmux. Check for invalid version information - * to detect this. + * Invalid version information may indicate either that the gmux + * device isn't present or that it's a new one that uses indexed + * io */ + ver_major = gmux_read8(gmux_data, GMUX_PORT_VERSION_MAJOR); ver_minor = gmux_read8(gmux_data, GMUX_PORT_VERSION_MINOR); ver_release = gmux_read8(gmux_data, GMUX_PORT_VERSION_RELEASE); if (ver_major == 0xff && ver_minor == 0xff && ver_release == 0xff) { - pr_info("gmux device not present\n"); - ret = -ENODEV; - goto err_release; + if (gmux_is_indexed(gmux_data)) { + mutex_init(&gmux_data->index_lock); + gmux_data->indexed = true; + } else { + pr_info("gmux device not present\n"); + ret = -ENODEV; + goto err_release; + } + pr_info("Found indexed gmux\n"); + } else { + pr_info("Found gmux version %d.%d.%d\n", ver_major, ver_minor, + ver_release); } - pr_info("Found gmux version %d.%d.%d\n", ver_major, ver_minor, - ver_release); - memset(&props, 0, sizeof(props)); props.type = BACKLIGHT_PLATFORM; props.max_brightness = gmux_read32(gmux_data, GMUX_PORT_MAX_BRIGHTNESS); @@ -194,13 +505,67 @@ static int __devinit gmux_probe(struct pnp_dev *pnp, * Disable the other backlight choices. */ acpi_video_dmi_promote_vendor(); -#ifdef CONFIG_ACPI_VIDEO +#if defined (CONFIG_ACPI_VIDEO) || defined (CONFIG_ACPI_VIDEO_MODULE) acpi_video_unregister(); #endif apple_bl_unregister(); + gmux_data->power_state = VGA_SWITCHEROO_ON; + + gmux_data->dhandle = DEVICE_ACPI_HANDLE(&pnp->dev); + if (!gmux_data->dhandle) { + pr_err("Cannot find acpi handle for pnp device %s\n", + dev_name(&pnp->dev)); + ret = -ENODEV; + goto err_notify; + } + + status = acpi_evaluate_integer(gmux_data->dhandle, "GMGP", NULL, &gpe); + if (ACPI_SUCCESS(status)) { + gmux_data->gpe = (int)gpe; + + status = acpi_install_notify_handler(gmux_data->dhandle, + ACPI_DEVICE_NOTIFY, + &gmux_notify_handler, pnp); + if (ACPI_FAILURE(status)) { + pr_err("Install notify handler failed: %s\n", + acpi_format_exception(status)); + ret = -ENODEV; + goto err_notify; + } + + status = acpi_enable_gpe(NULL, gmux_data->gpe); + if (ACPI_FAILURE(status)) { + pr_err("Cannot enable gpe: %s\n", + acpi_format_exception(status)); + goto err_enable_gpe; + } + } else { + pr_warn("No GPE found for gmux\n"); + gmux_data->gpe = -1; + } + + if (vga_switcheroo_register_handler(&gmux_handler)) { + ret = -ENODEV; + goto err_register_handler; + } + + init_completion(&gmux_data->powerchange_done); + apple_gmux_data = gmux_data; + gmux_enable_interrupts(gmux_data); + return 0; +err_register_handler: + if (gmux_data->gpe >= 0) + acpi_disable_gpe(NULL, gmux_data->gpe); +err_enable_gpe: + if (gmux_data->gpe >= 0) + acpi_remove_notify_handler(gmux_data->dhandle, + ACPI_DEVICE_NOTIFY, + &gmux_notify_handler); +err_notify: + backlight_device_unregister(bdev); err_release: release_region(gmux_data->iostart, gmux_data->iolen); err_free: @@ -212,12 +577,23 @@ static void __devexit gmux_remove(struct pnp_dev *pnp) { struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp); + vga_switcheroo_unregister_handler(); + gmux_disable_interrupts(gmux_data); + if (gmux_data->gpe >= 0) { + acpi_disable_gpe(NULL, gmux_data->gpe); + acpi_remove_notify_handler(gmux_data->dhandle, + ACPI_DEVICE_NOTIFY, + &gmux_notify_handler); + } + backlight_device_unregister(gmux_data->bdev); + release_region(gmux_data->iostart, gmux_data->iolen); + apple_gmux_data = NULL; kfree(gmux_data); acpi_video_dmi_demote_vendor(); -#ifdef CONFIG_ACPI_VIDEO +#if defined (CONFIG_ACPI_VIDEO) || defined (CONFIG_ACPI_VIDEO_MODULE) acpi_video_register(); #endif apple_bl_register(); @@ -233,6 +609,8 @@ static struct pnp_driver gmux_pnp_driver = { .probe = gmux_probe, .remove = __devexit_p(gmux_remove), .id_table = gmux_device_ids, + .suspend = gmux_suspend, + .resume = gmux_resume }; static int __init apple_gmux_init(void) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index c7a36f6b0580..2eb9fe8e8efd 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -101,6 +101,7 @@ MODULE_LICENSE("GPL"); #define ASUS_WMI_DEVID_WIRELESS_LED 0x00010002 #define ASUS_WMI_DEVID_CWAP 0x00010003 #define ASUS_WMI_DEVID_WLAN 0x00010011 +#define ASUS_WMI_DEVID_WLAN_LED 0x00010012 #define ASUS_WMI_DEVID_BLUETOOTH 0x00010013 #define ASUS_WMI_DEVID_GPS 0x00010015 #define ASUS_WMI_DEVID_WIMAX 0x00010017 @@ -731,8 +732,21 @@ static int asus_rfkill_set(void *data, bool blocked) { struct asus_rfkill *priv = data; u32 ctrl_param = !blocked; + u32 dev_id = priv->dev_id; - return asus_wmi_set_devstate(priv->dev_id, ctrl_param, NULL); + /* + * If the user bit is set, BIOS can't set and record the wlan status, + * it will report the value read from id ASUS_WMI_DEVID_WLAN_LED + * while we query the wlan status through WMI(ASUS_WMI_DEVID_WLAN). + * So, we have to record wlan status in id ASUS_WMI_DEVID_WLAN_LED + * while setting the wlan status through WMI. + * This is also the behavior that windows app will do. + */ + if ((dev_id == ASUS_WMI_DEVID_WLAN) && + priv->asus->driver->wlan_ctrl_by_user) + dev_id = ASUS_WMI_DEVID_WLAN_LED; + + return asus_wmi_set_devstate(dev_id, ctrl_param, NULL); } static void asus_rfkill_query(struct rfkill *rfkill, void *data) @@ -1653,6 +1667,7 @@ static int asus_wmi_add(struct platform_device *pdev) struct asus_wmi *asus; acpi_status status; int err; + u32 result; asus = kzalloc(sizeof(struct asus_wmi), GFP_KERNEL); if (!asus) @@ -1711,6 +1726,10 @@ static int asus_wmi_add(struct platform_device *pdev) if (err) goto fail_debugfs; + asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WLAN, &result); + if (result & (ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT)) + asus->driver->wlan_ctrl_by_user = 1; + return 0; fail_debugfs: diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h index 9c1da8b81bea..4c9bd38bb0a2 100644 --- a/drivers/platform/x86/asus-wmi.h +++ b/drivers/platform/x86/asus-wmi.h @@ -46,6 +46,7 @@ struct quirk_entry { struct asus_wmi_driver { int brightness; int panel_power; + int wlan_ctrl_by_user; const char *name; struct module *owner; diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c index cd33add118ce..c87ff16873f9 100644 --- a/drivers/platform/x86/classmate-laptop.c +++ b/drivers/platform/x86/classmate-laptop.c @@ -725,8 +725,10 @@ static void cmpc_tablet_handler(struct acpi_device *dev, u32 event) struct input_dev *inputdev = dev_get_drvdata(&dev->dev); if (event == 0x81) { - if (ACPI_SUCCESS(cmpc_get_tablet(dev->handle, &val))) + if (ACPI_SUCCESS(cmpc_get_tablet(dev->handle, &val))) { input_report_switch(inputdev, SW_TABLET_MODE, !val); + input_sync(inputdev); + } } } @@ -739,8 +741,10 @@ static void cmpc_tablet_idev_init(struct input_dev *inputdev) set_bit(SW_TABLET_MODE, inputdev->swbit); acpi = to_acpi_device(inputdev->dev.parent); - if (ACPI_SUCCESS(cmpc_get_tablet(acpi->handle, &val))) + if (ACPI_SUCCESS(cmpc_get_tablet(acpi->handle, &val))) { input_report_switch(inputdev, SW_TABLET_MODE, !val); + input_sync(inputdev); + } } static int cmpc_tablet_add(struct acpi_device *acpi) @@ -760,8 +764,10 @@ static int cmpc_tablet_resume(struct device *dev) struct input_dev *inputdev = dev_get_drvdata(dev); unsigned long long val = 0; - if (ACPI_SUCCESS(cmpc_get_tablet(to_acpi_device(dev)->handle, &val))) + if (ACPI_SUCCESS(cmpc_get_tablet(to_acpi_device(dev)->handle, &val))) { input_report_switch(inputdev, SW_TABLET_MODE, !val); + input_sync(inputdev); + } return 0; } #endif diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 4e96e8c0b60f..927c33af67ec 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -211,7 +211,7 @@ static struct dmi_system_id __devinitdata dell_quirks[] = { .ident = "Dell Inspiron 5420", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 5420"), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5420"), }, .driver_data = &quirk_dell_vostro_v130, }, @@ -220,7 +220,7 @@ static struct dmi_system_id __devinitdata dell_quirks[] = { .ident = "Dell Inspiron 5520", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 5520"), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5520"), }, .driver_data = &quirk_dell_vostro_v130, }, @@ -229,7 +229,7 @@ static struct dmi_system_id __devinitdata dell_quirks[] = { .ident = "Dell Inspiron 5720", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 5720"), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5720"), }, .driver_data = &quirk_dell_vostro_v130, }, @@ -238,7 +238,7 @@ static struct dmi_system_id __devinitdata dell_quirks[] = { .ident = "Dell Inspiron 7420", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 7420"), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7420"), }, .driver_data = &quirk_dell_vostro_v130, }, @@ -247,7 +247,7 @@ static struct dmi_system_id __devinitdata dell_quirks[] = { .ident = "Dell Inspiron 7520", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 7520"), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7520"), }, .driver_data = &quirk_dell_vostro_v130, }, @@ -256,7 +256,7 @@ static struct dmi_system_id __devinitdata dell_quirks[] = { .ident = "Dell Inspiron 7720", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 7720"), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7720"), }, .driver_data = &quirk_dell_vostro_v130, }, diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 17f6dfd8dbfb..dae7abe1d711 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -36,6 +36,7 @@ #include <linux/fb.h> #include <linux/debugfs.h> #include <linux/seq_file.h> +#include <linux/i8042.h> #define IDEAPAD_RFKILL_DEV_NUM (3) @@ -63,8 +64,11 @@ enum { VPCCMD_R_3G, VPCCMD_W_3G, VPCCMD_R_ODD, /* 0x21 */ - VPCCMD_R_RF = 0x23, + VPCCMD_W_FAN, + VPCCMD_R_RF, VPCCMD_W_RF, + VPCCMD_R_FAN = 0x2B, + VPCCMD_R_SPECIAL_BUTTONS = 0x31, VPCCMD_W_BL_POWER = 0x33, }; @@ -356,14 +360,46 @@ static ssize_t store_ideapad_cam(struct device *dev, return -EINVAL; ret = write_ec_cmd(ideapad_handle, VPCCMD_W_CAMERA, state); if (ret < 0) - return ret; + return -EIO; return count; } static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam); +static ssize_t show_ideapad_fan(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + unsigned long result; + + if (read_ec_data(ideapad_handle, VPCCMD_R_FAN, &result)) + return sprintf(buf, "-1\n"); + return sprintf(buf, "%lu\n", result); +} + +static ssize_t store_ideapad_fan(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int ret, state; + + if (!count) + return 0; + if (sscanf(buf, "%i", &state) != 1) + return -EINVAL; + if (state < 0 || state > 4 || state == 3) + return -EINVAL; + ret = write_ec_cmd(ideapad_handle, VPCCMD_W_FAN, state); + if (ret < 0) + return -EIO; + return count; +} + +static DEVICE_ATTR(fan_mode, 0644, show_ideapad_fan, store_ideapad_fan); + static struct attribute *ideapad_attributes[] = { &dev_attr_camera_power.attr, + &dev_attr_fan_mode.attr, NULL }; @@ -377,7 +413,10 @@ static umode_t ideapad_is_visible(struct kobject *kobj, if (attr == &dev_attr_camera_power.attr) supported = test_bit(CFG_CAMERA_BIT, &(priv->cfg)); - else + else if (attr == &dev_attr_fan_mode.attr) { + unsigned long value; + supported = !read_ec_data(ideapad_handle, VPCCMD_R_FAN, &value); + } else supported = true; return supported ? attr->mode : 0; @@ -518,9 +557,15 @@ static void ideapad_platform_exit(struct ideapad_private *priv) */ static const struct key_entry ideapad_keymap[] = { { KE_KEY, 6, { KEY_SWITCHVIDEOMODE } }, + { KE_KEY, 7, { KEY_CAMERA } }, + { KE_KEY, 11, { KEY_F16 } }, { KE_KEY, 13, { KEY_WLAN } }, { KE_KEY, 16, { KEY_PROG1 } }, { KE_KEY, 17, { KEY_PROG2 } }, + { KE_KEY, 64, { KEY_PROG3 } }, + { KE_KEY, 65, { KEY_PROG4 } }, + { KE_KEY, 66, { KEY_TOUCHPAD_OFF } }, + { KE_KEY, 67, { KEY_TOUCHPAD_ON } }, { KE_END, 0 }, }; @@ -587,6 +632,28 @@ static void ideapad_input_novokey(struct ideapad_private *priv) ideapad_input_report(priv, 16); } +static void ideapad_check_special_buttons(struct ideapad_private *priv) +{ + unsigned long bit, value; + + read_ec_data(ideapad_handle, VPCCMD_R_SPECIAL_BUTTONS, &value); + + for (bit = 0; bit < 16; bit++) { + if (test_bit(bit, &value)) { + switch (bit) { + case 6: + /* Thermal Management button */ + ideapad_input_report(priv, 65); + break; + case 1: + /* OneKey Theater button */ + ideapad_input_report(priv, 64); + break; + } + } + } +} + /* * backlight */ @@ -691,6 +758,24 @@ static const struct acpi_device_id ideapad_device_ids[] = { }; MODULE_DEVICE_TABLE(acpi, ideapad_device_ids); +static void ideapad_sync_touchpad_state(struct acpi_device *adevice) +{ + struct ideapad_private *priv = dev_get_drvdata(&adevice->dev); + unsigned long value; + + /* Without reading from EC touchpad LED doesn't switch state */ + if (!read_ec_data(adevice->handle, VPCCMD_R_TOUCHPAD, &value)) { + /* Some IdeaPads don't really turn off touchpad - they only + * switch the LED state. We (de)activate KBC AUX port to turn + * touchpad off and on. We send KEY_TOUCHPAD_OFF and + * KEY_TOUCHPAD_ON to not to get out of sync with LED */ + unsigned char param; + i8042_command(¶m, value ? I8042_CMD_AUX_ENABLE : + I8042_CMD_AUX_DISABLE); + ideapad_input_report(priv, value ? 67 : 66); + } +} + static int __devinit ideapad_acpi_add(struct acpi_device *adevice) { int ret, i; @@ -727,6 +812,7 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice) priv->rfk[i] = NULL; } ideapad_sync_rfk_state(priv); + ideapad_sync_touchpad_state(adevice); if (!acpi_video_backlight_support()) { ret = ideapad_backlight_init(priv); @@ -785,9 +871,14 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event) ideapad_sync_rfk_state(priv); break; case 13: + case 11: + case 7: case 6: ideapad_input_report(priv, vpc_bit); break; + case 5: + ideapad_sync_touchpad_state(adevice); + break; case 4: ideapad_backlight_notify_brightness(priv); break; @@ -797,6 +888,9 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event) case 2: ideapad_backlight_notify_power(priv); break; + case 0: + ideapad_check_special_buttons(priv); + break; default: pr_info("Unknown event: %lu\n", vpc_bit); } @@ -804,6 +898,15 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event) } } +static int ideapad_acpi_resume(struct device *device) +{ + ideapad_sync_rfk_state(ideapad_priv); + ideapad_sync_touchpad_state(to_acpi_device(device)); + return 0; +} + +static SIMPLE_DEV_PM_OPS(ideapad_pm, NULL, ideapad_acpi_resume); + static struct acpi_driver ideapad_acpi_driver = { .name = "ideapad_acpi", .class = "IdeaPad", @@ -811,6 +914,7 @@ static struct acpi_driver ideapad_acpi_driver = { .ops.add = ideapad_acpi_add, .ops.remove = ideapad_acpi_remove, .ops.notify = ideapad_acpi_notify, + .drv.pm = &ideapad_pm, .owner = THIS_MODULE, }; diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index f28f36ccdcf4..80e377949314 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -8664,6 +8664,13 @@ static int __must_check __init get_thinkpad_model_data( tp->model_str = kstrdup(s, GFP_KERNEL); if (!tp->model_str) return -ENOMEM; + } else { + s = dmi_get_system_info(DMI_BIOS_VENDOR); + if (s && !(strnicmp(s, "Lenovo", 6))) { + tp->model_str = kstrdup(s, GFP_KERNEL); + if (!tp->model_str) + return -ENOMEM; + } } s = dmi_get_system_info(DMI_PRODUCT_NAME); diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index 722246cf20ab..5d44252b7342 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -435,6 +435,9 @@ static void tsi721_db_dpc(struct work_struct *work) " info %4.4x\n", DBELL_SID(idb.bytes), DBELL_TID(idb.bytes), DBELL_INF(idb.bytes)); } + + wr_ptr = ioread32(priv->regs + + TSI721_IDQ_WP(IDB_QUEUE)) % IDB_QSIZE; } iowrite32(rd_ptr & (IDB_QSIZE - 1), @@ -445,6 +448,10 @@ static void tsi721_db_dpc(struct work_struct *work) regval |= TSI721_SR_CHINT_IDBQRCV; iowrite32(regval, priv->regs + TSI721_SR_CHINTE(IDB_QUEUE)); + + wr_ptr = ioread32(priv->regs + TSI721_IDQ_WP(IDB_QUEUE)) % IDB_QSIZE; + if (wr_ptr != rd_ptr) + schedule_work(&priv->idb_work); } /** @@ -2212,7 +2219,7 @@ static int __devinit tsi721_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct tsi721_device *priv; - int i, cap; + int cap; int err; u32 regval; @@ -2232,12 +2239,15 @@ static int __devinit tsi721_probe(struct pci_dev *pdev, priv->pdev = pdev; #ifdef DEBUG + { + int i; for (i = 0; i <= PCI_STD_RESOURCE_END; i++) { dev_dbg(&pdev->dev, "res[%d] @ 0x%llx (0x%lx, 0x%lx)\n", i, (unsigned long long)pci_resource_start(pdev, i), (unsigned long)pci_resource_len(pdev, i), pci_resource_flags(pdev, i)); } + } #endif /* * Verify BAR configuration diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index 182b553059c9..c151fd5d8c97 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c @@ -486,6 +486,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { .id = AB3100_BUCK, .ops = ®ulator_ops_variable_sleepable, .n_voltages = ARRAY_SIZE(ldo_e_buck_typ_voltages), + .volt_table = ldo_e_buck_typ_voltages, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .enable_time = 1000, diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c index e9c2085f9dfb..ce0fe72a428e 100644 --- a/drivers/regulator/anatop-regulator.c +++ b/drivers/regulator/anatop-regulator.c @@ -64,14 +64,15 @@ static int anatop_set_voltage_sel(struct regulator_dev *reg, unsigned selector) static int anatop_get_voltage_sel(struct regulator_dev *reg) { struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); - u32 val; + u32 val, mask; if (!anatop_reg->control_reg) return -ENOTSUPP; val = anatop_read_reg(anatop_reg->mfd, anatop_reg->control_reg); - val = (val & ((1 << anatop_reg->vol_bit_width) - 1)) >> + mask = ((1 << anatop_reg->vol_bit_width) - 1) << anatop_reg->vol_bit_shift; + val = (val & mask) >> anatop_reg->vol_bit_shift; return val - anatop_reg->min_bit_val; } diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index f092588a078c..48385318175a 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3217,7 +3217,7 @@ regulator_register(const struct regulator_desc *regulator_desc, dev_set_drvdata(&rdev->dev, rdev); - if (config->ena_gpio) { + if (config->ena_gpio && gpio_is_valid(config->ena_gpio)) { ret = gpio_request_one(config->ena_gpio, GPIOF_DIR_OUT | config->ena_gpio_flags, rdev_get_name(rdev)); diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index 34b67bee9323..8b5944f2d7d1 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -57,16 +57,17 @@ static int gpio_regulator_get_value(struct regulator_dev *dev) return -EINVAL; } -static int gpio_regulator_set_value(struct regulator_dev *dev, - int min, int max, unsigned *selector) +static int gpio_regulator_set_voltage(struct regulator_dev *dev, + int min_uV, int max_uV, + unsigned *selector) { struct gpio_regulator_data *data = rdev_get_drvdata(dev); int ptr, target = 0, state, best_val = INT_MAX; for (ptr = 0; ptr < data->nr_states; ptr++) if (data->states[ptr].value < best_val && - data->states[ptr].value >= min && - data->states[ptr].value <= max) { + data->states[ptr].value >= min_uV && + data->states[ptr].value <= max_uV) { target = data->states[ptr].gpios; best_val = data->states[ptr].value; if (selector) @@ -85,13 +86,6 @@ static int gpio_regulator_set_value(struct regulator_dev *dev, return 0; } -static int gpio_regulator_set_voltage(struct regulator_dev *dev, - int min_uV, int max_uV, - unsigned *selector) -{ - return gpio_regulator_set_value(dev, min_uV, max_uV, selector); -} - static int gpio_regulator_list_voltage(struct regulator_dev *dev, unsigned selector) { @@ -106,7 +100,27 @@ static int gpio_regulator_list_voltage(struct regulator_dev *dev, static int gpio_regulator_set_current_limit(struct regulator_dev *dev, int min_uA, int max_uA) { - return gpio_regulator_set_value(dev, min_uA, max_uA, NULL); + struct gpio_regulator_data *data = rdev_get_drvdata(dev); + int ptr, target = 0, state, best_val = 0; + + for (ptr = 0; ptr < data->nr_states; ptr++) + if (data->states[ptr].value > best_val && + data->states[ptr].value >= min_uA && + data->states[ptr].value <= max_uA) { + target = data->states[ptr].gpios; + best_val = data->states[ptr].value; + } + + if (best_val == 0) + return -EINVAL; + + for (ptr = 0; ptr < data->nr_gpios; ptr++) { + state = (target & (1 << ptr)) >> ptr; + gpio_set_value(data->gpios[ptr].gpio, state); + } + data->state = target; + + return 0; } static struct regulator_ops gpio_regulator_voltage_ops = { diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index 17d19fbbc490..46c7e88f8381 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c @@ -486,9 +486,12 @@ static int palmas_map_voltage_ldo(struct regulator_dev *rdev, { int ret, voltage; - ret = ((min_uV - 900000) / 50000) + 1; - if (ret < 0) - return ret; + if (min_uV == 0) + return 0; + + if (min_uV < 900000) + min_uV = 900000; + ret = DIV_ROUND_UP(min_uV - 900000, 50000) + 1; /* Map back into a voltage to verify we're still in bounds */ voltage = palmas_list_voltage_ldo(rdev, ret); @@ -586,7 +589,7 @@ static int palmas_ldo_init(struct palmas *palmas, int id, addr = palmas_regs_info[id].ctrl_addr; - ret = palmas_smps_read(palmas, addr, ®); + ret = palmas_ldo_read(palmas, addr, ®); if (ret) return ret; @@ -596,7 +599,7 @@ static int palmas_ldo_init(struct palmas *palmas, int id, if (reg_init->mode_sleep) reg |= PALMAS_LDO1_CTRL_MODE_SLEEP; - ret = palmas_smps_write(palmas, addr, reg); + ret = palmas_ldo_write(palmas, addr, reg); if (ret) return ret; @@ -630,7 +633,7 @@ static __devinit int palmas_probe(struct platform_device *pdev) ret = palmas_smps_read(palmas, PALMAS_SMPS_CTRL, ®); if (ret) - goto err_unregister_regulator; + return ret; if (reg & PALMAS_SMPS_CTRL_SMPS12_SMPS123_EN) pmic->smps123 = 1; @@ -676,7 +679,9 @@ static __devinit int palmas_probe(struct platform_device *pdev) case PALMAS_REG_SMPS10: pmic->desc[id].n_voltages = PALMAS_SMPS10_NUM_VOLTAGES; pmic->desc[id].ops = &palmas_ops_smps10; - pmic->desc[id].vsel_reg = PALMAS_SMPS10_CTRL; + pmic->desc[id].vsel_reg = + PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE, + PALMAS_SMPS10_CTRL); pmic->desc[id].vsel_mask = SMPS10_VSEL; pmic->desc[id].enable_reg = PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE, @@ -778,8 +783,10 @@ static __devinit int palmas_probe(struct platform_device *pdev) reg_init = pdata->reg_init[id]; if (reg_init) { ret = palmas_ldo_init(palmas, id, reg_init); - if (ret) + if (ret) { + regulator_unregister(pmic->rdev[id]); goto err_unregister_regulator; + } } } } diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index e6da90ab5153..19241fc30050 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c @@ -240,14 +240,16 @@ static struct tps6586x_regulator tps6586x_regulator[] = { TPS6586X_LDO(LDO_9, "vinldo9", ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7), TPS6586X_LDO(LDO_RTC, NULL, ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7), TPS6586X_LDO(LDO_1, "vinldo01", dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1), - TPS6586X_LDO(SM_2, "sm2", sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7), + TPS6586X_LDO(SM_2, "vin-sm2", sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7), TPS6586X_DVM(LDO_2, "vinldo23", dvm, LDO2BV1, 0, 5, ENA, 3, ENB, 3, VCC2, 6), TPS6586X_DVM(LDO_4, "vinldo4", ldo4, LDO4V1, 0, 5, ENC, 3, END, 3, VCC1, 6), - TPS6586X_DVM(SM_0, "sm0", dvm, SM0V1, 0, 5, ENA, 1, ENB, 1, VCC1, 2), - TPS6586X_DVM(SM_1, "sm1", dvm, SM1V1, 0, 5, ENA, 0, ENB, 0, VCC1, 0), + TPS6586X_DVM(SM_0, "vin-sm0", dvm, SM0V1, 0, 5, ENA, 1, + ENB, 1, VCC1, 2), + TPS6586X_DVM(SM_1, "vin-sm1", dvm, SM1V1, 0, 5, ENA, 0, + ENB, 0, VCC1, 0), }; /* diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 242fe90dc565..77a71a5c17c3 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -1037,7 +1037,7 @@ TWL6025_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300); TWL6025_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300); TWL6025_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300); TWL6025_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300); -TWL4030_FIXED_LDO(VINTANA2, 0x3f, 1500, 11, 100, 0x08); +TWL4030_FIXED_LDO(VINTANA1, 0x3f, 1500, 11, 100, 0x08); TWL4030_FIXED_LDO(VINTDIG, 0x47, 1500, 13, 100, 0x08); TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17, 100, 0x08); TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18, 100, 0x08); @@ -1048,7 +1048,6 @@ TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 0); TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 0); TWL6030_FIXED_LDO(V1V8, 0x16, 1800, 0); TWL6030_FIXED_LDO(V2V1, 0x1c, 2100, 0); -TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 0); TWL6025_ADJUSTABLE_SMPS(SMPS3, 0x34); TWL6025_ADJUSTABLE_SMPS(SMPS4, 0x10); TWL6025_ADJUSTABLE_SMPS(VIO, 0x16); @@ -1117,7 +1116,7 @@ static const struct of_device_id twl_of_match[] __devinitconst = { TWL6025_OF_MATCH("ti,twl6025-ldo6", LDO6), TWL6025_OF_MATCH("ti,twl6025-ldoln", LDOLN), TWL6025_OF_MATCH("ti,twl6025-ldousb", LDOUSB), - TWLFIXED_OF_MATCH("ti,twl4030-vintana2", VINTANA2), + TWLFIXED_OF_MATCH("ti,twl4030-vintana1", VINTANA1), TWLFIXED_OF_MATCH("ti,twl4030-vintdig", VINTDIG), TWLFIXED_OF_MATCH("ti,twl4030-vusb1v5", VUSB1V5), TWLFIXED_OF_MATCH("ti,twl4030-vusb1v8", VUSB1V8), diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index 836118795c0b..13e4df63974f 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c @@ -43,6 +43,7 @@ #include <linux/rtc.h> #include <linux/spi/spi.h> #include <linux/module.h> +#include <linux/sysfs.h> #define DRV_VERSION "0.6" @@ -292,6 +293,7 @@ static int __devinit pcf2123_probe(struct spi_device *spi) pdata->rtc = rtc; for (i = 0; i < 16; i++) { + sysfs_attr_init(&pdata->regs[i].attr.attr); sprintf(pdata->regs[i].name, "%1x", i); pdata->regs[i].attr.attr.mode = S_IRUGO | S_IWUSR; pdata->regs[i].attr.attr.name = pdata->regs[i].name; diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c index 77074ccd2850..fd5c7af04ae5 100644 --- a/drivers/rtc/rtc-rs5c348.c +++ b/drivers/rtc/rtc-rs5c348.c @@ -122,9 +122,12 @@ rs5c348_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_min = bcd2bin(rxbuf[RS5C348_REG_MINS] & RS5C348_MINS_MASK); tm->tm_hour = bcd2bin(rxbuf[RS5C348_REG_HOURS] & RS5C348_HOURS_MASK); if (!pdata->rtc_24h) { - tm->tm_hour %= 12; - if (rxbuf[RS5C348_REG_HOURS] & RS5C348_BIT_PM) + if (rxbuf[RS5C348_REG_HOURS] & RS5C348_BIT_PM) { + tm->tm_hour -= 20; + tm->tm_hour %= 12; tm->tm_hour += 12; + } else + tm->tm_hour %= 12; } tm->tm_wday = bcd2bin(rxbuf[RS5C348_REG_WDAY] & RS5C348_WDAY_MASK); tm->tm_mday = bcd2bin(rxbuf[RS5C348_REG_DAY] & RS5C348_DAY_MASK); diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index 6e25ef1bce91..ea0aaa3f13d0 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -438,7 +438,7 @@ out: static int __devexit bcm63xx_spi_remove(struct platform_device *pdev) { - struct spi_master *master = platform_get_drvdata(pdev); + struct spi_master *master = spi_master_get(platform_get_drvdata(pdev)); struct bcm63xx_spi *bs = spi_master_get_devdata(master); spi_unregister_master(master); @@ -452,6 +452,8 @@ static int __devexit bcm63xx_spi_remove(struct platform_device *pdev) platform_set_drvdata(pdev, 0); + spi_master_put(master); + return 0; } diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c index b2d4b9e4e010..764bfee75920 100644 --- a/drivers/spi/spi-coldfire-qspi.c +++ b/drivers/spi/spi-coldfire-qspi.c @@ -533,7 +533,6 @@ static int __devexit mcfqspi_remove(struct platform_device *pdev) iounmap(mcfqspi->iobase); release_mem_region(res->start, resource_size(res)); spi_unregister_master(master); - spi_master_put(master); return 0; } @@ -541,7 +540,7 @@ static int __devexit mcfqspi_remove(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP static int mcfqspi_suspend(struct device *dev) { - struct spi_master *master = spi_master_get(dev_get_drvdata(dev)); + struct spi_master *master = dev_get_drvdata(dev); struct mcfqspi *mcfqspi = spi_master_get_devdata(master); spi_master_suspend(master); @@ -553,7 +552,7 @@ static int mcfqspi_suspend(struct device *dev) static int mcfqspi_resume(struct device *dev) { - struct spi_master *master = spi_master_get(dev_get_drvdata(dev)); + struct spi_master *master = dev_get_drvdata(dev); struct mcfqspi *mcfqspi = spi_master_get_devdata(master); spi_master_resume(master); diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index bc4778175e34..b2fb141da375 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -1228,18 +1228,16 @@ static int __devinit omap2_mcspi_probe(struct platform_device *pdev) status = spi_register_master(master); if (status < 0) - goto err_spi_register; + goto disable_pm; return status; -err_spi_register: - spi_master_put(master); disable_pm: pm_runtime_disable(&pdev->dev); dma_chnl_free: kfree(mcspi->dma_channels); free_master: - kfree(master); + spi_master_put(master); platform_set_drvdata(pdev, NULL); return status; } diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index aab518ec2bbc..6abbe23c39b4 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -2053,7 +2053,6 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n", adev->res.start, pl022->virtbase); - pm_runtime_enable(dev); pm_runtime_resume(dev); pl022->clk = clk_get(&adev->dev, NULL); diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index cfa2c35dfeed..d1c8441f638c 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1479,40 +1479,40 @@ static const struct dev_pm_ops s3c64xx_spi_pm = { s3c64xx_spi_runtime_resume, NULL) }; -struct s3c64xx_spi_port_config s3c2443_spi_port_config = { +static struct s3c64xx_spi_port_config s3c2443_spi_port_config = { .fifo_lvl_mask = { 0x7f }, .rx_lvl_offset = 13, .tx_st_done = 21, .high_speed = true, }; -struct s3c64xx_spi_port_config s3c6410_spi_port_config = { +static struct s3c64xx_spi_port_config s3c6410_spi_port_config = { .fifo_lvl_mask = { 0x7f, 0x7F }, .rx_lvl_offset = 13, .tx_st_done = 21, }; -struct s3c64xx_spi_port_config s5p64x0_spi_port_config = { +static struct s3c64xx_spi_port_config s5p64x0_spi_port_config = { .fifo_lvl_mask = { 0x1ff, 0x7F }, .rx_lvl_offset = 15, .tx_st_done = 25, }; -struct s3c64xx_spi_port_config s5pc100_spi_port_config = { +static struct s3c64xx_spi_port_config s5pc100_spi_port_config = { .fifo_lvl_mask = { 0x7f, 0x7F }, .rx_lvl_offset = 13, .tx_st_done = 21, .high_speed = true, }; -struct s3c64xx_spi_port_config s5pv210_spi_port_config = { +static struct s3c64xx_spi_port_config s5pv210_spi_port_config = { .fifo_lvl_mask = { 0x1ff, 0x7F }, .rx_lvl_offset = 15, .tx_st_done = 25, .high_speed = true, }; -struct s3c64xx_spi_port_config exynos4_spi_port_config = { +static struct s3c64xx_spi_port_config exynos4_spi_port_config = { .fifo_lvl_mask = { 0x1ff, 0x7F, 0x7F }, .rx_lvl_offset = 15, .tx_st_done = 25, diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index b06fd5b723fa..d536756549e6 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -189,7 +189,7 @@ DEVICE_PARAM(b80211hEnable, "802.11h mode"); // Static vars definitions // -static struct usb_device_id vt6656_table[] __devinitdata = { +static struct usb_device_id vt6656_table[] = { {USB_DEVICE(VNT_USB_VENDOR_ID, VNT_USB_PRODUCT_ID)}, {} }; diff --git a/drivers/staging/winbond/wbusb.c b/drivers/staging/winbond/wbusb.c index ef360547ecec..0ca857ac473e 100644 --- a/drivers/staging/winbond/wbusb.c +++ b/drivers/staging/winbond/wbusb.c @@ -25,7 +25,7 @@ MODULE_DESCRIPTION("IS89C35 802.11bg WLAN USB Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION("0.1"); -static const struct usb_device_id wb35_table[] __devinitconst = { +static const struct usb_device_id wb35_table[] = { { USB_DEVICE(0x0416, 0x0035) }, { USB_DEVICE(0x18E8, 0x6201) }, { USB_DEVICE(0x18E8, 0x6206) }, diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index a7773a3e02b1..7065df6036ca 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -13,7 +13,7 @@ config USB_ARCH_HAS_OHCI default y if PXA3xx default y if ARCH_EP93XX default y if ARCH_AT91 - default y if ARCH_PNX4008 && I2C + default y if ARCH_PNX4008 default y if MFD_TC6393XB default y if ARCH_W90X900 default y if ARCH_DAVINCI_DA8XX diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 56d6bf668488..f763ed7ba91e 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1104,7 +1104,8 @@ skip_normal_probe: } - if (data_interface->cur_altsetting->desc.bNumEndpoints < 2) + if (data_interface->cur_altsetting->desc.bNumEndpoints < 2 || + control_interface->cur_altsetting->desc.bNumEndpoints == 0) return -EINVAL; epctrl = &control_interface->cur_altsetting->endpoint[0].desc; diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c index ff08015b230c..ae794b90766b 100644 --- a/drivers/usb/misc/emi62.c +++ b/drivers/usb/misc/emi62.c @@ -232,7 +232,7 @@ wraperr: return err; } -static const struct usb_device_id id_table[] __devinitconst = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(EMI62_VENDOR_ID, EMI62_PRODUCT_ID) }, { } /* Terminating entry */ }; diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 2e471c22abf5..f8a79fca4a22 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -372,8 +372,12 @@ static void fb_flashcursor(struct work_struct *work) struct vc_data *vc = NULL; int c; int mode; + int ret; + + ret = console_trylock(); + if (ret == 0) + return; - console_lock(); if (ops && ops->currcon != -1) vc = vc_cons[ops->currcon].d; |