aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath6kl/wmi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath6kl/wmi.c')
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.c148
1 files changed, 128 insertions, 20 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index f6f2aa27fc20..18fa9aa8af92 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
182int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb, 182int 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
217static u8 ath6kl_wmi_determine_user_priority(u8 *pkt, u32 layer2_pri) 219u8 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
241u8 ath6kl_wmi_get_traffic_class(u8 user_priority)
242{
243 return up_to_ac[user_priority & 0x7];
244}
245
239int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, u8 if_idx, 246int 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,
@@ -419,9 +426,6 @@ static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len)
419 ath6kl_dbg(ATH6KL_DBG_WMI, "comp: %d %d %d\n", 426 ath6kl_dbg(ATH6KL_DBG_WMI, "comp: %d %d %d\n",
420 evt->num_msg, evt->msg_len, evt->msg_type); 427 evt->num_msg, evt->msg_len, evt->msg_type);
421 428
422 if (!AR_DBG_LVL_CHECK(ATH6KL_DBG_WMI))
423 return 0;
424
425 for (index = 0; index < evt->num_msg; index++) { 429 for (index = 0; index < evt->num_msg; index++) {
426 size = sizeof(struct wmi_tx_complete_event) + 430 size = sizeof(struct wmi_tx_complete_event) +
427 (index * sizeof(struct tx_complete_msg_v1)); 431 (index * sizeof(struct tx_complete_msg_v1));
@@ -786,12 +790,14 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len,
786 ev->u.ap_sta.keymgmt, 790 ev->u.ap_sta.keymgmt,
787 le16_to_cpu(ev->u.ap_sta.cipher), 791 le16_to_cpu(ev->u.ap_sta.cipher),
788 ev->u.ap_sta.apsd_info); 792 ev->u.ap_sta.apsd_info);
793
789 ath6kl_connect_ap_mode_sta( 794 ath6kl_connect_ap_mode_sta(
790 vif, ev->u.ap_sta.aid, ev->u.ap_sta.mac_addr, 795 vif, ev->u.ap_sta.aid, ev->u.ap_sta.mac_addr,
791 ev->u.ap_sta.keymgmt, 796 ev->u.ap_sta.keymgmt,
792 le16_to_cpu(ev->u.ap_sta.cipher), 797 le16_to_cpu(ev->u.ap_sta.cipher),
793 ev->u.ap_sta.auth, ev->assoc_req_len, 798 ev->u.ap_sta.auth, ev->assoc_req_len,
794 ev->assoc_info + ev->beacon_ie_len); 799 ev->assoc_info + ev->beacon_ie_len,
800 ev->u.ap_sta.apsd_info);
795 } 801 }
796 return 0; 802 return 0;
797 } 803 }
@@ -1145,9 +1151,9 @@ static int ath6kl_wmi_bitrate_reply_rx(struct wmi *wmi, u8 *datap, int len)
1145 return 0; 1151 return 0;
1146} 1152}
1147 1153
1148static int ath6kl_wmi_tcmd_test_report_rx(struct wmi *wmi, u8 *datap, int len) 1154static int ath6kl_wmi_test_rx(struct wmi *wmi, u8 *datap, int len)
1149{ 1155{
1150 ath6kl_tm_rx_report_event(wmi->parent_dev, datap, len); 1156 ath6kl_tm_rx_event(wmi->parent_dev, datap, len);
1151 1157
1152 return 0; 1158 return 0;
1153} 1159}
@@ -2479,15 +2485,16 @@ int ath6kl_wmi_delete_pstream_cmd(struct wmi *wmi, u8 if_idx, u8 traffic_class,
2479 return ret; 2485 return ret;
2480} 2486}
2481 2487
2482int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd) 2488int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx,
2489 __be32 ips0, __be32 ips1)
2483{ 2490{
2484 struct sk_buff *skb; 2491 struct sk_buff *skb;
2485 struct wmi_set_ip_cmd *cmd; 2492 struct wmi_set_ip_cmd *cmd;
2486 int ret; 2493 int ret;
2487 2494
2488 /* Multicast address are not valid */ 2495 /* Multicast address are not valid */
2489 if ((*((u8 *) &ip_cmd->ips[0]) >= 0xE0) || 2496 if (ipv4_is_multicast(ips0) ||
2490 (*((u8 *) &ip_cmd->ips[1]) >= 0xE0)) 2497 ipv4_is_multicast(ips1))
2491 return -EINVAL; 2498 return -EINVAL;
2492 2499
2493 skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_ip_cmd)); 2500 skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_ip_cmd));
@@ -2495,9 +2502,10 @@ int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd)
2495 return -ENOMEM; 2502 return -ENOMEM;
2496 2503
2497 cmd = (struct wmi_set_ip_cmd *) skb->data; 2504 cmd = (struct wmi_set_ip_cmd *) skb->data;
2498 memcpy(cmd, ip_cmd, sizeof(struct wmi_set_ip_cmd)); 2505 cmd->ips[0] = ips0;
2506 cmd->ips[1] = ips1;
2499 2507
2500 ret = ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_IP_CMDID, 2508 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_IP_CMDID,
2501 NO_SYNC_WMIFLAG); 2509 NO_SYNC_WMIFLAG);
2502 return ret; 2510 return ret;
2503} 2511}
@@ -2582,6 +2590,18 @@ int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx,
2582 return ret; 2590 return ret;
2583} 2591}
2584 2592
2593/* This command has zero length payload */
2594static int ath6kl_wmi_host_sleep_mode_cmd_prcd_evt_rx(struct wmi *wmi,
2595 struct ath6kl_vif *vif)
2596{
2597 struct ath6kl *ar = wmi->parent_dev;
2598
2599 set_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags);
2600 wake_up(&ar->event_wq);
2601
2602 return 0;
2603}
2604
2585int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx, 2605int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx,
2586 enum ath6kl_wow_mode wow_mode, 2606 enum ath6kl_wow_mode wow_mode,
2587 u32 filter, u16 host_req_delay) 2607 u32 filter, u16 host_req_delay)
@@ -2612,7 +2632,8 @@ int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx,
2612 2632
2613int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, 2633int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
2614 u8 list_id, u8 filter_size, 2634 u8 list_id, u8 filter_size,
2615 u8 filter_offset, u8 *filter, u8 *mask) 2635 u8 filter_offset, const u8 *filter,
2636 const u8 *mask)
2616{ 2637{
2617 struct sk_buff *skb; 2638 struct sk_buff *skb;
2618 struct wmi_add_wow_pattern_cmd *cmd; 2639 struct wmi_add_wow_pattern_cmd *cmd;
@@ -2853,6 +2874,51 @@ int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len)
2853 return ret; 2874 return ret;
2854} 2875}
2855 2876
2877int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on)
2878{
2879 struct sk_buff *skb;
2880 struct wmi_mcast_filter_cmd *cmd;
2881 int ret;
2882
2883 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2884 if (!skb)
2885 return -ENOMEM;
2886
2887 cmd = (struct wmi_mcast_filter_cmd *) skb->data;
2888 cmd->mcast_all_enable = mc_all_on;
2889
2890 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_MCAST_FILTER_CMDID,
2891 NO_SYNC_WMIFLAG);
2892 return ret;
2893}
2894
2895int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx,
2896 u8 *filter, bool add_filter)
2897{
2898 struct sk_buff *skb;
2899 struct wmi_mcast_filter_add_del_cmd *cmd;
2900 int ret;
2901
2902 if ((filter[0] != 0x33 || filter[1] != 0x33) &&
2903 (filter[0] != 0x01 || filter[1] != 0x00 ||
2904 filter[2] != 0x5e || filter[3] > 0x7f)) {
2905 ath6kl_warn("invalid multicast filter address\n");
2906 return -EINVAL;
2907 }
2908
2909 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2910 if (!skb)
2911 return -ENOMEM;
2912
2913 cmd = (struct wmi_mcast_filter_add_del_cmd *) skb->data;
2914 memcpy(cmd->mcast_mac, filter, ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE);
2915 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
2916 add_filter ? WMI_SET_MCAST_FILTER_CMDID :
2917 WMI_DEL_MCAST_FILTER_CMDID,
2918 NO_SYNC_WMIFLAG);
2919
2920 return ret;
2921}
2856 2922
2857s32 ath6kl_wmi_get_rate(s8 rate_index) 2923s32 ath6kl_wmi_get_rate(s8 rate_index)
2858{ 2924{
@@ -2946,6 +3012,43 @@ int ath6kl_wmi_ap_set_mlme(struct wmi *wmip, u8 if_idx, u8 cmd, const u8 *mac,
2946 NO_SYNC_WMIFLAG); 3012 NO_SYNC_WMIFLAG);
2947} 3013}
2948 3014
3015/* This command will be used to enable/disable AP uAPSD feature */
3016int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable)
3017{
3018 struct wmi_ap_set_apsd_cmd *cmd;
3019 struct sk_buff *skb;
3020
3021 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
3022 if (!skb)
3023 return -ENOMEM;
3024
3025 cmd = (struct wmi_ap_set_apsd_cmd *)skb->data;
3026 cmd->enable = enable;
3027
3028 return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_AP_SET_APSD_CMDID,
3029 NO_SYNC_WMIFLAG);
3030}
3031
3032int ath6kl_wmi_set_apsd_bfrd_traf(struct wmi *wmi, u8 if_idx,
3033 u16 aid, u16 bitmap, u32 flags)
3034{
3035 struct wmi_ap_apsd_buffered_traffic_cmd *cmd;
3036 struct sk_buff *skb;
3037
3038 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
3039 if (!skb)
3040 return -ENOMEM;
3041
3042 cmd = (struct wmi_ap_apsd_buffered_traffic_cmd *)skb->data;
3043 cmd->aid = cpu_to_le16(aid);
3044 cmd->bitmap = cpu_to_le16(bitmap);
3045 cmd->flags = cpu_to_le32(flags);
3046
3047 return ath6kl_wmi_cmd_send(wmi, if_idx, skb,
3048 WMI_AP_APSD_BUFFERED_TRAFFIC_CMDID,
3049 NO_SYNC_WMIFLAG);
3050}
3051
2949static int ath6kl_wmi_pspoll_event_rx(struct wmi *wmi, u8 *datap, int len, 3052static int ath6kl_wmi_pspoll_event_rx(struct wmi *wmi, u8 *datap, int len,
2950 struct ath6kl_vif *vif) 3053 struct ath6kl_vif *vif)
2951{ 3054{
@@ -3400,7 +3503,7 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
3400 break; 3503 break;
3401 case WMI_TEST_EVENTID: 3504 case WMI_TEST_EVENTID:
3402 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TEST_EVENTID\n"); 3505 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TEST_EVENTID\n");
3403 ret = ath6kl_wmi_tcmd_test_report_rx(wmi, datap, len); 3506 ret = ath6kl_wmi_test_rx(wmi, datap, len);
3404 break; 3507 break;
3405 case WMI_GET_FIXRATES_CMDID: 3508 case WMI_GET_FIXRATES_CMDID:
3406 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_FIXRATES_CMDID\n"); 3509 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_FIXRATES_CMDID\n");
@@ -3465,6 +3568,11 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
3465 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_COMPLETE_EVENTID\n"); 3568 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_COMPLETE_EVENTID\n");
3466 ret = ath6kl_wmi_tx_complete_event_rx(datap, len); 3569 ret = ath6kl_wmi_tx_complete_event_rx(datap, len);
3467 break; 3570 break;
3571 case WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENTID:
3572 ath6kl_dbg(ATH6KL_DBG_WMI,
3573 "WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENTID");
3574 ret = ath6kl_wmi_host_sleep_mode_cmd_prcd_evt_rx(wmi, vif);
3575 break;
3468 case WMI_REMAIN_ON_CHNL_EVENTID: 3576 case WMI_REMAIN_ON_CHNL_EVENTID:
3469 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REMAIN_ON_CHNL_EVENTID\n"); 3577 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REMAIN_ON_CHNL_EVENTID\n");
3470 ret = ath6kl_wmi_remain_on_chnl_event_rx(wmi, datap, len, vif); 3578 ret = ath6kl_wmi_remain_on_chnl_event_rx(wmi, datap, len, vif);