diff options
author | Thirumalai Pachamuthu <tpachamu@qca.qualcomm.com> | 2012-01-12 07:51:39 -0500 |
---|---|---|
committer | Kalle Valo <kvalo@qca.qualcomm.com> | 2012-01-13 06:48:25 -0500 |
commit | c1762a3fe196483981f91b926f5f6ee18af757f2 (patch) | |
tree | 39247fd547f84646ed137bdbac25851d73c58262 /drivers/net/wireless/ath/ath6kl/wmi.c | |
parent | 8232736dabd2a0310f76944fa7af0542fe3ded4f (diff) |
ath6kl: Add support for uAPSD
* A new APSD power save queue is added in the station structure.
* When a station has APSD capability and goes to power save, the frame
designated to the station will be buffered in APSD queue.
* When the host receives a frame which the firmware marked as trigger,
host delivers the buffered frame from the APSD power save queue.
Number of frames to deliver is decided by MAX SP length.
* When a station moves from sleep to awake state, all frames buffered
in APSD power save queue are sent to the firmware.
* When a station is disconnected, all frames bufferes in APSD power save
queue are dropped.
* When the host queues the first frame to the APSD queue or removes the
last frame from the APSD queue, it is indicated to the firmware using
WMI_AP_APSD_BUFFERED_TRAFFIC_CMD.
kvalo: fix buggy handling of sks queues, made it more obvious
the user priority when wmm is disabled, remove unneed else block and
combined some variable declarations
Signed-off-by: Thirumalai Pachamuthu <tpachamu@qca.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath6kl/wmi.c')
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/wmi.c | 62 |
1 files changed, 54 insertions, 8 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index 08fbd9a9be4b..c2420f886ed8 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c | |||
@@ -180,7 +180,7 @@ static int ath6kl_wmi_meta_add(struct wmi *wmi, struct sk_buff *skb, | |||
180 | } | 180 | } |
181 | 181 | ||
182 | int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb, | 182 | int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb, |
183 | u8 msg_type, bool more_data, | 183 | u8 msg_type, u32 flags, |
184 | enum wmi_data_hdr_data_type data_type, | 184 | enum wmi_data_hdr_data_type data_type, |
185 | u8 meta_ver, void *tx_meta_info, u8 if_idx) | 185 | u8 meta_ver, void *tx_meta_info, u8 if_idx) |
186 | { | 186 | { |
@@ -204,17 +204,19 @@ int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb, | |||
204 | data_hdr->info = msg_type << WMI_DATA_HDR_MSG_TYPE_SHIFT; | 204 | data_hdr->info = msg_type << WMI_DATA_HDR_MSG_TYPE_SHIFT; |
205 | data_hdr->info |= data_type << WMI_DATA_HDR_DATA_TYPE_SHIFT; | 205 | data_hdr->info |= data_type << WMI_DATA_HDR_DATA_TYPE_SHIFT; |
206 | 206 | ||
207 | if (more_data) | 207 | if (flags & WMI_DATA_HDR_FLAGS_MORE) |
208 | data_hdr->info |= | 208 | data_hdr->info |= WMI_DATA_HDR_MORE; |
209 | WMI_DATA_HDR_MORE_MASK << WMI_DATA_HDR_MORE_SHIFT; | ||
210 | 209 | ||
211 | data_hdr->info2 = cpu_to_le16(meta_ver << WMI_DATA_HDR_META_SHIFT); | 210 | if (flags & WMI_DATA_HDR_FLAGS_EOSP) |
212 | data_hdr->info3 = cpu_to_le16(if_idx & WMI_DATA_HDR_IF_IDX_MASK); | 211 | data_hdr->info3 |= cpu_to_le16(WMI_DATA_HDR_EOSP); |
212 | |||
213 | data_hdr->info2 |= cpu_to_le16(meta_ver << WMI_DATA_HDR_META_SHIFT); | ||
214 | data_hdr->info3 |= cpu_to_le16(if_idx & WMI_DATA_HDR_IF_IDX_MASK); | ||
213 | 215 | ||
214 | return 0; | 216 | return 0; |
215 | } | 217 | } |
216 | 218 | ||
217 | static u8 ath6kl_wmi_determine_user_priority(u8 *pkt, u32 layer2_pri) | 219 | u8 ath6kl_wmi_determine_user_priority(u8 *pkt, u32 layer2_pri) |
218 | { | 220 | { |
219 | struct iphdr *ip_hdr = (struct iphdr *) pkt; | 221 | struct iphdr *ip_hdr = (struct iphdr *) pkt; |
220 | u8 ip_pri; | 222 | u8 ip_pri; |
@@ -236,6 +238,11 @@ static u8 ath6kl_wmi_determine_user_priority(u8 *pkt, u32 layer2_pri) | |||
236 | return ip_pri; | 238 | return ip_pri; |
237 | } | 239 | } |
238 | 240 | ||
241 | u8 ath6kl_wmi_get_traffic_class(u8 user_priority) | ||
242 | { | ||
243 | return up_to_ac[user_priority & 0x7]; | ||
244 | } | ||
245 | |||
239 | int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, u8 if_idx, | 246 | int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, u8 if_idx, |
240 | struct sk_buff *skb, | 247 | struct sk_buff *skb, |
241 | u32 layer2_priority, bool wmm_enabled, | 248 | u32 layer2_priority, bool wmm_enabled, |
@@ -786,12 +793,14 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len, | |||
786 | ev->u.ap_sta.keymgmt, | 793 | ev->u.ap_sta.keymgmt, |
787 | le16_to_cpu(ev->u.ap_sta.cipher), | 794 | le16_to_cpu(ev->u.ap_sta.cipher), |
788 | ev->u.ap_sta.apsd_info); | 795 | ev->u.ap_sta.apsd_info); |
796 | |||
789 | ath6kl_connect_ap_mode_sta( | 797 | ath6kl_connect_ap_mode_sta( |
790 | vif, ev->u.ap_sta.aid, ev->u.ap_sta.mac_addr, | 798 | vif, ev->u.ap_sta.aid, ev->u.ap_sta.mac_addr, |
791 | ev->u.ap_sta.keymgmt, | 799 | ev->u.ap_sta.keymgmt, |
792 | le16_to_cpu(ev->u.ap_sta.cipher), | 800 | le16_to_cpu(ev->u.ap_sta.cipher), |
793 | ev->u.ap_sta.auth, ev->assoc_req_len, | 801 | ev->u.ap_sta.auth, ev->assoc_req_len, |
794 | ev->assoc_info + ev->beacon_ie_len); | 802 | ev->assoc_info + ev->beacon_ie_len, |
803 | ev->u.ap_sta.apsd_info); | ||
795 | } | 804 | } |
796 | return 0; | 805 | return 0; |
797 | } | 806 | } |
@@ -2993,6 +3002,43 @@ int ath6kl_wmi_ap_set_mlme(struct wmi *wmip, u8 if_idx, u8 cmd, const u8 *mac, | |||
2993 | NO_SYNC_WMIFLAG); | 3002 | NO_SYNC_WMIFLAG); |
2994 | } | 3003 | } |
2995 | 3004 | ||
3005 | /* This command will be used to enable/disable AP uAPSD feature */ | ||
3006 | int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable) | ||
3007 | { | ||
3008 | struct wmi_ap_set_apsd_cmd *cmd; | ||
3009 | struct sk_buff *skb; | ||
3010 | |||
3011 | skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); | ||
3012 | if (!skb) | ||
3013 | return -ENOMEM; | ||
3014 | |||
3015 | cmd = (struct wmi_ap_set_apsd_cmd *)skb->data; | ||
3016 | cmd->enable = enable; | ||
3017 | |||
3018 | return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_AP_SET_APSD_CMDID, | ||
3019 | NO_SYNC_WMIFLAG); | ||
3020 | } | ||
3021 | |||
3022 | int ath6kl_wmi_set_apsd_bfrd_traf(struct wmi *wmi, u8 if_idx, | ||
3023 | u16 aid, u16 bitmap, u32 flags) | ||
3024 | { | ||
3025 | struct wmi_ap_apsd_buffered_traffic_cmd *cmd; | ||
3026 | struct sk_buff *skb; | ||
3027 | |||
3028 | skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); | ||
3029 | if (!skb) | ||
3030 | return -ENOMEM; | ||
3031 | |||
3032 | cmd = (struct wmi_ap_apsd_buffered_traffic_cmd *)skb->data; | ||
3033 | cmd->aid = cpu_to_le16(aid); | ||
3034 | cmd->bitmap = cpu_to_le16(bitmap); | ||
3035 | cmd->flags = cpu_to_le32(flags); | ||
3036 | |||
3037 | return ath6kl_wmi_cmd_send(wmi, if_idx, skb, | ||
3038 | WMI_AP_APSD_BUFFERED_TRAFFIC_CMDID, | ||
3039 | NO_SYNC_WMIFLAG); | ||
3040 | } | ||
3041 | |||
2996 | static int ath6kl_wmi_pspoll_event_rx(struct wmi *wmi, u8 *datap, int len, | 3042 | static int ath6kl_wmi_pspoll_event_rx(struct wmi *wmi, u8 *datap, int len, |
2997 | struct ath6kl_vif *vif) | 3043 | struct ath6kl_vif *vif) |
2998 | { | 3044 | { |