Skip to content

Commit

Permalink
ath6kl: Multicast filter support in wow suspend and non-suspend
Browse files Browse the repository at this point in the history
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: Naveen Gangadharan <ngangadh@qca.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
  • Loading branch information
Naveen Gangadharan authored and Kalle Valo committed Apr 26, 2012
1 parent 03e2084 commit 6251d80
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 10 deletions.
14 changes: 14 additions & 0 deletions drivers/net/wireless/ath/ath6kl/cfg80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
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 */
for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++)
ath6kl_wmi_del_wow_pattern_cmd(ar->wmi, vif->fw_vif_idx,
Expand Down Expand Up @@ -2204,6 +2211,13 @@ static int ath6kl_wow_resume(struct ath6kl *ar)

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);

return 0;
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/wireless/ath/ath6kl/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,8 @@ enum ath6kl_vif_state {
WLAN_ENABLED,
STATS_UPDATE_PEND,
HOST_SLEEP_MODE_CMD_PROCESSED,
NETDEV_MCAST_ALL_ON,
NETDEV_MCAST_ALL_OFF,
};

struct ath6kl_vif {
Expand Down
37 changes: 27 additions & 10 deletions drivers/net/wireless/ath/ath6kl/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1145,7 +1145,7 @@ static int ath6kl_set_features(struct net_device *dev,
static void ath6kl_set_multicast_list(struct net_device *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);
struct netdev_hw_addr *ha;
bool found;
Expand All @@ -1157,24 +1157,41 @@ static void ath6kl_set_multicast_list(struct net_device *ndev)
!test_bit(WLAN_ENABLED, &vif->flags))
return;

/* Enable multicast-all filter. */
mc_all_on = !!(ndev->flags & IFF_PROMISC) ||
!!(ndev->flags & IFF_ALLMULTI) ||
!!(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) {
/* Enable/disable all multicast */
ath6kl_dbg(ATH6KL_DBG_TRC, "%s multicast 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 || (vif->ar->state == ATH6KL_STATE_ON);

if (!(ndev->flags & IFF_MULTICAST)) {
mc_all_on = false;
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);
if (ret)
ath6kl_warn("Failed to %s multicast receive\n",
mc_all_on ? "enable" : "disable");
if (ret) {
ath6kl_warn("Failed to %s multicast-all receive\n",
mc_all_on ? "enable" : "disable");
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) {
found = false;
netdev_for_each_mc_addr(ha, ndev) {
Expand Down

0 comments on commit 6251d80

Please sign in to comment.