Add Agilex5 support in SVC driver and FPGA configuration and partial reconfiguration support for Agilex5
Subsystems (2)
v3 cover Add Agilex5 support in SVC driver and FPGA configuration and partial reconfiguration support for Agilex5
This series adds support for Agilex5 in the SVC driver and enables FPGA configuration and partial reconfiguration on Altera Agilex5 SoC.
On Agilex5 the DDR base address starts at 0x8000_0000, which is outside the addressable range of the SDM. The SMMU is used to remap DDR-allocated buffers to an IOVA within the SDM-accessible 0-512MB window. Agilex5 REV B introduced a hardware SDM address remapper, but it must be bypassed so no additional offset is applied to the IOVA, keeping the implementation consistent across all Agilex5 revisions.
Patch 1 adds the fpga-mgr child node and fpga-region to the Agilex5 DTSI. The SMMU is already enabled upstream.
Patch 2 reports unmatched frees in stratix10_svc_free_memory() with dev_warn() and cleans up related coding style in svc_pa_to_va(). The list-head corruption from list_del(&svc_data_mem) was already fixed by commit 9119ceb76e98 ("firmware: stratix10-svc: fix memory leaks and list corruption bugs").
Patch 3 adds all data-structure fields, macros, includes, helper function, and allocation/free paths required for the DMA coherent mode. This covers both the foundational types (dma_addr, use_dma_mem, dma_addr_offset, SVC_SDM_DMA_ADDR_BITS/OFFSET) and the functional DMA allocation/free code, keeping the structural and functional changes together so each intermediate commit is bisect-safe.
Patch 4 adds INTEL_SIP_SMC_SDM_REMAPPER_CONFIG and integrates the Agilex5 path into probe: enforces SMMU presence for intel,agilex5-svc, issues the remapper-bypass SMC, selects the DMA path via stratix10_svc_pdata.use_dma_mem, initialises the controller fields, registers a devm cleanup action for leaked buffers, and guards the error path against a NULL genpool.
---
changelog:
v2 -> v3:
- Squash former patch 2 (SMC remapper defines) into the probe enablement patch so the defines land with their first usage.
- Rebase on socfpga_firmware_for_v7.4.
- Drop SMMU status="disabled" removal from the DTS patch (already upstream in 10cf797f3f8a).
- Drop the list_del(&svc_data_mem) fix already present in 9119ceb76e98; keep the unmatched-free warning and style cleanup.
- Adapt of_device_id.data usage to extend stratix10_svc_pdata (shared with needs_psci_cpu_off) instead of casting BIT flags into .data.
- Keep kzalloc_obj()/kfree() lifetime for pmem on both gen_pool and DMA paths after 9119ceb76e98.
v1 -> v2:
- split original patch into smaller patches for easier review and backporting.
- Fixed the Fixes: tag in patch 3 referencing 5a0793ac66ac
- Replaced of_device_is_compatible() with of_device_id.data + of_device_get_match_data()
- Various commit message improvements
---
Adrian Ng Ho Yin (4):
arm64: dts: socfpga: agilex5: add FPGA manager and region nodes
firmware: stratix10-svc: warn on unmatched free in
stratix10_svc_free_memory
firmware: stratix10-svc: add DMA coherent memory allocation for
SMMU-enabled platforms
firmware: stratix10-svc: enable Agilex5 SMMU support in probe
.../arm64/boot/dts/intel/socfpga_agilex5.dtsi | 11 + drivers/firmware/stratix10-svc.c | 250 +++++++++++++++++--- include/linux/firmware/intel/stratix10-smc.h | 23 ++ 3 files changed, 239 insertions(+), 45 deletions(-)
Signature · 1 line
2.49.GIT
PATCH v3 1/4 arm64: dts: socfpga: agilex5: add FPGA manager and region nodes
Add the fpga-mgr child node under the svc firmware node and a fpga-region node to enable FPGA configuration and partial reconfiguration on Agilex5.
The SMMU is already enabled upstream; it remains a hard requirement for the svc driver to allocate DMA buffers within the SDM-accessible address range.
--- arch/arm64/boot/dts/intel/socfpga_agilex5.dtsi | 11 +++++++++++ 1 file changed, 11 insertions(+)
arch/arm64/boot/dts/intel/socfpga_agilex5.dtsi +11 -0
@@ -85,9 +85,20 @@ svc { method = "smc"; memory-region = <&service_reserved>; iommus = <&smmu 10>; + + fpga_mgr: fpga-mgr { + compatible = "intel,agilex-soc-fpga-mgr"; + }; }; }; + fpga-region { + compatible = "fpga-region"; + #address-cells = <0x2>; + #size-cells = <0x2>; + fpga-mgr = <&fpga_mgr>; + }; + psci { compatible = "arm,psci-0.2"; method = "smc";
Signature · 1 line
2.49.GIT
PATCH v3 2/4 firmware: stratix10-svc: warn on unmatched free in stratix10_svc_free_memory
In reply to Adrian Ng Ho YinAfter commit 9119ceb76e98 ("firmware: stratix10-svc: fix memory leaks and list corruption bugs") removed the erroneous list_del(&svc_data_mem) that corrupted the list head on failed lookups, an unmatched free still silently returned. Report the spurious address with dev_warn().
While here, refactor the loop to use an inverted condition with continue to reduce nesting. Add braces in svc_pa_to_va() for consistency, and fix a stale "physical address" comment to "address" since paddr is not strictly a physical address.
--- drivers/firmware/stratix10-svc.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-)
drivers/firmware/stratix10-svc.c +16 -11
@@ -338,11 +338,12 @@ static void *svc_pa_to_va(unsigned long addr)pr_debug ("claim back P-addr=0x%016x\n" , (unsigned int )addr);guard (mutex)(&svc_mem_lock); -list_for_each_entry (pmem, &svc_data_mem, node) +list_for_each_entry (pmem, &svc_data_mem, node) {if (pmem->paddr == addr)return pmem->vaddr; + } -/* physical address is not found */ +/* address is not found */ return NULL ; }
@@ -1997,19 +1998,23 @@ EXPORT_SYMBOL_GPL(stratix10_svc_allocate_memory);*/ void stratix10_svc_free_memory (struct stratix10_svc_chan *chan,void *kaddr) { +struct stratix10_svc_controller *ctrl = chan->ctrl;struct stratix10_svc_data_mem *pmem;guard (mutex)(&svc_mem_lock); -list_for_each_entry (pmem, &svc_data_mem, node) -if (pmem->vaddr == kaddr) { -gen_pool_free (chan->ctrl->genpool, - (unsigned long )kaddr, pmem->size); - pmem->vaddr =NULL ; -list_del (&pmem->node); -kfree (pmem); -return ; - } +list_for_each_entry (pmem, &svc_data_mem, node) { +if (pmem->vaddr != kaddr) +continue ; + +gen_pool_free (ctrl->genpool, (unsigned long )kaddr, pmem->size); + pmem->vaddr =NULL ; +list_del (&pmem->node); +kfree (pmem); +return ; + } + +dev_warn (ctrl->dev,"free of unknown buffer %p\n" , kaddr); }EXPORT_SYMBOL_GPL (stratix10_svc_free_memory);
Signature · 1 line
2.49.GIT
PATCH v3 3/4 firmware: stratix10-svc: add DMA coherent memory allocation for SMMU-enabled platforms
In reply to Adrian Ng Ho YinOn Agilex5, DDR starts at 0x8000_0000 which is outside the SDM's addressable range. When SMMU is active, the driver must allocate DMA-coherent buffers and pass IOVAs (not physical addresses) to ATF.
Add SVC_SDM_DMA_ADDR_BITS (29) and SVC_SDM_DMA_ADDR_OFFSET (0x8000_0000) to constrain IOVAs to the 0-512 MB window the SDM can reach and to satisfy ATF's address range check respectively.
Extend struct stratix10_svc_data_mem with dma_addr to hold the raw IOVA for teardown, and struct stratix10_svc_controller with use_dma_mem and dma_addr_offset to select the DMA path at runtime.
Add svc_setup_dma_memory() to set the 29-bit DMA mask. Update stratix10_svc_allocate_memory() and stratix10_svc_free_memory() with a dma_alloc_coherent()/dma_free_coherent() branch, and adjust svc_thread_cmd_data_claim() to reapply dma_addr_offset when resolving ATF completion addresses back to virtual addresses.
Both new controller fields default to zero so existing gen_pool platforms are unaffected.
--- drivers/firmware/stratix10-svc.c | 146 +++++++++++++++++++++++++------ 1 file changed, 121 insertions(+), 25 deletions(-)
drivers/firmware/stratix10-svc.c +121 -25
@@ -7,10 +7,12 @@#include <linux/atomic.h> #include <linux/completion.h> #include <linux/delay.h> +#include <linux/dma-mapping.h> #include <linux/genalloc.h> #include <linux/hashtable.h> #include <linux/idr.h> #include <linux/io.h> +#include <linux/iommu.h> #include <linux/kfifo.h> #include <linux/kthread.h> #include <linux/module.h>
@@ -48,6 +50,23 @@#define FPGA_CONFIG_STATUS_TIMEOUT_SEC 30#define BYTE_TO_WORD_SIZE 4 +/* +* SVC_SDM_DMA_ADDR_BITS - constrains the IOVA allocated by +* dma_alloc_coherent() to 29 bits (0x0000_0000 - 0x1FFF_FFFF) +* when SMMU is active on Agilex5. The SDM accesses these buffers +* via the SMMU using IOVAs, so the 29-bit limit keeps IOVAs within +* the SDM's addressable window. +* +* SVC_SDM_DMA_ADDR_OFFSET - ATF on Agilex5 distinguishes +* SMMU-mapped buffers from direct physical addresses by the +* presence of this offset. The driver adds it to the IOVA before +* passing the address to ATF via SMC; ATF strips it, translates +* the remaining IOVA through the SMMU, and the SDM accesses the +* underlying physical memory. +*/ +#define SVC_SDM_DMA_ADDR_BITS 29 +#define SVC_SDM_DMA_ADDR_OFFSET 0x80000000UL +/* stratix10 service layer clients */ #define STRATIX10_RSU "stratix10-rsu"#define SOCFPGA_HWMON "socfpga-hwmon"
@@ -149,18 +168,25 @@ struct stratix10_svc_sh_memory {/** * struct stratix10_svc_data_mem - service memory structure * @vaddr: virtual address -* @paddr: physical address +* @paddr: address passed to ATF via SMC and echoed back in completion +* notifications; used as the lookup key in svc_pa_to_va(). +* On the SMMU path this is (IOVA + %SVC_SDM_DMA_ADDR_OFFSET); +* on the gen_pool path this equals the raw physical address. * @size: size of memory +* @dma_addr: IOVA returned by dma_alloc_coherent(); used to free the +* mapping via dma_free_coherent() on the SMMU path. * @node: link list head node * * This struct is used in a list that keeps track of buffers which have * been allocated or freed from the memory pool. Service layer driver also -* uses this struct to transfer physical address to virtual address. +* uses this struct to map the address returned by ATF back to a virtual +* address. */ struct stratix10_svc_data_mem {void *vaddr;phys_addr_t paddr;size_t size; +dma_addr_t dma_addr;struct list_head node; };
@@ -296,6 +322,15 @@ struct stratix10_svc_chan {* @sdm_lock: only allows a single command single response to SDM * @actrl: async control structure * @psci_reboot_nb: reboot notifier for PSCI secondary CPU offlining +* @use_dma_mem: when true, buffers are allocated via dma_alloc_coherent() +* instead of the ATF reserved-memory gen_pool. +* @dma_addr_offset: value added to the DMA address (IOVA) before passing it +* to ATF via SMC. ATF uses this offset to distinguish +* SMMU-mapped buffers from direct physical addresses; it +* strips the offset, translates the remaining IOVA through +* the SMMU, and the SDM accesses the underlying memory. +* Set to %SVC_SDM_DMA_ADDR_OFFSET on Agilex5 when SMMU is +* active; zero otherwise. * @chans: array of service channels * * This struct is used to create communication channels for service clients, to
@@ -313,6 +348,8 @@ struct stratix10_svc_controller {struct mutex sdm_lock;struct stratix10_async_ctrl actrl;struct notifier_block psci_reboot_nb; +bool use_dma_mem; +unsigned long dma_addr_offset; struct stratix10_svc_chan chans[] __counted_by(num_chans); };
@@ -377,11 +414,17 @@ static void svc_thread_cmd_data_claim(struct stratix10_svc_controller *ctrl,break ; } cb_data->status =BIT (SVC_STATUS_BUFFER_DONE ); - cb_data->kaddr1 =svc_pa_to_va (res.a1); +/* +* The firmware COMPLETED_WRITE response returns the +* raw IOVA (without dma_addr_offset). Add it back to +* match the key stored in pmem->paddr at allocation +* time. dma_addr_offset is zero on non-SMMU paths. +*/ + cb_data->kaddr1 =svc_pa_to_va (res.a1 + ctrl->dma_addr_offset); cb_data->kaddr2 = (res.a2) ? -svc_pa_to_va (res.a2) :NULL ; +svc_pa_to_va (res.a2 + ctrl->dma_addr_offset) :NULL ; cb_data->kaddr3 = (res.a3) ? -svc_pa_to_va (res.a3) :NULL ; +svc_pa_to_va (res.a3 + ctrl->dma_addr_offset) :NULL ; p_data->chan->scl->receive_cb (p_data->chan->scl, cb_data); }else {
@@ -1052,6 +1095,38 @@ svc_create_memory_pool(struct platform_device *pdev,return genpool; } +/** +* svc_setup_dma_memory() - configure the device for dynamic DMA allocation +* @pdev: pointer to service layer device +* +* Called instead of svc_get_sh_memory() + svc_create_memory_pool() when +* the device is behind an SMMU. Sets a 29-bit coherent DMA mask so that +* every subsequent dma_alloc_coherent() call yields an IOVA within the +* first 512MB (0x0000_0000 - 0x1FFF_FFFF). The driver then adds +* %SVC_SDM_DMA_ADDR_OFFSET to the IOVA before passing it to ATF; ATF +* strips the offset and uses the SMMU to translate the IOVA to the +* underlying physical memory for SDM access. +* +* Return: 0 on success, or a negative error code on failure. +*/ +static int svc_setup_dma_memory (struct platform_device *pdev) +{ +struct device *dev = &pdev->dev; +int ret; + + ret =dma_set_mask_and_coherent (dev,DMA_BIT_MASK (SVC_SDM_DMA_ADDR_BITS )); +if (ret) { +dev_err (dev, +"failed to set %u-bit DMA mask: %d\n" , +SVC_SDM_DMA_ADDR_BITS , ret); +return ret; + } + +dev_info (dev, +"SMMU enabled: using dynamic DMA allocation (IOVA range 0-512MB)\n" ); +return 0 ; +} +/** * svc_smccc_smc() - secure monitor call between normal and secure world * @a0: argument passed in registers 0
@@ -1958,34 +2033,50 @@ EXPORT_SYMBOL_GPL(stratix10_svc_done);void *stratix10_svc_allocate_memory (struct stratix10_svc_chan *chan,size_t size) { +struct stratix10_svc_controller *ctrl = chan->ctrl;struct stratix10_svc_data_mem *pmem; -unsigned long va; -phys_addr_t pa; -struct gen_pool *genpool = chan->ctrl->genpool; -size_t s =roundup (size,1 << genpool->min_alloc_order); +struct gen_pool *genpool; +dma_addr_t dma_addr; +size_t s; +void *va; pmem =kzalloc_obj (*pmem);if (!pmem)return ERR_PTR (-ENOMEM ); -guard (mutex)(&svc_mem_lock); - va =gen_pool_alloc (genpool, s); -if (!va) { -kfree (pmem); -return ERR_PTR (-ENOMEM ); - } +if (ctrl->use_dma_mem) { + va =dma_alloc_coherent (ctrl->dev, size, &dma_addr,GFP_KERNEL ); +if (!va) { +kfree (pmem); +return ERR_PTR (-ENOMEM ); + } -memset ((void *)va,0 , s); - pa =gen_pool_virt_to_phys (genpool, va); + pmem->vaddr = va; + pmem->paddr = dma_addr + ctrl->dma_addr_offset; + pmem->dma_addr = dma_addr; + pmem->size = size; + }else { + genpool = ctrl->genpool; + s =roundup (size,1 << genpool->min_alloc_order); - pmem->vaddr = (void *)va; - pmem->paddr = pa; - pmem->size = s; + va = (void *)gen_pool_alloc (genpool, s); +if (!va) { +kfree (pmem); +return ERR_PTR (-ENOMEM ); + } + +memset (va,0 , s); + pmem->vaddr = va; + pmem->paddr =gen_pool_virt_to_phys (genpool, (unsigned long )va); + pmem->size = s; + } + +guard (mutex)(&svc_mem_lock);list_add_tail (&pmem->node, &svc_data_mem); -pr_debug ("%s: %s: va=%p, pa=0x%016x\n" , __func__, - chan->name, pmem->vaddr, (unsigned int )pmem->paddr); +pr_debug ("%s: %s: va=%p, addr=0x%016llx\n" , __func__, + chan->name, pmem->vaddr, (unsigned long long )pmem->paddr); -return (void *)va; +return va; }EXPORT_SYMBOL_GPL (stratix10_svc_allocate_memory);
@@ -2007,8 +2098,13 @@ void stratix10_svc_free_memory(struct stratix10_svc_chan *chan, void *kaddr)if (pmem->vaddr != kaddr)continue ; -gen_pool_free (ctrl->genpool, (unsigned long )kaddr, pmem->size); - pmem->vaddr =NULL ; +if (ctrl->use_dma_mem) { +dma_free_coherent (ctrl->dev, pmem->size, + pmem->vaddr, pmem->dma_addr); + }else { +gen_pool_free (ctrl->genpool, + (unsigned long )kaddr, pmem->size); + }list_del (&pmem->node);kfree (pmem);return ;
Signature · 1 line
2.49.GIT
PATCH v3 4/4 firmware: stratix10-svc: enable Agilex5 SMMU support in probe
In reply to Adrian Ng Ho YinWire up the Agilex5-specific path in stratix10_svc_drv_probe().
Add INTEL_SIP_SMC_SDM_REMAPPER_CONFIG to stratix10-smc.h and issue INTEL_SIP_SMC_SDM_REMAPPER_BYPASS from probe. On Agilex5 REV B the hardware SDM address remapper must be bypassed when the SMMU is active so no extra offset is applied on top of the IOVA translation.
Extend stratix10_svc_pdata with use_dma_mem and add intel,agilex5-svc to the of_device_id match table with that flag set. Probe reads the flag via of_device_get_match_data() so it shares the same pdata mechanism used for needs_psci_cpu_off.
On Agilex5, DDR starts at 0x8000_0000 which is outside the SDM's addressable range, making the SMMU mandatory. Fail probe with -ENODEV if no IOMMU domain is attached to the device.
Register svc_data_mem_cleanup() as a devm action on the DMA path to free any buffers leaked by service clients on driver unbind. Guard err_destroy_pool against NULL genpool for the early-exit DMA path.
--- drivers/firmware/stratix10-svc.c | 83 +++++++++++++++++--- include/linux/firmware/intel/stratix10-smc.h | 23 ++++++ 2 files changed, 94 insertions(+), 12 deletions(-)
drivers/firmware/stratix10-svc.c +71 -12
@@ -122,12 +122,17 @@struct stratix10_svc_pdata {bool needs_psci_cpu_off; +bool use_dma_mem; };static const struct stratix10_svc_pdata psci_cpu_off_pdata = { .needs_psci_cpu_off = true, }; +static const struct stratix10_svc_pdata agilex5_pdata = { + .use_dma_mem = true, +}; + typedef void (svc_invoke_fn)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long,
@@ -2169,6 +2174,7 @@ static void psci_cpu_off_teardown(struct stratix10_svc_controller *ctrl)static const struct of_device_id stratix10_svc_drv_match[] = { { .compatible ="intel,stratix10-svc" , .data = &psci_cpu_off_pdata }, { .compatible ="intel,agilex-svc" , .data = &psci_cpu_off_pdata }, + { .compatible ="intel,agilex5-svc" , .data = &agilex5_pdata }, {}, };
@@ -2179,14 +2185,38 @@ static const char * const chan_names[SVC_NUM_CHANNEL] = {SVC_CLIENT_HWMON }; +static void svc_data_mem_cleanup (void *data) +{ +struct stratix10_svc_controller *ctrl = data; +struct stratix10_svc_data_mem *pmem, *tmp; + +guard (mutex)(&svc_mem_lock); + +list_for_each_entry_safe (pmem, tmp, &svc_data_mem, node) { +dev_warn (ctrl->dev,"leaked svc buffer %p, freeing on unbind\n" , + pmem->vaddr); +if (ctrl->use_dma_mem) { +dma_free_coherent (ctrl->dev, pmem->size, + pmem->vaddr, pmem->dma_addr); + }else { +gen_pool_free (ctrl->genpool, + (unsigned long )pmem->vaddr, pmem->size); + } +list_del (&pmem->node); +kfree (pmem); + } +} +static int stratix10_svc_drv_probe (struct platform_device *pdev) {struct device *dev = &pdev->dev;struct stratix10_svc_controller *controller; -struct gen_pool *genpool; +struct gen_pool *genpool =NULL ;struct stratix10_svc_sh_memory *sh_memory;struct stratix10_svc *svc =NULL ;const struct stratix10_svc_pdata *pdata =of_device_get_match_data (dev); +struct arm_smccc_res res; +bool use_dma_mem = false;svc_invoke_fn *invoke_fn;size_t fifo_size;
@@ -2197,18 +2227,38 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev)if (IS_ERR (invoke_fn))return -EINVAL ; - sh_memory =devm_kzalloc (dev,sizeof (*sh_memory),GFP_KERNEL ); -if (!sh_memory) -return -ENOMEM ; + use_dma_mem = pdata && pdata->use_dma_mem; - sh_memory->invoke_fn = invoke_fn; - ret =svc_get_sh_memory (pdev, sh_memory); -if (ret) -return ret; +if (use_dma_mem) { +if (!iommu_get_domain_for_dev (dev)) { +dev_err (dev, +"SMMU is required for agilex5-svc but no IOMMU domain found\n" ); +dev_err (dev, +"Ensure the SMMU node is enabled in the device tree and 'iommus' is set for this node\n" ); +return -ENODEV ; + } + +invoke_fn (INTEL_SIP_SMC_SDM_REMAPPER_CONFIG , +INTEL_SIP_SMC_SDM_REMAPPER_BYPASS , +0 ,0 ,0 ,0 ,0 ,0 , &res); + + ret =svc_setup_dma_memory (pdev); +if (ret) +return ret; + }else { + sh_memory =devm_kzalloc (dev,sizeof (*sh_memory),GFP_KERNEL ); +if (!sh_memory) +return -ENOMEM ; - genpool =svc_create_memory_pool (pdev, sh_memory); -if (IS_ERR (genpool)) -return PTR_ERR (genpool); + sh_memory->invoke_fn = invoke_fn; + ret =svc_get_sh_memory (pdev, sh_memory); +if (ret) +return ret; + + genpool =svc_create_memory_pool (pdev, sh_memory); +if (IS_ERR (genpool)) +return PTR_ERR (genpool); + }/* allocate service controller and supporting channel */ controller = devm_kzalloc(dev, struct_size(controller, chans, SVC_NUM_CHANNEL),
@@ -2223,9 +2273,17 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev) controller->num_active_client =0 ; controller->genpool = genpool; controller->invoke_fn = invoke_fn; + controller->use_dma_mem = use_dma_mem; + controller->dma_addr_offset = use_dma_mem ?SVC_SDM_DMA_ADDR_OFFSET :0 ;INIT_LIST_HEAD (&controller->node);init_completion (&controller->complete_status); +if (use_dma_mem) { + ret =devm_add_action_or_reset (dev, svc_data_mem_cleanup, controller); +if (ret) + goto err_destroy_pool; + } +if (pdata && pdata->needs_psci_cpu_off) { controller->psci_reboot_nb.notifier_call = psci_cpu_off_reboot_notifier;
@@ -2333,7 +2391,8 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev) err_free_notifier:psci_cpu_off_teardown (controller); err_destroy_pool: -gen_pool_destroy (genpool); +if (genpool) +gen_pool_destroy (genpool);return ret; }
include/linux/firmware/intel/stratix10-smc.h +23 -0
@@ -813,4 +813,27 @@ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_COMPLETED_WRITE)#define INTEL_SIP_SMC_ASYNC_FUNC_ID_RSU_NOTIFY (0xEC)#define INTEL_SIP_SMC_ASYNC_RSU_NOTIFY \ INTEL_SIP_SMC_ASYNC_VAL(INTEL_SIP_SMC_ASYNC_FUNC_ID_RSU_NOTIFY) + +/** +* Request INTEL_SIP_SMC_SDM_REMAPPER_CONFIG +* +* Sync call to configure the SDM address remapper. On Agilex5, the remapper +* must be bypassed when the SMMU is active to avoid conflicts with IOMMU +* address translation. +* +* Call register usage: +* a0: INTEL_SIP_SMC_SDM_REMAPPER_CONFIG +* a1: INTEL_SIP_SMC_SDM_REMAPPER_ENABLE or INTEL_SIP_SMC_SDM_REMAPPER_BYPASS +* a2-7: not used +* +* Return status: +* a0: INTEL_SIP_SMC_STATUS_OK +* a1-3: not used +*/ +#define INTEL_SIP_SMC_FUNCID_SDM_REMAPPER_CONFIG 513 +#define INTEL_SIP_SMC_SDM_REMAPPER_CONFIG \ + INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_SDM_REMAPPER_CONFIG) +#define INTEL_SIP_SMC_SDM_REMAPPER_ENABLE 0 +#define INTEL_SIP_SMC_SDM_REMAPPER_BYPASS 1 +#endif
Signature · 1 line
2.49.GIT
Dinh Nguyen
maintainerQuoted 63 lines · Adrian Ng Ho Yin
This series adds support for Agilex5 in the SVC driver and enables FPGA configuration and partial reconfiguration on Altera Agilex5 SoC.
On Agilex5 the DDR base address starts at 0x8000_0000, which is outside the addressable range of the SDM. The SMMU is used to remap DDR-allocated buffers to an IOVA within the SDM-accessible 0-512MB window. Agilex5 REV B introduced a hardware SDM address remapper, but it must be bypassed so no additional offset is applied to the IOVA, keeping the implementation consistent across all Agilex5 revisions.
Patch 1 adds the fpga-mgr child node and fpga-region to the Agilex5 DTSI. The SMMU is already enabled upstream.
Patch 2 reports unmatched frees in
stratix10_svc_free_memory()withdev_warn()and cleans up related coding style insvc_pa_to_va(). The list-head corruption fromlist_del(&svc_data_mem)was already fixed by commit9119ceb76e98("firmware: stratix10-svc: fix memory leaks and list corruption bugs").Patch 3 adds all data-structure fields, macros, includes, helper function, and allocation/free paths required for the DMA coherent mode. This covers both the foundational types (
dma_addr,use_dma_mem,dma_addr_offset, SVC_SDM_DMA_ADDR_BITS/OFFSET) and the functional DMA allocation/free code, keeping the structural and functional changes together so each intermediate commit is bisect-safe.Patch 4 adds
INTEL_SIP_SMC_SDM_REMAPPER_CONFIGand integrates the Agilex5 path into probe: enforces SMMU presence for intel,agilex5-svc, issues the remapper-bypass SMC, selects the DMA path via stratix10_svc_pdata.use_dma_mem, initialises the controller fields, registers a devm cleanup action for leaked buffers, and guards the error path against a NULL genpool.---
changelog:
v2 -> v3:
- Squash former patch 2 (SMC remapper defines) into the probe enablement patch so the defines land with their first usage.
- Rebase on socfpga_firmware_for_v7.4.
- Drop SMMU status="disabled" removal from the DTS patch (already upstream in10cf797f3f8a).
- Drop thelist_del(&svc_data_mem)fix already present in9119ceb76e98; keep the unmatched-free warning and style cleanup.
- Adapt of_device_id.data usage to extendstratix10_svc_pdata(shared withneeds_psci_cpu_off) instead of casting BIT flags into .data.
- Keep kzalloc_obj()/kfree() lifetime for pmem on bothgen_pooland DMA paths after9119ceb76e98.v1 -> v2:
- split original patch into smaller patches for easier review and backporting.
- Fixed the Fixes: tag in patch 3 referencing5a0793ac66ac
- Replacedof_device_is_compatible()with of_device_id.data +of_device_get_match_data()
- Various commit message improvements
---Adrian Ng Ho Yin (4):
arm64: dts: socfpga: agilex5: add FPGA manager and region nodes
firmware: stratix10-svc: warn on unmatched free in
stratix10_svc_free_memory
firmware: stratix10-svc: add DMA coherent memory allocation for
SMMU-enabled platforms
firmware: stratix10-svc: enable Agilex5 SMMU support in probe
Quoted 5 lines
.../arm64/boot/dts/intel/socfpga_agilex5.dtsi | 11 + drivers/firmware/stratix10-svc.c | 250 +++++++++++++++++--- include/linux/firmware/intel/stratix10-smc.h | 23 ++ 3 files changed, 239 insertions(+), 45 deletions(-)
All patches applied!
Thanks,
Dinh
Dinh Nguyen
maintainerQuoted 70 lines · Dinh Nguyen
Quoted 67 lines · Adrian Ng Ho Yin
This series adds support for Agilex5 in the SVC driver and enables FPGA configuration and partial reconfiguration on Altera Agilex5 SoC.
On Agilex5 the DDR base address starts at 0x8000_0000, which is outside the addressable range of the SDM. The SMMU is used to remap DDR-allocated buffers to an IOVA within the SDM-accessible 0-512MB window. Agilex5 REV B introduced a hardware SDM address remapper, but it must be bypassed so no additional offset is applied to the IOVA, keeping the implementation consistent across all Agilex5 revisions.
Patch 1 adds the fpga-mgr child node and fpga-region to the Agilex5 DTSI. The SMMU is already enabled upstream.
Patch 2 reports unmatched frees in
stratix10_svc_free_memory()withdev_warn()and cleans up related coding style insvc_pa_to_va(). The list-head corruption fromlist_del(&svc_data_mem)was already fixed by commit9119ceb76e98("firmware: stratix10-svc: fix memory leaks and list corruption bugs").Patch 3 adds all data-structure fields, macros, includes, helper function, and allocation/free paths required for the DMA coherent mode. This covers both the foundational types (
dma_addr,use_dma_mem,dma_addr_offset, SVC_SDM_DMA_ADDR_BITS/OFFSET) and the functional DMA allocation/free code, keeping the structural and functional changes together so each intermediate commit is bisect-safe.Patch 4 adds
INTEL_SIP_SMC_SDM_REMAPPER_CONFIGand integrates the Agilex5 path into probe: enforces SMMU presence for intel,agilex5-svc, issues the remapper-bypass SMC, selects the DMA path via stratix10_svc_pdata.use_dma_mem, initialises the controller fields, registers a devm cleanup action for leaked buffers, and guards the error path against a NULL genpool.---
changelog:
v2 -> v3:
- Squash former patch 2 (SMC remapper defines) into the probe enablement patch so the defines land with their first usage.
- Rebase on socfpga_firmware_for_v7.4.
- Drop SMMU status="disabled" removal from the DTS patch (already upstream
in10cf797f3f8a).
- Drop thelist_del(&svc_data_mem)fix already present in9119ceb76e98; keep the unmatched-free warning and style cleanup.
- Adapt of_device_id.data usage to extendstratix10_svc_pdata(shared with
needs_psci_cpu_off) instead of casting BIT flags into .data.
- Keep kzalloc_obj()/kfree() lifetime for pmem on bothgen_pooland DMA paths after9119ceb76e98.v1 -> v2:
- split original patch into smaller patches for easier review and backporting.
- Fixed the Fixes: tag in patch 3 referencing5a0793ac66ac
- Replacedof_device_is_compatible()with of_device_id.data +of_device_get_match_data()
- Various commit message improvements
---Adrian Ng Ho Yin (4):
arm64: dts: socfpga: agilex5: add FPGA manager and region nodes
firmware: stratix10-svc: warn on unmatched free instratix10_svc_free_memory
firmware: stratix10-svc: add DMA coherent memory allocation for SMMU-enabled platforms
firmware: stratix10-svc: enable Agilex5 SMMU support in probe
Quoted 9 lines
Quoted 6 lines
.../arm64/boot/dts/intel/socfpga_agilex5.dtsi| 11 + drivers/firmware/stratix10-svc.c | 250 +++++++++++++++++--- include/linux/firmware/intel/stratix10-smc.h | 23 ++ 3 files changed, 239 insertions(+), 45 deletions(-)All patches applied!
Sorry, but I had to un-applied the firmware patches.
Patch "firmware: stratix10-svc: add DMA coherent memory allocation for SMMU-enabled platforms", when built by itself produces this warning:
drivers/firmware/stratix10-svc.c:1112:12: warning: ‘svc_setup_dma_memory’ defined but not used [-Wunused-function]
1112 | static int svc_setup_dma_memory(struct platform_device *pdev)
| ^~~~~~~~~~~~~~~~~~~~
Looks like you need to bring this function into "firmware: stratix10-svc: enable Agilex5 SMMU support in probe".
Please fix up and resend just the firmware patches.
Thanks,
Dinh
Quoted 11 lines · Dinh Nguyen
Sorry, but I had to un-applied the firmware patches.
Patch "firmware: stratix10-svc: add DMA coherent memory allocation for SMMU-enabled platforms", when built by itself produces this warning:
drivers/firmware/stratix10-svc.c:1112:12: warning: ‘svc_setup_dma_memory’ defined but not used [-Wunused-function] 1112 | static intsvc_setup_dma_memory(struct platform_device *pdev)
| ^~~~~~~~~~~~~~~~~~~~Looks like you need to bring this function into "firmware: stratix10-svc: enable Agilex5 SMMU support in probe".
Please fix up and resend just the firmware patches.
Hi Dinh,
Thanks for catching that. You are right — svc_setup_dma_memory() was unused until the probe patch, so building the DMA-allocation commit alone triggered -Wunused-function. That split was also inert on its own (use_dma_mem stayed false).
v4 squashes the DMA-allocation and Agilex5 probe enablement patches into one commit, and resends the firmware patches only.
Best regards,
Adrian
Quoted 3 lines
Thanks,
Dinh
v4 cover firmware: stratix10-svc: Agilex5 SMMU DMA coherent support
In reply to Adrian Ng Ho YinFrom: Adrian Ng Ho Yin <[email protected]>
This series adds Agilex5 SMMU DMA coherent support in the stratix10-svc driver.
On Agilex5 the DDR base address starts at 0x8000_0000, which is outside the addressable range of the SDM. When SMMU is active, the driver must allocate DMA-coherent buffers and pass IOVAs within the SDM-accessible 0-512MB window to ATF. Agilex5 REV B introduced a hardware SDM address remapper, but it must be bypassed so no additional offset is applied to the IOVA, keeping the implementation consistent across all Agilex5 revisions.
Patch 1 reports unmatched frees in stratix10_svc_free_memory() with dev_warn() and cleans up related coding style in svc_pa_to_va(). The list-head corruption from list_del(&svc_data_mem) was already fixed by commit 9119ceb76e98 ("firmware: stratix10-svc: fix memory leaks and list corruption bugs").
Patch 2 adds the DMA coherent allocation path and wires Agilex5 enablement in probe: require an IOMMU domain for intel,agilex5-svc, bypass the SDM address remapper via INTEL_SIP_SMC_SDM_REMAPPER_CONFIG, set the 29-bit DMA mask, select the DMA path through stratix10_svc_pdata, register a devm cleanup for leaked buffers, and guard err_destroy_pool against a NULL genpool.
---
changelog:
v3 -> v4:
- Squash the DMA-allocation and Agilex5 probe enablement patches into one commit. Building the former alone triggered -Wunused-function on svc_setup_dma_memory() and left use_dma_mem false (inert).
- Drop the arm64 DTS patch from this series; resend firmware patches only.
- Drop Signed-off-by: Dinh Nguyen from patch 1; resending with author Signed-off-by only.
v2 -> v3:
- Squash former patch 2 (SMC remapper defines) into the probe enablement patch so the defines land with their first usage.
- Rebase on socfpga_firmware_for_v7.4.
- Drop the list_del(&svc_data_mem) fix already present in 9119ceb76e98; keep the unmatched-free warning and style cleanup.
- Adapt of_device_id.data usage to extend stratix10_svc_pdata (shared with needs_psci_cpu_off) instead of casting BIT flags into .data.
- Keep kzalloc_obj()/kfree() lifetime for pmem on both gen_pool and DMA paths after 9119ceb76e98.
v1 -> v2:
- split original patch into smaller patches for easier review and backporting.
- Fixed the Fixes: tag in patch 3 referencing 5a0793ac66ac
- Replaced of_device_is_compatible() with of_device_id.data + of_device_get_match_data()
- Various commit message improvements
---
Adrian Ng Ho Yin (2):
firmware: stratix10-svc: warn on unmatched free in
stratix10_svc_free_memory
firmware: stratix10-svc: add Agilex5 SMMU DMA coherent support
drivers/firmware/stratix10-svc.c | 250 +++++++++++++++---- include/linux/firmware/intel/stratix10-smc.h | 23 ++ 2 files changed, 228 insertions(+), 45 deletions(-)
Signature · 1 line
2.49.GIT
PATCH v4 1/2 firmware: stratix10-svc: warn on unmatched free in stratix10_svc_free_memory
From: Adrian Ng Ho Yin <[email protected]>
After commit 9119ceb76e98 ("firmware: stratix10-svc: fix memory leaks and list corruption bugs") removed the erroneous list_del(&svc_data_mem) that corrupted the list head on failed lookups, an unmatched free still silently returned. Report the spurious address with dev_warn().
While here, refactor the loop to use an inverted condition with continue to reduce nesting. Add braces in svc_pa_to_va() for consistency, and fix a stale "physical address" comment to "address" since paddr is not strictly a physical address.
--- drivers/firmware/stratix10-svc.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-)
drivers/firmware/stratix10-svc.c +16 -11
@@ -338,11 +338,12 @@ static void *svc_pa_to_va(unsigned long addr)pr_debug ("claim back P-addr=0x%016x\n" , (unsigned int )addr);guard (mutex)(&svc_mem_lock); -list_for_each_entry (pmem, &svc_data_mem, node) +list_for_each_entry (pmem, &svc_data_mem, node) {if (pmem->paddr == addr)return pmem->vaddr; + } -/* physical address is not found */ +/* address is not found */ return NULL ; }
@@ -1997,19 +1998,23 @@ EXPORT_SYMBOL_GPL(stratix10_svc_allocate_memory);*/ void stratix10_svc_free_memory (struct stratix10_svc_chan *chan,void *kaddr) { +struct stratix10_svc_controller *ctrl = chan->ctrl;struct stratix10_svc_data_mem *pmem;guard (mutex)(&svc_mem_lock); -list_for_each_entry (pmem, &svc_data_mem, node) -if (pmem->vaddr == kaddr) { -gen_pool_free (chan->ctrl->genpool, - (unsigned long )kaddr, pmem->size); - pmem->vaddr =NULL ; -list_del (&pmem->node); -kfree (pmem); -return ; - } +list_for_each_entry (pmem, &svc_data_mem, node) { +if (pmem->vaddr != kaddr) +continue ; + +gen_pool_free (ctrl->genpool, (unsigned long )kaddr, pmem->size); + pmem->vaddr =NULL ; +list_del (&pmem->node); +kfree (pmem); +return ; + } + +dev_warn (ctrl->dev,"free of unknown buffer %p\n" , kaddr); }EXPORT_SYMBOL_GPL (stratix10_svc_free_memory);
Signature · 1 line
2.49.GIT
PATCH v4 2/2 firmware: stratix10-svc: add Agilex5 SMMU DMA coherent support
In reply to [email protected]From: Adrian Ng Ho Yin <[email protected]>
On Agilex5, DDR starts at 0x8000_0000 which is outside the SDM's addressable range. When SMMU is active, the driver must allocate DMA-coherent buffers and pass IOVAs (not physical addresses) to ATF.
Add SVC_SDM_DMA_ADDR_BITS (29) and SVC_SDM_DMA_ADDR_OFFSET (0x8000_0000) to constrain IOVAs to the 0-512 MB window the SDM can reach and to satisfy ATF's address range check respectively.
Extend struct stratix10_svc_data_mem with dma_addr, and struct stratix10_svc_controller with use_dma_mem and dma_addr_offset. Update allocate/free and svc_thread_cmd_data_claim() for the DMA path.
Wire the Agilex5 path in probe: require an IOMMU domain for intel,agilex5-svc, bypass the SDM address remapper via INTEL_SIP_SMC_SDM_REMAPPER_CONFIG, call svc_setup_dma_memory() to set the 29-bit DMA mask, select the DMA path through stratix10_svc_pdata, register a devm cleanup for leaked buffers, and guard err_destroy_pool against a NULL genpool.
--- drivers/firmware/stratix10-svc.c | 229 ++++++++++++++++--- include/linux/firmware/intel/stratix10-smc.h | 23 ++ 2 files changed, 215 insertions(+), 37 deletions(-)
drivers/firmware/stratix10-svc.c +192 -37
@@ -7,10 +7,12 @@#include <linux/atomic.h> #include <linux/completion.h> #include <linux/delay.h> +#include <linux/dma-mapping.h> #include <linux/genalloc.h> #include <linux/hashtable.h> #include <linux/idr.h> #include <linux/io.h> +#include <linux/iommu.h> #include <linux/kfifo.h> #include <linux/kthread.h> #include <linux/module.h>
@@ -48,6 +50,23 @@#define FPGA_CONFIG_STATUS_TIMEOUT_SEC 30#define BYTE_TO_WORD_SIZE 4 +/* +* SVC_SDM_DMA_ADDR_BITS - constrains the IOVA allocated by +* dma_alloc_coherent() to 29 bits (0x0000_0000 - 0x1FFF_FFFF) +* when SMMU is active on Agilex5. The SDM accesses these buffers +* via the SMMU using IOVAs, so the 29-bit limit keeps IOVAs within +* the SDM's addressable window. +* +* SVC_SDM_DMA_ADDR_OFFSET - ATF on Agilex5 distinguishes +* SMMU-mapped buffers from direct physical addresses by the +* presence of this offset. The driver adds it to the IOVA before +* passing the address to ATF via SMC; ATF strips it, translates +* the remaining IOVA through the SMMU, and the SDM accesses the +* underlying physical memory. +*/ +#define SVC_SDM_DMA_ADDR_BITS 29 +#define SVC_SDM_DMA_ADDR_OFFSET 0x80000000UL +/* stratix10 service layer clients */ #define STRATIX10_RSU "stratix10-rsu"#define SOCFPGA_HWMON "socfpga-hwmon"
@@ -103,12 +122,17 @@struct stratix10_svc_pdata {bool needs_psci_cpu_off; +bool use_dma_mem; };static const struct stratix10_svc_pdata psci_cpu_off_pdata = { .needs_psci_cpu_off = true, }; +static const struct stratix10_svc_pdata agilex5_pdata = { + .use_dma_mem = true, +}; + typedef void (svc_invoke_fn)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long,
@@ -149,18 +173,25 @@ struct stratix10_svc_sh_memory {/** * struct stratix10_svc_data_mem - service memory structure * @vaddr: virtual address -* @paddr: physical address +* @paddr: address passed to ATF via SMC and echoed back in completion +* notifications; used as the lookup key in svc_pa_to_va(). +* On the SMMU path this is (IOVA + %SVC_SDM_DMA_ADDR_OFFSET); +* on the gen_pool path this equals the raw physical address. * @size: size of memory +* @dma_addr: IOVA returned by dma_alloc_coherent(); used to free the +* mapping via dma_free_coherent() on the SMMU path. * @node: link list head node * * This struct is used in a list that keeps track of buffers which have * been allocated or freed from the memory pool. Service layer driver also -* uses this struct to transfer physical address to virtual address. +* uses this struct to map the address returned by ATF back to a virtual +* address. */ struct stratix10_svc_data_mem {void *vaddr;phys_addr_t paddr;size_t size; +dma_addr_t dma_addr;struct list_head node; };
@@ -296,6 +327,15 @@ struct stratix10_svc_chan {* @sdm_lock: only allows a single command single response to SDM * @actrl: async control structure * @psci_reboot_nb: reboot notifier for PSCI secondary CPU offlining +* @use_dma_mem: when true, buffers are allocated via dma_alloc_coherent() +* instead of the ATF reserved-memory gen_pool. +* @dma_addr_offset: value added to the DMA address (IOVA) before passing it +* to ATF via SMC. ATF uses this offset to distinguish +* SMMU-mapped buffers from direct physical addresses; it +* strips the offset, translates the remaining IOVA through +* the SMMU, and the SDM accesses the underlying memory. +* Set to %SVC_SDM_DMA_ADDR_OFFSET on Agilex5 when SMMU is +* active; zero otherwise. * @chans: array of service channels * * This struct is used to create communication channels for service clients, to
@@ -313,6 +353,8 @@ struct stratix10_svc_controller {struct mutex sdm_lock;struct stratix10_async_ctrl actrl;struct notifier_block psci_reboot_nb; +bool use_dma_mem; +unsigned long dma_addr_offset; struct stratix10_svc_chan chans[] __counted_by(num_chans); };
@@ -377,11 +419,17 @@ static void svc_thread_cmd_data_claim(struct stratix10_svc_controller *ctrl,break ; } cb_data->status =BIT (SVC_STATUS_BUFFER_DONE ); - cb_data->kaddr1 =svc_pa_to_va (res.a1); +/* +* The firmware COMPLETED_WRITE response returns the +* raw IOVA (without dma_addr_offset). Add it back to +* match the key stored in pmem->paddr at allocation +* time. dma_addr_offset is zero on non-SMMU paths. +*/ + cb_data->kaddr1 =svc_pa_to_va (res.a1 + ctrl->dma_addr_offset); cb_data->kaddr2 = (res.a2) ? -svc_pa_to_va (res.a2) :NULL ; +svc_pa_to_va (res.a2 + ctrl->dma_addr_offset) :NULL ; cb_data->kaddr3 = (res.a3) ? -svc_pa_to_va (res.a3) :NULL ; +svc_pa_to_va (res.a3 + ctrl->dma_addr_offset) :NULL ; p_data->chan->scl->receive_cb (p_data->chan->scl, cb_data); }else {
@@ -1052,6 +1100,38 @@ svc_create_memory_pool(struct platform_device *pdev,return genpool; } +/** +* svc_setup_dma_memory() - configure the device for dynamic DMA allocation +* @pdev: pointer to service layer device +* +* Called instead of svc_get_sh_memory() + svc_create_memory_pool() when +* the device is behind an SMMU. Sets a 29-bit coherent DMA mask so that +* every subsequent dma_alloc_coherent() call yields an IOVA within the +* first 512MB (0x0000_0000 - 0x1FFF_FFFF). The driver then adds +* %SVC_SDM_DMA_ADDR_OFFSET to the IOVA before passing it to ATF; ATF +* strips the offset and uses the SMMU to translate the IOVA to the +* underlying physical memory for SDM access. +* +* Return: 0 on success, or a negative error code on failure. +*/ +static int svc_setup_dma_memory (struct platform_device *pdev) +{ +struct device *dev = &pdev->dev; +int ret; + + ret =dma_set_mask_and_coherent (dev,DMA_BIT_MASK (SVC_SDM_DMA_ADDR_BITS )); +if (ret) { +dev_err (dev, +"failed to set %u-bit DMA mask: %d\n" , +SVC_SDM_DMA_ADDR_BITS , ret); +return ret; + } + +dev_info (dev, +"SMMU enabled: using dynamic DMA allocation (IOVA range 0-512MB)\n" ); +return 0 ; +} +/** * svc_smccc_smc() - secure monitor call between normal and secure world * @a0: argument passed in registers 0
@@ -1958,34 +2038,50 @@ EXPORT_SYMBOL_GPL(stratix10_svc_done);void *stratix10_svc_allocate_memory (struct stratix10_svc_chan *chan,size_t size) { +struct stratix10_svc_controller *ctrl = chan->ctrl;struct stratix10_svc_data_mem *pmem; -unsigned long va; -phys_addr_t pa; -struct gen_pool *genpool = chan->ctrl->genpool; -size_t s =roundup (size,1 << genpool->min_alloc_order); +struct gen_pool *genpool; +dma_addr_t dma_addr; +size_t s; +void *va; pmem =kzalloc_obj (*pmem);if (!pmem)return ERR_PTR (-ENOMEM ); -guard (mutex)(&svc_mem_lock); - va =gen_pool_alloc (genpool, s); -if (!va) { -kfree (pmem); -return ERR_PTR (-ENOMEM ); - } +if (ctrl->use_dma_mem) { + va =dma_alloc_coherent (ctrl->dev, size, &dma_addr,GFP_KERNEL ); +if (!va) { +kfree (pmem); +return ERR_PTR (-ENOMEM ); + } + + pmem->vaddr = va; + pmem->paddr = dma_addr + ctrl->dma_addr_offset; + pmem->dma_addr = dma_addr; + pmem->size = size; + }else { + genpool = ctrl->genpool; + s =roundup (size,1 << genpool->min_alloc_order); -memset ((void *)va,0 , s); - pa =gen_pool_virt_to_phys (genpool, va); + va = (void *)gen_pool_alloc (genpool, s); +if (!va) { +kfree (pmem); +return ERR_PTR (-ENOMEM ); + } + +memset (va,0 , s); + pmem->vaddr = va; + pmem->paddr =gen_pool_virt_to_phys (genpool, (unsigned long )va); + pmem->size = s; + } - pmem->vaddr = (void *)va; - pmem->paddr = pa; - pmem->size = s; +guard (mutex)(&svc_mem_lock);list_add_tail (&pmem->node, &svc_data_mem); -pr_debug ("%s: %s: va=%p, pa=0x%016x\n" , __func__, - chan->name, pmem->vaddr, (unsigned int )pmem->paddr); +pr_debug ("%s: %s: va=%p, addr=0x%016llx\n" , __func__, + chan->name, pmem->vaddr, (unsigned long long )pmem->paddr); -return (void *)va; +return va; }EXPORT_SYMBOL_GPL (stratix10_svc_allocate_memory);
@@ -2007,8 +2103,13 @@ void stratix10_svc_free_memory(struct stratix10_svc_chan *chan, void *kaddr)if (pmem->vaddr != kaddr)continue ; -gen_pool_free (ctrl->genpool, (unsigned long )kaddr, pmem->size); - pmem->vaddr =NULL ; +if (ctrl->use_dma_mem) { +dma_free_coherent (ctrl->dev, pmem->size, + pmem->vaddr, pmem->dma_addr); + }else { +gen_pool_free (ctrl->genpool, + (unsigned long )kaddr, pmem->size); + }list_del (&pmem->node);kfree (pmem);return ;
@@ -2073,6 +2174,7 @@ static void psci_cpu_off_teardown(struct stratix10_svc_controller *ctrl)static const struct of_device_id stratix10_svc_drv_match[] = { { .compatible ="intel,stratix10-svc" , .data = &psci_cpu_off_pdata }, { .compatible ="intel,agilex-svc" , .data = &psci_cpu_off_pdata }, + { .compatible ="intel,agilex5-svc" , .data = &agilex5_pdata }, {}, };
@@ -2083,14 +2185,38 @@ static const char * const chan_names[SVC_NUM_CHANNEL] = {SVC_CLIENT_HWMON }; +static void svc_data_mem_cleanup (void *data) +{ +struct stratix10_svc_controller *ctrl = data; +struct stratix10_svc_data_mem *pmem, *tmp; + +guard (mutex)(&svc_mem_lock); + +list_for_each_entry_safe (pmem, tmp, &svc_data_mem, node) { +dev_warn (ctrl->dev,"leaked svc buffer %p, freeing on unbind\n" , + pmem->vaddr); +if (ctrl->use_dma_mem) { +dma_free_coherent (ctrl->dev, pmem->size, + pmem->vaddr, pmem->dma_addr); + }else { +gen_pool_free (ctrl->genpool, + (unsigned long )pmem->vaddr, pmem->size); + } +list_del (&pmem->node); +kfree (pmem); + } +} +static int stratix10_svc_drv_probe (struct platform_device *pdev) {struct device *dev = &pdev->dev;struct stratix10_svc_controller *controller; -struct gen_pool *genpool; +struct gen_pool *genpool =NULL ;struct stratix10_svc_sh_memory *sh_memory;struct stratix10_svc *svc =NULL ;const struct stratix10_svc_pdata *pdata =of_device_get_match_data (dev); +struct arm_smccc_res res; +bool use_dma_mem = false;svc_invoke_fn *invoke_fn;size_t fifo_size;
@@ -2101,18 +2227,38 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev)if (IS_ERR (invoke_fn))return -EINVAL ; - sh_memory =devm_kzalloc (dev,sizeof (*sh_memory),GFP_KERNEL ); -if (!sh_memory) -return -ENOMEM ; + use_dma_mem = pdata && pdata->use_dma_mem; - sh_memory->invoke_fn = invoke_fn; - ret =svc_get_sh_memory (pdev, sh_memory); -if (ret) -return ret; +if (use_dma_mem) { +if (!iommu_get_domain_for_dev (dev)) { +dev_err (dev, +"SMMU is required for agilex5-svc but no IOMMU domain found\n" ); +dev_err (dev, +"Ensure the SMMU node is enabled in the device tree and 'iommus' is set for this node\n" ); +return -ENODEV ; + } - genpool =svc_create_memory_pool (pdev, sh_memory); -if (IS_ERR (genpool)) -return PTR_ERR (genpool); +invoke_fn (INTEL_SIP_SMC_SDM_REMAPPER_CONFIG , +INTEL_SIP_SMC_SDM_REMAPPER_BYPASS , +0 ,0 ,0 ,0 ,0 ,0 , &res); + + ret =svc_setup_dma_memory (pdev); +if (ret) +return ret; + }else { + sh_memory =devm_kzalloc (dev,sizeof (*sh_memory),GFP_KERNEL ); +if (!sh_memory) +return -ENOMEM ; + + sh_memory->invoke_fn = invoke_fn; + ret =svc_get_sh_memory (pdev, sh_memory); +if (ret) +return ret; + + genpool =svc_create_memory_pool (pdev, sh_memory); +if (IS_ERR (genpool)) +return PTR_ERR (genpool); + }/* allocate service controller and supporting channel */ controller = devm_kzalloc(dev, struct_size(controller, chans, SVC_NUM_CHANNEL),
@@ -2127,9 +2273,17 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev) controller->num_active_client =0 ; controller->genpool = genpool; controller->invoke_fn = invoke_fn; + controller->use_dma_mem = use_dma_mem; + controller->dma_addr_offset = use_dma_mem ?SVC_SDM_DMA_ADDR_OFFSET :0 ;INIT_LIST_HEAD (&controller->node);init_completion (&controller->complete_status); +if (use_dma_mem) { + ret =devm_add_action_or_reset (dev, svc_data_mem_cleanup, controller); +if (ret) + goto err_destroy_pool; + } +if (pdata && pdata->needs_psci_cpu_off) { controller->psci_reboot_nb.notifier_call = psci_cpu_off_reboot_notifier;
@@ -2237,7 +2391,8 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev) err_free_notifier:psci_cpu_off_teardown (controller); err_destroy_pool: -gen_pool_destroy (genpool); +if (genpool) +gen_pool_destroy (genpool);return ret; }
include/linux/firmware/intel/stratix10-smc.h +23 -0
@@ -813,4 +813,27 @@ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_COMPLETED_WRITE)#define INTEL_SIP_SMC_ASYNC_FUNC_ID_RSU_NOTIFY (0xEC)#define INTEL_SIP_SMC_ASYNC_RSU_NOTIFY \ INTEL_SIP_SMC_ASYNC_VAL(INTEL_SIP_SMC_ASYNC_FUNC_ID_RSU_NOTIFY) + +/** +* Request INTEL_SIP_SMC_SDM_REMAPPER_CONFIG +* +* Sync call to configure the SDM address remapper. On Agilex5, the remapper +* must be bypassed when the SMMU is active to avoid conflicts with IOMMU +* address translation. +* +* Call register usage: +* a0: INTEL_SIP_SMC_SDM_REMAPPER_CONFIG +* a1: INTEL_SIP_SMC_SDM_REMAPPER_ENABLE or INTEL_SIP_SMC_SDM_REMAPPER_BYPASS +* a2-7: not used +* +* Return status: +* a0: INTEL_SIP_SMC_STATUS_OK +* a1-3: not used +*/ +#define INTEL_SIP_SMC_FUNCID_SDM_REMAPPER_CONFIG 513 +#define INTEL_SIP_SMC_SDM_REMAPPER_CONFIG \ + INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_SDM_REMAPPER_CONFIG) +#define INTEL_SIP_SMC_SDM_REMAPPER_ENABLE 0 +#define INTEL_SIP_SMC_SDM_REMAPPER_BYPASS 1 +#endif
Signature · 1 line
2.49.GIT
Re: [PATCH v4 0/2] firmware: stratix10-svc: Agilex5 SMMU DMA coherent support
In reply to [email protected]Quoted 55 lines · On 9/11/26 10:52, [email protected] wrote:
From: Adrian Ng Ho Yin <[email protected]>
This series adds Agilex5 SMMU DMA coherent support in the stratix10-svc driver.
On Agilex5 the DDR base address starts at 0x8000_0000, which is outside the addressable range of the SDM. When SMMU is active, the driver must allocate DMA-coherent buffers and pass IOVAs within the SDM-accessible 0-512MB window to ATF. Agilex5 REV B introduced a hardware SDM address remapper, but it must be bypassed so no additional offset is applied to the IOVA, keeping the implementation consistent across all Agilex5 revisions.
Patch 1 reports unmatched frees in
stratix10_svc_free_memory()withdev_warn()and cleans up related coding style insvc_pa_to_va(). The list-head corruption fromlist_del(&svc_data_mem)was already fixed by commit9119ceb76e98("firmware: stratix10-svc: fix memory leaks and list corruption bugs").Patch 2 adds the DMA coherent allocation path and wires Agilex5 enablement in probe: require an IOMMU domain for intel,agilex5-svc, bypass the SDM address remapper via
INTEL_SIP_SMC_SDM_REMAPPER_CONFIG, set the 29-bit DMA mask, select the DMA path throughstratix10_svc_pdata, register a devm cleanup for leaked buffers, and guarderr_destroy_poolagainst a NULL genpool.---
changelog:
v3 -> v4:
- Squash the DMA-allocation and Agilex5 probe enablement patches into one commit. Building the former alone triggered -Wunused-function onsvc_setup_dma_memory()and leftuse_dma_memfalse (inert).
- Drop the arm64 DTS patch from this series; resend firmware patches only.
- Drop Signed-off-by: Dinh Nguyen from patch 1; resending with author Signed-off-by only.v2 -> v3:
- Squash former patch 2 (SMC remapper defines) into the probe enablement patch so the defines land with their first usage.
- Rebase on socfpga_firmware_for_v7.4.
- Drop thelist_del(&svc_data_mem)fix already present in9119ceb76e98; keep the unmatched-free warning and style cleanup.
- Adapt of_device_id.data usage to extendstratix10_svc_pdata(shared withneeds_psci_cpu_off) instead of casting BIT flags into .data.
- Keep kzalloc_obj()/kfree() lifetime for pmem on bothgen_pooland DMA paths after9119ceb76e98.v1 -> v2:
- split original patch into smaller patches for easier review and backporting.
- Fixed the Fixes: tag in patch 3 referencing5a0793ac66ac
- Replacedof_device_is_compatible()with of_device_id.data +of_device_get_match_data()
- Various commit message improvements
---
Quoted 9 lines
Adrian Ng Ho Yin (2):
firmware: stratix10-svc: warn on unmatched free in
stratix10_svc_free_memory
firmware: stratix10-svc: add Agilex5 SMMU DMA coherent supportdrivers/firmware/stratix10-svc.c | 250 +++++++++++++++---- include/linux/firmware/intel/stratix10-smc.h | 23 ++ 2 files changed, 228 insertions(+), 45 deletions(-)
Applied!
Thanks,
Dinh