1 /* 2 * Copyright (c) 2021, The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 /** 18 * DOC: wlan_hdd_sysfs_txrx_stats_console.c 19 * 20 * implementation for creating sysfs files: 21 * 22 * txrx_stats 23 */ 24 25 #include <wlan_hdd_includes.h> 26 #include "osif_psoc_sync.h" 27 #include <wlan_hdd_sysfs.h> 28 #include <wlan_hdd_sysfs_txrx_stats_console.h> 29 #include <cds_api.h> 30 #include <qdf_status.h> 31 32 #ifdef WLAN_SYSFS_DP_STATS 33 34 #define HDD_WLAN_SYSFS_TXRX_STATS_USER_CMD_SIZE (10) 35 #define SYSFS_INPUT_BUF_SIZE PAGE_SIZE 36 37 /* 38 * __hdd_wlan_txrx_stats_store() - Calls into dp layer to 39 * update the sysfs config values. 40 * @hdd_ctx: hdd context 41 * @buf: input buffer from user space 42 * @count: input buffer size 43 * 44 * Return: Return the size of input buffer. 45 */ 46 static ssize_t __hdd_wlan_txrx_stats_store(struct hdd_context * hdd_ctx,const char * buf,size_t count)47 __hdd_wlan_txrx_stats_store(struct hdd_context *hdd_ctx, 48 const char *buf, size_t count) 49 { 50 char buf_local[HDD_WLAN_SYSFS_TXRX_STATS_USER_CMD_SIZE + 1]; 51 char *sptr, *token; 52 uint32_t stat_type_requested; 53 uint32_t mac_id; 54 int ret; 55 ol_txrx_soc_handle soc = cds_get_context(QDF_MODULE_ID_SOC); 56 57 if (!soc) { 58 hdd_err_rl("soc is NULL"); 59 return -EINVAL; 60 } 61 62 if (count > HDD_WLAN_SYSFS_TXRX_STATS_USER_CMD_SIZE) 63 return -EINVAL; 64 65 if (!wlan_hdd_validate_modules_state(hdd_ctx)) 66 return -EINVAL; 67 68 ret = hdd_sysfs_validate_and_copy_buf(buf_local, sizeof(buf_local), 69 buf, count); 70 71 if (ret) 72 return -EINVAL; 73 74 sptr = buf_local; 75 /* get mac id */ 76 token = strsep(&sptr, " "); 77 if (!token) 78 return -EINVAL; 79 if (kstrtou32(token, 0, &stat_type_requested)) 80 return -EINVAL; 81 82 /* get stat type requested */ 83 token = strsep(&sptr, " "); 84 if (!token) 85 return -EINVAL; 86 if (kstrtou32(token, 0, &mac_id)) 87 return -EINVAL; 88 89 if (!soc->ops->cmn_drv_ops->txrx_sysfs_set_stat_type) { 90 hdd_err("txrx_sysfs_set_stat_type is NULL"); 91 return -EINVAL; 92 } 93 94 soc->ops->cmn_drv_ops->txrx_sysfs_set_stat_type(soc, 95 stat_type_requested, 96 mac_id); 97 98 return count; 99 } 100 101 /* 102 * __hdd_wlan_txrx_stats_show() - Calls into dp to fill stats. 103 * @buf: output buffer 104 * 105 * Return: output buffer size. 106 */ 107 static ssize_t __hdd_wlan_txrx_stats_show(char * buf)108 __hdd_wlan_txrx_stats_show(char *buf) 109 { 110 uint32_t size_of_output = 0; 111 ol_txrx_soc_handle soc = cds_get_context(QDF_MODULE_ID_SOC); 112 113 if (!soc) { 114 hdd_err_rl("hdd dp_soc cds_get_context returned NULL"); 115 return -EINVAL; 116 } 117 118 if (!soc->ops->cmn_drv_ops->txrx_sysfs_fill_stats) { 119 hdd_err_rl("txrx_sysfs_fill_stats is NULL"); 120 return -EINVAL; 121 } 122 soc->ops->cmn_drv_ops->txrx_sysfs_fill_stats(soc, 123 buf, 124 SYSFS_INPUT_BUF_SIZE); 125 size_of_output = strlen(buf); 126 return size_of_output; 127 } 128 129 /* 130 * hdd_sysfs_dp_txrx_stats_show() - Registered as sysfs show function. 131 * @kobj: kernel object 132 * @att: kobject attribute 133 * @buf: output buffer to be filled 134 * 135 * Return: Returns the length of the output buffer. 136 */ 137 static ssize_t hdd_sysfs_dp_txrx_stats_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)138 hdd_sysfs_dp_txrx_stats_show(struct kobject *kobj, 139 struct kobj_attribute *attr, 140 char *buf) 141 { 142 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); 143 struct osif_psoc_sync *psoc_sync = NULL; 144 ssize_t length = 0; 145 ssize_t errno = 0; 146 147 errno = wlan_hdd_validate_context(hdd_ctx); 148 if (errno) 149 return errno; 150 151 errno = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy), &psoc_sync); 152 if (errno) 153 return errno; 154 155 length = __hdd_wlan_txrx_stats_show(buf); 156 157 osif_psoc_sync_op_stop(psoc_sync); 158 159 return length; 160 } 161 162 /* 163 * hdd_sysfs_dp_txrx_stats_store() - Registered as sysfs write function. 164 * @kobj: kernel object 165 * @att: kobject attribute 166 * @buf: input buffer from user space 167 * @count: size of the input buffer 168 * 169 * Return: Returns the length of the input buffer. 170 */ 171 static ssize_t hdd_sysfs_dp_txrx_stats_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t count)172 hdd_sysfs_dp_txrx_stats_store(struct kobject *kobj, 173 struct kobj_attribute *attr, 174 const char *buf, 175 size_t count) 176 { 177 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); 178 struct osif_psoc_sync *psoc_sync = NULL; 179 ssize_t errno = 0; 180 181 errno = wlan_hdd_validate_context(hdd_ctx); 182 if (errno) 183 return errno; 184 185 errno = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy), &psoc_sync); 186 if (errno) 187 return errno; 188 189 errno = __hdd_wlan_txrx_stats_store(hdd_ctx, buf, count); 190 191 osif_psoc_sync_op_stop(psoc_sync); 192 193 return errno; 194 } 195 196 static struct kobj_attribute dp_txrx_stats_attribute = 197 __ATTR(txrx_stats, 0664, hdd_sysfs_dp_txrx_stats_show, 198 hdd_sysfs_dp_txrx_stats_store); 199 200 /* 201 * hdd_sysfs_dp_txrx_stats_sysfs_create() - Initialize sysfs file. 202 * @driver_kobject: driver kobject 203 * 204 * Return: return sysfs int val. 205 */ hdd_sysfs_dp_txrx_stats_sysfs_create(struct kobject * driver_kobject)206 int hdd_sysfs_dp_txrx_stats_sysfs_create(struct kobject *driver_kobject) 207 { 208 int error = 0; 209 210 if (!driver_kobject) { 211 hdd_err("could not get driver kobject"); 212 return -EINVAL; 213 } 214 215 error = sysfs_create_file(driver_kobject, 216 &dp_txrx_stats_attribute.attr); 217 218 if (error) 219 hdd_err("failed to create txrx_stats sysfs file"); 220 221 return error; 222 } 223 224 /* 225 * hdd_sysfs_dp_txrx_stats_sysfs_destroy() - Sysfs deinitialize. 226 * @driver_kobject: driver kobject 227 * 228 * Return: void 229 */ 230 void hdd_sysfs_dp_txrx_stats_sysfs_destroy(struct kobject * driver_kobject)231 hdd_sysfs_dp_txrx_stats_sysfs_destroy(struct kobject *driver_kobject) 232 { 233 if (!driver_kobject) { 234 hdd_err("failed to get driver kobject"); 235 return; 236 } 237 238 sysfs_remove_file(driver_kobject, &dp_txrx_stats_attribute.attr); 239 } 240 #endif /* WLAN_SYSFS_DP_STATS */ 241