18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#include <linux/device.h>
58c2ecf20Sopenharmony_ci#include <linux/pci.h>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include "ath5k.h"
88c2ecf20Sopenharmony_ci#include "reg.h"
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#define SIMPLE_SHOW_STORE(name, get, set)				\
118c2ecf20Sopenharmony_cistatic ssize_t ath5k_attr_show_##name(struct device *dev,		\
128c2ecf20Sopenharmony_ci			struct device_attribute *attr,			\
138c2ecf20Sopenharmony_ci			char *buf)					\
148c2ecf20Sopenharmony_ci{									\
158c2ecf20Sopenharmony_ci	struct ieee80211_hw *hw = dev_get_drvdata(dev);			\
168c2ecf20Sopenharmony_ci	struct ath5k_hw *ah = hw->priv;				\
178c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%d\n", get);			\
188c2ecf20Sopenharmony_ci}									\
198c2ecf20Sopenharmony_ci									\
208c2ecf20Sopenharmony_cistatic ssize_t ath5k_attr_store_##name(struct device *dev,		\
218c2ecf20Sopenharmony_ci			struct device_attribute *attr,			\
228c2ecf20Sopenharmony_ci			const char *buf, size_t count)			\
238c2ecf20Sopenharmony_ci{									\
248c2ecf20Sopenharmony_ci	struct ieee80211_hw *hw = dev_get_drvdata(dev);			\
258c2ecf20Sopenharmony_ci	struct ath5k_hw *ah = hw->priv;				\
268c2ecf20Sopenharmony_ci	int val, ret;							\
278c2ecf20Sopenharmony_ci									\
288c2ecf20Sopenharmony_ci	ret = kstrtoint(buf, 10, &val);					\
298c2ecf20Sopenharmony_ci	if (ret < 0)							\
308c2ecf20Sopenharmony_ci		return ret;						\
318c2ecf20Sopenharmony_ci	set(ah, val);						\
328c2ecf20Sopenharmony_ci	return count;							\
338c2ecf20Sopenharmony_ci}									\
348c2ecf20Sopenharmony_cistatic DEVICE_ATTR(name, 0644,						\
358c2ecf20Sopenharmony_ci		   ath5k_attr_show_##name, ath5k_attr_store_##name)
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci#define SIMPLE_SHOW(name, get)						\
388c2ecf20Sopenharmony_cistatic ssize_t ath5k_attr_show_##name(struct device *dev,		\
398c2ecf20Sopenharmony_ci			struct device_attribute *attr,			\
408c2ecf20Sopenharmony_ci			char *buf)					\
418c2ecf20Sopenharmony_ci{									\
428c2ecf20Sopenharmony_ci	struct ieee80211_hw *hw = dev_get_drvdata(dev);			\
438c2ecf20Sopenharmony_ci	struct ath5k_hw *ah = hw->priv;				\
448c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%d\n", get);			\
458c2ecf20Sopenharmony_ci}									\
468c2ecf20Sopenharmony_cistatic DEVICE_ATTR(name, 0444, ath5k_attr_show_##name, NULL)
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci/*** ANI ***/
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ciSIMPLE_SHOW_STORE(ani_mode, ah->ani_state.ani_mode, ath5k_ani_init);
518c2ecf20Sopenharmony_ciSIMPLE_SHOW_STORE(noise_immunity_level, ah->ani_state.noise_imm_level,
528c2ecf20Sopenharmony_ci			ath5k_ani_set_noise_immunity_level);
538c2ecf20Sopenharmony_ciSIMPLE_SHOW_STORE(spur_level, ah->ani_state.spur_level,
548c2ecf20Sopenharmony_ci			ath5k_ani_set_spur_immunity_level);
558c2ecf20Sopenharmony_ciSIMPLE_SHOW_STORE(firstep_level, ah->ani_state.firstep_level,
568c2ecf20Sopenharmony_ci			ath5k_ani_set_firstep_level);
578c2ecf20Sopenharmony_ciSIMPLE_SHOW_STORE(ofdm_weak_signal_detection, ah->ani_state.ofdm_weak_sig,
588c2ecf20Sopenharmony_ci			ath5k_ani_set_ofdm_weak_signal_detection);
598c2ecf20Sopenharmony_ciSIMPLE_SHOW_STORE(cck_weak_signal_detection, ah->ani_state.cck_weak_sig,
608c2ecf20Sopenharmony_ci			ath5k_ani_set_cck_weak_signal_detection);
618c2ecf20Sopenharmony_ciSIMPLE_SHOW(spur_level_max, ah->ani_state.max_spur_level);
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_cistatic ssize_t ath5k_attr_show_noise_immunity_level_max(struct device *dev,
648c2ecf20Sopenharmony_ci			struct device_attribute *attr,
658c2ecf20Sopenharmony_ci			char *buf)
668c2ecf20Sopenharmony_ci{
678c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%d\n", ATH5K_ANI_MAX_NOISE_IMM_LVL);
688c2ecf20Sopenharmony_ci}
698c2ecf20Sopenharmony_cistatic DEVICE_ATTR(noise_immunity_level_max, 0444,
708c2ecf20Sopenharmony_ci		   ath5k_attr_show_noise_immunity_level_max, NULL);
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_cistatic ssize_t ath5k_attr_show_firstep_level_max(struct device *dev,
738c2ecf20Sopenharmony_ci			struct device_attribute *attr,
748c2ecf20Sopenharmony_ci			char *buf)
758c2ecf20Sopenharmony_ci{
768c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%d\n", ATH5K_ANI_MAX_FIRSTEP_LVL);
778c2ecf20Sopenharmony_ci}
788c2ecf20Sopenharmony_cistatic DEVICE_ATTR(firstep_level_max, 0444,
798c2ecf20Sopenharmony_ci		   ath5k_attr_show_firstep_level_max, NULL);
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_cistatic struct attribute *ath5k_sysfs_entries_ani[] = {
828c2ecf20Sopenharmony_ci	&dev_attr_ani_mode.attr,
838c2ecf20Sopenharmony_ci	&dev_attr_noise_immunity_level.attr,
848c2ecf20Sopenharmony_ci	&dev_attr_spur_level.attr,
858c2ecf20Sopenharmony_ci	&dev_attr_firstep_level.attr,
868c2ecf20Sopenharmony_ci	&dev_attr_ofdm_weak_signal_detection.attr,
878c2ecf20Sopenharmony_ci	&dev_attr_cck_weak_signal_detection.attr,
888c2ecf20Sopenharmony_ci	&dev_attr_noise_immunity_level_max.attr,
898c2ecf20Sopenharmony_ci	&dev_attr_spur_level_max.attr,
908c2ecf20Sopenharmony_ci	&dev_attr_firstep_level_max.attr,
918c2ecf20Sopenharmony_ci	NULL
928c2ecf20Sopenharmony_ci};
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_cistatic struct attribute_group ath5k_attribute_group_ani = {
958c2ecf20Sopenharmony_ci	.name = "ani",
968c2ecf20Sopenharmony_ci	.attrs = ath5k_sysfs_entries_ani,
978c2ecf20Sopenharmony_ci};
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci/*** register / unregister ***/
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ciint
1038c2ecf20Sopenharmony_ciath5k_sysfs_register(struct ath5k_hw *ah)
1048c2ecf20Sopenharmony_ci{
1058c2ecf20Sopenharmony_ci	struct device *dev = ah->dev;
1068c2ecf20Sopenharmony_ci	int err;
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	err = sysfs_create_group(&dev->kobj, &ath5k_attribute_group_ani);
1098c2ecf20Sopenharmony_ci	if (err) {
1108c2ecf20Sopenharmony_ci		ATH5K_ERR(ah, "failed to create sysfs group\n");
1118c2ecf20Sopenharmony_ci		return err;
1128c2ecf20Sopenharmony_ci	}
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	return 0;
1158c2ecf20Sopenharmony_ci}
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_civoid
1188c2ecf20Sopenharmony_ciath5k_sysfs_unregister(struct ath5k_hw *ah)
1198c2ecf20Sopenharmony_ci{
1208c2ecf20Sopenharmony_ci	struct device *dev = ah->dev;
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci	sysfs_remove_group(&dev->kobj, &ath5k_attribute_group_ani);
1238c2ecf20Sopenharmony_ci}
124