351 lines
9.5 KiB
Diff
351 lines
9.5 KiB
Diff
From daa80ed6725d6a3a4f4bf9b5a7953ad6f08dcfd2 Mon Sep 17 00:00:00 2001
|
|
From: "Pawse, GuruprasadX" <guruprasadx.pawse@intel.com>
|
|
Date: Mon, 30 Jan 2017 20:12:52 +0530
|
|
Subject: [PATCH 190/550] ASoC: Intel: Skylake: add sysfs files for firmware
|
|
modules
|
|
|
|
This patch adds sysfs files for firmware modules.
|
|
|
|
Below is the structure of sysfs files created:
|
|
/sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/dsp/modules/<UUID>
|
|
|---id: module id
|
|
|---hash: module hash
|
|
|---loaded: module state loaded/unloaded
|
|
|
|
Change-Id: Ia097a3cc1409a33b2a82b1d1cdc634fb4b0eee90
|
|
Signed-off-by: Pawse, GuruprasadX <guruprasadx.pawse@intel.com>
|
|
Reviewed-on:
|
|
Reviewed-by: R, Dharageswari <dharageswari.r@intel.com>
|
|
Reviewed-by: Kp, Jeeja <jeeja.kp@intel.com>
|
|
Reviewed-by: Prodduvaka, Leoni <leoni.prodduvaka@intel.com>
|
|
Tested-by: Sm, Bhadur A <bhadur.a.sm@intel.com>
|
|
---
|
|
sound/soc/intel/skylake/skl-messages.c | 1 +
|
|
sound/soc/intel/skylake/skl-pcm.c | 3 +
|
|
sound/soc/intel/skylake/skl-sst-dsp.h | 7 +
|
|
sound/soc/intel/skylake/skl-sst-ipc.h | 3 +
|
|
sound/soc/intel/skylake/skl-sst-utils.c | 222 +++++++++++++++++++++++-
|
|
5 files changed, 235 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c
|
|
index f4ebdce7446d..54bd83eb55b5 100644
|
|
--- a/sound/soc/intel/skylake/skl-messages.c
|
|
+++ b/sound/soc/intel/skylake/skl-messages.c
|
|
@@ -1164,6 +1164,7 @@ int skl_free_dsp(struct skl *skl)
|
|
/* disable ppcap interrupt */
|
|
snd_hdac_ext_bus_ppcap_int_enable(bus, false);
|
|
|
|
+ skl_module_sysfs_exit(skl->skl_sst);
|
|
ctx->dsp_ops->cleanup(bus->dev, ctx);
|
|
|
|
kfree(ctx->cores.state);
|
|
diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c
|
|
index 265992ec11ff..361b85bfa792 100644
|
|
--- a/sound/soc/intel/skylake/skl-pcm.c
|
|
+++ b/sound/soc/intel/skylake/skl-pcm.c
|
|
@@ -1954,6 +1954,9 @@ static int skl_platform_soc_probe(struct snd_soc_component *component)
|
|
}
|
|
|
|
skl_get_probe_widget(component, skl);
|
|
+
|
|
+ /* create sysfs to list modules downloaded by driver */
|
|
+ skl_module_sysfs_init(skl->skl_sst, &component->dev->kobj);
|
|
}
|
|
pm_runtime_mark_last_busy(component->dev);
|
|
pm_runtime_put_autosuspend(component->dev);
|
|
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h
|
|
index 58c0c13c15aa..7be2cdeb85b6 100644
|
|
--- a/sound/soc/intel/skylake/skl-sst-dsp.h
|
|
+++ b/sound/soc/intel/skylake/skl-sst-dsp.h
|
|
@@ -137,6 +137,8 @@ struct skl_tlv_message {
|
|
|
|
#define DSP_BUF PAGE_SIZE
|
|
|
|
+#define DEFAULT_HASH_SHA256_LEN 32
|
|
+
|
|
enum skl_fw_info_type {
|
|
SKL_FW_VERSION = 0,
|
|
SKL_MEMORY_RECLAIMED,
|
|
@@ -218,6 +220,7 @@ struct uuid_module {
|
|
int *instance_id;
|
|
|
|
struct list_head list;
|
|
+ u8 hash[DEFAULT_HASH_SHA256_LEN];
|
|
};
|
|
|
|
struct skl_load_module_info {
|
|
@@ -301,4 +304,8 @@ int bxt_set_dsp_D0i0(struct sst_dsp *ctx);
|
|
int bxt_schedule_dsp_D0i3(struct sst_dsp *ctx);
|
|
|
|
void bxt_set_dsp_D0i3(struct work_struct *work);
|
|
+
|
|
+int skl_module_sysfs_init(struct skl_sst *ctx, struct kobject *fw_modules_kobj);
|
|
+
|
|
+void skl_module_sysfs_exit(struct skl_sst *ctx);
|
|
#endif /*__SKL_SST_DSP_H__*/
|
|
diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h
|
|
index 7700b5c54934..f3b8d7bc68ec 100644
|
|
--- a/sound/soc/intel/skylake/skl-sst-ipc.h
|
|
+++ b/sound/soc/intel/skylake/skl-sst-ipc.h
|
|
@@ -247,6 +247,9 @@ struct skl_sst {
|
|
|
|
/* firmware configuration information */
|
|
struct skl_fw_property_info fw_property;
|
|
+
|
|
+ /* sysfs for module info */
|
|
+ struct skl_sysfs_tree *sysfs_tree;
|
|
};
|
|
|
|
struct skl_ipc_init_instance_msg {
|
|
diff --git a/sound/soc/intel/skylake/skl-sst-utils.c b/sound/soc/intel/skylake/skl-sst-utils.c
|
|
index 2bd5565d5f80..0eaa88e6ae61 100644
|
|
--- a/sound/soc/intel/skylake/skl-sst-utils.c
|
|
+++ b/sound/soc/intel/skylake/skl-sst-utils.c
|
|
@@ -23,11 +23,35 @@
|
|
|
|
|
|
#define UUID_STR_SIZE 37
|
|
-#define DEFAULT_HASH_SHA256_LEN 32
|
|
|
|
/* FW Extended Manifest Header id = $AE1 */
|
|
#define SKL_EXT_MANIFEST_HEADER_MAGIC 0x31454124
|
|
|
|
+#define UUID_ATTR_RO(_name) \
|
|
+ struct uuid_attribute uuid_attr_##_name = __ATTR_RO(_name)
|
|
+
|
|
+struct skl_sysfs_tree {
|
|
+ struct kobject *dsp_kobj;
|
|
+ struct kobject *modules_kobj;
|
|
+ struct skl_sysfs_module **mod_obj;
|
|
+};
|
|
+
|
|
+struct skl_sysfs_module {
|
|
+ struct kobject kobj;
|
|
+ struct uuid_module *uuid_mod;
|
|
+ struct list_head *module_list;
|
|
+ int fw_ops_load_mod;
|
|
+};
|
|
+
|
|
+struct uuid_attribute {
|
|
+ struct attribute attr;
|
|
+ ssize_t (*show)(struct skl_sysfs_module *modinfo_obj,
|
|
+ struct uuid_attribute *attr, char *buf);
|
|
+ ssize_t (*store)(struct skl_sysfs_module *modinfo_obj,
|
|
+ struct uuid_attribute *attr, const char *buf,
|
|
+ size_t count);
|
|
+};
|
|
+
|
|
struct UUID {
|
|
u8 id[16];
|
|
};
|
|
@@ -319,6 +343,7 @@ int snd_skl_parse_uuids(struct sst_dsp *ctx, const struct firmware *fw,
|
|
ret = -ENOMEM;
|
|
goto free_uuid_list;
|
|
}
|
|
+ memcpy(&module->hash, mod_entry->hash1, sizeof(module->hash));
|
|
|
|
list_add_tail(&module->list, &skl->uuid_list);
|
|
|
|
@@ -665,3 +690,198 @@ int skl_get_firmware_configuration(struct sst_dsp *ctx)
|
|
kfree(ipc_data);
|
|
return ret;
|
|
}
|
|
+
|
|
+static ssize_t uuid_attr_show(struct kobject *kobj, struct attribute *attr,
|
|
+ char *buf)
|
|
+{
|
|
+ struct uuid_attribute *uuid_attr =
|
|
+ container_of(attr, struct uuid_attribute, attr);
|
|
+ struct skl_sysfs_module *modinfo_obj =
|
|
+ container_of(kobj, struct skl_sysfs_module, kobj);
|
|
+
|
|
+ if (uuid_attr->show)
|
|
+ return uuid_attr->show(modinfo_obj, uuid_attr, buf);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static const struct sysfs_ops uuid_sysfs_ops = {
|
|
+ .show = uuid_attr_show,
|
|
+};
|
|
+
|
|
+static void uuid_release(struct kobject *kobj)
|
|
+{
|
|
+ struct skl_sysfs_module *modinfo_obj =
|
|
+ container_of(kobj, struct skl_sysfs_module, kobj);
|
|
+
|
|
+ kfree(modinfo_obj);
|
|
+}
|
|
+
|
|
+static struct kobj_type uuid_ktype = {
|
|
+ .release = uuid_release,
|
|
+ .sysfs_ops = &uuid_sysfs_ops,
|
|
+};
|
|
+
|
|
+static ssize_t loaded_show(struct skl_sysfs_module *modinfo_obj,
|
|
+ struct uuid_attribute *attr, char *buf)
|
|
+{
|
|
+ struct skl_module_table *module_list;
|
|
+
|
|
+ if ((!modinfo_obj->fw_ops_load_mod) ||
|
|
+ (modinfo_obj->fw_ops_load_mod &&
|
|
+ !modinfo_obj->uuid_mod->is_loadable))
|
|
+ return sprintf(buf, "%d\n", true);
|
|
+
|
|
+ if (list_empty(modinfo_obj->module_list))
|
|
+ return sprintf(buf, "%d\n", false);
|
|
+
|
|
+ list_for_each_entry(module_list, modinfo_obj->module_list, list) {
|
|
+ if (module_list->mod_info->mod_id
|
|
+ == modinfo_obj->uuid_mod->id)
|
|
+ return sprintf(buf, "%d\n", module_list->usage_cnt);
|
|
+ }
|
|
+
|
|
+ return sprintf(buf, "%d\n", false);
|
|
+}
|
|
+
|
|
+static ssize_t hash_show(struct skl_sysfs_module *modinfo_obj,
|
|
+ struct uuid_attribute *attr, char *buf)
|
|
+{
|
|
+ int ret = 0;
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < DEFAULT_HASH_SHA256_LEN; i++)
|
|
+ ret += sprintf(buf + ret, "%d ",
|
|
+ modinfo_obj->uuid_mod->hash[i]);
|
|
+ ret += sprintf(buf + ret, "\n");
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+
|
|
+static ssize_t id_show(struct skl_sysfs_module *modinfo_obj,
|
|
+ struct uuid_attribute *attr, char *buf)
|
|
+{
|
|
+ return sprintf(buf, "%d\n", modinfo_obj->uuid_mod->id);
|
|
+}
|
|
+
|
|
+static UUID_ATTR_RO(loaded);
|
|
+static UUID_ATTR_RO(hash);
|
|
+static UUID_ATTR_RO(id);
|
|
+
|
|
+static struct attribute *modules_attrs[] = {
|
|
+ &uuid_attr_loaded.attr,
|
|
+ &uuid_attr_hash.attr,
|
|
+ &uuid_attr_id.attr,
|
|
+ NULL,
|
|
+};
|
|
+
|
|
+static const struct attribute_group uuid_group = {
|
|
+ .attrs = modules_attrs,
|
|
+};
|
|
+
|
|
+static void free_uuid_node(struct kobject *kobj,
|
|
+ const struct attribute_group *group)
|
|
+{
|
|
+ if (kobj) {
|
|
+ sysfs_remove_group(kobj, group);
|
|
+ kobject_put(kobj);
|
|
+ }
|
|
+}
|
|
+
|
|
+void skl_module_sysfs_exit(struct skl_sst *ctx)
|
|
+{
|
|
+ struct skl_sysfs_tree *tree = ctx->sysfs_tree;
|
|
+ struct skl_sysfs_module **m;
|
|
+
|
|
+ if (!tree)
|
|
+ return;
|
|
+
|
|
+ if (tree->mod_obj) {
|
|
+ for (m = tree->mod_obj; *m; m++)
|
|
+ free_uuid_node(&(*m)->kobj, &uuid_group);
|
|
+ kfree(tree->mod_obj);
|
|
+ }
|
|
+
|
|
+ if (tree->modules_kobj)
|
|
+ kobject_put(tree->modules_kobj);
|
|
+
|
|
+ if (tree->dsp_kobj)
|
|
+ kobject_put(tree->dsp_kobj);
|
|
+
|
|
+ kfree(tree);
|
|
+ ctx->sysfs_tree = NULL;
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(skl_module_sysfs_exit);
|
|
+
|
|
+int skl_module_sysfs_init(struct skl_sst *ctx, struct kobject *kobj)
|
|
+{
|
|
+ struct uuid_module *module;
|
|
+ struct skl_sysfs_module *modinfo_obj;
|
|
+ char *uuid_name;
|
|
+ int count = 0;
|
|
+ int max_mod = 0;
|
|
+ int ret = 0;
|
|
+
|
|
+ if (list_empty(&ctx->uuid_list))
|
|
+ return 0;
|
|
+
|
|
+ ctx->sysfs_tree = kzalloc(sizeof(*ctx->sysfs_tree), GFP_KERNEL);
|
|
+ if (!ctx->sysfs_tree) {
|
|
+ ret = -ENOMEM;
|
|
+ goto err_sysfs_exit;
|
|
+ }
|
|
+
|
|
+ ctx->sysfs_tree->dsp_kobj = kobject_create_and_add("dsp", kobj);
|
|
+ if (!ctx->sysfs_tree->dsp_kobj)
|
|
+ goto err_sysfs_exit;
|
|
+
|
|
+ ctx->sysfs_tree->modules_kobj = kobject_create_and_add("modules",
|
|
+ ctx->sysfs_tree->dsp_kobj);
|
|
+ if (!ctx->sysfs_tree->modules_kobj)
|
|
+ goto err_sysfs_exit;
|
|
+
|
|
+ list_for_each_entry(module, &ctx->uuid_list, list)
|
|
+ max_mod++;
|
|
+
|
|
+ ctx->sysfs_tree->mod_obj = kcalloc(max_mod + 1,
|
|
+ sizeof(*ctx->sysfs_tree->mod_obj), GFP_KERNEL);
|
|
+ if (!ctx->sysfs_tree->mod_obj) {
|
|
+ ret = -ENOMEM;
|
|
+ goto err_sysfs_exit;
|
|
+ }
|
|
+
|
|
+ list_for_each_entry(module, &ctx->uuid_list, list) {
|
|
+ modinfo_obj = kzalloc(sizeof(*modinfo_obj), GFP_KERNEL);
|
|
+ if (!modinfo_obj) {
|
|
+ ret = -ENOMEM;
|
|
+ goto err_sysfs_exit;
|
|
+ }
|
|
+
|
|
+ uuid_name = kasprintf(GFP_KERNEL, "%pUL", &module->uuid);
|
|
+ ret = kobject_init_and_add(&modinfo_obj->kobj, &uuid_ktype,
|
|
+ ctx->sysfs_tree->modules_kobj, uuid_name);
|
|
+ if (ret < 0)
|
|
+ goto err_sysfs_exit;
|
|
+
|
|
+ ret = sysfs_create_group(&modinfo_obj->kobj, &uuid_group);
|
|
+ if (ret < 0)
|
|
+ goto err_sysfs_exit;
|
|
+
|
|
+ modinfo_obj->uuid_mod = module;
|
|
+ modinfo_obj->module_list = &ctx->dsp->module_list;
|
|
+ modinfo_obj->fw_ops_load_mod =
|
|
+ (ctx->dsp->fw_ops.load_mod == NULL) ? 0 : 1;
|
|
+
|
|
+ ctx->sysfs_tree->mod_obj[count] = modinfo_obj;
|
|
+ count++;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+
|
|
+err_sysfs_exit:
|
|
+ skl_module_sysfs_exit(ctx);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(skl_module_sysfs_init);
|
|
--
|
|
2.19.1
|
|
|