summaryrefslogtreecommitdiff
path: root/net/mac802154/iface.c
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2015-02-18 07:28:37 -0800
committerTrond Myklebust <trond.myklebust@primarydata.com>2015-02-18 07:28:37 -0800
commit65d2918e716afb89359cfa59734d76c1ff8700cb (patch)
tree4685404f96642243d62c3a1a823340913d087090 /net/mac802154/iface.c
parentbf40e5561fd288a505d5d8d8bf45eef96fe7253d (diff)
parent338d00cfef07d74a072f96821c64b20f98517d72 (diff)
downloadlwn-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.c100
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;