diff options
author | Thierry Reding <treding@nvidia.com> | 2016-02-24 12:34:43 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2016-02-24 21:20:59 -0500 |
commit | 870571a5698b2e9d0f4d2e5c6245967b582aab45 (patch) | |
tree | 07007eaad18c24e2edaa7cb2396fb6561125d8f0 | |
parent | 398cb0c93b18b625703db30d874351e6d4cc645a (diff) |
drm/nouveau: platform: Fix deferred probe
The error cleanup paths aren't quite correct and will crash upon
deferred probe.
Cc: stable@vger.kernel.org # v4.3+
Reviewed-by: Ben Skeggs <bskeggs@redhat.com>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_platform.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c | 40 |
2 files changed, 30 insertions, 12 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_platform.c b/drivers/gpu/drm/nouveau/nouveau_platform.c index 8a70cec59bcd..2dfe58af12e4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_platform.c +++ b/drivers/gpu/drm/nouveau/nouveau_platform.c | |||
@@ -24,7 +24,7 @@ | |||
24 | static int nouveau_platform_probe(struct platform_device *pdev) | 24 | static int nouveau_platform_probe(struct platform_device *pdev) |
25 | { | 25 | { |
26 | const struct nvkm_device_tegra_func *func; | 26 | const struct nvkm_device_tegra_func *func; |
27 | struct nvkm_device *device; | 27 | struct nvkm_device *device = NULL; |
28 | struct drm_device *drm; | 28 | struct drm_device *drm; |
29 | int ret; | 29 | int ret; |
30 | 30 | ||
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c index 7f8a42721eb2..e7e581d6a8ff 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c | |||
@@ -252,32 +252,40 @@ nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func, | |||
252 | 252 | ||
253 | if (!(tdev = kzalloc(sizeof(*tdev), GFP_KERNEL))) | 253 | if (!(tdev = kzalloc(sizeof(*tdev), GFP_KERNEL))) |
254 | return -ENOMEM; | 254 | return -ENOMEM; |
255 | *pdevice = &tdev->device; | 255 | |
256 | tdev->func = func; | 256 | tdev->func = func; |
257 | tdev->pdev = pdev; | 257 | tdev->pdev = pdev; |
258 | tdev->irq = -1; | 258 | tdev->irq = -1; |
259 | 259 | ||
260 | tdev->vdd = devm_regulator_get(&pdev->dev, "vdd"); | 260 | tdev->vdd = devm_regulator_get(&pdev->dev, "vdd"); |
261 | if (IS_ERR(tdev->vdd)) | 261 | if (IS_ERR(tdev->vdd)) { |
262 | return PTR_ERR(tdev->vdd); | 262 | ret = PTR_ERR(tdev->vdd); |
263 | goto free; | ||
264 | } | ||
263 | 265 | ||
264 | tdev->rst = devm_reset_control_get(&pdev->dev, "gpu"); | 266 | tdev->rst = devm_reset_control_get(&pdev->dev, "gpu"); |
265 | if (IS_ERR(tdev->rst)) | 267 | if (IS_ERR(tdev->rst)) { |
266 | return PTR_ERR(tdev->rst); | 268 | ret = PTR_ERR(tdev->rst); |
269 | goto free; | ||
270 | } | ||
267 | 271 | ||
268 | tdev->clk = devm_clk_get(&pdev->dev, "gpu"); | 272 | tdev->clk = devm_clk_get(&pdev->dev, "gpu"); |
269 | if (IS_ERR(tdev->clk)) | 273 | if (IS_ERR(tdev->clk)) { |
270 | return PTR_ERR(tdev->clk); | 274 | ret = PTR_ERR(tdev->clk); |
275 | goto free; | ||
276 | } | ||
271 | 277 | ||
272 | tdev->clk_pwr = devm_clk_get(&pdev->dev, "pwr"); | 278 | tdev->clk_pwr = devm_clk_get(&pdev->dev, "pwr"); |
273 | if (IS_ERR(tdev->clk_pwr)) | 279 | if (IS_ERR(tdev->clk_pwr)) { |
274 | return PTR_ERR(tdev->clk_pwr); | 280 | ret = PTR_ERR(tdev->clk_pwr); |
281 | goto free; | ||
282 | } | ||
275 | 283 | ||
276 | nvkm_device_tegra_probe_iommu(tdev); | 284 | nvkm_device_tegra_probe_iommu(tdev); |
277 | 285 | ||
278 | ret = nvkm_device_tegra_power_up(tdev); | 286 | ret = nvkm_device_tegra_power_up(tdev); |
279 | if (ret) | 287 | if (ret) |
280 | return ret; | 288 | goto remove; |
281 | 289 | ||
282 | tdev->gpu_speedo = tegra_sku_info.gpu_speedo_value; | 290 | tdev->gpu_speedo = tegra_sku_info.gpu_speedo_value; |
283 | ret = nvkm_device_ctor(&nvkm_device_tegra_func, NULL, &pdev->dev, | 291 | ret = nvkm_device_ctor(&nvkm_device_tegra_func, NULL, &pdev->dev, |
@@ -285,9 +293,19 @@ nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func, | |||
285 | cfg, dbg, detect, mmio, subdev_mask, | 293 | cfg, dbg, detect, mmio, subdev_mask, |
286 | &tdev->device); | 294 | &tdev->device); |
287 | if (ret) | 295 | if (ret) |
288 | return ret; | 296 | goto powerdown; |
297 | |||
298 | *pdevice = &tdev->device; | ||
289 | 299 | ||
290 | return 0; | 300 | return 0; |
301 | |||
302 | powerdown: | ||
303 | nvkm_device_tegra_power_down(tdev); | ||
304 | remove: | ||
305 | nvkm_device_tegra_remove_iommu(tdev); | ||
306 | free: | ||
307 | kfree(tdev); | ||
308 | return ret; | ||
291 | } | 309 | } |
292 | #else | 310 | #else |
293 | int | 311 | int |