diff options
author | Dave Airlie <airlied@redhat.com> | 2018-07-05 16:28:05 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2018-07-05 16:29:24 -0400 |
commit | 96b2bb0b9637df1a68bb5b6853903a207fabcefd (patch) | |
tree | 6f9d61aeb2a46c0492aa18a98b77106c84306724 /drivers | |
parent | f29135ee4e0d4e01911ed569f731bfdb841cea6d (diff) | |
parent | f8466184bd5b5c21eb6196cd0e44668725a2e47a (diff) |
Merge tag 'omapdrm-4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux into drm-next
omapdrm changes for 4.19
* Workaround for DRA7 errata i932
* Fix mm_list locking
* Cleanups
Signed-off-by: Dave Airlie <airlied@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/88b2e77f-9646-d15f-645b-ba45af2a1966@ti.com
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/dss/core.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/dss/dispc.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/dss/display.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/dss/dpi.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/dss/dsi.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/dss/dss.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/dss/dss.h | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/dss/pll.c | 73 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/dss/sdi.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/dss/venc.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/dss/video-pll.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_debugfs.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_drv.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_drv.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_fbdev.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_gem.c | 286 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_gem.h | 3 |
19 files changed, 237 insertions, 176 deletions
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c index 92fe125ce22e..f34c06bb5bd7 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Copyright (C) 2010 Nokia Corporation | 4 | * Copyright (C) 2010 Nokia Corporation |
5 | * | 5 | * |
6 | * Original Driver Author: Imre Deak <imre.deak@nokia.com> | 6 | * Original Driver Author: Imre Deak <imre.deak@nokia.com> |
7 | * Based on panel-generic.c by Tomi Valkeinen <tomi.valkeinen@nokia.com> | 7 | * Based on panel-generic.c by Tomi Valkeinen <tomi.valkeinen@ti.com> |
8 | * Adapted to new DSS2 framework: Roger Quadros <roger.quadros@nokia.com> | 8 | * Adapted to new DSS2 framework: Roger Quadros <roger.quadros@nokia.com> |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify it | 10 | * This program is free software; you can redistribute it and/or modify it |
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c index b5d8a00df811..a1f1dc18407a 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Toppoly TD028TTEC1 panel support | 2 | * Toppoly TD028TTEC1 panel support |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Nokia Corporation | 4 | * Copyright (C) 2008 Nokia Corporation |
5 | * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> | 5 | * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> |
6 | * | 6 | * |
7 | * Neo 1973 code (jbt6k74.c): | 7 | * Neo 1973 code (jbt6k74.c): |
8 | * Copyright (C) 2006-2007 by OpenMoko, Inc. | 8 | * Copyright (C) 2006-2007 by OpenMoko, Inc. |
diff --git a/drivers/gpu/drm/omapdrm/dss/core.c b/drivers/gpu/drm/omapdrm/dss/core.c index acef7ece5783..07d00a186f15 100644 --- a/drivers/gpu/drm/omapdrm/dss/core.c +++ b/drivers/gpu/drm/omapdrm/dss/core.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2009 Nokia Corporation | 2 | * Copyright (C) 2009 Nokia Corporation |
3 | * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> | 3 | * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> |
4 | * | 4 | * |
5 | * Some code and ideas taken from drivers/video/omap/ driver | 5 | * Some code and ideas taken from drivers/video/omap/ driver |
6 | * by Imre Deak. | 6 | * by Imre Deak. |
@@ -82,7 +82,7 @@ static void __exit omap_dss_exit(void) | |||
82 | module_init(omap_dss_init); | 82 | module_init(omap_dss_init); |
83 | module_exit(omap_dss_exit); | 83 | module_exit(omap_dss_exit); |
84 | 84 | ||
85 | MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>"); | 85 | MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>"); |
86 | MODULE_DESCRIPTION("OMAP2/3 Display Subsystem"); | 86 | MODULE_DESCRIPTION("OMAP2/3 Display Subsystem"); |
87 | MODULE_LICENSE("GPL v2"); | 87 | MODULE_LICENSE("GPL v2"); |
88 | 88 | ||
diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 7f3ac6b13b56..84f274c4a4cb 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2009 Nokia Corporation | 2 | * Copyright (C) 2009 Nokia Corporation |
3 | * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> | 3 | * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> |
4 | * | 4 | * |
5 | * Some code and ideas taken from drivers/video/omap/ driver | 5 | * Some code and ideas taken from drivers/video/omap/ driver |
6 | * by Imre Deak. | 6 | * by Imre Deak. |
diff --git a/drivers/gpu/drm/omapdrm/dss/display.c b/drivers/gpu/drm/omapdrm/dss/display.c index 424143128cd4..9e7fcbd57e52 100644 --- a/drivers/gpu/drm/omapdrm/dss/display.c +++ b/drivers/gpu/drm/omapdrm/dss/display.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2009 Nokia Corporation | 2 | * Copyright (C) 2009 Nokia Corporation |
3 | * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> | 3 | * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> |
4 | * | 4 | * |
5 | * Some code and ideas taken from drivers/video/omap/ driver | 5 | * Some code and ideas taken from drivers/video/omap/ driver |
6 | * by Imre Deak. | 6 | * by Imre Deak. |
diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c index 3d662e6805eb..9fcc50217133 100644 --- a/drivers/gpu/drm/omapdrm/dss/dpi.c +++ b/drivers/gpu/drm/omapdrm/dss/dpi.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2009 Nokia Corporation | 2 | * Copyright (C) 2009 Nokia Corporation |
3 | * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> | 3 | * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> |
4 | * | 4 | * |
5 | * Some code and ideas taken from drivers/video/omap/ driver | 5 | * Some code and ideas taken from drivers/video/omap/ driver |
6 | * by Imre Deak. | 6 | * by Imre Deak. |
diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index d4a680629825..74467b308721 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2009 Nokia Corporation | 2 | * Copyright (C) 2009 Nokia Corporation |
3 | * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> | 3 | * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 as published by | 6 | * under the terms of the GNU General Public License version 2 as published by |
diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c index 0b908e9de792..cb80ddaa19d2 100644 --- a/drivers/gpu/drm/omapdrm/dss/dss.c +++ b/drivers/gpu/drm/omapdrm/dss/dss.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2009 Nokia Corporation | 2 | * Copyright (C) 2009 Nokia Corporation |
3 | * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> | 3 | * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> |
4 | * | 4 | * |
5 | * Some code and ideas taken from drivers/video/omap/ driver | 5 | * Some code and ideas taken from drivers/video/omap/ driver |
6 | * by Imre Deak. | 6 | * by Imre Deak. |
diff --git a/drivers/gpu/drm/omapdrm/dss/dss.h b/drivers/gpu/drm/omapdrm/dss/dss.h index 847c78ade024..38302631b64b 100644 --- a/drivers/gpu/drm/omapdrm/dss/dss.h +++ b/drivers/gpu/drm/omapdrm/dss/dss.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2009 Nokia Corporation | 2 | * Copyright (C) 2009 Nokia Corporation |
3 | * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> | 3 | * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> |
4 | * | 4 | * |
5 | * Some code and ideas taken from drivers/video/omap/ driver | 5 | * Some code and ideas taken from drivers/video/omap/ driver |
6 | * by Imre Deak. | 6 | * by Imre Deak. |
@@ -180,6 +180,9 @@ struct dss_pll_hw { | |||
180 | 180 | ||
181 | /* DRA7 errata i886: use high N & M to avoid jitter */ | 181 | /* DRA7 errata i886: use high N & M to avoid jitter */ |
182 | bool errata_i886; | 182 | bool errata_i886; |
183 | |||
184 | /* DRA7 errata i932: retry pll lock on failure */ | ||
185 | bool errata_i932; | ||
183 | }; | 186 | }; |
184 | 187 | ||
185 | struct dss_pll { | 188 | struct dss_pll { |
diff --git a/drivers/gpu/drm/omapdrm/dss/pll.c b/drivers/gpu/drm/omapdrm/dss/pll.c index 078b0e8216c3..ff362b38bf0d 100644 --- a/drivers/gpu/drm/omapdrm/dss/pll.c +++ b/drivers/gpu/drm/omapdrm/dss/pll.c | |||
@@ -16,6 +16,7 @@ | |||
16 | 16 | ||
17 | #define DSS_SUBSYS_NAME "PLL" | 17 | #define DSS_SUBSYS_NAME "PLL" |
18 | 18 | ||
19 | #include <linux/delay.h> | ||
19 | #include <linux/clk.h> | 20 | #include <linux/clk.h> |
20 | #include <linux/io.h> | 21 | #include <linux/io.h> |
21 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
@@ -381,6 +382,22 @@ static int dss_wait_hsdiv_ack(struct dss_pll *pll, u32 hsdiv_ack_mask) | |||
381 | return -ETIMEDOUT; | 382 | return -ETIMEDOUT; |
382 | } | 383 | } |
383 | 384 | ||
385 | static bool pll_is_locked(u32 stat) | ||
386 | { | ||
387 | /* | ||
388 | * Required value for each bitfield listed below | ||
389 | * | ||
390 | * PLL_STATUS[6] = 0 PLL_BYPASS | ||
391 | * PLL_STATUS[5] = 0 PLL_HIGHJITTER | ||
392 | * | ||
393 | * PLL_STATUS[3] = 0 PLL_LOSSREF | ||
394 | * PLL_STATUS[2] = 0 PLL_RECAL | ||
395 | * PLL_STATUS[1] = 1 PLL_LOCK | ||
396 | * PLL_STATUS[0] = 1 PLL_CTRL_RESET_DONE | ||
397 | */ | ||
398 | return ((stat & 0x6f) == 0x3); | ||
399 | } | ||
400 | |||
384 | int dss_pll_write_config_type_a(struct dss_pll *pll, | 401 | int dss_pll_write_config_type_a(struct dss_pll *pll, |
385 | const struct dss_pll_clock_info *cinfo) | 402 | const struct dss_pll_clock_info *cinfo) |
386 | { | 403 | { |
@@ -436,18 +453,54 @@ int dss_pll_write_config_type_a(struct dss_pll *pll, | |||
436 | l = FLD_MOD(l, 0, 25, 25); /* M7_CLOCK_EN */ | 453 | l = FLD_MOD(l, 0, 25, 25); /* M7_CLOCK_EN */ |
437 | writel_relaxed(l, base + PLL_CONFIGURATION2); | 454 | writel_relaxed(l, base + PLL_CONFIGURATION2); |
438 | 455 | ||
439 | writel_relaxed(1, base + PLL_GO); /* PLL_GO */ | 456 | if (hw->errata_i932) { |
457 | int cnt = 0; | ||
458 | u32 sleep_time; | ||
459 | const u32 max_lock_retries = 20; | ||
440 | 460 | ||
441 | if (wait_for_bit_change(base + PLL_GO, 0, 0) != 0) { | 461 | /* |
442 | DSSERR("DSS DPLL GO bit not going down.\n"); | 462 | * Calculate wait time for PLL LOCK |
443 | r = -EIO; | 463 | * 1000 REFCLK cycles in us. |
444 | goto err; | 464 | */ |
445 | } | 465 | sleep_time = DIV_ROUND_UP(1000*1000*1000, cinfo->fint); |
446 | 466 | ||
447 | if (wait_for_bit_change(base + PLL_STATUS, 1, 1) != 1) { | 467 | for (cnt = 0; cnt < max_lock_retries; cnt++) { |
448 | DSSERR("cannot lock DSS DPLL\n"); | 468 | writel_relaxed(1, base + PLL_GO); /* PLL_GO */ |
449 | r = -EIO; | 469 | |
450 | goto err; | 470 | /** |
471 | * read the register back to ensure the write is | ||
472 | * flushed | ||
473 | */ | ||
474 | readl_relaxed(base + PLL_GO); | ||
475 | |||
476 | usleep_range(sleep_time, sleep_time + 5); | ||
477 | l = readl_relaxed(base + PLL_STATUS); | ||
478 | |||
479 | if (pll_is_locked(l) && | ||
480 | !(readl_relaxed(base + PLL_GO) & 0x1)) | ||
481 | break; | ||
482 | |||
483 | } | ||
484 | |||
485 | if (cnt == max_lock_retries) { | ||
486 | DSSERR("cannot lock PLL\n"); | ||
487 | r = -EIO; | ||
488 | goto err; | ||
489 | } | ||
490 | } else { | ||
491 | writel_relaxed(1, base + PLL_GO); /* PLL_GO */ | ||
492 | |||
493 | if (wait_for_bit_change(base + PLL_GO, 0, 0) != 0) { | ||
494 | DSSERR("DSS DPLL GO bit not going down.\n"); | ||
495 | r = -EIO; | ||
496 | goto err; | ||
497 | } | ||
498 | |||
499 | if (wait_for_bit_change(base + PLL_STATUS, 1, 1) != 1) { | ||
500 | DSSERR("cannot lock DSS DPLL\n"); | ||
501 | r = -EIO; | ||
502 | goto err; | ||
503 | } | ||
451 | } | 504 | } |
452 | 505 | ||
453 | l = readl_relaxed(base + PLL_CONFIGURATION2); | 506 | l = readl_relaxed(base + PLL_CONFIGURATION2); |
diff --git a/drivers/gpu/drm/omapdrm/dss/sdi.c b/drivers/gpu/drm/omapdrm/dss/sdi.c index 1e2c931f6acf..69c3b7a3d5c7 100644 --- a/drivers/gpu/drm/omapdrm/dss/sdi.c +++ b/drivers/gpu/drm/omapdrm/dss/sdi.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2009 Nokia Corporation | 2 | * Copyright (C) 2009 Nokia Corporation |
3 | * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> | 3 | * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 as published by | 6 | * under the terms of the GNU General Public License version 2 as published by |
diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c index 24d1ced210bd..ac01907dcc34 100644 --- a/drivers/gpu/drm/omapdrm/dss/venc.c +++ b/drivers/gpu/drm/omapdrm/dss/venc.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2009 Nokia Corporation | 2 | * Copyright (C) 2009 Nokia Corporation |
3 | * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> | 3 | * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> |
4 | * | 4 | * |
5 | * VENC settings from TI's DSS driver | 5 | * VENC settings from TI's DSS driver |
6 | * | 6 | * |
diff --git a/drivers/gpu/drm/omapdrm/dss/video-pll.c b/drivers/gpu/drm/omapdrm/dss/video-pll.c index 585ed94ccf17..cb46311f92c9 100644 --- a/drivers/gpu/drm/omapdrm/dss/video-pll.c +++ b/drivers/gpu/drm/omapdrm/dss/video-pll.c | |||
@@ -134,6 +134,7 @@ static const struct dss_pll_hw dss_dra7_video_pll_hw = { | |||
134 | .has_refsel = true, | 134 | .has_refsel = true, |
135 | 135 | ||
136 | .errata_i886 = true, | 136 | .errata_i886 = true, |
137 | .errata_i932 = true, | ||
137 | }; | 138 | }; |
138 | 139 | ||
139 | struct dss_pll *dss_video_pll_init(struct dss_device *dss, | 140 | struct dss_pll *dss_video_pll_init(struct dss_device *dss, |
diff --git a/drivers/gpu/drm/omapdrm/omap_debugfs.c b/drivers/gpu/drm/omapdrm/omap_debugfs.c index b42e286616b0..91cf043f2b6b 100644 --- a/drivers/gpu/drm/omapdrm/omap_debugfs.c +++ b/drivers/gpu/drm/omapdrm/omap_debugfs.c | |||
@@ -30,16 +30,11 @@ static int gem_show(struct seq_file *m, void *arg) | |||
30 | struct drm_info_node *node = (struct drm_info_node *) m->private; | 30 | struct drm_info_node *node = (struct drm_info_node *) m->private; |
31 | struct drm_device *dev = node->minor->dev; | 31 | struct drm_device *dev = node->minor->dev; |
32 | struct omap_drm_private *priv = dev->dev_private; | 32 | struct omap_drm_private *priv = dev->dev_private; |
33 | int ret; | ||
34 | |||
35 | ret = mutex_lock_interruptible(&dev->struct_mutex); | ||
36 | if (ret) | ||
37 | return ret; | ||
38 | 33 | ||
39 | seq_printf(m, "All Objects:\n"); | 34 | seq_printf(m, "All Objects:\n"); |
35 | mutex_lock(&priv->list_lock); | ||
40 | omap_gem_describe_objects(&priv->obj_list, m); | 36 | omap_gem_describe_objects(&priv->obj_list, m); |
41 | 37 | mutex_unlock(&priv->list_lock); | |
42 | mutex_unlock(&dev->struct_mutex); | ||
43 | 38 | ||
44 | return 0; | 39 | return 0; |
45 | } | 40 | } |
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index ef3b0e3571ec..5005ecc284d2 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c | |||
@@ -493,7 +493,7 @@ static struct drm_driver omap_drm_driver = { | |||
493 | .prime_fd_to_handle = drm_gem_prime_fd_to_handle, | 493 | .prime_fd_to_handle = drm_gem_prime_fd_to_handle, |
494 | .gem_prime_export = omap_gem_prime_export, | 494 | .gem_prime_export = omap_gem_prime_export, |
495 | .gem_prime_import = omap_gem_prime_import, | 495 | .gem_prime_import = omap_gem_prime_import, |
496 | .gem_free_object = omap_gem_free_object, | 496 | .gem_free_object_unlocked = omap_gem_free_object, |
497 | .gem_vm_ops = &omap_gem_vm_ops, | 497 | .gem_vm_ops = &omap_gem_vm_ops, |
498 | .dumb_create = omap_gem_dumb_create, | 498 | .dumb_create = omap_gem_dumb_create, |
499 | .dumb_map_offset = omap_gem_dumb_map_offset, | 499 | .dumb_map_offset = omap_gem_dumb_map_offset, |
@@ -540,7 +540,7 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev) | |||
540 | priv->omaprev = soc ? (unsigned int)soc->data : 0; | 540 | priv->omaprev = soc ? (unsigned int)soc->data : 0; |
541 | priv->wq = alloc_ordered_workqueue("omapdrm", 0); | 541 | priv->wq = alloc_ordered_workqueue("omapdrm", 0); |
542 | 542 | ||
543 | spin_lock_init(&priv->list_lock); | 543 | mutex_init(&priv->list_lock); |
544 | INIT_LIST_HEAD(&priv->obj_list); | 544 | INIT_LIST_HEAD(&priv->obj_list); |
545 | 545 | ||
546 | /* Allocate and initialize the DRM device. */ | 546 | /* Allocate and initialize the DRM device. */ |
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index 6eaee4df4559..f27c8e216adf 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h | |||
@@ -71,7 +71,7 @@ struct omap_drm_private { | |||
71 | struct workqueue_struct *wq; | 71 | struct workqueue_struct *wq; |
72 | 72 | ||
73 | /* lock for obj_list below */ | 73 | /* lock for obj_list below */ |
74 | spinlock_t list_lock; | 74 | struct mutex list_lock; |
75 | 75 | ||
76 | /* list of GEM objects: */ | 76 | /* list of GEM objects: */ |
77 | struct list_head obj_list; | 77 | struct list_head obj_list; |
diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c index 0f66c74a54b0..d958cc813a94 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.c +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c | |||
@@ -170,13 +170,11 @@ static int omap_fbdev_create(struct drm_fb_helper *helper, | |||
170 | goto fail; | 170 | goto fail; |
171 | } | 171 | } |
172 | 172 | ||
173 | mutex_lock(&dev->struct_mutex); | ||
174 | |||
175 | fbi = drm_fb_helper_alloc_fbi(helper); | 173 | fbi = drm_fb_helper_alloc_fbi(helper); |
176 | if (IS_ERR(fbi)) { | 174 | if (IS_ERR(fbi)) { |
177 | dev_err(dev->dev, "failed to allocate fb info\n"); | 175 | dev_err(dev->dev, "failed to allocate fb info\n"); |
178 | ret = PTR_ERR(fbi); | 176 | ret = PTR_ERR(fbi); |
179 | goto fail_unlock; | 177 | goto fail; |
180 | } | 178 | } |
181 | 179 | ||
182 | DBG("fbi=%p, dev=%p", fbi, dev); | 180 | DBG("fbi=%p, dev=%p", fbi, dev); |
@@ -212,12 +210,8 @@ static int omap_fbdev_create(struct drm_fb_helper *helper, | |||
212 | DBG("par=%p, %dx%d", fbi->par, fbi->var.xres, fbi->var.yres); | 210 | DBG("par=%p, %dx%d", fbi->par, fbi->var.xres, fbi->var.yres); |
213 | DBG("allocated %dx%d fb", fbdev->fb->width, fbdev->fb->height); | 211 | DBG("allocated %dx%d fb", fbdev->fb->width, fbdev->fb->height); |
214 | 212 | ||
215 | mutex_unlock(&dev->struct_mutex); | ||
216 | |||
217 | return 0; | 213 | return 0; |
218 | 214 | ||
219 | fail_unlock: | ||
220 | mutex_unlock(&dev->struct_mutex); | ||
221 | fail: | 215 | fail: |
222 | 216 | ||
223 | if (ret) { | 217 | if (ret) { |
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index 17a53d207978..4ba5d035c590 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c | |||
@@ -47,6 +47,9 @@ struct omap_gem_object { | |||
47 | /** roll applied when mapping to DMM */ | 47 | /** roll applied when mapping to DMM */ |
48 | u32 roll; | 48 | u32 roll; |
49 | 49 | ||
50 | /** protects dma_addr_cnt, block, pages, dma_addrs and vaddr */ | ||
51 | struct mutex lock; | ||
52 | |||
50 | /** | 53 | /** |
51 | * dma_addr contains the buffer DMA address. It is valid for | 54 | * dma_addr contains the buffer DMA address. It is valid for |
52 | * | 55 | * |
@@ -137,14 +140,12 @@ struct omap_drm_usergart { | |||
137 | */ | 140 | */ |
138 | 141 | ||
139 | /** get mmap offset */ | 142 | /** get mmap offset */ |
140 | static u64 mmap_offset(struct drm_gem_object *obj) | 143 | u64 omap_gem_mmap_offset(struct drm_gem_object *obj) |
141 | { | 144 | { |
142 | struct drm_device *dev = obj->dev; | 145 | struct drm_device *dev = obj->dev; |
143 | int ret; | 146 | int ret; |
144 | size_t size; | 147 | size_t size; |
145 | 148 | ||
146 | WARN_ON(!mutex_is_locked(&dev->struct_mutex)); | ||
147 | |||
148 | /* Make it mmapable */ | 149 | /* Make it mmapable */ |
149 | size = omap_gem_mmap_size(obj); | 150 | size = omap_gem_mmap_size(obj); |
150 | ret = drm_gem_create_mmap_offset_size(obj, size); | 151 | ret = drm_gem_create_mmap_offset_size(obj, size); |
@@ -156,7 +157,7 @@ static u64 mmap_offset(struct drm_gem_object *obj) | |||
156 | return drm_vma_node_offset_addr(&obj->vma_node); | 157 | return drm_vma_node_offset_addr(&obj->vma_node); |
157 | } | 158 | } |
158 | 159 | ||
159 | static bool is_contiguous(struct omap_gem_object *omap_obj) | 160 | static bool omap_gem_is_contiguous(struct omap_gem_object *omap_obj) |
160 | { | 161 | { |
161 | if (omap_obj->flags & OMAP_BO_MEM_DMA_API) | 162 | if (omap_obj->flags & OMAP_BO_MEM_DMA_API) |
162 | return true; | 163 | return true; |
@@ -171,14 +172,14 @@ static bool is_contiguous(struct omap_gem_object *omap_obj) | |||
171 | * Eviction | 172 | * Eviction |
172 | */ | 173 | */ |
173 | 174 | ||
174 | static void evict_entry(struct drm_gem_object *obj, | 175 | static void omap_gem_evict_entry(struct drm_gem_object *obj, |
175 | enum tiler_fmt fmt, struct omap_drm_usergart_entry *entry) | 176 | enum tiler_fmt fmt, struct omap_drm_usergart_entry *entry) |
176 | { | 177 | { |
177 | struct omap_gem_object *omap_obj = to_omap_bo(obj); | 178 | struct omap_gem_object *omap_obj = to_omap_bo(obj); |
178 | struct omap_drm_private *priv = obj->dev->dev_private; | 179 | struct omap_drm_private *priv = obj->dev->dev_private; |
179 | int n = priv->usergart[fmt].height; | 180 | int n = priv->usergart[fmt].height; |
180 | size_t size = PAGE_SIZE * n; | 181 | size_t size = PAGE_SIZE * n; |
181 | loff_t off = mmap_offset(obj) + | 182 | loff_t off = omap_gem_mmap_offset(obj) + |
182 | (entry->obj_pgoff << PAGE_SHIFT); | 183 | (entry->obj_pgoff << PAGE_SHIFT); |
183 | const int m = DIV_ROUND_UP(omap_obj->width << fmt, PAGE_SIZE); | 184 | const int m = DIV_ROUND_UP(omap_obj->width << fmt, PAGE_SIZE); |
184 | 185 | ||
@@ -199,7 +200,7 @@ static void evict_entry(struct drm_gem_object *obj, | |||
199 | } | 200 | } |
200 | 201 | ||
201 | /* Evict a buffer from usergart, if it is mapped there */ | 202 | /* Evict a buffer from usergart, if it is mapped there */ |
202 | static void evict(struct drm_gem_object *obj) | 203 | static void omap_gem_evict(struct drm_gem_object *obj) |
203 | { | 204 | { |
204 | struct omap_gem_object *omap_obj = to_omap_bo(obj); | 205 | struct omap_gem_object *omap_obj = to_omap_bo(obj); |
205 | struct omap_drm_private *priv = obj->dev->dev_private; | 206 | struct omap_drm_private *priv = obj->dev->dev_private; |
@@ -213,7 +214,7 @@ static void evict(struct drm_gem_object *obj) | |||
213 | &priv->usergart[fmt].entry[i]; | 214 | &priv->usergart[fmt].entry[i]; |
214 | 215 | ||
215 | if (entry->obj == obj) | 216 | if (entry->obj == obj) |
216 | evict_entry(obj, fmt, entry); | 217 | omap_gem_evict_entry(obj, fmt, entry); |
217 | } | 218 | } |
218 | } | 219 | } |
219 | } | 220 | } |
@@ -222,7 +223,10 @@ static void evict(struct drm_gem_object *obj) | |||
222 | * Page Management | 223 | * Page Management |
223 | */ | 224 | */ |
224 | 225 | ||
225 | /** ensure backing pages are allocated */ | 226 | /* |
227 | * Ensure backing pages are allocated. Must be called with the omap_obj.lock | ||
228 | * held. | ||
229 | */ | ||
226 | static int omap_gem_attach_pages(struct drm_gem_object *obj) | 230 | static int omap_gem_attach_pages(struct drm_gem_object *obj) |
227 | { | 231 | { |
228 | struct drm_device *dev = obj->dev; | 232 | struct drm_device *dev = obj->dev; |
@@ -232,7 +236,14 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj) | |||
232 | int i, ret; | 236 | int i, ret; |
233 | dma_addr_t *addrs; | 237 | dma_addr_t *addrs; |
234 | 238 | ||
235 | WARN_ON(omap_obj->pages); | 239 | lockdep_assert_held(&omap_obj->lock); |
240 | |||
241 | /* | ||
242 | * If not using shmem (in which case backing pages don't need to be | ||
243 | * allocated) or if pages are already allocated we're done. | ||
244 | */ | ||
245 | if (!(omap_obj->flags & OMAP_BO_MEM_SHMEM) || omap_obj->pages) | ||
246 | return 0; | ||
236 | 247 | ||
237 | pages = drm_gem_get_pages(obj); | 248 | pages = drm_gem_get_pages(obj); |
238 | if (IS_ERR(pages)) { | 249 | if (IS_ERR(pages)) { |
@@ -288,35 +299,15 @@ free_pages: | |||
288 | return ret; | 299 | return ret; |
289 | } | 300 | } |
290 | 301 | ||
291 | /* acquire pages when needed (for example, for DMA where physically | 302 | /* Release backing pages. Must be called with the omap_obj.lock held. */ |
292 | * contiguous buffer is not required | ||
293 | */ | ||
294 | static int get_pages(struct drm_gem_object *obj, struct page ***pages) | ||
295 | { | ||
296 | struct omap_gem_object *omap_obj = to_omap_bo(obj); | ||
297 | int ret = 0; | ||
298 | |||
299 | if ((omap_obj->flags & OMAP_BO_MEM_SHMEM) && !omap_obj->pages) { | ||
300 | ret = omap_gem_attach_pages(obj); | ||
301 | if (ret) { | ||
302 | dev_err(obj->dev->dev, "could not attach pages\n"); | ||
303 | return ret; | ||
304 | } | ||
305 | } | ||
306 | |||
307 | /* TODO: even phys-contig.. we should have a list of pages? */ | ||
308 | *pages = omap_obj->pages; | ||
309 | |||
310 | return 0; | ||
311 | } | ||
312 | |||
313 | /** release backing pages */ | ||
314 | static void omap_gem_detach_pages(struct drm_gem_object *obj) | 303 | static void omap_gem_detach_pages(struct drm_gem_object *obj) |
315 | { | 304 | { |
316 | struct omap_gem_object *omap_obj = to_omap_bo(obj); | 305 | struct omap_gem_object *omap_obj = to_omap_bo(obj); |
317 | unsigned int npages = obj->size >> PAGE_SHIFT; | 306 | unsigned int npages = obj->size >> PAGE_SHIFT; |
318 | unsigned int i; | 307 | unsigned int i; |
319 | 308 | ||
309 | lockdep_assert_held(&omap_obj->lock); | ||
310 | |||
320 | for (i = 0; i < npages; i++) { | 311 | for (i = 0; i < npages; i++) { |
321 | if (omap_obj->dma_addrs[i]) | 312 | if (omap_obj->dma_addrs[i]) |
322 | dma_unmap_page(obj->dev->dev, omap_obj->dma_addrs[i], | 313 | dma_unmap_page(obj->dev->dev, omap_obj->dma_addrs[i], |
@@ -336,16 +327,6 @@ u32 omap_gem_flags(struct drm_gem_object *obj) | |||
336 | return to_omap_bo(obj)->flags; | 327 | return to_omap_bo(obj)->flags; |
337 | } | 328 | } |
338 | 329 | ||
339 | u64 omap_gem_mmap_offset(struct drm_gem_object *obj) | ||
340 | { | ||
341 | u64 offset; | ||
342 | |||
343 | mutex_lock(&obj->dev->struct_mutex); | ||
344 | offset = mmap_offset(obj); | ||
345 | mutex_unlock(&obj->dev->struct_mutex); | ||
346 | return offset; | ||
347 | } | ||
348 | |||
349 | /** get mmap size */ | 330 | /** get mmap size */ |
350 | size_t omap_gem_mmap_size(struct drm_gem_object *obj) | 331 | size_t omap_gem_mmap_size(struct drm_gem_object *obj) |
351 | { | 332 | { |
@@ -371,7 +352,7 @@ size_t omap_gem_mmap_size(struct drm_gem_object *obj) | |||
371 | */ | 352 | */ |
372 | 353 | ||
373 | /* Normal handling for the case of faulting in non-tiled buffers */ | 354 | /* Normal handling for the case of faulting in non-tiled buffers */ |
374 | static int fault_1d(struct drm_gem_object *obj, | 355 | static vm_fault_t omap_gem_fault_1d(struct drm_gem_object *obj, |
375 | struct vm_area_struct *vma, struct vm_fault *vmf) | 356 | struct vm_area_struct *vma, struct vm_fault *vmf) |
376 | { | 357 | { |
377 | struct omap_gem_object *omap_obj = to_omap_bo(obj); | 358 | struct omap_gem_object *omap_obj = to_omap_bo(obj); |
@@ -385,18 +366,19 @@ static int fault_1d(struct drm_gem_object *obj, | |||
385 | omap_gem_cpu_sync_page(obj, pgoff); | 366 | omap_gem_cpu_sync_page(obj, pgoff); |
386 | pfn = page_to_pfn(omap_obj->pages[pgoff]); | 367 | pfn = page_to_pfn(omap_obj->pages[pgoff]); |
387 | } else { | 368 | } else { |
388 | BUG_ON(!is_contiguous(omap_obj)); | 369 | BUG_ON(!omap_gem_is_contiguous(omap_obj)); |
389 | pfn = (omap_obj->dma_addr >> PAGE_SHIFT) + pgoff; | 370 | pfn = (omap_obj->dma_addr >> PAGE_SHIFT) + pgoff; |
390 | } | 371 | } |
391 | 372 | ||
392 | VERB("Inserting %p pfn %lx, pa %lx", (void *)vmf->address, | 373 | VERB("Inserting %p pfn %lx, pa %lx", (void *)vmf->address, |
393 | pfn, pfn << PAGE_SHIFT); | 374 | pfn, pfn << PAGE_SHIFT); |
394 | 375 | ||
395 | return vm_insert_mixed(vma, vmf->address, __pfn_to_pfn_t(pfn, PFN_DEV)); | 376 | return vmf_insert_mixed(vma, vmf->address, |
377 | __pfn_to_pfn_t(pfn, PFN_DEV)); | ||
396 | } | 378 | } |
397 | 379 | ||
398 | /* Special handling for the case of faulting in 2d tiled buffers */ | 380 | /* Special handling for the case of faulting in 2d tiled buffers */ |
399 | static int fault_2d(struct drm_gem_object *obj, | 381 | static vm_fault_t omap_gem_fault_2d(struct drm_gem_object *obj, |
400 | struct vm_area_struct *vma, struct vm_fault *vmf) | 382 | struct vm_area_struct *vma, struct vm_fault *vmf) |
401 | { | 383 | { |
402 | struct omap_gem_object *omap_obj = to_omap_bo(obj); | 384 | struct omap_gem_object *omap_obj = to_omap_bo(obj); |
@@ -407,7 +389,8 @@ static int fault_2d(struct drm_gem_object *obj, | |||
407 | unsigned long pfn; | 389 | unsigned long pfn; |
408 | pgoff_t pgoff, base_pgoff; | 390 | pgoff_t pgoff, base_pgoff; |
409 | unsigned long vaddr; | 391 | unsigned long vaddr; |
410 | int i, ret, slots; | 392 | int i, err, slots; |
393 | vm_fault_t ret = VM_FAULT_NOPAGE; | ||
411 | 394 | ||
412 | /* | 395 | /* |
413 | * Note the height of the slot is also equal to the number of pages | 396 | * Note the height of the slot is also equal to the number of pages |
@@ -443,7 +426,7 @@ static int fault_2d(struct drm_gem_object *obj, | |||
443 | 426 | ||
444 | /* evict previous buffer using this usergart entry, if any: */ | 427 | /* evict previous buffer using this usergart entry, if any: */ |
445 | if (entry->obj) | 428 | if (entry->obj) |
446 | evict_entry(entry->obj, fmt, entry); | 429 | omap_gem_evict_entry(entry->obj, fmt, entry); |
447 | 430 | ||
448 | entry->obj = obj; | 431 | entry->obj = obj; |
449 | entry->obj_pgoff = base_pgoff; | 432 | entry->obj_pgoff = base_pgoff; |
@@ -473,9 +456,10 @@ static int fault_2d(struct drm_gem_object *obj, | |||
473 | memset(pages + slots, 0, | 456 | memset(pages + slots, 0, |
474 | sizeof(struct page *) * (n - slots)); | 457 | sizeof(struct page *) * (n - slots)); |
475 | 458 | ||
476 | ret = tiler_pin(entry->block, pages, ARRAY_SIZE(pages), 0, true); | 459 | err = tiler_pin(entry->block, pages, ARRAY_SIZE(pages), 0, true); |
477 | if (ret) { | 460 | if (err) { |
478 | dev_err(obj->dev->dev, "failed to pin: %d\n", ret); | 461 | ret = vmf_error(err); |
462 | dev_err(obj->dev->dev, "failed to pin: %d\n", err); | ||
479 | return ret; | 463 | return ret; |
480 | } | 464 | } |
481 | 465 | ||
@@ -485,7 +469,10 @@ static int fault_2d(struct drm_gem_object *obj, | |||
485 | pfn, pfn << PAGE_SHIFT); | 469 | pfn, pfn << PAGE_SHIFT); |
486 | 470 | ||
487 | for (i = n; i > 0; i--) { | 471 | for (i = n; i > 0; i--) { |
488 | vm_insert_mixed(vma, vaddr, __pfn_to_pfn_t(pfn, PFN_DEV)); | 472 | ret = vmf_insert_mixed(vma, |
473 | vaddr, __pfn_to_pfn_t(pfn, PFN_DEV)); | ||
474 | if (ret & VM_FAULT_ERROR) | ||
475 | break; | ||
489 | pfn += priv->usergart[fmt].stride_pfn; | 476 | pfn += priv->usergart[fmt].stride_pfn; |
490 | vaddr += PAGE_SIZE * m; | 477 | vaddr += PAGE_SIZE * m; |
491 | } | 478 | } |
@@ -494,7 +481,7 @@ static int fault_2d(struct drm_gem_object *obj, | |||
494 | priv->usergart[fmt].last = (priv->usergart[fmt].last + 1) | 481 | priv->usergart[fmt].last = (priv->usergart[fmt].last + 1) |
495 | % NUM_USERGART_ENTRIES; | 482 | % NUM_USERGART_ENTRIES; |
496 | 483 | ||
497 | return 0; | 484 | return ret; |
498 | } | 485 | } |
499 | 486 | ||
500 | /** | 487 | /** |
@@ -509,24 +496,25 @@ static int fault_2d(struct drm_gem_object *obj, | |||
509 | * vma->vm_private_data points to the GEM object that is backing this | 496 | * vma->vm_private_data points to the GEM object that is backing this |
510 | * mapping. | 497 | * mapping. |
511 | */ | 498 | */ |
512 | int omap_gem_fault(struct vm_fault *vmf) | 499 | vm_fault_t omap_gem_fault(struct vm_fault *vmf) |
513 | { | 500 | { |
514 | struct vm_area_struct *vma = vmf->vma; | 501 | struct vm_area_struct *vma = vmf->vma; |
515 | struct drm_gem_object *obj = vma->vm_private_data; | 502 | struct drm_gem_object *obj = vma->vm_private_data; |
516 | struct omap_gem_object *omap_obj = to_omap_bo(obj); | 503 | struct omap_gem_object *omap_obj = to_omap_bo(obj); |
517 | struct drm_device *dev = obj->dev; | 504 | int err; |
518 | struct page **pages; | 505 | vm_fault_t ret; |
519 | int ret; | ||
520 | 506 | ||
521 | /* Make sure we don't parallel update on a fault, nor move or remove | 507 | /* Make sure we don't parallel update on a fault, nor move or remove |
522 | * something from beneath our feet | 508 | * something from beneath our feet |
523 | */ | 509 | */ |
524 | mutex_lock(&dev->struct_mutex); | 510 | mutex_lock(&omap_obj->lock); |
525 | 511 | ||
526 | /* if a shmem backed object, make sure we have pages attached now */ | 512 | /* if a shmem backed object, make sure we have pages attached now */ |
527 | ret = get_pages(obj, &pages); | 513 | err = omap_gem_attach_pages(obj); |
528 | if (ret) | 514 | if (err) { |
515 | ret = vmf_error(err); | ||
529 | goto fail; | 516 | goto fail; |
517 | } | ||
530 | 518 | ||
531 | /* where should we do corresponding put_pages().. we are mapping | 519 | /* where should we do corresponding put_pages().. we are mapping |
532 | * the original page, rather than thru a GART, so we can't rely | 520 | * the original page, rather than thru a GART, so we can't rely |
@@ -535,28 +523,14 @@ int omap_gem_fault(struct vm_fault *vmf) | |||
535 | */ | 523 | */ |
536 | 524 | ||
537 | if (omap_obj->flags & OMAP_BO_TILED) | 525 | if (omap_obj->flags & OMAP_BO_TILED) |
538 | ret = fault_2d(obj, vma, vmf); | 526 | ret = omap_gem_fault_2d(obj, vma, vmf); |
539 | else | 527 | else |
540 | ret = fault_1d(obj, vma, vmf); | 528 | ret = omap_gem_fault_1d(obj, vma, vmf); |
541 | 529 | ||
542 | 530 | ||
543 | fail: | 531 | fail: |
544 | mutex_unlock(&dev->struct_mutex); | 532 | mutex_unlock(&omap_obj->lock); |
545 | switch (ret) { | 533 | return ret; |
546 | case 0: | ||
547 | case -ERESTARTSYS: | ||
548 | case -EINTR: | ||
549 | case -EBUSY: | ||
550 | /* | ||
551 | * EBUSY is ok: this just means that another thread | ||
552 | * already did the job. | ||
553 | */ | ||
554 | return VM_FAULT_NOPAGE; | ||
555 | case -ENOMEM: | ||
556 | return VM_FAULT_OOM; | ||
557 | default: | ||
558 | return VM_FAULT_SIGBUS; | ||
559 | } | ||
560 | } | 534 | } |
561 | 535 | ||
562 | /** We override mainly to fix up some of the vm mapping flags.. */ | 536 | /** We override mainly to fix up some of the vm mapping flags.. */ |
@@ -689,21 +663,22 @@ int omap_gem_roll(struct drm_gem_object *obj, u32 roll) | |||
689 | 663 | ||
690 | omap_obj->roll = roll; | 664 | omap_obj->roll = roll; |
691 | 665 | ||
692 | mutex_lock(&obj->dev->struct_mutex); | 666 | mutex_lock(&omap_obj->lock); |
693 | 667 | ||
694 | /* if we aren't mapped yet, we don't need to do anything */ | 668 | /* if we aren't mapped yet, we don't need to do anything */ |
695 | if (omap_obj->block) { | 669 | if (omap_obj->block) { |
696 | struct page **pages; | 670 | ret = omap_gem_attach_pages(obj); |
697 | ret = get_pages(obj, &pages); | ||
698 | if (ret) | 671 | if (ret) |
699 | goto fail; | 672 | goto fail; |
700 | ret = tiler_pin(omap_obj->block, pages, npages, roll, true); | 673 | |
674 | ret = tiler_pin(omap_obj->block, omap_obj->pages, npages, | ||
675 | roll, true); | ||
701 | if (ret) | 676 | if (ret) |
702 | dev_err(obj->dev->dev, "could not repin: %d\n", ret); | 677 | dev_err(obj->dev->dev, "could not repin: %d\n", ret); |
703 | } | 678 | } |
704 | 679 | ||
705 | fail: | 680 | fail: |
706 | mutex_unlock(&obj->dev->struct_mutex); | 681 | mutex_unlock(&omap_obj->lock); |
707 | 682 | ||
708 | return ret; | 683 | return ret; |
709 | } | 684 | } |
@@ -722,7 +697,7 @@ fail: | |||
722 | * the omap_obj->dma_addrs[i] is set to the DMA address, and the page is | 697 | * the omap_obj->dma_addrs[i] is set to the DMA address, and the page is |
723 | * unmapped from the CPU. | 698 | * unmapped from the CPU. |
724 | */ | 699 | */ |
725 | static inline bool is_cached_coherent(struct drm_gem_object *obj) | 700 | static inline bool omap_gem_is_cached_coherent(struct drm_gem_object *obj) |
726 | { | 701 | { |
727 | struct omap_gem_object *omap_obj = to_omap_bo(obj); | 702 | struct omap_gem_object *omap_obj = to_omap_bo(obj); |
728 | 703 | ||
@@ -738,7 +713,7 @@ void omap_gem_cpu_sync_page(struct drm_gem_object *obj, int pgoff) | |||
738 | struct drm_device *dev = obj->dev; | 713 | struct drm_device *dev = obj->dev; |
739 | struct omap_gem_object *omap_obj = to_omap_bo(obj); | 714 | struct omap_gem_object *omap_obj = to_omap_bo(obj); |
740 | 715 | ||
741 | if (is_cached_coherent(obj)) | 716 | if (omap_gem_is_cached_coherent(obj)) |
742 | return; | 717 | return; |
743 | 718 | ||
744 | if (omap_obj->dma_addrs[pgoff]) { | 719 | if (omap_obj->dma_addrs[pgoff]) { |
@@ -758,7 +733,7 @@ void omap_gem_dma_sync_buffer(struct drm_gem_object *obj, | |||
758 | struct page **pages = omap_obj->pages; | 733 | struct page **pages = omap_obj->pages; |
759 | bool dirty = false; | 734 | bool dirty = false; |
760 | 735 | ||
761 | if (is_cached_coherent(obj)) | 736 | if (omap_gem_is_cached_coherent(obj)) |
762 | return; | 737 | return; |
763 | 738 | ||
764 | for (i = 0; i < npages; i++) { | 739 | for (i = 0; i < npages; i++) { |
@@ -804,18 +779,17 @@ int omap_gem_pin(struct drm_gem_object *obj, dma_addr_t *dma_addr) | |||
804 | struct omap_gem_object *omap_obj = to_omap_bo(obj); | 779 | struct omap_gem_object *omap_obj = to_omap_bo(obj); |
805 | int ret = 0; | 780 | int ret = 0; |
806 | 781 | ||
807 | mutex_lock(&obj->dev->struct_mutex); | 782 | mutex_lock(&omap_obj->lock); |
808 | 783 | ||
809 | if (!is_contiguous(omap_obj) && priv->has_dmm) { | 784 | if (!omap_gem_is_contiguous(omap_obj) && priv->has_dmm) { |
810 | if (omap_obj->dma_addr_cnt == 0) { | 785 | if (omap_obj->dma_addr_cnt == 0) { |
811 | struct page **pages; | ||
812 | u32 npages = obj->size >> PAGE_SHIFT; | 786 | u32 npages = obj->size >> PAGE_SHIFT; |
813 | enum tiler_fmt fmt = gem2fmt(omap_obj->flags); | 787 | enum tiler_fmt fmt = gem2fmt(omap_obj->flags); |
814 | struct tiler_block *block; | 788 | struct tiler_block *block; |
815 | 789 | ||
816 | BUG_ON(omap_obj->block); | 790 | BUG_ON(omap_obj->block); |
817 | 791 | ||
818 | ret = get_pages(obj, &pages); | 792 | ret = omap_gem_attach_pages(obj); |
819 | if (ret) | 793 | if (ret) |
820 | goto fail; | 794 | goto fail; |
821 | 795 | ||
@@ -835,7 +809,7 @@ int omap_gem_pin(struct drm_gem_object *obj, dma_addr_t *dma_addr) | |||
835 | } | 809 | } |
836 | 810 | ||
837 | /* TODO: enable async refill.. */ | 811 | /* TODO: enable async refill.. */ |
838 | ret = tiler_pin(block, pages, npages, | 812 | ret = tiler_pin(block, omap_obj->pages, npages, |
839 | omap_obj->roll, true); | 813 | omap_obj->roll, true); |
840 | if (ret) { | 814 | if (ret) { |
841 | tiler_release(block); | 815 | tiler_release(block); |
@@ -853,7 +827,7 @@ int omap_gem_pin(struct drm_gem_object *obj, dma_addr_t *dma_addr) | |||
853 | omap_obj->dma_addr_cnt++; | 827 | omap_obj->dma_addr_cnt++; |
854 | 828 | ||
855 | *dma_addr = omap_obj->dma_addr; | 829 | *dma_addr = omap_obj->dma_addr; |
856 | } else if (is_contiguous(omap_obj)) { | 830 | } else if (omap_gem_is_contiguous(omap_obj)) { |
857 | *dma_addr = omap_obj->dma_addr; | 831 | *dma_addr = omap_obj->dma_addr; |
858 | } else { | 832 | } else { |
859 | ret = -EINVAL; | 833 | ret = -EINVAL; |
@@ -861,7 +835,7 @@ int omap_gem_pin(struct drm_gem_object *obj, dma_addr_t *dma_addr) | |||
861 | } | 835 | } |
862 | 836 | ||
863 | fail: | 837 | fail: |
864 | mutex_unlock(&obj->dev->struct_mutex); | 838 | mutex_unlock(&omap_obj->lock); |
865 | 839 | ||
866 | return ret; | 840 | return ret; |
867 | } | 841 | } |
@@ -879,7 +853,8 @@ void omap_gem_unpin(struct drm_gem_object *obj) | |||
879 | struct omap_gem_object *omap_obj = to_omap_bo(obj); | 853 | struct omap_gem_object *omap_obj = to_omap_bo(obj); |
880 | int ret; | 854 | int ret; |
881 | 855 | ||
882 | mutex_lock(&obj->dev->struct_mutex); | 856 | mutex_lock(&omap_obj->lock); |
857 | |||
883 | if (omap_obj->dma_addr_cnt > 0) { | 858 | if (omap_obj->dma_addr_cnt > 0) { |
884 | omap_obj->dma_addr_cnt--; | 859 | omap_obj->dma_addr_cnt--; |
885 | if (omap_obj->dma_addr_cnt == 0) { | 860 | if (omap_obj->dma_addr_cnt == 0) { |
@@ -898,7 +873,7 @@ void omap_gem_unpin(struct drm_gem_object *obj) | |||
898 | } | 873 | } |
899 | } | 874 | } |
900 | 875 | ||
901 | mutex_unlock(&obj->dev->struct_mutex); | 876 | mutex_unlock(&omap_obj->lock); |
902 | } | 877 | } |
903 | 878 | ||
904 | /* Get rotated scanout address (only valid if already pinned), at the | 879 | /* Get rotated scanout address (only valid if already pinned), at the |
@@ -911,13 +886,16 @@ int omap_gem_rotated_dma_addr(struct drm_gem_object *obj, u32 orient, | |||
911 | struct omap_gem_object *omap_obj = to_omap_bo(obj); | 886 | struct omap_gem_object *omap_obj = to_omap_bo(obj); |
912 | int ret = -EINVAL; | 887 | int ret = -EINVAL; |
913 | 888 | ||
914 | mutex_lock(&obj->dev->struct_mutex); | 889 | mutex_lock(&omap_obj->lock); |
890 | |||
915 | if ((omap_obj->dma_addr_cnt > 0) && omap_obj->block && | 891 | if ((omap_obj->dma_addr_cnt > 0) && omap_obj->block && |
916 | (omap_obj->flags & OMAP_BO_TILED)) { | 892 | (omap_obj->flags & OMAP_BO_TILED)) { |
917 | *dma_addr = tiler_tsptr(omap_obj->block, orient, x, y); | 893 | *dma_addr = tiler_tsptr(omap_obj->block, orient, x, y); |
918 | ret = 0; | 894 | ret = 0; |
919 | } | 895 | } |
920 | mutex_unlock(&obj->dev->struct_mutex); | 896 | |
897 | mutex_unlock(&omap_obj->lock); | ||
898 | |||
921 | return ret; | 899 | return ret; |
922 | } | 900 | } |
923 | 901 | ||
@@ -944,17 +922,27 @@ int omap_gem_tiled_stride(struct drm_gem_object *obj, u32 orient) | |||
944 | int omap_gem_get_pages(struct drm_gem_object *obj, struct page ***pages, | 922 | int omap_gem_get_pages(struct drm_gem_object *obj, struct page ***pages, |
945 | bool remap) | 923 | bool remap) |
946 | { | 924 | { |
947 | int ret; | 925 | struct omap_gem_object *omap_obj = to_omap_bo(obj); |
948 | if (!remap) { | 926 | int ret = 0; |
949 | struct omap_gem_object *omap_obj = to_omap_bo(obj); | 927 | |
950 | if (!omap_obj->pages) | 928 | mutex_lock(&omap_obj->lock); |
951 | return -ENOMEM; | 929 | |
952 | *pages = omap_obj->pages; | 930 | if (remap) { |
953 | return 0; | 931 | ret = omap_gem_attach_pages(obj); |
932 | if (ret) | ||
933 | goto unlock; | ||
954 | } | 934 | } |
955 | mutex_lock(&obj->dev->struct_mutex); | 935 | |
956 | ret = get_pages(obj, pages); | 936 | if (!omap_obj->pages) { |
957 | mutex_unlock(&obj->dev->struct_mutex); | 937 | ret = -ENOMEM; |
938 | goto unlock; | ||
939 | } | ||
940 | |||
941 | *pages = omap_obj->pages; | ||
942 | |||
943 | unlock: | ||
944 | mutex_unlock(&omap_obj->lock); | ||
945 | |||
958 | return ret; | 946 | return ret; |
959 | } | 947 | } |
960 | 948 | ||
@@ -969,23 +957,34 @@ int omap_gem_put_pages(struct drm_gem_object *obj) | |||
969 | } | 957 | } |
970 | 958 | ||
971 | #ifdef CONFIG_DRM_FBDEV_EMULATION | 959 | #ifdef CONFIG_DRM_FBDEV_EMULATION |
972 | /* Get kernel virtual address for CPU access.. this more or less only | 960 | /* |
973 | * exists for omap_fbdev. This should be called with struct_mutex | 961 | * Get kernel virtual address for CPU access.. this more or less only |
974 | * held. | 962 | * exists for omap_fbdev. |
975 | */ | 963 | */ |
976 | void *omap_gem_vaddr(struct drm_gem_object *obj) | 964 | void *omap_gem_vaddr(struct drm_gem_object *obj) |
977 | { | 965 | { |
978 | struct omap_gem_object *omap_obj = to_omap_bo(obj); | 966 | struct omap_gem_object *omap_obj = to_omap_bo(obj); |
979 | WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex)); | 967 | void *vaddr; |
968 | int ret; | ||
969 | |||
970 | mutex_lock(&omap_obj->lock); | ||
971 | |||
980 | if (!omap_obj->vaddr) { | 972 | if (!omap_obj->vaddr) { |
981 | struct page **pages; | 973 | ret = omap_gem_attach_pages(obj); |
982 | int ret = get_pages(obj, &pages); | 974 | if (ret) { |
983 | if (ret) | 975 | vaddr = ERR_PTR(ret); |
984 | return ERR_PTR(ret); | 976 | goto unlock; |
985 | omap_obj->vaddr = vmap(pages, obj->size >> PAGE_SHIFT, | 977 | } |
978 | |||
979 | omap_obj->vaddr = vmap(omap_obj->pages, obj->size >> PAGE_SHIFT, | ||
986 | VM_MAP, pgprot_writecombine(PAGE_KERNEL)); | 980 | VM_MAP, pgprot_writecombine(PAGE_KERNEL)); |
987 | } | 981 | } |
988 | return omap_obj->vaddr; | 982 | |
983 | vaddr = omap_obj->vaddr; | ||
984 | |||
985 | unlock: | ||
986 | mutex_unlock(&omap_obj->lock); | ||
987 | return vaddr; | ||
989 | } | 988 | } |
990 | #endif | 989 | #endif |
991 | 990 | ||
@@ -1001,6 +1000,7 @@ int omap_gem_resume(struct drm_device *dev) | |||
1001 | struct omap_gem_object *omap_obj; | 1000 | struct omap_gem_object *omap_obj; |
1002 | int ret = 0; | 1001 | int ret = 0; |
1003 | 1002 | ||
1003 | mutex_lock(&priv->list_lock); | ||
1004 | list_for_each_entry(omap_obj, &priv->obj_list, mm_list) { | 1004 | list_for_each_entry(omap_obj, &priv->obj_list, mm_list) { |
1005 | if (omap_obj->block) { | 1005 | if (omap_obj->block) { |
1006 | struct drm_gem_object *obj = &omap_obj->base; | 1006 | struct drm_gem_object *obj = &omap_obj->base; |
@@ -1012,12 +1012,14 @@ int omap_gem_resume(struct drm_device *dev) | |||
1012 | omap_obj->roll, true); | 1012 | omap_obj->roll, true); |
1013 | if (ret) { | 1013 | if (ret) { |
1014 | dev_err(dev->dev, "could not repin: %d\n", ret); | 1014 | dev_err(dev->dev, "could not repin: %d\n", ret); |
1015 | return ret; | 1015 | goto done; |
1016 | } | 1016 | } |
1017 | } | 1017 | } |
1018 | } | 1018 | } |
1019 | 1019 | ||
1020 | return 0; | 1020 | done: |
1021 | mutex_unlock(&priv->list_lock); | ||
1022 | return ret; | ||
1021 | } | 1023 | } |
1022 | #endif | 1024 | #endif |
1023 | 1025 | ||
@@ -1033,6 +1035,8 @@ void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m) | |||
1033 | 1035 | ||
1034 | off = drm_vma_node_start(&obj->vma_node); | 1036 | off = drm_vma_node_start(&obj->vma_node); |
1035 | 1037 | ||
1038 | mutex_lock(&omap_obj->lock); | ||
1039 | |||
1036 | seq_printf(m, "%08x: %2d (%2d) %08llx %pad (%2d) %p %4d", | 1040 | seq_printf(m, "%08x: %2d (%2d) %08llx %pad (%2d) %p %4d", |
1037 | omap_obj->flags, obj->name, kref_read(&obj->refcount), | 1041 | omap_obj->flags, obj->name, kref_read(&obj->refcount), |
1038 | off, &omap_obj->dma_addr, omap_obj->dma_addr_cnt, | 1042 | off, &omap_obj->dma_addr, omap_obj->dma_addr_cnt, |
@@ -1050,6 +1054,8 @@ void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m) | |||
1050 | seq_printf(m, " %zu", obj->size); | 1054 | seq_printf(m, " %zu", obj->size); |
1051 | } | 1055 | } |
1052 | 1056 | ||
1057 | mutex_unlock(&omap_obj->lock); | ||
1058 | |||
1053 | seq_printf(m, "\n"); | 1059 | seq_printf(m, "\n"); |
1054 | } | 1060 | } |
1055 | 1061 | ||
@@ -1081,17 +1087,21 @@ void omap_gem_free_object(struct drm_gem_object *obj) | |||
1081 | struct omap_drm_private *priv = dev->dev_private; | 1087 | struct omap_drm_private *priv = dev->dev_private; |
1082 | struct omap_gem_object *omap_obj = to_omap_bo(obj); | 1088 | struct omap_gem_object *omap_obj = to_omap_bo(obj); |
1083 | 1089 | ||
1084 | evict(obj); | 1090 | omap_gem_evict(obj); |
1085 | |||
1086 | WARN_ON(!mutex_is_locked(&dev->struct_mutex)); | ||
1087 | 1091 | ||
1088 | spin_lock(&priv->list_lock); | 1092 | mutex_lock(&priv->list_lock); |
1089 | list_del(&omap_obj->mm_list); | 1093 | list_del(&omap_obj->mm_list); |
1090 | spin_unlock(&priv->list_lock); | 1094 | mutex_unlock(&priv->list_lock); |
1091 | 1095 | ||
1092 | /* this means the object is still pinned.. which really should | 1096 | /* |
1093 | * not happen. I think.. | 1097 | * We own the sole reference to the object at this point, but to keep |
1098 | * lockdep happy, we must still take the omap_obj_lock to call | ||
1099 | * omap_gem_detach_pages(). This should hardly make any difference as | ||
1100 | * there can't be any lock contention. | ||
1094 | */ | 1101 | */ |
1102 | mutex_lock(&omap_obj->lock); | ||
1103 | |||
1104 | /* The object should not be pinned. */ | ||
1095 | WARN_ON(omap_obj->dma_addr_cnt > 0); | 1105 | WARN_ON(omap_obj->dma_addr_cnt > 0); |
1096 | 1106 | ||
1097 | if (omap_obj->pages) { | 1107 | if (omap_obj->pages) { |
@@ -1110,8 +1120,12 @@ void omap_gem_free_object(struct drm_gem_object *obj) | |||
1110 | drm_prime_gem_destroy(obj, omap_obj->sgt); | 1120 | drm_prime_gem_destroy(obj, omap_obj->sgt); |
1111 | } | 1121 | } |
1112 | 1122 | ||
1123 | mutex_unlock(&omap_obj->lock); | ||
1124 | |||
1113 | drm_gem_object_release(obj); | 1125 | drm_gem_object_release(obj); |
1114 | 1126 | ||
1127 | mutex_destroy(&omap_obj->lock); | ||
1128 | |||
1115 | kfree(omap_obj); | 1129 | kfree(omap_obj); |
1116 | } | 1130 | } |
1117 | 1131 | ||
@@ -1167,6 +1181,7 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev, | |||
1167 | 1181 | ||
1168 | obj = &omap_obj->base; | 1182 | obj = &omap_obj->base; |
1169 | omap_obj->flags = flags; | 1183 | omap_obj->flags = flags; |
1184 | mutex_init(&omap_obj->lock); | ||
1170 | 1185 | ||
1171 | if (flags & OMAP_BO_TILED) { | 1186 | if (flags & OMAP_BO_TILED) { |
1172 | /* | 1187 | /* |
@@ -1206,9 +1221,9 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev, | |||
1206 | goto err_release; | 1221 | goto err_release; |
1207 | } | 1222 | } |
1208 | 1223 | ||
1209 | spin_lock(&priv->list_lock); | 1224 | mutex_lock(&priv->list_lock); |
1210 | list_add(&omap_obj->mm_list, &priv->obj_list); | 1225 | list_add(&omap_obj->mm_list, &priv->obj_list); |
1211 | spin_unlock(&priv->list_lock); | 1226 | mutex_unlock(&priv->list_lock); |
1212 | 1227 | ||
1213 | return obj; | 1228 | return obj; |
1214 | 1229 | ||
@@ -1231,16 +1246,15 @@ struct drm_gem_object *omap_gem_new_dmabuf(struct drm_device *dev, size_t size, | |||
1231 | if (sgt->orig_nents != 1 && !priv->has_dmm) | 1246 | if (sgt->orig_nents != 1 && !priv->has_dmm) |
1232 | return ERR_PTR(-EINVAL); | 1247 | return ERR_PTR(-EINVAL); |
1233 | 1248 | ||
1234 | mutex_lock(&dev->struct_mutex); | ||
1235 | |||
1236 | gsize.bytes = PAGE_ALIGN(size); | 1249 | gsize.bytes = PAGE_ALIGN(size); |
1237 | obj = omap_gem_new(dev, gsize, OMAP_BO_MEM_DMABUF | OMAP_BO_WC); | 1250 | obj = omap_gem_new(dev, gsize, OMAP_BO_MEM_DMABUF | OMAP_BO_WC); |
1238 | if (!obj) { | 1251 | if (!obj) |
1239 | obj = ERR_PTR(-ENOMEM); | 1252 | return ERR_PTR(-ENOMEM); |
1240 | goto done; | ||
1241 | } | ||
1242 | 1253 | ||
1243 | omap_obj = to_omap_bo(obj); | 1254 | omap_obj = to_omap_bo(obj); |
1255 | |||
1256 | mutex_lock(&omap_obj->lock); | ||
1257 | |||
1244 | omap_obj->sgt = sgt; | 1258 | omap_obj->sgt = sgt; |
1245 | 1259 | ||
1246 | if (sgt->orig_nents == 1) { | 1260 | if (sgt->orig_nents == 1) { |
@@ -1276,7 +1290,7 @@ struct drm_gem_object *omap_gem_new_dmabuf(struct drm_device *dev, size_t size, | |||
1276 | } | 1290 | } |
1277 | 1291 | ||
1278 | done: | 1292 | done: |
1279 | mutex_unlock(&dev->struct_mutex); | 1293 | mutex_unlock(&omap_obj->lock); |
1280 | return obj; | 1294 | return obj; |
1281 | } | 1295 | } |
1282 | 1296 | ||
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.h b/drivers/gpu/drm/omapdrm/omap_gem.h index a78bde05193a..c1c45fbde155 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.h +++ b/drivers/gpu/drm/omapdrm/omap_gem.h | |||
@@ -21,6 +21,7 @@ | |||
21 | #define __OMAPDRM_GEM_H__ | 21 | #define __OMAPDRM_GEM_H__ |
22 | 22 | ||
23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
24 | #include <linux/mm_types.h> | ||
24 | 25 | ||
25 | enum dma_data_direction; | 26 | enum dma_data_direction; |
26 | 27 | ||
@@ -80,7 +81,7 @@ struct dma_buf *omap_gem_prime_export(struct drm_device *dev, | |||
80 | struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev, | 81 | struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev, |
81 | struct dma_buf *buffer); | 82 | struct dma_buf *buffer); |
82 | 83 | ||
83 | int omap_gem_fault(struct vm_fault *vmf); | 84 | vm_fault_t omap_gem_fault(struct vm_fault *vmf); |
84 | int omap_gem_roll(struct drm_gem_object *obj, u32 roll); | 85 | int omap_gem_roll(struct drm_gem_object *obj, u32 roll); |
85 | void omap_gem_cpu_sync_page(struct drm_gem_object *obj, int pgoff); | 86 | void omap_gem_cpu_sync_page(struct drm_gem_object *obj, int pgoff); |
86 | void omap_gem_dma_sync_buffer(struct drm_gem_object *obj, | 87 | void omap_gem_dma_sync_buffer(struct drm_gem_object *obj, |