diff options
author | Alex Waterman <alexw@nvidia.com> | 2016-11-07 19:12:45 -0500 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2017-01-04 18:53:55 -0500 |
commit | a0242464f5f12d9f10fbf0d05614bfadde84386c (patch) | |
tree | 2f5981f5b9e90811c675ef59e2d1ca10e440c0ed /drivers/gpu | |
parent | b82d27e38490dc1155ece7d433fbcb6713b5a53b (diff) |
gpu: nvgpu: Handle no GPU cases in helper funcs
In many helper functions like gk20a_readl() the code assumed that
the GPU is present and registers and available. However, during
GPU shutdown this may not be the case.
In theory the driver should not be accessing GPU registers during
GPU shutdown (since shutdown is triggered by GPU registers being
unavailable) but these changes handle any missed cases where this
may happen.
This goes for GPU device access as well. Many parts of the code
assume that if the struct gk20a is valid, the the GPU dev must be
there are well. This isn't always the case, it seems.
Bug 1816516
Bug 1807277
Change-Id: Icaf6fd56ab7860724e77bda0f5e8d48f0da15642
Signed-off-by: Alex Waterman <alexw@nvidia.com>
Reviewed-on: http://git-master/r/1250024
(cherry picked from commit e8c9997b2d7cd424d798ecfce1307e6193c0cf32)
Reviewed-on: http://git-master/r/1274473
GVS: Gerrit_Virtual_Submit
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.c | 5 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.h | 82 |
2 files changed, 66 insertions, 21 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index 5e56fc81..a65ca6c2 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c | |||
@@ -309,6 +309,11 @@ int gk20a_restore_registers(struct gk20a *g) | |||
309 | return 0; | 309 | return 0; |
310 | } | 310 | } |
311 | 311 | ||
312 | void __gk20a_warn_on_no_regs(void) | ||
313 | { | ||
314 | WARN_ONCE(1, "Attempted access to GPU regs after unmapping!"); | ||
315 | } | ||
316 | |||
312 | static void kunmap_and_free_iopage(void **kvaddr, struct page **page) | 317 | static void kunmap_and_free_iopage(void **kvaddr, struct page **page) |
313 | { | 318 | { |
314 | if (*kvaddr) { | 319 | if (*kvaddr) { |
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index d219b815..eab9843a 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h | |||
@@ -1107,11 +1107,18 @@ do { \ | |||
1107 | 1107 | ||
1108 | #endif | 1108 | #endif |
1109 | 1109 | ||
1110 | #define gk20a_err(d, fmt, arg...) \ | 1110 | #define gk20a_err(d, fmt, arg...) \ |
1111 | dev_err(d, "%s: " fmt "\n", __func__, ##arg) | 1111 | do { \ |
1112 | if (d) \ | ||
1113 | dev_err(d, "%s: " fmt "\n", __func__, ##arg); \ | ||
1114 | } while (0) | ||
1115 | |||
1116 | #define gk20a_warn(d, fmt, arg...) \ | ||
1117 | do { \ | ||
1118 | if (d) \ | ||
1119 | dev_warn(d, "%s: " fmt "\n", __func__, ##arg); \ | ||
1120 | } while (0) | ||
1112 | 1121 | ||
1113 | #define gk20a_warn(d, fmt, arg...) \ | ||
1114 | dev_warn(d, "%s: " fmt "\n", __func__, ##arg) | ||
1115 | 1122 | ||
1116 | #define gk20a_dbg_fn(fmt, arg...) \ | 1123 | #define gk20a_dbg_fn(fmt, arg...) \ |
1117 | gk20a_dbg(gpu_dbg_fn, fmt, ##arg) | 1124 | gk20a_dbg(gpu_dbg_fn, fmt, ##arg) |
@@ -1126,44 +1133,74 @@ int gk20a_lockout_registers(struct gk20a *g); | |||
1126 | int gk20a_restore_registers(struct gk20a *g); | 1133 | int gk20a_restore_registers(struct gk20a *g); |
1127 | 1134 | ||
1128 | void __nvgpu_check_gpu_state(struct gk20a *g); | 1135 | void __nvgpu_check_gpu_state(struct gk20a *g); |
1136 | void __gk20a_warn_on_no_regs(void); | ||
1129 | 1137 | ||
1130 | static inline void gk20a_writel(struct gk20a *g, u32 r, u32 v) | 1138 | static inline void gk20a_writel(struct gk20a *g, u32 r, u32 v) |
1131 | { | 1139 | { |
1132 | gk20a_dbg(gpu_dbg_reg, " r=0x%x v=0x%x", r, v); | 1140 | if (unlikely(!g->regs)) { |
1133 | writel_relaxed(v, g->regs + r); | 1141 | __gk20a_warn_on_no_regs(); |
1134 | wmb(); | 1142 | gk20a_dbg(gpu_dbg_reg, "r=0x%x v=0x%x (failed)", r, v); |
1143 | } else { | ||
1144 | writel_relaxed(v, g->regs + r); | ||
1145 | wmb(); | ||
1146 | gk20a_dbg(gpu_dbg_reg, "r=0x%x v=0x%x", r, v); | ||
1147 | } | ||
1135 | } | 1148 | } |
1136 | static inline u32 gk20a_readl(struct gk20a *g, u32 r) | 1149 | static inline u32 gk20a_readl(struct gk20a *g, u32 r) |
1137 | { | 1150 | { |
1138 | u32 v = readl(g->regs + r); | ||
1139 | 1151 | ||
1140 | if (v == 0xffffffff) | 1152 | u32 v = 0xffffffff; |
1141 | __nvgpu_check_gpu_state(g); | ||
1142 | 1153 | ||
1143 | gk20a_dbg(gpu_dbg_reg, " r=0x%x v=0x%x", r, v); | 1154 | if (unlikely(!g->regs)) { |
1155 | __gk20a_warn_on_no_regs(); | ||
1156 | gk20a_dbg(gpu_dbg_reg, "r=0x%x v=0x%x (failed)", r, v); | ||
1157 | } else { | ||
1158 | v = readl(g->regs + r); | ||
1159 | if (v == 0xffffffff) | ||
1160 | __nvgpu_check_gpu_state(g); | ||
1161 | gk20a_dbg(gpu_dbg_reg, "r=0x%x v=0x%x", r, v); | ||
1162 | } | ||
1144 | 1163 | ||
1145 | return v; | 1164 | return v; |
1146 | } | 1165 | } |
1147 | static inline void gk20a_writel_check(struct gk20a *g, u32 r, u32 v) | 1166 | static inline void gk20a_writel_check(struct gk20a *g, u32 r, u32 v) |
1148 | { | 1167 | { |
1149 | gk20a_dbg(gpu_dbg_reg, " r=0x%x v=0x%x", r, v); | 1168 | if (unlikely(!g->regs)) { |
1150 | wmb(); | 1169 | __gk20a_warn_on_no_regs(); |
1151 | do { | 1170 | gk20a_dbg(gpu_dbg_reg, "r=0x%x v=0x%x (failed)", r, v); |
1152 | writel_relaxed(v, g->regs + r); | 1171 | } else { |
1153 | } while (readl(g->regs + r) != v); | 1172 | wmb(); |
1173 | do { | ||
1174 | writel_relaxed(v, g->regs + r); | ||
1175 | } while (readl(g->regs + r) != v); | ||
1176 | gk20a_dbg(gpu_dbg_reg, "r=0x%x v=0x%x", r, v); | ||
1177 | } | ||
1154 | } | 1178 | } |
1155 | 1179 | ||
1156 | static inline void gk20a_bar1_writel(struct gk20a *g, u32 b, u32 v) | 1180 | static inline void gk20a_bar1_writel(struct gk20a *g, u32 b, u32 v) |
1157 | { | 1181 | { |
1158 | gk20a_dbg(gpu_dbg_reg, " b=0x%x v=0x%x", b, v); | 1182 | if (unlikely(!g->bar1)) { |
1159 | wmb(); | 1183 | __gk20a_warn_on_no_regs(); |
1160 | writel_relaxed(v, g->bar1 + b); | 1184 | gk20a_dbg(gpu_dbg_reg, "b=0x%x v=0x%x (failed)", b, v); |
1185 | } else { | ||
1186 | wmb(); | ||
1187 | writel_relaxed(v, g->bar1 + b); | ||
1188 | gk20a_dbg(gpu_dbg_reg, "b=0x%x v=0x%x", b, v); | ||
1189 | } | ||
1161 | } | 1190 | } |
1162 | 1191 | ||
1163 | static inline u32 gk20a_bar1_readl(struct gk20a *g, u32 b) | 1192 | static inline u32 gk20a_bar1_readl(struct gk20a *g, u32 b) |
1164 | { | 1193 | { |
1165 | u32 v = readl(g->bar1 + b); | 1194 | u32 v = 0xffffffff; |
1166 | gk20a_dbg(gpu_dbg_reg, " b=0x%x v=0x%x", b, v); | 1195 | |
1196 | if (unlikely(!g->bar1)) { | ||
1197 | __gk20a_warn_on_no_regs(); | ||
1198 | gk20a_dbg(gpu_dbg_reg, "b=0x%x v=0x%x (failed)", b, v); | ||
1199 | } else { | ||
1200 | v = readl(g->bar1 + b); | ||
1201 | gk20a_dbg(gpu_dbg_reg, "b=0x%x v=0x%x", b, v); | ||
1202 | } | ||
1203 | |||
1167 | return v; | 1204 | return v; |
1168 | } | 1205 | } |
1169 | 1206 | ||
@@ -1174,6 +1211,9 @@ static inline struct device *dev_from_gk20a(struct gk20a *g) | |||
1174 | } | 1211 | } |
1175 | static inline struct gk20a *gk20a_from_dev(struct device *dev) | 1212 | static inline struct gk20a *gk20a_from_dev(struct device *dev) |
1176 | { | 1213 | { |
1214 | if (!dev) | ||
1215 | return NULL; | ||
1216 | |||
1177 | return ((struct gk20a_platform *)dev_get_drvdata(dev))->g; | 1217 | return ((struct gk20a_platform *)dev_get_drvdata(dev))->g; |
1178 | } | 1218 | } |
1179 | static inline struct gk20a *gk20a_from_as(struct gk20a_as *as) | 1219 | static inline struct gk20a *gk20a_from_as(struct gk20a_as *as) |