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 gixes from Dave Airlie:
 - exynos: infinite loop regressions fixed
 - i915: one regression
 - radeon: one race condition on monitor probing
 - noveau: two regressions
 - tegra: one vblank regression fix

* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux:
  drm/tegra: dc: Add missing call to drm_vblank_on()
  drm/nouveau/nv50/disp: Fix modeset on G94
  drm/gk20a/fb: fix setting of large page size bit
  drm/radeon: add locking around atombios scratch space usage
  drm/i915: Fix obj->map_and_fenceable across tiling changes
  drm/exynos: fix possible infinite loop issue
  drm/exynos: g2d: fix null pointer dereference
  drm/exynos: resolve infinite loop issue on non multi-platform
  drm/exynos: resolve infinite loop issue on multi-platform
  • Loading branch information
torvalds committed Nov 15, 2014
2 parents 51b97e3 + bcfef97 commit e061167
Show file tree
Hide file tree
Showing 11 changed files with 103 additions and 46 deletions.
49 changes: 33 additions & 16 deletions drivers/gpu/drm/exynos/exynos_drm_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,12 @@ static struct component_match *exynos_drm_match_add(struct device *dev)

mutex_lock(&drm_component_lock);

/* Do not retry to probe if there is no any kms driver regitered. */
if (list_empty(&drm_component_list)) {
mutex_unlock(&drm_component_lock);
return ERR_PTR(-ENODEV);
}

list_for_each_entry(cdev, &drm_component_list, list) {
/*
* Add components to master only in case that crtc and
Expand Down Expand Up @@ -585,10 +591,21 @@ static int exynos_drm_platform_probe(struct platform_device *pdev)
goto err_unregister_mixer_drv;
#endif

match = exynos_drm_match_add(&pdev->dev);
if (IS_ERR(match)) {
ret = PTR_ERR(match);
goto err_unregister_hdmi_drv;
}

ret = component_master_add_with_match(&pdev->dev, &exynos_drm_ops,
match);
if (ret < 0)
goto err_unregister_hdmi_drv;

#ifdef CONFIG_DRM_EXYNOS_G2D
ret = platform_driver_register(&g2d_driver);
if (ret < 0)
goto err_unregister_hdmi_drv;
goto err_del_component_master;
#endif

#ifdef CONFIG_DRM_EXYNOS_FIMC
Expand Down Expand Up @@ -619,23 +636,9 @@ static int exynos_drm_platform_probe(struct platform_device *pdev)
goto err_unregister_ipp_drv;
#endif

match = exynos_drm_match_add(&pdev->dev);
if (IS_ERR(match)) {
ret = PTR_ERR(match);
goto err_unregister_resources;
}

ret = component_master_add_with_match(&pdev->dev, &exynos_drm_ops,
match);
if (ret < 0)
goto err_unregister_resources;

return ret;

err_unregister_resources:

#ifdef CONFIG_DRM_EXYNOS_IPP
exynos_platform_device_ipp_unregister();
err_unregister_ipp_drv:
platform_driver_unregister(&ipp_driver);
err_unregister_gsc_drv:
Expand All @@ -658,9 +661,11 @@ static int exynos_drm_platform_probe(struct platform_device *pdev)

#ifdef CONFIG_DRM_EXYNOS_G2D
platform_driver_unregister(&g2d_driver);
err_unregister_hdmi_drv:
err_del_component_master:
#endif
component_master_del(&pdev->dev, &exynos_drm_ops);

err_unregister_hdmi_drv:
#ifdef CONFIG_DRM_EXYNOS_HDMI
platform_driver_unregister(&hdmi_driver);
err_unregister_mixer_drv:
Expand Down Expand Up @@ -741,6 +746,18 @@ static int exynos_drm_init(void)
{
int ret;

/*
* Register device object only in case of Exynos SoC.
*
* Below codes resolves temporarily infinite loop issue incurred
* by Exynos drm driver when using multi-platform kernel.
* So these codes will be replaced with more generic way later.
*/
if (!of_machine_is_compatible("samsung,exynos3") &&
!of_machine_is_compatible("samsung,exynos4") &&
!of_machine_is_compatible("samsung,exynos5"))
return -ENODEV;

exynos_drm_pdev = platform_device_register_simple("exynos-drm", -1,
NULL, 0);
if (IS_ERR(exynos_drm_pdev))
Expand Down
9 changes: 6 additions & 3 deletions drivers/gpu/drm/exynos/exynos_drm_g2d.c
Original file line number Diff line number Diff line change
Expand Up @@ -302,9 +302,12 @@ static void g2d_fini_cmdlist(struct g2d_data *g2d)
struct exynos_drm_subdrv *subdrv = &g2d->subdrv;

kfree(g2d->cmdlist_node);
dma_free_attrs(subdrv->drm_dev->dev, G2D_CMDLIST_POOL_SIZE,
g2d->cmdlist_pool_virt,
g2d->cmdlist_pool, &g2d->cmdlist_dma_attrs);

if (g2d->cmdlist_pool_virt && g2d->cmdlist_pool) {
dma_free_attrs(subdrv->drm_dev->dev, G2D_CMDLIST_POOL_SIZE,
g2d->cmdlist_pool_virt,
g2d->cmdlist_pool, &g2d->cmdlist_dma_attrs);
}
}

static struct g2d_cmdlist_node *g2d_get_cmdlist(struct g2d_data *g2d)
Expand Down
19 changes: 3 additions & 16 deletions drivers/gpu/drm/i915/i915_gem_tiling.c
Original file line number Diff line number Diff line change
Expand Up @@ -364,22 +364,9 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
* has to also include the unfenced register the GPU uses
* whilst executing a fenced command for an untiled object.
*/

obj->map_and_fenceable =
!i915_gem_obj_ggtt_bound(obj) ||
(i915_gem_obj_ggtt_offset(obj) +
obj->base.size <= dev_priv->gtt.mappable_end &&
i915_gem_object_fence_ok(obj, args->tiling_mode));

/* Rebind if we need a change of alignment */
if (!obj->map_and_fenceable) {
u32 unfenced_align =
i915_gem_get_gtt_alignment(dev, obj->base.size,
args->tiling_mode,
false);
if (i915_gem_obj_ggtt_offset(obj) & (unfenced_align - 1))
ret = i915_gem_object_ggtt_unbind(obj);
}
if (obj->map_and_fenceable &&
!i915_gem_object_fence_ok(obj, args->tiling_mode))
ret = i915_gem_object_ggtt_unbind(obj);

if (ret == 0) {
obj->fence_dirty =
Expand Down
16 changes: 15 additions & 1 deletion drivers/gpu/drm/nouveau/core/subdev/fb/gk20a.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,20 @@ struct gk20a_fb_priv {
struct nouveau_fb base;
};

static int
gk20a_fb_init(struct nouveau_object *object)
{
struct gk20a_fb_priv *priv = (void *)object;
int ret;

ret = nouveau_fb_init(&priv->base);
if (ret)
return ret;

nv_mask(priv, 0x100c80, 0x00000001, 0x00000000); /* 128KiB lpg */
return 0;
}

static int
gk20a_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
Expand All @@ -48,7 +62,7 @@ gk20a_fb_oclass = &(struct nouveau_fb_impl) {
.base.ofuncs = &(struct nouveau_ofuncs) {
.ctor = gk20a_fb_ctor,
.dtor = _nouveau_fb_dtor,
.init = _nouveau_fb_init,
.init = gk20a_fb_init,
.fini = _nouveau_fb_fini,
},
.memtype = nvc0_fb_memtype_valid,
Expand Down
25 changes: 23 additions & 2 deletions drivers/gpu/drm/nouveau/nv50_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,22 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update)
return 0;
}

static int
nv50_crtc_set_raster_vblank_dmi(struct nouveau_crtc *nv_crtc, u32 usec)
{
struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
u32 *push;

push = evo_wait(mast, 8);
if (!push)
return -ENOMEM;

evo_mthd(push, 0x0828 + (nv_crtc->index * 0x400), 1);
evo_data(push, usec);
evo_kick(push, mast);
return 0;
}

static int
nv50_crtc_set_color_vibrance(struct nouveau_crtc *nv_crtc, bool update)
{
Expand Down Expand Up @@ -1104,14 +1120,14 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode,
evo_mthd(push, 0x0804 + (nv_crtc->index * 0x400), 2);
evo_data(push, 0x00800000 | mode->clock);
evo_data(push, (ilace == 2) ? 2 : 0);
evo_mthd(push, 0x0810 + (nv_crtc->index * 0x400), 8);
evo_mthd(push, 0x0810 + (nv_crtc->index * 0x400), 6);
evo_data(push, 0x00000000);
evo_data(push, (vactive << 16) | hactive);
evo_data(push, ( vsynce << 16) | hsynce);
evo_data(push, (vblanke << 16) | hblanke);
evo_data(push, (vblanks << 16) | hblanks);
evo_data(push, (vblan2e << 16) | vblan2s);
evo_data(push, vblankus);
evo_mthd(push, 0x082c + (nv_crtc->index * 0x400), 1);
evo_data(push, 0x00000000);
evo_mthd(push, 0x0900 + (nv_crtc->index * 0x400), 2);
evo_data(push, 0x00000311);
Expand Down Expand Up @@ -1141,6 +1157,11 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode,
nv_connector = nouveau_crtc_connector_get(nv_crtc);
nv50_crtc_set_dither(nv_crtc, false);
nv50_crtc_set_scale(nv_crtc, false);

/* G94 only accepts this after setting scale */
if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA)
nv50_crtc_set_raster_vblank_dmi(nv_crtc, vblankus);

nv50_crtc_set_color_vibrance(nv_crtc, false);
nv50_crtc_set_image(nv_crtc, crtc->primary->fb, x, y, false);
return 0;
Expand Down
11 changes: 10 additions & 1 deletion drivers/gpu/drm/radeon/atom.c
Original file line number Diff line number Diff line change
Expand Up @@ -1217,7 +1217,7 @@ static int atom_execute_table_locked(struct atom_context *ctx, int index, uint32
return ret;
}

int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
int atom_execute_table_scratch_unlocked(struct atom_context *ctx, int index, uint32_t * params)
{
int r;

Expand All @@ -1238,6 +1238,15 @@ int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
return r;
}

int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
{
int r;
mutex_lock(&ctx->scratch_mutex);
r = atom_execute_table_scratch_unlocked(ctx, index, params);
mutex_unlock(&ctx->scratch_mutex);
return r;
}

static int atom_iio_len[] = { 1, 2, 3, 3, 3, 3, 4, 4, 4, 3 };

static void atom_index_iio(struct atom_context *ctx, int base)
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/radeon/atom.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ struct card_info {
struct atom_context {
struct card_info *card;
struct mutex mutex;
struct mutex scratch_mutex;
void *bios;
uint32_t cmd_table, data_table;
uint16_t *iio;
Expand All @@ -145,6 +146,7 @@ extern int atom_debug;

struct atom_context *atom_parse(struct card_info *, void *);
int atom_execute_table(struct atom_context *, int, uint32_t *);
int atom_execute_table_scratch_unlocked(struct atom_context *, int, uint32_t *);
int atom_asic_init(struct atom_context *);
void atom_destroy(struct atom_context *);
bool atom_parse_data_header(struct atom_context *ctx, int index, uint16_t *size,
Expand Down
4 changes: 3 additions & 1 deletion drivers/gpu/drm/radeon/atombios_dp.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
memset(&args, 0, sizeof(args));

mutex_lock(&chan->mutex);
mutex_lock(&rdev->mode_info.atom_context->scratch_mutex);

base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1);

Expand All @@ -113,7 +114,7 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
if (ASIC_IS_DCE4(rdev))
args.v2.ucHPD_ID = chan->rec.hpd;

atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
atom_execute_table_scratch_unlocked(rdev->mode_info.atom_context, index, (uint32_t *)&args);

*ack = args.v1.ucReplyStatus;

Expand Down Expand Up @@ -147,6 +148,7 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,

r = recv_bytes;
done:
mutex_unlock(&rdev->mode_info.atom_context->scratch_mutex);
mutex_unlock(&chan->mutex);

return r;
Expand Down
4 changes: 3 additions & 1 deletion drivers/gpu/drm/radeon/atombios_i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,
memset(&args, 0, sizeof(args));

mutex_lock(&chan->mutex);
mutex_lock(&rdev->mode_info.atom_context->scratch_mutex);

base = (unsigned char *)rdev->mode_info.atom_context->scratch;

Expand Down Expand Up @@ -82,7 +83,7 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,
args.ucSlaveAddr = slave_addr << 1;
args.ucLineNumber = chan->rec.i2c_id;

atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
atom_execute_table_scratch_unlocked(rdev->mode_info.atom_context, index, (uint32_t *)&args);

/* error */
if (args.ucStatus != HW_ASSISTED_I2C_STATUS_SUCCESS) {
Expand All @@ -95,6 +96,7 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,
radeon_atom_copy_swap(buf, base, num, false);

done:
mutex_unlock(&rdev->mode_info.atom_context->scratch_mutex);
mutex_unlock(&chan->mutex);

return r;
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/radeon/radeon_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -952,6 +952,7 @@ int radeon_atombios_init(struct radeon_device *rdev)
}

mutex_init(&rdev->mode_info.atom_context->mutex);
mutex_init(&rdev->mode_info.atom_context->scratch_mutex);
radeon_atom_initialize_bios_scratch_regs(rdev->ddev);
atom_allocate_fb_scratch(rdev->mode_info.atom_context);
return 0;
Expand Down
9 changes: 4 additions & 5 deletions drivers/gpu/drm/tegra/dc.c
Original file line number Diff line number Diff line change
Expand Up @@ -736,7 +736,6 @@ static const struct drm_crtc_funcs tegra_crtc_funcs = {

static void tegra_crtc_disable(struct drm_crtc *crtc)
{
struct tegra_dc *dc = to_tegra_dc(crtc);
struct drm_device *drm = crtc->dev;
struct drm_plane *plane;

Expand All @@ -752,7 +751,7 @@ static void tegra_crtc_disable(struct drm_crtc *crtc)
}
}

drm_vblank_off(drm, dc->pipe);
drm_crtc_vblank_off(crtc);
}

static bool tegra_crtc_mode_fixup(struct drm_crtc *crtc,
Expand Down Expand Up @@ -841,8 +840,6 @@ static int tegra_crtc_mode_set(struct drm_crtc *crtc,
u32 value;
int err;

drm_vblank_pre_modeset(crtc->dev, dc->pipe);

err = tegra_crtc_setup_clk(crtc, mode);
if (err) {
dev_err(dc->dev, "failed to setup clock for CRTC: %d\n", err);
Expand Down Expand Up @@ -896,6 +893,8 @@ static void tegra_crtc_prepare(struct drm_crtc *crtc)
unsigned int syncpt;
unsigned long value;

drm_crtc_vblank_off(crtc);

/* hardware initialization */
reset_control_deassert(dc->rst);
usleep_range(10000, 20000);
Expand Down Expand Up @@ -943,7 +942,7 @@ static void tegra_crtc_commit(struct drm_crtc *crtc)
value = GENERAL_ACT_REQ | WIN_A_ACT_REQ;
tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);

drm_vblank_post_modeset(crtc->dev, dc->pipe);
drm_crtc_vblank_on(crtc);
}

static void tegra_crtc_load_lut(struct drm_crtc *crtc)
Expand Down

0 comments on commit e061167

Please sign in to comment.