diff options
Diffstat (limited to 'drivers')
490 files changed, 4299 insertions, 2409 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index e3219dfd736c..1b41fca3d65a 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -29,7 +29,6 @@ #include <linux/async.h> #include <linux/suspend.h> #include <trace/events/power.h> -#include <linux/cpufreq.h> #include <linux/cpuidle.h> #include <linux/timer.h> @@ -541,7 +540,6 @@ static void dpm_resume_noirq(pm_message_t state) dpm_show_time(starttime, state, "noirq"); resume_device_irqs(); cpuidle_resume(); - cpufreq_resume(); } /** @@ -957,7 +955,6 @@ static int dpm_suspend_noirq(pm_message_t state) ktime_t starttime = ktime_get(); int error = 0; - cpufreq_suspend(); cpuidle_pause(); suspend_device_irqs(); mutex_lock(&dpm_list_mtx); diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c index 98745dd77e8c..81f977510775 100644 --- a/drivers/base/regmap/regmap-mmio.c +++ b/drivers/base/regmap/regmap-mmio.c @@ -40,7 +40,7 @@ static int regmap_mmio_gather_write(void *context, BUG_ON(reg_size != 4); - if (ctx->clk) { + if (!IS_ERR(ctx->clk)) { ret = clk_enable(ctx->clk); if (ret < 0) return ret; @@ -73,7 +73,7 @@ static int regmap_mmio_gather_write(void *context, offset += ctx->val_bytes; } - if (ctx->clk) + if (!IS_ERR(ctx->clk)) clk_disable(ctx->clk); return 0; @@ -96,7 +96,7 @@ static int regmap_mmio_read(void *context, BUG_ON(reg_size != 4); - if (ctx->clk) { + if (!IS_ERR(ctx->clk)) { ret = clk_enable(ctx->clk); if (ret < 0) return ret; @@ -129,7 +129,7 @@ static int regmap_mmio_read(void *context, offset += ctx->val_bytes; } - if (ctx->clk) + if (!IS_ERR(ctx->clk)) clk_disable(ctx->clk); return 0; @@ -139,7 +139,7 @@ static void regmap_mmio_free_context(void *context) { struct regmap_mmio_context *ctx = context; - if (ctx->clk) { + if (!IS_ERR(ctx->clk)) { clk_unprepare(ctx->clk); clk_put(ctx->clk); } @@ -209,6 +209,7 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, ctx->regs = regs; ctx->val_bytes = config->val_bits / 8; + ctx->clk = ERR_PTR(-ENODEV); if (clk_id == NULL) return ctx; diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 9c021d9cace0..c2e002100949 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -1549,7 +1549,7 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, val + (i * val_bytes), val_bytes); if (ret != 0) - return ret; + goto out; } } else { ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count); @@ -1743,7 +1743,7 @@ static int _regmap_read(struct regmap *map, unsigned int reg, /** * regmap_read(): Read a value from a single register * - * @map: Register map to write to + * @map: Register map to read from * @reg: Register to be read from * @val: Pointer to store read value * @@ -1770,7 +1770,7 @@ EXPORT_SYMBOL_GPL(regmap_read); /** * regmap_raw_read(): Read raw data from the device * - * @map: Register map to write to + * @map: Register map to read from * @reg: First register to be read from * @val: Pointer to store read value * @val_len: Size of data to read @@ -1882,7 +1882,7 @@ EXPORT_SYMBOL_GPL(regmap_fields_read); /** * regmap_bulk_read(): Read multiple registers from the device * - * @map: Register map to write to + * @map: Register map to read from * @reg: First register to be read from * @val: Pointer to store read value, in native register size for device * @val_count: Number of registers to read diff --git a/drivers/block/null_blk.c b/drivers/block/null_blk.c index ea192ec029c4..f370fc13aea5 100644 --- a/drivers/block/null_blk.c +++ b/drivers/block/null_blk.c @@ -495,23 +495,23 @@ static int null_add_dev(void) spin_lock_init(&nullb->lock); + if (queue_mode == NULL_Q_MQ && use_per_node_hctx) + submit_queues = nr_online_nodes; + if (setup_queues(nullb)) goto err; if (queue_mode == NULL_Q_MQ) { null_mq_reg.numa_node = home_node; null_mq_reg.queue_depth = hw_queue_depth; + null_mq_reg.nr_hw_queues = submit_queues; if (use_per_node_hctx) { null_mq_reg.ops->alloc_hctx = null_alloc_hctx; null_mq_reg.ops->free_hctx = null_free_hctx; - - null_mq_reg.nr_hw_queues = nr_online_nodes; } else { null_mq_reg.ops->alloc_hctx = blk_mq_alloc_single_hw_queue; null_mq_reg.ops->free_hctx = blk_mq_free_single_hw_queue; - - null_mq_reg.nr_hw_queues = submit_queues; } nullb->q = blk_mq_init_queue(&null_mq_reg, nullb); diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c index 40cc0cf2ded6..e6939e13e338 100644 --- a/drivers/char/i8k.c +++ b/drivers/char/i8k.c @@ -664,6 +664,13 @@ static struct dmi_system_id __initdata i8k_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Vostro"), }, }, + { + .ident = "Dell XPS421", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "XPS L421X"), + }, + }, { } }; diff --git a/drivers/cpufreq/at32ap-cpufreq.c b/drivers/cpufreq/at32ap-cpufreq.c index 856ad80418ae..7c03dd84f66a 100644 --- a/drivers/cpufreq/at32ap-cpufreq.c +++ b/drivers/cpufreq/at32ap-cpufreq.c @@ -58,7 +58,7 @@ static int at32_set_target(struct cpufreq_policy *policy, unsigned int index) return 0; } -static int __init at32_cpufreq_driver_init(struct cpufreq_policy *policy) +static int at32_cpufreq_driver_init(struct cpufreq_policy *policy) { unsigned int frequency, rate, min_freq; int retval, steps, i; diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 81e9d4412db8..02d534da22dd 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -26,7 +26,6 @@ #include <linux/module.h> #include <linux/mutex.h> #include <linux/slab.h> -#include <linux/suspend.h> #include <linux/syscore_ops.h> #include <linux/tick.h> #include <trace/events/power.h> @@ -48,9 +47,6 @@ static LIST_HEAD(cpufreq_policy_list); static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor); #endif -/* Flag to suspend/resume CPUFreq governors */ -static bool cpufreq_suspended; - static inline bool has_target(void) { return cpufreq_driver->target_index || cpufreq_driver->target; @@ -1466,41 +1462,6 @@ static struct subsys_interface cpufreq_interface = { .remove_dev = cpufreq_remove_dev, }; -void cpufreq_suspend(void) -{ - struct cpufreq_policy *policy; - - if (!has_target()) - return; - - pr_debug("%s: Suspending Governors\n", __func__); - - list_for_each_entry(policy, &cpufreq_policy_list, policy_list) - if (__cpufreq_governor(policy, CPUFREQ_GOV_STOP)) - pr_err("%s: Failed to stop governor for policy: %p\n", - __func__, policy); - - cpufreq_suspended = true; -} - -void cpufreq_resume(void) -{ - struct cpufreq_policy *policy; - - if (!has_target()) - return; - - pr_debug("%s: Resuming Governors\n", __func__); - - cpufreq_suspended = false; - - list_for_each_entry(policy, &cpufreq_policy_list, policy_list) - if (__cpufreq_governor(policy, CPUFREQ_GOV_START) - || __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS)) - pr_err("%s: Failed to start governor for policy: %p\n", - __func__, policy); -} - /** * cpufreq_bp_suspend - Prepare the boot CPU for system suspend. * @@ -1803,10 +1764,6 @@ static int __cpufreq_governor(struct cpufreq_policy *policy, struct cpufreq_governor *gov = NULL; #endif - /* Don't start any governor operations if we are entering suspend */ - if (cpufreq_suspended) - return 0; - if (policy->governor->max_transition_latency && policy->cpuinfo.transition_latency > policy->governor->max_transition_latency) { @@ -2119,6 +2076,9 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb, dev = get_cpu_device(cpu); if (dev) { + if (action & CPU_TASKS_FROZEN) + frozen = true; + switch (action & ~CPU_TASKS_FROZEN) { case CPU_ONLINE: __cpufreq_add_dev(dev, NULL, frozen); diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index 16a2aa28f856..ec4ee5c1fe9d 100644 --- a/drivers/dma/amba-pl08x.c +++ b/drivers/dma/amba-pl08x.c @@ -1169,7 +1169,7 @@ static void pl08x_desc_free(struct virt_dma_desc *vd) struct pl08x_txd *txd = to_pl08x_txd(&vd->tx); struct pl08x_dma_chan *plchan = to_pl08x_chan(vd->tx.chan); - dma_descriptor_unmap(txd); + dma_descriptor_unmap(&vd->tx); if (!txd->done) pl08x_release_mux(plchan); diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c index dcb1e05149a7..8869500ab92b 100644 --- a/drivers/dma/mmp_pdma.c +++ b/drivers/dma/mmp_pdma.c @@ -1017,6 +1017,7 @@ static int mmp_pdma_probe(struct platform_device *op) } } + platform_set_drvdata(op, pdev); dev_info(pdev->device.dev, "initialized %d channels\n", dma_channels); return 0; } diff --git a/drivers/dma/s3c24xx-dma.c b/drivers/dma/s3c24xx-dma.c index 4cb127978636..4eddedb6eb7d 100644 --- a/drivers/dma/s3c24xx-dma.c +++ b/drivers/dma/s3c24xx-dma.c @@ -628,42 +628,13 @@ retry: s3cchan->state = S3C24XX_DMA_CHAN_IDLE; } -static void s3c24xx_dma_unmap_buffers(struct s3c24xx_txd *txd) -{ - struct device *dev = txd->vd.tx.chan->device->dev; - struct s3c24xx_sg *dsg; - - if (!(txd->vd.tx.flags & DMA_COMPL_SKIP_SRC_UNMAP)) { - if (txd->vd.tx.flags & DMA_COMPL_SRC_UNMAP_SINGLE) - list_for_each_entry(dsg, &txd->dsg_list, node) - dma_unmap_single(dev, dsg->src_addr, dsg->len, - DMA_TO_DEVICE); - else { - list_for_each_entry(dsg, &txd->dsg_list, node) - dma_unmap_page(dev, dsg->src_addr, dsg->len, - DMA_TO_DEVICE); - } - } - - if (!(txd->vd.tx.flags & DMA_COMPL_SKIP_DEST_UNMAP)) { - if (txd->vd.tx.flags & DMA_COMPL_DEST_UNMAP_SINGLE) - list_for_each_entry(dsg, &txd->dsg_list, node) - dma_unmap_single(dev, dsg->dst_addr, dsg->len, - DMA_FROM_DEVICE); - else - list_for_each_entry(dsg, &txd->dsg_list, node) - dma_unmap_page(dev, dsg->dst_addr, dsg->len, - DMA_FROM_DEVICE); - } -} - static void s3c24xx_dma_desc_free(struct virt_dma_desc *vd) { struct s3c24xx_txd *txd = to_s3c24xx_txd(&vd->tx); struct s3c24xx_dma_chan *s3cchan = to_s3c24xx_dma_chan(vd->tx.chan); if (!s3cchan->slave) - s3c24xx_dma_unmap_buffers(txd); + dma_descriptor_unmap(&vd->tx); s3c24xx_dma_free_txd(txd); } @@ -795,7 +766,7 @@ static enum dma_status s3c24xx_dma_tx_status(struct dma_chan *chan, spin_lock_irqsave(&s3cchan->vc.lock, flags); ret = dma_cookie_status(chan, cookie, txstate); - if (ret == DMA_SUCCESS) { + if (ret == DMA_COMPLETE) { spin_unlock_irqrestore(&s3cchan->vc.lock, flags); return ret; } diff --git a/drivers/dma/sh/rcar-hpbdma.c b/drivers/dma/sh/rcar-hpbdma.c index ebad84591a6e..3083d901a414 100644 --- a/drivers/dma/sh/rcar-hpbdma.c +++ b/drivers/dma/sh/rcar-hpbdma.c @@ -60,6 +60,7 @@ #define HPB_DMAE_DSTPR_DMSTP BIT(0) /* DMA status register (DSTSR) bits */ +#define HPB_DMAE_DSTSR_DQSTS BIT(2) #define HPB_DMAE_DSTSR_DMSTS BIT(0) /* DMA common registers */ @@ -286,6 +287,9 @@ static void hpb_dmae_halt(struct shdma_chan *schan) ch_reg_write(chan, HPB_DMAE_DCMDR_DQEND, HPB_DMAE_DCMDR); ch_reg_write(chan, HPB_DMAE_DSTPR_DMSTP, HPB_DMAE_DSTPR); + + chan->plane_idx = 0; + chan->first_desc = true; } static const struct hpb_dmae_slave_config * @@ -385,7 +389,10 @@ static bool hpb_dmae_channel_busy(struct shdma_chan *schan) struct hpb_dmae_chan *chan = to_chan(schan); u32 dstsr = ch_reg_read(chan, HPB_DMAE_DSTSR); - return (dstsr & HPB_DMAE_DSTSR_DMSTS) == HPB_DMAE_DSTSR_DMSTS; + if (chan->xfer_mode == XFER_DOUBLE) + return dstsr & HPB_DMAE_DSTSR_DQSTS; + else + return dstsr & HPB_DMAE_DSTSR_DMSTS; } static int @@ -510,6 +517,8 @@ static int hpb_dmae_chan_probe(struct hpb_dmae_device *hpbdev, int id) } schan = &new_hpb_chan->shdma_chan; + schan->max_xfer_len = HPB_DMA_TCR_MAX; + shdma_chan_probe(sdev, schan, id); if (pdev->id >= 0) diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index 8472405c5586..d7f1b57bd3be 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -945,7 +945,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, u32 tad_offset; u32 rir_way; u32 mb, kb; - u64 ch_addr, offset, limit, prv = 0; + u64 ch_addr, offset, limit = 0, prv = 0; /* diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c index 3c55ec856e39..a287cece0593 100644 --- a/drivers/extcon/extcon-arizona.c +++ b/drivers/extcon/extcon-arizona.c @@ -1082,7 +1082,7 @@ static void arizona_micd_set_level(struct arizona *arizona, int index, static int arizona_extcon_probe(struct platform_device *pdev) { struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); - struct arizona_pdata *pdata; + struct arizona_pdata *pdata = &arizona->pdata; struct arizona_extcon_info *info; unsigned int val; int jack_irq_fall, jack_irq_rise; @@ -1091,8 +1091,6 @@ static int arizona_extcon_probe(struct platform_device *pdev) if (!arizona->dapm || !arizona->dapm->card) return -EPROBE_DEFER; - pdata = dev_get_platdata(arizona->dev); - info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); if (!info) { dev_err(&pdev->dev, "Failed to allocate memory\n"); diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 15443d3b6be1..76322330cbd7 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c @@ -792,6 +792,8 @@ void extcon_dev_unregister(struct extcon_dev *edev) return; } + device_unregister(&edev->dev); + if (edev->mutually_exclusive && edev->max_supported) { for (index = 0; edev->mutually_exclusive[index]; index++) @@ -812,7 +814,6 @@ void extcon_dev_unregister(struct extcon_dev *edev) if (switch_class) class_compat_remove_link(switch_class, &edev->dev, NULL); #endif - device_unregister(&edev->dev); put_device(&edev->dev); } EXPORT_SYMBOL_GPL(extcon_dev_unregister); diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index 8847adf392b7..84be70157ad6 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -327,7 +327,7 @@ static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset) * NOTE: we assume for now that only irqs in the first gpio_chip * can provide direct-mapped IRQs to AINTC (up to 32 GPIOs). */ - if (offset < d->irq_base) + if (offset < d->gpio_unbanked) return d->gpio_irq + offset; else return -ENODEV; @@ -419,6 +419,8 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) /* pass "bank 0" GPIO IRQs to AINTC */ chips[0].chip.to_irq = gpio_to_irq_unbanked; + chips[0].gpio_irq = bank_irq; + chips[0].gpio_unbanked = pdata->gpio_unbanked; binten = BIT(0); /* AINTC handles mask/unmask; GPIO handles triggering */ diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index fb7cf0e796f6..0a1e4a5f4234 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2674,7 +2674,7 @@ static int add_3d_struct_modes(struct drm_connector *connector, u16 structure, int modes = 0; u8 cea_mode; - if (video_db == NULL || video_index > video_len) + if (video_db == NULL || video_index >= video_len) return 0; /* CEA modes are numbered 1..127 */ @@ -2701,7 +2701,7 @@ static int add_3d_struct_modes(struct drm_connector *connector, u16 structure, if (structure & (1 << 8)) { newmode = drm_mode_duplicate(dev, &edid_cea_modes[cea_mode]); if (newmode) { - newmode->flags = DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF; + newmode->flags |= DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF; drm_mode_probed_add(connector, newmode); modes++; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index b676006a95a0..22b8f5eced80 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -173,28 +173,37 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file) static void exynos_drm_preclose(struct drm_device *dev, struct drm_file *file) { + exynos_drm_subdrv_close(dev, file); +} + +static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file) +{ struct exynos_drm_private *private = dev->dev_private; - struct drm_pending_vblank_event *e, *t; + struct drm_pending_vblank_event *v, *vt; + struct drm_pending_event *e, *et; unsigned long flags; - /* release events of current file */ + if (!file->driver_priv) + return; + + /* Release all events not unhandled by page flip handler. */ spin_lock_irqsave(&dev->event_lock, flags); - list_for_each_entry_safe(e, t, &private->pageflip_event_list, + list_for_each_entry_safe(v, vt, &private->pageflip_event_list, base.link) { - if (e->base.file_priv == file) { - list_del(&e->base.link); - e->base.destroy(&e->base); + if (v->base.file_priv == file) { + list_del(&v->base.link); + drm_vblank_put(dev, v->pipe); + v->base.destroy(&v->base); } } - spin_unlock_irqrestore(&dev->event_lock, flags); - exynos_drm_subdrv_close(dev, file); -} + /* Release all events handled by page flip handler but not freed. */ + list_for_each_entry_safe(e, et, &file->event_list, link) { + list_del(&e->link); + e->destroy(e); + } + spin_unlock_irqrestore(&dev->event_lock, flags); -static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file) -{ - if (!file->driver_priv) - return; kfree(file->driver_priv); file->driver_priv = NULL; diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 23da72b5eae9..a61878bf5dcd 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -31,7 +31,7 @@ #include "exynos_drm_iommu.h" /* - * FIMD is stand for Fully Interactive Mobile Display and + * FIMD stands for Fully Interactive Mobile Display and * as a display controller, it transfers contents drawn on memory * to a LCD Panel through Display Interfaces such as RGB or * CPU Interface. diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 989be12cdd6e..2e367a1c6a64 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -534,8 +534,10 @@ static int i915_drm_freeze(struct drm_device *dev) * Disable CRTCs directly since we want to preserve sw state * for _thaw. */ + mutex_lock(&dev->mode_config.mutex); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) dev_priv->display.crtc_disable(crtc); + mutex_unlock(&dev->mode_config.mutex); intel_modeset_suspend_hw(dev); } diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 12bbd5eac70d..621c7c67a643 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4442,10 +4442,9 @@ i915_gem_init_hw(struct drm_device *dev) if (dev_priv->ellc_size) I915_WRITE(HSW_IDICR, I915_READ(HSW_IDICR) | IDIHASHMSK(0xf)); - if (IS_HSW_GT3(dev)) - I915_WRITE(MI_PREDICATE_RESULT_2, LOWER_SLICE_ENABLED); - else - I915_WRITE(MI_PREDICATE_RESULT_2, LOWER_SLICE_DISABLED); + if (IS_HASWELL(dev)) + I915_WRITE(MI_PREDICATE_RESULT_2, IS_HSW_GT3(dev) ? + LOWER_SLICE_ENABLED : LOWER_SLICE_DISABLED); if (HAS_PCH_NOP(dev)) { u32 temp = I915_READ(GEN7_MSG_CTL); diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c index 7d5752fda5f1..9bb533e0d762 100644 --- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c @@ -125,13 +125,15 @@ static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf) ret = i915_gem_object_get_pages(obj); if (ret) - goto error; + goto err; + + i915_gem_object_pin_pages(obj); ret = -ENOMEM; pages = drm_malloc_ab(obj->base.size >> PAGE_SHIFT, sizeof(*pages)); if (pages == NULL) - goto error; + goto err_unpin; i = 0; for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0) @@ -141,15 +143,16 @@ static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf) drm_free_large(pages); if (!obj->dma_buf_vmapping) - goto error; + goto err_unpin; obj->vmapping_count = 1; - i915_gem_object_pin_pages(obj); out_unlock: mutex_unlock(&dev->struct_mutex); return obj->dma_buf_vmapping; -error: +err_unpin: + i915_gem_object_unpin_pages(obj); +err: mutex_unlock(&dev->struct_mutex); return ERR_PTR(ret); } diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 885d595e0e02..b7e787fb4649 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -33,6 +33,9 @@ #include "intel_drv.h" #include <linux/dma_remapping.h> +#define __EXEC_OBJECT_HAS_PIN (1<<31) +#define __EXEC_OBJECT_HAS_FENCE (1<<30) + struct eb_vmas { struct list_head vmas; int and; @@ -187,7 +190,28 @@ static struct i915_vma *eb_get_vma(struct eb_vmas *eb, unsigned long handle) } } -static void eb_destroy(struct eb_vmas *eb) { +static void +i915_gem_execbuffer_unreserve_vma(struct i915_vma *vma) +{ + struct drm_i915_gem_exec_object2 *entry; + struct drm_i915_gem_object *obj = vma->obj; + + if (!drm_mm_node_allocated(&vma->node)) + return; + + entry = vma->exec_entry; + + if (entry->flags & __EXEC_OBJECT_HAS_FENCE) + i915_gem_object_unpin_fence(obj); + + if (entry->flags & __EXEC_OBJECT_HAS_PIN) + i915_gem_object_unpin(obj); + + entry->flags &= ~(__EXEC_OBJECT_HAS_FENCE | __EXEC_OBJECT_HAS_PIN); +} + +static void eb_destroy(struct eb_vmas *eb) +{ while (!list_empty(&eb->vmas)) { struct i915_vma *vma; @@ -195,6 +219,7 @@ static void eb_destroy(struct eb_vmas *eb) { struct i915_vma, exec_list); list_del_init(&vma->exec_list); + i915_gem_execbuffer_unreserve_vma(vma); drm_gem_object_unreference(&vma->obj->base); } kfree(eb); @@ -478,9 +503,6 @@ i915_gem_execbuffer_relocate(struct eb_vmas *eb, return ret; } -#define __EXEC_OBJECT_HAS_PIN (1<<31) -#define __EXEC_OBJECT_HAS_FENCE (1<<30) - static int need_reloc_mappable(struct i915_vma *vma) { @@ -552,26 +574,6 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma, return 0; } -static void -i915_gem_execbuffer_unreserve_vma(struct i915_vma *vma) -{ - struct drm_i915_gem_exec_object2 *entry; - struct drm_i915_gem_object *obj = vma->obj; - - if (!drm_mm_node_allocated(&vma->node)) - return; - - entry = vma->exec_entry; - - if (entry->flags & __EXEC_OBJECT_HAS_FENCE) - i915_gem_object_unpin_fence(obj); - - if (entry->flags & __EXEC_OBJECT_HAS_PIN) - i915_gem_object_unpin(obj); - - entry->flags &= ~(__EXEC_OBJECT_HAS_FENCE | __EXEC_OBJECT_HAS_PIN); -} - static int i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring, struct list_head *vmas, @@ -670,13 +672,14 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring, goto err; } -err: /* Decrement pin count for bound objects */ - list_for_each_entry(vma, vmas, exec_list) - i915_gem_execbuffer_unreserve_vma(vma); - +err: if (ret != -ENOSPC || retry++) return ret; + /* Decrement pin count for bound objects */ + list_for_each_entry(vma, vmas, exec_list) + i915_gem_execbuffer_unreserve_vma(vma); + ret = i915_gem_evict_vm(vm, true); if (ret) return ret; @@ -708,6 +711,7 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, while (!list_empty(&eb->vmas)) { vma = list_first_entry(&eb->vmas, struct i915_vma, exec_list); list_del_init(&vma->exec_list); + i915_gem_execbuffer_unreserve_vma(vma); drm_gem_object_unreference(&vma->obj->base); } diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 3620a1b0a73c..38cb8d44a013 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -57,7 +57,9 @@ typedef gen8_gtt_pte_t gen8_ppgtt_pde_t; #define HSW_WB_LLC_AGE3 HSW_CACHEABILITY_CONTROL(0x2) #define HSW_WB_LLC_AGE0 HSW_CACHEABILITY_CONTROL(0x3) #define HSW_WB_ELLC_LLC_AGE0 HSW_CACHEABILITY_CONTROL(0xb) +#define HSW_WB_ELLC_LLC_AGE3 HSW_CACHEABILITY_CONTROL(0x8) #define HSW_WT_ELLC_LLC_AGE0 HSW_CACHEABILITY_CONTROL(0x6) +#define HSW_WT_ELLC_LLC_AGE3 HSW_CACHEABILITY_CONTROL(0x7) #define GEN8_PTES_PER_PAGE (PAGE_SIZE / sizeof(gen8_gtt_pte_t)) #define GEN8_PDES_PER_PAGE (PAGE_SIZE / sizeof(gen8_ppgtt_pde_t)) @@ -185,10 +187,10 @@ static gen6_gtt_pte_t iris_pte_encode(dma_addr_t addr, case I915_CACHE_NONE: break; case I915_CACHE_WT: - pte |= HSW_WT_ELLC_LLC_AGE0; + pte |= HSW_WT_ELLC_LLC_AGE3; break; default: - pte |= HSW_WB_ELLC_LLC_AGE0; + pte |= HSW_WB_ELLC_LLC_AGE3; break; } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index f9eafb6ed523..ee2742122a02 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -235,6 +235,7 @@ */ #define MI_LOAD_REGISTER_IMM(x) MI_INSTR(0x22, 2*x-1) #define MI_STORE_REGISTER_MEM(x) MI_INSTR(0x24, 2*x-1) +#define MI_SRM_LRM_GLOBAL_GTT (1<<22) #define MI_FLUSH_DW MI_INSTR(0x26, 1) /* for GEN6 */ #define MI_FLUSH_DW_STORE_INDEX (1<<21) #define MI_INVALIDATE_TLB (1<<18) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 330077bcd0bd..526c8ded16b0 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -173,7 +173,7 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port) ddi_translations = ddi_translations_dp; break; case PORT_D: - if (intel_dpd_is_edp(dev)) + if (intel_dp_is_edp(dev, PORT_D)) ddi_translations = ddi_translations_edp; else ddi_translations = ddi_translations_dp; @@ -1158,9 +1158,10 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder) if (wait) intel_wait_ddi_buf_idle(dev_priv, port); - if (type == INTEL_OUTPUT_EDP) { + if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); ironlake_edp_panel_vdd_on(intel_dp); + intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); ironlake_edp_panel_off(intel_dp); } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 7ec8b488bb1d..080f6fd4e839 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5815,7 +5815,7 @@ static void intel_set_pipe_csc(struct drm_crtc *crtc) uint16_t postoff = 0; if (intel_crtc->config.limited_color_range) - postoff = (16 * (1 << 13) / 255) & 0x1fff; + postoff = (16 * (1 << 12) / 255) & 0x1fff; I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff); I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), postoff); @@ -6402,7 +6402,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv) /* Make sure we're not on PC8 state before disabling PC8, otherwise * we'll hang the machine! */ - dev_priv->uncore.funcs.force_wake_get(dev_priv); + gen6_gt_force_wake_get(dev_priv); if (val & LCPLL_POWER_DOWN_ALLOW) { val &= ~LCPLL_POWER_DOWN_ALLOW; @@ -6436,7 +6436,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv) DRM_ERROR("Switching back to LCPLL failed\n"); } - dev_priv->uncore.funcs.force_wake_put(dev_priv); + gen6_gt_force_wake_put(dev_priv); } void hsw_enable_pc8_work(struct work_struct *__work) @@ -8354,7 +8354,8 @@ static int intel_gen7_queue_flip(struct drm_device *dev, intel_ring_emit(ring, ~(DERRMR_PIPEA_PRI_FLIP_DONE | DERRMR_PIPEB_PRI_FLIP_DONE | DERRMR_PIPEC_PRI_FLIP_DONE)); - intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1)); + intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1) | + MI_SRM_LRM_GLOBAL_GTT); intel_ring_emit(ring, DERRMR); intel_ring_emit(ring, ring->scratch.gtt_offset + 256); } @@ -10049,7 +10050,7 @@ static void intel_setup_outputs(struct drm_device *dev) intel_ddi_init(dev, PORT_D); } else if (HAS_PCH_SPLIT(dev)) { int found; - dpd_is_edp = intel_dpd_is_edp(dev); + dpd_is_edp = intel_dp_is_edp(dev, PORT_D); if (has_edp_a(dev)) intel_dp_init(dev, DP_A, PORT_A); @@ -10086,8 +10087,7 @@ static void intel_setup_outputs(struct drm_device *dev) intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIC, PORT_C); if (I915_READ(VLV_DISPLAY_BASE + DP_C) & DP_DETECTED) - intel_dp_init(dev, VLV_DISPLAY_BASE + DP_C, - PORT_C); + intel_dp_init(dev, VLV_DISPLAY_BASE + DP_C, PORT_C); } intel_dsi_init(dev); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 0b2e842fef01..30c627c7b7ba 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3326,11 +3326,19 @@ intel_trans_dp_port_sel(struct drm_crtc *crtc) } /* check the VBT to see whether the eDP is on DP-D port */ -bool intel_dpd_is_edp(struct drm_device *dev) +bool intel_dp_is_edp(struct drm_device *dev, enum port port) { struct drm_i915_private *dev_priv = dev->dev_private; union child_device_config *p_child; int i; + static const short port_mapping[] = { + [PORT_B] = PORT_IDPB, + [PORT_C] = PORT_IDPC, + [PORT_D] = PORT_IDPD, + }; + + if (port == PORT_A) + return true; if (!dev_priv->vbt.child_dev_num) return false; @@ -3338,7 +3346,7 @@ bool intel_dpd_is_edp(struct drm_device *dev) for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { p_child = dev_priv->vbt.child_dev + i; - if (p_child->common.dvo_port == PORT_IDPD && + if (p_child->common.dvo_port == port_mapping[port] && (p_child->common.device_type & DEVICE_TYPE_eDP_BITS) == (DEVICE_TYPE_eDP & DEVICE_TYPE_eDP_BITS)) return true; @@ -3616,26 +3624,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, intel_dp->DP = I915_READ(intel_dp->output_reg); intel_dp->attached_connector = intel_connector; - type = DRM_MODE_CONNECTOR_DisplayPort; - /* - * FIXME : We need to initialize built-in panels before external panels. - * For X0, DP_C is fixed as eDP. Revisit this as part of VLV eDP cleanup - */ - switch (port) { - case PORT_A: + if (intel_dp_is_edp(dev, port)) type = DRM_MODE_CONNECTOR_eDP; - break; - case PORT_C: - if (IS_VALLEYVIEW(dev)) - type = DRM_MODE_CONNECTOR_eDP; - break; - case PORT_D: - if (HAS_PCH_SPLIT(dev) && intel_dpd_is_edp(dev)) - type = DRM_MODE_CONNECTOR_eDP; - break; - default: /* silence GCC warning */ - break; - } + else + type = DRM_MODE_CONNECTOR_DisplayPort; /* * For eDP we always set the encoder type to INTEL_OUTPUT_EDP, but diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 1e49aa8f5377..a18e88b3e425 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -708,7 +708,7 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder); void intel_dp_check_link_status(struct intel_dp *intel_dp); bool intel_dp_compute_config(struct intel_encoder *encoder, struct intel_crtc_config *pipe_config); -bool intel_dpd_is_edp(struct drm_device *dev); +bool intel_dp_is_edp(struct drm_device *dev, enum port port); void ironlake_edp_backlight_on(struct intel_dp *intel_dp); void ironlake_edp_backlight_off(struct intel_dp *intel_dp); void ironlake_edp_panel_on(struct intel_dp *intel_dp); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index caf2ee4e5441..6e0d5e075b15 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1180,7 +1180,7 @@ static bool g4x_compute_wm0(struct drm_device *dev, adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; clock = adjusted_mode->crtc_clock; - htotal = adjusted_mode->htotal; + htotal = adjusted_mode->crtc_htotal; hdisplay = to_intel_crtc(crtc)->config.pipe_src_w; pixel_size = crtc->fb->bits_per_pixel / 8; @@ -1267,7 +1267,7 @@ static bool g4x_compute_srwm(struct drm_device *dev, crtc = intel_get_crtc_for_plane(dev, plane); adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; clock = adjusted_mode->crtc_clock; - htotal = adjusted_mode->htotal; + htotal = adjusted_mode->crtc_htotal; hdisplay = to_intel_crtc(crtc)->config.pipe_src_w; pixel_size = crtc->fb->bits_per_pixel / 8; @@ -1498,7 +1498,7 @@ static void i965_update_wm(struct drm_crtc *unused_crtc) const struct drm_display_mode *adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; int clock = adjusted_mode->crtc_clock; - int htotal = adjusted_mode->htotal; + int htotal = adjusted_mode->crtc_htotal; int hdisplay = to_intel_crtc(crtc)->config.pipe_src_w; int pixel_size = crtc->fb->bits_per_pixel / 8; unsigned long line_time_us; @@ -1624,7 +1624,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) const struct drm_display_mode *adjusted_mode = &to_intel_crtc(enabled)->config.adjusted_mode; int clock = adjusted_mode->crtc_clock; - int htotal = adjusted_mode->htotal; + int htotal = adjusted_mode->crtc_htotal; int hdisplay = to_intel_crtc(enabled)->config.pipe_src_w; int pixel_size = enabled->fb->bits_per_pixel / 8; unsigned long line_time_us; @@ -1776,7 +1776,7 @@ static bool ironlake_compute_srwm(struct drm_device *dev, int level, int plane, crtc = intel_get_crtc_for_plane(dev, plane); adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; clock = adjusted_mode->crtc_clock; - htotal = adjusted_mode->htotal; + htotal = adjusted_mode->crtc_htotal; hdisplay = to_intel_crtc(crtc)->config.pipe_src_w; pixel_size = crtc->fb->bits_per_pixel / 8; @@ -2469,8 +2469,9 @@ hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc) /* The WM are computed with base on how long it takes to fill a single * row at the given clock rate, multiplied by 8. * */ - linetime = DIV_ROUND_CLOSEST(mode->htotal * 1000 * 8, mode->clock); - ips_linetime = DIV_ROUND_CLOSEST(mode->htotal * 1000 * 8, + linetime = DIV_ROUND_CLOSEST(mode->crtc_htotal * 1000 * 8, + mode->crtc_clock); + ips_linetime = DIV_ROUND_CLOSEST(mode->crtc_htotal * 1000 * 8, intel_ddi_get_cdclk_freq(dev_priv)); return PIPE_WM_LINETIME_IPS_LINETIME(ips_linetime) | diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index edcf801613e6..b3fa1ba191b7 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -59,6 +59,7 @@ nouveau-y += core/subdev/clock/nv40.o nouveau-y += core/subdev/clock/nv50.o nouveau-y += core/subdev/clock/nv84.o nouveau-y += core/subdev/clock/nva3.o +nouveau-y += core/subdev/clock/nvaa.o nouveau-y += core/subdev/clock/nvc0.o nouveau-y += core/subdev/clock/nve0.o nouveau-y += core/subdev/clock/pllnv04.o diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv50.c b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c index db139827047c..db3fc7be856a 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c @@ -283,7 +283,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLOCK ] = nv84_clock_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = nvaa_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; @@ -311,7 +311,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLOCK ] = nv84_clock_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = nvaa_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c index 5f555788121c..e6352bd5b4ff 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c @@ -33,6 +33,7 @@ #include <engine/dmaobj.h> #include <engine/fifo.h> +#include "nv04.h" #include "nv50.h" /******************************************************************************* @@ -460,6 +461,8 @@ nv50_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nv_subdev(priv)->intr = nv04_fifo_intr; nv_engine(priv)->cclass = &nv50_fifo_cclass; nv_engine(priv)->sclass = nv50_fifo_sclass; + priv->base.pause = nv04_fifo_pause; + priv->base.start = nv04_fifo_start; return 0; } diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c index 0908dc834c84..fe0f41e65d9b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c @@ -35,6 +35,7 @@ #include <engine/dmaobj.h> #include <engine/fifo.h> +#include "nv04.h" #include "nv50.h" /******************************************************************************* @@ -432,6 +433,8 @@ nv84_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nv_subdev(priv)->intr = nv04_fifo_intr; nv_engine(priv)->cclass = &nv84_fifo_cclass; nv_engine(priv)->sclass = nv84_fifo_sclass; + priv->base.pause = nv04_fifo_pause; + priv->base.start = nv04_fifo_start; return 0; } diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nv50.c b/drivers/gpu/drm/nouveau/core/engine/software/nv50.c index b574dd4bb828..5ce686ee729e 100644 --- a/drivers/gpu/drm/nouveau/core/engine/software/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/software/nv50.c @@ -176,7 +176,7 @@ nv50_software_context_ctor(struct nouveau_object *parent, if (ret) return ret; - chan->vblank.nr_event = pdisp->vblank->index_nr; + chan->vblank.nr_event = pdisp ? pdisp->vblank->index_nr : 0; chan->vblank.event = kzalloc(chan->vblank.nr_event * sizeof(*chan->vblank.event), GFP_KERNEL); if (!chan->vblank.event) diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/clock.h b/drivers/gpu/drm/nouveau/core/include/subdev/clock.h index e2675bc0edba..8f4ced75444a 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/clock.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/clock.h @@ -14,6 +14,9 @@ enum nv_clk_src { nv_clk_src_hclk, nv_clk_src_hclkm3, nv_clk_src_hclkm3d2, + nv_clk_src_hclkm2d3, /* NVAA */ + nv_clk_src_hclkm4, /* NVAA */ + nv_clk_src_cclk, /* NVAA */ nv_clk_src_host, @@ -127,6 +130,7 @@ extern struct nouveau_oclass nv04_clock_oclass; extern struct nouveau_oclass nv40_clock_oclass; extern struct nouveau_oclass *nv50_clock_oclass; extern struct nouveau_oclass *nv84_clock_oclass; +extern struct nouveau_oclass *nvaa_clock_oclass; extern struct nouveau_oclass nva3_clock_oclass; extern struct nouveau_oclass nvc0_clock_oclass; extern struct nouveau_oclass nve0_clock_oclass; diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c index da50c1b12928..30c1f3a4158e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c @@ -69,6 +69,11 @@ nv04_clock_pll_prog(struct nouveau_clock *clk, u32 reg1, return 0; } +static struct nouveau_clocks +nv04_domain[] = { + { nv_clk_src_max } +}; + static int nv04_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, @@ -77,7 +82,7 @@ nv04_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nv04_clock_priv *priv; int ret; - ret = nouveau_clock_create(parent, engine, oclass, NULL, &priv); + ret = nouveau_clock_create(parent, engine, oclass, nv04_domain, &priv); *pobject = nv_object(priv); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c new file mode 100644 index 000000000000..7a723b4f564d --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c @@ -0,0 +1,445 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <engine/fifo.h> +#include <subdev/bios.h> +#include <subdev/bios/pll.h> +#include <subdev/timer.h> +#include <subdev/clock.h> + +#include "pll.h" + +struct nvaa_clock_priv { + struct nouveau_clock base; + enum nv_clk_src csrc, ssrc, vsrc; + u32 cctrl, sctrl; + u32 ccoef, scoef; + u32 cpost, spost; + u32 vdiv; +}; + +static u32 +read_div(struct nouveau_clock *clk) +{ + return nv_rd32(clk, 0x004600); +} + +static u32 +read_pll(struct nouveau_clock *clk, u32 base) +{ + u32 ctrl = nv_rd32(clk, base + 0); + u32 coef = nv_rd32(clk, base + 4); + u32 ref = clk->read(clk, nv_clk_src_href); + u32 post_div = 0; + u32 clock = 0; + int N1, M1; + + switch (base){ + case 0x4020: + post_div = 1 << ((nv_rd32(clk, 0x4070) & 0x000f0000) >> 16); + break; + case 0x4028: + post_div = (nv_rd32(clk, 0x4040) & 0x000f0000) >> 16; + break; + default: + break; + } + + N1 = (coef & 0x0000ff00) >> 8; + M1 = (coef & 0x000000ff); + if ((ctrl & 0x80000000) && M1) { + clock = ref * N1 / M1; + clock = clock / post_div; + } + + return clock; +} + +static int +nvaa_clock_read(struct nouveau_clock *clk, enum nv_clk_src src) +{ + struct nvaa_clock_priv *priv = (void *)clk; + u32 mast = nv_rd32(clk, 0x00c054); + u32 P = 0; + + switch (src) { + case nv_clk_src_crystal: + return nv_device(priv)->crystal; + case nv_clk_src_href: + return 100000; /* PCIE reference clock */ + case nv_clk_src_hclkm4: + return clk->read(clk, nv_clk_src_href) * 4; + case nv_clk_src_hclkm2d3: + return clk->read(clk, nv_clk_src_href) * 2 / 3; + case nv_clk_src_host: + switch (mast & 0x000c0000) { + case 0x00000000: return clk->read(clk, nv_clk_src_hclkm2d3); + case 0x00040000: break; + case 0x00080000: return clk->read(clk, nv_clk_src_hclkm4); + case 0x000c0000: return clk->read(clk, nv_clk_src_cclk); + } + break; + case nv_clk_src_core: + P = (nv_rd32(clk, 0x004028) & 0x00070000) >> 16; + + switch (mast & 0x00000003) { + case 0x00000000: return clk->read(clk, nv_clk_src_crystal) >> P; + case 0x00000001: return 0; + case 0x00000002: return clk->read(clk, nv_clk_src_hclkm4) >> P; + case 0x00000003: return read_pll(clk, 0x004028) >> P; + } + break; + case nv_clk_src_cclk: + if ((mast & 0x03000000) != 0x03000000) + return clk->read(clk, nv_clk_src_core); + + if ((mast & 0x00000200) == 0x00000000) + return clk->read(clk, nv_clk_src_core); + + switch (mast & 0x00000c00) { + case 0x00000000: return clk->read(clk, nv_clk_src_href); + case 0x00000400: return clk->read(clk, nv_clk_src_hclkm4); + case 0x00000800: return clk->read(clk, nv_clk_src_hclkm2d3); + default: return 0; + } + case nv_clk_src_shader: + P = (nv_rd32(clk, 0x004020) & 0x00070000) >> 16; + switch (mast & 0x00000030) { + case 0x00000000: + if (mast & 0x00000040) + return clk->read(clk, nv_clk_src_href) >> P; + return clk->read(clk, nv_clk_src_crystal) >> P; + case 0x00000010: break; + case 0x00000020: return read_pll(clk, 0x004028) >> P; + case 0x00000030: return read_pll(clk, 0x004020) >> P; + } + break; + case nv_clk_src_mem: + return 0; + break; + case nv_clk_src_vdec: + P = (read_div(clk) & 0x00000700) >> 8; + + switch (mast & 0x00400000) { + case 0x00400000: + return clk->read(clk, nv_clk_src_core) >> P; + break; + default: + return 500000 >> P; + break; + } + break; + default: + break; + } + + nv_debug(priv, "unknown clock source %d 0x%08x\n", src, mast); + return 0; +} + +static u32 +calc_pll(struct nvaa_clock_priv *priv, u32 reg, + u32 clock, int *N, int *M, int *P) +{ + struct nouveau_bios *bios = nouveau_bios(priv); + struct nvbios_pll pll; + struct nouveau_clock *clk = &priv->base; + int ret; + + ret = nvbios_pll_parse(bios, reg, &pll); + if (ret) + return 0; + + pll.vco2.max_freq = 0; + pll.refclk = clk->read(clk, nv_clk_src_href); + if (!pll.refclk) + return 0; + + return nv04_pll_calc(nv_subdev(priv), &pll, clock, N, M, NULL, NULL, P); +} + +static inline u32 +calc_P(u32 src, u32 target, int *div) +{ + u32 clk0 = src, clk1 = src; + for (*div = 0; *div <= 7; (*div)++) { + if (clk0 <= target) { + clk1 = clk0 << (*div ? 1 : 0); + break; + } + clk0 >>= 1; + } + + if (target - clk0 <= clk1 - target) + return clk0; + (*div)--; + return clk1; +} + +static int +nvaa_clock_calc(struct nouveau_clock *clk, struct nouveau_cstate *cstate) +{ + struct nvaa_clock_priv *priv = (void *)clk; + const int shader = cstate->domain[nv_clk_src_shader]; + const int core = cstate->domain[nv_clk_src_core]; + const int vdec = cstate->domain[nv_clk_src_vdec]; + u32 out = 0, clock = 0; + int N, M, P1, P2 = 0; + int divs = 0; + + /* cclk: find suitable source, disable PLL if we can */ + if (core < clk->read(clk, nv_clk_src_hclkm4)) + out = calc_P(clk->read(clk, nv_clk_src_hclkm4), core, &divs); + + /* Calculate clock * 2, so shader clock can use it too */ + clock = calc_pll(priv, 0x4028, (core << 1), &N, &M, &P1); + + if (abs(core - out) <= + abs(core - (clock >> 1))) { + priv->csrc = nv_clk_src_hclkm4; + priv->cctrl = divs << 16; + } else { + /* NVCTRL is actually used _after_ NVPOST, and after what we + * call NVPLL. To make matters worse, NVPOST is an integer + * divider instead of a right-shift number. */ + if(P1 > 2) { + P2 = P1 - 2; + P1 = 2; + } + + priv->csrc = nv_clk_src_core; + priv->ccoef = (N << 8) | M; + + priv->cctrl = (P2 + 1) << 16; + priv->cpost = (1 << P1) << 16; + } + + /* sclk: nvpll + divisor, href or spll */ + out = 0; + if (shader == clk->read(clk, nv_clk_src_href)) { + priv->ssrc = nv_clk_src_href; + } else { + clock = calc_pll(priv, 0x4020, shader, &N, &M, &P1); + if (priv->csrc == nv_clk_src_core) { + out = calc_P((core << 1), shader, &divs); + } + + if (abs(shader - out) <= + abs(shader - clock) && + (divs + P2) <= 7) { + priv->ssrc = nv_clk_src_core; + priv->sctrl = (divs + P2) << 16; + } else { + priv->ssrc = nv_clk_src_shader; + priv->scoef = (N << 8) | M; + priv->sctrl = P1 << 16; + } + } + + /* vclk */ + out = calc_P(core, vdec, &divs); + clock = calc_P(500000, vdec, &P1); + if(abs(vdec - out) <= + abs(vdec - clock)) { + priv->vsrc = nv_clk_src_cclk; + priv->vdiv = divs << 16; + } else { + priv->vsrc = nv_clk_src_vdec; + priv->vdiv = P1 << 16; + } + + /* Print strategy! */ + nv_debug(priv, "nvpll: %08x %08x %08x\n", + priv->ccoef, priv->cpost, priv->cctrl); + nv_debug(priv, " spll: %08x %08x %08x\n", + priv->scoef, priv->spost, priv->sctrl); + nv_debug(priv, " vdiv: %08x\n", priv->vdiv); + if (priv->csrc == nv_clk_src_hclkm4) + nv_debug(priv, "core: hrefm4\n"); + else + nv_debug(priv, "core: nvpll\n"); + + if (priv->ssrc == nv_clk_src_hclkm4) + nv_debug(priv, "shader: hrefm4\n"); + else if (priv->ssrc == nv_clk_src_core) + nv_debug(priv, "shader: nvpll\n"); + else + nv_debug(priv, "shader: spll\n"); + + if (priv->vsrc == nv_clk_src_hclkm4) + nv_debug(priv, "vdec: 500MHz\n"); + else + nv_debug(priv, "vdec: core\n"); + + return 0; +} + +static int +nvaa_clock_prog(struct nouveau_clock *clk) +{ + struct nvaa_clock_priv *priv = (void *)clk; + struct nouveau_fifo *pfifo = nouveau_fifo(clk); + unsigned long flags; + u32 pllmask = 0, mast, ptherm_gate; + int ret = -EBUSY; + + /* halt and idle execution engines */ + ptherm_gate = nv_mask(clk, 0x020060, 0x00070000, 0x00000000); + nv_mask(clk, 0x002504, 0x00000001, 0x00000001); + /* Wait until the interrupt handler is finished */ + if (!nv_wait(clk, 0x000100, 0xffffffff, 0x00000000)) + goto resume; + + if (pfifo) + pfifo->pause(pfifo, &flags); + + if (!nv_wait(clk, 0x002504, 0x00000010, 0x00000010)) + goto resume; + if (!nv_wait(clk, 0x00251c, 0x0000003f, 0x0000003f)) + goto resume; + + /* First switch to safe clocks: href */ + mast = nv_mask(clk, 0xc054, 0x03400e70, 0x03400640); + mast &= ~0x00400e73; + mast |= 0x03000000; + + switch (priv->csrc) { + case nv_clk_src_hclkm4: + nv_mask(clk, 0x4028, 0x00070000, priv->cctrl); + mast |= 0x00000002; + break; + case nv_clk_src_core: + nv_wr32(clk, 0x402c, priv->ccoef); + nv_wr32(clk, 0x4028, 0x80000000 | priv->cctrl); + nv_wr32(clk, 0x4040, priv->cpost); + pllmask |= (0x3 << 8); + mast |= 0x00000003; + break; + default: + nv_warn(priv,"Reclocking failed: unknown core clock\n"); + goto resume; + } + + switch (priv->ssrc) { + case nv_clk_src_href: + nv_mask(clk, 0x4020, 0x00070000, 0x00000000); + /* mast |= 0x00000000; */ + break; + case nv_clk_src_core: + nv_mask(clk, 0x4020, 0x00070000, priv->sctrl); + mast |= 0x00000020; + break; + case nv_clk_src_shader: + nv_wr32(clk, 0x4024, priv->scoef); + nv_wr32(clk, 0x4020, 0x80000000 | priv->sctrl); + nv_wr32(clk, 0x4070, priv->spost); + pllmask |= (0x3 << 12); + mast |= 0x00000030; + break; + default: + nv_warn(priv,"Reclocking failed: unknown sclk clock\n"); + goto resume; + } + + if (!nv_wait(clk, 0x004080, pllmask, pllmask)) { + nv_warn(priv,"Reclocking failed: unstable PLLs\n"); + goto resume; + } + + switch (priv->vsrc) { + case nv_clk_src_cclk: + mast |= 0x00400000; + default: + nv_wr32(clk, 0x4600, priv->vdiv); + } + + nv_wr32(clk, 0xc054, mast); + ret = 0; + +resume: + if (pfifo) + pfifo->start(pfifo, &flags); + + nv_mask(clk, 0x002504, 0x00000001, 0x00000000); + nv_wr32(clk, 0x020060, ptherm_gate); + + /* Disable some PLLs and dividers when unused */ + if (priv->csrc != nv_clk_src_core) { + nv_wr32(clk, 0x4040, 0x00000000); + nv_mask(clk, 0x4028, 0x80000000, 0x00000000); + } + + if (priv->ssrc != nv_clk_src_shader) { + nv_wr32(clk, 0x4070, 0x00000000); + nv_mask(clk, 0x4020, 0x80000000, 0x00000000); + } + + return ret; +} + +static void +nvaa_clock_tidy(struct nouveau_clock *clk) +{ +} + +static struct nouveau_clocks +nvaa_domains[] = { + { nv_clk_src_crystal, 0xff }, + { nv_clk_src_href , 0xff }, + { nv_clk_src_core , 0xff, 0, "core", 1000 }, + { nv_clk_src_shader , 0xff, 0, "shader", 1000 }, + { nv_clk_src_vdec , 0xff, 0, "vdec", 1000 }, + { nv_clk_src_max } +}; + +static int +nvaa_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nvaa_clock_priv *priv; + int ret; + + ret = nouveau_clock_create(parent, engine, oclass, nvaa_domains, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.read = nvaa_clock_read; + priv->base.calc = nvaa_clock_calc; + priv->base.prog = nvaa_clock_prog; + priv->base.tidy = nvaa_clock_tidy; + return 0; +} + +struct nouveau_oclass * +nvaa_clock_oclass = &(struct nouveau_oclass) { + .handle = NV_SUBDEV(CLOCK, 0xaa), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvaa_clock_ctor, + .dtor = _nouveau_clock_dtor, + .init = _nouveau_clock_init, + .fini = _nouveau_clock_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c index 3618ac6b6316..32e7064b819b 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c +++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c @@ -58,8 +58,8 @@ struct nouveau_plane { }; static uint32_t formats[] = { - DRM_FORMAT_NV12, DRM_FORMAT_UYVY, + DRM_FORMAT_NV12, }; /* Sine can be approximated with @@ -99,13 +99,28 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct nouveau_bo *cur = nv_plane->cur; bool flip = nv_plane->flip; - int format = ALIGN(src_w * 4, 0x100); int soff = NV_PCRTC0_SIZE * nv_crtc->index; int soff2 = NV_PCRTC0_SIZE * !nv_crtc->index; - int ret; + int format, ret; + + /* Source parameters given in 16.16 fixed point, ignore fractional. */ + src_x >>= 16; + src_y >>= 16; + src_w >>= 16; + src_h >>= 16; + + format = ALIGN(src_w * 4, 0x100); if (format > 0xffff) - return -EINVAL; + return -ERANGE; + + if (dev->chipset >= 0x30) { + if (crtc_w < (src_w >> 1) || crtc_h < (src_h >> 1)) + return -ERANGE; + } else { + if (crtc_w < (src_w >> 3) || crtc_h < (src_h >> 3)) + return -ERANGE; + } ret = nouveau_bo_pin(nv_fb->nvbo, TTM_PL_FLAG_VRAM); if (ret) @@ -113,12 +128,6 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, nv_plane->cur = nv_fb->nvbo; - /* Source parameters given in 16.16 fixed point, ignore fractional. */ - src_x = src_x >> 16; - src_y = src_y >> 16; - src_w = src_w >> 16; - src_h = src_h >> 16; - nv_mask(dev, NV_PCRTC_ENGINE_CTRL + soff, NV_CRTC_FSEL_OVERLAY, NV_CRTC_FSEL_OVERLAY); nv_mask(dev, NV_PCRTC_ENGINE_CTRL + soff2, NV_CRTC_FSEL_OVERLAY, 0); @@ -245,14 +254,25 @@ nv10_overlay_init(struct drm_device *device) { struct nouveau_device *dev = nouveau_dev(device); struct nouveau_plane *plane = kzalloc(sizeof(struct nouveau_plane), GFP_KERNEL); + int num_formats = ARRAY_SIZE(formats); int ret; if (!plane) return; + switch (dev->chipset) { + case 0x10: + case 0x11: + case 0x15: + case 0x1a: + case 0x20: + num_formats = 1; + break; + } + ret = drm_plane_init(device, &plane->base, 3 /* both crtc's */, &nv10_plane_funcs, - formats, ARRAY_SIZE(formats), false); + formats, num_formats, false); if (ret) goto err; diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 7809d92183c4..29c3efdfc7dd 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -608,6 +608,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, fence = nouveau_fence_ref(new_bo->bo.sync_obj); spin_unlock(&new_bo->bo.bdev->fence_lock); ret = nouveau_fence_sync(fence, chan); + nouveau_fence_unref(&fence); if (ret) return ret; @@ -701,7 +702,7 @@ nouveau_finish_page_flip(struct nouveau_channel *chan, s = list_first_entry(&fctx->flip, struct nouveau_page_flip_state, head); if (s->event) - drm_send_vblank_event(dev, -1, s->event); + drm_send_vblank_event(dev, s->crtc, s->event); list_del(&s->head); if (ps) diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index f8e66c08b11a..4e384a2f99c3 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -1265,7 +1265,7 @@ nv50_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start, uint32_t size) { struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - u32 end = max(start + size, (u32)256); + u32 end = min_t(u32, start + size, 256); u32 i; for (i = start; i < end; i++) { diff --git a/drivers/gpu/drm/radeon/atombios_i2c.c b/drivers/gpu/drm/radeon/atombios_i2c.c index 0652ee0a2098..f685035dbe39 100644 --- a/drivers/gpu/drm/radeon/atombios_i2c.c +++ b/drivers/gpu/drm/radeon/atombios_i2c.c @@ -44,7 +44,7 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan, PROCESS_I2C_CHANNEL_TRANSACTION_PS_ALLOCATION args; int index = GetIndexIntoMasterTable(COMMAND, ProcessI2cChannelTransaction); unsigned char *base; - u16 out; + u16 out = cpu_to_le16(0); memset(&args, 0, sizeof(args)); @@ -55,11 +55,14 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan, DRM_ERROR("hw i2c: tried to write too many bytes (%d vs 3)\n", num); return -EINVAL; } - args.ucRegIndex = buf[0]; - if (num > 1) { + if (buf == NULL) + args.ucRegIndex = 0; + else + args.ucRegIndex = buf[0]; + if (num) num--; + if (num) memcpy(&out, &buf[1], num); - } args.lpI2CDataOut = cpu_to_le16(out); } else { if (num > ATOM_MAX_HW_I2C_READ) { @@ -96,14 +99,14 @@ int radeon_atom_hw_i2c_xfer(struct i2c_adapter *i2c_adap, struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap); struct i2c_msg *p; int i, remaining, current_count, buffer_offset, max_bytes, ret; - u8 buf = 0, flags; + u8 flags; /* check for bus probe */ p = &msgs[0]; if ((num == 1) && (p->len == 0)) { ret = radeon_process_i2c_ch(i2c, p->addr, HW_I2C_WRITE, - &buf, 1); + NULL, 0); if (ret) return ret; else diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c index 009f46e0ce72..de86493cbc44 100644 --- a/drivers/gpu/drm/radeon/dce6_afmt.c +++ b/drivers/gpu/drm/radeon/dce6_afmt.c @@ -93,11 +93,13 @@ void dce6_afmt_select_pin(struct drm_encoder *encoder) struct radeon_device *rdev = encoder->dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; - u32 offset = dig->afmt->offset; + u32 offset; - if (!dig->afmt->pin) + if (!dig || !dig->afmt || !dig->afmt->pin) return; + offset = dig->afmt->offset; + WREG32(AFMT_AUDIO_SRC_CONTROL + offset, AFMT_AUDIO_SRC_SELECT(dig->afmt->pin->id)); } @@ -112,7 +114,7 @@ void dce6_afmt_write_latency_fields(struct drm_encoder *encoder, struct radeon_connector *radeon_connector = NULL; u32 tmp = 0, offset; - if (!dig->afmt->pin) + if (!dig || !dig->afmt || !dig->afmt->pin) return; offset = dig->afmt->pin->offset; @@ -156,7 +158,7 @@ void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder) u8 *sadb; int sad_count; - if (!dig->afmt->pin) + if (!dig || !dig->afmt || !dig->afmt->pin) return; offset = dig->afmt->pin->offset; @@ -217,7 +219,7 @@ void dce6_afmt_write_sad_regs(struct drm_encoder *encoder) { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO }, }; - if (!dig->afmt->pin) + if (!dig || !dig->afmt || !dig->afmt->pin) return; offset = dig->afmt->pin->offset; diff --git a/drivers/gpu/drm/radeon/ni_dpm.c b/drivers/gpu/drm/radeon/ni_dpm.c index cdc003085a76..49c4d48f54d6 100644 --- a/drivers/gpu/drm/radeon/ni_dpm.c +++ b/drivers/gpu/drm/radeon/ni_dpm.c @@ -785,8 +785,8 @@ static void ni_apply_state_adjust_rules(struct radeon_device *rdev, struct ni_ps *ps = ni_get_ps(rps); struct radeon_clock_and_voltage_limits *max_limits; bool disable_mclk_switching; - u32 mclk, sclk; - u16 vddc, vddci; + u32 mclk; + u16 vddci; u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc; int i; @@ -839,24 +839,14 @@ static void ni_apply_state_adjust_rules(struct radeon_device *rdev, /* XXX validate the min clocks required for display */ + /* adjust low state */ if (disable_mclk_switching) { - mclk = ps->performance_levels[ps->performance_level_count - 1].mclk; - sclk = ps->performance_levels[0].sclk; - vddc = ps->performance_levels[0].vddc; - vddci = ps->performance_levels[ps->performance_level_count - 1].vddci; - } else { - sclk = ps->performance_levels[0].sclk; - mclk = ps->performance_levels[0].mclk; - vddc = ps->performance_levels[0].vddc; - vddci = ps->performance_levels[0].vddci; + ps->performance_levels[0].mclk = + ps->performance_levels[ps->performance_level_count - 1].mclk; + ps->performance_levels[0].vddci = + ps->performance_levels[ps->performance_level_count - 1].vddci; } - /* adjusted low state */ - ps->performance_levels[0].sclk = sclk; - ps->performance_levels[0].mclk = mclk; - ps->performance_levels[0].vddc = vddc; - ps->performance_levels[0].vddci = vddci; - btc_skip_blacklist_clocks(rdev, max_limits->sclk, max_limits->mclk, &ps->performance_levels[0].sclk, &ps->performance_levels[0].mclk); @@ -868,11 +858,15 @@ static void ni_apply_state_adjust_rules(struct radeon_device *rdev, ps->performance_levels[i].vddc = ps->performance_levels[i - 1].vddc; } + /* adjust remaining states */ if (disable_mclk_switching) { mclk = ps->performance_levels[0].mclk; + vddci = ps->performance_levels[0].vddci; for (i = 1; i < ps->performance_level_count; i++) { if (mclk < ps->performance_levels[i].mclk) mclk = ps->performance_levels[i].mclk; + if (vddci < ps->performance_levels[i].vddci) + vddci = ps->performance_levels[i].vddci; } for (i = 0; i < ps->performance_level_count; i++) { ps->performance_levels[i].mclk = mclk; diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index 4b89262f3f0e..b7d3ecba43e3 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -304,9 +304,9 @@ void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock) WREG32(DCCG_AUDIO_DTO1_MODULE, dto_modulo); WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */ } - } else if (ASIC_IS_DCE3(rdev)) { + } else { /* according to the reg specs, this should DCE3.2 only, but in - * practice it seems to cover DCE3.0/3.1 as well. + * practice it seems to cover DCE2.0/3.0/3.1 as well. */ if (dig->dig_encoder == 0) { WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 100); @@ -317,10 +317,6 @@ void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock) WREG32(DCCG_AUDIO_DTO1_MODULE, clock * 100); WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */ } - } else { - /* according to the reg specs, this should be DCE2.0 and DCE3.0/3.1 */ - WREG32(AUDIO_DTO, AUDIO_DTO_PHASE(base_rate / 10) | - AUDIO_DTO_MODULE(clock / 10)); } } diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index ecf2a3960c07..b1f990d0eaa1 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -2710,10 +2710,10 @@ void radeon_vm_fence(struct radeon_device *rdev, struct radeon_vm *vm, struct radeon_fence *fence); uint64_t radeon_vm_map_gart(struct radeon_device *rdev, uint64_t addr); -int radeon_vm_bo_update_pte(struct radeon_device *rdev, - struct radeon_vm *vm, - struct radeon_bo *bo, - struct ttm_mem_reg *mem); +int radeon_vm_bo_update(struct radeon_device *rdev, + struct radeon_vm *vm, + struct radeon_bo *bo, + struct ttm_mem_reg *mem); void radeon_vm_bo_invalidate(struct radeon_device *rdev, struct radeon_bo *bo); struct radeon_bo_va *radeon_vm_bo_find(struct radeon_vm *vm, diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index f79ee184ffd5..5c39bf7c3d88 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -2918,7 +2918,7 @@ int radeon_atom_get_memory_pll_dividers(struct radeon_device *rdev, mpll_param->dll_speed = args.ucDllSpeed; mpll_param->bwcntl = args.ucBWCntl; mpll_param->vco_mode = - (args.ucPllCntlFlag & MPLL_CNTL_FLAG_VCO_MODE_MASK) ? 1 : 0; + (args.ucPllCntlFlag & MPLL_CNTL_FLAG_VCO_MODE_MASK); mpll_param->yclk_sel = (args.ucPllCntlFlag & MPLL_CNTL_FLAG_BYPASS_DQ_PLL) ? 1 : 0; mpll_param->qdr = diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index f41594b2eeac..0b366169d64d 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -360,13 +360,13 @@ static int radeon_bo_vm_update_pte(struct radeon_cs_parser *parser, struct radeon_bo *bo; int r; - r = radeon_vm_bo_update_pte(rdev, vm, rdev->ring_tmp_bo.bo, &rdev->ring_tmp_bo.bo->tbo.mem); + r = radeon_vm_bo_update(rdev, vm, rdev->ring_tmp_bo.bo, &rdev->ring_tmp_bo.bo->tbo.mem); if (r) { return r; } list_for_each_entry(lobj, &parser->validated, tv.head) { bo = lobj->bo; - r = radeon_vm_bo_update_pte(parser->rdev, vm, bo, &bo->tbo.mem); + r = radeon_vm_bo_update(parser->rdev, vm, bo, &bo->tbo.mem); if (r) { return r; } diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h index 543dcfae7e6f..00e0d449021c 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.h +++ b/drivers/gpu/drm/radeon/radeon_drv.h @@ -108,9 +108,10 @@ * 1.31- Add support for num Z pipes from GET_PARAM * 1.32- fixes for rv740 setup * 1.33- Add r6xx/r7xx const buffer support + * 1.34- fix evergreen/cayman GS register */ #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 33 +#define DRIVER_MINOR 34 #define DRIVER_PATCHLEVEL 0 long radeon_drm_ioctl(struct file *filp, diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index 3044e504f4ec..96e440061bdb 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -29,6 +29,7 @@ #include <drm/radeon_drm.h> #include "radeon.h" #include "radeon_reg.h" +#include "radeon_trace.h" /* * GART @@ -737,6 +738,7 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev, for (i = 0; i < 2; ++i) { if (choices[i]) { vm->id = choices[i]; + trace_radeon_vm_grab_id(vm->id, ring); return rdev->vm_manager.active[choices[i]]; } } @@ -1116,7 +1118,7 @@ static void radeon_vm_update_ptes(struct radeon_device *rdev, } /** - * radeon_vm_bo_update_pte - map a bo into the vm page table + * radeon_vm_bo_update - map a bo into the vm page table * * @rdev: radeon_device pointer * @vm: requested vm @@ -1128,10 +1130,10 @@ static void radeon_vm_update_ptes(struct radeon_device *rdev, * * Object have to be reserved & global and local mutex must be locked! */ -int radeon_vm_bo_update_pte(struct radeon_device *rdev, - struct radeon_vm *vm, - struct radeon_bo *bo, - struct ttm_mem_reg *mem) +int radeon_vm_bo_update(struct radeon_device *rdev, + struct radeon_vm *vm, + struct radeon_bo *bo, + struct ttm_mem_reg *mem) { struct radeon_ib ib; struct radeon_bo_va *bo_va; @@ -1176,6 +1178,8 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev, bo_va->valid = false; } + trace_radeon_vm_bo_update(bo_va); + nptes = radeon_bo_ngpu_pages(bo); /* assume two extra pdes in case the mapping overlaps the borders */ @@ -1257,7 +1261,7 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev, mutex_lock(&rdev->vm_manager.lock); mutex_lock(&bo_va->vm->mutex); if (bo_va->soffset) { - r = radeon_vm_bo_update_pte(rdev, bo_va->vm, bo_va->bo, NULL); + r = radeon_vm_bo_update(rdev, bo_va->vm, bo_va->bo, NULL); } mutex_unlock(&rdev->vm_manager.lock); list_del(&bo_va->vm_list); diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index d1385ccc672c..984097b907ef 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -537,8 +537,7 @@ static ssize_t radeon_hwmon_show_temp(struct device *dev, struct device_attribute *attr, char *buf) { - struct drm_device *ddev = dev_get_drvdata(dev); - struct radeon_device *rdev = ddev->dev_private; + struct radeon_device *rdev = dev_get_drvdata(dev); int temp; if (rdev->asic->pm.get_temperature) @@ -553,8 +552,7 @@ static ssize_t radeon_hwmon_show_temp_thresh(struct device *dev, struct device_attribute *attr, char *buf) { - struct drm_device *ddev = dev_get_drvdata(dev); - struct radeon_device *rdev = ddev->dev_private; + struct radeon_device *rdev = dev_get_drvdata(dev); int hyst = to_sensor_dev_attr(attr)->index; int temp; @@ -566,23 +564,14 @@ static ssize_t radeon_hwmon_show_temp_thresh(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d\n", temp); } -static ssize_t radeon_hwmon_show_name(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "radeon\n"); -} - static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, radeon_hwmon_show_temp, NULL, 0); static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, radeon_hwmon_show_temp_thresh, NULL, 0); static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, radeon_hwmon_show_temp_thresh, NULL, 1); -static SENSOR_DEVICE_ATTR(name, S_IRUGO, radeon_hwmon_show_name, NULL, 0); static struct attribute *hwmon_attributes[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_temp1_crit.dev_attr.attr, &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, - &sensor_dev_attr_name.dev_attr.attr, NULL }; @@ -590,8 +579,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, struct attribute *attr, int index) { struct device *dev = container_of(kobj, struct device, kobj); - struct drm_device *ddev = dev_get_drvdata(dev); - struct radeon_device *rdev = ddev->dev_private; + struct radeon_device *rdev = dev_get_drvdata(dev); /* Skip limit attributes if DPM is not enabled */ if (rdev->pm.pm_method != PM_METHOD_DPM && @@ -607,11 +595,15 @@ static const struct attribute_group hwmon_attrgroup = { .is_visible = hwmon_attributes_visible, }; +static const struct attribute_group *hwmon_groups[] = { + &hwmon_attrgroup, + NULL +}; + static int radeon_hwmon_init(struct radeon_device *rdev) { int err = 0; - - rdev->pm.int_hwmon_dev = NULL; + struct device *hwmon_dev; switch (rdev->pm.int_thermal_type) { case THERMAL_TYPE_RV6XX: @@ -624,20 +616,13 @@ static int radeon_hwmon_init(struct radeon_device *rdev) case THERMAL_TYPE_KV: if (rdev->asic->pm.get_temperature == NULL) return err; - rdev->pm.int_hwmon_dev = hwmon_device_register(rdev->dev); - if (IS_ERR(rdev->pm.int_hwmon_dev)) { - err = PTR_ERR(rdev->pm.int_hwmon_dev); + hwmon_dev = hwmon_device_register_with_groups(rdev->dev, + "radeon", rdev, + hwmon_groups); + if (IS_ERR(hwmon_dev)) { + err = PTR_ERR(hwmon_dev); dev_err(rdev->dev, "Unable to register hwmon device: %d\n", err); - break; - } - dev_set_drvdata(rdev->pm.int_hwmon_dev, rdev->ddev); - err = sysfs_create_group(&rdev->pm.int_hwmon_dev->kobj, - &hwmon_attrgroup); - if (err) { - dev_err(rdev->dev, - "Unable to create hwmon sysfs file: %d\n", err); - hwmon_device_unregister(rdev->dev); } break; default: @@ -647,14 +632,6 @@ static int radeon_hwmon_init(struct radeon_device *rdev) return err; } -static void radeon_hwmon_fini(struct radeon_device *rdev) -{ - if (rdev->pm.int_hwmon_dev) { - sysfs_remove_group(&rdev->pm.int_hwmon_dev->kobj, &hwmon_attrgroup); - hwmon_device_unregister(rdev->pm.int_hwmon_dev); - } -} - static void radeon_dpm_thermal_work_handler(struct work_struct *work) { struct radeon_device *rdev = @@ -1337,8 +1314,6 @@ static void radeon_pm_fini_old(struct radeon_device *rdev) if (rdev->pm.power_state) kfree(rdev->pm.power_state); - - radeon_hwmon_fini(rdev); } static void radeon_pm_fini_dpm(struct radeon_device *rdev) @@ -1358,8 +1333,6 @@ static void radeon_pm_fini_dpm(struct radeon_device *rdev) if (rdev->pm.power_state) kfree(rdev->pm.power_state); - - radeon_hwmon_fini(rdev); } void radeon_pm_fini(struct radeon_device *rdev) diff --git a/drivers/gpu/drm/radeon/radeon_trace.h b/drivers/gpu/drm/radeon/radeon_trace.h index 9f0e18172b6e..0473257d4078 100644 --- a/drivers/gpu/drm/radeon/radeon_trace.h +++ b/drivers/gpu/drm/radeon/radeon_trace.h @@ -47,6 +47,39 @@ TRACE_EVENT(radeon_cs, __entry->fences) ); +TRACE_EVENT(radeon_vm_grab_id, + TP_PROTO(unsigned vmid, int ring), + TP_ARGS(vmid, ring), + TP_STRUCT__entry( + __field(u32, vmid) + __field(u32, ring) + ), + + TP_fast_assign( + __entry->vmid = vmid; + __entry->ring = ring; + ), + TP_printk("vmid=%u, ring=%u", __entry->vmid, __entry->ring) +); + +TRACE_EVENT(radeon_vm_bo_update, + TP_PROTO(struct radeon_bo_va *bo_va), + TP_ARGS(bo_va), + TP_STRUCT__entry( + __field(u64, soffset) + __field(u64, eoffset) + __field(u32, flags) + ), + + TP_fast_assign( + __entry->soffset = bo_va->soffset; + __entry->eoffset = bo_va->eoffset; + __entry->flags = bo_va->flags; + ), + TP_printk("soffs=%010llx, eoffs=%010llx, flags=%08x", + __entry->soffset, __entry->eoffset, __entry->flags) +); + TRACE_EVENT(radeon_vm_set_page, TP_PROTO(uint64_t pe, uint64_t addr, unsigned count, uint32_t incr, uint32_t flags), diff --git a/drivers/gpu/drm/radeon/reg_srcs/cayman b/drivers/gpu/drm/radeon/reg_srcs/cayman index a072fa8c46b0..d46b58d078aa 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/cayman +++ b/drivers/gpu/drm/radeon/reg_srcs/cayman @@ -21,7 +21,7 @@ cayman 0x9400 0x000089AC VGT_COMPUTE_THREAD_GOURP_SIZE 0x000089B0 VGT_HS_OFFCHIP_PARAM 0x00008A14 PA_CL_ENHANCE -0x00008A60 PA_SC_LINE_STIPPLE_VALUE +0x00008A60 PA_SU_LINE_STIPPLE_VALUE 0x00008B10 PA_SC_LINE_STIPPLE_STATE 0x00008BF0 PA_SC_ENHANCE 0x00008D8C SQ_DYN_GPR_CNTL_PS_FLUSH_REQ @@ -532,7 +532,7 @@ cayman 0x9400 0x00028B84 PA_SU_POLY_OFFSET_FRONT_OFFSET 0x00028B88 PA_SU_POLY_OFFSET_BACK_SCALE 0x00028B8C PA_SU_POLY_OFFSET_BACK_OFFSET -0x00028B74 VGT_GS_INSTANCE_CNT +0x00028B90 VGT_GS_INSTANCE_CNT 0x00028BD4 PA_SC_CENTROID_PRIORITY_0 0x00028BD8 PA_SC_CENTROID_PRIORITY_1 0x00028BDC PA_SC_LINE_CNTL diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen index b912a37689bf..57745c8761c8 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/evergreen +++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen @@ -22,7 +22,7 @@ evergreen 0x9400 0x000089A4 VGT_COMPUTE_START_Z 0x000089AC VGT_COMPUTE_THREAD_GOURP_SIZE 0x00008A14 PA_CL_ENHANCE -0x00008A60 PA_SC_LINE_STIPPLE_VALUE +0x00008A60 PA_SU_LINE_STIPPLE_VALUE 0x00008B10 PA_SC_LINE_STIPPLE_STATE 0x00008BF0 PA_SC_ENHANCE 0x00008D8C SQ_DYN_GPR_CNTL_PS_FLUSH_REQ @@ -545,7 +545,7 @@ evergreen 0x9400 0x00028B84 PA_SU_POLY_OFFSET_FRONT_OFFSET 0x00028B88 PA_SU_POLY_OFFSET_BACK_SCALE 0x00028B8C PA_SU_POLY_OFFSET_BACK_OFFSET -0x00028B74 VGT_GS_INSTANCE_CNT +0x00028B90 VGT_GS_INSTANCE_CNT 0x00028C00 PA_SC_LINE_CNTL 0x00028C08 PA_SU_VTX_CNTL 0x00028C0C PA_CL_GB_VERT_CLIP_ADJ diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 6a64ccaa0695..a36736dab5e0 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -3882,8 +3882,15 @@ static int si_mc_init(struct radeon_device *rdev) rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0); rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0); /* size in MB on si */ - rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL; - rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL; + tmp = RREG32(CONFIG_MEMSIZE); + /* some boards may have garbage in the upper 16 bits */ + if (tmp & 0xffff0000) { + DRM_INFO("Probable bad vram size: 0x%08x\n", tmp); + if (tmp & 0xffff) + tmp &= 0xffff; + } + rdev->mc.mc_vram_size = tmp * 1024ULL * 1024ULL; + rdev->mc.real_vram_size = rdev->mc.mc_vram_size; rdev->mc.visible_vram_size = rdev->mc.aper_size; si_vram_gtt_location(rdev, &rdev->mc); radeon_update_bandwidth_info(rdev); diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 28e178137718..07eba596d458 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -135,11 +135,11 @@ int tegra_drm_submit(struct tegra_drm_context *context, unsigned int num_relocs = args->num_relocs; unsigned int num_waitchks = args->num_waitchks; struct drm_tegra_cmdbuf __user *cmdbufs = - (void * __user)(uintptr_t)args->cmdbufs; + (void __user *)(uintptr_t)args->cmdbufs; struct drm_tegra_reloc __user *relocs = - (void * __user)(uintptr_t)args->relocs; + (void __user *)(uintptr_t)args->relocs; struct drm_tegra_waitchk __user *waitchks = - (void * __user)(uintptr_t)args->waitchks; + (void __user *)(uintptr_t)args->waitchks; struct drm_tegra_syncpt syncpt; struct host1x_job *job; int err; @@ -163,9 +163,10 @@ int tegra_drm_submit(struct tegra_drm_context *context, struct drm_tegra_cmdbuf cmdbuf; struct host1x_bo *bo; - err = copy_from_user(&cmdbuf, cmdbufs, sizeof(cmdbuf)); - if (err) + if (copy_from_user(&cmdbuf, cmdbufs, sizeof(cmdbuf))) { + err = -EFAULT; goto fail; + } bo = host1x_bo_lookup(drm, file, cmdbuf.handle); if (!bo) { @@ -178,10 +179,11 @@ int tegra_drm_submit(struct tegra_drm_context *context, cmdbufs++; } - err = copy_from_user(job->relocarray, relocs, - sizeof(*relocs) * num_relocs); - if (err) + if (copy_from_user(job->relocarray, relocs, + sizeof(*relocs) * num_relocs)) { + err = -EFAULT; goto fail; + } while (num_relocs--) { struct host1x_reloc *reloc = &job->relocarray[num_relocs]; @@ -199,15 +201,17 @@ int tegra_drm_submit(struct tegra_drm_context *context, } } - err = copy_from_user(job->waitchk, waitchks, - sizeof(*waitchks) * num_waitchks); - if (err) + if (copy_from_user(job->waitchk, waitchks, + sizeof(*waitchks) * num_waitchks)) { + err = -EFAULT; goto fail; + } - err = copy_from_user(&syncpt, (void * __user)(uintptr_t)args->syncpts, - sizeof(syncpt)); - if (err) + if (copy_from_user(&syncpt, (void __user *)(uintptr_t)args->syncpts, + sizeof(syncpt))) { + err = -EFAULT; goto fail; + } job->is_addr_reg = context->client->ops->is_addr_reg; job->syncpt_incrs = syncpt.incrs; @@ -573,7 +577,7 @@ static void tegra_debugfs_cleanup(struct drm_minor *minor) } #endif -struct drm_driver tegra_drm_driver = { +static struct drm_driver tegra_drm_driver = { .driver_features = DRIVER_MODESET | DRIVER_GEM, .load = tegra_drm_load, .unload = tegra_drm_unload, diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index fdfe259ed7f8..7da0b923131f 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h @@ -116,7 +116,7 @@ host1x_client_to_dc(struct host1x_client *client) static inline struct tegra_dc *to_tegra_dc(struct drm_crtc *crtc) { - return container_of(crtc, struct tegra_dc, base); + return crtc ? container_of(crtc, struct tegra_dc, base) : NULL; } static inline void tegra_dc_writel(struct tegra_dc *dc, unsigned long value, diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c index 490f7719e317..a3835e7de184 100644 --- a/drivers/gpu/drm/tegra/fb.c +++ b/drivers/gpu/drm/tegra/fb.c @@ -247,7 +247,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper, info->var.yoffset * fb->pitches[0]; drm->mode_config.fb_base = (resource_size_t)bo->paddr; - info->screen_base = bo->vaddr + offset; + info->screen_base = (void __iomem *)bo->vaddr + offset; info->screen_size = size; info->fix.smem_start = (unsigned long)(bo->paddr + offset); info->fix.smem_len = size; diff --git a/drivers/gpu/drm/tegra/rgb.c b/drivers/gpu/drm/tegra/rgb.c index ba47ca4fb880..3b29018913a5 100644 --- a/drivers/gpu/drm/tegra/rgb.c +++ b/drivers/gpu/drm/tegra/rgb.c @@ -14,6 +14,8 @@ struct tegra_rgb { struct tegra_output output; + struct tegra_dc *dc; + struct clk *clk_parent; struct clk *clk; }; @@ -84,18 +86,18 @@ static void tegra_dc_write_regs(struct tegra_dc *dc, static int tegra_output_rgb_enable(struct tegra_output *output) { - struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc); + struct tegra_rgb *rgb = to_rgb(output); - tegra_dc_write_regs(dc, rgb_enable, ARRAY_SIZE(rgb_enable)); + tegra_dc_write_regs(rgb->dc, rgb_enable, ARRAY_SIZE(rgb_enable)); return 0; } static int tegra_output_rgb_disable(struct tegra_output *output) { - struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc); + struct tegra_rgb *rgb = to_rgb(output); - tegra_dc_write_regs(dc, rgb_disable, ARRAY_SIZE(rgb_disable)); + tegra_dc_write_regs(rgb->dc, rgb_disable, ARRAY_SIZE(rgb_disable)); return 0; } @@ -146,6 +148,7 @@ int tegra_dc_rgb_probe(struct tegra_dc *dc) rgb->output.dev = dc->dev; rgb->output.of_node = np; + rgb->dc = dc; err = tegra_output_probe(&rgb->output); if (err < 0) diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c index 24ffbe990736..8d67b943ac05 100644 --- a/drivers/gpu/drm/udl/udl_gem.c +++ b/drivers/gpu/drm/udl/udl_gem.c @@ -125,6 +125,12 @@ static int udl_gem_get_pages(struct udl_gem_object *obj, gfp_t gfpmask) static void udl_gem_put_pages(struct udl_gem_object *obj) { + if (obj->base.import_attach) { + drm_free_large(obj->pages); + obj->pages = NULL; + return; + } + drm_gem_put_pages(&obj->base, obj->pages, false, false); obj->pages = NULL; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c index 7776e6f0aef6..0489c6152482 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c @@ -150,6 +150,8 @@ struct vmw_ttm_tt { bool mapped; }; +const size_t vmw_tt_size = sizeof(struct vmw_ttm_tt); + /** * Helper functions to advance a struct vmw_piter iterator. * diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index db85985c7086..20890ad8408b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -615,6 +615,7 @@ extern int vmw_mmap(struct file *filp, struct vm_area_struct *vma); * TTM buffer object driver - vmwgfx_buffer.c */ +extern const size_t vmw_tt_size; extern struct ttm_placement vmw_vram_placement; extern struct ttm_placement vmw_vram_ne_placement; extern struct ttm_placement vmw_vram_sys_placement; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index ecb3d867b426..03f1c2038631 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -75,6 +75,7 @@ void vmw_display_unit_cleanup(struct vmw_display_unit *du) vmw_surface_unreference(&du->cursor_surface); if (du->cursor_dmabuf) vmw_dmabuf_unreference(&du->cursor_dmabuf); + drm_sysfs_connector_remove(&du->connector); drm_crtc_cleanup(&du->crtc); drm_encoder_cleanup(&du->encoder); drm_connector_cleanup(&du->connector); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 79f7e8e60529..a055a26819c2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -260,6 +260,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set) connector->encoder = NULL; encoder->crtc = NULL; crtc->fb = NULL; + crtc->enabled = false; vmw_ldu_del_active(dev_priv, ldu); @@ -285,6 +286,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set) crtc->x = set->x; crtc->y = set->y; crtc->mode = *mode; + crtc->enabled = true; vmw_ldu_add_active(dev_priv, ldu, vfb); @@ -369,6 +371,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) encoder->possible_crtcs = (1 << unit); encoder->possible_clones = 0; + (void) drm_sysfs_connector_add(connector); + drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs); drm_mode_crtc_set_gamma_size(crtc, 256); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index efe2b74c5eb1..9b5ea2ac7ddf 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -352,6 +352,38 @@ int vmw_user_lookup_handle(struct vmw_private *dev_priv, /** * Buffer management. */ + +/** + * vmw_dmabuf_acc_size - Calculate the pinned memory usage of buffers + * + * @dev_priv: Pointer to a struct vmw_private identifying the device. + * @size: The requested buffer size. + * @user: Whether this is an ordinary dma buffer or a user dma buffer. + */ +static size_t vmw_dmabuf_acc_size(struct vmw_private *dev_priv, size_t size, + bool user) +{ + static size_t struct_size, user_struct_size; + size_t num_pages = PAGE_ALIGN(size) >> PAGE_SHIFT; + size_t page_array_size = ttm_round_pot(num_pages * sizeof(void *)); + + if (unlikely(struct_size == 0)) { + size_t backend_size = ttm_round_pot(vmw_tt_size); + + struct_size = backend_size + + ttm_round_pot(sizeof(struct vmw_dma_buffer)); + user_struct_size = backend_size + + ttm_round_pot(sizeof(struct vmw_user_dma_buffer)); + } + + if (dev_priv->map_mode == vmw_dma_alloc_coherent) + page_array_size += + ttm_round_pot(num_pages * sizeof(dma_addr_t)); + + return ((user) ? user_struct_size : struct_size) + + page_array_size; +} + void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo) { struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo); @@ -359,6 +391,13 @@ void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo) kfree(vmw_bo); } +static void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo) +{ + struct vmw_user_dma_buffer *vmw_user_bo = vmw_user_dma_buffer(bo); + + ttm_prime_object_kfree(vmw_user_bo, prime); +} + int vmw_dmabuf_init(struct vmw_private *dev_priv, struct vmw_dma_buffer *vmw_bo, size_t size, struct ttm_placement *placement, @@ -368,28 +407,23 @@ int vmw_dmabuf_init(struct vmw_private *dev_priv, struct ttm_bo_device *bdev = &dev_priv->bdev; size_t acc_size; int ret; + bool user = (bo_free == &vmw_user_dmabuf_destroy); - BUG_ON(!bo_free); + BUG_ON(!bo_free && (!user && (bo_free != vmw_dmabuf_bo_free))); - acc_size = ttm_bo_acc_size(bdev, size, sizeof(struct vmw_dma_buffer)); + acc_size = vmw_dmabuf_acc_size(dev_priv, size, user); memset(vmw_bo, 0, sizeof(*vmw_bo)); INIT_LIST_HEAD(&vmw_bo->res_list); ret = ttm_bo_init(bdev, &vmw_bo->base, size, - ttm_bo_type_device, placement, + (user) ? ttm_bo_type_device : + ttm_bo_type_kernel, placement, 0, interruptible, NULL, acc_size, NULL, bo_free); return ret; } -static void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo) -{ - struct vmw_user_dma_buffer *vmw_user_bo = vmw_user_dma_buffer(bo); - - ttm_prime_object_kfree(vmw_user_bo, prime); -} - static void vmw_user_dmabuf_release(struct ttm_base_object **p_base) { struct vmw_user_dma_buffer *vmw_user_bo; @@ -781,54 +815,55 @@ err_ref: } +/** + * vmw_dumb_create - Create a dumb kms buffer + * + * @file_priv: Pointer to a struct drm_file identifying the caller. + * @dev: Pointer to the drm device. + * @args: Pointer to a struct drm_mode_create_dumb structure + * + * This is a driver callback for the core drm create_dumb functionality. + * Note that this is very similar to the vmw_dmabuf_alloc ioctl, except + * that the arguments have a different format. + */ int vmw_dumb_create(struct drm_file *file_priv, struct drm_device *dev, struct drm_mode_create_dumb *args) { struct vmw_private *dev_priv = vmw_priv(dev); struct vmw_master *vmaster = vmw_master(file_priv->master); - struct vmw_user_dma_buffer *vmw_user_bo; - struct ttm_buffer_object *tmp; + struct vmw_dma_buffer *dma_buf; int ret; args->pitch = args->width * ((args->bpp + 7) / 8); args->size = args->pitch * args->height; - vmw_user_bo = kzalloc(sizeof(*vmw_user_bo), GFP_KERNEL); - if (vmw_user_bo == NULL) - return -ENOMEM; - ret = ttm_read_lock(&vmaster->lock, true); - if (ret != 0) { - kfree(vmw_user_bo); + if (unlikely(ret != 0)) return ret; - } - ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, args->size, - &vmw_vram_sys_placement, true, - &vmw_user_dmabuf_destroy); - if (ret != 0) - goto out_no_dmabuf; - - tmp = ttm_bo_reference(&vmw_user_bo->dma.base); - ret = ttm_prime_object_init(vmw_fpriv(file_priv)->tfile, - args->size, - &vmw_user_bo->prime, - false, - ttm_buffer_type, - &vmw_user_dmabuf_release, NULL); + ret = vmw_user_dmabuf_alloc(dev_priv, vmw_fpriv(file_priv)->tfile, + args->size, false, &args->handle, + &dma_buf); if (unlikely(ret != 0)) - goto out_no_base_object; - - args->handle = vmw_user_bo->prime.base.hash.key; + goto out_no_dmabuf; -out_no_base_object: - ttm_bo_unref(&tmp); + vmw_dmabuf_unreference(&dma_buf); out_no_dmabuf: ttm_read_unlock(&vmaster->lock); return ret; } +/** + * vmw_dumb_map_offset - Return the address space offset of a dumb buffer + * + * @file_priv: Pointer to a struct drm_file identifying the caller. + * @dev: Pointer to the drm device. + * @handle: Handle identifying the dumb buffer. + * @offset: The address space offset returned. + * + * This is a driver callback for the core drm dumb_map_offset functionality. + */ int vmw_dumb_map_offset(struct drm_file *file_priv, struct drm_device *dev, uint32_t handle, uint64_t *offset) @@ -846,6 +881,15 @@ int vmw_dumb_map_offset(struct drm_file *file_priv, return 0; } +/** + * vmw_dumb_destroy - Destroy a dumb boffer + * + * @file_priv: Pointer to a struct drm_file identifying the caller. + * @dev: Pointer to the drm device. + * @handle: Handle identifying the dumb buffer. + * + * This is a driver callback for the core drm dumb_destroy functionality. + */ int vmw_dumb_destroy(struct drm_file *file_priv, struct drm_device *dev, uint32_t handle) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index 26387c3d5a21..22406c8651ea 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -310,6 +310,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set) crtc->fb = NULL; crtc->x = 0; crtc->y = 0; + crtc->enabled = false; vmw_sou_del_active(dev_priv, sou); @@ -370,6 +371,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set) crtc->fb = NULL; crtc->x = 0; crtc->y = 0; + crtc->enabled = false; return ret; } @@ -382,6 +384,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set) crtc->fb = fb; crtc->x = set->x; crtc->y = set->y; + crtc->enabled = true; return 0; } @@ -464,6 +467,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit) encoder->possible_crtcs = (1 << unit); encoder->possible_clones = 0; + (void) drm_sysfs_connector_add(connector); + drm_crtc_init(dev, crtc, &vmw_screen_object_crtc_funcs); drm_mode_crtc_set_gamma_size(crtc, 256); diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c index 509383f8be03..6a929591aa73 100644 --- a/drivers/gpu/host1x/bus.c +++ b/drivers/gpu/host1x/bus.c @@ -19,6 +19,7 @@ #include <linux/of.h> #include <linux/slab.h> +#include "bus.h" #include "dev.h" static DEFINE_MUTEX(clients_lock); @@ -257,7 +258,7 @@ static int host1x_unregister_client(struct host1x *host1x, return -ENODEV; } -struct bus_type host1x_bus_type = { +static struct bus_type host1x_bus_type = { .name = "host1x", }; @@ -301,7 +302,7 @@ static int host1x_device_add(struct host1x *host1x, device->dev.coherent_dma_mask = host1x->dev->coherent_dma_mask; device->dev.dma_mask = &device->dev.coherent_dma_mask; device->dev.release = host1x_device_release; - dev_set_name(&device->dev, driver->name); + dev_set_name(&device->dev, "%s", driver->name); device->dev.bus = &host1x_bus_type; device->dev.parent = host1x->dev; diff --git a/drivers/gpu/host1x/hw/cdma_hw.c b/drivers/gpu/host1x/hw/cdma_hw.c index 37e2a63241a9..6b09b71940c2 100644 --- a/drivers/gpu/host1x/hw/cdma_hw.c +++ b/drivers/gpu/host1x/hw/cdma_hw.c @@ -54,8 +54,8 @@ static void cdma_timeout_cpu_incr(struct host1x_cdma *cdma, u32 getptr, u32 *p = (u32 *)((u32)pb->mapped + getptr); *(p++) = HOST1X_OPCODE_NOP; *(p++) = HOST1X_OPCODE_NOP; - dev_dbg(host1x->dev, "%s: NOP at 0x%x\n", __func__, - pb->phys + getptr); + dev_dbg(host1x->dev, "%s: NOP at %#llx\n", __func__, + (u64)pb->phys + getptr); getptr = (getptr + 8) & (pb->size_bytes - 1); } wmb(); diff --git a/drivers/gpu/host1x/hw/debug_hw.c b/drivers/gpu/host1x/hw/debug_hw.c index 640c75ca5a8b..f72c873eff81 100644 --- a/drivers/gpu/host1x/hw/debug_hw.c +++ b/drivers/gpu/host1x/hw/debug_hw.c @@ -163,8 +163,8 @@ static void show_channel_gathers(struct output *o, struct host1x_cdma *cdma) continue; } - host1x_debug_output(o, " GATHER at %08x+%04x, %d words\n", - g->base, g->offset, g->words); + host1x_debug_output(o, " GATHER at %#llx+%04x, %d words\n", + (u64)g->base, g->offset, g->words); show_gather(o, g->base + g->offset, g->words, cdma, g->base, mapped); diff --git a/drivers/hid/hid-kye.c b/drivers/hid/hid-kye.c index ecb5ca669e97..e77696367591 100644 --- a/drivers/hid/hid-kye.c +++ b/drivers/hid/hid-kye.c @@ -341,6 +341,7 @@ static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, case USB_DEVICE_ID_GENIUS_GX_IMPERATOR: rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 83, "Genius Gx Imperator Keyboard"); + break; case USB_DEVICE_ID_GENIUS_MANTICORE: rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 104, "Genius Manticore Keyboard"); diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index a184e1921c11..8fab82829f8b 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c @@ -112,13 +112,15 @@ static int sensor_hub_get_physical_device_count( static void sensor_hub_fill_attr_info( struct hid_sensor_hub_attribute_info *info, - s32 index, s32 report_id, s32 units, s32 unit_expo, s32 size) + s32 index, s32 report_id, struct hid_field *field) { info->index = index; info->report_id = report_id; - info->units = units; - info->unit_expo = unit_expo; - info->size = size/8; + info->units = field->unit; + info->unit_expo = field->unit_exponent; + info->size = (field->report_size * field->report_count)/8; + info->logical_minimum = field->logical_minimum; + info->logical_maximum = field->logical_maximum; } static struct hid_sensor_hub_callbacks *sensor_hub_get_callback( @@ -325,9 +327,7 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev, if (field->physical == usage_id && field->logical == attr_usage_id) { sensor_hub_fill_attr_info(info, i, report->id, - field->unit, field->unit_exponent, - field->report_size * - field->report_count); + field); ret = 0; } else { for (j = 0; j < field->maxusage; ++j) { @@ -336,11 +336,7 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev, field->usage[j].collection_index == collection_index) { sensor_hub_fill_attr_info(info, - i, report->id, - field->unit, - field->unit_exponent, - field->report_size * - field->report_count); + i, report->id, field); ret = 0; break; } @@ -573,6 +569,8 @@ static int sensor_hub_probe(struct hid_device *hdev, goto err_free_names; } sd->hid_sensor_hub_client_devs[ + sd->hid_sensor_client_cnt].id = PLATFORM_DEVID_AUTO; + sd->hid_sensor_hub_client_devs[ sd->hid_sensor_client_cnt].name = name; sd->hid_sensor_hub_client_devs[ sd->hid_sensor_client_cnt].platform_data = diff --git a/drivers/hwmon/hih6130.c b/drivers/hwmon/hih6130.c index 2dc37c7c6947..7d68a08baaa8 100644 --- a/drivers/hwmon/hih6130.c +++ b/drivers/hwmon/hih6130.c @@ -43,6 +43,7 @@ * @last_update: time of last update (jiffies) * @temperature: cached temperature measurement value * @humidity: cached humidity measurement value + * @write_length: length for I2C measurement request */ struct hih6130 { struct device *hwmon_dev; @@ -51,6 +52,7 @@ struct hih6130 { unsigned long last_update; int temperature; int humidity; + size_t write_length; }; /** @@ -121,8 +123,15 @@ static int hih6130_update_measurements(struct i2c_client *client) */ if (time_after(jiffies, hih6130->last_update + HZ) || !hih6130->valid) { - /* write to slave address, no data, to request a measurement */ - ret = i2c_master_send(client, tmp, 0); + /* + * Write to slave address to request a measurement. + * According with the datasheet it should be with no data, but + * for systems with I2C bus drivers that do not allow zero + * length packets we write one dummy byte to allow sensor + * measurements on them. + */ + tmp[0] = 0; + ret = i2c_master_send(client, tmp, hih6130->write_length); if (ret < 0) goto out; @@ -252,6 +261,9 @@ static int hih6130_probe(struct i2c_client *client, goto fail_remove_sysfs; } + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_QUICK)) + hih6130->write_length = 1; + return 0; fail_remove_sysfs: diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index 6cf6bff79003..a2f3b4a365e4 100644 --- a/drivers/hwmon/lm78.c +++ b/drivers/hwmon/lm78.c @@ -94,6 +94,8 @@ static inline u8 FAN_TO_REG(long rpm, int div) { if (rpm <= 0) return 255; + if (rpm > 1350000) + return 1; return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254); } diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 4c4c1421bf28..8b8f3aa49726 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -1610,12 +1610,14 @@ static int lm90_probe(struct i2c_client *client, "lm90", client); if (err < 0) { dev_err(dev, "cannot request IRQ %d\n", client->irq); - goto exit_remove_files; + goto exit_unregister; } } return 0; +exit_unregister: + hwmon_device_unregister(data->hwmon_dev); exit_remove_files: lm90_remove_files(client, data); exit_restore: diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c index 1404e6319deb..72a889702f0d 100644 --- a/drivers/hwmon/sis5595.c +++ b/drivers/hwmon/sis5595.c @@ -141,6 +141,8 @@ static inline u8 FAN_TO_REG(long rpm, int div) { if (rpm <= 0) return 255; + if (rpm > 1350000) + return 1; return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254); } diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c index 0e7017841f7d..aee14e2192f8 100644 --- a/drivers/hwmon/vt8231.c +++ b/drivers/hwmon/vt8231.c @@ -145,7 +145,7 @@ static const u8 regtempmin[] = { 0x3a, 0x3e, 0x2c, 0x2e, 0x30, 0x32 }; */ static inline u8 FAN_TO_REG(long rpm, int div) { - if (rpm == 0) + if (rpm <= 0 || rpm > 1310720) return 0; return clamp_val(1310720 / (rpm * div), 1, 255); } diff --git a/drivers/hwmon/w83l786ng.c b/drivers/hwmon/w83l786ng.c index edb06cda5a68..6ed76ceb9270 100644 --- a/drivers/hwmon/w83l786ng.c +++ b/drivers/hwmon/w83l786ng.c @@ -481,9 +481,11 @@ store_pwm(struct device *dev, struct device_attribute *attr, if (err) return err; val = clamp_val(val, 0, 255); + val = DIV_ROUND_CLOSEST(val, 0x11); mutex_lock(&data->update_lock); - data->pwm[nr] = val; + data->pwm[nr] = val * 0x11; + val |= w83l786ng_read_value(client, W83L786NG_REG_PWM[nr]) & 0xf0; w83l786ng_write_value(client, W83L786NG_REG_PWM[nr], val); mutex_unlock(&data->update_lock); return count; @@ -510,7 +512,7 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr, mutex_lock(&data->update_lock); reg = w83l786ng_read_value(client, W83L786NG_REG_FAN_CFG); data->pwm_enable[nr] = val; - reg &= ~(0x02 << W83L786NG_PWM_ENABLE_SHIFT[nr]); + reg &= ~(0x03 << W83L786NG_PWM_ENABLE_SHIFT[nr]); reg |= (val - 1) << W83L786NG_PWM_ENABLE_SHIFT[nr]; w83l786ng_write_value(client, W83L786NG_REG_FAN_CFG, reg); mutex_unlock(&data->update_lock); @@ -776,9 +778,10 @@ static struct w83l786ng_data *w83l786ng_update_device(struct device *dev) ((pwmcfg >> W83L786NG_PWM_MODE_SHIFT[i]) & 1) ? 0 : 1; data->pwm_enable[i] = - ((pwmcfg >> W83L786NG_PWM_ENABLE_SHIFT[i]) & 2) + 1; - data->pwm[i] = w83l786ng_read_value(client, - W83L786NG_REG_PWM[i]); + ((pwmcfg >> W83L786NG_PWM_ENABLE_SHIFT[i]) & 3) + 1; + data->pwm[i] = + (w83l786ng_read_value(client, W83L786NG_REG_PWM[i]) + & 0x0f) * 0x11; } diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 1d7efa3169cd..d0cfbb4cb964 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -312,7 +312,9 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx) dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); - clk_prepare_enable(i2c_imx->clk); + result = clk_prepare_enable(i2c_imx->clk); + if (result) + return result; imx_i2c_write_reg(i2c_imx->ifdr, i2c_imx, IMX_I2C_IFDR); /* Enable I2C controller */ imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR); diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c index 797e3117bef7..2d0847b6be62 100644 --- a/drivers/i2c/i2c-mux.c +++ b/drivers/i2c/i2c-mux.c @@ -139,6 +139,8 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, priv->adap.algo = &priv->algo; priv->adap.algo_data = priv; priv->adap.dev.parent = &parent->dev; + priv->adap.retries = parent->retries; + priv->adap.timeout = parent->timeout; /* Sanity check on class */ if (i2c_mux_parent_classes(parent) & class) diff --git a/drivers/iio/common/hid-sensors/Kconfig b/drivers/iio/common/hid-sensors/Kconfig index 1178121b55b0..39188b72cd3b 100644 --- a/drivers/iio/common/hid-sensors/Kconfig +++ b/drivers/iio/common/hid-sensors/Kconfig @@ -25,13 +25,4 @@ config HID_SENSOR_IIO_TRIGGER If this driver is compiled as a module, it will be named hid-sensor-trigger. -config HID_SENSOR_ENUM_BASE_QUIRKS - bool "ENUM base quirks for HID Sensor IIO drivers" - depends on HID_SENSOR_IIO_COMMON - help - Say yes here to build support for sensor hub FW using - enumeration, which is using 1 as base instead of 0. - Since logical minimum is still set 0 instead of 1, - there is no easy way to differentiate. - endmenu diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c index bbd6426c9726..7dcf83998e6f 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c @@ -33,24 +33,34 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, { struct hid_sensor_common *st = iio_trigger_get_drvdata(trig); int state_val; + int report_val; if (state) { if (sensor_hub_device_open(st->hsdev)) return -EIO; - } else + state_val = + HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM; + report_val = + HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM; + + } else { sensor_hub_device_close(st->hsdev); + state_val = + HID_USAGE_SENSOR_PROP_POWER_STATE_D4_POWER_OFF_ENUM; + report_val = + HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM; + } - state_val = state ? 1 : 0; - if (IS_ENABLED(CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS)) - ++state_val; st->data_ready = state; + state_val += st->power_state.logical_minimum; + report_val += st->report_state.logical_minimum; sensor_hub_set_feature(st->hsdev, st->power_state.report_id, st->power_state.index, (s32)state_val); sensor_hub_set_feature(st->hsdev, st->report_state.report_id, st->report_state.index, - (s32)state_val); + (s32)report_val); return 0; } diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index b0d65df3ede2..a022f27c6690 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -43,6 +43,7 @@ config GP2AP020A00F depends on I2C select IIO_BUFFER select IIO_TRIGGERED_BUFFER + select IRQ_WORK help Say Y here if you have a Sharp GP2AP020A00F proximity/ALS combo-chip hooked to an I2C bus. diff --git a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c index fa7a95c1da0e..2909e9561cf3 100644 --- a/drivers/input/gameport/emu10k1-gp.c +++ b/drivers/input/gameport/emu10k1-gp.c @@ -30,7 +30,6 @@ #include <linux/module.h> #include <linux/ioport.h> -#include <linux/init.h> #include <linux/gameport.h> #include <linux/slab.h> #include <linux/pci.h> diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c index ae912d3aee4e..7c03114158e0 100644 --- a/drivers/input/gameport/fm801-gp.c +++ b/drivers/input/gameport/fm801-gp.c @@ -27,7 +27,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/pci.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/gameport.h> diff --git a/drivers/input/input.c b/drivers/input/input.c index d2965e4b3224..1c4c0db05550 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -1653,35 +1653,36 @@ static void input_dev_toggle(struct input_dev *dev, bool activate) */ void input_reset_device(struct input_dev *dev) { - mutex_lock(&dev->mutex); + unsigned long flags; - if (dev->users) { - input_dev_toggle(dev, true); + mutex_lock(&dev->mutex); + spin_lock_irqsave(&dev->event_lock, flags); - /* - * Keys that have been pressed at suspend time are unlikely - * to be still pressed when we resume. - */ - spin_lock_irq(&dev->event_lock); - input_dev_release_keys(dev); - spin_unlock_irq(&dev->event_lock); - } + input_dev_toggle(dev, true); + input_dev_release_keys(dev); + spin_unlock_irqrestore(&dev->event_lock, flags); mutex_unlock(&dev->mutex); } EXPORT_SYMBOL(input_reset_device); -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int input_dev_suspend(struct device *dev) { struct input_dev *input_dev = to_input_dev(dev); - mutex_lock(&input_dev->mutex); + spin_lock_irq(&input_dev->event_lock); - if (input_dev->users) - input_dev_toggle(input_dev, false); + /* + * Keys that are pressed now are unlikely to be + * still pressed when we resume. + */ + input_dev_release_keys(input_dev); - mutex_unlock(&input_dev->mutex); + /* Turn off LEDs and sounds, if any are active. */ + input_dev_toggle(input_dev, false); + + spin_unlock_irq(&input_dev->event_lock); return 0; } @@ -1690,7 +1691,43 @@ static int input_dev_resume(struct device *dev) { struct input_dev *input_dev = to_input_dev(dev); - input_reset_device(input_dev); + spin_lock_irq(&input_dev->event_lock); + + /* Restore state of LEDs and sounds, if any were active. */ + input_dev_toggle(input_dev, true); + + spin_unlock_irq(&input_dev->event_lock); + + return 0; +} + +static int input_dev_freeze(struct device *dev) +{ + struct input_dev *input_dev = to_input_dev(dev); + + spin_lock_irq(&input_dev->event_lock); + + /* + * Keys that are pressed now are unlikely to be + * still pressed when we resume. + */ + input_dev_release_keys(input_dev); + + spin_unlock_irq(&input_dev->event_lock); + + return 0; +} + +static int input_dev_poweroff(struct device *dev) +{ + struct input_dev *input_dev = to_input_dev(dev); + + spin_lock_irq(&input_dev->event_lock); + + /* Turn off LEDs and sounds, if any are active. */ + input_dev_toggle(input_dev, false); + + spin_unlock_irq(&input_dev->event_lock); return 0; } @@ -1698,7 +1735,8 @@ static int input_dev_resume(struct device *dev) static const struct dev_pm_ops input_dev_pm_ops = { .suspend = input_dev_suspend, .resume = input_dev_resume, - .poweroff = input_dev_suspend, + .freeze = input_dev_freeze, + .poweroff = input_dev_poweroff, .restore = input_dev_resume, }; #endif /* CONFIG_PM */ @@ -1707,7 +1745,7 @@ static struct device_type input_dev_type = { .groups = input_dev_attr_groups, .release = input_dev_release, .uevent = input_dev_uevent, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP .pm = &input_dev_pm_ops, #endif }; diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c index 85bc8dc07cfc..55efdfc7eb62 100644 --- a/drivers/input/joystick/a3d.c +++ b/drivers/input/joystick/a3d.c @@ -29,7 +29,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> -#include <linux/init.h> #include <linux/gameport.h> #include <linux/input.h> #include <linux/jiffies.h> diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c index 0cbfd2dfabf4..b78425765d3e 100644 --- a/drivers/input/joystick/adi.c +++ b/drivers/input/joystick/adi.c @@ -33,7 +33,6 @@ #include <linux/slab.h> #include <linux/input.h> #include <linux/gameport.h> -#include <linux/init.h> #include <linux/jiffies.h> #define DRIVER_DESC "Logitech ADI joystick family driver" diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c index 65367e44d715..ae3ee24a2368 100644 --- a/drivers/input/joystick/cobra.c +++ b/drivers/input/joystick/cobra.c @@ -29,7 +29,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> -#include <linux/init.h> #include <linux/gameport.h> #include <linux/input.h> #include <linux/jiffies.h> diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c index ab1cf2882004..0f519db64748 100644 --- a/drivers/input/joystick/gf2k.c +++ b/drivers/input/joystick/gf2k.c @@ -30,7 +30,6 @@ #include <linux/kernel.h> #include <linux/slab.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/input.h> #include <linux/gameport.h> #include <linux/jiffies.h> diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c index 9e1beff57c33..eac9c5b8d73e 100644 --- a/drivers/input/joystick/grip.c +++ b/drivers/input/joystick/grip.c @@ -28,7 +28,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/gameport.h> #include <linux/input.h> diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c index c0f9c7b7eb4e..573191dd78e8 100644 --- a/drivers/input/joystick/grip_mp.c +++ b/drivers/input/joystick/grip_mp.c @@ -11,7 +11,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/gameport.h> #include <linux/input.h> diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c index 55196f730af6..a9ac2f9cfce0 100644 --- a/drivers/input/joystick/guillemot.c +++ b/drivers/input/joystick/guillemot.c @@ -30,7 +30,6 @@ #include <linux/slab.h> #include <linux/module.h> #include <linux/delay.h> -#include <linux/init.h> #include <linux/gameport.h> #include <linux/input.h> #include <linux/jiffies.h> diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h index b1d7d9b0eb86..96ae4f5bd0eb 100644 --- a/drivers/input/joystick/iforce/iforce.h +++ b/drivers/input/joystick/iforce/iforce.h @@ -29,7 +29,6 @@ #include <linux/slab.h> #include <linux/input.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/spinlock.h> #include <linux/usb.h> #include <linux/serio.h> diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c index 88c22623a2e8..17c2c800743c 100644 --- a/drivers/input/joystick/interact.c +++ b/drivers/input/joystick/interact.c @@ -33,7 +33,6 @@ #include <linux/slab.h> #include <linux/module.h> #include <linux/delay.h> -#include <linux/init.h> #include <linux/gameport.h> #include <linux/input.h> #include <linux/jiffies.h> diff --git a/drivers/input/joystick/joydump.c b/drivers/input/joystick/joydump.c index 7eb878bab968..d1c6e4846a4a 100644 --- a/drivers/input/joystick/joydump.c +++ b/drivers/input/joystick/joydump.c @@ -31,7 +31,6 @@ #include <linux/gameport.h> #include <linux/kernel.h> #include <linux/delay.h> -#include <linux/init.h> #include <linux/slab.h> #define DRIVER_DESC "Gameport data dumper module" diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c index 9fb153eef2fc..c5358ba1f571 100644 --- a/drivers/input/joystick/magellan.c +++ b/drivers/input/joystick/magellan.c @@ -31,7 +31,6 @@ #include <linux/slab.h> #include <linux/input.h> #include <linux/serio.h> -#include <linux/init.h> #define DRIVER_DESC "Magellan and SpaceMouse 6dof controller driver" diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c index 04c69af37148..4a95b224169f 100644 --- a/drivers/input/joystick/sidewinder.c +++ b/drivers/input/joystick/sidewinder.c @@ -30,7 +30,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> -#include <linux/init.h> #include <linux/input.h> #include <linux/gameport.h> #include <linux/jiffies.h> diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c index 80a7b27a457a..f4445a4e8d6a 100644 --- a/drivers/input/joystick/spaceball.c +++ b/drivers/input/joystick/spaceball.c @@ -33,7 +33,6 @@ #include <linux/kernel.h> #include <linux/slab.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/input.h> #include <linux/serio.h> diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c index a41f291652e6..f2667820e8c5 100644 --- a/drivers/input/joystick/spaceorb.c +++ b/drivers/input/joystick/spaceorb.c @@ -32,7 +32,6 @@ #include <linux/kernel.h> #include <linux/slab.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/input.h> #include <linux/serio.h> diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c index 0f51a60e14a7..099c6d7b5e08 100644 --- a/drivers/input/joystick/stinger.c +++ b/drivers/input/joystick/stinger.c @@ -32,7 +32,6 @@ #include <linux/slab.h> #include <linux/input.h> #include <linux/serio.h> -#include <linux/init.h> #define DRIVER_DESC "Gravis Stinger gamepad driver" diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c index 5ef9bcdb0345..7e17cde464f0 100644 --- a/drivers/input/joystick/tmdc.c +++ b/drivers/input/joystick/tmdc.c @@ -33,7 +33,6 @@ #include <linux/kernel.h> #include <linux/slab.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/gameport.h> #include <linux/input.h> #include <linux/jiffies.h> diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c index 2556a8193579..7f7e5ab3f9e3 100644 --- a/drivers/input/joystick/twidjoy.c +++ b/drivers/input/joystick/twidjoy.c @@ -52,7 +52,6 @@ #include <linux/slab.h> #include <linux/input.h> #include <linux/serio.h> -#include <linux/init.h> #define DRIVER_DESC "Handykey Twiddler keyboard as a joystick driver" diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c index 23b3071abb6e..e13a9144a25d 100644 --- a/drivers/input/joystick/warrior.c +++ b/drivers/input/joystick/warrior.c @@ -31,7 +31,6 @@ #include <linux/slab.h> #include <linux/input.h> #include <linux/serio.h> -#include <linux/init.h> #define DRIVER_DESC "Logitech WingMan Warrior joystick driver" diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 995e79fa7dad..603fe0dd3682 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -74,7 +74,6 @@ */ #include <linux/kernel.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/stat.h> #include <linux/module.h> diff --git a/drivers/input/joystick/zhenhua.c b/drivers/input/joystick/zhenhua.c index c4de4388fd7f..30af2e8c670c 100644 --- a/drivers/input/joystick/zhenhua.c +++ b/drivers/input/joystick/zhenhua.c @@ -49,7 +49,6 @@ #include <linux/slab.h> #include <linux/input.h> #include <linux/serio.h> -#include <linux/init.h> #define DRIVER_DESC "RC transmitter with 5-byte Zhen Hua protocol joystick driver" diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index bb174c1a9886..a673c9f3a0b9 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -525,7 +525,7 @@ config KEYBOARD_SUNKBD config KEYBOARD_SH_KEYSC tristate "SuperH KEYSC keypad support" - depends on SUPERH || ARM || COMPILE_TEST + depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST help Say Y here if you want to use a keypad attached to the KEYSC block on SuperH processors such as sh7722 and sh7343. diff --git a/drivers/input/keyboard/adp5520-keys.c b/drivers/input/keyboard/adp5520-keys.c index ef26b17fb159..4cc14c2fa7d5 100644 --- a/drivers/input/keyboard/adp5520-keys.c +++ b/drivers/input/keyboard/adp5520-keys.c @@ -8,7 +8,6 @@ #include <linux/module.h> #include <linux/kernel.h> -#include <linux/init.h> #include <linux/platform_device.h> #include <linux/input.h> #include <linux/mfd/adp5520.h> @@ -71,7 +70,7 @@ static int adp5520_keys_notifier(struct notifier_block *nb, static int adp5520_keys_probe(struct platform_device *pdev) { - struct adp5520_keys_platform_data *pdata = pdev->dev.platform_data; + struct adp5520_keys_platform_data *pdata = dev_get_platdata(&pdev->dev); struct input_dev *input; struct adp5520_keys *dev; int ret, i; diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c index 3ed23513d881..bb3b57bea8ba 100644 --- a/drivers/input/keyboard/adp5588-keys.c +++ b/drivers/input/keyboard/adp5588-keys.c @@ -9,7 +9,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/workqueue.h> @@ -173,7 +172,7 @@ static int adp5588_build_gpiomap(struct adp5588_kpad *kpad, static int adp5588_gpio_add(struct adp5588_kpad *kpad) { struct device *dev = &kpad->client->dev; - const struct adp5588_kpad_platform_data *pdata = dev->platform_data; + const struct adp5588_kpad_platform_data *pdata = dev_get_platdata(dev); const struct adp5588_gpio_platform_data *gpio_data = pdata->gpio_data; int i, error; @@ -227,7 +226,7 @@ static int adp5588_gpio_add(struct adp5588_kpad *kpad) static void adp5588_gpio_remove(struct adp5588_kpad *kpad) { struct device *dev = &kpad->client->dev; - const struct adp5588_kpad_platform_data *pdata = dev->platform_data; + const struct adp5588_kpad_platform_data *pdata = dev_get_platdata(dev); const struct adp5588_gpio_platform_data *gpio_data = pdata->gpio_data; int error; @@ -321,7 +320,8 @@ static irqreturn_t adp5588_irq(int irq, void *handle) static int adp5588_setup(struct i2c_client *client) { - const struct adp5588_kpad_platform_data *pdata = client->dev.platform_data; + const struct adp5588_kpad_platform_data *pdata = + dev_get_platdata(&client->dev); const struct adp5588_gpio_platform_data *gpio_data = pdata->gpio_data; int i, ret; unsigned char evt_mode1 = 0, evt_mode2 = 0, evt_mode3 = 0; @@ -424,7 +424,8 @@ static int adp5588_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct adp5588_kpad *kpad; - const struct adp5588_kpad_platform_data *pdata = client->dev.platform_data; + const struct adp5588_kpad_platform_data *pdata = + dev_get_platdata(&client->dev); struct input_dev *input; unsigned int revid; int ret, i; diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c index 60dafd4fa692..6329549bf6ad 100644 --- a/drivers/input/keyboard/adp5589-keys.c +++ b/drivers/input/keyboard/adp5589-keys.c @@ -8,7 +8,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/workqueue.h> @@ -499,7 +498,7 @@ static int adp5589_build_gpiomap(struct adp5589_kpad *kpad, static int adp5589_gpio_add(struct adp5589_kpad *kpad) { struct device *dev = &kpad->client->dev; - const struct adp5589_kpad_platform_data *pdata = dev->platform_data; + const struct adp5589_kpad_platform_data *pdata = dev_get_platdata(dev); const struct adp5589_gpio_platform_data *gpio_data = pdata->gpio_data; int i, error; @@ -553,7 +552,7 @@ static int adp5589_gpio_add(struct adp5589_kpad *kpad) static void adp5589_gpio_remove(struct adp5589_kpad *kpad) { struct device *dev = &kpad->client->dev; - const struct adp5589_kpad_platform_data *pdata = dev->platform_data; + const struct adp5589_kpad_platform_data *pdata = dev_get_platdata(dev); const struct adp5589_gpio_platform_data *gpio_data = pdata->gpio_data; int error; @@ -658,7 +657,7 @@ static int adp5589_setup(struct adp5589_kpad *kpad) { struct i2c_client *client = kpad->client; const struct adp5589_kpad_platform_data *pdata = - client->dev.platform_data; + dev_get_platdata(&client->dev); u8 (*reg) (u8) = kpad->var->reg; unsigned char evt_mode1 = 0, evt_mode2 = 0, evt_mode3 = 0; unsigned char pull_mask = 0; @@ -864,7 +863,7 @@ static int adp5589_probe(struct i2c_client *client, { struct adp5589_kpad *kpad; const struct adp5589_kpad_platform_data *pdata = - client->dev.platform_data; + dev_get_platdata(&client->dev); struct input_dev *input; unsigned int revid; int ret, i; diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index 09b91d093087..e6d46c5994d7 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c @@ -30,7 +30,6 @@ #include <linux/module.h> -#include <linux/init.h> #include <linux/fs.h> #include <linux/interrupt.h> #include <linux/irq.h> @@ -180,7 +179,7 @@ static irqreturn_t bfin_kpad_isr(int irq, void *dev_id) static int bfin_kpad_probe(struct platform_device *pdev) { struct bf54x_kpad *bf54x_kpad; - struct bfin_kpad_platform_data *pdata = pdev->dev.platform_data; + struct bfin_kpad_platform_data *pdata = dev_get_platdata(&pdev->dev); struct input_dev *input; int i, error; @@ -333,7 +332,7 @@ out: static int bfin_kpad_remove(struct platform_device *pdev) { - struct bfin_kpad_platform_data *pdata = pdev->dev.platform_data; + struct bfin_kpad_platform_data *pdata = dev_get_platdata(&pdev->dev); struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); del_timer_sync(&bf54x_kpad->timer); diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c index 7e8b0a52af25..408379669d3c 100644 --- a/drivers/input/keyboard/cros_ec_keyb.c +++ b/drivers/input/keyboard/cros_ec_keyb.c @@ -38,6 +38,7 @@ * @row_shift: log2 or number of rows, rounded up * @keymap_data: Matrix keymap data used to convert to keyscan values * @ghost_filter: true to enable the matrix key-ghosting filter + * @old_kb_state: bitmap of keys pressed last scan * @dev: Device pointer * @idev: Input device * @ec: Top level ChromeOS device to use to talk to EC @@ -49,6 +50,7 @@ struct cros_ec_keyb { int row_shift; const struct matrix_keymap_data *keymap_data; bool ghost_filter; + uint8_t *old_kb_state; struct device *dev; struct input_dev *idev; @@ -135,6 +137,7 @@ static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev, struct input_dev *idev = ckdev->idev; int col, row; int new_state; + int old_state; int num_cols; num_cols = len; @@ -153,18 +156,19 @@ static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev, for (row = 0; row < ckdev->rows; row++) { int pos = MATRIX_SCAN_CODE(row, col, ckdev->row_shift); const unsigned short *keycodes = idev->keycode; - int code; - code = keycodes[pos]; new_state = kb_state[col] & (1 << row); - if (!!new_state != test_bit(code, idev->key)) { + old_state = ckdev->old_kb_state[col] & (1 << row); + if (new_state != old_state) { dev_dbg(ckdev->dev, "changed: [r%d c%d]: byte %02x\n", row, col, new_state); - input_report_key(idev, code, new_state); + input_report_key(idev, keycodes[pos], + new_state); } } + ckdev->old_kb_state[col] = kb_state[col]; } input_sync(ckdev->idev); } @@ -226,6 +230,9 @@ static int cros_ec_keyb_probe(struct platform_device *pdev) &ckdev->cols); if (err) return err; + ckdev->old_kb_state = devm_kzalloc(&pdev->dev, ckdev->cols, GFP_KERNEL); + if (!ckdev->old_kb_state) + return -ENOMEM; idev = devm_input_allocate_device(&pdev->dev); if (!idev) diff --git a/drivers/input/keyboard/davinci_keyscan.c b/drivers/input/keyboard/davinci_keyscan.c index d15977a8361e..1559dc1cf951 100644 --- a/drivers/input/keyboard/davinci_keyscan.c +++ b/drivers/input/keyboard/davinci_keyscan.c @@ -172,7 +172,7 @@ static int __init davinci_ks_probe(struct platform_device *pdev) struct input_dev *key_dev; struct resource *res, *mem; struct device *dev = &pdev->dev; - struct davinci_ks_platform_data *pdata = pdev->dev.platform_data; + struct davinci_ks_platform_data *pdata = dev_get_platdata(&pdev->dev); int error, i; if (pdata->device_enable) { diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c index 47206bdba411..e59876212b8c 100644 --- a/drivers/input/keyboard/ep93xx_keypad.c +++ b/drivers/input/keyboard/ep93xx_keypad.c @@ -244,7 +244,7 @@ static int ep93xx_keypad_probe(struct platform_device *pdev) if (!keypad) return -ENOMEM; - keypad->pdata = pdev->dev.platform_data; + keypad->pdata = dev_get_platdata(&pdev->dev); if (!keypad->pdata) { err = -EINVAL; goto failed_free; diff --git a/drivers/input/keyboard/goldfish_events.c b/drivers/input/keyboard/goldfish_events.c index 9f60a2ec88db..69e854763370 100644 --- a/drivers/input/keyboard/goldfish_events.c +++ b/drivers/input/keyboard/goldfish_events.c @@ -14,7 +14,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/types.h> #include <linux/input.h> diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c index 4e428199e580..e571e194ff84 100644 --- a/drivers/input/keyboard/gpio_keys_polled.c +++ b/drivers/input/keyboard/gpio_keys_polled.c @@ -17,7 +17,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/input.h> #include <linux/input-polldev.h> diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c index 589e3c258f3f..610a8af795a1 100644 --- a/drivers/input/keyboard/hil_kbd.c +++ b/drivers/input/keyboard/hil_kbd.c @@ -36,7 +36,6 @@ #include <linux/serio.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/completion.h> #include <linux/slab.h> #include <linux/pci_ids.h> diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c index 328cfc1eed95..cbf4f8038cba 100644 --- a/drivers/input/keyboard/imx_keypad.c +++ b/drivers/input/keyboard/imx_keypad.c @@ -13,7 +13,6 @@ #include <linux/delay.h> #include <linux/device.h> #include <linux/err.h> -#include <linux/init.h> #include <linux/input/matrix_keypad.h> #include <linux/interrupt.h> #include <linux/io.h> @@ -425,7 +424,8 @@ MODULE_DEVICE_TABLE(of, imx_keypad_of_match); static int imx_keypad_probe(struct platform_device *pdev) { - const struct matrix_keymap_data *keymap_data = pdev->dev.platform_data; + const struct matrix_keymap_data *keymap_data = + dev_get_platdata(&pdev->dev); struct imx_keypad *keypad; struct input_dev *input_dev; struct resource *res; diff --git a/drivers/input/keyboard/jornada680_kbd.c b/drivers/input/keyboard/jornada680_kbd.c index a2a034c25f0b..69b1f002ff52 100644 --- a/drivers/input/keyboard/jornada680_kbd.c +++ b/drivers/input/keyboard/jornada680_kbd.c @@ -16,7 +16,6 @@ * published by the Free Software Foundation. */ -#include <linux/init.h> #include <linux/input.h> #include <linux/input-polldev.h> #include <linux/interrupt.h> diff --git a/drivers/input/keyboard/jornada720_kbd.c b/drivers/input/keyboard/jornada720_kbd.c index b0ad457ca9d8..cd729d485e98 100644 --- a/drivers/input/keyboard/jornada720_kbd.c +++ b/drivers/input/keyboard/jornada720_kbd.c @@ -18,7 +18,6 @@ #include <linux/device.h> #include <linux/errno.h> #include <linux/interrupt.h> -#include <linux/init.h> #include <linux/input.h> #include <linux/kernel.h> #include <linux/module.h> diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c index fc0a63c2f278..9fcd9f1d5dc8 100644 --- a/drivers/input/keyboard/lkkbd.c +++ b/drivers/input/keyboard/lkkbd.c @@ -65,7 +65,6 @@ #include <linux/slab.h> #include <linux/module.h> #include <linux/interrupt.h> -#include <linux/init.h> #include <linux/input.h> #include <linux/serio.h> #include <linux/workqueue.h> diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c index 0de23f41b2d3..0b42118cbf8f 100644 --- a/drivers/input/keyboard/lm8323.c +++ b/drivers/input/keyboard/lm8323.c @@ -627,7 +627,7 @@ static DEVICE_ATTR(disable_kp, 0644, lm8323_show_disable, lm8323_set_disable); static int lm8323_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct lm8323_platform_data *pdata = client->dev.platform_data; + struct lm8323_platform_data *pdata = dev_get_platdata(&client->dev); struct input_dev *idev; struct lm8323_chip *lm; int pwm; diff --git a/drivers/input/keyboard/lm8333.c b/drivers/input/keyboard/lm8333.c index 5a8ca35dc9af..9081cbef11ea 100644 --- a/drivers/input/keyboard/lm8333.c +++ b/drivers/input/keyboard/lm8333.c @@ -131,7 +131,8 @@ static irqreturn_t lm8333_irq_thread(int irq, void *data) static int lm8333_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct lm8333_platform_data *pdata = client->dev.platform_data; + const struct lm8333_platform_data *pdata = + dev_get_platdata(&client->dev); struct lm8333 *lm8333; struct input_dev *input; int err, active_time; diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index 90ff73ace424..8d2e19e81e1e 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c @@ -14,7 +14,6 @@ #include <linux/types.h> #include <linux/delay.h> #include <linux/platform_device.h> -#include <linux/init.h> #include <linux/input.h> #include <linux/irq.h> #include <linux/interrupt.h> diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c index bc2cdaf563fd..430b54539720 100644 --- a/drivers/input/keyboard/max7359_keypad.c +++ b/drivers/input/keyboard/max7359_keypad.c @@ -182,7 +182,8 @@ static void max7359_initialize(struct i2c_client *client) static int max7359_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct matrix_keymap_data *keymap_data = client->dev.platform_data; + const struct matrix_keymap_data *keymap_data = + dev_get_platdata(&client->dev); struct max7359_keypad *keypad; struct input_dev *input_dev; int ret; diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c index 7c236f9c6a51..1da8e0b44b56 100644 --- a/drivers/input/keyboard/mcs_touchkey.c +++ b/drivers/input/keyboard/mcs_touchkey.c @@ -12,7 +12,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/i2c.h> #include <linux/i2c/mcs.h> #include <linux/interrupt.h> @@ -108,7 +107,7 @@ static int mcs_touchkey_probe(struct i2c_client *client, int error; int i; - pdata = client->dev.platform_data; + pdata = dev_get_platdata(&client->dev); if (!pdata) { dev_err(&client->dev, "no platform data defined\n"); return -EINVAL; diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c index f7f3e9a9fd3f..009c82256e89 100644 --- a/drivers/input/keyboard/mpr121_touchkey.c +++ b/drivers/input/keyboard/mpr121_touchkey.c @@ -13,7 +13,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/input.h> #include <linux/i2c.h> #include <linux/slab.h> @@ -188,7 +187,8 @@ err_i2c_write: static int mpr_touchkey_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct mpr121_platform_data *pdata = client->dev.platform_data; + const struct mpr121_platform_data *pdata = + dev_get_platdata(&client->dev); struct mpr121_touchkey *mpr121; struct input_dev *input_dev; int error; diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c index f971898ad591..20f044377990 100644 --- a/drivers/input/keyboard/newtonkbd.c +++ b/drivers/input/keyboard/newtonkbd.c @@ -29,7 +29,6 @@ #include <linux/slab.h> #include <linux/module.h> #include <linux/input.h> -#include <linux/init.h> #include <linux/serio.h> #define DRIVER_DESC "Newton keyboard driver" diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c index c7d505cce72f..63332e2f8628 100644 --- a/drivers/input/keyboard/nomadik-ske-keypad.c +++ b/drivers/input/keyboard/nomadik-ske-keypad.c @@ -222,7 +222,8 @@ static irqreturn_t ske_keypad_irq(int irq, void *dev_id) static int __init ske_keypad_probe(struct platform_device *pdev) { - const struct ske_keypad_platform_data *plat = pdev->dev.platform_data; + const struct ske_keypad_platform_data *plat = + dev_get_platdata(&pdev->dev); struct ske_keypad *keypad; struct input_dev *input; struct resource *res; diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index d0d5226d9cd4..b1acc9852eb7 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c @@ -25,7 +25,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/types.h> #include <linux/input.h> @@ -248,7 +247,7 @@ static int omap_kp_probe(struct platform_device *pdev) { struct omap_kp *omap_kp; struct input_dev *input_dev; - struct omap_kp_platform_data *pdata = pdev->dev.platform_data; + struct omap_kp_platform_data *pdata = dev_get_platdata(&pdev->dev); int i, col_idx, row_idx, ret; unsigned int row_shift, keycodemax; diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c index 30acfd49fa6c..0400b3f2b4b9 100644 --- a/drivers/input/keyboard/omap4-keypad.c +++ b/drivers/input/keyboard/omap4-keypad.c @@ -22,7 +22,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/errno.h> diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index 186138c720c7..d8241ba0afa0 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c @@ -18,7 +18,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/input.h> #include <linux/device.h> diff --git a/drivers/input/keyboard/pxa930_rotary.c b/drivers/input/keyboard/pxa930_rotary.c index 248cdcf95296..374ca0246c8f 100644 --- a/drivers/input/keyboard/pxa930_rotary.c +++ b/drivers/input/keyboard/pxa930_rotary.c @@ -8,7 +8,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/input.h> #include <linux/platform_device.h> @@ -84,7 +83,8 @@ static void pxa930_rotary_close(struct input_dev *dev) static int pxa930_rotary_probe(struct platform_device *pdev) { - struct pxa930_rotary_platform_data *pdata = pdev->dev.platform_data; + struct pxa930_rotary_platform_data *pdata = + dev_get_platdata(&pdev->dev); struct pxa930_rotary *r; struct input_dev *input_dev; struct resource *res; diff --git a/drivers/input/keyboard/qt1070.c b/drivers/input/keyboard/qt1070.c index 6c561ec3cc09..52cd6e88acd7 100644 --- a/drivers/input/keyboard/qt1070.c +++ b/drivers/input/keyboard/qt1070.c @@ -25,7 +25,6 @@ */ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/i2c.h> #include <linux/input.h> #include <linux/slab.h> diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c index 1c0ddad0a1cc..819b22897c13 100644 --- a/drivers/input/keyboard/qt2160.c +++ b/drivers/input/keyboard/qt2160.c @@ -19,7 +19,6 @@ */ #include <linux/kernel.h> -#include <linux/init.h> #include <linux/leds.h> #include <linux/module.h> #include <linux/slab.h> diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c index ac43a486c775..5e80fbf7b5ed 100644 --- a/drivers/input/keyboard/samsung-keypad.c +++ b/drivers/input/keyboard/samsung-keypad.c @@ -14,7 +14,6 @@ #include <linux/clk.h> #include <linux/delay.h> #include <linux/err.h> -#include <linux/init.h> #include <linux/input.h> #include <linux/interrupt.h> #include <linux/io.h> @@ -244,8 +243,8 @@ static void samsung_keypad_close(struct input_dev *input_dev) } #ifdef CONFIG_OF -static struct samsung_keypad_platdata *samsung_keypad_parse_dt( - struct device *dev) +static struct samsung_keypad_platdata * +samsung_keypad_parse_dt(struct device *dev) { struct samsung_keypad_platdata *pdata; struct matrix_keymap_data *keymap_data; @@ -253,17 +252,22 @@ static struct samsung_keypad_platdata *samsung_keypad_parse_dt( struct device_node *np = dev->of_node, *key_np; unsigned int key_count; + if (!np) { + dev_err(dev, "missing device tree data\n"); + return ERR_PTR(-EINVAL); + } + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) { dev_err(dev, "could not allocate memory for platform data\n"); - return NULL; + return ERR_PTR(-ENOMEM); } of_property_read_u32(np, "samsung,keypad-num-rows", &num_rows); of_property_read_u32(np, "samsung,keypad-num-columns", &num_cols); if (!num_rows || !num_cols) { dev_err(dev, "number of keypad rows/columns not specified\n"); - return NULL; + return ERR_PTR(-EINVAL); } pdata->rows = num_rows; pdata->cols = num_cols; @@ -271,7 +275,7 @@ static struct samsung_keypad_platdata *samsung_keypad_parse_dt( keymap_data = devm_kzalloc(dev, sizeof(*keymap_data), GFP_KERNEL); if (!keymap_data) { dev_err(dev, "could not allocate memory for keymap data\n"); - return NULL; + return ERR_PTR(-ENOMEM); } pdata->keymap_data = keymap_data; @@ -280,7 +284,7 @@ static struct samsung_keypad_platdata *samsung_keypad_parse_dt( keymap = devm_kzalloc(dev, sizeof(uint32_t) * key_count, GFP_KERNEL); if (!keymap) { dev_err(dev, "could not allocate memory for keymap\n"); - return NULL; + return ERR_PTR(-ENOMEM); } keymap_data->keymap = keymap; @@ -294,16 +298,19 @@ static struct samsung_keypad_platdata *samsung_keypad_parse_dt( if (of_get_property(np, "linux,input-no-autorepeat", NULL)) pdata->no_autorepeat = true; + if (of_get_property(np, "linux,input-wakeup", NULL)) pdata->wakeup = true; return pdata; } #else -static -struct samsung_keypad_platdata *samsung_keypad_parse_dt(struct device *dev) +static struct samsung_keypad_platdata * +samsung_keypad_parse_dt(struct device *dev) { - return NULL; + dev_err(dev, "no platform data defined\n"); + + return ERR_PTR(-EINVAL); } #endif @@ -318,13 +325,11 @@ static int samsung_keypad_probe(struct platform_device *pdev) unsigned int keymap_size; int error; - if (pdev->dev.of_node) - pdata = samsung_keypad_parse_dt(&pdev->dev); - else - pdata = pdev->dev.platform_data; + pdata = dev_get_platdata(&pdev->dev); if (!pdata) { - dev_err(&pdev->dev, "no platform data defined\n"); - return -EINVAL; + pdata = samsung_keypad_parse_dt(&pdev->dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); } keymap_data = pdata->keymap_data; diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index fe0e498d2479..7abf03b4cc9c 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c @@ -12,7 +12,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/delay.h> @@ -171,7 +170,7 @@ static int sh_keysc_probe(struct platform_device *pdev) int i; int irq, error; - if (!pdev->dev.platform_data) { + if (!dev_get_platdata(&pdev->dev)) { dev_err(&pdev->dev, "no platform data defined\n"); error = -EINVAL; goto err0; @@ -198,7 +197,7 @@ static int sh_keysc_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, priv); - memcpy(&priv->pdata, pdev->dev.platform_data, sizeof(priv->pdata)); + memcpy(&priv->pdata, dev_get_platdata(&pdev->dev), sizeof(priv->pdata)); pdata = &priv->pdata; priv->iomem_base = ioremap_nocache(res->start, resource_size(res)); diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c index 85ff530d9a91..258af10e5811 100644 --- a/drivers/input/keyboard/spear-keyboard.c +++ b/drivers/input/keyboard/spear-keyboard.c @@ -12,7 +12,6 @@ #include <linux/clk.h> #include <linux/errno.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/input.h> #include <linux/io.h> diff --git a/drivers/input/keyboard/stmpe-keypad.c b/drivers/input/keyboard/stmpe-keypad.c index 5cbec56f7720..c6727dda68f2 100644 --- a/drivers/input/keyboard/stmpe-keypad.c +++ b/drivers/input/keyboard/stmpe-keypad.c @@ -6,7 +6,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/input.h> #include <linux/interrupt.h> diff --git a/drivers/input/keyboard/stowaway.c b/drivers/input/keyboard/stowaway.c index cc612c5d5427..a6e0d565e306 100644 --- a/drivers/input/keyboard/stowaway.c +++ b/drivers/input/keyboard/stowaway.c @@ -32,7 +32,6 @@ #include <linux/slab.h> #include <linux/module.h> #include <linux/input.h> -#include <linux/init.h> #include <linux/serio.h> #define DRIVER_DESC "Stowaway keyboard driver" diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c index 5f836b1638c1..dc6bb9d5b4f0 100644 --- a/drivers/input/keyboard/sunkbd.c +++ b/drivers/input/keyboard/sunkbd.c @@ -31,7 +31,6 @@ #include <linux/slab.h> #include <linux/module.h> #include <linux/interrupt.h> -#include <linux/init.h> #include <linux/input.h> #include <linux/serio.h> #include <linux/workqueue.h> diff --git a/drivers/input/keyboard/tc3589x-keypad.c b/drivers/input/keyboard/tc3589x-keypad.c index 208de7cbb7fa..74494a357522 100644 --- a/drivers/input/keyboard/tc3589x-keypad.c +++ b/drivers/input/keyboard/tc3589x-keypad.c @@ -10,7 +10,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/input.h> #include <linux/platform_device.h> diff --git a/drivers/input/keyboard/tca6416-keypad.c b/drivers/input/keyboard/tca6416-keypad.c index bfc832c35a7c..dc983ab6c0ad 100644 --- a/drivers/input/keyboard/tca6416-keypad.c +++ b/drivers/input/keyboard/tca6416-keypad.c @@ -213,7 +213,7 @@ static int tca6416_keypad_probe(struct i2c_client *client, return -ENODEV; } - pdata = client->dev.platform_data; + pdata = dev_get_platdata(&client->dev); if (!pdata) { dev_dbg(&client->dev, "no platform data\n"); return -EINVAL; diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c index 8bd24d52bf1b..086511c2121b 100644 --- a/drivers/input/keyboard/tnetv107x-keypad.c +++ b/drivers/input/keyboard/tnetv107x-keypad.c @@ -162,7 +162,7 @@ static int keypad_probe(struct platform_device *pdev) int error = 0, sz, row_shift; u32 rev = 0; - pdata = pdev->dev.platform_data; + pdata = dev_get_platdata(&pdev->dev); if (!pdata) { dev_err(dev, "cannot find device data\n"); return -EINVAL; diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c index d2d178c84ea7..c5a11700a1bf 100644 --- a/drivers/input/keyboard/twl4030_keypad.c +++ b/drivers/input/keyboard/twl4030_keypad.c @@ -27,12 +27,12 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/input.h> #include <linux/platform_device.h> #include <linux/i2c/twl.h> #include <linux/slab.h> +#include <linux/of.h> /* * The TWL4030 family chips include a keypad controller that supports @@ -60,6 +60,7 @@ struct twl4030_keypad { unsigned short keymap[TWL4030_KEYMAP_SIZE]; u16 kp_state[TWL4030_MAX_ROWS]; + bool autorepeat; unsigned n_rows; unsigned n_cols; unsigned irq; @@ -330,70 +331,89 @@ static int twl4030_kp_program(struct twl4030_keypad *kp) */ static int twl4030_kp_probe(struct platform_device *pdev) { - struct twl4030_keypad_data *pdata = pdev->dev.platform_data; - const struct matrix_keymap_data *keymap_data; + struct twl4030_keypad_data *pdata = dev_get_platdata(&pdev->dev); + const struct matrix_keymap_data *keymap_data = NULL; struct twl4030_keypad *kp; struct input_dev *input; u8 reg; int error; - if (!pdata || !pdata->rows || !pdata->cols || !pdata->keymap_data || - pdata->rows > TWL4030_MAX_ROWS || pdata->cols > TWL4030_MAX_COLS) { - dev_err(&pdev->dev, "Invalid platform_data\n"); - return -EINVAL; - } + kp = devm_kzalloc(&pdev->dev, sizeof(*kp), GFP_KERNEL); + if (!kp) + return -ENOMEM; - keymap_data = pdata->keymap_data; - - kp = kzalloc(sizeof(*kp), GFP_KERNEL); - input = input_allocate_device(); - if (!kp || !input) { - error = -ENOMEM; - goto err1; - } + input = devm_input_allocate_device(&pdev->dev); + if (!input) + return -ENOMEM; - /* Get the debug Device */ - kp->dbg_dev = &pdev->dev; - kp->input = input; - - kp->n_rows = pdata->rows; - kp->n_cols = pdata->cols; - kp->irq = platform_get_irq(pdev, 0); + /* get the debug device */ + kp->dbg_dev = &pdev->dev; + kp->input = input; /* setup input device */ input->name = "TWL4030 Keypad"; input->phys = "twl4030_keypad/input0"; - input->dev.parent = &pdev->dev; input->id.bustype = BUS_HOST; input->id.vendor = 0x0001; input->id.product = 0x0001; input->id.version = 0x0003; + if (pdata) { + if (!pdata->rows || !pdata->cols || !pdata->keymap_data) { + dev_err(&pdev->dev, "Missing platform_data\n"); + return -EINVAL; + } + + kp->n_rows = pdata->rows; + kp->n_cols = pdata->cols; + kp->autorepeat = pdata->rep; + keymap_data = pdata->keymap_data; + } else { + error = matrix_keypad_parse_of_params(&pdev->dev, &kp->n_rows, + &kp->n_cols); + if (error) + return error; + + kp->autorepeat = true; + } + + if (kp->n_rows > TWL4030_MAX_ROWS || kp->n_cols > TWL4030_MAX_COLS) { + dev_err(&pdev->dev, + "Invalid rows/cols amount specified in platform/devicetree data\n"); + return -EINVAL; + } + + kp->irq = platform_get_irq(pdev, 0); + if (!kp->irq) { + dev_err(&pdev->dev, "no keyboard irq assigned\n"); + return -EINVAL; + } + error = matrix_keypad_build_keymap(keymap_data, NULL, TWL4030_MAX_ROWS, 1 << TWL4030_ROW_SHIFT, kp->keymap, input); if (error) { dev_err(kp->dbg_dev, "Failed to build keymap\n"); - goto err1; + return error; } input_set_capability(input, EV_MSC, MSC_SCAN); /* Enable auto repeat feature of Linux input subsystem */ - if (pdata->rep) + if (kp->autorepeat) __set_bit(EV_REP, input->evbit); error = input_register_device(input); if (error) { dev_err(kp->dbg_dev, "Unable to register twl4030 keypad device\n"); - goto err1; + return error; } error = twl4030_kp_program(kp); if (error) - goto err2; + return error; /* * This ISR will always execute in kernel thread context because of @@ -401,47 +421,33 @@ static int twl4030_kp_probe(struct platform_device *pdev) * * NOTE: we assume this host is wired to TWL4040 INT1, not INT2 ... */ - error = request_threaded_irq(kp->irq, NULL, do_kp_irq, - 0, pdev->name, kp); + error = devm_request_threaded_irq(&pdev->dev, kp->irq, NULL, do_kp_irq, + 0, pdev->name, kp); if (error) { - dev_info(kp->dbg_dev, "request_irq failed for irq no=%d\n", - kp->irq); - goto err2; + dev_info(kp->dbg_dev, "request_irq failed for irq no=%d: %d\n", + kp->irq, error); + return error; } /* Enable KP and TO interrupts now. */ reg = (u8) ~(KEYP_IMR1_KP | KEYP_IMR1_TO); if (twl4030_kpwrite_u8(kp, reg, KEYP_IMR1)) { - error = -EIO; - goto err3; + /* mask all events - we don't care about the result */ + (void) twl4030_kpwrite_u8(kp, 0xff, KEYP_IMR1); + return -EIO; } platform_set_drvdata(pdev, kp); return 0; - -err3: - /* mask all events - we don't care about the result */ - (void) twl4030_kpwrite_u8(kp, 0xff, KEYP_IMR1); - free_irq(kp->irq, kp); -err2: - input_unregister_device(input); - input = NULL; -err1: - input_free_device(input); - kfree(kp); - return error; } -static int twl4030_kp_remove(struct platform_device *pdev) -{ - struct twl4030_keypad *kp = platform_get_drvdata(pdev); - - free_irq(kp->irq, kp); - input_unregister_device(kp->input); - kfree(kp); - - return 0; -} +#ifdef CONFIG_OF +static const struct of_device_id twl4030_keypad_dt_match_table[] = { + { .compatible = "ti,twl4030-keypad" }, + {}, +}; +MODULE_DEVICE_TABLE(of, twl4030_keypad_dt_match_table); +#endif /* * NOTE: twl4030 are multi-function devices connected via I2C. @@ -451,10 +457,10 @@ static int twl4030_kp_remove(struct platform_device *pdev) static struct platform_driver twl4030_kp_driver = { .probe = twl4030_kp_probe, - .remove = twl4030_kp_remove, .driver = { .name = "twl4030_keypad", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(twl4030_keypad_dt_match_table), }, }; module_platform_driver(twl4030_kp_driver); diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c index 7b039162a3f8..e8b9d94daae7 100644 --- a/drivers/input/keyboard/w90p910_keypad.c +++ b/drivers/input/keyboard/w90p910_keypad.c @@ -11,7 +11,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/input.h> #include <linux/device.h> @@ -121,7 +120,7 @@ static void w90p910_keypad_close(struct input_dev *dev) static int w90p910_keypad_probe(struct platform_device *pdev) { const struct w90p910_keypad_platform_data *pdata = - pdev->dev.platform_data; + dev_get_platdata(&pdev->dev); const struct matrix_keymap_data *keymap_data; struct w90p910_keypad *keypad; struct input_dev *input_dev; diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c index d050d9d0011b..7c2325bd7408 100644 --- a/drivers/input/keyboard/xtkbd.c +++ b/drivers/input/keyboard/xtkbd.c @@ -29,7 +29,6 @@ #include <linux/slab.h> #include <linux/module.h> #include <linux/input.h> -#include <linux/init.h> #include <linux/serio.h> #define DRIVER_DESC "XT keyboard driver" diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 5f4967d01bc3..4ffc39732513 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -222,6 +222,15 @@ config INPUT_GP2A To compile this driver as a module, choose M here: the module will be called gp2ap002a00f. +config INPUT_GPIO_BEEPER + tristate "Generic GPIO Beeper support" + depends on OF_GPIO + help + Say Y here if you have a beeper connected to a GPIO pin. + + To compile this driver as a module, choose M here: the + module will be called gpio-beeper. + config INPUT_GPIO_TILT_POLLED tristate "Polled GPIO tilt switch" depends on GPIOLIB diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 0ebfb6dbf0f7..cda71fc52fb3 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_INPUT_DA9052_ONKEY) += da9052_onkey.o obj-$(CONFIG_INPUT_DA9055_ONKEY) += da9055_onkey.o obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o obj-$(CONFIG_INPUT_GP2A) += gp2ap002a00f.o +obj-$(CONFIG_INPUT_GPIO_BEEPER) += gpio-beeper.o obj-$(CONFIG_INPUT_GPIO_TILT_POLLED) += gpio_tilt_polled.o obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o obj-$(CONFIG_INPUT_IMS_PCU) += ims-pcu.o diff --git a/drivers/input/misc/ad714x.c b/drivers/input/misc/ad714x.c index 2e5d5e1de647..7a61e9ee682c 100644 --- a/drivers/input/misc/ad714x.c +++ b/drivers/input/misc/ad714x.c @@ -7,7 +7,6 @@ */ #include <linux/device.h> -#include <linux/init.h> #include <linux/input.h> #include <linux/interrupt.h> #include <linux/slab.h> @@ -969,7 +968,7 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq, int error; struct input_dev *input[MAX_DEVICE_NUM]; - struct ad714x_platform_data *plat_data = dev->platform_data; + struct ad714x_platform_data *plat_data = dev_get_platdata(dev); struct ad714x_chip *ad714x; void *drv_mem; unsigned long irqflags; @@ -986,7 +985,7 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq, goto err_out; } - if (dev->platform_data == NULL) { + if (dev_get_platdata(dev) == NULL) { dev_err(dev, "platform data for ad714x doesn't exist\n"); error = -EINVAL; goto err_out; diff --git a/drivers/input/misc/adxl34x.c b/drivers/input/misc/adxl34x.c index 1cb1da294419..2b2d02f408bb 100644 --- a/drivers/input/misc/adxl34x.c +++ b/drivers/input/misc/adxl34x.c @@ -8,7 +8,6 @@ */ #include <linux/device.h> -#include <linux/init.h> #include <linux/delay.h> #include <linux/input.h> #include <linux/interrupt.h> @@ -714,7 +713,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, ac->fifo_delay = fifo_delay_default; - pdata = dev->platform_data; + pdata = dev_get_platdata(dev); if (!pdata) { dev_dbg(dev, "No platform data: Using default initialization\n"); diff --git a/drivers/input/misc/atlas_btns.c b/drivers/input/misc/atlas_btns.c index 5d4402365a52..c0c5b63af90a 100644 --- a/drivers/input/misc/atlas_btns.c +++ b/drivers/input/misc/atlas_btns.c @@ -25,7 +25,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/input.h> #include <linux/types.h> #include <asm/uaccess.h> diff --git a/drivers/input/misc/bfin_rotary.c b/drivers/input/misc/bfin_rotary.c index cd139cb17e32..e69d9bcb37e1 100644 --- a/drivers/input/misc/bfin_rotary.c +++ b/drivers/input/misc/bfin_rotary.c @@ -6,7 +6,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/pm.h> @@ -92,7 +91,7 @@ static irqreturn_t bfin_rotary_isr(int irq, void *dev_id) static int bfin_rotary_probe(struct platform_device *pdev) { - struct bfin_rotary_platform_data *pdata = pdev->dev.platform_data; + struct bfin_rotary_platform_data *pdata = dev_get_platdata(&pdev->dev); struct bfin_rot *rotary; struct input_dev *input; int error; diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c index 865c2f9d25b9..52d3a9b28f0b 100644 --- a/drivers/input/misc/bma150.c +++ b/drivers/input/misc/bma150.c @@ -526,7 +526,8 @@ static int bma150_register_polled_device(struct bma150_data *bma150) static int bma150_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct bma150_platform_data *pdata = client->dev.platform_data; + const struct bma150_platform_data *pdata = + dev_get_platdata(&client->dev); const struct bma150_cfg *cfg; struct bma150_data *bma150; int chip_id; diff --git a/drivers/input/misc/cma3000_d0x.c b/drivers/input/misc/cma3000_d0x.c index df9b756594f8..c7d00748277b 100644 --- a/drivers/input/misc/cma3000_d0x.c +++ b/drivers/input/misc/cma3000_d0x.c @@ -284,7 +284,7 @@ EXPORT_SYMBOL(cma3000_resume); struct cma3000_accl_data *cma3000_init(struct device *dev, int irq, const struct cma3000_bus_ops *bops) { - const struct cma3000_platform_data *pdata = dev->platform_data; + const struct cma3000_platform_data *pdata = dev_get_platdata(dev); struct cma3000_accl_data *data; struct input_dev *input_dev; int rev; diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c index b5d71d245854..3e11510ff82d 100644 --- a/drivers/input/misc/cobalt_btns.c +++ b/drivers/input/misc/cobalt_btns.c @@ -17,7 +17,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include <linux/init.h> #include <linux/input-polldev.h> #include <linux/ioport.h> #include <linux/module.h> diff --git a/drivers/input/misc/da9052_onkey.c b/drivers/input/misc/da9052_onkey.c index 020569a499f2..1f695f229ea8 100644 --- a/drivers/input/misc/da9052_onkey.c +++ b/drivers/input/misc/da9052_onkey.c @@ -11,7 +11,6 @@ * option) any later version. */ -#include <linux/init.h> #include <linux/input.h> #include <linux/module.h> #include <linux/platform_device.h> diff --git a/drivers/input/misc/da9055_onkey.c b/drivers/input/misc/da9055_onkey.c index a0af8b2506ce..4b11ede34950 100644 --- a/drivers/input/misc/da9055_onkey.c +++ b/drivers/input/misc/da9055_onkey.c @@ -11,7 +11,6 @@ * option) any later version. */ -#include <linux/init.h> #include <linux/input.h> #include <linux/module.h> #include <linux/platform_device.h> diff --git a/drivers/input/misc/dm355evm_keys.c b/drivers/input/misc/dm355evm_keys.c index a309a5c0899e..0eba94f581df 100644 --- a/drivers/input/misc/dm355evm_keys.c +++ b/drivers/input/misc/dm355evm_keys.c @@ -9,7 +9,6 @@ * 2 of the License, or (at your option) any later version. */ #include <linux/kernel.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/input.h> #include <linux/input/sparse-keymap.h> diff --git a/drivers/input/misc/gp2ap002a00f.c b/drivers/input/misc/gp2ap002a00f.c index fe30bd0fe4bd..de21e317da32 100644 --- a/drivers/input/misc/gp2ap002a00f.c +++ b/drivers/input/misc/gp2ap002a00f.c @@ -125,7 +125,7 @@ static int gp2a_initialize(struct gp2a_data *dt) static int gp2a_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct gp2a_platform_data *pdata = client->dev.platform_data; + const struct gp2a_platform_data *pdata = dev_get_platdata(&client->dev); struct gp2a_data *dt; int error; diff --git a/drivers/input/misc/gpio-beeper.c b/drivers/input/misc/gpio-beeper.c new file mode 100644 index 000000000000..b757435e2b3d --- /dev/null +++ b/drivers/input/misc/gpio-beeper.c @@ -0,0 +1,127 @@ +/* + * Generic GPIO beeper driver + * + * Copyright (C) 2013 Alexander Shiyan <shc_work@mail.ru> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include <linux/input.h> +#include <linux/module.h> +#include <linux/of_gpio.h> +#include <linux/workqueue.h> +#include <linux/platform_device.h> + +#define BEEPER_MODNAME "gpio-beeper" + +struct gpio_beeper { + struct work_struct work; + int gpio; + bool active_low; + bool beeping; +}; + +static void gpio_beeper_toggle(struct gpio_beeper *beep, bool on) +{ + gpio_set_value_cansleep(beep->gpio, on ^ beep->active_low); +} + +static void gpio_beeper_work(struct work_struct *work) +{ + struct gpio_beeper *beep = container_of(work, struct gpio_beeper, work); + + gpio_beeper_toggle(beep, beep->beeping); +} + +static int gpio_beeper_event(struct input_dev *dev, unsigned int type, + unsigned int code, int value) +{ + struct gpio_beeper *beep = input_get_drvdata(dev); + + if (type != EV_SND || code != SND_BELL) + return -ENOTSUPP; + + if (value < 0) + return -EINVAL; + + beep->beeping = value; + /* Schedule work to actually turn the beeper on or off */ + schedule_work(&beep->work); + + return 0; +} + +static void gpio_beeper_close(struct input_dev *input) +{ + struct gpio_beeper *beep = input_get_drvdata(input); + + cancel_work_sync(&beep->work); + gpio_beeper_toggle(beep, false); +} + +static int gpio_beeper_probe(struct platform_device *pdev) +{ + struct gpio_beeper *beep; + enum of_gpio_flags flags; + struct input_dev *input; + unsigned long gflags; + int err; + + beep = devm_kzalloc(&pdev->dev, sizeof(*beep), GFP_KERNEL); + if (!beep) + return -ENOMEM; + + beep->gpio = of_get_gpio_flags(pdev->dev.of_node, 0, &flags); + if (!gpio_is_valid(beep->gpio)) + return beep->gpio; + + input = devm_input_allocate_device(&pdev->dev); + if (!input) + return -ENOMEM; + + INIT_WORK(&beep->work, gpio_beeper_work); + + input->name = pdev->name; + input->id.bustype = BUS_HOST; + input->id.vendor = 0x0001; + input->id.product = 0x0001; + input->id.version = 0x0100; + input->close = gpio_beeper_close; + input->event = gpio_beeper_event; + + input_set_capability(input, EV_SND, SND_BELL); + + beep->active_low = flags & OF_GPIO_ACTIVE_LOW; + gflags = beep->active_low ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; + + err = devm_gpio_request_one(&pdev->dev, beep->gpio, gflags, pdev->name); + if (err) + return err; + + input_set_drvdata(input, beep); + + return input_register_device(input); +} + +static struct of_device_id gpio_beeper_of_match[] = { + { .compatible = BEEPER_MODNAME, }, + { } +}; +MODULE_DEVICE_TABLE(of, gpio_beeper_of_match); + +static struct platform_driver gpio_beeper_platform_driver = { + .driver = { + .name = BEEPER_MODNAME, + .owner = THIS_MODULE, + .of_match_table = gpio_beeper_of_match, + }, + .probe = gpio_beeper_probe, +}; +module_platform_driver(gpio_beeper_platform_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>"); +MODULE_DESCRIPTION("Generic GPIO beeper driver"); diff --git a/drivers/input/misc/gpio_tilt_polled.c b/drivers/input/misc/gpio_tilt_polled.c index 714c68369134..1a81d9115226 100644 --- a/drivers/input/misc/gpio_tilt_polled.c +++ b/drivers/input/misc/gpio_tilt_polled.c @@ -16,7 +16,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/input.h> #include <linux/input-polldev.h> @@ -98,7 +97,8 @@ static void gpio_tilt_polled_close(struct input_polled_dev *dev) static int gpio_tilt_polled_probe(struct platform_device *pdev) { - const struct gpio_tilt_platform_data *pdata = pdev->dev.platform_data; + const struct gpio_tilt_platform_data *pdata = + dev_get_platdata(&pdev->dev); struct device *dev = &pdev->dev; struct gpio_tilt_polled_dev *tdev; struct input_polled_dev *poll_dev; diff --git a/drivers/input/misc/keyspan_remote.c b/drivers/input/misc/keyspan_remote.c index 290fa5f97ded..01f3b5b300f3 100644 --- a/drivers/input/misc/keyspan_remote.c +++ b/drivers/input/misc/keyspan_remote.c @@ -13,7 +13,6 @@ #include <linux/kernel.h> #include <linux/errno.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/usb/input.h> diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c index a993b67a8a5b..d708478bc5b5 100644 --- a/drivers/input/misc/kxtj9.c +++ b/drivers/input/misc/kxtj9.c @@ -509,7 +509,8 @@ out: static int kxtj9_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct kxtj9_platform_data *pdata = client->dev.platform_data; + const struct kxtj9_platform_data *pdata = + dev_get_platdata(&client->dev); struct kxtj9_data *tj9; int err; diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c index e973133212a5..1fea5484941f 100644 --- a/drivers/input/misc/max8997_haptic.c +++ b/drivers/input/misc/max8997_haptic.c @@ -23,7 +23,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/platform_device.h> #include <linux/err.h> diff --git a/drivers/input/misc/mc13783-pwrbutton.c b/drivers/input/misc/mc13783-pwrbutton.c index d0277a7b1579..0df6e8d8bd03 100644 --- a/drivers/input/misc/mc13783-pwrbutton.c +++ b/drivers/input/misc/mc13783-pwrbutton.c @@ -20,7 +20,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/input.h> diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c index 6983ffbbfb94..5e5051351c3a 100644 --- a/drivers/input/misc/mpu3050.c +++ b/drivers/input/misc/mpu3050.c @@ -30,7 +30,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/mutex.h> diff --git a/drivers/input/misc/pcap_keys.c b/drivers/input/misc/pcap_keys.c index 40ac9a5adf89..cd230365166e 100644 --- a/drivers/input/misc/pcap_keys.c +++ b/drivers/input/misc/pcap_keys.c @@ -12,7 +12,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/input.h> diff --git a/drivers/input/misc/pcf50633-input.c b/drivers/input/misc/pcf50633-input.c index 73b13ebabe56..db92f4f3c99b 100644 --- a/drivers/input/misc/pcf50633-input.c +++ b/drivers/input/misc/pcf50633-input.c @@ -16,7 +16,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/device.h> #include <linux/platform_device.h> #include <linux/input.h> diff --git a/drivers/input/misc/pcf8574_keypad.c b/drivers/input/misc/pcf8574_keypad.c index 0deca5a3c87f..97f711a7bd20 100644 --- a/drivers/input/misc/pcf8574_keypad.c +++ b/drivers/input/misc/pcf8574_keypad.c @@ -7,7 +7,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/input.h> #include <linux/interrupt.h> #include <linux/i2c.h> diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c index 7288b267613d..674a2cfc3c0e 100644 --- a/drivers/input/misc/pcspkr.c +++ b/drivers/input/misc/pcspkr.c @@ -15,7 +15,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/i8253.h> -#include <linux/init.h> #include <linux/input.h> #include <linux/platform_device.h> #include <linux/timex.h> diff --git a/drivers/input/misc/pm8xxx-vibrator.c b/drivers/input/misc/pm8xxx-vibrator.c index ec086f6f3cc3..b88b7cbf93e2 100644 --- a/drivers/input/misc/pm8xxx-vibrator.c +++ b/drivers/input/misc/pm8xxx-vibrator.c @@ -11,13 +11,12 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/platform_device.h> #include <linux/input.h> #include <linux/slab.h> -#include <linux/mfd/pm8xxx/core.h> +#include <linux/regmap.h> #define VIB_DRV 0x4A @@ -35,7 +34,7 @@ * struct pm8xxx_vib - structure to hold vibrator data * @vib_input_dev: input device supporting force feedback * @work: work structure to set the vibration parameters - * @dev: device supporting force feedback + * @regmap: regmap for register read/write * @speed: speed of vibration set from userland * @active: state of vibrator * @level: level of vibration to set in the chip @@ -44,7 +43,7 @@ struct pm8xxx_vib { struct input_dev *vib_input_dev; struct work_struct work; - struct device *dev; + struct regmap *regmap; int speed; int level; bool active; @@ -52,42 +51,6 @@ struct pm8xxx_vib { }; /** - * pm8xxx_vib_read_u8 - helper to read a byte from pmic chip - * @vib: pointer to vibrator structure - * @data: placeholder for data to be read - * @reg: register address - */ -static int pm8xxx_vib_read_u8(struct pm8xxx_vib *vib, - u8 *data, u16 reg) -{ - int rc; - - rc = pm8xxx_readb(vib->dev->parent, reg, data); - if (rc < 0) - dev_warn(vib->dev, "Error reading pm8xxx reg 0x%x(0x%x)\n", - reg, rc); - return rc; -} - -/** - * pm8xxx_vib_write_u8 - helper to write a byte to pmic chip - * @vib: pointer to vibrator structure - * @data: data to write - * @reg: register address - */ -static int pm8xxx_vib_write_u8(struct pm8xxx_vib *vib, - u8 data, u16 reg) -{ - int rc; - - rc = pm8xxx_writeb(vib->dev->parent, reg, data); - if (rc < 0) - dev_warn(vib->dev, "Error writing pm8xxx reg 0x%x(0x%x)\n", - reg, rc); - return rc; -} - -/** * pm8xxx_vib_set - handler to start/stop vibration * @vib: pointer to vibrator structure * @on: state to set @@ -95,14 +58,14 @@ static int pm8xxx_vib_write_u8(struct pm8xxx_vib *vib, static int pm8xxx_vib_set(struct pm8xxx_vib *vib, bool on) { int rc; - u8 val = vib->reg_vib_drv; + unsigned int val = vib->reg_vib_drv; if (on) val |= ((vib->level << VIB_DRV_SEL_SHIFT) & VIB_DRV_SEL_MASK); else val &= ~VIB_DRV_SEL_MASK; - rc = pm8xxx_vib_write_u8(vib, val, VIB_DRV); + rc = regmap_write(vib->regmap, VIB_DRV, val); if (rc < 0) return rc; @@ -118,9 +81,9 @@ static void pm8xxx_work_handler(struct work_struct *work) { struct pm8xxx_vib *vib = container_of(work, struct pm8xxx_vib, work); int rc; - u8 val; + unsigned int val; - rc = pm8xxx_vib_read_u8(vib, &val, VIB_DRV); + rc = regmap_read(vib->regmap, VIB_DRV, &val); if (rc < 0) return; @@ -184,34 +147,37 @@ static int pm8xxx_vib_probe(struct platform_device *pdev) struct pm8xxx_vib *vib; struct input_dev *input_dev; int error; - u8 val; - - vib = kzalloc(sizeof(*vib), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!vib || !input_dev) { - dev_err(&pdev->dev, "couldn't allocate memory\n"); - error = -ENOMEM; - goto err_free_mem; - } + unsigned int val; + + vib = devm_kzalloc(&pdev->dev, sizeof(*vib), GFP_KERNEL); + if (!vib) + return -ENOMEM; + + vib->regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!vib->regmap) + return -ENODEV; + + input_dev = devm_input_allocate_device(&pdev->dev); + if (!input_dev) + return -ENOMEM; INIT_WORK(&vib->work, pm8xxx_work_handler); - vib->dev = &pdev->dev; vib->vib_input_dev = input_dev; /* operate in manual mode */ - error = pm8xxx_vib_read_u8(vib, &val, VIB_DRV); + error = regmap_read(vib->regmap, VIB_DRV, &val); if (error < 0) - goto err_free_mem; + return error; + val &= ~VIB_DRV_EN_MANUAL_MASK; - error = pm8xxx_vib_write_u8(vib, val, VIB_DRV); + error = regmap_write(vib->regmap, VIB_DRV, val); if (error < 0) - goto err_free_mem; + return error; vib->reg_vib_drv = val; input_dev->name = "pm8xxx_vib_ffmemless"; input_dev->id.version = 1; - input_dev->dev.parent = &pdev->dev; input_dev->close = pm8xxx_vib_close; input_set_drvdata(input_dev, vib); input_set_capability(vib->vib_input_dev, EV_FF, FF_RUMBLE); @@ -221,35 +187,17 @@ static int pm8xxx_vib_probe(struct platform_device *pdev) if (error) { dev_err(&pdev->dev, "couldn't register vibrator as FF device\n"); - goto err_free_mem; + return error; } error = input_register_device(input_dev); if (error) { dev_err(&pdev->dev, "couldn't register input device\n"); - goto err_destroy_memless; + return error; } platform_set_drvdata(pdev, vib); return 0; - -err_destroy_memless: - input_ff_destroy(input_dev); -err_free_mem: - input_free_device(input_dev); - kfree(vib); - - return error; -} - -static int pm8xxx_vib_remove(struct platform_device *pdev) -{ - struct pm8xxx_vib *vib = platform_get_drvdata(pdev); - - input_unregister_device(vib->vib_input_dev); - kfree(vib); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -268,7 +216,6 @@ static SIMPLE_DEV_PM_OPS(pm8xxx_vib_pm_ops, pm8xxx_vib_suspend, NULL); static struct platform_driver pm8xxx_vib_driver = { .probe = pm8xxx_vib_probe, - .remove = pm8xxx_vib_remove, .driver = { .name = "pm8xxx-vib", .owner = THIS_MODULE, diff --git a/drivers/input/misc/pmic8xxx-pwrkey.c b/drivers/input/misc/pmic8xxx-pwrkey.c index b49b738aa9c6..0e1a05f95858 100644 --- a/drivers/input/misc/pmic8xxx-pwrkey.c +++ b/drivers/input/misc/pmic8xxx-pwrkey.c @@ -11,16 +11,15 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/slab.h> #include <linux/input.h> #include <linux/interrupt.h> #include <linux/platform_device.h> +#include <linux/regmap.h> #include <linux/log2.h> -#include <linux/mfd/pm8xxx/core.h> #include <linux/input/pmic8xxx-pwrkey.h> #define PON_CNTL_1 0x1C @@ -32,26 +31,25 @@ * @key_press_irq: key press irq number */ struct pmic8xxx_pwrkey { - struct input_dev *pwr; int key_press_irq; }; -static irqreturn_t pwrkey_press_irq(int irq, void *_pwrkey) +static irqreturn_t pwrkey_press_irq(int irq, void *_pwr) { - struct pmic8xxx_pwrkey *pwrkey = _pwrkey; + struct input_dev *pwr = _pwr; - input_report_key(pwrkey->pwr, KEY_POWER, 1); - input_sync(pwrkey->pwr); + input_report_key(pwr, KEY_POWER, 1); + input_sync(pwr); return IRQ_HANDLED; } -static irqreturn_t pwrkey_release_irq(int irq, void *_pwrkey) +static irqreturn_t pwrkey_release_irq(int irq, void *_pwr) { - struct pmic8xxx_pwrkey *pwrkey = _pwrkey; + struct input_dev *pwr = _pwr; - input_report_key(pwrkey->pwr, KEY_POWER, 0); - input_sync(pwrkey->pwr); + input_report_key(pwr, KEY_POWER, 0); + input_sync(pwr); return IRQ_HANDLED; } @@ -88,7 +86,8 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev) int key_press_irq = platform_get_irq(pdev, 1); int err; unsigned int delay; - u8 pon_cntl; + unsigned int pon_cntl; + struct regmap *regmap; struct pmic8xxx_pwrkey *pwrkey; const struct pm8xxx_pwrkey_platform_data *pdata = dev_get_platdata(&pdev->dev); @@ -103,30 +102,36 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev) return -EINVAL; } - pwrkey = kzalloc(sizeof(*pwrkey), GFP_KERNEL); + regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!regmap) { + dev_err(&pdev->dev, "failed to locate regmap for the device\n"); + return -ENODEV; + } + + pwrkey = devm_kzalloc(&pdev->dev, sizeof(*pwrkey), GFP_KERNEL); if (!pwrkey) return -ENOMEM; - pwr = input_allocate_device(); + pwrkey->key_press_irq = key_press_irq; + + pwr = devm_input_allocate_device(&pdev->dev); if (!pwr) { dev_dbg(&pdev->dev, "Can't allocate power button\n"); - err = -ENOMEM; - goto free_pwrkey; + return -ENOMEM; } input_set_capability(pwr, EV_KEY, KEY_POWER); pwr->name = "pmic8xxx_pwrkey"; pwr->phys = "pmic8xxx_pwrkey/input0"; - pwr->dev.parent = &pdev->dev; delay = (pdata->kpd_trigger_delay_us << 10) / USEC_PER_SEC; delay = 1 + ilog2(delay); - err = pm8xxx_readb(pdev->dev.parent, PON_CNTL_1, &pon_cntl); + err = regmap_read(regmap, PON_CNTL_1, &pon_cntl); if (err < 0) { dev_err(&pdev->dev, "failed reading PON_CNTL_1 err=%d\n", err); - goto free_input_dev; + return err; } pon_cntl &= ~PON_CNTL_TRIG_DELAY_MASK; @@ -136,69 +141,46 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev) else pon_cntl &= ~PON_CNTL_PULL_UP; - err = pm8xxx_writeb(pdev->dev.parent, PON_CNTL_1, pon_cntl); + err = regmap_write(regmap, PON_CNTL_1, pon_cntl); if (err < 0) { dev_err(&pdev->dev, "failed writing PON_CNTL_1 err=%d\n", err); - goto free_input_dev; + return err; } - err = input_register_device(pwr); + err = devm_request_irq(&pdev->dev, key_press_irq, pwrkey_press_irq, + IRQF_TRIGGER_RISING, + "pmic8xxx_pwrkey_press", pwr); if (err) { - dev_dbg(&pdev->dev, "Can't register power key: %d\n", err); - goto free_input_dev; + dev_err(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n", + key_press_irq, err); + return err; } - pwrkey->key_press_irq = key_press_irq; - pwrkey->pwr = pwr; - - platform_set_drvdata(pdev, pwrkey); - - err = request_irq(key_press_irq, pwrkey_press_irq, - IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_press", pwrkey); - if (err < 0) { - dev_dbg(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n", - key_press_irq, err); - goto unreg_input_dev; + err = devm_request_irq(&pdev->dev, key_release_irq, pwrkey_release_irq, + IRQF_TRIGGER_RISING, + "pmic8xxx_pwrkey_release", pwr); + if (err) { + dev_err(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n", + key_release_irq, err); + return err; } - err = request_irq(key_release_irq, pwrkey_release_irq, - IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_release", pwrkey); - if (err < 0) { - dev_dbg(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n", - key_release_irq, err); - - goto free_press_irq; + err = input_register_device(pwr); + if (err) { + dev_err(&pdev->dev, "Can't register power key: %d\n", err); + return err; } + platform_set_drvdata(pdev, pwrkey); device_init_wakeup(&pdev->dev, pdata->wakeup); return 0; - -free_press_irq: - free_irq(key_press_irq, pwrkey); -unreg_input_dev: - input_unregister_device(pwr); - pwr = NULL; -free_input_dev: - input_free_device(pwr); -free_pwrkey: - kfree(pwrkey); - return err; } static int pmic8xxx_pwrkey_remove(struct platform_device *pdev) { - struct pmic8xxx_pwrkey *pwrkey = platform_get_drvdata(pdev); - int key_release_irq = platform_get_irq(pdev, 0); - int key_press_irq = platform_get_irq(pdev, 1); - device_init_wakeup(&pdev->dev, 0); - free_irq(key_press_irq, pwrkey); - free_irq(key_release_irq, pwrkey); - input_unregister_device(pwrkey->pwr); - kfree(pwrkey); - return 0; } diff --git a/drivers/input/misc/powermate.c b/drivers/input/misc/powermate.c index 49c0c3ebd321..63b539d3daba 100644 --- a/drivers/input/misc/powermate.c +++ b/drivers/input/misc/powermate.c @@ -31,7 +31,6 @@ #include <linux/kernel.h> #include <linux/slab.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/spinlock.h> #include <linux/usb/input.h> diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c index 940566e7be13..8ef288e7c971 100644 --- a/drivers/input/misc/pwm-beeper.c +++ b/drivers/input/misc/pwm-beeper.c @@ -68,7 +68,7 @@ static int pwm_beeper_event(struct input_dev *input, static int pwm_beeper_probe(struct platform_device *pdev) { - unsigned long pwm_id = (unsigned long)pdev->dev.platform_data; + unsigned long pwm_id = (unsigned long)dev_get_platdata(&pdev->dev); struct pwm_beeper *beeper; int error; diff --git a/drivers/input/misc/retu-pwrbutton.c b/drivers/input/misc/retu-pwrbutton.c index 7ca09baa0016..4bff1aa9b0db 100644 --- a/drivers/input/misc/retu-pwrbutton.c +++ b/drivers/input/misc/retu-pwrbutton.c @@ -17,7 +17,6 @@ */ #include <linux/irq.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/errno.h> #include <linux/input.h> diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index f920ba7ab51f..99b9e42aa748 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c @@ -16,7 +16,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/input.h> #include <linux/device.h> diff --git a/drivers/input/misc/sgi_btns.c b/drivers/input/misc/sgi_btns.c index 95cf299ef9a3..f10474937a64 100644 --- a/drivers/input/misc/sgi_btns.c +++ b/drivers/input/misc/sgi_btns.c @@ -17,7 +17,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include <linux/init.h> #include <linux/input-polldev.h> #include <linux/ioport.h> #include <linux/module.h> diff --git a/drivers/input/misc/sirfsoc-onkey.c b/drivers/input/misc/sirfsoc-onkey.c index 7b8b03e0d0be..e8897c36d21b 100644 --- a/drivers/input/misc/sirfsoc-onkey.c +++ b/drivers/input/misc/sirfsoc-onkey.c @@ -7,7 +7,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/platform_device.h> diff --git a/drivers/input/misc/twl4030-pwrbutton.c b/drivers/input/misc/twl4030-pwrbutton.c index b9a05fda03e4..fb3b63b2f85c 100644 --- a/drivers/input/misc/twl4030-pwrbutton.c +++ b/drivers/input/misc/twl4030-pwrbutton.c @@ -52,15 +52,15 @@ static irqreturn_t powerbutton_irq(int irq, void *_pwr) return IRQ_HANDLED; } -static int __init twl4030_pwrbutton_probe(struct platform_device *pdev) +static int twl4030_pwrbutton_probe(struct platform_device *pdev) { struct input_dev *pwr; int irq = platform_get_irq(pdev, 0); int err; - pwr = input_allocate_device(); + pwr = devm_input_allocate_device(&pdev->dev); if (!pwr) { - dev_dbg(&pdev->dev, "Can't allocate power button\n"); + dev_err(&pdev->dev, "Can't allocate power button\n"); return -ENOMEM; } @@ -70,52 +70,42 @@ static int __init twl4030_pwrbutton_probe(struct platform_device *pdev) pwr->phys = "twl4030_pwrbutton/input0"; pwr->dev.parent = &pdev->dev; - err = request_threaded_irq(irq, NULL, powerbutton_irq, + err = devm_request_threaded_irq(&pwr->dev, irq, NULL, powerbutton_irq, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "twl4030_pwrbutton", pwr); if (err < 0) { - dev_dbg(&pdev->dev, "Can't get IRQ for pwrbutton: %d\n", err); - goto free_input_dev; + dev_err(&pdev->dev, "Can't get IRQ for pwrbutton: %d\n", err); + return err; } err = input_register_device(pwr); if (err) { - dev_dbg(&pdev->dev, "Can't register power button: %d\n", err); - goto free_irq; + dev_err(&pdev->dev, "Can't register power button: %d\n", err); + return err; } platform_set_drvdata(pdev, pwr); return 0; - -free_irq: - free_irq(irq, pwr); -free_input_dev: - input_free_device(pwr); - return err; } -static int __exit twl4030_pwrbutton_remove(struct platform_device *pdev) -{ - struct input_dev *pwr = platform_get_drvdata(pdev); - int irq = platform_get_irq(pdev, 0); - - free_irq(irq, pwr); - input_unregister_device(pwr); - - return 0; -} +#ifdef CONFIG_OF +static const struct of_device_id twl4030_pwrbutton_dt_match_table[] = { + { .compatible = "ti,twl4030-pwrbutton" }, + {}, +}; +MODULE_DEVICE_TABLE(of, twl4030_pwrbutton_dt_match_table); +#endif static struct platform_driver twl4030_pwrbutton_driver = { - .remove = __exit_p(twl4030_pwrbutton_remove), + .probe = twl4030_pwrbutton_probe, .driver = { .name = "twl4030_pwrbutton", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(twl4030_pwrbutton_dt_match_table), }, }; - -module_platform_driver_probe(twl4030_pwrbutton_driver, - twl4030_pwrbutton_probe); +module_platform_driver(twl4030_pwrbutton_driver); MODULE_ALIAS("platform:twl4030_pwrbutton"); MODULE_DESCRIPTION("Triton2 Power Button"); diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c index 68a5f33152a8..960ef2a70910 100644 --- a/drivers/input/misc/twl4030-vibra.c +++ b/drivers/input/misc/twl4030-vibra.c @@ -185,15 +185,17 @@ static bool twl4030_vibra_check_coexist(struct twl4030_vibra_data *pdata, if (pdata && pdata->coexist) return true; - if (of_find_node_by_name(node, "codec")) + if (of_find_node_by_name(node, "codec")) { + of_node_put(node); return true; + } return false; } static int twl4030_vibra_probe(struct platform_device *pdev) { - struct twl4030_vibra_data *pdata = pdev->dev.platform_data; + struct twl4030_vibra_data *pdata = dev_get_platdata(&pdev->dev); struct device_node *twl4030_core_node = pdev->dev.parent->of_node; struct vibra_info *info; int ret; diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c index 7864b0c3ebb3..77dc23b94eb1 100644 --- a/drivers/input/misc/twl6040-vibra.c +++ b/drivers/input/misc/twl6040-vibra.c @@ -258,17 +258,14 @@ static SIMPLE_DEV_PM_OPS(twl6040_vibra_pm_ops, twl6040_vibra_suspend, NULL); static int twl6040_vibra_probe(struct platform_device *pdev) { struct device *twl6040_core_dev = pdev->dev.parent; - struct device_node *twl6040_core_node = NULL; + struct device_node *twl6040_core_node; struct vibra_info *info; int vddvibl_uV = 0; int vddvibr_uV = 0; int ret; -#ifdef CONFIG_OF twl6040_core_node = of_find_node_by_name(twl6040_core_dev->of_node, "vibra"); -#endif - if (!twl6040_core_node) { dev_err(&pdev->dev, "parent of node is missing?\n"); return -EINVAL; @@ -276,6 +273,7 @@ static int twl6040_vibra_probe(struct platform_device *pdev) info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); if (!info) { + of_node_put(twl6040_core_node); dev_err(&pdev->dev, "couldn't allocate memory\n"); return -ENOMEM; } @@ -295,6 +293,8 @@ static int twl6040_vibra_probe(struct platform_device *pdev) of_property_read_u32(twl6040_core_node, "ti,vddvibl-uV", &vddvibl_uV); of_property_read_u32(twl6040_core_node, "ti,vddvibr-uV", &vddvibr_uV); + of_node_put(twl6040_core_node); + if ((!info->vibldrv_res && !info->viblmotor_res) || (!info->vibrdrv_res && !info->vibrmotor_res)) { dev_err(info->dev, "invalid vibra driver/motor resistance\n"); diff --git a/drivers/input/misc/wm831x-on.c b/drivers/input/misc/wm831x-on.c index caa2c4068f09..173b6dcca0da 100644 --- a/drivers/input/misc/wm831x-on.c +++ b/drivers/input/misc/wm831x-on.c @@ -18,7 +18,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/kernel.h> #include <linux/errno.h> diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c index 285a5bd6cbc9..79c964c075f1 100644 --- a/drivers/input/misc/yealink.c +++ b/drivers/input/misc/yealink.c @@ -47,7 +47,6 @@ */ #include <linux/kernel.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/rwsem.h> diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 5cf62e315218..fb15c64ffb95 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -277,6 +277,57 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) } /* + * Process bitmap data for V5 protocols. Return value is null. + * + * The bitmaps don't have enough data to track fingers, so this function + * only generates points representing a bounding box of at most two contacts. + * These two points are returned in x1, y1, x2, and y2. + */ +static void alps_process_bitmap_dolphin(struct alps_data *priv, + struct alps_fields *fields, + int *x1, int *y1, int *x2, int *y2) +{ + int box_middle_x, box_middle_y; + unsigned int x_map, y_map; + unsigned char start_bit, end_bit; + unsigned char x_msb, x_lsb, y_msb, y_lsb; + + x_map = fields->x_map; + y_map = fields->y_map; + + if (!x_map || !y_map) + return; + + /* Get Most-significant and Least-significant bit */ + x_msb = fls(x_map); + x_lsb = ffs(x_map); + y_msb = fls(y_map); + y_lsb = ffs(y_map); + + /* Most-significant bit should never exceed max sensor line number */ + if (x_msb > priv->x_bits || y_msb > priv->y_bits) + return; + + *x1 = *y1 = *x2 = *y2 = 0; + + if (fields->fingers > 1) { + start_bit = priv->x_bits - x_msb; + end_bit = priv->x_bits - x_lsb; + box_middle_x = (priv->x_max * (start_bit + end_bit)) / + (2 * (priv->x_bits - 1)); + + start_bit = y_lsb - 1; + end_bit = y_msb - 1; + box_middle_y = (priv->y_max * (start_bit + end_bit)) / + (2 * (priv->y_bits - 1)); + *x1 = fields->x; + *y1 = fields->y; + *x2 = 2 * box_middle_x - *x1; + *y2 = 2 * box_middle_y - *y1; + } +} + +/* * Process bitmap data from v3 and v4 protocols. Returns the number of * fingers detected. A return value of 0 means at least one of the * bitmaps was empty. @@ -481,7 +532,8 @@ static void alps_decode_buttons_v3(struct alps_fields *f, unsigned char *p) f->ts_middle = !!(p[3] & 0x40); } -static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p) +static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p, + struct psmouse *psmouse) { f->first_mp = !!(p[4] & 0x40); f->is_mp = !!(p[0] & 0x40); @@ -502,48 +554,61 @@ static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p) alps_decode_buttons_v3(f, p); } -static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p) +static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p, + struct psmouse *psmouse) { - alps_decode_pinnacle(f, p); + alps_decode_pinnacle(f, p, psmouse); f->x_map |= (p[5] & 0x10) << 11; f->y_map |= (p[5] & 0x20) << 6; } -static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p) +static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p, + struct psmouse *psmouse) { + u64 palm_data = 0; + struct alps_data *priv = psmouse->private; + f->first_mp = !!(p[0] & 0x02); f->is_mp = !!(p[0] & 0x20); - f->fingers = ((p[0] & 0x6) >> 1 | + if (!f->is_mp) { + f->x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7)); + f->y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3)); + f->z = (p[0] & 4) ? 0 : p[5] & 0x7f; + alps_decode_buttons_v3(f, p); + } else { + f->fingers = ((p[0] & 0x6) >> 1 | (p[0] & 0x10) >> 2); - f->x_map = ((p[2] & 0x60) >> 5) | - ((p[4] & 0x7f) << 2) | - ((p[5] & 0x7f) << 9) | - ((p[3] & 0x07) << 16) | - ((p[3] & 0x70) << 15) | - ((p[0] & 0x01) << 22); - f->y_map = (p[1] & 0x7f) | - ((p[2] & 0x1f) << 7); - - f->x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7)); - f->y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3)); - f->z = (p[0] & 4) ? 0 : p[5] & 0x7f; - alps_decode_buttons_v3(f, p); + palm_data = (p[1] & 0x7f) | + ((p[2] & 0x7f) << 7) | + ((p[4] & 0x7f) << 14) | + ((p[5] & 0x7f) << 21) | + ((p[3] & 0x07) << 28) | + (((u64)p[3] & 0x70) << 27) | + (((u64)p[0] & 0x01) << 34); + + /* Y-profile is stored in P(0) to p(n-1), n = y_bits; */ + f->y_map = palm_data & (BIT(priv->y_bits) - 1); + + /* X-profile is stored in p(n) to p(n+m-1), m = x_bits; */ + f->x_map = (palm_data >> priv->y_bits) & + (BIT(priv->x_bits) - 1); + } } -static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) +static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse) { struct alps_data *priv = psmouse->private; unsigned char *packet = psmouse->packet; struct input_dev *dev = psmouse->dev; struct input_dev *dev2 = priv->dev2; int x1 = 0, y1 = 0, x2 = 0, y2 = 0; - int fingers = 0, bmap_fingers; - struct alps_fields f; + int fingers = 0, bmap_fn; + struct alps_fields f = {0}; - priv->decode_fields(&f, packet); + priv->decode_fields(&f, packet, psmouse); /* * There's no single feature of touchpad position and bitmap packets @@ -560,19 +625,38 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) */ if (f.is_mp) { fingers = f.fingers; - bmap_fingers = alps_process_bitmap(priv, - f.x_map, f.y_map, - &x1, &y1, &x2, &y2); - - /* - * We shouldn't report more than one finger if - * we don't have two coordinates. - */ - if (fingers > 1 && bmap_fingers < 2) - fingers = bmap_fingers; - - /* Now process position packet */ - priv->decode_fields(&f, priv->multi_data); + if (priv->proto_version == ALPS_PROTO_V3) { + bmap_fn = alps_process_bitmap(priv, f.x_map, + f.y_map, &x1, &y1, + &x2, &y2); + + /* + * We shouldn't report more than one finger if + * we don't have two coordinates. + */ + if (fingers > 1 && bmap_fn < 2) + fingers = bmap_fn; + + /* Now process position packet */ + priv->decode_fields(&f, priv->multi_data, + psmouse); + } else { + /* + * Because Dolphin uses position packet's + * coordinate data as Pt1 and uses it to + * calculate Pt2, so we need to do position + * packet decode first. + */ + priv->decode_fields(&f, priv->multi_data, + psmouse); + + /* + * Since Dolphin's finger number is reliable, + * there is no need to compare with bmap_fn. + */ + alps_process_bitmap_dolphin(priv, &f, &x1, &y1, + &x2, &y2); + } } else { priv->multi_packet = 0; } @@ -662,7 +746,7 @@ static void alps_process_packet_v3(struct psmouse *psmouse) return; } - alps_process_touchpad_packet_v3(psmouse); + alps_process_touchpad_packet_v3_v5(psmouse); } static void alps_process_packet_v6(struct psmouse *psmouse) @@ -1709,6 +1793,52 @@ error: return -1; } +static int alps_dolphin_get_device_area(struct psmouse *psmouse, + struct alps_data *priv) +{ + struct ps2dev *ps2dev = &psmouse->ps2dev; + unsigned char param[4] = {0}; + int num_x_electrode, num_y_electrode; + + if (alps_enter_command_mode(psmouse)) + return -1; + + param[0] = 0x0a; + if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) || + ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) || + ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE)) + return -1; + + if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) + return -1; + + /* + * Dolphin's sensor line number is not fixed. It can be calculated + * by adding the device's register value with DOLPHIN_PROFILE_X/YOFFSET. + * Further more, we can get device's x_max and y_max by multiplying + * sensor line number with DOLPHIN_COUNT_PER_ELECTRODE. + * + * e.g. When we get register's sensor_x = 11 & sensor_y = 8, + * real sensor line number X = 11 + 8 = 19, and + * real sensor line number Y = 8 + 1 = 9. + * So, x_max = (19 - 1) * 64 = 1152, and + * y_max = (9 - 1) * 64 = 512. + */ + num_x_electrode = DOLPHIN_PROFILE_XOFFSET + (param[2] & 0x0F); + num_y_electrode = DOLPHIN_PROFILE_YOFFSET + ((param[2] >> 4) & 0x0F); + priv->x_bits = num_x_electrode; + priv->y_bits = num_y_electrode; + priv->x_max = (num_x_electrode - 1) * DOLPHIN_COUNT_PER_ELECTRODE; + priv->y_max = (num_y_electrode - 1) * DOLPHIN_COUNT_PER_ELECTRODE; + + if (alps_exit_command_mode(psmouse)) + return -1; + + return 0; +} + static int alps_hw_init_dolphin_v1(struct psmouse *psmouse) { struct ps2dev *ps2dev = &psmouse->ps2dev; @@ -1763,13 +1893,13 @@ static void alps_set_defaults(struct alps_data *priv) break; case ALPS_PROTO_V5: priv->hw_init = alps_hw_init_dolphin_v1; - priv->process_packet = alps_process_packet_v3; + priv->process_packet = alps_process_touchpad_packet_v3_v5; priv->decode_fields = alps_decode_dolphin; priv->set_abs_params = alps_set_abs_params_mt; priv->nibble_commands = alps_v3_nibble_commands; priv->addr_command = PSMOUSE_CMD_RESET_WRAP; priv->byte0 = 0xc8; - priv->mask0 = 0xc8; + priv->mask0 = 0xd8; priv->flags = 0; priv->x_max = 1360; priv->y_max = 660; @@ -1845,11 +1975,13 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) if (alps_match_table(psmouse, priv, e7, ec) == 0) { return 0; } else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 && - ec[0] == 0x73 && ec[1] == 0x01) { + ec[0] == 0x73 && (ec[1] == 0x01 || ec[1] == 0x02)) { priv->proto_version = ALPS_PROTO_V5; alps_set_defaults(priv); - - return 0; + if (alps_dolphin_get_device_area(psmouse, priv)) + return -EIO; + else + return 0; } else if (ec[0] == 0x88 && ec[1] == 0x08) { priv->proto_version = ALPS_PROTO_V3; alps_set_defaults(priv); diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h index 704f0f924307..03f88b6940c7 100644 --- a/drivers/input/mouse/alps.h +++ b/drivers/input/mouse/alps.h @@ -19,6 +19,10 @@ #define ALPS_PROTO_V5 5 #define ALPS_PROTO_V6 6 +#define DOLPHIN_COUNT_PER_ELECTRODE 64 +#define DOLPHIN_PROFILE_XOFFSET 8 /* x-electrode offset */ +#define DOLPHIN_PROFILE_YOFFSET 1 /* y-electrode offset */ + /** * struct alps_model_info - touchpad ID table * @signature: E7 response string to match. @@ -146,7 +150,8 @@ struct alps_data { int (*hw_init)(struct psmouse *psmouse); void (*process_packet)(struct psmouse *psmouse); - void (*decode_fields)(struct alps_fields *f, unsigned char *p); + void (*decode_fields)(struct alps_fields *f, unsigned char *p, + struct psmouse *psmouse); void (*set_abs_params)(struct alps_data *priv, struct input_dev *dev1); int prev_fin; diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index e42f1fa8cdc0..800ca7dfafc2 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c @@ -30,7 +30,6 @@ #include <linux/kernel.h> #include <linux/errno.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/usb/input.h> diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index a73f9618b0ad..c329cdb0b91a 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -34,7 +34,6 @@ #include <linux/kernel.h> #include <linux/errno.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/usb/input.h> diff --git a/drivers/input/mouse/cypress_ps2.c b/drivers/input/mouse/cypress_ps2.c index a5869a856ea5..87095e2f5153 100644 --- a/drivers/input/mouse/cypress_ps2.c +++ b/drivers/input/mouse/cypress_ps2.c @@ -15,7 +15,6 @@ * the Free Software Foundation. */ -#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/slab.h> diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 597e9b8fc18d..ef1cf52f8bb9 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -486,6 +486,7 @@ static void elantech_input_sync_v4(struct psmouse *psmouse) unsigned char *packet = psmouse->packet; input_report_key(dev, BTN_LEFT, packet[0] & 0x01); + input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); input_mt_report_pointer_emulation(dev, true); input_sync(dev); } @@ -984,6 +985,44 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse, } /* + * Advertise INPUT_PROP_BUTTONPAD for clickpads. The testing of bit 12 in + * fw_version for this is based on the following fw_version & caps table: + * + * Laptop-model: fw_version: caps: buttons: + * Acer S3 0x461f00 10, 13, 0e clickpad + * Acer S7-392 0x581f01 50, 17, 0d clickpad + * Acer V5-131 0x461f02 01, 16, 0c clickpad + * Acer V5-551 0x461f00 ? clickpad + * Asus K53SV 0x450f01 78, 15, 0c 2 hw buttons + * Asus G46VW 0x460f02 00, 18, 0c 2 hw buttons + * Asus G750JX 0x360f00 00, 16, 0c 2 hw buttons + * Asus UX31 0x361f00 20, 15, 0e clickpad + * Asus UX32VD 0x361f02 00, 15, 0e clickpad + * Avatar AVIU-145A2 0x361f00 ? clickpad + * Gigabyte U2442 0x450f01 58, 17, 0c 2 hw buttons + * Lenovo L430 0x350f02 b9, 15, 0c 2 hw buttons (*) + * Samsung NF210 0x150b00 78, 14, 0a 2 hw buttons + * Samsung NP770Z5E 0x575f01 10, 15, 0f clickpad + * Samsung NP700Z5B 0x361f06 21, 15, 0f clickpad + * Samsung NP900X3E-A02 0x575f03 ? clickpad + * Samsung NP-QX410 0x851b00 19, 14, 0c clickpad + * Samsung RC512 0x450f00 08, 15, 0c 2 hw buttons + * Samsung RF710 0x450f00 ? 2 hw buttons + * System76 Pangolin 0x250f01 ? 2 hw buttons + * (*) + 3 trackpoint buttons + */ +static void elantech_set_buttonpad_prop(struct psmouse *psmouse) +{ + struct input_dev *dev = psmouse->dev; + struct elantech_data *etd = psmouse->private; + + if (etd->fw_version & 0x001000) { + __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); + __clear_bit(BTN_RIGHT, dev->keybit); + } +} + +/* * Set the appropriate event bits for the input subsystem */ static int elantech_set_input_params(struct psmouse *psmouse) @@ -1026,6 +1065,8 @@ static int elantech_set_input_params(struct psmouse *psmouse) __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); /* fall through */ case 3: + if (etd->hw_version == 3) + elantech_set_buttonpad_prop(psmouse); input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); if (etd->reports_pressure) { @@ -1047,9 +1088,7 @@ static int elantech_set_input_params(struct psmouse *psmouse) */ psmouse_warn(psmouse, "couldn't query resolution data.\n"); } - /* v4 is clickpad, with only one button. */ - __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); - __clear_bit(BTN_RIGHT, dev->keybit); + elantech_set_buttonpad_prop(psmouse); __set_bit(BTN_TOOL_QUADTAP, dev->keybit); /* For X to recognize me as touchpad. */ input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c index 6b44413f54e3..8c7d94200bdb 100644 --- a/drivers/input/mouse/gpio_mouse.c +++ b/drivers/input/mouse/gpio_mouse.c @@ -8,7 +8,6 @@ * published by the Free Software Foundation. */ -#include <linux/init.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/input-polldev.h> @@ -48,7 +47,7 @@ static void gpio_mouse_scan(struct input_polled_dev *dev) static int gpio_mouse_probe(struct platform_device *pdev) { - struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data; + struct gpio_mouse_platform_data *pdata = dev_get_platdata(&pdev->dev); struct input_polled_dev *input_poll; struct input_dev *input; int pin, i; diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c index 84de2fc6acc1..136e222e2a16 100644 --- a/drivers/input/mouse/logips2pp.c +++ b/drivers/input/mouse/logips2pp.c @@ -220,7 +220,7 @@ static const struct ps2pp_info *get_model_info(unsigned char model) { 61, PS2PP_KIND_MX, /* MX700 */ PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN | PS2PP_EXTRA_BTN | PS2PP_NAV_BTN }, - { 66, PS2PP_KIND_MX, /* MX3100 reciver */ + { 66, PS2PP_KIND_MX, /* MX3100 receiver */ PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN | PS2PP_EXTRA_BTN | PS2PP_NAV_BTN | PS2PP_HWHEEL }, { 72, PS2PP_KIND_TRACKMAN, 0 }, /* T-CH11: TrackMan Marble */ diff --git a/drivers/input/mouse/navpoint.c b/drivers/input/mouse/navpoint.c index 0b8d33591dee..1ccc88af1f0b 100644 --- a/drivers/input/mouse/navpoint.c +++ b/drivers/input/mouse/navpoint.c @@ -9,7 +9,6 @@ */ #include <linux/kernel.h> -#include <linux/init.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/clk.h> diff --git a/drivers/input/mouse/pxa930_trkball.c b/drivers/input/mouse/pxa930_trkball.c index 0ecb9e7945eb..9b4d9a59e229 100644 --- a/drivers/input/mouse/pxa930_trkball.c +++ b/drivers/input/mouse/pxa930_trkball.c @@ -10,7 +10,6 @@ * published by the Free Software Foundation. */ -#include <linux/init.h> #include <linux/input.h> #include <linux/interrupt.h> #include <linux/module.h> @@ -166,7 +165,7 @@ static int pxa930_trkball_probe(struct platform_device *pdev) if (!trkball) return -ENOMEM; - trkball->pdata = pdev->dev.platform_data; + trkball->pdata = dev_get_platdata(&pdev->dev); if (!trkball->pdata) { dev_err(&pdev->dev, "no platform data defined\n"); error = -EINVAL; diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c index d5928fd0c914..8df526620ebf 100644 --- a/drivers/input/mouse/sermouse.c +++ b/drivers/input/mouse/sermouse.c @@ -32,7 +32,6 @@ #include <linux/interrupt.h> #include <linux/input.h> #include <linux/serio.h> -#include <linux/init.h> #define DRIVER_DESC "Serial mouse driver" diff --git a/drivers/input/mouse/synaptics_usb.c b/drivers/input/mouse/synaptics_usb.c index 64cf34ea7604..e122bda16aab 100644 --- a/drivers/input/mouse/synaptics_usb.c +++ b/drivers/input/mouse/synaptics_usb.c @@ -39,7 +39,6 @@ */ #include <linux/kernel.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/moduleparam.h> diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c index e900d465aaf6..38298232124f 100644 --- a/drivers/input/mouse/vsxxxaa.c +++ b/drivers/input/mouse/vsxxxaa.c @@ -82,7 +82,6 @@ #include <linux/interrupt.h> #include <linux/input.h> #include <linux/serio.h> -#include <linux/init.h> #define DRIVER_DESC "Driver for DEC VSXXX-AA and -GA mice and VSXXX-AB tablet" diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index 8541f949778d..aec54e283580 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig @@ -16,14 +16,19 @@ config SERIO To compile this driver as a module, choose M here: the module will be called serio. +config ARCH_MIGHT_HAVE_PC_SERIO + bool + help + Select this config option from the architecture Kconfig if + the architecture might use a PC serio device (i8042) to + communicate with keyboard, mouse, etc. + if SERIO config SERIO_I8042 tristate "i8042 PC Keyboard controller" default y - depends on !PARISC && (!ARM || FOOTBRIDGE_HOST) && \ - (!SUPERH || SH_CAYMAN) && !M68K && !BLACKFIN && !S390 && \ - !ARC + depends on ARCH_MIGHT_HAVE_PC_SERIO help i8042 is the chip over which the standard AT keyboard and PS/2 mouse are connected to the computer. If you use these devices, diff --git a/drivers/input/serio/altera_ps2.c b/drivers/input/serio/altera_ps2.c index 4777a73cd390..cce69d6b9587 100644 --- a/drivers/input/serio/altera_ps2.c +++ b/drivers/input/serio/altera_ps2.c @@ -12,7 +12,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/input.h> #include <linux/serio.h> #include <linux/interrupt.h> diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c index 4e2fd44865e1..3e3776c7bd21 100644 --- a/drivers/input/serio/ambakmi.c +++ b/drivers/input/serio/ambakmi.c @@ -10,7 +10,6 @@ * (at your option) any later version. */ #include <linux/module.h> -#include <linux/init.h> #include <linux/serio.h> #include <linux/errno.h> #include <linux/interrupt.h> diff --git a/drivers/input/serio/hyperv-keyboard.c b/drivers/input/serio/hyperv-keyboard.c index 3a83c3c14b23..613261994621 100644 --- a/drivers/input/serio/hyperv-keyboard.c +++ b/drivers/input/serio/hyperv-keyboard.c @@ -160,7 +160,9 @@ static void hv_kbd_on_receive(struct hv_device *hv_dev, if (info & IS_E0) serio_interrupt(kbd_dev->hv_serio, XTKBD_EMUL0, 0); - + if (info & IS_E1) + serio_interrupt(kbd_dev->hv_serio, + XTKBD_EMUL1, 0); scan_code = __le16_to_cpu(ks_msg->make_code); if (info & IS_BREAK) scan_code |= XTKBD_RELEASE; diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index 07a8363f3c5c..75516996db20 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c @@ -18,7 +18,6 @@ #include <linux/input.h> #include <linux/serio.h> #include <linux/i8042.h> -#include <linux/init.h> #include <linux/libps2.h> #define DRIVER_DESC "PS/2 driver library" diff --git a/drivers/input/serio/olpc_apsp.c b/drivers/input/serio/olpc_apsp.c index 51b1d40cc286..5d2fe7ece7ca 100644 --- a/drivers/input/serio/olpc_apsp.c +++ b/drivers/input/serio/olpc_apsp.c @@ -16,7 +16,6 @@ #include <linux/module.h> #include <linux/interrupt.h> -#include <linux/init.h> #include <linux/serio.h> #include <linux/err.h> #include <linux/platform_device.h> diff --git a/drivers/input/serio/pcips2.c b/drivers/input/serio/pcips2.c index 76f83836fd5a..e862c6ea9d9e 100644 --- a/drivers/input/serio/pcips2.c +++ b/drivers/input/serio/pcips2.c @@ -16,7 +16,6 @@ #include <linux/input.h> #include <linux/pci.h> #include <linux/slab.h> -#include <linux/init.h> #include <linux/serio.h> #include <linux/delay.h> #include <asm/io.h> @@ -181,7 +180,6 @@ static void pcips2_remove(struct pci_dev *dev) struct pcips2_data *ps2if = pci_get_drvdata(dev); serio_unregister_port(ps2if->io); - pci_set_drvdata(dev, NULL); kfree(ps2if); pci_release_regions(dev); pci_disable_device(dev); diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c index 7a65a1bc5226..594256c38554 100644 --- a/drivers/input/serio/q40kbd.c +++ b/drivers/input/serio/q40kbd.c @@ -30,7 +30,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/serio.h> #include <linux/interrupt.h> #include <linux/err.h> diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c index 567566ae0dae..e462e7791bb8 100644 --- a/drivers/input/serio/rpckbd.c +++ b/drivers/input/serio/rpckbd.c @@ -29,7 +29,6 @@ #include <linux/module.h> #include <linux/interrupt.h> -#include <linux/init.h> #include <linux/serio.h> #include <linux/err.h> #include <linux/platform_device.h> diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index 59df2e7317a3..c9a02fe57576 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c @@ -15,7 +15,6 @@ #include <linux/poll.h> #include <linux/module.h> #include <linux/serio.h> -#include <linux/init.h> #include <linux/major.h> #include <linux/device.h> #include <linux/miscdevice.h> diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c index dfbcd872f95e..e6cf52ebad87 100644 --- a/drivers/input/serio/xilinx_ps2.c +++ b/drivers/input/serio/xilinx_ps2.c @@ -20,7 +20,6 @@ #include <linux/interrupt.h> #include <linux/errno.h> #include <linux/slab.h> -#include <linux/init.h> #include <linux/list.h> #include <linux/io.h> #include <linux/of_address.h> diff --git a/drivers/input/tablet/acecad.c b/drivers/input/tablet/acecad.c index e062ec899ca1..889f6b77e8cb 100644 --- a/drivers/input/tablet/acecad.c +++ b/drivers/input/tablet/acecad.c @@ -28,7 +28,6 @@ #include <linux/kernel.h> #include <linux/slab.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/usb/input.h> /* diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c index ee83c3904ee8..e7f966da6efa 100644 --- a/drivers/input/tablet/aiptek.c +++ b/drivers/input/tablet/aiptek.c @@ -74,7 +74,6 @@ #include <linux/kernel.h> #include <linux/slab.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/usb/input.h> #include <asm/uaccess.h> #include <asm/unaligned.h> diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c index 29e01ab6859f..caecffe8caff 100644 --- a/drivers/input/tablet/gtco.c +++ b/drivers/input/tablet/gtco.c @@ -53,7 +53,6 @@ Scott Hill shill@gtcocalcomp.com #include <linux/kernel.h> #include <linux/module.h> #include <linux/errno.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/input.h> #include <linux/usb.h> diff --git a/drivers/input/tablet/hanwang.c b/drivers/input/tablet/hanwang.c index 5cc04124995c..cd852059b99e 100644 --- a/drivers/input/tablet/hanwang.c +++ b/drivers/input/tablet/hanwang.c @@ -26,7 +26,6 @@ #include <linux/kernel.h> #include <linux/slab.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/usb/input.h> #define DRIVER_AUTHOR "Xing Wei <weixing@hanwang.com.cn>" diff --git a/drivers/input/tablet/kbtab.c b/drivers/input/tablet/kbtab.c index 3fba74b9b602..d2ac7c2b5b82 100644 --- a/drivers/input/tablet/kbtab.c +++ b/drivers/input/tablet/kbtab.c @@ -1,7 +1,6 @@ #include <linux/kernel.h> #include <linux/slab.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/usb/input.h> #include <asm/unaligned.h> diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h index b79d45198d82..9ebf0ed3b3b3 100644 --- a/drivers/input/tablet/wacom.h +++ b/drivers/input/tablet/wacom.h @@ -86,7 +86,6 @@ #include <linux/slab.h> #include <linux/module.h> #include <linux/mod_devicetable.h> -#include <linux/init.h> #include <linux/usb/input.h> #include <linux/power_supply.h> #include <asm/unaligned.h> diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 867e7c33ac55..b16ebef5b911 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -304,7 +304,7 @@ static int wacom_parse_hid(struct usb_interface *intf, struct usb_device *dev = interface_to_usbdev(intf); char limit = 0; /* result has to be defined as int for some devices */ - int result = 0; + int result = 0, touch_max = 0; int i = 0, usage = WCM_UNDEFINED, finger = 0, pen = 0; unsigned char *report; @@ -351,7 +351,8 @@ static int wacom_parse_hid(struct usb_interface *intf, if (usage == WCM_DESKTOP) { if (finger) { features->device_type = BTN_TOOL_FINGER; - + /* touch device at least supports one touch point */ + touch_max = 1; switch (features->type) { case TABLETPC2FG: features->pktlen = WACOM_PKGLEN_TPC2FG; @@ -504,6 +505,8 @@ static int wacom_parse_hid(struct usb_interface *intf, } out: + if (!features->touch_max && touch_max) + features->touch_max = touch_max; result = 0; kfree(report); return result; @@ -1194,12 +1197,15 @@ static void wacom_wireless_work(struct work_struct *work) wacom_wac1->features.device_type = BTN_TOOL_PEN; snprintf(wacom_wac1->name, WACOM_NAME_MAX, "%s (WL) Pen", wacom_wac1->features.name); + wacom_wac1->shared->touch_max = wacom_wac1->features.touch_max; + wacom_wac1->shared->type = wacom_wac1->features.type; error = wacom_register_input(wacom1); if (error) goto fail; /* Touch interface */ - if (wacom_wac1->features.touch_max) { + if (wacom_wac1->features.touch_max || + wacom_wac1->features.type == INTUOSHT) { wacom_wac2->features = *((struct wacom_features *)id->driver_info); wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3; @@ -1214,6 +1220,10 @@ static void wacom_wireless_work(struct work_struct *work) error = wacom_register_input(wacom2); if (error) goto fail; + + if (wacom_wac1->features.type == INTUOSHT && + wacom_wac1->features.touch_max) + wacom_wac->shared->touch_input = wacom_wac2->input; } error = wacom_initialize_battery(wacom); @@ -1322,7 +1332,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i * HID descriptor. If this is the touch interface (wMaxPacketSize * of WACOM_PKGLEN_BBTOUCH3), override the table values. */ - if (features->type >= INTUOS5S && features->type <= INTUOSPL) { + if (features->type >= INTUOS5S && features->type <= INTUOSHT) { if (endpoint->wMaxPacketSize == WACOM_PKGLEN_BBTOUCH3) { features->device_type = BTN_TOOL_FINGER; features->pktlen = WACOM_PKGLEN_BBTOUCH3; @@ -1393,6 +1403,11 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i } } + if (wacom_wac->features.type == INTUOSHT && wacom_wac->features.touch_max) { + if (wacom_wac->features.device_type == BTN_TOOL_FINGER) + wacom_wac->shared->touch_input = wacom_wac->input; + } + return 0; fail5: wacom_destroy_leds(wacom); diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 782c2535f1d8..05f371df6c40 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -210,6 +210,62 @@ static int wacom_dtu_irq(struct wacom_wac *wacom) return 1; } +static int wacom_dtus_irq(struct wacom_wac *wacom) +{ + char *data = wacom->data; + struct input_dev *input = wacom->input; + unsigned short prox, pressure = 0; + + if (data[0] != WACOM_REPORT_DTUS && data[0] != WACOM_REPORT_DTUSPAD) { + dev_dbg(input->dev.parent, + "%s: received unknown report #%d", __func__, data[0]); + return 0; + } else if (data[0] == WACOM_REPORT_DTUSPAD) { + input_report_key(input, BTN_0, (data[1] & 0x01)); + input_report_key(input, BTN_1, (data[1] & 0x02)); + input_report_key(input, BTN_2, (data[1] & 0x04)); + input_report_key(input, BTN_3, (data[1] & 0x08)); + input_report_abs(input, ABS_MISC, + data[1] & 0x0f ? PAD_DEVICE_ID : 0); + /* + * Serial number is required when expresskeys are + * reported through pen interface. + */ + input_event(input, EV_MSC, MSC_SERIAL, 0xf0); + return 1; + } else { + prox = data[1] & 0x80; + if (prox) { + switch ((data[1] >> 3) & 3) { + case 1: /* Rubber */ + wacom->tool[0] = BTN_TOOL_RUBBER; + wacom->id[0] = ERASER_DEVICE_ID; + break; + + case 2: /* Pen */ + wacom->tool[0] = BTN_TOOL_PEN; + wacom->id[0] = STYLUS_DEVICE_ID; + break; + } + } + + input_report_key(input, BTN_STYLUS, data[1] & 0x20); + input_report_key(input, BTN_STYLUS2, data[1] & 0x40); + input_report_abs(input, ABS_X, get_unaligned_be16(&data[3])); + input_report_abs(input, ABS_Y, get_unaligned_be16(&data[5])); + pressure = ((data[1] & 0x03) << 8) | (data[2] & 0xff); + input_report_abs(input, ABS_PRESSURE, pressure); + input_report_key(input, BTN_TOUCH, pressure > 10); + + if (!prox) /* out-prox */ + wacom->id[0] = 0; + input_report_key(input, wacom->tool[0], prox); + input_report_abs(input, ABS_MISC, wacom->id[0]); + input_event(input, EV_MSC, MSC_SERIAL, 1); + return 1; + } +} + static int wacom_graphire_irq(struct wacom_wac *wacom) { struct wacom_features *features = &wacom->features; @@ -331,7 +387,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) /* Enter report */ if ((data[1] & 0xfc) == 0xc0) { - if (features->quirks == WACOM_QUIRK_MULTI_INPUT) + if (features->quirks & WACOM_QUIRK_MULTI_INPUT) wacom->shared->stylus_in_proximity = true; /* serial number of the tool */ @@ -436,7 +492,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) /* Exit report */ if ((data[1] & 0xfe) == 0x80) { - if (features->quirks == WACOM_QUIRK_MULTI_INPUT) + if (features->quirks & WACOM_QUIRK_MULTI_INPUT) wacom->shared->stylus_in_proximity = false; /* @@ -1151,8 +1207,8 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data) int width, height; if (features->type >= INTUOSPS && features->type <= INTUOSPL) { - width = data[5]; - height = data[6]; + width = data[5] * 100; + height = data[6] * 100; } else { /* * "a" is a scaled-down area which we assume is @@ -1176,10 +1232,16 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data) static void wacom_bpt3_button_msg(struct wacom_wac *wacom, unsigned char *data) { struct input_dev *input = wacom->input; + struct wacom_features *features = &wacom->features; - input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0); + if (features->type == INTUOSHT) { + input_report_key(input, BTN_LEFT, (data[1] & 0x02) != 0); + input_report_key(input, BTN_BACK, (data[1] & 0x08) != 0); + } else { + input_report_key(input, BTN_BACK, (data[1] & 0x02) != 0); + input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0); + } input_report_key(input, BTN_FORWARD, (data[1] & 0x04) != 0); - input_report_key(input, BTN_BACK, (data[1] & 0x02) != 0); input_report_key(input, BTN_RIGHT, (data[1] & 0x01) != 0); } @@ -1213,13 +1275,23 @@ static int wacom_bpt3_touch(struct wacom_wac *wacom) static int wacom_bpt_pen(struct wacom_wac *wacom) { + struct wacom_features *features = &wacom->features; struct input_dev *input = wacom->input; unsigned char *data = wacom->data; int prox = 0, x = 0, y = 0, p = 0, d = 0, pen = 0, btn1 = 0, btn2 = 0; - if (data[0] != 0x02) + if (data[0] != WACOM_REPORT_PENABLED && data[0] != WACOM_REPORT_USB) return 0; + if (data[0] == WACOM_REPORT_USB) { + if (features->type == INTUOSHT && features->touch_max) { + input_report_switch(wacom->shared->touch_input, + SW_MUTE_DEVICE, data[8] & 0x40); + input_sync(wacom->shared->touch_input); + } + return 0; + } + prox = (data[1] & 0x20) == 0x20; /* @@ -1252,8 +1324,8 @@ static int wacom_bpt_pen(struct wacom_wac *wacom) * touching and applying pressure; do not report negative * distance. */ - if (data[8] <= wacom->features.distance_max) - d = wacom->features.distance_max - data[8]; + if (data[8] <= features->distance_max) + d = features->distance_max - data[8]; pen = data[1] & 0x01; btn1 = data[1] & 0x02; @@ -1297,13 +1369,20 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len) unsigned char *data = wacom->data; int connected; - if (len != WACOM_PKGLEN_WIRELESS || data[0] != 0x80) + if (len != WACOM_PKGLEN_WIRELESS || data[0] != WACOM_REPORT_WL) return 0; connected = data[1] & 0x01; if (connected) { int pid, battery; + if ((wacom->shared->type == INTUOSHT) && + wacom->shared->touch_max) { + input_report_switch(wacom->shared->touch_input, + SW_MUTE_DEVICE, data[5] & 0x40); + input_sync(wacom->shared->touch_input); + } + pid = get_unaligned_be16(&data[6]); battery = data[5] & 0x3f; if (wacom->pid != pid) { @@ -1348,6 +1427,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) sync = wacom_dtu_irq(wacom_wac); break; + case DTUS: + sync = wacom_dtus_irq(wacom_wac); + break; + case INTUOS: case INTUOS3S: case INTUOS3: @@ -1391,6 +1474,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) break; case BAMBOO_PT: + case INTUOSHT: sync = wacom_bpt_irq(wacom_wac, len); break; @@ -1459,7 +1543,7 @@ void wacom_setup_device_quirks(struct wacom_features *features) /* these device have multiple inputs */ if (features->type >= WIRELESS || - (features->type >= INTUOS5S && features->type <= INTUOSPL) || + (features->type >= INTUOS5S && features->type <= INTUOSHT) || (features->oVid && features->oPid)) features->quirks |= WACOM_QUIRK_MULTI_INPUT; @@ -1538,7 +1622,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, wacom_abs_set_axis(input_dev, wacom_wac); - switch (wacom_wac->features.type) { + switch (features->type) { case WACOM_MO: input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0); /* fall through */ @@ -1749,8 +1833,14 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, /* fall through */ + case DTUS: case PL: case DTU: + if (features->type == DTUS) { + input_set_capability(input_dev, EV_MSC, MSC_SERIAL); + for (i = 0; i < 3; i++) + __set_bit(BTN_0 + i, input_dev->keybit); + } __set_bit(BTN_TOOL_PEN, input_dev->keybit); __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); __set_bit(BTN_STYLUS, input_dev->keybit); @@ -1771,33 +1861,50 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, __set_bit(INPUT_PROP_POINTER, input_dev->propbit); break; + case INTUOSHT: + if (features->touch_max && + features->device_type == BTN_TOOL_FINGER) { + input_dev->evbit[0] |= BIT_MASK(EV_SW); + __set_bit(SW_MUTE_DEVICE, input_dev->swbit); + } + /* fall through */ + case BAMBOO_PT: __clear_bit(ABS_MISC, input_dev->absbit); - __set_bit(INPUT_PROP_POINTER, input_dev->propbit); - if (features->device_type == BTN_TOOL_FINGER) { - unsigned int flags = INPUT_MT_POINTER; __set_bit(BTN_LEFT, input_dev->keybit); __set_bit(BTN_FORWARD, input_dev->keybit); __set_bit(BTN_BACK, input_dev->keybit); __set_bit(BTN_RIGHT, input_dev->keybit); - if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { - input_set_abs_params(input_dev, + if (features->touch_max) { + /* touch interface */ + unsigned int flags = INPUT_MT_POINTER; + + __set_bit(INPUT_PROP_POINTER, input_dev->propbit); + if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { + input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, features->x_max, 0, 0); - input_set_abs_params(input_dev, + input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, 0, features->y_max, 0, 0); + } else { + __set_bit(BTN_TOOL_FINGER, input_dev->keybit); + __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); + flags = 0; + } + input_mt_init_slots(input_dev, features->touch_max, flags); } else { - __set_bit(BTN_TOOL_FINGER, input_dev->keybit); - __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); - flags = 0; + /* buttons/keys only interface */ + __clear_bit(ABS_X, input_dev->absbit); + __clear_bit(ABS_Y, input_dev->absbit); + __clear_bit(BTN_TOUCH, input_dev->keybit); } - input_mt_init_slots(input_dev, features->touch_max, flags); } else if (features->device_type == BTN_TOOL_PEN) { + __set_bit(INPUT_PROP_POINTER, input_dev->propbit); __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); __set_bit(BTN_TOOL_PEN, input_dev->keybit); __set_bit(BTN_STYLUS, input_dev->keybit); @@ -2055,6 +2162,9 @@ static const struct wacom_features wacom_features_0xCE = static const struct wacom_features wacom_features_0xF0 = { "Wacom DTU1631", WACOM_PKGLEN_GRAPHIRE, 34623, 19553, 511, 0, DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0xFB = + { "Wacom DTU1031", WACOM_PKGLEN_DTUS, 22096, 13960, 511, + 0, DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x57 = { "Wacom DTK2241", WACOM_PKGLEN_INTUOS, 95840, 54260, 2047, 63, DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES}; @@ -2200,6 +2310,17 @@ static const struct wacom_features wacom_features_0x300 = static const struct wacom_features wacom_features_0x301 = { "Wacom Bamboo One M", WACOM_PKGLEN_BBPEN, 21648, 13530, 1023, 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0x302 = + { "Wacom Intuos PT S", WACOM_PKGLEN_BBPEN, 15200, 9500, 1023, + 31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, + .touch_max = 16 }; +static const struct wacom_features wacom_features_0x303 = + { "Wacom Intuos PT M", WACOM_PKGLEN_BBPEN, 21600, 13500, 1023, + 31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, + .touch_max = 16 }; +static const struct wacom_features wacom_features_0x30E = + { "Wacom Intuos S", WACOM_PKGLEN_BBPEN, 15200, 9500, 1023, + 31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x6004 = { "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255, 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; @@ -2337,6 +2458,9 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x10F) }, { USB_DEVICE_WACOM(0x300) }, { USB_DEVICE_WACOM(0x301) }, + { USB_DEVICE_DETAILED(0x302, USB_CLASS_HID, 0, 0) }, + { USB_DEVICE_DETAILED(0x303, USB_CLASS_HID, 0, 0) }, + { USB_DEVICE_DETAILED(0x30E, USB_CLASS_HID, 0, 0) }, { USB_DEVICE_WACOM(0x304) }, { USB_DEVICE_DETAILED(0x314, USB_CLASS_HID, 0, 0) }, { USB_DEVICE_DETAILED(0x315, USB_CLASS_HID, 0, 0) }, @@ -2347,6 +2471,7 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0xF8) }, { USB_DEVICE_DETAILED(0xF6, USB_CLASS_HID, 0, 0) }, { USB_DEVICE_WACOM(0xFA) }, + { USB_DEVICE_WACOM(0xFB) }, { USB_DEVICE_WACOM(0x0307) }, { USB_DEVICE_DETAILED(0x0309, USB_CLASS_HID, 0, 0) }, { USB_DEVICE_LENOVO(0x6004) }, diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index fd23a3790605..f69c0ebe7fa9 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -12,7 +12,7 @@ #include <linux/types.h> /* maximum packet length for USB devices */ -#define WACOM_PKGLEN_MAX 64 +#define WACOM_PKGLEN_MAX 68 #define WACOM_NAME_MAX 64 @@ -29,6 +29,7 @@ #define WACOM_PKGLEN_WIRELESS 32 #define WACOM_PKGLEN_MTOUCH 62 #define WACOM_PKGLEN_MTTPC 40 +#define WACOM_PKGLEN_DTUS 68 /* wacom data size per MT contact */ #define WACOM_BYTES_PER_MT_PACKET 11 @@ -47,13 +48,17 @@ #define WACOM_REPORT_INTUOSWRITE 6 #define WACOM_REPORT_INTUOSPAD 12 #define WACOM_REPORT_INTUOS5PAD 3 +#define WACOM_REPORT_DTUSPAD 21 #define WACOM_REPORT_TPC1FG 6 #define WACOM_REPORT_TPC2FG 13 #define WACOM_REPORT_TPCMT 13 #define WACOM_REPORT_TPCHID 15 #define WACOM_REPORT_TPCST 16 +#define WACOM_REPORT_DTUS 17 #define WACOM_REPORT_TPC1FGE 18 #define WACOM_REPORT_24HDT 1 +#define WACOM_REPORT_WL 128 +#define WACOM_REPORT_USB 192 /* device quirks */ #define WACOM_QUIRK_MULTI_INPUT 0x0001 @@ -68,6 +73,7 @@ enum { PTU, PL, DTU, + DTUS, INTUOS, INTUOS3S, INTUOS3, @@ -81,6 +87,7 @@ enum { INTUOSPS, INTUOSPM, INTUOSPL, + INTUOSHT, WACOM_21UX2, WACOM_22HD, DTK, @@ -129,6 +136,10 @@ struct wacom_features { struct wacom_shared { bool stylus_in_proximity; bool touch_down; + /* for wireless device to access USB interfaces */ + unsigned touch_max; + int type; + struct input_dev *touch_input; }; struct wacom_wac { diff --git a/drivers/input/touchscreen/88pm860x-ts.c b/drivers/input/touchscreen/88pm860x-ts.c index f7de14a268bf..544e20c551f8 100644 --- a/drivers/input/touchscreen/88pm860x-ts.c +++ b/drivers/input/touchscreen/88pm860x-ts.c @@ -172,7 +172,7 @@ static int pm860x_touch_dt_init(struct platform_device *pdev, static int pm860x_touch_probe(struct platform_device *pdev) { struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); - struct pm860x_touch_pdata *pdata = pdev->dev.platform_data; + struct pm860x_touch_pdata *pdata = dev_get_platdata(&pdev->dev); struct pm860x_touch *touch; struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ : chip->companion; diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index 69834dd3c313..6793c85903ae 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c @@ -37,7 +37,6 @@ #include <linux/device.h> -#include <linux/init.h> #include <linux/delay.h> #include <linux/input.h> #include <linux/interrupt.h> @@ -686,7 +685,7 @@ static int ad7877_probe(struct spi_device *spi) { struct ad7877 *ts; struct input_dev *input_dev; - struct ad7877_platform_data *pdata = spi->dev.platform_data; + struct ad7877_platform_data *pdata = dev_get_platdata(&spi->dev); int err; u16 verify; diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c index facd3057b62d..fce590677b7b 100644 --- a/drivers/input/touchscreen/ad7879.c +++ b/drivers/input/touchscreen/ad7879.c @@ -22,7 +22,6 @@ */ #include <linux/device.h> -#include <linux/init.h> #include <linux/delay.h> #include <linux/input.h> #include <linux/interrupt.h> @@ -470,7 +469,7 @@ static int ad7879_gpio_add(struct ad7879 *ts, static void ad7879_gpio_remove(struct ad7879 *ts) { - const struct ad7879_platform_data *pdata = ts->dev->platform_data; + const struct ad7879_platform_data *pdata = dev_get_platdata(ts->dev); int ret; if (pdata->gpio_export) { @@ -495,7 +494,7 @@ static inline void ad7879_gpio_remove(struct ad7879 *ts) struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq, const struct ad7879_bus_ops *bops) { - struct ad7879_platform_data *pdata = dev->platform_data; + struct ad7879_platform_data *pdata = dev_get_platdata(dev); struct ad7879 *ts; struct input_dev *input_dev; int err; diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index ea195360747e..45a06e495ed2 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -19,7 +19,6 @@ */ #include <linux/types.h> #include <linux/hwmon.h> -#include <linux/init.h> #include <linux/err.h> #include <linux/sched.h> #include <linux/delay.h> @@ -101,8 +100,7 @@ struct ads7846 { struct spi_device *spi; struct regulator *reg; -#if defined(CONFIG_HWMON) || defined(CONFIG_HWMON_MODULE) - struct attribute_group *attr_group; +#if IS_ENABLED(CONFIG_HWMON) struct device *hwmon; #endif @@ -421,7 +419,7 @@ static int ads7845_read12_ser(struct device *dev, unsigned command) return status; } -#if defined(CONFIG_HWMON) || defined(CONFIG_HWMON_MODULE) +#if IS_ENABLED(CONFIG_HWMON) #define SHOW(name, var, adjust) static ssize_t \ name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \ @@ -479,42 +477,36 @@ static inline unsigned vbatt_adjust(struct ads7846 *ts, ssize_t v) SHOW(in0_input, vaux, vaux_adjust) SHOW(in1_input, vbatt, vbatt_adjust) -static struct attribute *ads7846_attributes[] = { - &dev_attr_temp0.attr, - &dev_attr_temp1.attr, - &dev_attr_in0_input.attr, - &dev_attr_in1_input.attr, - NULL, -}; - -static struct attribute_group ads7846_attr_group = { - .attrs = ads7846_attributes, -}; +static umode_t ads7846_is_visible(struct kobject *kobj, struct attribute *attr, + int index) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct ads7846 *ts = dev_get_drvdata(dev); -static struct attribute *ads7843_attributes[] = { - &dev_attr_in0_input.attr, - &dev_attr_in1_input.attr, - NULL, -}; + if (ts->model == 7843 && index < 2) /* in0, in1 */ + return 0; + if (ts->model == 7845 && index != 2) /* in0 */ + return 0; -static struct attribute_group ads7843_attr_group = { - .attrs = ads7843_attributes, -}; + return attr->mode; +} -static struct attribute *ads7845_attributes[] = { - &dev_attr_in0_input.attr, +static struct attribute *ads7846_attributes[] = { + &dev_attr_temp0.attr, /* 0 */ + &dev_attr_temp1.attr, /* 1 */ + &dev_attr_in0_input.attr, /* 2 */ + &dev_attr_in1_input.attr, /* 3 */ NULL, }; -static struct attribute_group ads7845_attr_group = { - .attrs = ads7845_attributes, +static struct attribute_group ads7846_attr_group = { + .attrs = ads7846_attributes, + .is_visible = ads7846_is_visible, }; +__ATTRIBUTE_GROUPS(ads7846_attr); static int ads784x_hwmon_register(struct spi_device *spi, struct ads7846 *ts) { - struct device *hwmon; - int err; - /* hwmon sensors need a reference voltage */ switch (ts->model) { case 7846: @@ -535,43 +527,19 @@ static int ads784x_hwmon_register(struct spi_device *spi, struct ads7846 *ts) break; } - /* different chips have different sensor groups */ - switch (ts->model) { - case 7846: - ts->attr_group = &ads7846_attr_group; - break; - case 7845: - ts->attr_group = &ads7845_attr_group; - break; - case 7843: - ts->attr_group = &ads7843_attr_group; - break; - default: - dev_dbg(&spi->dev, "ADS%d not recognized\n", ts->model); - return 0; - } - - err = sysfs_create_group(&spi->dev.kobj, ts->attr_group); - if (err) - return err; - - hwmon = hwmon_device_register(&spi->dev); - if (IS_ERR(hwmon)) { - sysfs_remove_group(&spi->dev.kobj, ts->attr_group); - return PTR_ERR(hwmon); - } + ts->hwmon = hwmon_device_register_with_groups(&spi->dev, spi->modalias, + ts, ads7846_attr_groups); + if (IS_ERR(ts->hwmon)) + return PTR_ERR(ts->hwmon); - ts->hwmon = hwmon; return 0; } static void ads784x_hwmon_unregister(struct spi_device *spi, struct ads7846 *ts) { - if (ts->hwmon) { - sysfs_remove_group(&spi->dev.kobj, ts->attr_group); + if (ts->hwmon) hwmon_device_unregister(ts->hwmon); - } } #else diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 59aa24002c7b..a70400754e92 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -12,7 +12,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/delay.h> #include <linux/firmware.h> #include <linux/i2c.h> @@ -1130,7 +1129,7 @@ static void mxt_input_close(struct input_dev *dev) static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct mxt_platform_data *pdata = client->dev.platform_data; + const struct mxt_platform_data *pdata = dev_get_platdata(&client->dev); struct mxt_data *data; struct input_dev *input_dev; int error; diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index bddabc595077..a7c9d6967d1e 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c @@ -12,7 +12,6 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#include <linux/init.h> #include <linux/err.h> #include <linux/kernel.h> #include <linux/module.h> @@ -182,7 +181,7 @@ static int atmel_tsadcc_probe(struct platform_device *pdev) struct atmel_tsadcc *ts_dev; struct input_dev *input_dev; struct resource *res; - struct at91_tsadcc_data *pdata = pdev->dev.platform_data; + struct at91_tsadcc_data *pdata = dev_get_platdata(&pdev->dev); int err; unsigned int prsc; unsigned int reg; diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c index 8c651985a5c4..5bf1aeeea825 100644 --- a/drivers/input/touchscreen/cy8ctmg110_ts.c +++ b/drivers/input/touchscreen/cy8ctmg110_ts.c @@ -178,7 +178,7 @@ static irqreturn_t cy8ctmg110_irq_thread(int irq, void *dev_id) static int cy8ctmg110_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct cy8ctmg110_pdata *pdata = client->dev.platform_data; + const struct cy8ctmg110_pdata *pdata = dev_get_platdata(&client->dev); struct cy8ctmg110 *ts; struct input_dev *input_dev; int err; diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c index 4204841cdc49..eee656f77a2e 100644 --- a/drivers/input/touchscreen/cyttsp_core.c +++ b/drivers/input/touchscreen/cyttsp_core.c @@ -534,7 +534,7 @@ static void cyttsp_close(struct input_dev *dev) struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, struct device *dev, int irq, size_t xfer_buf_size) { - const struct cyttsp_platform_data *pdata = dev->platform_data; + const struct cyttsp_platform_data *pdata = dev_get_platdata(dev); struct cyttsp *ts; struct input_dev *input_dev; int error; @@ -553,7 +553,7 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, ts->dev = dev; ts->input = input_dev; - ts->pdata = dev->platform_data; + ts->pdata = dev_get_platdata(dev); ts->bus_ops = bus_ops; ts->irq = irq; diff --git a/drivers/input/touchscreen/cyttsp_i2c_common.c b/drivers/input/touchscreen/cyttsp_i2c_common.c index 1d7b6f154168..ccefa56ca212 100644 --- a/drivers/input/touchscreen/cyttsp_i2c_common.c +++ b/drivers/input/touchscreen/cyttsp_i2c_common.c @@ -31,6 +31,8 @@ #include <linux/module.h> #include <linux/types.h> +#include "cyttsp4_core.h" + int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u16 addr, u8 length, void *values) { diff --git a/drivers/input/touchscreen/da9034-ts.c b/drivers/input/touchscreen/da9034-ts.c index 34ad84105e6e..8ccf7bb4028a 100644 --- a/drivers/input/touchscreen/da9034-ts.c +++ b/drivers/input/touchscreen/da9034-ts.c @@ -13,7 +13,6 @@ #include <linux/module.h> #include <linux/kernel.h> -#include <linux/init.h> #include <linux/delay.h> #include <linux/platform_device.h> #include <linux/input.h> @@ -299,7 +298,7 @@ static void da9034_touch_close(struct input_dev *dev) static int da9034_touch_probe(struct platform_device *pdev) { - struct da9034_touch_pdata *pdata = pdev->dev.platform_data; + struct da9034_touch_pdata *pdata = dev_get_platdata(&pdev->dev); struct da9034_touch *touch; struct input_dev *input_dev; int ret; diff --git a/drivers/input/touchscreen/dynapro.c b/drivers/input/touchscreen/dynapro.c index 1809677a6513..86237a910876 100644 --- a/drivers/input/touchscreen/dynapro.c +++ b/drivers/input/touchscreen/dynapro.c @@ -24,7 +24,6 @@ #include <linux/slab.h> #include <linux/input.h> #include <linux/serio.h> -#include <linux/init.h> #define DRIVER_DESC "Dynapro serial touchscreen driver" diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 83fa1b15a97f..412a85ec9ba5 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -623,8 +623,9 @@ static int edt_ft5x06_ts_reset(struct i2c_client *client, if (gpio_is_valid(reset_pin)) { /* this pulls reset down, enabling the low active reset */ - error = gpio_request_one(reset_pin, GPIOF_OUT_INIT_LOW, - "edt-ft5x06 reset"); + error = devm_gpio_request_one(&client->dev, reset_pin, + GPIOF_OUT_INIT_LOW, + "edt-ft5x06 reset"); if (error) { dev_err(&client->dev, "Failed to request GPIO %d as reset pin, error %d\n", @@ -705,7 +706,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { const struct edt_ft5x06_platform_data *pdata = - client->dev.platform_data; + dev_get_platdata(&client->dev); struct edt_ft5x06_ts_data *tsdata; struct input_dev *input; int error; @@ -723,8 +724,8 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, return error; if (gpio_is_valid(pdata->irq_pin)) { - error = gpio_request_one(pdata->irq_pin, - GPIOF_IN, "edt-ft5x06 irq"); + error = devm_gpio_request_one(&client->dev, pdata->irq_pin, + GPIOF_IN, "edt-ft5x06 irq"); if (error) { dev_err(&client->dev, "Failed to request GPIO %d, error %d\n", @@ -733,12 +734,16 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, } } - tsdata = kzalloc(sizeof(*tsdata), GFP_KERNEL); - input = input_allocate_device(); - if (!tsdata || !input) { + tsdata = devm_kzalloc(&client->dev, sizeof(*tsdata), GFP_KERNEL); + if (!tsdata) { dev_err(&client->dev, "failed to allocate driver data.\n"); - error = -ENOMEM; - goto err_free_mem; + return -ENOMEM; + } + + input = devm_input_allocate_device(&client->dev); + if (!input) { + dev_err(&client->dev, "failed to allocate input device.\n"); + return -ENOMEM; } mutex_init(&tsdata->mutex); @@ -749,7 +754,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, error = edt_ft5x06_ts_identify(client, tsdata->name, fw_version); if (error) { dev_err(&client->dev, "touchscreen probe failed\n"); - goto err_free_mem; + return error; } edt_ft5x06_ts_get_defaults(tsdata, pdata); @@ -776,27 +781,30 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, error = input_mt_init_slots(input, MAX_SUPPORT_POINTS, 0); if (error) { dev_err(&client->dev, "Unable to init MT slots.\n"); - goto err_free_mem; + return error; } input_set_drvdata(input, tsdata); i2c_set_clientdata(client, tsdata); - error = request_threaded_irq(client->irq, NULL, edt_ft5x06_ts_isr, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - client->name, tsdata); + error = devm_request_threaded_irq(&client->dev, client->irq, + NULL, edt_ft5x06_ts_isr, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + client->name, tsdata); if (error) { dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); - goto err_free_mem; + return error; } error = sysfs_create_group(&client->dev.kobj, &edt_ft5x06_attr_group); if (error) - goto err_free_irq; + return error; error = input_register_device(input); - if (error) - goto err_remove_attrs; + if (error) { + sysfs_remove_group(&client->dev.kobj, &edt_ft5x06_attr_group); + return error; + } edt_ft5x06_ts_prepare_debugfs(tsdata, dev_driver_string(&client->dev)); device_init_wakeup(&client->dev, 1); @@ -806,40 +814,15 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, pdata->irq_pin, pdata->reset_pin); return 0; - -err_remove_attrs: - sysfs_remove_group(&client->dev.kobj, &edt_ft5x06_attr_group); -err_free_irq: - free_irq(client->irq, tsdata); -err_free_mem: - input_free_device(input); - kfree(tsdata); - - if (gpio_is_valid(pdata->irq_pin)) - gpio_free(pdata->irq_pin); - - return error; } static int edt_ft5x06_ts_remove(struct i2c_client *client) { - const struct edt_ft5x06_platform_data *pdata = - dev_get_platdata(&client->dev); struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client); edt_ft5x06_ts_teardown_debugfs(tsdata); sysfs_remove_group(&client->dev.kobj, &edt_ft5x06_attr_group); - free_irq(client->irq, tsdata); - input_unregister_device(tsdata->input); - - if (gpio_is_valid(pdata->irq_pin)) - gpio_free(pdata->irq_pin); - if (gpio_is_valid(pdata->reset_pin)) - gpio_free(pdata->reset_pin); - - kfree(tsdata); - return 0; } diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 1ce3d29ffca5..b1884ddd7a84 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c @@ -157,7 +157,7 @@ static void eeti_ts_close(struct input_dev *dev) static int eeti_ts_probe(struct i2c_client *client, const struct i2c_device_id *idp) { - struct eeti_ts_platform_data *pdata = client->dev.platform_data; + struct eeti_ts_platform_data *pdata = dev_get_platdata(&client->dev); struct eeti_ts_priv *priv; struct input_dev *input; unsigned int irq_flags; diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c index 054d22583248..e6bcb13680b2 100644 --- a/drivers/input/touchscreen/egalax_ts.c +++ b/drivers/input/touchscreen/egalax_ts.c @@ -18,7 +18,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/i2c.h> #include <linux/interrupt.h> #include <linux/input.h> diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c index 957423d1471d..8051a4b704ea 100644 --- a/drivers/input/touchscreen/elo.c +++ b/drivers/input/touchscreen/elo.c @@ -22,7 +22,6 @@ #include <linux/slab.h> #include <linux/input.h> #include <linux/serio.h> -#include <linux/init.h> #include <linux/ctype.h> #define DRIVER_DESC "Elo serial touchscreen driver" diff --git a/drivers/input/touchscreen/fujitsu_ts.c b/drivers/input/touchscreen/fujitsu_ts.c index 10794ddbdf58..d0e46a7e183b 100644 --- a/drivers/input/touchscreen/fujitsu_ts.c +++ b/drivers/input/touchscreen/fujitsu_ts.c @@ -16,7 +16,6 @@ #include <linux/slab.h> #include <linux/input.h> #include <linux/serio.h> -#include <linux/init.h> #define DRIVER_DESC "Fujitsu serial touchscreen driver" diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c index 41c71766bf18..e2ee62615273 100644 --- a/drivers/input/touchscreen/gunze.c +++ b/drivers/input/touchscreen/gunze.c @@ -32,7 +32,6 @@ #include <linux/slab.h> #include <linux/input.h> #include <linux/serio.h> -#include <linux/init.h> #define DRIVER_DESC "Gunze AHL-51S touchscreen driver" diff --git a/drivers/input/touchscreen/hampshire.c b/drivers/input/touchscreen/hampshire.c index 0cc47ea98acf..ecb1e0e01328 100644 --- a/drivers/input/touchscreen/hampshire.c +++ b/drivers/input/touchscreen/hampshire.c @@ -23,7 +23,6 @@ #include <linux/slab.h> #include <linux/input.h> #include <linux/serio.h> -#include <linux/init.h> #define DRIVER_DESC "Hampshire serial touchscreen driver" diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c index 1418bdda61bb..2a5089139818 100644 --- a/drivers/input/touchscreen/ili210x.c +++ b/drivers/input/touchscreen/ili210x.c @@ -184,7 +184,7 @@ static int ili210x_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct device *dev = &client->dev; - const struct ili210x_platform_data *pdata = dev->platform_data; + const struct ili210x_platform_data *pdata = dev_get_platdata(dev); struct ili210x *priv; struct input_dev *input; struct panel_info panel; diff --git a/drivers/input/touchscreen/inexio.c b/drivers/input/touchscreen/inexio.c index a29c99c32245..adb80b65a259 100644 --- a/drivers/input/touchscreen/inexio.c +++ b/drivers/input/touchscreen/inexio.c @@ -23,7 +23,6 @@ #include <linux/slab.h> #include <linux/input.h> #include <linux/serio.h> -#include <linux/init.h> #define DRIVER_DESC "iNexio serial touchscreen driver" diff --git a/drivers/input/touchscreen/intel-mid-touch.c b/drivers/input/touchscreen/intel-mid-touch.c index e30d837dae2f..4f6b156144e9 100644 --- a/drivers/input/touchscreen/intel-mid-touch.c +++ b/drivers/input/touchscreen/intel-mid-touch.c @@ -27,7 +27,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/input.h> #include <linux/interrupt.h> #include <linux/err.h> diff --git a/drivers/input/touchscreen/jornada720_ts.c b/drivers/input/touchscreen/jornada720_ts.c index e463a79ffecc..7324c5c0fb86 100644 --- a/drivers/input/touchscreen/jornada720_ts.c +++ b/drivers/input/touchscreen/jornada720_ts.c @@ -14,7 +14,6 @@ */ #include <linux/platform_device.h> -#include <linux/init.h> #include <linux/input.h> #include <linux/interrupt.h> #include <linux/module.h> diff --git a/drivers/input/touchscreen/lpc32xx_ts.c b/drivers/input/touchscreen/lpc32xx_ts.c index 9101ee529c92..2058253b55d9 100644 --- a/drivers/input/touchscreen/lpc32xx_ts.c +++ b/drivers/input/touchscreen/lpc32xx_ts.c @@ -15,7 +15,6 @@ */ #include <linux/platform_device.h> -#include <linux/init.h> #include <linux/input.h> #include <linux/interrupt.h> #include <linux/module.h> diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c index 7d2b2136e5ad..0786010d7ed0 100644 --- a/drivers/input/touchscreen/mainstone-wm97xx.c +++ b/drivers/input/touchscreen/mainstone-wm97xx.c @@ -25,7 +25,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h> -#include <linux/init.h> #include <linux/delay.h> #include <linux/irq.h> #include <linux/interrupt.h> diff --git a/drivers/input/touchscreen/max11801_ts.c b/drivers/input/touchscreen/max11801_ts.c index 9f84fcd08732..a68ec142ee9a 100644 --- a/drivers/input/touchscreen/max11801_ts.c +++ b/drivers/input/touchscreen/max11801_ts.c @@ -33,7 +33,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/i2c.h> #include <linux/interrupt.h> #include <linux/input.h> diff --git a/drivers/input/touchscreen/mcs5000_ts.c b/drivers/input/touchscreen/mcs5000_ts.c index f9f4e0c56eda..647e36f5930e 100644 --- a/drivers/input/touchscreen/mcs5000_ts.c +++ b/drivers/input/touchscreen/mcs5000_ts.c @@ -14,7 +14,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/i2c.h> #include <linux/i2c/mcs.h> #include <linux/interrupt.h> @@ -194,7 +193,7 @@ static int mcs5000_ts_probe(struct i2c_client *client, struct input_dev *input_dev; int ret; - if (!client->dev.platform_data) + if (!dev_get_platdata(&client->dev)) return -EINVAL; data = kzalloc(sizeof(struct mcs5000_ts_data), GFP_KERNEL); @@ -207,7 +206,7 @@ static int mcs5000_ts_probe(struct i2c_client *client, data->client = client; data->input_dev = input_dev; - data->platform_data = client->dev.platform_data; + data->platform_data = dev_get_platdata(&client->dev); input_dev->name = "MELPAS MCS-5000 Touchscreen"; input_dev->id.bustype = BUS_I2C; diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c index 1443532fe6c4..8a598c065391 100644 --- a/drivers/input/touchscreen/mms114.c +++ b/drivers/input/touchscreen/mms114.c @@ -8,7 +8,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/delay.h> #include <linux/of.h> #include <linux/i2c.h> diff --git a/drivers/input/touchscreen/mtouch.c b/drivers/input/touchscreen/mtouch.c index eb66b7c37c2f..9b5552a26169 100644 --- a/drivers/input/touchscreen/mtouch.c +++ b/drivers/input/touchscreen/mtouch.c @@ -21,7 +21,6 @@ #include <linux/slab.h> #include <linux/input.h> #include <linux/serio.h> -#include <linux/init.h> #define DRIVER_DESC "MicroTouch serial touchscreen driver" diff --git a/drivers/input/touchscreen/pcap_ts.c b/drivers/input/touchscreen/pcap_ts.c index f22e04dd4e16..cff2376817e5 100644 --- a/drivers/input/touchscreen/pcap_ts.c +++ b/drivers/input/touchscreen/pcap_ts.c @@ -11,7 +11,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/fs.h> #include <linux/string.h> #include <linux/slab.h> diff --git a/drivers/input/touchscreen/penmount.c b/drivers/input/touchscreen/penmount.c index b49f0b836925..417d87379265 100644 --- a/drivers/input/touchscreen/penmount.c +++ b/drivers/input/touchscreen/penmount.c @@ -21,7 +21,6 @@ #include <linux/input.h> #include <linux/input/mt.h> #include <linux/serio.h> -#include <linux/init.h> #define DRIVER_DESC "PenMount serial touchscreen driver" diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index 6cc6b36663ff..02392d2061d6 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c @@ -128,7 +128,8 @@ static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops, static int pixcir_i2c_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct pixcir_ts_platform_data *pdata = client->dev.platform_data; + const struct pixcir_ts_platform_data *pdata = + dev_get_platdata(&client->dev); struct pixcir_i2c_ts_data *tsdata; struct input_dev *input; int error; diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c index b061af2c8376..19cb247dbb86 100644 --- a/drivers/input/touchscreen/s3c2410_ts.c +++ b/drivers/input/touchscreen/s3c2410_ts.c @@ -28,7 +28,6 @@ #include <linux/module.h> #include <linux/gpio.h> #include <linux/input.h> -#include <linux/init.h> #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/platform_device.h> @@ -251,7 +250,7 @@ static int s3c2410ts_probe(struct platform_device *pdev) ts.dev = dev; - info = pdev->dev.platform_data; + info = dev_get_platdata(&pdev->dev); if (!info) { dev_err(dev, "no platform data, cannot attach\n"); return -EINVAL; @@ -392,7 +391,7 @@ static int s3c2410ts_suspend(struct device *dev) static int s3c2410ts_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); - struct s3c2410_ts_mach_info *info = pdev->dev.platform_data; + struct s3c2410_ts_mach_info *info = dev_get_platdata(&pdev->dev); clk_enable(ts.clock); enable_irq(ts.irq_tc); diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index 2f03b2f289dd..5c342b3139e8 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c @@ -154,7 +154,7 @@ static int st1232_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct st1232_ts_data *ts; - struct st1232_pdata *pdata = client->dev.platform_data; + struct st1232_pdata *pdata = dev_get_platdata(&client->dev); struct input_dev *input_dev; int error; diff --git a/drivers/input/touchscreen/stmpe-ts.c b/drivers/input/touchscreen/stmpe-ts.c index 59e81b00f244..42ce31afa259 100644 --- a/drivers/input/touchscreen/stmpe-ts.c +++ b/drivers/input/touchscreen/stmpe-ts.c @@ -15,7 +15,6 @@ #include <linux/module.h> #include <linux/sched.h> #include <linux/interrupt.h> -#include <linux/init.h> #include <linux/device.h> #include <linux/of.h> #include <linux/platform_device.h> diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 68beadaabceb..6c9cd1268dc3 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -14,7 +14,6 @@ */ -#include <linux/init.h> #include <linux/kernel.h> #include <linux/err.h> #include <linux/module.h> diff --git a/drivers/input/touchscreen/touchit213.c b/drivers/input/touchscreen/touchit213.c index 5f29e5b8e1c1..c27cf8f3d1ca 100644 --- a/drivers/input/touchscreen/touchit213.c +++ b/drivers/input/touchscreen/touchit213.c @@ -21,7 +21,6 @@ #include <linux/slab.h> #include <linux/input.h> #include <linux/serio.h> -#include <linux/init.h> #define DRIVER_DESC "Sahara TouchIT-213 serial touchscreen driver" diff --git a/drivers/input/touchscreen/touchright.c b/drivers/input/touchscreen/touchright.c index 8a2887daf194..4000e5205407 100644 --- a/drivers/input/touchscreen/touchright.c +++ b/drivers/input/touchscreen/touchright.c @@ -20,7 +20,6 @@ #include <linux/slab.h> #include <linux/input.h> #include <linux/serio.h> -#include <linux/init.h> #define DRIVER_DESC "Touchright serial touchscreen driver" diff --git a/drivers/input/touchscreen/touchwin.c b/drivers/input/touchscreen/touchwin.c index 588cdcb839dd..ba90f447df75 100644 --- a/drivers/input/touchscreen/touchwin.c +++ b/drivers/input/touchscreen/touchwin.c @@ -27,7 +27,6 @@ #include <linux/slab.h> #include <linux/input.h> #include <linux/serio.h> -#include <linux/init.h> #define DRIVER_DESC "Touchwindow serial touchscreen driver" diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index 811353353917..550adcbbfc23 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c @@ -571,7 +571,7 @@ static void tsc2005_setup_spi_xfer(struct tsc2005 *ts) static int tsc2005_probe(struct spi_device *spi) { - const struct tsc2005_platform_data *pdata = spi->dev.platform_data; + const struct tsc2005_platform_data *pdata = dev_get_platdata(&spi->dev); struct tsc2005 *ts; struct input_dev *input_dev; unsigned int max_x, max_y, max_p; diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index 0b67ba476b4c..1bf9906b5a3f 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c @@ -26,6 +26,9 @@ #include <linux/interrupt.h> #include <linux/i2c.h> #include <linux/i2c/tsc2007.h> +#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/of_gpio.h> #define TSC2007_MEASURE_TEMP0 (0x0 << 4) #define TSC2007_MEASURE_AUX (0x2 << 4) @@ -72,15 +75,18 @@ struct tsc2007 { u16 model; u16 x_plate_ohms; u16 max_rt; - unsigned long poll_delay; unsigned long poll_period; + int fuzzx; + int fuzzy; + int fuzzz; + unsigned gpio; int irq; wait_queue_head_t wait; bool stopped; - int (*get_pendown_state)(void); + int (*get_pendown_state)(struct device *); void (*clear_penirq)(void); }; @@ -161,7 +167,7 @@ static bool tsc2007_is_pen_down(struct tsc2007 *ts) if (!ts->get_pendown_state) return true; - return ts->get_pendown_state(); + return ts->get_pendown_state(&ts->client->dev); } static irqreturn_t tsc2007_soft_irq(int irq, void *handle) @@ -178,7 +184,7 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle) rt = tsc2007_calculate_pressure(ts, &tc); - if (rt == 0 && !ts->get_pendown_state) { + if (!rt && !ts->get_pendown_state) { /* * If pressure reported is 0 and we don't have * callback to check pendown state, we have to @@ -228,7 +234,7 @@ static irqreturn_t tsc2007_hard_irq(int irq, void *handle) { struct tsc2007 *ts = handle; - if (!ts->get_pendown_state || likely(ts->get_pendown_state())) + if (tsc2007_is_pen_down(ts)) return IRQ_WAKE_THREAD; if (ts->clear_penirq) @@ -273,49 +279,134 @@ static void tsc2007_close(struct input_dev *input_dev) tsc2007_stop(ts); } -static int tsc2007_probe(struct i2c_client *client, - const struct i2c_device_id *id) +#ifdef CONFIG_OF +static int tsc2007_get_pendown_state_gpio(struct device *dev) { - struct tsc2007 *ts; - struct tsc2007_platform_data *pdata = client->dev.platform_data; - struct input_dev *input_dev; - int err; + struct i2c_client *client = to_i2c_client(dev); + struct tsc2007 *ts = i2c_get_clientdata(client); + + return !gpio_get_value(ts->gpio); +} + +static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts) +{ + struct device_node *np = client->dev.of_node; + u32 val32; + u64 val64; - if (!pdata) { - dev_err(&client->dev, "platform data is required!\n"); + if (!np) { + dev_err(&client->dev, "missing device tree data\n"); return -EINVAL; } - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_WORD_DATA)) - return -EIO; + if (!of_property_read_u32(np, "ti,max-rt", &val32)) + ts->max_rt = val32; + else + ts->max_rt = MAX_12BIT; + + if (!of_property_read_u32(np, "ti,fuzzx", &val32)) + ts->fuzzx = val32; + + if (!of_property_read_u32(np, "ti,fuzzy", &val32)) + ts->fuzzy = val32; + + if (!of_property_read_u32(np, "ti,fuzzz", &val32)) + ts->fuzzz = val32; + + if (!of_property_read_u64(np, "ti,poll-period", &val64)) + ts->poll_period = val64; + else + ts->poll_period = 1; - ts = kzalloc(sizeof(struct tsc2007), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ts || !input_dev) { - err = -ENOMEM; - goto err_free_mem; + if (!of_property_read_u32(np, "ti,x-plate-ohms", &val32)) { + ts->x_plate_ohms = val32; + } else { + dev_err(&client->dev, "missing ti,x-plate-ohms devicetree property."); + return -EINVAL; } - ts->client = client; - ts->irq = client->irq; - ts->input = input_dev; - init_waitqueue_head(&ts->wait); + ts->gpio = of_get_gpio(np, 0); + if (gpio_is_valid(ts->gpio)) + ts->get_pendown_state = tsc2007_get_pendown_state_gpio; + else + dev_warn(&client->dev, + "GPIO not specified in DT (of_get_gpio returned %d)\n", + ts->gpio); + + return 0; +} +#else +static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts) +{ + dev_err(&client->dev, "platform data is required!\n"); + return -EINVAL; +} +#endif +static int tsc2007_probe_pdev(struct i2c_client *client, struct tsc2007 *ts, + const struct tsc2007_platform_data *pdata, + const struct i2c_device_id *id) +{ ts->model = pdata->model; ts->x_plate_ohms = pdata->x_plate_ohms; ts->max_rt = pdata->max_rt ? : MAX_12BIT; - ts->poll_delay = pdata->poll_delay ? : 1; ts->poll_period = pdata->poll_period ? : 1; ts->get_pendown_state = pdata->get_pendown_state; ts->clear_penirq = pdata->clear_penirq; + ts->fuzzx = pdata->fuzzx; + ts->fuzzy = pdata->fuzzy; + ts->fuzzz = pdata->fuzzz; if (pdata->x_plate_ohms == 0) { dev_err(&client->dev, "x_plate_ohms is not set up in platform data"); - err = -EINVAL; - goto err_free_mem; + return -EINVAL; } + return 0; +} + +static void tsc2007_call_exit_platform_hw(void *data) +{ + struct device *dev = data; + const struct tsc2007_platform_data *pdata = dev_get_platdata(dev); + + pdata->exit_platform_hw(); +} + +static int tsc2007_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + const struct tsc2007_platform_data *pdata = dev_get_platdata(&client->dev); + struct tsc2007 *ts; + struct input_dev *input_dev; + int err; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_WORD_DATA)) + return -EIO; + + ts = devm_kzalloc(&client->dev, sizeof(struct tsc2007), GFP_KERNEL); + if (!ts) + return -ENOMEM; + + if (pdata) + err = tsc2007_probe_pdev(client, ts, pdata, id); + else + err = tsc2007_probe_dt(client, ts); + if (err) + return err; + + input_dev = devm_input_allocate_device(&client->dev); + if (!input_dev) + return -ENOMEM; + + i2c_set_clientdata(client, ts); + + ts->client = client; + ts->irq = client->irq; + ts->input = input_dev; + init_waitqueue_head(&ts->wait); + snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&client->dev)); @@ -331,53 +422,46 @@ static int tsc2007_probe(struct i2c_client *client, input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); - input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, pdata->fuzzx, 0); - input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, pdata->fuzzy, 0); + input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, ts->fuzzx, 0); + input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, ts->fuzzy, 0); input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, - pdata->fuzzz, 0); + ts->fuzzz, 0); + + if (pdata) { + if (pdata->exit_platform_hw) { + err = devm_add_action(&client->dev, + tsc2007_call_exit_platform_hw, + &client->dev); + if (err) { + dev_err(&client->dev, + "Failed to register exit_platform_hw action, %d\n", + err); + return err; + } + } - if (pdata->init_platform_hw) - pdata->init_platform_hw(); + if (pdata->init_platform_hw) + pdata->init_platform_hw(); + } - err = request_threaded_irq(ts->irq, tsc2007_hard_irq, tsc2007_soft_irq, - IRQF_ONESHOT, client->dev.driver->name, ts); - if (err < 0) { - dev_err(&client->dev, "irq %d busy?\n", ts->irq); - goto err_free_mem; + err = devm_request_threaded_irq(&client->dev, ts->irq, + tsc2007_hard_irq, tsc2007_soft_irq, + IRQF_ONESHOT, + client->dev.driver->name, ts); + if (err) { + dev_err(&client->dev, "Failed to request irq %d: %d\n", + ts->irq, err); + return err; } tsc2007_stop(ts); err = input_register_device(input_dev); - if (err) - goto err_free_irq; - - i2c_set_clientdata(client, ts); - - return 0; - - err_free_irq: - free_irq(ts->irq, ts); - if (pdata->exit_platform_hw) - pdata->exit_platform_hw(); - err_free_mem: - input_free_device(input_dev); - kfree(ts); - return err; -} - -static int tsc2007_remove(struct i2c_client *client) -{ - struct tsc2007 *ts = i2c_get_clientdata(client); - struct tsc2007_platform_data *pdata = client->dev.platform_data; - - free_irq(ts->irq, ts); - - if (pdata->exit_platform_hw) - pdata->exit_platform_hw(); - - input_unregister_device(ts->input); - kfree(ts); + if (err) { + dev_err(&client->dev, + "Failed to register input device: %d\n", err); + return err; + } return 0; } @@ -389,14 +473,22 @@ static const struct i2c_device_id tsc2007_idtable[] = { MODULE_DEVICE_TABLE(i2c, tsc2007_idtable); +#ifdef CONFIG_OF +static const struct of_device_id tsc2007_of_match[] = { + { .compatible = "ti,tsc2007" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, tsc2007_of_match); +#endif + static struct i2c_driver tsc2007_driver = { .driver = { .owner = THIS_MODULE, - .name = "tsc2007" + .name = "tsc2007", + .of_match_table = of_match_ptr(tsc2007_of_match), }, .id_table = tsc2007_idtable, .probe = tsc2007_probe, - .remove = tsc2007_remove, }; module_i2c_driver(tsc2007_driver); diff --git a/drivers/input/touchscreen/tsc40.c b/drivers/input/touchscreen/tsc40.c index eb96f168fb9d..29687872cb94 100644 --- a/drivers/input/touchscreen/tsc40.c +++ b/drivers/input/touchscreen/tsc40.c @@ -11,7 +11,6 @@ #include <linux/slab.h> #include <linux/input.h> #include <linux/serio.h> -#include <linux/init.h> #define PACKET_LENGTH 5 struct tsc_ser { diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index 1271f97b4079..b46c55cd1bbb 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c @@ -19,7 +19,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/delay.h> #include <linux/sched.h> #include <linux/wait.h> @@ -320,7 +319,7 @@ static int ucb1400_ts_detect_irq(struct ucb1400_ts *ucb, static int ucb1400_ts_probe(struct platform_device *pdev) { - struct ucb1400_ts *ucb = pdev->dev.platform_data; + struct ucb1400_ts *ucb = dev_get_platdata(&pdev->dev); int error, x_res, y_res; u16 fcsr; @@ -399,7 +398,7 @@ err: static int ucb1400_ts_remove(struct platform_device *pdev) { - struct ucb1400_ts *ucb = pdev->dev.platform_data; + struct ucb1400_ts *ucb = dev_get_platdata(&pdev->dev); free_irq(ucb->irq, ucb); input_unregister_device(ucb->ts_idev); @@ -410,7 +409,7 @@ static int ucb1400_ts_remove(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP static int ucb1400_ts_suspend(struct device *dev) { - struct ucb1400_ts *ucb = dev->platform_data; + struct ucb1400_ts *ucb = dev_get_platdata(dev); struct input_dev *idev = ucb->ts_idev; mutex_lock(&idev->mutex); @@ -424,7 +423,7 @@ static int ucb1400_ts_suspend(struct device *dev) static int ucb1400_ts_resume(struct device *dev) { - struct ucb1400_ts *ucb = dev->platform_data; + struct ucb1400_ts *ucb = dev_get_platdata(dev); struct input_dev *idev = ucb->ts_idev; mutex_lock(&idev->mutex); diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 5f87bed05467..a0966331a89b 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c @@ -51,7 +51,6 @@ #include <linux/slab.h> #include <linux/input.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/usb.h> #include <linux/usb/input.h> #include <linux/hid.h> diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c index 9a83be6b6584..2792ca397dd0 100644 --- a/drivers/input/touchscreen/wacom_w8001.c +++ b/drivers/input/touchscreen/wacom_w8001.c @@ -18,7 +18,6 @@ #include <linux/slab.h> #include <linux/input/mt.h> #include <linux/serio.h> -#include <linux/init.h> #include <linux/ctype.h> #include <linux/delay.h> diff --git a/drivers/input/touchscreen/wm831x-ts.c b/drivers/input/touchscreen/wm831x-ts.c index 6be2eb6a153a..1b953a066b2c 100644 --- a/drivers/input/touchscreen/wm831x-ts.c +++ b/drivers/input/touchscreen/wm831x-ts.c @@ -13,7 +13,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h> -#include <linux/init.h> #include <linux/string.h> #include <linux/pm.h> #include <linux/input.h> diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c index 7e45c9f6e6b7..d0ef91fc87d1 100644 --- a/drivers/input/touchscreen/wm97xx-core.c +++ b/drivers/input/touchscreen/wm97xx-core.c @@ -584,7 +584,7 @@ static void wm97xx_ts_input_close(struct input_dev *idev) static int wm97xx_probe(struct device *dev) { struct wm97xx *wm; - struct wm97xx_pdata *pdata = dev->platform_data; + struct wm97xx_pdata *pdata = dev_get_platdata(dev); int ret = 0, id = 0; wm = kzalloc(sizeof(struct wm97xx), GFP_KERNEL); diff --git a/drivers/input/touchscreen/zforce_ts.c b/drivers/input/touchscreen/zforce_ts.c index aa127ba392a4..2175f3419002 100644 --- a/drivers/input/touchscreen/zforce_ts.c +++ b/drivers/input/touchscreen/zforce_ts.c @@ -279,7 +279,8 @@ static int zforce_start(struct zforce_ts *ts) goto error; } - if (zforce_setconfig(ts, SETCONFIG_DUALTOUCH)) { + ret = zforce_setconfig(ts, SETCONFIG_DUALTOUCH); + if (ret) { dev_err(&client->dev, "Unable to set config\n"); goto error; } diff --git a/drivers/input/touchscreen/zylonite-wm97xx.c b/drivers/input/touchscreen/zylonite-wm97xx.c index bf0869a7a78e..e2ccd683de6e 100644 --- a/drivers/input/touchscreen/zylonite-wm97xx.c +++ b/drivers/input/touchscreen/zylonite-wm97xx.c @@ -20,7 +20,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h> -#include <linux/init.h> #include <linux/delay.h> #include <linux/gpio.h> #include <linux/irq.h> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 1abfb5684ab7..e46a88700b68 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -392,7 +392,7 @@ struct arm_smmu_domain { struct arm_smmu_cfg root_cfg; phys_addr_t output_mask; - spinlock_t lock; + struct mutex lock; }; static DEFINE_SPINLOCK(arm_smmu_devices_lock); @@ -900,7 +900,7 @@ static int arm_smmu_domain_init(struct iommu_domain *domain) goto out_free_domain; smmu_domain->root_cfg.pgd = pgd; - spin_lock_init(&smmu_domain->lock); + mutex_init(&smmu_domain->lock); domain->priv = smmu_domain; return 0; @@ -1137,7 +1137,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) * Sanity check the domain. We don't currently support domains * that cross between different SMMU chains. */ - spin_lock(&smmu_domain->lock); + mutex_lock(&smmu_domain->lock); if (!smmu_domain->leaf_smmu) { /* Now that we have a master, we can finalise the domain */ ret = arm_smmu_init_domain_context(domain, dev); @@ -1152,7 +1152,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) dev_name(device_smmu->dev)); goto err_unlock; } - spin_unlock(&smmu_domain->lock); + mutex_unlock(&smmu_domain->lock); /* Looks ok, so add the device to the domain */ master = find_smmu_master(smmu_domain->leaf_smmu, dev->of_node); @@ -1162,7 +1162,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) return arm_smmu_domain_add_master(smmu_domain, master); err_unlock: - spin_unlock(&smmu_domain->lock); + mutex_unlock(&smmu_domain->lock); return ret; } @@ -1394,7 +1394,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain, if (paddr & ~output_mask) return -ERANGE; - spin_lock(&smmu_domain->lock); + mutex_lock(&smmu_domain->lock); pgd += pgd_index(iova); end = iova + size; do { @@ -1410,7 +1410,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain, } while (pgd++, iova != end); out_unlock: - spin_unlock(&smmu_domain->lock); + mutex_unlock(&smmu_domain->lock); /* Ensure new page tables are visible to the hardware walker */ if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK) @@ -1423,9 +1423,8 @@ static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, size_t size, int flags) { struct arm_smmu_domain *smmu_domain = domain->priv; - struct arm_smmu_device *smmu = smmu_domain->leaf_smmu; - if (!smmu_domain || !smmu) + if (!smmu_domain) return -ENODEV; /* Check for silent address truncation up the SMMU chain. */ @@ -1449,44 +1448,34 @@ static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, static phys_addr_t arm_smmu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova) { - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - pte_t *pte; + pgd_t *pgdp, pgd; + pud_t pud; + pmd_t pmd; + pte_t pte; struct arm_smmu_domain *smmu_domain = domain->priv; struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg; - struct arm_smmu_device *smmu = root_cfg->smmu; - spin_lock(&smmu_domain->lock); - pgd = root_cfg->pgd; - if (!pgd) - goto err_unlock; + pgdp = root_cfg->pgd; + if (!pgdp) + return 0; - pgd += pgd_index(iova); - if (pgd_none_or_clear_bad(pgd)) - goto err_unlock; + pgd = *(pgdp + pgd_index(iova)); + if (pgd_none(pgd)) + return 0; - pud = pud_offset(pgd, iova); - if (pud_none_or_clear_bad(pud)) - goto err_unlock; + pud = *pud_offset(&pgd, iova); + if (pud_none(pud)) + return 0; - pmd = pmd_offset(pud, iova); - if (pmd_none_or_clear_bad(pmd)) - goto err_unlock; + pmd = *pmd_offset(&pud, iova); + if (pmd_none(pmd)) + return 0; - pte = pmd_page_vaddr(*pmd) + pte_index(iova); + pte = *(pmd_page_vaddr(pmd) + pte_index(iova)); if (pte_none(pte)) - goto err_unlock; - - spin_unlock(&smmu_domain->lock); - return __pfn_to_phys(pte_pfn(*pte)) | (iova & ~PAGE_MASK); + return 0; -err_unlock: - spin_unlock(&smmu_domain->lock); - dev_warn(smmu->dev, - "invalid (corrupt?) page tables detected for iova 0x%llx\n", - (unsigned long long)iova); - return -EINVAL; + return __pfn_to_phys(pte_pfn(pte)) | (iova & ~PAGE_MASK); } static int arm_smmu_domain_has_cap(struct iommu_domain *domain, @@ -1863,6 +1852,7 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) dev_err(dev, "found only %d context interrupt(s) but %d required\n", smmu->num_context_irqs, smmu->num_context_banks); + err = -ENODEV; goto out_put_parent; } diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c index 173cbb20d104..54bdd923316f 100644 --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c @@ -1717,6 +1717,11 @@ static int __init dm_bufio_init(void) { __u64 mem; + dm_bufio_allocated_kmem_cache = 0; + dm_bufio_allocated_get_free_pages = 0; + dm_bufio_allocated_vmalloc = 0; + dm_bufio_current_allocated = 0; + memset(&dm_bufio_caches, 0, sizeof dm_bufio_caches); memset(&dm_bufio_cache_names, 0, sizeof dm_bufio_cache_names); diff --git a/drivers/md/dm-cache-policy-mq.c b/drivers/md/dm-cache-policy-mq.c index 416b7b752a6e..64780ad73bb0 100644 --- a/drivers/md/dm-cache-policy-mq.c +++ b/drivers/md/dm-cache-policy-mq.c @@ -730,15 +730,18 @@ static int pre_cache_entry_found(struct mq_policy *mq, struct entry *e, int r = 0; bool updated = updated_this_tick(mq, e); - requeue_and_update_tick(mq, e); - if ((!discarded_oblock && updated) || - !should_promote(mq, e, discarded_oblock, data_dir)) + !should_promote(mq, e, discarded_oblock, data_dir)) { + requeue_and_update_tick(mq, e); result->op = POLICY_MISS; - else if (!can_migrate) + + } else if (!can_migrate) r = -EWOULDBLOCK; - else + + else { + requeue_and_update_tick(mq, e); r = pre_cache_to_cache(mq, e, result); + } return r; } diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index 9efcf1059b99..1b1469ebe5cb 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c @@ -2755,7 +2755,7 @@ static int resize_cache_dev(struct cache *cache, dm_cblock_t new_size) { int r; - r = dm_cache_resize(cache->cmd, cache->cache_size); + r = dm_cache_resize(cache->cmd, new_size); if (r) { DMERR("could not resize cache metadata"); return r; diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c index 496d5f3646a5..2f91d6d4a2cc 100644 --- a/drivers/md/dm-delay.c +++ b/drivers/md/dm-delay.c @@ -20,6 +20,7 @@ struct delay_c { struct timer_list delay_timer; struct mutex timer_lock; + struct workqueue_struct *kdelayd_wq; struct work_struct flush_expired_bios; struct list_head delayed_bios; atomic_t may_delay; @@ -45,14 +46,13 @@ struct dm_delay_info { static DEFINE_MUTEX(delayed_bios_lock); -static struct workqueue_struct *kdelayd_wq; static struct kmem_cache *delayed_cache; static void handle_delayed_timer(unsigned long data) { struct delay_c *dc = (struct delay_c *)data; - queue_work(kdelayd_wq, &dc->flush_expired_bios); + queue_work(dc->kdelayd_wq, &dc->flush_expired_bios); } static void queue_timeout(struct delay_c *dc, unsigned long expires) @@ -191,6 +191,12 @@ out: goto bad_dev_write; } + dc->kdelayd_wq = alloc_workqueue("kdelayd", WQ_MEM_RECLAIM, 0); + if (!dc->kdelayd_wq) { + DMERR("Couldn't start kdelayd"); + goto bad_queue; + } + setup_timer(&dc->delay_timer, handle_delayed_timer, (unsigned long)dc); INIT_WORK(&dc->flush_expired_bios, flush_expired_bios); @@ -203,6 +209,8 @@ out: ti->private = dc; return 0; +bad_queue: + mempool_destroy(dc->delayed_pool); bad_dev_write: if (dc->dev_write) dm_put_device(ti, dc->dev_write); @@ -217,7 +225,7 @@ static void delay_dtr(struct dm_target *ti) { struct delay_c *dc = ti->private; - flush_workqueue(kdelayd_wq); + destroy_workqueue(dc->kdelayd_wq); dm_put_device(ti, dc->dev_read); @@ -350,12 +358,6 @@ static int __init dm_delay_init(void) { int r = -ENOMEM; - kdelayd_wq = alloc_workqueue("kdelayd", WQ_MEM_RECLAIM, 0); - if (!kdelayd_wq) { - DMERR("Couldn't start kdelayd"); - goto bad_queue; - } - delayed_cache = KMEM_CACHE(dm_delay_info, 0); if (!delayed_cache) { DMERR("Couldn't create delayed bio cache."); @@ -373,8 +375,6 @@ static int __init dm_delay_init(void) bad_register: kmem_cache_destroy(delayed_cache); bad_memcache: - destroy_workqueue(kdelayd_wq); -bad_queue: return r; } @@ -382,7 +382,6 @@ static void __exit dm_delay_exit(void) { dm_unregister_target(&delay_target); kmem_cache_destroy(delayed_cache); - destroy_workqueue(kdelayd_wq); } /* Module hooks */ diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index aec57d76db5d..944690bafd93 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -66,6 +66,18 @@ struct dm_snapshot { atomic_t pending_exceptions_count; + /* Protected by "lock" */ + sector_t exception_start_sequence; + + /* Protected by kcopyd single-threaded callback */ + sector_t exception_complete_sequence; + + /* + * A list of pending exceptions that completed out of order. + * Protected by kcopyd single-threaded callback. + */ + struct list_head out_of_order_list; + mempool_t *pending_pool; struct dm_exception_table pending; @@ -173,6 +185,14 @@ struct dm_snap_pending_exception { */ int started; + /* There was copying error. */ + int copy_error; + + /* A sequence number, it is used for in-order completion. */ + sector_t exception_sequence; + + struct list_head out_of_order_entry; + /* * For writing a complete chunk, bypassing the copy. */ @@ -1094,6 +1114,9 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) s->valid = 1; s->active = 0; atomic_set(&s->pending_exceptions_count, 0); + s->exception_start_sequence = 0; + s->exception_complete_sequence = 0; + INIT_LIST_HEAD(&s->out_of_order_list); init_rwsem(&s->lock); INIT_LIST_HEAD(&s->list); spin_lock_init(&s->pe_lock); @@ -1443,6 +1466,19 @@ static void commit_callback(void *context, int success) pending_complete(pe, success); } +static void complete_exception(struct dm_snap_pending_exception *pe) +{ + struct dm_snapshot *s = pe->snap; + + if (unlikely(pe->copy_error)) + pending_complete(pe, 0); + + else + /* Update the metadata if we are persistent */ + s->store->type->commit_exception(s->store, &pe->e, + commit_callback, pe); +} + /* * Called when the copy I/O has finished. kcopyd actually runs * this code so don't block. @@ -1452,13 +1488,32 @@ static void copy_callback(int read_err, unsigned long write_err, void *context) struct dm_snap_pending_exception *pe = context; struct dm_snapshot *s = pe->snap; - if (read_err || write_err) - pending_complete(pe, 0); + pe->copy_error = read_err || write_err; - else - /* Update the metadata if we are persistent */ - s->store->type->commit_exception(s->store, &pe->e, - commit_callback, pe); + if (pe->exception_sequence == s->exception_complete_sequence) { + s->exception_complete_sequence++; + complete_exception(pe); + + while (!list_empty(&s->out_of_order_list)) { + pe = list_entry(s->out_of_order_list.next, + struct dm_snap_pending_exception, out_of_order_entry); + if (pe->exception_sequence != s->exception_complete_sequence) + break; + s->exception_complete_sequence++; + list_del(&pe->out_of_order_entry); + complete_exception(pe); + } + } else { + struct list_head *lh; + struct dm_snap_pending_exception *pe2; + + list_for_each_prev(lh, &s->out_of_order_list) { + pe2 = list_entry(lh, struct dm_snap_pending_exception, out_of_order_entry); + if (pe2->exception_sequence < pe->exception_sequence) + break; + } + list_add(&pe->out_of_order_entry, lh); + } } /* @@ -1553,6 +1608,8 @@ __find_pending_exception(struct dm_snapshot *s, return NULL; } + pe->exception_sequence = s->exception_start_sequence++; + dm_insert_exception(&s->pending, &pe->e); return pe; @@ -2192,7 +2249,7 @@ static struct target_type origin_target = { static struct target_type snapshot_target = { .name = "snapshot", - .version = {1, 11, 1}, + .version = {1, 12, 0}, .module = THIS_MODULE, .ctr = snapshot_ctr, .dtr = snapshot_dtr, diff --git a/drivers/md/dm-stats.c b/drivers/md/dm-stats.c index 3d404c1371ed..28a90122a5a8 100644 --- a/drivers/md/dm-stats.c +++ b/drivers/md/dm-stats.c @@ -964,6 +964,7 @@ int dm_stats_message(struct mapped_device *md, unsigned argc, char **argv, int __init dm_statistics_init(void) { + shared_memory_amount = 0; dm_stat_need_rcu_barrier = 0; return 0; } diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 465f08ca62b1..3ba6a3859ce3 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -200,6 +200,11 @@ int dm_table_create(struct dm_table **result, fmode_t mode, num_targets = dm_round_up(num_targets, KEYS_PER_NODE); + if (!num_targets) { + kfree(t); + return -ENOMEM; + } + if (alloc_targets(t, num_targets)) { kfree(t); return -ENOMEM; diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c index 60bce435f4fa..8a30ad54bd46 100644 --- a/drivers/md/dm-thin-metadata.c +++ b/drivers/md/dm-thin-metadata.c @@ -1697,6 +1697,14 @@ void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd) up_write(&pmd->root_lock); } +void dm_pool_metadata_read_write(struct dm_pool_metadata *pmd) +{ + down_write(&pmd->root_lock); + pmd->read_only = false; + dm_bm_set_read_write(pmd->bm); + up_write(&pmd->root_lock); +} + int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd, dm_block_t threshold, dm_sm_threshold_fn fn, diff --git a/drivers/md/dm-thin-metadata.h b/drivers/md/dm-thin-metadata.h index 845ebbe589a9..7bcc0e1d6238 100644 --- a/drivers/md/dm-thin-metadata.h +++ b/drivers/md/dm-thin-metadata.h @@ -193,6 +193,7 @@ int dm_pool_resize_metadata_dev(struct dm_pool_metadata *pmd, dm_block_t new_siz * that nothing is changing. */ void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd); +void dm_pool_metadata_read_write(struct dm_pool_metadata *pmd); int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd, dm_block_t threshold, diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 2c0cf511ec23..ee29037ffc2e 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -640,7 +640,9 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m) */ r = dm_thin_insert_block(tc->td, m->virt_block, m->data_block); if (r) { - DMERR_LIMIT("dm_thin_insert_block() failed"); + DMERR_LIMIT("%s: dm_thin_insert_block() failed: error = %d", + dm_device_name(pool->pool_md), r); + set_pool_mode(pool, PM_READ_ONLY); cell_error(pool, m->cell); goto out; } @@ -881,32 +883,23 @@ static void schedule_zero(struct thin_c *tc, dm_block_t virt_block, } } -static int commit(struct pool *pool) -{ - int r; - - r = dm_pool_commit_metadata(pool->pmd); - if (r) - DMERR_LIMIT("%s: commit failed: error = %d", - dm_device_name(pool->pool_md), r); - - return r; -} - /* * A non-zero return indicates read_only or fail_io mode. * Many callers don't care about the return value. */ -static int commit_or_fallback(struct pool *pool) +static int commit(struct pool *pool) { int r; if (get_pool_mode(pool) != PM_WRITE) return -EINVAL; - r = commit(pool); - if (r) + r = dm_pool_commit_metadata(pool->pmd); + if (r) { + DMERR_LIMIT("%s: dm_pool_commit_metadata failed: error = %d", + dm_device_name(pool->pool_md), r); set_pool_mode(pool, PM_READ_ONLY); + } return r; } @@ -943,7 +936,9 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result) * Try to commit to see if that will free up some * more space. */ - (void) commit_or_fallback(pool); + r = commit(pool); + if (r) + return r; r = dm_pool_get_free_block_count(pool->pmd, &free_blocks); if (r) @@ -957,7 +952,7 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result) * table reload). */ if (!free_blocks) { - DMWARN("%s: no free space available.", + DMWARN("%s: no free data space available.", dm_device_name(pool->pool_md)); spin_lock_irqsave(&pool->lock, flags); pool->no_free_space = 1; @@ -967,8 +962,16 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result) } r = dm_pool_alloc_data_block(pool->pmd, result); - if (r) + if (r) { + if (r == -ENOSPC && + !dm_pool_get_free_metadata_block_count(pool->pmd, &free_blocks) && + !free_blocks) { + DMWARN("%s: no free metadata space available.", + dm_device_name(pool->pool_md)); + set_pool_mode(pool, PM_READ_ONLY); + } return r; + } return 0; } @@ -1349,7 +1352,7 @@ static void process_deferred_bios(struct pool *pool) if (bio_list_empty(&bios) && !need_commit_due_to_time(pool)) return; - if (commit_or_fallback(pool)) { + if (commit(pool)) { while ((bio = bio_list_pop(&bios))) bio_io_error(bio); return; @@ -1397,6 +1400,7 @@ static void set_pool_mode(struct pool *pool, enum pool_mode mode) case PM_FAIL: DMERR("%s: switching pool to failure mode", dm_device_name(pool->pool_md)); + dm_pool_metadata_read_only(pool->pmd); pool->process_bio = process_bio_fail; pool->process_discard = process_bio_fail; pool->process_prepared_mapping = process_prepared_mapping_fail; @@ -1421,6 +1425,7 @@ static void set_pool_mode(struct pool *pool, enum pool_mode mode) break; case PM_WRITE: + dm_pool_metadata_read_write(pool->pmd); pool->process_bio = process_bio; pool->process_discard = process_discard; pool->process_prepared_mapping = process_prepared_mapping; @@ -1637,12 +1642,19 @@ static int bind_control_target(struct pool *pool, struct dm_target *ti) struct pool_c *pt = ti->private; /* - * We want to make sure that degraded pools are never upgraded. + * We want to make sure that a pool in PM_FAIL mode is never upgraded. */ enum pool_mode old_mode = pool->pf.mode; enum pool_mode new_mode = pt->adjusted_pf.mode; - if (old_mode > new_mode) + /* + * If we were in PM_FAIL mode, rollback of metadata failed. We're + * not going to recover without a thin_repair. So we never let the + * pool move out of the old mode. On the other hand a PM_READ_ONLY + * may have been due to a lack of metadata or data space, and may + * now work (ie. if the underlying devices have been resized). + */ + if (old_mode == PM_FAIL) new_mode = old_mode; pool->ti = ti; @@ -2266,7 +2278,7 @@ static int pool_preresume(struct dm_target *ti) return r; if (need_commit1 || need_commit2) - (void) commit_or_fallback(pool); + (void) commit(pool); return 0; } @@ -2293,7 +2305,7 @@ static void pool_postsuspend(struct dm_target *ti) cancel_delayed_work(&pool->waker); flush_workqueue(pool->wq); - (void) commit_or_fallback(pool); + (void) commit(pool); } static int check_arg_count(unsigned argc, unsigned args_required) @@ -2427,7 +2439,7 @@ static int process_reserve_metadata_snap_mesg(unsigned argc, char **argv, struct if (r) return r; - (void) commit_or_fallback(pool); + (void) commit(pool); r = dm_pool_reserve_metadata_snap(pool->pmd); if (r) @@ -2489,7 +2501,7 @@ static int pool_message(struct dm_target *ti, unsigned argc, char **argv) DMWARN("Unrecognised thin pool target message received: %s", argv[0]); if (!r) - (void) commit_or_fallback(pool); + (void) commit(pool); return r; } @@ -2544,7 +2556,7 @@ static void pool_status(struct dm_target *ti, status_type_t type, /* Commit to ensure statistics aren't out-of-date */ if (!(status_flags & DM_STATUS_NOFLUSH_FLAG) && !dm_suspended(ti)) - (void) commit_or_fallback(pool); + (void) commit(pool); r = dm_pool_get_metadata_transaction_id(pool->pmd, &transaction_id); if (r) { diff --git a/drivers/md/persistent-data/dm-array.c b/drivers/md/persistent-data/dm-array.c index af96e24ec328..1d75b1dc1e2e 100644 --- a/drivers/md/persistent-data/dm-array.c +++ b/drivers/md/persistent-data/dm-array.c @@ -317,8 +317,16 @@ static int shadow_ablock(struct dm_array_info *info, dm_block_t *root, * The shadow op will often be a noop. Only insert if it really * copied data. */ - if (dm_block_location(*block) != b) + if (dm_block_location(*block) != b) { + /* + * dm_tm_shadow_block will have already decremented the old + * block, but it is still referenced by the btree. We + * increment to stop the insert decrementing it below zero + * when overwriting the old value. + */ + dm_tm_inc(info->btree_info.tm, b); r = insert_ablock(info, index, *block, root); + } return r; } diff --git a/drivers/md/persistent-data/dm-block-manager.c b/drivers/md/persistent-data/dm-block-manager.c index a7e8bf296388..064a3c271baa 100644 --- a/drivers/md/persistent-data/dm-block-manager.c +++ b/drivers/md/persistent-data/dm-block-manager.c @@ -626,6 +626,12 @@ void dm_bm_set_read_only(struct dm_block_manager *bm) } EXPORT_SYMBOL_GPL(dm_bm_set_read_only); +void dm_bm_set_read_write(struct dm_block_manager *bm) +{ + bm->read_only = false; +} +EXPORT_SYMBOL_GPL(dm_bm_set_read_write); + u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor) { return crc32c(~(u32) 0, data, len) ^ init_xor; diff --git a/drivers/md/persistent-data/dm-block-manager.h b/drivers/md/persistent-data/dm-block-manager.h index 9a82083a66b6..13cd58e1fe69 100644 --- a/drivers/md/persistent-data/dm-block-manager.h +++ b/drivers/md/persistent-data/dm-block-manager.h @@ -108,9 +108,9 @@ int dm_bm_unlock(struct dm_block *b); int dm_bm_flush_and_unlock(struct dm_block_manager *bm, struct dm_block *superblock); - /* - * Request data be prefetched into the cache. - */ +/* + * Request data is prefetched into the cache. + */ void dm_bm_prefetch(struct dm_block_manager *bm, dm_block_t b); /* @@ -125,6 +125,7 @@ void dm_bm_prefetch(struct dm_block_manager *bm, dm_block_t b); * be returned if you do. */ void dm_bm_set_read_only(struct dm_block_manager *bm); +void dm_bm_set_read_write(struct dm_block_manager *bm); u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor); diff --git a/drivers/md/persistent-data/dm-space-map-common.c b/drivers/md/persistent-data/dm-space-map-common.c index 6058569fe86c..466a60bbd716 100644 --- a/drivers/md/persistent-data/dm-space-map-common.c +++ b/drivers/md/persistent-data/dm-space-map-common.c @@ -381,7 +381,7 @@ int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin, } static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b, - uint32_t (*mutator)(void *context, uint32_t old), + int (*mutator)(void *context, uint32_t old, uint32_t *new), void *context, enum allocation_event *ev) { int r; @@ -410,11 +410,17 @@ static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b, if (old > 2) { r = sm_ll_lookup_big_ref_count(ll, b, &old); - if (r < 0) + if (r < 0) { + dm_tm_unlock(ll->tm, nb); return r; + } } - ref_count = mutator(context, old); + r = mutator(context, old, &ref_count); + if (r) { + dm_tm_unlock(ll->tm, nb); + return r; + } if (ref_count <= 2) { sm_set_bitmap(bm_le, bit, ref_count); @@ -465,9 +471,10 @@ static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b, return ll->save_ie(ll, index, &ie_disk); } -static uint32_t set_ref_count(void *context, uint32_t old) +static int set_ref_count(void *context, uint32_t old, uint32_t *new) { - return *((uint32_t *) context); + *new = *((uint32_t *) context); + return 0; } int sm_ll_insert(struct ll_disk *ll, dm_block_t b, @@ -476,9 +483,10 @@ int sm_ll_insert(struct ll_disk *ll, dm_block_t b, return sm_ll_mutate(ll, b, set_ref_count, &ref_count, ev); } -static uint32_t inc_ref_count(void *context, uint32_t old) +static int inc_ref_count(void *context, uint32_t old, uint32_t *new) { - return old + 1; + *new = old + 1; + return 0; } int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev) @@ -486,9 +494,15 @@ int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev) return sm_ll_mutate(ll, b, inc_ref_count, NULL, ev); } -static uint32_t dec_ref_count(void *context, uint32_t old) +static int dec_ref_count(void *context, uint32_t old, uint32_t *new) { - return old - 1; + if (!old) { + DMERR_LIMIT("unable to decrement a reference count below 0"); + return -EINVAL; + } + + *new = old - 1; + return 0; } int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev) diff --git a/drivers/md/persistent-data/dm-space-map-metadata.c b/drivers/md/persistent-data/dm-space-map-metadata.c index 1c959684caef..58fc1eef7499 100644 --- a/drivers/md/persistent-data/dm-space-map-metadata.c +++ b/drivers/md/persistent-data/dm-space-map-metadata.c @@ -384,12 +384,16 @@ static int sm_metadata_new_block(struct dm_space_map *sm, dm_block_t *b) struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); int r = sm_metadata_new_block_(sm, b); - if (r) + if (r) { DMERR("unable to allocate new metadata block"); + return r; + } r = sm_metadata_get_nr_free(sm, &count); - if (r) + if (r) { DMERR("couldn't get free block count"); + return r; + } check_threshold(&smm->threshold, count); diff --git a/drivers/media/common/siano/smscoreapi.h b/drivers/media/common/siano/smscoreapi.h index d0799e323364..9c9063cd3208 100644 --- a/drivers/media/common/siano/smscoreapi.h +++ b/drivers/media/common/siano/smscoreapi.h @@ -955,7 +955,7 @@ struct sms_rx_stats { u32 modem_state; /* from SMSHOSTLIB_DVB_MODEM_STATE_ET */ s32 SNR; /* dB */ u32 ber; /* Post Viterbi ber [1E-5] */ - u32 ber_error_count; /* Number of erronous SYNC bits. */ + u32 ber_error_count; /* Number of erroneous SYNC bits. */ u32 ber_bit_count; /* Total number of SYNC bits. */ u32 ts_per; /* Transport stream PER, 0xFFFFFFFF indicate N/A */ @@ -981,7 +981,7 @@ struct sms_rx_stats_ex { u32 modem_state; /* from SMSHOSTLIB_DVB_MODEM_STATE_ET */ s32 SNR; /* dB */ u32 ber; /* Post Viterbi ber [1E-5] */ - u32 ber_error_count; /* Number of erronous SYNC bits. */ + u32 ber_error_count; /* Number of erroneous SYNC bits. */ u32 ber_bit_count; /* Total number of SYNC bits. */ u32 ts_per; /* Transport stream PER, 0xFFFFFFFF indicate N/A */ diff --git a/drivers/media/common/siano/smsdvb.h b/drivers/media/common/siano/smsdvb.h index 92c413ba0c79..ae36d0ae0fb1 100644 --- a/drivers/media/common/siano/smsdvb.h +++ b/drivers/media/common/siano/smsdvb.h @@ -95,7 +95,7 @@ struct RECEPTION_STATISTICS_PER_SLICES_S { u32 is_demod_locked; /* 0 - not locked, 1 - locked */ u32 ber_bit_count; /* Total number of SYNC bits. */ - u32 ber_error_count; /* Number of erronous SYNC bits. */ + u32 ber_error_count; /* Number of erroneous SYNC bits. */ s32 MRC_SNR; /* dB */ s32 mrc_in_band_pwr; /* In band power in dBM */ diff --git a/drivers/media/dvb-core/dvb_demux.c b/drivers/media/dvb-core/dvb_demux.c index 58de4410c525..6c7ff0cdcd32 100644 --- a/drivers/media/dvb-core/dvb_demux.c +++ b/drivers/media/dvb-core/dvb_demux.c @@ -435,7 +435,7 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) dprintk_tscheck("TEI detected. " "PID=0x%x data1=0x%x\n", pid, buf[1]); - /* data in this packet cant be trusted - drop it unless + /* data in this packet can't be trusted - drop it unless * module option dvb_demux_feed_err_pkts is set */ if (!dvb_demux_feed_err_pkts) return; @@ -1032,8 +1032,13 @@ static int dmx_section_feed_release_filter(struct dmx_section_feed *feed, return -EINVAL; } - if (feed->is_filtering) + if (feed->is_filtering) { + /* release dvbdmx->mutex as far as it is + acquired by stop_filtering() itself */ + mutex_unlock(&dvbdmx->mutex); feed->stop_filtering(feed); + mutex_lock(&dvbdmx->mutex); + } spin_lock_irq(&dvbdmx->lock); f = dvbdmxfeed->filter; diff --git a/drivers/media/dvb-frontends/af9033.c b/drivers/media/dvb-frontends/af9033.c index 30ee59052157..65728c25ea05 100644 --- a/drivers/media/dvb-frontends/af9033.c +++ b/drivers/media/dvb-frontends/af9033.c @@ -170,18 +170,18 @@ static int af9033_rd_reg_mask(struct af9033_state *state, u32 reg, u8 *val, static int af9033_wr_reg_val_tab(struct af9033_state *state, const struct reg_val *tab, int tab_len) { +#define MAX_TAB_LEN 212 int ret, i, j; - u8 buf[MAX_XFER_SIZE]; + u8 buf[1 + MAX_TAB_LEN]; + + dev_dbg(&state->i2c->dev, "%s: tab_len=%d\n", __func__, tab_len); if (tab_len > sizeof(buf)) { - dev_warn(&state->i2c->dev, - "%s: i2c wr len=%d is too big!\n", - KBUILD_MODNAME, tab_len); + dev_warn(&state->i2c->dev, "%s: tab len %d is too big\n", + KBUILD_MODNAME, tab_len); return -EINVAL; } - dev_dbg(&state->i2c->dev, "%s: tab_len=%d\n", __func__, tab_len); - for (i = 0, j = 0; i < tab_len; i++) { buf[j] = tab[i].val; diff --git a/drivers/media/dvb-frontends/cxd2820r_c.c b/drivers/media/dvb-frontends/cxd2820r_c.c index 125a44041011..5c6ab4921bf1 100644 --- a/drivers/media/dvb-frontends/cxd2820r_c.c +++ b/drivers/media/dvb-frontends/cxd2820r_c.c @@ -78,7 +78,7 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe) num = if_freq / 1000; /* Hz => kHz */ num *= 0x4000; - if_ctl = cxd2820r_div_u64_round_closest(num, 41000); + if_ctl = 0x4000 - cxd2820r_div_u64_round_closest(num, 41000); buf[0] = (if_ctl >> 8) & 0x3f; buf[1] = (if_ctl >> 0) & 0xff; diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c index 90536147bf04..6dbbee453ee1 100644 --- a/drivers/media/dvb-frontends/dib8000.c +++ b/drivers/media/dvb-frontends/dib8000.c @@ -3048,7 +3048,7 @@ static int dib8000_tune(struct dvb_frontend *fe) dib8000_set_diversity_in(state->fe[0], state->diversity_onoff); locks = (dib8000_read_word(state, 180) >> 6) & 0x3f; /* P_coff_winlen ? */ - /* coff should lock over P_coff_winlen ofdm symbols : give 3 times this lenght to lock */ + /* coff should lock over P_coff_winlen ofdm symbols : give 3 times this length to lock */ *timeout = dib8000_get_timeout(state, 2 * locks, SYMBOL_DEPENDENT_ON); *tune_state = CT_DEMOD_STEP_5; break; @@ -3115,7 +3115,7 @@ static int dib8000_tune(struct dvb_frontend *fe) case CT_DEMOD_STEP_9: /* 39 */ if ((state->revision == 0x8090) || ((dib8000_read_word(state, 1291) >> 9) & 0x1)) { /* fe capable of deinterleaving : esram */ - /* defines timeout for mpeg lock depending on interleaver lenght of longest layer */ + /* defines timeout for mpeg lock depending on interleaver length of longest layer */ for (i = 0; i < 3; i++) { if (c->layer[i].interleaving >= deeper_interleaver) { dprintk("layer%i: time interleaver = %d ", i, c->layer[i].interleaving); diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c index d416c15691da..bf29a3f0e6f0 100644 --- a/drivers/media/dvb-frontends/drxk_hard.c +++ b/drivers/media/dvb-frontends/drxk_hard.c @@ -1191,7 +1191,7 @@ static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable) goto error; if (state->m_enable_parallel == true) { - /* paralel -> enable MD1 to MD7 */ + /* parallel -> enable MD1 to MD7 */ status = write16(state, SIO_PDR_MD1_CFG__A, sio_pdr_mdx_cfg); if (status < 0) @@ -1428,7 +1428,7 @@ static int mpegts_stop(struct drxk_state *state) dprintk(1, "\n"); - /* Gracefull shutdown (byte boundaries) */ + /* Graceful shutdown (byte boundaries) */ status = read16(state, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode); if (status < 0) goto error; @@ -2021,7 +2021,7 @@ static int mpegts_dto_setup(struct drxk_state *state, fec_oc_dto_burst_len = 204; } - /* Check serial or parrallel output */ + /* Check serial or parallel output */ fec_oc_reg_ipr_mode &= (~(FEC_OC_IPR_MODE_SERIAL__M)); if (state->m_enable_parallel == false) { /* MPEG data output is serial -> set ipr_mode[0] */ @@ -2908,7 +2908,7 @@ static int adc_synchronization(struct drxk_state *state) goto error; if (count == 1) { - /* Try sampling on a diffrent edge */ + /* Try sampling on a different edge */ u16 clk_neg = 0; status = read16(state, IQM_AF_CLKNEG__A, &clk_neg); @@ -3306,7 +3306,7 @@ static int dvbt_sc_command(struct drxk_state *state, if (status < 0) goto error; - /* Retreive results parameters from SC */ + /* Retrieve results parameters from SC */ switch (cmd) { /* All commands yielding 5 results */ /* All commands yielding 4 results */ @@ -3849,7 +3849,7 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, break; } #if 0 - /* No hierachical channels support in BDA */ + /* No hierarchical channels support in BDA */ /* Priority (only for hierarchical channels) */ switch (channel->priority) { case DRX_PRIORITY_LOW: @@ -4081,7 +4081,7 @@ error: /*============================================================================*/ /** -* \brief Retreive lock status . +* \brief Retrieve lock status . * \param demod Pointer to demodulator instance. * \param lockStat Pointer to lock status structure. * \return DRXStatus_t. @@ -6174,7 +6174,7 @@ static int init_drxk(struct drxk_state *state) goto error; /* Stamp driver version number in SCU data RAM in BCD code - Done to enable field application engineers to retreive drxdriver version + Done to enable field application engineers to retrieve drxdriver version via I2C from SCU RAM. Not using SCU command interface for SCU register access since no microcode may be present. @@ -6399,7 +6399,7 @@ static int drxk_set_parameters(struct dvb_frontend *fe) fe->ops.tuner_ops.get_if_frequency(fe, &IF); start(state, 0, IF); - /* After set_frontend, stats aren't avaliable */ + /* After set_frontend, stats aren't available */ p->strength.stat[0].scale = FE_SCALE_RELATIVE; p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index 7efb796c472c..50e8b63e5169 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -710,6 +710,7 @@ struct dvb_frontend *rtl2830_attach(const struct rtl2830_config *cfg, sizeof(priv->tuner_i2c_adapter.name)); priv->tuner_i2c_adapter.algo = &rtl2830_tuner_i2c_algo; priv->tuner_i2c_adapter.algo_data = NULL; + priv->tuner_i2c_adapter.dev.parent = &i2c->dev; i2c_set_adapdata(&priv->tuner_i2c_adapter, priv); if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) { dev_err(&i2c->dev, diff --git a/drivers/media/i2c/adv7183_regs.h b/drivers/media/i2c/adv7183_regs.h index 4a5b7d211d2f..b253d400e817 100644 --- a/drivers/media/i2c/adv7183_regs.h +++ b/drivers/media/i2c/adv7183_regs.h @@ -52,9 +52,9 @@ #define ADV7183_VS_FIELD_CTRL_1 0x31 /* Vsync field control 1 */ #define ADV7183_VS_FIELD_CTRL_2 0x32 /* Vsync field control 2 */ #define ADV7183_VS_FIELD_CTRL_3 0x33 /* Vsync field control 3 */ -#define ADV7183_HS_POS_CTRL_1 0x34 /* Hsync positon control 1 */ -#define ADV7183_HS_POS_CTRL_2 0x35 /* Hsync positon control 2 */ -#define ADV7183_HS_POS_CTRL_3 0x36 /* Hsync positon control 3 */ +#define ADV7183_HS_POS_CTRL_1 0x34 /* Hsync position control 1 */ +#define ADV7183_HS_POS_CTRL_2 0x35 /* Hsync position control 2 */ +#define ADV7183_HS_POS_CTRL_3 0x36 /* Hsync position control 3 */ #define ADV7183_POLARITY 0x37 /* Polarity */ #define ADV7183_NTSC_COMB_CTRL 0x38 /* NTSC comb control */ #define ADV7183_PAL_COMB_CTRL 0x39 /* PAL comb control */ diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index fbfdd2fc2a36..a324106b9f11 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -877,7 +877,7 @@ static void configure_custom_video_timings(struct v4l2_subdev *sd, break; case ADV7604_MODE_HDMI: /* set default prim_mode/vid_std for HDMI - accoring to [REF_03, c. 4.2] */ + according to [REF_03, c. 4.2] */ io_write(sd, 0x00, 0x02); /* video std */ io_write(sd, 0x01, 0x06); /* prim mode */ break; diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c index 22f729d66a96..b154f36740b4 100644 --- a/drivers/media/i2c/adv7842.c +++ b/drivers/media/i2c/adv7842.c @@ -1013,7 +1013,7 @@ static void configure_custom_video_timings(struct v4l2_subdev *sd, break; case ADV7842_MODE_HDMI: /* set default prim_mode/vid_std for HDMI - accoring to [REF_03, c. 4.2] */ + according to [REF_03, c. 4.2] */ io_write(sd, 0x00, 0x02); /* video std */ io_write(sd, 0x01, 0x06); /* prim mode */ break; diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c index 82bf5679da30..99ee456700f4 100644 --- a/drivers/media/i2c/ir-kbd-i2c.c +++ b/drivers/media/i2c/ir-kbd-i2c.c @@ -394,7 +394,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) if (!rc) { /* - * If platform_data doesn't specify rc_dev, initilize it + * If platform_data doesn't specify rc_dev, initialize it * internally */ rc = rc_allocate_device(); diff --git a/drivers/media/i2c/m5mols/m5mols_controls.c b/drivers/media/i2c/m5mols/m5mols_controls.c index f34429e452ab..a60931e66312 100644 --- a/drivers/media/i2c/m5mols/m5mols_controls.c +++ b/drivers/media/i2c/m5mols/m5mols_controls.c @@ -544,7 +544,7 @@ int m5mols_init_controls(struct v4l2_subdev *sd) u16 zoom_step; int ret; - /* Determine the firmware dependant control range and step values */ + /* Determine the firmware dependent control range and step values */ ret = m5mols_read_u16(sd, AE_MAX_GAIN_MON, &exposure_max); if (ret < 0) return ret; diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c index 4734836fe5a4..1c2303d18bf4 100644 --- a/drivers/media/i2c/mt9p031.c +++ b/drivers/media/i2c/mt9p031.c @@ -19,6 +19,7 @@ #include <linux/i2c.h> #include <linux/log2.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/of_gpio.h> #include <linux/pm.h> #include <linux/regulator/consumer.h> diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index 6fec9384d86e..e7f555cc827a 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c @@ -1460,7 +1460,7 @@ static int s5c73m3_oif_registered(struct v4l2_subdev *sd) mutex_unlock(&state->lock); v4l2_dbg(1, s5c73m3_dbg, sd, "%s: Booting %s (%d)\n", - __func__, ret ? "failed" : "succeded", ret); + __func__, ret ? "failed" : "succeeded", ret); return ret; } diff --git a/drivers/media/i2c/s5c73m3/s5c73m3.h b/drivers/media/i2c/s5c73m3/s5c73m3.h index 9d2c08652246..9dfa516f6944 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3.h +++ b/drivers/media/i2c/s5c73m3/s5c73m3.h @@ -393,7 +393,7 @@ struct s5c73m3 { /* External master clock frequency */ u32 mclk_frequency; - /* Video bus type - MIPI-CSI2/paralell */ + /* Video bus type - MIPI-CSI2/parallel */ enum v4l2_mbus_type bus_type; const struct s5c73m3_frame_size *sensor_pix_size[2]; diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c index 637d02634527..afdbcb045cee 100644 --- a/drivers/media/i2c/saa7115.c +++ b/drivers/media/i2c/saa7115.c @@ -1699,7 +1699,7 @@ static void saa711x_write_platform_data(struct saa711x_state *state, * the analog demod. * If the tuner is not found, it returns -ENODEV. * If auto-detection is disabled and the tuner doesn't match what it was - * requred, it returns -EINVAL and fills 'name'. + * required, it returns -EINVAL and fills 'name'. * If the chip is found, it returns the chip ID and fills 'name'. */ static int saa711x_detect_chip(struct i2c_client *client, diff --git a/drivers/media/i2c/soc_camera/ov5642.c b/drivers/media/i2c/soc_camera/ov5642.c index 0a5c5d4fedd6..d2daa6a8f272 100644 --- a/drivers/media/i2c/soc_camera/ov5642.c +++ b/drivers/media/i2c/soc_camera/ov5642.c @@ -642,7 +642,7 @@ static const struct ov5642_datafmt static int reg_read(struct i2c_client *client, u16 reg, u8 *val) { int ret; - /* We have 16-bit i2c addresses - care for endianess */ + /* We have 16-bit i2c addresses - care for endianness */ unsigned char data[2] = { reg >> 8, reg & 0xff }; ret = i2c_master_send(client, data, 2); diff --git a/drivers/media/i2c/ths7303.c b/drivers/media/i2c/ths7303.c index 42276d93624c..ed9ae8875348 100644 --- a/drivers/media/i2c/ths7303.c +++ b/drivers/media/i2c/ths7303.c @@ -83,7 +83,8 @@ static int ths7303_write(struct v4l2_subdev *sd, u8 reg, u8 val) } /* following function is used to set ths7303 */ -int ths7303_setval(struct v4l2_subdev *sd, enum ths7303_filter_mode mode) +static int ths7303_setval(struct v4l2_subdev *sd, + enum ths7303_filter_mode mode) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct ths7303_state *state = to_state(sd); diff --git a/drivers/media/i2c/wm8775.c b/drivers/media/i2c/wm8775.c index 3f584a7d0781..bee7946faa7c 100644 --- a/drivers/media/i2c/wm8775.c +++ b/drivers/media/i2c/wm8775.c @@ -130,12 +130,10 @@ static int wm8775_s_routing(struct v4l2_subdev *sd, return -EINVAL; } state->input = input; - if (!v4l2_ctrl_g_ctrl(state->mute)) + if (v4l2_ctrl_g_ctrl(state->mute)) return 0; if (!v4l2_ctrl_g_ctrl(state->vol)) return 0; - if (!v4l2_ctrl_g_ctrl(state->bal)) - return 0; wm8775_set_audio(sd, 1); return 0; } diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index a3b1ee9c00d7..92a06fd85865 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -4182,7 +4182,8 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) } btv->std = V4L2_STD_PAL; init_irqreg(btv); - v4l2_ctrl_handler_setup(hdl); + if (!bttv_tvcards[btv->c.type].no_video) + v4l2_ctrl_handler_setup(hdl); if (hdl->error) { result = hdl->error; goto fail2; diff --git a/drivers/media/pci/cx18/cx18-driver.h b/drivers/media/pci/cx18/cx18-driver.h index 2767c64df0c8..57f4688ea55b 100644 --- a/drivers/media/pci/cx18/cx18-driver.h +++ b/drivers/media/pci/cx18/cx18-driver.h @@ -262,7 +262,7 @@ struct cx18_options { }; /* per-mdl bit flags */ -#define CX18_F_M_NEED_SWAP 0 /* mdl buffer data must be endianess swapped */ +#define CX18_F_M_NEED_SWAP 0 /* mdl buffer data must be endianness swapped */ /* per-stream, s_flags */ #define CX18_F_S_CLAIMED 3 /* this stream is claimed */ diff --git a/drivers/media/pci/cx23885/cx23885-417.c b/drivers/media/pci/cx23885/cx23885-417.c index e3fc2c71808a..95666eee7b27 100644 --- a/drivers/media/pci/cx23885/cx23885-417.c +++ b/drivers/media/pci/cx23885/cx23885-417.c @@ -427,7 +427,7 @@ int mc417_register_read(struct cx23885_dev *dev, u16 address, u32 *value) cx_write(MC417_RWD, regval); /* Transition RD to effect read transaction across bus. - * Transtion 0x5000 -> 0x9000 correct (RD/RDY -> WR/RDY)? + * Transition 0x5000 -> 0x9000 correct (RD/RDY -> WR/RDY)? * Should it be 0x9000 -> 0xF000 (also why is RDY being set, its * input only...) */ diff --git a/drivers/media/pci/pluto2/pluto2.c b/drivers/media/pci/pluto2/pluto2.c index 8164d74b46a4..655d6854a8d7 100644 --- a/drivers/media/pci/pluto2/pluto2.c +++ b/drivers/media/pci/pluto2/pluto2.c @@ -401,7 +401,7 @@ static int pluto_hw_init(struct pluto *pluto) /* set automatic LED control by FPGA */ pluto_rw(pluto, REG_MISC, MISC_ALED, MISC_ALED); - /* set data endianess */ + /* set data endianness */ #ifdef __LITTLE_ENDIAN pluto_rw(pluto, REG_PIDn(0), PID0_END, PID0_END); #else diff --git a/drivers/media/pci/saa7164/saa7164-core.c b/drivers/media/pci/saa7164/saa7164-core.c index 57ef5456f1e8..1bf06970ca3e 100644 --- a/drivers/media/pci/saa7164/saa7164-core.c +++ b/drivers/media/pci/saa7164/saa7164-core.c @@ -1354,9 +1354,11 @@ static int saa7164_initdev(struct pci_dev *pci_dev, if (fw_debug) { dev->kthread = kthread_run(saa7164_thread_function, dev, "saa7164 debug"); - if (!dev->kthread) + if (IS_ERR(dev->kthread)) { + dev->kthread = NULL; printk(KERN_ERR "%s() Failed to create " "debug kernel thread\n", __func__); + } } } /* != BOARD_UNKNOWN */ diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index bd72fb97fea5..61f3dbcc259f 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -1434,7 +1434,7 @@ static void coda_buf_queue(struct vb2_buffer *vb) if (q_data->fourcc == V4L2_PIX_FMT_H264 && vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { /* - * For backwards compatiblity, queuing an empty buffer marks + * For backwards compatibility, queuing an empty buffer marks * the stream end */ if (vb2_get_plane_payload(vb, 0) == 0) diff --git a/drivers/media/platform/exynos4-is/fimc-core.c b/drivers/media/platform/exynos4-is/fimc-core.c index 3d66d88ea3a1..f7915695c907 100644 --- a/drivers/media/platform/exynos4-is/fimc-core.c +++ b/drivers/media/platform/exynos4-is/fimc-core.c @@ -1039,7 +1039,7 @@ static int fimc_runtime_resume(struct device *dev) dbg("fimc%d: state: 0x%lx", fimc->id, fimc->state); - /* Enable clocks and perform basic initalization */ + /* Enable clocks and perform basic initialization */ clk_enable(fimc->clock[CLK_GATE]); fimc_hw_reset(fimc); diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index 7a4ee4c0449d..c1bce170df6f 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -759,7 +759,7 @@ static int fimc_md_register_platform_entity(struct fimc_md *fmd, goto dev_unlock; drvdata = dev_get_drvdata(dev); - /* Some subdev didn't probe succesfully id drvdata is NULL */ + /* Some subdev didn't probe successfully id drvdata is NULL */ if (drvdata) { switch (plat_entity) { case IDX_FIMC: diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c index 3458fa0e2fd5..054507f16734 100644 --- a/drivers/media/platform/marvell-ccic/mmp-driver.c +++ b/drivers/media/platform/marvell-ccic/mmp-driver.c @@ -142,12 +142,6 @@ static int mmpcam_power_up(struct mcam_camera *mcam) struct mmp_camera *cam = mcam_to_cam(mcam); struct mmp_camera_platform_data *pdata; - if (mcam->bus_type == V4L2_MBUS_CSI2) { - cam->mipi_clk = devm_clk_get(mcam->dev, "mipi"); - if ((IS_ERR(cam->mipi_clk) && mcam->dphy[2] == 0)) - return PTR_ERR(cam->mipi_clk); - } - /* * Turn on power and clocks to the controller. */ @@ -186,12 +180,6 @@ static void mmpcam_power_down(struct mcam_camera *mcam) gpio_set_value(pdata->sensor_power_gpio, 0); gpio_set_value(pdata->sensor_reset_gpio, 0); - if (mcam->bus_type == V4L2_MBUS_CSI2 && !IS_ERR(cam->mipi_clk)) { - if (cam->mipi_clk) - devm_clk_put(mcam->dev, cam->mipi_clk); - cam->mipi_clk = NULL; - } - mcam_clk_disable(mcam); } @@ -292,8 +280,9 @@ void mmpcam_calc_dphy(struct mcam_camera *mcam) return; /* get the escape clk, this is hard coded */ + clk_prepare_enable(cam->mipi_clk); tx_clk_esc = (clk_get_rate(cam->mipi_clk) / 1000000) / 12; - + clk_disable_unprepare(cam->mipi_clk); /* * dphy[2] - CSI2_DPHY6: * bit 0 ~ bit 7: CK Term Enable @@ -325,19 +314,6 @@ static irqreturn_t mmpcam_irq(int irq, void *data) return IRQ_RETVAL(handled); } -static void mcam_deinit_clk(struct mcam_camera *mcam) -{ - unsigned int i; - - for (i = 0; i < NR_MCAM_CLK; i++) { - if (!IS_ERR(mcam->clk[i])) { - if (mcam->clk[i]) - devm_clk_put(mcam->dev, mcam->clk[i]); - } - mcam->clk[i] = NULL; - } -} - static void mcam_init_clk(struct mcam_camera *mcam) { unsigned int i; @@ -371,7 +347,6 @@ static int mmpcam_probe(struct platform_device *pdev) if (cam == NULL) return -ENOMEM; cam->pdev = pdev; - cam->mipi_clk = NULL; INIT_LIST_HEAD(&cam->devlist); mcam = &cam->mcam; @@ -387,6 +362,11 @@ static int mmpcam_probe(struct platform_device *pdev) mcam->mclk_div = pdata->mclk_div; mcam->bus_type = pdata->bus_type; mcam->dphy = pdata->dphy; + if (mcam->bus_type == V4L2_MBUS_CSI2) { + cam->mipi_clk = devm_clk_get(mcam->dev, "mipi"); + if ((IS_ERR(cam->mipi_clk) && mcam->dphy[2] == 0)) + return PTR_ERR(cam->mipi_clk); + } mcam->mipi_enabled = false; mcam->lane = pdata->lane; mcam->chip_id = MCAM_ARMADA610; @@ -444,7 +424,7 @@ static int mmpcam_probe(struct platform_device *pdev) */ ret = mmpcam_power_up(mcam); if (ret) - goto out_deinit_clk; + return ret; ret = mccic_register(mcam); if (ret) goto out_power_down; @@ -469,8 +449,6 @@ out_unregister: mccic_shutdown(mcam); out_power_down: mmpcam_power_down(mcam); -out_deinit_clk: - mcam_deinit_clk(mcam); return ret; } @@ -478,18 +456,10 @@ out_deinit_clk: static int mmpcam_remove(struct mmp_camera *cam) { struct mcam_camera *mcam = &cam->mcam; - struct mmp_camera_platform_data *pdata; mmpcam_remove_device(cam); mccic_shutdown(mcam); mmpcam_power_down(mcam); - pdata = cam->pdev->dev.platform_data; - gpio_free(pdata->sensor_reset_gpio); - gpio_free(pdata->sensor_power_gpio); - mcam_deinit_clk(mcam); - iounmap(cam->power_regs); - iounmap(mcam->regs); - kfree(cam); return 0; } diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 1c3608039663..561bce8ffb1b 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -1673,7 +1673,7 @@ void omap3isp_print_status(struct isp_device *isp) * ISP clocks get disabled in suspend(). Similarly, the clocks are reenabled in * resume(), and the the pipelines are restarted in complete(). * - * TODO: PM dependencies between the ISP and sensors are not modeled explicitly + * TODO: PM dependencies between the ISP and sensors are not modelled explicitly * yet. */ static int isp_pm_prepare(struct device *dev) diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index a908d006f527..f6304bb074f5 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c @@ -339,14 +339,11 @@ __isp_video_get_format(struct isp_video *video, struct v4l2_format *format) if (subdev == NULL) return -EINVAL; - mutex_lock(&video->mutex); - fmt.pad = pad; fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; - ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt); - if (ret == -ENOIOCTLCMD) - ret = -EINVAL; + mutex_lock(&video->mutex); + ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt); mutex_unlock(&video->mutex); if (ret) diff --git a/drivers/media/platform/s5p-mfc/regs-mfc.h b/drivers/media/platform/s5p-mfc/regs-mfc.h index 9319e93599ae..6ccc3f8c122a 100644 --- a/drivers/media/platform/s5p-mfc/regs-mfc.h +++ b/drivers/media/platform/s5p-mfc/regs-mfc.h @@ -382,7 +382,7 @@ #define S5P_FIMV_R2H_CMD_EDFU_INIT_RET 16 #define S5P_FIMV_R2H_CMD_ERR_RET 32 -/* Dummy definition for MFCv6 compatibilty */ +/* Dummy definition for MFCv6 compatibility */ #define S5P_FIMV_CODEC_H264_MVC_DEC -1 #define S5P_FIMV_R2H_CMD_FIELD_DONE_RET -1 #define S5P_FIMV_MFC_RESET -1 diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 5f2c4ad6c2cb..e46067a57853 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -239,7 +239,7 @@ static void s5p_mfc_handle_frame_copy_time(struct s5p_mfc_ctx *ctx) frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev); /* Copy timestamp / timecode from decoded src to dst and set - appropraite flags */ + appropriate flags */ src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); list_for_each_entry(dst_buf, &ctx->dst_queue, list) { if (vb2_dma_contig_plane_dma_addr(dst_buf->b, 0) == dec_y_addr) { @@ -428,7 +428,7 @@ static void s5p_mfc_handle_error(struct s5p_mfc_dev *dev, case MFCINST_FINISHING: case MFCINST_FINISHED: case MFCINST_RUNNING: - /* It is higly probable that an error occured + /* It is highly probable that an error occurred * while decoding a frame */ clear_work_bit(ctx); ctx->state = MFCINST_ERROR; @@ -611,7 +611,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) mfc_debug(1, "Int reason: %d (err: %08x)\n", reason, err); switch (reason) { case S5P_MFC_R2H_CMD_ERR_RET: - /* An error has occured */ + /* An error has occurred */ if (ctx->state == MFCINST_RUNNING && s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) >= dev->warn_start) @@ -840,7 +840,7 @@ static int s5p_mfc_open(struct file *file) mutex_unlock(&dev->mfc_mutex); mfc_debug_leave(); return ret; - /* Deinit when failure occured */ + /* Deinit when failure occurred */ err_queue_init: if (dev->num_inst == 1) s5p_mfc_deinit_hw(dev); @@ -881,14 +881,14 @@ static int s5p_mfc_release(struct file *file) /* Mark context as idle */ clear_work_bit_irqsave(ctx); /* If instance was initialised then - * return instance and free reosurces */ + * return instance and free resources */ if (ctx->inst_no != MFC_NO_INSTANCE_SET) { mfc_debug(2, "Has to free instance\n"); ctx->state = MFCINST_RETURN_INST; set_work_bit_irqsave(ctx); s5p_mfc_clean_ctx_int_flags(ctx); s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); - /* Wait until instance is returned or timeout occured */ + /* Wait until instance is returned or timeout occurred */ if (s5p_mfc_wait_for_done_ctx (ctx, S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET, 0)) { s5p_mfc_clock_off(); diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c index 7cab6849fb5b..2475a3c9a0a6 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c @@ -69,7 +69,7 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) } else { /* In this case bank2 can point to the same address as bank1. - * Firmware will always occupy the beggining of this area so it is + * Firmware will always occupy the beginning of this area so it is * impossible having a video frame buffer with zero address. */ dev->bank2 = dev->bank1; } diff --git a/drivers/media/platform/s5p-tv/mixer.h b/drivers/media/platform/s5p-tv/mixer.h index 04e6490a45be..fb2acc53112a 100644 --- a/drivers/media/platform/s5p-tv/mixer.h +++ b/drivers/media/platform/s5p-tv/mixer.h @@ -65,7 +65,7 @@ struct mxr_format { int num_subframes; /** specifies to which subframe belong given plane */ int plane2subframe[MXR_MAX_PLANES]; - /** internal code, driver dependant */ + /** internal code, driver dependent */ unsigned long cookie; }; diff --git a/drivers/media/platform/s5p-tv/mixer_video.c b/drivers/media/platform/s5p-tv/mixer_video.c index 641b1f071e06..81b97db111d8 100644 --- a/drivers/media/platform/s5p-tv/mixer_video.c +++ b/drivers/media/platform/s5p-tv/mixer_video.c @@ -528,7 +528,7 @@ static int mxr_s_dv_timings(struct file *file, void *fh, mutex_lock(&mdev->mutex); /* timings change cannot be done while there is an entity - * dependant on output configuration + * dependent on output configuration */ if (mdev->n_output > 0) { mutex_unlock(&mdev->mutex); @@ -585,7 +585,7 @@ static int mxr_s_std(struct file *file, void *fh, v4l2_std_id norm) mutex_lock(&mdev->mutex); /* standard change cannot be done while there is an entity - * dependant on output configuration + * dependent on output configuration */ if (mdev->n_output > 0) { mutex_unlock(&mdev->mutex); diff --git a/drivers/media/platform/soc_camera/omap1_camera.c b/drivers/media/platform/soc_camera/omap1_camera.c index 6769193c7c7b..74ce8b6b79fa 100644 --- a/drivers/media/platform/soc_camera/omap1_camera.c +++ b/drivers/media/platform/soc_camera/omap1_camera.c @@ -1495,7 +1495,7 @@ static int omap1_cam_set_bus_param(struct soc_camera_device *icd) if (ctrlclock & LCLK_EN) CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock); - /* select bus endianess */ + /* select bus endianness */ xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); fmt = xlate->host_fmt; diff --git a/drivers/media/platform/vivi.c b/drivers/media/platform/vivi.c index 1d3f11965196..2d4e73b45c5e 100644 --- a/drivers/media/platform/vivi.c +++ b/drivers/media/platform/vivi.c @@ -1108,7 +1108,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) return 0; } -/* timeperframe is arbitrary and continous */ +/* timeperframe is arbitrary and continuous */ static int vidioc_enum_frameintervals(struct file *file, void *priv, struct v4l2_frmivalenum *fival) { @@ -1125,7 +1125,7 @@ static int vidioc_enum_frameintervals(struct file *file, void *priv, fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS; - /* fill in stepwise (step=1.0 is requred by V4L2 spec) */ + /* fill in stepwise (step=1.0 is required by V4L2 spec) */ fival->stepwise.min = tpf_min; fival->stepwise.max = tpf_max; fival->stepwise.step = (struct v4l2_fract) {1, 1}; diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 1c9e771aa15c..d16bf0f41e24 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -323,7 +323,7 @@ static void vsp1_clocks_disable(struct vsp1_device *vsp1) * Increment the VSP1 reference count and initialize the device if the first * reference is taken. * - * Return a pointer to the VSP1 device or NULL if an error occured. + * Return a pointer to the VSP1 device or NULL if an error occurred. */ struct vsp1_device *vsp1_device_get(struct vsp1_device *vsp1) { diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 714c53ef6c11..4b0ac07af662 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -1026,8 +1026,10 @@ int vsp1_video_init(struct vsp1_video *video, struct vsp1_entity *rwpf) /* ... and the buffers queue... */ video->alloc_ctx = vb2_dma_contig_init_ctx(video->vsp1->dev); - if (IS_ERR(video->alloc_ctx)) + if (IS_ERR(video->alloc_ctx)) { + ret = PTR_ERR(video->alloc_ctx); goto error; + } video->queue.type = video->type; video->queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; diff --git a/drivers/media/radio/radio-shark.c b/drivers/media/radio/radio-shark.c index 3db8a8cfe1a8..050b3bb96fec 100644 --- a/drivers/media/radio/radio-shark.c +++ b/drivers/media/radio/radio-shark.c @@ -271,8 +271,7 @@ static void shark_unregister_leds(struct shark_device *shark) cancel_work_sync(&shark->led_work); } -#ifdef CONFIG_PM -static void shark_resume_leds(struct shark_device *shark) +static inline void shark_resume_leds(struct shark_device *shark) { if (test_bit(BLUE_IS_PULSE, &shark->brightness_new)) set_bit(BLUE_PULSE_LED, &shark->brightness_new); @@ -281,7 +280,6 @@ static void shark_resume_leds(struct shark_device *shark) set_bit(RED_LED, &shark->brightness_new); schedule_work(&shark->led_work); } -#endif #else static int shark_register_leds(struct shark_device *shark, struct device *dev) { diff --git a/drivers/media/radio/radio-shark2.c b/drivers/media/radio/radio-shark2.c index d86d90dab8bf..8654e0dc5c95 100644 --- a/drivers/media/radio/radio-shark2.c +++ b/drivers/media/radio/radio-shark2.c @@ -237,8 +237,7 @@ static void shark_unregister_leds(struct shark_device *shark) cancel_work_sync(&shark->led_work); } -#ifdef CONFIG_PM -static void shark_resume_leds(struct shark_device *shark) +static inline void shark_resume_leds(struct shark_device *shark) { int i; @@ -247,7 +246,6 @@ static void shark_resume_leds(struct shark_device *shark) schedule_work(&shark->led_work); } -#endif #else static int shark_register_leds(struct shark_device *shark, struct device *dev) { diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c index 9c9084cb99f7..2fd9009f8663 100644 --- a/drivers/media/radio/radio-si476x.c +++ b/drivers/media/radio/radio-si476x.c @@ -268,8 +268,8 @@ struct si476x_radio; * * @tune_freq: Tune chip to a specific frequency * @seek_start: Star station seeking - * @rsq_status: Get Recieved Signal Quality(RSQ) status - * @rds_blckcnt: Get recived RDS blocks count + * @rsq_status: Get Received Signal Quality(RSQ) status + * @rds_blckcnt: Get received RDS blocks count * @phase_diversity: Change phase diversity mode of the tuner * @phase_div_status: Get phase diversity mode status * @acf_status: Get the status of Automatically Controlled diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c index 036e2f54f4db..3ed1f5669f79 100644 --- a/drivers/media/radio/radio-tea5764.c +++ b/drivers/media/radio/radio-tea5764.c @@ -356,7 +356,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, So we keep it as-is. */ return -EINVAL; } - clamp(freq, FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL); + freq = clamp(freq, FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL); tea5764_power_up(radio); tea5764_tune(radio, (freq * 125) / 2); return 0; diff --git a/drivers/media/radio/tef6862.c b/drivers/media/radio/tef6862.c index 69e3245a58a0..a9319a24c7ef 100644 --- a/drivers/media/radio/tef6862.c +++ b/drivers/media/radio/tef6862.c @@ -112,7 +112,7 @@ static int tef6862_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequen if (f->tuner != 0) return -EINVAL; - clamp(freq, TEF6862_LO_FREQ, TEF6862_HI_FREQ); + freq = clamp(freq, TEF6862_LO_FREQ, TEF6862_HI_FREQ); pll = 1964 + ((freq - TEF6862_LO_FREQ) * 20) / FREQ_MUL; i2cmsg[0] = (MSA_MODE_PRESET << MSA_MODE_SHIFT) | WM_SUB_PLLM; i2cmsg[1] = (pll >> 8) & 0xff; diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index 72e3fa652481..f329485c6629 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -1370,7 +1370,7 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf) * 0x68nnnnB7 to 0x6AnnnnB7, the left mouse button generates * 0x688301b7 and the right one 0x688481b7. All other keys generate * 0x2nnnnnnn. Position coordinate is encoded in buf[1] and buf[2] with - * reversed endianess. Extract direction from buffer, rotate endianess, + * reversed endianness. Extract direction from buffer, rotate endianness, * adjust sign and feed the values into stabilize(). The resulting codes * will be 0x01008000, 0x01007F00, which match the newer devices. */ diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c index 094484fac94c..a5d4f883d053 100644 --- a/drivers/media/rc/redrat3.c +++ b/drivers/media/rc/redrat3.c @@ -118,7 +118,7 @@ static int debug; #define RR3_IR_IO_LENGTH_FUZZ 0x04 /* Timeout for end of signal detection */ #define RR3_IR_IO_SIG_TIMEOUT 0x05 -/* Minumum value for pause recognition. */ +/* Minimum value for pause recognition. */ #define RR3_IR_IO_MIN_PAUSE 0x06 /* Clock freq. of EZ-USB chip */ diff --git a/drivers/media/tuners/mt2063.c b/drivers/media/tuners/mt2063.c index 2e1a02e360ff..20cca405bf45 100644 --- a/drivers/media/tuners/mt2063.c +++ b/drivers/media/tuners/mt2063.c @@ -1195,7 +1195,7 @@ static u32 mt2063_set_dnc_output_enable(struct mt2063_state *state, * DNC Output is selected, the other is always off) * * @state: ptr to mt2063_state structure - * @Mode: desired reciever delivery system + * @Mode: desired receiver delivery system * * Note: Register cache must be valid for it to work */ @@ -2119,7 +2119,7 @@ static int mt2063_set_analog_params(struct dvb_frontend *fe, /* * As defined on EN 300 429, the DVB-C roll-off factor is 0.15. - * So, the amount of the needed bandwith is given by: + * So, the amount of the needed bandwidth is given by: * Bw = Symbol_rate * (1 + 0.15) * As such, the maximum symbol rate supported by 6 MHz is given by: * max_symbol_rate = 6 MHz / 1.15 = 5217391 Bauds diff --git a/drivers/media/tuners/tuner-xc2028-types.h b/drivers/media/tuners/tuner-xc2028-types.h index 74dc46a71f64..7e4798783db7 100644 --- a/drivers/media/tuners/tuner-xc2028-types.h +++ b/drivers/media/tuners/tuner-xc2028-types.h @@ -119,7 +119,7 @@ #define V4L2_STD_A2 (V4L2_STD_A2_A | V4L2_STD_A2_B) #define V4L2_STD_NICAM (V4L2_STD_NICAM_A | V4L2_STD_NICAM_B) -/* To preserve backward compatibilty, +/* To preserve backward compatibility, (std & V4L2_STD_AUDIO) = 0 means that ALL audio stds are supported */ diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index e9d017bea377..528cce958a82 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -1412,8 +1412,8 @@ err_v4l2: usb_set_intfdata(interface, NULL); err_if: usb_put_dev(udev); - kfree(dev); clear_bit(dev->devno, &cx231xx_devused); + kfree(dev); return retval; } diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c index c8fcd78425bd..8f9b2cea88f0 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.c +++ b/drivers/media/usb/dvb-usb-v2/af9035.c @@ -131,7 +131,7 @@ static int af9035_wr_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len) { u8 wbuf[MAX_XFER_SIZE]; u8 mbox = (reg >> 16) & 0xff; - struct usb_req req = { CMD_MEM_WR, mbox, sizeof(wbuf), wbuf, 0, NULL }; + struct usb_req req = { CMD_MEM_WR, mbox, 6 + len, wbuf, 0, NULL }; if (6 + len > sizeof(wbuf)) { dev_warn(&d->udev->dev, "%s: i2c wr: len=%d is too big!\n", @@ -238,14 +238,15 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap, } else { /* I2C */ u8 buf[MAX_XFER_SIZE]; - struct usb_req req = { CMD_I2C_RD, 0, sizeof(buf), + struct usb_req req = { CMD_I2C_RD, 0, 5 + msg[0].len, buf, msg[1].len, msg[1].buf }; if (5 + msg[0].len > sizeof(buf)) { dev_warn(&d->udev->dev, "%s: i2c xfer: len=%d is too big!\n", KBUILD_MODNAME, msg[0].len); - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; + goto unlock; } req.mbox |= ((msg[0].addr & 0x80) >> 3); buf[0] = msg[1].len; @@ -274,14 +275,15 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap, } else { /* I2C */ u8 buf[MAX_XFER_SIZE]; - struct usb_req req = { CMD_I2C_WR, 0, sizeof(buf), buf, - 0, NULL }; + struct usb_req req = { CMD_I2C_WR, 0, 5 + msg[0].len, + buf, 0, NULL }; if (5 + msg[0].len > sizeof(buf)) { dev_warn(&d->udev->dev, "%s: i2c xfer: len=%d is too big!\n", KBUILD_MODNAME, msg[0].len); - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; + goto unlock; } req.mbox |= ((msg[0].addr & 0x80) >> 3); buf[0] = msg[0].len; @@ -319,6 +321,7 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap, ret = -EOPNOTSUPP; } +unlock: mutex_unlock(&d->i2c_mutex); if (ret < 0) @@ -1534,6 +1537,8 @@ static const struct usb_device_id af9035_id_table[] = { /* XXX: that same ID [0ccd:0099] is used by af9015 driver too */ { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x0099, &af9035_props, "TerraTec Cinergy T Stick Dual RC (rev. 2)", NULL) }, + { DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6a05, + &af9035_props, "Leadtek WinFast DTV Dongle Dual", NULL) }, { } }; MODULE_DEVICE_TABLE(usb, af9035_id_table); diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c index 2627553f7de1..08240e498451 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c @@ -266,7 +266,7 @@ static int mxl111sf_adap_fe_init(struct dvb_frontend *fe) struct mxl111sf_adap_state *adap_state = &state->adap_state[fe->id]; int err; - /* exit if we didnt initialize the driver yet */ + /* exit if we didn't initialize the driver yet */ if (!state->chip_id) { mxl_debug("driver not yet initialized, exit."); goto fail; @@ -322,7 +322,7 @@ static int mxl111sf_adap_fe_sleep(struct dvb_frontend *fe) struct mxl111sf_adap_state *adap_state = &state->adap_state[fe->id]; int err; - /* exit if we didnt initialize the driver yet */ + /* exit if we didn't initialize the driver yet */ if (!state->chip_id) { mxl_debug("driver not yet initialized, exit."); goto fail; diff --git a/drivers/media/usb/dvb-usb/technisat-usb2.c b/drivers/media/usb/dvb-usb/technisat-usb2.c index 40832a1aef6c..98d24aefb640 100644 --- a/drivers/media/usb/dvb-usb/technisat-usb2.c +++ b/drivers/media/usb/dvb-usb/technisat-usb2.c @@ -102,7 +102,7 @@ static int technisat_usb2_i2c_access(struct usb_device *udev, if (rxlen > 62) { err("i2c RX buffer can't exceed 62 bytes (dev 0x%02x)", device_addr); - txlen = 62; + rxlen = 62; } b[0] = I2C_SPEED_100KHZ_BIT; diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index fc5d60efd4ab..dd19c9ff76e0 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -1664,8 +1664,8 @@ static int em28xx_v4l2_close(struct file *filp) em28xx_videodbg("users=%d\n", dev->users); - mutex_lock(&dev->lock); vb2_fop_release(filp); + mutex_lock(&dev->lock); if (dev->users == 1) { /* the device is already disconnect, diff --git a/drivers/media/usb/gspca/gl860/gl860.c b/drivers/media/usb/gspca/gl860/gl860.c index cb1e64ca59c9..cea8d7f51c3c 100644 --- a/drivers/media/usb/gspca/gl860/gl860.c +++ b/drivers/media/usb/gspca/gl860/gl860.c @@ -438,7 +438,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, s32 nToSkip = sd->swapRB * (gspca_dev->cam.cam_mode[mode].bytesperline + 1); - /* Test only against 0202h, so endianess does not matter */ + /* Test only against 0202h, so endianness does not matter */ switch (*(s16 *) data) { case 0x0202: /* End of frame, start a new one */ gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); diff --git a/drivers/media/usb/gspca/pac207.c b/drivers/media/usb/gspca/pac207.c index cd79c180f67b..07529e5a0c56 100644 --- a/drivers/media/usb/gspca/pac207.c +++ b/drivers/media/usb/gspca/pac207.c @@ -416,7 +416,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, #if IS_ENABLED(CONFIG_INPUT) static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, /* interrupt packet data */ - int len) /* interrput packet length */ + int len) /* interrupt packet length */ { int ret = -EINVAL; diff --git a/drivers/media/usb/gspca/pac7302.c b/drivers/media/usb/gspca/pac7302.c index a91509643563..2fd1c5e31a0f 100644 --- a/drivers/media/usb/gspca/pac7302.c +++ b/drivers/media/usb/gspca/pac7302.c @@ -874,7 +874,7 @@ static int sd_dbg_s_register(struct gspca_dev *gspca_dev, #if IS_ENABLED(CONFIG_INPUT) static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, /* interrupt packet data */ - int len) /* interrput packet length */ + int len) /* interrupt packet length */ { int ret = -EINVAL; u8 data0, data1; diff --git a/drivers/media/usb/gspca/stk1135.c b/drivers/media/usb/gspca/stk1135.c index 1fc80af2a189..48234c9a8b6c 100644 --- a/drivers/media/usb/gspca/stk1135.c +++ b/drivers/media/usb/gspca/stk1135.c @@ -361,6 +361,9 @@ static void stk1135_configure_clock(struct gspca_dev *gspca_dev) /* set serial interface clock divider (30MHz/0x1f*16+2) = 60240 kHz) */ reg_w(gspca_dev, STK1135_REG_SICTL + 2, 0x1f); + + /* wait a while for sensor to catch up */ + udelay(1000); } static void stk1135_camera_disable(struct gspca_dev *gspca_dev) diff --git a/drivers/media/usb/gspca/stv0680.c b/drivers/media/usb/gspca/stv0680.c index 9c0827631b9c..7f94ec74282e 100644 --- a/drivers/media/usb/gspca/stv0680.c +++ b/drivers/media/usb/gspca/stv0680.c @@ -139,7 +139,7 @@ static int sd_config(struct gspca_dev *gspca_dev, struct sd *sd = (struct sd *) gspca_dev; struct cam *cam = &gspca_dev->cam; - /* Give the camera some time to settle, otherwise initalization will + /* Give the camera some time to settle, otherwise initialization will fail on hotplug, and yes it really needs a full second. */ msleep(1000); diff --git a/drivers/media/usb/gspca/sunplus.c b/drivers/media/usb/gspca/sunplus.c index a517d185febe..46c9f2229a18 100644 --- a/drivers/media/usb/gspca/sunplus.c +++ b/drivers/media/usb/gspca/sunplus.c @@ -1027,6 +1027,7 @@ static const struct usb_device_id device_table[] = { {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)}, {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)}, {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)}, + {USB_DEVICE(0x06d6, 0x0041), BS(SPCA504B, 0)}, {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)}, {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)}, {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)}, diff --git a/drivers/media/usb/gspca/zc3xx.c b/drivers/media/usb/gspca/zc3xx.c index 7b95d8e88a20..d3e1b6d8bf49 100644 --- a/drivers/media/usb/gspca/zc3xx.c +++ b/drivers/media/usb/gspca/zc3xx.c @@ -6905,7 +6905,7 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev, #if IS_ENABLED(CONFIG_INPUT) static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, /* interrupt packet data */ - int len) /* interrput packet length */ + int len) /* interrupt packet length */ { if (len == 8 && data[4] == 1) { input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c index 77bbf7889659..78c9bc8e7f56 100644 --- a/drivers/media/usb/pwc/pwc-if.c +++ b/drivers/media/usb/pwc/pwc-if.c @@ -1039,7 +1039,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id /* Set the leds off */ pwc_set_leds(pdev, 0, 0); - /* Setup intial videomode */ + /* Setup initial videomode */ rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT, V4L2_PIX_FMT_YUV420, 30, &compression, 1); if (rc) diff --git a/drivers/media/usb/usbtv/usbtv.c b/drivers/media/usb/usbtv/usbtv.c index 8a505a90d318..6222a4ab1e00 100644 --- a/drivers/media/usb/usbtv/usbtv.c +++ b/drivers/media/usb/usbtv/usbtv.c @@ -50,13 +50,8 @@ #define USBTV_ISOC_TRANSFERS 16 #define USBTV_ISOC_PACKETS 8 -#define USBTV_WIDTH 720 -#define USBTV_HEIGHT 480 - #define USBTV_CHUNK_SIZE 256 #define USBTV_CHUNK 240 -#define USBTV_CHUNKS (USBTV_WIDTH * USBTV_HEIGHT \ - / 4 / USBTV_CHUNK) /* Chunk header. */ #define USBTV_MAGIC_OK(chunk) ((be32_to_cpu(chunk[0]) & 0xff000000) \ @@ -65,6 +60,27 @@ #define USBTV_ODD(chunk) ((be32_to_cpu(chunk[0]) & 0x0000f000) >> 15) #define USBTV_CHUNK_NO(chunk) (be32_to_cpu(chunk[0]) & 0x00000fff) +#define USBTV_TV_STD (V4L2_STD_525_60 | V4L2_STD_PAL) + +/* parameters for supported TV norms */ +struct usbtv_norm_params { + v4l2_std_id norm; + int cap_width, cap_height; +}; + +static struct usbtv_norm_params norm_params[] = { + { + .norm = V4L2_STD_525_60, + .cap_width = 720, + .cap_height = 480, + }, + { + .norm = V4L2_STD_PAL, + .cap_width = 720, + .cap_height = 576, + } +}; + /* A single videobuf2 frame buffer. */ struct usbtv_buf { struct vb2_buffer vb; @@ -94,11 +110,38 @@ struct usbtv { USBTV_COMPOSITE_INPUT, USBTV_SVIDEO_INPUT, } input; + v4l2_std_id norm; + int width, height; + int n_chunks; int iso_size; unsigned int sequence; struct urb *isoc_urbs[USBTV_ISOC_TRANSFERS]; }; +static int usbtv_configure_for_norm(struct usbtv *usbtv, v4l2_std_id norm) +{ + int i, ret = 0; + struct usbtv_norm_params *params = NULL; + + for (i = 0; i < ARRAY_SIZE(norm_params); i++) { + if (norm_params[i].norm & norm) { + params = &norm_params[i]; + break; + } + } + + if (params) { + usbtv->width = params->cap_width; + usbtv->height = params->cap_height; + usbtv->n_chunks = usbtv->width * usbtv->height + / 4 / USBTV_CHUNK; + usbtv->norm = params->norm; + } else + ret = -EINVAL; + + return ret; +} + static int usbtv_set_regs(struct usbtv *usbtv, const u16 regs[][2], int size) { int ret; @@ -158,6 +201,57 @@ static int usbtv_select_input(struct usbtv *usbtv, int input) return ret; } +static int usbtv_select_norm(struct usbtv *usbtv, v4l2_std_id norm) +{ + int ret; + static const u16 pal[][2] = { + { USBTV_BASE + 0x001a, 0x0068 }, + { USBTV_BASE + 0x010e, 0x0072 }, + { USBTV_BASE + 0x010f, 0x00a2 }, + { USBTV_BASE + 0x0112, 0x00b0 }, + { USBTV_BASE + 0x0117, 0x0001 }, + { USBTV_BASE + 0x0118, 0x002c }, + { USBTV_BASE + 0x012d, 0x0010 }, + { USBTV_BASE + 0x012f, 0x0020 }, + { USBTV_BASE + 0x024f, 0x0002 }, + { USBTV_BASE + 0x0254, 0x0059 }, + { USBTV_BASE + 0x025a, 0x0016 }, + { USBTV_BASE + 0x025b, 0x0035 }, + { USBTV_BASE + 0x0263, 0x0017 }, + { USBTV_BASE + 0x0266, 0x0016 }, + { USBTV_BASE + 0x0267, 0x0036 } + }; + + static const u16 ntsc[][2] = { + { USBTV_BASE + 0x001a, 0x0079 }, + { USBTV_BASE + 0x010e, 0x0068 }, + { USBTV_BASE + 0x010f, 0x009c }, + { USBTV_BASE + 0x0112, 0x00f0 }, + { USBTV_BASE + 0x0117, 0x0000 }, + { USBTV_BASE + 0x0118, 0x00fc }, + { USBTV_BASE + 0x012d, 0x0004 }, + { USBTV_BASE + 0x012f, 0x0008 }, + { USBTV_BASE + 0x024f, 0x0001 }, + { USBTV_BASE + 0x0254, 0x005f }, + { USBTV_BASE + 0x025a, 0x0012 }, + { USBTV_BASE + 0x025b, 0x0001 }, + { USBTV_BASE + 0x0263, 0x001c }, + { USBTV_BASE + 0x0266, 0x0011 }, + { USBTV_BASE + 0x0267, 0x0005 } + }; + + ret = usbtv_configure_for_norm(usbtv, norm); + + if (!ret) { + if (norm & V4L2_STD_525_60) + ret = usbtv_set_regs(usbtv, ntsc, ARRAY_SIZE(ntsc)); + else if (norm & V4L2_STD_PAL) + ret = usbtv_set_regs(usbtv, pal, ARRAY_SIZE(pal)); + } + + return ret; +} + static int usbtv_setup_capture(struct usbtv *usbtv) { int ret; @@ -225,26 +319,11 @@ static int usbtv_setup_capture(struct usbtv *usbtv) { USBTV_BASE + 0x0284, 0x0088 }, { USBTV_BASE + 0x0003, 0x0004 }, - { USBTV_BASE + 0x001a, 0x0079 }, { USBTV_BASE + 0x0100, 0x00d3 }, - { USBTV_BASE + 0x010e, 0x0068 }, - { USBTV_BASE + 0x010f, 0x009c }, - { USBTV_BASE + 0x0112, 0x00f0 }, { USBTV_BASE + 0x0115, 0x0015 }, - { USBTV_BASE + 0x0117, 0x0000 }, - { USBTV_BASE + 0x0118, 0x00fc }, - { USBTV_BASE + 0x012d, 0x0004 }, - { USBTV_BASE + 0x012f, 0x0008 }, { USBTV_BASE + 0x0220, 0x002e }, { USBTV_BASE + 0x0225, 0x0008 }, { USBTV_BASE + 0x024e, 0x0002 }, - { USBTV_BASE + 0x024f, 0x0001 }, - { USBTV_BASE + 0x0254, 0x005f }, - { USBTV_BASE + 0x025a, 0x0012 }, - { USBTV_BASE + 0x025b, 0x0001 }, - { USBTV_BASE + 0x0263, 0x001c }, - { USBTV_BASE + 0x0266, 0x0011 }, - { USBTV_BASE + 0x0267, 0x0005 }, { USBTV_BASE + 0x024e, 0x0002 }, { USBTV_BASE + 0x024f, 0x0002 }, }; @@ -253,6 +332,10 @@ static int usbtv_setup_capture(struct usbtv *usbtv) if (ret) return ret; + ret = usbtv_select_norm(usbtv, usbtv->norm); + if (ret) + return ret; + ret = usbtv_select_input(usbtv, usbtv->input); if (ret) return ret; @@ -296,7 +379,7 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk) frame_id = USBTV_FRAME_ID(chunk); odd = USBTV_ODD(chunk); chunk_no = USBTV_CHUNK_NO(chunk); - if (chunk_no >= USBTV_CHUNKS) + if (chunk_no >= usbtv->n_chunks) return; /* Beginning of a frame. */ @@ -324,10 +407,10 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk) usbtv->chunks_done++; /* Last chunk in a frame, signalling an end */ - if (odd && chunk_no == USBTV_CHUNKS-1) { + if (odd && chunk_no == usbtv->n_chunks-1) { int size = vb2_plane_size(&buf->vb, 0); enum vb2_buffer_state state = usbtv->chunks_done == - USBTV_CHUNKS ? + usbtv->n_chunks ? VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR; @@ -500,6 +583,8 @@ static int usbtv_querycap(struct file *file, void *priv, static int usbtv_enum_input(struct file *file, void *priv, struct v4l2_input *i) { + struct usbtv *dev = video_drvdata(file); + switch (i->index) { case USBTV_COMPOSITE_INPUT: strlcpy(i->name, "Composite", sizeof(i->name)); @@ -512,7 +597,7 @@ static int usbtv_enum_input(struct file *file, void *priv, } i->type = V4L2_INPUT_TYPE_CAMERA; - i->std = V4L2_STD_525_60; + i->std = dev->vdev.tvnorms; return 0; } @@ -531,23 +616,37 @@ static int usbtv_enum_fmt_vid_cap(struct file *file, void *priv, static int usbtv_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - f->fmt.pix.width = USBTV_WIDTH; - f->fmt.pix.height = USBTV_HEIGHT; + struct usbtv *usbtv = video_drvdata(file); + + f->fmt.pix.width = usbtv->width; + f->fmt.pix.height = usbtv->height; f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; f->fmt.pix.field = V4L2_FIELD_INTERLACED; - f->fmt.pix.bytesperline = USBTV_WIDTH * 2; + f->fmt.pix.bytesperline = usbtv->width * 2; f->fmt.pix.sizeimage = (f->fmt.pix.bytesperline * f->fmt.pix.height); f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - f->fmt.pix.priv = 0; + return 0; } static int usbtv_g_std(struct file *file, void *priv, v4l2_std_id *norm) { - *norm = V4L2_STD_525_60; + struct usbtv *usbtv = video_drvdata(file); + *norm = usbtv->norm; return 0; } +static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm) +{ + int ret = -EINVAL; + struct usbtv *usbtv = video_drvdata(file); + + if ((norm & V4L2_STD_525_60) || (norm & V4L2_STD_PAL)) + ret = usbtv_select_norm(usbtv, norm); + + return ret; +} + static int usbtv_g_input(struct file *file, void *priv, unsigned int *i) { struct usbtv *usbtv = video_drvdata(file); @@ -561,13 +660,6 @@ static int usbtv_s_input(struct file *file, void *priv, unsigned int i) return usbtv_select_input(usbtv, i); } -static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm) -{ - if (norm & V4L2_STD_525_60) - return 0; - return -EINVAL; -} - struct v4l2_ioctl_ops usbtv_ioctl_ops = { .vidioc_querycap = usbtv_querycap, .vidioc_enum_input = usbtv_enum_input, @@ -604,10 +696,12 @@ static int usbtv_queue_setup(struct vb2_queue *vq, const struct v4l2_format *v4l_fmt, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { + struct usbtv *usbtv = vb2_get_drv_priv(vq); + if (*nbuffers < 2) *nbuffers = 2; *nplanes = 1; - sizes[0] = USBTV_WIDTH * USBTV_HEIGHT / 2 * sizeof(u32); + sizes[0] = USBTV_CHUNK * usbtv->n_chunks * 2 * sizeof(u32); return 0; } @@ -690,7 +784,11 @@ static int usbtv_probe(struct usb_interface *intf, return -ENOMEM; usbtv->dev = dev; usbtv->udev = usb_get_dev(interface_to_usbdev(intf)); + usbtv->iso_size = size; + + (void)usbtv_configure_for_norm(usbtv, V4L2_STD_525_60); + spin_lock_init(&usbtv->buflock); mutex_init(&usbtv->v4l2_lock); mutex_init(&usbtv->vb2q_lock); @@ -727,7 +825,7 @@ static int usbtv_probe(struct usb_interface *intf, usbtv->vdev.release = video_device_release_empty; usbtv->vdev.fops = &usbtv_fops; usbtv->vdev.ioctl_ops = &usbtv_ioctl_ops; - usbtv->vdev.tvnorms = V4L2_STD_525_60; + usbtv->vdev.tvnorms = USBTV_TV_STD; usbtv->vdev.queue = &usbtv->vb2q; usbtv->vdev.lock = &usbtv->v4l2_lock; set_bit(V4L2_FL_USE_FH_PRIO, &usbtv->vdev.flags); diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index 899cb6d1c4a4..898c208889cd 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -556,7 +556,7 @@ static u16 uvc_video_clock_host_sof(const struct uvc_clock_sample *sample) * * SOF = ((SOF2 - SOF1) * PTS + SOF1 * STC2 - SOF2 * STC1) / (STC2 - STC1) (1) * - * to avoid loosing precision in the division. Similarly, the host timestamp is + * to avoid losing precision in the division. Similarly, the host timestamp is * computed with * * TS = ((TS2 - TS1) * PTS + TS1 * SOF2 - TS2 * SOF1) / (SOF2 - SOF1) (2) diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 60dcc0f3b32e..fb46790d0eca 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -420,7 +420,7 @@ const char * const *v4l2_ctrl_get_menu(u32 id) "Advanced Simple", "Core", "Simple Scalable", - "Advanced Coding Efficency", + "Advanced Coding Efficiency", NULL, }; diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index b19b306c8f7f..0edc165f418d 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -145,6 +145,25 @@ static void __vb2_buf_dmabuf_put(struct vb2_buffer *vb) } /** + * __setup_lengths() - setup initial lengths for every plane in + * every buffer on the queue + */ +static void __setup_lengths(struct vb2_queue *q, unsigned int n) +{ + unsigned int buffer, plane; + struct vb2_buffer *vb; + + for (buffer = q->num_buffers; buffer < q->num_buffers + n; ++buffer) { + vb = q->bufs[buffer]; + if (!vb) + continue; + + for (plane = 0; plane < vb->num_planes; ++plane) + vb->v4l2_planes[plane].length = q->plane_sizes[plane]; + } +} + +/** * __setup_offsets() - setup unique offsets ("cookies") for every plane in * every buffer on the queue */ @@ -169,7 +188,6 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n) continue; for (plane = 0; plane < vb->num_planes; ++plane) { - vb->v4l2_planes[plane].length = q->plane_sizes[plane]; vb->v4l2_planes[plane].m.mem_offset = off; dprintk(3, "Buffer %d, plane %d offset 0x%08lx\n", @@ -241,6 +259,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory, q->bufs[q->num_buffers + buffer] = vb; } + __setup_lengths(q, buffer); if (memory == V4L2_MEMORY_MMAP) __setup_offsets(q, buffer); @@ -1824,8 +1843,8 @@ int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb) return -EINVAL; } - if (eb->flags & ~O_CLOEXEC) { - dprintk(1, "Queue does support only O_CLOEXEC flag\n"); + if (eb->flags & ~(O_CLOEXEC | O_ACCMODE)) { + dprintk(1, "Queue does support only O_CLOEXEC and access mode flags\n"); return -EINVAL; } @@ -1848,14 +1867,14 @@ int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb) vb_plane = &vb->planes[eb->plane]; - dbuf = call_memop(q, get_dmabuf, vb_plane->mem_priv); + dbuf = call_memop(q, get_dmabuf, vb_plane->mem_priv, eb->flags & O_ACCMODE); if (IS_ERR_OR_NULL(dbuf)) { dprintk(1, "Failed to export buffer %d, plane %d\n", eb->index, eb->plane); return -EINVAL; } - ret = dma_buf_fd(dbuf, eb->flags); + ret = dma_buf_fd(dbuf, eb->flags & ~O_ACCMODE); if (ret < 0) { dprintk(3, "buffer %d, plane %d failed to export (%d)\n", eb->index, eb->plane, ret); diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c index 646f08f4f504..33d3871d1e13 100644 --- a/drivers/media/v4l2-core/videobuf2-dma-contig.c +++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c @@ -393,7 +393,7 @@ static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf) return sgt; } -static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv) +static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv, unsigned long flags) { struct vb2_dc_buf *buf = buf_priv; struct dma_buf *dbuf; @@ -404,7 +404,7 @@ static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv) if (WARN_ON(!buf->sgt_base)) return NULL; - dbuf = dma_buf_export(buf, &vb2_dc_dmabuf_ops, buf->size, 0); + dbuf = dma_buf_export(buf, &vb2_dc_dmabuf_ops, buf->size, flags); if (IS_ERR(dbuf)) return NULL; diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c index 2f860543912c..0d3a8ffe47a3 100644 --- a/drivers/media/v4l2-core/videobuf2-dma-sg.c +++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c @@ -178,7 +178,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr, buf->pages = kzalloc(buf->num_pages * sizeof(struct page *), GFP_KERNEL); if (!buf->pages) - return NULL; + goto userptr_fail_alloc_pages; num_pages_from_user = get_user_pages(current, current->mm, vaddr & PAGE_MASK, @@ -204,6 +204,7 @@ userptr_fail_get_user_pages: while (--num_pages_from_user >= 0) put_page(buf->pages[num_pages_from_user]); kfree(buf->pages); +userptr_fail_alloc_pages: kfree(buf); return NULL; } diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 62a60caa5d1f..dd671582c9a1 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -32,7 +32,7 @@ config MFD_AS3722 select MFD_CORE select REGMAP_I2C select REGMAP_IRQ - depends on I2C && OF + depends on I2C=y && OF help The ams AS3722 is a compact system PMU suitable for mobile phones, tablets etc. It has 4 DC/DC step-down regulators, 3 DC/DC step-down diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c index da1c6566d93d..37edf9e989b0 100644 --- a/drivers/mfd/lpc_ich.c +++ b/drivers/mfd/lpc_ich.c @@ -506,7 +506,7 @@ static struct lpc_ich_info lpc_chipset_info[] = { .iTCO_version = 2, }, [LPC_WPT_LP] = { - .name = "Lynx Point_LP", + .name = "Wildcat Point_LP", .iTCO_version = 2, }, }; diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index 34c18fb8c089..54cc25546592 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -81,31 +81,31 @@ static struct of_device_id sec_dt_match[] = { int sec_reg_read(struct sec_pmic_dev *sec_pmic, u8 reg, void *dest) { - return regmap_read(sec_pmic->regmap, reg, dest); + return regmap_read(sec_pmic->regmap_pmic, reg, dest); } EXPORT_SYMBOL_GPL(sec_reg_read); int sec_bulk_read(struct sec_pmic_dev *sec_pmic, u8 reg, int count, u8 *buf) { - return regmap_bulk_read(sec_pmic->regmap, reg, buf, count); + return regmap_bulk_read(sec_pmic->regmap_pmic, reg, buf, count); } EXPORT_SYMBOL_GPL(sec_bulk_read); int sec_reg_write(struct sec_pmic_dev *sec_pmic, u8 reg, u8 value) { - return regmap_write(sec_pmic->regmap, reg, value); + return regmap_write(sec_pmic->regmap_pmic, reg, value); } EXPORT_SYMBOL_GPL(sec_reg_write); int sec_bulk_write(struct sec_pmic_dev *sec_pmic, u8 reg, int count, u8 *buf) { - return regmap_raw_write(sec_pmic->regmap, reg, buf, count); + return regmap_raw_write(sec_pmic->regmap_pmic, reg, buf, count); } EXPORT_SYMBOL_GPL(sec_bulk_write); int sec_reg_update(struct sec_pmic_dev *sec_pmic, u8 reg, u8 val, u8 mask) { - return regmap_update_bits(sec_pmic->regmap, reg, mask, val); + return regmap_update_bits(sec_pmic->regmap_pmic, reg, mask, val); } EXPORT_SYMBOL_GPL(sec_reg_update); @@ -166,6 +166,11 @@ static struct regmap_config s5m8767_regmap_config = { .cache_type = REGCACHE_FLAT, }; +static const struct regmap_config sec_rtc_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; + #ifdef CONFIG_OF /* * Only the common platform data elements for s5m8767 are parsed here from the @@ -266,9 +271,9 @@ static int sec_pmic_probe(struct i2c_client *i2c, break; } - sec_pmic->regmap = devm_regmap_init_i2c(i2c, regmap); - if (IS_ERR(sec_pmic->regmap)) { - ret = PTR_ERR(sec_pmic->regmap); + sec_pmic->regmap_pmic = devm_regmap_init_i2c(i2c, regmap); + if (IS_ERR(sec_pmic->regmap_pmic)) { + ret = PTR_ERR(sec_pmic->regmap_pmic); dev_err(&i2c->dev, "Failed to allocate register map: %d\n", ret); return ret; @@ -277,6 +282,15 @@ static int sec_pmic_probe(struct i2c_client *i2c, sec_pmic->rtc = i2c_new_dummy(i2c->adapter, RTC_I2C_ADDR); i2c_set_clientdata(sec_pmic->rtc, sec_pmic); + sec_pmic->regmap_rtc = devm_regmap_init_i2c(sec_pmic->rtc, + &sec_rtc_regmap_config); + if (IS_ERR(sec_pmic->regmap_rtc)) { + ret = PTR_ERR(sec_pmic->regmap_rtc); + dev_err(&i2c->dev, "Failed to allocate RTC register map: %d\n", + ret); + return ret; + } + if (pdata && pdata->cfg_pmic_irq) pdata->cfg_pmic_irq(); diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c index 0dd84e99081e..b441b1be27cb 100644 --- a/drivers/mfd/sec-irq.c +++ b/drivers/mfd/sec-irq.c @@ -280,19 +280,19 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic) switch (type) { case S5M8763X: - ret = regmap_add_irq_chip(sec_pmic->regmap, sec_pmic->irq, + ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, sec_pmic->irq_base, &s5m8763_irq_chip, &sec_pmic->irq_data); break; case S5M8767X: - ret = regmap_add_irq_chip(sec_pmic->regmap, sec_pmic->irq, + ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, sec_pmic->irq_base, &s5m8767_irq_chip, &sec_pmic->irq_data); break; case S2MPS11X: - ret = regmap_add_irq_chip(sec_pmic->regmap, sec_pmic->irq, + ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, sec_pmic->irq_base, &s2mps11_irq_chip, &sec_pmic->irq_data); diff --git a/drivers/mfd/ti-ssp.c b/drivers/mfd/ti-ssp.c index 71e3e0c5bf73..a5424579679c 100644 --- a/drivers/mfd/ti-ssp.c +++ b/drivers/mfd/ti-ssp.c @@ -32,6 +32,7 @@ #include <linux/platform_device.h> #include <linux/delay.h> #include <linux/io.h> +#include <linux/sched.h> #include <linux/mfd/core.h> #include <linux/mfd/ti_ssp.h> @@ -409,7 +410,6 @@ static int ti_ssp_probe(struct platform_device *pdev) cells[id].id = id; cells[id].name = data->dev_name; cells[id].platform_data = data->pdata; - cells[id].data_size = data->pdata_size; } error = mfd_add_devices(dev, 0, cells, 2, NULL, 0, NULL); diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h index 6c0fde55270d..66f411a6e8ea 100644 --- a/drivers/misc/mei/hw-me-regs.h +++ b/drivers/misc/mei/hw-me-regs.h @@ -109,9 +109,12 @@ #define MEI_DEV_ID_PPT_2 0x1CBA /* Panther Point */ #define MEI_DEV_ID_PPT_3 0x1DBA /* Panther Point */ -#define MEI_DEV_ID_LPT 0x8C3A /* Lynx Point */ +#define MEI_DEV_ID_LPT_H 0x8C3A /* Lynx Point H */ #define MEI_DEV_ID_LPT_W 0x8D3A /* Lynx Point - Wellsburg */ #define MEI_DEV_ID_LPT_LP 0x9C3A /* Lynx Point LP */ +#define MEI_DEV_ID_LPT_HR 0x8CBA /* Lynx Point H Refresh */ + +#define MEI_DEV_ID_WPT_LP 0x9CBA /* Wildcat Point LP */ /* * MEI HW Section */ diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index b96205aece0c..2cab3c0a6805 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -76,9 +76,11 @@ static DEFINE_PCI_DEVICE_TABLE(mei_me_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_1)}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_2)}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_3)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT_H)}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT_W)}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT_LP)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT_HR)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_WPT_LP)}, /* required last entry */ {0, } diff --git a/drivers/misc/mic/card/mic_virtio.c b/drivers/misc/mic/card/mic_virtio.c index 8aa42e738acc..653799b96bfa 100644 --- a/drivers/misc/mic/card/mic_virtio.c +++ b/drivers/misc/mic/card/mic_virtio.c @@ -154,14 +154,14 @@ static void mic_reset_inform_host(struct virtio_device *vdev) { struct mic_vdev *mvdev = to_micvdev(vdev); struct mic_device_ctrl __iomem *dc = mvdev->dc; - int retry = 100, i; + int retry; iowrite8(0, &dc->host_ack); iowrite8(1, &dc->vdev_reset); mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db); /* Wait till host completes all card accesses and acks the reset */ - for (i = retry; i--;) { + for (retry = 100; retry--;) { if (ioread8(&dc->host_ack)) break; msleep(100); @@ -187,11 +187,12 @@ static void mic_reset(struct virtio_device *vdev) /* * The virtio_ring code calls this API when it wants to notify the Host. */ -static void mic_notify(struct virtqueue *vq) +static bool mic_notify(struct virtqueue *vq) { struct mic_vdev *mvdev = vq->priv; mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db); + return true; } static void mic_del_vq(struct virtqueue *vq, int n) @@ -247,17 +248,17 @@ static struct virtqueue *mic_find_vq(struct virtio_device *vdev, /* First assign the vring's allocated in host memory */ vqconfig = mic_vq_config(mvdev->desc) + index; memcpy_fromio(&config, vqconfig, sizeof(config)); - _vr_size = vring_size(config.num, MIC_VIRTIO_RING_ALIGN); + _vr_size = vring_size(le16_to_cpu(config.num), MIC_VIRTIO_RING_ALIGN); vr_size = PAGE_ALIGN(_vr_size + sizeof(struct _mic_vring_info)); - va = mic_card_map(mvdev->mdev, config.address, vr_size); + va = mic_card_map(mvdev->mdev, le64_to_cpu(config.address), vr_size); if (!va) return ERR_PTR(-ENOMEM); mvdev->vr[index] = va; memset_io(va, 0x0, _vr_size); - vq = vring_new_virtqueue(index, - config.num, MIC_VIRTIO_RING_ALIGN, vdev, - false, - va, mic_notify, callback, name); + vq = vring_new_virtqueue(index, le16_to_cpu(config.num), + MIC_VIRTIO_RING_ALIGN, vdev, false, + (void __force *)va, mic_notify, callback, + name); if (!vq) { err = -ENOMEM; goto unmap; @@ -272,7 +273,8 @@ static struct virtqueue *mic_find_vq(struct virtio_device *vdev, /* Allocate and reassign used ring now */ mvdev->used_size[index] = PAGE_ALIGN(sizeof(__u16) * 3 + - sizeof(struct vring_used_elem) * config.num); + sizeof(struct vring_used_elem) * + le16_to_cpu(config.num)); used = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, get_order(mvdev->used_size[index])); if (!used) { @@ -309,7 +311,7 @@ static int mic_find_vqs(struct virtio_device *vdev, unsigned nvqs, { struct mic_vdev *mvdev = to_micvdev(vdev); struct mic_device_ctrl __iomem *dc = mvdev->dc; - int i, err, retry = 100; + int i, err, retry; /* We must have this many virtqueues. */ if (nvqs > ioread8(&mvdev->desc->num_vq)) @@ -331,7 +333,7 @@ static int mic_find_vqs(struct virtio_device *vdev, unsigned nvqs, * rings have been re-assigned. */ mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db); - for (i = retry; i--;) { + for (retry = 100; retry--;) { if (!ioread8(&dc->used_address_updated)) break; msleep(100); @@ -519,8 +521,8 @@ static void mic_scan_devices(struct mic_driver *mdrv, bool remove) struct device *dev; int ret; - for (i = mic_aligned_size(struct mic_bootparam); - i < MIC_DP_SIZE; i += mic_total_desc_size(d)) { + for (i = sizeof(struct mic_bootparam); i < MIC_DP_SIZE; + i += mic_total_desc_size(d)) { d = mdrv->dp + i; dc = (void __iomem *)d + mic_aligned_desc_size(d); /* @@ -539,7 +541,8 @@ static void mic_scan_devices(struct mic_driver *mdrv, bool remove) continue; /* device already exists */ - dev = device_find_child(mdrv->dev, d, mic_match_desc); + dev = device_find_child(mdrv->dev, (void __force *)d, + mic_match_desc); if (dev) { if (remove) iowrite8(MIC_VIRTIO_PARAM_DEV_REMOVE, diff --git a/drivers/misc/mic/card/mic_virtio.h b/drivers/misc/mic/card/mic_virtio.h index 2c5c22c93ba8..d0407ba53bb7 100644 --- a/drivers/misc/mic/card/mic_virtio.h +++ b/drivers/misc/mic/card/mic_virtio.h @@ -42,8 +42,8 @@ static inline unsigned mic_desc_size(struct mic_device_desc __iomem *desc) { - return mic_aligned_size(*desc) - + ioread8(&desc->num_vq) * mic_aligned_size(struct mic_vqconfig) + return sizeof(*desc) + + ioread8(&desc->num_vq) * sizeof(struct mic_vqconfig) + ioread8(&desc->feature_len) * 2 + ioread8(&desc->config_len); } @@ -67,8 +67,7 @@ mic_vq_configspace(struct mic_device_desc __iomem *desc) } static inline unsigned mic_total_desc_size(struct mic_device_desc __iomem *desc) { - return mic_aligned_desc_size(desc) + - mic_aligned_size(struct mic_device_ctrl); + return mic_aligned_desc_size(desc) + sizeof(struct mic_device_ctrl); } int mic_devices_init(struct mic_driver *mdrv); diff --git a/drivers/misc/mic/host/mic_boot.c b/drivers/misc/mic/host/mic_boot.c index 7558d9186438..b75c6b5cc20f 100644 --- a/drivers/misc/mic/host/mic_boot.c +++ b/drivers/misc/mic/host/mic_boot.c @@ -62,7 +62,7 @@ void mic_bootparam_init(struct mic_device *mdev) { struct mic_bootparam *bootparam = mdev->dp; - bootparam->magic = MIC_MAGIC; + bootparam->magic = cpu_to_le32(MIC_MAGIC); bootparam->c2h_shutdown_db = mdev->shutdown_db; bootparam->h2c_shutdown_db = -1; bootparam->h2c_config_db = -1; diff --git a/drivers/misc/mic/host/mic_virtio.c b/drivers/misc/mic/host/mic_virtio.c index 5b8494bd1e00..e04bb4fe6823 100644 --- a/drivers/misc/mic/host/mic_virtio.c +++ b/drivers/misc/mic/host/mic_virtio.c @@ -41,7 +41,7 @@ static int mic_virtio_copy_to_user(struct mic_vdev *mvdev, * We are copying from IO below an should ideally use something * like copy_to_user_fromio(..) if it existed. */ - if (copy_to_user(ubuf, dbuf, len)) { + if (copy_to_user(ubuf, (void __force *)dbuf, len)) { err = -EFAULT; dev_err(mic_dev(mvdev), "%s %d err %d\n", __func__, __LINE__, err); @@ -66,7 +66,7 @@ static int mic_virtio_copy_from_user(struct mic_vdev *mvdev, * We are copying to IO below and should ideally use something * like copy_from_user_toio(..) if it existed. */ - if (copy_from_user(dbuf, ubuf, len)) { + if (copy_from_user((void __force *)dbuf, ubuf, len)) { err = -EFAULT; dev_err(mic_dev(mvdev), "%s %d err %d\n", __func__, __LINE__, err); @@ -293,7 +293,7 @@ static void mic_virtio_init_post(struct mic_vdev *mvdev) continue; } mvdev->mvr[i].vrh.vring.used = - mvdev->mdev->aper.va + + (void __force *)mvdev->mdev->aper.va + le64_to_cpu(vqconfig[i].used_address); } @@ -378,7 +378,7 @@ int mic_virtio_config_change(struct mic_vdev *mvdev, void __user *argp) { DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake); - int ret = 0, retry = 100, i; + int ret = 0, retry, i; struct mic_bootparam *bootparam = mvdev->mdev->dp; s8 db = bootparam->h2c_config_db; @@ -401,7 +401,7 @@ int mic_virtio_config_change(struct mic_vdev *mvdev, mvdev->dc->config_change = MIC_VIRTIO_PARAM_CONFIG_CHANGED; mvdev->mdev->ops->send_intr(mvdev->mdev, db); - for (i = retry; i--;) { + for (retry = 100; retry--;) { ret = wait_event_timeout(wake, mvdev->dc->guest_ack, msecs_to_jiffies(100)); if (ret) @@ -467,7 +467,7 @@ static int mic_copy_dp_entry(struct mic_vdev *mvdev, } /* Find the first free device page entry */ - for (i = mic_aligned_size(struct mic_bootparam); + for (i = sizeof(struct mic_bootparam); i < MIC_DP_SIZE - mic_total_desc_size(dd_config); i += mic_total_desc_size(devp)) { devp = mdev->dp + i; @@ -525,6 +525,7 @@ int mic_virtio_add_device(struct mic_vdev *mvdev, char irqname[10]; struct mic_bootparam *bootparam = mdev->dp; u16 num; + dma_addr_t vr_addr; mutex_lock(&mdev->mic_mutex); @@ -559,17 +560,16 @@ int mic_virtio_add_device(struct mic_vdev *mvdev, } vr->len = vr_size; vr->info = vr->va + vring_size(num, MIC_VIRTIO_RING_ALIGN); - vr->info->magic = MIC_MAGIC + mvdev->virtio_id + i; - vqconfig[i].address = mic_map_single(mdev, - vr->va, vr_size); - if (mic_map_error(vqconfig[i].address)) { + vr->info->magic = cpu_to_le32(MIC_MAGIC + mvdev->virtio_id + i); + vr_addr = mic_map_single(mdev, vr->va, vr_size); + if (mic_map_error(vr_addr)) { free_pages((unsigned long)vr->va, get_order(vr_size)); ret = -ENOMEM; dev_err(mic_dev(mvdev), "%s %d err %d\n", __func__, __LINE__, ret); goto err; } - vqconfig[i].address = cpu_to_le64(vqconfig[i].address); + vqconfig[i].address = cpu_to_le64(vr_addr); vring_init(&vr->vr, num, vr->va, MIC_VIRTIO_RING_ALIGN); ret = vringh_init_kern(&mvr->vrh, @@ -639,7 +639,7 @@ void mic_virtio_del_device(struct mic_vdev *mvdev) struct mic_vdev *tmp_mvdev; struct mic_device *mdev = mvdev->mdev; DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake); - int i, ret, retry = 100; + int i, ret, retry; struct mic_vqconfig *vqconfig; struct mic_bootparam *bootparam = mdev->dp; s8 db; @@ -652,16 +652,16 @@ void mic_virtio_del_device(struct mic_vdev *mvdev) "Requesting hot remove id %d\n", mvdev->virtio_id); mvdev->dc->config_change = MIC_VIRTIO_PARAM_DEV_REMOVE; mdev->ops->send_intr(mdev, db); - for (i = retry; i--;) { + for (retry = 100; retry--;) { ret = wait_event_timeout(wake, mvdev->dc->guest_ack, msecs_to_jiffies(100)); if (ret) break; } dev_dbg(mdev->sdev->parent, - "Device id %d config_change %d guest_ack %d\n", + "Device id %d config_change %d guest_ack %d retry %d\n", mvdev->virtio_id, mvdev->dc->config_change, - mvdev->dc->guest_ack); + mvdev->dc->guest_ack, retry); mvdev->dc->config_change = 0; mvdev->dc->guest_ack = 0; skip_hot_remove: diff --git a/drivers/misc/mic/host/mic_x100.c b/drivers/misc/mic/host/mic_x100.c index 81e9541b784c..0dfa8a81436e 100644 --- a/drivers/misc/mic/host/mic_x100.c +++ b/drivers/misc/mic/host/mic_x100.c @@ -397,8 +397,8 @@ mic_x100_load_ramdisk(struct mic_device *mdev) * so copy over the ramdisk @ 128M. */ memcpy_toio(mdev->aper.va + (mdev->bootaddr << 1), fw->data, fw->size); - iowrite32(cpu_to_le32(mdev->bootaddr << 1), &bp->hdr.ramdisk_image); - iowrite32(cpu_to_le32(fw->size), &bp->hdr.ramdisk_size); + iowrite32(mdev->bootaddr << 1, &bp->hdr.ramdisk_image); + iowrite32(fw->size, &bp->hdr.ramdisk_size); release_firmware(fw); error: return rc; diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 4cabdc9fda90..4b3aaa898a8b 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -962,7 +962,7 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info) { struct platform_device *pdev = info->pdev; - if (use_dma) { + if (info->use_dma) { pxa_free_dma(info->data_dma_ch); dma_free_coherent(&pdev->dev, info->buf_size, info->data_buff, info->data_buff_phys); @@ -1259,10 +1259,6 @@ static struct of_device_id pxa3xx_nand_dt_ids[] = { .compatible = "marvell,pxa3xx-nand", .data = (void *)PXA3XX_NAND_VARIANT_PXA, }, - { - .compatible = "marvell,armada370-nand", - .data = (void *)PXA3XX_NAND_VARIANT_ARMADA370, - }, {} }; MODULE_DEVICE_TABLE(of, pxa3xx_nand_dt_ids); diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 36eab0c4fb33..398e299ee1bd 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -4199,9 +4199,9 @@ static int bond_check_params(struct bond_params *params) (arp_ip_count < BOND_MAX_ARP_TARGETS) && arp_ip_target[i]; i++) { /* not complete check, but should be good enough to catch mistakes */ - __be32 ip = in_aton(arp_ip_target[i]); - if (!isdigit(arp_ip_target[i][0]) || ip == 0 || - ip == htonl(INADDR_BROADCAST)) { + __be32 ip; + if (!in4_pton(arp_ip_target[i], -1, (u8 *)&ip, -1, NULL) || + IS_IP_TARGET_UNUSABLE_ADDRESS(ip)) { pr_warning("Warning: bad arp_ip_target module parameter (%s), ARP monitoring will not be performed\n", arp_ip_target[i]); arp_interval = 0; diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index abf5e106edc5..0ae580bbc5db 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -1635,12 +1635,12 @@ static ssize_t bonding_show_packets_per_slave(struct device *d, char *buf) { struct bonding *bond = to_bond(d); - int packets_per_slave = bond->params.packets_per_slave; + unsigned int packets_per_slave = bond->params.packets_per_slave; if (packets_per_slave > 1) packets_per_slave = reciprocal_value(packets_per_slave); - return sprintf(buf, "%d\n", packets_per_slave); + return sprintf(buf, "%u\n", packets_per_slave); } static ssize_t bonding_store_packets_per_slave(struct device *d, diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c index 50b853a79d77..46dfb1378c17 100644 --- a/drivers/net/ethernet/allwinner/sun4i-emac.c +++ b/drivers/net/ethernet/allwinner/sun4i-emac.c @@ -717,8 +717,7 @@ static int emac_open(struct net_device *dev) if (netif_msg_ifup(db)) dev_dbg(db->dev, "enabling %s\n", dev->name); - if (devm_request_irq(db->dev, dev->irq, &emac_interrupt, - 0, dev->name, dev)) + if (request_irq(dev->irq, &emac_interrupt, 0, dev->name, dev)) return -EAGAIN; /* Initialize EMAC board */ @@ -774,6 +773,8 @@ static int emac_stop(struct net_device *ndev) emac_shutdown(ndev); + free_irq(ndev->irq, ndev); + return 0; } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index 0216d592d0ce..2e46c28fc601 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c @@ -3114,6 +3114,11 @@ int bnx2x_sriov_configure(struct pci_dev *dev, int num_vfs_param) { struct bnx2x *bp = netdev_priv(pci_get_drvdata(dev)); + if (!IS_SRIOV(bp)) { + BNX2X_ERR("failed to configure SR-IOV since vfdb was not allocated. Check dmesg for errors in probe stage\n"); + return -EINVAL; + } + DP(BNX2X_MSG_IOV, "bnx2x_sriov_configure called with %d, BNX2X_NR_VIRTFN(bp) was %d\n", num_vfs_param, BNX2X_NR_VIRTFN(bp)); diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 369b736dde05..f3dd93b4aeaa 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -8932,6 +8932,9 @@ static int tg3_chip_reset(struct tg3 *tp) void (*write_op)(struct tg3 *, u32, u32); int i, err; + if (!pci_device_is_present(tp->pdev)) + return -ENODEV; + tg3_nvram_lock(tp); tg3_ape_lock(tp, TG3_APE_LOCK_GRC); @@ -11581,10 +11584,11 @@ static int tg3_close(struct net_device *dev) memset(&tp->net_stats_prev, 0, sizeof(tp->net_stats_prev)); memset(&tp->estats_prev, 0, sizeof(tp->estats_prev)); - tg3_power_down_prepare(tp); - - tg3_carrier_off(tp); + if (pci_device_is_present(tp->pdev)) { + tg3_power_down_prepare(tp); + tg3_carrier_off(tp); + } return 0; } @@ -16499,6 +16503,9 @@ static int tg3_get_invariants(struct tg3 *tp, const struct pci_device_id *ent) /* Clear this out for sanity. */ tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0); + /* Clear TG3PCI_REG_BASE_ADDR to prevent hangs. */ + tw32(TG3PCI_REG_BASE_ADDR, 0); + pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE, &pci_state_reg); if ((pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0 && @@ -17726,10 +17733,12 @@ static int tg3_suspend(struct device *device) struct pci_dev *pdev = to_pci_dev(device); struct net_device *dev = pci_get_drvdata(pdev); struct tg3 *tp = netdev_priv(dev); - int err; + int err = 0; + + rtnl_lock(); if (!netif_running(dev)) - return 0; + goto unlock; tg3_reset_task_cancel(tp); tg3_phy_stop(tp); @@ -17771,6 +17780,8 @@ out: tg3_phy_start(tp); } +unlock: + rtnl_unlock(); return err; } @@ -17779,10 +17790,12 @@ static int tg3_resume(struct device *device) struct pci_dev *pdev = to_pci_dev(device); struct net_device *dev = pci_get_drvdata(pdev); struct tg3 *tp = netdev_priv(dev); - int err; + int err = 0; + + rtnl_lock(); if (!netif_running(dev)) - return 0; + goto unlock; netif_device_attach(dev); @@ -17806,6 +17819,8 @@ out: if (!err) tg3_phy_start(tp); +unlock: + rtnl_unlock(); return err; } #endif /* CONFIG_PM_SLEEP */ diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index ecd2fb3ef695..6c9308850453 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -49,13 +49,15 @@ #include <asm/io.h> #include "cxgb4_uld.h" -#define FW_VERSION_MAJOR 1 -#define FW_VERSION_MINOR 4 -#define FW_VERSION_MICRO 0 +#define T4FW_VERSION_MAJOR 0x01 +#define T4FW_VERSION_MINOR 0x06 +#define T4FW_VERSION_MICRO 0x18 +#define T4FW_VERSION_BUILD 0x00 -#define FW_VERSION_MAJOR_T5 0 -#define FW_VERSION_MINOR_T5 0 -#define FW_VERSION_MICRO_T5 0 +#define T5FW_VERSION_MAJOR 0x01 +#define T5FW_VERSION_MINOR 0x08 +#define T5FW_VERSION_MICRO 0x1C +#define T5FW_VERSION_BUILD 0x00 #define CH_WARN(adap, fmt, ...) dev_warn(adap->pdev_dev, fmt, ## __VA_ARGS__) @@ -240,6 +242,26 @@ struct pci_params { unsigned char width; }; +#define CHELSIO_CHIP_CODE(version, revision) (((version) << 4) | (revision)) +#define CHELSIO_CHIP_FPGA 0x100 +#define CHELSIO_CHIP_VERSION(code) (((code) >> 4) & 0xf) +#define CHELSIO_CHIP_RELEASE(code) ((code) & 0xf) + +#define CHELSIO_T4 0x4 +#define CHELSIO_T5 0x5 + +enum chip_type { + T4_A1 = CHELSIO_CHIP_CODE(CHELSIO_T4, 1), + T4_A2 = CHELSIO_CHIP_CODE(CHELSIO_T4, 2), + T4_FIRST_REV = T4_A1, + T4_LAST_REV = T4_A2, + + T5_A0 = CHELSIO_CHIP_CODE(CHELSIO_T5, 0), + T5_A1 = CHELSIO_CHIP_CODE(CHELSIO_T5, 1), + T5_FIRST_REV = T5_A0, + T5_LAST_REV = T5_A1, +}; + struct adapter_params { struct tp_params tp; struct vpd_params vpd; @@ -259,7 +281,7 @@ struct adapter_params { unsigned char nports; /* # of ethernet ports */ unsigned char portvec; - unsigned char rev; /* chip revision */ + enum chip_type chip; /* chip code */ unsigned char offload; unsigned char bypass; @@ -267,6 +289,23 @@ struct adapter_params { unsigned int ofldq_wr_cred; }; +#include "t4fw_api.h" + +#define FW_VERSION(chip) ( \ + FW_HDR_FW_VER_MAJOR_GET(chip##FW_VERSION_MAJOR) | \ + FW_HDR_FW_VER_MINOR_GET(chip##FW_VERSION_MINOR) | \ + FW_HDR_FW_VER_MICRO_GET(chip##FW_VERSION_MICRO) | \ + FW_HDR_FW_VER_BUILD_GET(chip##FW_VERSION_BUILD)) +#define FW_INTFVER(chip, intf) (FW_HDR_INTFVER_##intf) + +struct fw_info { + u8 chip; + char *fs_name; + char *fw_mod_name; + struct fw_hdr fw_hdr; +}; + + struct trace_params { u32 data[TRACE_LEN / 4]; u32 mask[TRACE_LEN / 4]; @@ -512,25 +551,6 @@ struct sge { struct l2t_data; -#define CHELSIO_CHIP_CODE(version, revision) (((version) << 4) | (revision)) -#define CHELSIO_CHIP_VERSION(code) ((code) >> 4) -#define CHELSIO_CHIP_RELEASE(code) ((code) & 0xf) - -#define CHELSIO_T4 0x4 -#define CHELSIO_T5 0x5 - -enum chip_type { - T4_A1 = CHELSIO_CHIP_CODE(CHELSIO_T4, 0), - T4_A2 = CHELSIO_CHIP_CODE(CHELSIO_T4, 1), - T4_A3 = CHELSIO_CHIP_CODE(CHELSIO_T4, 2), - T4_FIRST_REV = T4_A1, - T4_LAST_REV = T4_A3, - - T5_A1 = CHELSIO_CHIP_CODE(CHELSIO_T5, 0), - T5_FIRST_REV = T5_A1, - T5_LAST_REV = T5_A1, -}; - #ifdef CONFIG_PCI_IOV /* T4 supports SRIOV on PF0-3 and T5 on PF0-7. However, the Serial @@ -715,12 +735,12 @@ enum { static inline int is_t5(enum chip_type chip) { - return (chip >= T5_FIRST_REV && chip <= T5_LAST_REV); + return CHELSIO_CHIP_VERSION(chip) == CHELSIO_T5; } static inline int is_t4(enum chip_type chip) { - return (chip >= T4_FIRST_REV && chip <= T4_LAST_REV); + return CHELSIO_CHIP_VERSION(chip) == CHELSIO_T4; } static inline u32 t4_read_reg(struct adapter *adap, u32 reg_addr) @@ -900,7 +920,11 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p); int t4_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size); unsigned int t4_flash_cfg_addr(struct adapter *adapter); int t4_load_cfg(struct adapter *adapter, const u8 *cfg_data, unsigned int size); -int t4_check_fw_version(struct adapter *adapter); +int t4_get_fw_version(struct adapter *adapter, u32 *vers); +int t4_get_tp_version(struct adapter *adapter, u32 *vers); +int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info, + const u8 *fw_data, unsigned int fw_size, + struct fw_hdr *card_fw, enum dev_state state, int *reset); int t4_prep_adapter(struct adapter *adapter); int t4_port_init(struct adapter *adap, int mbox, int pf, int vf); void t4_fatal_err(struct adapter *adapter); diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 8b929eeecd2d..d6b12e035a7d 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -276,9 +276,9 @@ static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = { { 0, } }; -#define FW_FNAME "cxgb4/t4fw.bin" +#define FW4_FNAME "cxgb4/t4fw.bin" #define FW5_FNAME "cxgb4/t5fw.bin" -#define FW_CFNAME "cxgb4/t4-config.txt" +#define FW4_CFNAME "cxgb4/t4-config.txt" #define FW5_CFNAME "cxgb4/t5-config.txt" MODULE_DESCRIPTION(DRV_DESC); @@ -286,7 +286,7 @@ MODULE_AUTHOR("Chelsio Communications"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_VERSION(DRV_VERSION); MODULE_DEVICE_TABLE(pci, cxgb4_pci_tbl); -MODULE_FIRMWARE(FW_FNAME); +MODULE_FIRMWARE(FW4_FNAME); MODULE_FIRMWARE(FW5_FNAME); /* @@ -1071,72 +1071,6 @@ freeout: t4_free_sge_resources(adap); } /* - * Returns 0 if new FW was successfully loaded, a positive errno if a load was - * started but failed, and a negative errno if flash load couldn't start. - */ -static int upgrade_fw(struct adapter *adap) -{ - int ret; - u32 vers, exp_major; - const struct fw_hdr *hdr; - const struct firmware *fw; - struct device *dev = adap->pdev_dev; - char *fw_file_name; - - switch (CHELSIO_CHIP_VERSION(adap->chip)) { - case CHELSIO_T4: - fw_file_name = FW_FNAME; - exp_major = FW_VERSION_MAJOR; - break; - case CHELSIO_T5: - fw_file_name = FW5_FNAME; - exp_major = FW_VERSION_MAJOR_T5; - break; - default: - dev_err(dev, "Unsupported chip type, %x\n", adap->chip); - return -EINVAL; - } - - ret = request_firmware(&fw, fw_file_name, dev); - if (ret < 0) { - dev_err(dev, "unable to load firmware image %s, error %d\n", - fw_file_name, ret); - return ret; - } - - hdr = (const struct fw_hdr *)fw->data; - vers = ntohl(hdr->fw_ver); - if (FW_HDR_FW_VER_MAJOR_GET(vers) != exp_major) { - ret = -EINVAL; /* wrong major version, won't do */ - goto out; - } - - /* - * If the flash FW is unusable or we found something newer, load it. - */ - if (FW_HDR_FW_VER_MAJOR_GET(adap->params.fw_vers) != exp_major || - vers > adap->params.fw_vers) { - dev_info(dev, "upgrading firmware ...\n"); - ret = t4_fw_upgrade(adap, adap->mbox, fw->data, fw->size, - /*force=*/false); - if (!ret) - dev_info(dev, - "firmware upgraded to version %pI4 from %s\n", - &hdr->fw_ver, fw_file_name); - else - dev_err(dev, "firmware upgrade failed! err=%d\n", -ret); - } else { - /* - * Tell our caller that we didn't upgrade the firmware. - */ - ret = -EINVAL; - } - -out: release_firmware(fw); - return ret; -} - -/* * Allocate a chunk of memory using kmalloc or, if that fails, vmalloc. * The allocated memory is cleared. */ @@ -1415,7 +1349,7 @@ static int get_sset_count(struct net_device *dev, int sset) static int get_regs_len(struct net_device *dev) { struct adapter *adap = netdev2adap(dev); - if (is_t4(adap->chip)) + if (is_t4(adap->params.chip)) return T4_REGMAP_SIZE; else return T5_REGMAP_SIZE; @@ -1499,7 +1433,7 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats, data += sizeof(struct port_stats) / sizeof(u64); collect_sge_port_stats(adapter, pi, (struct queue_port_stats *)data); data += sizeof(struct queue_port_stats) / sizeof(u64); - if (!is_t4(adapter->chip)) { + if (!is_t4(adapter->params.chip)) { t4_write_reg(adapter, SGE_STAT_CFG, STATSOURCE_T5(7)); val1 = t4_read_reg(adapter, SGE_STAT_TOTAL); val2 = t4_read_reg(adapter, SGE_STAT_MATCH); @@ -1521,8 +1455,8 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats, */ static inline unsigned int mk_adap_vers(const struct adapter *ap) { - return CHELSIO_CHIP_VERSION(ap->chip) | - (CHELSIO_CHIP_RELEASE(ap->chip) << 10) | (1 << 16); + return CHELSIO_CHIP_VERSION(ap->params.chip) | + (CHELSIO_CHIP_RELEASE(ap->params.chip) << 10) | (1 << 16); } static void reg_block_dump(struct adapter *ap, void *buf, unsigned int start, @@ -2189,7 +2123,7 @@ static void get_regs(struct net_device *dev, struct ethtool_regs *regs, static const unsigned int *reg_ranges; int arr_size = 0, buf_size = 0; - if (is_t4(ap->chip)) { + if (is_t4(ap->params.chip)) { reg_ranges = &t4_reg_ranges[0]; arr_size = ARRAY_SIZE(t4_reg_ranges); buf_size = T4_REGMAP_SIZE; @@ -2967,7 +2901,7 @@ static int setup_debugfs(struct adapter *adap) size = t4_read_reg(adap, MA_EDRAM1_BAR); add_debugfs_mem(adap, "edc1", MEM_EDC1, EDRAM_SIZE_GET(size)); } - if (is_t4(adap->chip)) { + if (is_t4(adap->params.chip)) { size = t4_read_reg(adap, MA_EXT_MEMORY_BAR); if (i & EXT_MEM_ENABLE) add_debugfs_mem(adap, "mc", MEM_MC, @@ -3419,7 +3353,7 @@ unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo) v1 = t4_read_reg(adap, A_SGE_DBFIFO_STATUS); v2 = t4_read_reg(adap, SGE_DBFIFO_STATUS2); - if (is_t4(adap->chip)) { + if (is_t4(adap->params.chip)) { lp_count = G_LP_COUNT(v1); hp_count = G_HP_COUNT(v1); } else { @@ -3588,7 +3522,7 @@ static void drain_db_fifo(struct adapter *adap, int usecs) do { v1 = t4_read_reg(adap, A_SGE_DBFIFO_STATUS); v2 = t4_read_reg(adap, SGE_DBFIFO_STATUS2); - if (is_t4(adap->chip)) { + if (is_t4(adap->params.chip)) { lp_count = G_LP_COUNT(v1); hp_count = G_HP_COUNT(v1); } else { @@ -3708,7 +3642,7 @@ static void process_db_drop(struct work_struct *work) adap = container_of(work, struct adapter, db_drop_task); - if (is_t4(adap->chip)) { + if (is_t4(adap->params.chip)) { disable_dbs(adap); notify_rdma_uld(adap, CXGB4_CONTROL_DB_DROP); drain_db_fifo(adap, 1); @@ -3753,7 +3687,7 @@ static void process_db_drop(struct work_struct *work) void t4_db_full(struct adapter *adap) { - if (is_t4(adap->chip)) { + if (is_t4(adap->params.chip)) { t4_set_reg_field(adap, SGE_INT_ENABLE3, DBFIFO_HP_INT | DBFIFO_LP_INT, 0); queue_work(workq, &adap->db_full_task); @@ -3762,7 +3696,7 @@ void t4_db_full(struct adapter *adap) void t4_db_dropped(struct adapter *adap) { - if (is_t4(adap->chip)) + if (is_t4(adap->params.chip)) queue_work(workq, &adap->db_drop_task); } @@ -3789,7 +3723,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld) lli.nchan = adap->params.nports; lli.nports = adap->params.nports; lli.wr_cred = adap->params.ofldq_wr_cred; - lli.adapter_type = adap->params.rev; + lli.adapter_type = adap->params.chip; lli.iscsi_iolen = MAXRXDATA_GET(t4_read_reg(adap, TP_PARA_REG2)); lli.udb_density = 1 << QUEUESPERPAGEPF0_GET( t4_read_reg(adap, SGE_EGRESS_QUEUES_PER_PAGE_PF) >> @@ -4483,7 +4417,7 @@ static void setup_memwin(struct adapter *adap) u32 bar0, mem_win0_base, mem_win1_base, mem_win2_base; bar0 = pci_resource_start(adap->pdev, 0); /* truncation intentional */ - if (is_t4(adap->chip)) { + if (is_t4(adap->params.chip)) { mem_win0_base = bar0 + MEMWIN0_BASE; mem_win1_base = bar0 + MEMWIN1_BASE; mem_win2_base = bar0 + MEMWIN2_BASE; @@ -4668,8 +4602,10 @@ static int adap_init0_config(struct adapter *adapter, int reset) const struct firmware *cf; unsigned long mtype = 0, maddr = 0; u32 finiver, finicsum, cfcsum; - int ret, using_flash; + int ret; + int config_issued = 0; char *fw_config_file, fw_config_file_path[256]; + char *config_name = NULL; /* * Reset device if necessary. @@ -4686,9 +4622,9 @@ static int adap_init0_config(struct adapter *adapter, int reset) * then use that. Otherwise, use the configuration file stored * in the adapter flash ... */ - switch (CHELSIO_CHIP_VERSION(adapter->chip)) { + switch (CHELSIO_CHIP_VERSION(adapter->params.chip)) { case CHELSIO_T4: - fw_config_file = FW_CFNAME; + fw_config_file = FW4_CFNAME; break; case CHELSIO_T5: fw_config_file = FW5_CFNAME; @@ -4702,13 +4638,16 @@ static int adap_init0_config(struct adapter *adapter, int reset) ret = request_firmware(&cf, fw_config_file, adapter->pdev_dev); if (ret < 0) { - using_flash = 1; + config_name = "On FLASH"; mtype = FW_MEMTYPE_CF_FLASH; maddr = t4_flash_cfg_addr(adapter); } else { u32 params[7], val[7]; - using_flash = 0; + sprintf(fw_config_file_path, + "/lib/firmware/%s", fw_config_file); + config_name = fw_config_file_path; + if (cf->size >= FLASH_CFG_MAX_SIZE) ret = -ENOMEM; else { @@ -4776,6 +4715,26 @@ static int adap_init0_config(struct adapter *adapter, int reset) FW_LEN16(caps_cmd)); ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd), &caps_cmd); + + /* If the CAPS_CONFIG failed with an ENOENT (for a Firmware + * Configuration File in FLASH), our last gasp effort is to use the + * Firmware Configuration File which is embedded in the firmware. A + * very few early versions of the firmware didn't have one embedded + * but we can ignore those. + */ + if (ret == -ENOENT) { + memset(&caps_cmd, 0, sizeof(caps_cmd)); + caps_cmd.op_to_write = + htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | + FW_CMD_REQUEST | + FW_CMD_READ); + caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd)); + ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, + sizeof(caps_cmd), &caps_cmd); + config_name = "Firmware Default"; + } + + config_issued = 1; if (ret < 0) goto bye; @@ -4816,7 +4775,6 @@ static int adap_init0_config(struct adapter *adapter, int reset) if (ret < 0) goto bye; - sprintf(fw_config_file_path, "/lib/firmware/%s", fw_config_file); /* * Return successfully and note that we're operating with parameters * not supplied by the driver, rather than from hard-wired @@ -4824,11 +4782,8 @@ static int adap_init0_config(struct adapter *adapter, int reset) */ adapter->flags |= USING_SOFT_PARAMS; dev_info(adapter->pdev_dev, "Successfully configured using Firmware "\ - "Configuration File %s, version %#x, computed checksum %#x\n", - (using_flash - ? "in device FLASH" - : fw_config_file_path), - finiver, cfcsum); + "Configuration File \"%s\", version %#x, computed checksum %#x\n", + config_name, finiver, cfcsum); return 0; /* @@ -4837,9 +4792,9 @@ static int adap_init0_config(struct adapter *adapter, int reset) * want to issue a warning since this is fairly common.) */ bye: - if (ret != -ENOENT) - dev_warn(adapter->pdev_dev, "Configuration file error %d\n", - -ret); + if (config_issued && ret != -ENOENT) + dev_warn(adapter->pdev_dev, "\"%s\" configuration file error %d\n", + config_name, -ret); return ret; } @@ -5086,6 +5041,47 @@ bye: return ret; } +static struct fw_info fw_info_array[] = { + { + .chip = CHELSIO_T4, + .fs_name = FW4_CFNAME, + .fw_mod_name = FW4_FNAME, + .fw_hdr = { + .chip = FW_HDR_CHIP_T4, + .fw_ver = __cpu_to_be32(FW_VERSION(T4)), + .intfver_nic = FW_INTFVER(T4, NIC), + .intfver_vnic = FW_INTFVER(T4, VNIC), + .intfver_ri = FW_INTFVER(T4, RI), + .intfver_iscsi = FW_INTFVER(T4, ISCSI), + .intfver_fcoe = FW_INTFVER(T4, FCOE), + }, + }, { + .chip = CHELSIO_T5, + .fs_name = FW5_CFNAME, + .fw_mod_name = FW5_FNAME, + .fw_hdr = { + .chip = FW_HDR_CHIP_T5, + .fw_ver = __cpu_to_be32(FW_VERSION(T5)), + .intfver_nic = FW_INTFVER(T5, NIC), + .intfver_vnic = FW_INTFVER(T5, VNIC), + .intfver_ri = FW_INTFVER(T5, RI), + .intfver_iscsi = FW_INTFVER(T5, ISCSI), + .intfver_fcoe = FW_INTFVER(T5, FCOE), + }, + } +}; + +static struct fw_info *find_fw_info(int chip) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(fw_info_array); i++) { + if (fw_info_array[i].chip == chip) + return &fw_info_array[i]; + } + return NULL; +} + /* * Phase 0 of initialization: contact FW, obtain config, perform basic init. */ @@ -5123,44 +5119,54 @@ static int adap_init0(struct adapter *adap) * later reporting and B. to warn if the currently loaded firmware * is excessively mismatched relative to the driver.) */ - ret = t4_check_fw_version(adap); - - /* The error code -EFAULT is returned by t4_check_fw_version() if - * firmware on adapter < supported firmware. If firmware on adapter - * is too old (not supported by driver) and we're the MASTER_PF set - * adapter state to DEV_STATE_UNINIT to force firmware upgrade - * and reinitialization. - */ - if ((adap->flags & MASTER_PF) && ret == -EFAULT) - state = DEV_STATE_UNINIT; + t4_get_fw_version(adap, &adap->params.fw_vers); + t4_get_tp_version(adap, &adap->params.tp_vers); if ((adap->flags & MASTER_PF) && state != DEV_STATE_INIT) { - if (ret == -EINVAL || ret == -EFAULT || ret > 0) { - if (upgrade_fw(adap) >= 0) { - /* - * Note that the chip was reset as part of the - * firmware upgrade so we don't reset it again - * below and grab the new firmware version. - */ - reset = 0; - ret = t4_check_fw_version(adap); - } else - if (ret == -EFAULT) { - /* - * Firmware is old but still might - * work if we force reinitialization - * of the adapter. Ignoring FW upgrade - * failure. - */ - dev_warn(adap->pdev_dev, - "Ignoring firmware upgrade " - "failure, and forcing driver " - "to reinitialize the " - "adapter.\n"); - ret = 0; - } + struct fw_info *fw_info; + struct fw_hdr *card_fw; + const struct firmware *fw; + const u8 *fw_data = NULL; + unsigned int fw_size = 0; + + /* This is the firmware whose headers the driver was compiled + * against + */ + fw_info = find_fw_info(CHELSIO_CHIP_VERSION(adap->params.chip)); + if (fw_info == NULL) { + dev_err(adap->pdev_dev, + "unable to get firmware info for chip %d.\n", + CHELSIO_CHIP_VERSION(adap->params.chip)); + return -EINVAL; } + + /* allocate memory to read the header of the firmware on the + * card + */ + card_fw = t4_alloc_mem(sizeof(*card_fw)); + + /* Get FW from from /lib/firmware/ */ + ret = request_firmware(&fw, fw_info->fw_mod_name, + adap->pdev_dev); + if (ret < 0) { + dev_err(adap->pdev_dev, + "unable to load firmware image %s, error %d\n", + fw_info->fw_mod_name, ret); + } else { + fw_data = fw->data; + fw_size = fw->size; + } + + /* upgrade FW logic */ + ret = t4_prep_fw(adap, fw_info, fw_data, fw_size, card_fw, + state, &reset); + + /* Cleaning up */ + if (fw != NULL) + release_firmware(fw); + t4_free_mem(card_fw); + if (ret < 0) - return ret; + goto bye; } /* @@ -5245,7 +5251,7 @@ static int adap_init0(struct adapter *adap) if (ret == -ENOENT) { dev_info(adap->pdev_dev, "No Configuration File present " - "on adapter. Using hard-wired " + "on adapter. Using hard-wired " "configuration parameters.\n"); ret = adap_init0_no_config(adap, reset); } @@ -5787,7 +5793,7 @@ static void print_port_info(const struct net_device *dev) netdev_info(dev, "Chelsio %s rev %d %s %sNIC PCIe x%d%s%s\n", adap->params.vpd.id, - CHELSIO_CHIP_RELEASE(adap->params.rev), buf, + CHELSIO_CHIP_RELEASE(adap->params.chip), buf, is_offload(adap) ? "R" : "", adap->params.pci.width, spd, (adap->flags & USING_MSIX) ? " MSI-X" : (adap->flags & USING_MSI) ? " MSI" : ""); @@ -5910,7 +5916,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (err) goto out_unmap_bar0; - if (!is_t4(adapter->chip)) { + if (!is_t4(adapter->params.chip)) { s_qpp = QUEUESPERPAGEPF1 * adapter->fn; qpp = 1 << QUEUESPERPAGEPF0_GET(t4_read_reg(adapter, SGE_EGRESS_QUEUES_PER_PAGE_PF) >> s_qpp); @@ -6064,7 +6070,7 @@ sriov: out_free_dev: free_some_resources(adapter); out_unmap_bar: - if (!is_t4(adapter->chip)) + if (!is_t4(adapter->params.chip)) iounmap(adapter->bar2); out_unmap_bar0: iounmap(adapter->regs); @@ -6116,7 +6122,7 @@ static void remove_one(struct pci_dev *pdev) free_some_resources(adapter); iounmap(adapter->regs); - if (!is_t4(adapter->chip)) + if (!is_t4(adapter->params.chip)) iounmap(adapter->bar2); kfree(adapter); pci_disable_pcie_error_reporting(pdev); diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index ac311f5f3eb9..cc380c36e1a8 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c @@ -509,7 +509,7 @@ static inline void ring_fl_db(struct adapter *adap, struct sge_fl *q) u32 val; if (q->pend_cred >= 8) { val = PIDX(q->pend_cred / 8); - if (!is_t4(adap->chip)) + if (!is_t4(adap->params.chip)) val |= DBTYPE(1); wmb(); t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL), DBPRIO(1) | @@ -847,7 +847,7 @@ static inline void ring_tx_db(struct adapter *adap, struct sge_txq *q, int n) wmb(); /* write descriptors before telling HW */ spin_lock(&q->db_lock); if (!q->db_disabled) { - if (is_t4(adap->chip)) { + if (is_t4(adap->params.chip)) { t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL), QID(q->cntxt_id) | PIDX(n)); } else { @@ -1596,7 +1596,7 @@ static noinline int handle_trace_pkt(struct adapter *adap, return 0; } - if (is_t4(adap->chip)) + if (is_t4(adap->params.chip)) __skb_pull(skb, sizeof(struct cpl_trace_pkt)); else __skb_pull(skb, sizeof(struct cpl_t5_trace_pkt)); @@ -1661,7 +1661,7 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp, const struct cpl_rx_pkt *pkt; struct sge_eth_rxq *rxq = container_of(q, struct sge_eth_rxq, rspq); struct sge *s = &q->adap->sge; - int cpl_trace_pkt = is_t4(q->adap->chip) ? + int cpl_trace_pkt = is_t4(q->adap->params.chip) ? CPL_TRACE_PKT : CPL_TRACE_PKT_T5; if (unlikely(*(u8 *)rsp == cpl_trace_pkt)) @@ -2182,7 +2182,7 @@ err: static void init_txq(struct adapter *adap, struct sge_txq *q, unsigned int id) { q->cntxt_id = id; - if (!is_t4(adap->chip)) { + if (!is_t4(adap->params.chip)) { unsigned int s_qpp; unsigned short udb_density; unsigned long qpshift; @@ -2641,7 +2641,7 @@ static int t4_sge_init_hard(struct adapter *adap) * Set up to drop DOORBELL writes when the DOORBELL FIFO overflows * and generate an interrupt when this occurs so we can recover. */ - if (is_t4(adap->chip)) { + if (is_t4(adap->params.chip)) { t4_set_reg_field(adap, A_SGE_DBFIFO_STATUS, V_HP_INT_THRESH(M_HP_INT_THRESH) | V_LP_INT_THRESH(M_LP_INT_THRESH), diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index 4cbb2f9850be..74a6fce5a15a 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -296,7 +296,7 @@ int t4_mc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc) u32 mc_bist_cmd, mc_bist_cmd_addr, mc_bist_cmd_len; u32 mc_bist_status_rdata, mc_bist_data_pattern; - if (is_t4(adap->chip)) { + if (is_t4(adap->params.chip)) { mc_bist_cmd = MC_BIST_CMD; mc_bist_cmd_addr = MC_BIST_CMD_ADDR; mc_bist_cmd_len = MC_BIST_CMD_LEN; @@ -349,7 +349,7 @@ int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc) u32 edc_bist_cmd, edc_bist_cmd_addr, edc_bist_cmd_len; u32 edc_bist_cmd_data_pattern, edc_bist_status_rdata; - if (is_t4(adap->chip)) { + if (is_t4(adap->params.chip)) { edc_bist_cmd = EDC_REG(EDC_BIST_CMD, idx); edc_bist_cmd_addr = EDC_REG(EDC_BIST_CMD_ADDR, idx); edc_bist_cmd_len = EDC_REG(EDC_BIST_CMD_LEN, idx); @@ -402,7 +402,7 @@ int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc) static int t4_mem_win_rw(struct adapter *adap, u32 addr, __be32 *data, int dir) { int i; - u32 win_pf = is_t4(adap->chip) ? 0 : V_PFNUM(adap->fn); + u32 win_pf = is_t4(adap->params.chip) ? 0 : V_PFNUM(adap->fn); /* * Setup offset into PCIE memory window. Address must be a @@ -863,104 +863,169 @@ unlock: } /** - * get_fw_version - read the firmware version + * t4_get_fw_version - read the firmware version * @adapter: the adapter * @vers: where to place the version * * Reads the FW version from flash. */ -static int get_fw_version(struct adapter *adapter, u32 *vers) +int t4_get_fw_version(struct adapter *adapter, u32 *vers) { - return t4_read_flash(adapter, adapter->params.sf_fw_start + - offsetof(struct fw_hdr, fw_ver), 1, vers, 0); + return t4_read_flash(adapter, FLASH_FW_START + + offsetof(struct fw_hdr, fw_ver), 1, + vers, 0); } /** - * get_tp_version - read the TP microcode version + * t4_get_tp_version - read the TP microcode version * @adapter: the adapter * @vers: where to place the version * * Reads the TP microcode version from flash. */ -static int get_tp_version(struct adapter *adapter, u32 *vers) +int t4_get_tp_version(struct adapter *adapter, u32 *vers) { - return t4_read_flash(adapter, adapter->params.sf_fw_start + + return t4_read_flash(adapter, FLASH_FW_START + offsetof(struct fw_hdr, tp_microcode_ver), 1, vers, 0); } -/** - * t4_check_fw_version - check if the FW is compatible with this driver - * @adapter: the adapter - * - * Checks if an adapter's FW is compatible with the driver. Returns 0 - * if there's exact match, a negative error if the version could not be - * read or there's a major version mismatch, and a positive value if the - * expected major version is found but there's a minor version mismatch. +/* Is the given firmware API compatible with the one the driver was compiled + * with? */ -int t4_check_fw_version(struct adapter *adapter) +static int fw_compatible(const struct fw_hdr *hdr1, const struct fw_hdr *hdr2) { - u32 api_vers[2]; - int ret, major, minor, micro; - int exp_major, exp_minor, exp_micro; - ret = get_fw_version(adapter, &adapter->params.fw_vers); - if (!ret) - ret = get_tp_version(adapter, &adapter->params.tp_vers); - if (!ret) - ret = t4_read_flash(adapter, adapter->params.sf_fw_start + - offsetof(struct fw_hdr, intfver_nic), - 2, api_vers, 1); - if (ret) - return ret; + /* short circuit if it's the exact same firmware version */ + if (hdr1->chip == hdr2->chip && hdr1->fw_ver == hdr2->fw_ver) + return 1; - major = FW_HDR_FW_VER_MAJOR_GET(adapter->params.fw_vers); - minor = FW_HDR_FW_VER_MINOR_GET(adapter->params.fw_vers); - micro = FW_HDR_FW_VER_MICRO_GET(adapter->params.fw_vers); +#define SAME_INTF(x) (hdr1->intfver_##x == hdr2->intfver_##x) + if (hdr1->chip == hdr2->chip && SAME_INTF(nic) && SAME_INTF(vnic) && + SAME_INTF(ri) && SAME_INTF(iscsi) && SAME_INTF(fcoe)) + return 1; +#undef SAME_INTF - switch (CHELSIO_CHIP_VERSION(adapter->chip)) { - case CHELSIO_T4: - exp_major = FW_VERSION_MAJOR; - exp_minor = FW_VERSION_MINOR; - exp_micro = FW_VERSION_MICRO; - break; - case CHELSIO_T5: - exp_major = FW_VERSION_MAJOR_T5; - exp_minor = FW_VERSION_MINOR_T5; - exp_micro = FW_VERSION_MICRO_T5; - break; - default: - dev_err(adapter->pdev_dev, "Unsupported chip type, %x\n", - adapter->chip); - return -EINVAL; - } + return 0; +} - memcpy(adapter->params.api_vers, api_vers, - sizeof(adapter->params.api_vers)); +/* The firmware in the filesystem is usable, but should it be installed? + * This routine explains itself in detail if it indicates the filesystem + * firmware should be installed. + */ +static int should_install_fs_fw(struct adapter *adap, int card_fw_usable, + int k, int c) +{ + const char *reason; - if (major < exp_major || (major == exp_major && minor < exp_minor) || - (major == exp_major && minor == exp_minor && micro < exp_micro)) { - dev_err(adapter->pdev_dev, - "Card has firmware version %u.%u.%u, minimum " - "supported firmware is %u.%u.%u.\n", major, minor, - micro, exp_major, exp_minor, exp_micro); - return -EFAULT; + if (!card_fw_usable) { + reason = "incompatible or unusable"; + goto install; } - if (major != exp_major) { /* major mismatch - fail */ - dev_err(adapter->pdev_dev, - "card FW has major version %u, driver wants %u\n", - major, exp_major); - return -EINVAL; + if (k > c) { + reason = "older than the version supported with this driver"; + goto install; } - if (minor == exp_minor && micro == exp_micro) - return 0; /* perfect match */ + return 0; + +install: + dev_err(adap->pdev_dev, "firmware on card (%u.%u.%u.%u) is %s, " + "installing firmware %u.%u.%u.%u on card.\n", + FW_HDR_FW_VER_MAJOR_GET(c), FW_HDR_FW_VER_MINOR_GET(c), + FW_HDR_FW_VER_MICRO_GET(c), FW_HDR_FW_VER_BUILD_GET(c), reason, + FW_HDR_FW_VER_MAJOR_GET(k), FW_HDR_FW_VER_MINOR_GET(k), + FW_HDR_FW_VER_MICRO_GET(k), FW_HDR_FW_VER_BUILD_GET(k)); - /* Minor/micro version mismatch. Report it but often it's OK. */ return 1; } +int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info, + const u8 *fw_data, unsigned int fw_size, + struct fw_hdr *card_fw, enum dev_state state, + int *reset) +{ + int ret, card_fw_usable, fs_fw_usable; + const struct fw_hdr *fs_fw; + const struct fw_hdr *drv_fw; + + drv_fw = &fw_info->fw_hdr; + + /* Read the header of the firmware on the card */ + ret = -t4_read_flash(adap, FLASH_FW_START, + sizeof(*card_fw) / sizeof(uint32_t), + (uint32_t *)card_fw, 1); + if (ret == 0) { + card_fw_usable = fw_compatible(drv_fw, (const void *)card_fw); + } else { + dev_err(adap->pdev_dev, + "Unable to read card's firmware header: %d\n", ret); + card_fw_usable = 0; + } + + if (fw_data != NULL) { + fs_fw = (const void *)fw_data; + fs_fw_usable = fw_compatible(drv_fw, fs_fw); + } else { + fs_fw = NULL; + fs_fw_usable = 0; + } + + if (card_fw_usable && card_fw->fw_ver == drv_fw->fw_ver && + (!fs_fw_usable || fs_fw->fw_ver == drv_fw->fw_ver)) { + /* Common case: the firmware on the card is an exact match and + * the filesystem one is an exact match too, or the filesystem + * one is absent/incompatible. + */ + } else if (fs_fw_usable && state == DEV_STATE_UNINIT && + should_install_fs_fw(adap, card_fw_usable, + be32_to_cpu(fs_fw->fw_ver), + be32_to_cpu(card_fw->fw_ver))) { + ret = -t4_fw_upgrade(adap, adap->mbox, fw_data, + fw_size, 0); + if (ret != 0) { + dev_err(adap->pdev_dev, + "failed to install firmware: %d\n", ret); + goto bye; + } + + /* Installed successfully, update the cached header too. */ + memcpy(card_fw, fs_fw, sizeof(*card_fw)); + card_fw_usable = 1; + *reset = 0; /* already reset as part of load_fw */ + } + + if (!card_fw_usable) { + uint32_t d, c, k; + + d = be32_to_cpu(drv_fw->fw_ver); + c = be32_to_cpu(card_fw->fw_ver); + k = fs_fw ? be32_to_cpu(fs_fw->fw_ver) : 0; + + dev_err(adap->pdev_dev, "Cannot find a usable firmware: " + "chip state %d, " + "driver compiled with %d.%d.%d.%d, " + "card has %d.%d.%d.%d, filesystem has %d.%d.%d.%d\n", + state, + FW_HDR_FW_VER_MAJOR_GET(d), FW_HDR_FW_VER_MINOR_GET(d), + FW_HDR_FW_VER_MICRO_GET(d), FW_HDR_FW_VER_BUILD_GET(d), + FW_HDR_FW_VER_MAJOR_GET(c), FW_HDR_FW_VER_MINOR_GET(c), + FW_HDR_FW_VER_MICRO_GET(c), FW_HDR_FW_VER_BUILD_GET(c), + FW_HDR_FW_VER_MAJOR_GET(k), FW_HDR_FW_VER_MINOR_GET(k), + FW_HDR_FW_VER_MICRO_GET(k), FW_HDR_FW_VER_BUILD_GET(k)); + ret = EINVAL; + goto bye; + } + + /* We're using whatever's on the card and it's known to be good. */ + adap->params.fw_vers = be32_to_cpu(card_fw->fw_ver); + adap->params.tp_vers = be32_to_cpu(card_fw->tp_microcode_ver); + +bye: + return ret; +} + /** * t4_flash_erase_sectors - erase a range of flash sectors * @adapter: the adapter @@ -1368,7 +1433,7 @@ static void pcie_intr_handler(struct adapter *adapter) PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS, pcie_port_intr_info) + t4_handle_intr_status(adapter, PCIE_INT_CAUSE, - is_t4(adapter->chip) ? + is_t4(adapter->params.chip) ? pcie_intr_info : t5_pcie_intr_info); if (fat) @@ -1782,7 +1847,7 @@ static void xgmac_intr_handler(struct adapter *adap, int port) { u32 v, int_cause_reg; - if (is_t4(adap->chip)) + if (is_t4(adap->params.chip)) int_cause_reg = PORT_REG(port, XGMAC_PORT_INT_CAUSE); else int_cause_reg = T5_PORT_REG(port, MAC_PORT_INT_CAUSE); @@ -2250,7 +2315,7 @@ void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p) #define GET_STAT(name) \ t4_read_reg64(adap, \ - (is_t4(adap->chip) ? PORT_REG(idx, MPS_PORT_STAT_##name##_L) : \ + (is_t4(adap->params.chip) ? PORT_REG(idx, MPS_PORT_STAT_##name##_L) : \ T5_PORT_REG(idx, MPS_PORT_STAT_##name##_L))) #define GET_STAT_COM(name) t4_read_reg64(adap, MPS_STAT_##name##_L) @@ -2332,7 +2397,7 @@ void t4_wol_magic_enable(struct adapter *adap, unsigned int port, { u32 mag_id_reg_l, mag_id_reg_h, port_cfg_reg; - if (is_t4(adap->chip)) { + if (is_t4(adap->params.chip)) { mag_id_reg_l = PORT_REG(port, XGMAC_PORT_MAGIC_MACID_LO); mag_id_reg_h = PORT_REG(port, XGMAC_PORT_MAGIC_MACID_HI); port_cfg_reg = PORT_REG(port, XGMAC_PORT_CFG2); @@ -2374,7 +2439,7 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map, int i; u32 port_cfg_reg; - if (is_t4(adap->chip)) + if (is_t4(adap->params.chip)) port_cfg_reg = PORT_REG(port, XGMAC_PORT_CFG2); else port_cfg_reg = T5_PORT_REG(port, MAC_PORT_CFG2); @@ -2387,7 +2452,7 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map, return -EINVAL; #define EPIO_REG(name) \ - (is_t4(adap->chip) ? PORT_REG(port, XGMAC_PORT_EPIO_##name) : \ + (is_t4(adap->params.chip) ? PORT_REG(port, XGMAC_PORT_EPIO_##name) : \ T5_PORT_REG(port, MAC_PORT_EPIO_##name)) t4_write_reg(adap, EPIO_REG(DATA1), mask0 >> 32); @@ -2474,7 +2539,7 @@ int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox, int t4_mem_win_read_len(struct adapter *adap, u32 addr, __be32 *data, int len) { int i, off; - u32 win_pf = is_t4(adap->chip) ? 0 : V_PFNUM(adap->fn); + u32 win_pf = is_t4(adap->params.chip) ? 0 : V_PFNUM(adap->fn); /* Align on a 2KB boundary. */ @@ -3306,7 +3371,7 @@ int t4_alloc_mac_filt(struct adapter *adap, unsigned int mbox, int i, ret; struct fw_vi_mac_cmd c; struct fw_vi_mac_exact *p; - unsigned int max_naddr = is_t4(adap->chip) ? + unsigned int max_naddr = is_t4(adap->params.chip) ? NUM_MPS_CLS_SRAM_L_INSTANCES : NUM_MPS_T5_CLS_SRAM_L_INSTANCES; @@ -3368,7 +3433,7 @@ int t4_change_mac(struct adapter *adap, unsigned int mbox, unsigned int viid, int ret, mode; struct fw_vi_mac_cmd c; struct fw_vi_mac_exact *p = c.u.exact; - unsigned int max_mac_addr = is_t4(adap->chip) ? + unsigned int max_mac_addr = is_t4(adap->params.chip) ? NUM_MPS_CLS_SRAM_L_INSTANCES : NUM_MPS_T5_CLS_SRAM_L_INSTANCES; @@ -3699,13 +3764,14 @@ int t4_prep_adapter(struct adapter *adapter) { int ret, ver; uint16_t device_id; + u32 pl_rev; ret = t4_wait_dev_ready(adapter); if (ret < 0) return ret; get_pci_mode(adapter, &adapter->params.pci); - adapter->params.rev = t4_read_reg(adapter, PL_REV); + pl_rev = G_REV(t4_read_reg(adapter, PL_REV)); ret = get_flash_params(adapter); if (ret < 0) { @@ -3717,14 +3783,13 @@ int t4_prep_adapter(struct adapter *adapter) */ pci_read_config_word(adapter->pdev, PCI_DEVICE_ID, &device_id); ver = device_id >> 12; + adapter->params.chip = 0; switch (ver) { case CHELSIO_T4: - adapter->chip = CHELSIO_CHIP_CODE(CHELSIO_T4, - adapter->params.rev); + adapter->params.chip |= CHELSIO_CHIP_CODE(CHELSIO_T4, pl_rev); break; case CHELSIO_T5: - adapter->chip = CHELSIO_CHIP_CODE(CHELSIO_T5, - adapter->params.rev); + adapter->params.chip |= CHELSIO_CHIP_CODE(CHELSIO_T5, pl_rev); break; default: dev_err(adapter->pdev_dev, "Device %d is not supported\n", @@ -3732,9 +3797,6 @@ int t4_prep_adapter(struct adapter *adapter) return -EINVAL; } - /* Reassign the updated revision field */ - adapter->params.rev = adapter->chip; - init_cong_ctrl(adapter->params.a_wnd, adapter->params.b_wnd); /* diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h index ef146c0ba481..0a8205d69d2c 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h @@ -1092,6 +1092,11 @@ #define PL_REV 0x1943c +#define S_REV 0 +#define M_REV 0xfU +#define V_REV(x) ((x) << S_REV) +#define G_REV(x) (((x) >> S_REV) & M_REV) + #define LE_DB_CONFIG 0x19c04 #define HASHEN 0x00100000U @@ -1199,4 +1204,13 @@ #define EDC_STRIDE_T5 (EDC_T51_BASE_ADDR - EDC_T50_BASE_ADDR) #define EDC_REG_T5(reg, idx) (reg + EDC_STRIDE_T5 * idx) +#define A_PL_VF_REV 0x4 +#define A_PL_VF_WHOAMI 0x0 +#define A_PL_VF_REVISION 0x8 + +#define S_CHIPID 4 +#define M_CHIPID 0xfU +#define V_CHIPID(x) ((x) << S_CHIPID) +#define G_CHIPID(x) (((x) >> S_CHIPID) & M_CHIPID) + #endif /* __T4_REGS_H */ diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h index 6f77ac487743..74fea74ce0aa 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h @@ -2157,7 +2157,7 @@ struct fw_debug_cmd { struct fw_hdr { u8 ver; - u8 reserved1; + u8 chip; /* terminator chip type */ __be16 len512; /* bin length in units of 512-bytes */ __be32 fw_ver; /* firmware version */ __be32 tp_microcode_ver; @@ -2176,6 +2176,11 @@ struct fw_hdr { __be32 reserved6[23]; }; +enum fw_hdr_chip { + FW_HDR_CHIP_T4, + FW_HDR_CHIP_T5 +}; + #define FW_HDR_FW_VER_MAJOR_GET(x) (((x) >> 24) & 0xff) #define FW_HDR_FW_VER_MINOR_GET(x) (((x) >> 16) & 0xff) #define FW_HDR_FW_VER_MICRO_GET(x) (((x) >> 8) & 0xff) diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h b/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h index be5c7ef6ca93..68eaa9c88c7d 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h +++ b/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h @@ -344,7 +344,6 @@ struct adapter { unsigned long registered_device_map; unsigned long open_device_map; unsigned long flags; - enum chip_type chip; struct adapter_params params; /* queue and interrupt resources */ diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c index 5f90ec5f7519..0899c0983594 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c @@ -1064,7 +1064,7 @@ static inline unsigned int mk_adap_vers(const struct adapter *adapter) /* * Chip version 4, revision 0x3f (cxgb4vf). */ - return CHELSIO_CHIP_VERSION(adapter->chip) | (0x3f << 10); + return CHELSIO_CHIP_VERSION(adapter->params.chip) | (0x3f << 10); } /* @@ -1551,9 +1551,13 @@ static void cxgb4vf_get_regs(struct net_device *dev, reg_block_dump(adapter, regbuf, T4VF_MPS_BASE_ADDR + T4VF_MOD_MAP_MPS_FIRST, T4VF_MPS_BASE_ADDR + T4VF_MOD_MAP_MPS_LAST); + + /* T5 adds new registers in the PL Register map. + */ reg_block_dump(adapter, regbuf, T4VF_PL_BASE_ADDR + T4VF_MOD_MAP_PL_FIRST, - T4VF_PL_BASE_ADDR + T4VF_MOD_MAP_PL_LAST); + T4VF_PL_BASE_ADDR + (is_t4(adapter->params.chip) + ? A_PL_VF_WHOAMI : A_PL_VF_REVISION)); reg_block_dump(adapter, regbuf, T4VF_CIM_BASE_ADDR + T4VF_MOD_MAP_CIM_FIRST, T4VF_CIM_BASE_ADDR + T4VF_MOD_MAP_CIM_LAST); @@ -2087,6 +2091,7 @@ static int adap_init0(struct adapter *adapter) unsigned int ethqsets; int err; u32 param, val = 0; + unsigned int chipid; /* * Wait for the device to become ready before proceeding ... @@ -2114,12 +2119,14 @@ static int adap_init0(struct adapter *adapter) return err; } + adapter->params.chip = 0; switch (adapter->pdev->device >> 12) { case CHELSIO_T4: - adapter->chip = CHELSIO_CHIP_CODE(CHELSIO_T4, 0); + adapter->params.chip = CHELSIO_CHIP_CODE(CHELSIO_T4, 0); break; case CHELSIO_T5: - adapter->chip = CHELSIO_CHIP_CODE(CHELSIO_T5, 0); + chipid = G_REV(t4_read_reg(adapter, A_PL_VF_REV)); + adapter->params.chip |= CHELSIO_CHIP_CODE(CHELSIO_T5, chipid); break; } diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c index 8475c4cda9e4..0a89963c48ce 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c @@ -537,7 +537,7 @@ static inline void ring_fl_db(struct adapter *adapter, struct sge_fl *fl) */ if (fl->pend_cred >= FL_PER_EQ_UNIT) { val = PIDX(fl->pend_cred / FL_PER_EQ_UNIT); - if (!is_t4(adapter->chip)) + if (!is_t4(adapter->params.chip)) val |= DBTYPE(1); wmb(); t4_write_reg(adapter, T4VF_SGE_BASE_ADDR + SGE_VF_KDOORBELL, diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h index 53cbfed21d0b..61362450d05b 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h +++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h @@ -39,21 +39,28 @@ #include "../cxgb4/t4fw_api.h" #define CHELSIO_CHIP_CODE(version, revision) (((version) << 4) | (revision)) -#define CHELSIO_CHIP_VERSION(code) ((code) >> 4) +#define CHELSIO_CHIP_VERSION(code) (((code) >> 4) & 0xf) #define CHELSIO_CHIP_RELEASE(code) ((code) & 0xf) +/* All T4 and later chips have their PCI-E Device IDs encoded as 0xVFPP where: + * + * V = "4" for T4; "5" for T5, etc. or + * = "a" for T4 FPGA; "b" for T4 FPGA, etc. + * F = "0" for PF 0..3; "4".."7" for PF4..7; and "8" for VFs + * PP = adapter product designation + */ #define CHELSIO_T4 0x4 #define CHELSIO_T5 0x5 enum chip_type { - T4_A1 = CHELSIO_CHIP_CODE(CHELSIO_T4, 0), - T4_A2 = CHELSIO_CHIP_CODE(CHELSIO_T4, 1), - T4_A3 = CHELSIO_CHIP_CODE(CHELSIO_T4, 2), + T4_A1 = CHELSIO_CHIP_CODE(CHELSIO_T4, 1), + T4_A2 = CHELSIO_CHIP_CODE(CHELSIO_T4, 2), T4_FIRST_REV = T4_A1, - T4_LAST_REV = T4_A3, + T4_LAST_REV = T4_A2, - T5_A1 = CHELSIO_CHIP_CODE(CHELSIO_T5, 0), - T5_FIRST_REV = T5_A1, + T5_A0 = CHELSIO_CHIP_CODE(CHELSIO_T5, 0), + T5_A1 = CHELSIO_CHIP_CODE(CHELSIO_T5, 1), + T5_FIRST_REV = T5_A0, T5_LAST_REV = T5_A1, }; @@ -203,6 +210,7 @@ struct adapter_params { struct vpd_params vpd; /* Vital Product Data */ struct rss_params rss; /* Receive Side Scaling */ struct vf_resources vfres; /* Virtual Function Resource limits */ + enum chip_type chip; /* chip code */ u8 nports; /* # of Ethernet "ports" */ }; @@ -253,7 +261,7 @@ static inline int t4vf_wr_mbox_ns(struct adapter *adapter, const void *cmd, static inline int is_t4(enum chip_type chip) { - return (chip >= T4_FIRST_REV && chip <= T4_LAST_REV); + return CHELSIO_CHIP_VERSION(chip) == CHELSIO_T4; } int t4vf_wait_dev_ready(struct adapter *); diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c index 9f96dc3bb112..d958c44341b5 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c @@ -1027,7 +1027,7 @@ int t4vf_alloc_mac_filt(struct adapter *adapter, unsigned int viid, bool free, unsigned nfilters = 0; unsigned int rem = naddr; struct fw_vi_mac_cmd cmd, rpl; - unsigned int max_naddr = is_t4(adapter->chip) ? + unsigned int max_naddr = is_t4(adapter->params.chip) ? NUM_MPS_CLS_SRAM_L_INSTANCES : NUM_MPS_T5_CLS_SRAM_L_INSTANCES; @@ -1121,7 +1121,7 @@ int t4vf_change_mac(struct adapter *adapter, unsigned int viid, struct fw_vi_mac_exact *p = &cmd.u.exact[0]; size_t len16 = DIV_ROUND_UP(offsetof(struct fw_vi_mac_cmd, u.exact[1]), 16); - unsigned int max_naddr = is_t4(adapter->chip) ? + unsigned int max_naddr = is_t4(adapter->params.chip) ? NUM_MPS_CLS_SRAM_L_INSTANCES : NUM_MPS_T5_CLS_SRAM_L_INSTANCES; diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h index 3e2162121601..dc88782185f2 100644 --- a/drivers/net/ethernet/emulex/benet/be_hw.h +++ b/drivers/net/ethernet/emulex/benet/be_hw.h @@ -64,6 +64,9 @@ #define SLIPORT_ERROR_NO_RESOURCE1 0x2 #define SLIPORT_ERROR_NO_RESOURCE2 0x9 +#define SLIPORT_ERROR_FW_RESET1 0x2 +#define SLIPORT_ERROR_FW_RESET2 0x0 + /********* Memory BAR register ************/ #define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 0xfc /* Host Interrupt Enable, if set interrupts are enabled although "PCI Interrupt diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index fee64bf10446..0fde69d5cb6a 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -2464,8 +2464,16 @@ void be_detect_error(struct be_adapter *adapter) */ if (sliport_status & SLIPORT_STATUS_ERR_MASK) { adapter->hw_error = true; - dev_err(&adapter->pdev->dev, - "Error detected in the card\n"); + /* Do not log error messages if its a FW reset */ + if (sliport_err1 == SLIPORT_ERROR_FW_RESET1 && + sliport_err2 == SLIPORT_ERROR_FW_RESET2) { + dev_info(&adapter->pdev->dev, + "Firmware update in progress\n"); + return; + } else { + dev_err(&adapter->pdev->dev, + "Error detected in the card\n"); + } } if (sliport_status & SLIPORT_STATUS_ERR_MASK) { @@ -2932,28 +2940,35 @@ static void be_cancel_worker(struct be_adapter *adapter) } } -static int be_clear(struct be_adapter *adapter) +static void be_mac_clear(struct be_adapter *adapter) { int i; + if (adapter->pmac_id) { + for (i = 0; i < (adapter->uc_macs + 1); i++) + be_cmd_pmac_del(adapter, adapter->if_handle, + adapter->pmac_id[i], 0); + adapter->uc_macs = 0; + + kfree(adapter->pmac_id); + adapter->pmac_id = NULL; + } +} + +static int be_clear(struct be_adapter *adapter) +{ be_cancel_worker(adapter); if (sriov_enabled(adapter)) be_vf_clear(adapter); /* delete the primary mac along with the uc-mac list */ - for (i = 0; i < (adapter->uc_macs + 1); i++) - be_cmd_pmac_del(adapter, adapter->if_handle, - adapter->pmac_id[i], 0); - adapter->uc_macs = 0; + be_mac_clear(adapter); be_cmd_if_destroy(adapter, adapter->if_handle, 0); be_clear_queues(adapter); - kfree(adapter->pmac_id); - adapter->pmac_id = NULL; - be_msix_disable(adapter); return 0; } @@ -3812,6 +3827,8 @@ static int lancer_fw_download(struct be_adapter *adapter, } if (change_status == LANCER_FW_RESET_NEEDED) { + dev_info(&adapter->pdev->dev, + "Resetting adapter to activate new FW\n"); status = lancer_physdev_ctrl(adapter, PHYSDEV_CONTROL_FW_RESET_MASK); if (status) { @@ -4363,13 +4380,13 @@ static int lancer_recover_func(struct be_adapter *adapter) goto err; } - dev_err(dev, "Error recovery successful\n"); + dev_err(dev, "Adapter recovery successful\n"); return 0; err: if (status == -EAGAIN) dev_err(dev, "Waiting for resource provisioning\n"); else - dev_err(dev, "Error recovery failed\n"); + dev_err(dev, "Adapter recovery failed\n"); return status; } diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 4cbebf3d80eb..e7c8b749c5a5 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -98,10 +98,6 @@ static void set_multicast_list(struct net_device *ndev); * detected as not set during a prior frame transmission, then the * ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs * were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in - * If the ready bit in the transmit buffer descriptor (TxBD[R]) is previously - * detected as not set during a prior frame transmission, then the - * ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs - * were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in * frames not being transmitted until there is a 0-to-1 transition on * ENET_TDAR[TDAR]. */ @@ -385,7 +381,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) * data. */ bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, bufaddr, - FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE); + skb->len, DMA_TO_DEVICE); if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) { bdp->cbd_bufaddr = 0; fep->tx_skbuff[index] = NULL; @@ -779,11 +775,10 @@ fec_enet_tx(struct net_device *ndev) else index = bdp - fep->tx_bd_base; - dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, - FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE); - bdp->cbd_bufaddr = 0; - skb = fep->tx_skbuff[index]; + dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, skb->len, + DMA_TO_DEVICE); + bdp->cbd_bufaddr = 0; /* Check for errors. */ if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC | diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c index 2d1c6bdd3618..7628e0fd8455 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_main.c +++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c @@ -3033,7 +3033,7 @@ static struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter, dev->hw_features = NETIF_F_SG | NETIF_F_TSO | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_CTAG_TX; - dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO | + dev->features = NETIF_F_SG | NETIF_F_TSO | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_RXCSUM; diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index be15938ba213..12b0932204ba 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -354,6 +354,9 @@ static struct rtnl_link_stats64 *i40e_get_netdev_stats_struct( struct rtnl_link_stats64 *vsi_stats = i40e_get_vsi_stats_struct(vsi); int i; + if (!vsi->tx_rings) + return stats; + rcu_read_lock(); for (i = 0; i < vsi->num_queue_pairs; i++) { struct i40e_ring *tx_ring, *rx_ring; diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.c b/drivers/net/ethernet/intel/igb/e1000_phy.c index c4c4fe332c7e..ad2b74d95138 100644 --- a/drivers/net/ethernet/intel/igb/e1000_phy.c +++ b/drivers/net/ethernet/intel/igb/e1000_phy.c @@ -1728,7 +1728,10 @@ s32 igb_phy_has_link(struct e1000_hw *hw, u32 iterations, * ownership of the resources, wait and try again to * see if they have relinquished the resources yet. */ - udelay(usec_interval); + if (usec_interval >= 1000) + mdelay(usec_interval/1000); + else + udelay(usec_interval); } ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); if (ret_val) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index b8e232b4ea2d..d5f0d72e5e33 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -1378,7 +1378,7 @@ static void mvneta_rxq_drop_pkts(struct mvneta_port *pp, dev_kfree_skb_any(skb); dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr, - rx_desc->data_size, DMA_FROM_DEVICE); + MVNETA_RX_BUF_SIZE(pp->pkt_size), DMA_FROM_DEVICE); } if (rx_done) @@ -1424,7 +1424,7 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo, } dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr, - rx_desc->data_size, DMA_FROM_DEVICE); + MVNETA_RX_BUF_SIZE(pp->pkt_size), DMA_FROM_DEVICE); rx_bytes = rx_desc->data_size - (ETH_FCS_LEN + MVNETA_MH_SIZE); diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 5789ea2c934d..01fc6515384d 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -2635,6 +2635,8 @@ static int __init mlx4_init(void) return -ENOMEM; ret = pci_register_driver(&mlx4_driver); + if (ret < 0) + destroy_workqueue(mlx4_wq); return ret < 0 ? ret : 0; } diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c index 2d045be4b5cf..1e8b9514718b 100644 --- a/drivers/net/ethernet/nvidia/forcedeth.c +++ b/drivers/net/ethernet/nvidia/forcedeth.c @@ -5150,8 +5150,10 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64 { struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); - int result; - memset(buffer, 0, nv_get_sset_count(dev, ETH_SS_TEST)*sizeof(u64)); + int result, count; + + count = nv_get_sset_count(dev, ETH_SS_TEST); + memset(buffer, 0, count * sizeof(u64)); if (!nv_link_test(dev)) { test->flags |= ETH_TEST_FL_FAILED; @@ -5195,7 +5197,7 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64 return; } - if (!nv_loopback_test(dev)) { + if (count > NV_TEST_COUNT_BASE && !nv_loopback_test(dev)) { test->flags |= ETH_TEST_FL_FAILED; buffer[3] = 1; } diff --git a/drivers/net/ethernet/qlogic/qlge/qlge.h b/drivers/net/ethernet/qlogic/qlge/qlge.h index 0c9c4e895595..03517478e589 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge.h +++ b/drivers/net/ethernet/qlogic/qlge/qlge.h @@ -18,7 +18,7 @@ */ #define DRV_NAME "qlge" #define DRV_STRING "QLogic 10 Gigabit PCI-E Ethernet Driver " -#define DRV_VERSION "1.00.00.33" +#define DRV_VERSION "1.00.00.34" #define WQ_ADDR_ALIGN 0x3 /* 4 byte alignment */ diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c b/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c index 0780e039b271..8dee1beb9854 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c @@ -181,6 +181,7 @@ static const char ql_gstrings_test[][ETH_GSTRING_LEN] = { }; #define QLGE_TEST_LEN (sizeof(ql_gstrings_test) / ETH_GSTRING_LEN) #define QLGE_STATS_LEN ARRAY_SIZE(ql_gstrings_stats) +#define QLGE_RCV_MAC_ERR_STATS 7 static int ql_update_ring_coalescing(struct ql_adapter *qdev) { @@ -280,6 +281,9 @@ static void ql_update_stats(struct ql_adapter *qdev) iter++; } + /* Update receive mac error statistics */ + iter += QLGE_RCV_MAC_ERR_STATS; + /* * Get Per-priority TX pause frame counter statistics. */ diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c index a245dc18d769..449f506d2e8f 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c @@ -2376,14 +2376,6 @@ static netdev_features_t qlge_fix_features(struct net_device *ndev, netdev_features_t features) { int err; - /* - * Since there is no support for separate rx/tx vlan accel - * enable/disable make sure tx flag is always in same state as rx. - */ - if (features & NETIF_F_HW_VLAN_CTAG_RX) - features |= NETIF_F_HW_VLAN_CTAG_TX; - else - features &= ~NETIF_F_HW_VLAN_CTAG_TX; /* Update the behavior of vlan accel in the adapter */ err = qlge_update_hw_vlan_features(ndev, features); diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 2e27837ce6a2..fd844b53e385 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -585,7 +585,7 @@ static void efx_start_datapath(struct efx_nic *efx) EFX_MAX_FRAME_LEN(efx->net_dev->mtu) + efx->type->rx_buffer_padding); rx_buf_len = (sizeof(struct efx_rx_page_state) + - NET_IP_ALIGN + efx->rx_dma_len); + efx->rx_ip_align + efx->rx_dma_len); if (rx_buf_len <= PAGE_SIZE) { efx->rx_scatter = efx->type->always_rx_scatter; efx->rx_buffer_order = 0; @@ -645,6 +645,8 @@ static void efx_start_datapath(struct efx_nic *efx) WARN_ON(channel->rx_pkt_n_frags); } + efx_ptp_start_datapath(efx); + if (netif_device_present(efx->net_dev)) netif_tx_wake_all_queues(efx->net_dev); } @@ -659,6 +661,8 @@ static void efx_stop_datapath(struct efx_nic *efx) EFX_ASSERT_RESET_SERIALISED(efx); BUG_ON(efx->port_enabled); + efx_ptp_stop_datapath(efx); + /* Stop RX refill */ efx_for_each_channel(channel, efx) { efx_for_each_channel_rx_queue(rx_queue, channel) @@ -2540,6 +2544,8 @@ static int efx_init_struct(struct efx_nic *efx, efx->net_dev = net_dev; efx->rx_prefix_size = efx->type->rx_prefix_size; + efx->rx_ip_align = + NET_IP_ALIGN ? (efx->rx_prefix_size + NET_IP_ALIGN) % 4 : 0; efx->rx_packet_hash_offset = efx->type->rx_hash_offset - efx->type->rx_prefix_size; spin_lock_init(&efx->stats_lock); diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index 366c8e3e3784..4b0bd8a1514d 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -50,6 +50,7 @@ struct efx_mcdi_async_param { static void efx_mcdi_timeout_async(unsigned long context); static int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating, bool *was_attached_out); +static bool efx_mcdi_poll_once(struct efx_nic *efx); static inline struct efx_mcdi_iface *efx_mcdi(struct efx_nic *efx) { @@ -237,6 +238,21 @@ static void efx_mcdi_read_response_header(struct efx_nic *efx) } } +static bool efx_mcdi_poll_once(struct efx_nic *efx) +{ + struct efx_mcdi_iface *mcdi = efx_mcdi(efx); + + rmb(); + if (!efx->type->mcdi_poll_response(efx)) + return false; + + spin_lock_bh(&mcdi->iface_lock); + efx_mcdi_read_response_header(efx); + spin_unlock_bh(&mcdi->iface_lock); + + return true; +} + static int efx_mcdi_poll(struct efx_nic *efx) { struct efx_mcdi_iface *mcdi = efx_mcdi(efx); @@ -272,18 +288,13 @@ static int efx_mcdi_poll(struct efx_nic *efx) time = jiffies; - rmb(); - if (efx->type->mcdi_poll_response(efx)) + if (efx_mcdi_poll_once(efx)) break; if (time_after(time, finish)) return -ETIMEDOUT; } - spin_lock_bh(&mcdi->iface_lock); - efx_mcdi_read_response_header(efx); - spin_unlock_bh(&mcdi->iface_lock); - /* Return rc=0 like wait_event_timeout() */ return 0; } @@ -619,6 +630,16 @@ int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen, rc = efx_mcdi_await_completion(efx); if (rc != 0) { + netif_err(efx, hw, efx->net_dev, + "MC command 0x%x inlen %d mode %d timed out\n", + cmd, (int)inlen, mcdi->mode); + + if (mcdi->mode == MCDI_MODE_EVENTS && efx_mcdi_poll_once(efx)) { + netif_err(efx, hw, efx->net_dev, + "MCDI request was completed without an event\n"); + rc = 0; + } + /* Close the race with efx_mcdi_ev_cpl() executing just too late * and completing a request we've just cancelled, by ensuring * that the seqno check therein fails. @@ -627,11 +648,9 @@ int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen, ++mcdi->seqno; ++mcdi->credits; spin_unlock_bh(&mcdi->iface_lock); + } - netif_err(efx, hw, efx->net_dev, - "MC command 0x%x inlen %d mode %d timed out\n", - cmd, (int)inlen, mcdi->mode); - } else { + if (rc == 0) { size_t hdr_len, data_len; /* At the very least we need a memory barrier here to ensure diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index b14a717ac3e8..542a0d252ae0 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -683,6 +683,8 @@ struct vfdi_status; * @n_channels: Number of channels in use * @n_rx_channels: Number of channels used for RX (= number of RX queues) * @n_tx_channels: Number of channels used for TX + * @rx_ip_align: RX DMA address offset to have IP header aligned in + * in accordance with NET_IP_ALIGN * @rx_dma_len: Current maximum RX DMA length * @rx_buffer_order: Order (log2) of number of pages for each RX buffer * @rx_buffer_truesize: Amortised allocation size of an RX buffer, @@ -816,6 +818,7 @@ struct efx_nic { unsigned rss_spread; unsigned tx_channel_offset; unsigned n_tx_channels; + unsigned int rx_ip_align; unsigned int rx_dma_len; unsigned int rx_buffer_order; unsigned int rx_buffer_truesize; diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index 11b6112d9249..91c63ec79c5f 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -560,6 +560,8 @@ void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info); bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev); +void efx_ptp_start_datapath(struct efx_nic *efx); +void efx_ptp_stop_datapath(struct efx_nic *efx); extern const struct efx_nic_type falcon_a1_nic_type; extern const struct efx_nic_type falcon_b0_nic_type; diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index 03acf57df045..3dd39dcfe36b 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -220,6 +220,7 @@ struct efx_ptp_timeset { * @evt_list: List of MC receive events awaiting packets * @evt_free_list: List of free events * @evt_lock: Lock for manipulating evt_list and evt_free_list + * @evt_overflow: Boolean indicating that event list has overflowed * @rx_evts: Instantiated events (on evt_list and evt_free_list) * @workwq: Work queue for processing pending PTP operations * @work: Work task @@ -270,6 +271,7 @@ struct efx_ptp_data { struct list_head evt_list; struct list_head evt_free_list; spinlock_t evt_lock; + bool evt_overflow; struct efx_ptp_event_rx rx_evts[MAX_RECEIVE_EVENTS]; struct workqueue_struct *workwq; struct work_struct work; @@ -635,6 +637,11 @@ static void efx_ptp_drop_time_expired_events(struct efx_nic *efx) } } } + /* If the event overflow flag is set and the event list is now empty + * clear the flag to re-enable the overflow warning message. + */ + if (ptp->evt_overflow && list_empty(&ptp->evt_list)) + ptp->evt_overflow = false; spin_unlock_bh(&ptp->evt_lock); } @@ -676,6 +683,11 @@ static enum ptp_packet_state efx_ptp_match_rx(struct efx_nic *efx, break; } } + /* If the event overflow flag is set and the event list is now empty + * clear the flag to re-enable the overflow warning message. + */ + if (ptp->evt_overflow && list_empty(&ptp->evt_list)) + ptp->evt_overflow = false; spin_unlock_bh(&ptp->evt_lock); return rc; @@ -705,8 +717,9 @@ static bool efx_ptp_process_events(struct efx_nic *efx, struct sk_buff_head *q) __skb_queue_tail(q, skb); } else if (time_after(jiffies, match->expiry)) { match->state = PTP_PACKET_STATE_TIMED_OUT; - netif_warn(efx, rx_err, efx->net_dev, - "PTP packet - no timestamp seen\n"); + if (net_ratelimit()) + netif_warn(efx, rx_err, efx->net_dev, + "PTP packet - no timestamp seen\n"); __skb_queue_tail(q, skb); } else { /* Replace unprocessed entry and stop */ @@ -788,9 +801,14 @@ fail: static int efx_ptp_stop(struct efx_nic *efx) { struct efx_ptp_data *ptp = efx->ptp_data; - int rc = efx_ptp_disable(efx); struct list_head *cursor; struct list_head *next; + int rc; + + if (ptp == NULL) + return 0; + + rc = efx_ptp_disable(efx); if (ptp->rxfilter_installed) { efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED, @@ -809,11 +827,19 @@ static int efx_ptp_stop(struct efx_nic *efx) list_for_each_safe(cursor, next, &efx->ptp_data->evt_list) { list_move(cursor, &efx->ptp_data->evt_free_list); } + ptp->evt_overflow = false; spin_unlock_bh(&efx->ptp_data->evt_lock); return rc; } +static int efx_ptp_restart(struct efx_nic *efx) +{ + if (efx->ptp_data && efx->ptp_data->enabled) + return efx_ptp_start(efx); + return 0; +} + static void efx_ptp_pps_worker(struct work_struct *work) { struct efx_ptp_data *ptp = @@ -901,6 +927,7 @@ static int efx_ptp_probe_channel(struct efx_channel *channel) spin_lock_init(&ptp->evt_lock); for (pos = 0; pos < MAX_RECEIVE_EVENTS; pos++) list_add(&ptp->rx_evts[pos].link, &ptp->evt_free_list); + ptp->evt_overflow = false; ptp->phc_clock_info.owner = THIS_MODULE; snprintf(ptp->phc_clock_info.name, @@ -989,7 +1016,11 @@ bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb) skb->len >= PTP_MIN_LENGTH && skb->len <= MC_CMD_PTP_IN_TRANSMIT_PACKET_MAXNUM && likely(skb->protocol == htons(ETH_P_IP)) && + skb_transport_header_was_set(skb) && + skb_network_header_len(skb) >= sizeof(struct iphdr) && ip_hdr(skb)->protocol == IPPROTO_UDP && + skb_headlen(skb) >= + skb_transport_offset(skb) + sizeof(struct udphdr) && udp_hdr(skb)->dest == htons(PTP_EVENT_PORT); } @@ -1106,7 +1137,7 @@ static int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted, { if ((enable_wanted != efx->ptp_data->enabled) || (enable_wanted && (efx->ptp_data->mode != new_mode))) { - int rc; + int rc = 0; if (enable_wanted) { /* Change of mode requires disable */ @@ -1123,7 +1154,8 @@ static int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted, * succeed. */ efx->ptp_data->mode = new_mode; - rc = efx_ptp_start(efx); + if (netif_running(efx->net_dev)) + rc = efx_ptp_start(efx); if (rc == 0) { rc = efx_ptp_synchronize(efx, PTP_SYNC_ATTEMPTS * 2); @@ -1295,8 +1327,13 @@ static void ptp_event_rx(struct efx_nic *efx, struct efx_ptp_data *ptp) list_add_tail(&evt->link, &ptp->evt_list); queue_work(ptp->workwq, &ptp->work); - } else { - netif_err(efx, rx_err, efx->net_dev, "No free PTP event"); + } else if (!ptp->evt_overflow) { + /* Log a warning message and set the event overflow flag. + * The message won't be logged again until the event queue + * becomes empty. + */ + netif_err(efx, rx_err, efx->net_dev, "PTP event queue overflow\n"); + ptp->evt_overflow = true; } spin_unlock_bh(&ptp->evt_lock); } @@ -1389,7 +1426,7 @@ static int efx_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta) if (rc != 0) return rc; - ptp_data->current_adjfreq = delta; + ptp_data->current_adjfreq = adjustment_ns; return 0; } @@ -1404,7 +1441,7 @@ static int efx_phc_adjtime(struct ptp_clock_info *ptp, s64 delta) MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_ADJUST); MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0); - MCDI_SET_QWORD(inbuf, PTP_IN_ADJUST_FREQ, 0); + MCDI_SET_QWORD(inbuf, PTP_IN_ADJUST_FREQ, ptp_data->current_adjfreq); MCDI_SET_DWORD(inbuf, PTP_IN_ADJUST_SECONDS, (u32)delta_ts.tv_sec); MCDI_SET_DWORD(inbuf, PTP_IN_ADJUST_NANOSECONDS, (u32)delta_ts.tv_nsec); return efx_mcdi_rpc(efx, MC_CMD_PTP, inbuf, sizeof(inbuf), @@ -1491,3 +1528,14 @@ void efx_ptp_probe(struct efx_nic *efx) efx->extra_channel_type[EFX_EXTRA_CHANNEL_PTP] = &efx_ptp_channel_type; } + +void efx_ptp_start_datapath(struct efx_nic *efx) +{ + if (efx_ptp_restart(efx)) + netif_err(efx, drv, efx->net_dev, "Failed to restart PTP.\n"); +} + +void efx_ptp_stop_datapath(struct efx_nic *efx) +{ + efx_ptp_stop(efx); +} diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c index 8f09e686fc23..42488df1f4ec 100644 --- a/drivers/net/ethernet/sfc/rx.c +++ b/drivers/net/ethernet/sfc/rx.c @@ -94,7 +94,7 @@ static inline void efx_sync_rx_buffer(struct efx_nic *efx, void efx_rx_config_page_split(struct efx_nic *efx) { - efx->rx_page_buf_step = ALIGN(efx->rx_dma_len + NET_IP_ALIGN, + efx->rx_page_buf_step = ALIGN(efx->rx_dma_len + efx->rx_ip_align, EFX_RX_BUF_ALIGNMENT); efx->rx_bufs_per_page = efx->rx_buffer_order ? 1 : ((PAGE_SIZE - sizeof(struct efx_rx_page_state)) / @@ -189,9 +189,9 @@ static int efx_init_rx_buffers(struct efx_rx_queue *rx_queue) do { index = rx_queue->added_count & rx_queue->ptr_mask; rx_buf = efx_rx_buffer(rx_queue, index); - rx_buf->dma_addr = dma_addr + NET_IP_ALIGN; + rx_buf->dma_addr = dma_addr + efx->rx_ip_align; rx_buf->page = page; - rx_buf->page_offset = page_offset + NET_IP_ALIGN; + rx_buf->page_offset = page_offset + efx->rx_ip_align; rx_buf->len = efx->rx_dma_len; rx_buf->flags = 0; ++rx_queue->added_count; diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c index 0c9b5d94154f..8bf29eb4a5a0 100644 --- a/drivers/net/ethernet/smsc/smc91x.c +++ b/drivers/net/ethernet/smsc/smc91x.c @@ -82,6 +82,7 @@ static const char version[] = #include <linux/mii.h> #include <linux/workqueue.h> #include <linux/of.h> +#include <linux/of_device.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> @@ -2184,6 +2185,15 @@ static void smc_release_datacs(struct platform_device *pdev, struct net_device * } } +#if IS_BUILTIN(CONFIG_OF) +static const struct of_device_id smc91x_match[] = { + { .compatible = "smsc,lan91c94", }, + { .compatible = "smsc,lan91c111", }, + {}, +}; +MODULE_DEVICE_TABLE(of, smc91x_match); +#endif + /* * smc_init(void) * Input parameters: @@ -2198,6 +2208,7 @@ static void smc_release_datacs(struct platform_device *pdev, struct net_device * static int smc_drv_probe(struct platform_device *pdev) { struct smc91x_platdata *pd = dev_get_platdata(&pdev->dev); + const struct of_device_id *match = NULL; struct smc_local *lp; struct net_device *ndev; struct resource *res, *ires; @@ -2217,11 +2228,34 @@ static int smc_drv_probe(struct platform_device *pdev) */ lp = netdev_priv(ndev); + lp->cfg.flags = 0; if (pd) { memcpy(&lp->cfg, pd, sizeof(lp->cfg)); lp->io_shift = SMC91X_IO_SHIFT(lp->cfg.flags); - } else { + } + +#if IS_BUILTIN(CONFIG_OF) + match = of_match_device(of_match_ptr(smc91x_match), &pdev->dev); + if (match) { + struct device_node *np = pdev->dev.of_node; + u32 val; + + /* Combination of IO widths supported, default to 16-bit */ + if (!of_property_read_u32(np, "reg-io-width", &val)) { + if (val & 1) + lp->cfg.flags |= SMC91X_USE_8BIT; + if ((val == 0) || (val & 2)) + lp->cfg.flags |= SMC91X_USE_16BIT; + if (val & 4) + lp->cfg.flags |= SMC91X_USE_32BIT; + } else { + lp->cfg.flags |= SMC91X_USE_16BIT; + } + } +#endif + + if (!pd && !match) { lp->cfg.flags |= (SMC_CAN_USE_8BIT) ? SMC91X_USE_8BIT : 0; lp->cfg.flags |= (SMC_CAN_USE_16BIT) ? SMC91X_USE_16BIT : 0; lp->cfg.flags |= (SMC_CAN_USE_32BIT) ? SMC91X_USE_32BIT : 0; @@ -2370,15 +2404,6 @@ static int smc_drv_resume(struct device *dev) return 0; } -#ifdef CONFIG_OF -static const struct of_device_id smc91x_match[] = { - { .compatible = "smsc,lan91c94", }, - { .compatible = "smsc,lan91c111", }, - {}, -}; -MODULE_DEVICE_TABLE(of, smc91x_match); -#endif - static struct dev_pm_ops smc_drv_pm_ops = { .suspend = smc_drv_suspend, .resume = smc_drv_resume, diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c index dd0dd6279b4e..4f1d2549130e 100644 --- a/drivers/net/ethernet/tehuti/tehuti.c +++ b/drivers/net/ethernet/tehuti/tehuti.c @@ -2019,7 +2019,6 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ndev->features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_RXCSUM - /*| NETIF_F_FRAGLIST */ ; ndev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO | NETIF_F_HW_VLAN_CTAG_TX; diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 7536a4c01293..5120d9ce1dd4 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -1151,6 +1151,12 @@ static int cpsw_ndo_open(struct net_device *ndev) * receive descs */ cpsw_info(priv, ifup, "submitted %d rx descriptors\n", i); + + if (cpts_register(&priv->pdev->dev, priv->cpts, + priv->data.cpts_clock_mult, + priv->data.cpts_clock_shift)) + dev_err(priv->dev, "error registering cpts device\n"); + } /* Enable Interrupt pacing if configured */ @@ -1197,6 +1203,7 @@ static int cpsw_ndo_stop(struct net_device *ndev) netif_carrier_off(priv->ndev); if (cpsw_common_res_usage_state(priv) <= 1) { + cpts_unregister(priv->cpts); cpsw_intr_disable(priv); cpdma_ctlr_int_ctrl(priv->dma, false); cpdma_ctlr_stop(priv->dma); @@ -1816,6 +1823,8 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data, } i++; + if (i == data->slaves) + break; } return 0; @@ -1983,9 +1992,15 @@ static int cpsw_probe(struct platform_device *pdev) goto clean_runtime_disable_ret; } priv->regs = ss_regs; - priv->version = __raw_readl(&priv->regs->id_ver); priv->host_port = HOST_PORT_NUM; + /* Need to enable clocks with runtime PM api to access module + * registers + */ + pm_runtime_get_sync(&pdev->dev); + priv->version = readl(&priv->regs->id_ver); + pm_runtime_put_sync(&pdev->dev); + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); priv->wr_regs = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(priv->wr_regs)) { @@ -2155,8 +2170,6 @@ static int cpsw_remove(struct platform_device *pdev) unregister_netdev(cpsw_get_slave_ndev(priv, 1)); unregister_netdev(ndev); - cpts_unregister(priv->cpts); - cpsw_ale_destroy(priv->ale); cpdma_chan_destroy(priv->txch); cpdma_chan_destroy(priv->rxch); diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c index 41ba974bf37c..cd9b164a0434 100644 --- a/drivers/net/ethernet/ti/davinci_emac.c +++ b/drivers/net/ethernet/ti/davinci_emac.c @@ -61,6 +61,7 @@ #include <linux/davinci_emac.h> #include <linux/of.h> #include <linux/of_address.h> +#include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/of_net.h> @@ -1752,10 +1753,14 @@ static const struct net_device_ops emac_netdev_ops = { #endif }; +static const struct of_device_id davinci_emac_of_match[]; + static struct emac_platform_data * davinci_emac_of_get_pdata(struct platform_device *pdev, struct emac_priv *priv) { struct device_node *np; + const struct of_device_id *match; + const struct emac_platform_data *auxdata; struct emac_platform_data *pdata = NULL; const u8 *mac_addr; @@ -1793,7 +1798,20 @@ davinci_emac_of_get_pdata(struct platform_device *pdev, struct emac_priv *priv) priv->phy_node = of_parse_phandle(np, "phy-handle", 0); if (!priv->phy_node) - pdata->phy_id = ""; + pdata->phy_id = NULL; + + auxdata = pdev->dev.platform_data; + if (auxdata) { + pdata->interrupt_enable = auxdata->interrupt_enable; + pdata->interrupt_disable = auxdata->interrupt_disable; + } + + match = of_match_device(davinci_emac_of_match, &pdev->dev); + if (match && match->data) { + auxdata = match->data; + pdata->version = auxdata->version; + pdata->hw_ram_addr = auxdata->hw_ram_addr; + } pdev->dev.platform_data = pdata; @@ -2020,8 +2038,14 @@ static const struct dev_pm_ops davinci_emac_pm_ops = { }; #if IS_ENABLED(CONFIG_OF) +static const struct emac_platform_data am3517_emac_data = { + .version = EMAC_VERSION_2, + .hw_ram_addr = 0x01e20000, +}; + static const struct of_device_id davinci_emac_of_match[] = { {.compatible = "ti,davinci-dm6467-emac", }, + {.compatible = "ti,am3517-emac", .data = &am3517_emac_data, }, {}, }; MODULE_DEVICE_TABLE(of, davinci_emac_of_match); diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c index 1f2364126323..2166e879a096 100644 --- a/drivers/net/ethernet/xilinx/ll_temac_main.c +++ b/drivers/net/ethernet/xilinx/ll_temac_main.c @@ -1017,7 +1017,7 @@ static int temac_of_probe(struct platform_device *op) platform_set_drvdata(op, ndev); SET_NETDEV_DEV(ndev, &op->dev); ndev->flags &= ~IFF_MULTICAST; /* clear multicast */ - ndev->features = NETIF_F_SG | NETIF_F_FRAGLIST; + ndev->features = NETIF_F_SG; ndev->netdev_ops = &temac_netdev_ops; ndev->ethtool_ops = &temac_ethtool_ops; #if 0 diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index b2ff038d6d20..f9293da19e26 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -1486,7 +1486,7 @@ static int axienet_of_probe(struct platform_device *op) SET_NETDEV_DEV(ndev, &op->dev); ndev->flags &= ~IFF_MULTICAST; /* clear multicast */ - ndev->features = NETIF_F_SG | NETIF_F_FRAGLIST; + ndev->features = NETIF_F_SG; ndev->netdev_ops = &axienet_netdev_ops; ndev->ethtool_ops = &axienet_ethtool_ops; diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c index 74234a51c851..fefb8cd5eb65 100644 --- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c +++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c @@ -163,26 +163,9 @@ static void xemaclite_enable_interrupts(struct net_local *drvdata) __raw_writel(reg_data | XEL_TSR_XMIT_IE_MASK, drvdata->base_addr + XEL_TSR_OFFSET); - /* Enable the Tx interrupts for the second Buffer if - * configured in HW */ - if (drvdata->tx_ping_pong != 0) { - reg_data = __raw_readl(drvdata->base_addr + - XEL_BUFFER_OFFSET + XEL_TSR_OFFSET); - __raw_writel(reg_data | XEL_TSR_XMIT_IE_MASK, - drvdata->base_addr + XEL_BUFFER_OFFSET + - XEL_TSR_OFFSET); - } - /* Enable the Rx interrupts for the first buffer */ __raw_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr + XEL_RSR_OFFSET); - /* Enable the Rx interrupts for the second Buffer if - * configured in HW */ - if (drvdata->rx_ping_pong != 0) { - __raw_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr + - XEL_BUFFER_OFFSET + XEL_RSR_OFFSET); - } - /* Enable the Global Interrupt Enable */ __raw_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET); } @@ -206,31 +189,10 @@ static void xemaclite_disable_interrupts(struct net_local *drvdata) __raw_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK), drvdata->base_addr + XEL_TSR_OFFSET); - /* Disable the Tx interrupts for the second Buffer - * if configured in HW */ - if (drvdata->tx_ping_pong != 0) { - reg_data = __raw_readl(drvdata->base_addr + XEL_BUFFER_OFFSET + - XEL_TSR_OFFSET); - __raw_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK), - drvdata->base_addr + XEL_BUFFER_OFFSET + - XEL_TSR_OFFSET); - } - /* Disable the Rx interrupts for the first buffer */ reg_data = __raw_readl(drvdata->base_addr + XEL_RSR_OFFSET); __raw_writel(reg_data & (~XEL_RSR_RECV_IE_MASK), drvdata->base_addr + XEL_RSR_OFFSET); - - /* Disable the Rx interrupts for the second buffer - * if configured in HW */ - if (drvdata->rx_ping_pong != 0) { - - reg_data = __raw_readl(drvdata->base_addr + XEL_BUFFER_OFFSET + - XEL_RSR_OFFSET); - __raw_writel(reg_data & (~XEL_RSR_RECV_IE_MASK), - drvdata->base_addr + XEL_BUFFER_OFFSET + - XEL_RSR_OFFSET); - } } /** @@ -258,6 +220,13 @@ static void xemaclite_aligned_write(void *src_ptr, u32 *dest_ptr, *to_u16_ptr++ = *from_u16_ptr++; *to_u16_ptr++ = *from_u16_ptr++; + /* This barrier resolves occasional issues seen around + * cases where the data is not properly flushed out + * from the processor store buffers to the destination + * memory locations. + */ + wmb(); + /* Output a word */ *to_u32_ptr++ = align_buffer; } @@ -273,6 +242,12 @@ static void xemaclite_aligned_write(void *src_ptr, u32 *dest_ptr, for (; length > 0; length--) *to_u8_ptr++ = *from_u8_ptr++; + /* This barrier resolves occasional issues seen around + * cases where the data is not properly flushed out + * from the processor store buffers to the destination + * memory locations. + */ + wmb(); *to_u32_ptr = align_buffer; } } diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 9093004f9b63..2a89da080317 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -770,7 +770,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, int ret; int vnet_hdr_len = 0; int vlan_offset = 0; - int copied; + int copied, total; if (q->flags & IFF_VNET_HDR) { struct virtio_net_hdr vnet_hdr; @@ -785,7 +785,8 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, if (memcpy_toiovecend(iv, (void *)&vnet_hdr, 0, sizeof(vnet_hdr))) return -EFAULT; } - copied = vnet_hdr_len; + total = copied = vnet_hdr_len; + total += skb->len; if (!vlan_tx_tag_present(skb)) len = min_t(int, skb->len, len); @@ -800,6 +801,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto); len = min_t(int, skb->len + VLAN_HLEN, len); + total += VLAN_HLEN; copy = min_t(int, vlan_offset, len); ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy); @@ -817,10 +819,9 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, } ret = skb_copy_datagram_const_iovec(skb, vlan_offset, iv, copied, len); - copied += len; done: - return ret ? ret : copied; + return ret ? ret : total; } static ssize_t macvtap_do_read(struct macvtap_queue *q, struct kiocb *iocb, @@ -875,7 +876,9 @@ static ssize_t macvtap_aio_read(struct kiocb *iocb, const struct iovec *iv, } ret = macvtap_do_read(q, iocb, iv, len, file->f_flags & O_NONBLOCK); - ret = min_t(ssize_t, ret, len); /* XXX copied from tun.c. Why? */ + ret = min_t(ssize_t, ret, len); + if (ret > 0) + iocb->ki_pos = ret; out: return ret; } diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 3ae28f420868..26fa05a472b4 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -336,6 +336,21 @@ static struct phy_driver ksphy_driver[] = { .resume = genphy_resume, .driver = { .owner = THIS_MODULE,}, }, { + .phy_id = PHY_ID_KSZ8041RNLI, + .phy_id_mask = 0x00fffff0, + .name = "Micrel KSZ8041RNLI", + .features = PHY_BASIC_FEATURES | + SUPPORTED_Pause | SUPPORTED_Asym_Pause, + .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, + .config_init = kszphy_config_init, + .config_aneg = genphy_config_aneg, + .read_status = genphy_read_status, + .ack_interrupt = kszphy_ack_interrupt, + .config_intr = kszphy_config_intr, + .suspend = genphy_suspend, + .resume = genphy_resume, + .driver = { .owner = THIS_MODULE,}, +}, { .phy_id = PHY_ID_KSZ8051, .phy_id_mask = 0x00fffff0, .name = "Micrel KSZ8051", diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 782e38bfc1ee..7c8343a4f918 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1184,7 +1184,7 @@ static ssize_t tun_put_user(struct tun_struct *tun, { struct tun_pi pi = { 0, skb->protocol }; ssize_t total = 0; - int vlan_offset = 0; + int vlan_offset = 0, copied; if (!(tun->flags & TUN_NO_PI)) { if ((len -= sizeof(pi)) < 0) @@ -1248,6 +1248,8 @@ static ssize_t tun_put_user(struct tun_struct *tun, total += tun->vnet_hdr_sz; } + copied = total; + total += skb->len; if (!vlan_tx_tag_present(skb)) { len = min_t(int, skb->len, len); } else { @@ -1262,24 +1264,24 @@ static ssize_t tun_put_user(struct tun_struct *tun, vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto); len = min_t(int, skb->len + VLAN_HLEN, len); + total += VLAN_HLEN; copy = min_t(int, vlan_offset, len); - ret = skb_copy_datagram_const_iovec(skb, 0, iv, total, copy); + ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy); len -= copy; - total += copy; + copied += copy; if (ret || !len) goto done; copy = min_t(int, sizeof(veth), len); - ret = memcpy_toiovecend(iv, (void *)&veth, total, copy); + ret = memcpy_toiovecend(iv, (void *)&veth, copied, copy); len -= copy; - total += copy; + copied += copy; if (ret || !len) goto done; } - skb_copy_datagram_const_iovec(skb, vlan_offset, iv, total, len); - total += len; + skb_copy_datagram_const_iovec(skb, vlan_offset, iv, copied, len); done: tun->dev->stats.tx_packets++; @@ -1356,6 +1358,8 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, ret = tun_do_read(tun, tfile, iocb, iv, len, file->f_flags & O_NONBLOCK); ret = min_t(ssize_t, ret, len); + if (ret > 0) + iocb->ki_pos = ret; out: tun_put(tun); return ret; diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 916241d16c67..d208f8604981 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -426,10 +426,10 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len) if (unlikely(len < sizeof(struct virtio_net_hdr) + ETH_HLEN)) { pr_debug("%s: short packet %i\n", dev->name, len); dev->stats.rx_length_errors++; - if (vi->big_packets) - give_pages(rq, buf); - else if (vi->mergeable_rx_bufs) + if (vi->mergeable_rx_bufs) put_page(virt_to_head_page(buf)); + else if (vi->big_packets) + give_pages(rq, buf); else dev_kfree_skb(buf); return; @@ -1367,6 +1367,11 @@ static void virtnet_config_changed(struct virtio_device *vdev) static void virtnet_free_queues(struct virtnet_info *vi) { + int i; + + for (i = 0; i < vi->max_queue_pairs; i++) + netif_napi_del(&vi->rq[i].napi); + kfree(vi->rq); kfree(vi->sq); } @@ -1396,10 +1401,10 @@ static void free_unused_bufs(struct virtnet_info *vi) struct virtqueue *vq = vi->rq[i].vq; while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) { - if (vi->big_packets) - give_pages(&vi->rq[i], buf); - else if (vi->mergeable_rx_bufs) + if (vi->mergeable_rx_bufs) put_page(virt_to_head_page(buf)); + else if (vi->big_packets) + give_pages(&vi->rq[i], buf); else dev_kfree_skb(buf); --vi->rq[i].num; diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 0358c07f7669..249e01c5600c 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1668,7 +1668,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, netdev_dbg(dev, "circular route to %pI4\n", &dst->sin.sin_addr.s_addr); dev->stats.collisions++; - goto tx_error; + goto rt_tx_error; } /* Bypass encapsulation if the destination is local */ diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 1ec52356b5a1..130657db5c43 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -3984,18 +3984,20 @@ static void ar9003_hw_quick_drop_apply(struct ath_hw *ah, u16 freq) int quick_drop; s32 t[3], f[3] = {5180, 5500, 5785}; - if (!(pBase->miscConfiguration & BIT(1))) + if (!(pBase->miscConfiguration & BIT(4))) return; - if (freq < 4000) - quick_drop = eep->modalHeader2G.quick_drop; - else { - t[0] = eep->base_ext1.quick_drop_low; - t[1] = eep->modalHeader5G.quick_drop; - t[2] = eep->base_ext1.quick_drop_high; - quick_drop = ar9003_hw_power_interpolate(freq, f, t, 3); + if (AR_SREV_9300(ah) || AR_SREV_9580(ah) || AR_SREV_9340(ah)) { + if (freq < 4000) { + quick_drop = eep->modalHeader2G.quick_drop; + } else { + t[0] = eep->base_ext1.quick_drop_low; + t[1] = eep->modalHeader5G.quick_drop; + t[2] = eep->base_ext1.quick_drop_high; + quick_drop = ar9003_hw_power_interpolate(freq, f, t, 3); + } + REG_RMW_FIELD(ah, AR_PHY_AGC, AR_PHY_AGC_QUICK_DROP, quick_drop); } - REG_RMW_FIELD(ah, AR_PHY_AGC, AR_PHY_AGC_QUICK_DROP, quick_drop); } static void ar9003_hw_txend_to_xpa_off_apply(struct ath_hw *ah, bool is2ghz) @@ -4035,7 +4037,7 @@ static void ar9003_hw_xlna_bias_strength_apply(struct ath_hw *ah, bool is2ghz) struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; u8 bias; - if (!(eep->baseEepHeader.featureEnable & 0x40)) + if (!(eep->baseEepHeader.miscConfiguration & 0x40)) return; if (!AR_SREV_9300(ah)) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 54b04155e43b..8918035da3a3 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -146,10 +146,9 @@ static void ath9k_hw_set_clockrate(struct ath_hw *ah) else clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM; - if (IS_CHAN_HT40(chan)) - clockrate *= 2; - - if (ah->curchan) { + if (chan) { + if (IS_CHAN_HT40(chan)) + clockrate *= 2; if (IS_CHAN_HALF_RATE(chan)) clockrate /= 2; if (IS_CHAN_QUARTER_RATE(chan)) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 09cdbcd09739..b5a19e098f2d 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1276,6 +1276,10 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf, if (!rts_thresh || (len > rts_thresh)) rts = true; } + + if (!aggr) + len = fi->framelen; + ath_buf_set_rate(sc, bf, &info, len, rts); } diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index de9eb2cfbf4b..366339421d4f 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -2041,13 +2041,20 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len) case WCN36XX_HAL_DELETE_STA_CONTEXT_IND: mutex_lock(&wcn->hal_ind_mutex); msg_ind = kmalloc(sizeof(*msg_ind), GFP_KERNEL); - msg_ind->msg_len = len; - msg_ind->msg = kmalloc(len, GFP_KERNEL); - memcpy(msg_ind->msg, buf, len); - list_add_tail(&msg_ind->list, &wcn->hal_ind_queue); - queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work); - wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n"); + if (msg_ind) { + msg_ind->msg_len = len; + msg_ind->msg = kmalloc(len, GFP_KERNEL); + memcpy(msg_ind->msg, buf, len); + list_add_tail(&msg_ind->list, &wcn->hal_ind_queue); + queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work); + wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n"); + } mutex_unlock(&wcn->hal_ind_mutex); + if (msg_ind) + break; + /* FIXME: Do something smarter then just printing an error. */ + wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n", + msg_header->msg_type); break; default: wcn36xx_err("SMD_EVENT (%d) not supported\n", diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig index b00a7e92225f..54e36fcb3954 100644 --- a/drivers/net/wireless/brcm80211/Kconfig +++ b/drivers/net/wireless/brcm80211/Kconfig @@ -5,6 +5,8 @@ config BRCMSMAC tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver" depends on MAC80211 depends on BCMA + select NEW_LEDS if BCMA_DRIVER_GPIO + select LEDS_CLASS if BCMA_DRIVER_GPIO select BRCMUTIL select FW_LOADER select CRC_CCITT diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index 905704e335d7..abc9ceca70f3 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c @@ -109,6 +109,8 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev, brcmf_err("Disable F2 failed:%d\n", err_ret); } + } else { + err_ret = -ENOENT; } } else if ((regaddr == SDIO_CCCR_ABORT) || (regaddr == SDIO_CCCR_IENx)) { diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index 85879dbaa402..3c34a72a5d64 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c @@ -67,8 +67,8 @@ #include "iwl-agn-hw.h" /* Highest firmware API version supported */ -#define IWL7260_UCODE_API_MAX 7 -#define IWL3160_UCODE_API_MAX 7 +#define IWL7260_UCODE_API_MAX 8 +#define IWL3160_UCODE_API_MAX 8 /* Oldest version we won't warn about */ #define IWL7260_UCODE_API_OK 7 @@ -130,6 +130,7 @@ const struct iwl_cfg iwl7260_2ac_cfg = { .ht_params = &iwl7000_ht_params, .nvm_ver = IWL7260_NVM_VERSION, .nvm_calib_ver = IWL7260_TX_POWER_VERSION, + .host_interrupt_operation_mode = true, }; const struct iwl_cfg iwl7260_2ac_cfg_high_temp = { @@ -140,6 +141,7 @@ const struct iwl_cfg iwl7260_2ac_cfg_high_temp = { .nvm_ver = IWL7260_NVM_VERSION, .nvm_calib_ver = IWL7260_TX_POWER_VERSION, .high_temp = true, + .host_interrupt_operation_mode = true, }; const struct iwl_cfg iwl7260_2n_cfg = { @@ -149,6 +151,7 @@ const struct iwl_cfg iwl7260_2n_cfg = { .ht_params = &iwl7000_ht_params, .nvm_ver = IWL7260_NVM_VERSION, .nvm_calib_ver = IWL7260_TX_POWER_VERSION, + .host_interrupt_operation_mode = true, }; const struct iwl_cfg iwl7260_n_cfg = { @@ -158,6 +161,7 @@ const struct iwl_cfg iwl7260_n_cfg = { .ht_params = &iwl7000_ht_params, .nvm_ver = IWL7260_NVM_VERSION, .nvm_calib_ver = IWL7260_TX_POWER_VERSION, + .host_interrupt_operation_mode = true, }; const struct iwl_cfg iwl3160_2ac_cfg = { @@ -167,6 +171,7 @@ const struct iwl_cfg iwl3160_2ac_cfg = { .ht_params = &iwl7000_ht_params, .nvm_ver = IWL3160_NVM_VERSION, .nvm_calib_ver = IWL3160_TX_POWER_VERSION, + .host_interrupt_operation_mode = true, }; const struct iwl_cfg iwl3160_2n_cfg = { @@ -176,6 +181,7 @@ const struct iwl_cfg iwl3160_2n_cfg = { .ht_params = &iwl7000_ht_params, .nvm_ver = IWL3160_NVM_VERSION, .nvm_calib_ver = IWL3160_TX_POWER_VERSION, + .host_interrupt_operation_mode = true, }; const struct iwl_cfg iwl3160_n_cfg = { @@ -185,6 +191,7 @@ const struct iwl_cfg iwl3160_n_cfg = { .ht_params = &iwl7000_ht_params, .nvm_ver = IWL3160_NVM_VERSION, .nvm_calib_ver = IWL3160_TX_POWER_VERSION, + .host_interrupt_operation_mode = true, }; const struct iwl_cfg iwl7265_2ac_cfg = { @@ -196,5 +203,23 @@ const struct iwl_cfg iwl7265_2ac_cfg = { .nvm_calib_ver = IWL7265_TX_POWER_VERSION, }; +const struct iwl_cfg iwl7265_2n_cfg = { + .name = "Intel(R) Dual Band Wireless N 7265", + .fw_name_pre = IWL7265_FW_PRE, + IWL_DEVICE_7000, + .ht_params = &iwl7000_ht_params, + .nvm_ver = IWL7265_NVM_VERSION, + .nvm_calib_ver = IWL7265_TX_POWER_VERSION, +}; + +const struct iwl_cfg iwl7265_n_cfg = { + .name = "Intel(R) Wireless N 7265", + .fw_name_pre = IWL7265_FW_PRE, + IWL_DEVICE_7000, + .ht_params = &iwl7000_ht_params, + .nvm_ver = IWL7265_NVM_VERSION, + .nvm_calib_ver = IWL7265_TX_POWER_VERSION, +}; + MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK)); diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index 18f232e8e812..03fd9aa8bfda 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h @@ -207,6 +207,8 @@ struct iwl_eeprom_params { * @rx_with_siso_diversity: 1x1 device with rx antenna diversity * @internal_wimax_coex: internal wifi/wimax combo device * @high_temp: Is this NIC is designated to be in high temperature. + * @host_interrupt_operation_mode: device needs host interrupt operation + * mode set * * We enable the driver to be backward compatible wrt. hardware features. * API differences in uCode shouldn't be handled here but through TLVs @@ -235,6 +237,7 @@ struct iwl_cfg { enum iwl_led_mode led_mode; const bool rx_with_siso_diversity; const bool internal_wimax_coex; + const bool host_interrupt_operation_mode; bool high_temp; }; @@ -294,6 +297,8 @@ extern const struct iwl_cfg iwl3160_2ac_cfg; extern const struct iwl_cfg iwl3160_2n_cfg; extern const struct iwl_cfg iwl3160_n_cfg; extern const struct iwl_cfg iwl7265_2ac_cfg; +extern const struct iwl_cfg iwl7265_2n_cfg; +extern const struct iwl_cfg iwl7265_n_cfg; #endif /* CONFIG_IWLMVM */ #endif /* __IWL_CONFIG_H__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 54a4fdc631b7..da4eca8b3007 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -495,14 +495,11 @@ enum secure_load_status_reg { * the CSR_INT_COALESCING is an 8 bit register in 32-usec unit * * default interrupt coalescing timer is 64 x 32 = 2048 usecs - * default interrupt coalescing calibration timer is 16 x 32 = 512 usecs */ #define IWL_HOST_INT_TIMEOUT_MAX (0xFF) #define IWL_HOST_INT_TIMEOUT_DEF (0x40) #define IWL_HOST_INT_TIMEOUT_MIN (0x0) -#define IWL_HOST_INT_CALIB_TIMEOUT_MAX (0xFF) -#define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10) -#define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0) +#define IWL_HOST_INT_OPER_MODE BIT(31) /***************************************************************************** * 7000/3000 series SHR DTS addresses * diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c index 5d066cbc5ac7..75b72a956552 100644 --- a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c @@ -391,7 +391,6 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) BT_VALID_LUT | BT_VALID_WIFI_RX_SW_PRIO_BOOST | BT_VALID_WIFI_TX_SW_PRIO_BOOST | - BT_VALID_MULTI_PRIO_LUT | BT_VALID_CORUN_LUT_20 | BT_VALID_CORUN_LUT_40 | BT_VALID_ANT_ISOLATION | @@ -842,6 +841,11 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac, sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id], lockdep_is_held(&mvm->mutex)); + + /* This can happen if the station has been removed right now */ + if (IS_ERR_OR_NULL(sta)) + return; + mvmsta = (void *)sta->drv_priv; data->num_bss_ifaces++; diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index 6f45966817bb..b9b81e881dd0 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c @@ -895,7 +895,7 @@ static int iwl_mvm_get_last_nonqos_seq(struct iwl_mvm *mvm, /* new API returns next, not last-used seqno */ if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API) - err -= 0x10; + err = (u16) (err - 0x10); } iwl_free_resp(&cmd); @@ -1549,7 +1549,7 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm, if (gtkdata.unhandled_cipher) return false; if (!gtkdata.num_keys) - return true; + goto out; if (!gtkdata.last_gtk) return false; @@ -1600,6 +1600,7 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm, (void *)&replay_ctr, GFP_KERNEL); } +out: mvmvif->seqno_valid = true; /* +0x10 because the set API expects next-to-use, not last-used */ mvmvif->seqno = le16_to_cpu(status->non_qos_seq_ctr) + 0x10; diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index 9864d713eb2c..a8fe6b41f9a3 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c @@ -119,6 +119,10 @@ static ssize_t iwl_dbgfs_sta_drain_write(struct file *file, if (sscanf(buf, "%d %d", &sta_id, &drain) != 2) return -EINVAL; + if (sta_id < 0 || sta_id >= IWL_MVM_STATION_COUNT) + return -EINVAL; + if (drain < 0 || drain > 1) + return -EINVAL; mutex_lock(&mvm->mutex); diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c index 33cf56fdfc41..95ce4b601fef 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c @@ -176,8 +176,11 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm, * P2P Device discoveribility, while there are other higher priority * events in the system). */ - if (WARN_ONCE(!le32_to_cpu(notif->status), - "Failed to schedule time event\n")) { + if (!le32_to_cpu(notif->status)) { + bool start = le32_to_cpu(notif->action) & + TE_V2_NOTIF_HOST_EVENT_START; + IWL_WARN(mvm, "Time Event %s notification failure\n", + start ? "start" : "end"); if (iwl_mvm_te_check_disconnect(mvm, te_data->vif, NULL)) { iwl_mvm_te_clear_data(mvm, te_data); return; diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index 941c0c88f982..86605027c41d 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c @@ -353,6 +353,27 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { /* 7265 Series */ {IWL_PCI_DEVICE(0x095A, 0x5010, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x5110, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095B, 0x5310, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095B, 0x5302, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095B, 0x5210, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095B, 0x5012, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095B, 0x500A, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x5410, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x1010, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x5000, iwl7265_2n_cfg)}, + {IWL_PCI_DEVICE(0x095B, 0x5200, iwl7265_2n_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x5002, iwl7265_n_cfg)}, + {IWL_PCI_DEVICE(0x095B, 0x5202, iwl7265_n_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x9010, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x9210, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x9410, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x5020, iwl7265_2n_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x502A, iwl7265_2n_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x5420, iwl7265_2n_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x5090, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095B, 0x5290, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x5490, iwl7265_2ac_cfg)}, #endif /* CONFIG_IWLMVM */ {0} diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index fa22639b63c9..051268c037b1 100644 --- a/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h @@ -477,4 +477,12 @@ static inline bool iwl_is_rfkill_set(struct iwl_trans *trans) CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW); } +static inline void iwl_nic_error(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + + set_bit(STATUS_FW_ERROR, &trans_pcie->status); + iwl_op_mode_nic_error(trans->op_mode); +} + #endif /* __iwl_trans_int_pcie_h__ */ diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index 3f237b42eb36..be3995afa9d0 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c @@ -489,6 +489,10 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq) /* Set interrupt coalescing timer to default (2048 usecs) */ iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); + + /* W/A for interrupt coalescing bug in 7260 and 3160 */ + if (trans->cfg->host_interrupt_operation_mode) + iwl_set_bit(trans, CSR_INT_COALESCING, IWL_HOST_INT_OPER_MODE); } static void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq) @@ -796,12 +800,13 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans) iwl_pcie_dump_csr(trans); iwl_dump_fh(trans, NULL); + /* set the ERROR bit before we wake up the caller */ set_bit(STATUS_FW_ERROR, &trans_pcie->status); clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); wake_up(&trans_pcie->wait_command_queue); local_bh_disable(); - iwl_op_mode_nic_error(trans->op_mode); + iwl_nic_error(trans); local_bh_enable(); } diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 5d9337bec67a..cde9c16f6e4f 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -279,9 +279,6 @@ static int iwl_pcie_nic_init(struct iwl_trans *trans) spin_lock_irqsave(&trans_pcie->irq_lock, flags); iwl_pcie_apm_init(trans); - /* Set interrupt coalescing calibration timer to default (512 usecs) */ - iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF); - spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); iwl_pcie_set_pwr(trans, false); diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 059c5acad3a0..0adde919a258 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c @@ -207,7 +207,7 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data) IWL_ERR(trans, "scratch %d = 0x%08x\n", i, le32_to_cpu(txq->scratchbufs[i].scratch)); - iwl_op_mode_nic_error(trans->op_mode); + iwl_nic_error(trans); } /* @@ -1023,7 +1023,7 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx) if (nfreed++ > 0) { IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n", idx, q->write_ptr, q->read_ptr); - iwl_op_mode_nic_error(trans->op_mode); + iwl_nic_error(trans); } } @@ -1562,7 +1562,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, get_cmd_string(trans_pcie, cmd->id)); ret = -ETIMEDOUT; - iwl_op_mode_nic_error(trans->op_mode); + iwl_nic_error(trans); goto cancel; } diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 9df7bc91a26f..c72438bb2faf 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -383,6 +383,14 @@ struct hwsim_radiotap_hdr { __le16 rt_chbitmask; } __packed; +struct hwsim_radiotap_ack_hdr { + struct ieee80211_radiotap_header hdr; + u8 rt_flags; + u8 pad; + __le16 rt_channel; + __le16 rt_chbitmask; +} __packed; + /* MAC80211_HWSIM netlinf family */ static struct genl_family hwsim_genl_family = { .id = GENL_ID_GENERATE, @@ -500,7 +508,7 @@ static void mac80211_hwsim_monitor_ack(struct ieee80211_channel *chan, const u8 *addr) { struct sk_buff *skb; - struct hwsim_radiotap_hdr *hdr; + struct hwsim_radiotap_ack_hdr *hdr; u16 flags; struct ieee80211_hdr *hdr11; @@ -511,14 +519,14 @@ static void mac80211_hwsim_monitor_ack(struct ieee80211_channel *chan, if (skb == NULL) return; - hdr = (struct hwsim_radiotap_hdr *) skb_put(skb, sizeof(*hdr)); + hdr = (struct hwsim_radiotap_ack_hdr *) skb_put(skb, sizeof(*hdr)); hdr->hdr.it_version = PKTHDR_RADIOTAP_VERSION; hdr->hdr.it_pad = 0; hdr->hdr.it_len = cpu_to_le16(sizeof(*hdr)); hdr->hdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | (1 << IEEE80211_RADIOTAP_CHANNEL)); hdr->rt_flags = 0; - hdr->rt_rate = 0; + hdr->pad = 0; hdr->rt_channel = cpu_to_le16(chan->center_freq); flags = IEEE80211_CHAN_2GHZ; hdr->rt_chbitmask = cpu_to_le16(flags); @@ -1230,7 +1238,7 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, HRTIMER_MODE_REL); } else if (!info->enable_beacon) { unsigned int count = 0; - ieee80211_iterate_active_interfaces( + ieee80211_iterate_active_interfaces_atomic( data->hw, IEEE80211_IFACE_ITER_NORMAL, mac80211_hwsim_bcn_en_iter, &count); wiphy_debug(hw->wiphy, " beaconing vifs remaining: %u", diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index c8e029df770e..a09398fe9e2a 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -319,8 +319,8 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, if (bss_desc && bss_desc->ssid.ssid_len && (!mwifiex_ssid_cmp(&priv->curr_bss_params.bss_descriptor. ssid, &bss_desc->ssid))) { - kfree(bss_desc); - return 0; + ret = 0; + goto done; } /* Exit Adhoc mode first */ diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 2329cccf1fa6..870f1fa58370 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -368,11 +368,11 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, unsigned long rx_ring_ref, unsigned int tx_evtchn, unsigned int rx_evtchn) { + struct task_struct *task; int err = -ENOMEM; - /* Already connected through? */ - if (vif->tx_irq) - return 0; + BUG_ON(vif->tx_irq); + BUG_ON(vif->task); err = xenvif_map_frontend_rings(vif, tx_ring_ref, rx_ring_ref); if (err < 0) @@ -411,14 +411,16 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, } init_waitqueue_head(&vif->wq); - vif->task = kthread_create(xenvif_kthread, - (void *)vif, "%s", vif->dev->name); - if (IS_ERR(vif->task)) { + task = kthread_create(xenvif_kthread, + (void *)vif, "%s", vif->dev->name); + if (IS_ERR(task)) { pr_warn("Could not allocate kthread for %s\n", vif->dev->name); - err = PTR_ERR(vif->task); + err = PTR_ERR(task); goto err_rx_unbind; } + vif->task = task; + rtnl_lock(); if (!vif->can_sg && vif->dev->mtu > ETH_DATA_LEN) dev_set_mtu(vif->dev, ETH_DATA_LEN); @@ -461,8 +463,10 @@ void xenvif_disconnect(struct xenvif *vif) if (netif_carrier_ok(vif->dev)) xenvif_carrier_off(vif); - if (vif->task) + if (vif->task) { kthread_stop(vif->task); + vif->task = NULL; + } if (vif->tx_irq) { if (vif->tx_irq == vif->rx_irq) diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 64f0e0d18b81..e884ee1fe7ed 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -452,7 +452,7 @@ static int xenvif_gop_skb(struct sk_buff *skb, } /* Set up a GSO prefix descriptor, if necessary */ - if ((1 << skb_shinfo(skb)->gso_type) & vif->gso_prefix_mask) { + if ((1 << gso_type) & vif->gso_prefix_mask) { req = RING_GET_REQUEST(&vif->rx, vif->rx.req_cons++); meta = npo->meta + npo->meta_prod++; meta->gso_type = gso_type; @@ -1149,75 +1149,92 @@ static int xenvif_set_skb_gso(struct xenvif *vif, return 0; } -static inline void maybe_pull_tail(struct sk_buff *skb, unsigned int len) +static inline int maybe_pull_tail(struct sk_buff *skb, unsigned int len, + unsigned int max) { - if (skb_is_nonlinear(skb) && skb_headlen(skb) < len) { - /* If we need to pullup then pullup to the max, so we - * won't need to do it again. - */ - int target = min_t(int, skb->len, MAX_TCP_HEADER); - __pskb_pull_tail(skb, target - skb_headlen(skb)); - } + if (skb_headlen(skb) >= len) + return 0; + + /* If we need to pullup then pullup to the max, so we + * won't need to do it again. + */ + if (max > skb->len) + max = skb->len; + + if (__pskb_pull_tail(skb, max - skb_headlen(skb)) == NULL) + return -ENOMEM; + + if (skb_headlen(skb) < len) + return -EPROTO; + + return 0; } +/* This value should be large enough to cover a tagged ethernet header plus + * maximally sized IP and TCP or UDP headers. + */ +#define MAX_IP_HDR_LEN 128 + static int checksum_setup_ip(struct xenvif *vif, struct sk_buff *skb, int recalculate_partial_csum) { - struct iphdr *iph = (void *)skb->data; - unsigned int header_size; unsigned int off; - int err = -EPROTO; + bool fragment; + int err; - off = sizeof(struct iphdr); + fragment = false; - header_size = skb->network_header + off + MAX_IPOPTLEN; - maybe_pull_tail(skb, header_size); + err = maybe_pull_tail(skb, + sizeof(struct iphdr), + MAX_IP_HDR_LEN); + if (err < 0) + goto out; - off = iph->ihl * 4; + if (ip_hdr(skb)->frag_off & htons(IP_OFFSET | IP_MF)) + fragment = true; - switch (iph->protocol) { + off = ip_hdrlen(skb); + + err = -EPROTO; + + switch (ip_hdr(skb)->protocol) { case IPPROTO_TCP: + err = maybe_pull_tail(skb, + off + sizeof(struct tcphdr), + MAX_IP_HDR_LEN); + if (err < 0) + goto out; + if (!skb_partial_csum_set(skb, off, offsetof(struct tcphdr, check))) goto out; - if (recalculate_partial_csum) { - struct tcphdr *tcph = tcp_hdr(skb); - - header_size = skb->network_header + - off + - sizeof(struct tcphdr); - maybe_pull_tail(skb, header_size); - - tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, - skb->len - off, - IPPROTO_TCP, 0); - } + if (recalculate_partial_csum) + tcp_hdr(skb)->check = + ~csum_tcpudp_magic(ip_hdr(skb)->saddr, + ip_hdr(skb)->daddr, + skb->len - off, + IPPROTO_TCP, 0); break; case IPPROTO_UDP: + err = maybe_pull_tail(skb, + off + sizeof(struct udphdr), + MAX_IP_HDR_LEN); + if (err < 0) + goto out; + if (!skb_partial_csum_set(skb, off, offsetof(struct udphdr, check))) goto out; - if (recalculate_partial_csum) { - struct udphdr *udph = udp_hdr(skb); - - header_size = skb->network_header + - off + - sizeof(struct udphdr); - maybe_pull_tail(skb, header_size); - - udph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, - skb->len - off, - IPPROTO_UDP, 0); - } + if (recalculate_partial_csum) + udp_hdr(skb)->check = + ~csum_tcpudp_magic(ip_hdr(skb)->saddr, + ip_hdr(skb)->daddr, + skb->len - off, + IPPROTO_UDP, 0); break; default: - if (net_ratelimit()) - netdev_err(vif->dev, - "Attempting to checksum a non-TCP/UDP packet, " - "dropping a protocol %d packet\n", - iph->protocol); goto out; } @@ -1227,121 +1244,138 @@ out: return err; } +/* This value should be large enough to cover a tagged ethernet header plus + * an IPv6 header, all options, and a maximal TCP or UDP header. + */ +#define MAX_IPV6_HDR_LEN 256 + +#define OPT_HDR(type, skb, off) \ + (type *)(skb_network_header(skb) + (off)) + static int checksum_setup_ipv6(struct xenvif *vif, struct sk_buff *skb, int recalculate_partial_csum) { - int err = -EPROTO; - struct ipv6hdr *ipv6h = (void *)skb->data; + int err; u8 nexthdr; - unsigned int header_size; unsigned int off; + unsigned int len; bool fragment; bool done; + fragment = false; done = false; off = sizeof(struct ipv6hdr); - header_size = skb->network_header + off; - maybe_pull_tail(skb, header_size); + err = maybe_pull_tail(skb, off, MAX_IPV6_HDR_LEN); + if (err < 0) + goto out; - nexthdr = ipv6h->nexthdr; + nexthdr = ipv6_hdr(skb)->nexthdr; - while ((off <= sizeof(struct ipv6hdr) + ntohs(ipv6h->payload_len)) && - !done) { + len = sizeof(struct ipv6hdr) + ntohs(ipv6_hdr(skb)->payload_len); + while (off <= len && !done) { switch (nexthdr) { case IPPROTO_DSTOPTS: case IPPROTO_HOPOPTS: case IPPROTO_ROUTING: { - struct ipv6_opt_hdr *hp = (void *)(skb->data + off); + struct ipv6_opt_hdr *hp; - header_size = skb->network_header + - off + - sizeof(struct ipv6_opt_hdr); - maybe_pull_tail(skb, header_size); + err = maybe_pull_tail(skb, + off + + sizeof(struct ipv6_opt_hdr), + MAX_IPV6_HDR_LEN); + if (err < 0) + goto out; + hp = OPT_HDR(struct ipv6_opt_hdr, skb, off); nexthdr = hp->nexthdr; off += ipv6_optlen(hp); break; } case IPPROTO_AH: { - struct ip_auth_hdr *hp = (void *)(skb->data + off); + struct ip_auth_hdr *hp; - header_size = skb->network_header + - off + - sizeof(struct ip_auth_hdr); - maybe_pull_tail(skb, header_size); + err = maybe_pull_tail(skb, + off + + sizeof(struct ip_auth_hdr), + MAX_IPV6_HDR_LEN); + if (err < 0) + goto out; + hp = OPT_HDR(struct ip_auth_hdr, skb, off); nexthdr = hp->nexthdr; - off += (hp->hdrlen+2)<<2; + off += ipv6_authlen(hp); + break; + } + case IPPROTO_FRAGMENT: { + struct frag_hdr *hp; + + err = maybe_pull_tail(skb, + off + + sizeof(struct frag_hdr), + MAX_IPV6_HDR_LEN); + if (err < 0) + goto out; + + hp = OPT_HDR(struct frag_hdr, skb, off); + + if (hp->frag_off & htons(IP6_OFFSET | IP6_MF)) + fragment = true; + + nexthdr = hp->nexthdr; + off += sizeof(struct frag_hdr); break; } - case IPPROTO_FRAGMENT: - fragment = true; - /* fall through */ default: done = true; break; } } - if (!done) { - if (net_ratelimit()) - netdev_err(vif->dev, "Failed to parse packet header\n"); - goto out; - } + err = -EPROTO; - if (fragment) { - if (net_ratelimit()) - netdev_err(vif->dev, "Packet is a fragment!\n"); + if (!done || fragment) goto out; - } switch (nexthdr) { case IPPROTO_TCP: + err = maybe_pull_tail(skb, + off + sizeof(struct tcphdr), + MAX_IPV6_HDR_LEN); + if (err < 0) + goto out; + if (!skb_partial_csum_set(skb, off, offsetof(struct tcphdr, check))) goto out; - if (recalculate_partial_csum) { - struct tcphdr *tcph = tcp_hdr(skb); - - header_size = skb->network_header + - off + - sizeof(struct tcphdr); - maybe_pull_tail(skb, header_size); - - tcph->check = ~csum_ipv6_magic(&ipv6h->saddr, - &ipv6h->daddr, - skb->len - off, - IPPROTO_TCP, 0); - } + if (recalculate_partial_csum) + tcp_hdr(skb)->check = + ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, + &ipv6_hdr(skb)->daddr, + skb->len - off, + IPPROTO_TCP, 0); break; case IPPROTO_UDP: + err = maybe_pull_tail(skb, + off + sizeof(struct udphdr), + MAX_IPV6_HDR_LEN); + if (err < 0) + goto out; + if (!skb_partial_csum_set(skb, off, offsetof(struct udphdr, check))) goto out; - if (recalculate_partial_csum) { - struct udphdr *udph = udp_hdr(skb); - - header_size = skb->network_header + - off + - sizeof(struct udphdr); - maybe_pull_tail(skb, header_size); - - udph->check = ~csum_ipv6_magic(&ipv6h->saddr, - &ipv6h->daddr, - skb->len - off, - IPPROTO_UDP, 0); - } + if (recalculate_partial_csum) + udp_hdr(skb)->check = + ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, + &ipv6_hdr(skb)->daddr, + skb->len - off, + IPPROTO_UDP, 0); break; default: - if (net_ratelimit()) - netdev_err(vif->dev, - "Attempting to checksum a non-TCP/UDP packet, " - "dropping a protocol %d packet\n", - nexthdr); goto out; } @@ -1411,14 +1445,15 @@ static bool tx_credit_exceeded(struct xenvif *vif, unsigned size) return false; } -static unsigned xenvif_tx_build_gops(struct xenvif *vif) +static unsigned xenvif_tx_build_gops(struct xenvif *vif, int budget) { struct gnttab_copy *gop = vif->tx_copy_ops, *request_gop; struct sk_buff *skb; int ret; while ((nr_pending_reqs(vif) + XEN_NETBK_LEGACY_SLOTS_MAX - < MAX_PENDING_REQS)) { + < MAX_PENDING_REQS) && + (skb_queue_len(&vif->tx_queue) < budget)) { struct xen_netif_tx_request txreq; struct xen_netif_tx_request txfrags[XEN_NETBK_LEGACY_SLOTS_MAX]; struct page *page; @@ -1440,7 +1475,7 @@ static unsigned xenvif_tx_build_gops(struct xenvif *vif) continue; } - RING_FINAL_CHECK_FOR_REQUESTS(&vif->tx, work_to_do); + work_to_do = RING_HAS_UNCONSUMED_REQUESTS(&vif->tx); if (!work_to_do) break; @@ -1580,14 +1615,13 @@ static unsigned xenvif_tx_build_gops(struct xenvif *vif) } -static int xenvif_tx_submit(struct xenvif *vif, int budget) +static int xenvif_tx_submit(struct xenvif *vif) { struct gnttab_copy *gop = vif->tx_copy_ops; struct sk_buff *skb; int work_done = 0; - while (work_done < budget && - (skb = __skb_dequeue(&vif->tx_queue)) != NULL) { + while ((skb = __skb_dequeue(&vif->tx_queue)) != NULL) { struct xen_netif_tx_request *txp; u16 pending_idx; unsigned data_len; @@ -1662,14 +1696,14 @@ int xenvif_tx_action(struct xenvif *vif, int budget) if (unlikely(!tx_work_todo(vif))) return 0; - nr_gops = xenvif_tx_build_gops(vif); + nr_gops = xenvif_tx_build_gops(vif, budget); if (nr_gops == 0) return 0; gnttab_batch_copy(vif->tx_copy_ops, nr_gops); - work_done = xenvif_tx_submit(vif, nr_gops); + work_done = xenvif_tx_submit(vif); return work_done; } diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index c269e430c760..2aa7b77c7c88 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c @@ -447,6 +447,11 @@ static int mvebu_sw_pci_bridge_read(struct mvebu_pcie_port *port, *value = 0; break; + case PCI_INTERRUPT_LINE: + /* LINE PIN MIN_GNT MAX_LAT */ + *value = 0; + break; + default: *value = 0xffffffff; return PCIBIOS_BAD_REGISTER_NUMBER; diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 9042fdbd7244..25f0bc659164 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -19,6 +19,7 @@ #include <linux/cpu.h> #include <linux/pm_runtime.h> #include <linux/suspend.h> +#include <linux/kexec.h> #include "pci.h" struct pci_dynid { @@ -288,12 +289,27 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev, int error, node; struct drv_dev_and_id ddi = { drv, dev, id }; - /* Execute driver initialization on node where the device's - bus is attached to. This way the driver likely allocates - its local memory on the right node without any need to - change it. */ + /* + * Execute driver initialization on node where the device is + * attached. This way the driver likely allocates its local memory + * on the right node. + */ node = dev_to_node(&dev->dev); - if (node >= 0) { + + /* + * On NUMA systems, we are likely to call a PF probe function using + * work_on_cpu(). If that probe calls pci_enable_sriov() (which + * adds the VF devices via pci_bus_add_device()), we may re-enter + * this function to call the VF probe function. Calling + * work_on_cpu() again will cause a lockdep warning. Since VFs are + * always on the same node as the PF, we can work around this by + * avoiding work_on_cpu() when we're already on the correct node. + * + * Preemption is enabled, so it's theoretically unsafe to use + * numa_node_id(), but even if we run the probe function on the + * wrong node, it should be functionally correct. + */ + if (node >= 0 && node != numa_node_id()) { int cpu; get_online_cpus(); @@ -305,6 +321,7 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev, put_online_cpus(); } else error = local_pci_probe(&ddi); + return error; } @@ -399,12 +416,17 @@ static void pci_device_shutdown(struct device *dev) pci_msi_shutdown(pci_dev); pci_msix_shutdown(pci_dev); +#ifdef CONFIG_KEXEC /* - * Turn off Bus Master bit on the device to tell it to not - * continue to do DMA. Don't touch devices in D3cold or unknown states. + * If this is a kexec reboot, turn off Bus Master bit on the + * device to tell it to not continue to do DMA. Don't touch + * devices in D3cold or unknown states. + * If it is not a kexec reboot, firmware will hit the PCI + * devices with big hammer and stop their DMA any way. */ - if (pci_dev->current_state <= PCI_D3hot) + if (kexec_in_progress && (pci_dev->current_state <= PCI_D3hot)) pci_clear_master(pci_dev); +#endif } #ifdef CONFIG_PM diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 33120d156668..07369f32e8bb 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -4165,6 +4165,14 @@ int pci_set_vga_state(struct pci_dev *dev, bool decode, return 0; } +bool pci_device_is_present(struct pci_dev *pdev) +{ + u32 v; + + return pci_bus_read_dev_vendor_id(pdev->bus, pdev->devfn, &v, 0); +} +EXPORT_SYMBOL_GPL(pci_device_is_present); + #define RESOURCE_ALIGNMENT_PARAM_SIZE COMMAND_LINE_SIZE static char resource_alignment_param[RESOURCE_ALIGNMENT_PARAM_SIZE] = {0}; static DEFINE_SPINLOCK(resource_alignment_lock); diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c index 1576851028db..cc9337a71529 100644 --- a/drivers/pci/remove.c +++ b/drivers/pci/remove.c @@ -24,7 +24,7 @@ static void pci_stop_dev(struct pci_dev *dev) if (dev->is_added) { pci_proc_detach_device(dev); pci_remove_sysfs_dev_files(dev); - device_del(&dev->dev); + device_release_driver(&dev->dev); dev->is_added = 0; } @@ -34,6 +34,8 @@ static void pci_stop_dev(struct pci_dev *dev) static void pci_destroy_dev(struct pci_dev *dev) { + device_del(&dev->dev); + down_write(&pci_bus_sem); list_del(&dev->bus_list); up_write(&pci_bus_sem); diff --git a/drivers/regulator/as3722-regulator.c b/drivers/regulator/as3722-regulator.c index 5917fe3dc983..b9f1d24c6812 100644 --- a/drivers/regulator/as3722-regulator.c +++ b/drivers/regulator/as3722-regulator.c @@ -590,8 +590,8 @@ static int as3722_sd016_set_current_limit(struct regulator_dev *rdev, default: return -EINVAL; } + ret <<= ffs(mask) - 1; val = ret & mask; - val <<= ffs(mask) - 1; return as3722_update_bits(as3722, reg, mask, val); } diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 3fe13130baec..d85f31385b24 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -119,6 +119,11 @@ static const char *rdev_get_name(struct regulator_dev *rdev) return ""; } +static bool have_full_constraints(void) +{ + return has_full_constraints || of_have_populated_dt(); +} + /** * of_get_regulator - get a regulator device node based on supply name * @dev: Device pointer for the consumer (of regulator) device @@ -1340,7 +1345,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id, * Assume that a regulator is physically present and enabled * even if it isn't hooked up and just provide a dummy. */ - if (has_full_constraints && allow_dummy) { + if (have_full_constraints() && allow_dummy) { pr_warn("%s supply %s not found, using dummy regulator\n", devname, id); @@ -3627,7 +3632,7 @@ int regulator_suspend_finish(void) if (error) ret = error; } else { - if (!has_full_constraints) + if (!have_full_constraints()) goto unlock; if (!ops->disable) goto unlock; @@ -3825,7 +3830,7 @@ static int __init regulator_init_complete(void) if (!enabled) goto unlock; - if (has_full_constraints) { + if (have_full_constraints()) { /* We log since this may kill the system if it * goes wrong. */ rdev_info(rdev, "disabling\n"); diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index 032df3799efb..8b5e4c712a01 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c @@ -38,7 +38,7 @@ #define PFUZE100_DEVICEID 0x0 #define PFUZE100_REVID 0x3 -#define PFUZE100_FABID 0x3 +#define PFUZE100_FABID 0x4 #define PFUZE100_SW1ABVOL 0x20 #define PFUZE100_SW1CVOL 0x2e diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index cbf91e25cf7f..aeb40aad0ae7 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -925,7 +925,7 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) config.dev = s5m8767->dev; config.init_data = pdata->regulators[i].initdata; config.driver_data = s5m8767; - config.regmap = iodev->regmap; + config.regmap = iodev->regmap_pmic; config.of_node = pdata->regulators[i].reg_node; rdev[i] = devm_regulator_register(&pdev->dev, ®ulators[id], diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index c0da95e95702..3281c90691c3 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c @@ -220,6 +220,8 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) at91_alarm_year = tm.tm_year; + tm.tm_mon = alrm->time.tm_mon; + tm.tm_mday = alrm->time.tm_mday; tm.tm_hour = alrm->time.tm_hour; tm.tm_min = alrm->time.tm_min; tm.tm_sec = alrm->time.tm_sec; diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c index b7fd02bc0a14..ae8119dc2846 100644 --- a/drivers/rtc/rtc-s5m.c +++ b/drivers/rtc/rtc-s5m.c @@ -28,10 +28,20 @@ #include <linux/mfd/samsung/irq.h> #include <linux/mfd/samsung/rtc.h> +/* + * Maximum number of retries for checking changes in UDR field + * of SEC_RTC_UDR_CON register (to limit possible endless loop). + * + * After writing to RTC registers (setting time or alarm) read the UDR field + * in SEC_RTC_UDR_CON register. UDR is auto-cleared when data have + * been transferred. + */ +#define UDR_READ_RETRY_CNT 5 + struct s5m_rtc_info { struct device *dev; struct sec_pmic_dev *s5m87xx; - struct regmap *rtc; + struct regmap *regmap; struct rtc_device *rtc_dev; int irq; int device_type; @@ -84,12 +94,31 @@ static int s5m8767_tm_to_data(struct rtc_time *tm, u8 *data) } } +/* + * Read RTC_UDR_CON register and wait till UDR field is cleared. + * This indicates that time/alarm update ended. + */ +static inline int s5m8767_wait_for_udr_update(struct s5m_rtc_info *info) +{ + int ret, retry = UDR_READ_RETRY_CNT; + unsigned int data; + + do { + ret = regmap_read(info->regmap, SEC_RTC_UDR_CON, &data); + } while (--retry && (data & RTC_UDR_MASK) && !ret); + + if (!retry) + dev_err(info->dev, "waiting for UDR update, reached max number of retries\n"); + + return ret; +} + static inline int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info) { int ret; unsigned int data; - ret = regmap_read(info->rtc, SEC_RTC_UDR_CON, &data); + ret = regmap_read(info->regmap, SEC_RTC_UDR_CON, &data); if (ret < 0) { dev_err(info->dev, "failed to read update reg(%d)\n", ret); return ret; @@ -98,15 +127,13 @@ static inline int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info) data |= RTC_TIME_EN_MASK; data |= RTC_UDR_MASK; - ret = regmap_write(info->rtc, SEC_RTC_UDR_CON, data); + ret = regmap_write(info->regmap, SEC_RTC_UDR_CON, data); if (ret < 0) { dev_err(info->dev, "failed to write update reg(%d)\n", ret); return ret; } - do { - ret = regmap_read(info->rtc, SEC_RTC_UDR_CON, &data); - } while ((data & RTC_UDR_MASK) && !ret); + ret = s5m8767_wait_for_udr_update(info); return ret; } @@ -116,7 +143,7 @@ static inline int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info) int ret; unsigned int data; - ret = regmap_read(info->rtc, SEC_RTC_UDR_CON, &data); + ret = regmap_read(info->regmap, SEC_RTC_UDR_CON, &data); if (ret < 0) { dev_err(info->dev, "%s: fail to read update reg(%d)\n", __func__, ret); @@ -126,16 +153,14 @@ static inline int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info) data &= ~RTC_TIME_EN_MASK; data |= RTC_UDR_MASK; - ret = regmap_write(info->rtc, SEC_RTC_UDR_CON, data); + ret = regmap_write(info->regmap, SEC_RTC_UDR_CON, data); if (ret < 0) { dev_err(info->dev, "%s: fail to write update reg(%d)\n", __func__, ret); return ret; } - do { - ret = regmap_read(info->rtc, SEC_RTC_UDR_CON, &data); - } while ((data & RTC_UDR_MASK) && !ret); + ret = s5m8767_wait_for_udr_update(info); return ret; } @@ -178,7 +203,7 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm) u8 data[8]; int ret; - ret = regmap_bulk_read(info->rtc, SEC_RTC_SEC, data, 8); + ret = regmap_bulk_read(info->regmap, SEC_RTC_SEC, data, 8); if (ret < 0) return ret; @@ -226,7 +251,7 @@ static int s5m_rtc_set_time(struct device *dev, struct rtc_time *tm) 1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_wday); - ret = regmap_raw_write(info->rtc, SEC_RTC_SEC, data, 8); + ret = regmap_raw_write(info->regmap, SEC_RTC_SEC, data, 8); if (ret < 0) return ret; @@ -242,20 +267,20 @@ static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) unsigned int val; int ret, i; - ret = regmap_bulk_read(info->rtc, SEC_ALARM0_SEC, data, 8); + ret = regmap_bulk_read(info->regmap, SEC_ALARM0_SEC, data, 8); if (ret < 0) return ret; switch (info->device_type) { case S5M8763X: s5m8763_data_to_tm(data, &alrm->time); - ret = regmap_read(info->rtc, SEC_ALARM0_CONF, &val); + ret = regmap_read(info->regmap, SEC_ALARM0_CONF, &val); if (ret < 0) return ret; alrm->enabled = !!val; - ret = regmap_read(info->rtc, SEC_RTC_STATUS, &val); + ret = regmap_read(info->regmap, SEC_RTC_STATUS, &val); if (ret < 0) return ret; @@ -278,7 +303,7 @@ static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) } alrm->pending = 0; - ret = regmap_read(info->rtc, SEC_RTC_STATUS, &val); + ret = regmap_read(info->regmap, SEC_RTC_STATUS, &val); if (ret < 0) return ret; break; @@ -301,7 +326,7 @@ static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info) int ret, i; struct rtc_time tm; - ret = regmap_bulk_read(info->rtc, SEC_ALARM0_SEC, data, 8); + ret = regmap_bulk_read(info->regmap, SEC_ALARM0_SEC, data, 8); if (ret < 0) return ret; @@ -312,14 +337,14 @@ static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info) switch (info->device_type) { case S5M8763X: - ret = regmap_write(info->rtc, SEC_ALARM0_CONF, 0); + ret = regmap_write(info->regmap, SEC_ALARM0_CONF, 0); break; case S5M8767X: for (i = 0; i < 7; i++) data[i] &= ~ALARM_ENABLE_MASK; - ret = regmap_raw_write(info->rtc, SEC_ALARM0_SEC, data, 8); + ret = regmap_raw_write(info->regmap, SEC_ALARM0_SEC, data, 8); if (ret < 0) return ret; @@ -341,7 +366,7 @@ static int s5m_rtc_start_alarm(struct s5m_rtc_info *info) u8 alarm0_conf; struct rtc_time tm; - ret = regmap_bulk_read(info->rtc, SEC_ALARM0_SEC, data, 8); + ret = regmap_bulk_read(info->regmap, SEC_ALARM0_SEC, data, 8); if (ret < 0) return ret; @@ -353,7 +378,7 @@ static int s5m_rtc_start_alarm(struct s5m_rtc_info *info) switch (info->device_type) { case S5M8763X: alarm0_conf = 0x77; - ret = regmap_write(info->rtc, SEC_ALARM0_CONF, alarm0_conf); + ret = regmap_write(info->regmap, SEC_ALARM0_CONF, alarm0_conf); break; case S5M8767X: @@ -368,7 +393,7 @@ static int s5m_rtc_start_alarm(struct s5m_rtc_info *info) if (data[RTC_YEAR1] & 0x7f) data[RTC_YEAR1] |= ALARM_ENABLE_MASK; - ret = regmap_raw_write(info->rtc, SEC_ALARM0_SEC, data, 8); + ret = regmap_raw_write(info->regmap, SEC_ALARM0_SEC, data, 8); if (ret < 0) return ret; ret = s5m8767_rtc_set_alarm_reg(info); @@ -410,7 +435,7 @@ static int s5m_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) if (ret < 0) return ret; - ret = regmap_raw_write(info->rtc, SEC_ALARM0_SEC, data, 8); + ret = regmap_raw_write(info->regmap, SEC_ALARM0_SEC, data, 8); if (ret < 0) return ret; @@ -455,7 +480,7 @@ static const struct rtc_class_ops s5m_rtc_ops = { static void s5m_rtc_enable_wtsr(struct s5m_rtc_info *info, bool enable) { int ret; - ret = regmap_update_bits(info->rtc, SEC_WTSR_SMPL_CNTL, + ret = regmap_update_bits(info->regmap, SEC_WTSR_SMPL_CNTL, WTSR_ENABLE_MASK, enable ? WTSR_ENABLE_MASK : 0); if (ret < 0) @@ -466,7 +491,7 @@ static void s5m_rtc_enable_wtsr(struct s5m_rtc_info *info, bool enable) static void s5m_rtc_enable_smpl(struct s5m_rtc_info *info, bool enable) { int ret; - ret = regmap_update_bits(info->rtc, SEC_WTSR_SMPL_CNTL, + ret = regmap_update_bits(info->regmap, SEC_WTSR_SMPL_CNTL, SMPL_ENABLE_MASK, enable ? SMPL_ENABLE_MASK : 0); if (ret < 0) @@ -481,7 +506,7 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info) int ret; struct rtc_time tm; - ret = regmap_read(info->rtc, SEC_RTC_UDR_CON, &tp_read); + ret = regmap_read(info->regmap, SEC_RTC_UDR_CON, &tp_read); if (ret < 0) { dev_err(info->dev, "%s: fail to read control reg(%d)\n", __func__, ret); @@ -493,7 +518,7 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info) data[1] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); info->rtc_24hr_mode = 1; - ret = regmap_raw_write(info->rtc, SEC_ALARM0_CONF, data, 2); + ret = regmap_raw_write(info->regmap, SEC_ALARM0_CONF, data, 2); if (ret < 0) { dev_err(info->dev, "%s: fail to write controlm reg(%d)\n", __func__, ret); @@ -515,7 +540,7 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info) ret = s5m_rtc_set_time(info->dev, &tm); } - ret = regmap_update_bits(info->rtc, SEC_RTC_UDR_CON, + ret = regmap_update_bits(info->regmap, SEC_RTC_UDR_CON, RTC_TCON_MASK, tp_read | RTC_TCON_MASK); if (ret < 0) dev_err(info->dev, "%s: fail to update TCON reg(%d)\n", @@ -542,17 +567,19 @@ static int s5m_rtc_probe(struct platform_device *pdev) info->dev = &pdev->dev; info->s5m87xx = s5m87xx; - info->rtc = s5m87xx->rtc; + info->regmap = s5m87xx->regmap_rtc; info->device_type = s5m87xx->device_type; info->wtsr_smpl = s5m87xx->wtsr_smpl; switch (pdata->device_type) { case S5M8763X: - info->irq = s5m87xx->irq_base + S5M8763_IRQ_ALARM0; + info->irq = regmap_irq_get_virq(s5m87xx->irq_data, + S5M8763_IRQ_ALARM0); break; case S5M8767X: - info->irq = s5m87xx->irq_base + S5M8767_IRQ_RTCA1; + info->irq = regmap_irq_get_virq(s5m87xx->irq_data, + S5M8767_IRQ_RTCA1); break; default: @@ -596,7 +623,7 @@ static void s5m_rtc_shutdown(struct platform_device *pdev) if (info->wtsr_smpl) { for (i = 0; i < 3; i++) { s5m_rtc_enable_wtsr(info, false); - regmap_read(info->rtc, SEC_WTSR_SMPL_CNTL, &val); + regmap_read(info->regmap, SEC_WTSR_SMPL_CNTL, &val); pr_debug("%s: WTSR_SMPL reg(0x%02x)\n", __func__, val); if (val & WTSR_ENABLE_MASK) pr_emerg("%s: fail to disable WTSR\n", @@ -612,6 +639,30 @@ static void s5m_rtc_shutdown(struct platform_device *pdev) s5m_rtc_enable_smpl(info, false); } +static int s5m_rtc_resume(struct device *dev) +{ + struct s5m_rtc_info *info = dev_get_drvdata(dev); + int ret = 0; + + if (device_may_wakeup(dev)) + ret = disable_irq_wake(info->irq); + + return ret; +} + +static int s5m_rtc_suspend(struct device *dev) +{ + struct s5m_rtc_info *info = dev_get_drvdata(dev); + int ret = 0; + + if (device_may_wakeup(dev)) + ret = enable_irq_wake(info->irq); + + return ret; +} + +static SIMPLE_DEV_PM_OPS(s5m_rtc_pm_ops, s5m_rtc_suspend, s5m_rtc_resume); + static const struct platform_device_id s5m_rtc_id[] = { { "s5m-rtc", 0 }, }; @@ -620,6 +671,7 @@ static struct platform_driver s5m_rtc_driver = { .driver = { .name = "s5m-rtc", .owner = THIS_MODULE, + .pm = &s5m_rtc_pm_ops, }, .probe = s5m_rtc_probe, .shutdown = s5m_rtc_shutdown, diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c index f64921756ad6..f224d59c4b6b 100644 --- a/drivers/s390/block/dasd_genhd.c +++ b/drivers/s390/block/dasd_genhd.c @@ -87,7 +87,6 @@ void dasd_gendisk_free(struct dasd_block *block) { if (block->gdp) { del_gendisk(block->gdp); - block->gdp->queue = NULL; block->gdp->private_data = NULL; put_disk(block->gdp); block->gdp = NULL; diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c index f7aa080e9b28..1465e9563101 100644 --- a/drivers/s390/char/sclp_early.c +++ b/drivers/s390/char/sclp_early.c @@ -35,7 +35,6 @@ struct read_info_sccb { u8 _reserved5[4096 - 112]; /* 112-4095 */ } __packed __aligned(PAGE_SIZE); -static __initdata struct init_sccb early_event_mask_sccb __aligned(PAGE_SIZE); static __initdata struct read_info_sccb early_read_info_sccb; static __initdata char sccb_early[PAGE_SIZE] __aligned(PAGE_SIZE); static unsigned long sclp_hsa_size; @@ -113,7 +112,7 @@ static void __init sclp_facilities_detect(void) bool __init sclp_has_linemode(void) { - struct init_sccb *sccb = &early_event_mask_sccb; + struct init_sccb *sccb = (void *) &sccb_early; if (sccb->header.response_code != 0x20) return 0; @@ -126,7 +125,7 @@ bool __init sclp_has_linemode(void) bool __init sclp_has_vt220(void) { - struct init_sccb *sccb = &early_event_mask_sccb; + struct init_sccb *sccb = (void *) &sccb_early; if (sccb->header.response_code != 0x20) return 0; diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c index 1aa4a3fd0f1b..56e355b3e7fa 100644 --- a/drivers/staging/tidspbridge/rmgr/drv_interface.c +++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c @@ -258,7 +258,8 @@ err: /* This function maps kernel space memory to user space memory. */ static int bridge_mmap(struct file *filp, struct vm_area_struct *vma) { - u32 status; + struct omap_dsp_platform_data *pdata = + omap_dspbridge_dev->dev.platform_data; /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); @@ -268,13 +269,9 @@ static int bridge_mmap(struct file *filp, struct vm_area_struct *vma) vma->vm_start, vma->vm_end, vma->vm_page_prot, vma->vm_flags); - status = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, - vma->vm_end - vma->vm_start, - vma->vm_page_prot); - if (status != 0) - status = -EAGAIN; - - return status; + return vm_iomap_memory(vma, + pdata->phys_mempool_base, + pdata->phys_mempool_size); } static const struct file_operations bridge_fops = { diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 0f74945af624..268b62768f2b 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -810,7 +810,8 @@ static void process_echoes(struct tty_struct *tty) struct n_tty_data *ldata = tty->disc_data; size_t echoed; - if (!L_ECHO(tty) || ldata->echo_commit == ldata->echo_tail) + if ((!L_ECHO(tty) && !L_ECHONL(tty)) || + ldata->echo_commit == ldata->echo_tail) return; mutex_lock(&ldata->output_lock); @@ -825,7 +826,8 @@ static void flush_echoes(struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; - if (!L_ECHO(tty) || ldata->echo_commit == ldata->echo_head) + if ((!L_ECHO(tty) && !L_ECHONL(tty)) || + ldata->echo_commit == ldata->echo_head) return; mutex_lock(&ldata->output_lock); diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 3e7560f004f8..e8404319ca68 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1515,6 +1515,8 @@ static int acm_reset_resume(struct usb_interface *intf) static const struct usb_device_id acm_ids[] = { /* quirky and broken devices */ + { USB_DEVICE(0x17ef, 0x7000), /* Lenovo USB modem */ + .driver_info = NO_UNION_NORMAL, },/* has no union descriptor */ { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */ .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ }, diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index a7c04e24ca48..bd9dc3504b51 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -4832,8 +4832,9 @@ static void hub_events(void) hub->ports[i - 1]->child; dev_dbg(hub_dev, "warm reset port %d\n", i); - if (!udev || !(portstatus & - USB_PORT_STAT_CONNECTION)) { + if (!udev || + !(portstatus & USB_PORT_STAT_CONNECTION) || + udev->state == USB_STATE_NOTATTACHED) { status = hub_port_reset(hub, i, NULL, HUB_BH_RESET_TIME, true); diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 95f7649c71a7..21a352079bc2 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -459,6 +459,8 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, dep = dwc3_wIndex_to_dep(dwc, wIndex); if (!dep) return -EINVAL; + if (set == 0 && (dep->flags & DWC3_EP_WEDGE)) + break; ret = __dwc3_gadget_ep_set_halt(dep, set); if (ret) return -EINVAL; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 5452c0fce360..02e44fcaf205 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1200,9 +1200,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value) else dep->flags |= DWC3_EP_STALL; } else { - if (dep->flags & DWC3_EP_WEDGE) - return 0; - ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, DWC3_DEPCMD_CLEARSTALL, ¶ms); if (ret) @@ -1210,7 +1207,7 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value) value ? "set" : "clear", dep->name); else - dep->flags &= ~DWC3_EP_STALL; + dep->flags &= ~(DWC3_EP_STALL | DWC3_EP_WEDGE); } return ret; diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index a91e6422f930..f66d96ad1f51 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -682,6 +682,7 @@ config USB_CONFIGFS_PHONET config USB_CONFIGFS_MASS_STORAGE boolean "Mass storage" depends on USB_CONFIGFS + depends on BLOCK select USB_F_MASS_STORAGE help The Mass Storage Gadget acts as a USB Mass Storage disk drive. diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 3e7ae707f691..2018ba1a2172 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -593,6 +593,7 @@ static void reset_config(struct usb_composite_dev *cdev) bitmap_zero(f->endpoints, 32); } cdev->config = NULL; + cdev->delayed_status = 0; } static int set_config(struct usb_composite_dev *cdev, diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 774e8b89cdb5..241fc873ffa4 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -1304,7 +1304,7 @@ static struct ffs_data *ffs_data_new(void) { struct ffs_data *ffs = kzalloc(sizeof *ffs, GFP_KERNEL); if (unlikely(!ffs)) - return 0; + return NULL; ENTER(); diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index a03ba2c83589..b96393908860 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -523,7 +523,7 @@ static int fsg_setup(struct usb_function *f, */ DBG(fsg, "bulk reset request\n"); raise_exception(fsg->common, FSG_STATE_RESET); - return DELAYED_STATUS; + return USB_GADGET_DELAYED_STATUS; case US_BULK_GET_MAX_LUN: if (ctrl->bRequestType != @@ -602,13 +602,14 @@ static bool start_out_transfer(struct fsg_common *common, struct fsg_buffhd *bh) return true; } -static int sleep_thread(struct fsg_common *common) +static int sleep_thread(struct fsg_common *common, bool can_freeze) { int rc = 0; /* Wait until a signal arrives or we are woken up */ for (;;) { - try_to_freeze(); + if (can_freeze) + try_to_freeze(); set_current_state(TASK_INTERRUPTIBLE); if (signal_pending(current)) { rc = -EINTR; @@ -682,7 +683,7 @@ static int do_read(struct fsg_common *common) /* Wait for the next buffer to become available */ bh = common->next_buffhd_to_fill; while (bh->state != BUF_STATE_EMPTY) { - rc = sleep_thread(common); + rc = sleep_thread(common, false); if (rc) return rc; } @@ -937,7 +938,7 @@ static int do_write(struct fsg_common *common) } /* Wait for something to happen */ - rc = sleep_thread(common); + rc = sleep_thread(common, false); if (rc) return rc; } @@ -1504,7 +1505,7 @@ static int throw_away_data(struct fsg_common *common) } /* Otherwise wait for something to happen */ - rc = sleep_thread(common); + rc = sleep_thread(common, true); if (rc) return rc; } @@ -1625,7 +1626,7 @@ static int send_status(struct fsg_common *common) /* Wait for the next buffer to become available */ bh = common->next_buffhd_to_fill; while (bh->state != BUF_STATE_EMPTY) { - rc = sleep_thread(common); + rc = sleep_thread(common, true); if (rc) return rc; } @@ -1828,7 +1829,7 @@ static int do_scsi_command(struct fsg_common *common) bh = common->next_buffhd_to_fill; common->next_buffhd_to_drain = bh; while (bh->state != BUF_STATE_EMPTY) { - rc = sleep_thread(common); + rc = sleep_thread(common, true); if (rc) return rc; } @@ -2174,7 +2175,7 @@ static int get_next_command(struct fsg_common *common) /* Wait for the next buffer to become available */ bh = common->next_buffhd_to_fill; while (bh->state != BUF_STATE_EMPTY) { - rc = sleep_thread(common); + rc = sleep_thread(common, true); if (rc) return rc; } @@ -2193,7 +2194,7 @@ static int get_next_command(struct fsg_common *common) /* Wait for the CBW to arrive */ while (bh->state != BUF_STATE_FULL) { - rc = sleep_thread(common); + rc = sleep_thread(common, true); if (rc) return rc; } @@ -2379,7 +2380,7 @@ static void handle_exception(struct fsg_common *common) } if (num_active == 0) break; - if (sleep_thread(common)) + if (sleep_thread(common, true)) return; } @@ -2516,7 +2517,7 @@ static int fsg_main_thread(void *common_) } if (!common->running) { - sleep_thread(common); + sleep_thread(common, true); continue; } @@ -3111,7 +3112,7 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) fsg->common->can_stall); if (ret) return ret; - fsg_common_set_inquiry_string(fsg->common, 0, 0); + fsg_common_set_inquiry_string(fsg->common, NULL, NULL); ret = fsg_common_run_thread(fsg->common); if (ret) return ret; diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index 0ac6064aa3b8..409a3c45a36a 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -54,6 +54,7 @@ */ #ifdef CONFIG_ARCH_PXA #include <mach/pxa25x-udc.h> +#include <mach/hardware.h> #endif #ifdef CONFIG_ARCH_LUBBOCK diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 9875d9c0823f..e20bc109fdd7 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -1180,6 +1180,7 @@ static int s3c_hsotg_process_req_feature(struct s3c_hsotg *hsotg, } static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg); +static void s3c_hsotg_disconnect(struct s3c_hsotg *hsotg); /** * s3c_hsotg_process_control - process a control request @@ -1221,6 +1222,7 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg, if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) { switch (ctrl->bRequest) { case USB_REQ_SET_ADDRESS: + s3c_hsotg_disconnect(hsotg); dcfg = readl(hsotg->regs + DCFG); dcfg &= ~DCFG_DevAddr_MASK; dcfg |= ctrl->wValue << DCFG_DevAddr_SHIFT; @@ -1245,7 +1247,9 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg, /* as a fallback, try delivering it to the driver to deal with */ if (ret == 0 && hsotg->driver) { + spin_unlock(&hsotg->lock); ret = hsotg->driver->setup(&hsotg->gadget, ctrl); + spin_lock(&hsotg->lock); if (ret < 0) dev_dbg(hsotg->dev, "driver->setup() ret %d\n", ret); } @@ -1308,10 +1312,12 @@ static void s3c_hsotg_complete_setup(struct usb_ep *ep, return; } + spin_lock(&hsotg->lock); if (req->actual == 0) s3c_hsotg_enqueue_setup(hsotg); else s3c_hsotg_process_control(hsotg, req->buf); + spin_unlock(&hsotg->lock); } /** @@ -2533,7 +2539,6 @@ irq_retry: writel(GINTSTS_USBSusp, hsotg->regs + GINTSTS); call_gadget(hsotg, suspend); - s3c_hsotg_disconnect(hsotg); } if (gintsts & GINTSTS_WkUpInt) { diff --git a/drivers/usb/gadget/storage_common.h b/drivers/usb/gadget/storage_common.h index c74c2fdbd56e..70c891469f57 100644 --- a/drivers/usb/gadget/storage_common.h +++ b/drivers/usb/gadget/storage_common.h @@ -119,10 +119,6 @@ static inline bool fsg_lun_is_open(struct fsg_lun *curlun) return curlun->filp != NULL; } -/* Big enough to hold our biggest descriptor */ -#define EP0_BUFSIZE 256 -#define DELAYED_STATUS (EP0_BUFSIZE + 999) /* An impossibly large value */ - /* Default size of buffer length. */ #define FSG_BUFLEN ((u32)16384) diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c index 6c3d7950d2a9..0f8aad78b54f 100644 --- a/drivers/usb/gadget/tcm_usb_gadget.c +++ b/drivers/usb/gadget/tcm_usb_gadget.c @@ -370,7 +370,7 @@ err: return -ENOMEM; } -void bot_cleanup_old_alt(struct f_uas *fu) +static void bot_cleanup_old_alt(struct f_uas *fu) { if (!(fu->flags & USBG_ENABLED)) return; diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 0dd07ae1555d..f49b0b61ecc8 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -91,17 +91,17 @@ static struct usb_zero_options gzero_options = { * functional coverage for the "USBCV" test harness from USB-IF. * It's always set if OTG mode is enabled. */ -unsigned autoresume = DEFAULT_AUTORESUME; +static unsigned autoresume = DEFAULT_AUTORESUME; module_param(autoresume, uint, S_IRUGO); MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup"); /* Maximum Autoresume time */ -unsigned max_autoresume; +static unsigned max_autoresume; module_param(max_autoresume, uint, S_IRUGO); MODULE_PARM_DESC(max_autoresume, "maximum seconds before remote wakeup"); /* Interval between two remote wakeups */ -unsigned autoresume_interval_ms; +static unsigned autoresume_interval_ms; module_param(autoresume_interval_ms, uint, S_IRUGO); MODULE_PARM_DESC(autoresume_interval_ms, "milliseconds to increase successive wakeup delays"); diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index e89ac4d4b87e..9b7435f0dcd6 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -21,6 +21,7 @@ #include <linux/clk.h> #include <linux/device.h> +#include <linux/dma-mapping.h> #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 1e2f3f495843..53c2e296467f 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2973,8 +2973,58 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, } while (1) { - if (room_on_ring(xhci, ep_ring, num_trbs)) - break; + if (room_on_ring(xhci, ep_ring, num_trbs)) { + union xhci_trb *trb = ep_ring->enqueue; + unsigned int usable = ep_ring->enq_seg->trbs + + TRBS_PER_SEGMENT - 1 - trb; + u32 nop_cmd; + + /* + * Section 4.11.7.1 TD Fragments states that a link + * TRB must only occur at the boundary between + * data bursts (eg 512 bytes for 480M). + * While it is possible to split a large fragment + * we don't know the size yet. + * Simplest solution is to fill the trb before the + * LINK with nop commands. + */ + if (num_trbs == 1 || num_trbs <= usable || usable == 0) + break; + + if (ep_ring->type != TYPE_BULK) + /* + * While isoc transfers might have a buffer that + * crosses a 64k boundary it is unlikely. + * Since we can't add NOPs without generating + * gaps in the traffic just hope it never + * happens at the end of the ring. + * This could be fixed by writing a LINK TRB + * instead of the first NOP - however the + * TRB_TYPE_LINK_LE32() calls would all need + * changing to check the ring length. + */ + break; + + if (num_trbs >= TRBS_PER_SEGMENT) { + xhci_err(xhci, "Too many fragments %d, max %d\n", + num_trbs, TRBS_PER_SEGMENT - 1); + return -ENOMEM; + } + + nop_cmd = cpu_to_le32(TRB_TYPE(TRB_TR_NOOP) | + ep_ring->cycle_state); + ep_ring->num_trbs_free -= usable; + do { + trb->generic.field[0] = 0; + trb->generic.field[1] = 0; + trb->generic.field[2] = 0; + trb->generic.field[3] = nop_cmd; + trb++; + } while (--usable); + ep_ring->enqueue = trb; + if (room_on_ring(xhci, ep_ring, num_trbs)) + break; + } if (ep_ring == xhci->cmd_ring) { xhci_err(xhci, "Do not support expand command ring\n"); diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 0a43329569d1..4d4499b80449 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1809,7 +1809,6 @@ static void musb_free(struct musb *musb) disable_irq_wake(musb->nIrq); free_irq(musb->nIrq, musb); } - cancel_work_sync(&musb->irq_work); musb_host_free(musb); } @@ -1896,6 +1895,9 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) musb_platform_disable(musb); musb_generic_disable(musb); + /* Init IRQ workqueue before request_irq */ + INIT_WORK(&musb->irq_work, musb_irq_work); + /* setup musb parts of the core (especially endpoints) */ status = musb_core_init(plat->config->multipoint ? MUSB_CONTROLLER_MHDRC @@ -1905,9 +1907,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb); - /* Init IRQ workqueue before request_irq */ - INIT_WORK(&musb->irq_work, musb_irq_work); - /* attach to the IRQ */ if (request_irq(nIrq, musb->isr, 0, dev_name(dev), musb)) { dev_err(dev, "request_irq %d failed!\n", nIrq); @@ -1981,6 +1980,7 @@ fail4: musb_host_cleanup(musb); fail3: + cancel_work_sync(&musb->irq_work); if (musb->dma_controller) dma_controller_destroy(musb->dma_controller); fail2_5: @@ -2043,6 +2043,7 @@ static int musb_remove(struct platform_device *pdev) if (musb->dma_controller) dma_controller_destroy(musb->dma_controller); + cancel_work_sync(&musb->irq_work); musb_free(musb); device_init_wakeup(dev, 0); return 0; diff --git a/drivers/usb/musb/musb_cppi41.c b/drivers/usb/musb/musb_cppi41.c index ff9d6de2b746..a12bd30401e0 100644 --- a/drivers/usb/musb/musb_cppi41.c +++ b/drivers/usb/musb/musb_cppi41.c @@ -38,6 +38,7 @@ struct cppi41_dma_channel { u32 prog_len; u32 transferred; u32 packet_sz; + struct list_head tx_check; }; #define MUSB_DMA_NUM_CHANNELS 15 @@ -47,6 +48,8 @@ struct cppi41_dma_controller { struct cppi41_dma_channel rx_channel[MUSB_DMA_NUM_CHANNELS]; struct cppi41_dma_channel tx_channel[MUSB_DMA_NUM_CHANNELS]; struct musb *musb; + struct hrtimer early_tx; + struct list_head early_tx_list; u32 rx_mode; u32 tx_mode; u32 auto_req; @@ -96,31 +99,27 @@ static void update_rx_toggle(struct cppi41_dma_channel *cppi41_channel) cppi41_channel->usb_toggle = toggle; } -static void cppi41_dma_callback(void *private_data) +static bool musb_is_tx_fifo_empty(struct musb_hw_ep *hw_ep) { - struct dma_channel *channel = private_data; - struct cppi41_dma_channel *cppi41_channel = channel->private_data; - struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep; - struct musb *musb = hw_ep->musb; - unsigned long flags; - struct dma_tx_state txstate; - u32 transferred; + u8 epnum = hw_ep->epnum; + struct musb *musb = hw_ep->musb; + void __iomem *epio = musb->endpoints[epnum].regs; + u16 csr; - spin_lock_irqsave(&musb->lock, flags); + csr = musb_readw(epio, MUSB_TXCSR); + if (csr & MUSB_TXCSR_TXPKTRDY) + return false; + return true; +} - dmaengine_tx_status(cppi41_channel->dc, cppi41_channel->cookie, - &txstate); - transferred = cppi41_channel->prog_len - txstate.residue; - cppi41_channel->transferred += transferred; +static void cppi41_dma_callback(void *private_data); - dev_dbg(musb->controller, "DMA transfer done on hw_ep=%d bytes=%d/%d\n", - hw_ep->epnum, cppi41_channel->transferred, - cppi41_channel->total_len); +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; - update_rx_toggle(cppi41_channel); - - if (cppi41_channel->transferred == cppi41_channel->total_len || - transferred < cppi41_channel->packet_sz) { + if (!cppi41_channel->prog_len) { /* done, complete */ cppi41_channel->channel.actual_len = @@ -150,13 +149,11 @@ static void cppi41_dma_callback(void *private_data) remain_bytes, direction, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (WARN_ON(!dma_desc)) { - spin_unlock_irqrestore(&musb->lock, flags); + if (WARN_ON(!dma_desc)) return; - } dma_desc->callback = cppi41_dma_callback; - dma_desc->callback_param = channel; + dma_desc->callback_param = &cppi41_channel->channel; cppi41_channel->cookie = dma_desc->tx_submit(dma_desc); dma_async_issue_pending(dc); @@ -166,6 +163,117 @@ static void cppi41_dma_callback(void *private_data) musb_writew(epio, MUSB_RXCSR, csr); } } +} + +static enum hrtimer_restart cppi41_recheck_tx_req(struct hrtimer *timer) +{ + struct cppi41_dma_controller *controller; + struct cppi41_dma_channel *cppi41_channel, *n; + struct musb *musb; + unsigned long flags; + enum hrtimer_restart ret = HRTIMER_NORESTART; + + controller = container_of(timer, struct cppi41_dma_controller, + early_tx); + musb = controller->musb; + + spin_lock_irqsave(&musb->lock, flags); + list_for_each_entry_safe(cppi41_channel, n, &controller->early_tx_list, + tx_check) { + bool empty; + struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep; + + empty = musb_is_tx_fifo_empty(hw_ep); + if (empty) { + list_del_init(&cppi41_channel->tx_check); + cppi41_trans_done(cppi41_channel); + } + } + + if (!list_empty(&controller->early_tx_list)) { + ret = HRTIMER_RESTART; + hrtimer_forward_now(&controller->early_tx, + ktime_set(0, 150 * NSEC_PER_USEC)); + } + + spin_unlock_irqrestore(&musb->lock, flags); + return ret; +} + +static void cppi41_dma_callback(void *private_data) +{ + struct dma_channel *channel = private_data; + struct cppi41_dma_channel *cppi41_channel = channel->private_data; + struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep; + struct musb *musb = hw_ep->musb; + unsigned long flags; + struct dma_tx_state txstate; + u32 transferred; + bool empty; + + spin_lock_irqsave(&musb->lock, flags); + + dmaengine_tx_status(cppi41_channel->dc, cppi41_channel->cookie, + &txstate); + transferred = cppi41_channel->prog_len - txstate.residue; + cppi41_channel->transferred += transferred; + + dev_dbg(musb->controller, "DMA transfer done on hw_ep=%d bytes=%d/%d\n", + hw_ep->epnum, cppi41_channel->transferred, + cppi41_channel->total_len); + + update_rx_toggle(cppi41_channel); + + if (cppi41_channel->transferred == cppi41_channel->total_len || + transferred < cppi41_channel->packet_sz) + cppi41_channel->prog_len = 0; + + empty = musb_is_tx_fifo_empty(hw_ep); + if (empty) { + cppi41_trans_done(cppi41_channel); + } else { + struct cppi41_dma_controller *controller; + /* + * On AM335x it has been observed that the TX interrupt fires + * too early that means the TXFIFO is not yet empty but the DMA + * engine says that it is done with the transfer. We don't + * receive a FIFO empty interrupt so the only thing we can do is + * to poll for the bit. On HS it usually takes 2us, on FS around + * 110us - 150us depending on the transfer size. + * We spin on HS (no longer than than 25us and setup a timer on + * FS to check for the bit and complete the transfer. + */ + controller = cppi41_channel->controller; + + if (musb->g.speed == USB_SPEED_HIGH) { + unsigned wait = 25; + + do { + empty = musb_is_tx_fifo_empty(hw_ep); + if (empty) + break; + wait--; + if (!wait) + break; + udelay(1); + } while (1); + + empty = musb_is_tx_fifo_empty(hw_ep); + if (empty) { + cppi41_trans_done(cppi41_channel); + goto out; + } + } + list_add_tail(&cppi41_channel->tx_check, + &controller->early_tx_list); + if (!hrtimer_active(&controller->early_tx)) { + hrtimer_start_range_ns(&controller->early_tx, + ktime_set(0, 140 * NSEC_PER_USEC), + 40 * NSEC_PER_USEC, + HRTIMER_MODE_REL); + } + } +out: spin_unlock_irqrestore(&musb->lock, flags); } @@ -364,6 +472,8 @@ static int cppi41_is_compatible(struct dma_channel *channel, u16 maxpacket, WARN_ON(1); return 1; } + if (cppi41_channel->hw_ep->ep_in.type != USB_ENDPOINT_XFER_BULK) + return 0; if (cppi41_channel->is_tx) return 1; /* AM335x Advisory 1.0.13. No workaround for device RX mode */ @@ -388,6 +498,7 @@ static int cppi41_dma_channel_abort(struct dma_channel *channel) if (cppi41_channel->channel.status == MUSB_DMA_STATUS_FREE) return 0; + list_del_init(&cppi41_channel->tx_check); if (is_tx) { csr = musb_readw(epio, MUSB_TXCSR); csr &= ~MUSB_TXCSR_DMAENAB; @@ -495,6 +606,7 @@ static int cppi41_dma_controller_start(struct cppi41_dma_controller *controller) cppi41_channel->controller = controller; cppi41_channel->port_num = port; cppi41_channel->is_tx = is_tx; + INIT_LIST_HEAD(&cppi41_channel->tx_check); musb_dma = &cppi41_channel->channel; musb_dma->private_data = cppi41_channel; @@ -520,6 +632,7 @@ void dma_controller_destroy(struct dma_controller *c) struct cppi41_dma_controller *controller = container_of(c, struct cppi41_dma_controller, controller); + hrtimer_cancel(&controller->early_tx); cppi41_dma_controller_stop(controller); kfree(controller); } @@ -539,6 +652,9 @@ struct dma_controller *dma_controller_create(struct musb *musb, if (!controller) goto kzalloc_fail; + hrtimer_init(&controller->early_tx, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + controller->early_tx.function = cppi41_recheck_tx_req; + INIT_LIST_HEAD(&controller->early_tx_list); controller->musb = musb; controller->controller.channel_alloc = cppi41_dma_channel_allocate; diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index d2d3a173b315..32fb057c03f5 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1796,7 +1796,11 @@ int musb_gadget_setup(struct musb *musb) /* this "gadget" abstracts/virtualizes the controller */ musb->g.name = musb_driver_name; +#if IS_ENABLED(CONFIG_USB_MUSB_DUAL_ROLE) musb->g.is_otg = 1; +#elif IS_ENABLED(CONFIG_USB_MUSB_GADGET) + musb->g.is_otg = 0; +#endif musb_g_init_endpoints(musb); diff --git a/drivers/usb/phy/phy-am335x.c b/drivers/usb/phy/phy-am335x.c index 6370e50649d7..0e3c60cb669a 100644 --- a/drivers/usb/phy/phy-am335x.c +++ b/drivers/usb/phy/phy-am335x.c @@ -52,8 +52,7 @@ static int am335x_phy_probe(struct platform_device *pdev) return am_phy->id; } - ret = usb_phy_gen_create_phy(dev, &am_phy->usb_phy_gen, - USB_PHY_TYPE_USB2, 0, false); + ret = usb_phy_gen_create_phy(dev, &am_phy->usb_phy_gen, NULL); if (ret) return ret; @@ -66,8 +65,6 @@ static int am335x_phy_probe(struct platform_device *pdev) platform_set_drvdata(pdev, am_phy); return 0; - - return ret; } static int am335x_phy_remove(struct platform_device *pdev) diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c index fce3a9e9bb5d..aa6d37b3378a 100644 --- a/drivers/usb/phy/phy-generic.c +++ b/drivers/usb/phy/phy-generic.c @@ -48,8 +48,9 @@ void usb_nop_xceiv_register(void) if (pd) return; pd = platform_device_register_simple("usb_phy_gen_xceiv", -1, NULL, 0); - if (!pd) { + if (IS_ERR(pd)) { pr_err("Unable to register generic usb transceiver\n"); + pd = NULL; return; } } @@ -150,10 +151,40 @@ static int nop_set_host(struct usb_otg *otg, struct usb_bus *host) } int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop, - enum usb_phy_type type, u32 clk_rate, bool needs_vcc) + struct usb_phy_gen_xceiv_platform_data *pdata) { + enum usb_phy_type type = USB_PHY_TYPE_USB2; int err; + u32 clk_rate = 0; + bool needs_vcc = false; + + nop->reset_active_low = true; /* default behaviour */ + + if (dev->of_node) { + struct device_node *node = dev->of_node; + enum of_gpio_flags flags = 0; + + if (of_property_read_u32(node, "clock-frequency", &clk_rate)) + clk_rate = 0; + + needs_vcc = of_property_read_bool(node, "vcc-supply"); + nop->gpio_reset = of_get_named_gpio_flags(node, "reset-gpios", + 0, &flags); + if (nop->gpio_reset == -EPROBE_DEFER) + return -EPROBE_DEFER; + + nop->reset_active_low = flags & OF_GPIO_ACTIVE_LOW; + + } else if (pdata) { + type = pdata->type; + clk_rate = pdata->clk_rate; + needs_vcc = pdata->needs_vcc; + nop->gpio_reset = pdata->gpio_reset; + } else { + nop->gpio_reset = -1; + } + nop->phy.otg = devm_kzalloc(dev, sizeof(*nop->phy.otg), GFP_KERNEL); if (!nop->phy.otg) @@ -218,43 +249,14 @@ EXPORT_SYMBOL_GPL(usb_phy_gen_create_phy); static int usb_phy_gen_xceiv_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct usb_phy_gen_xceiv_platform_data *pdata = - dev_get_platdata(&pdev->dev); struct usb_phy_gen_xceiv *nop; - enum usb_phy_type type = USB_PHY_TYPE_USB2; int err; - u32 clk_rate = 0; - bool needs_vcc = false; nop = devm_kzalloc(dev, sizeof(*nop), GFP_KERNEL); if (!nop) return -ENOMEM; - nop->reset_active_low = true; /* default behaviour */ - - if (dev->of_node) { - struct device_node *node = dev->of_node; - enum of_gpio_flags flags; - - if (of_property_read_u32(node, "clock-frequency", &clk_rate)) - clk_rate = 0; - - needs_vcc = of_property_read_bool(node, "vcc-supply"); - nop->gpio_reset = of_get_named_gpio_flags(node, "reset-gpios", - 0, &flags); - if (nop->gpio_reset == -EPROBE_DEFER) - return -EPROBE_DEFER; - - nop->reset_active_low = flags & OF_GPIO_ACTIVE_LOW; - - } else if (pdata) { - type = pdata->type; - clk_rate = pdata->clk_rate; - needs_vcc = pdata->needs_vcc; - nop->gpio_reset = pdata->gpio_reset; - } - - err = usb_phy_gen_create_phy(dev, nop, type, clk_rate, needs_vcc); + err = usb_phy_gen_create_phy(dev, nop, dev_get_platdata(&pdev->dev)); if (err) return err; @@ -271,8 +273,6 @@ static int usb_phy_gen_xceiv_probe(struct platform_device *pdev) platform_set_drvdata(pdev, nop); return 0; - - return err; } static int usb_phy_gen_xceiv_remove(struct platform_device *pdev) diff --git a/drivers/usb/phy/phy-generic.h b/drivers/usb/phy/phy-generic.h index d2a220d81734..38a81f307b82 100644 --- a/drivers/usb/phy/phy-generic.h +++ b/drivers/usb/phy/phy-generic.h @@ -1,6 +1,8 @@ #ifndef _PHY_GENERIC_H_ #define _PHY_GENERIC_H_ +#include <linux/usb/usb_phy_gen_xceiv.h> + struct usb_phy_gen_xceiv { struct usb_phy phy; struct device *dev; @@ -14,6 +16,6 @@ int usb_gen_phy_init(struct usb_phy *phy); void usb_gen_phy_shutdown(struct usb_phy *phy); int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop, - enum usb_phy_type type, u32 clk_rate, bool needs_vcc); + struct usb_phy_gen_xceiv_platform_data *pdata); #endif diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c index fdd33b44dbd3..545844b7e796 100644 --- a/drivers/usb/phy/phy-mxs-usb.c +++ b/drivers/usb/phy/phy-mxs-usb.c @@ -164,7 +164,7 @@ static int mxs_phy_probe(struct platform_device *pdev) mxs_phy->clk = clk; - platform_set_drvdata(pdev, &mxs_phy->phy); + platform_set_drvdata(pdev, mxs_phy); ret = usb_add_phy_dev(&mxs_phy->phy); if (ret) diff --git a/drivers/usb/phy/phy-rcar-gen2-usb.c b/drivers/usb/phy/phy-rcar-gen2-usb.c index a99a6953f11c..db3ab34cddb4 100644 --- a/drivers/usb/phy/phy-rcar-gen2-usb.c +++ b/drivers/usb/phy/phy-rcar-gen2-usb.c @@ -107,10 +107,10 @@ static void __rcar_gen2_usb_phy_init(struct rcar_gen2_usb_phy_priv *priv) clk_prepare_enable(priv->clk); /* Set USB channels in the USBHS UGCTRL2 register */ - val = ioread32(priv->base); + val = ioread32(priv->base + USBHS_UGCTRL2_REG); val &= ~(USBHS_UGCTRL2_USB0_HS | USBHS_UGCTRL2_USB2_SS); val |= priv->ugctrl2; - iowrite32(val, priv->base); + iowrite32(val, priv->base + USBHS_UGCTRL2_REG); } /* Shutdown USB channels */ diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 9ced8937a8f3..fb0d537435eb 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -2123,6 +2123,20 @@ static void ftdi_set_termios(struct tty_struct *tty, termios->c_cflag |= CRTSCTS; } + /* + * All FTDI UART chips are limited to CS7/8. We won't pretend to + * support CS5/6 and revert the CSIZE setting instead. + */ + if ((C_CSIZE(tty) != CS8) && (C_CSIZE(tty) != CS7)) { + dev_warn(ddev, "requested CSIZE setting not supported\n"); + + termios->c_cflag &= ~CSIZE; + if (old_termios) + termios->c_cflag |= old_termios->c_cflag & CSIZE; + else + termios->c_cflag |= CS8; + } + cflag = termios->c_cflag; if (!old_termios) @@ -2159,19 +2173,16 @@ no_skip: } else { urb_value |= FTDI_SIO_SET_DATA_PARITY_NONE; } - if (cflag & CSIZE) { - switch (cflag & CSIZE) { - case CS7: - urb_value |= 7; - dev_dbg(ddev, "Setting CS7\n"); - break; - case CS8: - urb_value |= 8; - dev_dbg(ddev, "Setting CS8\n"); - break; - default: - dev_err(ddev, "CSIZE was set but not CS7-CS8\n"); - } + switch (cflag & CSIZE) { + case CS7: + urb_value |= 7; + dev_dbg(ddev, "Setting CS7\n"); + break; + default: + case CS8: + urb_value |= 8; + dev_dbg(ddev, "Setting CS8\n"); + break; } /* This is needed by the break command since it uses the same command diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 2b01ec8651c2..b63ce023f96f 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -173,16 +173,8 @@ retry: clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags); return result; } - /* - * Try sending off another urb, unless called from completion handler - * (in which case there will be no free urb or no data). - */ - if (mem_flags != GFP_ATOMIC) - goto retry; - clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags); - - return 0; + goto retry; /* try sending off another urb */ } EXPORT_SYMBOL_GPL(usb_serial_generic_write_start); @@ -208,7 +200,7 @@ int usb_serial_generic_write(struct tty_struct *tty, return 0; count = kfifo_in_locked(&port->write_fifo, buf, count, &port->lock); - result = usb_serial_generic_write_start(port, GFP_KERNEL); + result = usb_serial_generic_write_start(port, GFP_ATOMIC); if (result) return result; diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index e5bdd987b9e8..a69da83604c0 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -1813,25 +1813,25 @@ static void mos7840_change_port_settings(struct tty_struct *tty, iflag = tty->termios.c_iflag; /* Change the number of bits */ - if (cflag & CSIZE) { - switch (cflag & CSIZE) { - case CS5: - lData = LCR_BITS_5; - break; + switch (cflag & CSIZE) { + case CS5: + lData = LCR_BITS_5; + break; - case CS6: - lData = LCR_BITS_6; - break; + case CS6: + lData = LCR_BITS_6; + break; - case CS7: - lData = LCR_BITS_7; - break; - default: - case CS8: - lData = LCR_BITS_8; - break; - } + case CS7: + lData = LCR_BITS_7; + break; + + default: + case CS8: + lData = LCR_BITS_8; + break; } + /* Change the Parity bit */ if (cflag & PARENB) { if (cflag & PARODD) { diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index c3d94853b4ab..496b7e39d5be 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -85,6 +85,7 @@ static void option_instat_callback(struct urb *urb); #define HUAWEI_PRODUCT_K4505 0x1464 #define HUAWEI_PRODUCT_K3765 0x1465 #define HUAWEI_PRODUCT_K4605 0x14C6 +#define HUAWEI_PRODUCT_E173S6 0x1C07 #define QUANTA_VENDOR_ID 0x0408 #define QUANTA_PRODUCT_Q101 0xEA02 @@ -572,6 +573,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c23, USB_CLASS_COMM, 0x02, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &net_intf1_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173S6, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t) &net_intf1_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1750, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1441, USB_CLASS_COMM, 0x02, 0xff) }, @@ -634,6 +637,10 @@ static const struct usb_device_id option_ids[] = { { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6D) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6E) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x72) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x73) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x74) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x75) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x78) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x79) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7A) }, @@ -688,6 +695,10 @@ static const struct usb_device_id option_ids[] = { { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6D) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6E) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x72) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x73) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x74) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x75) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x78) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x79) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7A) }, @@ -742,6 +753,10 @@ static const struct usb_device_id option_ids[] = { { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6D) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6E) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x72) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x73) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x74) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x75) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x78) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x79) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x7A) }, @@ -796,6 +811,10 @@ static const struct usb_device_id option_ids[] = { { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6D) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6E) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x72) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x73) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x74) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x75) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x78) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x79) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x7A) }, @@ -850,6 +869,10 @@ static const struct usb_device_id option_ids[] = { { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6D) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6E) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x72) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x73) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x74) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x75) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x78) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x79) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x7A) }, @@ -904,6 +927,10 @@ static const struct usb_device_id option_ids[] = { { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6D) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6E) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x72) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x73) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x74) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x75) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x78) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x79) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x7A) }, diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 1e6de4cd079d..1e3318dfa1cb 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -361,23 +361,21 @@ static void pl2303_set_termios(struct tty_struct *tty, 0, 0, buf, 7, 100); dev_dbg(&port->dev, "0xa1:0x21:0:0 %d - %7ph\n", i, buf); - if (C_CSIZE(tty)) { - switch (C_CSIZE(tty)) { - case CS5: - buf[6] = 5; - break; - case CS6: - buf[6] = 6; - break; - case CS7: - buf[6] = 7; - break; - default: - case CS8: - buf[6] = 8; - } - dev_dbg(&port->dev, "data bits = %d\n", buf[6]); + switch (C_CSIZE(tty)) { + case CS5: + buf[6] = 5; + break; + case CS6: + buf[6] = 6; + break; + case CS7: + buf[6] = 7; + break; + default: + case CS8: + buf[6] = 8; } + dev_dbg(&port->dev, "data bits = %d\n", buf[6]); /* For reference buf[0]:buf[3] baud rate value */ pl2303_encode_baudrate(tty, port, &buf[0]); diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 4abac28b5992..5b793c352267 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -348,22 +348,20 @@ static void spcp8x5_set_termios(struct tty_struct *tty, } /* Set Data Length : 00:5bit, 01:6bit, 10:7bit, 11:8bit */ - if (cflag & CSIZE) { - switch (cflag & CSIZE) { - case CS5: - buf[1] |= SET_UART_FORMAT_SIZE_5; - break; - case CS6: - buf[1] |= SET_UART_FORMAT_SIZE_6; - break; - case CS7: - buf[1] |= SET_UART_FORMAT_SIZE_7; - break; - default: - case CS8: - buf[1] |= SET_UART_FORMAT_SIZE_8; - break; - } + switch (cflag & CSIZE) { + case CS5: + buf[1] |= SET_UART_FORMAT_SIZE_5; + break; + case CS6: + buf[1] |= SET_UART_FORMAT_SIZE_6; + break; + case CS7: + buf[1] |= SET_UART_FORMAT_SIZE_7; + break; + default: + case CS8: + buf[1] |= SET_UART_FORMAT_SIZE_8; + break; } /* Set Stop bit2 : 0:1bit 1:2bit */ diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c index e538b72c4e3a..f14e7929ba22 100644 --- a/drivers/usb/wusbcore/devconnect.c +++ b/drivers/usb/wusbcore/devconnect.c @@ -97,18 +97,12 @@ static void wusbhc_devconnect_acked_work(struct work_struct *work); static void wusb_dev_free(struct wusb_dev *wusb_dev) { - if (wusb_dev) { - kfree(wusb_dev->set_gtk_req); - usb_free_urb(wusb_dev->set_gtk_urb); - kfree(wusb_dev); - } + kfree(wusb_dev); } static struct wusb_dev *wusb_dev_alloc(struct wusbhc *wusbhc) { struct wusb_dev *wusb_dev; - struct urb *urb; - struct usb_ctrlrequest *req; wusb_dev = kzalloc(sizeof(*wusb_dev), GFP_KERNEL); if (wusb_dev == NULL) @@ -118,22 +112,6 @@ static struct wusb_dev *wusb_dev_alloc(struct wusbhc *wusbhc) INIT_WORK(&wusb_dev->devconnect_acked_work, wusbhc_devconnect_acked_work); - urb = usb_alloc_urb(0, GFP_KERNEL); - if (urb == NULL) - goto err; - wusb_dev->set_gtk_urb = urb; - - req = kmalloc(sizeof(*req), GFP_KERNEL); - if (req == NULL) - goto err; - wusb_dev->set_gtk_req = req; - - req->bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE; - req->bRequest = USB_REQ_SET_DESCRIPTOR; - req->wValue = cpu_to_le16(USB_DT_KEY << 8 | wusbhc->gtk_index); - req->wIndex = 0; - req->wLength = cpu_to_le16(wusbhc->gtk.descr.bLength); - return wusb_dev; err: wusb_dev_free(wusb_dev); @@ -411,9 +389,6 @@ static void __wusbhc_dev_disconnect(struct wusbhc *wusbhc, /* * Refresh the list of keep alives to emit in the MMC * - * Some devices don't respond to keep alives unless they've been - * authenticated, so skip unauthenticated devices. - * * We only publish the first four devices that have a coming timeout * condition. Then when we are done processing those, we go for the * next ones. We ignore the ones that have timed out already (they'll @@ -448,7 +423,7 @@ static void __wusbhc_keep_alive(struct wusbhc *wusbhc) if (wusb_dev == NULL) continue; - if (wusb_dev->usb_dev == NULL || !wusb_dev->usb_dev->authenticated) + if (wusb_dev->usb_dev == NULL) continue; if (time_after(jiffies, wusb_dev->entry_ts + tt)) { @@ -524,11 +499,19 @@ static struct wusb_dev *wusbhc_find_dev_by_addr(struct wusbhc *wusbhc, u8 addr) * * @wusbhc shall be referenced and unlocked */ -static void wusbhc_handle_dn_alive(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) +static void wusbhc_handle_dn_alive(struct wusbhc *wusbhc, u8 srcaddr) { + struct wusb_dev *wusb_dev; + mutex_lock(&wusbhc->mutex); - wusb_dev->entry_ts = jiffies; - __wusbhc_keep_alive(wusbhc); + wusb_dev = wusbhc_find_dev_by_addr(wusbhc, srcaddr); + if (wusb_dev == NULL) { + dev_dbg(wusbhc->dev, "ignoring DN_Alive from unconnected device %02x\n", + srcaddr); + } else { + wusb_dev->entry_ts = jiffies; + __wusbhc_keep_alive(wusbhc); + } mutex_unlock(&wusbhc->mutex); } @@ -582,14 +565,22 @@ static void wusbhc_handle_dn_connect(struct wusbhc *wusbhc, * * @wusbhc shall be referenced and unlocked */ -static void wusbhc_handle_dn_disconnect(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) +static void wusbhc_handle_dn_disconnect(struct wusbhc *wusbhc, u8 srcaddr) { struct device *dev = wusbhc->dev; - - dev_info(dev, "DN DISCONNECT: device 0x%02x going down\n", wusb_dev->addr); + struct wusb_dev *wusb_dev; mutex_lock(&wusbhc->mutex); - __wusbhc_dev_disconnect(wusbhc, wusb_port_by_idx(wusbhc, wusb_dev->port_idx)); + wusb_dev = wusbhc_find_dev_by_addr(wusbhc, srcaddr); + if (wusb_dev == NULL) { + dev_dbg(dev, "ignoring DN DISCONNECT from unconnected device %02x\n", + srcaddr); + } else { + dev_info(dev, "DN DISCONNECT: device 0x%02x going down\n", + wusb_dev->addr); + __wusbhc_dev_disconnect(wusbhc, wusb_port_by_idx(wusbhc, + wusb_dev->port_idx)); + } mutex_unlock(&wusbhc->mutex); } @@ -611,30 +602,21 @@ void wusbhc_handle_dn(struct wusbhc *wusbhc, u8 srcaddr, struct wusb_dn_hdr *dn_hdr, size_t size) { struct device *dev = wusbhc->dev; - struct wusb_dev *wusb_dev; if (size < sizeof(struct wusb_dn_hdr)) { dev_err(dev, "DN data shorter than DN header (%d < %d)\n", (int)size, (int)sizeof(struct wusb_dn_hdr)); return; } - - wusb_dev = wusbhc_find_dev_by_addr(wusbhc, srcaddr); - if (wusb_dev == NULL && dn_hdr->bType != WUSB_DN_CONNECT) { - dev_dbg(dev, "ignoring DN %d from unconnected device %02x\n", - dn_hdr->bType, srcaddr); - return; - } - switch (dn_hdr->bType) { case WUSB_DN_CONNECT: wusbhc_handle_dn_connect(wusbhc, dn_hdr, size); break; case WUSB_DN_ALIVE: - wusbhc_handle_dn_alive(wusbhc, wusb_dev); + wusbhc_handle_dn_alive(wusbhc, srcaddr); break; case WUSB_DN_DISCONNECT: - wusbhc_handle_dn_disconnect(wusbhc, wusb_dev); + wusbhc_handle_dn_disconnect(wusbhc, srcaddr); break; case WUSB_DN_MASAVAILCHANGED: case WUSB_DN_RWAKE: diff --git a/drivers/usb/wusbcore/security.c b/drivers/usb/wusbcore/security.c index dd88441c8f78..4c40d0dbf53d 100644 --- a/drivers/usb/wusbcore/security.c +++ b/drivers/usb/wusbcore/security.c @@ -29,19 +29,16 @@ #include <linux/export.h> #include "wusbhc.h" -static void wusbhc_set_gtk_callback(struct urb *urb); -static void wusbhc_gtk_rekey_done_work(struct work_struct *work); +static void wusbhc_gtk_rekey_work(struct work_struct *work); int wusbhc_sec_create(struct wusbhc *wusbhc) { wusbhc->gtk.descr.bLength = sizeof(wusbhc->gtk.descr) + sizeof(wusbhc->gtk.data); wusbhc->gtk.descr.bDescriptorType = USB_DT_KEY; wusbhc->gtk.descr.bReserved = 0; + wusbhc->gtk_index = 0; - wusbhc->gtk_index = wusb_key_index(0, WUSB_KEY_INDEX_TYPE_GTK, - WUSB_KEY_INDEX_ORIGINATOR_HOST); - - INIT_WORK(&wusbhc->gtk_rekey_done_work, wusbhc_gtk_rekey_done_work); + INIT_WORK(&wusbhc->gtk_rekey_work, wusbhc_gtk_rekey_work); return 0; } @@ -113,7 +110,7 @@ int wusbhc_sec_start(struct wusbhc *wusbhc) wusbhc_generate_gtk(wusbhc); result = wusbhc->set_gtk(wusbhc, wusbhc->gtk_tkid, - &wusbhc->gtk.descr.bKeyData, key_size); + &wusbhc->gtk.descr.bKeyData, key_size); if (result < 0) dev_err(wusbhc->dev, "cannot set GTK for the host: %d\n", result); @@ -129,7 +126,7 @@ int wusbhc_sec_start(struct wusbhc *wusbhc) */ void wusbhc_sec_stop(struct wusbhc *wusbhc) { - cancel_work_sync(&wusbhc->gtk_rekey_done_work); + cancel_work_sync(&wusbhc->gtk_rekey_work); } @@ -185,12 +182,14 @@ static int wusb_dev_set_encryption(struct usb_device *usb_dev, int value) static int wusb_dev_set_gtk(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) { struct usb_device *usb_dev = wusb_dev->usb_dev; + u8 key_index = wusb_key_index(wusbhc->gtk_index, + WUSB_KEY_INDEX_TYPE_GTK, WUSB_KEY_INDEX_ORIGINATOR_HOST); return usb_control_msg( usb_dev, usb_sndctrlpipe(usb_dev, 0), USB_REQ_SET_DESCRIPTOR, USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, - USB_DT_KEY << 8 | wusbhc->gtk_index, 0, + USB_DT_KEY << 8 | key_index, 0, &wusbhc->gtk.descr, wusbhc->gtk.descr.bLength, 1000); } @@ -520,24 +519,55 @@ error_kzalloc: * Once all connected and authenticated devices have received the new * GTK, switch the host to using it. */ -static void wusbhc_gtk_rekey_done_work(struct work_struct *work) +static void wusbhc_gtk_rekey_work(struct work_struct *work) { - struct wusbhc *wusbhc = container_of(work, struct wusbhc, gtk_rekey_done_work); + struct wusbhc *wusbhc = container_of(work, + struct wusbhc, gtk_rekey_work); size_t key_size = sizeof(wusbhc->gtk.data); + int port_idx; + struct wusb_dev *wusb_dev, *wusb_dev_next; + LIST_HEAD(rekey_list); mutex_lock(&wusbhc->mutex); + /* generate the new key */ + wusbhc_generate_gtk(wusbhc); + /* roll the gtk index. */ + wusbhc->gtk_index = (wusbhc->gtk_index + 1) % (WUSB_KEY_INDEX_MAX + 1); + /* + * Save all connected devices on a list while holding wusbhc->mutex and + * take a reference to each one. Then submit the set key request to + * them after releasing the lock in order to avoid a deadlock. + */ + for (port_idx = 0; port_idx < wusbhc->ports_max; port_idx++) { + wusb_dev = wusbhc->port[port_idx].wusb_dev; + if (!wusb_dev || !wusb_dev->usb_dev + || !wusb_dev->usb_dev->authenticated) + continue; - if (--wusbhc->pending_set_gtks == 0) - wusbhc->set_gtk(wusbhc, wusbhc->gtk_tkid, &wusbhc->gtk.descr.bKeyData, key_size); - + wusb_dev_get(wusb_dev); + list_add_tail(&wusb_dev->rekey_node, &rekey_list); + } mutex_unlock(&wusbhc->mutex); -} -static void wusbhc_set_gtk_callback(struct urb *urb) -{ - struct wusbhc *wusbhc = urb->context; + /* Submit the rekey requests without holding wusbhc->mutex. */ + list_for_each_entry_safe(wusb_dev, wusb_dev_next, &rekey_list, + rekey_node) { + list_del_init(&wusb_dev->rekey_node); + dev_dbg(&wusb_dev->usb_dev->dev, "%s: rekey device at port %d\n", + __func__, wusb_dev->port_idx); + + if (wusb_dev_set_gtk(wusbhc, wusb_dev) < 0) { + dev_err(&wusb_dev->usb_dev->dev, "%s: rekey device at port %d failed\n", + __func__, wusb_dev->port_idx); + } + wusb_dev_put(wusb_dev); + } - queue_work(wusbd, &wusbhc->gtk_rekey_done_work); + /* Switch the host controller to use the new GTK. */ + mutex_lock(&wusbhc->mutex); + wusbhc->set_gtk(wusbhc, wusbhc->gtk_tkid, + &wusbhc->gtk.descr.bKeyData, key_size); + mutex_unlock(&wusbhc->mutex); } /** @@ -553,26 +583,12 @@ static void wusbhc_set_gtk_callback(struct urb *urb) */ void wusbhc_gtk_rekey(struct wusbhc *wusbhc) { - static const size_t key_size = sizeof(wusbhc->gtk.data); - int p; - - wusbhc_generate_gtk(wusbhc); - - for (p = 0; p < wusbhc->ports_max; p++) { - struct wusb_dev *wusb_dev; - - wusb_dev = wusbhc->port[p].wusb_dev; - if (!wusb_dev || !wusb_dev->usb_dev || !wusb_dev->usb_dev->authenticated) - continue; - - usb_fill_control_urb(wusb_dev->set_gtk_urb, wusb_dev->usb_dev, - usb_sndctrlpipe(wusb_dev->usb_dev, 0), - (void *)wusb_dev->set_gtk_req, - &wusbhc->gtk.descr, wusbhc->gtk.descr.bLength, - wusbhc_set_gtk_callback, wusbhc); - if (usb_submit_urb(wusb_dev->set_gtk_urb, GFP_KERNEL) == 0) - wusbhc->pending_set_gtks++; - } - if (wusbhc->pending_set_gtks == 0) - wusbhc->set_gtk(wusbhc, wusbhc->gtk_tkid, &wusbhc->gtk.descr.bKeyData, key_size); + /* + * We need to submit a URB to the downstream WUSB devices in order to + * change the group key. This can't be done while holding the + * wusbhc->mutex since that is also taken in the urb_enqueue routine + * and will cause a deadlock. Instead, queue a work item to do + * it when the lock is not held + */ + queue_work(wusbd, &wusbhc->gtk_rekey_work); } diff --git a/drivers/usb/wusbcore/wusbhc.h b/drivers/usb/wusbcore/wusbhc.h index 711b1952b114..6bd3b819a6b5 100644 --- a/drivers/usb/wusbcore/wusbhc.h +++ b/drivers/usb/wusbcore/wusbhc.h @@ -97,6 +97,7 @@ struct wusb_dev { struct kref refcnt; struct wusbhc *wusbhc; struct list_head cack_node; /* Connect-Ack list */ + struct list_head rekey_node; /* GTK rekey list */ u8 port_idx; u8 addr; u8 beacon_type:4; @@ -107,8 +108,6 @@ struct wusb_dev { struct usb_wireless_cap_descriptor *wusb_cap_descr; struct uwb_mas_bm availability; struct work_struct devconnect_acked_work; - struct urb *set_gtk_urb; - struct usb_ctrlrequest *set_gtk_req; struct usb_device *usb_dev; }; @@ -296,8 +295,7 @@ struct wusbhc { } __attribute__((packed)) gtk; u8 gtk_index; u32 gtk_tkid; - struct work_struct gtk_rekey_done_work; - int pending_set_gtks; + struct work_struct gtk_rekey_work; struct usb_encryption_descriptor *ccm1_etd; }; diff --git a/drivers/video/offb.c b/drivers/video/offb.c index 9dbea2223401..7d44d669d5b6 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -91,6 +91,15 @@ extern boot_infos_t *boot_infos; #define AVIVO_DC_LUTB_WHITE_OFFSET_GREEN 0x6cd4 #define AVIVO_DC_LUTB_WHITE_OFFSET_RED 0x6cd8 +#define FB_RIGHT_POS(p, bpp) (fb_be_math(p) ? 0 : (32 - (bpp))) + +static inline u32 offb_cmap_byteswap(struct fb_info *info, u32 value) +{ + u32 bpp = info->var.bits_per_pixel; + + return cpu_to_be32(value) >> FB_RIGHT_POS(info, bpp); +} + /* * Set a single color register. The values supplied are already * rounded down to the hardware's capabilities (according to the @@ -120,7 +129,7 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, mask <<= info->var.transp.offset; value |= mask; } - pal[regno] = value; + pal[regno] = offb_cmap_byteswap(info, value); return 0; } @@ -301,7 +310,7 @@ static struct fb_ops offb_ops = { static void __iomem *offb_map_reg(struct device_node *np, int index, unsigned long offset, unsigned long size) { - const u32 *addrp; + const __be32 *addrp; u64 asize, taddr; unsigned int flags; @@ -369,7 +378,11 @@ static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp } of_node_put(pciparent); } else if (dp && of_device_is_compatible(dp, "qemu,std-vga")) { - const u32 io_of_addr[3] = { 0x01000000, 0x0, 0x0 }; +#ifdef __BIG_ENDIAN + const __be32 io_of_addr[3] = { 0x01000000, 0x0, 0x0 }; +#else + const __be32 io_of_addr[3] = { 0x00000001, 0x0, 0x0 }; +#endif u64 io_addr = of_translate_address(dp, io_of_addr); if (io_addr != OF_BAD_ADDR) { par->cmap_adr = ioremap(io_addr + 0x3c8, 2); @@ -535,7 +548,7 @@ static void __init offb_init_nodriver(struct device_node *dp, int no_real_node) unsigned int flags, rsize, addr_prop = 0; unsigned long max_size = 0; u64 rstart, address = OF_BAD_ADDR; - const u32 *pp, *addrp, *up; + const __be32 *pp, *addrp, *up; u64 asize; int foreign_endian = 0; @@ -551,25 +564,25 @@ static void __init offb_init_nodriver(struct device_node *dp, int no_real_node) if (pp == NULL) pp = of_get_property(dp, "depth", &len); if (pp && len == sizeof(u32)) - depth = *pp; + depth = be32_to_cpup(pp); pp = of_get_property(dp, "linux,bootx-width", &len); if (pp == NULL) pp = of_get_property(dp, "width", &len); if (pp && len == sizeof(u32)) - width = *pp; + width = be32_to_cpup(pp); pp = of_get_property(dp, "linux,bootx-height", &len); if (pp == NULL) pp = of_get_property(dp, "height", &len); if (pp && len == sizeof(u32)) - height = *pp; + height = be32_to_cpup(pp); pp = of_get_property(dp, "linux,bootx-linebytes", &len); if (pp == NULL) pp = of_get_property(dp, "linebytes", &len); if (pp && len == sizeof(u32) && (*pp != 0xffffffffu)) - pitch = *pp; + pitch = be32_to_cpup(pp); else pitch = width * ((depth + 7) / 8); diff --git a/drivers/watchdog/bcm2835_wdt.c b/drivers/watchdog/bcm2835_wdt.c index a6a2cebb2587..cafa973c43be 100644 --- a/drivers/watchdog/bcm2835_wdt.c +++ b/drivers/watchdog/bcm2835_wdt.c @@ -19,7 +19,6 @@ #include <linux/watchdog.h> #include <linux/platform_device.h> #include <linux/of_address.h> -#include <linux/miscdevice.h> #define PM_RSTC 0x1c #define PM_WDOG 0x24 diff --git a/drivers/watchdog/ep93xx_wdt.c b/drivers/watchdog/ep93xx_wdt.c index 833e81311848..d1d07f2f69df 100644 --- a/drivers/watchdog/ep93xx_wdt.c +++ b/drivers/watchdog/ep93xx_wdt.c @@ -28,7 +28,6 @@ #include <linux/platform_device.h> #include <linux/module.h> -#include <linux/miscdevice.h> #include <linux/watchdog.h> #include <linux/timer.h> #include <linux/io.h> diff --git a/drivers/watchdog/ie6xx_wdt.c b/drivers/watchdog/ie6xx_wdt.c index 70a240297c6d..07f88f54e5c0 100644 --- a/drivers/watchdog/ie6xx_wdt.c +++ b/drivers/watchdog/ie6xx_wdt.c @@ -28,7 +28,6 @@ #include <linux/kernel.h> #include <linux/types.h> #include <linux/watchdog.h> -#include <linux/miscdevice.h> #include <linux/seq_file.h> #include <linux/debugfs.h> #include <linux/uaccess.h> diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c index 2de486a7eea1..3aa50cfa335f 100644 --- a/drivers/watchdog/jz4740_wdt.c +++ b/drivers/watchdog/jz4740_wdt.c @@ -17,7 +17,6 @@ #include <linux/moduleparam.h> #include <linux/types.h> #include <linux/kernel.h> -#include <linux/miscdevice.h> #include <linux/watchdog.h> #include <linux/init.h> #include <linux/platform_device.h> diff --git a/drivers/watchdog/kempld_wdt.c b/drivers/watchdog/kempld_wdt.c index a1a3638c579c..20dc73844737 100644 --- a/drivers/watchdog/kempld_wdt.c +++ b/drivers/watchdog/kempld_wdt.c @@ -26,7 +26,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> -#include <linux/miscdevice.h> #include <linux/uaccess.h> #include <linux/watchdog.h> #include <linux/platform_device.h> diff --git a/drivers/watchdog/max63xx_wdt.c b/drivers/watchdog/max63xx_wdt.c index 6d4f3998e1f6..bdb3f4a5b27c 100644 --- a/drivers/watchdog/max63xx_wdt.c +++ b/drivers/watchdog/max63xx_wdt.c @@ -19,7 +19,6 @@ #include <linux/moduleparam.h> #include <linux/types.h> #include <linux/kernel.h> -#include <linux/miscdevice.h> #include <linux/watchdog.h> #include <linux/init.h> #include <linux/bitops.h> diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c index 44edca66d564..f7722a424676 100644 --- a/drivers/watchdog/orion_wdt.c +++ b/drivers/watchdog/orion_wdt.c @@ -16,7 +16,6 @@ #include <linux/moduleparam.h> #include <linux/types.h> #include <linux/kernel.h> -#include <linux/miscdevice.h> #include <linux/platform_device.h> #include <linux/watchdog.h> #include <linux/init.h> diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c index 1bdcc313e1d9..5bec20f5dc2d 100644 --- a/drivers/watchdog/pnx4008_wdt.c +++ b/drivers/watchdog/pnx4008_wdt.c @@ -23,7 +23,6 @@ #include <linux/moduleparam.h> #include <linux/types.h> #include <linux/kernel.h> -#include <linux/miscdevice.h> #include <linux/watchdog.h> #include <linux/init.h> #include <linux/platform_device.h> diff --git a/drivers/watchdog/rt2880_wdt.c b/drivers/watchdog/rt2880_wdt.c index 53d37fea183e..d92c2d5859ce 100644 --- a/drivers/watchdog/rt2880_wdt.c +++ b/drivers/watchdog/rt2880_wdt.c @@ -16,7 +16,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/watchdog.h> -#include <linux/miscdevice.h> #include <linux/moduleparam.h> #include <linux/platform_device.h> diff --git a/drivers/watchdog/sc1200wdt.c b/drivers/watchdog/sc1200wdt.c index 3b9fff9dcf65..131193a7acdf 100644 --- a/drivers/watchdog/sc1200wdt.c +++ b/drivers/watchdog/sc1200wdt.c @@ -409,8 +409,9 @@ static int __init sc1200wdt_init(void) #if defined CONFIG_PNP /* now that the user has specified an IO port and we haven't detected * any devices, disable pnp support */ + if (isapnp) + pnp_unregister_driver(&scl200wdt_pnp_driver); isapnp = 0; - pnp_unregister_driver(&scl200wdt_pnp_driver); #endif if (!request_region(io, io_len, SC1200_MODULE_NAME)) { diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c index f9b8e06f3558..af3528f84d65 100644 --- a/drivers/watchdog/shwdt.c +++ b/drivers/watchdog/shwdt.c @@ -26,7 +26,6 @@ #include <linux/init.h> #include <linux/types.h> #include <linux/spinlock.h> -#include <linux/miscdevice.h> #include <linux/watchdog.h> #include <linux/pm_runtime.h> #include <linux/fs.h> diff --git a/drivers/watchdog/softdog.c b/drivers/watchdog/softdog.c index ef2638fee4a8..c04a1aa158e2 100644 --- a/drivers/watchdog/softdog.c +++ b/drivers/watchdog/softdog.c @@ -42,7 +42,6 @@ #include <linux/moduleparam.h> #include <linux/types.h> #include <linux/timer.h> -#include <linux/miscdevice.h> #include <linux/watchdog.h> #include <linux/notifier.h> #include <linux/reboot.h> diff --git a/drivers/watchdog/stmp3xxx_rtc_wdt.c b/drivers/watchdog/stmp3xxx_rtc_wdt.c index d667f6b51d35..bb64ae3f47da 100644 --- a/drivers/watchdog/stmp3xxx_rtc_wdt.c +++ b/drivers/watchdog/stmp3xxx_rtc_wdt.c @@ -12,7 +12,6 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/miscdevice.h> #include <linux/watchdog.h> #include <linux/platform_device.h> #include <linux/stmp3xxx_rtc_wdt.h> diff --git a/drivers/watchdog/txx9wdt.c b/drivers/watchdog/txx9wdt.c index 0fd0e8ae62a8..6a447e321dd0 100644 --- a/drivers/watchdog/txx9wdt.c +++ b/drivers/watchdog/txx9wdt.c @@ -13,7 +13,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/types.h> -#include <linux/miscdevice.h> #include <linux/watchdog.h> #include <linux/init.h> #include <linux/platform_device.h> diff --git a/drivers/watchdog/ux500_wdt.c b/drivers/watchdog/ux500_wdt.c index e029b5768f2c..5aed9d7ad47e 100644 --- a/drivers/watchdog/ux500_wdt.c +++ b/drivers/watchdog/ux500_wdt.c @@ -12,7 +12,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/moduleparam.h> -#include <linux/miscdevice.h> #include <linux/err.h> #include <linux/uaccess.h> #include <linux/watchdog.h> |