net: wireless: bcm4329: Clean ARP offload table on IP update
authorGreg Goldman <ggoldman@broadcom.com>
Wed, 20 Apr 2011 18:23:06 +0000 (11:23 -0700)
committermgross <mark.gross@intel.com>
Wed, 9 Nov 2011 20:07:28 +0000 (12:07 -0800)
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
drivers/net/wireless/bcm4329/dhd.h
drivers/net/wireless/bcm4329/dhd_common.c
drivers/net/wireless/bcm4329/dhd_linux.c

index 6c29988..7b1d076 100644 (file)
@@ -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_ */
index 8fcb95f..e50da14 100644 (file)
@@ -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)
 {
index 4d0f3be..8270a13 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/ethtool.h>
 #include <linux/fcntl.h>
 #include <linux/fs.h>
+#include <linux/inetdevice.h>
 #include <linux/mutex.h>
 
 #include <asm/uaccess.h>
@@ -202,6 +203,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>
@@ -2016,6 +2023,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)
 {
@@ -2172,6 +2180,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:
@@ -2332,6 +2342,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)
 {
@@ -2405,6 +2457,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
@@ -2470,6 +2523,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);