1caab277bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2a7d3c950SRob Clark /*
3a7d3c950SRob Clark * Copyright (C) 2013 Red Hat
4a7d3c950SRob Clark * Author: Rob Clark <robdclark@gmail.com>
5a7d3c950SRob Clark */
6a7d3c950SRob Clark
7a7d3c950SRob Clark /* For debugging crashes, userspace can:
8a7d3c950SRob Clark *
9a7d3c950SRob Clark * tail -f /sys/kernel/debug/dri/<minor>/rd > logfile.rd
10a7d3c950SRob Clark *
112165e2b9SRob Clark * to log the cmdstream in a format that is understood by freedreno/cffdump
12a7d3c950SRob Clark * utility. By comparing the last successfully completed fence #, to the
13a7d3c950SRob Clark * cmdstream for the next fence, you can narrow down which process and submit
14a7d3c950SRob Clark * caused the gpu crash/lockup.
15a7d3c950SRob Clark *
162165e2b9SRob Clark * Additionally:
172165e2b9SRob Clark *
182165e2b9SRob Clark * tail -f /sys/kernel/debug/dri/<minor>/hangrd > logfile.rd
192165e2b9SRob Clark *
202165e2b9SRob Clark * will capture just the cmdstream from submits which triggered a GPU hang.
212165e2b9SRob Clark *
22a7d3c950SRob Clark * This bypasses drm_debugfs_create_files() mainly because we need to use
23a7d3c950SRob Clark * our own fops for a bit more control. In particular, we don't want to
24a7d3c950SRob Clark * do anything if userspace doesn't have the debugfs file open.
2579c21187SRob Clark *
2679c21187SRob Clark * The module-param "rd_full", which defaults to false, enables snapshotting
2779c21187SRob Clark * all (non-written) buffers in the submit, rather than just cmdstream bo's.
2879c21187SRob Clark * This is useful to capture the contents of (for example) vbo's or textures,
2979c21187SRob Clark * or shader programs (if not emitted inline in cmdstream).
30a7d3c950SRob Clark */
31a7d3c950SRob Clark
32a7d3c950SRob Clark #include <linux/circ_buf.h>
33feea39a8SSam Ravnborg #include <linux/debugfs.h>
34feea39a8SSam Ravnborg #include <linux/kfifo.h>
35feea39a8SSam Ravnborg #include <linux/uaccess.h>
36a7d3c950SRob Clark #include <linux/wait.h>
37a7d3c950SRob Clark
38feea39a8SSam Ravnborg #include <drm/drm_file.h>
39feea39a8SSam Ravnborg
40a7d3c950SRob Clark #include "msm_drv.h"
41a7d3c950SRob Clark #include "msm_gpu.h"
42a7d3c950SRob Clark #include "msm_gem.h"
43a7d3c950SRob Clark
44e515af8dSRob Clark bool rd_full = false;
4579c21187SRob Clark MODULE_PARM_DESC(rd_full, "If true, $debugfs/.../rd will snapshot all buffer contents");
4679c21187SRob Clark module_param_named(rd_full, rd_full, bool, 0600);
4779c21187SRob Clark
4820aebe83SBjorn Andersson #ifdef CONFIG_DEBUG_FS
4920aebe83SBjorn Andersson
50a7d3c950SRob Clark enum rd_sect_type {
51a7d3c950SRob Clark RD_NONE,
52a7d3c950SRob Clark RD_TEST, /* ascii text */
53a7d3c950SRob Clark RD_CMD, /* ascii text */
54a7d3c950SRob Clark RD_GPUADDR, /* u32 gpuaddr, u32 size */
55a7d3c950SRob Clark RD_CONTEXT, /* raw dump */
56a7d3c950SRob Clark RD_CMDSTREAM, /* raw dump */
57a7d3c950SRob Clark RD_CMDSTREAM_ADDR, /* gpu addr of cmdstream */
58a7d3c950SRob Clark RD_PARAM, /* u32 param_type, u32 param_val, u32 bitlen */
59a7d3c950SRob Clark RD_FLUSH, /* empty, clear previous params */
60a7d3c950SRob Clark RD_PROGRAM, /* shader program, raw dump */
61a7d3c950SRob Clark RD_VERT_SHADER,
62a7d3c950SRob Clark RD_FRAG_SHADER,
63a7d3c950SRob Clark RD_BUFFER_CONTENTS,
64a7d3c950SRob Clark RD_GPU_ID,
65cfdc428dSRob Clark RD_CHIP_ID,
66a7d3c950SRob Clark };
67a7d3c950SRob Clark
68a7d3c950SRob Clark #define BUF_SZ 512 /* should be power of 2 */
69a7d3c950SRob Clark
70a7d3c950SRob Clark /* space used: */
71a7d3c950SRob Clark #define circ_count(circ) \
72a7d3c950SRob Clark (CIRC_CNT((circ)->head, (circ)->tail, BUF_SZ))
73a7d3c950SRob Clark #define circ_count_to_end(circ) \
74a7d3c950SRob Clark (CIRC_CNT_TO_END((circ)->head, (circ)->tail, BUF_SZ))
75a7d3c950SRob Clark /* space available: */
76a7d3c950SRob Clark #define circ_space(circ) \
77a7d3c950SRob Clark (CIRC_SPACE((circ)->head, (circ)->tail, BUF_SZ))
78a7d3c950SRob Clark #define circ_space_to_end(circ) \
79a7d3c950SRob Clark (CIRC_SPACE_TO_END((circ)->head, (circ)->tail, BUF_SZ))
80a7d3c950SRob Clark
81a7d3c950SRob Clark struct msm_rd_state {
82a7d3c950SRob Clark struct drm_device *dev;
83a7d3c950SRob Clark
84a7d3c950SRob Clark bool open;
85a7d3c950SRob Clark
86a7d3c950SRob Clark /* fifo access is synchronized on the producer side by
87171f580eSRob Clark * write_lock. And read_lock synchronizes the reads
88a7d3c950SRob Clark */
89171f580eSRob Clark struct mutex read_lock, write_lock;
90a7d3c950SRob Clark
91a7d3c950SRob Clark wait_queue_head_t fifo_event;
92a7d3c950SRob Clark struct circ_buf fifo;
93a7d3c950SRob Clark
94a7d3c950SRob Clark char buf[BUF_SZ];
95a7d3c950SRob Clark };
96a7d3c950SRob Clark
rd_write(struct msm_rd_state * rd,const void * buf,int sz)97a7d3c950SRob Clark static void rd_write(struct msm_rd_state *rd, const void *buf, int sz)
98a7d3c950SRob Clark {
99a7d3c950SRob Clark struct circ_buf *fifo = &rd->fifo;
100a7d3c950SRob Clark const char *ptr = buf;
101a7d3c950SRob Clark
102a7d3c950SRob Clark while (sz > 0) {
103a7d3c950SRob Clark char *fptr = &fifo->buf[fifo->head];
104a7d3c950SRob Clark int n;
105a7d3c950SRob Clark
10699c66bc0SKristian H. Kristensen wait_event(rd->fifo_event, circ_space(&rd->fifo) > 0 || !rd->open);
10799c66bc0SKristian H. Kristensen if (!rd->open)
10899c66bc0SKristian H. Kristensen return;
109a7d3c950SRob Clark
110f44001e2SRob Clark /* Note that smp_load_acquire() is not strictly required
111f44001e2SRob Clark * as CIRC_SPACE_TO_END() does not access the tail more
112f44001e2SRob Clark * than once.
113f44001e2SRob Clark */
114a7d3c950SRob Clark n = min(sz, circ_space_to_end(&rd->fifo));
115a7d3c950SRob Clark memcpy(fptr, ptr, n);
116a7d3c950SRob Clark
117f44001e2SRob Clark smp_store_release(&fifo->head, (fifo->head + n) & (BUF_SZ - 1));
118a7d3c950SRob Clark sz -= n;
119a7d3c950SRob Clark ptr += n;
120a7d3c950SRob Clark
121a7d3c950SRob Clark wake_up_all(&rd->fifo_event);
122a7d3c950SRob Clark }
123a7d3c950SRob Clark }
124a7d3c950SRob Clark
rd_write_section(struct msm_rd_state * rd,enum rd_sect_type type,const void * buf,int sz)125a7d3c950SRob Clark static void rd_write_section(struct msm_rd_state *rd,
126a7d3c950SRob Clark enum rd_sect_type type, const void *buf, int sz)
127a7d3c950SRob Clark {
128a7d3c950SRob Clark rd_write(rd, &type, 4);
129a7d3c950SRob Clark rd_write(rd, &sz, 4);
130a7d3c950SRob Clark rd_write(rd, buf, sz);
131a7d3c950SRob Clark }
132a7d3c950SRob Clark
rd_read(struct file * file,char __user * buf,size_t sz,loff_t * ppos)133a7d3c950SRob Clark static ssize_t rd_read(struct file *file, char __user *buf,
134a7d3c950SRob Clark size_t sz, loff_t *ppos)
135a7d3c950SRob Clark {
136a7d3c950SRob Clark struct msm_rd_state *rd = file->private_data;
137a7d3c950SRob Clark struct circ_buf *fifo = &rd->fifo;
138a7d3c950SRob Clark const char *fptr = &fifo->buf[fifo->tail];
139a7d3c950SRob Clark int n = 0, ret = 0;
140a7d3c950SRob Clark
141a7d3c950SRob Clark mutex_lock(&rd->read_lock);
142a7d3c950SRob Clark
143a7d3c950SRob Clark ret = wait_event_interruptible(rd->fifo_event,
144a7d3c950SRob Clark circ_count(&rd->fifo) > 0);
145a7d3c950SRob Clark if (ret)
146a7d3c950SRob Clark goto out;
147a7d3c950SRob Clark
148f44001e2SRob Clark /* Note that smp_load_acquire() is not strictly required
149f44001e2SRob Clark * as CIRC_CNT_TO_END() does not access the head more than
150f44001e2SRob Clark * once.
151f44001e2SRob Clark */
152a7d3c950SRob Clark n = min_t(int, sz, circ_count_to_end(&rd->fifo));
1535745d21fSDan Carpenter if (copy_to_user(buf, fptr, n)) {
1545745d21fSDan Carpenter ret = -EFAULT;
155a7d3c950SRob Clark goto out;
1565745d21fSDan Carpenter }
157a7d3c950SRob Clark
158f44001e2SRob Clark smp_store_release(&fifo->tail, (fifo->tail + n) & (BUF_SZ - 1));
159a7d3c950SRob Clark *ppos += n;
160a7d3c950SRob Clark
161a7d3c950SRob Clark wake_up_all(&rd->fifo_event);
162a7d3c950SRob Clark
163a7d3c950SRob Clark out:
164a7d3c950SRob Clark mutex_unlock(&rd->read_lock);
165a7d3c950SRob Clark if (ret)
166a7d3c950SRob Clark return ret;
167a7d3c950SRob Clark return n;
168a7d3c950SRob Clark }
169a7d3c950SRob Clark
rd_open(struct inode * inode,struct file * file)170a7d3c950SRob Clark static int rd_open(struct inode *inode, struct file *file)
171a7d3c950SRob Clark {
172a7d3c950SRob Clark struct msm_rd_state *rd = inode->i_private;
173a7d3c950SRob Clark struct drm_device *dev = rd->dev;
174a7d3c950SRob Clark struct msm_drm_private *priv = dev->dev_private;
175a7d3c950SRob Clark struct msm_gpu *gpu = priv->gpu;
176a7d3c950SRob Clark uint64_t val;
177a7d3c950SRob Clark uint32_t gpu_id;
1784bfba716SRob Clark uint32_t zero = 0;
179a7d3c950SRob Clark int ret = 0;
180a7d3c950SRob Clark
181c28e2f2bSRob Clark if (!gpu)
182c28e2f2bSRob Clark return -ENODEV;
183a7d3c950SRob Clark
184c28e2f2bSRob Clark mutex_lock(&gpu->lock);
185c28e2f2bSRob Clark
186c28e2f2bSRob Clark if (rd->open) {
187a7d3c950SRob Clark ret = -EBUSY;
188a7d3c950SRob Clark goto out;
189a7d3c950SRob Clark }
190a7d3c950SRob Clark
191a7d3c950SRob Clark file->private_data = rd;
192a7d3c950SRob Clark rd->open = true;
193a7d3c950SRob Clark
194174974d8SRob Clark /* Reset fifo to clear any previously unread data: */
195174974d8SRob Clark rd->fifo.head = rd->fifo.tail = 0;
196174974d8SRob Clark
197a7d3c950SRob Clark /* the parsing tools need to know gpu-id to know which
198a7d3c950SRob Clark * register database to load.
199f98f915bSRob Clark *
200f98f915bSRob Clark * Note: These particular params do not require a context
201a7d3c950SRob Clark */
2024bfba716SRob Clark gpu->funcs->get_param(gpu, NULL, MSM_PARAM_GPU_ID, &val, &zero);
203a7d3c950SRob Clark gpu_id = val;
204a7d3c950SRob Clark
205a7d3c950SRob Clark rd_write_section(rd, RD_GPU_ID, &gpu_id, sizeof(gpu_id));
206a7d3c950SRob Clark
2074bfba716SRob Clark gpu->funcs->get_param(gpu, NULL, MSM_PARAM_CHIP_ID, &val, &zero);
208cfdc428dSRob Clark rd_write_section(rd, RD_CHIP_ID, &val, sizeof(val));
209cfdc428dSRob Clark
210a7d3c950SRob Clark out:
211c28e2f2bSRob Clark mutex_unlock(&gpu->lock);
212a7d3c950SRob Clark return ret;
213a7d3c950SRob Clark }
214a7d3c950SRob Clark
rd_release(struct inode * inode,struct file * file)215a7d3c950SRob Clark static int rd_release(struct inode *inode, struct file *file)
216a7d3c950SRob Clark {
217a7d3c950SRob Clark struct msm_rd_state *rd = inode->i_private;
21899c66bc0SKristian H. Kristensen
219a7d3c950SRob Clark rd->open = false;
22099c66bc0SKristian H. Kristensen wake_up_all(&rd->fifo_event);
22199c66bc0SKristian H. Kristensen
222a7d3c950SRob Clark return 0;
223a7d3c950SRob Clark }
224a7d3c950SRob Clark
225a7d3c950SRob Clark
226a7d3c950SRob Clark static const struct file_operations rd_debugfs_fops = {
227a7d3c950SRob Clark .owner = THIS_MODULE,
228a7d3c950SRob Clark .open = rd_open,
229a7d3c950SRob Clark .read = rd_read,
230a7d3c950SRob Clark .llseek = no_llseek,
231a7d3c950SRob Clark .release = rd_release,
232a7d3c950SRob Clark };
233a7d3c950SRob Clark
2342165e2b9SRob Clark
rd_cleanup(struct msm_rd_state * rd)2352165e2b9SRob Clark static void rd_cleanup(struct msm_rd_state *rd)
236a7d3c950SRob Clark {
2372165e2b9SRob Clark if (!rd)
2382165e2b9SRob Clark return;
2392165e2b9SRob Clark
2402165e2b9SRob Clark mutex_destroy(&rd->read_lock);
241171f580eSRob Clark mutex_destroy(&rd->write_lock);
2422165e2b9SRob Clark kfree(rd);
2432165e2b9SRob Clark }
2442165e2b9SRob Clark
rd_init(struct drm_minor * minor,const char * name)2452165e2b9SRob Clark static struct msm_rd_state *rd_init(struct drm_minor *minor, const char *name)
2462165e2b9SRob Clark {
247a7d3c950SRob Clark struct msm_rd_state *rd;
248a7d3c950SRob Clark
249a7d3c950SRob Clark rd = kzalloc(sizeof(*rd), GFP_KERNEL);
250a7d3c950SRob Clark if (!rd)
2512165e2b9SRob Clark return ERR_PTR(-ENOMEM);
252a7d3c950SRob Clark
253a7d3c950SRob Clark rd->dev = minor->dev;
254a7d3c950SRob Clark rd->fifo.buf = rd->buf;
255a7d3c950SRob Clark
256a7d3c950SRob Clark mutex_init(&rd->read_lock);
257171f580eSRob Clark mutex_init(&rd->write_lock);
258a7d3c950SRob Clark
259a7d3c950SRob Clark init_waitqueue_head(&rd->fifo_event);
260a7d3c950SRob Clark
261c8bffdcbSGreg Kroah-Hartman debugfs_create_file(name, S_IFREG | S_IRUGO, minor->debugfs_root, rd,
262c8bffdcbSGreg Kroah-Hartman &rd_debugfs_fops);
263a7d3c950SRob Clark
2642165e2b9SRob Clark return rd;
2652165e2b9SRob Clark }
2662165e2b9SRob Clark
msm_rd_debugfs_init(struct drm_minor * minor)2672165e2b9SRob Clark int msm_rd_debugfs_init(struct drm_minor *minor)
2682165e2b9SRob Clark {
2692165e2b9SRob Clark struct msm_drm_private *priv = minor->dev->dev_private;
2702165e2b9SRob Clark struct msm_rd_state *rd;
2712165e2b9SRob Clark int ret;
2722165e2b9SRob Clark
2732165e2b9SRob Clark /* only create on first minor: */
2742165e2b9SRob Clark if (priv->rd)
2752165e2b9SRob Clark return 0;
2762165e2b9SRob Clark
2772165e2b9SRob Clark rd = rd_init(minor, "rd");
2782165e2b9SRob Clark if (IS_ERR(rd)) {
2792165e2b9SRob Clark ret = PTR_ERR(rd);
2802165e2b9SRob Clark goto fail;
2812165e2b9SRob Clark }
2822165e2b9SRob Clark
2832165e2b9SRob Clark priv->rd = rd;
2842165e2b9SRob Clark
2852165e2b9SRob Clark rd = rd_init(minor, "hangrd");
2862165e2b9SRob Clark if (IS_ERR(rd)) {
2872165e2b9SRob Clark ret = PTR_ERR(rd);
2882165e2b9SRob Clark goto fail;
2892165e2b9SRob Clark }
2902165e2b9SRob Clark
2912165e2b9SRob Clark priv->hangrd = rd;
2922165e2b9SRob Clark
293a7d3c950SRob Clark return 0;
294a7d3c950SRob Clark
295a7d3c950SRob Clark fail:
29685eac470SNoralf Trønnes msm_rd_debugfs_cleanup(priv);
2972165e2b9SRob Clark return ret;
298a7d3c950SRob Clark }
299a7d3c950SRob Clark
msm_rd_debugfs_cleanup(struct msm_drm_private * priv)30085eac470SNoralf Trønnes void msm_rd_debugfs_cleanup(struct msm_drm_private *priv)
301a7d3c950SRob Clark {
3022165e2b9SRob Clark rd_cleanup(priv->rd);
303a7d3c950SRob Clark priv->rd = NULL;
3042165e2b9SRob Clark
3052165e2b9SRob Clark rd_cleanup(priv->hangrd);
3062165e2b9SRob Clark priv->hangrd = NULL;
307a7d3c950SRob Clark }
308a7d3c950SRob Clark
snapshot_buf(struct msm_rd_state * rd,struct msm_gem_submit * submit,int idx,uint64_t iova,uint32_t size,bool full)3096507e799SRob Clark static void snapshot_buf(struct msm_rd_state *rd,
3106507e799SRob Clark struct msm_gem_submit *submit, int idx,
311abdfd18fSRob Clark uint64_t iova, uint32_t size, bool full)
3126507e799SRob Clark {
313*6ba5daa5SRob Clark struct drm_gem_object *obj = submit->bos[idx].obj;
31447e7f506SRob Clark unsigned offset = 0;
3156507e799SRob Clark const char *buf;
3166507e799SRob Clark
31779c21187SRob Clark if (iova) {
31847e7f506SRob Clark offset = iova - submit->bos[idx].iova;
31979c21187SRob Clark } else {
32079c21187SRob Clark iova = submit->bos[idx].iova;
321*6ba5daa5SRob Clark size = obj->size;
32279c21187SRob Clark }
3236507e799SRob Clark
32478b8e5b8SJordan Crouse /*
32578b8e5b8SJordan Crouse * Always write the GPUADDR header so can get a complete list of all the
32678b8e5b8SJordan Crouse * buffers in the cmd
32778b8e5b8SJordan Crouse */
3286507e799SRob Clark rd_write_section(rd, RD_GPUADDR,
329d0651fe8SRob Clark (uint32_t[3]){ iova, size, iova >> 32 }, 12);
33078b8e5b8SJordan Crouse
331abdfd18fSRob Clark if (!full)
332abdfd18fSRob Clark return;
333abdfd18fSRob Clark
33478b8e5b8SJordan Crouse /* But only dump the contents of buffers marked READ */
33578b8e5b8SJordan Crouse if (!(submit->bos[idx].flags & MSM_SUBMIT_BO_READ))
33678b8e5b8SJordan Crouse return;
33778b8e5b8SJordan Crouse
338*6ba5daa5SRob Clark buf = msm_gem_get_vaddr_active(obj);
33978b8e5b8SJordan Crouse if (IS_ERR(buf))
340171f580eSRob Clark return;
34178b8e5b8SJordan Crouse
34247e7f506SRob Clark buf += offset;
34347e7f506SRob Clark
3446507e799SRob Clark rd_write_section(rd, RD_BUFFER_CONTENTS, buf, size);
3456507e799SRob Clark
346*6ba5daa5SRob Clark msm_gem_put_vaddr_locked(obj);
3476507e799SRob Clark }
3486507e799SRob Clark
349c28e2f2bSRob Clark /* called under gpu->lock */
msm_rd_dump_submit(struct msm_rd_state * rd,struct msm_gem_submit * submit,const char * fmt,...)350998b9a58SRob Clark void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit,
351998b9a58SRob Clark const char *fmt, ...)
352a7d3c950SRob Clark {
3532165e2b9SRob Clark struct task_struct *task;
354998b9a58SRob Clark char msg[256];
355a7d3c950SRob Clark int i, n;
356a7d3c950SRob Clark
357a7d3c950SRob Clark if (!rd->open)
358a7d3c950SRob Clark return;
359a7d3c950SRob Clark
360171f580eSRob Clark mutex_lock(&rd->write_lock);
361a7d3c950SRob Clark
362998b9a58SRob Clark if (fmt) {
363998b9a58SRob Clark va_list args;
364998b9a58SRob Clark
365998b9a58SRob Clark va_start(args, fmt);
366b689a830SRob Clark n = vscnprintf(msg, sizeof(msg), fmt, args);
367998b9a58SRob Clark va_end(args);
368998b9a58SRob Clark
369998b9a58SRob Clark rd_write_section(rd, RD_CMD, msg, ALIGN(n, 4));
370998b9a58SRob Clark }
371998b9a58SRob Clark
3722165e2b9SRob Clark rcu_read_lock();
3732165e2b9SRob Clark task = pid_task(submit->pid, PIDTYPE_PID);
3742165e2b9SRob Clark if (task) {
375b689a830SRob Clark n = scnprintf(msg, sizeof(msg), "%.*s/%d: fence=%u",
3762165e2b9SRob Clark TASK_COMM_LEN, task->comm,
3772165e2b9SRob Clark pid_nr(submit->pid), submit->seqno);
3782165e2b9SRob Clark } else {
379b689a830SRob Clark n = scnprintf(msg, sizeof(msg), "???/%d: fence=%u",
3802165e2b9SRob Clark pid_nr(submit->pid), submit->seqno);
3812165e2b9SRob Clark }
3822165e2b9SRob Clark rcu_read_unlock();
383a7d3c950SRob Clark
384a7d3c950SRob Clark rd_write_section(rd, RD_CMD, msg, ALIGN(n, 4));
385a7d3c950SRob Clark
3867a93d5c3SRob Clark for (i = 0; i < submit->nr_bos; i++)
387abdfd18fSRob Clark snapshot_buf(rd, submit, i, 0, 0, should_dump(submit, i));
388a7d3c950SRob Clark
389a7d3c950SRob Clark for (i = 0; i < submit->nr_cmds; i++) {
390a7d3c950SRob Clark uint32_t szd = submit->cmd[i].size; /* in dwords */
391a7d3c950SRob Clark
39279c21187SRob Clark /* snapshot cmdstream bo's (if we haven't already): */
3937a93d5c3SRob Clark if (!should_dump(submit, i)) {
3946507e799SRob Clark snapshot_buf(rd, submit, submit->cmd[i].idx,
395abdfd18fSRob Clark submit->cmd[i].iova, szd * 4, true);
39679c21187SRob Clark }
397c4b0222eSRob Clark }
398c4b0222eSRob Clark
399c4b0222eSRob Clark for (i = 0; i < submit->nr_cmds; i++) {
400c4b0222eSRob Clark uint64_t iova = submit->cmd[i].iova;
401c4b0222eSRob Clark uint32_t szd = submit->cmd[i].size; /* in dwords */
402a7d3c950SRob Clark
403a7d3c950SRob Clark switch (submit->cmd[i].type) {
404a7d3c950SRob Clark case MSM_SUBMIT_CMD_IB_TARGET_BUF:
405a7d3c950SRob Clark /* ignore IB-targets, we've logged the buffer, the
406a7d3c950SRob Clark * parser tool will follow the IB based on the logged
407a7d3c950SRob Clark * buffer/gpuaddr, so nothing more to do.
408a7d3c950SRob Clark */
409a7d3c950SRob Clark break;
410a7d3c950SRob Clark case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
411a7d3c950SRob Clark case MSM_SUBMIT_CMD_BUF:
412a7d3c950SRob Clark rd_write_section(rd, RD_CMDSTREAM_ADDR,
41322dd5c14SJordan Crouse (uint32_t[3]){ iova, szd, iova >> 32 }, 12);
414a7d3c950SRob Clark break;
415a7d3c950SRob Clark }
416a7d3c950SRob Clark }
417171f580eSRob Clark
418171f580eSRob Clark mutex_unlock(&rd->write_lock);
419a7d3c950SRob Clark }
420a7d3c950SRob Clark #endif
421