linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2] ath6kl: Add support for setting tx rateset.
@ 2012-05-21 10:41 Bala Shanmugam
  2012-05-22  7:35 ` Bala Shanmugam
  0 siblings, 1 reply; 2+ messages in thread
From: Bala Shanmugam @ 2012-05-21 10:41 UTC (permalink / raw)
  To: kvalo; +Cc: ath6kl-devel, linux-wireless

Tx legacy and mcs rateset can configured using iw for
2.4 and 5 bands.  Add support for the same in driver.

Signed-off-by: Bala Shanmugam <bkamatch@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath6kl/cfg80211.c |   25 +++++++
 drivers/net/wireless/ath/ath6kl/core.h     |    2 +
 drivers/net/wireless/ath/ath6kl/init.c     |    5 ++
 drivers/net/wireless/ath/ath6kl/wmi.c      |  109 ++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath6kl/wmi.h      |   32 ++++++++
 5 files changed, 173 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 7845d33..8c69880 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -3320,6 +3320,19 @@ static int ath6kl_cfg80211_sscan_stop(struct wiphy *wiphy,
 	return 0;
 }
 
+static int ath6kl_cfg80211_set_bitrate_mask(
+				struct wiphy *wiphy,
+				struct net_device *dev,
+				const u8 *addr,
+				const struct cfg80211_bitrate_mask *mask)
+{
+	struct ath6kl *ar = ath6kl_priv(dev);
+	struct ath6kl_vif *vif = netdev_priv(dev);
+
+	return ath6kl_wmi_set_bitrate_mask(ar->wmi, vif->fw_vif_idx,
+				mask);
+}
+
 static const struct ieee80211_txrx_stypes
 ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = {
 	[NL80211_IFTYPE_STATION] = {
@@ -3386,6 +3399,7 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = {
 	.mgmt_frame_register = ath6kl_mgmt_frame_register,
 	.sched_scan_start = ath6kl_cfg80211_sscan_start,
 	.sched_scan_stop = ath6kl_cfg80211_sscan_stop,
+	.set_bitrate_mask = ath6kl_cfg80211_set_bitrate_mask,
 };
 
 void ath6kl_cfg80211_stop(struct ath6kl_vif *vif)
@@ -3616,6 +3630,17 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
 		ath6kl_band_5ghz.ht_cap.cap = 0;
 		ath6kl_band_5ghz.ht_cap.ht_supported = false;
 	}
+
+	if (ar->hw.flags & ATH6KL_64BIT_BITRATES) {
+		ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
+		ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
+		ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff;
+		ath6kl_band_5ghz.ht_cap.mcs.rx_mask[1] = 0xff;
+	} else {
+		ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
+		ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
+	}
+
 	if (band_2gig)
 		wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz;
 	if (band_5gig)
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index 991bd96..d944b98 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -701,6 +701,8 @@ struct ath6kl {
 		u32 uarttx_pin;
 		u32 testscript_addr;
 		enum wmi_phy_cap cap;
+#define ATH6KL_64BIT_BITRATES 1
+		u32 flags;
 
 		struct ath6kl_hw_fw {
 			const char *dir;
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index 10de132..96205f3 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -42,6 +42,7 @@ static const struct ath6kl_hw hw_list[] = {
 		.reserved_ram_size		= 6912,
 		.refclk_hz			= 26000000,
 		.uarttx_pin			= 8,
+		.flags				= 0,
 
 		/* hw2.0 needs override address hardcoded */
 		.app_start_override_addr	= 0x944C00,
@@ -67,6 +68,7 @@ static const struct ath6kl_hw hw_list[] = {
 		.refclk_hz			= 26000000,
 		.uarttx_pin			= 8,
 		.testscript_addr		= 0x57ef74,
+		.flags				= 0,
 
 		.fw = {
 			.dir		= AR6003_HW_2_1_1_FW_DIR,
@@ -91,6 +93,7 @@ static const struct ath6kl_hw hw_list[] = {
 		.board_addr			= 0x433900,
 		.refclk_hz			= 26000000,
 		.uarttx_pin			= 11,
+		.flags				= ATH6KL_64BIT_BITRATES,
 
 		.fw = {
 			.dir		= AR6004_HW_1_0_FW_DIR,
@@ -110,6 +113,7 @@ static const struct ath6kl_hw hw_list[] = {
 		.board_addr			= 0x43d400,
 		.refclk_hz			= 40000000,
 		.uarttx_pin			= 11,
+		.flags				= ATH6KL_64BIT_BITRATES,
 
 		.fw = {
 			.dir		= AR6004_HW_1_1_FW_DIR,
@@ -129,6 +133,7 @@ static const struct ath6kl_hw hw_list[] = {
 		.board_addr			= 0x435c00,
 		.refclk_hz			= 40000000,
 		.uarttx_pin			= 11,
+		.flags				= ATH6KL_64BIT_BITRATES,
 
 		.fw = {
 			.dir		= AR6004_HW_1_2_FW_DIR,
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index 6ad762d..77b8367 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -2599,6 +2599,115 @@ static void ath6kl_wmi_relinquish_implicit_pstream_credits(struct wmi *wmi)
 	spin_unlock_bh(&wmi->lock);
 }
 
+static int ath6kl_set_bitrate_mask64(struct wmi *wmi, u8 if_idx,
+				     const struct cfg80211_bitrate_mask *mask)
+{
+	struct sk_buff *skb;
+	int ret, mode, band;
+	u64 mcsrate, ratemask[IEEE80211_NUM_BANDS];
+	struct wmi_set_tx_select_rates64_cmd *cmd;
+
+	memset(&ratemask, 0, sizeof(ratemask));
+	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+		/* copy legacy rate mask */
+		ratemask[band] = mask->control[band].legacy;
+		if (band == IEEE80211_BAND_5GHZ)
+			ratemask[band] =
+				mask->control[band].legacy << 4;
+
+		/* copy mcs rate mask */
+		mcsrate = mask->control[band].mcs[1];
+		mcsrate <<= 8;
+		mcsrate |= mask->control[band].mcs[0];
+		ratemask[band] |= mcsrate << 12;
+		ratemask[band] |= mcsrate << 28;
+	}
+
+	ath6kl_dbg(ATH6KL_DBG_WMI,
+			"Ratemask 64 bit: 2.4:%llx 5:%llx\n",
+			ratemask[0], ratemask[1]);
+
+	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd) * WMI_RATES_MODE_MAX);
+	if (!skb)
+		return -ENOMEM;
+
+	cmd = (struct wmi_set_tx_select_rates64_cmd *) skb->data;
+	for (mode = 0; mode < WMI_RATES_MODE_MAX; mode++) {
+		/* A mode operate in 5GHZ band */
+		if (mode == WMI_RATES_MODE_11A ||
+		    mode == WMI_RATES_MODE_11A_HT20 ||
+		    mode == WMI_RATES_MODE_11A_HT40)
+			band = IEEE80211_BAND_5GHZ;
+		else
+			band = IEEE80211_BAND_2GHZ;
+		cmd->ratemask[mode] = cpu_to_le64(ratemask[band]);
+	}
+
+	ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
+				  WMI_SET_TX_SELECT_RATES_CMDID,
+				  NO_SYNC_WMIFLAG);
+	return ret;
+}
+
+static int ath6kl_set_bitrate_mask32(struct wmi *wmi, u8 if_idx,
+				     const struct cfg80211_bitrate_mask *mask)
+{
+	struct sk_buff *skb;
+	int ret, mode, band;
+	u32 mcsrate, ratemask[IEEE80211_NUM_BANDS];
+	struct wmi_set_tx_select_rates32_cmd *cmd;
+
+	memset(&ratemask, 0, sizeof(ratemask));
+	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+		/* copy legacy rate mask */
+		ratemask[band] = mask->control[band].legacy;
+		if (band == IEEE80211_BAND_5GHZ)
+			ratemask[band] =
+				mask->control[band].legacy << 4;
+
+		/* copy mcs rate mask */
+		mcsrate = mask->control[band].mcs[0];
+		ratemask[band] |= mcsrate << 12;
+		ratemask[band] |= mcsrate << 20;
+	}
+
+	ath6kl_dbg(ATH6KL_DBG_WMI,
+			"Ratemask 32 bit: 2.4:%x 5:%x\n",
+			ratemask[0], ratemask[1]);
+
+	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd) * WMI_RATES_MODE_MAX);
+	if (!skb)
+		return -ENOMEM;
+
+	cmd = (struct wmi_set_tx_select_rates32_cmd *) skb->data;
+	for (mode = 0; mode < WMI_RATES_MODE_MAX; mode++) {
+		/* A mode operate in 5GHZ band */
+		if (mode == WMI_RATES_MODE_11A ||
+		    mode == WMI_RATES_MODE_11A_HT20 ||
+		    mode == WMI_RATES_MODE_11A_HT40)
+			band = IEEE80211_BAND_5GHZ;
+		else
+			band = IEEE80211_BAND_2GHZ;
+		cmd->ratemask[mode] = cpu_to_le32(ratemask[band]);
+	}
+
+	ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
+				  WMI_SET_TX_SELECT_RATES_CMDID,
+				  NO_SYNC_WMIFLAG);
+	return ret;
+}
+
+int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx,
+				const struct cfg80211_bitrate_mask *mask)
+{
+	struct ath6kl *ar = wmi->parent_dev;
+
+	if (ar->hw.flags & ATH6KL_64BIT_BITRATES)
+		return ath6kl_set_bitrate_mask64(wmi, if_idx, mask);
+	else
+		return ath6kl_set_bitrate_mask32(wmi, if_idx, mask);
+}
+
 int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx,
 				       enum ath6kl_host_mode host_mode)
 {
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
index 4775679..7c94fe3 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.h
+++ b/drivers/net/wireless/ath/ath6kl/wmi.h
@@ -1063,6 +1063,36 @@ struct wmi_power_params_cmd {
 	__le16 ps_fail_event_policy;
 } __packed;
 
+/*
+ * Ratemask for below modes should be passed
+ * to WMI_SET_TX_SELECT_RATES_CMDID.
+ * AR6003 has 32 bit mask for each modes.
+ * First 12 bits for legacy rates, 13 to 20
+ * bits for HT 20 rates and 21 to 28 bits for
+ * HT 40 rates
+ */
+enum wmi_mode_phy {
+	WMI_RATES_MODE_11A = 0,
+	WMI_RATES_MODE_11G,
+	WMI_RATES_MODE_11B,
+	WMI_RATES_MODE_11GONLY,
+	WMI_RATES_MODE_11A_HT20,
+	WMI_RATES_MODE_11G_HT20,
+	WMI_RATES_MODE_11A_HT40,
+	WMI_RATES_MODE_11G_HT40,
+	WMI_RATES_MODE_MAX
+};
+
+/* WMI_SET_TX_SELECT_RATES_CMDID */
+struct wmi_set_tx_select_rates32_cmd {
+	__le32 ratemask[WMI_RATES_MODE_MAX];
+} __packed;
+
+/* WMI_SET_TX_SELECT_RATES_CMDID */
+struct wmi_set_tx_select_rates64_cmd {
+	__le64 ratemask[WMI_RATES_MODE_MAX];
+} __packed;
+
 /* WMI_SET_DISC_TIMEOUT_CMDID */
 struct wmi_disc_timeout_cmd {
 	/* seconds */
@@ -2547,6 +2577,8 @@ int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx,
 			  __be32 ips0, __be32 ips1);
 int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx,
 				       enum ath6kl_host_mode host_mode);
+int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx,
+				const struct cfg80211_bitrate_mask *mask);
 int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx,
 				enum ath6kl_wow_mode wow_mode,
 				u32 filter, u16 host_req_delay);
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH v2] ath6kl: Add support for setting tx rateset.
  2012-05-21 10:41 [PATCH v2] ath6kl: Add support for setting tx rateset Bala Shanmugam
@ 2012-05-22  7:35 ` Bala Shanmugam
  0 siblings, 0 replies; 2+ messages in thread
From: Bala Shanmugam @ 2012-05-22  7:35 UTC (permalink / raw)
  To: kvalo; +Cc: ath6kl-devel, linux-wireless

Some indentation issues are seen.
Will send a new patch.

Regards,
Bala.
On 05/21/2012 04:11 PM, Bala Shanmugam wrote:
> Tx legacy and mcs rateset can configured using iw for
> 2.4 and 5 bands.  Add support for the same in driver.
>
> Signed-off-by: Bala Shanmugam<bkamatch@qca.qualcomm.com>
> ---
>   drivers/net/wireless/ath/ath6kl/cfg80211.c |   25 +++++++
>   drivers/net/wireless/ath/ath6kl/core.h     |    2 +
>   drivers/net/wireless/ath/ath6kl/init.c     |    5 ++
>   drivers/net/wireless/ath/ath6kl/wmi.c      |  109 ++++++++++++++++++++++++++++
>   drivers/net/wireless/ath/ath6kl/wmi.h      |   32 ++++++++
>   5 files changed, 173 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
> index 7845d33..8c69880 100644
> --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
> +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
> @@ -3320,6 +3320,19 @@ static int ath6kl_cfg80211_sscan_stop(struct wiphy *wiphy,
>   	return 0;
>   }
>
> +static int ath6kl_cfg80211_set_bitrate_mask(
> +				struct wiphy *wiphy,
> +				struct net_device *dev,
> +				const u8 *addr,
> +				const struct cfg80211_bitrate_mask *mask)
> +{
> +	struct ath6kl *ar = ath6kl_priv(dev);
> +	struct ath6kl_vif *vif = netdev_priv(dev);
> +
> +	return ath6kl_wmi_set_bitrate_mask(ar->wmi, vif->fw_vif_idx,
> +				mask);
> +}
> +
>   static const struct ieee80211_txrx_stypes
>   ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = {
>   	[NL80211_IFTYPE_STATION] = {
> @@ -3386,6 +3399,7 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = {
>   	.mgmt_frame_register = ath6kl_mgmt_frame_register,
>   	.sched_scan_start = ath6kl_cfg80211_sscan_start,
>   	.sched_scan_stop = ath6kl_cfg80211_sscan_stop,
> +	.set_bitrate_mask = ath6kl_cfg80211_set_bitrate_mask,
>   };
>
>   void ath6kl_cfg80211_stop(struct ath6kl_vif *vif)
> @@ -3616,6 +3630,17 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
>   		ath6kl_band_5ghz.ht_cap.cap = 0;
>   		ath6kl_band_5ghz.ht_cap.ht_supported = false;
>   	}
> +
> +	if (ar->hw.flags&  ATH6KL_64BIT_BITRATES) {
> +		ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
> +		ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
> +		ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff;
> +		ath6kl_band_5ghz.ht_cap.mcs.rx_mask[1] = 0xff;
> +	} else {
> +		ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
> +		ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
> +	}
> +
>   	if (band_2gig)
>   		wiphy->bands[IEEE80211_BAND_2GHZ] =&ath6kl_band_2ghz;
>   	if (band_5gig)
> diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
> index 991bd96..d944b98 100644
> --- a/drivers/net/wireless/ath/ath6kl/core.h
> +++ b/drivers/net/wireless/ath/ath6kl/core.h
> @@ -701,6 +701,8 @@ struct ath6kl {
>   		u32 uarttx_pin;
>   		u32 testscript_addr;
>   		enum wmi_phy_cap cap;
> +#define ATH6KL_64BIT_BITRATES 1
> +		u32 flags;
>
>   		struct ath6kl_hw_fw {
>   			const char *dir;
> diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
> index 10de132..96205f3 100644
> --- a/drivers/net/wireless/ath/ath6kl/init.c
> +++ b/drivers/net/wireless/ath/ath6kl/init.c
> @@ -42,6 +42,7 @@ static const struct ath6kl_hw hw_list[] = {
>   		.reserved_ram_size		= 6912,
>   		.refclk_hz			= 26000000,
>   		.uarttx_pin			= 8,
> +		.flags				= 0,
>
>   		/* hw2.0 needs override address hardcoded */
>   		.app_start_override_addr	= 0x944C00,
> @@ -67,6 +68,7 @@ static const struct ath6kl_hw hw_list[] = {
>   		.refclk_hz			= 26000000,
>   		.uarttx_pin			= 8,
>   		.testscript_addr		= 0x57ef74,
> +		.flags				= 0,
>
>   		.fw = {
>   			.dir		= AR6003_HW_2_1_1_FW_DIR,
> @@ -91,6 +93,7 @@ static const struct ath6kl_hw hw_list[] = {
>   		.board_addr			= 0x433900,
>   		.refclk_hz			= 26000000,
>   		.uarttx_pin			= 11,
> +		.flags				= ATH6KL_64BIT_BITRATES,
>
>   		.fw = {
>   			.dir		= AR6004_HW_1_0_FW_DIR,
> @@ -110,6 +113,7 @@ static const struct ath6kl_hw hw_list[] = {
>   		.board_addr			= 0x43d400,
>   		.refclk_hz			= 40000000,
>   		.uarttx_pin			= 11,
> +		.flags				= ATH6KL_64BIT_BITRATES,
>
>   		.fw = {
>   			.dir		= AR6004_HW_1_1_FW_DIR,
> @@ -129,6 +133,7 @@ static const struct ath6kl_hw hw_list[] = {
>   		.board_addr			= 0x435c00,
>   		.refclk_hz			= 40000000,
>   		.uarttx_pin			= 11,
> +		.flags				= ATH6KL_64BIT_BITRATES,
>
>   		.fw = {
>   			.dir		= AR6004_HW_1_2_FW_DIR,
> diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
> index 6ad762d..77b8367 100644
> --- a/drivers/net/wireless/ath/ath6kl/wmi.c
> +++ b/drivers/net/wireless/ath/ath6kl/wmi.c
> @@ -2599,6 +2599,115 @@ static void ath6kl_wmi_relinquish_implicit_pstream_credits(struct wmi *wmi)
>   	spin_unlock_bh(&wmi->lock);
>   }
>
> +static int ath6kl_set_bitrate_mask64(struct wmi *wmi, u8 if_idx,
> +				     const struct cfg80211_bitrate_mask *mask)
> +{
> +	struct sk_buff *skb;
> +	int ret, mode, band;
> +	u64 mcsrate, ratemask[IEEE80211_NUM_BANDS];
> +	struct wmi_set_tx_select_rates64_cmd *cmd;
> +
> +	memset(&ratemask, 0, sizeof(ratemask));
> +	for (band = 0; band<  IEEE80211_NUM_BANDS; band++) {
> +		/* copy legacy rate mask */
> +		ratemask[band] = mask->control[band].legacy;
> +		if (band == IEEE80211_BAND_5GHZ)
> +			ratemask[band] =
> +				mask->control[band].legacy<<  4;
> +
> +		/* copy mcs rate mask */
> +		mcsrate = mask->control[band].mcs[1];
> +		mcsrate<<= 8;
> +		mcsrate |= mask->control[band].mcs[0];
> +		ratemask[band] |= mcsrate<<  12;
> +		ratemask[band] |= mcsrate<<  28;
> +	}
> +
> +	ath6kl_dbg(ATH6KL_DBG_WMI,
> +			"Ratemask 64 bit: 2.4:%llx 5:%llx\n",
> +			ratemask[0], ratemask[1]);
> +
> +	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd) * WMI_RATES_MODE_MAX);
> +	if (!skb)
> +		return -ENOMEM;
> +
> +	cmd = (struct wmi_set_tx_select_rates64_cmd *) skb->data;
> +	for (mode = 0; mode<  WMI_RATES_MODE_MAX; mode++) {
> +		/* A mode operate in 5GHZ band */
> +		if (mode == WMI_RATES_MODE_11A ||
> +		    mode == WMI_RATES_MODE_11A_HT20 ||
> +		    mode == WMI_RATES_MODE_11A_HT40)
> +			band = IEEE80211_BAND_5GHZ;
> +		else
> +			band = IEEE80211_BAND_2GHZ;
> +		cmd->ratemask[mode] = cpu_to_le64(ratemask[band]);
> +	}
> +
> +	ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
> +				  WMI_SET_TX_SELECT_RATES_CMDID,
> +				  NO_SYNC_WMIFLAG);
> +	return ret;
> +}
> +
> +static int ath6kl_set_bitrate_mask32(struct wmi *wmi, u8 if_idx,
> +				     const struct cfg80211_bitrate_mask *mask)
> +{
> +	struct sk_buff *skb;
> +	int ret, mode, band;
> +	u32 mcsrate, ratemask[IEEE80211_NUM_BANDS];
> +	struct wmi_set_tx_select_rates32_cmd *cmd;
> +
> +	memset(&ratemask, 0, sizeof(ratemask));
> +	for (band = 0; band<  IEEE80211_NUM_BANDS; band++) {
> +		/* copy legacy rate mask */
> +		ratemask[band] = mask->control[band].legacy;
> +		if (band == IEEE80211_BAND_5GHZ)
> +			ratemask[band] =
> +				mask->control[band].legacy<<  4;
> +
> +		/* copy mcs rate mask */
> +		mcsrate = mask->control[band].mcs[0];
> +		ratemask[band] |= mcsrate<<  12;
> +		ratemask[band] |= mcsrate<<  20;
> +	}
> +
> +	ath6kl_dbg(ATH6KL_DBG_WMI,
> +			"Ratemask 32 bit: 2.4:%x 5:%x\n",
> +			ratemask[0], ratemask[1]);
> +
> +	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd) * WMI_RATES_MODE_MAX);
> +	if (!skb)
> +		return -ENOMEM;
> +
> +	cmd = (struct wmi_set_tx_select_rates32_cmd *) skb->data;
> +	for (mode = 0; mode<  WMI_RATES_MODE_MAX; mode++) {
> +		/* A mode operate in 5GHZ band */
> +		if (mode == WMI_RATES_MODE_11A ||
> +		    mode == WMI_RATES_MODE_11A_HT20 ||
> +		    mode == WMI_RATES_MODE_11A_HT40)
> +			band = IEEE80211_BAND_5GHZ;
> +		else
> +			band = IEEE80211_BAND_2GHZ;
> +		cmd->ratemask[mode] = cpu_to_le32(ratemask[band]);
> +	}
> +
> +	ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
> +				  WMI_SET_TX_SELECT_RATES_CMDID,
> +				  NO_SYNC_WMIFLAG);
> +	return ret;
> +}
> +
> +int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx,
> +				const struct cfg80211_bitrate_mask *mask)
> +{
> +	struct ath6kl *ar = wmi->parent_dev;
> +
> +	if (ar->hw.flags&  ATH6KL_64BIT_BITRATES)
> +		return ath6kl_set_bitrate_mask64(wmi, if_idx, mask);
> +	else
> +		return ath6kl_set_bitrate_mask32(wmi, if_idx, mask);
> +}
> +
>   int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx,
>   				       enum ath6kl_host_mode host_mode)
>   {
> diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
> index 4775679..7c94fe3 100644
> --- a/drivers/net/wireless/ath/ath6kl/wmi.h
> +++ b/drivers/net/wireless/ath/ath6kl/wmi.h
> @@ -1063,6 +1063,36 @@ struct wmi_power_params_cmd {
>   	__le16 ps_fail_event_policy;
>   } __packed;
>
> +/*
> + * Ratemask for below modes should be passed
> + * to WMI_SET_TX_SELECT_RATES_CMDID.
> + * AR6003 has 32 bit mask for each modes.
> + * First 12 bits for legacy rates, 13 to 20
> + * bits for HT 20 rates and 21 to 28 bits for
> + * HT 40 rates
> + */
> +enum wmi_mode_phy {
> +	WMI_RATES_MODE_11A = 0,
> +	WMI_RATES_MODE_11G,
> +	WMI_RATES_MODE_11B,
> +	WMI_RATES_MODE_11GONLY,
> +	WMI_RATES_MODE_11A_HT20,
> +	WMI_RATES_MODE_11G_HT20,
> +	WMI_RATES_MODE_11A_HT40,
> +	WMI_RATES_MODE_11G_HT40,
> +	WMI_RATES_MODE_MAX
> +};
> +
> +/* WMI_SET_TX_SELECT_RATES_CMDID */
> +struct wmi_set_tx_select_rates32_cmd {
> +	__le32 ratemask[WMI_RATES_MODE_MAX];
> +} __packed;
> +
> +/* WMI_SET_TX_SELECT_RATES_CMDID */
> +struct wmi_set_tx_select_rates64_cmd {
> +	__le64 ratemask[WMI_RATES_MODE_MAX];
> +} __packed;
> +
>   /* WMI_SET_DISC_TIMEOUT_CMDID */
>   struct wmi_disc_timeout_cmd {
>   	/* seconds */
> @@ -2547,6 +2577,8 @@ int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx,
>   			  __be32 ips0, __be32 ips1);
>   int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx,
>   				       enum ath6kl_host_mode host_mode);
> +int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx,
> +				const struct cfg80211_bitrate_mask *mask);
>   int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx,
>   				enum ath6kl_wow_mode wow_mode,
>   				u32 filter, u16 host_req_delay);


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2012-05-22  7:35 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-05-21 10:41 [PATCH v2] ath6kl: Add support for setting tx rateset Bala Shanmugam
2012-05-22  7:35 ` Bala Shanmugam

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).