drivers/firmware/arm_ffa/driver.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-)
A partition manager may reject unsupported RX/TX buffer sizes by
returning INVALID_PARAMETERS. Commit 83210251fd70 ("firmware: arm_ffa:
Use the correct buffer size during RXTX_MAP") has the effect of rounding
up the buffer size from FFA_FEATURES to be PAGE_SIZE-aligned, which may
be larger than what the partition manager supports. This caused RXTX_MAP
to fail for some FF-A implementations on kernels with PAGE_SIZE > 4K.
In FF-A v1.2+ the partition manager can specify a maximum buffer size via
FFA_FEATURES, but the driver currently doesn't use it. Add support for
decoding and honoring the maximum buffer size.
Some v1.1 implementations also return INVALID_PARAMETERS from RXTX_MAP if
the buffer sizes are too large but lack a mechanism for discovering the
maximum buffer size. The relevant bits must be zero in v1.1 and earlier,
corresponding to "no maximum" in v1.2+, so we can handle both using
the same logic. First, try using a PAGE_SIZE-aligned buffer as is done
now. If this fails with INVALID_PARAMETERS, retry using the minimum
buffer size, which should always be supported.
While there, also update RXTX_MAP_MIN_BUFSZ() to use FIELD_GET() for
consistency.
Fixes: 83210251fd70 ("firmware: arm_ffa: Use the correct buffer size during RXTX_MAP")
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Seth Forshee <sforshee@nvidia.com>
---
Changes in v2:
- Combine into one patch.
- Remove unnecessary check for FF-A version when decoding maximum
buffer size, as this field must be zero in earlier versions.
- Simplify the implementation.
- Remove unnecessary typecast.
- Remove unnecessary comments.
- Rebase to for-next/ffa/updates.
- Link to v1: https://patch.msgid.link/20260601-b4-ffa-rxtx-map-fixes-v1-0-c071b12ae05c@nvidia.com
To: Sudeep Holla <sudeep.holla@kernel.org>
To: Sebastian Ene <sebastianene@google.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
---
drivers/firmware/arm_ffa/driver.c | 27 ++++++++++++++++++++-------
1 file changed, 20 insertions(+), 7 deletions(-)
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 0f468362c288..bc2685331b27 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -32,6 +32,7 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
+#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/mutex.h>
@@ -59,7 +60,9 @@
(FIELD_PREP(SENDER_ID_MASK, (s)) | FIELD_PREP(RECEIVER_ID_MASK, (r)))
#define RXTX_MAP_MIN_BUFSZ_MASK GENMASK(1, 0)
-#define RXTX_MAP_MIN_BUFSZ(x) ((x) & RXTX_MAP_MIN_BUFSZ_MASK)
+#define RXTX_MAP_MAX_BUFSZ_MASK GENMASK(31, 16)
+#define RXTX_MAP_MIN_BUFSZ(x) (FIELD_GET(RXTX_MAP_MIN_BUFSZ_MASK, (x)))
+#define RXTX_MAP_MAX_BUFSZ(x) (FIELD_GET(RXTX_MAP_MAX_BUFSZ_MASK, (x)))
#define FFA_MAX_NOTIFICATIONS 64
@@ -2101,7 +2104,7 @@ static int ffa_probe(struct platform_device *pdev)
{
int ret;
u32 buf_sz;
- size_t rxtx_bufsz = SZ_4K;
+ size_t rxtx_min_bufsz = SZ_4K, rxtx_max_bufsz = 0, rxtx_bufsz;
if (IS_BUILTIN(CONFIG_ARM_FFA_TRANSPORT) &&
is_protected_kvm_enabled() && !is_pkvm_initialized())
@@ -2132,15 +2135,18 @@ static int ffa_probe(struct platform_device *pdev)
ret = ffa_features(FFA_FN_NATIVE(RXTX_MAP), 0, &buf_sz, NULL);
if (!ret) {
if (RXTX_MAP_MIN_BUFSZ(buf_sz) == 1)
- rxtx_bufsz = SZ_64K;
+ rxtx_min_bufsz = SZ_64K;
else if (RXTX_MAP_MIN_BUFSZ(buf_sz) == 2)
- rxtx_bufsz = SZ_16K;
+ rxtx_min_bufsz = SZ_16K;
else
- rxtx_bufsz = SZ_4K;
+ rxtx_min_bufsz = SZ_4K;
+
+ rxtx_max_bufsz = RXTX_MAP_MAX_BUFSZ(buf_sz) * SZ_4K;
+ if (rxtx_max_bufsz != 0 && rxtx_max_bufsz < rxtx_min_bufsz)
+ rxtx_max_bufsz = rxtx_min_bufsz;
}
- rxtx_bufsz = PAGE_ALIGN(rxtx_bufsz);
- drv_info->rxtx_bufsz = rxtx_bufsz;
+ rxtx_bufsz = min_not_zero(PAGE_ALIGN(rxtx_min_bufsz), rxtx_max_bufsz);
drv_info->rx_buffer = alloc_pages_exact(rxtx_bufsz, GFP_KERNEL);
if (!drv_info->rx_buffer) {
ret = -ENOMEM;
@@ -2156,10 +2162,17 @@ static int ffa_probe(struct platform_device *pdev)
ret = ffa_rxtx_map(virt_to_phys(drv_info->tx_buffer),
virt_to_phys(drv_info->rx_buffer),
rxtx_bufsz / FFA_PAGE_SIZE);
+ if (ret == -EINVAL && !rxtx_max_bufsz && rxtx_min_bufsz < rxtx_bufsz) {
+ rxtx_bufsz = rxtx_min_bufsz;
+ ret = ffa_rxtx_map(virt_to_phys(drv_info->tx_buffer),
+ virt_to_phys(drv_info->rx_buffer),
+ rxtx_bufsz / FFA_PAGE_SIZE);
+ }
if (ret) {
pr_err("failed to register FFA RxTx buffers\n");
goto free_pages;
}
+ drv_info->rxtx_bufsz = rxtx_bufsz;
mutex_init(&drv_info->rx_lock);
mutex_init(&drv_info->tx_lock);
---
base-commit: 18706ea68fc4344049bf693b702cb311a7c27ca7
change-id: 20260531-b4-ffa-rxtx-map-fixes-244ede71a935
Best regards,
--
Seth Forshee <sforshee@nvidia.com>
On Tue, Jun 02, 2026 at 09:54:06PM +0000, Seth Forshee wrote:
> A partition manager may reject unsupported RX/TX buffer sizes by
> returning INVALID_PARAMETERS. Commit 83210251fd70 ("firmware: arm_ffa:
> Use the correct buffer size during RXTX_MAP") has the effect of rounding
> up the buffer size from FFA_FEATURES to be PAGE_SIZE-aligned, which may
> be larger than what the partition manager supports. This caused RXTX_MAP
> to fail for some FF-A implementations on kernels with PAGE_SIZE > 4K.
>
> In FF-A v1.2+ the partition manager can specify a maximum buffer size via
> FFA_FEATURES, but the driver currently doesn't use it. Add support for
> decoding and honoring the maximum buffer size.
>
> Some v1.1 implementations also return INVALID_PARAMETERS from RXTX_MAP if
> the buffer sizes are too large but lack a mechanism for discovering the
> maximum buffer size. The relevant bits must be zero in v1.1 and earlier,
> corresponding to "no maximum" in v1.2+, so we can handle both using
> the same logic. First, try using a PAGE_SIZE-aligned buffer as is done
> now. If this fails with INVALID_PARAMETERS, retry using the minimum
> buffer size, which should always be supported.
>
> While there, also update RXTX_MAP_MIN_BUFSZ() to use FIELD_GET() for
> consistency.
>
> Fixes: 83210251fd70 ("firmware: arm_ffa: Use the correct buffer size during RXTX_MAP")
> Assisted-by: Claude:claude-opus-4-8
I am planning to drop this as you just replace your code with exact verbatim
of what I suggested. I will replace with my suggested-by.
Thanks for testing and posting the patch. I have potentially queued it but
will rebase at v7.2-rc1 and send it as fix, so it may take some time. It will
be backported to v7.1 eventually, may have some trivial conflict but we can
take care when this lands in upstream.
--
Regards,
Sudeep
© 2016 - 2026 Red Hat, Inc.