Search Linux Wireless

Re: [PATCH V2 13/13] brcmfmac: add arp offload ip address table configuration support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 12/10/2015 01:43 PM, Arend van Spriel wrote:
From: Franky Lin <frankyl@xxxxxxxxxxxx>

Obtain ipv4 address through inetaddr notification for ARP offload host
ip table configuration.

Turns out this patch has a sparse warning, ie. would not work on big-endian system. We have a fix for that. Should I mark this patch as dropped in patchwork?

Regards,
Arend

Signed-off-by: Franky Lin <frankyl@xxxxxxxxxxxx>
Signed-off-by: Arend van Spriel <arend@xxxxxxxxxxxx>
---
  .../wireless/broadcom/brcm80211/brcmfmac/core.c    | 108 +++++++++++++++++++++
  .../wireless/broadcom/brcm80211/brcmfmac/core.h    |   2 +
  2 files changed, 110 insertions(+)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index 3a39192..2631f6f 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -17,6 +17,7 @@
  #include <linux/kernel.h>
  #include <linux/etherdevice.h>
  #include <linux/module.h>
+#include <linux/inetdevice.h>
  #include <net/cfg80211.h>
  #include <net/rtnetlink.h>
  #include <brcmu_utils.h>
@@ -620,6 +621,8 @@ static int brcmf_netdev_stop(struct net_device *ndev)

  	brcmf_cfg80211_down(ndev);

+	brcmf_fil_iovar_data_set(ifp, "arp_hostip_clear", NULL, 0);
+
  	brcmf_net_setcarrier(ifp, false);

  	return 0;
@@ -940,6 +943,98 @@ int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr)
  	return available ? bsscfgidx : -ENOMEM;
  }

+#ifdef CONFIG_INET
+#define ARPOL_MAX_ENTRIES	8
+static int brcmf_inetaddr_changed(struct notifier_block *nb,
+				  unsigned long action, void *data)
+{
+	struct brcmf_pub *drvr = container_of(nb, struct brcmf_pub,
+					      inetaddr_notifier);
+	struct in_ifaddr *ifa = data;
+	struct net_device *ndev = ifa->ifa_dev->dev;
+	struct brcmf_if *ifp;
+	int idx, i, ret;
+	u32 val;
+	u32 addr_table[ARPOL_MAX_ENTRIES] = {0};
+
+	/* Find out if the notification is meant for us */
+	for (idx = 0; idx < BRCMF_MAX_IFS; idx++) {
+		ifp = drvr->iflist[idx];
+		if (ifp && ifp->ndev == ndev)
+			break;
+		if (idx == BRCMF_MAX_IFS - 1)
+			return NOTIFY_DONE;
+	}
+
+	/* check if arp offload is supported */
+	ret = brcmf_fil_iovar_int_get(ifp, "arpoe", &val);
+	if (ret)
+		return NOTIFY_OK;
+
+	/* old version only support primary index */
+	ret = brcmf_fil_iovar_int_get(ifp, "arp_version", &val);
+	if (ret)
+		val = 1;
+	if (val == 1)
+		ifp = drvr->iflist[0];
+
+	/* retrieve the table from firmware */
+	ret = brcmf_fil_iovar_data_get(ifp, "arp_hostip", addr_table,
+				       sizeof(addr_table));
+	if (ret) {
+		brcmf_err("fail to get arp ip table err:%d\n", ret);
+		return NOTIFY_OK;
+	}
+
+	for (i = 0; i < ARPOL_MAX_ENTRIES; i++)
+		if (ifa->ifa_address == addr_table[i])
+			break;
+
+	switch (action) {
+	case NETDEV_UP:
+		if (i == ARPOL_MAX_ENTRIES) {
+			brcmf_dbg(TRACE, "add %pI4 to arp table\n",
+				  &ifa->ifa_address);
+			/* set it directly */
+			ret = brcmf_fil_iovar_int_set(ifp, "arp_hostip",
+						      ifa->ifa_address);
+			if (ret)
+				brcmf_err("add arp ip err %d\n", ret);
+		}
+		break;
+	case NETDEV_DOWN:
+		if (i < ARPOL_MAX_ENTRIES) {
+			addr_table[i] = 0;
+			brcmf_dbg(TRACE, "remove %pI4 from arp table\n",
+				  &ifa->ifa_address);
+			/* clear the table in firmware */
+			ret = brcmf_fil_iovar_data_set(ifp, "arp_hostip_clear",
+						       NULL, 0);
+			if (ret) {
+				brcmf_err("fail to clear arp ip table err:%d\n",
+					  ret);
+				return NOTIFY_OK;
+			}
+			for (i = 0; i < ARPOL_MAX_ENTRIES; i++) {
+				if (addr_table[i] != 0) {
+					brcmf_fil_iovar_int_set(ifp,
+								"arp_hostip",
+								addr_table[i]);
+					if (ret)
+						brcmf_err("add arp ip err %d\n",
+							  ret);
+				}
+			}
+		}
+		break;
+	default:
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+#endif
+
  int brcmf_attach(struct device *dev)
  {
  	struct brcmf_pub *drvr = NULL;
@@ -1068,6 +1163,15 @@ int brcmf_bus_start(struct device *dev)
  		if (p2p_ifp)
  			ret = brcmf_net_p2p_attach(p2p_ifp);
  	}
+
+	if (ret)
+		goto fail;
+
+#ifdef CONFIG_INET
+	drvr->inetaddr_notifier.notifier_call = brcmf_inetaddr_changed;
+	ret = register_inetaddr_notifier(&drvr->inetaddr_notifier);
+#endif
+
  fail:
  	if (ret < 0) {
  		brcmf_err("failed: %d\n", ret);
@@ -1133,6 +1237,10 @@ void brcmf_detach(struct device *dev)
  	if (drvr == NULL)
  		return;

+#ifdef CONFIG_INET
+	unregister_inetaddr_notifier(&drvr->inetaddr_notifier);
+#endif
+
  	/* stop firmware event handling */
  	brcmf_fweh_detach(drvr);
  	if (drvr->config)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
index 77d8239..6018af7 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
@@ -141,6 +141,8 @@ struct brcmf_pub {
  #ifdef DEBUG
  	struct dentry *dbgfs_dir;
  #endif
+
+	struct notifier_block inetaddr_notifier;
  };

  /* forward declarations */


--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux