1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright (c) 2010-2015, NVIDIA Corporation.
8 #include <linux/dma-mapping.h>
10 #include <linux/host1x.h>
11 #include <linux/kref.h>
12 #include <linux/module.h>
13 #include <linux/scatterlist.h>
14 #include <linux/slab.h>
15 #include <linux/vmalloc.h>
16 #include <trace/events/host1x.h>
23 #define HOST1X_WAIT_SYNCPT_OFFSET 0x8
25 struct host1x_job
*host1x_job_alloc(struct host1x_channel
*ch
,
26 u32 num_cmdbufs
, u32 num_relocs
)
28 struct host1x_job
*job
= NULL
;
29 unsigned int num_unpins
= num_cmdbufs
+ num_relocs
;
33 /* Check that we're not going to overflow */
34 total
= sizeof(struct host1x_job
) +
35 (u64
)num_relocs
* sizeof(struct host1x_reloc
) +
36 (u64
)num_unpins
* sizeof(struct host1x_job_unpin_data
) +
37 (u64
)num_cmdbufs
* sizeof(struct host1x_job_gather
) +
38 (u64
)num_unpins
* sizeof(dma_addr_t
) +
39 (u64
)num_unpins
* sizeof(u32
*);
40 if (total
> ULONG_MAX
)
43 mem
= job
= kzalloc(total
, GFP_KERNEL
);
50 /* Redistribute memory to the structs */
51 mem
+= sizeof(struct host1x_job
);
52 job
->relocs
= num_relocs
? mem
: NULL
;
53 mem
+= num_relocs
* sizeof(struct host1x_reloc
);
54 job
->unpins
= num_unpins
? mem
: NULL
;
55 mem
+= num_unpins
* sizeof(struct host1x_job_unpin_data
);
56 job
->gathers
= num_cmdbufs
? mem
: NULL
;
57 mem
+= num_cmdbufs
* sizeof(struct host1x_job_gather
);
58 job
->addr_phys
= num_unpins
? mem
: NULL
;
60 job
->reloc_addr_phys
= job
->addr_phys
;
61 job
->gather_addr_phys
= &job
->addr_phys
[num_relocs
];
65 EXPORT_SYMBOL(host1x_job_alloc
);
67 struct host1x_job
*host1x_job_get(struct host1x_job
*job
)
72 EXPORT_SYMBOL(host1x_job_get
);
74 static void job_free(struct kref
*ref
)
76 struct host1x_job
*job
= container_of(ref
, struct host1x_job
, ref
);
81 void host1x_job_put(struct host1x_job
*job
)
83 kref_put(&job
->ref
, job_free
);
85 EXPORT_SYMBOL(host1x_job_put
);
87 void host1x_job_add_gather(struct host1x_job
*job
, struct host1x_bo
*bo
,
88 unsigned int words
, unsigned int offset
)
90 struct host1x_job_gather
*gather
= &job
->gathers
[job
->num_gathers
];
92 gather
->words
= words
;
94 gather
->offset
= offset
;
98 EXPORT_SYMBOL(host1x_job_add_gather
);
100 static unsigned int pin_job(struct host1x
*host
, struct host1x_job
*job
)
107 for (i
= 0; i
< job
->num_relocs
; i
++) {
108 struct host1x_reloc
*reloc
= &job
->relocs
[i
];
109 struct sg_table
*sgt
;
110 dma_addr_t phys_addr
;
112 reloc
->target
.bo
= host1x_bo_get(reloc
->target
.bo
);
113 if (!reloc
->target
.bo
) {
118 phys_addr
= host1x_bo_pin(reloc
->target
.bo
, &sgt
);
120 job
->addr_phys
[job
->num_unpins
] = phys_addr
;
121 job
->unpins
[job
->num_unpins
].bo
= reloc
->target
.bo
;
122 job
->unpins
[job
->num_unpins
].sgt
= sgt
;
126 for (i
= 0; i
< job
->num_gathers
; i
++) {
127 struct host1x_job_gather
*g
= &job
->gathers
[i
];
128 size_t gather_size
= 0;
129 struct scatterlist
*sg
;
130 struct sg_table
*sgt
;
131 dma_addr_t phys_addr
;
136 g
->bo
= host1x_bo_get(g
->bo
);
142 phys_addr
= host1x_bo_pin(g
->bo
, &sgt
);
144 if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL
) && host
->domain
) {
145 for_each_sg(sgt
->sgl
, sg
, sgt
->nents
, j
)
146 gather_size
+= sg
->length
;
147 gather_size
= iova_align(&host
->iova
, gather_size
);
149 shift
= iova_shift(&host
->iova
);
150 alloc
= alloc_iova(&host
->iova
, gather_size
>> shift
,
151 host
->iova_end
>> shift
, true);
157 err
= iommu_map_sg(host
->domain
,
158 iova_dma_addr(&host
->iova
, alloc
),
159 sgt
->sgl
, sgt
->nents
, IOMMU_READ
);
161 __free_iova(&host
->iova
, alloc
);
166 job
->addr_phys
[job
->num_unpins
] =
167 iova_dma_addr(&host
->iova
, alloc
);
168 job
->unpins
[job
->num_unpins
].size
= gather_size
;
170 job
->addr_phys
[job
->num_unpins
] = phys_addr
;
173 job
->gather_addr_phys
[i
] = job
->addr_phys
[job
->num_unpins
];
175 job
->unpins
[job
->num_unpins
].bo
= g
->bo
;
176 job
->unpins
[job
->num_unpins
].sgt
= sgt
;
183 host1x_job_unpin(job
);
187 static int do_relocs(struct host1x_job
*job
, struct host1x_job_gather
*g
)
190 void *cmdbuf_page_addr
= NULL
;
191 struct host1x_bo
*cmdbuf
= g
->bo
;
194 /* pin & patch the relocs for one gather */
195 for (i
= 0; i
< job
->num_relocs
; i
++) {
196 struct host1x_reloc
*reloc
= &job
->relocs
[i
];
197 u32 reloc_addr
= (job
->reloc_addr_phys
[i
] +
198 reloc
->target
.offset
) >> reloc
->shift
;
201 /* skip all other gathers */
202 if (cmdbuf
!= reloc
->cmdbuf
.bo
)
205 if (IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL
)) {
206 target
= (u32
*)job
->gather_copy_mapped
+
207 reloc
->cmdbuf
.offset
/ sizeof(u32
) +
208 g
->offset
/ sizeof(u32
);
212 if (last_page
!= reloc
->cmdbuf
.offset
>> PAGE_SHIFT
) {
213 if (cmdbuf_page_addr
)
214 host1x_bo_kunmap(cmdbuf
, last_page
,
217 cmdbuf_page_addr
= host1x_bo_kmap(cmdbuf
,
218 reloc
->cmdbuf
.offset
>> PAGE_SHIFT
);
219 last_page
= reloc
->cmdbuf
.offset
>> PAGE_SHIFT
;
221 if (unlikely(!cmdbuf_page_addr
)) {
222 pr_err("Could not map cmdbuf for relocation\n");
227 target
= cmdbuf_page_addr
+ (reloc
->cmdbuf
.offset
& ~PAGE_MASK
);
229 *target
= reloc_addr
;
232 if (cmdbuf_page_addr
)
233 host1x_bo_kunmap(cmdbuf
, last_page
, cmdbuf_page_addr
);
238 static bool check_reloc(struct host1x_reloc
*reloc
, struct host1x_bo
*cmdbuf
,
241 offset
*= sizeof(u32
);
243 if (reloc
->cmdbuf
.bo
!= cmdbuf
|| reloc
->cmdbuf
.offset
!= offset
)
246 /* relocation shift value validation isn't implemented yet */
253 struct host1x_firewall
{
254 struct host1x_job
*job
;
257 unsigned int num_relocs
;
258 struct host1x_reloc
*reloc
;
260 struct host1x_bo
*cmdbuf
;
270 static int check_register(struct host1x_firewall
*fw
, unsigned long offset
)
272 if (!fw
->job
->is_addr_reg
)
275 if (fw
->job
->is_addr_reg(fw
->dev
, fw
->class, offset
)) {
279 if (!check_reloc(fw
->reloc
, fw
->cmdbuf
, fw
->offset
))
289 static int check_class(struct host1x_firewall
*fw
, u32
class)
291 if (!fw
->job
->is_valid_class
) {
292 if (fw
->class != class)
295 if (!fw
->job
->is_valid_class(fw
->class))
302 static int check_mask(struct host1x_firewall
*fw
)
313 ret
= check_register(fw
, reg
);
327 static int check_incr(struct host1x_firewall
*fw
)
329 u32 count
= fw
->count
;
337 ret
= check_register(fw
, reg
);
350 static int check_nonincr(struct host1x_firewall
*fw
)
352 u32 count
= fw
->count
;
359 ret
= check_register(fw
, fw
->reg
);
371 static int validate(struct host1x_firewall
*fw
, struct host1x_job_gather
*g
)
373 u32
*cmdbuf_base
= (u32
*)fw
->job
->gather_copy_mapped
+
374 (g
->offset
/ sizeof(u32
));
375 u32 job_class
= fw
->class;
378 fw
->words
= g
->words
;
382 while (fw
->words
&& !err
) {
383 u32 word
= cmdbuf_base
[fw
->offset
];
384 u32 opcode
= (word
& 0xf0000000) >> 28;
394 fw
->class = word
>> 6 & 0x3ff;
395 fw
->mask
= word
& 0x3f;
396 fw
->reg
= word
>> 16 & 0xfff;
397 err
= check_class(fw
, job_class
);
399 err
= check_mask(fw
);
404 fw
->reg
= word
>> 16 & 0xfff;
405 fw
->count
= word
& 0xffff;
406 err
= check_incr(fw
);
412 fw
->reg
= word
>> 16 & 0xfff;
413 fw
->count
= word
& 0xffff;
414 err
= check_nonincr(fw
);
420 fw
->mask
= word
& 0xffff;
421 fw
->reg
= word
>> 16 & 0xfff;
422 err
= check_mask(fw
);
439 static inline int copy_gathers(struct host1x_job
*job
, struct device
*dev
)
441 struct host1x_firewall fw
;
448 fw
.reloc
= job
->relocs
;
449 fw
.num_relocs
= job
->num_relocs
;
450 fw
.class = job
->class;
452 for (i
= 0; i
< job
->num_gathers
; i
++) {
453 struct host1x_job_gather
*g
= &job
->gathers
[i
];
455 size
+= g
->words
* sizeof(u32
);
459 * Try a non-blocking allocation from a higher priority pools first,
460 * as awaiting for the allocation here is a major performance hit.
462 job
->gather_copy_mapped
= dma_alloc_wc(dev
, size
, &job
->gather_copy
,
465 /* the higher priority allocation failed, try the generic-blocking */
466 if (!job
->gather_copy_mapped
)
467 job
->gather_copy_mapped
= dma_alloc_wc(dev
, size
,
470 if (!job
->gather_copy_mapped
)
473 job
->gather_copy_size
= size
;
475 for (i
= 0; i
< job
->num_gathers
; i
++) {
476 struct host1x_job_gather
*g
= &job
->gathers
[i
];
479 /* Copy the gather */
480 gather
= host1x_bo_mmap(g
->bo
);
481 memcpy(job
->gather_copy_mapped
+ offset
, gather
+ g
->offset
,
482 g
->words
* sizeof(u32
));
483 host1x_bo_munmap(g
->bo
, gather
);
485 /* Store the location in the buffer */
486 g
->base
= job
->gather_copy
;
489 /* Validate the job */
490 if (validate(&fw
, g
))
493 offset
+= g
->words
* sizeof(u32
);
496 /* No relocs should remain at this point */
503 int host1x_job_pin(struct host1x_job
*job
, struct device
*dev
)
507 struct host1x
*host
= dev_get_drvdata(dev
->parent
);
510 err
= pin_job(host
, job
);
514 if (IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL
)) {
515 err
= copy_gathers(job
, dev
);
521 for (i
= 0; i
< job
->num_gathers
; i
++) {
522 struct host1x_job_gather
*g
= &job
->gathers
[i
];
524 /* process each gather mem only once */
528 /* copy_gathers() sets gathers base if firewall is enabled */
529 if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL
))
530 g
->base
= job
->gather_addr_phys
[i
];
532 for (j
= i
+ 1; j
< job
->num_gathers
; j
++) {
533 if (job
->gathers
[j
].bo
== g
->bo
) {
534 job
->gathers
[j
].handled
= true;
535 job
->gathers
[j
].base
= g
->base
;
539 err
= do_relocs(job
, g
);
546 host1x_job_unpin(job
);
551 EXPORT_SYMBOL(host1x_job_pin
);
553 void host1x_job_unpin(struct host1x_job
*job
)
555 struct host1x
*host
= dev_get_drvdata(job
->channel
->dev
->parent
);
558 for (i
= 0; i
< job
->num_unpins
; i
++) {
559 struct host1x_job_unpin_data
*unpin
= &job
->unpins
[i
];
561 if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL
) &&
562 unpin
->size
&& host
->domain
) {
563 iommu_unmap(host
->domain
, job
->addr_phys
[i
],
565 free_iova(&host
->iova
,
566 iova_pfn(&host
->iova
, job
->addr_phys
[i
]));
569 host1x_bo_unpin(unpin
->bo
, unpin
->sgt
);
570 host1x_bo_put(unpin
->bo
);
575 if (job
->gather_copy_size
)
576 dma_free_wc(job
->channel
->dev
, job
->gather_copy_size
,
577 job
->gather_copy_mapped
, job
->gather_copy
);
579 EXPORT_SYMBOL(host1x_job_unpin
);
582 * Debug routine used to dump job entries
584 void host1x_job_dump(struct device
*dev
, struct host1x_job
*job
)
586 dev_dbg(dev
, " SYNCPT_ID %d\n", job
->syncpt_id
);
587 dev_dbg(dev
, " SYNCPT_VAL %d\n", job
->syncpt_end
);
588 dev_dbg(dev
, " FIRST_GET 0x%x\n", job
->first_get
);
589 dev_dbg(dev
, " TIMEOUT %d\n", job
->timeout
);
590 dev_dbg(dev
, " NUM_SLOTS %d\n", job
->num_slots
);
591 dev_dbg(dev
, " NUM_HANDLES %d\n", job
->num_unpins
);