[PATCH 3/6] ASoC: Intel: avs: Preallocate memory for module configuration

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



In order to instantiate modules on the firmware side, the driver sends
payload with module configuration. In some case size of this information
is not known before hand, so driver allocates temporary memory during
module creation and frees it after use. Optimize the flow a bit, by
preallocating maximum buffer. This removes the time spend on allocating
memory, as well as potential OOM errors during module initialization.

Handlers for modules, where configuration data fits on stack, are left
as is.

Reviewed-by: Cezary Rojewski <cezary.rojewski@xxxxxxxxx>
Signed-off-by: Amadeusz Sławiński <amadeuszx.slawinski@xxxxxxxxxxxxxxx>
---
 sound/soc/intel/avs/avs.h  |  1 +
 sound/soc/intel/avs/core.c |  5 +++++
 sound/soc/intel/avs/path.c | 31 +++++++++++++++----------------
 3 files changed, 21 insertions(+), 16 deletions(-)

diff --git a/sound/soc/intel/avs/avs.h b/sound/soc/intel/avs/avs.h
index 0012f989b24f..d694e08e44e1 100644
--- a/sound/soc/intel/avs/avs.h
+++ b/sound/soc/intel/avs/avs.h
@@ -121,6 +121,7 @@ struct avs_dev {
 	struct avs_mods_info *mods_info;
 	struct ida **mod_idas;
 	struct mutex modres_mutex;
+	void *modcfg_buf;		/* module configuration buffer */
 	struct ida ppl_ida;
 	struct list_head fw_list;
 	int *core_refs;		/* reference count per core */
diff --git a/sound/soc/intel/avs/core.c b/sound/soc/intel/avs/core.c
index 859b217fc761..62fd60d5b660 100644
--- a/sound/soc/intel/avs/core.c
+++ b/sound/soc/intel/avs/core.c
@@ -26,6 +26,7 @@
 #include "../../codecs/hda.h"
 #include "avs.h"
 #include "cldma.h"
+#include "messages.h"
 
 static u32 pgctl_mask = AZX_PGCTL_LSRMD_MASK;
 module_param(pgctl_mask, uint, 0444);
@@ -380,6 +381,10 @@ static int avs_bus_init(struct avs_dev *adev, struct pci_dev *pci, const struct
 	if (ret < 0)
 		return ret;
 
+	adev->modcfg_buf = devm_kzalloc(dev, AVS_MAILBOX_SIZE, GFP_KERNEL);
+	if (!adev->modcfg_buf)
+		return -ENOMEM;
+
 	adev->dev = dev;
 	adev->spec = (const struct avs_spec *)id->driver_data;
 	adev->ipc = ipc;
diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c
index adbe23a47847..aa8b50b931c3 100644
--- a/sound/soc/intel/avs/path.c
+++ b/sound/soc/intel/avs/path.c
@@ -237,11 +237,11 @@ static int avs_copier_create(struct avs_dev *adev, struct avs_path_module *mod)
 	/* Every config-BLOB contains gateway attributes. */
 	if (data_size)
 		cfg_size -= sizeof(cfg->gtw_cfg.config.attrs);
+	if (cfg_size > AVS_MAILBOX_SIZE)
+		return -EINVAL;
 
-	cfg = kzalloc(cfg_size, GFP_KERNEL);
-	if (!cfg)
-		return -ENOMEM;
-
+	cfg = adev->modcfg_buf;
+	memset(cfg, 0, cfg_size);
 	cfg->base.cpc = t->cfg_base->cpc;
 	cfg->base.ibs = t->cfg_base->ibs;
 	cfg->base.obs = t->cfg_base->obs;
@@ -261,7 +261,6 @@ static int avs_copier_create(struct avs_dev *adev, struct avs_path_module *mod)
 	ret = avs_dsp_init_module(adev, mod->module_id, mod->owner->instance_id,
 				  t->core_id, t->domain, cfg, cfg_size,
 				  &mod->instance_id);
-	kfree(cfg);
 	return ret;
 }
 
@@ -294,7 +293,7 @@ static int avs_peakvol_create(struct avs_dev *adev, struct avs_path_module *mod)
 	struct avs_control_data *ctl_data;
 	struct avs_peakvol_cfg *cfg;
 	int volume = S32_MAX;
-	size_t size;
+	size_t cfg_size;
 	int ret;
 
 	ctl_data = avs_get_module_control(mod);
@@ -302,11 +301,12 @@ static int avs_peakvol_create(struct avs_dev *adev, struct avs_path_module *mod)
 		volume = ctl_data->volume;
 
 	/* As 2+ channels controls are unsupported, have a single block for all channels. */
-	size = struct_size(cfg, vols, 1);
-	cfg = kzalloc(size, GFP_KERNEL);
-	if (!cfg)
-		return -ENOMEM;
+	cfg_size = struct_size(cfg, vols, 1);
+	if (cfg_size > AVS_MAILBOX_SIZE)
+		return -EINVAL;
 
+	cfg = adev->modcfg_buf;
+	memset(cfg, 0, cfg_size);
 	cfg->base.cpc = t->cfg_base->cpc;
 	cfg->base.ibs = t->cfg_base->ibs;
 	cfg->base.obs = t->cfg_base->obs;
@@ -318,9 +318,8 @@ static int avs_peakvol_create(struct avs_dev *adev, struct avs_path_module *mod)
 	cfg->vols[0].curve_duration = 0;
 
 	ret = avs_dsp_init_module(adev, mod->module_id, mod->owner->instance_id, t->core_id,
-				  t->domain, cfg, size, &mod->instance_id);
+				  t->domain, cfg, cfg_size, &mod->instance_id);
 
-	kfree(cfg);
 	return ret;
 }
 
@@ -480,10 +479,11 @@ static int avs_modext_create(struct avs_dev *adev, struct avs_path_module *mod)
 	num_pins = tcfg->generic.num_input_pins + tcfg->generic.num_output_pins;
 	cfg_size = struct_size(cfg, pin_fmts, num_pins);
 
-	cfg = kzalloc(cfg_size, GFP_KERNEL);
-	if (!cfg)
-		return -ENOMEM;
+	if (cfg_size > AVS_MAILBOX_SIZE)
+		return -EINVAL;
 
+	cfg = adev->modcfg_buf;
+	memset(cfg, 0, cfg_size);
 	cfg->base.cpc = t->cfg_base->cpc;
 	cfg->base.ibs = t->cfg_base->ibs;
 	cfg->base.obs = t->cfg_base->obs;
@@ -505,7 +505,6 @@ static int avs_modext_create(struct avs_dev *adev, struct avs_path_module *mod)
 	ret = avs_dsp_init_module(adev, mod->module_id, mod->owner->instance_id,
 				  t->core_id, t->domain, cfg, cfg_size,
 				  &mod->instance_id);
-	kfree(cfg);
 	return ret;
 }
 
-- 
2.34.1




[Index of Archives]     [ALSA User]     [Linux Audio Users]     [Pulse Audio]     [Kernel Archive]     [Asterisk PBX]     [Photo Sharing]     [Linux Sound]     [Video 4 Linux]     [Gimp]     [Yosemite News]

  Powered by Linux