summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorGreg Goldman <ggoldman@broadcom.com>2011-04-20 11:23:06 -0700
committerDmitry Shmidt <dimitrysh@google.com>2011-04-20 15:26:26 -0700
commit438f97f7bd3127a95174ee8c36c6826bd9ba11ea (patch)
tree24c5a7fb144ea276c0b87670ef7df1fc89c925de /drivers
parent0d48e31fcc17a91dcffb2f43c18c7ca1761abb98 (diff)
net: wireless: bcm4329: Clean ARP offload table on IP update
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/bcm4329/dhd.h5
-rw-r--r--drivers/net/wireless/bcm4329/dhd_common.c78
-rw-r--r--drivers/net/wireless/bcm4329/dhd_linux.c55
3 files changed, 137 insertions, 1 deletions
diff --git a/drivers/net/wireless/bcm4329/dhd.h b/drivers/net/wireless/bcm4329/dhd.h
index 6c2998806e4d..7b1d076763ef 100644
--- a/drivers/net/wireless/bcm4329/dhd.h
+++ b/drivers/net/wireless/bcm4329/dhd.h
@@ -448,4 +448,9 @@ extern char nv_path[MOD_PARAM_PATHLEN];
extern void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar);
extern void dhd_wait_event_wakeup(dhd_pub_t*dhd);
+/* dhd_commn arp offload wrapers */
+extern void dhd_arp_cleanup(dhd_pub_t *dhd);
+int dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen);
+void dhd_arp_offload_add_ip(dhd_pub_t *dhd, u32 ipaddr);
+
#endif /* _dhd_h_ */
diff --git a/drivers/net/wireless/bcm4329/dhd_common.c b/drivers/net/wireless/bcm4329/dhd_common.c
index 8fcb95fde827..e50da1414c9e 100644
--- a/drivers/net/wireless/bcm4329/dhd_common.c
+++ b/drivers/net/wireless/bcm4329/dhd_common.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_common.c,v 1.5.6.8.2.6.6.69.4.25 2011/02/11 21:16:02 Exp $
+ * $Id: dhd_common.c,v 1.5.6.8.2.6.6.69.4.25 2011-02-11 21:16:02 Exp $
*/
#include <typedefs.h>
#include <osl.h>
@@ -1220,6 +1220,82 @@ dhd_arp_offload_enable(dhd_pub_t * dhd, int arp_enable)
}
#endif
+
+void dhd_arp_cleanup(dhd_pub_t *dhd)
+{
+#ifdef ARP_OFFLOAD_SUPPORT
+ int ret = 0;
+ int iov_len = 0;
+ char iovbuf[128];
+
+ if (dhd == NULL) return;
+
+ dhd_os_proto_block(dhd);
+
+ iov_len = bcm_mkiovar("arp_hostip_clear", 0, 0, iovbuf, sizeof(iovbuf));
+ if ((ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, iov_len)) < 0)
+ DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret));
+
+ iov_len = bcm_mkiovar("arp_table_clear", 0, 0, iovbuf, sizeof(iovbuf));
+ if ((ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, iov_len)) < 0)
+ DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret));
+
+ dhd_os_proto_unblock(dhd);
+
+#endif /* ARP_OFFLOAD_SUPPORT */
+}
+
+void dhd_arp_offload_add_ip(dhd_pub_t *dhd, u32 ipaddr)
+{
+#ifdef ARP_OFFLOAD_SUPPORT
+ int iov_len = 0;
+ char iovbuf[32];
+ int retcode;
+
+ dhd_os_proto_block(dhd);
+
+ iov_len = bcm_mkiovar("arp_hostip", (char *)&ipaddr, 4, iovbuf, sizeof(iovbuf));
+ retcode = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, iov_len);
+
+ dhd_os_proto_unblock(dhd);
+
+ if (retcode)
+ DHD_TRACE(("%s: ARP ip addr add failed, retcode = %d\n",
+ __FUNCTION__, retcode));
+ else
+ DHD_TRACE(("%s: ARP ipaddr entry added\n",
+ __FUNCTION__));
+#endif /* ARP_OFFLOAD_SUPPORT */
+}
+
+
+int dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen)
+{
+#ifdef ARP_OFFLOAD_SUPPORT
+ int retcode;
+ int iov_len = 0;
+
+ if (!buf)
+ return -1;
+
+ dhd_os_proto_block(dhd);
+
+ iov_len = bcm_mkiovar("arp_hostip", 0, 0, buf, buflen);
+ retcode = dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, buf, buflen);
+
+ dhd_os_proto_unblock(dhd);
+
+ if (retcode) {
+ DHD_TRACE(("%s: ioctl WLC_GET_VAR error %d\n",
+ __FUNCTION__, retcode));
+
+ return -1;
+ }
+#endif /* ARP_OFFLOAD_SUPPORT */
+ return 0;
+}
+
+
int
dhd_preinit_ioctls(dhd_pub_t *dhd)
{
diff --git a/drivers/net/wireless/bcm4329/dhd_linux.c b/drivers/net/wireless/bcm4329/dhd_linux.c
index 3bfdd6989fba..bbb15b93c013 100644
--- a/drivers/net/wireless/bcm4329/dhd_linux.c
+++ b/drivers/net/wireless/bcm4329/dhd_linux.c
@@ -43,6 +43,7 @@
#include <linux/ethtool.h>
#include <linux/fcntl.h>
#include <linux/fs.h>
+#include <linux/inetdevice.h>
#include <asm/uaccess.h>
#include <asm/unaligned.h>
@@ -201,6 +202,12 @@ void wifi_del_dev(void)
}
#endif /* defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) */
+static int dhd_device_event(struct notifier_block *this, unsigned long event,
+ void *ptr);
+
+static struct notifier_block dhd_notifier = {
+ .notifier_call = dhd_device_event
+};
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
#include <linux/suspend.h>
@@ -2015,6 +2022,7 @@ dhd_del_if(dhd_info_t *dhd, int ifidx)
up(&dhd->sysioc_sem);
}
+
dhd_pub_t *
dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
{
@@ -2171,6 +2179,8 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
register_early_suspend(&dhd->early_suspend);
#endif
+ register_inetaddr_notifier(&dhd_notifier);
+
return &dhd->pub;
fail:
@@ -2331,6 +2341,48 @@ static struct net_device_ops dhd_ops_virt = {
};
#endif
+static int dhd_device_event(struct notifier_block *this, unsigned long event,
+ void *ptr)
+{
+ struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
+ dhd_info_t *dhd;
+ dhd_pub_t *dhd_pub;
+
+ if (!ifa)
+ return NOTIFY_DONE;
+
+ dhd = *(dhd_info_t **)netdev_priv(ifa->ifa_dev->dev);
+ dhd_pub = &dhd->pub;
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 31))
+ if (ifa->ifa_dev->dev->netdev_ops == &dhd_ops_pri) {
+#else
+ if (ifa->ifa_dev->dev->open == &dhd_open) {
+#endif
+ switch (event) {
+ case NETDEV_UP:
+ DHD_TRACE(("%s: [%s] Up IP: 0x%x\n",
+ __FUNCTION__, ifa->ifa_label, ifa->ifa_address));
+
+ dhd_arp_cleanup(dhd_pub);
+ break;
+
+ case NETDEV_DOWN:
+ DHD_TRACE(("%s: [%s] Down IP: 0x%x\n",
+ __FUNCTION__, ifa->ifa_label, ifa->ifa_address));
+
+ dhd_arp_cleanup(dhd_pub);
+ break;
+
+ default:
+ DHD_TRACE(("%s: [%s] Event: %lu\n",
+ __FUNCTION__, ifa->ifa_label, event));
+ break;
+ }
+ }
+ return NOTIFY_DONE;
+}
+
int
dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
{
@@ -2404,6 +2456,7 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
dhd->pub.mac.octet[0], dhd->pub.mac.octet[1], dhd->pub.mac.octet[2],
dhd->pub.mac.octet[3], dhd->pub.mac.octet[4], dhd->pub.mac.octet[5]);
+
#if defined(CONFIG_WIRELESS_EXT)
#if defined(CONFIG_FIRST_SCAN)
#ifdef SOFTAP
@@ -2469,6 +2522,8 @@ dhd_detach(dhd_pub_t *dhdp)
dhd_if_t *ifp;
int i;
+ unregister_inetaddr_notifier(&dhd_notifier);
+
#if defined(CONFIG_HAS_EARLYSUSPEND)
if (dhd->early_suspend.suspend)
unregister_early_suspend(&dhd->early_suspend);