diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2013-02-18 17:50:51 -0500 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2013-02-20 01:01:02 -0500 |
commit | 5cc027f6b1ec651c18a4322ed3e30c6e9cf01e96 (patch) | |
tree | 1f39b3fb82ea8e7d395a974584f5915c95dcfa6c /drivers/gpu/drm/nouveau | |
parent | 7dcd060c0e6e4f76ce7eea94c66437ce8f546530 (diff) |
drm/nv50-/disp: handle supervisor tasks from workqueue
i2c_algo_bit sleeps...
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau')
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nv50.c | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nv50.h | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nv84.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nv94.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nva0.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nva3.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c | 47 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nve0.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_display.c | 5 |
9 files changed, 53 insertions, 32 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c index c3806122d771..d22f6569768c 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c | |||
@@ -940,7 +940,6 @@ nv50_disp_intr_unk10(struct nv50_disp_priv *priv, u32 super) | |||
940 | exec_script(priv, head, 1); | 940 | exec_script(priv, head, 1); |
941 | } | 941 | } |
942 | 942 | ||
943 | nv_wr32(priv, 0x610024, 0x00000010); | ||
944 | nv_wr32(priv, 0x610030, 0x80000000); | 943 | nv_wr32(priv, 0x610030, 0x80000000); |
945 | } | 944 | } |
946 | 945 | ||
@@ -1097,7 +1096,6 @@ nv50_disp_intr_unk20(struct nv50_disp_priv *priv, u32 super) | |||
1097 | } | 1096 | } |
1098 | } | 1097 | } |
1099 | 1098 | ||
1100 | nv_wr32(priv, 0x610024, 0x00000020); | ||
1101 | nv_wr32(priv, 0x610030, 0x80000000); | 1099 | nv_wr32(priv, 0x610030, 0x80000000); |
1102 | } | 1100 | } |
1103 | 1101 | ||
@@ -1136,22 +1134,23 @@ nv50_disp_intr_unk40(struct nv50_disp_priv *priv, u32 super) | |||
1136 | } | 1134 | } |
1137 | } | 1135 | } |
1138 | 1136 | ||
1139 | nv_wr32(priv, 0x610024, 0x00000040); | ||
1140 | nv_wr32(priv, 0x610030, 0x80000000); | 1137 | nv_wr32(priv, 0x610030, 0x80000000); |
1141 | } | 1138 | } |
1142 | 1139 | ||
1143 | static void | 1140 | void |
1144 | nv50_disp_intr_super(struct nv50_disp_priv *priv, u32 intr1) | 1141 | nv50_disp_intr_supervisor(struct work_struct *work) |
1145 | { | 1142 | { |
1143 | struct nv50_disp_priv *priv = | ||
1144 | container_of(work, struct nv50_disp_priv, supervisor); | ||
1146 | u32 super = nv_rd32(priv, 0x610030); | 1145 | u32 super = nv_rd32(priv, 0x610030); |
1147 | 1146 | ||
1148 | nv_debug(priv, "supervisor 0x%08x 0x%08x\n", intr1, super); | 1147 | nv_debug(priv, "supervisor 0x%08x 0x%08x\n", priv->super, super); |
1149 | 1148 | ||
1150 | if (intr1 & 0x00000010) | 1149 | if (priv->super & 0x00000010) |
1151 | nv50_disp_intr_unk10(priv, super); | 1150 | nv50_disp_intr_unk10(priv, super); |
1152 | if (intr1 & 0x00000020) | 1151 | if (priv->super & 0x00000020) |
1153 | nv50_disp_intr_unk20(priv, super); | 1152 | nv50_disp_intr_unk20(priv, super); |
1154 | if (intr1 & 0x00000040) | 1153 | if (priv->super & 0x00000040) |
1155 | nv50_disp_intr_unk40(priv, super); | 1154 | nv50_disp_intr_unk40(priv, super); |
1156 | } | 1155 | } |
1157 | 1156 | ||
@@ -1180,7 +1179,9 @@ nv50_disp_intr(struct nouveau_subdev *subdev) | |||
1180 | } | 1179 | } |
1181 | 1180 | ||
1182 | if (intr1 & 0x00000070) { | 1181 | if (intr1 & 0x00000070) { |
1183 | nv50_disp_intr_super(priv, intr1); | 1182 | priv->super = (intr1 & 0x00000070); |
1183 | schedule_work(&priv->supervisor); | ||
1184 | nv_wr32(priv, 0x610024, priv->super); | ||
1184 | intr1 &= ~0x00000070; | 1185 | intr1 &= ~0x00000070; |
1185 | } | 1186 | } |
1186 | } | 1187 | } |
@@ -1202,6 +1203,7 @@ nv50_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
1202 | nv_engine(priv)->sclass = nv50_disp_base_oclass; | 1203 | nv_engine(priv)->sclass = nv50_disp_base_oclass; |
1203 | nv_engine(priv)->cclass = &nv50_disp_cclass; | 1204 | nv_engine(priv)->cclass = &nv50_disp_cclass; |
1204 | nv_subdev(priv)->intr = nv50_disp_intr; | 1205 | nv_subdev(priv)->intr = nv50_disp_intr; |
1206 | INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor); | ||
1205 | priv->sclass = nv50_disp_sclass; | 1207 | priv->sclass = nv50_disp_sclass; |
1206 | priv->head.nr = 2; | 1208 | priv->head.nr = 2; |
1207 | priv->dac.nr = 3; | 1209 | priv->dac.nr = 3; |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h index fc897181fa38..b88a62129814 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h | |||
@@ -15,6 +15,10 @@ struct dcb_output; | |||
15 | struct nv50_disp_priv { | 15 | struct nv50_disp_priv { |
16 | struct nouveau_disp base; | 16 | struct nouveau_disp base; |
17 | struct nouveau_oclass *sclass; | 17 | struct nouveau_oclass *sclass; |
18 | |||
19 | struct work_struct supervisor; | ||
20 | u32 super; | ||
21 | |||
18 | struct { | 22 | struct { |
19 | int nr; | 23 | int nr; |
20 | } head; | 24 | } head; |
@@ -126,6 +130,7 @@ extern struct nouveau_ofuncs nv50_disp_oimm_ofuncs; | |||
126 | extern struct nouveau_ofuncs nv50_disp_curs_ofuncs; | 130 | extern struct nouveau_ofuncs nv50_disp_curs_ofuncs; |
127 | extern struct nouveau_ofuncs nv50_disp_base_ofuncs; | 131 | extern struct nouveau_ofuncs nv50_disp_base_ofuncs; |
128 | extern struct nouveau_oclass nv50_disp_cclass; | 132 | extern struct nouveau_oclass nv50_disp_cclass; |
133 | void nv50_disp_intr_supervisor(struct work_struct *); | ||
129 | void nv50_disp_intr(struct nouveau_subdev *); | 134 | void nv50_disp_intr(struct nouveau_subdev *); |
130 | 135 | ||
131 | extern struct nouveau_omthds nv84_disp_base_omthds[]; | 136 | extern struct nouveau_omthds nv84_disp_base_omthds[]; |
@@ -139,6 +144,7 @@ extern struct nouveau_ofuncs nvd0_disp_oimm_ofuncs; | |||
139 | extern struct nouveau_ofuncs nvd0_disp_curs_ofuncs; | 144 | extern struct nouveau_ofuncs nvd0_disp_curs_ofuncs; |
140 | extern struct nouveau_ofuncs nvd0_disp_base_ofuncs; | 145 | extern struct nouveau_ofuncs nvd0_disp_base_ofuncs; |
141 | extern struct nouveau_oclass nvd0_disp_cclass; | 146 | extern struct nouveau_oclass nvd0_disp_cclass; |
147 | void nvd0_disp_intr_supervisor(struct work_struct *); | ||
142 | void nvd0_disp_intr(struct nouveau_subdev *); | 148 | void nvd0_disp_intr(struct nouveau_subdev *); |
143 | 149 | ||
144 | #endif | 150 | #endif |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c index a2153424605d..9ec942a0f9f6 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c | |||
@@ -72,6 +72,7 @@ nv84_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
72 | nv_engine(priv)->sclass = nv84_disp_base_oclass; | 72 | nv_engine(priv)->sclass = nv84_disp_base_oclass; |
73 | nv_engine(priv)->cclass = &nv50_disp_cclass; | 73 | nv_engine(priv)->cclass = &nv50_disp_cclass; |
74 | nv_subdev(priv)->intr = nv50_disp_intr; | 74 | nv_subdev(priv)->intr = nv50_disp_intr; |
75 | INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor); | ||
75 | priv->sclass = nv84_disp_sclass; | 76 | priv->sclass = nv84_disp_sclass; |
76 | priv->head.nr = 2; | 77 | priv->head.nr = 2; |
77 | priv->dac.nr = 3; | 78 | priv->dac.nr = 3; |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c index a315e28ac17e..a838bdd2019b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c | |||
@@ -78,6 +78,7 @@ nv94_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
78 | nv_engine(priv)->sclass = nv94_disp_base_oclass; | 78 | nv_engine(priv)->sclass = nv94_disp_base_oclass; |
79 | nv_engine(priv)->cclass = &nv50_disp_cclass; | 79 | nv_engine(priv)->cclass = &nv50_disp_cclass; |
80 | nv_subdev(priv)->intr = nv50_disp_intr; | 80 | nv_subdev(priv)->intr = nv50_disp_intr; |
81 | INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor); | ||
81 | priv->sclass = nv94_disp_sclass; | 82 | priv->sclass = nv94_disp_sclass; |
82 | priv->head.nr = 2; | 83 | priv->head.nr = 2; |
83 | priv->dac.nr = 3; | 84 | priv->dac.nr = 3; |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c index 480e2ded95fa..ce539ca1d308 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c | |||
@@ -62,6 +62,7 @@ nva0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
62 | nv_engine(priv)->sclass = nva0_disp_base_oclass; | 62 | nv_engine(priv)->sclass = nva0_disp_base_oclass; |
63 | nv_engine(priv)->cclass = &nv50_disp_cclass; | 63 | nv_engine(priv)->cclass = &nv50_disp_cclass; |
64 | nv_subdev(priv)->intr = nv50_disp_intr; | 64 | nv_subdev(priv)->intr = nv50_disp_intr; |
65 | INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor); | ||
65 | priv->sclass = nva0_disp_sclass; | 66 | priv->sclass = nva0_disp_sclass; |
66 | priv->head.nr = 2; | 67 | priv->head.nr = 2; |
67 | priv->dac.nr = 3; | 68 | priv->dac.nr = 3; |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c index 718b4f66352e..bd2bb4751089 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c | |||
@@ -79,6 +79,7 @@ nva3_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
79 | nv_engine(priv)->sclass = nva3_disp_base_oclass; | 79 | nv_engine(priv)->sclass = nva3_disp_base_oclass; |
80 | nv_engine(priv)->cclass = &nv50_disp_cclass; | 80 | nv_engine(priv)->cclass = &nv50_disp_cclass; |
81 | nv_subdev(priv)->intr = nv50_disp_intr; | 81 | nv_subdev(priv)->intr = nv50_disp_intr; |
82 | INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor); | ||
82 | priv->sclass = nva3_disp_sclass; | 83 | priv->sclass = nva3_disp_sclass; |
83 | priv->head.nr = 2; | 84 | priv->head.nr = 2; |
84 | priv->dac.nr = 3; | 85 | priv->dac.nr = 3; |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c index 77cc73024072..1c91eb1679a0 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c | |||
@@ -836,6 +836,26 @@ nvd0_display_unk4_handler(struct nv50_disp_priv *priv, u32 head, u32 mask) | |||
836 | } | 836 | } |
837 | 837 | ||
838 | void | 838 | void |
839 | nvd0_disp_intr_supervisor(struct work_struct *work) | ||
840 | { | ||
841 | struct nv50_disp_priv *priv = | ||
842 | container_of(work, struct nv50_disp_priv, supervisor); | ||
843 | u32 mask = 0, head = ~0; | ||
844 | |||
845 | while (!mask && ++head < priv->head.nr) | ||
846 | mask = nv_rd32(priv, 0x6101d4 + (head * 0x800)); | ||
847 | |||
848 | nv_debug(priv, "supervisor %08x %08x %d\n", priv->super, mask, head); | ||
849 | |||
850 | if (priv->super & 0x00000001) | ||
851 | nvd0_display_unk1_handler(priv, head, mask); | ||
852 | if (priv->super & 0x00000002) | ||
853 | nvd0_display_unk2_handler(priv, head, mask); | ||
854 | if (priv->super & 0x00000004) | ||
855 | nvd0_display_unk4_handler(priv, head, mask); | ||
856 | } | ||
857 | |||
858 | void | ||
839 | nvd0_disp_intr(struct nouveau_subdev *subdev) | 859 | nvd0_disp_intr(struct nouveau_subdev *subdev) |
840 | { | 860 | { |
841 | struct nv50_disp_priv *priv = (void *)subdev; | 861 | struct nv50_disp_priv *priv = (void *)subdev; |
@@ -868,27 +888,11 @@ nvd0_disp_intr(struct nouveau_subdev *subdev) | |||
868 | 888 | ||
869 | if (intr & 0x00100000) { | 889 | if (intr & 0x00100000) { |
870 | u32 stat = nv_rd32(priv, 0x6100ac); | 890 | u32 stat = nv_rd32(priv, 0x6100ac); |
871 | u32 mask = 0, crtc = ~0; | 891 | if (stat & 0x00000007) { |
872 | 892 | priv->super = (stat & 0x00000007); | |
873 | while (!mask && ++crtc < priv->head.nr) | 893 | schedule_work(&priv->supervisor); |
874 | mask = nv_rd32(priv, 0x6101d4 + (crtc * 0x800)); | 894 | nv_wr32(priv, 0x6100ac, priv->super); |
875 | 895 | stat &= ~0x00000007; | |
876 | if (stat & 0x00000001) { | ||
877 | nv_wr32(priv, 0x6100ac, 0x00000001); | ||
878 | nvd0_display_unk1_handler(priv, crtc, mask); | ||
879 | stat &= ~0x00000001; | ||
880 | } | ||
881 | |||
882 | if (stat & 0x00000002) { | ||
883 | nv_wr32(priv, 0x6100ac, 0x00000002); | ||
884 | nvd0_display_unk2_handler(priv, crtc, mask); | ||
885 | stat &= ~0x00000002; | ||
886 | } | ||
887 | |||
888 | if (stat & 0x00000004) { | ||
889 | nv_wr32(priv, 0x6100ac, 0x00000004); | ||
890 | nvd0_display_unk4_handler(priv, crtc, mask); | ||
891 | stat &= ~0x00000004; | ||
892 | } | 896 | } |
893 | 897 | ||
894 | if (stat) { | 898 | if (stat) { |
@@ -929,6 +933,7 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
929 | nv_engine(priv)->sclass = nvd0_disp_base_oclass; | 933 | nv_engine(priv)->sclass = nvd0_disp_base_oclass; |
930 | nv_engine(priv)->cclass = &nv50_disp_cclass; | 934 | nv_engine(priv)->cclass = &nv50_disp_cclass; |
931 | nv_subdev(priv)->intr = nvd0_disp_intr; | 935 | nv_subdev(priv)->intr = nvd0_disp_intr; |
936 | INIT_WORK(&priv->supervisor, nvd0_disp_intr_supervisor); | ||
932 | priv->sclass = nvd0_disp_sclass; | 937 | priv->sclass = nvd0_disp_sclass; |
933 | priv->head.nr = heads; | 938 | priv->head.nr = heads; |
934 | priv->dac.nr = 3; | 939 | priv->dac.nr = 3; |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c index 5512296a61d7..65c19ca073b1 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c | |||
@@ -63,6 +63,7 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
63 | nv_engine(priv)->sclass = nve0_disp_base_oclass; | 63 | nv_engine(priv)->sclass = nve0_disp_base_oclass; |
64 | nv_engine(priv)->cclass = &nv50_disp_cclass; | 64 | nv_engine(priv)->cclass = &nv50_disp_cclass; |
65 | nv_subdev(priv)->intr = nvd0_disp_intr; | 65 | nv_subdev(priv)->intr = nvd0_disp_intr; |
66 | INIT_WORK(&priv->supervisor, nvd0_disp_intr_supervisor); | ||
66 | priv->sclass = nve0_disp_sclass; | 67 | priv->sclass = nve0_disp_sclass; |
67 | priv->head.nr = heads; | 68 | priv->head.nr = heads; |
68 | priv->dac.nr = 3; | 69 | priv->dac.nr = 3; |
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 75d116137c0a..2cd37979dcd3 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c | |||
@@ -424,7 +424,10 @@ evo_kick(u32 *push, void *evoc) | |||
424 | static bool | 424 | static bool |
425 | evo_sync_wait(void *data) | 425 | evo_sync_wait(void *data) |
426 | { | 426 | { |
427 | return nouveau_bo_rd32(data, EVO_MAST_NTFY) != 0x00000000; | 427 | if (nouveau_bo_rd32(data, EVO_MAST_NTFY) != 0x00000000) |
428 | return true; | ||
429 | usleep_range(1, 2); | ||
430 | return false; | ||
428 | } | 431 | } |
429 | 432 | ||
430 | static int | 433 | static int |