Merge "drm/msm/sde: fix msm drm driver probe sequence" into msm-4.8
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 9fa1a20..50d34d16 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -17,6 +17,7 @@
*/
#include <linux/of_address.h>
+#include <linux/kthread.h>
#include "msm_drv.h"
#include "msm_debugfs.h"
#include "msm_fence.h"
@@ -222,8 +223,9 @@
static int msm_drm_uninit(struct device *dev)
{
- struct msm_drm_private *priv = dev->dev_private;
- struct platform_device *pdev = dev->platformdev;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct drm_device *ddev = platform_get_drvdata(pdev);
+ struct msm_drm_private *priv = ddev->dev_private;
struct msm_kms *kms = priv->kms;
struct msm_gpu *gpu = priv->gpu;
struct msm_vblank_ctrl *vbl_ctrl = &priv->vblank_ctrl;
@@ -243,6 +245,9 @@
drm_kms_helper_poll_fini(ddev);
+ drm_mode_config_cleanup(ddev);
+ drm_vblank_cleanup(ddev);
+
drm_dev_unregister(ddev);
#ifdef CONFIG_DRM_FBDEV_EMULATION
@@ -284,21 +289,25 @@
sde_power_client_destroy(&priv->phandle, priv->pclient);
sde_power_resource_deinit(pdev, &priv->phandle);
- component_unbind_all(dev->dev, dev);
+ component_unbind_all(dev, ddev);
+
+ sde_power_client_destroy(&priv->phandle, priv->pclient);
+
+ sde_power_resource_deinit(pdev, &priv->phandle);
msm_mdss_destroy(ddev);
ddev->dev_private = NULL;
- drm_dev_unref(ddev);
-
kfree(priv);
+ drm_dev_unref(ddev);
+
return 0;
}
-#define KMS_MDP4 0
-#define KMS_MDP5 1
-#define KMS_SDE 2
+#define KMS_MDP4 4
+#define KMS_MDP5 5
+#define KMS_SDE 3
static int get_mdp_ver(struct platform_device *pdev)
{
@@ -425,33 +434,43 @@
struct msm_kms *kms;
int ret;
+ ddev = drm_dev_alloc(drv, dev);
+ if (!ddev) {
+ dev_err(dev, "failed to allocate drm_device\n");
+ return -ENOMEM;
+ }
+
+ drm_mode_config_init(ddev);
+ platform_set_drvdata(pdev, ddev);
+ ddev->platformdev = pdev;
+
+ ret = drm_dev_register(ddev, 0);
+ if (ret)
+ goto fail;
+
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) {
- drm_dev_unref(ddev);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto priv_alloc_fail;
}
ddev->dev_private = priv;
priv->dev = ddev;
+ ret = msm_mdss_init(ddev);
+ if (ret)
+ goto mdss_init_fail;
+
priv->wq = alloc_ordered_workqueue("msm_drm", 0);
- init_waitqueue_head(&priv->fence_event);
+ priv->atomic_wq = alloc_ordered_workqueue("msm:atomic", 0);
init_waitqueue_head(&priv->pending_crtcs_event);
INIT_LIST_HEAD(&priv->client_event_list);
INIT_LIST_HEAD(&priv->inactive_list);
- INIT_LIST_HEAD(&priv->fence_cbs);
INIT_LIST_HEAD(&priv->vblank_ctrl.event_list);
- init_kthread_work(&priv->vblank_ctrl.work, vblank_ctrl_worker);
+ INIT_WORK(&priv->vblank_ctrl.work, vblank_ctrl_worker);
spin_lock_init(&priv->vblank_ctrl.lock);
- drm_mode_config_init(dev);
-
- priv->wq = alloc_ordered_workqueue("msm", 0);
- priv->atomic_wq = alloc_ordered_workqueue("msm:atomic", 0);
- init_waitqueue_head(&priv->fence_event);
- init_waitqueue_head(&priv->pending_crtcs_event);
-
ret = sde_power_resource_init(pdev, &priv->phandle);
if (ret) {
pr_err("sde power resource init failed\n");
@@ -466,30 +485,29 @@
}
/* Bind all our sub-components: */
- ret = msm_component_bind_all(dev->dev, dev);
+ ret = msm_component_bind_all(dev, ddev);
if (ret)
return ret;
- }
ret = msm_init_vram(ddev);
if (ret)
goto fail;
- ret = sde_evtlog_init(dev->primary->debugfs_root);
+ ret = sde_evtlog_init(ddev->primary->debugfs_root);
if (ret) {
- dev_err(dev->dev, "failed to init evtlog: %d\n", ret);
+ dev_err(dev, "failed to init evtlog: %d\n", ret);
goto fail;
}
switch (get_mdp_ver(pdev)) {
case KMS_MDP4:
- kms = mdp4_kms_init(dev);
+ kms = mdp4_kms_init(ddev);
break;
case KMS_MDP5:
- kms = mdp5_kms_init(dev);
+ kms = mdp5_kms_init(ddev);
break;
case KMS_SDE:
- kms = sde_kms_init(dev);
+ kms = sde_kms_init(ddev);
break;
default:
kms = ERR_PTR(-ENODEV);
@@ -504,10 +522,12 @@
* imx drm driver on iMX5
*/
priv->kms = NULL;
- dev_err(dev->dev, "failed to load kms\n");
+ dev_err(dev, "failed to load kms\n");
ret = PTR_ERR(kms);
goto fail;
}
+ priv->kms = kms;
+ pm_runtime_enable(dev);
if (kms) {
ret = kms->funcs->hw_init(kms);
@@ -516,7 +536,6 @@
goto fail;
}
}
-
ddev->mode_config.funcs = &mode_config_funcs;
ret = drm_vblank_init(ddev, priv->num_crtcs);
@@ -527,7 +546,7 @@
if (kms) {
pm_runtime_get_sync(dev);
- ret = drm_irq_install(ddev, kms->irq);
+ ret = drm_irq_install(ddev, platform_get_irq(pdev, 0));
pm_runtime_put_sync(dev);
if (ret < 0) {
dev_err(dev, "failed to install IRQ handler\n");
@@ -535,9 +554,6 @@
}
}
- ret = drm_dev_register(ddev, 0);
- if (ret)
- goto fail;
drm_mode_config_reset(ddev);
@@ -554,18 +570,23 @@
if (kms && kms->funcs && kms->funcs->postinit) {
ret = kms->funcs->postinit(kms);
if (ret) {
- dev_err(dev->dev, "kms post init failed: %d\n", ret);
+ pr_err("kms post init failed: %d\n", ret);
goto fail;
}
}
- drm_kms_helper_poll_init(dev);
+ drm_kms_helper_poll_init(ddev);
return 0;
fail:
msm_drm_uninit(dev);
return ret;
+mdss_init_fail:
+ kfree(priv);
+priv_alloc_fail:
+ drm_dev_unref(ddev);
+ return ret;
}
/*
@@ -1092,27 +1113,6 @@
SET_SYSTEM_SLEEP_PM_OPS(msm_pm_suspend, msm_pm_resume)
};
-static int msm_drm_bind(struct device *dev)
-{
- int ret;
-
- ret = drm_platform_init(&msm_driver, to_platform_device(dev));
- if (ret)
- DRM_ERROR("drm_platform_init failed: %d\n", ret);
-
- return ret;
-}
-
-static void msm_drm_unbind(struct device *dev)
-{
- drm_put_dev(platform_get_drvdata(to_platform_device(dev)));
-}
-
-static const struct component_master_ops msm_drm_ops = {
- .bind = msm_drm_bind,
- .unbind = msm_drm_unbind,
-};
-
/*
* Componentized driver support:
*/
@@ -1196,11 +1196,64 @@
static int compare_name_mdp(struct device *dev, void *data)
{
+ return (strnstr(dev_name(dev), "mdp", strlen("mdp")) != NULL);
+}
+
+static int add_display_components(struct device *dev,
+ struct component_match **matchptr)
+{
+ struct device *mdp_dev = NULL;
int ret;
- ret = component_master_add_with_match(dev, &msm_drm_ops, match);
+ if (of_device_is_compatible(dev->of_node, "qcom,sde-kms")) {
+ struct device_node *np = dev->of_node;
+ unsigned int i;
+
+ for (i = 0; ; i++) {
+ struct device_node *node;
+
+ node = of_parse_phandle(np, "connectors", i);
+ if (!node)
+ break;
+
+ component_match_add(dev, matchptr, compare_of, node);
+ }
+ return 0;
+ }
+
+ /*
+ * MDP5 based devices don't have a flat hierarchy. There is a top level
+ * parent: MDSS, and children: MDP5, DSI, HDMI, eDP etc. Populate the
+ * children devices, find the MDP5 node, and then add the interfaces
+ * to our components list.
+ */
+ if (of_device_is_compatible(dev->of_node, "qcom,mdss")) {
+ ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
+ if (ret) {
+ dev_err(dev, "failed to populate children devices\n");
+ return ret;
+ }
+
+ mdp_dev = device_find_child(dev, NULL, compare_name_mdp);
+ if (!mdp_dev) {
+ dev_err(dev, "failed to find MDSS MDP node\n");
+ of_platform_depopulate(dev);
+ return -ENODEV;
+ }
+
+ put_device(mdp_dev);
+
+ /* add the MDP component itself */
+ component_match_add(dev, matchptr, compare_of,
+ mdp_dev->of_node);
+ } else {
+ /* MDP4 */
+ mdp_dev = dev;
+ }
+
+ ret = add_components_mdp(mdp_dev, matchptr);
if (ret)
- DRM_ERROR("component add match failed: %d\n", ret);
+ of_platform_depopulate(dev);
return ret;
}
@@ -1232,18 +1285,20 @@
return 0;
}
-#else
-static int compare_dev(struct device *dev, void *data)
+static int msm_drm_bind(struct device *dev)
{
return msm_drm_init(dev, &msm_driver);
}
-static int msm_add_master_component(struct device *dev,
- struct component_match *match)
+static void msm_drm_unbind(struct device *dev)
{
msm_drm_uninit(dev);
}
-#endif
+
+static const struct component_master_ops msm_drm_ops = {
+ .bind = msm_drm_bind,
+ .unbind = msm_drm_unbind,
+};
/*
* Platform driver:
@@ -1254,49 +1309,31 @@
int ret;
struct component_match *match = NULL;
-#ifdef CONFIG_OF
- add_components(&pdev->dev, &match, "connectors");
- add_components(&pdev->dev, &match, "gpus");
-#else
- /* For non-DT case, it kinda sucks. We don't actually have a way
- * to know whether or not we are waiting for certain devices (or if
- * they are simply not present). But for non-DT we only need to
- * care about apq8064/apq8060/etc (all mdp4/a3xx):
- */
- static const char * const devnames[] = {
- "hdmi_msm.0", "kgsl-3d0.0",
- };
- int i;
-
- DBG("Adding components..");
-
- for (i = 0; i < ARRAY_SIZE(devnames); i++) {
- struct device *dev;
-
ret = add_display_components(&pdev->dev, &match);
if (ret)
return ret;
- component_match_add(&pdev->dev, &match, compare_dev, dev);
- }
-#endif
- pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
- ret = msm_add_master_component(&pdev->dev, match);
+ ret = add_gpu_components(&pdev->dev, &match);
+ if (ret)
+ return ret;
- return ret;
+ pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+ return component_master_add_with_match(&pdev->dev, &msm_drm_ops, match);
}
static int msm_pdev_remove(struct platform_device *pdev)
{
- msm_drm_unbind(&pdev->dev);
component_master_del(&pdev->dev, &msm_drm_ops);
+ of_platform_depopulate(&pdev->dev);
+
+ msm_drm_unbind(&pdev->dev);
return 0;
}
static const struct of_device_id dt_match[] = {
- { .compatible = "qcom,mdp" }, /* mdp4 */
- { .compatible = "qcom,mdss_mdp" }, /* mdp5 */
- { .compatible = "qcom,sde-kms" }, /* sde */
+ { .compatible = "qcom,mdp4", .data = (void *)4 }, /* MDP4 */
+ { .compatible = "qcom,mdss", .data = (void *)5 }, /* MDP5 MDSS */
+ { .compatible = "qcom,sde-kms", .data = (void *)3 }, /* sde */
{}
};
MODULE_DEVICE_TABLE(of, dt_match);
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 869833f6..e6fdeb9 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -232,7 +232,6 @@
struct msm_drm_event {
struct drm_pending_event base;
struct drm_event event;
- struct drm_msm_event_req info;
u8 data[];
};
@@ -326,6 +325,12 @@
struct msm_vblank_ctrl vblank_ctrl;
+ /* task holding struct_mutex.. currently only used in submit path
+ * to detect and reject faults from copy_from_user() for submit
+ * ioctl.
+ */
+ struct task_struct *struct_mutex_task;
+
/* list of clients waiting for events */
struct list_head client_event_list;
};
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index 9d4e04b..c4cc729 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -960,7 +960,7 @@
ret = PTR_ERR(mmu);
SDE_ERROR("failed to init iommu id %d: rc: %d\n", i,
ret);
- goto fail;
+ continue;
}
ret = mmu->funcs->attach(mmu, (const char **)iommu_ports,
@@ -968,7 +968,7 @@
if (ret) {
SDE_ERROR("failed to attach iommu %d: %d\n", i, ret);
mmu->funcs->destroy(mmu);
- goto fail;
+ continue;
}
sde_kms->mmu_id[i] = msm_register_mmu(sde_kms->dev, mmu);