aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c14
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.h2
-rw-r--r--drivers/net/wireless/ath/ath6kl/main.c37
3 files changed, 43 insertions, 10 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index d4172137499a..f4467733ff5b 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -2076,6 +2076,13 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
2076 if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST)) 2076 if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST))
2077 return -EINVAL; 2077 return -EINVAL;
2078 2078
2079 if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags)) {
2080 ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi,
2081 vif->fw_vif_idx, false);
2082 if (ret)
2083 return ret;
2084 }
2085
2079 /* Clear existing WOW patterns */ 2086 /* Clear existing WOW patterns */
2080 for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++) 2087 for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++)
2081 ath6kl_wmi_del_wow_pattern_cmd(ar->wmi, vif->fw_vif_idx, 2088 ath6kl_wmi_del_wow_pattern_cmd(ar->wmi, vif->fw_vif_idx,
@@ -2204,6 +2211,13 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
2204 2211
2205 ar->state = ATH6KL_STATE_ON; 2212 ar->state = ATH6KL_STATE_ON;
2206 2213
2214 if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags)) {
2215 ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi,
2216 vif->fw_vif_idx, true);
2217 if (ret)
2218 return ret;
2219 }
2220
2207 netif_wake_queue(vif->ndev); 2221 netif_wake_queue(vif->ndev);
2208 2222
2209 return 0; 2223 return 0;
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index c26f0a269168..4d9c6f142698 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -510,6 +510,8 @@ enum ath6kl_vif_state {
510 WLAN_ENABLED, 510 WLAN_ENABLED,
511 STATS_UPDATE_PEND, 511 STATS_UPDATE_PEND,
512 HOST_SLEEP_MODE_CMD_PROCESSED, 512 HOST_SLEEP_MODE_CMD_PROCESSED,
513 NETDEV_MCAST_ALL_ON,
514 NETDEV_MCAST_ALL_OFF,
513}; 515};
514 516
515struct ath6kl_vif { 517struct ath6kl_vif {
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index ff0b999f6f66..e5524470529c 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -1145,7 +1145,7 @@ static int ath6kl_set_features(struct net_device *dev,
1145static void ath6kl_set_multicast_list(struct net_device *ndev) 1145static void ath6kl_set_multicast_list(struct net_device *ndev)
1146{ 1146{
1147 struct ath6kl_vif *vif = netdev_priv(ndev); 1147 struct ath6kl_vif *vif = netdev_priv(ndev);
1148 bool mc_all_on = false, mc_all_off = false; 1148 bool mc_all_on = false;
1149 int mc_count = netdev_mc_count(ndev); 1149 int mc_count = netdev_mc_count(ndev);
1150 struct netdev_hw_addr *ha; 1150 struct netdev_hw_addr *ha;
1151 bool found; 1151 bool found;
@@ -1157,24 +1157,41 @@ static void ath6kl_set_multicast_list(struct net_device *ndev)
1157 !test_bit(WLAN_ENABLED, &vif->flags)) 1157 !test_bit(WLAN_ENABLED, &vif->flags))
1158 return; 1158 return;
1159 1159
1160 /* Enable multicast-all filter. */
1160 mc_all_on = !!(ndev->flags & IFF_PROMISC) || 1161 mc_all_on = !!(ndev->flags & IFF_PROMISC) ||
1161 !!(ndev->flags & IFF_ALLMULTI) || 1162 !!(ndev->flags & IFF_ALLMULTI) ||
1162 !!(mc_count > ATH6K_MAX_MC_FILTERS_PER_LIST); 1163 !!(mc_count > ATH6K_MAX_MC_FILTERS_PER_LIST);
1163 1164
1164 mc_all_off = !(ndev->flags & IFF_MULTICAST) || mc_count == 0; 1165 if (mc_all_on)
1166 set_bit(NETDEV_MCAST_ALL_ON, &vif->flags);
1167 else
1168 clear_bit(NETDEV_MCAST_ALL_ON, &vif->flags);
1165 1169
1166 if (mc_all_on || mc_all_off) { 1170 mc_all_on = mc_all_on || (vif->ar->state == ATH6KL_STATE_ON);
1167 /* Enable/disable all multicast */ 1171
1168 ath6kl_dbg(ATH6KL_DBG_TRC, "%s multicast filter\n", 1172 if (!(ndev->flags & IFF_MULTICAST)) {
1169 mc_all_on ? "enabling" : "disabling"); 1173 mc_all_on = false;
1170 ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, vif->fw_vif_idx, 1174 set_bit(NETDEV_MCAST_ALL_OFF, &vif->flags);
1175 } else {
1176 clear_bit(NETDEV_MCAST_ALL_OFF, &vif->flags);
1177 }
1178
1179 /* Enable/disable "multicast-all" filter*/
1180 ath6kl_dbg(ATH6KL_DBG_TRC, "%s multicast-all filter\n",
1181 mc_all_on ? "enabling" : "disabling");
1182
1183 ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, vif->fw_vif_idx,
1171 mc_all_on); 1184 mc_all_on);
1172 if (ret) 1185 if (ret) {
1173 ath6kl_warn("Failed to %s multicast receive\n", 1186 ath6kl_warn("Failed to %s multicast-all receive\n",
1174 mc_all_on ? "enable" : "disable"); 1187 mc_all_on ? "enable" : "disable");
1175 return; 1188 return;
1176 } 1189 }
1177 1190
1191 if (test_bit(NETDEV_MCAST_ALL_ON, &vif->flags))
1192 return;
1193
1194 /* Keep the driver and firmware mcast list in sync. */
1178 list_for_each_entry_safe(mc_filter, tmp, &vif->mc_filter, list) { 1195 list_for_each_entry_safe(mc_filter, tmp, &vif->mc_filter, list) {
1179 found = false; 1196 found = false;
1180 netdev_for_each_mc_addr(ha, ndev) { 1197 netdev_for_each_mc_addr(ha, ndev) {