const unsigned char bridge_tunnel_header[] __aligned(2) =
{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
+struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy)
+{
+ struct ieee80211_local *local;
+ BUG_ON(!wiphy);
+
+ local = wiphy_priv(wiphy);
+ return &local->hw;
+}
+EXPORT_SYMBOL(wiphy_to_ieee80211_hw);
u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
enum nl80211_iftype type)
{
struct ieee80211_local *local = hw_to_local(hw);
- /* we don't need to track ampdu queues */
- if (queue < ieee80211_num_regular_queues(hw)) {
- __clear_bit(reason, &local->queue_stop_reasons[queue]);
+ if (queue >= hw->queues) {
+ if (local->ampdu_ac_queue[queue - hw->queues] < 0)
+ return;
- if (local->queue_stop_reasons[queue] != 0)
- /* someone still has this queue stopped */
+ /*
+ * for virtual aggregation queues, we need to refcount the
+ * internal mac80211 disable (multiple times!), keep track of
+ * driver disable _and_ make sure the regular queue is
+ * actually enabled.
+ */
+ if (reason == IEEE80211_QUEUE_STOP_REASON_AGGREGATION)
+ local->amdpu_ac_stop_refcnt[queue - hw->queues]--;
+ else
+ __clear_bit(reason, &local->queue_stop_reasons[queue]);
+
+ if (local->queue_stop_reasons[queue] ||
+ local->amdpu_ac_stop_refcnt[queue - hw->queues])
return;
+
+ /* now go on to treat the corresponding regular queue */
+ queue = local->ampdu_ac_queue[queue - hw->queues];
+ reason = IEEE80211_QUEUE_STOP_REASON_AGGREGATION;
}
+ __clear_bit(reason, &local->queue_stop_reasons[queue]);
+
+ if (local->queue_stop_reasons[queue] != 0)
+ /* someone still has this queue stopped */
+ return;
+
if (test_bit(queue, local->queues_pending)) {
set_bit(queue, local->queues_pending_run);
tasklet_schedule(&local->tx_pending_tasklet);
}
}
-static void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
- enum queue_stop_reason reason)
+void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
+ enum queue_stop_reason reason)
{
struct ieee80211_local *local = hw_to_local(hw);
unsigned long flags;
{
struct ieee80211_local *local = hw_to_local(hw);
- /* we don't need to track ampdu queues */
- if (queue < ieee80211_num_regular_queues(hw))
- __set_bit(reason, &local->queue_stop_reasons[queue]);
+ if (queue >= hw->queues) {
+ if (local->ampdu_ac_queue[queue - hw->queues] < 0)
+ return;
+
+ /*
+ * for virtual aggregation queues, we need to refcount the
+ * internal mac80211 disable (multiple times!), keep track of
+ * driver disable _and_ make sure the regular queue is
+ * actually enabled.
+ */
+ if (reason == IEEE80211_QUEUE_STOP_REASON_AGGREGATION)
+ local->amdpu_ac_stop_refcnt[queue - hw->queues]++;
+ else
+ __set_bit(reason, &local->queue_stop_reasons[queue]);
+
+ /* now go on to treat the corresponding regular queue */
+ queue = local->ampdu_ac_queue[queue - hw->queues];
+ reason = IEEE80211_QUEUE_STOP_REASON_AGGREGATION;
+ }
+
+ __set_bit(reason, &local->queue_stop_reasons[queue]);
netif_stop_subqueue(local->mdev, queue);
}
-static void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
- enum queue_stop_reason reason)
+void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
+ enum queue_stop_reason reason)
{
struct ieee80211_local *local = hw_to_local(hw);
unsigned long flags;
spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
- for (i = 0; i < ieee80211_num_queues(hw); i++)
+ for (i = 0; i < hw->queues; i++)
__ieee80211_stop_queue(hw, i, reason);
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue)
{
struct ieee80211_local *local = hw_to_local(hw);
+ unsigned long flags;
+
+ if (queue >= hw->queues) {
+ spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
+ queue = local->ampdu_ac_queue[queue - hw->queues];
+ spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+ if (queue < 0)
+ return true;
+ }
+
return __netif_subqueue_stopped(local->mdev, queue);
}
EXPORT_SYMBOL(ieee80211_queue_stopped);
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_sub_if_data *sdata;
- rtnl_lock();
+ mutex_lock(&local->iflist_mtx);
list_for_each_entry(sdata, &local->interfaces, list) {
switch (sdata->vif.type) {
&sdata->vif);
}
- rtnl_unlock();
+ mutex_unlock(&local->iflist_mtx);
}
EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces);