diff options
Diffstat (limited to 'drivers/gpu/drm')
39 files changed, 284 insertions, 190 deletions
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 1d1f1e5e33f0..046bcda36abe 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -24,7 +24,7 @@ config DRM_EXYNOS_DMABUF config DRM_EXYNOS_FIMD bool "Exynos DRM FIMD" - depends on DRM_EXYNOS && !FB_S3C + depends on DRM_EXYNOS && !FB_S3C && !ARCH_MULTIPLATFORM help Choose this option if you want to use Exynos FIMD for DRM. @@ -48,7 +48,7 @@ config DRM_EXYNOS_G2D config DRM_EXYNOS_IPP bool "Exynos DRM IPP" - depends on DRM_EXYNOS + depends on DRM_EXYNOS && !ARCH_MULTIPLATFORM help Choose this option if you want to use IPP feature for DRM. diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c index ab37437bad8a..4c5b6859c9ea 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_connector.c +++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c @@ -18,7 +18,6 @@ #include "exynos_drm_drv.h" #include "exynos_drm_encoder.h" -#define MAX_EDID 256 #define to_exynos_connector(x) container_of(x, struct exynos_drm_connector,\ drm_connector) @@ -96,7 +95,9 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector) to_exynos_connector(connector); struct exynos_drm_manager *manager = exynos_connector->manager; struct exynos_drm_display_ops *display_ops = manager->display_ops; - unsigned int count; + struct edid *edid = NULL; + unsigned int count = 0; + int ret; DRM_DEBUG_KMS("%s\n", __FILE__); @@ -114,27 +115,21 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector) * because lcd panel has only one mode. */ if (display_ops->get_edid) { - int ret; - void *edid; - - edid = kzalloc(MAX_EDID, GFP_KERNEL); - if (!edid) { - DRM_ERROR("failed to allocate edid\n"); - return 0; + edid = display_ops->get_edid(manager->dev, connector); + if (IS_ERR_OR_NULL(edid)) { + ret = PTR_ERR(edid); + edid = NULL; + DRM_ERROR("Panel operation get_edid failed %d\n", ret); + goto out; } - ret = display_ops->get_edid(manager->dev, connector, - edid, MAX_EDID); - if (ret < 0) { - DRM_ERROR("failed to get edid data.\n"); - kfree(edid); - edid = NULL; - return 0; + count = drm_add_edid_modes(connector, edid); + if (count < 0) { + DRM_ERROR("Add edid modes failed %d\n", count); + goto out; } drm_mode_connector_update_edid_property(connector, edid); - count = drm_add_edid_modes(connector, edid); - kfree(edid); } else { struct exynos_drm_panel_info *panel; struct drm_display_mode *mode = drm_mode_create(connector->dev); @@ -161,6 +156,8 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector) count = 1; } +out: + kfree(edid); return count; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c index 9df97714b6c0..ba0a3aa78547 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c @@ -19,6 +19,7 @@ struct exynos_drm_dmabuf_attachment { struct sg_table sgt; enum dma_data_direction dir; + bool is_mapped; }; static int exynos_gem_attach_dma_buf(struct dma_buf *dmabuf, @@ -72,17 +73,10 @@ static struct sg_table * DRM_DEBUG_PRIME("%s\n", __FILE__); - if (WARN_ON(dir == DMA_NONE)) - return ERR_PTR(-EINVAL); - /* just return current sgt if already requested. */ - if (exynos_attach->dir == dir) + if (exynos_attach->dir == dir && exynos_attach->is_mapped) return &exynos_attach->sgt; - /* reattaching is not allowed. */ - if (WARN_ON(exynos_attach->dir != DMA_NONE)) - return ERR_PTR(-EBUSY); - buf = gem_obj->buffer; if (!buf) { DRM_ERROR("buffer is null.\n"); @@ -107,13 +101,17 @@ static struct sg_table * wr = sg_next(wr); } - nents = dma_map_sg(attach->dev, sgt->sgl, sgt->orig_nents, dir); - if (!nents) { - DRM_ERROR("failed to map sgl with iommu.\n"); - sgt = ERR_PTR(-EIO); - goto err_unlock; + if (dir != DMA_NONE) { + nents = dma_map_sg(attach->dev, sgt->sgl, sgt->orig_nents, dir); + if (!nents) { + DRM_ERROR("failed to map sgl with iommu.\n"); + sg_free_table(sgt); + sgt = ERR_PTR(-EIO); + goto err_unlock; + } } + exynos_attach->is_mapped = true; exynos_attach->dir = dir; attach->priv = exynos_attach; diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index b9e51bc09e81..4606fac7241a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -148,8 +148,8 @@ struct exynos_drm_overlay { struct exynos_drm_display_ops { enum exynos_drm_output_type type; bool (*is_connected)(struct device *dev); - int (*get_edid)(struct device *dev, struct drm_connector *connector, - u8 *edid, int len); + struct edid *(*get_edid)(struct device *dev, + struct drm_connector *connector); void *(*get_panel)(struct device *dev); int (*check_timing)(struct device *dev, void *timing); int (*power_on)(struct device *dev, int mode); diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 36c3905536a6..9a4c08e7453c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -324,7 +324,7 @@ out: g2d_userptr = NULL; } -dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev, +static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev, unsigned long userptr, unsigned long size, struct drm_file *filp, diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c index 850e9950b7da..28644539b305 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c @@ -108,18 +108,17 @@ static bool drm_hdmi_is_connected(struct device *dev) return false; } -static int drm_hdmi_get_edid(struct device *dev, - struct drm_connector *connector, u8 *edid, int len) +static struct edid *drm_hdmi_get_edid(struct device *dev, + struct drm_connector *connector) { struct drm_hdmi_context *ctx = to_context(dev); DRM_DEBUG_KMS("%s\n", __FILE__); if (hdmi_ops && hdmi_ops->get_edid) - return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector, edid, - len); + return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector); - return 0; + return NULL; } static int drm_hdmi_check_timing(struct device *dev, void *timing) diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h index 784a7e9a766c..d80516fc9ed7 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h @@ -30,8 +30,8 @@ struct exynos_drm_hdmi_context { struct exynos_hdmi_ops { /* display */ bool (*is_connected)(void *ctx); - int (*get_edid)(void *ctx, struct drm_connector *connector, - u8 *edid, int len); + struct edid *(*get_edid)(void *ctx, + struct drm_connector *connector); int (*check_timing)(void *ctx, void *timing); int (*power_on)(void *ctx, int mode); diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c index 0bda96454a02..1a556354e92f 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c @@ -869,7 +869,7 @@ static void ipp_put_event(struct drm_exynos_ipp_cmd_node *c_node, } } -void ipp_handle_cmd_work(struct device *dev, +static void ipp_handle_cmd_work(struct device *dev, struct exynos_drm_ippdrv *ippdrv, struct drm_exynos_ipp_cmd_work *cmd_work, struct drm_exynos_ipp_cmd_node *c_node) diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c b/drivers/gpu/drm/exynos/exynos_drm_rotator.c index e9e83ef688f0..f976e29def6e 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c +++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c @@ -734,7 +734,7 @@ static int rotator_remove(struct platform_device *pdev) return 0; } -struct rot_limit_table rot_limit_tbl = { +static struct rot_limit_table rot_limit_tbl = { .ycbcr420_2p = { .min_w = 32, .min_h = 32, @@ -751,7 +751,7 @@ struct rot_limit_table rot_limit_tbl = { }, }; -struct platform_device_id rotator_driver_ids[] = { +static struct platform_device_id rotator_driver_ids[] = { { .name = "exynos-rot", .driver_data = (unsigned long)&rot_limit_tbl, diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index d0ca3c4e06c6..13ccbd4bcfaa 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -98,10 +98,12 @@ static bool vidi_display_is_connected(struct device *dev) return ctx->connected ? true : false; } -static int vidi_get_edid(struct device *dev, struct drm_connector *connector, - u8 *edid, int len) +static struct edid *vidi_get_edid(struct device *dev, + struct drm_connector *connector) { struct vidi_context *ctx = get_vidi_context(dev); + struct edid *edid; + int edid_len; DRM_DEBUG_KMS("%s\n", __FILE__); @@ -111,13 +113,18 @@ static int vidi_get_edid(struct device *dev, struct drm_connector *connector, */ if (!ctx->raw_edid) { DRM_DEBUG_KMS("raw_edid is null.\n"); - return -EFAULT; + return ERR_PTR(-EFAULT); } - memcpy(edid, ctx->raw_edid, min((1 + ctx->raw_edid->extensions) - * EDID_LENGTH, len)); + edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH; + edid = kzalloc(edid_len, GFP_KERNEL); + if (!edid) { + DRM_DEBUG_KMS("failed to allocate edid\n"); + return ERR_PTR(-ENOMEM); + } - return 0; + memcpy(edid, ctx->raw_edid, edid_len); + return edid; } static void *vidi_get_panel(struct device *dev) @@ -514,7 +521,6 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data, struct exynos_drm_manager *manager; struct exynos_drm_display_ops *display_ops; struct drm_exynos_vidi_connection *vidi = data; - struct edid *raw_edid; int edid_len; DRM_DEBUG_KMS("%s\n", __FILE__); @@ -551,11 +557,11 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data, } if (vidi->connection) { - if (!vidi->edid) { - DRM_DEBUG_KMS("edid data is null.\n"); + struct edid *raw_edid = (struct edid *)(uint32_t)vidi->edid; + if (!drm_edid_is_valid(raw_edid)) { + DRM_DEBUG_KMS("edid data is invalid.\n"); return -EINVAL; } - raw_edid = (struct edid *)(uint32_t)vidi->edid; edid_len = (1 + raw_edid->extensions) * EDID_LENGTH; ctx->raw_edid = kzalloc(edid_len, GFP_KERNEL); if (!ctx->raw_edid) { diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 41ff79d8ac8e..fbab3c468603 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -34,7 +34,6 @@ #include <linux/regulator/consumer.h> #include <linux/io.h> #include <linux/of_gpio.h> -#include <plat/gpio-cfg.h> #include <drm/exynos_drm.h> @@ -98,8 +97,7 @@ struct hdmi_context { void __iomem *regs; void *parent_ctx; - int external_irq; - int internal_irq; + int irq; struct i2c_client *ddc_port; struct i2c_client *hdmiphy_port; @@ -1391,8 +1389,7 @@ static bool hdmi_is_connected(void *ctx) return hdata->hpd; } -static int hdmi_get_edid(void *ctx, struct drm_connector *connector, - u8 *edid, int len) +static struct edid *hdmi_get_edid(void *ctx, struct drm_connector *connector) { struct edid *raw_edid; struct hdmi_context *hdata = ctx; @@ -1400,22 +1397,18 @@ static int hdmi_get_edid(void *ctx, struct drm_connector *connector, DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); if (!hdata->ddc_port) - return -ENODEV; + return ERR_PTR(-ENODEV); raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter); - if (raw_edid) { - hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid); - memcpy(edid, raw_edid, min((1 + raw_edid->extensions) - * EDID_LENGTH, len)); - DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n", - (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"), - raw_edid->width_cm, raw_edid->height_cm); - kfree(raw_edid); - } else { - return -ENODEV; - } + if (!raw_edid) + return ERR_PTR(-ENODEV); - return 0; + hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid); + DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n", + (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"), + raw_edid->width_cm, raw_edid->height_cm); + + return raw_edid; } static int hdmi_v13_check_timing(struct fb_videomode *check_timing) @@ -1652,16 +1645,16 @@ static void hdmi_conf_reset(struct hdmi_context *hdata) /* resetting HDMI core */ hdmi_reg_writemask(hdata, reg, 0, HDMI_CORE_SW_RSTOUT); - mdelay(10); + usleep_range(10000, 12000); hdmi_reg_writemask(hdata, reg, ~0, HDMI_CORE_SW_RSTOUT); - mdelay(10); + usleep_range(10000, 12000); } static void hdmi_conf_init(struct hdmi_context *hdata) { struct hdmi_infoframe infoframe; - /* disable HPD interrupts */ + /* disable HPD interrupts from HDMI IP block, use GPIO instead */ hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL | HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG); @@ -1779,7 +1772,7 @@ static void hdmi_v13_timing_apply(struct hdmi_context *hdata) u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS); if (val & HDMI_PHY_STATUS_READY) break; - mdelay(1); + usleep_range(1000, 2000); } /* steady state not achieved */ if (tries == 0) { @@ -1946,7 +1939,7 @@ static void hdmi_v14_timing_apply(struct hdmi_context *hdata) u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0); if (val & HDMI_PHY_STATUS_READY) break; - mdelay(1); + usleep_range(1000, 2000); } /* steady state not achieved */ if (tries == 0) { @@ -1998,9 +1991,9 @@ static void hdmiphy_conf_reset(struct hdmi_context *hdata) /* reset hdmiphy */ hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT); - mdelay(10); + usleep_range(10000, 12000); hdmi_reg_writemask(hdata, reg, 0, HDMI_PHY_SW_RSTOUT); - mdelay(10); + usleep_range(10000, 12000); } static void hdmiphy_poweron(struct hdmi_context *hdata) @@ -2048,7 +2041,7 @@ static void hdmiphy_conf_apply(struct hdmi_context *hdata) return; } - mdelay(10); + usleep_range(10000, 12000); /* operation mode */ operation[0] = 0x1f; @@ -2170,6 +2163,13 @@ static void hdmi_commit(void *ctx) DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); + mutex_lock(&hdata->hdmi_mutex); + if (!hdata->powered) { + mutex_unlock(&hdata->hdmi_mutex); + return; + } + mutex_unlock(&hdata->hdmi_mutex); + hdmi_conf_apply(hdata); } @@ -2265,7 +2265,7 @@ static struct exynos_hdmi_ops hdmi_ops = { .dpms = hdmi_dpms, }; -static irqreturn_t hdmi_external_irq_thread(int irq, void *arg) +static irqreturn_t hdmi_irq_thread(int irq, void *arg) { struct exynos_drm_hdmi_context *ctx = arg; struct hdmi_context *hdata = ctx->ctx; @@ -2280,31 +2280,6 @@ static irqreturn_t hdmi_external_irq_thread(int irq, void *arg) return IRQ_HANDLED; } -static irqreturn_t hdmi_internal_irq_thread(int irq, void *arg) -{ - struct exynos_drm_hdmi_context *ctx = arg; - struct hdmi_context *hdata = ctx->ctx; - u32 intc_flag; - - intc_flag = hdmi_reg_read(hdata, HDMI_INTC_FLAG); - /* clearing flags for HPD plug/unplug */ - if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) { - DRM_DEBUG_KMS("unplugged\n"); - hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0, - HDMI_INTC_FLAG_HPD_UNPLUG); - } - if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) { - DRM_DEBUG_KMS("plugged\n"); - hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0, - HDMI_INTC_FLAG_HPD_PLUG); - } - - if (ctx->drm_dev) - drm_helper_hpd_irq_event(ctx->drm_dev); - - return IRQ_HANDLED; -} - static int hdmi_resources_init(struct hdmi_context *hdata) { struct device *dev = hdata->dev; @@ -2555,39 +2530,24 @@ static int hdmi_probe(struct platform_device *pdev) hdata->hdmiphy_port = hdmi_hdmiphy; - hdata->external_irq = gpio_to_irq(hdata->hpd_gpio); - if (hdata->external_irq < 0) { - DRM_ERROR("failed to get GPIO external irq\n"); - ret = hdata->external_irq; - goto err_hdmiphy; - } - - hdata->internal_irq = platform_get_irq(pdev, 0); - if (hdata->internal_irq < 0) { - DRM_ERROR("failed to get platform internal irq\n"); - ret = hdata->internal_irq; + hdata->irq = gpio_to_irq(hdata->hpd_gpio); + if (hdata->irq < 0) { + DRM_ERROR("failed to get GPIO irq\n"); + ret = hdata->irq; goto err_hdmiphy; } hdata->hpd = gpio_get_value(hdata->hpd_gpio); - ret = request_threaded_irq(hdata->external_irq, NULL, - hdmi_external_irq_thread, IRQF_TRIGGER_RISING | + ret = request_threaded_irq(hdata->irq, NULL, + hdmi_irq_thread, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - "hdmi_external", drm_hdmi_ctx); + "hdmi", drm_hdmi_ctx); if (ret) { - DRM_ERROR("failed to register hdmi external interrupt\n"); + DRM_ERROR("failed to register hdmi interrupt\n"); goto err_hdmiphy; } - ret = request_threaded_irq(hdata->internal_irq, NULL, - hdmi_internal_irq_thread, IRQF_ONESHOT, - "hdmi_internal", drm_hdmi_ctx); - if (ret) { - DRM_ERROR("failed to register hdmi internal interrupt\n"); - goto err_free_irq; - } - /* Attach HDMI Driver to common hdmi. */ exynos_hdmi_drv_attach(drm_hdmi_ctx); @@ -2598,8 +2558,6 @@ static int hdmi_probe(struct platform_device *pdev) return 0; -err_free_irq: - free_irq(hdata->external_irq, drm_hdmi_ctx); err_hdmiphy: i2c_del_driver(&hdmiphy_driver); err_ddc: @@ -2617,8 +2575,7 @@ static int hdmi_remove(struct platform_device *pdev) pm_runtime_disable(dev); - free_irq(hdata->internal_irq, hdata); - free_irq(hdata->external_irq, hdata); + free_irq(hdata->irq, hdata); /* hdmiphy i2c driver */ @@ -2637,8 +2594,7 @@ static int hdmi_suspend(struct device *dev) DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - disable_irq(hdata->internal_irq); - disable_irq(hdata->external_irq); + disable_irq(hdata->irq); hdata->hpd = false; if (ctx->drm_dev) @@ -2663,8 +2619,7 @@ static int hdmi_resume(struct device *dev) hdata->hpd = gpio_get_value(hdata->hpd_gpio); - enable_irq(hdata->external_irq); - enable_irq(hdata->internal_irq); + enable_irq(hdata->irq); if (!pm_runtime_suspended(dev)) { DRM_DEBUG_KMS("%s : Already resumed\n", __func__); diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index c187ea33b748..c414584bfbae 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -600,7 +600,7 @@ static void vp_win_reset(struct mixer_context *ctx) /* waiting until VP_SRESET_PROCESSING is 0 */ if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING) break; - mdelay(10); + usleep_range(10000, 12000); } WARN(tries == 0, "failed to reset Video Processor\n"); } @@ -776,6 +776,13 @@ static void mixer_win_commit(void *ctx, int win) DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win); + mutex_lock(&mixer_ctx->mixer_mutex); + if (!mixer_ctx->powered) { + mutex_unlock(&mixer_ctx->mixer_mutex); + return; + } + mutex_unlock(&mixer_ctx->mixer_mutex); + if (win > 1 && mixer_ctx->vp_enabled) vp_video_buffer(mixer_ctx, win); else diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index e6a11ca85eaf..9d4a2c2adf0e 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -30,6 +30,7 @@ #include <linux/debugfs.h> #include <linux/slab.h> #include <linux/export.h> +#include <generated/utsrelease.h> #include <drm/drmP.h> #include "intel_drv.h" #include "intel_ringbuffer.h" @@ -641,6 +642,7 @@ static void i915_ring_error_state(struct seq_file *m, seq_printf(m, "%s command stream:\n", ring_str(ring)); seq_printf(m, " HEAD: 0x%08x\n", error->head[ring]); seq_printf(m, " TAIL: 0x%08x\n", error->tail[ring]); + seq_printf(m, " CTL: 0x%08x\n", error->ctl[ring]); seq_printf(m, " ACTHD: 0x%08x\n", error->acthd[ring]); seq_printf(m, " IPEIR: 0x%08x\n", error->ipeir[ring]); seq_printf(m, " IPEHR: 0x%08x\n", error->ipehr[ring]); @@ -689,10 +691,13 @@ static int i915_error_state(struct seq_file *m, void *unused) seq_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec, error->time.tv_usec); + seq_printf(m, "Kernel: " UTS_RELEASE); seq_printf(m, "PCI ID: 0x%04x\n", dev->pci_device); seq_printf(m, "EIR: 0x%08x\n", error->eir); seq_printf(m, "IER: 0x%08x\n", error->ier); seq_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er); + seq_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake); + seq_printf(m, "DERRMR: 0x%08x\n", error->derrmr); seq_printf(m, "CCID: 0x%08x\n", error->ccid); for (i = 0; i < dev_priv->num_fence_regs; i++) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ed3059575576..12ab3bdea54d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -188,10 +188,13 @@ struct drm_i915_error_state { u32 pgtbl_er; u32 ier; u32 ccid; + u32 derrmr; + u32 forcewake; bool waiting[I915_NUM_RINGS]; u32 pipestat[I915_MAX_PIPES]; u32 tail[I915_NUM_RINGS]; u32 head[I915_NUM_RINGS]; + u32 ctl[I915_NUM_RINGS]; u32 ipeir[I915_NUM_RINGS]; u32 ipehr[I915_NUM_RINGS]; u32 instdone[I915_NUM_RINGS]; diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index d6a994a07393..26d08bb58218 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -539,6 +539,8 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, total = 0; for (i = 0; i < count; i++) { struct drm_i915_gem_relocation_entry __user *user_relocs; + u64 invalid_offset = (u64)-1; + int j; user_relocs = (void __user *)(uintptr_t)exec[i].relocs_ptr; @@ -549,6 +551,25 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, goto err; } + /* As we do not update the known relocation offsets after + * relocating (due to the complexities in lock handling), + * we need to mark them as invalid now so that we force the + * relocation processing next time. Just in case the target + * object is evicted and then rebound into its old + * presumed_offset before the next execbuffer - if that + * happened we would make the mistake of assuming that the + * relocations were valid. + */ + for (j = 0; j < exec[i].relocation_count; j++) { + if (copy_to_user(&user_relocs[j].presumed_offset, + &invalid_offset, + sizeof(invalid_offset))) { + ret = -EFAULT; + mutex_lock(&dev->struct_mutex); + goto err; + } + } + reloc_offset[i] = total; total += exec[i].relocation_count; } diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 2220dec3e5d9..fe843389c7b4 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1157,6 +1157,7 @@ static void i915_record_ring_state(struct drm_device *dev, error->acthd[ring->id] = intel_ring_get_active_head(ring); error->head[ring->id] = I915_READ_HEAD(ring); error->tail[ring->id] = I915_READ_TAIL(ring); + error->ctl[ring->id] = I915_READ_CTL(ring); error->cpu_ring_head[ring->id] = ring->head; error->cpu_ring_tail[ring->id] = ring->tail; @@ -1251,6 +1252,16 @@ static void i915_capture_error_state(struct drm_device *dev) else error->ier = I915_READ(IER); + if (INTEL_INFO(dev)->gen >= 6) + error->derrmr = I915_READ(DERRMR); + + if (IS_VALLEYVIEW(dev)) + error->forcewake = I915_READ(FORCEWAKE_VLV); + else if (INTEL_INFO(dev)->gen >= 7) + error->forcewake = I915_READ(FORCEWAKE_MT); + else if (INTEL_INFO(dev)->gen == 6) + error->forcewake = I915_READ(FORCEWAKE); + for_each_pipe(pipe) error->pipestat[pipe] = I915_READ(PIPESTAT(pipe)); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 186ee5c85b51..59afb7eb6db6 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -512,6 +512,8 @@ #define GEN7_ERR_INT 0x44040 #define ERR_INT_MMIO_UNCLAIMED (1<<13) +#define DERRMR 0x44050 + /* GM45+ chicken bits -- debug workaround bits that may be required * for various sorts of correct behavior. The top 16 bits of each are * the enables for writing to the corresponding low bit. @@ -531,6 +533,7 @@ #define MI_MODE 0x0209c # define VS_TIMER_DISPATCH (1 << 6) # define MI_FLUSH_ENABLE (1 << 12) +# define ASYNC_FLIP_PERF_DISABLE (1 << 14) #define GEN6_GT_MODE 0x20d0 #define GEN6_GT_MODE_HI (1 << 9) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1b63d55318a0..fb3715b4b09d 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2579,7 +2579,8 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect static void intel_dp_init_panel_power_sequencer(struct drm_device *dev, - struct intel_dp *intel_dp) + struct intel_dp *intel_dp, + struct edp_power_seq *out) { struct drm_i915_private *dev_priv = dev->dev_private; struct edp_power_seq cur, vbt, spec, final; @@ -2650,16 +2651,35 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, intel_dp->panel_power_cycle_delay = get_delay(t11_t12); #undef get_delay + DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n", + intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay, + intel_dp->panel_power_cycle_delay); + + DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n", + intel_dp->backlight_on_delay, intel_dp->backlight_off_delay); + + if (out) + *out = final; +} + +static void +intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, + struct intel_dp *intel_dp, + struct edp_power_seq *seq) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 pp_on, pp_off, pp_div; + /* And finally store the new values in the power sequencer. */ - pp_on = (final.t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) | - (final.t8 << PANEL_LIGHT_ON_DELAY_SHIFT); - pp_off = (final.t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) | - (final.t10 << PANEL_POWER_DOWN_DELAY_SHIFT); + pp_on = (seq->t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) | + (seq->t8 << PANEL_LIGHT_ON_DELAY_SHIFT); + pp_off = (seq->t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) | + (seq->t10 << PANEL_POWER_DOWN_DELAY_SHIFT); /* Compute the divisor for the pp clock, simply match the Bspec * formula. */ pp_div = ((100 * intel_pch_rawclk(dev))/2 - 1) << PP_REFERENCE_DIVIDER_SHIFT; - pp_div |= (DIV_ROUND_UP(final.t11_t12, 1000) + pp_div |= (DIV_ROUND_UP(seq->t11_t12, 1000) << PANEL_POWER_CYCLE_DELAY_SHIFT); /* Haswell doesn't have any port selection bits for the panel @@ -2675,14 +2695,6 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, I915_WRITE(PCH_PP_OFF_DELAYS, pp_off); I915_WRITE(PCH_PP_DIVISOR, pp_div); - - DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n", - intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay, - intel_dp->panel_power_cycle_delay); - - DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n", - intel_dp->backlight_on_delay, intel_dp->backlight_off_delay); - DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n", I915_READ(PCH_PP_ON_DELAYS), I915_READ(PCH_PP_OFF_DELAYS), @@ -2699,6 +2711,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, struct drm_device *dev = intel_encoder->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_display_mode *fixed_mode = NULL; + struct edp_power_seq power_seq = { 0 }; enum port port = intel_dig_port->port; const char *name = NULL; int type; @@ -2771,7 +2784,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, } if (is_edp(intel_dp)) - intel_dp_init_panel_power_sequencer(dev, intel_dp); + intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq); intel_dp_i2c_init(intel_dp, intel_connector, name); @@ -2798,6 +2811,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, return; } + /* We now know it's not a ghost, init power sequence regs. */ + intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, + &power_seq); + ironlake_edp_panel_vdd_on(intel_dp); edid = drm_get_edid(connector, &intel_dp->adapter); if (edid) { diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index e83a11794172..3280cffe50f4 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4250,7 +4250,8 @@ static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) static void __gen6_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv) { I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(0xffff)); - POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */ + /* something from same cacheline, but !FORCEWAKE_MT */ + POSTING_READ(ECOBUS); } static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) @@ -4267,7 +4268,8 @@ static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n"); I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL)); - POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */ + /* something from same cacheline, but !FORCEWAKE_MT */ + POSTING_READ(ECOBUS); if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1), FORCEWAKE_ACK_TIMEOUT_MS)) @@ -4304,14 +4306,16 @@ void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv) static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) { I915_WRITE_NOTRACE(FORCEWAKE, 0); - /* gen6_gt_check_fifodbg doubles as the POSTING_READ */ + /* something from same cacheline, but !FORCEWAKE */ + POSTING_READ(ECOBUS); gen6_gt_check_fifodbg(dev_priv); } static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) { I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); - /* gen6_gt_check_fifodbg doubles as the POSTING_READ */ + /* something from same cacheline, but !FORCEWAKE_MT */ + POSTING_READ(ECOBUS); gen6_gt_check_fifodbg(dev_priv); } @@ -4351,6 +4355,8 @@ int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) static void vlv_force_wake_reset(struct drm_i915_private *dev_priv) { I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(0xffff)); + /* something from same cacheline, but !FORCEWAKE_VLV */ + POSTING_READ(FORCEWAKE_ACK_VLV); } static void vlv_force_wake_get(struct drm_i915_private *dev_priv) @@ -4371,7 +4377,8 @@ static void vlv_force_wake_get(struct drm_i915_private *dev_priv) static void vlv_force_wake_put(struct drm_i915_private *dev_priv) { I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); - /* The below doubles as a POSTING_READ */ + /* something from same cacheline, but !FORCEWAKE_VLV */ + POSTING_READ(FORCEWAKE_ACK_VLV); gen6_gt_check_fifodbg(dev_priv); } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index ae253e04c391..42ff97d667d2 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -505,13 +505,25 @@ static int init_render_ring(struct intel_ring_buffer *ring) struct drm_i915_private *dev_priv = dev->dev_private; int ret = init_ring_common(ring); - if (INTEL_INFO(dev)->gen > 3) { + if (INTEL_INFO(dev)->gen > 3) I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH)); - if (IS_GEN7(dev)) - I915_WRITE(GFX_MODE_GEN7, - _MASKED_BIT_DISABLE(GFX_TLB_INVALIDATE_ALWAYS) | - _MASKED_BIT_ENABLE(GFX_REPLAY_MODE)); - } + + /* We need to disable the AsyncFlip performance optimisations in order + * to use MI_WAIT_FOR_EVENT within the CS. It should already be + * programmed to '1' on all products. + */ + if (INTEL_INFO(dev)->gen >= 6) + I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE)); + + /* Required for the hardware to program scanline values for waiting */ + if (INTEL_INFO(dev)->gen == 6) + I915_WRITE(GFX_MODE, + _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_ALWAYS)); + + if (IS_GEN7(dev)) + I915_WRITE(GFX_MODE_GEN7, + _MASKED_BIT_DISABLE(GFX_TLB_INVALIDATE_ALWAYS) | + _MASKED_BIT_ENABLE(GFX_REPLAY_MODE)); if (INTEL_INFO(dev)->gen >= 5) { ret = init_pipe_control(ring); diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 061fa0a28900..4d0e60adbc6d 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -2401,6 +2401,12 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) { struct evergreen_mc_save save; + if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) + reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE); + + if (RREG32(DMA_STATUS_REG) & DMA_IDLE) + reset_mask &= ~RADEON_RESET_DMA; + if (reset_mask == 0) return 0; diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 896f1cbc58a5..835992d8d067 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -1216,7 +1216,7 @@ void cayman_dma_stop(struct radeon_device *rdev) int cayman_dma_resume(struct radeon_device *rdev) { struct radeon_ring *ring; - u32 rb_cntl, dma_cntl; + u32 rb_cntl, dma_cntl, ib_cntl; u32 rb_bufsz; u32 reg_offset, wb_offset; int i, r; @@ -1265,7 +1265,11 @@ int cayman_dma_resume(struct radeon_device *rdev) WREG32(DMA_RB_BASE + reg_offset, ring->gpu_addr >> 8); /* enable DMA IBs */ - WREG32(DMA_IB_CNTL + reg_offset, DMA_IB_ENABLE | CMD_VMID_FORCE); + ib_cntl = DMA_IB_ENABLE | CMD_VMID_FORCE; +#ifdef __BIG_ENDIAN + ib_cntl |= DMA_IB_SWAP_ENABLE; +#endif + WREG32(DMA_IB_CNTL + reg_offset, ib_cntl); dma_cntl = RREG32(DMA_CNTL + reg_offset); dma_cntl &= ~CTXEMPTY_INT_ENABLE; @@ -1409,6 +1413,12 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) { struct evergreen_mc_save save; + if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) + reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE); + + if (RREG32(DMA_STATUS_REG) & DMA_IDLE) + reset_mask &= ~RADEON_RESET_DMA; + if (reset_mask == 0) return 0; diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 537e259b3837..bc2540b17c5e 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1378,6 +1378,12 @@ static int r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) { struct rv515_mc_save save; + if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) + reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE); + + if (RREG32(DMA_STATUS_REG) & DMA_IDLE) + reset_mask &= ~RADEON_RESET_DMA; + if (reset_mask == 0) return 0; @@ -2307,7 +2313,7 @@ void r600_dma_stop(struct radeon_device *rdev) int r600_dma_resume(struct radeon_device *rdev) { struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; - u32 rb_cntl, dma_cntl; + u32 rb_cntl, dma_cntl, ib_cntl; u32 rb_bufsz; int r; @@ -2347,7 +2353,11 @@ int r600_dma_resume(struct radeon_device *rdev) WREG32(DMA_RB_BASE, ring->gpu_addr >> 8); /* enable DMA IBs */ - WREG32(DMA_IB_CNTL, DMA_IB_ENABLE); + ib_cntl = DMA_IB_ENABLE; +#ifdef __BIG_ENDIAN + ib_cntl |= DMA_IB_SWAP_ENABLE; +#endif + WREG32(DMA_IB_CNTL, ib_cntl); dma_cntl = RREG32(DMA_CNTL); dma_cntl &= ~CTXEMPTY_INT_ENABLE; diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 34e52304a525..a08f657329a0 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -324,7 +324,6 @@ struct radeon_bo { struct list_head list; /* Protected by tbo.reserved */ u32 placements[3]; - u32 busy_placements[3]; struct ttm_placement placement; struct ttm_buffer_object tbo; struct ttm_bo_kmap_obj kmap; @@ -654,6 +653,8 @@ struct radeon_ring { u32 ptr_reg_mask; u32 nop; u32 idx; + u64 last_semaphore_signal_addr; + u64 last_semaphore_wait_addr; }; /* diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 469661fd1903..5407459e56d2 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -286,6 +286,8 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) p->chunks[p->chunk_ib_idx].kpage[1] == NULL) { kfree(p->chunks[p->chunk_ib_idx].kpage[0]); kfree(p->chunks[p->chunk_ib_idx].kpage[1]); + p->chunks[p->chunk_ib_idx].kpage[0] = NULL; + p->chunks[p->chunk_ib_idx].kpage[1] = NULL; return -ENOMEM; } } diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index ad6df625e8b8..0d67674b64b1 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c @@ -241,7 +241,8 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, y = 0; } - if (ASIC_IS_AVIVO(rdev)) { + /* fixed on DCE6 and newer */ + if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE6(rdev)) { int i = 0; struct drm_crtc *crtc_p; diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index edfc54e41842..0d6562bb0c93 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -429,7 +429,8 @@ bool radeon_card_posted(struct radeon_device *rdev) { uint32_t reg; - if (efi_enabled && rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) + if (efi_enabled(EFI_BOOT) && + rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) return false; /* first check CRTCs */ diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 1da2386d7cf7..ff3def784619 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -1122,7 +1122,7 @@ radeon_user_framebuffer_create(struct drm_device *dev, if (ret) { kfree(radeon_fb); drm_gem_object_unreference_unlocked(obj); - return NULL; + return ERR_PTR(ret); } return &radeon_fb->base; diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index dff6cf77f953..d9bf96ee299a 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -69,9 +69,10 @@ * 2.26.0 - r600-eg: fix htile size computation * 2.27.0 - r600-SI: Add CS ioctl support for async DMA * 2.28.0 - r600-eg: Add MEM_WRITE packet support + * 2.29.0 - R500 FP16 color clear registers */ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 28 +#define KMS_DRIVER_MINOR 29 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 883c95d8d90f..d3aface2d12d 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -84,6 +84,7 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) rbo->placement.fpfn = 0; rbo->placement.lpfn = 0; rbo->placement.placement = rbo->placements; + rbo->placement.busy_placement = rbo->placements; if (domain & RADEON_GEM_DOMAIN_VRAM) rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM; @@ -104,14 +105,6 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) if (!c) rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM; rbo->placement.num_placement = c; - - c = 0; - rbo->placement.busy_placement = rbo->busy_placements; - if (rbo->rdev->flags & RADEON_IS_AGP) { - rbo->busy_placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_TT; - } else { - rbo->busy_placements[c++] = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_TT; - } rbo->placement.num_busy_placement = c; } @@ -357,6 +350,7 @@ int radeon_bo_list_validate(struct list_head *head) { struct radeon_bo_list *lobj; struct radeon_bo *bo; + u32 domain; int r; r = ttm_eu_reserve_buffers(head); @@ -366,9 +360,17 @@ int radeon_bo_list_validate(struct list_head *head) list_for_each_entry(lobj, head, tv.head) { bo = lobj->bo; if (!bo->pin_count) { + domain = lobj->wdomain ? lobj->wdomain : lobj->rdomain; + + retry: + radeon_ttm_placement_from_domain(bo, domain); r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false); if (unlikely(r)) { + if (r != -ERESTARTSYS && domain == RADEON_GEM_DOMAIN_VRAM) { + domain |= RADEON_GEM_DOMAIN_GTT; + goto retry; + } return r; } } diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index 141f2b6a9cf2..2430d80b1871 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c @@ -784,6 +784,8 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data) } seq_printf(m, "driver's copy of the wptr: 0x%08x [%5d]\n", ring->wptr, ring->wptr); seq_printf(m, "driver's copy of the rptr: 0x%08x [%5d]\n", ring->rptr, ring->rptr); + seq_printf(m, "last semaphore signal addr : 0x%016llx\n", ring->last_semaphore_signal_addr); + seq_printf(m, "last semaphore wait addr : 0x%016llx\n", ring->last_semaphore_wait_addr); seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw); seq_printf(m, "%u dwords in ring\n", count); /* print 8 dw before current rptr as often it's the last executed diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c b/drivers/gpu/drm/radeon/radeon_semaphore.c index 97f3ece81cd2..8dcc20f53d73 100644 --- a/drivers/gpu/drm/radeon/radeon_semaphore.c +++ b/drivers/gpu/drm/radeon/radeon_semaphore.c @@ -95,6 +95,10 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev, /* we assume caller has already allocated space on waiters ring */ radeon_semaphore_emit_wait(rdev, waiter, semaphore); + /* for debugging lockup only, used by sysfs debug files */ + rdev->ring[signaler].last_semaphore_signal_addr = semaphore->gpu_addr; + rdev->ring[waiter].last_semaphore_wait_addr = semaphore->gpu_addr; + return 0; } diff --git a/drivers/gpu/drm/radeon/reg_srcs/rv515 b/drivers/gpu/drm/radeon/reg_srcs/rv515 index 911a8fbd32bb..78d5e99d759d 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/rv515 +++ b/drivers/gpu/drm/radeon/reg_srcs/rv515 @@ -324,6 +324,8 @@ rv515 0x6d40 0x46AC US_OUT_FMT_2 0x46B0 US_OUT_FMT_3 0x46B4 US_W_FMT +0x46C0 RB3D_COLOR_CLEAR_VALUE_AR +0x46C4 RB3D_COLOR_CLEAR_VALUE_GB 0x4BC0 FG_FOG_BLEND 0x4BC4 FG_FOG_FACTOR 0x4BC8 FG_FOG_COLOR_R diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 3240a3d64f30..ae8b48205a6c 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -2215,6 +2215,12 @@ static int si_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) { struct evergreen_mc_save save; + if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) + reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE); + + if (RREG32(DMA_STATUS_REG) & DMA_IDLE) + reset_mask &= ~RADEON_RESET_DMA; + if (reset_mask == 0) return 0; diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 656b2e3334a6..56813f967c8f 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -12,8 +12,7 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> - -#include <mach/clk.h> +#include <linux/clk/tegra.h> #include "drm.h" #include "dc.h" diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 3a503c9e4686..d980dc75788c 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -11,7 +11,6 @@ #include <linux/of_address.h> #include <linux/of_platform.h> -#include <mach/clk.h> #include <linux/dma-mapping.h> #include <asm/dma-iommu.h> diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c index e060c7e6434d..92ad276cc5e0 100644 --- a/drivers/gpu/drm/tegra/hdmi.c +++ b/drivers/gpu/drm/tegra/hdmi.c @@ -14,8 +14,7 @@ #include <linux/of.h> #include <linux/platform_device.h> #include <linux/regulator/consumer.h> - -#include <mach/clk.h> +#include <linux/clk/tegra.h> #include "hdmi.h" #include "drm.h" diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 33d20be87db5..52b20b12c83a 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -434,6 +434,7 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, bo->mem = tmp_mem; bdev->driver->move_notify(bo, mem); bo->mem = *mem; + *mem = tmp_mem; } goto out_err; diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index d73d6e3e17b2..44420fca7dfa 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -344,8 +344,12 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, if (ttm->state == tt_unpopulated) { ret = ttm->bdev->driver->ttm_tt_populate(ttm); - if (ret) + if (ret) { + /* if we fail here don't nuke the mm node + * as the bo still owns it */ + old_copy.mm_node = NULL; goto out1; + } } add = 0; @@ -371,8 +375,11 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, prot); } else ret = ttm_copy_io_page(new_iomap, old_iomap, page); - if (ret) + if (ret) { + /* failing here, means keep old copy as-is */ + old_copy.mm_node = NULL; goto out1; + } } mb(); out2: |