Skip to content

Commit 36637ac

Browse files
hoshinolinamarcan
authored andcommitted
media: apple: isp: Remove ioread/iowrite and stop doing raw address translation
Translating IOVAs via the DART and then trying to access physical memory directly is slow and error-prone. We know what surfaces IOVAs are supposed to be part of, so we can use the surface vmap to access the contents. Where we get an IOVA from the firmware, assert that it is within the expected range before accessing it. Since we're using threaded IRQs now, this also lets us get rid of the deferred vmap. Signed-off-by: Asahi Lina <[email protected]>
1 parent e2df294 commit 36637ac

9 files changed

Lines changed: 129 additions & 89 deletions

File tree

drivers/media/platform/apple/isp/isp-cam.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ static int isp_ch_load_setfile(struct apple_isp *isp, u32 ch)
323323
return -EINVAL;
324324
}
325325

326-
isp_iowrite(isp, isp->data_surf->iova, (void *)fw->data, setfile->size);
326+
memcpy(isp->data_surf->virt, (void *)fw->data, setfile->size);
327327
release_firmware(fw);
328328

329329
return isp_cmd_ch_set_file_load(isp, ch, isp->data_surf->iova,

drivers/media/platform/apple/isp/isp-cmd.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ static int cisp_send(struct apple_isp *isp, void *args, u32 insize, u32 outsize)
2424
req->arg1 = insize;
2525
req->arg2 = outsize;
2626

27-
isp_iowrite(isp, isp->cmd_iova, args, insize);
27+
memcpy(isp->cmd_virt, args, insize);
2828
err = ipc_chan_send(isp, chan, CISP_TIMEOUT);
2929
if (err) {
3030
u64 opcode;
@@ -45,7 +45,8 @@ static int cisp_send_read(struct apple_isp *isp, void *args, u32 insize,
4545
int err = cisp_send(isp, args, insize, outsize);
4646
if (err)
4747
return err;
48-
isp_ioread(isp, isp->cmd_iova, args, outsize);
48+
49+
memcpy(args, isp->cmd_virt, outsize);
4950
return 0;
5051
}
5152

drivers/media/platform/apple/isp/isp-drv.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ struct isp_surf {
3232
struct drm_mm_node *mm;
3333
struct list_head head;
3434
u64 size;
35+
u64 type;
3536
u32 num_pages;
3637
struct page **pages;
3738
struct sg_table sgt;
@@ -60,6 +61,7 @@ struct isp_channel {
6061
u32 num;
6162
u64 size;
6263
dma_addr_t iova;
64+
void *virt;
6365
u32 doorbell;
6466
u32 cursor;
6567
spinlock_t lock;
@@ -210,6 +212,8 @@ struct apple_isp {
210212
struct isp_surf *ipc_surf;
211213
struct isp_surf *extra_surf;
212214
struct isp_surf *data_surf;
215+
struct isp_surf *log_surf;
216+
struct isp_surf *bt_surf;
213217
struct list_head gc;
214218
struct workqueue_struct *wq;
215219

@@ -225,6 +229,7 @@ struct apple_isp {
225229

226230
wait_queue_head_t wait;
227231
dma_addr_t cmd_iova;
232+
void *cmd_virt;
228233

229234
unsigned long state;
230235
spinlock_t buf_lock;

drivers/media/platform/apple/isp/isp-fw.c

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// SPDX-License-Identifier: GPL-2.0-only
22
/* Copyright 2023 Eileen Yoon <[email protected]> */
33

4+
#include "isp-fw.h"
5+
46
#include <linux/delay.h>
57
#include <linux/pm_runtime.h>
68

@@ -37,6 +39,35 @@ static inline void isp_gpio_write32(struct apple_isp *isp, u32 reg, u32 val)
3739
writel(val, isp->gpio + reg);
3840
}
3941

42+
void *apple_isp_translate(struct apple_isp *isp, struct isp_surf *surf,
43+
dma_addr_t iova, size_t size)
44+
{
45+
dma_addr_t end = iova + size;
46+
if (!surf) {
47+
dev_err(isp->dev,
48+
"Failed to translate IPC iova 0x%llx (0x%zx): No surface\n",
49+
(long long)iova, size);
50+
return NULL;
51+
}
52+
53+
if (end < iova || iova < surf->iova ||
54+
end > (surf->iova + surf->size)) {
55+
dev_err(isp->dev,
56+
"Failed to translate IPC iova 0x%llx (0x%zx): Out of bounds\n",
57+
(long long)iova, size);
58+
return NULL;
59+
}
60+
61+
if (!surf->virt) {
62+
dev_err(isp->dev,
63+
"Failed to translate IPC iova 0x%llx (0x%zx): No VMap\n",
64+
(long long)iova, size);
65+
return NULL;
66+
}
67+
68+
return surf->virt + (iova - surf->iova);
69+
}
70+
4071
struct isp_firmware_bootargs {
4172
u32 pad_0[2];
4273
u64 ipc_iova;
@@ -231,13 +262,17 @@ int apple_isp_alloc_firmware_surface(struct apple_isp *isp)
231262
isp_err(isp, "failed to alloc shared surface for ipc\n");
232263
return -ENOMEM;
233264
}
265+
dev_info(isp->dev, "IPC surface iova: 0x%llx\n",
266+
(long long)isp->ipc_surf->iova);
234267

235268
isp->data_surf = isp_alloc_surface_vmap(isp, ISP_FIRMWARE_DATA_SIZE);
236269
if (!isp->data_surf) {
237270
isp_err(isp, "failed to alloc shared surface for data files\n");
238271
isp_free_surface(isp, isp->ipc_surf);
239272
return -ENOMEM;
240273
}
274+
dev_info(isp->dev, "Data surface iova: 0x%llx\n",
275+
(long long)isp->data_surf->iova);
241276

242277
return 0;
243278
}
@@ -257,6 +292,7 @@ static int isp_firmware_boot_stage2(struct apple_isp *isp)
257292
{
258293
struct isp_firmware_bootargs args;
259294
dma_addr_t args_iova;
295+
void *args_virt;
260296
int err, retries;
261297

262298
u32 num_ipc_chans = isp_gpio_read32(isp, ISP_GPIO_0);
@@ -280,7 +316,9 @@ static int isp_firmware_boot_stage2(struct apple_isp *isp)
280316
}
281317

282318
args_iova = isp->ipc_surf->iova + args_offset + 0x40;
319+
args_virt = isp->ipc_surf->virt + args_offset + 0x40;
283320
isp->cmd_iova = args_iova + sizeof(args) + 0x40;
321+
isp->cmd_virt = args_virt + sizeof(args) + 0x40;
284322

285323
memset(&args, 0, sizeof(args));
286324
args.ipc_iova = isp->ipc_surf->iova;
@@ -294,7 +332,7 @@ static int isp_firmware_boot_stage2(struct apple_isp *isp)
294332
args.unk7 = 0x1; // 0?
295333
args.unk_iova1 = args_iova + sizeof(args) - 0xc;
296334
args.unk9 = 0x3;
297-
isp_iowrite(isp, args_iova, &args, sizeof(args));
335+
memcpy(args_virt, &args, sizeof(args));
298336

299337
isp_gpio_write32(isp, ISP_GPIO_0, args_iova);
300338
isp_gpio_write32(isp, ISP_GPIO_1, args_iova >> 32);
@@ -354,7 +392,15 @@ static void isp_free_channel_info(struct apple_isp *isp)
354392
static int isp_fill_channel_info(struct apple_isp *isp)
355393
{
356394
u64 table_iova = isp_gpio_read32(isp, ISP_GPIO_0) |
357-
((u64)isp_gpio_read32(isp, ISP_GPIO_1)) << 32;
395+
((u64)isp_gpio_read32(isp, ISP_GPIO_1)) << 32;
396+
void *table_virt = apple_isp_ipc_translate(
397+
isp, table_iova,
398+
sizeof(struct isp_chan_desc) * isp->num_ipc_chans);
399+
400+
if (!table_virt) {
401+
dev_err(isp->dev, "Failed to find channel table\n");
402+
return -EIO;
403+
}
358404

359405
isp->ipc_chans = kcalloc(isp->num_ipc_chans,
360406
sizeof(struct isp_channel *), GFP_KERNEL);
@@ -363,24 +409,31 @@ static int isp_fill_channel_info(struct apple_isp *isp)
363409

364410
for (int i = 0; i < isp->num_ipc_chans; i++) {
365411
struct isp_chan_desc desc;
366-
dma_addr_t desc_iova = table_iova + (i * sizeof(desc));
412+
void *desc_virt = table_virt + (i * sizeof(desc));
367413
struct isp_channel *chan =
368414
kzalloc(sizeof(struct isp_channel), GFP_KERNEL);
369415
if (!chan)
370416
goto out;
371417
isp->ipc_chans[i] = chan;
372418

373-
isp_ioread(isp, desc_iova, &desc, sizeof(desc));
419+
memcpy(&desc, desc_virt, sizeof(desc));
374420
chan->name = kstrdup(desc.name, GFP_KERNEL);
375421
chan->type = desc.type;
376422
chan->src = desc.src;
377423
chan->doorbell = 1 << chan->src;
378424
chan->num = desc.num;
379425
chan->size = desc.num * ISP_IPC_MESSAGE_SIZE;
380426
chan->iova = desc.iova;
427+
chan->virt =
428+
apple_isp_ipc_translate(isp, desc.iova, chan->size);
381429
chan->cursor = 0;
382430
spin_lock_init(&chan->lock);
383431

432+
if (!chan->virt) {
433+
dev_err(isp->dev, "Failed to find channel buffer\n");
434+
goto out;
435+
}
436+
384437
if ((chan->type != ISP_IPC_CHAN_TYPE_COMMAND) &&
385438
(chan->type != ISP_IPC_CHAN_TYPE_REPLY) &&
386439
(chan->type != ISP_IPC_CHAN_TYPE_REPORT)) {
@@ -438,11 +491,11 @@ static int isp_firmware_boot_stage3(struct apple_isp *isp)
438491
continue;
439492
for (int j = 0; j < chan->num; j++) {
440493
struct isp_message msg;
441-
dma_addr_t msg_iova = chan->iova + (j * sizeof(msg));
494+
void *msg_virt = chan->virt + (j * sizeof(msg));
442495

443496
memset(&msg, 0, sizeof(msg));
444497
msg.arg0 = ISP_IPC_FLAG_ACK;
445-
isp_iowrite(isp, msg_iova, &msg, sizeof(msg));
498+
memcpy(msg_virt, &msg, sizeof(msg));
446499
}
447500
}
448501
wmb();
@@ -546,6 +599,10 @@ static int isp_start_command_processor(struct apple_isp *isp)
546599
static void isp_collect_gc_surface(struct apple_isp *isp)
547600
{
548601
struct isp_surf *tmp, *surf;
602+
603+
isp->log_surf = NULL;
604+
isp->bt_surf = NULL;
605+
549606
list_for_each_entry_safe_reverse(surf, tmp, &isp->gc, head) {
550607
isp_dbg(isp, "freeing iova: 0x%llx size: 0x%llx virt: %pS\n",
551608
surf->iova, surf->size, (void *)surf->virt);

drivers/media/platform/apple/isp/isp-fw.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,13 @@ void apple_isp_free_firmware_surface(struct apple_isp *isp);
1212
int apple_isp_firmware_boot(struct apple_isp *isp);
1313
void apple_isp_firmware_shutdown(struct apple_isp *isp);
1414

15+
void *apple_isp_translate(struct apple_isp *isp, struct isp_surf *surf,
16+
dma_addr_t iova, size_t size);
17+
18+
static inline void *apple_isp_ipc_translate(struct apple_isp *isp,
19+
dma_addr_t iova, size_t size)
20+
{
21+
return apple_isp_translate(isp, isp->ipc_surf, iova, size);
22+
}
23+
1524
#endif /* __ISP_FW_H__ */

drivers/media/platform/apple/isp/isp-iommu.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -212,12 +212,6 @@ void isp_free_surface(struct apple_isp *isp, struct isp_surf *surf)
212212
}
213213
}
214214

215-
void *isp_iotranslate(struct apple_isp *isp, dma_addr_t iova)
216-
{
217-
phys_addr_t phys = iommu_iova_to_phys(isp->domain, iova);
218-
return phys_to_virt(phys);
219-
}
220-
221215
int apple_isp_iommu_map_sgt(struct apple_isp *isp, struct isp_surf *surf,
222216
struct sg_table *sgt, u64 size)
223217
{

drivers/media/platform/apple/isp/isp-iommu.h

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,6 @@ struct isp_surf *__isp_alloc_surface(struct apple_isp *isp, u64 size, bool gc);
1212
struct isp_surf *isp_alloc_surface_vmap(struct apple_isp *isp, u64 size);
1313
int isp_surf_vmap(struct apple_isp *isp, struct isp_surf *surf);
1414
void isp_free_surface(struct apple_isp *isp, struct isp_surf *surf);
15-
void *isp_iotranslate(struct apple_isp *isp, dma_addr_t iova);
16-
17-
static inline void isp_ioread(struct apple_isp *isp, dma_addr_t iova,
18-
void *data, u64 size)
19-
{
20-
void *virt = isp_iotranslate(isp, iova);
21-
memcpy(data, virt, size);
22-
}
23-
24-
static inline void isp_iowrite(struct apple_isp *isp, dma_addr_t iova,
25-
void *data, u64 size)
26-
{
27-
void *virt = isp_iotranslate(isp, iova);
28-
memcpy(virt, data, size);
29-
}
3015

3116
int apple_isp_iommu_map_sgt(struct apple_isp *isp, struct isp_surf *surf,
3217
struct sg_table *sgt, u64 size);

0 commit comments

Comments
 (0)