1 /* 2 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. 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_get_freq_for_pwr.c 19 * 20 * implementation for creating sysfs file valid_freq 21 */ 22 23 #include <wlan_hdd_includes.h> 24 #include "osif_vdev_sync.h" 25 #include <wlan_hdd_sysfs.h> 26 #include "wlan_hdd_sysfs_get_freq_for_pwr.h" 27 #include "osif_psoc_sync.h" 28 #include "reg_services_public_struct.h" 29 #include <wma_api.h> 30 31 static ssize_t __hdd_sysfs_power_level_store(struct hdd_context * hdd_ctx,char const * buf,size_t count)32 __hdd_sysfs_power_level_store(struct hdd_context *hdd_ctx, 33 char const *buf, size_t count) 34 { 35 char buf_local[MAX_SYSFS_USER_COMMAND_SIZE_LENGTH + 1]; 36 char *sptr, *token; 37 int ret; 38 39 ret = wlan_hdd_validate_context(hdd_ctx); 40 if (ret != 0) 41 return ret; 42 43 if (!wlan_hdd_validate_modules_state(hdd_ctx)) 44 return -EINVAL; 45 46 ret = hdd_sysfs_validate_and_copy_buf(buf_local, sizeof(buf_local), 47 buf, count); 48 if (ret) { 49 hdd_err_rl("invalid input"); 50 return ret; 51 } 52 sptr = buf_local; 53 token = strsep(&sptr, " "); 54 if (!token) 55 return -EINVAL; 56 57 if (!strncasecmp(token, "VLP", strlen("VLP"))) 58 hdd_ctx->power_type = REG_VERY_LOW_POWER_AP; 59 else if (!strncasecmp(token, "LP", strlen("LP"))) 60 hdd_ctx->power_type = REG_INDOOR_AP; 61 else if (!strncasecmp(token, "SP", strlen("SP"))) 62 hdd_ctx->power_type = REG_STANDARD_POWER_AP; 63 else 64 hdd_ctx->power_type = REG_MAX_SUPP_AP_TYPE; 65 66 hdd_debug("power level %s(%d)", token, 67 hdd_ctx->power_type); 68 69 return count; 70 } 71 72 static ssize_t wlan_hdd_sysfs_power_store(struct kobject * kobj,struct kobj_attribute * attr,char const * buf,size_t count)73 wlan_hdd_sysfs_power_store(struct kobject *kobj, 74 struct kobj_attribute *attr, 75 char const *buf, size_t count) 76 { 77 struct osif_psoc_sync *psoc_sync; 78 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); 79 ssize_t err_size; 80 81 if (wlan_hdd_validate_context(hdd_ctx)) 82 return 0; 83 84 err_size = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy), 85 &psoc_sync); 86 if (err_size) 87 return err_size; 88 89 err_size = __hdd_sysfs_power_level_store(hdd_ctx, buf, count); 90 osif_psoc_sync_op_stop(psoc_sync); 91 92 return err_size; 93 } 94 95 static ssize_t __wlan_hdd_sysfs_freq_show(struct hdd_context * hdd_ctx,struct kobj_attribute * attr,char * buf)96 __wlan_hdd_sysfs_freq_show(struct hdd_context *hdd_ctx, 97 struct kobj_attribute *attr, char *buf) 98 { 99 int ret = 0; 100 struct regulatory_channel *chan_list; 101 uint32_t len_6g = 102 NUM_6GHZ_CHANNELS * sizeof(struct regulatory_channel); 103 QDF_STATUS status; 104 uint32_t i; 105 106 ret = wlan_hdd_validate_context(hdd_ctx); 107 if (ret != 0) 108 return ret; 109 110 if (!wlan_hdd_validate_modules_state(hdd_ctx)) 111 return -EINVAL; 112 113 ret = scnprintf(buf, PAGE_SIZE, "freq list for power type %s\n", 114 wlan_reg_get_power_string(hdd_ctx->power_type)); 115 116 if (!strcmp(wlan_reg_get_power_string(hdd_ctx->power_type), "INVALID")) 117 return -EINVAL; 118 119 chan_list = qdf_mem_malloc(len_6g); 120 if (!chan_list) 121 return -ENOMEM; 122 123 status = wlan_reg_get_6g_ap_master_chan_list( 124 hdd_ctx->pdev, 125 hdd_ctx->power_type, 126 chan_list); 127 128 for (i = 0; i < NUM_6GHZ_CHANNELS; i++) { 129 if ((chan_list[i].state != CHANNEL_STATE_DISABLE) && 130 !(chan_list[i].chan_flags & REGULATORY_CHAN_DISABLED)) { 131 if ((PAGE_SIZE - ret) <= 0) 132 goto err; 133 ret += scnprintf(buf + ret, PAGE_SIZE - ret, 134 "%d ", chan_list[i].center_freq); 135 } 136 } 137 138 err: 139 qdf_mem_free(chan_list); 140 return ret; 141 } 142 wlan_hdd_sysfs_freq_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)143 static ssize_t wlan_hdd_sysfs_freq_show(struct kobject *kobj, 144 struct kobj_attribute *attr, 145 char *buf) 146 { 147 struct osif_psoc_sync *psoc_sync; 148 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); 149 ssize_t err_size; 150 int ret; 151 152 ret = wlan_hdd_validate_context(hdd_ctx); 153 if (ret != 0) 154 return ret; 155 156 err_size = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy), 157 &psoc_sync); 158 if (err_size) 159 return err_size; 160 161 err_size = __wlan_hdd_sysfs_freq_show(hdd_ctx, attr, buf); 162 163 osif_psoc_sync_op_stop(psoc_sync); 164 165 return err_size; 166 } 167 168 static struct kobj_attribute valid_freq_attribute = 169 __ATTR(valid_freq, 0664, wlan_hdd_sysfs_freq_show, wlan_hdd_sysfs_power_store); 170 hdd_sysfs_get_valid_freq_for_power_create(struct kobject * driver_kobject)171 int hdd_sysfs_get_valid_freq_for_power_create(struct kobject *driver_kobject) 172 { 173 int error; 174 175 error = sysfs_create_file(driver_kobject, &valid_freq_attribute.attr); 176 if (error) 177 hdd_err("could not create valid_freq sysfs file"); 178 179 return error; 180 } 181 182 void hdd_sysfs_get_valid_freq_for_power_destroy(struct kobject * driver_kobject)183 hdd_sysfs_get_valid_freq_for_power_destroy(struct kobject *driver_kobject) 184 { 185 if (!driver_kobject) { 186 hdd_err("could not get driver kobject!"); 187 return; 188 } 189 sysfs_remove_file(driver_kobject, &valid_freq_attribute.attr); 190 } 191