From fe7b87d908da33326fbf6fe2b3830426432ec66c Mon Sep 17 00:00:00 2001 From: Yi Sun Date: Wed, 7 Jan 2026 16:02:23 -0800 Subject: [PATCH] dmaengine: idxd: Add Max SGL Size Support for DSA3.0 Certain DSA 3.0 opcodes, such as Gather copy and Gather reduce, require max SGL configured for workqueues prior to supporting these opcodes. Configure the maximum scatter-gather list (SGL) size for workqueues during setup on the supported HW. Application can then properly handle the SGL size without explicitly setting it. Signed-off-by: Yi Sun Co-developed-by: Anil S Keshavamurthy Signed-off-by: Anil S Keshavamurthy Reviewed-by: Dave Jiang Tested-by: Yi Lai Acked-by: Vinicius Costa Gomes Link: https://patch.msgid.link/20260107-idxd-yi-sun-dsa3-sgl-size-v2-2-dbef8f559e48@intel.com Signed-off-by: Vinod Koul --- drivers/dma/idxd/device.c | 5 +++++ drivers/dma/idxd/idxd.h | 16 ++++++++++++++++ drivers/dma/idxd/init.c | 5 +++++ drivers/dma/idxd/registers.h | 3 ++- 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c index c2cdf41b6e576..c26128529ff49 100644 --- a/drivers/dma/idxd/device.c +++ b/drivers/dma/idxd/device.c @@ -390,6 +390,7 @@ static void idxd_wq_disable_cleanup(struct idxd_wq *wq) memset(wq->name, 0, WQ_NAME_SIZE); wq->max_xfer_bytes = WQ_DEFAULT_MAX_XFER; idxd_wq_set_max_batch_size(idxd->data->type, wq, WQ_DEFAULT_MAX_BATCH); + idxd_wq_set_init_max_sgl_size(idxd, wq); if (wq->opcap_bmap) bitmap_copy(wq->opcap_bmap, idxd->opcap_bmap, IDXD_MAX_OPCAP_BITS); } @@ -989,6 +990,8 @@ static int idxd_wq_config_write(struct idxd_wq *wq) /* bytes 12-15 */ wq->wqcfg->max_xfer_shift = ilog2(wq->max_xfer_bytes); idxd_wqcfg_set_max_batch_shift(idxd->data->type, wq->wqcfg, ilog2(wq->max_batch_size)); + if (idxd_sgl_supported(idxd)) + wq->wqcfg->max_sgl_shift = ilog2(wq->max_sgl_size); /* bytes 32-63 */ if (idxd->hw.wq_cap.op_config && wq->opcap_bmap) { @@ -1167,6 +1170,8 @@ static int idxd_wq_load_config(struct idxd_wq *wq) wq->max_xfer_bytes = 1ULL << wq->wqcfg->max_xfer_shift; idxd_wq_set_max_batch_size(idxd->data->type, wq, 1U << wq->wqcfg->max_batch_shift); + if (idxd_sgl_supported(idxd)) + wq->max_sgl_size = 1U << wq->wqcfg->max_sgl_shift; for (i = 0; i < WQCFG_STRIDES(idxd); i++) { wqcfg_offset = WQCFG_OFFSET(idxd, wq->id, i); diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h index cc0a3fe1c9573..ea8c4daed38d4 100644 --- a/drivers/dma/idxd/idxd.h +++ b/drivers/dma/idxd/idxd.h @@ -227,6 +227,7 @@ struct idxd_wq { char name[WQ_NAME_SIZE + 1]; u64 max_xfer_bytes; u32 max_batch_size; + u32 max_sgl_size; /* Lock to protect upasid_xa access. */ struct mutex uc_lock; @@ -348,6 +349,7 @@ struct idxd_device { u64 max_xfer_bytes; u32 max_batch_size; + u32 max_sgl_size; int max_groups; int max_engines; int max_rdbufs; @@ -692,6 +694,20 @@ static inline void idxd_wq_set_max_batch_size(int idxd_type, struct idxd_wq *wq, wq->max_batch_size = max_batch_size; } +static bool idxd_sgl_supported(struct idxd_device *idxd) +{ + return idxd->data->type == IDXD_TYPE_DSA && + idxd->hw.version >= DEVICE_VERSION_3 && + idxd->hw.dsacap0.sgl_formats; +} + +static inline void idxd_wq_set_init_max_sgl_size(struct idxd_device *idxd, + struct idxd_wq *wq) +{ + if (idxd_sgl_supported(idxd)) + wq->max_sgl_size = 1U << idxd->hw.dsacap0.max_sgl_shift; +} + static inline void idxd_wqcfg_set_max_batch_shift(int idxd_type, union wqcfg *wqcfg, u32 max_batch_shift) { diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c index 2bdd1b34d50af..fb80803d5b573 100644 --- a/drivers/dma/idxd/init.c +++ b/drivers/dma/idxd/init.c @@ -222,6 +222,7 @@ static int idxd_setup_wqs(struct idxd_device *idxd) init_completion(&wq->wq_resurrect); wq->max_xfer_bytes = WQ_DEFAULT_MAX_XFER; idxd_wq_set_max_batch_size(idxd->data->type, wq, WQ_DEFAULT_MAX_BATCH); + idxd_wq_set_init_max_sgl_size(idxd, wq); wq->enqcmds_retries = IDXD_ENQCMDS_RETRIES; wq->wqcfg = kzalloc_node(idxd->wqcfg_size, GFP_KERNEL, dev_to_node(dev)); if (!wq->wqcfg) { @@ -590,6 +591,10 @@ static void idxd_read_caps(struct idxd_device *idxd) idxd->hw.dsacap1.bits = ioread64(idxd->reg_base + IDXD_DSACAP1_OFFSET); idxd->hw.dsacap2.bits = ioread64(idxd->reg_base + IDXD_DSACAP2_OFFSET); } + if (idxd_sgl_supported(idxd)) { + idxd->max_sgl_size = 1U << idxd->hw.dsacap0.max_sgl_shift; + dev_dbg(dev, "max sgl size: %u\n", idxd->max_sgl_size); + } /* read iaa cap */ if (idxd->data->type == IDXD_TYPE_IAX && idxd->hw.version >= DEVICE_VERSION_2) diff --git a/drivers/dma/idxd/registers.h b/drivers/dma/idxd/registers.h index 85e83a61a50b1..f95411363ea9a 100644 --- a/drivers/dma/idxd/registers.h +++ b/drivers/dma/idxd/registers.h @@ -390,7 +390,8 @@ union wqcfg { /* bytes 12-15 */ u32 max_xfer_shift:5; u32 max_batch_shift:4; - u32 rsvd4:23; + u32 max_sgl_shift:4; + u32 rsvd4:19; /* bytes 16-19 */ u16 occupancy_inth; -- 2.47.3