Commit 6251d801 authored by Naveen Gangadharan's avatar Naveen Gangadharan Committed by Kalle Valo

ath6kl: Multicast filter support in wow suspend and non-suspend

This patch enables all multicast packets in non suspend mode
and enable multicast filtering in wow suspend mode. This also
fixes a bug in multicast where the driver assumed disable
multicast-all command disabled/filtered all multicast
packets, which was wrong assumption, because firmware will
apply the programmed filter.

Multicast requirements
 - Enable forward all multicast packets(no filtering) in
      non suspend mode.
 - Enable multicast filtering in wow suspend mode for both
      AP and CLIENT.

kvalo: fix a checkpatch warning and drop unrelated newline removal
Signed-off-by: default avatarNaveen Gangadharan <ngangadh@qca.qualcomm.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 03e2084a
...@@ -2076,6 +2076,13 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) ...@@ -2076,6 +2076,13 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST)) if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST))
return -EINVAL; return -EINVAL;
if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags)) {
ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi,
vif->fw_vif_idx, false);
if (ret)
return ret;
}
/* Clear existing WOW patterns */ /* Clear existing WOW patterns */
for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++) for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++)
ath6kl_wmi_del_wow_pattern_cmd(ar->wmi, vif->fw_vif_idx, 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,6 +2211,13 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
ar->state = ATH6KL_STATE_ON; ar->state = ATH6KL_STATE_ON;
if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags)) {
ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi,
vif->fw_vif_idx, true);
if (ret)
return ret;
}
netif_wake_queue(vif->ndev); netif_wake_queue(vif->ndev);
return 0; return 0;
......
...@@ -510,6 +510,8 @@ enum ath6kl_vif_state { ...@@ -510,6 +510,8 @@ enum ath6kl_vif_state {
WLAN_ENABLED, WLAN_ENABLED,
STATS_UPDATE_PEND, STATS_UPDATE_PEND,
HOST_SLEEP_MODE_CMD_PROCESSED, HOST_SLEEP_MODE_CMD_PROCESSED,
NETDEV_MCAST_ALL_ON,
NETDEV_MCAST_ALL_OFF,
}; };
struct ath6kl_vif { struct ath6kl_vif {
......
...@@ -1145,7 +1145,7 @@ static int ath6kl_set_features(struct net_device *dev, ...@@ -1145,7 +1145,7 @@ static int ath6kl_set_features(struct net_device *dev,
static void ath6kl_set_multicast_list(struct net_device *ndev) static void ath6kl_set_multicast_list(struct net_device *ndev)
{ {
struct ath6kl_vif *vif = netdev_priv(ndev); struct ath6kl_vif *vif = netdev_priv(ndev);
bool mc_all_on = false, mc_all_off = false; bool mc_all_on = false;
int mc_count = netdev_mc_count(ndev); int mc_count = netdev_mc_count(ndev);
struct netdev_hw_addr *ha; struct netdev_hw_addr *ha;
bool found; bool found;
...@@ -1157,24 +1157,41 @@ static void ath6kl_set_multicast_list(struct net_device *ndev) ...@@ -1157,24 +1157,41 @@ static void ath6kl_set_multicast_list(struct net_device *ndev)
!test_bit(WLAN_ENABLED, &vif->flags)) !test_bit(WLAN_ENABLED, &vif->flags))
return; return;
/* Enable multicast-all filter. */
mc_all_on = !!(ndev->flags & IFF_PROMISC) || mc_all_on = !!(ndev->flags & IFF_PROMISC) ||
!!(ndev->flags & IFF_ALLMULTI) || !!(ndev->flags & IFF_ALLMULTI) ||
!!(mc_count > ATH6K_MAX_MC_FILTERS_PER_LIST); !!(mc_count > ATH6K_MAX_MC_FILTERS_PER_LIST);
mc_all_off = !(ndev->flags & IFF_MULTICAST) || mc_count == 0; if (mc_all_on)
set_bit(NETDEV_MCAST_ALL_ON, &vif->flags);
else
clear_bit(NETDEV_MCAST_ALL_ON, &vif->flags);
if (mc_all_on || mc_all_off) { mc_all_on = mc_all_on || (vif->ar->state == ATH6KL_STATE_ON);
/* Enable/disable all multicast */
ath6kl_dbg(ATH6KL_DBG_TRC, "%s multicast filter\n", if (!(ndev->flags & IFF_MULTICAST)) {
mc_all_on ? "enabling" : "disabling"); mc_all_on = false;
ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, vif->fw_vif_idx, set_bit(NETDEV_MCAST_ALL_OFF, &vif->flags);
} else {
clear_bit(NETDEV_MCAST_ALL_OFF, &vif->flags);
}
/* Enable/disable "multicast-all" filter*/
ath6kl_dbg(ATH6KL_DBG_TRC, "%s multicast-all filter\n",
mc_all_on ? "enabling" : "disabling");
ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, vif->fw_vif_idx,
mc_all_on); mc_all_on);
if (ret) if (ret) {
ath6kl_warn("Failed to %s multicast receive\n", ath6kl_warn("Failed to %s multicast-all receive\n",
mc_all_on ? "enable" : "disable"); mc_all_on ? "enable" : "disable");
return; return;
} }
if (test_bit(NETDEV_MCAST_ALL_ON, &vif->flags))
return;
/* Keep the driver and firmware mcast list in sync. */
list_for_each_entry_safe(mc_filter, tmp, &vif->mc_filter, list) { list_for_each_entry_safe(mc_filter, tmp, &vif->mc_filter, list) {
found = false; found = false;
netdev_for_each_mc_addr(ha, ndev) { netdev_for_each_mc_addr(ha, ndev) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment