Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -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,
@@ -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;
+2 −0
Original line number Diff line number Diff line
@@ -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 {
+27 −10
Original line number Diff line number Diff line
@@ -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;
@@ -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 = 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",
	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) {