firmware: arm_ffa: Fetch the Rx/Tx buffer size using ffa_features()

An endpoint can discover the minimum size, maximum size and alignment
boundary for the Rx/Tx buffers by passing the function ID of the
FFA_RXTX_MAP ABI as input in the FFA_FEATURES interface. The maximum
size is an optional field and a value of 0 means that the partition
manager or the hypervisor does not enforce a maximum size.

Use the discovery mechanism and remove the hardcoded 4kB buffer size.
If the discovery fails, it still defaults to 4kB.

Message-Id: <20240820-ffa_v1-2-v2-7-18c0c5f3c65e@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
This commit is contained in:
Sudeep Holla 2024-08-20 15:28:00 +01:00
parent eaca7ef8f3
commit 61824feae5

View File

@ -54,11 +54,8 @@
#define PACK_TARGET_INFO(s, r) \ #define PACK_TARGET_INFO(s, r) \
(FIELD_PREP(SENDER_ID_MASK, (s)) | FIELD_PREP(RECEIVER_ID_MASK, (r))) (FIELD_PREP(SENDER_ID_MASK, (s)) | FIELD_PREP(RECEIVER_ID_MASK, (r)))
/* #define RXTX_MAP_MIN_BUFSZ_MASK GENMASK(1, 0)
* Keeping RX TX buffer size as 4K for now #define RXTX_MAP_MIN_BUFSZ(x) ((x) & RXTX_MAP_MIN_BUFSZ_MASK)
* 64K may be preferred to keep it min a page in 64K PAGE_SIZE config
*/
#define RXTX_BUFFER_SIZE SZ_4K
#define FFA_MAX_NOTIFICATIONS 64 #define FFA_MAX_NOTIFICATIONS 64
@ -99,6 +96,7 @@ struct ffa_drv_info {
struct mutex tx_lock; /* lock to protect Tx buffer */ struct mutex tx_lock; /* lock to protect Tx buffer */
void *rx_buffer; void *rx_buffer;
void *tx_buffer; void *tx_buffer;
size_t rxtx_bufsz;
bool mem_ops_native; bool mem_ops_native;
bool msg_direct_req2_supp; bool msg_direct_req2_supp;
bool bitmap_created; bool bitmap_created;
@ -454,7 +452,7 @@ static int ffa_msg_send2(u16 src_id, u16 dst_id, void *buf, size_t sz)
ffa_value_t ret; ffa_value_t ret;
int retval = 0; int retval = 0;
if (sz > (RXTX_BUFFER_SIZE - sizeof(*msg))) if (sz > (drv_info->rxtx_bufsz - sizeof(*msg)))
return -ERANGE; return -ERANGE;
mutex_lock(&drv_info->tx_lock); mutex_lock(&drv_info->tx_lock);
@ -689,9 +687,10 @@ static int ffa_memory_ops(u32 func_id, struct ffa_mem_ops_args *args)
{ {
int ret; int ret;
void *buffer; void *buffer;
size_t rxtx_bufsz = drv_info->rxtx_bufsz;
if (!args->use_txbuf) { if (!args->use_txbuf) {
buffer = alloc_pages_exact(RXTX_BUFFER_SIZE, GFP_KERNEL); buffer = alloc_pages_exact(rxtx_bufsz, GFP_KERNEL);
if (!buffer) if (!buffer)
return -ENOMEM; return -ENOMEM;
} else { } else {
@ -699,12 +698,12 @@ static int ffa_memory_ops(u32 func_id, struct ffa_mem_ops_args *args)
mutex_lock(&drv_info->tx_lock); mutex_lock(&drv_info->tx_lock);
} }
ret = ffa_setup_and_transmit(func_id, buffer, RXTX_BUFFER_SIZE, args); ret = ffa_setup_and_transmit(func_id, buffer, rxtx_bufsz, args);
if (args->use_txbuf) if (args->use_txbuf)
mutex_unlock(&drv_info->tx_lock); mutex_unlock(&drv_info->tx_lock);
else else
free_pages_exact(buffer, RXTX_BUFFER_SIZE); free_pages_exact(buffer, rxtx_bufsz);
return ret < 0 ? ret : 0; return ret < 0 ? ret : 0;
} }
@ -1718,6 +1717,8 @@ cleanup:
static int __init ffa_init(void) static int __init ffa_init(void)
{ {
int ret; int ret;
u32 buf_sz;
size_t rxtx_bufsz = SZ_4K;
ret = ffa_transport_init(&invoke_ffa_fn); ret = ffa_transport_init(&invoke_ffa_fn);
if (ret) if (ret)
@ -1737,13 +1738,24 @@ static int __init ffa_init(void)
goto free_drv_info; goto free_drv_info;
} }
drv_info->rx_buffer = alloc_pages_exact(RXTX_BUFFER_SIZE, GFP_KERNEL); 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;
else if (RXTX_MAP_MIN_BUFSZ(buf_sz) == 2)
rxtx_bufsz = SZ_16K;
else
rxtx_bufsz = SZ_4K;
}
drv_info->rxtx_bufsz = rxtx_bufsz;
drv_info->rx_buffer = alloc_pages_exact(rxtx_bufsz, GFP_KERNEL);
if (!drv_info->rx_buffer) { if (!drv_info->rx_buffer) {
ret = -ENOMEM; ret = -ENOMEM;
goto free_pages; goto free_pages;
} }
drv_info->tx_buffer = alloc_pages_exact(RXTX_BUFFER_SIZE, GFP_KERNEL); drv_info->tx_buffer = alloc_pages_exact(rxtx_bufsz, GFP_KERNEL);
if (!drv_info->tx_buffer) { if (!drv_info->tx_buffer) {
ret = -ENOMEM; ret = -ENOMEM;
goto free_pages; goto free_pages;
@ -1751,7 +1763,7 @@ static int __init ffa_init(void)
ret = ffa_rxtx_map(virt_to_phys(drv_info->tx_buffer), ret = ffa_rxtx_map(virt_to_phys(drv_info->tx_buffer),
virt_to_phys(drv_info->rx_buffer), virt_to_phys(drv_info->rx_buffer),
RXTX_BUFFER_SIZE / FFA_PAGE_SIZE); rxtx_bufsz / FFA_PAGE_SIZE);
if (ret) { if (ret) {
pr_err("failed to register FFA RxTx buffers\n"); pr_err("failed to register FFA RxTx buffers\n");
goto free_pages; goto free_pages;
@ -1781,8 +1793,8 @@ cleanup_notifs:
ffa_notifications_cleanup(); ffa_notifications_cleanup();
free_pages: free_pages:
if (drv_info->tx_buffer) if (drv_info->tx_buffer)
free_pages_exact(drv_info->tx_buffer, RXTX_BUFFER_SIZE); free_pages_exact(drv_info->tx_buffer, rxtx_bufsz);
free_pages_exact(drv_info->rx_buffer, RXTX_BUFFER_SIZE); free_pages_exact(drv_info->rx_buffer, rxtx_bufsz);
free_drv_info: free_drv_info:
kfree(drv_info); kfree(drv_info);
return ret; return ret;
@ -1794,8 +1806,8 @@ static void __exit ffa_exit(void)
ffa_notifications_cleanup(); ffa_notifications_cleanup();
ffa_partitions_cleanup(); ffa_partitions_cleanup();
ffa_rxtx_unmap(drv_info->vm_id); ffa_rxtx_unmap(drv_info->vm_id);
free_pages_exact(drv_info->tx_buffer, RXTX_BUFFER_SIZE); free_pages_exact(drv_info->tx_buffer, drv_info->rxtx_bufsz);
free_pages_exact(drv_info->rx_buffer, RXTX_BUFFER_SIZE); free_pages_exact(drv_info->rx_buffer, drv_info->rxtx_bufsz);
kfree(drv_info); kfree(drv_info);
} }
module_exit(ffa_exit); module_exit(ffa_exit);