Minor improvements for Host1x driver
cover Minor improvements for Host1x driver
Hello,
This series contains some minor improvements for the Host1x driver which I picked up from an older local git branch. I selected the less invasive and most relevant patches and added one new patch that dumps the push buffer state, a day ago it helped me to debug SMMU driver issue that is easily triggered using the vanilla upstream Host1x driver.
Dmitry Osipenko (4):
gpu: host1x: Optimize BOs usage when firewall is enabled
gpu: host1x: Put gather's BO on pinning error
gpu: host1x: debug: Fix multiple channels emitting messages
simultaneously
gpu: host1x: debug: Dump push buffer state
drivers/gpu/host1x/debug.c | 4 ++++ drivers/gpu/host1x/hw/debug_hw.c | 6 ++++++ drivers/gpu/host1x/job.c | 27 ++++++++++++++++++++------- 3 files changed, 30 insertions(+), 7 deletions(-)
Signature · 1 line
2.26.0
PATCH 1/4 gpu: host1x: Optimize BOs usage when firewall is enabled
We don't need to hold and pin original BOs of the gathers in a case of enabled firewall because in this case gather's content is copied and the copy is used by the executed job.
--- drivers/gpu/host1x/job.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
drivers/gpu/host1x/job.c +12 -2
@@ -27,10 +27,13 @@ struct host1x_job *host1x_job_alloc(struct host1x_channel *ch, u32 num_cmdbufs, u32 num_relocs) {struct host1x_job *job =NULL ; -unsigned int num_unpins = num_cmdbufs + num_relocs; +unsigned int num_unpins = num_relocs;u64 total;void *mem; +if (!IS_ENABLED (CONFIG_TEGRA_HOST1X_FIREWALL )) + num_unpins += num_cmdbufs; +/* Check that we're not going to overflow */ total =sizeof (struct host1x_job ) + (u64)num_relocs * sizeof(struct host1x_reloc) +
@@ -183,6 +186,13 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) job->num_unpins++; } +/* +* We will copy gathers BO content later, so there is no need to +* hold and pin them. +*/ +if (IS_ENABLED (CONFIG_TEGRA_HOST1X_FIREWALL )) +return 0 ; +for (i =0 ; i < job->num_gathers; i++) {struct host1x_job_gather *g = &job->gathers[i];size_t gather_size =0 ;
@@ -216,7 +226,7 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) goto unpin; } -if (!IS_ENABLED (CONFIG_TEGRA_HOST1X_FIREWALL ) && host->domain) { +if (host->domain) {for_each_sg (sgt->sgl, sg, sgt->nents, j) gather_size += sg->length; gather_size =iova_align (&host->iova, gather_size);
Signature · 1 line
2.26.0
PATCH 2/4 gpu: host1x: Put gather's BO on pinning error
In reply to Dmitry OsipenkoThis patch fixes gather's BO refcounting on a pinning error. Gather's BO won't be leaked now if something goes wrong.
--- drivers/gpu/host1x/job.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
drivers/gpu/host1x/job.c +8 -5
@@ -105,6 +105,7 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) {struct host1x_client *client = job->client;struct device *dev = client->dev; +struct host1x_job_gather *g;struct iommu_domain *domain;unsigned int i;int err;
@@ -194,7 +195,6 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job)return 0 ;for (i =0 ; i < job->num_gathers; i++) { -struct host1x_job_gather *g = &job->gathers[i];size_t gather_size =0 ;struct scatterlist *sg;struct sg_table *sgt;
@@ -204,6 +204,7 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job)dma_addr_t *phys;unsigned int j; + g = &job->gathers[i]; g->bo =host1x_bo_get (g->bo);if (!g->bo) { err = -EINVAL ;
@@ -223,7 +224,7 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) sgt =host1x_bo_pin (host->dev, g->bo, phys);if (IS_ERR (sgt)) { err =PTR_ERR (sgt); - goto unpin; + goto put; }if (host->domain) {
@@ -236,7 +237,7 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) host->iova_end >> shift, true);if (!alloc) { err = -ENOMEM ; - goto unpin; + goto put; } err = iommu_map_sg(host->domain,
@@ -245,7 +246,7 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job)if (err ==0 ) {__free_iova (&host->iova, alloc); err = -EINVAL ; - goto unpin; + goto put; } job->unpins[job->num_unpins].size = gather_size;
@@ -255,7 +256,7 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) DMA_TO_DEVICE);if (!err) { err = -ENOMEM ; - goto unpin; + goto put; } job->unpins[job->num_unpins].dir =DMA_TO_DEVICE ;
@@ -273,6 +274,8 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job)return 0 ; +put: +host1x_bo_put (g->bo); unpin:host1x_job_unpin (job);return err;
Signature · 1 line
2.26.0
PATCH 3/4 gpu: host1x: debug: Fix multiple channels emitting messages simultaneously
In reply to Dmitry OsipenkoOnce channel's job is hung, it dumps the channel's state into KMSG before tearing down the offending job. If multiple channels hang at once, then they dump messages simultaneously, making the debug info unreadable, and thus, useless. This patch adds mutex which allows only one channel to emit debug messages at a time.
--- drivers/gpu/host1x/debug.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/gpu/host1x/debug.c +4 -0
@@ -16,6 +16,8 @@#include "debug.h" #include "channel.h" +static DEFINE_MUTEX (debug_lock); +unsigned int host1x_debug_trace_cmdbuf;static pid_t host1x_debug_force_timeout_pid;
@@ -52,12 +54,14 @@ static int show_channel(struct host1x_channel *ch, void *data, bool show_fifo)struct output *o = data;mutex_lock (&ch->cdma.lock); +mutex_lock (&debug_lock);if (show_fifo)host1x_hw_show_channel_fifo (m, ch, o);host1x_hw_show_channel_cdma (m, ch, o); +mutex_unlock (&debug_lock);mutex_unlock (&ch->cdma.lock);return 0 ;
Signature · 1 line
2.26.0
PATCH 4/4 gpu: host1x: debug: Dump push buffer state
In reply to Dmitry OsipenkoWhen job hangs and there is a memory error pointing at channel's push buffer, it is very handy to know the push buffer's state. This patch makes the push buffer's state to be dumped into KMSG in addition to the job's gathers.
--- drivers/gpu/host1x/hw/debug_hw.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/gpu/host1x/hw/debug_hw.c +6 -0
@@ -192,8 +192,14 @@ static void show_gather(struct output *o, phys_addr_t phys_addr,static void show_channel_gathers (struct output *o,struct host1x_cdma *cdma) { +struct push_buffer *pb = &cdma->push_buffer;struct host1x_job *job; +host1x_debug_output (o,"Push Buffer at %08x, %d words\n" , + pb->dma, pb->size /4 ); + +show_gather (o, pb->dma, pb->size /4 , cdma, pb->dma, pb->mapped); +list_for_each_entry (job, &cdma->sync_queue, list) {unsigned int i;
Signature · 1 line
2.26.0
kbuild test robot
build botRe: [PATCH v1 4/4] gpu: host1x: debug: Dump push buffer state
I love your patch! Perhaps something to improve:
Hi Dmitry,
I love your patch! Perhaps something to improve:
[auto build test WARNING on tegra-drm/drm/tegra/for-next]
[also build test WARNING on v5.7-rc7 next-20200526]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system. BTW, we also suggest to use '--base' option to specify the base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/Dmitry-Osipenko/Minor-improvements-for-Host1x-driver/20200525-152833 base: git://anongit.freedesktop.org/tegra/linux.git drm/tegra/for-next config: arm64-allyesconfig (attached as .config) compiler: aarch64-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=arm64
If you fix the issue, kindly add following tag as appropriate
All warnings (new ones prefixed by >>, old ones prefixed by <<):
In file included from drivers/gpu/host1x/hw/host1x01.c:17:drivers/gpu/host1x/hw/debug_hw.c: In function 'show_channel_gathers':
>> drivers/gpu/host1x/hw/debug_hw.c:198:44: warning: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'dma_addr_t' {aka 'long long unsigned int'} [-Wformat=]
198 | host1x_debug_output(o, "Push Buffer at %08x, %d wordsn",
| ~~~^
| |
| unsigned int
| %08llx
199 | pb->dma, pb->size / 4);
| ~~~~~~~
| |
| dma_addr_t {aka long long unsigned int}vim +198 drivers/gpu/host1x/hw/debug_hw.c
192
193 static void show_channel_gathers(struct output *o, struct host1x_cdma *cdma)
194 {
195 struct push_buffer *pb = &cdma->push_buffer;
196 struct host1x_job *job;
197
> 198 host1x_debug_output(o, "Push Buffer at %08x, %d words\n",
199 pb->dma, pb->size / 4);
200
201 show_gather(o, pb->dma, pb->size / 4, cdma, pb->dma, pb->mapped);
202
203 list_for_each_entry(job, &cdma->sync_queue, list) {
204 unsigned int i;
205
206 host1x_debug_output(o, "\n%p: JOB, syncpt_id=%d, syncpt_val=%d, first_get=%08x, timeout=%d num_slots=%d, num_handles=%d\n",
207 job, job->syncpt_id, job->syncpt_end,
208 job->first_get, job->timeout,
209 job->num_slots, job->num_unpins); 210
211 for (i = 0; i < job->num_gathers; i++) {
212 struct host1x_job_gather *g = &job->gathers[i];
213 u32 *mapped;
214
215 if (job->gather_copy_mapped)
216 mapped = (u32 *)job->gather_copy_mapped;
217 else
218 mapped = host1x_bo_mmap(g->bo);
219
220 if (!mapped) {
221 host1x_debug_output(o, "[could not mmap]\n");
222 continue;
223 }
224
225 host1x_debug_output(o, " GATHER at %pad+%#x, %d words\n",
226 &g->base, g->offset, g->words);
227
228 show_gather(o, g->base + g->offset, g->words, cdma,
229 g->base, mapped);
230
231 if (!job->gather_copy_mapped)
232 host1x_bo_munmap(g->bo, mapped);
233 }
234 }
235 }
236
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/[email protected]