Change the number of active antennas (RF-chains)

Okhwan Lee ohlee at mwnl.snu.ac.kr
Thu Sep 11 00:37:07 PDT 2014


Hi,

I have been trying to configure the number of active antennas (not
spatial stream) by using ath10k/QCA9880.

When I use ath9k, we can easily change the number of active antenna by
using REG_WRITE(ah, AR_PHY_RX_CHAINMASK, ah->rxchainmask) function
used in ar9003_hw_set_chain_masks.

However, in ath10k, we failed to handle the values (e.g, rx/tx chain
mask of QCA9880) by using ath10k_wmi_pdev_set_param(ar,
ar->wmi.pdev_param->rx_chain_mask, rx_ant) funcion in used in
__ath10k_set_antenna.

I use debugfs module to configure the parameters and you can find our
code (for both ath9k and ath10k) at the end of this e-mail.
aWe measured  the power consumption of NIC to confirm whether the
codes can change the number of active RF-chains or not.
As you might know, the power consumption is highly depends on the
number of active RF-chains.
In ath9k, the power consumption decreases as the number of active
rf-chains (rx_chainmask, antennas) is decrease.
However, in ath10, we failed to configure the number of active
RF-chains, and the power consumption does not change at all.

If you have any idea on this issue, please let me know.

Thank you.

Okhwan

/********************ath10k/debug.c (this is not work)*********************/

static ssize_t ath10k_read_rx_chainmask(struct file *file,
                                        char __user *user_buf,
                                             size_t count, loff_t *ppos)
{
//      printk(KERN_DEBUG "%s",__FUNCTION__);
        ath10k_dbg(ATH10K_DBG_MAC, "%s -> ",__FUNCTION__);
        struct ath10k *ar = file->private_data;
        char buf[32];
        unsigned int len;

        len = sprintf(buf, "0x%08x\n", ar->cfg_rx_chainmask);
        return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}

static ssize_t ath10k_write_rx_chainmask(struct file *file, const char
__user *user_buf,
                             size_t count, loff_t *ppos)
{
        ath10k_dbg(ATH10K_DBG_MAC, "%s -> ",__FUNCTION__);
        struct ath10k *ar = file->private_data;
        unsigned long mask;
        int ret;

        ret = kstrtoul_from_user(user_buf, count, 0, &mask);
        ath10k_dbg(ATH10K_DBG_MAC, "%s -> mask: 0x%x\n",__FUNCTION__,
(unsigned int)mask);
        if (mask > 0x7){
                ath10k_dbg(ATH10K_DBG_MAC, "%s -> mask: %lu should be
< 7\n",__FUNCTION__, mask);
                return -E2BIG;
        }

        if ((ar->state != ATH10K_STATE_ON) &&
            (ar->state != ATH10K_STATE_RESTARTED)){
                ath10k_dbg(ATH10K_DBG_MAC, "%s -> failed pass state
check stat: %d\n",__FUNCTION__, ar->state);
                ret = 1;
                goto out;
        }

        ath10k_dbg(ATH10K_DBG_MAC, "%s -> start lock\n",__FUNCTION__);
        mutex_lock(&ar->conf_mutex);
        ath10k_dbg(ATH10K_DBG_MAC, "%s -> locked\n",__FUNCTION__);

        ar->cfg_rx_chainmask = mask;

        ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->rx_chain_mask,
                                        (u32)mask);
        if (ret) {
                ath10k_warn("failed to set rx-chainmask: %d, req 0x%x\n",
                            ret, (unsigned int)mask);
                goto out;
        }
        ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->tx_chain_mask,
                                        (u32)mask);



        ret = count;
out:
        mutex_unlock(&ar->conf_mutex);

        return ret;
}

static const struct file_operations fops_rx_chainmask = {
        .read = ath10k_read_rx_chainmask,
        .write = ath10k_write_rx_chainmask,
        .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
};

/*****************************************/


/********************ath9k/debug.c (this is work)*********************/


static ssize_t read_file_rx_chainmask(struct file *file, char __user *user_buf,
           size_t count, loff_t *ppos)
{
  printk(KERN_DEBUG “%s”,__FUNCTION__);
  struct ath_softc *sc = file->private_data;
  struct ath_hw *ah = sc->sc_ah;
  char buf[32];
  unsigned int len;


  len = sprintf(buf, “0x%08x\n”, ah->rxchainmask);
  return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}


static ssize_t write_file_rx_chainmask(struct file *file, const char
__user *user_buf,
           size_t count, loff_t *ppos)
{
  printk(KERN_DEBUG “%s”,__FUNCTION__);
  struct ath_softc *sc = file->private_data;
  struct ath_hw *ah = sc->sc_ah;
  unsigned long mask;
  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 (strict_strtoul(buf, 0, &mask))
    return -EINVAL;


  ah->rxchainmask = mask;
  ah->caps.rx_chainmask = mask;
  ah->eep_ops->fill_eeprom(ah);
  REG_WRITE(ah, AR_PHY_RX_CHAINMASK, ah->rxchainmask);
  REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, ah->rxchainmask);


  return count;
}


/*****************************************/

Sincerely yours,

Okhwan Lee , Ph.D. student
Multimedia & Wireless Networking Lab. (MWNL),
School of Electrical Engineering,
Seoul National University (SNU)

Tel: +82-2-880-1755
Cell: +82-10-4632-1980
URL: http://mwnl.snu.ac.kr/~ohlee



More information about the ath10k mailing list