aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/iface.c
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2015-03-27 16:30:37 -0400
committerJohannes Berg <johannes.berg@intel.com>2015-04-01 14:44:34 -0400
commitba8c3d6f16a1f9305c23ac1d2fd3992508c5ac03 (patch)
treec03bbdf0affccbd1f3a4fd0c239e59bb44f28e99 /net/mac80211/iface.c
parentcef2fc1ce4326f7f24c3cf938b94a661fbe773e3 (diff)
mac80211: add an intermediate software queue implementation
This allows drivers to request per-vif and per-sta-tid queues from which they can pull frames. This makes it easier to keep the hardware queues short, and to improve fairness between clients and vifs. The task of scheduling packet transmission is left up to the driver - queueing is controlled by mac80211. Drivers can only dequeue packets by calling ieee80211_tx_dequeue. This makes it possible to add active queue management later without changing drivers using this code. This can also be used as a starting point to implement A-MSDU aggregation in a way that does not add artificially induced latency. Signed-off-by: Felix Fietkau <nbd@openwrt.org> [resolved minor context conflict, minor changes, endian annotations] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r--net/mac80211/iface.c23
1 files changed, 22 insertions, 1 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index a0cd97fd0c49..b4ac596a7cb7 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -969,6 +969,13 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
969 } 969 }
970 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 970 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
971 971
972 if (sdata->vif.txq) {
973 struct txq_info *txqi = to_txq_info(sdata->vif.txq);
974
975 ieee80211_purge_tx_queue(&local->hw, &txqi->queue);
976 atomic_set(&sdata->txqs_len[txqi->txq.ac], 0);
977 }
978
972 if (local->open_count == 0) 979 if (local->open_count == 0)
973 ieee80211_clear_tx_pending(local); 980 ieee80211_clear_tx_pending(local);
974 981
@@ -1654,6 +1661,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
1654{ 1661{
1655 struct net_device *ndev = NULL; 1662 struct net_device *ndev = NULL;
1656 struct ieee80211_sub_if_data *sdata = NULL; 1663 struct ieee80211_sub_if_data *sdata = NULL;
1664 struct txq_info *txqi;
1657 int ret, i; 1665 int ret, i;
1658 int txqs = 1; 1666 int txqs = 1;
1659 1667
@@ -1673,10 +1681,18 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
1673 ieee80211_assign_perm_addr(local, wdev->address, type); 1681 ieee80211_assign_perm_addr(local, wdev->address, type);
1674 memcpy(sdata->vif.addr, wdev->address, ETH_ALEN); 1682 memcpy(sdata->vif.addr, wdev->address, ETH_ALEN);
1675 } else { 1683 } else {
1684 int size = ALIGN(sizeof(*sdata) + local->hw.vif_data_size,
1685 sizeof(void *));
1686 int txq_size = 0;
1687
1688 if (local->ops->wake_tx_queue)
1689 txq_size += sizeof(struct txq_info) +
1690 local->hw.txq_data_size;
1691
1676 if (local->hw.queues >= IEEE80211_NUM_ACS) 1692 if (local->hw.queues >= IEEE80211_NUM_ACS)
1677 txqs = IEEE80211_NUM_ACS; 1693 txqs = IEEE80211_NUM_ACS;
1678 1694
1679 ndev = alloc_netdev_mqs(sizeof(*sdata) + local->hw.vif_data_size, 1695 ndev = alloc_netdev_mqs(size + txq_size,
1680 name, name_assign_type, 1696 name, name_assign_type,
1681 ieee80211_if_setup, txqs, 1); 1697 ieee80211_if_setup, txqs, 1);
1682 if (!ndev) 1698 if (!ndev)
@@ -1711,6 +1727,11 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
1711 memcpy(sdata->vif.addr, ndev->dev_addr, ETH_ALEN); 1727 memcpy(sdata->vif.addr, ndev->dev_addr, ETH_ALEN);
1712 memcpy(sdata->name, ndev->name, IFNAMSIZ); 1728 memcpy(sdata->name, ndev->name, IFNAMSIZ);
1713 1729
1730 if (txq_size) {
1731 txqi = netdev_priv(ndev) + size;
1732 ieee80211_init_tx_queue(sdata, NULL, txqi, 0);
1733 }
1734
1714 sdata->dev = ndev; 1735 sdata->dev = ndev;
1715 } 1736 }
1716 1737