Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 203516
b: refs/heads/master
c: eb887df
h: refs/heads/master
v: v3
  • Loading branch information
Juuso Oikarinen authored and John W. Linville committed Jul 8, 2010
1 parent 08ee68f commit c09d782
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 109 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: bbbb538e337a3eb2166d5a20307b93822bdacc4f
refs/heads/master: eb887dfd8837bf0a2538418c02b3992fb9ff1f28
19 changes: 6 additions & 13 deletions trunk/drivers/net/wireless/wl12xx/wl1271_acx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1075,31 +1075,24 @@ int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable)
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) {
ret = -ENOMEM;
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));
Expand Down
3 changes: 1 addition & 2 deletions trunk/drivers/net/wireless/wl12xx/wl1271_acx.h
Original file line number Diff line number Diff line change
Expand Up @@ -1117,8 +1117,7 @@ int wl1271_acx_init_mem_config(struct wl1271 *wl);
int wl1271_acx_init_rx_interrupt(struct wl1271 *wl);
int wl1271_acx_smart_reflex(struct wl1271 *wl);
int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable);
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);
int wl1271_acx_pm_config(struct wl1271 *wl);
int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable);
int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid);
Expand Down
142 changes: 49 additions & 93 deletions trunk/drivers/net/wireless/wl12xx/wl1271_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
#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>

Expand Down Expand Up @@ -818,93 +817,6 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
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");
Expand Down Expand Up @@ -1008,10 +920,8 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
out:
mutex_unlock(&wl->mutex);

if (!ret) {
if (!ret)
list_add(&wl->list, &wl_list);
register_inetaddr_notifier(&wl1271_dev_notifier);
}

return ret;
}
Expand All @@ -1022,8 +932,6 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
struct wl1271 *wl = hw->priv;
int i;

unregister_inetaddr_notifier(&wl1271_dev_notifier);

mutex_lock(&wl->mutex);
wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");

Expand Down Expand Up @@ -1400,6 +1308,53 @@ struct wl1271_filter_params {
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)
{
Expand Down Expand Up @@ -2213,6 +2168,7 @@ static const struct ieee80211_ops wl1271_ops = {
.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,
Expand Down

0 comments on commit c09d782

Please sign in to comment.