diff --git a/net/mac802154/ieee802154_dev.c b/net/mac802154/ieee802154_dev.c index 10cdb091b775..e7aa76445fe1 100644 --- a/net/mac802154/ieee802154_dev.c +++ b/net/mac802154/ieee802154_dev.c @@ -36,9 +36,28 @@ int mac802154_slave_open(struct net_device *dev) { struct mac802154_sub_if_data *priv = netdev_priv(dev); + struct mac802154_sub_if_data *subif; struct mac802154_priv *ipriv = priv->hw; int res = 0; + ASSERT_RTNL(); + + if (priv->type == IEEE802154_DEV_WPAN) { + mutex_lock(&priv->hw->slaves_mtx); + list_for_each_entry(subif, &priv->hw->slaves, list) { + if (subif != priv && subif->type == priv->type && + subif->running) { + mutex_unlock(&priv->hw->slaves_mtx); + return -EBUSY; + } + } + mutex_unlock(&priv->hw->slaves_mtx); + } + + mutex_lock(&priv->hw->slaves_mtx); + priv->running = true; + mutex_unlock(&priv->hw->slaves_mtx); + if (ipriv->open_count++ == 0) { res = ipriv->ops->start(&ipriv->hw); WARN_ON(res); @@ -69,8 +88,14 @@ int mac802154_slave_close(struct net_device *dev) struct mac802154_sub_if_data *priv = netdev_priv(dev); struct mac802154_priv *ipriv = priv->hw; + ASSERT_RTNL(); + netif_stop_queue(dev); + mutex_lock(&priv->hw->slaves_mtx); + priv->running = false; + mutex_unlock(&priv->hw->slaves_mtx); + if (!--ipriv->open_count) ipriv->ops->stop(&ipriv->hw); diff --git a/net/mac802154/mac802154.h b/net/mac802154/mac802154.h index 4619486f1da2..f40522ef288c 100644 --- a/net/mac802154/mac802154.h +++ b/net/mac802154/mac802154.h @@ -71,6 +71,7 @@ struct mac802154_sub_if_data { struct net_device *dev; int type; + bool running; spinlock_t mib_lock;