Skip to content

Commit

Permalink
Merge pull request #324 from jwrdegoede/psys-dma-fix-for-6.12
Browse files Browse the repository at this point in the history
ipu6-psys: Adjust DMA code for ipu6-bus DMA changes in kernels >= 6.12
  • Loading branch information
hao-yao authored Feb 17, 2025
2 parents 3340c78 + ea1e978 commit b4ba63d
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 7 deletions.
63 changes: 61 additions & 2 deletions drivers/media/pci/intel/ipu6/psys/ipu-psys.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,12 @@ struct ipu_psys_pg *__get_pg_buf(struct ipu_psys *psys, size_t pg_size)
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 10, 0)
kpg->pg = dma_alloc_attrs(&psys->adev->dev, pg_size,
&kpg->pg_dma_addr, GFP_KERNEL, 0);
#else
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 12, 5)
kpg->pg = dma_alloc_attrs(dev, pg_size, &kpg->pg_dma_addr,
GFP_KERNEL, 0);
#else
kpg->pg = ipu6_dma_alloc(to_ipu6_bus_device(dev), pg_size,
&kpg->pg_dma_addr, GFP_KERNEL, 0);
#endif
if (!kpg->pg) {
kfree(kpg);
Expand Down Expand Up @@ -597,6 +600,7 @@ static void ipu_dma_buf_detach(struct dma_buf *dbuf,
attach->priv = NULL;
}

#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 12, 5)
static struct sg_table *ipu_dma_buf_map(struct dma_buf_attachment *attach,
enum dma_data_direction dir)
{
Expand Down Expand Up @@ -658,6 +662,50 @@ static void ipu_dma_buf_unmap(struct dma_buf_attachment *attach,
#endif
}

#else

static struct sg_table *ipu_dma_buf_map(struct dma_buf_attachment *attach,
enum dma_data_direction dir)
{
struct ipu_dma_buf_attach *ipu_attach = attach->priv;
struct ipu6_bus_device *adev = to_ipu6_bus_device(attach->dev);
struct pci_dev *pdev = adev->isp->pdev;
unsigned long attrs;
int ret;

attrs = DMA_ATTR_SKIP_CPU_SYNC;
ret = dma_map_sgtable(&pdev->dev, ipu_attach->sgt, dir, attrs);
if (ret) {
dev_dbg(attach->dev, "buf map failed\n");
return ERR_PTR(-EIO);
}

ret = ipu6_dma_map_sgtable(adev, ipu_attach->sgt, dir, attrs);
if (ret) {
dma_unmap_sgtable(&pdev->dev, ipu_attach->sgt, dir, attrs);
return ERR_PTR(-EIO);
}

/*
* Initial cache flush to avoid writing dirty pages for buffers which
* are later marked as IPU_BUFFER_FLAG_NO_FLUSH.
*/
ipu6_dma_sync_sgtable(adev, ipu_attach->sgt);

return ipu_attach->sgt;
}

static void ipu_dma_buf_unmap(struct dma_buf_attachment *attach,
struct sg_table *sgt, enum dma_data_direction dir)
{
struct ipu6_bus_device *adev = to_ipu6_bus_device(attach->dev);
struct pci_dev *pdev = adev->isp->pdev;

ipu6_dma_unmap_sgtable(adev, sgt, dir, DMA_ATTR_SKIP_CPU_SYNC);
dma_unmap_sgtable(&pdev->dev, sgt, dir, DMA_ATTR_SKIP_CPU_SYNC);
}
#endif

static int ipu_dma_buf_mmap(struct dma_buf *dbuf, struct vm_area_struct *vma)
{
return -ENOTTY;
Expand Down Expand Up @@ -2371,7 +2419,12 @@ static int ipu6_psys_probe(struct auxiliary_device *auxdev,
kpg = kzalloc(sizeof(*kpg), GFP_KERNEL);
if (!kpg)
goto out_free_pgs;

#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 12, 5)
kpg->pg = dma_alloc_attrs(dev, IPU_PSYS_PG_MAX_SIZE,
#else
kpg->pg = ipu6_dma_alloc(adev, IPU_PSYS_PG_MAX_SIZE,
#endif
&kpg->pg_dma_addr,
GFP_KERNEL, 0);
if (!kpg->pg) {
Expand Down Expand Up @@ -2426,7 +2479,11 @@ static int ipu6_psys_probe(struct auxiliary_device *auxdev,
ipu6_fw_com_release(psys->fwcom, 1);
out_free_pgs:
list_for_each_entry_safe(kpg, kpg0, &psys->pgs, list) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 12, 5)
dma_free_attrs(dev, kpg->size, kpg->pg, kpg->pg_dma_addr, 0);
#else
ipu6_dma_free(adev, kpg->size, kpg->pg, kpg->pg_dma_addr, 0);
#endif
kfree(kpg);
}

Expand Down Expand Up @@ -2484,8 +2541,10 @@ static void ipu6_psys_remove(struct auxiliary_device *auxdev)
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 10, 0)
dma_free_attrs(&adev->dev, kpg->size, kpg->pg,
kpg->pg_dma_addr, 0);
#else
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 12, 5)
dma_free_attrs(dev, kpg->size, kpg->pg, kpg->pg_dma_addr, 0);
#else
ipu6_dma_free(psys->adev, kpg->size, kpg->pg, kpg->pg_dma_addr, 0);
#endif
kfree(kpg);
}
Expand Down
3 changes: 3 additions & 0 deletions drivers/media/pci/intel/ipu6/psys/ipu-psys.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
#include "ipu6.h"
#include "ipu6-bus.h"
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 5)
#include "ipu6-dma.h"
#endif
#include "ipu-fw-psys.h"
#include "ipu-platform-psys.h"

Expand Down
5 changes: 4 additions & 1 deletion drivers/media/pci/intel/ipu6/psys/ipu6-ppg.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,12 @@ __get_buf_set(struct ipu_psys_fh *fh, size_t buf_set_size)
kbuf_set->kaddr = dma_alloc_attrs(&fh->psys->adev->dev,
buf_set_size, &kbuf_set->dma_addr,
GFP_KERNEL, 0);
#else
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 12, 5)
kbuf_set->kaddr = dma_alloc_attrs(dev, buf_set_size,
&kbuf_set->dma_addr, GFP_KERNEL, 0);
#else
kbuf_set->kaddr = ipu6_dma_alloc(to_ipu6_bus_device(dev), buf_set_size,
&kbuf_set->dma_addr, GFP_KERNEL, 0);
#endif
if (!kbuf_set->kaddr) {
kfree(kbuf_set);
Expand Down
21 changes: 17 additions & 4 deletions drivers/media/pci/intel/ipu6/psys/ipu6-psys.c
Original file line number Diff line number Diff line change
Expand Up @@ -450,10 +450,12 @@ static struct ipu_psys_kcmd *ipu_psys_copy_cmd(struct ipu_psys_command *cmd,
kcmd->kbufs[i]->sgt->sgl,
kcmd->kbufs[i]->sgt->orig_nents,
DMA_BIDIRECTIONAL);
#else
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 12, 5)
dma_sync_sg_for_device(dev, kcmd->kbufs[i]->sgt->sgl,
kcmd->kbufs[i]->sgt->orig_nents,
DMA_BIDIRECTIONAL);
#else
ipu6_dma_sync_sgtable(psys->adev, kcmd->kbufs[i]->sgt);
#endif
}

Expand Down Expand Up @@ -1102,11 +1104,16 @@ int ipu_psys_fh_init(struct ipu_psys_fh *fh)
&kbuf_set->dma_addr,
GFP_KERNEL,
0);
#else
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 12, 5)
kbuf_set->kaddr = dma_alloc_attrs(dev,
IPU_PSYS_BUF_SET_MAX_SIZE,
&kbuf_set->dma_addr,
GFP_KERNEL, 0);
#else
kbuf_set->kaddr = ipu6_dma_alloc(to_ipu6_bus_device(dev),
IPU_PSYS_BUF_SET_MAX_SIZE,
&kbuf_set->dma_addr,
GFP_KERNEL, 0);
#endif
if (!kbuf_set->kaddr) {
kfree(kbuf_set);
Expand All @@ -1124,8 +1131,11 @@ int ipu_psys_fh_init(struct ipu_psys_fh *fh)
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 10, 0)
dma_free_attrs(&psys->adev->dev,
kbuf_set->size, kbuf_set->kaddr,
#else
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 12, 5)
dma_free_attrs(dev, kbuf_set->size, kbuf_set->kaddr,
#else
ipu6_dma_free(to_ipu6_bus_device(dev),
kbuf_set->size, kbuf_set->kaddr,
#endif
kbuf_set->dma_addr, 0);
list_del(&kbuf_set->list);
Expand Down Expand Up @@ -1229,8 +1239,11 @@ int ipu_psys_fh_deinit(struct ipu_psys_fh *fh)
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 10, 0)
dma_free_attrs(&psys->adev->dev,
kbuf_set->size, kbuf_set->kaddr,
#else
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 12, 5)
dma_free_attrs(dev, kbuf_set->size, kbuf_set->kaddr,
#else
ipu6_dma_free(to_ipu6_bus_device(dev),
kbuf_set->size, kbuf_set->kaddr,
#endif
kbuf_set->dma_addr, 0);
list_del(&kbuf_set->list);
Expand Down
55 changes: 55 additions & 0 deletions patches/0001-v6.10-IPU6-headers-used-by-PSYS.patch
Original file line number Diff line number Diff line change
Expand Up @@ -1195,6 +1195,61 @@ index 000000000..92e3c3414
+ int pkg_dir_idx, void __iomem *base, u64 *pkg_dir,
+ dma_addr_t pkg_dir_dma_addr);
+#endif /* IPU6_H */
diff --git a/drivers/media/pci/intel/ipu6/ipu6-dma.h b/drivers/media/pci/intel/ipu6/ipu6-dma.h
new file mode 100644
index 000000000..b51244add
--- /dev/null
+++ b/drivers/media/pci/intel/ipu6/ipu6-dma.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (C) 2013--2024 Intel Corporation */
+
+#ifndef IPU6_DMA_H
+#define IPU6_DMA_H
+
+#include <linux/dma-map-ops.h>
+#include <linux/dma-mapping.h>
+#include <linux/iova.h>
+#include <linux/iova.h>
+#include <linux/scatterlist.h>
+#include <linux/types.h>
+
+#include "ipu6-bus.h"
+
+struct ipu6_mmu_info;
+
+struct ipu6_dma_mapping {
+ struct ipu6_mmu_info *mmu_info;
+ struct iova_domain iovad;
+};
+
+void ipu6_dma_sync_single(struct ipu6_bus_device *sys, dma_addr_t dma_handle,
+ size_t size);
+void ipu6_dma_sync_sg(struct ipu6_bus_device *sys, struct scatterlist *sglist,
+ int nents);
+void ipu6_dma_sync_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt);
+void *ipu6_dma_alloc(struct ipu6_bus_device *sys, size_t size,
+ dma_addr_t *dma_handle, gfp_t gfp,
+ unsigned long attrs);
+void ipu6_dma_free(struct ipu6_bus_device *sys, size_t size, void *vaddr,
+ dma_addr_t dma_handle, unsigned long attrs);
+int ipu6_dma_mmap(struct ipu6_bus_device *sys, struct vm_area_struct *vma,
+ void *addr, dma_addr_t iova, size_t size,
+ unsigned long attrs);
+int ipu6_dma_map_sg(struct ipu6_bus_device *sys, struct scatterlist *sglist,
+ int nents, enum dma_data_direction dir,
+ unsigned long attrs);
+void ipu6_dma_unmap_sg(struct ipu6_bus_device *sys, struct scatterlist *sglist,
+ int nents, enum dma_data_direction dir,
+ unsigned long attrs);
+int ipu6_dma_map_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt,
+ enum dma_data_direction dir, unsigned long attrs);
+void ipu6_dma_unmap_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt,
+ enum dma_data_direction dir, unsigned long attrs);
+int ipu6_dma_get_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt,
+ void *cpu_addr, dma_addr_t handle, size_t size,
+ unsigned long attrs);
+#endif /* IPU6_DMA_H */
--
2.43.0

0 comments on commit b4ba63d

Please sign in to comment.