|
@@ -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);
|