On Mittwoch, 29. März 2017 09:49:21 CEST Johannes Berg wrote: > > But I could be completely wrong about it. It would therefore be > > interesting for me to know who would be responsible to start the > > queues when ieee80211_do_open rejected it for IBSS. > > Well, once ieee80211_offchannel_return() is called, that should do the > needful and end up in ieee80211_propagate_queue_wake(). > > Can you check what the IBSS vif's queues are (vif->hw_queue[...])?
I've just dumped the data in ieee80211_propagate_queue_wake and checked when the function returns. The test patch (sorry, really ugly debug printk stuff) is attached. The most interesting part is that if (local->ops->wake_tx_queue) return; evaluates to true. The rest rest of the function is therefore always skipped for ath9k. This was noticed when looking at the debug output: root@lede:/# dmesg|grep ieee80211_propagate_queue_wake [ 20.865005] ieee80211_propagate_queue_wake:248 queue 00000000 [ 20.870839] ieee80211_propagate_queue_wake:248 queue 00000001 [ 20.876661] ieee80211_propagate_queue_wake:248 queue 00000002 [ 20.882487] ieee80211_propagate_queue_wake:248 queue 00000003 [ 21.794795] ieee80211_propagate_queue_wake:248 queue 00000000 [ 21.800629] ieee80211_propagate_queue_wake:248 queue 00000001 [ 21.806452] ieee80211_propagate_queue_wake:248 queue 00000002 [ 21.812278] ieee80211_propagate_queue_wake:248 queue 00000003 [ 21.830078] ieee80211_propagate_queue_wake:248 queue 00000000 [ 21.835918] ieee80211_propagate_queue_wake:248 queue 00000001 [ 21.841740] ieee80211_propagate_queue_wake:248 queue 00000002 [ 21.847566] ieee80211_propagate_queue_wake:248 queue 00000003 [ 23.320814] ieee80211_propagate_queue_wake:248 queue 00000000 [ 23.326643] ieee80211_propagate_queue_wake:248 queue 00000001 [ 23.332469] ieee80211_propagate_queue_wake:248 queue 00000002 [ 23.338294] ieee80211_propagate_queue_wake:248 queue 00000003 [ 41.930942] ieee80211_propagate_queue_wake:248 queue 00000000 [ 41.940709] ieee80211_propagate_queue_wake:248 queue 00000002 [ 46.949087] ieee80211_propagate_queue_wake:248 queue 00000000 [ 82.999021] ieee80211_propagate_queue_wake:248 queue 00000000 Removing this is enough to fix the problem. And now you will propably say "hey, this is not my code". And this is the reason why I have now CC'ed the author of 80a83cfc434b ("mac80211: skip netdev queue control with software queuing"). This change in ieee80211_propagate_queue_wake is basically breaking the (delayed) startup of the ibss netdev queue [1] when the device was offchan during the ieee80211_do_open of the ibss interface. Not sure whether removing it in ieee80211_propagate_queue_wake will have other odd side effects with software queuing. Maybe Michal Kazior can tell us if it is safe to remove it. > However, I also don't understand the difference between encrypted and > unencrypted here. My best guess is timing. LEDE is not using wpa_supplicant when encryption is disabled. Kind regards, Sven [1] https://lkml.kernel.org/r/1978424.XTv2Qph05K@bentobox
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 036fa1d..9a1079f 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -517,6 +517,10 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) u32 changed = 0; int res; u32 hw_reconf_flags = 0; + const char *ifname = "unknown"; + + if (sdata->dev) + ifname = sdata->dev->name; switch (sdata->vif.type) { case NL80211_IFTYPE_WDS: @@ -745,11 +749,14 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) if (sdata->vif.type == NL80211_IFTYPE_MONITOR || sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { /* XXX: for AP_VLAN, actually track AP queues */ + + printk("%s:%u netif_tx_start_all_queues %s\n", __func__, __LINE__, ifname); netif_tx_start_all_queues(dev); } else if (dev) { unsigned long flags; int n_acs = IEEE80211_NUM_ACS; int ac; + int started = 0; if (local->hw.queues < IEEE80211_NUM_ACS) n_acs = 1; @@ -762,11 +769,20 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) int ac_queue = sdata->vif.hw_queue[ac]; if (local->queue_stop_reasons[ac_queue] == 0 && - skb_queue_empty(&local->pending[ac_queue])) + skb_queue_empty(&local->pending[ac_queue])) { + //printk("%s:%u netif_start_subqueue type %u %s\n", __func__, __LINE__, sdata->vif.type, ifname); netif_start_subqueue(dev, ac); + started = 1; + } else { + printk("%s:%u NOT netif_start_subqueue type %u stop_reasons %d queue_empty %d %s\n", __func__, __LINE__, sdata->vif.type, local->queue_stop_reasons[ac_queue], skb_queue_empty(&local->pending[ac_queue]), ifname); + } } + } else { + printk("%s:%u NOT netif_start_subqueue type %u cab_queue %d stop_reasons %d queue_empty %d %s\n", __func__, __LINE__, sdata->vif.type, sdata->vif.cab_queue, local->queue_stop_reasons[sdata->vif.cab_queue], skb_queue_empty(&local->pending[sdata->vif.cab_queue]), ifname); + } spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); + WARN_ON(started); } return 0; @@ -816,6 +832,10 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, struct cfg80211_chan_def chandef; bool cancel_scan; struct cfg80211_nan_func *func; + const char *ifname = "unknown"; + + if (sdata->dev) + ifname = sdata->dev->name; clear_bit(SDATA_STATE_RUNNING, &sdata->state); @@ -826,8 +846,10 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, /* * Stop TX on this interface first. */ - if (sdata->dev) + if (sdata->dev) { + printk("%s:%u netif_tx_stop_all_queues %s\n", __func__, __LINE__, ifname); netif_tx_stop_all_queues(sdata->dev); + } ieee80211_roc_purge(local, sdata); diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index fc2a601..6681c5c 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c @@ -118,6 +118,7 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local) * Stop queues and transmit all frames queued by the driver * before sending nullfunc to enable powersave at the AP. */ + printk("%s:%u ieee80211_stop_queues_by_reason\n", __func__, __LINE__); ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP, IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL, false); @@ -183,6 +184,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local) } mutex_unlock(&local->iflist_mtx); + printk("%s:%u ieee80211_offchannel_return\n", __func__, __LINE__); ieee80211_wake_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP, IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL, false); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 73069f9..8bb0853 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -243,10 +243,15 @@ void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue) { struct ieee80211_sub_if_data *sdata; int n_acs = IEEE80211_NUM_ACS; + const char *ifname = "unknown"; + + printk("%s:%u queue %08x\n", __func__, __LINE__, queue); if (local->ops->wake_tx_queue) return; + printk("%s:%u queue %08x\n", __func__, __LINE__, queue); + if (local->hw.queues < IEEE80211_NUM_ACS) n_acs = 1; @@ -256,13 +261,24 @@ void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue) if (!sdata->dev) continue; + ifname = sdata->dev->name; + + printk("%s:%u %s queue %08x\n", __func__, __LINE__, ifname, queue); + if (sdata->vif.cab_queue != IEEE80211_INVAL_HW_QUEUE && local->queue_stop_reasons[sdata->vif.cab_queue] != 0) continue; + + printk("%s:%u %s\n", __func__, __LINE__, ifname); + for (ac = 0; ac < n_acs; ac++) { int ac_queue = sdata->vif.hw_queue[ac]; + printk("%s:%u %s queue %08x sdata->vif.hw_queue[ac] %08x\n", __func__, __LINE__, ifname, queue, ac_queue); + printk("%s:%u %s queue %08x local->queue_stop_reasons[ac_queue] %08x\n", __func__, __LINE__, ifname, queue, local->queue_stop_reasons[ac_queue]); + printk("%s:%u %s queue %08x skb_queue_empty(...) %08x\n", __func__, __LINE__, ifname, queue, skb_queue_empty(&local->pending[ac_queue])); + if (ac_queue == queue || (sdata->vif.cab_queue == queue && local->queue_stop_reasons[ac_queue] == 0 &&
signature.asc
Description: This is a digitally signed message part.