aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBala Shanmugam <bkamatch@qca.qualcomm.com>2012-05-22 03:53:12 -0400
committerKalle Valo <kvalo@qca.qualcomm.com>2012-05-24 03:22:22 -0400
commit06e360ace9434bf37164fd87941b797cc0f3cb7e (patch)
tree2ec9a7c6f660648e107343f1787c58c0f7787d64 /drivers
parentfa338be062e31141a8dadd822a98f558785c8818 (diff)
ath6kl: Add support for setting tx rateset.
Tx legacy and mcs rateset can configured using iw for 2.4 and 5 bands. Add support for the same in driver. kvalo: add an enum for the hw flags and rename the flag accordingly, rename ath6kl_cfg80211_set_bitrate_mask() to a shorter version to make it easier to indent Signed-off-by: Bala Shanmugam <bkamatch@qca.qualcomm.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c24
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.h6
-rw-r--r--drivers/net/wireless/ath/ath6kl/init.c5
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.c109
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.h32
5 files changed, 176 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 7845d33deed9..6a934e16ae83 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -3320,6 +3320,18 @@ static int ath6kl_cfg80211_sscan_stop(struct wiphy *wiphy,
3320 return 0; 3320 return 0;
3321} 3321}
3322 3322
3323static int ath6kl_cfg80211_set_bitrate(struct wiphy *wiphy,
3324 struct net_device *dev,
3325 const u8 *addr,
3326 const struct cfg80211_bitrate_mask *mask)
3327{
3328 struct ath6kl *ar = ath6kl_priv(dev);
3329 struct ath6kl_vif *vif = netdev_priv(dev);
3330
3331 return ath6kl_wmi_set_bitrate_mask(ar->wmi, vif->fw_vif_idx,
3332 mask);
3333}
3334
3323static const struct ieee80211_txrx_stypes 3335static const struct ieee80211_txrx_stypes
3324ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = { 3336ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = {
3325 [NL80211_IFTYPE_STATION] = { 3337 [NL80211_IFTYPE_STATION] = {
@@ -3386,6 +3398,7 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = {
3386 .mgmt_frame_register = ath6kl_mgmt_frame_register, 3398 .mgmt_frame_register = ath6kl_mgmt_frame_register,
3387 .sched_scan_start = ath6kl_cfg80211_sscan_start, 3399 .sched_scan_start = ath6kl_cfg80211_sscan_start,
3388 .sched_scan_stop = ath6kl_cfg80211_sscan_stop, 3400 .sched_scan_stop = ath6kl_cfg80211_sscan_stop,
3401 .set_bitrate_mask = ath6kl_cfg80211_set_bitrate,
3389}; 3402};
3390 3403
3391void ath6kl_cfg80211_stop(struct ath6kl_vif *vif) 3404void ath6kl_cfg80211_stop(struct ath6kl_vif *vif)
@@ -3616,6 +3629,17 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
3616 ath6kl_band_5ghz.ht_cap.cap = 0; 3629 ath6kl_band_5ghz.ht_cap.cap = 0;
3617 ath6kl_band_5ghz.ht_cap.ht_supported = false; 3630 ath6kl_band_5ghz.ht_cap.ht_supported = false;
3618 } 3631 }
3632
3633 if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES) {
3634 ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
3635 ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
3636 ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff;
3637 ath6kl_band_5ghz.ht_cap.mcs.rx_mask[1] = 0xff;
3638 } else {
3639 ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
3640 ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
3641 }
3642
3619 if (band_2gig) 3643 if (band_2gig)
3620 wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; 3644 wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz;
3621 if (band_5gig) 3645 if (band_5gig)
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index 991bd96f7cf6..b1bc6bc69f2a 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -127,6 +127,10 @@ struct ath6kl_fw_ie {
127 u8 data[0]; 127 u8 data[0];
128}; 128};
129 129
130enum ath6kl_hw_flags {
131 ATH6KL_HW_FLAG_64BIT_RATES = BIT(0),
132};
133
130#define ATH6KL_FW_API2_FILE "fw-2.bin" 134#define ATH6KL_FW_API2_FILE "fw-2.bin"
131#define ATH6KL_FW_API3_FILE "fw-3.bin" 135#define ATH6KL_FW_API3_FILE "fw-3.bin"
132 136
@@ -702,6 +706,8 @@ struct ath6kl {
702 u32 testscript_addr; 706 u32 testscript_addr;
703 enum wmi_phy_cap cap; 707 enum wmi_phy_cap cap;
704 708
709 u32 flags;
710
705 struct ath6kl_hw_fw { 711 struct ath6kl_hw_fw {
706 const char *dir; 712 const char *dir;
707 const char *otp; 713 const char *otp;
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index 241febcd7f7c..daf24ee9d28a 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[] = {
42 .reserved_ram_size = 6912, 42 .reserved_ram_size = 6912,
43 .refclk_hz = 26000000, 43 .refclk_hz = 26000000,
44 .uarttx_pin = 8, 44 .uarttx_pin = 8,
45 .flags = 0,
45 46
46 /* hw2.0 needs override address hardcoded */ 47 /* hw2.0 needs override address hardcoded */
47 .app_start_override_addr = 0x944C00, 48 .app_start_override_addr = 0x944C00,
@@ -67,6 +68,7 @@ static const struct ath6kl_hw hw_list[] = {
67 .refclk_hz = 26000000, 68 .refclk_hz = 26000000,
68 .uarttx_pin = 8, 69 .uarttx_pin = 8,
69 .testscript_addr = 0x57ef74, 70 .testscript_addr = 0x57ef74,
71 .flags = 0,
70 72
71 .fw = { 73 .fw = {
72 .dir = AR6003_HW_2_1_1_FW_DIR, 74 .dir = AR6003_HW_2_1_1_FW_DIR,
@@ -91,6 +93,7 @@ static const struct ath6kl_hw hw_list[] = {
91 .board_addr = 0x433900, 93 .board_addr = 0x433900,
92 .refclk_hz = 26000000, 94 .refclk_hz = 26000000,
93 .uarttx_pin = 11, 95 .uarttx_pin = 11,
96 .flags = ATH6KL_HW_FLAG_64BIT_RATES,
94 97
95 .fw = { 98 .fw = {
96 .dir = AR6004_HW_1_0_FW_DIR, 99 .dir = AR6004_HW_1_0_FW_DIR,
@@ -110,6 +113,7 @@ static const struct ath6kl_hw hw_list[] = {
110 .board_addr = 0x43d400, 113 .board_addr = 0x43d400,
111 .refclk_hz = 40000000, 114 .refclk_hz = 40000000,
112 .uarttx_pin = 11, 115 .uarttx_pin = 11,
116 .flags = ATH6KL_HW_FLAG_64BIT_RATES,
113 117
114 .fw = { 118 .fw = {
115 .dir = AR6004_HW_1_1_FW_DIR, 119 .dir = AR6004_HW_1_1_FW_DIR,
@@ -129,6 +133,7 @@ static const struct ath6kl_hw hw_list[] = {
129 .board_addr = 0x435c00, 133 .board_addr = 0x435c00,
130 .refclk_hz = 40000000, 134 .refclk_hz = 40000000,
131 .uarttx_pin = 11, 135 .uarttx_pin = 11,
136 .flags = ATH6KL_HW_FLAG_64BIT_RATES,
132 137
133 .fw = { 138 .fw = {
134 .dir = AR6004_HW_1_2_FW_DIR, 139 .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 6ad762daa425..63dc4fd73c4c 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)
2599 spin_unlock_bh(&wmi->lock); 2599 spin_unlock_bh(&wmi->lock);
2600} 2600}
2601 2601
2602static int ath6kl_set_bitrate_mask64(struct wmi *wmi, u8 if_idx,
2603 const struct cfg80211_bitrate_mask *mask)
2604{
2605 struct sk_buff *skb;
2606 int ret, mode, band;
2607 u64 mcsrate, ratemask[IEEE80211_NUM_BANDS];
2608 struct wmi_set_tx_select_rates64_cmd *cmd;
2609
2610 memset(&ratemask, 0, sizeof(ratemask));
2611 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
2612 /* copy legacy rate mask */
2613 ratemask[band] = mask->control[band].legacy;
2614 if (band == IEEE80211_BAND_5GHZ)
2615 ratemask[band] =
2616 mask->control[band].legacy << 4;
2617
2618 /* copy mcs rate mask */
2619 mcsrate = mask->control[band].mcs[1];
2620 mcsrate <<= 8;
2621 mcsrate |= mask->control[band].mcs[0];
2622 ratemask[band] |= mcsrate << 12;
2623 ratemask[band] |= mcsrate << 28;
2624 }
2625
2626 ath6kl_dbg(ATH6KL_DBG_WMI,
2627 "Ratemask 64 bit: 2.4:%llx 5:%llx\n",
2628 ratemask[0], ratemask[1]);
2629
2630 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd) * WMI_RATES_MODE_MAX);
2631 if (!skb)
2632 return -ENOMEM;
2633
2634 cmd = (struct wmi_set_tx_select_rates64_cmd *) skb->data;
2635 for (mode = 0; mode < WMI_RATES_MODE_MAX; mode++) {
2636 /* A mode operate in 5GHZ band */
2637 if (mode == WMI_RATES_MODE_11A ||
2638 mode == WMI_RATES_MODE_11A_HT20 ||
2639 mode == WMI_RATES_MODE_11A_HT40)
2640 band = IEEE80211_BAND_5GHZ;
2641 else
2642 band = IEEE80211_BAND_2GHZ;
2643 cmd->ratemask[mode] = cpu_to_le64(ratemask[band]);
2644 }
2645
2646 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
2647 WMI_SET_TX_SELECT_RATES_CMDID,
2648 NO_SYNC_WMIFLAG);
2649 return ret;
2650}
2651
2652static int ath6kl_set_bitrate_mask32(struct wmi *wmi, u8 if_idx,
2653 const struct cfg80211_bitrate_mask *mask)
2654{
2655 struct sk_buff *skb;
2656 int ret, mode, band;
2657 u32 mcsrate, ratemask[IEEE80211_NUM_BANDS];
2658 struct wmi_set_tx_select_rates32_cmd *cmd;
2659
2660 memset(&ratemask, 0, sizeof(ratemask));
2661 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
2662 /* copy legacy rate mask */
2663 ratemask[band] = mask->control[band].legacy;
2664 if (band == IEEE80211_BAND_5GHZ)
2665 ratemask[band] =
2666 mask->control[band].legacy << 4;
2667
2668 /* copy mcs rate mask */
2669 mcsrate = mask->control[band].mcs[0];
2670 ratemask[band] |= mcsrate << 12;
2671 ratemask[band] |= mcsrate << 20;
2672 }
2673
2674 ath6kl_dbg(ATH6KL_DBG_WMI,
2675 "Ratemask 32 bit: 2.4:%x 5:%x\n",
2676 ratemask[0], ratemask[1]);
2677
2678 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd) * WMI_RATES_MODE_MAX);
2679 if (!skb)
2680 return -ENOMEM;
2681
2682 cmd = (struct wmi_set_tx_select_rates32_cmd *) skb->data;
2683 for (mode = 0; mode < WMI_RATES_MODE_MAX; mode++) {
2684 /* A mode operate in 5GHZ band */
2685 if (mode == WMI_RATES_MODE_11A ||
2686 mode == WMI_RATES_MODE_11A_HT20 ||
2687 mode == WMI_RATES_MODE_11A_HT40)
2688 band = IEEE80211_BAND_5GHZ;
2689 else
2690 band = IEEE80211_BAND_2GHZ;
2691 cmd->ratemask[mode] = cpu_to_le32(ratemask[band]);
2692 }
2693
2694 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
2695 WMI_SET_TX_SELECT_RATES_CMDID,
2696 NO_SYNC_WMIFLAG);
2697 return ret;
2698}
2699
2700int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx,
2701 const struct cfg80211_bitrate_mask *mask)
2702{
2703 struct ath6kl *ar = wmi->parent_dev;
2704
2705 if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES)
2706 return ath6kl_set_bitrate_mask64(wmi, if_idx, mask);
2707 else
2708 return ath6kl_set_bitrate_mask32(wmi, if_idx, mask);
2709}
2710
2602int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx, 2711int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx,
2603 enum ath6kl_host_mode host_mode) 2712 enum ath6kl_host_mode host_mode)
2604{ 2713{
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
index 47756795a26c..7c94fe3e9e6d 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 {
1063 __le16 ps_fail_event_policy; 1063 __le16 ps_fail_event_policy;
1064} __packed; 1064} __packed;
1065 1065
1066/*
1067 * Ratemask for below modes should be passed
1068 * to WMI_SET_TX_SELECT_RATES_CMDID.
1069 * AR6003 has 32 bit mask for each modes.
1070 * First 12 bits for legacy rates, 13 to 20
1071 * bits for HT 20 rates and 21 to 28 bits for
1072 * HT 40 rates
1073 */
1074enum wmi_mode_phy {
1075 WMI_RATES_MODE_11A = 0,
1076 WMI_RATES_MODE_11G,
1077 WMI_RATES_MODE_11B,
1078 WMI_RATES_MODE_11GONLY,
1079 WMI_RATES_MODE_11A_HT20,
1080 WMI_RATES_MODE_11G_HT20,
1081 WMI_RATES_MODE_11A_HT40,
1082 WMI_RATES_MODE_11G_HT40,
1083 WMI_RATES_MODE_MAX
1084};
1085
1086/* WMI_SET_TX_SELECT_RATES_CMDID */
1087struct wmi_set_tx_select_rates32_cmd {
1088 __le32 ratemask[WMI_RATES_MODE_MAX];
1089} __packed;
1090
1091/* WMI_SET_TX_SELECT_RATES_CMDID */
1092struct wmi_set_tx_select_rates64_cmd {
1093 __le64 ratemask[WMI_RATES_MODE_MAX];
1094} __packed;
1095
1066/* WMI_SET_DISC_TIMEOUT_CMDID */ 1096/* WMI_SET_DISC_TIMEOUT_CMDID */
1067struct wmi_disc_timeout_cmd { 1097struct wmi_disc_timeout_cmd {
1068 /* seconds */ 1098 /* seconds */
@@ -2547,6 +2577,8 @@ int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx,
2547 __be32 ips0, __be32 ips1); 2577 __be32 ips0, __be32 ips1);
2548int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx, 2578int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx,
2549 enum ath6kl_host_mode host_mode); 2579 enum ath6kl_host_mode host_mode);
2580int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx,
2581 const struct cfg80211_bitrate_mask *mask);
2550int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx, 2582int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx,
2551 enum ath6kl_wow_mode wow_mode, 2583 enum ath6kl_wow_mode wow_mode,
2552 u32 filter, u16 host_req_delay); 2584 u32 filter, u16 host_req_delay);