diff options
Diffstat (limited to 'drivers')
89 files changed, 1125 insertions, 582 deletions
diff --git a/drivers/acpi/acpi_cmos_rtc.c b/drivers/acpi/acpi_cmos_rtc.c index 2da8660262e..81dc75033f1 100644 --- a/drivers/acpi/acpi_cmos_rtc.c +++ b/drivers/acpi/acpi_cmos_rtc.c @@ -33,7 +33,7 @@ acpi_cmos_rtc_space_handler(u32 function, acpi_physical_address address, void *handler_context, void *region_context) { int i; - u8 *value = (u8 *)&value64; + u8 *value = (u8 *)value64; if (address > 0xff || !value64) return AE_BAD_PARAMETER; diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 9dfec48dd4e..fddc1e86f9d 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -610,7 +610,7 @@ static int acpi_lpss_suspend_late(struct device *dev) return acpi_dev_suspend_late(dev); } -static int acpi_lpss_restore_early(struct device *dev) +static int acpi_lpss_resume_early(struct device *dev) { int ret = acpi_dev_resume_early(dev); @@ -650,15 +650,15 @@ static int acpi_lpss_runtime_resume(struct device *dev) static struct dev_pm_domain acpi_lpss_pm_domain = { .ops = { #ifdef CONFIG_PM_SLEEP - .suspend_late = acpi_lpss_suspend_late, - .restore_early = acpi_lpss_restore_early, .prepare = acpi_subsys_prepare, .complete = acpi_subsys_complete, .suspend = acpi_subsys_suspend, - .resume_early = acpi_subsys_resume_early, + .suspend_late = acpi_lpss_suspend_late, + .resume_early = acpi_lpss_resume_early, .freeze = acpi_subsys_freeze, .poweroff = acpi_subsys_suspend, - .poweroff_late = acpi_subsys_suspend_late, + .poweroff_late = acpi_lpss_suspend_late, + .restore_early = acpi_lpss_resume_early, #endif #ifdef CONFIG_PM_RUNTIME .runtime_suspend = acpi_lpss_runtime_suspend, diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 1c162e7be04..5fdfe65fe16 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -534,20 +534,6 @@ static int acpi_battery_get_state(struct acpi_battery *battery) " invalid.\n"); } - /* - * When fully charged, some batteries wrongly report - * capacity_now = design_capacity instead of = full_charge_capacity - */ - if (battery->capacity_now > battery->full_charge_capacity - && battery->full_charge_capacity != ACPI_BATTERY_VALUE_UNKNOWN) { - if (battery->capacity_now != battery->design_capacity) - printk_once(KERN_WARNING FW_BUG - "battery: reported current charge level (%d) " - "is higher than reported maximum charge level (%d).\n", - battery->capacity_now, battery->full_charge_capacity); - battery->capacity_now = battery->full_charge_capacity; - } - if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags) && battery->capacity_now >= 0 && battery->capacity_now <= 100) battery->capacity_now = (battery->capacity_now * diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index db1e9560d8a..5c8e7fe0774 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -3918,7 +3918,6 @@ skip_create_disk: if (rv) { dev_err(&dd->pdev->dev, "Unable to allocate request queue\n"); - rv = -ENOMEM; goto block_queue_alloc_init_error; } diff --git a/drivers/block/null_blk.c b/drivers/block/null_blk.c index a3b042c4d44..00d469c7f9f 100644 --- a/drivers/block/null_blk.c +++ b/drivers/block/null_blk.c @@ -462,17 +462,21 @@ static int null_add_dev(void) struct gendisk *disk; struct nullb *nullb; sector_t size; + int rv; nullb = kzalloc_node(sizeof(*nullb), GFP_KERNEL, home_node); - if (!nullb) + if (!nullb) { + rv = -ENOMEM; goto out; + } spin_lock_init(&nullb->lock); if (queue_mode == NULL_Q_MQ && use_per_node_hctx) submit_queues = nr_online_nodes; - if (setup_queues(nullb)) + rv = setup_queues(nullb); + if (rv) goto out_free_nullb; if (queue_mode == NULL_Q_MQ) { @@ -484,22 +488,29 @@ static int null_add_dev(void) nullb->tag_set.flags = BLK_MQ_F_SHOULD_MERGE; nullb->tag_set.driver_data = nullb; - if (blk_mq_alloc_tag_set(&nullb->tag_set)) + rv = blk_mq_alloc_tag_set(&nullb->tag_set); + if (rv) goto out_cleanup_queues; nullb->q = blk_mq_init_queue(&nullb->tag_set); - if (!nullb->q) + if (!nullb->q) { + rv = -ENOMEM; goto out_cleanup_tags; + } } else if (queue_mode == NULL_Q_BIO) { nullb->q = blk_alloc_queue_node(GFP_KERNEL, home_node); - if (!nullb->q) + if (!nullb->q) { + rv = -ENOMEM; goto out_cleanup_queues; + } blk_queue_make_request(nullb->q, null_queue_bio); init_driver_queues(nullb); } else { nullb->q = blk_init_queue_node(null_request_fn, &nullb->lock, home_node); - if (!nullb->q) + if (!nullb->q) { + rv = -ENOMEM; goto out_cleanup_queues; + } blk_queue_prep_rq(nullb->q, null_rq_prep_fn); blk_queue_softirq_done(nullb->q, null_softirq_done_fn); init_driver_queues(nullb); @@ -509,8 +520,10 @@ static int null_add_dev(void) queue_flag_set_unlocked(QUEUE_FLAG_NONROT, nullb->q); disk = nullb->disk = alloc_disk_node(1, home_node); - if (!disk) + if (!disk) { + rv = -ENOMEM; goto out_cleanup_blk_queue; + } mutex_lock(&lock); list_add_tail(&nullb->list, &nullb_list); @@ -544,7 +557,7 @@ out_cleanup_queues: out_free_nullb: kfree(nullb); out: - return -ENOMEM; + return rv; } static int __init null_init(void) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 623c84145b7..4b97baf8afa 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -5087,9 +5087,11 @@ static int rbd_dev_device_setup(struct rbd_device *rbd_dev) set_capacity(rbd_dev->disk, rbd_dev->mapping.size / SECTOR_SIZE); set_disk_ro(rbd_dev->disk, rbd_dev->mapping.read_only); - rbd_dev->rq_wq = alloc_workqueue(rbd_dev->disk->disk_name, 0, 0); - if (!rbd_dev->rq_wq) + rbd_dev->rq_wq = alloc_workqueue("%s", 0, 0, rbd_dev->disk->disk_name); + if (!rbd_dev->rq_wq) { + ret = -ENOMEM; goto err_out_mapping; + } ret = rbd_bus_add_dev(rbd_dev); if (ret) diff --git a/drivers/cpufreq/cpufreq_opp.c b/drivers/cpufreq/cpufreq_opp.c index f7a32d2326c..773bcde893c 100644 --- a/drivers/cpufreq/cpufreq_opp.c +++ b/drivers/cpufreq/cpufreq_opp.c @@ -60,7 +60,7 @@ int dev_pm_opp_init_cpufreq_table(struct device *dev, goto out; } - freq_table = kcalloc(sizeof(*freq_table), (max_opps + 1), GFP_ATOMIC); + freq_table = kcalloc((max_opps + 1), sizeof(*freq_table), GFP_ATOMIC); if (!freq_table) { ret = -ENOMEM; goto out; diff --git a/drivers/dma/dma-jz4740.c b/drivers/dma/dma-jz4740.c index 6a9d89c93b1..ae2ab14e64b 100644 --- a/drivers/dma/dma-jz4740.c +++ b/drivers/dma/dma-jz4740.c @@ -362,8 +362,9 @@ static void jz4740_dma_chan_irq(struct jz4740_dmaengine_chan *chan) vchan_cyclic_callback(&chan->desc->vdesc); } else { if (chan->next_sg == chan->desc->num_sgs) { - chan->desc = NULL; + list_del(&chan->desc->vdesc.node); vchan_cookie_complete(&chan->desc->vdesc); + chan->desc = NULL; } } } diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index a2cc6be9798..b792194e0d9 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -67,6 +67,7 @@ static int ast_detect_chip(struct drm_device *dev) { struct ast_private *ast = dev->dev_private; uint32_t data, jreg; + ast_open_key(ast); if (dev->pdev->device == PCI_CHIP_AST1180) { ast->chip = AST1100; @@ -104,7 +105,7 @@ static int ast_detect_chip(struct drm_device *dev) } ast->vga2_clone = false; } else { - ast->chip = 2000; + ast->chip = AST2000; DRM_INFO("AST 2000 detected\n"); } } diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 2e7f03ad5ee..9933c26017e 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1336,12 +1336,17 @@ static int i915_load_modeset_init(struct drm_device *dev) intel_power_domains_init_hw(dev_priv); + /* + * We enable some interrupt sources in our postinstall hooks, so mark + * interrupts as enabled _before_ actually enabling them to avoid + * special cases in our ordering checks. + */ + dev_priv->pm._irqs_disabled = false; + ret = drm_irq_install(dev, dev->pdev->irq); if (ret) goto cleanup_gem_stolen; - dev_priv->pm._irqs_disabled = false; - /* Important: The output setup functions called by modeset_init need * working irqs for e.g. gmbus and dp aux transfers. */ intel_modeset_init(dev); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7a830eac5ba..3524306d8cf 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -184,6 +184,7 @@ enum hpd_pin { if ((1 << (domain)) & (mask)) struct drm_i915_private; +struct i915_mm_struct; struct i915_mmu_object; enum intel_dpll_id { @@ -1506,9 +1507,8 @@ struct drm_i915_private { struct i915_gtt gtt; /* VM representing the global address space */ struct i915_gem_mm mm; -#if defined(CONFIG_MMU_NOTIFIER) - DECLARE_HASHTABLE(mmu_notifiers, 7); -#endif + DECLARE_HASHTABLE(mm_structs, 7); + struct mutex mm_lock; /* Kernel Modesetting */ @@ -1814,8 +1814,8 @@ struct drm_i915_gem_object { unsigned workers :4; #define I915_GEM_USERPTR_MAX_WORKERS 15 - struct mm_struct *mm; - struct i915_mmu_object *mn; + struct i915_mm_struct *mm; + struct i915_mmu_object *mmu_object; struct work_struct *work; } userptr; }; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index ba7f5c6bb50..ad55b06a3cb 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1590,10 +1590,13 @@ unlock: out: switch (ret) { case -EIO: - /* If this -EIO is due to a gpu hang, give the reset code a - * chance to clean up the mess. Otherwise return the proper - * SIGBUS. */ - if (i915_terminally_wedged(&dev_priv->gpu_error)) { + /* + * We eat errors when the gpu is terminally wedged to avoid + * userspace unduly crashing (gl has no provisions for mmaps to + * fail). But any other -EIO isn't ours (e.g. swap in failure) + * and so needs to be reported. + */ + if (!i915_terminally_wedged(&dev_priv->gpu_error)) { ret = VM_FAULT_SIGBUS; break; } diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index fe69fc837d9..d3841399737 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -32,6 +32,15 @@ #include <linux/mempolicy.h> #include <linux/swap.h> +struct i915_mm_struct { + struct mm_struct *mm; + struct drm_device *dev; + struct i915_mmu_notifier *mn; + struct hlist_node node; + struct kref kref; + struct work_struct work; +}; + #if defined(CONFIG_MMU_NOTIFIER) #include <linux/interval_tree.h> @@ -41,16 +50,12 @@ struct i915_mmu_notifier { struct mmu_notifier mn; struct rb_root objects; struct list_head linear; - struct drm_device *dev; - struct mm_struct *mm; - struct work_struct work; - unsigned long count; unsigned long serial; bool has_linear; }; struct i915_mmu_object { - struct i915_mmu_notifier *mmu; + struct i915_mmu_notifier *mn; struct interval_tree_node it; struct list_head link; struct drm_i915_gem_object *obj; @@ -96,18 +101,18 @@ static void *invalidate_range__linear(struct i915_mmu_notifier *mn, unsigned long start, unsigned long end) { - struct i915_mmu_object *mmu; + struct i915_mmu_object *mo; unsigned long serial; restart: serial = mn->serial; - list_for_each_entry(mmu, &mn->linear, link) { + list_for_each_entry(mo, &mn->linear, link) { struct drm_i915_gem_object *obj; - if (mmu->it.last < start || mmu->it.start > end) + if (mo->it.last < start || mo->it.start > end) continue; - obj = mmu->obj; + obj = mo->obj; drm_gem_object_reference(&obj->base); spin_unlock(&mn->lock); @@ -160,130 +165,47 @@ static const struct mmu_notifier_ops i915_gem_userptr_notifier = { }; static struct i915_mmu_notifier * -__i915_mmu_notifier_lookup(struct drm_device *dev, struct mm_struct *mm) -{ - struct drm_i915_private *dev_priv = to_i915(dev); - struct i915_mmu_notifier *mmu; - - /* Protected by dev->struct_mutex */ - hash_for_each_possible(dev_priv->mmu_notifiers, mmu, node, (unsigned long)mm) - if (mmu->mm == mm) - return mmu; - - return NULL; -} - -static struct i915_mmu_notifier * -i915_mmu_notifier_get(struct drm_device *dev, struct mm_struct *mm) +i915_mmu_notifier_create(struct mm_struct *mm) { - struct drm_i915_private *dev_priv = to_i915(dev); - struct i915_mmu_notifier *mmu; + struct i915_mmu_notifier *mn; int ret; - lockdep_assert_held(&dev->struct_mutex); - - mmu = __i915_mmu_notifier_lookup(dev, mm); - if (mmu) - return mmu; - - mmu = kmalloc(sizeof(*mmu), GFP_KERNEL); - if (mmu == NULL) + mn = kmalloc(sizeof(*mn), GFP_KERNEL); + if (mn == NULL) return ERR_PTR(-ENOMEM); - spin_lock_init(&mmu->lock); - mmu->dev = dev; - mmu->mn.ops = &i915_gem_userptr_notifier; - mmu->mm = mm; - mmu->objects = RB_ROOT; - mmu->count = 0; - mmu->serial = 1; - INIT_LIST_HEAD(&mmu->linear); - mmu->has_linear = false; - - /* Protected by mmap_sem (write-lock) */ - ret = __mmu_notifier_register(&mmu->mn, mm); + spin_lock_init(&mn->lock); + mn->mn.ops = &i915_gem_userptr_notifier; + mn->objects = RB_ROOT; + mn->serial = 1; + INIT_LIST_HEAD(&mn->linear); + mn->has_linear = false; + + /* Protected by mmap_sem (write-lock) */ + ret = __mmu_notifier_register(&mn->mn, mm); if (ret) { - kfree(mmu); + kfree(mn); return ERR_PTR(ret); } - /* Protected by dev->struct_mutex */ - hash_add(dev_priv->mmu_notifiers, &mmu->node, (unsigned long)mm); - return mmu; + return mn; } -static void -__i915_mmu_notifier_destroy_worker(struct work_struct *work) +static void __i915_mmu_notifier_update_serial(struct i915_mmu_notifier *mn) { - struct i915_mmu_notifier *mmu = container_of(work, typeof(*mmu), work); - mmu_notifier_unregister(&mmu->mn, mmu->mm); - kfree(mmu); -} - -static void -__i915_mmu_notifier_destroy(struct i915_mmu_notifier *mmu) -{ - lockdep_assert_held(&mmu->dev->struct_mutex); - - /* Protected by dev->struct_mutex */ - hash_del(&mmu->node); - - /* Our lock ordering is: mmap_sem, mmu_notifier_scru, struct_mutex. - * We enter the function holding struct_mutex, therefore we need - * to drop our mutex prior to calling mmu_notifier_unregister in - * order to prevent lock inversion (and system-wide deadlock) - * between the mmap_sem and struct-mutex. Hence we defer the - * unregistration to a workqueue where we hold no locks. - */ - INIT_WORK(&mmu->work, __i915_mmu_notifier_destroy_worker); - schedule_work(&mmu->work); -} - -static void __i915_mmu_notifier_update_serial(struct i915_mmu_notifier *mmu) -{ - if (++mmu->serial == 0) - mmu->serial = 1; -} - -static bool i915_mmu_notifier_has_linear(struct i915_mmu_notifier *mmu) -{ - struct i915_mmu_object *mn; - - list_for_each_entry(mn, &mmu->linear, link) - if (mn->is_linear) - return true; - - return false; -} - -static void -i915_mmu_notifier_del(struct i915_mmu_notifier *mmu, - struct i915_mmu_object *mn) -{ - lockdep_assert_held(&mmu->dev->struct_mutex); - - spin_lock(&mmu->lock); - list_del(&mn->link); - if (mn->is_linear) - mmu->has_linear = i915_mmu_notifier_has_linear(mmu); - else - interval_tree_remove(&mn->it, &mmu->objects); - __i915_mmu_notifier_update_serial(mmu); - spin_unlock(&mmu->lock); - - /* Protected against _add() by dev->struct_mutex */ - if (--mmu->count == 0) - __i915_mmu_notifier_destroy(mmu); + if (++mn->serial == 0) + mn->serial = 1; } static int -i915_mmu_notifier_add(struct i915_mmu_notifier *mmu, - struct i915_mmu_object *mn) +i915_mmu_notifier_add(struct drm_device *dev, + struct i915_mmu_notifier *mn, + struct i915_mmu_object *mo) { struct interval_tree_node *it; int ret; - ret = i915_mutex_lock_interruptible(mmu->dev); + ret = i915_mutex_lock_interruptible(dev); if (ret) return ret; @@ -291,11 +213,11 @@ i915_mmu_notifier_add(struct i915_mmu_notifier *mmu, * remove the objects from the interval tree) before we do * the check for overlapping objects. */ - i915_gem_retire_requests(mmu->dev); + i915_gem_retire_requests(dev); - spin_lock(&mmu->lock); - it = interval_tree_iter_first(&mmu->objects, - mn->it.start, mn->it.last); + spin_lock(&mn->lock); + it = interval_tree_iter_first(&mn->objects, + mo->it.start, mo->it.last); if (it) { struct drm_i915_gem_object *obj; @@ -312,86 +234,122 @@ i915_mmu_notifier_add(struct i915_mmu_notifier *mmu, obj = container_of(it, struct i915_mmu_object, it)->obj; if (!obj->userptr.workers) - mmu->has_linear = mn->is_linear = true; + mn->has_linear = mo->is_linear = true; else ret = -EAGAIN; } else - interval_tree_insert(&mn->it, &mmu->objects); + interval_tree_insert(&mo->it, &mn->objects); if (ret == 0) { - list_add(&mn->link, &mmu->linear); - __i915_mmu_notifier_update_serial(mmu); + list_add(&mo->link, &mn->linear); + __i915_mmu_notifier_update_serial(mn); } - spin_unlock(&mmu->lock); - mutex_unlock(&mmu->dev->struct_mutex); + spin_unlock(&mn->lock); + mutex_unlock(&dev->struct_mutex); return ret; } +static bool i915_mmu_notifier_has_linear(struct i915_mmu_notifier *mn) +{ + struct i915_mmu_object *mo; + + list_for_each_entry(mo, &mn->linear, link) + if (mo->is_linear) + return true; + + return false; +} + +static void +i915_mmu_notifier_del(struct i915_mmu_notifier *mn, + struct i915_mmu_object *mo) +{ + spin_lock(&mn->lock); + list_del(&mo->link); + if (mo->is_linear) + mn->has_linear = i915_mmu_notifier_has_linear(mn); + else + interval_tree_remove(&mo->it, &mn->objects); + __i915_mmu_notifier_update_serial(mn); + spin_unlock(&mn->lock); +} + static void i915_gem_userptr_release__mmu_notifier(struct drm_i915_gem_object *obj) { - struct i915_mmu_object *mn; + struct i915_mmu_object *mo; - mn = obj->userptr.mn; - if (mn == NULL) + mo = obj->userptr.mmu_object; + if (mo == NULL) return; - i915_mmu_notifier_del(mn->mmu, mn); - obj->userptr.mn = NULL; + i915_mmu_notifier_del(mo->mn, mo); + kfree(mo); + + obj->userptr.mmu_object = NULL; +} + +static struct i915_mmu_notifier * +i915_mmu_notifier_find(struct i915_mm_struct *mm) +{ + if (mm->mn == NULL) { + down_write(&mm->mm->mmap_sem); + mutex_lock(&to_i915(mm->dev)->mm_lock); + if (mm->mn == NULL) + mm->mn = i915_mmu_notifier_create(mm->mm); + mutex_unlock(&to_i915(mm->dev)->mm_lock); + up_write(&mm->mm->mmap_sem); + } + return mm->mn; } static int i915_gem_userptr_init__mmu_notifier(struct drm_i915_gem_object *obj, unsigned flags) { - struct i915_mmu_notifier *mmu; - struct i915_mmu_object *mn; + struct i915_mmu_notifier *mn; + struct i915_mmu_object *mo; int ret; if (flags & I915_USERPTR_UNSYNCHRONIZED) return capable(CAP_SYS_ADMIN) ? 0 : -EPERM; - down_write(&obj->userptr.mm->mmap_sem); - ret = i915_mutex_lock_interruptible(obj->base.dev); - if (ret == 0) { - mmu = i915_mmu_notifier_get(obj->base.dev, obj->userptr.mm); - if (!IS_ERR(mmu)) - mmu->count++; /* preemptive add to act as a refcount */ - else - ret = PTR_ERR(mmu); - mutex_unlock(&obj->base.dev->struct_mutex); - } - up_write(&obj->userptr.mm->mmap_sem); - if (ret) - return ret; + if (WARN_ON(obj->userptr.mm == NULL)) + return -EINVAL; - mn = kzalloc(sizeof(*mn), GFP_KERNEL); - if (mn == NULL) { - ret = -ENOMEM; - goto destroy_mmu; - } + mn = i915_mmu_notifier_find(obj->userptr.mm); + if (IS_ERR(mn)) + return PTR_ERR(mn); - mn->mmu = mmu; - mn->it.start = obj->userptr.ptr; - mn->it.last = mn->it.start + obj->base.size - 1; - mn->obj = obj; + mo = kzalloc(sizeof(*mo), GFP_KERNEL); + if (mo == NULL) + return -ENOMEM; - ret = i915_mmu_notifier_add(mmu, mn); - if (ret) - goto free_mn; + mo->mn = mn; + mo->it.start = obj->userptr.ptr; + mo->it.last = mo->it.start + obj->base.size - 1; + mo->obj = obj; - obj->userptr.mn = mn; + ret = i915_mmu_notifier_add(obj->base.dev, mn, mo); + if (ret) { + kfree(mo); + return ret; + } + + obj->userptr.mmu_object = mo; return 0; +} + +static void +i915_mmu_notifier_free(struct i915_mmu_notifier *mn, + struct mm_struct *mm) +{ + if (mn == NULL) + return; -free_mn: + mmu_notifier_unregister(&mn->mn, mm); kfree(mn); -destroy_mmu: - mutex_lock(&obj->base.dev->struct_mutex); - if (--mmu->count == 0) - __i915_mmu_notifier_destroy(mmu); - mutex_unlock(&obj->base.dev->struct_mutex); - return ret; } #else @@ -413,15 +371,114 @@ i915_gem_userptr_init__mmu_notifier(struct drm_i915_gem_object *obj, return 0; } + +static void +i915_mmu_notifier_free(struct i915_mmu_notifier *mn, + struct mm_struct *mm) +{ +} + #endif +static struct i915_mm_struct * +__i915_mm_struct_find(struct drm_i915_private *dev_priv, struct mm_struct *real) +{ + struct i915_mm_struct *mm; + + /* Protected by dev_priv->mm_lock */ + hash_for_each_possible(dev_priv->mm_structs, mm, node, (unsigned long)real) + if (mm->mm == real) + return mm; + + return NULL; +} + +static int +i915_gem_userptr_init__mm_struct(struct drm_i915_gem_object *obj) +{ + struct drm_i915_private *dev_priv = to_i915(obj->base.dev); + struct i915_mm_struct *mm; + int ret = 0; + + /* During release of the GEM object we hold the struct_mutex. This + * precludes us from calling mmput() at that time as that may be + * the last reference and so call exit_mmap(). exit_mmap() will + * attempt to reap the vma, and if we were holding a GTT mmap + * would then call drm_gem_vm_close() and attempt to reacquire + * the struct mutex. So in order to avoid that recursion, we have + * to defer releasing the mm reference until after we drop the + * struct_mutex, i.e. we need to schedule a worker to do the clean + * up. + */ + mutex_lock(&dev_priv->mm_lock); + mm = __i915_mm_struct_find(dev_priv, current->mm); + if (mm == NULL) { + mm = kmalloc(sizeof(*mm), GFP_KERNEL); + if (mm == NULL) { + ret = -ENOMEM; + goto out; + } + + kref_init(&mm->kref); + mm->dev = obj->base.dev; + + mm->mm = current->mm; + atomic_inc(¤t->mm->mm_count); + + mm->mn = NULL; + + /* Protected by dev_priv->mm_lock */ + hash_add(dev_priv->mm_structs, + &mm->node, (unsigned long)mm->mm); + } else + kref_get(&mm->kref); + + obj->userptr.mm = mm; +out: + mutex_unlock(&dev_priv->mm_lock); + return ret; +} + +static void +__i915_mm_struct_free__worker(struct work_struct *work) +{ + struct i915_mm_struct *mm = container_of(work, typeof(*mm), work); + i915_mmu_notifier_free(mm->mn, mm->mm); + mmdrop(mm->mm); + kfree(mm); +} + +static void +__i915_mm_struct_free(struct kref *kref) +{ + struct i915_mm_struct *mm = container_of(kref, typeof(*mm), kref); + + /* Protected by dev_priv->mm_lock */ + hash_del(&mm->node); + mutex_unlock(&to_i915(mm->dev)->mm_lock); + + INIT_WORK(&mm->work, __i915_mm_struct_free__worker); + schedule_work(&mm->work); +} + +static void +i915_gem_userptr_release__mm_struct(struct drm_i915_gem_object *obj) +{ + if (obj->userptr.mm == NULL) + return; + + kref_put_mutex(&obj->userptr.mm->kref, + __i915_mm_struct_free, + &to_i915(obj->base.dev)->mm_lock); + obj->userptr.mm = NULL; +} + struct get_pages_work { struct work_struct work; struct drm_i915_gem_object *obj; struct task_struct *task; }; - #if IS_ENABLED(CONFIG_SWIOTLB) #define swiotlb_active() swiotlb_nr_tbl() #else @@ -479,7 +536,7 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work) if (pvec == NULL) pvec = drm_malloc_ab(num_pages, sizeof(struct page *)); if (pvec != NULL) { - struct mm_struct *mm = obj->userptr.mm; + struct mm_struct *mm = obj->userptr.mm->mm; down_read(&mm->mmap_sem); while (pinned < num_pages) { @@ -545,7 +602,7 @@ i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj) pvec = NULL; pinned = 0; - if (obj->userptr.mm == current->mm) { + if (obj->userptr.mm->mm == current->mm) { pvec = kmalloc(num_pages*sizeof(struct page *), GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY); if (pvec == NULL) { @@ -651,17 +708,13 @@ static void i915_gem_userptr_release(struct drm_i915_gem_object *obj) { i915_gem_userptr_release__mmu_notifier(obj); - - if (obj->userptr.mm) { - mmput(obj->userptr.mm); - obj->userptr.mm = NULL; - } + i915_gem_userptr_release__mm_struct(obj); } static int i915_gem_userptr_dmabuf_export(struct drm_i915_gem_object *obj) { - if (obj->userptr.mn) + if (obj->userptr.mmu_object) return 0; return i915_gem_userptr_init__mmu_notifier(obj, 0); @@ -736,7 +789,6 @@ i915_gem_userptr_ioctl(struct drm_device *dev, void *data, struct drm_file *file return -ENODEV; } - /* Allocate the new object */ obj = i915_gem_object_alloc(dev); if (obj == NULL) return -ENOMEM; @@ -754,8 +806,8 @@ i915_gem_userptr_ioctl(struct drm_device *dev, void *data, struct drm_file *file * at binding. This means that we need to hook into the mmu_notifier * in order to detect if the mmu is destroyed. */ - ret = -ENOMEM; - if ((obj->userptr.mm = get_task_mm(current))) + ret = i915_gem_userptr_init__mm_struct(obj); + if (ret == 0) ret = i915_gem_userptr_init__mmu_notifier(obj, args->flags); if (ret == 0) ret = drm_gem_handle_create(file, &obj->base, &handle); @@ -772,9 +824,8 @@ i915_gem_userptr_ioctl(struct drm_device *dev, void *data, struct drm_file *file int i915_gem_init_userptr(struct drm_device *dev) { -#if defined(CONFIG_MMU_NOTIFIER) struct drm_i915_private *dev_priv = to_i915(dev); - hash_init(dev_priv->mmu_notifiers); -#endif + mutex_init(&dev_priv->mm_lock); + hash_init(dev_priv->mm_structs); return 0; } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e4d7607da2c..f29b44c86a2 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -334,16 +334,20 @@ #define GFX_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1) #define GFX_OP_DRAWRECT_INFO ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3)) #define GFX_OP_DRAWRECT_INFO_I965 ((0x7900<<16)|0x2) -#define SRC_COPY_BLT_CMD ((2<<29)|(0x43<<22)|4) + +#define COLOR_BLT_CMD (2<<29 | 0x40<<22 | (5-2)) +#define SRC_COPY_BLT_CMD ((2<<29)|(0x43<<22)|4) #define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6) #define XY_MONO_SRC_COPY_IMM_BLT ((2<<29)|(0x71<<22)|5) -#define XY_SRC_COPY_BLT_WRITE_ALPHA (1<<21) -#define XY_SRC_COPY_BLT_WRITE_RGB (1<<20) +#define BLT_WRITE_A (2<<20) +#define BLT_WRITE_RGB (1<<20) +#define BLT_WRITE_RGBA (BLT_WRITE_RGB | BLT_WRITE_A) #define BLT_DEPTH_8 (0<<24) #define BLT_DEPTH_16_565 (1<<24) #define BLT_DEPTH_16_1555 (2<<24) #define BLT_DEPTH_32 (3<<24) -#define BLT_ROP_GXCOPY (0xcc<<16) +#define BLT_ROP_SRC_COPY (0xcc<<16) +#define BLT_ROP_COLOR_COPY (0xf0<<16) #define XY_SRC_COPY_BLT_SRC_TILED (1<<15) /* 965+ only */ #define XY_SRC_COPY_BLT_DST_TILED (1<<11) /* 965+ only */ #define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 16371a44442..2d068edd1ad 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1363,54 +1363,66 @@ i965_dispatch_execbuffer(struct intel_engine_cs *ring, /* Just userspace ABI convention to limit the wa batch bo to a resonable size */ #define I830_BATCH_LIMIT (256*1024) +#define I830_TLB_ENTRIES (2) +#define I830_WA_SIZE max(I830_TLB_ENTRIES*4096, I830_BATCH_LIMIT) static int i830_dispatch_execbuffer(struct intel_engine_cs *ring, u64 offset, u32 len, unsigned flags) { + u32 cs_offset = ring->scratch.gtt_offset; int ret; - if (flags & I915_DISPATCH_PINNED) { - ret = intel_ring_begin(ring, 4); - if (ret) - return ret; + ret = intel_ring_begin(ring, 6); + if (ret) + return ret; - intel_ring_emit(ring, MI_BATCH_BUFFER); - intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE)); - intel_ring_emit(ring, offset + len - 8); - intel_ring_emit(ring, MI_NOOP); - intel_ring_advance(ring); - } else { - u32 cs_offset = ring->scratch.gtt_offset; + /* Evict the invalid PTE TLBs */ + intel_ring_emit(ring, COLOR_BLT_CMD | BLT_WRITE_RGBA); + intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | 4096); + intel_ring_emit(ring, I830_TLB_ENTRIES << 16 | 4); /* load each page */ + intel_ring_emit(ring, cs_offset); + intel_ring_emit(ring, 0xdeadbeef); + intel_ring_emit(ring, MI_NOOP); + intel_ring_advance(ring); + if ((flags & I915_DISPATCH_PINNED) == 0) { if (len > I830_BATCH_LIMIT) return -ENOSPC; - ret = intel_ring_begin(ring, 9+3); + ret = intel_ring_begin(ring, 6 + 2); if (ret) return ret; - /* Blit the batch (which has now all relocs applied) to the stable batch - * scratch bo area (so that the CS never stumbles over its tlb - * invalidation bug) ... */ - intel_ring_emit(ring, XY_SRC_COPY_BLT_CMD | - XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB); - intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_GXCOPY | 4096); - intel_ring_emit(ring, 0); - intel_ring_emit(ring, (DIV_ROUND_UP(len, 4096) << 16) | 1024); + + /* Blit the batch (which has now all relocs applied) to the + * stable batch scratch bo area (so that the CS never + * stumbles over its tlb invalidation bug) ... + */ + intel_ring_emit(ring, SRC_COPY_BLT_CMD | BLT_WRITE_RGBA); + intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_SRC_COPY | 4096); + intel_ring_emit(ring, DIV_ROUND_UP(len, 4096) << 16 | 1024); intel_ring_emit(ring, cs_offset); - intel_ring_emit(ring, 0); intel_ring_emit(ring, 4096); intel_ring_emit(ring, offset); + intel_ring_emit(ring, MI_FLUSH); + intel_ring_emit(ring, MI_NOOP); + intel_ring_advance(ring); /* ... and execute it. */ - intel_ring_emit(ring, MI_BATCH_BUFFER); - intel_ring_emit(ring, cs_offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE)); - intel_ring_emit(ring, cs_offset + len - 8); - intel_ring_advance(ring); + offset = cs_offset; } + ret = intel_ring_begin(ring, 4); + if (ret) + return ret; + + intel_ring_emit(ring, MI_BATCH_BUFFER); + intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE)); + intel_ring_emit(ring, offset + len - 8); + intel_ring_emit(ring, MI_NOOP); + intel_ring_advance(ring); + return 0; } @@ -2200,7 +2212,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev) /* Workaround batchbuffer to combat CS tlb bug. */ if (HAS_BROKEN_CS_TLB(dev)) { - obj = i915_gem_alloc_object(dev, I830_BATCH_LIMIT); + obj = i915_gem_alloc_object(dev, I830_WA_SIZE); if (obj == NULL) { DRM_ERROR("Failed to allocate batch bo\n"); return -ENOMEM; diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index c69d3ce1b3d..c14341ca3ef 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -854,6 +854,10 @@ intel_enable_tv(struct intel_encoder *encoder) struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + /* Prevents vblank waits from timing out in intel_tv_detect_type() */ + intel_wait_for_vblank(encoder->base.dev, + to_intel_crtc(encoder->base.crtc)->pipe); + I915_WRITE(TV_CTL, I915_READ(TV_CTL) | TV_ENC_ENABLE); } diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index a125a7e3274..c6c9b02e0ad 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -258,28 +258,30 @@ static void set_hdmi_pdev(struct drm_device *dev, priv->hdmi_pdev = pdev; } +#ifdef CONFIG_OF +static int get_gpio(struct device *dev, struct device_node *of_node, const char *name) +{ + int gpio = of_get_named_gpio(of_node, name, 0); + if (gpio < 0) { + char name2[32]; + snprintf(name2, sizeof(name2), "%s-gpio", name); + gpio = of_get_named_gpio(of_node, name2, 0); + if (gpio < 0) { + dev_err(dev, "failed to get gpio: %s (%d)\n", + name, gpio); + gpio = -1; + } + } + return gpio; +} +#endif + static int hdmi_bind(struct device *dev, struct device *master, void *data) { static struct hdmi_platform_config config = {}; #ifdef CONFIG_OF struct device_node *of_node = dev->of_node; - int get_gpio(const char *name) - { - int gpio = of_get_named_gpio(of_node, name, 0); - if (gpio < 0) { - char name2[32]; - snprintf(name2, sizeof(name2), "%s-gpio", name); - gpio = of_get_named_gpio(of_node, name2, 0); - if (gpio < 0) { - dev_err(dev, "failed to get gpio: %s (%d)\n", - name, gpio); - gpio = -1; - } - } - return gpio; - } - if (of_device_is_compatible(of_node, "qcom,hdmi-tx-8074")) { static const char *hpd_reg_names[] = {"hpd-gdsc", "hpd-5v"}; static const char *pwr_reg_names[] = {"core-vdda", "core-vcc"}; @@ -312,12 +314,12 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data) } config.mmio_name = "core_physical"; - config.ddc_clk_gpio = get_gpio("qcom,hdmi-tx-ddc-clk"); - config.ddc_data_gpio = get_gpio("qcom,hdmi-tx-ddc-data"); - config.hpd_gpio = get_gpio("qcom,hdmi-tx-hpd"); - config.mux_en_gpio = get_gpio("qcom,hdmi-tx-mux-en"); - config.mux_sel_gpio = get_gpio("qcom,hdmi-tx-mux-sel"); - config.mux_lpm_gpio = get_gpio("qcom,hdmi-tx-mux-lpm"); + config.ddc_clk_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-ddc-clk"); + config.ddc_data_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-ddc-data"); + config.hpd_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-hpd"); + config.mux_en_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-mux-en"); + config.mux_sel_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-mux-sel"); + config.mux_lpm_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-mux-lpm"); #else static const char *hpd_clk_names[] = { diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c index 902d7685d44..f408b69486a 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c @@ -15,19 +15,25 @@ * this program. If not, see <http://www.gnu.org/licenses/>. */ +#ifdef CONFIG_COMMON_CLK #include <linux/clk.h> #include <linux/clk-provider.h> +#endif #include "hdmi.h" struct hdmi_phy_8960 { struct hdmi_phy base; struct hdmi *hdmi; +#ifdef CONFIG_COMMON_CLK struct clk_hw pll_hw; struct clk *pll; unsigned long pixclk; +#endif }; #define to_hdmi_phy_8960(x) container_of(x, struct hdmi_phy_8960, base) + +#ifdef CONFIG_COMMON_CLK #define clk_to_phy(x) container_of(x, struct hdmi_phy_8960, pll_hw) /* @@ -374,7 +380,7 @@ static struct clk_init_data pll_init = { .parent_names = hdmi_pll_parents, .num_parents = ARRAY_SIZE(hdmi_pll_parents), }; - +#endif /* * HDMI Phy: @@ -480,12 +486,15 @@ struct hdmi_phy *hdmi_phy_8960_init(struct hdmi *hdmi) { struct hdmi_phy_8960 *phy_8960; struct hdmi_phy *phy = NULL; - int ret, i; + int ret; +#ifdef CONFIG_COMMON_CLK + int i; /* sanity check: */ for (i = 0; i < (ARRAY_SIZE(freqtbl) - 1); i++) if (WARN_ON(freqtbl[i].rate < freqtbl[i+1].rate)) return ERR_PTR(-EINVAL); +#endif phy_8960 = kzalloc(sizeof(*phy_8960), GFP_KERNEL); if (!phy_8960) { @@ -499,6 +508,7 @@ struct hdmi_phy *hdmi_phy_8960_init(struct hdmi *hdmi) phy_8960->hdmi = hdmi; +#ifdef CONFIG_COMMON_CLK phy_8960->pll_hw.init = &pll_init; phy_8960->pll = devm_clk_register(hdmi->dev->dev, &phy_8960->pll_hw); if (IS_ERR(phy_8960->pll)) { @@ -506,6 +516,7 @@ struct hdmi_phy *hdmi_phy_8960_init(struct hdmi *hdmi) phy_8960->pll = NULL; goto fail; } +#endif return phy; diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 26ee80db17a..fcf95680413 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -52,7 +52,7 @@ module_param(reglog, bool, 0600); #define reglog 0 #endif -static char *vram; +static char *vram = "16m"; MODULE_PARM_DESC(vram, "Configure VRAM size (for devices without IOMMU/GPUMMU"); module_param(vram, charp, 0); diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index b1e11f8434e..ac14b67621d 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -405,16 +405,13 @@ bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector) u8 msg[DP_DPCD_SIZE]; int ret; - char dpcd_hex_dump[DP_DPCD_SIZE * 3]; - ret = drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_DPCD_REV, msg, DP_DPCD_SIZE); if (ret > 0) { memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE); - hex_dump_to_buffer(dig_connector->dpcd, sizeof(dig_connector->dpcd), - 32, 1, dpcd_hex_dump, sizeof(dpcd_hex_dump), false); - DRM_DEBUG_KMS("DPCD: %s\n", dpcd_hex_dump); + DRM_DEBUG_KMS("DPCD: %*ph\n", (int)sizeof(dig_connector->dpcd), + dig_connector->dpcd); radeon_dp_probe_oui(radeon_connector); diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index e616eb5f6e7..3cfb50056f7 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2769,8 +2769,8 @@ bool r600_semaphore_ring_emit(struct radeon_device *rdev, radeon_ring_write(ring, lower_32_bits(addr)); radeon_ring_write(ring, (upper_32_bits(addr) & 0xff) | sel); - /* PFP_SYNC_ME packet only exists on 7xx+ */ - if (emit_wait && (rdev->family >= CHIP_RV770)) { + /* PFP_SYNC_ME packet only exists on 7xx+, only enable it on eg+ */ + if (emit_wait && (rdev->family >= CHIP_CEDAR)) { /* Prevent the PFP from running ahead of the semaphore wait */ radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0)); radeon_ring_write(ring, 0x0); diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 92b2d8dd473..e74c7e387dd 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -447,6 +447,13 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, } } + /* Fujitsu D3003-S2 board lists DVI-I as DVI-I and VGA */ + if ((dev->pdev->device == 0x9805) && + (dev->pdev->subsystem_vendor == 0x1734) && + (dev->pdev->subsystem_device == 0x11bd)) { + if (*connector_type == DRM_MODE_CONNECTOR_VGA) + return false; + } return true; } @@ -2281,19 +2288,31 @@ static void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *r (controller->ucFanParameters & ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); rdev->pm.int_thermal_type = THERMAL_TYPE_KV; - } else if ((controller->ucType == - ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) || - (controller->ucType == - ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) || - (controller->ucType == - ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL)) { - DRM_INFO("Special thermal controller config\n"); + } else if (controller->ucType == + ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) { + DRM_INFO("External GPIO thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + rdev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL_GPIO; + } else if (controller->ucType == + ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) { + DRM_INFO("ADT7473 with internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + rdev->pm.int_thermal_type = THERMAL_TYPE_ADT7473_WITH_INTERNAL; + } else if (controller->ucType == + ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL) { + DRM_INFO("EMC2103 with internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + rdev->pm.int_thermal_type = THERMAL_TYPE_EMC2103_WITH_INTERNAL; } else if (controller->ucType < ARRAY_SIZE(pp_lib_thermal_controller_names)) { DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n", pp_lib_thermal_controller_names[controller->ucType], controller->ucI2cAddress >> 1, (controller->ucFanParameters & ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + rdev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL; i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine); rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); if (rdev->pm.i2c_bus) { diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c b/drivers/gpu/drm/radeon/radeon_semaphore.c index 56d9fd66d8a..abd6753a570 100644 --- a/drivers/gpu/drm/radeon/radeon_semaphore.c +++ b/drivers/gpu/drm/radeon/radeon_semaphore.c @@ -34,7 +34,7 @@ int radeon_semaphore_create(struct radeon_device *rdev, struct radeon_semaphore **semaphore) { - uint32_t *cpu_addr; + uint64_t *cpu_addr; int i, r; *semaphore = kmalloc(sizeof(struct radeon_semaphore), GFP_KERNEL); diff --git a/drivers/input/keyboard/cap1106.c b/drivers/input/keyboard/cap1106.c index 180b184ab90..d70b65a14ce 100644 --- a/drivers/input/keyboard/cap1106.c +++ b/drivers/input/keyboard/cap1106.c @@ -33,8 +33,8 @@ #define CAP1106_REG_SENSOR_CONFIG 0x22 #define CAP1106_REG_SENSOR_CONFIG2 0x23 #define CAP1106_REG_SAMPLING_CONFIG 0x24 -#define CAP1106_REG_CALIBRATION 0x25 -#define CAP1106_REG_INT_ENABLE 0x26 +#define CAP1106_REG_CALIBRATION 0x26 +#define CAP1106_REG_INT_ENABLE 0x27 #define CAP1106_REG_REPEAT_RATE 0x28 #define CAP1106_REG_MT_CONFIG 0x2a #define CAP1106_REG_MT_PATTERN_CONFIG 0x2b diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index 8d2e19e81e1..e651fa692af 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c @@ -332,23 +332,24 @@ static int matrix_keypad_init_gpio(struct platform_device *pdev, } if (pdata->clustered_irq > 0) { - err = request_irq(pdata->clustered_irq, + err = request_any_context_irq(pdata->clustered_irq, matrix_keypad_interrupt, pdata->clustered_irq_flags, "matrix-keypad", keypad); - if (err) { + if (err < 0) { dev_err(&pdev->dev, "Unable to acquire clustered interrupt\n"); goto err_free_rows; } } else { for (i = 0; i < pdata->num_row_gpios; i++) { - err = request_irq(gpio_to_irq(pdata->row_gpios[i]), + err = request_any_context_irq( + gpio_to_irq(pdata->row_gpios[i]), matrix_keypad_interrupt, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "matrix-keypad", keypad); - if (err) { + if (err < 0) { dev_err(&pdev->dev, "Unable to acquire interrupt for GPIO line %i\n", pdata->row_gpios[i]); diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index a956b980ee7..35a49bf5722 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -2373,6 +2373,10 @@ int alps_init(struct psmouse *psmouse) dev2->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); + __set_bit(INPUT_PROP_POINTER, dev2->propbit); + if (priv->flags & ALPS_DUALPOINT) + __set_bit(INPUT_PROP_POINTING_STICK, dev2->propbit); + if (input_register_device(priv->dev2)) goto init_fail; diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index da51738eb59..06fc6e76ffb 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -1331,6 +1331,13 @@ static bool elantech_is_signature_valid(const unsigned char *param) if (param[1] == 0) return true; + /* + * Some models have a revision higher then 20. Meaning param[2] may + * be 10 or 20, skip the rates check for these. + */ + if (param[0] == 0x46 && (param[1] & 0xef) == 0x0f && param[2] < 40) + return true; + for (i = 0; i < ARRAY_SIZE(rates); i++) if (param[2] == rates[i]) return false; @@ -1607,6 +1614,10 @@ int elantech_init(struct psmouse *psmouse) tp_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); + + __set_bit(INPUT_PROP_POINTER, tp_dev->propbit); + __set_bit(INPUT_PROP_POINTING_STICK, tp_dev->propbit); + error = input_register_device(etd->tp_dev); if (error < 0) goto init_fail_tp_reg; diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index cff065f6261..b4e1f014ddc 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -670,6 +670,8 @@ static void psmouse_apply_defaults(struct psmouse *psmouse) __set_bit(REL_X, input_dev->relbit); __set_bit(REL_Y, input_dev->relbit); + __set_bit(INPUT_PROP_POINTER, input_dev->propbit); + psmouse->set_rate = psmouse_set_rate; psmouse->set_resolution = psmouse_set_resolution; psmouse->poll = psmouse_poll; diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index e8573c68f77..fd23181c1fb 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -629,10 +629,61 @@ static int synaptics_parse_hw_state(const unsigned char buf[], ((buf[0] & 0x04) >> 1) | ((buf[3] & 0x04) >> 2)); + if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) || + SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) && + hw->w == 2) { + synaptics_parse_agm(buf, priv, hw); + return 1; + } + + hw->x = (((buf[3] & 0x10) << 8) | + ((buf[1] & 0x0f) << 8) | + buf[4]); + hw->y = (((buf[3] & 0x20) << 7) | + ((buf[1] & 0xf0) << 4) | + buf[5]); + hw->z = buf[2]; + hw->left = (buf[0] & 0x01) ? 1 : 0; hw->right = (buf[0] & 0x02) ? 1 : 0; - if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { + if (SYN_CAP_FORCEPAD(priv->ext_cap_0c)) { + /* + * ForcePads, like Clickpads, use middle button + * bits to report primary button clicks. + * Unfortunately they report primary button not + * only when user presses on the pad above certain + * threshold, but also when there are more than one + * finger on the touchpad, which interferes with + * out multi-finger gestures. + */ + if (hw->z == 0) { + /* No contacts */ + priv->press = priv->report_press = false; + } else if (hw->w >= 4 && ((buf[0] ^ buf[3]) & 0x01)) { + /* + * Single-finger touch with pressure above + * the threshold. If pressure stays long + * enough, we'll start reporting primary + * button. We rely on the device continuing + * sending data even if finger does not + * move. + */ + if (!priv->press) { + priv->press_start = jiffies; + priv->press = true; + } else if (time_after(jiffies, + priv->press_start + + msecs_to_jiffies(50))) { + priv->report_press = true; + } + } else { + priv->press = false; + } + + hw->left = priv->report_press; + + } else if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { /* * Clickpad's button is transmitted as middle button, * however, since it is primary button, we will report @@ -651,21 +702,6 @@ static int synaptics_parse_hw_state(const unsigned char buf[], hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0; } - if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) || - SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) && - hw->w == 2) { - synaptics_parse_agm(buf, priv, hw); - return 1; - } - - hw->x = (((buf[3] & 0x10) << 8) | - ((buf[1] & 0x0f) << 8) | - buf[4]); - hw->y = (((buf[3] & 0x20) << 7) | - ((buf[1] & 0xf0) << 4) | - buf[5]); - hw->z = buf[2]; - if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) && ((buf[0] ^ buf[3]) & 0x02)) { switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index e594af0b264..fb2e076738a 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h @@ -78,6 +78,11 @@ * 2 0x08 image sensor image sensor tracks 5 fingers, but only * reports 2. * 2 0x20 report min query 0x0f gives min coord reported + * 2 0x80 forcepad forcepad is a variant of clickpad that + * does not have physical buttons but rather + * uses pressure above certain threshold to + * report primary clicks. Forcepads also have + * clickpad bit set. */ #define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */ #define SYN_CAP_CLICKPAD2BTN(ex0c) ((ex0c) & 0x000100) /* 2-button ClickPad */ @@ -86,6 +91,7 @@ #define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000) #define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400) #define SYN_CAP_IMAGE_SENSOR(ex0c) ((ex0c) & 0x000800) +#define SYN_CAP_FORCEPAD(ex0c) ((ex0c) & 0x008000) /* synaptics modes query bits */ #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) @@ -177,6 +183,11 @@ struct synaptics_data { */ struct synaptics_hw_state agm; bool agm_pending; /* new AGM packet received */ + + /* ForcePad handling */ + unsigned long press_start; + bool press; + bool report_press; }; void synaptics_module_init(void); diff --git a/drivers/input/mouse/synaptics_usb.c b/drivers/input/mouse/synaptics_usb.c index e122bda16aa..6bcc0189c1c 100644 --- a/drivers/input/mouse/synaptics_usb.c +++ b/drivers/input/mouse/synaptics_usb.c @@ -387,6 +387,7 @@ static int synusb_probe(struct usb_interface *intf, __set_bit(EV_REL, input_dev->evbit); __set_bit(REL_X, input_dev->relbit); __set_bit(REL_Y, input_dev->relbit); + __set_bit(INPUT_PROP_POINTING_STICK, input_dev->propbit); input_set_abs_params(input_dev, ABS_PRESSURE, 0, 127, 0, 0); } else { input_set_abs_params(input_dev, ABS_X, @@ -401,6 +402,11 @@ static int synusb_probe(struct usb_interface *intf, __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); } + if (synusb->flags & SYNUSB_TOUCHSCREEN) + __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); + else + __set_bit(INPUT_PROP_POINTER, input_dev->propbit); + __set_bit(BTN_LEFT, input_dev->keybit); __set_bit(BTN_RIGHT, input_dev->keybit); __set_bit(BTN_MIDDLE, input_dev->keybit); diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c index ca843b6cf6b..30c8b699880 100644 --- a/drivers/input/mouse/trackpoint.c +++ b/drivers/input/mouse/trackpoint.c @@ -393,6 +393,9 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties) if ((button_info & 0x0f) >= 3) __set_bit(BTN_MIDDLE, psmouse->dev->keybit); + __set_bit(INPUT_PROP_POINTER, psmouse->dev->propbit); + __set_bit(INPUT_PROP_POINTING_STICK, psmouse->dev->propbit); + trackpoint_defaults(psmouse->private); error = trackpoint_power_on_reset(&psmouse->ps2dev); diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c index 0cb7ef59071..69175b82534 100644 --- a/drivers/input/serio/serport.c +++ b/drivers/input/serio/serport.c @@ -21,6 +21,7 @@ #include <linux/init.h> #include <linux/serio.h> #include <linux/tty.h> +#include <linux/compat.h> MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_DESCRIPTION("Input device TTY line discipline"); @@ -198,28 +199,55 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u return 0; } +static void serport_set_type(struct tty_struct *tty, unsigned long type) +{ + struct serport *serport = tty->disc_data; + + serport->id.proto = type & 0x000000ff; + serport->id.id = (type & 0x0000ff00) >> 8; + serport->id.extra = (type & 0x00ff0000) >> 16; +} + /* * serport_ldisc_ioctl() allows to set the port protocol, and device ID */ -static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg) +static int serport_ldisc_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) { - struct serport *serport = (struct serport*) tty->disc_data; - unsigned long type; - if (cmd == SPIOCSTYPE) { + unsigned long type; + if (get_user(type, (unsigned long __user *) arg)) return -EFAULT; - serport->id.proto = type & 0x000000ff; - serport->id.id = (type & 0x0000ff00) >> 8; - serport->id.extra = (type & 0x00ff0000) >> 16; + serport_set_type(tty, type); + return 0; + } + + return -EINVAL; +} + +#ifdef CONFIG_COMPAT +#define COMPAT_SPIOCSTYPE _IOW('q', 0x01, compat_ulong_t) +static long serport_ldisc_compat_ioctl(struct tty_struct *tty, + struct file *file, + unsigned int cmd, unsigned long arg) +{ + if (cmd == COMPAT_SPIOCSTYPE) { + void __user *uarg = compat_ptr(arg); + compat_ulong_t compat_type; + + if (get_user(compat_type, (compat_ulong_t __user *)uarg)) + return -EFAULT; + serport_set_type(tty, compat_type); return 0; } return -EINVAL; } +#endif static void serport_ldisc_write_wakeup(struct tty_struct * tty) { @@ -243,6 +271,9 @@ static struct tty_ldisc_ops serport_ldisc = { .close = serport_ldisc_close, .read = serport_ldisc_read, .ioctl = serport_ldisc_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = serport_ldisc_compat_ioctl, +#endif .receive_buf = serport_ldisc_receive, .write_wakeup = serport_ldisc_write_wakeup }; diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index db178ed2b47..aaacf8bfa61 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -837,7 +837,12 @@ static irqreturn_t mxt_process_messages_t44(struct mxt_data *data) count = data->msg_buf[0]; if (count == 0) { - dev_warn(dev, "Interrupt triggered but zero messages\n"); + /* + * This condition is caused by the CHG line being configured + * in Mode 0. It results in unnecessary I2C operations but it + * is benign. + */ + dev_dbg(dev, "Interrupt triggered but zero messages\n"); return IRQ_NONE; } else if (count > data->max_reportid) { dev_err(dev, "T44 count %d exceeded max report id\n", count); @@ -1374,11 +1379,16 @@ static int mxt_get_info(struct mxt_data *data) return 0; } -static void mxt_free_object_table(struct mxt_data *data) +static void mxt_free_input_device(struct mxt_data *data) { - input_unregister_device(data->input_dev); - data->input_dev = NULL; + if (data->input_dev) { + input_unregister_device(data->input_dev); + data->input_dev = NULL; + } +} +static void mxt_free_object_table(struct mxt_data *data) +{ kfree(data->object_table); data->object_table = NULL; kfree(data->msg_buf); @@ -1957,11 +1967,13 @@ static int mxt_load_fw(struct device *dev, const char *fn) ret = mxt_lookup_bootloader_address(data, 0); if (ret) goto release_firmware; + + mxt_free_input_device(data); + mxt_free_object_table(data); } else { enable_irq(data->irq); } - mxt_free_object_table(data); reinit_completion(&data->bl_completion); ret = mxt_check_bootloader(data, MXT_WAITING_BOOTLOAD_CMD, false); @@ -2210,6 +2222,7 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) return 0; err_free_object: + mxt_free_input_device(data); mxt_free_object_table(data); err_free_irq: free_irq(client->irq, data); @@ -2224,7 +2237,7 @@ static int mxt_remove(struct i2c_client *client) sysfs_remove_group(&client->dev.kobj, &mxt_attr_group); free_irq(data->irq, data); - input_unregister_device(data->input_dev); + mxt_free_input_device(data); mxt_free_object_table(data); kfree(data); diff --git a/drivers/input/touchscreen/wm9712.c b/drivers/input/touchscreen/wm9712.c index 16b52115c27..705ffa1e064 100644 --- a/drivers/input/touchscreen/wm9712.c +++ b/drivers/input/touchscreen/wm9712.c @@ -41,7 +41,7 @@ */ static int rpu = 8; module_param(rpu, int, 0); -MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect."); +MODULE_PARM_DESC(rpu, "Set internal pull up resistor for pen detect."); /* * Set current used for pressure measurement. diff --git a/drivers/input/touchscreen/wm9713.c b/drivers/input/touchscreen/wm9713.c index 7405353199d..572a5a64fac 100644 --- a/drivers/input/touchscreen/wm9713.c +++ b/drivers/input/touchscreen/wm9713.c @@ -41,7 +41,7 @@ */ static int rpu = 8; module_param(rpu, int, 0); -MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect."); +MODULE_PARM_DESC(rpu, "Set internal pull up resistor for pen detect."); /* * Set current used for pressure measurement. diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index ca18d6d42a9..a83cc2a2a2c 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -146,6 +146,8 @@ #define ID0_CTTW (1 << 14) #define ID0_NUMIRPT_SHIFT 16 #define ID0_NUMIRPT_MASK 0xff +#define ID0_NUMSIDB_SHIFT 9 +#define ID0_NUMSIDB_MASK 0xf #define ID0_NUMSMRG_SHIFT 0 #define ID0_NUMSMRG_MASK 0xff @@ -524,9 +526,18 @@ static int register_smmu_master(struct arm_smmu_device *smmu, master->of_node = masterspec->np; master->cfg.num_streamids = masterspec->args_count; - for (i = 0; i < master->cfg.num_streamids; ++i) - master->cfg.streamids[i] = masterspec->args[i]; + for (i = 0; i < master->cfg.num_streamids; ++i) { + u16 streamid = masterspec->args[i]; + if (!(smmu->features & ARM_SMMU_FEAT_STREAM_MATCH) && + (streamid >= smmu->num_mapping_groups)) { + dev_err(dev, + "stream ID for master device %s greater than maximum allowed (%d)\n", + masterspec->np->name, smmu->num_mapping_groups); + return -ERANGE; + } + master->cfg.streamids[i] = streamid; + } return insert_smmu_master(smmu, master); } @@ -623,7 +634,7 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev) if (fsr & FSR_IGN) dev_err_ratelimited(smmu->dev, - "Unexpected context fault (fsr 0x%u)\n", + "Unexpected context fault (fsr 0x%x)\n", fsr); fsynr = readl_relaxed(cb_base + ARM_SMMU_CB_FSYNR0); @@ -752,6 +763,7 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain) reg = (TTBCR2_ADDR_36 << TTBCR2_SEP_SHIFT); break; case 39: + case 40: reg = (TTBCR2_ADDR_40 << TTBCR2_SEP_SHIFT); break; case 42: @@ -773,6 +785,7 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain) reg |= (TTBCR2_ADDR_36 << TTBCR2_PASIZE_SHIFT); break; case 39: + case 40: reg |= (TTBCR2_ADDR_40 << TTBCR2_PASIZE_SHIFT); break; case 42: @@ -843,8 +856,11 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain) reg |= TTBCR_EAE | (TTBCR_SH_IS << TTBCR_SH0_SHIFT) | (TTBCR_RGN_WBWA << TTBCR_ORGN0_SHIFT) | - (TTBCR_RGN_WBWA << TTBCR_IRGN0_SHIFT) | - (TTBCR_SL0_LVL_1 << TTBCR_SL0_SHIFT); + (TTBCR_RGN_WBWA << TTBCR_IRGN0_SHIFT); + + if (!stage1) + reg |= (TTBCR_SL0_LVL_1 << TTBCR_SL0_SHIFT); + writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBCR); /* MAIR0 (stage-1 only) */ @@ -868,10 +884,15 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain) static int arm_smmu_init_domain_context(struct iommu_domain *domain, struct arm_smmu_device *smmu) { - int irq, ret, start; + int irq, start, ret = 0; + unsigned long flags; struct arm_smmu_domain *smmu_domain = domain->priv; struct arm_smmu_cfg *cfg = &smmu_domain->cfg; + spin_lock_irqsave(&smmu_domain->lock, flags); + if (smmu_domain->smmu) + goto out_unlock; + if (smmu->features & ARM_SMMU_FEAT_TRANS_NESTED) { /* * We will likely want to change this if/when KVM gets @@ -890,7 +911,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, ret = __arm_smmu_alloc_bitmap(smmu->context_map, start, smmu->num_context_banks); if (IS_ERR_VALUE(ret)) - return ret; + goto out_unlock; cfg->cbndx = ret; if (smmu->version == 1) { @@ -900,6 +921,10 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, cfg->irptndx = cfg->cbndx; } + ACCESS_ONCE(smmu_domain->smmu) = smmu; + arm_smmu_init_context_bank(smmu_domain); + spin_unlock_irqrestore(&smmu_domain->lock, flags); + irq = smmu->irqs[smmu->num_global_irqs + cfg->irptndx]; ret = request_irq(irq, arm_smmu_context_fault, IRQF_SHARED, "arm-smmu-context-fault", domain); @@ -907,15 +932,12 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, dev_err(smmu->dev, "failed to request context IRQ %d (%u)\n", cfg->irptndx, irq); cfg->irptndx = INVALID_IRPTNDX; - goto out_free_context; } - smmu_domain->smmu = smmu; - arm_smmu_init_context_bank(smmu_domain); return 0; -out_free_context: - __arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx); +out_unlock: + spin_unlock_irqrestore(&smmu_domain->lock, flags); return ret; } @@ -975,7 +997,6 @@ static void arm_smmu_free_ptes(pmd_t *pmd) { pgtable_t table = pmd_pgtable(*pmd); - pgtable_page_dtor(table); __free_page(table); } @@ -1108,6 +1129,9 @@ static void arm_smmu_master_free_smrs(struct arm_smmu_device *smmu, void __iomem *gr0_base = ARM_SMMU_GR0(smmu); struct arm_smmu_smr *smrs = cfg->smrs; + if (!smrs) + return; + /* Invalidate the SMRs before freeing back to the allocator */ for (i = 0; i < cfg->num_streamids; ++i) { u8 idx = smrs[i].idx; @@ -1120,20 +1144,6 @@ static void arm_smmu_master_free_smrs(struct arm_smmu_device *smmu, kfree(smrs); } -static void arm_smmu_bypass_stream_mapping(struct arm_smmu_device *smmu, - struct arm_smmu_master_cfg *cfg) -{ - int i; - void __iomem *gr0_base = ARM_SMMU_GR0(smmu); - - for (i = 0; i < cfg->num_streamids; ++i) { - u16 sid = cfg->streamids[i]; - - writel_relaxed(S2CR_TYPE_BYPASS, - gr0_base + ARM_SMMU_GR0_S2CR(sid)); - } -} - static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain, struct arm_smmu_master_cfg *cfg) { @@ -1160,23 +1170,30 @@ static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain, static void arm_smmu_domain_remove_master(struct arm_smmu_domain *smmu_domain, struct arm_smmu_master_cfg *cfg) { + int i; struct arm_smmu_device *smmu = smmu_domain->smmu; + void __iomem *gr0_base = ARM_SMMU_GR0(smmu); /* * We *must* clear the S2CR first, because freeing the SMR means * that it can be re-allocated immediately. */ - arm_smmu_bypass_stream_mapping(smmu, cfg); + for (i = 0; i < cfg->num_streamids; ++i) { + u32 idx = cfg->smrs ? cfg->smrs[i].idx : cfg->streamids[i]; + + writel_relaxed(S2CR_TYPE_BYPASS, + gr0_base + ARM_SMMU_GR0_S2CR(idx)); + } + arm_smmu_master_free_smrs(smmu, cfg); } static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) { - int ret = -EINVAL; + int ret; struct arm_smmu_domain *smmu_domain = domain->priv; - struct arm_smmu_device *smmu; + struct arm_smmu_device *smmu, *dom_smmu; struct arm_smmu_master_cfg *cfg; - unsigned long flags; smmu = dev_get_master_dev(dev)->archdata.iommu; if (!smmu) { @@ -1188,20 +1205,22 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) * Sanity check the domain. We don't support domains across * different SMMUs. */ - spin_lock_irqsave(&smmu_domain->lock, flags); - if (!smmu_domain->smmu) { + dom_smmu = ACCESS_ONCE(smmu_domain->smmu); + if (!dom_smmu) { /* Now that we have a master, we can finalise the domain */ ret = arm_smmu_init_domain_context(domain, smmu); if (IS_ERR_VALUE(ret)) - goto err_unlock; - } else if (smmu_domain->smmu != smmu) { + return ret; + + dom_smmu = smmu_domain->smmu; + } + + if (dom_smmu != smmu) { dev_err(dev, "cannot attach to SMMU %s whilst already attached to domain on SMMU %s\n", - dev_name(smmu_domain->smmu->dev), - dev_name(smmu->dev)); - goto err_unlock; + dev_name(smmu_domain->smmu->dev), dev_name(smmu->dev)); + return -EINVAL; } - spin_unlock_irqrestore(&smmu_domain->lock, flags); /* Looks ok, so add the device to the domain */ cfg = find_smmu_master_cfg(smmu_domain->smmu, dev); @@ -1209,10 +1228,6 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) return -ENODEV; return arm_smmu_domain_add_master(smmu_domain, cfg); - -err_unlock: - spin_unlock_irqrestore(&smmu_domain->lock, flags); - return ret; } static void arm_smmu_detach_dev(struct iommu_domain *domain, struct device *dev) @@ -1247,10 +1262,6 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd, return -ENOMEM; arm_smmu_flush_pgtable(smmu, page_address(table), PAGE_SIZE); - if (!pgtable_page_ctor(table)) { - __free_page(table); - return -ENOMEM; - } pmd_populate(NULL, pmd, table); arm_smmu_flush_pgtable(smmu, pmd, sizeof(*pmd)); } @@ -1626,7 +1637,7 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu) /* Mark all SMRn as invalid and all S2CRn as bypass */ for (i = 0; i < smmu->num_mapping_groups; ++i) { - writel_relaxed(~SMR_VALID, gr0_base + ARM_SMMU_GR0_SMR(i)); + writel_relaxed(0, gr0_base + ARM_SMMU_GR0_SMR(i)); writel_relaxed(S2CR_TYPE_BYPASS, gr0_base + ARM_SMMU_GR0_S2CR(i)); } @@ -1761,6 +1772,9 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) dev_notice(smmu->dev, "\tstream matching with %u register groups, mask 0x%x", smmu->num_mapping_groups, mask); + } else { + smmu->num_mapping_groups = (id >> ID0_NUMSIDB_SHIFT) & + ID0_NUMSIDB_MASK; } /* ID1 */ @@ -1794,11 +1808,16 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) * Stage-1 output limited by stage-2 input size due to pgd * allocation (PTRS_PER_PGD). */ + if (smmu->features & ARM_SMMU_FEAT_TRANS_NESTED) { #ifdef CONFIG_64BIT - smmu->s1_output_size = min_t(unsigned long, VA_BITS, size); + smmu->s1_output_size = min_t(unsigned long, VA_BITS, size); #else - smmu->s1_output_size = min(32UL, size); + smmu->s1_output_size = min(32UL, size); #endif + } else { + smmu->s1_output_size = min_t(unsigned long, PHYS_MASK_SHIFT, + size); + } /* The stage-2 output mask is also applied for bypass */ size = arm_smmu_id_size_to_bits((id >> ID2_OAS_SHIFT) & ID2_OAS_MASK); @@ -1889,6 +1908,10 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) smmu->irqs[i] = irq; } + err = arm_smmu_device_cfg_probe(smmu); + if (err) + return err; + i = 0; smmu->masters = RB_ROOT; while (!of_parse_phandle_with_args(dev->of_node, "mmu-masters", @@ -1905,10 +1928,6 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) } dev_notice(dev, "registered %d master devices\n", i); - err = arm_smmu_device_cfg_probe(smmu); - if (err) - goto out_put_masters; - parse_driver_options(smmu); if (smmu->version > 1 && diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 60ab474bfff..06d268abe95 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -678,8 +678,7 @@ static int __init dmar_acpi_dev_scope_init(void) andd->device_name); continue; } - acpi_bus_get_device(h, &adev); - if (!adev) { + if (acpi_bus_get_device(h, &adev)) { pr_err("Failed to get device for ACPI object %s\n", andd->device_name); continue; diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c index 61d1dafa242..56feed7cec1 100644 --- a/drivers/iommu/fsl_pamu_domain.c +++ b/drivers/iommu/fsl_pamu_domain.c @@ -984,7 +984,7 @@ static int fsl_pamu_add_device(struct device *dev) struct iommu_group *group = ERR_PTR(-ENODEV); struct pci_dev *pdev; const u32 *prop; - int ret, len; + int ret = 0, len; /* * For platform devices we allocate a separate group for @@ -1007,7 +1007,13 @@ static int fsl_pamu_add_device(struct device *dev) if (IS_ERR(group)) return PTR_ERR(group); - ret = iommu_group_add_device(group, dev); + /* + * Check if device has already been added to an iommu group. + * Group could have already been created for a PCI device in + * the iommu_group_get_for_dev path. + */ + if (!dev->iommu_group) + ret = iommu_group_add_device(group, dev); iommu_group_put(group); return ret; diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index ac4adb33703..0639b9274b1 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -678,15 +678,17 @@ static struct iommu_group *iommu_group_get_for_pci_dev(struct pci_dev *pdev) */ struct iommu_group *iommu_group_get_for_dev(struct device *dev) { - struct iommu_group *group = ERR_PTR(-EIO); + struct iommu_group *group; int ret; group = iommu_group_get(dev); if (group) return group; - if (dev_is_pci(dev)) - group = iommu_group_get_for_pci_dev(to_pci_dev(dev)); + if (!dev_is_pci(dev)) + return ERR_PTR(-EINVAL); + + group = iommu_group_get_for_pci_dev(to_pci_dev(dev)); if (IS_ERR(group)) return group; diff --git a/drivers/irqchip/exynos-combiner.c b/drivers/irqchip/exynos-combiner.c index f8636a650cf..5945223b73f 100644 --- a/drivers/irqchip/exynos-combiner.c +++ b/drivers/irqchip/exynos-combiner.c @@ -15,6 +15,7 @@ #include <linux/slab.h> #include <linux/irqdomain.h> #include <linux/irqchip/chained_irq.h> +#include <linux/interrupt.h> #include <linux/of_address.h> #include <linux/of_irq.h> diff --git a/drivers/irqchip/irq-crossbar.c b/drivers/irqchip/irq-crossbar.c index 85c2985d8bc..bbbaf5de65d 100644 --- a/drivers/irqchip/irq-crossbar.c +++ b/drivers/irqchip/irq-crossbar.c @@ -220,7 +220,7 @@ static int __init crossbar_of_init(struct device_node *node) of_property_read_u32_index(node, "ti,irqs-reserved", i, &entry); - if (entry > max) { + if (entry >= max) { pr_err("Invalid reserved entry\n"); ret = -EINVAL; goto err_irq_map; @@ -238,7 +238,7 @@ static int __init crossbar_of_init(struct device_node *node) of_property_read_u32_index(node, "ti,irqs-skip", i, &entry); - if (entry > max) { + if (entry >= max) { pr_err("Invalid skip entry\n"); ret = -EINVAL; goto err_irq_map; diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 57eaa5a0b1e..a0698b4f030 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -36,7 +36,7 @@ struct gic_chip_data { void __iomem *dist_base; void __iomem **redist_base; - void __percpu __iomem **rdist; + void __iomem * __percpu *rdist; struct irq_domain *domain; u64 redist_stride; u32 redist_regions; @@ -104,7 +104,7 @@ static void gic_redist_wait_for_rwp(void) } /* Low level accessors */ -static u64 gic_read_iar(void) +static u64 __maybe_unused gic_read_iar(void) { u64 irqstat; @@ -112,24 +112,24 @@ static u64 gic_read_iar(void) return irqstat; } -static void gic_write_pmr(u64 val) +static void __maybe_unused gic_write_pmr(u64 val) { asm volatile("msr_s " __stringify(ICC_PMR_EL1) ", %0" : : "r" (val)); } -static void gic_write_ctlr(u64 val) +static void __maybe_unused gic_write_ctlr(u64 val) { asm volatile("msr_s " __stringify(ICC_CTLR_EL1) ", %0" : : "r" (val)); isb(); } -static void gic_write_grpen1(u64 val) +static void __maybe_unused gic_write_grpen1(u64 val) { asm volatile("msr_s " __stringify(ICC_GRPEN1_EL1) ", %0" : : "r" (val)); isb(); } -static void gic_write_sgi1r(u64 val) +static void __maybe_unused gic_write_sgi1r(u64 val) { asm volatile("msr_s " __stringify(ICC_SGI1R_EL1) ", %0" : : "r" (val)); } @@ -200,19 +200,6 @@ static void gic_poke_irq(struct irq_data *d, u32 offset) rwp_wait(); } -static int gic_peek_irq(struct irq_data *d, u32 offset) -{ - u32 mask = 1 << (gic_irq(d) % 32); - void __iomem *base; - - if (gic_irq_in_rdist(d)) - base = gic_data_rdist_sgi_base(); - else - base = gic_data.dist_base; - - return !!(readl_relaxed(base + offset + (gic_irq(d) / 32) * 4) & mask); -} - static void gic_mask_irq(struct irq_data *d) { gic_poke_irq(d, GICD_ICENABLER); @@ -401,6 +388,19 @@ static void gic_cpu_init(void) } #ifdef CONFIG_SMP +static int gic_peek_irq(struct irq_data *d, u32 offset) +{ + u32 mask = 1 << (gic_irq(d) % 32); + void __iomem *base; + + if (gic_irq_in_rdist(d)) + base = gic_data_rdist_sgi_base(); + else + base = gic_data.dist_base; + + return !!(readl_relaxed(base + offset + (gic_irq(d) / 32) * 4) & mask); +} + static int gic_secondary_init(struct notifier_block *nfb, unsigned long action, void *hcpu) { diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 4b959e606fe..dda6dbc2356 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -867,7 +867,7 @@ static int gic_routable_irq_domain_xlate(struct irq_domain *d, return 0; } -const struct irq_domain_ops gic_default_routable_irq_domain_ops = { +static const struct irq_domain_ops gic_default_routable_irq_domain_ops = { .map = gic_routable_irq_domain_map, .unmap = gic_routable_irq_domain_unmap, .xlate = gic_routable_irq_domain_xlate, diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index 1af40ee209e..7130505c242 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c @@ -895,8 +895,8 @@ static void migration_success_pre_commit(struct dm_cache_migration *mg) struct cache *cache = mg->cache; if (mg->writeback) { - cell_defer(cache, mg->old_ocell, false); clear_dirty(cache, mg->old_oblock, mg->cblock); + cell_defer(cache, mg->old_ocell, false); cleanup_migration(mg); return; @@ -951,13 +951,13 @@ static void migration_success_post_commit(struct dm_cache_migration *mg) } } else { + clear_dirty(cache, mg->new_oblock, mg->cblock); if (mg->requeue_holder) cell_defer(cache, mg->new_ocell, true); else { bio_endio(mg->new_ocell->holder, 0); cell_defer(cache, mg->new_ocell, false); } - clear_dirty(cache, mg->new_oblock, mg->cblock); cleanup_migration(mg); } } diff --git a/drivers/misc/lattice-ecp3-config.c b/drivers/misc/lattice-ecp3-config.c index 7ffdb589841..7e1efd5f58f 100644 --- a/drivers/misc/lattice-ecp3-config.c +++ b/drivers/misc/lattice-ecp3-config.c @@ -79,6 +79,11 @@ static void firmware_load(const struct firmware *fw, void *context) u32 jedec_id; u32 status; + if (fw == NULL) { + dev_err(&spi->dev, "Cannot load firmware, aborting\n"); + return; + } + if (fw->size == 0) { dev_err(&spi->dev, "Error: Firmware size is 0!\n"); return; diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c index 9dd63b82202..e9bf2f47b61 100644 --- a/drivers/ntb/ntb_transport.c +++ b/drivers/ntb/ntb_transport.c @@ -510,7 +510,7 @@ static void ntb_transport_setup_qp_mw(struct ntb_transport *nt, WARN_ON(nt->mw[mw_num].virt_addr == NULL); - if (nt->max_qps % mw_max && mw_num < nt->max_qps % mw_max) + if (nt->max_qps % mw_max && mw_num + 1 < nt->max_qps / mw_max) num_qps_mw = nt->max_qps / mw_max + 1; else num_qps_mw = nt->max_qps / mw_max; @@ -576,6 +576,19 @@ static int ntb_set_mw(struct ntb_transport *nt, int num_mw, unsigned int size) return -ENOMEM; } + /* + * we must ensure that the memory address allocated is BAR size + * aligned in order for the XLAT register to take the value. This + * is a requirement of the hardware. It is recommended to setup CMA + * for BAR sizes equal or greater than 4MB. + */ + if (!IS_ALIGNED(mw->dma_addr, mw->size)) { + dev_err(&pdev->dev, "DMA memory %pad not aligned to BAR size\n", + &mw->dma_addr); + ntb_free_mw(nt, num_mw); + return -ENOMEM; + } + /* Notify HW the memory location of the receive buffer */ ntb_set_mw_addr(nt->ndev, num_mw, mw->dma_addr); @@ -856,7 +869,7 @@ static int ntb_transport_init_queue(struct ntb_transport *nt, qp->client_ready = NTB_LINK_DOWN; qp->event_handler = NULL; - if (nt->max_qps % mw_max && mw_num < nt->max_qps % mw_max) + if (nt->max_qps % mw_max && mw_num + 1 < nt->max_qps / mw_max) num_qps_mw = nt->max_qps / mw_max + 1; else num_qps_mw = nt->max_qps / mw_max; diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index 9eae9834bcc..a0580afe171 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -913,7 +913,7 @@ static int __init dino_probe(struct parisc_device *dev) printk("%s version %s found at 0x%lx\n", name, version, hpa); if (!request_mem_region(hpa, PAGE_SIZE, name)) { - printk(KERN_ERR "DINO: Hey! Someone took my MMIO space (0x%ld)!\n", + printk(KERN_ERR "DINO: Hey! Someone took my MMIO space (0x%lx)!\n", hpa); return 1; } diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 0dd74271915..4ff8cbb620d 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -41,9 +41,9 @@ config PHY_MVEBU_SATA config PHY_MIPHY365X tristate "STMicroelectronics MIPHY365X PHY driver for STiH41x series" depends on ARCH_STI - depends on GENERIC_PHY depends on HAS_IOMEM depends on OF + select GENERIC_PHY help Enable this to support the miphy transceiver (for SATA/PCIE) that is part of STMicroelectronics STiH41x SoC series. diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/phy-exynos5-usbdrd.c index b05302b09c9..392101c8d6b 100644 --- a/drivers/phy/phy-exynos5-usbdrd.c +++ b/drivers/phy/phy-exynos5-usbdrd.c @@ -542,6 +542,7 @@ static const struct of_device_id exynos5_usbdrd_phy_of_match[] = { }, { }, }; +MODULE_DEVICE_TABLE(of, exynos5_usbdrd_phy_of_match); static int exynos5_usbdrd_phy_probe(struct platform_device *pdev) { diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c index e1a6623d469..9cd33a4bcfb 100644 --- a/drivers/phy/phy-twl4030-usb.c +++ b/drivers/phy/phy-twl4030-usb.c @@ -34,6 +34,7 @@ #include <linux/delay.h> #include <linux/usb/otg.h> #include <linux/phy/phy.h> +#include <linux/pm_runtime.h> #include <linux/usb/musb-omap.h> #include <linux/usb/ulpi.h> #include <linux/i2c/twl.h> @@ -422,37 +423,55 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on) } } -static int twl4030_phy_power_off(struct phy *phy) +static int twl4030_usb_runtime_suspend(struct device *dev) { - struct twl4030_usb *twl = phy_get_drvdata(phy); + struct twl4030_usb *twl = dev_get_drvdata(dev); + dev_dbg(twl->dev, "%s\n", __func__); if (twl->asleep) return 0; twl4030_phy_power(twl, 0); twl->asleep = 1; - dev_dbg(twl->dev, "%s\n", __func__); + return 0; } -static void __twl4030_phy_power_on(struct twl4030_usb *twl) +static int twl4030_usb_runtime_resume(struct device *dev) { + struct twl4030_usb *twl = dev_get_drvdata(dev); + + dev_dbg(twl->dev, "%s\n", __func__); + if (!twl->asleep) + return 0; + twl4030_phy_power(twl, 1); - twl4030_i2c_access(twl, 1); - twl4030_usb_set_mode(twl, twl->usb_mode); - if (twl->usb_mode == T2_USB_MODE_ULPI) - twl4030_i2c_access(twl, 0); + twl->asleep = 0; + + return 0; +} + +static int twl4030_phy_power_off(struct phy *phy) +{ + struct twl4030_usb *twl = phy_get_drvdata(phy); + + dev_dbg(twl->dev, "%s\n", __func__); + pm_runtime_mark_last_busy(twl->dev); + pm_runtime_put_autosuspend(twl->dev); + + return 0; } static int twl4030_phy_power_on(struct phy *phy) { struct twl4030_usb *twl = phy_get_drvdata(phy); - if (!twl->asleep) - return 0; - __twl4030_phy_power_on(twl); - twl->asleep = 0; dev_dbg(twl->dev, "%s\n", __func__); + pm_runtime_get_sync(twl->dev); + twl4030_i2c_access(twl, 1); + twl4030_usb_set_mode(twl, twl->usb_mode); + if (twl->usb_mode == T2_USB_MODE_ULPI) + twl4030_i2c_access(twl, 0); /* * XXX When VBUS gets driven after musb goes to A mode, @@ -558,9 +577,27 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) * USB_LINK_VBUS state. musb_hdrc won't care until it * starts to handle softconnect right. */ + if ((status == OMAP_MUSB_VBUS_VALID) || + (status == OMAP_MUSB_ID_GROUND)) { + if (twl->asleep) + pm_runtime_get_sync(twl->dev); + } else { + if (!twl->asleep) { + pm_runtime_mark_last_busy(twl->dev); + pm_runtime_put_autosuspend(twl->dev); + } + } omap_musb_mailbox(status); } - sysfs_notify(&twl->dev->kobj, NULL, "vbus"); + + /* don't schedule during sleep - irq works right then */ + if (status == OMAP_MUSB_ID_GROUND && !twl->asleep) { + cancel_delayed_work(&twl->id_workaround_work); + schedule_delayed_work(&twl->id_workaround_work, HZ); + } + + if (irq) + sysfs_notify(&twl->dev->kobj, NULL, "vbus"); return IRQ_HANDLED; } @@ -569,29 +606,8 @@ static void twl4030_id_workaround_work(struct work_struct *work) { struct twl4030_usb *twl = container_of(work, struct twl4030_usb, id_workaround_work.work); - enum omap_musb_vbus_id_status status; - bool status_changed = false; - - status = twl4030_usb_linkstat(twl); - - spin_lock_irq(&twl->lock); - if (status >= 0 && status != twl->linkstat) { - twl->linkstat = status; - status_changed = true; - } - spin_unlock_irq(&twl->lock); - - if (status_changed) { - dev_dbg(twl->dev, "handle missing status change to %d\n", - status); - omap_musb_mailbox(status); - } - /* don't schedule during sleep - irq works right then */ - if (status == OMAP_MUSB_ID_GROUND && !twl->asleep) { - cancel_delayed_work(&twl->id_workaround_work); - schedule_delayed_work(&twl->id_workaround_work, HZ); - } + twl4030_usb_irq(0, twl); } static int twl4030_phy_init(struct phy *phy) @@ -599,22 +615,17 @@ static int twl4030_phy_init(struct phy *phy) struct twl4030_usb *twl = phy_get_drvdata(phy); enum omap_musb_vbus_id_status status; - /* - * Start in sleep state, we'll get called through set_suspend() - * callback when musb is runtime resumed and it's time to start. - */ - __twl4030_phy_power(twl, 0); - twl->asleep = 1; - + pm_runtime_get_sync(twl->dev); status = twl4030_usb_linkstat(twl); twl->linkstat = status; - if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID) { + if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID) omap_musb_mailbox(twl->linkstat); - twl4030_phy_power_on(phy); - } sysfs_notify(&twl->dev->kobj, NULL, "vbus"); + pm_runtime_mark_last_busy(twl->dev); + pm_runtime_put_autosuspend(twl->dev); + return 0; } @@ -650,6 +661,11 @@ static const struct phy_ops ops = { .owner = THIS_MODULE, }; +static const struct dev_pm_ops twl4030_usb_pm_ops = { + SET_RUNTIME_PM_OPS(twl4030_usb_runtime_suspend, + twl4030_usb_runtime_resume, NULL) +}; + static int twl4030_usb_probe(struct platform_device *pdev) { struct twl4030_usb_data *pdata = dev_get_platdata(&pdev->dev); @@ -726,6 +742,11 @@ static int twl4030_usb_probe(struct platform_device *pdev) ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_set_autosuspend_delay(&pdev->dev, 2000); + pm_runtime_enable(&pdev->dev); + pm_runtime_get_sync(&pdev->dev); + /* Our job is to use irqs and status from the power module * to keep the transceiver disabled when nothing's connected. * @@ -744,6 +765,9 @@ static int twl4030_usb_probe(struct platform_device *pdev) return status; } + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_put_autosuspend(twl->dev); + dev_info(&pdev->dev, "Initialized TWL4030 USB module\n"); return 0; } @@ -753,6 +777,7 @@ static int twl4030_usb_remove(struct platform_device *pdev) struct twl4030_usb *twl = platform_get_drvdata(pdev); int val; + pm_runtime_get_sync(twl->dev); cancel_delayed_work(&twl->id_workaround_work); device_remove_file(twl->dev, &dev_attr_vbus); @@ -772,9 +797,8 @@ static int twl4030_usb_remove(struct platform_device *pdev) /* disable complete OTG block */ twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); - - if (!twl->asleep) - twl4030_phy_power(twl, 0); + pm_runtime_mark_last_busy(twl->dev); + pm_runtime_put(twl->dev); return 0; } @@ -792,6 +816,7 @@ static struct platform_driver twl4030_usb_driver = { .remove = twl4030_usb_remove, .driver = { .name = "twl4030_usb", + .pm = &twl4030_usb_pm_ops, .owner = THIS_MODULE, .of_match_table = of_match_ptr(twl4030_usb_id_table), }, diff --git a/drivers/pinctrl/pinctrl-baytrail.c b/drivers/pinctrl/pinctrl-baytrail.c index 9ca59a01874..e12e5b07f6d 100644 --- a/drivers/pinctrl/pinctrl-baytrail.c +++ b/drivers/pinctrl/pinctrl-baytrail.c @@ -461,6 +461,7 @@ static struct irq_chip byt_irqchip = { .irq_mask = byt_irq_mask, .irq_unmask = byt_irq_unmask, .irq_set_type = byt_irq_type, + .flags = IRQCHIP_SKIP_SET_WAKE, }; static void byt_gpio_irq_init_hw(struct byt_gpio *vg) diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index e7b2e023419..69139ce7420 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -199,7 +199,6 @@ struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt) fence->num_fences = 1; atomic_set(&fence->status, 1); - fence_get(&pt->base); fence->cbs[0].sync_pt = &pt->base; fence->cbs[0].fence = fence; if (fence_add_callback(&pt->base, &fence->cbs[0].cb, diff --git a/drivers/staging/imx-drm/imx-ldb.c b/drivers/staging/imx-drm/imx-ldb.c index 7e3f019d7e7..4662e00b456 100644 --- a/drivers/staging/imx-drm/imx-ldb.c +++ b/drivers/staging/imx-drm/imx-ldb.c @@ -574,6 +574,9 @@ static void imx_ldb_unbind(struct device *dev, struct device *master, for (i = 0; i < 2; i++) { struct imx_ldb_channel *channel = &imx_ldb->channel[i]; + if (!channel->connector.funcs) + continue; + channel->connector.funcs->destroy(&channel->connector); channel->encoder.funcs->destroy(&channel->encoder); } diff --git a/drivers/staging/imx-drm/ipuv3-plane.c b/drivers/staging/imx-drm/ipuv3-plane.c index 6f393a11f44..50de10a550e 100644 --- a/drivers/staging/imx-drm/ipuv3-plane.c +++ b/drivers/staging/imx-drm/ipuv3-plane.c @@ -281,7 +281,8 @@ static void ipu_plane_dpms(struct ipu_plane *ipu_plane, int mode) ipu_idmac_put(ipu_plane->ipu_ch); ipu_dmfc_put(ipu_plane->dmfc); - ipu_dp_put(ipu_plane->dp); + if (ipu_plane->dp) + ipu_dp_put(ipu_plane->dp); } } diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 4db7987ec22..57d9df84ce5 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -540,6 +540,7 @@ static const struct acpi_device_id dw8250_acpi_match[] = { { "INT3434", 0 }, { "INT3435", 0 }, { "80860F0A", 0 }, + { "8086228A", 0 }, { }, }; MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match); diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 7b63677475c..d7d4584549a 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -527,6 +527,45 @@ static void atmel_enable_ms(struct uart_port *port) } /* + * Disable modem status interrupts + */ +static void atmel_disable_ms(struct uart_port *port) +{ + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + uint32_t idr = 0; + + /* + * Interrupt should not be disabled twice + */ + if (!atmel_port->ms_irq_enabled) + return; + + atmel_port->ms_irq_enabled = false; + + if (atmel_port->gpio_irq[UART_GPIO_CTS] >= 0) + disable_irq(atmel_port->gpio_irq[UART_GPIO_CTS]); + else + idr |= ATMEL_US_CTSIC; + + if (atmel_port->gpio_irq[UART_GPIO_DSR] >= 0) + disable_irq(atmel_port->gpio_irq[UART_GPIO_DSR]); + else + idr |= ATMEL_US_DSRIC; + + if (atmel_port->gpio_irq[UART_GPIO_RI] >= 0) + disable_irq(atmel_port->gpio_irq[UART_GPIO_RI]); + else + idr |= ATMEL_US_RIIC; + + if (atmel_port->gpio_irq[UART_GPIO_DCD] >= 0) + disable_irq(atmel_port->gpio_irq[UART_GPIO_DCD]); + else + idr |= ATMEL_US_DCDIC; + + UART_PUT_IDR(port, idr); +} + +/* * Control the transmission of a break signal */ static void atmel_break_ctl(struct uart_port *port, int break_state) @@ -1993,7 +2032,9 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, /* CTS flow-control and modem-status interrupts */ if (UART_ENABLE_MS(port, termios->c_cflag)) - port->ops->enable_ms(port); + atmel_enable_ms(port); + else + atmel_disable_ms(port); spin_unlock_irqrestore(&port->lock, flags); } diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 01951d27cc0..806e4bcadbd 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -581,7 +581,7 @@ static unsigned int cdns_uart_tx_empty(struct uart_port *port) { unsigned int status; - status = cdns_uart_readl(CDNS_UART_ISR_OFFSET) & CDNS_UART_IXR_TXEMPTY; + status = cdns_uart_readl(CDNS_UART_SR_OFFSET) & CDNS_UART_SR_TXEMPTY; return status ? TIOCSER_TEMT : 0; } diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c index d72b9d2de2c..4935ac38fd0 100644 --- a/drivers/usb/chipidea/ci_hdrc_msm.c +++ b/drivers/usb/chipidea/ci_hdrc_msm.c @@ -20,13 +20,13 @@ static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event) { struct device *dev = ci->gadget.dev.parent; - int val; switch (event) { case CI_HDRC_CONTROLLER_RESET_EVENT: dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n"); writel(0, USB_AHBBURST); writel(0, USB_AHBMODE); + usb_phy_init(ci->transceiver); break; case CI_HDRC_CONTROLLER_STOPPED_EVENT: dev_dbg(dev, "CI_HDRC_CONTROLLER_STOPPED_EVENT received\n"); @@ -34,10 +34,7 @@ static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event) * Put the transceiver in non-driving mode. Otherwise host * may not detect soft-disconnection. */ - val = usb_phy_io_read(ci->transceiver, ULPI_FUNC_CTRL); - val &= ~ULPI_FUNC_CTRL_OPMODE_MASK; - val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; - usb_phy_io_write(ci->transceiver, val, ULPI_FUNC_CTRL); + usb_phy_notify_disconnect(ci->transceiver, USB_SPEED_UNKNOWN); break; default: dev_dbg(dev, "unknown ci_hdrc event\n"); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 46f5161c789..d481c99a20d 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -5024,9 +5024,10 @@ static void hub_events(void) hub = list_entry(tmp, struct usb_hub, event_list); kref_get(&hub->kref); + hdev = hub->hdev; + usb_get_dev(hdev); spin_unlock_irq(&hub_event_lock); - hdev = hub->hdev; hub_dev = hub->intfdev; intf = to_usb_interface(hub_dev); dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n", @@ -5139,6 +5140,7 @@ static void hub_events(void) usb_autopm_put_interface(intf); loop_disconnected: usb_unlock_device(hdev); + usb_put_dev(hdev); kref_put(&hub->kref, hub_release); } /* end while (1) */ diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 7c9618e916e..ce6071d65d5 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -1649,6 +1649,7 @@ static void s3c_hsotg_txfifo_flush(struct s3c_hsotg *hsotg, unsigned int idx) dev_err(hsotg->dev, "%s: timeout flushing fifo (GRSTCTL=%08x)\n", __func__, val); + break; } udelay(1); @@ -2747,13 +2748,14 @@ static void s3c_hsotg_phy_enable(struct s3c_hsotg *hsotg) dev_dbg(hsotg->dev, "pdev 0x%p\n", pdev); - if (hsotg->phy) { - phy_init(hsotg->phy); - phy_power_on(hsotg->phy); - } else if (hsotg->uphy) + if (hsotg->uphy) usb_phy_init(hsotg->uphy); - else if (hsotg->plat->phy_init) + else if (hsotg->plat && hsotg->plat->phy_init) hsotg->plat->phy_init(pdev, hsotg->plat->phy_type); + else { + phy_init(hsotg->phy); + phy_power_on(hsotg->phy); + } } /** @@ -2767,13 +2769,14 @@ static void s3c_hsotg_phy_disable(struct s3c_hsotg *hsotg) { struct platform_device *pdev = to_platform_device(hsotg->dev); - if (hsotg->phy) { - phy_power_off(hsotg->phy); - phy_exit(hsotg->phy); - } else if (hsotg->uphy) + if (hsotg->uphy) usb_phy_shutdown(hsotg->uphy); - else if (hsotg->plat->phy_exit) + else if (hsotg->plat && hsotg->plat->phy_exit) hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type); + else { + phy_power_off(hsotg->phy); + phy_exit(hsotg->phy); + } } /** @@ -2892,13 +2895,11 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget, return -ENODEV; /* all endpoints should be shutdown */ - for (ep = 0; ep < hsotg->num_of_eps; ep++) + for (ep = 1; ep < hsotg->num_of_eps; ep++) s3c_hsotg_ep_disable(&hsotg->eps[ep].ep); spin_lock_irqsave(&hsotg->lock, flags); - s3c_hsotg_phy_disable(hsotg); - if (!driver) hsotg->driver = NULL; @@ -2941,7 +2942,6 @@ static int s3c_hsotg_pullup(struct usb_gadget *gadget, int is_on) s3c_hsotg_phy_enable(hsotg); s3c_hsotg_core_init(hsotg); } else { - s3c_hsotg_disconnect(hsotg); s3c_hsotg_phy_disable(hsotg); } @@ -3441,13 +3441,6 @@ static int s3c_hsotg_probe(struct platform_device *pdev) hsotg->irq = ret; - ret = devm_request_irq(&pdev->dev, hsotg->irq, s3c_hsotg_irq, 0, - dev_name(dev), hsotg); - if (ret < 0) { - dev_err(dev, "cannot claim IRQ\n"); - goto err_clk; - } - dev_info(dev, "regs %p, irq %d\n", hsotg->regs, hsotg->irq); hsotg->gadget.max_speed = USB_SPEED_HIGH; @@ -3488,9 +3481,6 @@ static int s3c_hsotg_probe(struct platform_device *pdev) if (hsotg->phy && (phy_get_bus_width(phy) == 8)) hsotg->phyif = GUSBCFG_PHYIF8; - if (hsotg->phy) - phy_init(hsotg->phy); - /* usb phy enable */ s3c_hsotg_phy_enable(hsotg); @@ -3498,6 +3488,17 @@ static int s3c_hsotg_probe(struct platform_device *pdev) s3c_hsotg_init(hsotg); s3c_hsotg_hw_cfg(hsotg); + ret = devm_request_irq(&pdev->dev, hsotg->irq, s3c_hsotg_irq, 0, + dev_name(dev), hsotg); + if (ret < 0) { + s3c_hsotg_phy_disable(hsotg); + clk_disable_unprepare(hsotg->clk); + regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), + hsotg->supplies); + dev_err(dev, "cannot claim IRQ\n"); + goto err_clk; + } + /* hsotg->num_of_eps holds number of EPs other than ep0 */ if (hsotg->num_of_eps == 0) { @@ -3582,9 +3583,6 @@ static int s3c_hsotg_remove(struct platform_device *pdev) usb_gadget_unregister_driver(hsotg->driver); } - s3c_hsotg_phy_disable(hsotg); - if (hsotg->phy) - phy_exit(hsotg->phy); clk_disable_unprepare(hsotg->clk); return 0; diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index b769c1faaf0..9069984fe5c 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -799,20 +799,21 @@ static int dwc3_remove(struct platform_device *pdev) { struct dwc3 *dwc = platform_get_drvdata(pdev); + dwc3_debugfs_exit(dwc); + dwc3_core_exit_mode(dwc); + dwc3_event_buffers_cleanup(dwc); + dwc3_free_event_buffers(dwc); + usb_phy_set_suspend(dwc->usb2_phy, 1); usb_phy_set_suspend(dwc->usb3_phy, 1); phy_power_off(dwc->usb2_generic_phy); phy_power_off(dwc->usb3_generic_phy); + dwc3_core_exit(dwc); + pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); - dwc3_debugfs_exit(dwc); - dwc3_core_exit_mode(dwc); - dwc3_event_buffers_cleanup(dwc); - dwc3_free_event_buffers(dwc); - dwc3_core_exit(dwc); - return 0; } diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 9dcfbe7cd5f..fc0de375364 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -576,9 +576,9 @@ static int dwc3_omap_remove(struct platform_device *pdev) if (omap->extcon_id_dev.edev) extcon_unregister_interest(&omap->extcon_id_dev); dwc3_omap_disable_irqs(omap); + device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); - device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core); return 0; } diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 349cacc577d..490a6ca0073 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -527,7 +527,7 @@ static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep, dep->stream_capable = true; } - if (usb_endpoint_xfer_isoc(desc)) + if (!usb_endpoint_xfer_control(desc)) params.param1 |= DWC3_DEPCFG_XFER_IN_PROGRESS_EN; /* @@ -1225,16 +1225,17 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, int ret; + spin_lock_irqsave(&dwc->lock, flags); if (!dep->endpoint.desc) { dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n", request, ep->name); + spin_unlock_irqrestore(&dwc->lock, flags); return -ESHUTDOWN; } dev_vdbg(dwc->dev, "queing request %p to %s length %d\n", request, ep->name, request->length); - spin_lock_irqsave(&dwc->lock, flags); ret = __dwc3_gadget_ep_queue(dep, req); spin_unlock_irqrestore(&dwc->lock, flags); @@ -2041,12 +2042,6 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, dwc3_endpoint_transfer_complete(dwc, dep, event); break; case DWC3_DEPEVT_XFERINPROGRESS: - if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) { - dev_dbg(dwc->dev, "%s is not an Isochronous endpoint\n", - dep->name); - return; - } - dwc3_endpoint_transfer_complete(dwc, dep, event); break; case DWC3_DEPEVT_XFERNOTREADY: diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index dc30adf15a0..0dc3552d136 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -155,6 +155,12 @@ struct ffs_io_data { struct usb_request *req; }; +struct ffs_desc_helper { + struct ffs_data *ffs; + unsigned interfaces_count; + unsigned eps_count; +}; + static int __must_check ffs_epfiles_create(struct ffs_data *ffs); static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count); @@ -1830,7 +1836,8 @@ static int __ffs_data_do_entity(enum ffs_entity_type type, u8 *valuep, struct usb_descriptor_header *desc, void *priv) { - struct ffs_data *ffs = priv; + struct ffs_desc_helper *helper = priv; + struct usb_endpoint_descriptor *d; ENTER(); @@ -1844,8 +1851,8 @@ static int __ffs_data_do_entity(enum ffs_entity_type type, * encountered interface "n" then there are at least * "n+1" interfaces. */ - if (*valuep >= ffs->interfaces_count) - ffs->interfaces_count = *valuep + 1; + if (*valuep >= helper->interfaces_count) + helper->interfaces_count = *valuep + 1; break; case FFS_STRING: @@ -1853,14 +1860,22 @@ static int __ffs_data_do_entity(enum ffs_entity_type type, * Strings are indexed from 1 (0 is magic ;) reserved * for languages list or some such) */ - if (*valuep > ffs->strings_count) - ffs->strings_count = *valuep; + if (*valuep > helper->ffs->strings_count) + helper->ffs->strings_count = *valuep; break; case FFS_ENDPOINT: - /* Endpoints are indexed from 1 as well. */ - if ((*valuep & USB_ENDPOINT_NUMBER_MASK) > ffs->eps_count) - ffs->eps_count = (*valuep & USB_ENDPOINT_NUMBER_MASK); + d = (void *)desc; + helper->eps_count++; + if (helper->eps_count >= 15) + return -EINVAL; + /* Check if descriptors for any speed were already parsed */ + if (!helper->ffs->eps_count && !helper->ffs->interfaces_count) + helper->ffs->eps_addrmap[helper->eps_count] = + d->bEndpointAddress; + else if (helper->ffs->eps_addrmap[helper->eps_count] != + d->bEndpointAddress) + return -EINVAL; break; } @@ -2053,6 +2068,7 @@ static int __ffs_data_got_descs(struct ffs_data *ffs, char *data = _data, *raw_descs; unsigned os_descs_count = 0, counts[3], flags; int ret = -EINVAL, i; + struct ffs_desc_helper helper; ENTER(); @@ -2101,13 +2117,29 @@ static int __ffs_data_got_descs(struct ffs_data *ffs, /* Read descriptors */ raw_descs = data; + helper.ffs = ffs; for (i = 0; i < 3; ++i) { if (!counts[i]) continue; + helper.interfaces_count = 0; + helper.eps_count = 0; ret = ffs_do_descs(counts[i], data, len, - __ffs_data_do_entity, ffs); + __ffs_data_do_entity, &helper); if (ret < 0) goto error; + if (!ffs->eps_count && !ffs->interfaces_count) { + ffs->eps_count = helper.eps_count; + ffs->interfaces_count = helper.interfaces_count; + } else { + if (ffs->eps_count != helper.eps_count) { + ret = -EINVAL; + goto error; + } + if (ffs->interfaces_count != helper.interfaces_count) { + ret = -EINVAL; + goto error; + } + } data += ret; len -= ret; } @@ -2342,9 +2374,18 @@ static void ffs_event_add(struct ffs_data *ffs, spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags); } - /* Bind/unbind USB function hooks *******************************************/ +static int ffs_ep_addr2idx(struct ffs_data *ffs, u8 endpoint_address) +{ + int i; + + for (i = 1; i < ARRAY_SIZE(ffs->eps_addrmap); ++i) + if (ffs->eps_addrmap[i] == endpoint_address) + return i; + return -ENOENT; +} + static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep, struct usb_descriptor_header *desc, void *priv) @@ -2378,7 +2419,10 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep, if (!desc || desc->bDescriptorType != USB_DT_ENDPOINT) return 0; - idx = (ds->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) - 1; + idx = ffs_ep_addr2idx(func->ffs, ds->bEndpointAddress) - 1; + if (idx < 0) + return idx; + ffs_ep = func->eps + idx; if (unlikely(ffs_ep->descs[ep_desc_id])) { diff --git a/drivers/usb/gadget/function/u_fs.h b/drivers/usb/gadget/function/u_fs.h index 63d6e71569c..d48897e8ffe 100644 --- a/drivers/usb/gadget/function/u_fs.h +++ b/drivers/usb/gadget/function/u_fs.h @@ -224,6 +224,8 @@ struct ffs_data { void *ms_os_descs_ext_prop_name_avail; void *ms_os_descs_ext_prop_data_avail; + u8 eps_addrmap[15]; + unsigned short strings_count; unsigned short interfaces_count; unsigned short eps_count; diff --git a/drivers/usb/gadget/udc/fusb300_udc.h b/drivers/usb/gadget/udc/fusb300_udc.h index ae811d8d38b..ad39f892d20 100644 --- a/drivers/usb/gadget/udc/fusb300_udc.h +++ b/drivers/usb/gadget/udc/fusb300_udc.h @@ -12,7 +12,7 @@ #ifndef __FUSB300_UDC_H__ -#define __FUSB300_UDC_H_ +#define __FUSB300_UDC_H__ #include <linux/kernel.h> diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c index f4eac113690..2e95715b50c 100644 --- a/drivers/usb/gadget/udc/net2280.c +++ b/drivers/usb/gadget/udc/net2280.c @@ -3320,7 +3320,7 @@ static void handle_stat1_irqs(struct net2280 *dev, u32 stat) if (stat & tmp) { writel(tmp, &dev->regs->irqstat1); if ((((stat & BIT(ROOT_PORT_RESET_INTERRUPT)) && - (readl(&dev->usb->usbstat) & mask)) || + ((readl(&dev->usb->usbstat) & mask) == 0)) || ((readl(&dev->usb->usbctl) & BIT(VBUS_PIN)) == 0)) && (dev->gadget.speed != USB_SPEED_UNKNOWN)) { diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index aa79e874904..69aece31143 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -468,7 +468,8 @@ static void xhci_hub_report_usb2_link_state(u32 *status, u32 status_reg) } /* Updates Link Status for super Speed port */ -static void xhci_hub_report_usb3_link_state(u32 *status, u32 status_reg) +static void xhci_hub_report_usb3_link_state(struct xhci_hcd *xhci, + u32 *status, u32 status_reg) { u32 pls = status_reg & PORT_PLS_MASK; @@ -507,7 +508,8 @@ static void xhci_hub_report_usb3_link_state(u32 *status, u32 status_reg) * in which sometimes the port enters compliance mode * caused by a delay on the host-device negotiation. */ - if (pls == USB_SS_PORT_LS_COMP_MOD) + if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && + (pls == USB_SS_PORT_LS_COMP_MOD)) pls |= USB_PORT_STAT_CONNECTION; } @@ -666,7 +668,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, } /* Update Port Link State */ if (hcd->speed == HCD_USB3) { - xhci_hub_report_usb3_link_state(&status, raw_port_status); + xhci_hub_report_usb3_link_state(xhci, &status, raw_port_status); /* * Verify if all USB3 Ports Have entered U0 already. * Delete Compliance Mode Timer if so. diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 8056d90690e..8936211b161 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1812,6 +1812,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) if (xhci->lpm_command) xhci_free_command(xhci, xhci->lpm_command); + xhci->lpm_command = NULL; if (xhci->cmd_ring) xhci_ring_free(xhci, xhci->cmd_ring); xhci->cmd_ring = NULL; @@ -1819,7 +1820,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) xhci_cleanup_command_queue(xhci); num_ports = HCS_MAX_PORTS(xhci->hcs_params1); - for (i = 0; i < num_ports; i++) { + for (i = 0; i < num_ports && xhci->rh_bw; i++) { struct xhci_interval_bw_table *bwt = &xhci->rh_bw[i].bw_table; for (j = 0; j < XHCI_MAX_INTERVAL; j++) { struct list_head *ep = &bwt->interval_bw[j].endpoints; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index c020b094fe7..c4a8fca8ae9 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3971,13 +3971,21 @@ static int __maybe_unused xhci_change_max_exit_latency(struct xhci_hcd *xhci, int ret; spin_lock_irqsave(&xhci->lock, flags); - if (max_exit_latency == xhci->devs[udev->slot_id]->current_mel) { + + virt_dev = xhci->devs[udev->slot_id]; + + /* + * virt_dev might not exists yet if xHC resumed from hibernate (S4) and + * xHC was re-initialized. Exit latency will be set later after + * hub_port_finish_reset() is done and xhci->devs[] are re-allocated + */ + + if (!virt_dev || max_exit_latency == virt_dev->current_mel) { spin_unlock_irqrestore(&xhci->lock, flags); return 0; } /* Attempt to issue an Evaluate Context command to change the MEL. */ - virt_dev = xhci->devs[udev->slot_id]; command = xhci->lpm_command; ctrl_ctx = xhci_get_input_control_ctx(xhci, command->in_ctx); if (!ctrl_ctx) { diff --git a/drivers/usb/musb/musb_cppi41.c b/drivers/usb/musb/musb_cppi41.c index 47ae6455d07..3ee133f675a 100644 --- a/drivers/usb/musb/musb_cppi41.c +++ b/drivers/usb/musb/musb_cppi41.c @@ -39,6 +39,7 @@ struct cppi41_dma_channel { u32 transferred; u32 packet_sz; struct list_head tx_check; + int tx_zlp; }; #define MUSB_DMA_NUM_CHANNELS 15 @@ -122,6 +123,8 @@ static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel) { struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep; struct musb *musb = hw_ep->musb; + void __iomem *epio = hw_ep->regs; + u16 csr; if (!cppi41_channel->prog_len || (cppi41_channel->channel.status == MUSB_DMA_STATUS_FREE)) { @@ -131,15 +134,24 @@ static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel) cppi41_channel->transferred; cppi41_channel->channel.status = MUSB_DMA_STATUS_FREE; cppi41_channel->channel.rx_packet_done = true; + + /* + * transmit ZLP using PIO mode for transfers which size is + * multiple of EP packet size. + */ + if (cppi41_channel->tx_zlp && (cppi41_channel->transferred % + cppi41_channel->packet_sz) == 0) { + musb_ep_select(musb->mregs, hw_ep->epnum); + csr = MUSB_TXCSR_MODE | MUSB_TXCSR_TXPKTRDY; + musb_writew(epio, MUSB_TXCSR, csr); + } musb_dma_completion(musb, hw_ep->epnum, cppi41_channel->is_tx); } else { /* next iteration, reload */ struct dma_chan *dc = cppi41_channel->dc; struct dma_async_tx_descriptor *dma_desc; enum dma_transfer_direction direction; - u16 csr; u32 remain_bytes; - void __iomem *epio = cppi41_channel->hw_ep->regs; cppi41_channel->buf_addr += cppi41_channel->packet_sz; @@ -363,6 +375,7 @@ static bool cppi41_configure_channel(struct dma_channel *channel, cppi41_channel->total_len = len; cppi41_channel->transferred = 0; cppi41_channel->packet_sz = packet_sz; + cppi41_channel->tx_zlp = (cppi41_channel->is_tx && mode) ? 1 : 0; /* * Due to AM335x' Advisory 1.0.13 we are not allowed to transfer more diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c index c42bdf0c4a1..00972eca04e 100644 --- a/drivers/usb/phy/phy-mxs-usb.c +++ b/drivers/usb/phy/phy-mxs-usb.c @@ -1,5 +1,5 @@ /* - * Copyright 2012-2013 Freescale Semiconductor, Inc. + * Copyright 2012-2014 Freescale Semiconductor, Inc. * Copyright (C) 2012 Marek Vasut <marex@denx.de> * on behalf of DENX Software Engineering GmbH * @@ -125,7 +125,13 @@ static const struct mxs_phy_data imx6sl_phy_data = { MXS_PHY_NEED_IP_FIX, }; +static const struct mxs_phy_data imx6sx_phy_data = { + .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS | + MXS_PHY_NEED_IP_FIX, +}; + static const struct of_device_id mxs_phy_dt_ids[] = { + { .compatible = "fsl,imx6sx-usbphy", .data = &imx6sx_phy_data, }, { .compatible = "fsl,imx6sl-usbphy", .data = &imx6sl_phy_data, }, { .compatible = "fsl,imx6q-usbphy", .data = &imx6q_phy_data, }, { .compatible = "fsl,imx23-usbphy", .data = &imx23_phy_data, }, diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c index 13b4fa287da..886f1807a67 100644 --- a/drivers/usb/phy/phy-tegra-usb.c +++ b/drivers/usb/phy/phy-tegra-usb.c @@ -878,8 +878,8 @@ static int utmi_phy_probe(struct tegra_usb_phy *tegra_phy, return -ENOMEM; } - tegra_phy->config = devm_kzalloc(&pdev->dev, - sizeof(*tegra_phy->config), GFP_KERNEL); + tegra_phy->config = devm_kzalloc(&pdev->dev, sizeof(*config), + GFP_KERNEL); if (!tegra_phy->config) { dev_err(&pdev->dev, "unable to allocate memory for USB UTMIP config\n"); diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 4fd36530bfa..b0c97a3f1bf 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -108,19 +108,45 @@ static struct usbhs_pkt *__usbhsf_pkt_get(struct usbhs_pipe *pipe) return list_first_entry(&pipe->list, struct usbhs_pkt, node); } +static void usbhsf_fifo_clear(struct usbhs_pipe *pipe, + struct usbhs_fifo *fifo); +static void usbhsf_fifo_unselect(struct usbhs_pipe *pipe, + struct usbhs_fifo *fifo); +static struct dma_chan *usbhsf_dma_chan_get(struct usbhs_fifo *fifo, + struct usbhs_pkt *pkt); +#define usbhsf_dma_map(p) __usbhsf_dma_map_ctrl(p, 1) +#define usbhsf_dma_unmap(p) __usbhsf_dma_map_ctrl(p, 0) +static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map); struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt) { struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); + struct usbhs_fifo *fifo = usbhs_pipe_to_fifo(pipe); unsigned long flags; /******************** spin lock ********************/ usbhs_lock(priv, flags); + usbhs_pipe_disable(pipe); + if (!pkt) pkt = __usbhsf_pkt_get(pipe); - if (pkt) + if (pkt) { + struct dma_chan *chan = NULL; + + if (fifo) + chan = usbhsf_dma_chan_get(fifo, pkt); + if (chan) { + dmaengine_terminate_all(chan); + usbhsf_fifo_clear(pipe, fifo); + usbhsf_dma_unmap(pkt); + } + __usbhsf_pkt_del(pkt); + } + + if (fifo) + usbhsf_fifo_unselect(pipe, fifo); usbhs_unlock(priv, flags); /******************** spin unlock ******************/ @@ -544,6 +570,7 @@ static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done) usbhsf_send_terminator(pipe, fifo); usbhsf_tx_irq_ctrl(pipe, !*is_done); + usbhs_pipe_running(pipe, !*is_done); usbhs_pipe_enable(pipe); dev_dbg(dev, " send %d (%d/ %d/ %d/ %d)\n", @@ -570,12 +597,21 @@ usbhs_fifo_write_busy: * retry in interrupt */ usbhsf_tx_irq_ctrl(pipe, 1); + usbhs_pipe_running(pipe, 1); return ret; } +static int usbhsf_pio_prepare_push(struct usbhs_pkt *pkt, int *is_done) +{ + if (usbhs_pipe_is_running(pkt->pipe)) + return 0; + + return usbhsf_pio_try_push(pkt, is_done); +} + struct usbhs_pkt_handle usbhs_fifo_pio_push_handler = { - .prepare = usbhsf_pio_try_push, + .prepare = usbhsf_pio_prepare_push, .try_run = usbhsf_pio_try_push, }; @@ -589,6 +625,9 @@ static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done) if (usbhs_pipe_is_busy(pipe)) return 0; + if (usbhs_pipe_is_running(pipe)) + return 0; + /* * pipe enable to prepare packet receive */ @@ -597,6 +636,7 @@ static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done) usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->length); usbhs_pipe_enable(pipe); + usbhs_pipe_running(pipe, 1); usbhsf_rx_irq_ctrl(pipe, 1); return 0; @@ -642,6 +682,7 @@ static int usbhsf_pio_try_pop(struct usbhs_pkt *pkt, int *is_done) (total_len < maxp)) { /* short packet */ *is_done = 1; usbhsf_rx_irq_ctrl(pipe, 0); + usbhs_pipe_running(pipe, 0); usbhs_pipe_disable(pipe); /* disable pipe first */ } @@ -763,8 +804,6 @@ static void __usbhsf_dma_ctrl(struct usbhs_pipe *pipe, usbhs_bset(priv, fifo->sel, DREQE, dreqe); } -#define usbhsf_dma_map(p) __usbhsf_dma_map_ctrl(p, 1) -#define usbhsf_dma_unmap(p) __usbhsf_dma_map_ctrl(p, 0) static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map) { struct usbhs_pipe *pipe = pkt->pipe; @@ -805,6 +844,7 @@ static void xfer_work(struct work_struct *work) dev_dbg(dev, " %s %d (%d/ %d)\n", fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero); + usbhs_pipe_running(pipe, 1); usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->trans); usbhs_pipe_enable(pipe); usbhsf_dma_start(pipe, fifo); @@ -836,6 +876,10 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done) if ((uintptr_t)(pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ goto usbhsf_pio_prepare_push; + /* return at this time if the pipe is running */ + if (usbhs_pipe_is_running(pipe)) + return 0; + /* get enable DMA fifo */ fifo = usbhsf_get_dma_fifo(priv, pkt); if (!fifo) @@ -869,15 +913,29 @@ usbhsf_pio_prepare_push: static int usbhsf_dma_push_done(struct usbhs_pkt *pkt, int *is_done) { struct usbhs_pipe *pipe = pkt->pipe; + int is_short = pkt->trans % usbhs_pipe_get_maxpacket(pipe); + + pkt->actual += pkt->trans; - pkt->actual = pkt->trans; + if (pkt->actual < pkt->length) + *is_done = 0; /* there are remainder data */ + else if (is_short) + *is_done = 1; /* short packet */ + else + *is_done = !pkt->zero; /* send zero packet? */ - *is_done = !pkt->zero; /* send zero packet ? */ + usbhs_pipe_running(pipe, !*is_done); usbhsf_dma_stop(pipe, pipe->fifo); usbhsf_dma_unmap(pkt); usbhsf_fifo_unselect(pipe, pipe->fifo); + if (!*is_done) { + /* change handler to PIO */ + pkt->handler = &usbhs_fifo_pio_push_handler; + return pkt->handler->try_run(pkt, is_done); + } + return 0; } @@ -972,8 +1030,10 @@ static int usbhsf_dma_pop_done(struct usbhs_pkt *pkt, int *is_done) if ((pkt->actual == pkt->length) || /* receive all data */ (pkt->trans < maxp)) { /* short packet */ *is_done = 1; + usbhs_pipe_running(pipe, 0); } else { /* re-enable */ + usbhs_pipe_running(pipe, 0); usbhsf_prepare_pop(pkt, is_done); } diff --git a/drivers/usb/renesas_usbhs/mod.c b/drivers/usb/renesas_usbhs/mod.c index 6a030b931a3..9a705b15b3a 100644 --- a/drivers/usb/renesas_usbhs/mod.c +++ b/drivers/usb/renesas_usbhs/mod.c @@ -213,7 +213,10 @@ static int usbhs_status_get_each_irq(struct usbhs_priv *priv, { struct usbhs_mod *mod = usbhs_mod_get_current(priv); u16 intenb0, intenb1; + unsigned long flags; + /******************** spin lock ********************/ + usbhs_lock(priv, flags); state->intsts0 = usbhs_read(priv, INTSTS0); state->intsts1 = usbhs_read(priv, INTSTS1); @@ -229,6 +232,8 @@ static int usbhs_status_get_each_irq(struct usbhs_priv *priv, state->bempsts &= mod->irq_bempsts; state->brdysts &= mod->irq_brdysts; } + usbhs_unlock(priv, flags); + /******************** spin unlock ******************/ /* * Check whether the irq enable registers and the irq status are set diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c index 75fbcf6b102..040bcefcb04 100644 --- a/drivers/usb/renesas_usbhs/pipe.c +++ b/drivers/usb/renesas_usbhs/pipe.c @@ -578,6 +578,19 @@ int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe) return usbhsp_flags_has(pipe, IS_DIR_HOST); } +int usbhs_pipe_is_running(struct usbhs_pipe *pipe) +{ + return usbhsp_flags_has(pipe, IS_RUNNING); +} + +void usbhs_pipe_running(struct usbhs_pipe *pipe, int running) +{ + if (running) + usbhsp_flags_set(pipe, IS_RUNNING); + else + usbhsp_flags_clr(pipe, IS_RUNNING); +} + void usbhs_pipe_data_sequence(struct usbhs_pipe *pipe, int sequence) { u16 mask = (SQCLR | SQSET); diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h index 406f36d050e..d24a0597237 100644 --- a/drivers/usb/renesas_usbhs/pipe.h +++ b/drivers/usb/renesas_usbhs/pipe.h @@ -36,6 +36,7 @@ struct usbhs_pipe { #define USBHS_PIPE_FLAGS_IS_USED (1 << 0) #define USBHS_PIPE_FLAGS_IS_DIR_IN (1 << 1) #define USBHS_PIPE_FLAGS_IS_DIR_HOST (1 << 2) +#define USBHS_PIPE_FLAGS_IS_RUNNING (1 << 3) struct usbhs_pkt_handle *handler; @@ -80,6 +81,9 @@ int usbhs_pipe_probe(struct usbhs_priv *priv); void usbhs_pipe_remove(struct usbhs_priv *priv); int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe); int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe); +int usbhs_pipe_is_running(struct usbhs_pipe *pipe); +void usbhs_pipe_running(struct usbhs_pipe *pipe, int running); + void usbhs_pipe_init(struct usbhs_priv *priv, int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map)); int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe); diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 824ea5e7ec8..dc72b924c39 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -728,6 +728,7 @@ static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(FTDI_VID, FTDI_NDI_AURORA_SCU_PID), .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) }, + { USB_DEVICE(NOVITUS_VID, NOVITUS_BONO_E_PID) }, { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_S03_PID) }, { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_59_PID) }, { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_57A_PID) }, @@ -939,6 +940,8 @@ static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(FTDI_VID, FTDI_EKEY_CONV_USB_PID) }, /* Infineon Devices */ { USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_PID, 1) }, + /* GE Healthcare devices */ + { USB_DEVICE(GE_HEALTHCARE_VID, GE_HEALTHCARE_NEMO_TRACKER_PID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 70b0b1d88ae..5937b2d242f 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -837,6 +837,12 @@ #define TELLDUS_TELLSTICK_PID 0x0C30 /* RF control dongle 433 MHz using FT232RL */ /* + * NOVITUS printers + */ +#define NOVITUS_VID 0x1a28 +#define NOVITUS_BONO_E_PID 0x6010 + +/* * RT Systems programming cables for various ham radios */ #define RTSYSTEMS_VID 0x2100 /* Vendor ID */ @@ -1385,3 +1391,9 @@ * ekey biometric systems GmbH (http://ekey.net/) */ #define FTDI_EKEY_CONV_USB_PID 0xCB08 /* Converter USB */ + +/* + * GE Healthcare devices + */ +#define GE_HEALTHCARE_VID 0x1901 +#define GE_HEALTHCARE_NEMO_TRACKER_PID 0x0015 diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 6f7f01eb556..46179a0828e 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -282,14 +282,19 @@ static const struct usb_device_id id_table[] = { /* Sierra Wireless HSPA Non-Composite Device */ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)}, { USB_DEVICE(0x1199, 0x6893) }, /* Sierra Wireless Device */ - { USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modems */ + /* Sierra Wireless Direct IP modems */ + { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68A3, 0xFF, 0xFF, 0xFF), + .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist + }, + { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68AA, 0xFF, 0xFF, 0xFF), .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist }, /* AT&T Direct IP LTE modems */ { USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68AA, 0xFF, 0xFF, 0xFF), .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist }, - { USB_DEVICE(0x0f3d, 0x68A3), /* Airprime/Sierra Wireless Direct IP modems */ + /* Airprime/Sierra Wireless Direct IP modems */ + { USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68A3, 0xFF, 0xFF, 0xFF), .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist }, diff --git a/drivers/usb/serial/zte_ev.c b/drivers/usb/serial/zte_ev.c index 1a132e9e947..c9bb107d5e5 100644 --- a/drivers/usb/serial/zte_ev.c +++ b/drivers/usb/serial/zte_ev.c @@ -272,6 +272,14 @@ static void zte_ev_usb_serial_close(struct usb_serial_port *port) } static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x19d2, 0xffec) }, + { USB_DEVICE(0x19d2, 0xffee) }, + { USB_DEVICE(0x19d2, 0xfff6) }, + { USB_DEVICE(0x19d2, 0xfff7) }, + { USB_DEVICE(0x19d2, 0xfff8) }, + { USB_DEVICE(0x19d2, 0xfff9) }, + { USB_DEVICE(0x19d2, 0xfffb) }, + { USB_DEVICE(0x19d2, 0xfffc) }, /* MG880 */ { USB_DEVICE(0x19d2, 0xfffd) }, { }, diff --git a/drivers/usb/storage/uas-detect.h b/drivers/usb/storage/uas-detect.h index 503ac5c8d80..8a6f371ed6e 100644 --- a/drivers/usb/storage/uas-detect.h +++ b/drivers/usb/storage/uas-detect.h @@ -59,10 +59,6 @@ static int uas_use_uas_driver(struct usb_interface *intf, unsigned long flags = id->driver_info; int r, alt; - usb_stor_adjust_quirks(udev, &flags); - - if (flags & US_FL_IGNORE_UAS) - return 0; alt = uas_find_uas_alt_setting(intf); if (alt < 0) @@ -72,6 +68,29 @@ static int uas_use_uas_driver(struct usb_interface *intf, if (r < 0) return 0; + /* + * ASM1051 and older ASM1053 devices have the same usb-id, and UAS is + * broken on the ASM1051, use the number of streams to differentiate. + * New ASM1053-s also support 32 streams, but have a different prod-id. + */ + if (le16_to_cpu(udev->descriptor.idVendor) == 0x174c && + le16_to_cpu(udev->descriptor.idProduct) == 0x55aa) { + if (udev->speed < USB_SPEED_SUPER) { + /* No streams info, assume ASM1051 */ + flags |= US_FL_IGNORE_UAS; + } else if (usb_ss_max_streams(&eps[1]->ss_ep_comp) == 32) { + flags |= US_FL_IGNORE_UAS; + } + } + + usb_stor_adjust_quirks(udev, &flags); + + if (flags & US_FL_IGNORE_UAS) { + dev_warn(&udev->dev, + "UAS is blacklisted for this device, using usb-storage instead\n"); + return 0; + } + if (udev->bus->sg_tablesize == 0) { dev_warn(&udev->dev, "The driver for the USB controller %s does not support scatter-gather which is\n", diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 7ef99b2f3aa..60cfcbc7855 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -741,6 +741,12 @@ UNUSUAL_DEV( 0x059b, 0x0001, 0x0100, 0x0100, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), +UNUSUAL_DEV( 0x059b, 0x0040, 0x0100, 0x0100, + "Iomega", + "Jaz USB Adapter", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_SINGLE_LUN ), + /* Reported by <Hendryk.Pfeiffer@gmx.de> */ UNUSUAL_DEV( 0x059f, 0x0643, 0x0000, 0x0000, "LaCie", diff --git a/drivers/uwb/lc-dev.c b/drivers/uwb/lc-dev.c index 80079b8fed1..d0303f0dbe1 100644 --- a/drivers/uwb/lc-dev.c +++ b/drivers/uwb/lc-dev.c @@ -431,16 +431,19 @@ void uwbd_dev_onair(struct uwb_rc *rc, struct uwb_beca_e *bce) uwb_dev->mac_addr = *bce->mac_addr; uwb_dev->dev_addr = bce->dev_addr; dev_set_name(&uwb_dev->dev, "%s", macbuf); + + /* plug the beacon cache */ + bce->uwb_dev = uwb_dev; + uwb_dev->bce = bce; + uwb_bce_get(bce); /* released in uwb_dev_sys_release() */ + result = uwb_dev_add(uwb_dev, &rc->uwb_dev.dev, rc); if (result < 0) { dev_err(dev, "new device %s: cannot instantiate device\n", macbuf); goto error_dev_add; } - /* plug the beacon cache */ - bce->uwb_dev = uwb_dev; - uwb_dev->bce = bce; - uwb_bce_get(bce); /* released in uwb_dev_sys_release() */ + dev_info(dev, "uwb device (mac %s dev %s) connected to %s %s\n", macbuf, devbuf, rc->uwb_dev.dev.parent->bus->name, dev_name(rc->uwb_dev.dev.parent)); @@ -448,6 +451,8 @@ void uwbd_dev_onair(struct uwb_rc *rc, struct uwb_beca_e *bce) return; error_dev_add: + bce->uwb_dev = NULL; + uwb_bce_put(bce); kfree(uwb_dev); return; } diff --git a/drivers/video/fbdev/amba-clcd.c b/drivers/video/fbdev/amba-clcd.c index a7b6217ac87..6ad23bd3523 100644 --- a/drivers/video/fbdev/amba-clcd.c +++ b/drivers/video/fbdev/amba-clcd.c @@ -639,9 +639,7 @@ static int clcdfb_of_init_tft_panel(struct clcd_fb *fb, u32 r0, u32 g0, u32 b0) if (g0 != panels[i].g0) continue; if (r0 == panels[i].r0 && b0 == panels[i].b0) - fb->panel->caps = panels[i].caps & CLCD_CAP_RGB; - if (r0 == panels[i].b0 && b0 == panels[i].r0) - fb->panel->caps = panels[i].caps & CLCD_CAP_BGR; + fb->panel->caps = panels[i].caps; } return fb->panel->caps ? 0 : -EINVAL; diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index 5c660c77f03..1e0a317d3dc 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -230,8 +230,8 @@ static enum bp_state reserve_additional_memory(long credit) rc = add_memory(nid, hotplug_start_paddr, balloon_hotplug << PAGE_SHIFT); if (rc) { - pr_info("%s: add_memory() failed: %i\n", __func__, rc); - return BP_EAGAIN; + pr_warn("Cannot add additional memory (%i)\n", rc); + return BP_ECANCELED; } balloon_hotplug -= credit; diff --git a/drivers/xen/gntalloc.c b/drivers/xen/gntalloc.c index 787d1794541..e53fe191738 100644 --- a/drivers/xen/gntalloc.c +++ b/drivers/xen/gntalloc.c @@ -124,7 +124,7 @@ static int add_grefs(struct ioctl_gntalloc_alloc_gref *op, int i, rc, readonly; LIST_HEAD(queue_gref); LIST_HEAD(queue_file); - struct gntalloc_gref *gref; + struct gntalloc_gref *gref, *next; readonly = !(op->flags & GNTALLOC_FLAG_WRITABLE); rc = -ENOMEM; @@ -141,13 +141,11 @@ static int add_grefs(struct ioctl_gntalloc_alloc_gref *op, goto undo; /* Grant foreign access to the page. */ - gref->gref_id = gnttab_grant_foreign_access(op->domid, + rc = gnttab_grant_foreign_access(op->domid, pfn_to_mfn(page_to_pfn(gref->page)), readonly); - if ((int)gref->gref_id < 0) { - rc = gref->gref_id; + if (rc < 0) goto undo; - } - gref_ids[i] = gref->gref_id; + gref_ids[i] = gref->gref_id = rc; } /* Add to gref lists. */ @@ -162,8 +160,8 @@ undo: mutex_lock(&gref_mutex); gref_size -= (op->count - i); - list_for_each_entry(gref, &queue_file, next_file) { - /* __del_gref does not remove from queue_file */ + list_for_each_entry_safe(gref, next, &queue_file, next_file) { + list_del(&gref->next_file); __del_gref(gref); } @@ -193,7 +191,7 @@ static void __del_gref(struct gntalloc_gref *gref) gref->notify.flags = 0; - if (gref->gref_id > 0) { + if (gref->gref_id) { if (gnttab_query_foreign_access(gref->gref_id)) return; diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 5f1e1f3cd18..f8bb36f9d9c 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c @@ -103,16 +103,11 @@ static void do_suspend(void) shutting_down = SHUTDOWN_SUSPEND; -#ifdef CONFIG_PREEMPT - /* If the kernel is preemptible, we need to freeze all the processes - to prevent them from being in the middle of a pagetable update - during suspend. */ err = freeze_processes(); if (err) { pr_err("%s: freeze failed %d\n", __func__, err); goto out; } -#endif err = dpm_suspend_start(PMSG_FREEZE); if (err) { @@ -157,10 +152,8 @@ out_resume: dpm_resume_end(si.cancelled ? PMSG_THAW : PMSG_RESTORE); out_thaw: -#ifdef CONFIG_PREEMPT thaw_processes(); out: -#endif shutting_down = SHUTDOWN_INVALID; } #endif /* CONFIG_HIBERNATE_CALLBACKS */ |