diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath6kl/wmi.c')
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/wmi.c | 148 |
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 | ||
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, |
@@ -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 | ||
1148 | static int ath6kl_wmi_tcmd_test_report_rx(struct wmi *wmi, u8 *datap, int len) | 1154 | static 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 | ||
2482 | int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd) | 2488 | int 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 */ | ||
2594 | static 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 | |||
2585 | int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx, | 2605 | int 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 | ||
2613 | int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, | 2633 | int 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 | ||
2877 | int 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 | |||
2895 | int 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 | ||
2857 | s32 ath6kl_wmi_get_rate(s8 rate_index) | 2923 | s32 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 */ | ||
3016 | int 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 | |||
3032 | int 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 | |||
2949 | static int ath6kl_wmi_pspoll_event_rx(struct wmi *wmi, u8 *datap, int len, | 3052 | static 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); |