There is no reason to put master interface to UP/DOWN state manually.

Calling of hw->open and hw->stop callbacks logically belongs to
ieee80211_master_open and ieee80211_master_stop functions, but then we need
to refuse putting master interface to UP state when there is no other
interface running, and similarly, to refuse putting master interface DOWN
when there are other interfaces running. Because the second is not possible,
hw->open and hw->stop need to be called from ieee80211_open/ieee80211_stop.

Signed-off-by: Jiri Benc <[EMAIL PROTECTED]>

---

 net/d80211/ieee80211.c |   57 +++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 44 insertions(+), 13 deletions(-)

e5df634b3ae1c945076820434d8dcf897c0eb574
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index c20cb00..ea71b6c 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -1829,10 +1829,38 @@ static inline int identical_mac_addr_all
                  type2 == IEEE80211_IF_TYPE_AP)));
 }
 
+static int ieee80211_master_open(struct net_device *dev)
+{
+       struct ieee80211_local *local = dev->priv;
+       struct ieee80211_sub_if_data *sdata;
+       int res = -EOPNOTSUPP;
+
+       list_for_each_entry(sdata, &local->sub_if_list, list) {
+               if (sdata->dev != dev && netif_running(sdata->dev)) {
+                       res = 0;
+                       break;
+               }
+       }
+       return res;
+}
+
+static int ieee80211_master_stop(struct net_device *dev)
+{
+       struct ieee80211_local *local = dev->priv;
+       struct ieee80211_sub_if_data *sdata;
+
+       list_for_each_entry(sdata, &local->sub_if_list, list) {
+               if (sdata->dev != dev && netif_running(sdata->dev))
+                       return -EOPNOTSUPP;
+       }
+       return 0;
+}
+
 static int ieee80211_open(struct net_device *dev)
 {
        struct ieee80211_sub_if_data *sdata, *nsdata;
        struct ieee80211_local *local = dev->priv;
+       struct ieee80211_if_init_conf conf;
        int res;
 
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -1852,8 +1880,6 @@ static int ieee80211_open(struct net_dev
                return -ENOLINK;
 
        if (local->hw->add_interface) {
-               struct ieee80211_if_init_conf conf;
-
                conf.if_id = dev->ifindex;
                conf.type = sdata->type;
                conf.mac_addr = dev->dev_addr;
@@ -1868,10 +1894,18 @@ static int ieee80211_open(struct net_dev
        }
 
         if (local->open_count == 0) {
-               if (local->hw->open) {
+               res = 0;
+               if (local->hw->open)
                        res = local->hw->open(sdata->master);
-                       if (res)
-                               return res;
+               if (res == 0) {
+                       res = dev_open(sdata->master);
+                       if (res && local->hw->stop)
+                               local->hw->stop(sdata->master);
+               }
+               if (res) {
+                       if (local->hw->remove_interface)
+                               local->hw->remove_interface(dev, &conf);
+                       return res;
                }
                ieee80211_init_scan(sdata->master);
        }
@@ -1886,7 +1920,6 @@ static int ieee80211_stop(struct net_dev
 {
        struct ieee80211_sub_if_data *sdata;
        struct ieee80211_local *local = dev->priv;
-       int res;
 
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
@@ -1895,11 +1928,9 @@ static int ieee80211_stop(struct net_dev
        local->open_count--;
         if (local->open_count == 0) {
                ieee80211_stop_scan(sdata->master);
-               if (local->hw->stop) {
-                       res = local->hw->stop(sdata->master);
-                       if (res)
-                               return res;
-               }
+               dev_close(sdata->master);
+               if (local->hw->stop)
+                       local->hw->stop(sdata->master);
         }
        if (local->hw->remove_interface) {
                struct ieee80211_if_init_conf conf;
@@ -4035,8 +4066,8 @@ struct net_device *ieee80211_alloc_hw(si
        mdev->change_mtu = ieee80211_change_mtu;
         mdev->tx_timeout = ieee80211_tx_timeout;
         mdev->get_stats = ieee80211_get_stats;
-        mdev->open = ieee80211_open;
-       mdev->stop = ieee80211_stop;
+       mdev->open = ieee80211_master_open;
+       mdev->stop = ieee80211_master_stop;
        mdev->type = ARPHRD_IEEE80211;
         mdev->hard_header_parse = header_parse_80211;
        sprintf(mdev->name, "%s.11", dev->name);
-- 
1.3.0

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to