summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorPraneeth Bajjuri <praneeth@ti.com>2015-02-02 13:57:00 -0600
committerPraneeth Bajjuri <praneeth@ti.com>2015-02-02 13:57:00 -0600
commite96b6cca684ee9c6005c5632a2825267da92d788 (patch)
tree6f9db51b9e6d5c50b508554c4c5d715cb736ad9b /drivers
parentb68f1c99f34f6cecd273dbafe969fb4685db0926 (diff)
parent44b9c6063d9a4ae0edced1bb4fb0d870d4a9a715 (diff)
Merge branch 'p-ti-linux-3.14.y-common' into p-ti-linux-3.14.y-android
* p-ti-linux-3.14.y-common: (97 commits) media: ti-vpe: vpe: Add RGB565 and RGB5551 support media: ti-vpe: vpe: Post next descriptor only for list complete IRQ media: ti-vpe: vpe: Setup srcdst parameters in streamON omapdrm: Expose the OMAP pre-multiplied alpha property through DRM omapdrm: Expose the OMAP global alpha property through DRM ti_fragments: audio_display: enable BACKLIGHT_GPIO and PANEL_DPI ti_fragments: audio_display: clean up arm/dts: am57xx-evm: Add LCD support backlight: gpio-backlight: Add DT support arm/dts: dra7xx: fix display compatible strings OMAPDSS: add missing 'omapdss' prefixes to display drivers OMAPDSS: add dra7-dss to dt conversion list Linux 3.14.31 md/raid5: fetch_block must fetch all the blocks handle_stripe_dirtying wants. mm: get rid of radix tree gfp mask for pagecache_get_page mm: page_alloc: reduce cost of the fair zone allocation policy mm: page_alloc: abort fair zone allocation policy when remotes nodes are encountered mm: vmscan: only update per-cpu thresholds for online CPU mm: move zone->pages_scanned into a vmstat counter mm: rearrange zone fields into read-only, page alloc, statistics and page reclaim lines ... Change-Id: Ib0c33383880f80ba4468e919de46bbeaf42b1bd5 Signed-off-by: Praneeth Bajjuri <praneeth@ti.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/libata-sff.c12
-rw-r--r--drivers/ata/sata_dwc_460ex.c26
-rw-r--r--drivers/block/drbd/drbd_req.c1
-rw-r--r--drivers/bus/mvebu-mbus.c13
-rw-r--r--drivers/clocksource/exynos_mct.c4
-rw-r--r--drivers/crypto/padlock-aes.c2
-rw-r--r--drivers/crypto/padlock-sha.c8
-rw-r--r--drivers/crypto/ux500/cryp/cryp_core.c4
-rw-r--r--drivers/crypto/ux500/hash/hash_core.c8
-rw-r--r--drivers/gpio/gpiolib.c46
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c2
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.h2
-rw-r--r--drivers/gpu/drm/omapdrm/omap_plane.c34
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.c18
-rw-r--r--drivers/gpu/drm/radeon/radeon_pm.c33
-rw-r--r--drivers/gpu/drm/radeon/si_dpm.c39
-rw-r--r--drivers/input/evdev.c13
-rw-r--r--drivers/md/dm-cache-metadata.c101
-rw-r--r--drivers/md/dm-cache-target.c89
-rw-r--r--drivers/md/raid5.c3
-rw-r--r--drivers/media/platform/ti-vpe/vpe.c32
-rw-r--r--drivers/mmc/host/sdhci.c2
-rw-r--r--drivers/net/can/dev.c8
-rw-r--r--drivers/pci/pci.c40
-rw-r--r--drivers/pci/quirks.c14
-rw-r--r--drivers/pinctrl/Kconfig11
-rw-r--r--drivers/pinctrl/Makefile1
-rw-r--r--drivers/pinctrl/core.c5
-rw-r--r--drivers/pinctrl/pinctrl-ti-iodelay.c962
-rw-r--r--drivers/s390/crypto/ap_bus.c3
-rw-r--r--drivers/scsi/ipr.c92
-rw-r--r--drivers/scsi/ipr.h1
-rw-r--r--drivers/tty/n_tty.c9
-rw-r--r--drivers/video/backlight/gpio_backlight.c58
-rw-r--r--drivers/video/fbdev/omap2/displays-new/dra7-evm-encoder-tpd12s015.c2
-rw-r--r--drivers/video/fbdev/omap2/displays-new/panel-tlc59108.c4
-rw-r--r--drivers/video/fbdev/omap2/dss/omapdss-boot-init.c1
-rw-r--r--drivers/xen/swiotlb-xen.c2
38 files changed, 1574 insertions, 131 deletions
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 37acda6fa7e..136803c47cd 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -1333,7 +1333,19 @@ void ata_sff_flush_pio_task(struct ata_port *ap)
DPRINTK("ENTER\n");
cancel_delayed_work_sync(&ap->sff_pio_task);
+
+ /*
+ * We wanna reset the HSM state to IDLE. If we do so without
+ * grabbing the port lock, critical sections protected by it which
+ * expect the HSM state to stay stable may get surprised. For
+ * example, we may set IDLE in between the time
+ * __ata_sff_port_intr() checks for HSM_ST_IDLE and before it calls
+ * ata_sff_hsm_move() causing ata_sff_hsm_move() to BUG().
+ */
+ spin_lock_irq(ap->lock);
ap->hsm_task_state = HSM_ST_IDLE;
+ spin_unlock_irq(ap->lock);
+
ap->sff_pio_task_link = NULL;
if (ata_msg_ctl(ap))
diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 73510d0d140..113d7226cb6 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -798,7 +798,7 @@ static int dma_dwc_init(struct sata_dwc_device *hsdev, int irq)
if (err) {
dev_err(host_pvt.dwc_dev, "%s: dma_request_interrupts returns"
" %d\n", __func__, err);
- goto error_out;
+ return err;
}
/* Enabe DMA */
@@ -809,11 +809,6 @@ static int dma_dwc_init(struct sata_dwc_device *hsdev, int irq)
sata_dma_regs);
return 0;
-
-error_out:
- dma_dwc_exit(hsdev);
-
- return err;
}
static int sata_dwc_scr_read(struct ata_link *link, unsigned int scr, u32 *val)
@@ -1663,7 +1658,7 @@ static int sata_dwc_probe(struct platform_device *ofdev)
char *ver = (char *)&versionr;
u8 *base = NULL;
int err = 0;
- int irq, rc;
+ int irq;
struct ata_host *host;
struct ata_port_info pi = sata_dwc_port_info[0];
const struct ata_port_info *ppi[] = { &pi, NULL };
@@ -1726,7 +1721,7 @@ static int sata_dwc_probe(struct platform_device *ofdev)
if (irq == NO_IRQ) {
dev_err(&ofdev->dev, "no SATA DMA irq\n");
err = -ENODEV;
- goto error_out;
+ goto error_iomap;
}
/* Get physical SATA DMA register base address */
@@ -1735,14 +1730,16 @@ static int sata_dwc_probe(struct platform_device *ofdev)
dev_err(&ofdev->dev, "ioremap failed for AHBDMA register"
" address\n");
err = -ENODEV;
- goto error_out;
+ goto error_iomap;
}
/* Save dev for later use in dev_xxx() routines */
host_pvt.dwc_dev = &ofdev->dev;
/* Initialize AHB DMAC */
- dma_dwc_init(hsdev, irq);
+ err = dma_dwc_init(hsdev, irq);
+ if (err)
+ goto error_dma_iomap;
/* Enable SATA Interrupts */
sata_dwc_enable_interrupts(hsdev);
@@ -1760,9 +1757,8 @@ static int sata_dwc_probe(struct platform_device *ofdev)
* device discovery process, invoking our port_start() handler &
* error_handler() to execute a dummy Softreset EH session
*/
- rc = ata_host_activate(host, irq, sata_dwc_isr, 0, &sata_dwc_sht);
-
- if (rc != 0)
+ err = ata_host_activate(host, irq, sata_dwc_isr, 0, &sata_dwc_sht);
+ if (err)
dev_err(&ofdev->dev, "failed to activate host");
dev_set_drvdata(&ofdev->dev, host);
@@ -1771,7 +1767,8 @@ static int sata_dwc_probe(struct platform_device *ofdev)
error_out:
/* Free SATA DMA resources */
dma_dwc_exit(hsdev);
-
+error_dma_iomap:
+ iounmap((void __iomem *)host_pvt.sata_dma_regs);
error_iomap:
iounmap(base);
error_kmalloc:
@@ -1792,6 +1789,7 @@ static int sata_dwc_remove(struct platform_device *ofdev)
/* Free SATA DMA resources */
dma_dwc_exit(hsdev);
+ iounmap((void __iomem *)host_pvt.sata_dma_regs);
iounmap(hsdev->reg_base);
kfree(hsdev);
kfree(host);
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index 104a040f24d..6efdbeafa33 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -1310,6 +1310,7 @@ int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct
struct request_queue * const b =
mdev->ldev->backing_bdev->bd_disk->queue;
if (b->merge_bvec_fn) {
+ bvm->bi_bdev = mdev->ldev->backing_bdev;
backing_limit = b->merge_bvec_fn(b, bvm, bvec);
limit = min(limit, backing_limit);
}
diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c
index 372ae72cce3..e990deed2d3 100644
--- a/drivers/bus/mvebu-mbus.c
+++ b/drivers/bus/mvebu-mbus.c
@@ -181,12 +181,25 @@ static void mvebu_mbus_disable_window(struct mvebu_mbus_state *mbus,
}
/* Checks whether the given window number is available */
+
+/* On Armada XP, 375 and 38x the MBus window 13 has the remap
+ * capability, like windows 0 to 7. However, the mvebu-mbus driver
+ * isn't currently taking into account this special case, which means
+ * that when window 13 is actually used, the remap registers are left
+ * to 0, making the device using this MBus window unavailable. The
+ * quick fix for stable is to not use window 13. A follow up patch
+ * will correctly handle this window.
+*/
static int mvebu_mbus_window_is_free(struct mvebu_mbus_state *mbus,
const int win)
{
void __iomem *addr = mbus->mbuswins_base +
mbus->soc->win_cfg_offset(win);
u32 ctrl = readl(addr + WIN_CTRL_OFF);
+
+ if (win == 13)
+ return false;
+
return !(ctrl & WIN_CTRL_ENABLE);
}
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c
index e252939b9ee..831b48287a2 100644
--- a/drivers/clocksource/exynos_mct.c
+++ b/drivers/clocksource/exynos_mct.c
@@ -98,8 +98,8 @@ static void exynos4_mct_write(unsigned int value, unsigned long offset)
__raw_writel(value, reg_base + offset);
if (likely(offset >= EXYNOS4_MCT_L_BASE(0))) {
- stat_addr = (offset & ~EXYNOS4_MCT_L_MASK) + MCT_L_WSTAT_OFFSET;
- switch (offset & EXYNOS4_MCT_L_MASK) {
+ stat_addr = (offset & EXYNOS4_MCT_L_MASK) + MCT_L_WSTAT_OFFSET;
+ switch (offset & ~EXYNOS4_MCT_L_MASK) {
case MCT_L_TCON_OFFSET:
mask = 1 << 3; /* L_TCON write status */
break;
diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c
index 633ba945e15..c178ed8c390 100644
--- a/drivers/crypto/padlock-aes.c
+++ b/drivers/crypto/padlock-aes.c
@@ -563,4 +563,4 @@ MODULE_DESCRIPTION("VIA PadLock AES algorithm support");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Michal Ludvig");
-MODULE_ALIAS("aes");
+MODULE_ALIAS_CRYPTO("aes");
diff --git a/drivers/crypto/padlock-sha.c b/drivers/crypto/padlock-sha.c
index 9266c0e2549..93d7753ab38 100644
--- a/drivers/crypto/padlock-sha.c
+++ b/drivers/crypto/padlock-sha.c
@@ -593,7 +593,7 @@ MODULE_DESCRIPTION("VIA PadLock SHA1/SHA256 algorithms support.");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Michal Ludvig");
-MODULE_ALIAS("sha1-all");
-MODULE_ALIAS("sha256-all");
-MODULE_ALIAS("sha1-padlock");
-MODULE_ALIAS("sha256-padlock");
+MODULE_ALIAS_CRYPTO("sha1-all");
+MODULE_ALIAS_CRYPTO("sha256-all");
+MODULE_ALIAS_CRYPTO("sha1-padlock");
+MODULE_ALIAS_CRYPTO("sha256-padlock");
diff --git a/drivers/crypto/ux500/cryp/cryp_core.c b/drivers/crypto/ux500/cryp/cryp_core.c
index 92105f3dc8e..e4cea7c4514 100644
--- a/drivers/crypto/ux500/cryp/cryp_core.c
+++ b/drivers/crypto/ux500/cryp/cryp_core.c
@@ -1810,7 +1810,7 @@ module_exit(ux500_cryp_mod_fini);
module_param(cryp_mode, int, 0);
MODULE_DESCRIPTION("Driver for ST-Ericsson UX500 CRYP crypto engine.");
-MODULE_ALIAS("aes-all");
-MODULE_ALIAS("des-all");
+MODULE_ALIAS_CRYPTO("aes-all");
+MODULE_ALIAS_CRYPTO("des-all");
MODULE_LICENSE("GPL");
diff --git a/drivers/crypto/ux500/hash/hash_core.c b/drivers/crypto/ux500/hash/hash_core.c
index 1c73f4fbc25..8e5e0187506 100644
--- a/drivers/crypto/ux500/hash/hash_core.c
+++ b/drivers/crypto/ux500/hash/hash_core.c
@@ -1995,7 +1995,7 @@ module_exit(ux500_hash_mod_fini);
MODULE_DESCRIPTION("Driver for ST-Ericsson UX500 HASH engine.");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("sha1-all");
-MODULE_ALIAS("sha256-all");
-MODULE_ALIAS("hmac-sha1-all");
-MODULE_ALIAS("hmac-sha256-all");
+MODULE_ALIAS_CRYPTO("sha1-all");
+MODULE_ALIAS_CRYPTO("sha256-all");
+MODULE_ALIAS_CRYPTO("hmac-sha1-all");
+MODULE_ALIAS_CRYPTO("hmac-sha256-all");
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 88dbf31b389..3542137441c 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -408,7 +408,7 @@ static ssize_t gpio_value_store(struct device *dev,
return status;
}
-static const DEVICE_ATTR(value, 0644,
+static DEVICE_ATTR(value, 0644,
gpio_value_show, gpio_value_store);
static irqreturn_t gpio_sysfs_irq(int irq, void *priv)
@@ -633,18 +633,16 @@ static ssize_t gpio_active_low_store(struct device *dev,
return status ? : size;
}
-static const DEVICE_ATTR(active_low, 0644,
+static DEVICE_ATTR(active_low, 0644,
gpio_active_low_show, gpio_active_low_store);
-static const struct attribute *gpio_attrs[] = {
+static struct attribute *gpio_attrs[] = {
&dev_attr_value.attr,
&dev_attr_active_low.attr,
NULL,
};
-static const struct attribute_group gpio_attr_group = {
- .attrs = (struct attribute **) gpio_attrs,
-};
+ATTRIBUTE_GROUPS(gpio);
/*
* /sys/class/gpio/gpiochipN/
@@ -680,16 +678,13 @@ static ssize_t chip_ngpio_show(struct device *dev,
}
static DEVICE_ATTR(ngpio, 0444, chip_ngpio_show, NULL);
-static const struct attribute *gpiochip_attrs[] = {
+static struct attribute *gpiochip_attrs[] = {
&dev_attr_base.attr,
&dev_attr_label.attr,
&dev_attr_ngpio.attr,
NULL,
};
-
-static const struct attribute_group gpiochip_attr_group = {
- .attrs = (struct attribute **) gpiochip_attrs,
-};
+ATTRIBUTE_GROUPS(gpiochip);
/*
* /sys/class/gpio/export ... write-only
@@ -844,18 +839,15 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
if (desc->chip->names && desc->chip->names[offset])
ioname = desc->chip->names[offset];
- dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
- desc, ioname ? ioname : "gpio%u",
- desc_to_gpio(desc));
+ dev = device_create_with_groups(&gpio_class, desc->chip->dev,
+ MKDEV(0, 0), desc, gpio_groups,
+ ioname ? ioname : "gpio%u",
+ desc_to_gpio(desc));
if (IS_ERR(dev)) {
status = PTR_ERR(dev);
goto fail_unlock;
}
- status = sysfs_create_group(&dev->kobj, &gpio_attr_group);
- if (status)
- goto fail_unregister_device;
-
if (direction_may_change) {
status = device_create_file(dev, &dev_attr_direction);
if (status)
@@ -866,13 +858,15 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
!test_bit(FLAG_IS_OUT, &desc->flags))) {
status = device_create_file(dev, &dev_attr_edge);
if (status)
- goto fail_unregister_device;
+ goto fail_remove_attr_direction;
}
set_bit(FLAG_EXPORT, &desc->flags);
mutex_unlock(&sysfs_lock);
return 0;
+fail_remove_attr_direction:
+ device_remove_file(dev, &dev_attr_direction);
fail_unregister_device:
device_unregister(dev);
fail_unlock:
@@ -1006,6 +1000,8 @@ void gpiod_unexport(struct gpio_desc *desc)
mutex_unlock(&sysfs_lock);
if (dev) {
+ device_remove_file(dev, &dev_attr_edge);
+ device_remove_file(dev, &dev_attr_direction);
device_unregister(dev);
put_device(dev);
}
@@ -1030,13 +1026,13 @@ static int gpiochip_export(struct gpio_chip *chip)
/* use chip->base for the ID; it's already known to be unique */
mutex_lock(&sysfs_lock);
- dev = device_create(&gpio_class, chip->dev, MKDEV(0, 0), chip,
- "gpiochip%d", chip->base);
- if (!IS_ERR(dev)) {
- status = sysfs_create_group(&dev->kobj,
- &gpiochip_attr_group);
- } else
+ dev = device_create_with_groups(&gpio_class, chip->dev, MKDEV(0, 0),
+ chip, gpiochip_groups,
+ "gpiochip%d", chip->base);
+ if (IS_ERR(dev))
status = PTR_ERR(dev);
+ else
+ status = 0;
chip->exported = (status == 0);
mutex_unlock(&sysfs_lock);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 15953551d02..fca1d554437 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -4979,7 +4979,7 @@ static bool mutex_is_locked_by(struct mutex *mutex, struct task_struct *task)
if (!mutex_is_locked(mutex))
return false;
-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_MUTEXES)
+#if defined(CONFIG_SMP) && !defined(CONFIG_DEBUG_MUTEXES)
return mutex->owner == task;
#else
/* Since UP may be pre-empted, we cannot assume that we own the lock */
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index a02b5131669..8f1758cec62 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -115,6 +115,8 @@ struct omap_drm_private {
/* properties: */
struct drm_property *rotation_prop;
struct drm_property *zorder_prop;
+ struct drm_property *global_alpha_prop;
+ struct drm_property *pre_mult_alpha_prop;
/* irq handling: */
struct list_head irq_list; /* list of omap_drm_irq */
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c
index 8f8b3041e61..e67873daa9d 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.c
+++ b/drivers/gpu/drm/omapdrm/omap_plane.c
@@ -320,6 +320,11 @@ int omap_plane_dpms(struct drm_plane *plane, int mode)
return ret;
}
+static const struct drm_prop_enum_list pre_mult[] = {
+ { 0, "disable"},
+ { 1, "enable"},
+};
+
/* helper to install properties which are common to planes and crtcs */
void omap_plane_install_properties(struct drm_plane *plane,
struct drm_mode_object *obj)
@@ -356,6 +361,26 @@ void omap_plane_install_properties(struct drm_plane *plane,
priv->zorder_prop = prop;
}
drm_object_attach_property(obj, prop, 0);
+
+ prop = priv->global_alpha_prop;
+ if (!prop) {
+ prop = drm_property_create_range(dev, 0, "global_alpha",
+ 0, 255);
+ if (prop == NULL)
+ return;
+ priv->global_alpha_prop = prop;
+ }
+ drm_object_attach_property(obj, prop, 0);
+
+ prop = priv->pre_mult_alpha_prop;
+ if (!prop) {
+ prop = drm_property_create_enum(dev, 0, "pre_mult_alpha",
+ pre_mult, ARRAY_SIZE(pre_mult));
+ if (prop == NULL)
+ return;
+ priv->pre_mult_alpha_prop = prop;
+ }
+ drm_object_attach_property(obj, prop, 0);
}
int omap_plane_set_property(struct drm_plane *plane,
@@ -373,6 +398,15 @@ int omap_plane_set_property(struct drm_plane *plane,
DBG("%s: zorder: %02x", omap_plane->name, (uint32_t)val);
omap_plane->info.zorder = val;
ret = apply(plane);
+ } else if (property == priv->global_alpha_prop) {
+ DBG("%s: global_alpha: %02x", omap_plane->name, (uint32_t)val);
+ omap_plane->info.global_alpha = val;
+ ret = apply(plane);
+ } else if (property == priv->pre_mult_alpha_prop) {
+ DBG("%s: pre_mult_alpha: %02x", omap_plane->name,
+ (uint32_t)val);
+ omap_plane->info.pre_mult_alpha = val;
+ ret = apply(plane);
}
return ret;
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index 5600d4c5f98..64d6cfba995 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -335,6 +335,20 @@ static struct radeon_asic_ring r300_gfx_ring = {
.set_wptr = &r100_gfx_set_wptr,
};
+static struct radeon_asic_ring rv515_gfx_ring = {
+ .ib_execute = &r100_ring_ib_execute,
+ .emit_fence = &r300_fence_ring_emit,
+ .emit_semaphore = &r100_semaphore_ring_emit,
+ .cs_parse = &r300_cs_parse,
+ .ring_start = &rv515_ring_start,
+ .ring_test = &r100_ring_test,
+ .ib_test = &r100_ib_test,
+ .is_lockup = &r100_gpu_is_lockup,
+ .get_rptr = &r100_gfx_get_rptr,
+ .get_wptr = &r100_gfx_get_wptr,
+ .set_wptr = &r100_gfx_set_wptr,
+};
+
static struct radeon_asic r300_asic = {
.init = &r300_init,
.fini = &r300_fini,
@@ -756,7 +770,7 @@ static struct radeon_asic rv515_asic = {
.set_page = &rv370_pcie_gart_set_page,
},
.ring = {
- [RADEON_RING_TYPE_GFX_INDEX] = &r300_gfx_ring
+ [RADEON_RING_TYPE_GFX_INDEX] = &rv515_gfx_ring
},
.irq = {
.set = &rs600_irq_set,
@@ -823,7 +837,7 @@ static struct radeon_asic r520_asic = {
.set_page = &rv370_pcie_gart_set_page,
},
.ring = {
- [RADEON_RING_TYPE_GFX_INDEX] = &r300_gfx_ring
+ [RADEON_RING_TYPE_GFX_INDEX] = &rv515_gfx_ring
},
.irq = {
.set = &rs600_irq_set,
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
index cfb513f933d..0095ee7fce3 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -1260,8 +1260,39 @@ dpm_failed:
return ret;
}
+struct radeon_dpm_quirk {
+ u32 chip_vendor;
+ u32 chip_device;
+ u32 subsys_vendor;
+ u32 subsys_device;
+};
+
+/* cards with dpm stability problems */
+static struct radeon_dpm_quirk radeon_dpm_quirk_list[] = {
+ /* TURKS - https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1386534 */
+ { PCI_VENDOR_ID_ATI, 0x6759, 0x1682, 0x3195 },
+ /* TURKS - https://bugzilla.kernel.org/show_bug.cgi?id=83731 */
+ { PCI_VENDOR_ID_ATI, 0x6840, 0x1179, 0xfb81 },
+ { 0, 0, 0, 0 },
+};
+
int radeon_pm_init(struct radeon_device *rdev)
{
+ struct radeon_dpm_quirk *p = radeon_dpm_quirk_list;
+ bool disable_dpm = false;
+
+ /* Apply dpm quirks */
+ while (p && p->chip_device != 0) {
+ if (rdev->pdev->vendor == p->chip_vendor &&
+ rdev->pdev->device == p->chip_device &&
+ rdev->pdev->subsystem_vendor == p->subsys_vendor &&
+ rdev->pdev->subsystem_device == p->subsys_device) {
+ disable_dpm = true;
+ break;
+ }
+ ++p;
+ }
+
/* enable dpm on rv6xx+ */
switch (rdev->family) {
case CHIP_RV610:
@@ -1316,6 +1347,8 @@ int radeon_pm_init(struct radeon_device *rdev)
(!(rdev->flags & RADEON_IS_IGP)) &&
(!rdev->smc_fw))
rdev->pm.pm_method = PM_METHOD_PROFILE;
+ else if (disable_dpm && (radeon_dpm == -1))
+ rdev->pm.pm_method = PM_METHOD_PROFILE;
else if (radeon_dpm == 0)
rdev->pm.pm_method = PM_METHOD_PROFILE;
else
diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c
index 879e62844b2..35bf2bba69b 100644
--- a/drivers/gpu/drm/radeon/si_dpm.c
+++ b/drivers/gpu/drm/radeon/si_dpm.c
@@ -2900,6 +2900,22 @@ static int si_init_smc_spll_table(struct radeon_device *rdev)
return ret;
}
+struct si_dpm_quirk {
+ u32 chip_vendor;
+ u32 chip_device;
+ u32 subsys_vendor;
+ u32 subsys_device;
+ u32 max_sclk;
+ u32 max_mclk;
+};
+
+/* cards with dpm stability problems */
+static struct si_dpm_quirk si_dpm_quirk_list[] = {
+ /* PITCAIRN - https://bugs.freedesktop.org/show_bug.cgi?id=76490 */
+ { PCI_VENDOR_ID_ATI, 0x6810, 0x1462, 0x3036, 0, 120000 },
+ { 0, 0, 0, 0 },
+};
+
static void si_apply_state_adjust_rules(struct radeon_device *rdev,
struct radeon_ps *rps)
{
@@ -2910,7 +2926,22 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
u32 mclk, sclk;
u16 vddc, vddci;
u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc;
+ u32 max_sclk = 0, max_mclk = 0;
int i;
+ struct si_dpm_quirk *p = si_dpm_quirk_list;
+
+ /* Apply dpm quirks */
+ while (p && p->chip_device != 0) {
+ if (rdev->pdev->vendor == p->chip_vendor &&
+ rdev->pdev->device == p->chip_device &&
+ rdev->pdev->subsystem_vendor == p->subsys_vendor &&
+ rdev->pdev->subsystem_device == p->subsys_device) {
+ max_sclk = p->max_sclk;
+ max_mclk = p->max_mclk;
+ break;
+ }
+ ++p;
+ }
if ((rdev->pm.dpm.new_active_crtc_count > 1) ||
ni_dpm_vblank_too_short(rdev))
@@ -2964,6 +2995,14 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
if (ps->performance_levels[i].mclk > max_mclk_vddc)
ps->performance_levels[i].mclk = max_mclk_vddc;
}
+ if (max_mclk) {
+ if (ps->performance_levels[i].mclk > max_mclk)
+ ps->performance_levels[i].mclk = max_mclk;
+ }
+ if (max_sclk) {
+ if (ps->performance_levels[i].sclk > max_sclk)
+ ps->performance_levels[i].sclk = max_sclk;
+ }
}
/* XXX validate the min clocks required for display */
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 9188f0495f1..92e43884e73 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -773,20 +773,23 @@ static int evdev_handle_set_keycode_v2(struct input_dev *dev, void __user *p)
*/
static int evdev_handle_get_val(struct evdev_client *client,
struct input_dev *dev, unsigned int type,
- unsigned long *bits, unsigned int max,
- unsigned int size, void __user *p, int compat)
+ unsigned long *bits, unsigned int maxbit,
+ unsigned int maxlen, void __user *p,
+ int compat)
{
int ret;
unsigned long *mem;
+ size_t len;
- mem = kmalloc(sizeof(unsigned long) * max, GFP_KERNEL);
+ len = BITS_TO_LONGS(maxbit) * sizeof(unsigned long);
+ mem = kmalloc(len, GFP_KERNEL);
if (!mem)
return -ENOMEM;
spin_lock_irq(&dev->event_lock);
spin_lock(&client->buffer_lock);
- memcpy(mem, bits, sizeof(unsigned long) * max);
+ memcpy(mem, bits, len);
spin_unlock(&dev->event_lock);
@@ -794,7 +797,7 @@ static int evdev_handle_get_val(struct evdev_client *client,
spin_unlock_irq(&client->buffer_lock);
- ret = bits_to_user(mem, max, size, p, compat);
+ ret = bits_to_user(mem, maxbit, maxlen, p, compat);
if (ret < 0)
evdev_queue_syn_dropped(client);
diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c
index a87d3fab027..d290e839611 100644
--- a/drivers/md/dm-cache-metadata.c
+++ b/drivers/md/dm-cache-metadata.c
@@ -94,6 +94,9 @@ struct cache_disk_superblock {
} __packed;
struct dm_cache_metadata {
+ atomic_t ref_count;
+ struct list_head list;
+
struct block_device *bdev;
struct dm_block_manager *bm;
struct dm_space_map *metadata_sm;
@@ -669,10 +672,10 @@ static void unpack_value(__le64 value_le, dm_oblock_t *block, unsigned *flags)
/*----------------------------------------------------------------*/
-struct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev,
- sector_t data_block_size,
- bool may_format_device,
- size_t policy_hint_size)
+static struct dm_cache_metadata *metadata_open(struct block_device *bdev,
+ sector_t data_block_size,
+ bool may_format_device,
+ size_t policy_hint_size)
{
int r;
struct dm_cache_metadata *cmd;
@@ -683,6 +686,7 @@ struct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev,
return NULL;
}
+ atomic_set(&cmd->ref_count, 1);
init_rwsem(&cmd->root_lock);
cmd->bdev = bdev;
cmd->data_block_size = data_block_size;
@@ -705,10 +709,95 @@ struct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev,
return cmd;
}
+/*
+ * We keep a little list of ref counted metadata objects to prevent two
+ * different target instances creating separate bufio instances. This is
+ * an issue if a table is reloaded before the suspend.
+ */
+static DEFINE_MUTEX(table_lock);
+static LIST_HEAD(table);
+
+static struct dm_cache_metadata *lookup(struct block_device *bdev)
+{
+ struct dm_cache_metadata *cmd;
+
+ list_for_each_entry(cmd, &table, list)
+ if (cmd->bdev == bdev) {
+ atomic_inc(&cmd->ref_count);
+ return cmd;
+ }
+
+ return NULL;
+}
+
+static struct dm_cache_metadata *lookup_or_open(struct block_device *bdev,
+ sector_t data_block_size,
+ bool may_format_device,
+ size_t policy_hint_size)
+{
+ struct dm_cache_metadata *cmd, *cmd2;
+
+ mutex_lock(&table_lock);
+ cmd = lookup(bdev);
+ mutex_unlock(&table_lock);
+
+ if (cmd)
+ return cmd;
+
+ cmd = metadata_open(bdev, data_block_size, may_format_device, policy_hint_size);
+ if (cmd) {
+ mutex_lock(&table_lock);
+ cmd2 = lookup(bdev);
+ if (cmd2) {
+ mutex_unlock(&table_lock);
+ __destroy_persistent_data_objects(cmd);
+ kfree(cmd);
+ return cmd2;
+ }
+ list_add(&cmd->list, &table);
+ mutex_unlock(&table_lock);
+ }
+
+ return cmd;
+}
+
+static bool same_params(struct dm_cache_metadata *cmd, sector_t data_block_size)
+{
+ if (cmd->data_block_size != data_block_size) {
+ DMERR("data_block_size (%llu) different from that in metadata (%llu)\n",
+ (unsigned long long) data_block_size,
+ (unsigned long long) cmd->data_block_size);
+ return false;
+ }
+
+ return true;
+}
+
+struct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev,
+ sector_t data_block_size,
+ bool may_format_device,
+ size_t policy_hint_size)
+{
+ struct dm_cache_metadata *cmd = lookup_or_open(bdev, data_block_size,
+ may_format_device, policy_hint_size);
+ if (cmd && !same_params(cmd, data_block_size)) {
+ dm_cache_metadata_close(cmd);
+ return NULL;
+ }
+
+ return cmd;
+}
+
void dm_cache_metadata_close(struct dm_cache_metadata *cmd)
{
- __destroy_persistent_data_objects(cmd);
- kfree(cmd);
+ if (atomic_dec_and_test(&cmd->ref_count)) {
+ mutex_lock(&table_lock);
+ list_del(&cmd->list);
+ mutex_unlock(&table_lock);
+
+ __destroy_persistent_data_objects(cmd);
+ kfree(cmd);
+ }
}
/*
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c
index ff284b7a17b..c10dec0f6e9 100644
--- a/drivers/md/dm-cache-target.c
+++ b/drivers/md/dm-cache-target.c
@@ -222,7 +222,13 @@ struct cache {
struct list_head need_commit_migrations;
sector_t migration_threshold;
wait_queue_head_t migration_wait;
- atomic_t nr_migrations;
+ atomic_t nr_allocated_migrations;
+
+ /*
+ * The number of in flight migrations that are performing
+ * background io. eg, promotion, writeback.
+ */
+ atomic_t nr_io_migrations;
wait_queue_head_t quiescing_wait;
atomic_t quiescing;
@@ -259,7 +265,6 @@ struct cache {
struct dm_deferred_set *all_io_ds;
mempool_t *migration_pool;
- struct dm_cache_migration *next_migration;
struct dm_cache_policy *policy;
unsigned policy_nr_args;
@@ -350,10 +355,31 @@ static void free_prison_cell(struct cache *cache, struct dm_bio_prison_cell *cel
dm_bio_prison_free_cell(cache->prison, cell);
}
+static struct dm_cache_migration *alloc_migration(struct cache *cache)
+{
+ struct dm_cache_migration *mg;
+
+ mg = mempool_alloc(cache->migration_pool, GFP_NOWAIT);
+ if (mg) {
+ mg->cache = cache;
+ atomic_inc(&mg->cache->nr_allocated_migrations);
+ }
+
+ return mg;
+}
+
+static void free_migration(struct dm_cache_migration *mg)
+{
+ if (atomic_dec_and_test(&mg->cache->nr_allocated_migrations))
+ wake_up(&mg->cache->migration_wait);
+
+ mempool_free(mg, mg->cache->migration_pool);
+}
+
static int prealloc_data_structs(struct cache *cache, struct prealloc *p)
{
if (!p->mg) {
- p->mg = mempool_alloc(cache->migration_pool, GFP_NOWAIT);
+ p->mg = alloc_migration(cache);
if (!p->mg)
return -ENOMEM;
}
@@ -382,7 +408,7 @@ static void prealloc_free_structs(struct cache *cache, struct prealloc *p)
free_prison_cell(cache, p->cell1);
if (p->mg)
- mempool_free(p->mg, cache->migration_pool);
+ free_migration(p->mg);
}
static struct dm_cache_migration *prealloc_get_migration(struct prealloc *p)
@@ -812,24 +838,14 @@ static void remap_to_origin_then_cache(struct cache *cache, struct bio *bio,
* Migration covers moving data from the origin device to the cache, or
* vice versa.
*--------------------------------------------------------------*/
-static void free_migration(struct dm_cache_migration *mg)
-{
- mempool_free(mg, mg->cache->migration_pool);
-}
-
-static void inc_nr_migrations(struct cache *cache)
+static void inc_io_migrations(struct cache *cache)
{
- atomic_inc(&cache->nr_migrations);
+ atomic_inc(&cache->nr_io_migrations);
}
-static void dec_nr_migrations(struct cache *cache)
+static void dec_io_migrations(struct cache *cache)
{
- atomic_dec(&cache->nr_migrations);
-
- /*
- * Wake the worker in case we're suspending the target.
- */
- wake_up(&cache->migration_wait);
+ atomic_dec(&cache->nr_io_migrations);
}
static void __cell_defer(struct cache *cache, struct dm_bio_prison_cell *cell,
@@ -852,11 +868,10 @@ static void cell_defer(struct cache *cache, struct dm_bio_prison_cell *cell,
wake_worker(cache);
}
-static void cleanup_migration(struct dm_cache_migration *mg)
+static void free_io_migration(struct dm_cache_migration *mg)
{
- struct cache *cache = mg->cache;
+ dec_io_migrations(mg->cache);
free_migration(mg);
- dec_nr_migrations(cache);
}
static void migration_failure(struct dm_cache_migration *mg)
@@ -881,7 +896,7 @@ static void migration_failure(struct dm_cache_migration *mg)
cell_defer(cache, mg->new_ocell, true);
}
- cleanup_migration(mg);
+ free_io_migration(mg);
}
static void migration_success_pre_commit(struct dm_cache_migration *mg)
@@ -892,7 +907,7 @@ static void migration_success_pre_commit(struct dm_cache_migration *mg)
if (mg->writeback) {
clear_dirty(cache, mg->old_oblock, mg->cblock);
cell_defer(cache, mg->old_ocell, false);
- cleanup_migration(mg);
+ free_io_migration(mg);
return;
} else if (mg->demote) {
@@ -902,14 +917,14 @@ static void migration_success_pre_commit(struct dm_cache_migration *mg)
mg->old_oblock);
if (mg->promote)
cell_defer(cache, mg->new_ocell, true);
- cleanup_migration(mg);
+ free_io_migration(mg);
return;
}
} else {
if (dm_cache_insert_mapping(cache->cmd, mg->cblock, mg->new_oblock)) {
DMWARN_LIMIT("promotion failed; couldn't update on disk metadata");
policy_remove_mapping(cache->policy, mg->new_oblock);
- cleanup_migration(mg);
+ free_io_migration(mg);
return;
}
}
@@ -942,7 +957,7 @@ static void migration_success_post_commit(struct dm_cache_migration *mg)
} else {
if (mg->invalidate)
policy_remove_mapping(cache->policy, mg->old_oblock);
- cleanup_migration(mg);
+ free_io_migration(mg);
}
} else {
@@ -957,7 +972,7 @@ static void migration_success_post_commit(struct dm_cache_migration *mg)
bio_endio(mg->new_ocell->holder, 0);
cell_defer(cache, mg->new_ocell, false);
}
- cleanup_migration(mg);
+ free_io_migration(mg);
}
}
@@ -1169,7 +1184,7 @@ static void promote(struct cache *cache, struct prealloc *structs,
mg->new_ocell = cell;
mg->start_jiffies = jiffies;
- inc_nr_migrations(cache);
+ inc_io_migrations(cache);
quiesce_migration(mg);
}
@@ -1192,7 +1207,7 @@ static void writeback(struct cache *cache, struct prealloc *structs,
mg->new_ocell = NULL;
mg->start_jiffies = jiffies;
- inc_nr_migrations(cache);
+ inc_io_migrations(cache);
quiesce_migration(mg);
}
@@ -1218,7 +1233,7 @@ static void demote_then_promote(struct cache *cache, struct prealloc *structs,
mg->new_ocell = new_ocell;
mg->start_jiffies = jiffies;
- inc_nr_migrations(cache);
+ inc_io_migrations(cache);
quiesce_migration(mg);
}
@@ -1245,7 +1260,7 @@ static void invalidate(struct cache *cache, struct prealloc *structs,
mg->new_ocell = NULL;
mg->start_jiffies = jiffies;
- inc_nr_migrations(cache);
+ inc_io_migrations(cache);
quiesce_migration(mg);
}
@@ -1306,7 +1321,7 @@ static void process_discard_bio(struct cache *cache, struct bio *bio)
static bool spare_migration_bandwidth(struct cache *cache)
{
- sector_t current_volume = (atomic_read(&cache->nr_migrations) + 1) *
+ sector_t current_volume = (atomic_read(&cache->nr_io_migrations) + 1) *
cache->sectors_per_block;
return current_volume < cache->migration_threshold;
}
@@ -1661,7 +1676,7 @@ static void stop_quiescing(struct cache *cache)
static void wait_for_migrations(struct cache *cache)
{
- wait_event(cache->migration_wait, !atomic_read(&cache->nr_migrations));
+ wait_event(cache->migration_wait, !atomic_read(&cache->nr_allocated_migrations));
}
static void stop_worker(struct cache *cache)
@@ -1772,9 +1787,6 @@ static void destroy(struct cache *cache)
{
unsigned i;
- if (cache->next_migration)
- mempool_free(cache->next_migration, cache->migration_pool);
-
if (cache->migration_pool)
mempool_destroy(cache->migration_pool);
@@ -2282,7 +2294,8 @@ static int cache_create(struct cache_args *ca, struct cache **result)
INIT_LIST_HEAD(&cache->quiesced_migrations);
INIT_LIST_HEAD(&cache->completed_migrations);
INIT_LIST_HEAD(&cache->need_commit_migrations);
- atomic_set(&cache->nr_migrations, 0);
+ atomic_set(&cache->nr_allocated_migrations, 0);
+ atomic_set(&cache->nr_io_migrations, 0);
init_waitqueue_head(&cache->migration_wait);
init_waitqueue_head(&cache->quiescing_wait);
@@ -2342,8 +2355,6 @@ static int cache_create(struct cache_args *ca, struct cache **result)
goto bad;
}
- cache->next_migration = NULL;
-
cache->need_tick_bio = true;
cache->sized = false;
cache->invalidate = false;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 4913c069087..175584ad643 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -2896,7 +2896,8 @@ static int fetch_block(struct stripe_head *sh, struct stripe_head_state *s,
(s->failed >= 2 && fdev[1]->toread) ||
(sh->raid_conf->level <= 5 && s->failed && fdev[0]->towrite &&
!test_bit(R5_OVERWRITE, &fdev[0]->flags)) ||
- (sh->raid_conf->level == 6 && s->failed && s->to_write))) {
+ ((sh->raid_conf->level == 6 || sh->sector >= sh->raid_conf->mddev->recovery_cp)
+ && s->failed && s->to_write))) {
/* we would like to get this block, possibly by computing it,
* otherwise read it if the backing disk is insync
*/
diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c
index cc87a798f8b..e96b556806b 100644
--- a/drivers/media/platform/ti-vpe/vpe.c
+++ b/drivers/media/platform/ti-vpe/vpe.c
@@ -299,6 +299,22 @@ static struct vpe_fmt vpe_formats[] = {
.vpdma_fmt = { &vpdma_rgb_fmts[VPDMA_DATA_FMT_ABGR32],
},
},
+ {
+ .name = "RGB565",
+ .fourcc = V4L2_PIX_FMT_RGB565,
+ .types = VPE_FMT_TYPE_CAPTURE,
+ .coplanar = 0,
+ .vpdma_fmt = { &vpdma_rgb_fmts[VPDMA_DATA_FMT_RGB565],
+ },
+ },
+ {
+ .name = "RGB5551",
+ .fourcc = V4L2_PIX_FMT_RGB555,
+ .types = VPE_FMT_TYPE_CAPTURE,
+ .coplanar = 0,
+ .vpdma_fmt = { &vpdma_rgb_fmts[VPDMA_DATA_FMT_RGBA16_5551],
+ },
+ },
};
/*
@@ -745,9 +761,11 @@ static void set_dst_registers(struct vpe_ctx *ctx)
struct vpe_fmt *fmt = ctx->q_data[Q_DATA_DST].fmt;
u32 val = 0;
- if (clrspc == V4L2_COLORSPACE_SRGB)
+ if (clrspc == V4L2_COLORSPACE_SRGB) {
val |= VPE_RGB_OUT_SELECT;
- else if (fmt->fourcc == V4L2_PIX_FMT_NV16)
+ vpdma_set_bg_color(ctx->dev->vpdma,
+ (struct vpdma_data_format *)fmt->vpdma_fmt[0], 0xff);
+ } else if (fmt->fourcc == V4L2_PIX_FMT_NV16)
val |= VPE_COLOR_SEPARATE_422;
/*
@@ -876,6 +894,7 @@ static int set_srcdst_params(struct vpe_ctx *ctx)
}
free_vbs(ctx);
+ ctx->src_vbs[2] = ctx->src_vbs[1] = ctx->src_vbs[0] = NULL;
ret = realloc_mv_buffers(ctx, mv_buf_size);
if (ret)
@@ -1307,6 +1326,7 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data)
struct v4l2_buffer *s_buf, *d_buf;
unsigned long flags;
u32 irqst0, irqst1;
+ bool list_complete = false;
irqst0 = read_reg(dev, VPE_INT0_STATUS0);
if (irqst0) {
@@ -1342,6 +1362,7 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data)
vpdma_clear_list_stat(ctx->dev->vpdma, 0, 0);
irqst0 &= ~(VPE_INT0_LIST0_COMPLETE);
+ list_complete = true;
}
if (irqst0 | irqst1) {
@@ -1350,6 +1371,11 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data)
irqst0, irqst1);
}
+ /* Setup next operation only when list complete IRQ occurs
+ * otherwise, skip the following code */
+ if (list_complete != true)
+ goto handled;
+
disable_irqs(ctx);
vpdma_unmap_desc_buf(dev->vpdma, &ctx->desc_list.buf);
@@ -1897,6 +1923,8 @@ static int vpe_streamon(struct file *file, void *priv, enum v4l2_buf_type type)
if (ctx->deinterlacing)
config_edi_input_mode(ctx, 0x0);
+ if (ctx->sequence != 0)
+ set_srcdst_params(ctx);
return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
}
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 7e0176321af..881bf89acfc 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2537,7 +2537,7 @@ out:
/*
* We have to delay this as it calls back into the driver.
*/
- if (cardint)
+ if (cardint && host->mmc->sdio_irqs)
mmc_signal_sdio_irq(host->mmc);
return result;
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index cc11f7f5e91..1468c465880 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -664,10 +664,14 @@ static int can_changelink(struct net_device *dev,
if (dev->flags & IFF_UP)
return -EBUSY;
cm = nla_data(data[IFLA_CAN_CTRLMODE]);
- if (cm->flags & ~priv->ctrlmode_supported)
+
+ /* check whether changed bits are allowed to be modified */
+ if (cm->mask & ~priv->ctrlmode_supported)
return -EOPNOTSUPP;
+
+ /* clear bits to be modified and copy the flag values */
priv->ctrlmode &= ~cm->mask;
- priv->ctrlmode |= cm->flags;
+ priv->ctrlmode |= (cm->flags & cm->mask);
}
if (data[IFLA_CAN_RESTART_MS]) {
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index dae70d21676..78c65d327e3 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -3187,7 +3187,8 @@ static int pci_parent_bus_reset(struct pci_dev *dev, int probe)
{
struct pci_dev *pdev;
- if (pci_is_root_bus(dev->bus) || dev->subordinate || !dev->bus->self)
+ if (pci_is_root_bus(dev->bus) || dev->subordinate ||
+ !dev->bus->self || dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET)
return -ENOTTY;
list_for_each_entry(pdev, &dev->bus->devices, bus_list)
@@ -3221,7 +3222,8 @@ static int pci_dev_reset_slot_function(struct pci_dev *dev, int probe)
{
struct pci_dev *pdev;
- if (dev->subordinate || !dev->slot)
+ if (dev->subordinate || !dev->slot ||
+ dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET)
return -ENOTTY;
list_for_each_entry(pdev, &dev->bus->devices, bus_list)
@@ -3452,6 +3454,20 @@ int pci_try_reset_function(struct pci_dev *dev)
}
EXPORT_SYMBOL_GPL(pci_try_reset_function);
+/* Do any devices on or below this bus prevent a bus reset? */
+static bool pci_bus_resetable(struct pci_bus *bus)
+{
+ struct pci_dev *dev;
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ if (dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET ||
+ (dev->subordinate && !pci_bus_resetable(dev->subordinate)))
+ return false;
+ }
+
+ return true;
+}
+
/* Lock devices from the top of the tree down */
static void pci_bus_lock(struct pci_bus *bus)
{
@@ -3502,6 +3518,22 @@ unlock:
return 0;
}
+/* Do any devices on or below this slot prevent a bus reset? */
+static bool pci_slot_resetable(struct pci_slot *slot)
+{
+ struct pci_dev *dev;
+
+ list_for_each_entry(dev, &slot->bus->devices, bus_list) {
+ if (!dev->slot || dev->slot != slot)
+ continue;
+ if (dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET ||
+ (dev->subordinate && !pci_bus_resetable(dev->subordinate)))
+ return false;
+ }
+
+ return true;
+}
+
/* Lock devices from the top of the tree down */
static void pci_slot_lock(struct pci_slot *slot)
{
@@ -3623,7 +3655,7 @@ static int pci_slot_reset(struct pci_slot *slot, int probe)
{
int rc;
- if (!slot)
+ if (!slot || !pci_slot_resetable(slot))
return -ENOTTY;
if (!probe)
@@ -3715,7 +3747,7 @@ EXPORT_SYMBOL_GPL(pci_try_reset_slot);
static int pci_bus_reset(struct pci_bus *bus, int probe)
{
- if (!bus->self)
+ if (!bus->self || !pci_bus_resetable(bus))
return -ENOTTY;
if (probe)
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 6e8776b59a2..27abeb40dfa 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -3008,6 +3008,20 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CHELSIO, 0x0030,
DECLARE_PCI_FIXUP_HEADER(0x1814, 0x0601, /* Ralink RT2800 802.11n PCI */
quirk_broken_intx_masking);
+static void quirk_no_bus_reset(struct pci_dev *dev)
+{
+ dev->dev_flags |= PCI_DEV_FLAGS_NO_BUS_RESET;
+}
+
+/*
+ * Atheros AR93xx chips do not behave after a bus reset. The device will
+ * throw a Link Down error on AER-capable systems and regardless of AER,
+ * config space of the device is never accessible again and typically
+ * causes the system to hang or reset when access is attempted.
+ * http://www.spinics.net/lists/linux-pci/msg34797.html
+ */
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0030, quirk_no_bus_reset);
+
static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
struct pci_fixup *end)
{
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 1e4e69384ba..3dba5d52070 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -117,6 +117,17 @@ config PINCTRL_CAPRI
BCM28145, and BCM28155 SoCs. This driver requires the pinctrl
framework. GPIO is provided by a separate GPIO driver.
+config PINCTRL_TI_IODELAY
+ bool "TI IODelay Module pinconf driver"
+ depends on OF
+ select PINCONF
+ select GENERIC_PINCONF
+ select REGMAP_MMIO
+ help
+ Say Y here to support Texas Instruments' IODelay pinconf driver.
+ IODelay module is used for the DRA7 SoC family. This driver is in
+ addition to PINCTRL_SINGLE which controls the mux.
+
config PINCTRL_IMX
bool
select PINMUX
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 4b835880cf8..c7b52f78f63 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -53,6 +53,7 @@ obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o
obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o
obj-$(CONFIG_PINCTRL_TEGRA114) += pinctrl-tegra114.o
obj-$(CONFIG_PINCTRL_TEGRA124) += pinctrl-tegra124.o
+obj-$(CONFIG_PINCTRL_TI_IODELAY)+= pinctrl-ti-iodelay.o
obj-$(CONFIG_PINCTRL_TZ1090) += pinctrl-tz1090.o
obj-$(CONFIG_PINCTRL_TZ1090_PDC) += pinctrl-tz1090-pdc.o
obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index eb226c18789..f99f7df1cf6 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -1813,14 +1813,15 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev)
if (pctldev == NULL)
return;
- mutex_lock(&pinctrldev_list_mutex);
mutex_lock(&pctldev->mutex);
-
pinctrl_remove_device_debugfs(pctldev);
+ mutex_unlock(&pctldev->mutex);
if (!IS_ERR(pctldev->p))
pinctrl_put(pctldev->p);
+ mutex_lock(&pinctrldev_list_mutex);
+ mutex_lock(&pctldev->mutex);
/* TODO: check that no pinmuxes are still active? */
list_del(&pctldev->node);
/* Destroy descriptor tree */
diff --git a/drivers/pinctrl/pinctrl-ti-iodelay.c b/drivers/pinctrl/pinctrl-ti-iodelay.c
new file mode 100644
index 00000000000..8f713334398
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-ti-iodelay.c
@@ -0,0 +1,962 @@
+/*
+ * Support for configuration of IO Delay module found on Texas Instruments SoCs
+ * such as DRA7
+ *
+ * Copyright (C) 2015 Texas Instruments, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#define IODELAY_REG_NAME_LEN ((sizeof(u32) * 2) + 3)
+#define DRIVER_NAME "ti-io-delay"
+/* Should I change this? Abuse? */
+#define IODELAY_MUX_PINS_NAME "pinctrl-single,pins"
+
+/* Device tree match, populated later */
+static struct of_device_id ti_iodelay_of_match[];
+
+/**
+ * struct ti_iodelay_conf_vals - Description of each configuration parameters.
+ * @offset: Configuration register offset
+ * @a_delay: Agnostic Delay (in ps)
+ * @g_delay: Gnostic Delay (in ps)
+ */
+struct ti_iodelay_conf_vals {
+ u16 offset;
+ u16 a_delay;
+ u16 g_delay;
+};
+
+/**
+ * struct ti_iodelay_reg_data - Describes the registers for the IOdelay instance
+ * @signature_mask: Conf reg- mask for the signature bits
+ * @signature_value: Conf reg- signature value to be written (see TRM)
+ * @lock_mask: Conf reg- mask for the lock bits
+ * @lock_val: Conf reg- lock value for the lock bits (see TRM)
+ * @unlock_val: Conf reg- unlock value for the lock bits (see TRM)
+ * @binary_data_coarse_mask: Conf reg- coarse mask (see TRM)
+ * @binary_data_fine_mask: Conf reg- fine mask (see TRM)
+ * @reg_refclk_offset: Refclk register offset
+ * @refclk_period_mask: Refclk mask
+ * @reg_coarse_offset: Coarse register configuration offset
+ * @coarse_delay_count_mask: Coarse delay count mask
+ * @coarse_ref_count_mask: Coarse ref count mask
+ * @reg_fine_offset: Fine register configuration offset
+ * @fine_delay_count_mask: Fine delay count mask
+ * @fine_ref_count_mask: Fine ref count mask
+ * @reg_global_lock_offset: Global(for the IOdelay module) lock register offset
+ * @global_lock_mask: Lock mask
+ * @global_unlock_val: unlock value
+ * @global_lock_val: lock value
+ * @reg_start_offset: Where does the configuration registers start?
+ * @regmap_config: Regmap configuration for the IODelay region
+ */
+struct ti_iodelay_reg_data {
+ u32 signature_mask;
+ u32 signature_value;
+ u32 lock_mask;
+ u32 lock_val;
+ u32 unlock_val;
+ u32 binary_data_coarse_mask;
+ u32 binary_data_fine_mask;
+
+ u32 reg_refclk_offset;
+ u32 refclk_period_mask;
+
+ u32 reg_coarse_offset;
+ u32 coarse_delay_count_mask;
+ u32 coarse_ref_count_mask;
+
+ u32 reg_fine_offset;
+ u32 fine_delay_count_mask;
+ u32 fine_ref_count_mask;
+
+ u32 reg_global_lock_offset;
+ u32 global_lock_mask;
+ u32 global_unlock_val;
+ u32 global_lock_val;
+
+ u32 reg_start_offset;
+
+ struct regmap_config *regmap_config;
+};
+
+/**
+ * struct ti_iodelay_reg_values - Computed io_reg configuration values (see TRM)
+ * @coarse_ref_count: Coarse reference count
+ * @coarse_delay_count: Coarse delay count
+ * @fine_ref_count: Fine reference count
+ * @fine_delay_count: Fine Delay count
+ * @ref_clk_period: Reference Clock period
+ * @cdpe: Coarse delay parameter
+ * @fdpe: Fine delay parameter
+ */
+struct ti_iodelay_reg_values {
+ u16 coarse_ref_count;
+ u16 coarse_delay_count;
+
+ u16 fine_ref_count;
+ u16 fine_delay_count;
+
+ u16 ref_clk_period;
+
+ u32 cdpe;
+ u32 fdpe;
+};
+
+/**
+ * struct ti_iodelay_pin_name - name of the pins
+ * @name: name
+ */
+struct ti_iodelay_pin_name {
+ char name[IODELAY_REG_NAME_LEN];
+};
+
+/**
+ * struct ti_iodelay_pingroup - Structure that describes one group
+ * @np: Node pointer (device tree)
+ * @name: Name of the group
+ * @map: pinctrl map allocated for the group
+ * @vals: configuration values allocated for the group (from dt)
+ * @nvals: number of configuration values allocated
+ * @config: pinconf "Config" - currently a dummy value
+ * @node: list node to next group
+ */
+struct ti_iodelay_pingroup {
+ struct device_node *np;
+ const char *name;
+ struct pinctrl_map *map;
+ struct ti_iodelay_conf_vals *vals;
+ int nvals;
+ unsigned long config;
+ struct list_head node;
+};
+
+/**
+ * struct ti_iodelay_device - Represents information for a IOdelay instance
+ * @dev: device pointer
+ * @reg_base: Remapped virtual address
+ * @regmap: Regmap for this IOdelay instance
+ * @pctl: Pinctrl device
+ * @desc: pinctrl descriptor for pctl
+ * @pa: pinctrl pin wise description
+ * @names: names of the pins
+ * @groups: list of pinconf groups for iodelay instance
+ * @ngroups: number of groups in the list
+ * @mutex: mutex to protect group list modification
+ * @reg_data: Register definition data for the IODelay instance
+ * @reg_init_conf_values: Initial configuration values.
+ */
+struct ti_iodelay_device {
+ struct device *dev;
+ void __iomem *reg_base;
+ struct regmap *regmap;
+
+ struct pinctrl_dev *pctl;
+ struct pinctrl_desc desc;
+ struct pinctrl_pin_desc *pa;
+ struct ti_iodelay_pin_name *names;
+
+ struct list_head groups;
+ int ngroups;
+ struct mutex mutex; /* list protection */
+
+ const struct ti_iodelay_reg_data *reg_data;
+ struct ti_iodelay_reg_values reg_init_conf_values;
+};
+
+/*--- IOdelay configuration stuff ----*/
+
+/**
+ * ti_iodelay_extract() - extract bits for a field
+ * @val: register value
+ * @mask: Mask
+ *
+ * Return: extracted value which is appropriately shifted
+ */
+static inline u32 ti_iodelay_extract(u32 val, u32 mask)
+{
+ return (val & mask) >> __ffs(mask);
+}
+
+/**
+ * ti_iodelay_compute_dpe() - Compute equation for delay paramter
+ * @period: Period to use
+ * @ref: Reference Count
+ * @delay: Delay count
+ * @delay_m: Delay multiplier
+ *
+ * Return: Computed delay parameter
+ */
+static inline u32 ti_iodelay_compute_dpe(u16 period, u16 ref, u16 delay,
+ u16 delay_m)
+{
+ u64 m, d;
+
+ /* Handle overflow conditions */
+ m = 10 * (u64)period * (u64)ref;
+ d = 2 * (u64)delay * (u64)delay_m;
+
+ /* Truncate result back to 32 bits */
+ return div64_u64(m, d);
+}
+
+/**
+ * ti_iodelay_pinconf_set() - Configure the pin configuration
+ * @iod: IODelay device
+ * @val: Configuration value
+ *
+ * Update the configuration register as per TRM and lockup once done.
+ * *IMPORTANT NOTE* SoC TRM does recommend doing iodelay programmation only
+ * while in Isolation. But, then, isolation also implies that every pin
+ * on the SoC(including DDR) will be isolated out. The only benefit being
+ * a glitchless configuration, However, the intent of this driver is purely
+ * to support a "glitchy" configuration where applicable.
+ *
+ * Return: 0 in case of success, else appropriate error value
+ */
+static int ti_iodelay_pinconf_set(struct ti_iodelay_device *iod,
+ struct ti_iodelay_conf_vals *val)
+{
+ const struct ti_iodelay_reg_data *reg = iod->reg_data;
+ struct ti_iodelay_reg_values *ival = &iod->reg_init_conf_values;
+ struct device *dev = iod->dev;
+ u32 g_delay_coarse, g_delay_fine;
+ u32 a_delay_coarse, a_delay_fine;
+ u32 c_elements, f_elements;
+ u32 total_delay;
+ u32 reg_mask, reg_val, tmp_val;
+ int r;
+
+ /* NOTE: Truncation is expected in all division below */
+ g_delay_coarse = val->g_delay / 920;
+ g_delay_fine = ((val->g_delay % 920) * 10) / 60;
+
+ a_delay_coarse = val->a_delay / ival->cdpe;
+ a_delay_fine = ((val->a_delay % ival->cdpe) * 10) / ival->fdpe;
+
+ c_elements = g_delay_coarse + a_delay_coarse;
+ f_elements = (g_delay_fine + a_delay_fine) / 10;
+
+ if (f_elements > 22) {
+ total_delay = c_elements * ival->cdpe + f_elements * ival->fdpe;
+ c_elements = total_delay / ival->cdpe;
+ f_elements = (total_delay % ival->cdpe) / ival->fdpe;
+ }
+
+ reg_mask = reg->signature_mask;
+ reg_val = reg->signature_value << __ffs(reg->signature_mask);
+
+ reg_mask |= reg->binary_data_coarse_mask;
+ tmp_val = c_elements << __ffs(reg->binary_data_coarse_mask);
+ if (tmp_val & ~reg->binary_data_coarse_mask) {
+ dev_err(dev, "Masking overflow of coarse elements %08x\n",
+ tmp_val);
+ tmp_val &= reg->binary_data_coarse_mask;
+ }
+ reg_val |= tmp_val;
+
+ reg_mask |= reg->binary_data_fine_mask;
+ tmp_val = f_elements << __ffs(reg->binary_data_fine_mask);
+ if (tmp_val & ~reg->binary_data_fine_mask) {
+ dev_err(dev, "Masking overflow of fine elements %08x\n",
+ tmp_val);
+ tmp_val &= reg->binary_data_fine_mask;
+ }
+ reg_val |= tmp_val;
+
+ /* Write with lock value - we DONOT want h/w updates */
+ reg_mask |= reg->lock_mask;
+ reg_val |= reg->lock_val << __ffs(reg->lock_mask);
+ r = regmap_update_bits(iod->regmap, val->offset, reg_mask, reg_val);
+
+ dev_dbg(dev, "Set reg 0x%x Delay(a=%d g=%d), Elements(C=%d F=%d)0x%x\n",
+ val->offset, val->a_delay, val->g_delay, c_elements,
+ f_elements, reg_val);
+
+ return r;
+}
+
+/**
+ * ti_iodelay_pinconf_init_dev() - Initialize IODelay device
+ * @iod: IODelay device
+ *
+ * Unlocks the IODelay region, computes the common parameters
+ *
+ * Return: 0 in case of success, else appropriate error value
+ */
+static int ti_iodelay_pinconf_init_dev(struct ti_iodelay_device *iod)
+{
+ const struct ti_iodelay_reg_data *reg = iod->reg_data;
+ struct device *dev = iod->dev;
+ struct ti_iodelay_reg_values *ival = &iod->reg_init_conf_values;
+ u32 val;
+ int r;
+
+ /* unlock the IOdelay region */
+ r = regmap_update_bits(iod->regmap, reg->reg_global_lock_offset,
+ reg->global_lock_mask, reg->global_unlock_val);
+ if (r)
+ return r;
+
+ /* Read up Recalibration sequence done by bootloader */
+ r = regmap_read(iod->regmap, reg->reg_refclk_offset, &val);
+ if (r)
+ return r;
+ ival->ref_clk_period = ti_iodelay_extract(val, reg->refclk_period_mask);
+ dev_dbg(dev, "refclk_period=0x%04x\n", ival->ref_clk_period);
+
+ r = regmap_read(iod->regmap, reg->reg_coarse_offset, &val);
+ if (r)
+ return r;
+ ival->coarse_ref_count =
+ ti_iodelay_extract(val, reg->coarse_ref_count_mask);
+ ival->coarse_delay_count =
+ ti_iodelay_extract(val, reg->coarse_delay_count_mask);
+ if (!ival->coarse_delay_count) {
+ dev_err(dev, "Invalid Coarse delay count (0) (reg=0x%08x)\n",
+ val);
+ return -EINVAL;
+ }
+ ival->cdpe = ti_iodelay_compute_dpe(ival->ref_clk_period,
+ ival->coarse_ref_count,
+ ival->coarse_delay_count, 88);
+ if (!ival->cdpe) {
+ dev_err(dev, "Invalid cdpe computed params = %d %d %d\n",
+ ival->ref_clk_period, ival->coarse_ref_count,
+ ival->coarse_delay_count);
+ return -EINVAL;
+ }
+ dev_dbg(iod->dev, "coarse: ref=0x%04x delay=0x%04x cdpe=0x%08x\n",
+ ival->coarse_ref_count, ival->coarse_delay_count, ival->cdpe);
+
+ r = regmap_read(iod->regmap, reg->reg_fine_offset, &val);
+ if (r)
+ return r;
+ ival->fine_ref_count =
+ ti_iodelay_extract(val, reg->fine_ref_count_mask);
+ ival->fine_delay_count =
+ ti_iodelay_extract(val, reg->fine_delay_count_mask);
+ if (!ival->fine_delay_count) {
+ dev_err(dev, "Invalid Fine delay count (0) (reg=0x%08x)\n",
+ val);
+ return -EINVAL;
+ }
+ ival->fdpe = ti_iodelay_compute_dpe(ival->ref_clk_period,
+ ival->fine_ref_count,
+ ival->fine_delay_count, 264);
+ if (!ival->fdpe) {
+ dev_err(dev, "Invalid fdpe(0) computed params = %d %d %d\n",
+ ival->ref_clk_period, ival->fine_ref_count,
+ ival->fine_delay_count);
+ return -EINVAL;
+ }
+ dev_dbg(iod->dev, "fine: ref=0x%04x delay=0x%04x fdpe=0x%08x\n",
+ ival->fine_ref_count, ival->fine_delay_count, ival->fdpe);
+
+ return 0;
+}
+
+/**
+ * ti_iodelay_pinconf_deinit_dev() - deinit the IOdelay device
+ * @iod: IODelay device
+ *
+ * Deinitialize the IODelay device (basically just lock the region back up.
+ */
+static void ti_iodelay_pinconf_deinit_dev(struct ti_iodelay_device *iod)
+{
+ const struct ti_iodelay_reg_data *reg = iod->reg_data;
+
+ /* lock the IOdelay region back again */
+ regmap_update_bits(iod->regmap, reg->reg_global_lock_offset,
+ reg->global_lock_mask, reg->global_lock_val);
+}
+
+/*--- Pinctrl/pinconf framework stuff ----*/
+
+/**
+ * ti_iodelay_get_group() - Find the group mapped by a group selector
+ * @iod: IODelay device
+ * @gselector: Group Selector
+ *
+ * Return: Corresponding group representing group selector in list of groups
+ * managed in IOdelay device OR NULL if not found.
+ */
+static struct ti_iodelay_pingroup *ti_iodelay_get_group(struct ti_iodelay_device
+ *iod,
+ unsigned gselector)
+{
+ struct ti_iodelay_pingroup *group;
+ int gid = 0;
+
+ list_for_each_entry(group, &iod->groups, node) {
+ if (gid == gselector)
+ return group;
+ gid++;
+ }
+
+ dev_err(iod->dev, "%s could not find pingroup %i\n", __func__,
+ gselector);
+ return NULL;
+}
+
+/**
+ * ti_iodelay_dt_node_to_map() - Map a device tree node to appropriate group
+ * @pctldev: pinctrl device representing IODelay device
+ * @np: Node Pointer (device tree)
+ * @map: Pinctrl Map returned back to pinctrl framework
+ * @num_maps: Number of maps (1)
+ *
+ * Maps the device tree description into a group of configuration paramters
+ * for IOdelay block entry.
+ *
+ * Return: 0 in case of success, else appropriate error value
+ */
+static int ti_iodelay_dt_node_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np,
+ struct pinctrl_map **map,
+ unsigned *num_maps)
+{
+ struct ti_iodelay_device *iod;
+ struct device *dev;
+ /* const char **pgnames; */
+ int ret = 0;
+ const __be32 *mux;
+ struct ti_iodelay_conf_vals *vals;
+ struct ti_iodelay_pingroup *group;
+ int size, index, idx, rows;
+ u32 offset, val;
+
+ iod = pinctrl_dev_get_drvdata(pctldev);
+ if (!iod)
+ return -EINVAL;
+ dev = iod->dev;
+
+ *map = devm_kzalloc(dev, sizeof(**map), GFP_KERNEL);
+ if (!*map)
+ return -ENOMEM;
+ *num_maps = 0;
+
+ group = devm_kzalloc(dev, sizeof(*group), GFP_KERNEL);
+ if (!group) {
+ ret = -ENOMEM;
+ goto free_map;
+ }
+
+ mux = of_get_property(np, IODELAY_MUX_PINS_NAME, &size);
+ if ((!mux) || (size < sizeof(*mux) * 2)) {
+ dev_err(dev, "bad data for mux %s\n", np->name);
+ ret = -EINVAL;
+ goto free_group;
+ }
+
+ size /= sizeof(*mux); /* Number of elements in array */
+ rows = size / 2;
+
+ vals = devm_kzalloc(dev, sizeof(*vals) * rows, GFP_KERNEL);
+ if (!vals) {
+ ret = -ENOMEM;
+ goto free_group;
+ }
+
+ index = 0;
+ idx = 0;
+ while (index < size) {
+ offset = be32_to_cpup(mux + index++);
+ val = be32_to_cpup(mux + index++);
+ vals[idx].offset = offset;
+ vals[idx].a_delay = val & 0xFFFF;
+ vals[idx].g_delay = (val & 0xFFFF0000) >> 16;
+ if (offset > iod->reg_data->regmap_config->max_register) {
+ dev_err(dev, "Invalid offset for %s 0x%x\n",
+ np->name, offset);
+ break;
+ }
+ dev_dbg(dev, "%s offset=%x a_delay = %d g_delay = %d\n",
+ np->name, vals[idx].offset, vals[idx].a_delay,
+ vals[idx].g_delay);
+ idx++;
+ }
+
+ group->name = np->name;
+ group->np = np;
+ group->vals = vals;
+ group->nvals = idx;
+ group->config = PIN_CONFIG_END;
+ group->map = *map;
+
+ /* Add to group list */
+ mutex_lock(&iod->mutex);
+ list_add_tail(&group->node, &iod->groups);
+ iod->ngroups++;
+ mutex_unlock(&iod->mutex);
+
+ (*map)->type = PIN_MAP_TYPE_CONFIGS_GROUP;
+ (*map)->data.configs.group_or_pin = np->name;
+ (*map)->data.configs.configs = &group->config;
+ (*map)->data.configs.num_configs = 1;
+ *num_maps = 1;
+
+ return 0;
+
+free_group:
+ devm_kfree(dev, group);
+free_map:
+ devm_kfree(dev, *map);
+ return ret;
+}
+
+/**
+ * ti_iodelay_dt_free_map() - Free map and resource alloted as per the map
+ * @pctldev: pinctrl device representing IODelay device
+ * @map: Map allocated by ti_iodelay_dt_node_to_map
+ * @num_maps: Num maps (1)
+ *
+ * Removes the group associated with the map and frees all resources allocated
+ * for the group.
+ */
+static void ti_iodelay_dt_free_map(struct pinctrl_dev *pctldev,
+ struct pinctrl_map *map, unsigned num_maps)
+{
+ struct ti_iodelay_device *iod;
+ struct device *dev;
+ struct ti_iodelay_pingroup *group;
+ bool found = false;
+
+ if (!map)
+ return;
+
+ iod = pinctrl_dev_get_drvdata(pctldev);
+ if (!iod)
+ return;
+ dev = iod->dev;
+
+ mutex_lock(&iod->mutex);
+ list_for_each_entry(group, &iod->groups, node) {
+ if (group->map == map) {
+ found = true;
+ list_del(&group->node);
+ iod->ngroups--;
+ break;
+ }
+ }
+ mutex_unlock(&iod->mutex);
+
+ /* If some freaky pinconf framework bug... */
+ if (!found)
+ return;
+
+ devm_kfree(dev, group->vals);
+ devm_kfree(dev, group);
+ devm_kfree(dev, map);
+}
+
+/**
+ * ti_iodelay_pinctrl_get_groups_count() - Get number of groups registered
+ * @pctldev: pinctrl device representing IODelay device
+ *
+ * Return: number of groups mapped on the IODelay
+ */
+static int ti_iodelay_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+ struct ti_iodelay_device *iod;
+ struct device *dev;
+
+ iod = pinctrl_dev_get_drvdata(pctldev);
+ dev = iod->dev;
+
+ return iod->ngroups;
+}
+
+/**
+ * ti_iodelay_pinctrl_get_group_name() - Get the group name
+ * @pctldev: pinctrl device representing IODelay device
+ * @gselector: group selector
+ *
+ * Return: name of the Group given a valid gselector, else NULL.
+ */
+static const char *ti_iodelay_pinctrl_get_group_name(struct pinctrl_dev
+ *pctldev,
+ unsigned gselector)
+{
+ struct ti_iodelay_device *iod;
+ struct device *dev;
+ struct ti_iodelay_pingroup *group;
+
+ iod = pinctrl_dev_get_drvdata(pctldev);
+ dev = iod->dev;
+
+ group = ti_iodelay_get_group(iod, gselector);
+ if (!group)
+ return NULL;
+
+ return group->name;
+}
+
+/**
+ * ti_iodelay_pinctrl_get_group_pins() - get group pins
+ * @pctldev: pinctrl device representing IODelay device
+ * @gselector: Group selector
+ * @pins: pointer to the pins
+ * @npins: number of pins
+ *
+ * Dummy implementation since we do not track pins, we track configurations
+ * Forced by pinctrl's pinctrl_check_ops()
+ *
+ * Return: -EINVAL
+ */
+static int ti_iodelay_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned gselector,
+ const unsigned **pins,
+ unsigned *npins)
+{
+ /* Dummy implementation - we dont do pin mux */
+ return -EINVAL;
+}
+
+/**
+ * ti_iodelay_pinconf_group_get() - Get the group configuration
+ * @pctldev: pinctrl device representing IODelay device
+ * @gselector: Group selector
+ * @config: configuration returned
+ *
+ * Return: The configuration if the group is valid, else returns -EINVAL
+ */
+static int ti_iodelay_pinconf_group_get(struct pinctrl_dev *pctldev,
+ unsigned gselector,
+ unsigned long *config)
+{
+ struct ti_iodelay_device *iod;
+ struct device *dev;
+ struct ti_iodelay_pingroup *group;
+
+ iod = pinctrl_dev_get_drvdata(pctldev);
+ dev = iod->dev;
+ group = ti_iodelay_get_group(iod, gselector);
+
+ if (!group)
+ return -EINVAL;
+
+ *config = group->config;
+ return 0;
+}
+
+/**
+ * ti_iodelay_pinconf_group_set() - Configure the groups of pins
+ * @pctldev: pinctrl device representing IODelay device
+ * @gselector: Group selector
+ * @configs: Configurations
+ * @num_configs: Number of configurations
+ *
+ * Return: 0 if all went fine, else appropriate error value.
+ */
+static int ti_iodelay_pinconf_group_set(struct pinctrl_dev *pctldev,
+ unsigned gselector,
+ unsigned long *configs,
+ unsigned num_configs)
+{
+ struct ti_iodelay_device *iod;
+ struct device *dev;
+ struct ti_iodelay_pingroup *group;
+ int i;
+
+ iod = pinctrl_dev_get_drvdata(pctldev);
+ dev = iod->dev;
+ group = ti_iodelay_get_group(iod, gselector);
+
+ if (num_configs != 1) {
+ dev_err(dev, "Unsupported number of configurations %d\n",
+ num_configs);
+ return -EINVAL;
+ }
+
+ if (*configs != PIN_CONFIG_END) {
+ dev_err(dev, "Unsupported configuration\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < group->nvals; i++) {
+ if (ti_iodelay_pinconf_set(iod, &group->vals[i]))
+ return -ENOTSUPP;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+/**
+ * ti_iodelay_pinconf_group_dbg_show() - show the group information
+ * @pctldev: Show the group information
+ * @s: Sequence file
+ * @gselector: group selector
+ *
+ * Provide the configuration information of the selected group
+ */
+static void ti_iodelay_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s,
+ unsigned gselector)
+{
+ struct ti_iodelay_device *iod;
+ struct device *dev;
+ struct ti_iodelay_pingroup *group;
+ int i;
+
+ iod = pinctrl_dev_get_drvdata(pctldev);
+ dev = iod->dev;
+ group = ti_iodelay_get_group(iod, gselector);
+ if (!group)
+ return;
+
+ for (i = 0; i < group->nvals; i++) {
+ struct ti_iodelay_conf_vals *val;
+ u32 reg = 0;
+ val = &group->vals[i];
+ regmap_read(iod->regmap, val->offset, &reg),
+ seq_printf(s, "\n\t0x%08x = 0x%08x (%3d, %3d)",
+ val->offset, reg, val->a_delay, val->g_delay);
+ }
+}
+#endif
+
+static struct pinctrl_ops ti_iodelay_pinctrl_ops = {
+ .dt_node_to_map = ti_iodelay_dt_node_to_map,
+ .dt_free_map = ti_iodelay_dt_free_map,
+ .get_groups_count = ti_iodelay_pinctrl_get_groups_count,
+ .get_group_name = ti_iodelay_pinctrl_get_group_name,
+ .get_group_pins = ti_iodelay_pinctrl_get_group_pins,
+};
+
+static struct pinconf_ops ti_iodelay_pinctrl_pinconf_ops = {
+ .pin_config_group_get = ti_iodelay_pinconf_group_get,
+ .pin_config_group_set = ti_iodelay_pinconf_group_set,
+#ifdef CONFIG_DEBUG_FS
+ .pin_config_group_dbg_show = ti_iodelay_pinconf_group_dbg_show,
+#endif
+};
+
+/**
+ * ti_iodelay_alloc_pins() - Allocate structures needed for pins for IOdelay
+ * @dev: device pointer
+ * @iod: IODelay device
+ * @base_phy: Base Physical Address
+ *
+ * Return: 0 if all went fine, else appropriate error value.
+ */
+static int ti_iodelay_alloc_pins(struct device *dev,
+ struct ti_iodelay_device *iod, u32 base_phy)
+{
+ const struct ti_iodelay_reg_data *r = iod->reg_data;
+ struct pinctrl_pin_desc *pin;
+ struct ti_iodelay_pin_name *pn;
+ u32 phy_reg;
+ int nr_pins, i;
+
+ nr_pins = (r->regmap_config->max_register - r->reg_start_offset) / 4;
+
+ dev_dbg(dev, "Allocating %i pins\n", nr_pins);
+
+ iod->pa = devm_kzalloc(dev, sizeof(*iod->pa) * nr_pins, GFP_KERNEL);
+ if (!iod->pa)
+ return -ENOMEM;
+
+ iod->names =
+ devm_kzalloc(dev, sizeof(struct ti_iodelay_pin_name) * nr_pins,
+ GFP_KERNEL);
+ if (!iod->names)
+ return -ENOMEM;
+
+ iod->desc.pins = iod->pa;
+ iod->desc.npins = nr_pins;
+
+ phy_reg = r->reg_start_offset + base_phy;
+ pn = iod->names;
+ for (i = 0; i < nr_pins; i++, pn++, phy_reg += 4) {
+ pin = &iod->pa[i];
+ sprintf(pn->name, "%x.%d", phy_reg, i);
+ pin->number = i;
+ pin->name = pn->name;
+ }
+
+ return 0;
+}
+
+/**
+ * ti_iodelay_probe() - Standard probe
+ * @pdev: platform device
+ *
+ * Return: 0 if all went fine, else appropriate error value.
+ */
+static int ti_iodelay_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = of_node_get(dev->of_node);
+ const struct of_device_id *match;
+ struct resource *res;
+ struct ti_iodelay_device *iod;
+ int ret = 0;
+
+ if (!np) {
+ ret = -EINVAL;
+ dev_err(dev, "No OF node\n");
+ goto exit_out;
+ }
+
+ match = of_match_device(ti_iodelay_of_match, dev);
+ if (!match) {
+ ret = -EINVAL;
+ dev_err(dev, "No DATA match\n");
+ goto exit_out;
+ }
+
+ iod = devm_kzalloc(dev, sizeof(*iod), GFP_KERNEL);
+ if (!iod) {
+ ret = -ENOMEM;
+ goto exit_out;
+ }
+ iod->dev = dev;
+ iod->reg_data = match->data;
+
+ /* So far We can assume there is only 1 bank of registers */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(dev, "Missing MEM resource\n");
+ ret = -ENODEV;
+ goto exit_out;
+ }
+
+ iod->reg_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(iod->reg_base)) {
+ ret = PTR_ERR(iod->reg_base);
+ goto exit_out;
+ }
+
+ iod->regmap = devm_regmap_init_mmio(dev, iod->reg_base,
+ iod->reg_data->regmap_config);
+ if (IS_ERR(iod->regmap)) {
+ dev_err(dev, "Regmap MMIO init failed.\n");
+ ret = PTR_ERR(iod->regmap);
+ goto exit_out;
+ }
+
+ if (ti_iodelay_pinconf_init_dev(iod))
+ goto exit_out;
+
+ ret = ti_iodelay_alloc_pins(dev, iod, res->start);
+ if (ret)
+ goto exit_out;
+
+ INIT_LIST_HEAD(&iod->groups);
+ mutex_init(&iod->mutex);
+
+ iod->desc.pctlops = &ti_iodelay_pinctrl_ops;
+ /* no pinmux ops - we are pinconf */
+ iod->desc.confops = &ti_iodelay_pinctrl_pinconf_ops;
+ iod->desc.name = dev_name(dev);
+ iod->desc.owner = THIS_MODULE;
+
+ iod->pctl = pinctrl_register(&iod->desc, dev, iod);
+ if (!iod->pctl) {
+ dev_err(dev, "Failed to register pinctrl\n");
+ ret = -ENODEV;
+ goto exit_out;
+ }
+
+ platform_set_drvdata(pdev, iod);
+
+exit_out:
+ of_node_put(np);
+ return ret;
+}
+
+/**
+ * ti_iodelay_remove() - standard remove
+ * @pdev: platform device
+ *
+ * Return: 0 if all went fine, else appropriate error value.
+ */
+static int ti_iodelay_remove(struct platform_device *pdev)
+{
+ struct ti_iodelay_device *iod = platform_get_drvdata(pdev);
+
+ if (!iod)
+ return 0;
+ if (iod->pctl)
+ pinctrl_unregister(iod->pctl);
+
+ ti_iodelay_pinconf_deinit_dev(iod);
+
+ /* Expect other allocations to be freed by devm */
+
+ return 0;
+}
+
+static struct regmap_config dra7_iodelay_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0xD1C,
+};
+
+static struct ti_iodelay_reg_data dra7_iodelay_data = {
+ .signature_mask = 0x0003F000,
+ .signature_value = 0x29,
+ .lock_mask = 0x00000400,
+ .lock_val = 1,
+ .unlock_val = 0,
+ .binary_data_coarse_mask = 0x000003E0,
+ .binary_data_fine_mask = 0x0000001F,
+
+ .reg_refclk_offset = 0x14,
+ .refclk_period_mask = 0xFFFF,
+
+ .reg_coarse_offset = 0x18,
+ .coarse_delay_count_mask = 0xFFFF0000,
+ .coarse_ref_count_mask = 0x0000FFFF,
+
+ .reg_fine_offset = 0x1C,
+ .fine_delay_count_mask = 0xFFFF0000,
+ .fine_ref_count_mask = 0x0000FFFF,
+
+ .reg_global_lock_offset = 0x2C,
+ .global_lock_mask = 0x0000FFFF,
+ .global_unlock_val = 0x0000AAAA,
+ .global_lock_val = 0x0000AAAB,
+
+ .reg_start_offset = 0x30,
+ .regmap_config = &dra7_iodelay_regmap_config,
+};
+
+static struct of_device_id ti_iodelay_of_match[] = {
+ {.compatible = "ti,dra7-iodelay", .data = &dra7_iodelay_data},
+ { /* Hopefully no more.. */ },
+};
+MODULE_DEVICE_TABLE(of, ti_iodelay_of_match);
+
+static struct platform_driver ti_iodelay_driver = {
+ .probe = ti_iodelay_probe,
+ .remove = ti_iodelay_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRIVER_NAME,
+ .of_match_table = ti_iodelay_of_match,
+ },
+};
+module_platform_driver(ti_iodelay_driver);
+
+MODULE_AUTHOR("Texas Instruments, Inc.");
+MODULE_DESCRIPTION("Pinconf driver for TI's IO Delay module");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index ab3baa7f950..86ade85481b 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -44,6 +44,7 @@
#include <linux/hrtimer.h>
#include <linux/ktime.h>
#include <asm/facility.h>
+#include <linux/crypto.h>
#include "ap_bus.h"
@@ -71,7 +72,7 @@ MODULE_AUTHOR("IBM Corporation");
MODULE_DESCRIPTION("Adjunct Processor Bus driver, " \
"Copyright IBM Corp. 2006, 2012");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("z90crypt");
+MODULE_ALIAS_CRYPTO("z90crypt");
/*
* Module parameter
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 3f5b56a9989..b4ddb7310e3 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -683,6 +683,7 @@ static void ipr_init_ipr_cmnd(struct ipr_cmnd *ipr_cmd,
ipr_reinit_ipr_cmnd(ipr_cmd);
ipr_cmd->u.scratch = 0;
ipr_cmd->sibling = NULL;
+ ipr_cmd->eh_comp = NULL;
ipr_cmd->fast_done = fast_done;
init_timer(&ipr_cmd->timer);
}
@@ -848,6 +849,8 @@ static void ipr_scsi_eh_done(struct ipr_cmnd *ipr_cmd)
scsi_dma_unmap(ipr_cmd->scsi_cmd);
scsi_cmd->scsi_done(scsi_cmd);
+ if (ipr_cmd->eh_comp)
+ complete(ipr_cmd->eh_comp);
list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
}
@@ -4805,6 +4808,84 @@ static int ipr_slave_alloc(struct scsi_device *sdev)
return rc;
}
+/**
+ * ipr_match_lun - Match function for specified LUN
+ * @ipr_cmd: ipr command struct
+ * @device: device to match (sdev)
+ *
+ * Returns:
+ * 1 if command matches sdev / 0 if command does not match sdev
+ **/
+static int ipr_match_lun(struct ipr_cmnd *ipr_cmd, void *device)
+{
+ if (ipr_cmd->scsi_cmd && ipr_cmd->scsi_cmd->device == device)
+ return 1;
+ return 0;
+}
+
+/**
+ * ipr_wait_for_ops - Wait for matching commands to complete
+ * @ipr_cmd: ipr command struct
+ * @device: device to match (sdev)
+ * @match: match function to use
+ *
+ * Returns:
+ * SUCCESS / FAILED
+ **/
+static int ipr_wait_for_ops(struct ipr_ioa_cfg *ioa_cfg, void *device,
+ int (*match)(struct ipr_cmnd *, void *))
+{
+ struct ipr_cmnd *ipr_cmd;
+ int wait;
+ unsigned long flags;
+ struct ipr_hrr_queue *hrrq;
+ signed long timeout = IPR_ABORT_TASK_TIMEOUT;
+ DECLARE_COMPLETION_ONSTACK(comp);
+
+ ENTER;
+ do {
+ wait = 0;
+
+ for_each_hrrq(hrrq, ioa_cfg) {
+ spin_lock_irqsave(hrrq->lock, flags);
+ list_for_each_entry(ipr_cmd, &hrrq->hrrq_pending_q, queue) {
+ if (match(ipr_cmd, device)) {
+ ipr_cmd->eh_comp = &comp;
+ wait++;
+ }
+ }
+ spin_unlock_irqrestore(hrrq->lock, flags);
+ }
+
+ if (wait) {
+ timeout = wait_for_completion_timeout(&comp, timeout);
+
+ if (!timeout) {
+ wait = 0;
+
+ for_each_hrrq(hrrq, ioa_cfg) {
+ spin_lock_irqsave(hrrq->lock, flags);
+ list_for_each_entry(ipr_cmd, &hrrq->hrrq_pending_q, queue) {
+ if (match(ipr_cmd, device)) {
+ ipr_cmd->eh_comp = NULL;
+ wait++;
+ }
+ }
+ spin_unlock_irqrestore(hrrq->lock, flags);
+ }
+
+ if (wait)
+ dev_err(&ioa_cfg->pdev->dev, "Timed out waiting for aborted commands\n");
+ LEAVE;
+ return wait ? FAILED : SUCCESS;
+ }
+ }
+ } while (wait);
+
+ LEAVE;
+ return SUCCESS;
+}
+
static int ipr_eh_host_reset(struct scsi_cmnd *cmd)
{
struct ipr_ioa_cfg *ioa_cfg;
@@ -5023,11 +5104,17 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd *scsi_cmd)
static int ipr_eh_dev_reset(struct scsi_cmnd *cmd)
{
int rc;
+ struct ipr_ioa_cfg *ioa_cfg;
+
+ ioa_cfg = (struct ipr_ioa_cfg *) cmd->device->host->hostdata;
spin_lock_irq(cmd->device->host->host_lock);
rc = __ipr_eh_dev_reset(cmd);
spin_unlock_irq(cmd->device->host->host_lock);
+ if (rc == SUCCESS)
+ rc = ipr_wait_for_ops(ioa_cfg, cmd->device, ipr_match_lun);
+
return rc;
}
@@ -5205,13 +5292,18 @@ static int ipr_eh_abort(struct scsi_cmnd *scsi_cmd)
{
unsigned long flags;
int rc;
+ struct ipr_ioa_cfg *ioa_cfg;
ENTER;
+ ioa_cfg = (struct ipr_ioa_cfg *) scsi_cmd->device->host->hostdata;
+
spin_lock_irqsave(scsi_cmd->device->host->host_lock, flags);
rc = ipr_cancel_op(scsi_cmd);
spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, flags);
+ if (rc == SUCCESS)
+ rc = ipr_wait_for_ops(ioa_cfg, scsi_cmd->device, ipr_match_lun);
LEAVE;
return rc;
}
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index 9ce38a22647..0801f3df4b2 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -1585,6 +1585,7 @@ struct ipr_cmnd {
struct scsi_device *sdev;
} u;
+ struct completion *eh_comp;
struct ipr_hrr_queue *hrrq;
struct ipr_ioa_cfg *ioa_cfg;
};
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index d46b4ccec8c..850e232d086 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -2417,12 +2417,17 @@ static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file,
poll_wait(file, &tty->read_wait, wait);
poll_wait(file, &tty->write_wait, wait);
+ if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
+ mask |= POLLHUP;
if (input_available_p(tty, 1))
mask |= POLLIN | POLLRDNORM;
+ else if (mask & POLLHUP) {
+ tty_flush_to_ldisc(tty);
+ if (input_available_p(tty, 1))
+ mask |= POLLIN | POLLRDNORM;
+ }
if (tty->packet && tty->link->ctrl_status)
mask |= POLLPRI | POLLIN | POLLRDNORM;
- if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
- mask |= POLLHUP;
if (tty_hung_up_p(file))
mask |= POLLHUP;
if (!(mask & (POLLHUP | POLLIN | POLLRDNORM))) {
diff --git a/drivers/video/backlight/gpio_backlight.c b/drivers/video/backlight/gpio_backlight.c
index 81fb12770c2..a2eba12e1cb 100644
--- a/drivers/video/backlight/gpio_backlight.c
+++ b/drivers/video/backlight/gpio_backlight.c
@@ -13,6 +13,8 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
#include <linux/platform_data/gpio_backlight.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@@ -23,6 +25,7 @@ struct gpio_backlight {
int gpio;
int active;
+ int def_value;
};
static int gpio_backlight_update_status(struct backlight_device *bl)
@@ -60,6 +63,29 @@ static const struct backlight_ops gpio_backlight_ops = {
.check_fb = gpio_backlight_check_fb,
};
+static int gpio_backlight_probe_dt(struct platform_device *pdev,
+ struct gpio_backlight *gbl)
+{
+ struct device_node *np = pdev->dev.of_node;
+ enum of_gpio_flags gpio_flags;
+
+ gbl->gpio = of_get_gpio_flags(np, 0, &gpio_flags);
+
+ if (!gpio_is_valid(gbl->gpio)) {
+ if (gbl->gpio != -EPROBE_DEFER) {
+ dev_err(&pdev->dev,
+ "Error: The gpios parameter is missing or invalid.\n");
+ }
+ return gbl->gpio;
+ }
+
+ gbl->active = (gpio_flags & OF_GPIO_ACTIVE_LOW) ? 0 : 1;
+
+ gbl->def_value = of_property_read_bool(np, "default-on");
+
+ return 0;
+}
+
static int gpio_backlight_probe(struct platform_device *pdev)
{
struct gpio_backlight_platform_data *pdata =
@@ -67,10 +93,12 @@ static int gpio_backlight_probe(struct platform_device *pdev)
struct backlight_properties props;
struct backlight_device *bl;
struct gpio_backlight *gbl;
+ struct device_node *np = pdev->dev.of_node;
int ret;
- if (!pdata) {
- dev_err(&pdev->dev, "failed to find platform data\n");
+ if (!pdata && !np) {
+ dev_err(&pdev->dev,
+ "failed to find platform data or device tree node.\n");
return -ENODEV;
}
@@ -79,14 +107,22 @@ static int gpio_backlight_probe(struct platform_device *pdev)
return -ENOMEM;
gbl->dev = &pdev->dev;
- gbl->fbdev = pdata->fbdev;
- gbl->gpio = pdata->gpio;
- gbl->active = pdata->active_low ? 0 : 1;
+
+ if (np) {
+ ret = gpio_backlight_probe_dt(pdev, gbl);
+ if (ret)
+ return ret;
+ } else {
+ gbl->fbdev = pdata->fbdev;
+ gbl->gpio = pdata->gpio;
+ gbl->active = pdata->active_low ? 0 : 1;
+ gbl->def_value = pdata->def_value;
+ }
ret = devm_gpio_request_one(gbl->dev, gbl->gpio, GPIOF_DIR_OUT |
(gbl->active ? GPIOF_INIT_LOW
: GPIOF_INIT_HIGH),
- pdata->name);
+ pdata ? pdata->name : "backlight");
if (ret < 0) {
dev_err(&pdev->dev, "unable to request GPIO\n");
return ret;
@@ -103,17 +139,25 @@ static int gpio_backlight_probe(struct platform_device *pdev)
return PTR_ERR(bl);
}
- bl->props.brightness = pdata->def_value;
+ bl->props.brightness = gbl->def_value;
backlight_update_status(bl);
platform_set_drvdata(pdev, bl);
return 0;
}
+#ifdef CONFIG_OF
+static struct of_device_id gpio_backlight_of_match[] = {
+ { .compatible = "gpio-backlight" },
+ { /* sentinel */ }
+};
+#endif
+
static struct platform_driver gpio_backlight_driver = {
.driver = {
.name = "gpio-backlight",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(gpio_backlight_of_match),
},
.probe = gpio_backlight_probe,
};
diff --git a/drivers/video/fbdev/omap2/displays-new/dra7-evm-encoder-tpd12s015.c b/drivers/video/fbdev/omap2/displays-new/dra7-evm-encoder-tpd12s015.c
index d74486be117..ec42daa626e 100644
--- a/drivers/video/fbdev/omap2/displays-new/dra7-evm-encoder-tpd12s015.c
+++ b/drivers/video/fbdev/omap2/displays-new/dra7-evm-encoder-tpd12s015.c
@@ -501,7 +501,7 @@ static int __exit tpd_remove(struct platform_device *pdev)
}
static const struct of_device_id tpd_of_match[] = {
- { .compatible = "ti,dra7evm-tpd12s015", },
+ { .compatible = "omapdss,ti,dra7evm-tpd12s015", },
{},
};
diff --git a/drivers/video/fbdev/omap2/displays-new/panel-tlc59108.c b/drivers/video/fbdev/omap2/displays-new/panel-tlc59108.c
index 9f5b3ce2c9a..4f6e8c263b9 100644
--- a/drivers/video/fbdev/omap2/displays-new/panel-tlc59108.c
+++ b/drivers/video/fbdev/omap2/displays-new/panel-tlc59108.c
@@ -267,11 +267,11 @@ static struct omap_dss_driver panel_dpi_ops = {
static const struct of_device_id tlc59108_of_match[] = {
{
- .compatible = "ti,tlc59108-tfcs9700",
+ .compatible = "omapdss,ti,tlc59108-tfcs9700",
.data = &tlc_7_inch_data,
},
{
- .compatible = "ti,tlc59108-lp101",
+ .compatible = "omapdss,ti,tlc59108-lp101",
.data = &tlc_10_inch_data,
},
{ }
diff --git a/drivers/video/fbdev/omap2/dss/omapdss-boot-init.c b/drivers/video/fbdev/omap2/dss/omapdss-boot-init.c
index 99af9e88b2d..64f9a88cde8 100644
--- a/drivers/video/fbdev/omap2/dss/omapdss-boot-init.c
+++ b/drivers/video/fbdev/omap2/dss/omapdss-boot-init.c
@@ -184,6 +184,7 @@ static const struct of_device_id omapdss_of_match[] __initconst = {
{ .compatible = "ti,omap3-dss", },
{ .compatible = "ti,omap4-dss", },
{ .compatible = "ti,omap5-dss", },
+ { .compatible = "ti,dra7-dss", },
{},
};
diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
index 9df5d6ec7ee..f3a9d831d0f 100644
--- a/drivers/xen/swiotlb-xen.c
+++ b/drivers/xen/swiotlb-xen.c
@@ -449,7 +449,7 @@ static void xen_unmap_single(struct device *hwdev, dma_addr_t dev_addr,
/* NOTE: We use dev_addr here, not paddr! */
if (is_xen_swiotlb_buffer(dev_addr)) {
- swiotlb_tbl_unmap_single(hwdev, dev_addr, size, dir);
+ swiotlb_tbl_unmap_single(hwdev, paddr, size, dir);
return;
}