diff options
author | Bala Shanmugam <bkamatch@qca.qualcomm.com> | 2012-05-22 03:53:12 -0400 |
---|---|---|
committer | Kalle Valo <kvalo@qca.qualcomm.com> | 2012-05-24 03:22:22 -0400 |
commit | 06e360ace9434bf37164fd87941b797cc0f3cb7e (patch) | |
tree | 2ec9a7c6f660648e107343f1787c58c0f7787d64 /drivers | |
parent | fa338be062e31141a8dadd822a98f558785c8818 (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.c | 24 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/core.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/init.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/wmi.c | 109 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/wmi.h | 32 |
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 | ||
3323 | static 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 | |||
3323 | static const struct ieee80211_txrx_stypes | 3335 | static const struct ieee80211_txrx_stypes |
3324 | ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = { | 3336 | ath6kl_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 | ||
3391 | void ath6kl_cfg80211_stop(struct ath6kl_vif *vif) | 3404 | void 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 | ||
130 | enum 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 | ||
2602 | static 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 | |||
2652 | static 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 | |||
2700 | int 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 | |||
2602 | int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx, | 2711 | int 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 | */ | ||
1074 | enum 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 */ | ||
1087 | struct wmi_set_tx_select_rates32_cmd { | ||
1088 | __le32 ratemask[WMI_RATES_MODE_MAX]; | ||
1089 | } __packed; | ||
1090 | |||
1091 | /* WMI_SET_TX_SELECT_RATES_CMDID */ | ||
1092 | struct 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 */ |
1067 | struct wmi_disc_timeout_cmd { | 1097 | struct 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); |
2548 | int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx, | 2578 | int 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); |
2580 | int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx, | ||
2581 | const struct cfg80211_bitrate_mask *mask); | ||
2550 | int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx, | 2582 | int 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); |