From: Greg Goldman Date: Wed, 20 Apr 2011 18:23:06 +0000 (-0700) Subject: net: wireless: bcm4329: Clean ARP offload table on IP update X-Git-Tag: 2.1b_release~2626 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0b196e506924011d68324b1dbaf9883f5114b8b4;p=platform%2Fkernel%2Fkernel-mfld-blackbay.git net: wireless: bcm4329: Clean ARP offload table on IP update Signed-off-by: Dmitry Shmidt --- diff --git a/drivers/net/wireless/bcm4329/dhd.h b/drivers/net/wireless/bcm4329/dhd.h index 6c29988..7b1d076 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 8fcb95f..e50da14 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 #include @@ -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 4d0f3be..8270a13 100644 --- a/drivers/net/wireless/bcm4329/dhd_linux.c +++ b/drivers/net/wireless/bcm4329/dhd_linux.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -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 @@ -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);