rsi: Add support for configuring tx power
authorPrameela Rani Garnepudi <prameela.j04cs@gmail.com>
Fri, 18 Nov 2016 10:38:04 +0000 (16:08 +0530)
committerKalle Valo <kvalo@codeaurora.org>
Fri, 25 Nov 2016 09:47:35 +0000 (11:47 +0200)
TX power can be configured from iwconfig, iw or from mac80211 when
regulatory changes are done. Hence support for configuring tx power
to device is added using the RADIO_PARAMS_UPDATE command frame.

Signed-off-by: Prameela Rani Garnepudi <prameela.j04cs@gmail.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/rsi/rsi_91x_mac80211.c
drivers/net/wireless/rsi/rsi_91x_mgmt.c
drivers/net/wireless/rsi/rsi_main.h
drivers/net/wireless/rsi/rsi_mgmt.h

index 6f065d31320b998c35488c05fcb55810eafd4d9d..f63d6bb232a056e8f44f64a40bbe05214fa358b1 100644 (file)
@@ -410,6 +410,34 @@ static int rsi_channel_change(struct ieee80211_hw *hw)
        return status;
 }
 
+/**
+ * rsi_config_power() - This function configures tx power to device
+ * @hw: Pointer to the ieee80211_hw structure.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+static int rsi_config_power(struct ieee80211_hw *hw)
+{
+       struct rsi_hw *adapter = hw->priv;
+       struct rsi_common *common = adapter->priv;
+       struct ieee80211_conf *conf = &hw->conf;
+
+       if (adapter->sc_nvifs <= 0) {
+               rsi_dbg(ERR_ZONE, "%s: No virtual interface found\n", __func__);
+               return -EINVAL;
+       }
+
+       rsi_dbg(INFO_ZONE,
+               "%s: Set tx power: %d dBM\n", __func__, conf->power_level);
+
+       if (conf->power_level == common->tx_power)
+               return 0;
+
+       common->tx_power = conf->power_level;
+
+       return rsi_send_radio_params_update(common);
+}
+
 /**
  * rsi_mac80211_config() - This function is a handler for configuration
  *                        requests. The stack calls this function to
@@ -431,6 +459,12 @@ static int rsi_mac80211_config(struct ieee80211_hw *hw,
        if (changed & IEEE80211_CONF_CHANGE_CHANNEL)
                status = rsi_channel_change(hw);
 
+       /* tx power */
+       if (changed & IEEE80211_CONF_CHANGE_POWER) {
+               rsi_dbg(INFO_ZONE, "%s: Configuring Power\n", __func__);
+               status = rsi_config_power(hw);
+       }
+
        mutex_unlock(&common->mutex);
 
        return status;
index 631cdb13c336d21ecccdba20187d0bc2e79f2177..99c25607d840a9ba645c94a68aa05b79aa88d635 100644 (file)
@@ -952,6 +952,43 @@ int rsi_set_channel(struct rsi_common *common, u16 channel)
        return rsi_send_internal_mgmt_frame(common, skb);
 }
 
+/**
+ * rsi_send_radio_params_update() - This function sends the radio
+ *                             parameters update to device
+ * @common: Pointer to the driver private structure.
+ * @channel: Channel value to be set.
+ *
+ * Return: 0 on success, corresponding error code on failure.
+ */
+int rsi_send_radio_params_update(struct rsi_common *common)
+{
+       struct rsi_mac_frame *cmd_frame;
+       struct sk_buff *skb = NULL;
+
+       rsi_dbg(MGMT_TX_ZONE,
+               "%s: Sending Radio Params update frame\n", __func__);
+
+       skb = dev_alloc_skb(FRAME_DESC_SZ);
+       if (!skb) {
+               rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+                       __func__);
+               return -ENOMEM;
+       }
+
+       memset(skb->data, 0, FRAME_DESC_SZ);
+       cmd_frame = (struct rsi_mac_frame *)skb->data;
+
+       cmd_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
+       cmd_frame->desc_word[1] = cpu_to_le16(RADIO_PARAMS_UPDATE);
+       cmd_frame->desc_word[3] = cpu_to_le16(BIT(0));
+
+       cmd_frame->desc_word[3] |= cpu_to_le16(common->tx_power << 8);
+
+       skb_put(skb, FRAME_DESC_SZ);
+
+       return rsi_send_internal_mgmt_frame(common, skb);
+}
+
 /**
  * rsi_compare() - This function is used to compare two integers
  * @a: pointer to the first integer
index dcd095787166e3aa0cf6de80054e2ee5e6134d77..3938f137fdb049adff46bac28c1e1975809fc854 100644 (file)
@@ -204,6 +204,8 @@ struct rsi_common {
        struct cqm_info cqm_info;
 
        bool hw_data_qs_blocked;
+       
+       int tx_power;
 };
 
 struct rsi_hw {
index 2cf6542ddc0255dd34b22b07e77b874461d99ec7..72f7cfb698ca2d42f926910c278001d55b0f193b 100644 (file)
@@ -200,7 +200,8 @@ enum cmd_frame_type {
        BG_SCAN_PARAMS,
        BG_SCAN_PROBE_REQ,
        CW_MODE_REQ,
-       PER_CMD_PKT
+       PER_CMD_PKT,
+       RADIO_PARAMS_UPDATE = 0x29
 };
 
 struct rsi_mac_frame {
@@ -324,4 +325,5 @@ int rsi_send_mgmt_pkt(struct rsi_common *common, struct sk_buff *skb);
 int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb);
 int rsi_band_check(struct rsi_common *common);
 int rsi_send_rx_filter_frame(struct rsi_common *common, u16 rx_filter_word);
+int rsi_send_radio_params_update(struct rsi_common *common);
 #endif