return ret;
 }
 
-int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address,
-                            u8 version)
+int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 mode, u8 *address)
 {
        struct wl1271_acx_arp_filter *acx;
        int ret;
 
-       wl1271_debug(DEBUG_ACX, "acx arp ip filter, enable: %d", enable);
+       wl1271_debug(DEBUG_ACX, "acx arp ip filter, mode: %d", mode);
 
        acx = kzalloc(sizeof(*acx), GFP_KERNEL);
        if (!acx) {
                goto out;
        }
 
-       acx->version = version;
-       acx->enable = enable;
+       acx->version = ACX_IPV4_VERSION;
+       acx->enable = mode;
 
-       if (enable == true) {
-               if (version == ACX_IPV4_VERSION)
-                       memcpy(acx->address, address, ACX_IPV4_ADDR_SIZE);
-               else if (version == ACX_IPV6_VERSION)
-                       memcpy(acx->address, address, sizeof(acx->address));
-               else
-                       wl1271_error("Invalid IP version");
-       }
+       if (mode != ACX_ARP_DISABLE)
+               memcpy(acx->address, address, ACX_IPV4_ADDR_SIZE);
 
        ret = wl1271_cmd_configure(wl, ACX_ARP_IP_FILTER,
                                   acx, sizeof(*acx));
 
 #include <linux/crc32.h>
 #include <linux/etherdevice.h>
 #include <linux/vmalloc.h>
-#include <linux/inetdevice.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 
        return NETDEV_TX_OK;
 }
 
-static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
-                            void *arg)
-{
-       struct net_device *dev;
-       struct wireless_dev *wdev;
-       struct wiphy *wiphy;
-       struct ieee80211_hw *hw;
-       struct wl1271 *wl;
-       struct wl1271 *wl_temp;
-       struct in_device *idev;
-       struct in_ifaddr *ifa = arg;
-       int ret = 0;
-
-       /* FIXME: this ugly function should probably be implemented in the
-        * mac80211, and here should only be a simple callback handling actual
-        * setting of the filters. Now we need to dig up references to
-        * various structures to gain access to what we need.
-        * Also, because of this, there is no "initial" setting of the filter
-        * in "op_start", because we don't want to dig up struct net_device
-        * there - the filter will be set upon first change of the interface
-        * IP address. */
-
-       dev = ifa->ifa_dev->dev;
-
-       wdev = dev->ieee80211_ptr;
-       if (wdev == NULL)
-               return NOTIFY_DONE;
-
-       wiphy = wdev->wiphy;
-       if (wiphy == NULL)
-               return NOTIFY_DONE;
-
-       hw = wiphy_priv(wiphy);
-       if (hw == NULL)
-               return NOTIFY_DONE;
-
-       /* Check that the interface is one supported by this driver. */
-       wl_temp = hw->priv;
-       list_for_each_entry(wl, &wl_list, list) {
-               if (wl == wl_temp)
-                       break;
-       }
-       if (wl != wl_temp)
-               return NOTIFY_DONE;
-
-       /* Get the interface IP address for the device. "ifa" will become
-          NULL if:
-            - there is no IPV4 protocol address configured
-            - there are multiple (virtual) IPV4 addresses configured
-          When "ifa" is NULL, filtering will be disabled.
-       */
-       ifa = NULL;
-       idev = dev->ip_ptr;
-       if (idev)
-               ifa = idev->ifa_list;
-
-       if (ifa && ifa->ifa_next)
-               ifa = NULL;
-
-       mutex_lock(&wl->mutex);
-
-       if (wl->state == WL1271_STATE_OFF)
-               goto out;
-
-       ret = wl1271_ps_elp_wakeup(wl, false);
-       if (ret < 0)
-               goto out;
-       if (ifa)
-               ret = wl1271_acx_arp_ip_filter(wl, true,
-                                              (u8 *)&ifa->ifa_address,
-                                              ACX_IPV4_VERSION);
-       else
-               ret = wl1271_acx_arp_ip_filter(wl, false, NULL,
-                                              ACX_IPV4_VERSION);
-       wl1271_ps_elp_sleep(wl);
-
-out:
-       mutex_unlock(&wl->mutex);
-
-       return NOTIFY_OK;
-}
-
-static struct notifier_block wl1271_dev_notifier = {
-       .notifier_call = wl1271_dev_notify,
-};
-
-
 static int wl1271_op_start(struct ieee80211_hw *hw)
 {
        wl1271_debug(DEBUG_MAC80211, "mac80211 start");
 out:
        mutex_unlock(&wl->mutex);
 
-       if (!ret) {
+       if (!ret)
                list_add(&wl->list, &wl_list);
-               register_inetaddr_notifier(&wl1271_dev_notifier);
-       }
 
        return ret;
 }
        struct wl1271 *wl = hw->priv;
        int i;
 
-       unregister_inetaddr_notifier(&wl1271_dev_notifier);
-
        mutex_lock(&wl->mutex);
        wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
 
        u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN];
 };
 
+static int wl1271_op_configure_arp_filter(struct ieee80211_hw *hw,
+                                         struct ieee80211_vif *vif,
+                                         struct in_ifaddr *ifa_list)
+{
+       struct wl1271 *wl = hw->priv;
+       int ret = 0;
+
+       WARN_ON(vif != wl->vif);
+
+       /* disable filtering if there are multiple addresses */
+       if (ifa_list && ifa_list->ifa_next)
+               ifa_list = NULL;
+
+       mutex_lock(&wl->mutex);
+
+       if (wl->state == WL1271_STATE_OFF)
+               goto out;
+
+       WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS);
+
+       ret = wl1271_ps_elp_wakeup(wl, false);
+       if (ret < 0)
+               goto out;
+
+       if (ifa_list) {
+               ret = wl1271_cmd_build_arp_reply(wl, &ifa_list->ifa_address);
+               if (ret < 0)
+                       goto out_sleep;
+               ret = wl1271_acx_arp_ip_filter(wl, ACX_ARP_FILTER_AND_REPLY,
+                                              (u8 *)&ifa_list->ifa_address);
+               if (ret < 0)
+                       goto out_sleep;
+       } else {
+               ret = wl1271_acx_arp_ip_filter(wl, ACX_ARP_DISABLE, NULL);
+               if (ret < 0)
+                       goto out_sleep;
+       }
+
+out_sleep:
+       wl1271_ps_elp_sleep(wl);
+
+out:
+       mutex_unlock(&wl->mutex);
+
+       return ret;
+}
+
 static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw,
                                       struct netdev_hw_addr_list *mc_list)
 {
        .add_interface = wl1271_op_add_interface,
        .remove_interface = wl1271_op_remove_interface,
        .config = wl1271_op_config,
+       .configure_arp_filter = wl1271_op_configure_arp_filter,
        .prepare_multicast = wl1271_op_prepare_multicast,
        .configure_filter = wl1271_op_configure_filter,
        .tx = wl1271_op_tx,