浏览代码

mac80211: insert WDS peer after adding interface

This reorders the open code so that WDS peer STA info entries
are added after the corresponding interface is added to the
driver so that driver callbacks aren't invoked out of order.
Also make any master device startup fatal.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Johannes Berg 17 年之前
父节点
当前提交
636c5d488b
共有 1 个文件被更改,包括 27 次插入17 次删除
  1. 27 17
      net/mac80211/main.c

+ 27 - 17
net/mac80211/main.c

@@ -257,20 +257,6 @@ static int ieee80211_open(struct net_device *dev)
 	case IEEE80211_IF_TYPE_WDS:
 	case IEEE80211_IF_TYPE_WDS:
 		if (!is_valid_ether_addr(sdata->u.wds.remote_addr))
 		if (!is_valid_ether_addr(sdata->u.wds.remote_addr))
 			return -ENOLINK;
 			return -ENOLINK;
-
-		/* Create STA entry for the WDS peer */
-		sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
-				     GFP_KERNEL);
-		if (!sta)
-			return -ENOMEM;
-
-		sta->flags |= WLAN_STA_AUTHORIZED;
-
-		res = sta_info_insert(sta);
-		if (res) {
-			/* STA has been freed */
-			return res;
-		}
 		break;
 		break;
 	case IEEE80211_IF_TYPE_VLAN:
 	case IEEE80211_IF_TYPE_VLAN:
 		if (!sdata->u.vlan.ap)
 		if (!sdata->u.vlan.ap)
@@ -337,10 +323,8 @@ static int ieee80211_open(struct net_device *dev)
 		conf.type = sdata->vif.type;
 		conf.type = sdata->vif.type;
 		conf.mac_addr = dev->dev_addr;
 		conf.mac_addr = dev->dev_addr;
 		res = local->ops->add_interface(local_to_hw(local), &conf);
 		res = local->ops->add_interface(local_to_hw(local), &conf);
-		if (res && !local->open_count && local->ops->stop)
-			local->ops->stop(local_to_hw(local));
 		if (res)
 		if (res)
-			return res;
+			goto err_stop;
 
 
 		ieee80211_if_config(dev);
 		ieee80211_if_config(dev);
 		ieee80211_reset_erp_info(dev);
 		ieee80211_reset_erp_info(dev);
@@ -353,9 +337,29 @@ static int ieee80211_open(struct net_device *dev)
 			netif_carrier_on(dev);
 			netif_carrier_on(dev);
 	}
 	}
 
 
+	if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) {
+		/* Create STA entry for the WDS peer */
+		sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
+				     GFP_KERNEL);
+		if (!sta) {
+			res = -ENOMEM;
+			goto err_del_interface;
+		}
+
+		sta->flags |= WLAN_STA_AUTHORIZED;
+
+		res = sta_info_insert(sta);
+		if (res) {
+			/* STA has been freed */
+			goto err_del_interface;
+		}
+	}
+
 	if (local->open_count == 0) {
 	if (local->open_count == 0) {
 		res = dev_open(local->mdev);
 		res = dev_open(local->mdev);
 		WARN_ON(res);
 		WARN_ON(res);
+		if (res)
+			goto err_del_interface;
 		tasklet_enable(&local->tx_pending_tasklet);
 		tasklet_enable(&local->tx_pending_tasklet);
 		tasklet_enable(&local->tasklet);
 		tasklet_enable(&local->tasklet);
 	}
 	}
@@ -390,6 +394,12 @@ static int ieee80211_open(struct net_device *dev)
 	netif_start_queue(dev);
 	netif_start_queue(dev);
 
 
 	return 0;
 	return 0;
+ err_del_interface:
+	local->ops->remove_interface(local_to_hw(local), &conf);
+ err_stop:
+	if (!local->open_count && local->ops->stop)
+		local->ops->stop(local_to_hw(local));
+	return res;
 }
 }
 
 
 static int ieee80211_stop(struct net_device *dev)
 static int ieee80211_stop(struct net_device *dev)