diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_debugfs.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_debugfs.c | 131 |
1 files changed, 123 insertions, 8 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 87c8e29465e3..51c2257b11e6 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
@@ -106,11 +106,12 @@ static const char *get_tiling_flag(struct drm_i915_gem_object *obj) | |||
106 | } | 106 | } |
107 | } | 107 | } |
108 | 108 | ||
109 | static const char *agp_type_str(int type) | 109 | static const char *cache_level_str(int type) |
110 | { | 110 | { |
111 | switch (type) { | 111 | switch (type) { |
112 | case 0: return " uncached"; | 112 | case I915_CACHE_NONE: return " uncached"; |
113 | case 1: return " snooped"; | 113 | case I915_CACHE_LLC: return " snooped (LLC)"; |
114 | case I915_CACHE_LLC_MLC: return " snooped (LLC+MLC)"; | ||
114 | default: return ""; | 115 | default: return ""; |
115 | } | 116 | } |
116 | } | 117 | } |
@@ -127,7 +128,7 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) | |||
127 | obj->base.write_domain, | 128 | obj->base.write_domain, |
128 | obj->last_rendering_seqno, | 129 | obj->last_rendering_seqno, |
129 | obj->last_fenced_seqno, | 130 | obj->last_fenced_seqno, |
130 | agp_type_str(obj->agp_type == AGP_USER_CACHED_MEMORY), | 131 | cache_level_str(obj->cache_level), |
131 | obj->dirty ? " dirty" : "", | 132 | obj->dirty ? " dirty" : "", |
132 | obj->madv == I915_MADV_DONTNEED ? " purgeable" : ""); | 133 | obj->madv == I915_MADV_DONTNEED ? " purgeable" : ""); |
133 | if (obj->base.name) | 134 | if (obj->base.name) |
@@ -714,7 +715,7 @@ static void print_error_buffers(struct seq_file *m, | |||
714 | dirty_flag(err->dirty), | 715 | dirty_flag(err->dirty), |
715 | purgeable_flag(err->purgeable), | 716 | purgeable_flag(err->purgeable), |
716 | ring_str(err->ring), | 717 | ring_str(err->ring), |
717 | agp_type_str(err->agp_type)); | 718 | cache_level_str(err->cache_level)); |
718 | 719 | ||
719 | if (err->name) | 720 | if (err->name) |
720 | seq_printf(m, " (name: %d)", err->name); | 721 | seq_printf(m, " (name: %d)", err->name); |
@@ -852,6 +853,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused) | |||
852 | struct drm_info_node *node = (struct drm_info_node *) m->private; | 853 | struct drm_info_node *node = (struct drm_info_node *) m->private; |
853 | struct drm_device *dev = node->minor->dev; | 854 | struct drm_device *dev = node->minor->dev; |
854 | drm_i915_private_t *dev_priv = dev->dev_private; | 855 | drm_i915_private_t *dev_priv = dev->dev_private; |
856 | int ret; | ||
855 | 857 | ||
856 | if (IS_GEN5(dev)) { | 858 | if (IS_GEN5(dev)) { |
857 | u16 rgvswctl = I915_READ16(MEMSWCTL); | 859 | u16 rgvswctl = I915_READ16(MEMSWCTL); |
@@ -873,7 +875,11 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused) | |||
873 | int max_freq; | 875 | int max_freq; |
874 | 876 | ||
875 | /* RPSTAT1 is in the GT power well */ | 877 | /* RPSTAT1 is in the GT power well */ |
876 | __gen6_gt_force_wake_get(dev_priv); | 878 | ret = mutex_lock_interruptible(&dev->struct_mutex); |
879 | if (ret) | ||
880 | return ret; | ||
881 | |||
882 | gen6_gt_force_wake_get(dev_priv); | ||
877 | 883 | ||
878 | rpstat = I915_READ(GEN6_RPSTAT1); | 884 | rpstat = I915_READ(GEN6_RPSTAT1); |
879 | rpupei = I915_READ(GEN6_RP_CUR_UP_EI); | 885 | rpupei = I915_READ(GEN6_RP_CUR_UP_EI); |
@@ -883,6 +889,9 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused) | |||
883 | rpcurdown = I915_READ(GEN6_RP_CUR_DOWN); | 889 | rpcurdown = I915_READ(GEN6_RP_CUR_DOWN); |
884 | rpprevdown = I915_READ(GEN6_RP_PREV_DOWN); | 890 | rpprevdown = I915_READ(GEN6_RP_PREV_DOWN); |
885 | 891 | ||
892 | gen6_gt_force_wake_put(dev_priv); | ||
893 | mutex_unlock(&dev->struct_mutex); | ||
894 | |||
886 | seq_printf(m, "GT_PERF_STATUS: 0x%08x\n", gt_perf_status); | 895 | seq_printf(m, "GT_PERF_STATUS: 0x%08x\n", gt_perf_status); |
887 | seq_printf(m, "RPSTAT1: 0x%08x\n", rpstat); | 896 | seq_printf(m, "RPSTAT1: 0x%08x\n", rpstat); |
888 | seq_printf(m, "Render p-state ratio: %d\n", | 897 | seq_printf(m, "Render p-state ratio: %d\n", |
@@ -917,8 +926,6 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused) | |||
917 | max_freq = rp_state_cap & 0xff; | 926 | max_freq = rp_state_cap & 0xff; |
918 | seq_printf(m, "Max non-overclocked (RP0) frequency: %dMHz\n", | 927 | seq_printf(m, "Max non-overclocked (RP0) frequency: %dMHz\n", |
919 | max_freq * 50); | 928 | max_freq * 50); |
920 | |||
921 | __gen6_gt_force_wake_put(dev_priv); | ||
922 | } else { | 929 | } else { |
923 | seq_printf(m, "no P-state info available\n"); | 930 | seq_printf(m, "no P-state info available\n"); |
924 | } | 931 | } |
@@ -1058,6 +1065,9 @@ static int i915_fbc_status(struct seq_file *m, void *unused) | |||
1058 | case FBC_MULTIPLE_PIPES: | 1065 | case FBC_MULTIPLE_PIPES: |
1059 | seq_printf(m, "multiple pipes are enabled"); | 1066 | seq_printf(m, "multiple pipes are enabled"); |
1060 | break; | 1067 | break; |
1068 | case FBC_MODULE_PARAM: | ||
1069 | seq_printf(m, "disabled per module param (default off)"); | ||
1070 | break; | ||
1061 | default: | 1071 | default: |
1062 | seq_printf(m, "unknown reason"); | 1072 | seq_printf(m, "unknown reason"); |
1063 | } | 1073 | } |
@@ -1186,6 +1196,42 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data) | |||
1186 | return 0; | 1196 | return 0; |
1187 | } | 1197 | } |
1188 | 1198 | ||
1199 | static int i915_context_status(struct seq_file *m, void *unused) | ||
1200 | { | ||
1201 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
1202 | struct drm_device *dev = node->minor->dev; | ||
1203 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
1204 | int ret; | ||
1205 | |||
1206 | ret = mutex_lock_interruptible(&dev->mode_config.mutex); | ||
1207 | if (ret) | ||
1208 | return ret; | ||
1209 | |||
1210 | seq_printf(m, "power context "); | ||
1211 | describe_obj(m, dev_priv->pwrctx); | ||
1212 | seq_printf(m, "\n"); | ||
1213 | |||
1214 | seq_printf(m, "render context "); | ||
1215 | describe_obj(m, dev_priv->renderctx); | ||
1216 | seq_printf(m, "\n"); | ||
1217 | |||
1218 | mutex_unlock(&dev->mode_config.mutex); | ||
1219 | |||
1220 | return 0; | ||
1221 | } | ||
1222 | |||
1223 | static int i915_gen6_forcewake_count_info(struct seq_file *m, void *data) | ||
1224 | { | ||
1225 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
1226 | struct drm_device *dev = node->minor->dev; | ||
1227 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1228 | |||
1229 | seq_printf(m, "forcewake count = %d\n", | ||
1230 | atomic_read(&dev_priv->forcewake_count)); | ||
1231 | |||
1232 | return 0; | ||
1233 | } | ||
1234 | |||
1189 | static int | 1235 | static int |
1190 | i915_wedged_open(struct inode *inode, | 1236 | i915_wedged_open(struct inode *inode, |
1191 | struct file *filp) | 1237 | struct file *filp) |
@@ -1288,6 +1334,67 @@ static int i915_wedged_create(struct dentry *root, struct drm_minor *minor) | |||
1288 | return drm_add_fake_info_node(minor, ent, &i915_wedged_fops); | 1334 | return drm_add_fake_info_node(minor, ent, &i915_wedged_fops); |
1289 | } | 1335 | } |
1290 | 1336 | ||
1337 | static int i915_forcewake_open(struct inode *inode, struct file *file) | ||
1338 | { | ||
1339 | struct drm_device *dev = inode->i_private; | ||
1340 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1341 | int ret; | ||
1342 | |||
1343 | if (!IS_GEN6(dev)) | ||
1344 | return 0; | ||
1345 | |||
1346 | ret = mutex_lock_interruptible(&dev->struct_mutex); | ||
1347 | if (ret) | ||
1348 | return ret; | ||
1349 | gen6_gt_force_wake_get(dev_priv); | ||
1350 | mutex_unlock(&dev->struct_mutex); | ||
1351 | |||
1352 | return 0; | ||
1353 | } | ||
1354 | |||
1355 | int i915_forcewake_release(struct inode *inode, struct file *file) | ||
1356 | { | ||
1357 | struct drm_device *dev = inode->i_private; | ||
1358 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1359 | |||
1360 | if (!IS_GEN6(dev)) | ||
1361 | return 0; | ||
1362 | |||
1363 | /* | ||
1364 | * It's bad that we can potentially hang userspace if struct_mutex gets | ||
1365 | * forever stuck. However, if we cannot acquire this lock it means that | ||
1366 | * almost certainly the driver has hung, is not unload-able. Therefore | ||
1367 | * hanging here is probably a minor inconvenience not to be seen my | ||
1368 | * almost every user. | ||
1369 | */ | ||
1370 | mutex_lock(&dev->struct_mutex); | ||
1371 | gen6_gt_force_wake_put(dev_priv); | ||
1372 | mutex_unlock(&dev->struct_mutex); | ||
1373 | |||
1374 | return 0; | ||
1375 | } | ||
1376 | |||
1377 | static const struct file_operations i915_forcewake_fops = { | ||
1378 | .owner = THIS_MODULE, | ||
1379 | .open = i915_forcewake_open, | ||
1380 | .release = i915_forcewake_release, | ||
1381 | }; | ||
1382 | |||
1383 | static int i915_forcewake_create(struct dentry *root, struct drm_minor *minor) | ||
1384 | { | ||
1385 | struct drm_device *dev = minor->dev; | ||
1386 | struct dentry *ent; | ||
1387 | |||
1388 | ent = debugfs_create_file("i915_forcewake_user", | ||
1389 | S_IRUSR, | ||
1390 | root, dev, | ||
1391 | &i915_forcewake_fops); | ||
1392 | if (IS_ERR(ent)) | ||
1393 | return PTR_ERR(ent); | ||
1394 | |||
1395 | return drm_add_fake_info_node(minor, ent, &i915_forcewake_fops); | ||
1396 | } | ||
1397 | |||
1291 | static struct drm_info_list i915_debugfs_list[] = { | 1398 | static struct drm_info_list i915_debugfs_list[] = { |
1292 | {"i915_capabilities", i915_capabilities, 0}, | 1399 | {"i915_capabilities", i915_capabilities, 0}, |
1293 | {"i915_gem_objects", i915_gem_object_info, 0}, | 1400 | {"i915_gem_objects", i915_gem_object_info, 0}, |
@@ -1324,6 +1431,8 @@ static struct drm_info_list i915_debugfs_list[] = { | |||
1324 | {"i915_sr_status", i915_sr_status, 0}, | 1431 | {"i915_sr_status", i915_sr_status, 0}, |
1325 | {"i915_opregion", i915_opregion, 0}, | 1432 | {"i915_opregion", i915_opregion, 0}, |
1326 | {"i915_gem_framebuffer", i915_gem_framebuffer_info, 0}, | 1433 | {"i915_gem_framebuffer", i915_gem_framebuffer_info, 0}, |
1434 | {"i915_context_status", i915_context_status, 0}, | ||
1435 | {"i915_gen6_forcewake_count", i915_gen6_forcewake_count_info, 0}, | ||
1327 | }; | 1436 | }; |
1328 | #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list) | 1437 | #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list) |
1329 | 1438 | ||
@@ -1335,6 +1444,10 @@ int i915_debugfs_init(struct drm_minor *minor) | |||
1335 | if (ret) | 1444 | if (ret) |
1336 | return ret; | 1445 | return ret; |
1337 | 1446 | ||
1447 | ret = i915_forcewake_create(minor->debugfs_root, minor); | ||
1448 | if (ret) | ||
1449 | return ret; | ||
1450 | |||
1338 | return drm_debugfs_create_files(i915_debugfs_list, | 1451 | return drm_debugfs_create_files(i915_debugfs_list, |
1339 | I915_DEBUGFS_ENTRIES, | 1452 | I915_DEBUGFS_ENTRIES, |
1340 | minor->debugfs_root, minor); | 1453 | minor->debugfs_root, minor); |
@@ -1344,6 +1457,8 @@ void i915_debugfs_cleanup(struct drm_minor *minor) | |||
1344 | { | 1457 | { |
1345 | drm_debugfs_remove_files(i915_debugfs_list, | 1458 | drm_debugfs_remove_files(i915_debugfs_list, |
1346 | I915_DEBUGFS_ENTRIES, minor); | 1459 | I915_DEBUGFS_ENTRIES, minor); |
1460 | drm_debugfs_remove_files((struct drm_info_list *) &i915_forcewake_fops, | ||
1461 | 1, minor); | ||
1347 | drm_debugfs_remove_files((struct drm_info_list *) &i915_wedged_fops, | 1462 | drm_debugfs_remove_files((struct drm_info_list *) &i915_wedged_fops, |
1348 | 1, minor); | 1463 | 1, minor); |
1349 | } | 1464 | } |