diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-02-18 07:28:37 -0800 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-02-18 07:28:37 -0800 |
commit | 65d2918e716afb89359cfa59734d76c1ff8700cb (patch) | |
tree | 4685404f96642243d62c3a1a823340913d087090 /net/mac802154/iface.c | |
parent | bf40e5561fd288a505d5d8d8bf45eef96fe7253d (diff) | |
parent | 338d00cfef07d74a072f96821c64b20f98517d72 (diff) | |
download | lwn-65d2918e716afb89359cfa59734d76c1ff8700cb.tar.gz lwn-65d2918e716afb89359cfa59734d76c1ff8700cb.zip |
Merge branch 'cleanups'
Merge cleanups requested by Linus.
* cleanups: (3 commits)
pnfs: Refactor the *_layout_mark_request_commit to use pnfs_layout_mark_request_commit
nfs: Can call nfs_clear_page_commit() instead
nfs: Provide and use helper functions for marking a page as unstable
Diffstat (limited to 'net/mac802154/iface.c')
-rw-r--r-- | net/mac802154/iface.c | 100 |
1 files changed, 86 insertions, 14 deletions
diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index 9ae893057dd7..6fb6bdf9868c 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c @@ -137,25 +137,11 @@ static int mac802154_wpan_mac_addr(struct net_device *dev, void *p) static int mac802154_slave_open(struct net_device *dev) { struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); - struct ieee802154_sub_if_data *subif; struct ieee802154_local *local = sdata->local; int res = 0; ASSERT_RTNL(); - if (sdata->vif.type == NL802154_IFTYPE_NODE) { - mutex_lock(&sdata->local->iflist_mtx); - list_for_each_entry(subif, &sdata->local->interfaces, list) { - if (subif != sdata && - subif->vif.type == sdata->vif.type && - ieee802154_sdata_running(subif)) { - mutex_unlock(&sdata->local->iflist_mtx); - return -EBUSY; - } - } - mutex_unlock(&sdata->local->iflist_mtx); - } - set_bit(SDATA_STATE_RUNNING, &sdata->state); if (!local->open_count) { @@ -175,6 +161,88 @@ err: return res; } +static int +ieee802154_check_mac_settings(struct ieee802154_local *local, + struct wpan_dev *wpan_dev, + struct wpan_dev *nwpan_dev) +{ + ASSERT_RTNL(); + + if (local->hw.flags & IEEE802154_HW_PROMISCUOUS) { + if (wpan_dev->promiscuous_mode != nwpan_dev->promiscuous_mode) + return -EBUSY; + } + + if (local->hw.flags & IEEE802154_HW_AFILT) { + if (wpan_dev->pan_id != nwpan_dev->pan_id) + return -EBUSY; + + if (wpan_dev->short_addr != nwpan_dev->short_addr) + return -EBUSY; + + if (wpan_dev->extended_addr != nwpan_dev->extended_addr) + return -EBUSY; + } + + if (local->hw.flags & IEEE802154_HW_CSMA_PARAMS) { + if (wpan_dev->min_be != nwpan_dev->min_be) + return -EBUSY; + + if (wpan_dev->max_be != nwpan_dev->max_be) + return -EBUSY; + + if (wpan_dev->csma_retries != nwpan_dev->csma_retries) + return -EBUSY; + } + + if (local->hw.flags & IEEE802154_HW_FRAME_RETRIES) { + if (wpan_dev->frame_retries != nwpan_dev->frame_retries) + return -EBUSY; + } + + if (local->hw.flags & IEEE802154_HW_LBT) { + if (wpan_dev->lbt != nwpan_dev->lbt) + return -EBUSY; + } + + return 0; +} + +static int +ieee802154_check_concurrent_iface(struct ieee802154_sub_if_data *sdata, + enum nl802154_iftype iftype) +{ + struct ieee802154_local *local = sdata->local; + struct wpan_dev *wpan_dev = &sdata->wpan_dev; + struct ieee802154_sub_if_data *nsdata; + + /* we hold the RTNL here so can safely walk the list */ + list_for_each_entry(nsdata, &local->interfaces, list) { + if (nsdata != sdata && ieee802154_sdata_running(nsdata)) { + int ret; + + /* TODO currently we don't support multiple node types + * we need to run skb_clone at rx path. Check if there + * exist really an use case if we need to support + * multiple node types at the same time. + */ + if (sdata->vif.type == NL802154_IFTYPE_NODE && + nsdata->vif.type == NL802154_IFTYPE_NODE) + return -EBUSY; + + /* check all phy mac sublayer settings are the same. + * We have only one phy, different values makes trouble. + */ + ret = ieee802154_check_mac_settings(local, wpan_dev, + &nsdata->wpan_dev); + if (ret < 0) + return ret; + } + } + + return 0; +} + static int mac802154_wpan_open(struct net_device *dev) { int rc; @@ -183,6 +251,10 @@ static int mac802154_wpan_open(struct net_device *dev) struct wpan_dev *wpan_dev = &sdata->wpan_dev; struct wpan_phy *phy = sdata->local->phy; + rc = ieee802154_check_concurrent_iface(sdata, sdata->vif.type); + if (rc < 0) + return rc; + rc = mac802154_slave_open(dev); if (rc < 0) return rc; |