Skip to content

Commit

Permalink
Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
Browse files Browse the repository at this point in the history
Pull drm fixes from Dave Airlie:
 "This has two main sets of fixes:

   - A bunch of Exynos fixes, mainly for their MIC component.

   - vblank regression fixes from Mario, apparantly some changes in 4.4
     caused some vblank breakage on radeon/nouveau, this set fixes all
     the issues seen.

  There is also a revert of one of the MST changse, that I was
  overzealous in including, that broke 30" MST monitors, and two qxl
  fixes"

* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux:
  drm/qxl: fix erroneous return value
  drm/nouveau/display: Enable vblank irqs after display engine is on again.
  drm/radeon/pm: Handle failure of drm_vblank_get.
  drm: Fix treatment of drm_vblank_offdelay in drm_vblank_on() (v2)
  drm: Fix drm_vblank_pre/post_modeset regression from Linux 4.4
  drm: Prevent vblank counter bumps > 1 with active vblank clients. (v2)
  drm: No-Op redundant calls to drm_vblank_off() (v2)
  drm/qxl: use kmalloc_array to alloc reloc_info in qxl_process_single_command
  Revert "drm/dp/mst: change MST detection scheme"
  drm/exynos/decon: fix disable clocks order
  drm/exynos: fix incorrect cpu address for dma_mmap_attrs()
  drm/exynos: exynos5433_decon: fix wrong state in decon_vblank_enable
  drm/exynos: exynos5433_decon: fix wrong state assignment in decon_enable
  drm/exynos: dsi: restore support for drm bridge
  drm/exynos: mic: make all functions static
  drm/exynos: mic: convert to component framework
  drm/exynos: mic: use devm_clk interface
  drm/exynos: fix types for compilation on 64bit architectures
  drm/exynos: ipp: fix incorrect format specifiers in debug messages
  drm/exynos: depend on ARCH_EXYNOS for DRM_EXYNOS
  • Loading branch information
torvalds committed Feb 17, 2016
2 parents a9f70bd + dada168 commit 35683dd
Show file tree
Hide file tree
Showing 18 changed files with 178 additions and 93 deletions.
37 changes: 18 additions & 19 deletions drivers/gpu/drm/drm_dp_mst_topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -1159,11 +1159,13 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
drm_dp_put_port(port);
goto out;
}

drm_mode_connector_set_tile_property(port->connector);

if (port->port_num >= DP_MST_LOGICAL_PORT_0) {
port->cached_edid = drm_get_edid(port->connector, &port->aux.ddc);
drm_mode_connector_set_tile_property(port->connector);
}
(*mstb->mgr->cbs->register_connector)(port->connector);
}

out:
/* put reference to this port */
drm_dp_put_port(port);
Expand All @@ -1188,8 +1190,8 @@ static void drm_dp_update_port(struct drm_dp_mst_branch *mstb,
port->ddps = conn_stat->displayport_device_plug_status;

if (old_ddps != port->ddps) {
dowork = true;
if (port->ddps) {
dowork = true;
} else {
port->available_pbn = 0;
}
Expand Down Expand Up @@ -1294,13 +1296,8 @@ static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *m
if (port->input)
continue;

if (!port->ddps) {
if (port->cached_edid) {
kfree(port->cached_edid);
port->cached_edid = NULL;
}
if (!port->ddps)
continue;
}

if (!port->available_pbn)
drm_dp_send_enum_path_resources(mgr, mstb, port);
Expand All @@ -1311,12 +1308,6 @@ static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *m
drm_dp_check_and_send_link_address(mgr, mstb_child);
drm_dp_put_mst_branch_device(mstb_child);
}
} else if (port->pdt == DP_PEER_DEVICE_SST_SINK ||
port->pdt == DP_PEER_DEVICE_DP_LEGACY_CONV) {
if (!port->cached_edid) {
port->cached_edid =
drm_get_edid(port->connector, &port->aux.ddc);
}
}
}
}
Expand All @@ -1336,8 +1327,6 @@ static void drm_dp_mst_link_probe_work(struct work_struct *work)
drm_dp_check_and_send_link_address(mgr, mstb);
drm_dp_put_mst_branch_device(mstb);
}

(*mgr->cbs->hotplug)(mgr);
}

static bool drm_dp_validate_guid(struct drm_dp_mst_topology_mgr *mgr,
Expand Down Expand Up @@ -1597,6 +1586,7 @@ static void drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
for (i = 0; i < txmsg->reply.u.link_addr.nports; i++) {
drm_dp_add_port(mstb, mgr->dev, &txmsg->reply.u.link_addr.ports[i]);
}
(*mgr->cbs->hotplug)(mgr);
}
} else {
mstb->link_address_sent = false;
Expand Down Expand Up @@ -2293,6 +2283,8 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
drm_dp_update_port(mstb, &msg.u.conn_stat);

DRM_DEBUG_KMS("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n", msg.u.conn_stat.port_number, msg.u.conn_stat.legacy_device_plug_status, msg.u.conn_stat.displayport_device_plug_status, msg.u.conn_stat.message_capability_status, msg.u.conn_stat.input_port, msg.u.conn_stat.peer_device_type);
(*mgr->cbs->hotplug)(mgr);

} else if (msg.req_type == DP_RESOURCE_STATUS_NOTIFY) {
drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false);
if (!mstb)
Expand Down Expand Up @@ -2379,6 +2371,10 @@ enum drm_connector_status drm_dp_mst_detect_port(struct drm_connector *connector

case DP_PEER_DEVICE_SST_SINK:
status = connector_status_connected;
/* for logical ports - cache the EDID */
if (port->port_num >= 8 && !port->cached_edid) {
port->cached_edid = drm_get_edid(connector, &port->aux.ddc);
}
break;
case DP_PEER_DEVICE_DP_LEGACY_CONV:
if (port->ldps)
Expand Down Expand Up @@ -2433,7 +2429,10 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_

if (port->cached_edid)
edid = drm_edid_duplicate(port->cached_edid);

else {
edid = drm_get_edid(connector, &port->aux.ddc);
drm_mode_connector_set_tile_property(connector);
}
port->has_audio = drm_detect_monitor_audio(edid);
drm_dp_put_port(port);
return edid;
Expand Down
73 changes: 70 additions & 3 deletions drivers/gpu/drm/drm_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,64 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
diff = (flags & DRM_CALLED_FROM_VBLIRQ) != 0;
}

/*
* Within a drm_vblank_pre_modeset - drm_vblank_post_modeset
* interval? If so then vblank irqs keep running and it will likely
* happen that the hardware vblank counter is not trustworthy as it
* might reset at some point in that interval and vblank timestamps
* are not trustworthy either in that interval. Iow. this can result
* in a bogus diff >> 1 which must be avoided as it would cause
* random large forward jumps of the software vblank counter.
*/
if (diff > 1 && (vblank->inmodeset & 0x2)) {
DRM_DEBUG_VBL("clamping vblank bump to 1 on crtc %u: diffr=%u"
" due to pre-modeset.\n", pipe, diff);
diff = 1;
}

/*
* FIMXE: Need to replace this hack with proper seqlocks.
*
* Restrict the bump of the software vblank counter to a safe maximum
* value of +1 whenever there is the possibility that concurrent readers
* of vblank timestamps could be active at the moment, as the current
* implementation of the timestamp caching and updating is not safe
* against concurrent readers for calls to store_vblank() with a bump
* of anything but +1. A bump != 1 would very likely return corrupted
* timestamps to userspace, because the same slot in the cache could
* be concurrently written by store_vblank() and read by one of those
* readers without the read-retry logic detecting the collision.
*
* Concurrent readers can exist when we are called from the
* drm_vblank_off() or drm_vblank_on() functions and other non-vblank-
* irq callers. However, all those calls to us are happening with the
* vbl_lock locked to prevent drm_vblank_get(), so the vblank refcount
* can't increase while we are executing. Therefore a zero refcount at
* this point is safe for arbitrary counter bumps if we are called
* outside vblank irq, a non-zero count is not 100% safe. Unfortunately
* we must also accept a refcount of 1, as whenever we are called from
* drm_vblank_get() -> drm_vblank_enable() the refcount will be 1 and
* we must let that one pass through in order to not lose vblank counts
* during vblank irq off - which would completely defeat the whole
* point of this routine.
*
* Whenever we are called from vblank irq, we have to assume concurrent
* readers exist or can show up any time during our execution, even if
* the refcount is currently zero, as vblank irqs are usually only
* enabled due to the presence of readers, and because when we are called
* from vblank irq we can't hold the vbl_lock to protect us from sudden
* bumps in vblank refcount. Therefore also restrict bumps to +1 when
* called from vblank irq.
*/
if ((diff > 1) && (atomic_read(&vblank->refcount) > 1 ||
(flags & DRM_CALLED_FROM_VBLIRQ))) {
DRM_DEBUG_VBL("clamping vblank bump to 1 on crtc %u: diffr=%u "
"refcount %u, vblirq %u\n", pipe, diff,
atomic_read(&vblank->refcount),
(flags & DRM_CALLED_FROM_VBLIRQ) != 0);
diff = 1;
}

DRM_DEBUG_VBL("updating vblank count on crtc %u:"
" current=%u, diff=%u, hw=%u hw_last=%u\n",
pipe, vblank->count, diff, cur_vblank, vblank->last);
Expand Down Expand Up @@ -1316,7 +1374,13 @@ void drm_vblank_off(struct drm_device *dev, unsigned int pipe)
spin_lock_irqsave(&dev->event_lock, irqflags);

spin_lock(&dev->vbl_lock);
vblank_disable_and_save(dev, pipe);
DRM_DEBUG_VBL("crtc %d, vblank enabled %d, inmodeset %d\n",
pipe, vblank->enabled, vblank->inmodeset);

/* Avoid redundant vblank disables without previous drm_vblank_on(). */
if (drm_core_check_feature(dev, DRIVER_ATOMIC) || !vblank->inmodeset)
vblank_disable_and_save(dev, pipe);

wake_up(&vblank->queue);

/*
Expand Down Expand Up @@ -1418,6 +1482,9 @@ void drm_vblank_on(struct drm_device *dev, unsigned int pipe)
return;

spin_lock_irqsave(&dev->vbl_lock, irqflags);
DRM_DEBUG_VBL("crtc %d, vblank enabled %d, inmodeset %d\n",
pipe, vblank->enabled, vblank->inmodeset);

/* Drop our private "prevent drm_vblank_get" refcount */
if (vblank->inmodeset) {
atomic_dec(&vblank->refcount);
Expand All @@ -1430,8 +1497,7 @@ void drm_vblank_on(struct drm_device *dev, unsigned int pipe)
* re-enable interrupts if there are users left, or the
* user wishes vblank interrupts to be enabled all the time.
*/
if (atomic_read(&vblank->refcount) != 0 ||
(!dev->vblank_disable_immediate && drm_vblank_offdelay == 0))
if (atomic_read(&vblank->refcount) != 0 || drm_vblank_offdelay == 0)
WARN_ON(drm_vblank_enable(dev, pipe));
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
}
Expand Down Expand Up @@ -1526,6 +1592,7 @@ void drm_vblank_post_modeset(struct drm_device *dev, unsigned int pipe)
if (vblank->inmodeset) {
spin_lock_irqsave(&dev->vbl_lock, irqflags);
dev->vblank_disable_allowed = true;
drm_reset_vblank_timestamp(dev, pipe);
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);

if (vblank->inmodeset & 0x2)
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/exynos/Kconfig
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
config DRM_EXYNOS
tristate "DRM Support for Samsung SoC EXYNOS Series"
depends on OF && DRM && (PLAT_SAMSUNG || ARCH_MULTIPLATFORM)
depends on OF && DRM && (ARCH_S3C64XX || ARCH_EXYNOS || ARCH_MULTIPLATFORM)
select DRM_KMS_HELPER
select DRM_KMS_FB_HELPER
select FB_CFB_FILLRECT
Expand Down
8 changes: 3 additions & 5 deletions drivers/gpu/drm/exynos/exynos5433_drm_decon.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ static int decon_enable_vblank(struct exynos_drm_crtc *crtc)
if (test_bit(BIT_SUSPENDED, &ctx->flags))
return -EPERM;

if (test_and_set_bit(BIT_IRQS_ENABLED, &ctx->flags)) {
if (!test_and_set_bit(BIT_IRQS_ENABLED, &ctx->flags)) {
val = VIDINTCON0_INTEN;
if (ctx->out_type == IFTYPE_I80)
val |= VIDINTCON0_FRAMEDONE;
Expand Down Expand Up @@ -402,8 +402,6 @@ static void decon_enable(struct exynos_drm_crtc *crtc)
decon_enable_vblank(ctx->crtc);

decon_commit(ctx->crtc);

set_bit(BIT_SUSPENDED, &ctx->flags);
}

static void decon_disable(struct exynos_drm_crtc *crtc)
Expand Down Expand Up @@ -582,9 +580,9 @@ static irqreturn_t decon_irq_handler(int irq, void *dev_id)
static int exynos5433_decon_suspend(struct device *dev)
{
struct decon_context *ctx = dev_get_drvdata(dev);
int i;
int i = ARRAY_SIZE(decon_clks_name);

for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++)
while (--i >= 0)
clk_disable_unprepare(ctx->clks[i]);

return 0;
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/exynos/exynos_drm_dsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1782,6 +1782,7 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,

bridge = of_drm_find_bridge(dsi->bridge_node);
if (bridge) {
encoder->bridge = bridge;
drm_bridge_attach(drm_dev, bridge);
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/exynos/exynos_drm_fbdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ static int exynos_drm_fb_mmap(struct fb_info *info,
if (vm_size > exynos_gem->size)
return -EINVAL;

ret = dma_mmap_attrs(helper->dev->dev, vma, exynos_gem->pages,
ret = dma_mmap_attrs(helper->dev->dev, vma, exynos_gem->cookie,
exynos_gem->dma_addr, exynos_gem->size,
&exynos_gem->dma_attrs);
if (ret < 0) {
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/exynos/exynos_drm_fimc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1723,7 +1723,7 @@ static int fimc_probe(struct platform_device *pdev)
goto err_put_clk;
}

DRM_DEBUG_KMS("id[%d]ippdrv[0x%x]\n", ctx->id, (int)ippdrv);
DRM_DEBUG_KMS("id[%d]ippdrv[%p]\n", ctx->id, ippdrv);

spin_lock_init(&ctx->lock);
platform_set_drvdata(pdev, ctx);
Expand Down
5 changes: 3 additions & 2 deletions drivers/gpu/drm/exynos/exynos_drm_g2d.c
Original file line number Diff line number Diff line change
Expand Up @@ -1166,7 +1166,7 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
goto err_free_event;
}

cmd = (struct drm_exynos_g2d_cmd *)(uint32_t)req->cmd;
cmd = (struct drm_exynos_g2d_cmd *)(unsigned long)req->cmd;

if (copy_from_user(cmdlist->data + cmdlist->last,
(void __user *)cmd,
Expand All @@ -1184,7 +1184,8 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
if (req->cmd_buf_nr) {
struct drm_exynos_g2d_cmd *cmd_buf;

cmd_buf = (struct drm_exynos_g2d_cmd *)(uint32_t)req->cmd_buf;
cmd_buf = (struct drm_exynos_g2d_cmd *)
(unsigned long)req->cmd_buf;

if (copy_from_user(cmdlist->data + cmdlist->last,
(void __user *)cmd_buf,
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/exynos/exynos_drm_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ static struct exynos_drm_gem *exynos_drm_gem_init(struct drm_device *dev,
return ERR_PTR(ret);
}

DRM_DEBUG_KMS("created file object = 0x%x\n", (unsigned int)obj->filp);
DRM_DEBUG_KMS("created file object = %p\n", obj->filp);

return exynos_gem;
}
Expand Down Expand Up @@ -335,7 +335,7 @@ static int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem *exynos_gem,
if (vm_size > exynos_gem->size)
return -EINVAL;

ret = dma_mmap_attrs(drm_dev->dev, vma, exynos_gem->pages,
ret = dma_mmap_attrs(drm_dev->dev, vma, exynos_gem->cookie,
exynos_gem->dma_addr, exynos_gem->size,
&exynos_gem->dma_attrs);
if (ret < 0) {
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/exynos/exynos_drm_gsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1723,7 +1723,7 @@ static int gsc_probe(struct platform_device *pdev)
return ret;
}

DRM_DEBUG_KMS("id[%d]ippdrv[0x%x]\n", ctx->id, (int)ippdrv);
DRM_DEBUG_KMS("id[%d]ippdrv[%p]\n", ctx->id, ippdrv);

mutex_init(&ctx->lock);
platform_set_drvdata(pdev, ctx);
Expand Down
Loading

0 comments on commit 35683dd

Please sign in to comment.