drm/msm: return -EFAULT instead of bytes remaining
[cascardo/linux.git] / drivers / gpu / drm / msm / msm_rd.c
index 0857710..3a5fdfc 100644 (file)
  * This bypasses drm_debugfs_create_files() mainly because we need to use
  * our own fops for a bit more control.  In particular, we don't want to
  * do anything if userspace doesn't have the debugfs file open.
+ *
+ * The module-param "rd_full", which defaults to false, enables snapshotting
+ * all (non-written) buffers in the submit, rather than just cmdstream bo's.
+ * This is useful to capture the contents of (for example) vbo's or textures,
+ * or shader programs (if not emitted inline in cmdstream).
  */
 
 #ifdef CONFIG_DEBUG_FS
 #include "msm_gpu.h"
 #include "msm_gem.h"
 
+static bool rd_full = false;
+MODULE_PARM_DESC(rd_full, "If true, $debugfs/.../rd will snapshot all buffer contents");
+module_param_named(rd_full, rd_full, bool, 0600);
+
 enum rd_sect_type {
        RD_NONE,
        RD_TEST,       /* ascii text */
@@ -140,9 +149,10 @@ static ssize_t rd_read(struct file *file, char __user *buf,
                goto out;
 
        n = min_t(int, sz, circ_count_to_end(&rd->fifo));
-       ret = copy_to_user(buf, fptr, n);
-       if (ret)
+       if (copy_to_user(buf, fptr, n)) {
+               ret = -EFAULT;
                goto out;
+       }
 
        fifo->tail = (fifo->tail + n) & (BUF_SZ - 1);
        *ppos += n;
@@ -277,6 +287,31 @@ void msm_rd_debugfs_cleanup(struct drm_minor *minor)
        kfree(rd);
 }
 
+static void snapshot_buf(struct msm_rd_state *rd,
+               struct msm_gem_submit *submit, int idx,
+               uint32_t iova, uint32_t size)
+{
+       struct msm_gem_object *obj = submit->bos[idx].obj;
+       const char *buf;
+
+       buf = msm_gem_get_vaddr_locked(&obj->base);
+       if (IS_ERR(buf))
+               return;
+
+       if (iova) {
+               buf += iova - submit->bos[idx].iova;
+       } else {
+               iova = submit->bos[idx].iova;
+               size = obj->base.size;
+       }
+
+       rd_write_section(rd, RD_GPUADDR,
+                       (uint32_t[2]){ iova, size }, 8);
+       rd_write_section(rd, RD_BUFFER_CONTENTS, buf, size);
+
+       msm_gem_put_vaddr_locked(&obj->base);
+}
+
 /* called under struct_mutex */
 void msm_rd_dump_submit(struct msm_gem_submit *submit)
 {
@@ -300,27 +335,27 @@ void msm_rd_dump_submit(struct msm_gem_submit *submit)
 
        rd_write_section(rd, RD_CMD, msg, ALIGN(n, 4));
 
-       /* could be nice to have an option (module-param?) to snapshot
-        * all the bo's associated with the submit.  Handy to see vtx
-        * buffers, etc.  For now just the cmdstream bo's is enough.
-        */
+       if (rd_full) {
+               for (i = 0; i < submit->nr_bos; i++) {
+                       /* buffers that are written to probably don't start out
+                        * with anything interesting:
+                        */
+                       if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE)
+                               continue;
+
+                       snapshot_buf(rd, submit, i, 0, 0);
+               }
+       }
 
        for (i = 0; i < submit->nr_cmds; i++) {
-               uint32_t idx  = submit->cmd[i].idx;
                uint32_t iova = submit->cmd[i].iova;
                uint32_t szd  = submit->cmd[i].size; /* in dwords */
-               struct msm_gem_object *obj = submit->bos[idx].obj;
-               const char *buf = msm_gem_vaddr_locked(&obj->base);
-
-               if (IS_ERR(buf))
-                       continue;
 
-               buf += iova - submit->bos[idx].iova;
-
-               rd_write_section(rd, RD_GPUADDR,
-                               (uint32_t[2]){ iova, szd * 4 }, 8);
-               rd_write_section(rd, RD_BUFFER_CONTENTS,
-                               buf, szd * 4);
+               /* snapshot cmdstream bo's (if we haven't already): */
+               if (!rd_full) {
+                       snapshot_buf(rd, submit, submit->cmd[i].idx,
+                                       submit->cmd[i].iova, szd * 4);
+               }
 
                switch (submit->cmd[i].type) {
                case MSM_SUBMIT_CMD_IB_TARGET_BUF: