qcacld-3.0: Add sysfs interface for retrieving version information
User-space needs sysfs interface for retrieving version
information for both firmware and driver. Add this new
sysfs interface.
Change-Id: I666aff1868f4d1d954773fae1ae85c1ebd0fdc87
CRs-Fixed: 2153885
diff --git a/Kbuild b/Kbuild
index 7937f99..1fd12bf 100644
--- a/Kbuild
+++ b/Kbuild
@@ -440,6 +440,7 @@
$(HDD_SRC_DIR)/wlan_hdd_request_manager.o \
$(HDD_SRC_DIR)/wlan_hdd_scan.o \
$(HDD_SRC_DIR)/wlan_hdd_softap_tx_rx.o \
+ $(HDD_SRC_DIR)/wlan_hdd_sysfs.o \
$(HDD_SRC_DIR)/wlan_hdd_tx_rx.o \
$(HDD_SRC_DIR)/wlan_hdd_trace.o \
$(HDD_SRC_DIR)/wlan_hdd_wext.o \
diff --git a/core/hdd/inc/wlan_hdd_sysfs.h b/core/hdd/inc/wlan_hdd_sysfs.h
new file mode 100644
index 0000000..8f380a3
--- /dev/null
+++ b/core/hdd/inc/wlan_hdd_sysfs.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ *
+ * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * hdd_sysfs_create_version_interface() - create version interface
+ * @psoc: PSOC ptr
+ *
+ * Return: none
+ */
+void hdd_sysfs_create_version_interface(struct wlan_objmgr_psoc *psoc);
+
+/**
+ * hdd_sysfs_destroy_version_interface() - destroy version interface
+ *
+ * Return: none
+ */
+void hdd_sysfs_destroy_version_interface(void);
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index 77d0b30..e1393c6 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -127,6 +127,7 @@
#include "sme_power_save_api.h"
#include "enet.h"
#include <cdp_txrx_cmn_struct.h>
+#include "wlan_hdd_sysfs.h"
#ifdef CNSS_GENL
#include <net/cnss_nl.h>
@@ -2491,6 +2492,8 @@
hdd_register_policy_manager_callback(
hdd_ctx->hdd_psoc);
+ hdd_sysfs_create_version_interface(hdd_ctx->hdd_psoc);
+
hdd_update_hw_sw_info(hdd_ctx);
hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
hdd_info("Wlan transitioned (now OPENED)");
@@ -11608,6 +11611,9 @@
component_deinit();
dispatcher_deinit();
+
+ hdd_sysfs_destroy_version_interface();
+
hdd_deinit();
pld_deinit();
diff --git a/core/hdd/src/wlan_hdd_sysfs.c b/core/hdd/src/wlan_hdd_sysfs.c
new file mode 100644
index 0000000..3be1303
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_sysfs.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ *
+ * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: wlan_hdd_sysfs.c
+ *
+ * WLAN Host Device Driver implementation
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kobject.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include "wlan_hdd_includes.h"
+#include "wlan_hdd_sysfs.h"
+#include "qwlan_version.h"
+#include "cds_api.h"
+
+#define MAX_PSOC_ID_SIZE 10
+
+#ifdef MULTI_IF_NAME
+#define DRIVER_NAME MULTI_IF_NAME
+#else
+#define DRIVER_NAME "wlan"
+#endif
+
+static struct kobject *wlan_kobject;
+static struct kobject *driver_kobject;
+static struct kobject *fw_kobject;
+static struct kobject *psoc_kobject;
+
+static ssize_t __show_driver_version(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE, QWLAN_VERSIONSTR);
+}
+
+static ssize_t show_driver_version(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ ssize_t ret_val;
+
+ cds_ssr_protect(__func__);
+ ret_val = __show_driver_version(kobj, attr, buf);
+ cds_ssr_unprotect(__func__);
+
+ return ret_val;
+}
+
+static ssize_t __show_fw_version(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ const char *hw_version;
+ uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
+ uint32_t sub_id = 0;
+ struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
+ int ret;
+
+ ret = wlan_hdd_validate_context(hdd_ctx);
+ if (ret) {
+ hdd_err("hdd ctx is invalid");
+ return ret;
+ }
+
+ hdd_debug("Rcvd req for FW version");
+ hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
+ &crmid);
+ sub_id = (hdd_ctx->target_fw_vers_ext & 0xf0000000) >> 28;
+ hw_version = hdd_ctx->target_hw_name;
+
+ return scnprintf(buf, PAGE_SIZE,
+ "FW:%d.%d.%d.%d.%d HW:%s", major_spid,
+ minor_spid, siid, crmid, sub_id,
+ hw_version);
+}
+
+static ssize_t show_fw_version(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ ssize_t ret_val;
+
+ cds_ssr_protect(__func__);
+ ret_val = __show_fw_version(kobj, attr, buf);
+ cds_ssr_unprotect(__func__);
+
+ return ret_val;
+}
+
+static struct kobj_attribute dr_ver_attribute =
+ __ATTR(driver_version, 0440, show_driver_version, NULL);
+static struct kobj_attribute fw_ver_attribute =
+ __ATTR(version, 0440, show_fw_version, NULL);
+
+void hdd_sysfs_create_version_interface(struct wlan_objmgr_psoc *psoc)
+{
+ int error = 0;
+ uint32_t psoc_id;
+ char buf[MAX_PSOC_ID_SIZE];
+
+ wlan_kobject = kobject_create_and_add("wlan", kernel_kobj);
+ if (!wlan_kobject) {
+ hdd_err("could not allocate wlan kobject");
+ return;
+ }
+
+ driver_kobject = kobject_create_and_add(DRIVER_NAME, wlan_kobject);
+ if (!driver_kobject) {
+ hdd_err("could not allocate driver kobject");
+ goto free_wlan_kobj;
+ }
+
+ error = sysfs_create_file(driver_kobject, &dr_ver_attribute.attr);
+ if (error) {
+ hdd_err("could not create driver sysfs file");
+ goto free_drv_kobj;
+ }
+
+ fw_kobject = kobject_create_and_add("fw", driver_kobject);
+ if (!fw_kobject) {
+ hdd_err("could not allocate fw kobject");
+ goto free_fw_kobj;
+ }
+
+ psoc_id = wlan_psoc_get_nif_phy_version(psoc);
+ scnprintf(buf, PAGE_SIZE, "%d", psoc_id);
+
+ psoc_kobject = kobject_create_and_add(buf, fw_kobject);
+ if (!psoc_kobject) {
+ hdd_err("could not allocate psoc kobject");
+ goto free_fw_kobj;
+ }
+
+ error = sysfs_create_file(psoc_kobject, &fw_ver_attribute.attr);
+ if (error) {
+ hdd_err("could not create fw sysfs file");
+ goto free_psoc_kobj;
+ }
+
+ return;
+
+free_psoc_kobj:
+ kobject_put(psoc_kobject);
+ psoc_kobject = NULL;
+
+free_fw_kobj:
+ kobject_put(fw_kobject);
+ fw_kobject = NULL;
+
+free_drv_kobj:
+ kobject_put(driver_kobject);
+ driver_kobject = NULL;
+
+free_wlan_kobj:
+ kobject_put(wlan_kobject);
+ wlan_kobject = NULL;
+}
+
+void hdd_sysfs_destroy_version_interface(void)
+{
+ if (psoc_kobject) {
+ kobject_put(psoc_kobject);
+ psoc_kobject = NULL;
+ kobject_put(fw_kobject);
+ fw_kobject = NULL;
+ kobject_put(driver_kobject);
+ driver_kobject = NULL;
+ kobject_put(wlan_kobject);
+ wlan_kobject = NULL;
+ }
+}