| /* |
| * 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" |
| |
| #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; |
| hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); |
| |
| if (!hdd_ctx) { |
| hdd_err("hdd ctx is NULL"); |
| return 0; |
| } |
| |
| 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(void) |
| { |
| int error = 0; |
| |
| wlan_kobject = kobject_create_and_add("wifi", 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_kobject = kobject_create_and_add("0", 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; |
| } |
| } |