aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath6kl/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath6kl/main.c')
-rw-r--r--drivers/net/wireless/ath/ath6kl/main.c182
1 files changed, 164 insertions, 18 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index eea3c747653e..b96d01a7919b 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -52,9 +52,11 @@ struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid)
52 return conn; 52 return conn;
53} 53}
54 54
55static void ath6kl_add_new_sta(struct ath6kl *ar, u8 *mac, u16 aid, u8 *wpaie, 55static void ath6kl_add_new_sta(struct ath6kl_vif *vif, u8 *mac, u16 aid,
56 u8 ielen, u8 keymgmt, u8 ucipher, u8 auth) 56 u8 *wpaie, size_t ielen, u8 keymgmt,
57 u8 ucipher, u8 auth, u8 apsd_info)
57{ 58{
59 struct ath6kl *ar = vif->ar;
58 struct ath6kl_sta *sta; 60 struct ath6kl_sta *sta;
59 u8 free_slot; 61 u8 free_slot;
60 62
@@ -68,9 +70,11 @@ static void ath6kl_add_new_sta(struct ath6kl *ar, u8 *mac, u16 aid, u8 *wpaie,
68 sta->keymgmt = keymgmt; 70 sta->keymgmt = keymgmt;
69 sta->ucipher = ucipher; 71 sta->ucipher = ucipher;
70 sta->auth = auth; 72 sta->auth = auth;
73 sta->apsd_info = apsd_info;
71 74
72 ar->sta_list_index = ar->sta_list_index | (1 << free_slot); 75 ar->sta_list_index = ar->sta_list_index | (1 << free_slot);
73 ar->ap_stats.sta[free_slot].aid = cpu_to_le32(aid); 76 ar->ap_stats.sta[free_slot].aid = cpu_to_le32(aid);
77 aggr_conn_init(vif, vif->aggr_cntxt, sta->aggr_conn);
74} 78}
75 79
76static void ath6kl_sta_cleanup(struct ath6kl *ar, u8 i) 80static void ath6kl_sta_cleanup(struct ath6kl *ar, u8 i)
@@ -80,6 +84,7 @@ static void ath6kl_sta_cleanup(struct ath6kl *ar, u8 i)
80 /* empty the queued pkts in the PS queue if any */ 84 /* empty the queued pkts in the PS queue if any */
81 spin_lock_bh(&sta->psq_lock); 85 spin_lock_bh(&sta->psq_lock);
82 skb_queue_purge(&sta->psq); 86 skb_queue_purge(&sta->psq);
87 skb_queue_purge(&sta->apsdq);
83 spin_unlock_bh(&sta->psq_lock); 88 spin_unlock_bh(&sta->psq_lock);
84 89
85 memset(&ar->ap_stats.sta[sta->aid - 1], 0, 90 memset(&ar->ap_stats.sta[sta->aid - 1], 0,
@@ -90,7 +95,7 @@ static void ath6kl_sta_cleanup(struct ath6kl *ar, u8 i)
90 sta->sta_flags = 0; 95 sta->sta_flags = 0;
91 96
92 ar->sta_list_index = ar->sta_list_index & ~(1 << i); 97 ar->sta_list_index = ar->sta_list_index & ~(1 << i);
93 98 aggr_reset_state(sta->aggr_conn);
94} 99}
95 100
96static u8 ath6kl_remove_sta(struct ath6kl *ar, u8 *mac, u16 reason) 101static u8 ath6kl_remove_sta(struct ath6kl *ar, u8 *mac, u16 reason)
@@ -252,7 +257,7 @@ int ath6kl_read_fwlogs(struct ath6kl *ar)
252 struct ath6kl_dbglog_hdr debug_hdr; 257 struct ath6kl_dbglog_hdr debug_hdr;
253 struct ath6kl_dbglog_buf debug_buf; 258 struct ath6kl_dbglog_buf debug_buf;
254 u32 address, length, dropped, firstbuf, debug_hdr_addr; 259 u32 address, length, dropped, firstbuf, debug_hdr_addr;
255 int ret = 0, loop; 260 int ret, loop;
256 u8 *buf; 261 u8 *buf;
257 262
258 buf = kmalloc(ATH6KL_FWLOG_PAYLOAD_SIZE, GFP_KERNEL); 263 buf = kmalloc(ATH6KL_FWLOG_PAYLOAD_SIZE, GFP_KERNEL);
@@ -347,9 +352,6 @@ void ath6kl_reset_device(struct ath6kl *ar, u32 target_type,
347 case TARGET_TYPE_AR6004: 352 case TARGET_TYPE_AR6004:
348 address = AR6004_RESET_CONTROL_ADDRESS; 353 address = AR6004_RESET_CONTROL_ADDRESS;
349 break; 354 break;
350 default:
351 address = AR6003_RESET_CONTROL_ADDRESS;
352 break;
353 } 355 }
354 356
355 status = ath6kl_diag_write32(ar, address, data); 357 status = ath6kl_diag_write32(ar, address, data);
@@ -363,7 +365,7 @@ static void ath6kl_install_static_wep_keys(struct ath6kl_vif *vif)
363 u8 index; 365 u8 index;
364 u8 keyusage; 366 u8 keyusage;
365 367
366 for (index = WMI_MIN_KEY_INDEX; index <= WMI_MAX_KEY_INDEX; index++) { 368 for (index = 0; index <= WMI_MAX_KEY_INDEX; index++) {
367 if (vif->wep_key_list[index].key_len) { 369 if (vif->wep_key_list[index].key_len) {
368 keyusage = GROUP_USAGE; 370 keyusage = GROUP_USAGE;
369 if (index == vif->def_txkey_index) 371 if (index == vif->def_txkey_index)
@@ -428,9 +430,8 @@ void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel)
428 430
429void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr, 431void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr,
430 u8 keymgmt, u8 ucipher, u8 auth, 432 u8 keymgmt, u8 ucipher, u8 auth,
431 u8 assoc_req_len, u8 *assoc_info) 433 u8 assoc_req_len, u8 *assoc_info, u8 apsd_info)
432{ 434{
433 struct ath6kl *ar = vif->ar;
434 u8 *ies = NULL, *wpa_ie = NULL, *pos; 435 u8 *ies = NULL, *wpa_ie = NULL, *pos;
435 size_t ies_len = 0; 436 size_t ies_len = 0;
436 struct station_info sinfo; 437 struct station_info sinfo;
@@ -484,9 +485,9 @@ void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr,
484 pos += 2 + pos[1]; 485 pos += 2 + pos[1];
485 } 486 }
486 487
487 ath6kl_add_new_sta(ar, mac_addr, aid, wpa_ie, 488 ath6kl_add_new_sta(vif, mac_addr, aid, wpa_ie,
488 wpa_ie ? 2 + wpa_ie[1] : 0, 489 wpa_ie ? 2 + wpa_ie[1] : 0,
489 keymgmt, ucipher, auth); 490 keymgmt, ucipher, auth, apsd_info);
490 491
491 /* send event to application */ 492 /* send event to application */
492 memset(&sinfo, 0, sizeof(sinfo)); 493 memset(&sinfo, 0, sizeof(sinfo));
@@ -587,10 +588,11 @@ void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, u8 *bssid,
587 memcpy(vif->bssid, bssid, sizeof(vif->bssid)); 588 memcpy(vif->bssid, bssid, sizeof(vif->bssid));
588 vif->bss_ch = channel; 589 vif->bss_ch = channel;
589 590
590 if ((vif->nw_type == INFRA_NETWORK)) 591 if ((vif->nw_type == INFRA_NETWORK)) {
592 ar->listen_intvl_b = listen_int;
591 ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx, 593 ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
592 ar->listen_intvl_t, 594 0, ar->listen_intvl_b);
593 ar->listen_intvl_b); 595 }
594 596
595 netif_wake_queue(vif->ndev); 597 netif_wake_queue(vif->ndev);
596 598
@@ -601,7 +603,7 @@ void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, u8 *bssid,
601 netif_carrier_on(vif->ndev); 603 netif_carrier_on(vif->ndev);
602 spin_unlock_bh(&vif->if_lock); 604 spin_unlock_bh(&vif->if_lock);
603 605
604 aggr_reset_state(vif->aggr_cntxt); 606 aggr_reset_state(vif->aggr_cntxt->aggr_conn);
605 vif->reconnect_flag = 0; 607 vif->reconnect_flag = 0;
606 608
607 if ((vif->nw_type == ADHOC_NETWORK) && ar->ibss_ps_enable) { 609 if ((vif->nw_type == ADHOC_NETWORK) && ar->ibss_ps_enable) {
@@ -923,7 +925,7 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid,
923 assoc_resp_len, assoc_info, 925 assoc_resp_len, assoc_info,
924 prot_reason_status); 926 prot_reason_status);
925 927
926 aggr_reset_state(vif->aggr_cntxt); 928 aggr_reset_state(vif->aggr_cntxt->aggr_conn);
927 929
928 del_timer(&vif->disconnect_timer); 930 del_timer(&vif->disconnect_timer);
929 931
@@ -1020,11 +1022,155 @@ static struct net_device_stats *ath6kl_get_stats(struct net_device *dev)
1020 return &vif->net_stats; 1022 return &vif->net_stats;
1021} 1023}
1022 1024
1023static struct net_device_ops ath6kl_netdev_ops = { 1025static int ath6kl_set_features(struct net_device *dev,
1026 netdev_features_t features)
1027{
1028 struct ath6kl_vif *vif = netdev_priv(dev);
1029 struct ath6kl *ar = vif->ar;
1030 int err = 0;
1031
1032 if ((features & NETIF_F_RXCSUM) &&
1033 (ar->rx_meta_ver != WMI_META_VERSION_2)) {
1034 ar->rx_meta_ver = WMI_META_VERSION_2;
1035 err = ath6kl_wmi_set_rx_frame_format_cmd(ar->wmi,
1036 vif->fw_vif_idx,
1037 ar->rx_meta_ver, 0, 0);
1038 if (err) {
1039 dev->features = features & ~NETIF_F_RXCSUM;
1040 return err;
1041 }
1042 } else if (!(features & NETIF_F_RXCSUM) &&
1043 (ar->rx_meta_ver == WMI_META_VERSION_2)) {
1044 ar->rx_meta_ver = 0;
1045 err = ath6kl_wmi_set_rx_frame_format_cmd(ar->wmi,
1046 vif->fw_vif_idx,
1047 ar->rx_meta_ver, 0, 0);
1048 if (err) {
1049 dev->features = features | NETIF_F_RXCSUM;
1050 return err;
1051 }
1052
1053 }
1054
1055 return err;
1056}
1057
1058static void ath6kl_set_multicast_list(struct net_device *ndev)
1059{
1060 struct ath6kl_vif *vif = netdev_priv(ndev);
1061 bool mc_all_on = false, mc_all_off = false;
1062 int mc_count = netdev_mc_count(ndev);
1063 struct netdev_hw_addr *ha;
1064 bool found;
1065 struct ath6kl_mc_filter *mc_filter, *tmp;
1066 struct list_head mc_filter_new;
1067 int ret;
1068
1069 if (!test_bit(WMI_READY, &vif->ar->flag) ||
1070 !test_bit(WLAN_ENABLED, &vif->flags))
1071 return;
1072
1073 mc_all_on = !!(ndev->flags & IFF_PROMISC) ||
1074 !!(ndev->flags & IFF_ALLMULTI) ||
1075 !!(mc_count > ATH6K_MAX_MC_FILTERS_PER_LIST);
1076
1077 mc_all_off = !(ndev->flags & IFF_MULTICAST) || mc_count == 0;
1078
1079 if (mc_all_on || mc_all_off) {
1080 /* Enable/disable all multicast */
1081 ath6kl_dbg(ATH6KL_DBG_TRC, "%s multicast filter\n",
1082 mc_all_on ? "enabling" : "disabling");
1083 ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, vif->fw_vif_idx,
1084 mc_all_on);
1085 if (ret)
1086 ath6kl_warn("Failed to %s multicast receive\n",
1087 mc_all_on ? "enable" : "disable");
1088 return;
1089 }
1090
1091 list_for_each_entry_safe(mc_filter, tmp, &vif->mc_filter, list) {
1092 found = false;
1093 netdev_for_each_mc_addr(ha, ndev) {
1094 if (memcmp(ha->addr, mc_filter->hw_addr,
1095 ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE) == 0) {
1096 found = true;
1097 break;
1098 }
1099 }
1100
1101 if (!found) {
1102 /*
1103 * Delete the filter which was previously set
1104 * but not in the new request.
1105 */
1106 ath6kl_dbg(ATH6KL_DBG_TRC,
1107 "Removing %pM from multicast filter\n",
1108 mc_filter->hw_addr);
1109 ret = ath6kl_wmi_add_del_mcast_filter_cmd(vif->ar->wmi,
1110 vif->fw_vif_idx, mc_filter->hw_addr,
1111 false);
1112 if (ret) {
1113 ath6kl_warn("Failed to remove multicast filter:%pM\n",
1114 mc_filter->hw_addr);
1115 return;
1116 }
1117
1118 list_del(&mc_filter->list);
1119 kfree(mc_filter);
1120 }
1121 }
1122
1123 INIT_LIST_HEAD(&mc_filter_new);
1124
1125 netdev_for_each_mc_addr(ha, ndev) {
1126 found = false;
1127 list_for_each_entry(mc_filter, &vif->mc_filter, list) {
1128 if (memcmp(ha->addr, mc_filter->hw_addr,
1129 ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE) == 0) {
1130 found = true;
1131 break;
1132 }
1133 }
1134
1135 if (!found) {
1136 mc_filter = kzalloc(sizeof(struct ath6kl_mc_filter),
1137 GFP_ATOMIC);
1138 if (!mc_filter) {
1139 WARN_ON(1);
1140 goto out;
1141 }
1142
1143 memcpy(mc_filter->hw_addr, ha->addr,
1144 ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE);
1145 /* Set the multicast filter */
1146 ath6kl_dbg(ATH6KL_DBG_TRC,
1147 "Adding %pM to multicast filter list\n",
1148 mc_filter->hw_addr);
1149 ret = ath6kl_wmi_add_del_mcast_filter_cmd(vif->ar->wmi,
1150 vif->fw_vif_idx, mc_filter->hw_addr,
1151 true);
1152 if (ret) {
1153 ath6kl_warn("Failed to add multicast filter :%pM\n",
1154 mc_filter->hw_addr);
1155 kfree(mc_filter);
1156 goto out;
1157 }
1158
1159 list_add_tail(&mc_filter->list, &mc_filter_new);
1160 }
1161 }
1162
1163out:
1164 list_splice_tail(&mc_filter_new, &vif->mc_filter);
1165}
1166
1167static const struct net_device_ops ath6kl_netdev_ops = {
1024 .ndo_open = ath6kl_open, 1168 .ndo_open = ath6kl_open,
1025 .ndo_stop = ath6kl_close, 1169 .ndo_stop = ath6kl_close,
1026 .ndo_start_xmit = ath6kl_data_tx, 1170 .ndo_start_xmit = ath6kl_data_tx,
1027 .ndo_get_stats = ath6kl_get_stats, 1171 .ndo_get_stats = ath6kl_get_stats,
1172 .ndo_set_features = ath6kl_set_features,
1173 .ndo_set_rx_mode = ath6kl_set_multicast_list,
1028}; 1174};
1029 1175
1030void init_netdev(struct net_device *dev) 1176void init_netdev(struct net_device *dev)