diff options
Diffstat (limited to 'net/mac80211/iface.c')
| -rw-r--r-- | net/mac80211/iface.c | 44 | 
1 files changed, 37 insertions, 7 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 60f1ce5e5e52..98d20c0f6fed 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -159,9 +159,10 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)  	return 0;  } -static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr) +static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr)  { -	struct ieee80211_sub_if_data *sdata; +	struct ieee80211_local *local = sdata->local; +	struct ieee80211_sub_if_data *iter;  	u64 new, mask, tmp;  	u8 *m;  	int ret = 0; @@ -181,11 +182,14 @@ static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr)  	mutex_lock(&local->iflist_mtx); -	list_for_each_entry(sdata, &local->interfaces, list) { -		if (sdata->vif.type == NL80211_IFTYPE_MONITOR) +	list_for_each_entry(iter, &local->interfaces, list) { +		if (iter == sdata) +			continue; + +		if (iter->vif.type == NL80211_IFTYPE_MONITOR)  			continue; -		m = sdata->vif.addr; +		m = iter->vif.addr;  		tmp =	((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |  			((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |  			((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); @@ -209,7 +213,7 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr)  	if (ieee80211_sdata_running(sdata))  		return -EBUSY; -	ret = ieee80211_verify_mac(sdata->local, sa->sa_data); +	ret = ieee80211_verify_mac(sdata, sa->sa_data);  	if (ret)  		return ret; @@ -474,6 +478,9 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)  			master->control_port_protocol;  		sdata->control_port_no_encrypt =  			master->control_port_no_encrypt; +		sdata->vif.cab_queue = master->vif.cab_queue; +		memcpy(sdata->vif.hw_queue, master->vif.hw_queue, +		       sizeof(sdata->vif.hw_queue));  		break;  		}  	case NL80211_IFTYPE_AP: @@ -653,7 +660,11 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)  	ieee80211_recalc_ps(local, -1); -	if (dev) { +	if (sdata->vif.type == NL80211_IFTYPE_MONITOR || +	    sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { +		/* XXX: for AP_VLAN, actually track AP queues */ +		netif_tx_start_all_queues(dev); +	} else if (dev) {  		unsigned long flags;  		int n_acs = IEEE80211_NUM_ACS;  		int ac; @@ -1479,7 +1490,17 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,  			break;  		} +		/* +		 * Pick address of existing interface in case user changed +		 * MAC address manually, default to perm_addr. +		 */  		m = local->hw.wiphy->perm_addr; +		list_for_each_entry(sdata, &local->interfaces, list) { +			if (sdata->vif.type == NL80211_IFTYPE_MONITOR) +				continue; +			m = sdata->vif.addr; +			break; +		}  		start = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |  			((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |  			((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); @@ -1696,6 +1717,15 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local)  	ASSERT_RTNL(); +	/* +	 * Close all AP_VLAN interfaces first, as otherwise they +	 * might be closed while the AP interface they belong to +	 * is closed, causing unregister_netdevice_many() to crash. +	 */ +	list_for_each_entry(sdata, &local->interfaces, list) +		if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) +			dev_close(sdata->dev); +  	mutex_lock(&local->iflist_mtx);  	list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {  		list_del(&sdata->list);  |