[PATCH v9 09/13] firmware: qcom: qseecom: convert to using the TZ allocator

From: Bartosz Golaszewski
Date: Mon Mar 25 2024 - 10:00:48 EST


From: Bartosz Golaszewski <bartosz.golaszewski@xxxxxxxxxx>

Drop the DMA mapping operations from qcom_scm_qseecom_app_send() and
convert all users of it in the qseecom module to using the TZ allocator
for creating SCM call buffers. As this is largely a module separate from
the SCM driver, let's use a separate memory pool. Set the initial size to
4K and - if we run out - add twice the current amount to the pool.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@xxxxxxxxxx>
---
.../firmware/qcom/qcom_qseecom_uefisecapp.c | 47 ++++++++++++-------
drivers/firmware/qcom/qcom_scm.c | 30 +++---------
include/linux/firmware/qcom/qcom_qseecom.h | 4 +-
3 files changed, 39 insertions(+), 42 deletions(-)

diff --git a/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c b/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c
index 1f8c5efc2b5a..0bb13c8225c2 100644
--- a/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c
+++ b/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c
@@ -14,11 +14,14 @@
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/sizes.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/ucs2_string.h>

#include <linux/firmware/qcom/qcom_qseecom.h>
+#include <linux/firmware/qcom/qcom_scm.h>
+#include <linux/firmware/qcom/qcom_tzmem.h>

/* -- Qualcomm "uefisecapp" interface definitions. -------------------------- */

@@ -254,6 +257,7 @@ struct qsee_rsp_uefi_query_variable_info {
struct qcuefi_client {
struct qseecom_client *client;
struct efivars efivars;
+ struct qcom_tzmem_pool *mempool;
};

static struct device *qcuefi_dev(struct qcuefi_client *qcuefi)
@@ -273,8 +277,8 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e
const efi_guid_t *guid, u32 *attributes,
unsigned long *data_size, void *data)
{
- struct qsee_req_uefi_get_variable *req_data __free(kfree) = NULL;
- struct qsee_rsp_uefi_get_variable *rsp_data __free(kfree) = NULL;
+ struct qsee_req_uefi_get_variable *req_data __free(qcom_tzmem) = NULL;
+ struct qsee_rsp_uefi_get_variable *rsp_data __free(qcom_tzmem) = NULL;
unsigned long buffer_size = *data_size;
unsigned long name_length;
efi_status_t efi_status;
@@ -305,11 +309,11 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e
__array(u8, buffer_size)
);

- req_data = kzalloc(req_size, GFP_KERNEL);
+ req_data = qcom_tzmem_alloc(qcuefi->mempool, req_size, GFP_KERNEL);
if (!req_data)
return EFI_OUT_OF_RESOURCES;

- rsp_data = kzalloc(rsp_size, GFP_KERNEL);
+ rsp_data = qcom_tzmem_alloc(qcuefi->mempool, rsp_size, GFP_KERNEL);
if (!rsp_data)
return EFI_OUT_OF_RESOURCES;

@@ -394,8 +398,8 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e
const efi_guid_t *guid, u32 attributes,
unsigned long data_size, const void *data)
{
- struct qsee_req_uefi_set_variable *req_data __free(kfree) = NULL;
- struct qsee_rsp_uefi_set_variable *rsp_data __free(kfree) = NULL;
+ struct qsee_req_uefi_set_variable *req_data __free(qcom_tzmem) = NULL;
+ struct qsee_rsp_uefi_set_variable *rsp_data __free(qcom_tzmem) = NULL;
unsigned long name_length;
size_t name_offs;
size_t guid_offs;
@@ -425,11 +429,11 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e
__array_offs(u8, data_size, &data_offs)
);

- req_data = kzalloc(req_size, GFP_KERNEL);
+ req_data = qcom_tzmem_alloc(qcuefi->mempool, req_size, GFP_KERNEL);
if (!req_data)
return EFI_OUT_OF_RESOURCES;

- rsp_data = kzalloc(sizeof(*rsp_data), GFP_KERNEL);
+ rsp_data = qcom_tzmem_alloc(qcuefi->mempool, sizeof(*rsp_data), GFP_KERNEL);
if (!rsp_data)
return EFI_OUT_OF_RESOURCES;

@@ -476,8 +480,8 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
unsigned long *name_size, efi_char16_t *name,
efi_guid_t *guid)
{
- struct qsee_req_uefi_get_next_variable *req_data __free(kfree) = NULL;
- struct qsee_rsp_uefi_get_next_variable *rsp_data __free(kfree) = NULL;
+ struct qsee_req_uefi_get_next_variable *req_data __free(qcom_tzmem) = NULL;
+ struct qsee_rsp_uefi_get_next_variable *rsp_data __free(qcom_tzmem) = NULL;
efi_status_t efi_status;
size_t guid_offs;
size_t name_offs;
@@ -503,11 +507,11 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
__array(*name, *name_size / sizeof(*name))
);

- req_data = kzalloc(req_size, GFP_KERNEL);
+ req_data = qcom_tzmem_alloc(qcuefi->mempool, req_size, GFP_KERNEL);
if (!req_data)
return EFI_OUT_OF_RESOURCES;

- rsp_data = kzalloc(rsp_size, GFP_KERNEL);
+ rsp_data = qcom_tzmem_alloc(qcuefi->mempool, rsp_size, GFP_KERNEL);
if (!rsp_data)
return EFI_OUT_OF_RESOURCES;

@@ -587,15 +591,15 @@ static efi_status_t qsee_uefi_query_variable_info(struct qcuefi_client *qcuefi,
u64 *storage_space, u64 *remaining_space,
u64 *max_variable_size)
{
- struct qsee_req_uefi_query_variable_info *req_data __free(kfree) = NULL;
- struct qsee_rsp_uefi_query_variable_info *rsp_data __free(kfree) = NULL;
+ struct qsee_req_uefi_query_variable_info *req_data __free(qcom_tzmem) = NULL;
+ struct qsee_rsp_uefi_query_variable_info *rsp_data __free(qcom_tzmem) = NULL;
int status;

- req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
+ req_data = qcom_tzmem_alloc(qcuefi->mempool, sizeof(*req_data), GFP_KERNEL);
if (!req_data)
return EFI_OUT_OF_RESOURCES;

- rsp_data = kzalloc(sizeof(*rsp_data), GFP_KERNEL);
+ rsp_data = qcom_tzmem_alloc(qcuefi->mempool, sizeof(*rsp_data), GFP_KERNEL);
if (!rsp_data)
return EFI_OUT_OF_RESOURCES;

@@ -740,6 +744,7 @@ static const struct efivar_operations qcom_efivar_ops = {
static int qcom_uefisecapp_probe(struct auxiliary_device *aux_dev,
const struct auxiliary_device_id *aux_dev_id)
{
+ struct qcom_tzmem_pool_config pool_config;
struct qcuefi_client *qcuefi;
int status;

@@ -758,6 +763,16 @@ static int qcom_uefisecapp_probe(struct auxiliary_device *aux_dev,
if (status)
qcuefi_set_reference(NULL);

+ memset(&pool_config, 0, sizeof(pool_config));
+ pool_config.initial_size = SZ_4K;
+ pool_config.policy = QCOM_TZMEM_POLICY_MULTIPLIER;
+ pool_config.increment = 2;
+ pool_config.max_size = SZ_256K;
+
+ qcuefi->mempool = devm_qcom_tzmem_pool_new(&aux_dev->dev, &pool_config);
+ if (IS_ERR(qcuefi->mempool))
+ return PTR_ERR(qcuefi->mempool);
+
return status;
}

diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c
index d9b189632e61..f871af4af829 100644
--- a/drivers/firmware/qcom/qcom_scm.c
+++ b/drivers/firmware/qcom/qcom_scm.c
@@ -1570,9 +1570,9 @@ EXPORT_SYMBOL_GPL(qcom_scm_qseecom_app_get_id);
/**
* qcom_scm_qseecom_app_send() - Send to and receive data from a given QSEE app.
* @app_id: The ID of the target app.
- * @req: Request buffer sent to the app (must be DMA-mappable).
+ * @req: Request buffer sent to the app (must be TZ memory)
* @req_size: Size of the request buffer.
- * @rsp: Response buffer, written to by the app (must be DMA-mappable).
+ * @rsp: Response buffer, written to by the app (must be TZ memory)
* @rsp_size: Size of the response buffer.
*
* Sends a request to the QSEE app associated with the given ID and read back
@@ -1588,26 +1588,12 @@ int qcom_scm_qseecom_app_send(u32 app_id, void *req, size_t req_size, void *rsp,
{
struct qcom_scm_qseecom_resp res = {};
struct qcom_scm_desc desc = {};
- dma_addr_t req_phys;
- dma_addr_t rsp_phys;
+ phys_addr_t req_phys;
+ phys_addr_t rsp_phys;
int status;

- /* Map request buffer */
- req_phys = dma_map_single(__scm->dev, req, req_size, DMA_TO_DEVICE);
- status = dma_mapping_error(__scm->dev, req_phys);
- if (status) {
- dev_err(__scm->dev, "qseecom: failed to map request buffer\n");
- return status;
- }
-
- /* Map response buffer */
- rsp_phys = dma_map_single(__scm->dev, rsp, rsp_size, DMA_FROM_DEVICE);
- status = dma_mapping_error(__scm->dev, rsp_phys);
- if (status) {
- dma_unmap_single(__scm->dev, req_phys, req_size, DMA_TO_DEVICE);
- dev_err(__scm->dev, "qseecom: failed to map response buffer\n");
- return status;
- }
+ req_phys = qcom_tzmem_to_phys(req);
+ rsp_phys = qcom_tzmem_to_phys(rsp);

/* Set up SCM call data */
desc.owner = QSEECOM_TZ_OWNER_TZ_APPS;
@@ -1625,10 +1611,6 @@ int qcom_scm_qseecom_app_send(u32 app_id, void *req, size_t req_size, void *rsp,
/* Perform call */
status = qcom_scm_qseecom_call(&desc, &res);

- /* Unmap buffers */
- dma_unmap_single(__scm->dev, rsp_phys, rsp_size, DMA_FROM_DEVICE);
- dma_unmap_single(__scm->dev, req_phys, req_size, DMA_TO_DEVICE);
-
if (status)
return status;

diff --git a/include/linux/firmware/qcom/qcom_qseecom.h b/include/linux/firmware/qcom/qcom_qseecom.h
index 5c28298a98be..e868fac55675 100644
--- a/include/linux/firmware/qcom/qcom_qseecom.h
+++ b/include/linux/firmware/qcom/qcom_qseecom.h
@@ -27,9 +27,9 @@ struct qseecom_client {
/**
* qcom_qseecom_app_send() - Send to and receive data from a given QSEE app.
* @client: The QSEECOM client associated with the target app.
- * @req: Request buffer sent to the app (must be DMA-mappable).
+ * @req: Request buffer sent to the app (must be TZ memory).
* @req_size: Size of the request buffer.
- * @rsp: Response buffer, written to by the app (must be DMA-mappable).
+ * @rsp: Response buffer, written to by the app (must be TZ memory).
* @rsp_size: Size of the response buffer.
*
* Sends a request to the QSEE app associated with the given client and read
--
2.40.1