Am 14.04.2014 20:29, schrieb Ashish Patro: > --- > drivers/net/wireless/ath/ath9k/Makefile | 2 +- > drivers/net/wireless/ath/ath9k/ar9002_phy.c | 10 +- > drivers/net/wireless/ath/ath9k/htc.h | 13 + > drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 5 +- > drivers/net/wireless/ath/ath9k/htc_drv_init.c | 8 + > drivers/net/wireless/ath/ath9k/htc_drv_main.c | 81 +++++ > drivers/net/wireless/ath/ath9k/htc_drv_spectral.c | 358 > +++++++++++++++++++++ > drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 17 + > 8 files changed, 490 insertions(+), 4 deletions(-) > create mode 100644 drivers/net/wireless/ath/ath9k/htc_drv_spectral.c > > diff --git a/drivers/net/wireless/ath/ath9k/Makefile > b/drivers/net/wireless/ath/ath9k/Makefile > index 613bf30..aaa5a34 100644 > --- a/drivers/net/wireless/ath/ath9k/Makefile > +++ b/drivers/net/wireless/ath/ath9k/Makefile > @@ -65,6 +65,6 @@ ath9k_htc-y += htc_hst.o \ > htc_drv_init.o \ > htc_drv_gpio.o > > -ath9k_htc-$(CONFIG_ATH9K_HTC_DEBUGFS) += htc_drv_debug.o > +ath9k_htc-$(CONFIG_ATH9K_HTC_DEBUGFS) += htc_drv_debug.o htc_drv_spectral.o > > obj-$(CONFIG_ATH9K_HTC) += ath9k_htc.o > diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c > b/drivers/net/wireless/ath/ath9k/ar9002_phy.c > index 9a2afa2..e9eb794 100644 > --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c > +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c > @@ -641,11 +641,17 @@ static void ar9002_hw_spectral_scan_config(struct > ath_hw *ah, > /* on AR92xx, the highest bit of count will make the the chip send > * spectral samples endlessly. Check if this really was intended, > * and fix otherwise. > + * > + * For AR9271 chipsets, set count = 0 using the debugfs mechanism. > */ > count = param->count; > - if (param->endless) > + if (param->endless) { > count = 0x80; > - else if (count & 0x80) > + > + if (AR_SREV_9271(ah)) { > + count = 0; > + }
Please fix coding style. > + } else if (count & 0x80) > count = 0x7f; > > REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN, > diff --git a/drivers/net/wireless/ath/ath9k/htc.h > b/drivers/net/wireless/ath/ath9k/htc.h > index dab1f0c..178eb99 100644 > --- a/drivers/net/wireless/ath/ath9k/htc.h > +++ b/drivers/net/wireless/ath/ath9k/htc.h > @@ -31,6 +31,7 @@ > #include "htc_hst.h" > #include "hif_usb.h" > #include "wmi.h" > +#include "spectral.h" Should be common-sprectral.h > > #define ATH_STA_SHORT_CALINTERVAL 1000 /* 1 second */ > #define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */ > @@ -529,6 +530,11 @@ struct ath9k_htc_priv { > struct ath9k_debug debug; > #endif > struct mutex mutex; > + > + /* relay(fs) channel for spectral scan */ > + struct rchan *rfs_chan_spec_scan; > + enum spectral_mode spectral_mode; > + struct ath_spec_scan spec_config; > }; > > static inline void ath_read_cachesize(struct ath_common *common, int *csz) > @@ -636,4 +642,11 @@ int ath9k_htc_init_debug(struct ath_hw *ah); > static inline int ath9k_htc_init_debug(struct ath_hw *ah) { return 0; }; > #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ > > +void ath9k_htc_spectral_init_debug(struct ath9k_htc_priv *priv); > +void ath9k_htc_spectral_deinit_debug(struct ath9k_htc_priv *priv); > + > +void ath9k_htc_spectral_scan_trigger(struct ieee80211_hw *hw); > +int ath9k_htc_spectral_scan_config(struct ieee80211_hw *hw, > + enum spectral_mode spectral_mode); > + > #endif /* HTC_H */ > diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c > b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c > index fb071ee..00d8905 100644 > --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c > +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c > @@ -992,7 +992,10 @@ int ath9k_htc_init_debug(struct ath_hw *ah) > priv->hw->wiphy->debugfsdir); > if (!priv->debug.debugfs_phy) > return -ENOMEM; > - > + > + /* Initialize the debugFS files for the spectral scans */ > + ath9k_htc_spectral_init_debug(priv); > + > debugfs_create_file("tgt_int_stats", S_IRUSR, priv->debug.debugfs_phy, > priv, &fops_tgt_int_stats); > debugfs_create_file("tgt_tx_stats", S_IRUSR, priv->debug.debugfs_phy, > diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c > b/drivers/net/wireless/ath/ath9k/htc_drv_init.c > index 8a3bd5f..71a80ba 100644 > --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c > +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c > @@ -449,6 +449,14 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv) > > common->last_rssi = ATH_RSSI_DUMMY_MARKER; > priv->ah->opmode = NL80211_IFTYPE_STATION; > + > + priv->spec_config.enabled = 0; > + /* Set false for AR9271. */ > + priv->spec_config.short_repeat = false; > + priv->spec_config.count = 8; > + priv->spec_config.endless = false; > + priv->spec_config.period = 18; > + priv->spec_config.fft_period = 0x02; > } > > static int ath9k_init_priv(struct ath9k_htc_priv *priv, > diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c > b/drivers/net/wireless/ath/ath9k/htc_drv_main.c > index f46cd02..051ffa7 100644 > --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c > +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c > @@ -310,6 +310,11 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv > *priv, > > mod_timer(&priv->tx.cleanup_timer, > jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); > + > + /* perform spectral scan if requested. */ > + if (test_bit(ATH_OP_SCANNING, &priv->op_flags) && > + priv->spectral_mode == SPECTRAL_CHANSCAN) > + ath9k_htc_spectral_scan_trigger(hw); > > err: > ath9k_htc_ps_restore(priv); > @@ -1158,6 +1163,82 @@ static void ath9k_htc_remove_interface(struct > ieee80211_hw *hw, > mutex_unlock(&priv->mutex); > } > > +/* Start generating the spectral scans. */ > +void ath9k_htc_spectral_scan_trigger(struct ieee80211_hw *hw) > +{ > + struct ath9k_htc_priv *priv = hw->priv; > + struct ath_hw *ah = priv->ah; > + struct ath_common *common = ath9k_hw_common(ah); > + u32 rxfilter; > + > + /* TODO: Is this condition required? > + if (config_enabled(CONFIG_ATH9K_TX99)) > + return; > + */ you can remove it. ath9k_htc do not have dependencies on TX99. > + if (!ath9k_hw_ops(ah)->spectral_scan_trigger) { > + ath_err(common, "spectrum analyzer not implemented on this > hardware\n"); > + return; > + } > + > + ath9k_htc_ps_wakeup(priv); > + rxfilter = ath9k_hw_getrxfilter(ah); > + ath9k_hw_setrxfilter(ah, rxfilter | > + ATH9K_RX_FILTER_PHYRADAR | > + ATH9K_RX_FILTER_PHYERR); > + > + /* TODO: usually this should not be neccesary, but for some reason > + * (or in some mode?) the trigger must be called after the > + * configuration, otherwise the register will have its values reset > + * (on my ar9220 to value 0x01002310) > + */ > + ath9k_htc_spectral_scan_config(hw, priv->spectral_mode); > + ath9k_hw_ops(ah)->spectral_scan_trigger(ah); > + ath9k_htc_ps_restore(priv); > +} > + > +/* Configure the status of the spectral scan feature. */ > +int ath9k_htc_spectral_scan_config(struct ieee80211_hw *hw, > + enum spectral_mode spectral_mode) > +{ > + struct ath9k_htc_priv *priv = hw->priv; > + struct ath_hw *ah = priv->ah; > + struct ath_common *common = ath9k_hw_common(ah); > + > + if (!ath9k_hw_ops(ah)->spectral_scan_trigger) { > + ath_err(common, "spectrum analyzer not implemented on this > hardware\n"); > + return -1; > + } > + > + switch (spectral_mode) { > + case SPECTRAL_DISABLED: > + priv->spec_config.enabled = 0; > + break; > + case SPECTRAL_BACKGROUND: > + /* send endless samples. > + */ > + priv->spec_config.endless = 1; > + priv->spec_config.enabled = 1; > + break; > + case SPECTRAL_CHANSCAN: > + case SPECTRAL_MANUAL: > + priv->spec_config.endless = 0; > + priv->spec_config.enabled = 1; > + break; > + default: > + return -1; > + } > + > + ath9k_htc_ps_wakeup(priv); > + ath9k_hw_ops(ah)->spectral_scan_config(ah, &priv->spec_config); > + ath9k_htc_ps_restore(priv); > + > + priv->spectral_mode = spectral_mode; > + > + return 0; > +} > + > + > static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) > { > struct ath9k_htc_priv *priv = hw->priv; > diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_spectral.c > b/drivers/net/wireless/ath/ath9k/htc_drv_spectral.c > new file mode 100644 > index 0000000..d6a0894 > --- /dev/null > +++ b/drivers/net/wireless/ath/ath9k/htc_drv_spectral.c > @@ -0,0 +1,358 @@ > +/* > + * Copyright (c) 2013 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. > + */ > + > +#include <linux/relay.h> > +#include "htc.h" > + > +/*********************/ > +/* spectral_scan_ctl */ > +/*********************/ > + > +static ssize_t read_file_spec_scan_ctl(struct file *file, char __user > *user_buf, > + size_t count, loff_t *ppos) > +{ > + struct ath9k_htc_priv *priv = file->private_data; > + char *mode = ""; > + unsigned int len; > + > + switch (priv->spectral_mode) { > + case SPECTRAL_DISABLED: > + mode = "disable"; > + break; > + case SPECTRAL_BACKGROUND: > + mode = "background"; > + break; > + case SPECTRAL_CHANSCAN: > + mode = "chanscan"; > + break; > + case SPECTRAL_MANUAL: > + mode = "manual"; > + break; > + } > + len = strlen(mode); > + return simple_read_from_buffer(user_buf, count, ppos, mode, len); > +} > + > +static ssize_t write_file_spec_scan_ctl(struct file *file, > + const char __user *user_buf, > + size_t count, loff_t *ppos) > +{ > + struct ath9k_htc_priv *priv = file->private_data; > + struct ath_common *common = ath9k_hw_common(priv->ah); > + char buf[32]; > + ssize_t len; > + > + /* TODO: Is it required for ath9k_htc?? > + if (config_enabled(CONFIG_ATH9K_TX99)) > + return -EOPNOTSUPP; > + */ Can be removed. > + len = min(count, sizeof(buf) - 1); > + if (copy_from_user(buf, user_buf, len)) > + return -EFAULT; > + > + buf[len] = '\0'; > + > + if (strncmp("trigger", buf, 7) == 0) { > + ath9k_htc_spectral_scan_trigger(priv->hw); > + } else if (strncmp("background", buf, 9) == 0) { > + ath9k_htc_spectral_scan_config(priv->hw, SPECTRAL_BACKGROUND); > + ath_dbg(common, CONFIG, "spectral scan: background mode > enabled\n"); > + } else if (strncmp("chanscan", buf, 8) == 0) { > + ath9k_htc_spectral_scan_config(priv->hw, SPECTRAL_CHANSCAN); > + ath_dbg(common, CONFIG, "spectral scan: channel scan mode > enabled\n"); > + } else if (strncmp("manual", buf, 6) == 0) { > + ath9k_htc_spectral_scan_config(priv->hw, SPECTRAL_MANUAL); > + ath_dbg(common, CONFIG, "spectral scan: manual mode enabled\n"); > + } else if (strncmp("disable", buf, 7) == 0) { > + ath9k_htc_spectral_scan_config(priv->hw, SPECTRAL_DISABLED); > + ath_dbg(common, CONFIG, "spectral scan: disabled\n"); > + } else { > + return -EINVAL; > + } > + > + return count; > +} > + > +static const struct file_operations fops_spec_scan_ctl = { > + .read = read_file_spec_scan_ctl, > + .write = write_file_spec_scan_ctl, > + .open = simple_open, > + .owner = THIS_MODULE, > + .llseek = default_llseek, > +}; > + > +/*************************/ > +/* spectral_short_repeat */ > +/*************************/ > + > +static ssize_t read_file_spectral_short_repeat(struct file *file, > + char __user *user_buf, > + size_t count, loff_t *ppos) > +{ > + struct ath9k_htc_priv *priv = file->private_data; > + char buf[32]; > + unsigned int len; > + > + len = sprintf(buf, "%d\n", priv->spec_config.short_repeat); > + return simple_read_from_buffer(user_buf, count, ppos, buf, len); > +} > + > +static ssize_t write_file_spectral_short_repeat(struct file *file, > + const char __user *user_buf, > + size_t count, loff_t *ppos) > +{ > + struct ath9k_htc_priv *priv = file->private_data; > + unsigned long val; > + char buf[32]; > + ssize_t len; > + > + len = min(count, sizeof(buf) - 1); > + if (copy_from_user(buf, user_buf, len)) > + return -EFAULT; > + > + buf[len] = '\0'; > + if (kstrtoul(buf, 0, &val)) > + return -EINVAL; > + > + if (val < 0 || val > 1) > + return -EINVAL; > + > + priv->spec_config.short_repeat = val; > + return count; > +} > + > +static const struct file_operations fops_spectral_short_repeat = { > + .read = read_file_spectral_short_repeat, > + .write = write_file_spectral_short_repeat, > + .open = simple_open, > + .owner = THIS_MODULE, > + .llseek = default_llseek, > +}; > + > +/******************/ > +/* spectral_count */ > +/******************/ > + > +static ssize_t read_file_spectral_count(struct file *file, > + char __user *user_buf, > + size_t count, loff_t *ppos) > +{ > + struct ath9k_htc_priv *priv = file->private_data; > + char buf[32]; > + unsigned int len; > + > + len = sprintf(buf, "%d\n", priv->spec_config.count); > + return simple_read_from_buffer(user_buf, count, ppos, buf, len); > +} > + > +static ssize_t write_file_spectral_count(struct file *file, > + const char __user *user_buf, > + size_t count, loff_t *ppos) > +{ > + struct ath9k_htc_priv *priv = file->private_data; > + unsigned long val; > + char buf[32]; > + ssize_t len; > + > + len = min(count, sizeof(buf) - 1); > + if (copy_from_user(buf, user_buf, len)) > + return -EFAULT; > + > + buf[len] = '\0'; > + if (kstrtoul(buf, 0, &val)) > + return -EINVAL; > + > + if (val < 0 || val > 255) > + return -EINVAL; > + > + priv->spec_config.count = val; > + return count; > +} > + > +static const struct file_operations fops_spectral_count = { > + .read = read_file_spectral_count, > + .write = write_file_spectral_count, > + .open = simple_open, > + .owner = THIS_MODULE, > + .llseek = default_llseek, > +}; > + > +/*******************/ > +/* spectral_period */ > +/*******************/ > + > +static ssize_t read_file_spectral_period(struct file *file, > + char __user *user_buf, > + size_t count, loff_t *ppos) > +{ > + struct ath9k_htc_priv *priv = file->private_data; > + char buf[32]; > + unsigned int len; > + > + len = sprintf(buf, "%d\n", priv->spec_config.period); > + return simple_read_from_buffer(user_buf, count, ppos, buf, len); > +} > + > +static ssize_t write_file_spectral_period(struct file *file, > + const char __user *user_buf, > + size_t count, loff_t *ppos) > +{ > + struct ath9k_htc_priv *priv = file->private_data; > + unsigned long val; > + char buf[32]; > + ssize_t len; > + > + len = min(count, sizeof(buf) - 1); > + if (copy_from_user(buf, user_buf, len)) > + return -EFAULT; > + > + buf[len] = '\0'; > + if (kstrtoul(buf, 0, &val)) > + return -EINVAL; > + > + if (val < 0 || val > 255) > + return -EINVAL; > + > + priv->spec_config.period = val; > + return count; > +} > + > +static const struct file_operations fops_spectral_period = { > + .read = read_file_spectral_period, > + .write = write_file_spectral_period, > + .open = simple_open, > + .owner = THIS_MODULE, > + .llseek = default_llseek, > +}; > + > +/***********************/ > +/* spectral_fft_period */ > +/***********************/ > + > +static ssize_t read_file_spectral_fft_period(struct file *file, > + char __user *user_buf, > + size_t count, loff_t *ppos) > +{ > + struct ath9k_htc_priv *priv = file->private_data; > + char buf[32]; > + unsigned int len; > + > + len = sprintf(buf, "%d\n", priv->spec_config.fft_period); > + return simple_read_from_buffer(user_buf, count, ppos, buf, len); > +} > + > +static ssize_t write_file_spectral_fft_period(struct file *file, > + const char __user *user_buf, > + size_t count, loff_t *ppos) > +{ > + struct ath9k_htc_priv *priv = file->private_data; > + unsigned long val; > + char buf[32]; > + ssize_t len; > + > + len = min(count, sizeof(buf) - 1); > + if (copy_from_user(buf, user_buf, len)) > + return -EFAULT; > + > + buf[len] = '\0'; > + if (kstrtoul(buf, 0, &val)) > + return -EINVAL; > + > + if (val < 0 || val > 15) > + return -EINVAL; > + > + priv->spec_config.fft_period = val; > + return count; > +} > + > +static const struct file_operations fops_spectral_fft_period = { > + .read = read_file_spectral_fft_period, > + .write = write_file_spectral_fft_period, > + .open = simple_open, > + .owner = THIS_MODULE, > + .llseek = default_llseek, > +}; > + > +/*******************/ > +/* Relay interface */ > +/*******************/ > + > +static struct dentry *create_buf_file_handler(const char *filename, > + struct dentry *parent, > + umode_t mode, > + struct rchan_buf *buf, > + int *is_global) > +{ > + struct dentry *buf_file; > + > + buf_file = debugfs_create_file(filename, mode, parent, buf, > + &relay_file_operations); > + *is_global = 1; > + return buf_file; > +} > + > +static int remove_buf_file_handler(struct dentry *dentry) > +{ > + debugfs_remove(dentry); > + > + return 0; > +} > + > +static struct rchan_callbacks rfs_spec_scan_cb = { > + .create_buf_file = create_buf_file_handler, > + .remove_buf_file = remove_buf_file_handler, > +}; > + > +/*********************/ > +/* Debug Init/Deinit */ > +/*********************/ > + > +void ath9k_htc_spectral_deinit_debug(struct ath9k_htc_priv *priv) > +{ > + if (config_enabled(CONFIG_ATH9K_DEBUGFS) && priv->rfs_chan_spec_scan) { > + relay_close(priv->rfs_chan_spec_scan); > + priv->rfs_chan_spec_scan = NULL; > + } > +} > + > +void ath9k_htc_spectral_init_debug(struct ath9k_htc_priv *priv) > +{ > + priv->rfs_chan_spec_scan = relay_open("spectral_scan", > + priv->debug.debugfs_phy, > + 1024, 256, &rfs_spec_scan_cb, > + NULL); > + debugfs_create_file("spectral_scan_ctl", > + S_IRUSR | S_IWUSR, > + priv->debug.debugfs_phy, priv, > + &fops_spec_scan_ctl); > + debugfs_create_file("spectral_short_repeat", > + S_IRUSR | S_IWUSR, > + priv->debug.debugfs_phy, priv, > + &fops_spectral_short_repeat); > + debugfs_create_file("spectral_count", > + S_IRUSR | S_IWUSR, > + priv->debug.debugfs_phy, priv, > + &fops_spectral_count); > + debugfs_create_file("spectral_period", > + S_IRUSR | S_IWUSR, > + priv->debug.debugfs_phy, priv, > + &fops_spectral_period); > + debugfs_create_file("spectral_fft_period", > + S_IRUSR | S_IWUSR, > + priv->debug.debugfs_phy, priv, > + &fops_spectral_fft_period); > +} Note for me: It is big junk of duplicats. But we need to rework complete debugfs part for both ath9k and ath9k-htc to solve this problem. > diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c > b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c > index e8149e3..d21e685 100644 > --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c > +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c > @@ -1010,6 +1010,23 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv > *priv, > * separately to avoid doing two lookups for a rate for each frame. > */ > hdr = (struct ieee80211_hdr *)skb->data; > + > + /* > + * Process PHY errors and return so that the packet > + * can be dropped. > + */ > + #ifdef CONFIG_ATH9K_HTC_DEBUGFS > + if (rx_stats.rs_status & ATH9K_RXERR_PHY) { > + /* TODO: Not using DFS processing now. */ > + if (ath_process_fft(priv->ah, hdr, priv->hw, > priv->rfs_chan_spec_scan, > + &rx_stats, rx_status->mactime, true)) { > + /* TODO: Add code for collecting statistics about spectral scan */ > + } > + > + goto rx_next; > + } > + #endif Add code for collecting statistics about spectral scan :) > if (!ath9k_cmn_rx_accept(common, hdr, rx_status, &rx_stats, > &decrypt_error, priv->rxfilter)) > goto rx_next; > -- Regards, Oleksij
signature.asc
Description: OpenPGP digital signature
_______________________________________________ ath9k-devel mailing list ath9k-devel@lists.ath9k.org https://lists.ath9k.org/mailman/listinfo/ath9k-devel