diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2008-05-16 18:57:14 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-05-21 21:48:14 -0400 |
commit | e2530083609148a7835b54c431f6b8956407c1f6 (patch) | |
tree | 8ed43347541444c7a72d2c79f550f69a93cad591 /net/mac80211/tx.c | |
parent | eefce91a384a64c7bbf913eb08c4adfb911c3639 (diff) |
mac80211: use multi-queue master netdevice
This patch updates mac80211 and drivers to be multi-queue aware and
use that instead of the internal queue mapping. Also does a number
of cleanups in various pieces of the code that fall out and reduces
internal mac80211 state size.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r-- | net/mac80211/tx.c | 97 |
1 files changed, 45 insertions, 52 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 6268bbca148e..9273651d3d7c 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -213,18 +213,6 @@ static u16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | |||
213 | return dur; | 213 | return dur; |
214 | } | 214 | } |
215 | 215 | ||
216 | static inline int __ieee80211_queue_stopped(const struct ieee80211_local *local, | ||
217 | int queue) | ||
218 | { | ||
219 | return test_bit(IEEE80211_LINK_STATE_XOFF, &local->state[queue]); | ||
220 | } | ||
221 | |||
222 | static inline int __ieee80211_queue_pending(const struct ieee80211_local *local, | ||
223 | int queue) | ||
224 | { | ||
225 | return test_bit(IEEE80211_LINK_STATE_PENDING, &local->state[queue]); | ||
226 | } | ||
227 | |||
228 | static int inline is_ieee80211_device(struct net_device *dev, | 216 | static int inline is_ieee80211_device(struct net_device *dev, |
229 | struct net_device *master) | 217 | struct net_device *master) |
230 | { | 218 | { |
@@ -680,7 +668,8 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | |||
680 | * etc. | 668 | * etc. |
681 | */ | 669 | */ |
682 | if (WARN_ON(tx->flags & IEEE80211_TX_CTL_AMPDU || | 670 | if (WARN_ON(tx->flags & IEEE80211_TX_CTL_AMPDU || |
683 | IEEE80211_SKB_CB(tx->skb)->queue >= tx->local->hw.queues)) | 671 | skb_get_queue_mapping(tx->skb) >= |
672 | ieee80211_num_regular_queues(&tx->local->hw))) | ||
684 | return TX_DROP; | 673 | return TX_DROP; |
685 | 674 | ||
686 | first = tx->skb; | 675 | first = tx->skb; |
@@ -1098,11 +1087,9 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, | |||
1098 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1087 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1099 | int ret, i; | 1088 | int ret, i; |
1100 | 1089 | ||
1101 | if (!ieee80211_qdisc_installed(local->mdev) && | 1090 | if (netif_subqueue_stopped(local->mdev, skb)) |
1102 | __ieee80211_queue_stopped(local, 0)) { | ||
1103 | netif_stop_queue(local->mdev); | ||
1104 | return IEEE80211_TX_AGAIN; | 1091 | return IEEE80211_TX_AGAIN; |
1105 | } | 1092 | |
1106 | if (skb) { | 1093 | if (skb) { |
1107 | ieee80211_dump_frame(wiphy_name(local->hw.wiphy), | 1094 | ieee80211_dump_frame(wiphy_name(local->hw.wiphy), |
1108 | "TX to low-level driver", skb); | 1095 | "TX to low-level driver", skb); |
@@ -1121,7 +1108,8 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, | |||
1121 | IEEE80211_TX_CTL_USE_CTS_PROTECT | | 1108 | IEEE80211_TX_CTL_USE_CTS_PROTECT | |
1122 | IEEE80211_TX_CTL_CLEAR_PS_FILT | | 1109 | IEEE80211_TX_CTL_CLEAR_PS_FILT | |
1123 | IEEE80211_TX_CTL_FIRST_FRAGMENT); | 1110 | IEEE80211_TX_CTL_FIRST_FRAGMENT); |
1124 | if (__ieee80211_queue_stopped(local, info->queue)) | 1111 | if (netif_subqueue_stopped(local->mdev, |
1112 | tx->extra_frag[i])) | ||
1125 | return IEEE80211_TX_FRAG_AGAIN; | 1113 | return IEEE80211_TX_FRAG_AGAIN; |
1126 | if (i == tx->num_extra_frag) { | 1114 | if (i == tx->num_extra_frag) { |
1127 | info->tx_rate_idx = tx->last_frag_rate_idx; | 1115 | info->tx_rate_idx = tx->last_frag_rate_idx; |
@@ -1160,9 +1148,11 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) | |||
1160 | ieee80211_tx_result res = TX_DROP, res_prepare; | 1148 | ieee80211_tx_result res = TX_DROP, res_prepare; |
1161 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1149 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1162 | int ret, i; | 1150 | int ret, i; |
1163 | int queue = info->queue; | 1151 | u16 queue; |
1164 | 1152 | ||
1165 | WARN_ON(__ieee80211_queue_pending(local, queue)); | 1153 | queue = skb_get_queue_mapping(skb); |
1154 | |||
1155 | WARN_ON(test_bit(queue, local->queues_pending)); | ||
1166 | 1156 | ||
1167 | if (unlikely(skb->len < 10)) { | 1157 | if (unlikely(skb->len < 10)) { |
1168 | dev_kfree_skb(skb); | 1158 | dev_kfree_skb(skb); |
@@ -1233,28 +1223,28 @@ retry: | |||
1233 | * queues, there's no reason for a driver to reject | 1223 | * queues, there's no reason for a driver to reject |
1234 | * a frame there, warn and drop it. | 1224 | * a frame there, warn and drop it. |
1235 | */ | 1225 | */ |
1236 | if (WARN_ON(queue >= local->hw.queues)) | 1226 | if (WARN_ON(queue >= ieee80211_num_regular_queues(&local->hw))) |
1237 | goto drop; | 1227 | goto drop; |
1238 | 1228 | ||
1239 | store = &local->pending_packet[queue]; | 1229 | store = &local->pending_packet[queue]; |
1240 | 1230 | ||
1241 | if (ret == IEEE80211_TX_FRAG_AGAIN) | 1231 | if (ret == IEEE80211_TX_FRAG_AGAIN) |
1242 | skb = NULL; | 1232 | skb = NULL; |
1243 | set_bit(IEEE80211_LINK_STATE_PENDING, | 1233 | set_bit(queue, local->queues_pending); |
1244 | &local->state[queue]); | ||
1245 | smp_mb(); | 1234 | smp_mb(); |
1246 | /* When the driver gets out of buffers during sending of | 1235 | /* |
1247 | * fragments and calls ieee80211_stop_queue, there is | 1236 | * When the driver gets out of buffers during sending of |
1248 | * a small window between IEEE80211_LINK_STATE_XOFF and | 1237 | * fragments and calls ieee80211_stop_queue, the netif |
1249 | * IEEE80211_LINK_STATE_PENDING flags are set. If a buffer | 1238 | * subqueue is stopped. There is, however, a small window |
1239 | * in which the PENDING bit is not yet set. If a buffer | ||
1250 | * gets available in that window (i.e. driver calls | 1240 | * gets available in that window (i.e. driver calls |
1251 | * ieee80211_wake_queue), we would end up with ieee80211_tx | 1241 | * ieee80211_wake_queue), we would end up with ieee80211_tx |
1252 | * called with IEEE80211_LINK_STATE_PENDING. Prevent this by | 1242 | * called with the PENDING bit still set. Prevent this by |
1253 | * continuing transmitting here when that situation is | 1243 | * continuing transmitting here when that situation is |
1254 | * possible to have happened. */ | 1244 | * possible to have happened. |
1255 | if (!__ieee80211_queue_stopped(local, queue)) { | 1245 | */ |
1256 | clear_bit(IEEE80211_LINK_STATE_PENDING, | 1246 | if (!__netif_subqueue_stopped(local->mdev, queue)) { |
1257 | &local->state[queue]); | 1247 | clear_bit(queue, local->queues_pending); |
1258 | goto retry; | 1248 | goto retry; |
1259 | } | 1249 | } |
1260 | store->skb = skb; | 1250 | store->skb = skb; |
@@ -1509,7 +1499,8 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1509 | } | 1499 | } |
1510 | 1500 | ||
1511 | /* receiver and we are QoS enabled, use a QoS type frame */ | 1501 | /* receiver and we are QoS enabled, use a QoS type frame */ |
1512 | if (sta_flags & WLAN_STA_WME && local->hw.queues >= 4) { | 1502 | if (sta_flags & WLAN_STA_WME && |
1503 | ieee80211_num_regular_queues(&local->hw) >= 4) { | ||
1513 | fc |= IEEE80211_STYPE_QOS_DATA; | 1504 | fc |= IEEE80211_STYPE_QOS_DATA; |
1514 | hdrlen += 2; | 1505 | hdrlen += 2; |
1515 | } | 1506 | } |
@@ -1661,41 +1652,51 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1661 | return ret; | 1652 | return ret; |
1662 | } | 1653 | } |
1663 | 1654 | ||
1664 | /* helper functions for pending packets for when queues are stopped */ | ||
1665 | 1655 | ||
1656 | /* | ||
1657 | * ieee80211_clear_tx_pending may not be called in a context where | ||
1658 | * it is possible that it packets could come in again. | ||
1659 | */ | ||
1666 | void ieee80211_clear_tx_pending(struct ieee80211_local *local) | 1660 | void ieee80211_clear_tx_pending(struct ieee80211_local *local) |
1667 | { | 1661 | { |
1668 | int i, j; | 1662 | int i, j; |
1669 | struct ieee80211_tx_stored_packet *store; | 1663 | struct ieee80211_tx_stored_packet *store; |
1670 | 1664 | ||
1671 | for (i = 0; i < local->hw.queues; i++) { | 1665 | for (i = 0; i < ieee80211_num_regular_queues(&local->hw); i++) { |
1672 | if (!__ieee80211_queue_pending(local, i)) | 1666 | if (!test_bit(i, local->queues_pending)) |
1673 | continue; | 1667 | continue; |
1674 | store = &local->pending_packet[i]; | 1668 | store = &local->pending_packet[i]; |
1675 | kfree_skb(store->skb); | 1669 | kfree_skb(store->skb); |
1676 | for (j = 0; j < store->num_extra_frag; j++) | 1670 | for (j = 0; j < store->num_extra_frag; j++) |
1677 | kfree_skb(store->extra_frag[j]); | 1671 | kfree_skb(store->extra_frag[j]); |
1678 | kfree(store->extra_frag); | 1672 | kfree(store->extra_frag); |
1679 | clear_bit(IEEE80211_LINK_STATE_PENDING, &local->state[i]); | 1673 | clear_bit(i, local->queues_pending); |
1680 | } | 1674 | } |
1681 | } | 1675 | } |
1682 | 1676 | ||
1677 | /* | ||
1678 | * Transmit all pending packets. Called from tasklet, locks master device | ||
1679 | * TX lock so that no new packets can come in. | ||
1680 | */ | ||
1683 | void ieee80211_tx_pending(unsigned long data) | 1681 | void ieee80211_tx_pending(unsigned long data) |
1684 | { | 1682 | { |
1685 | struct ieee80211_local *local = (struct ieee80211_local *)data; | 1683 | struct ieee80211_local *local = (struct ieee80211_local *)data; |
1686 | struct net_device *dev = local->mdev; | 1684 | struct net_device *dev = local->mdev; |
1687 | struct ieee80211_tx_stored_packet *store; | 1685 | struct ieee80211_tx_stored_packet *store; |
1688 | struct ieee80211_tx_data tx; | 1686 | struct ieee80211_tx_data tx; |
1689 | int i, ret, reschedule = 0; | 1687 | int i, ret; |
1690 | 1688 | ||
1691 | netif_tx_lock_bh(dev); | 1689 | netif_tx_lock_bh(dev); |
1692 | for (i = 0; i < local->hw.queues; i++) { | 1690 | for (i = 0; i < ieee80211_num_regular_queues(&local->hw); i++) { |
1693 | if (__ieee80211_queue_stopped(local, i)) | 1691 | /* Check that this queue is ok */ |
1692 | if (__netif_subqueue_stopped(local->mdev, i)) | ||
1694 | continue; | 1693 | continue; |
1695 | if (!__ieee80211_queue_pending(local, i)) { | 1694 | |
1696 | reschedule = 1; | 1695 | if (!test_bit(i, local->queues_pending)) { |
1696 | ieee80211_wake_queue(&local->hw, i); | ||
1697 | continue; | 1697 | continue; |
1698 | } | 1698 | } |
1699 | |||
1699 | store = &local->pending_packet[i]; | 1700 | store = &local->pending_packet[i]; |
1700 | tx.extra_frag = store->extra_frag; | 1701 | tx.extra_frag = store->extra_frag; |
1701 | tx.num_extra_frag = store->num_extra_frag; | 1702 | tx.num_extra_frag = store->num_extra_frag; |
@@ -1708,19 +1709,11 @@ void ieee80211_tx_pending(unsigned long data) | |||
1708 | if (ret == IEEE80211_TX_FRAG_AGAIN) | 1709 | if (ret == IEEE80211_TX_FRAG_AGAIN) |
1709 | store->skb = NULL; | 1710 | store->skb = NULL; |
1710 | } else { | 1711 | } else { |
1711 | clear_bit(IEEE80211_LINK_STATE_PENDING, | 1712 | clear_bit(i, local->queues_pending); |
1712 | &local->state[i]); | 1713 | ieee80211_wake_queue(&local->hw, i); |
1713 | reschedule = 1; | ||
1714 | } | 1714 | } |
1715 | } | 1715 | } |
1716 | netif_tx_unlock_bh(dev); | 1716 | netif_tx_unlock_bh(dev); |
1717 | if (reschedule) { | ||
1718 | if (!ieee80211_qdisc_installed(dev)) { | ||
1719 | if (!__ieee80211_queue_stopped(local, 0)) | ||
1720 | netif_wake_queue(dev); | ||
1721 | } else | ||
1722 | netif_schedule(dev); | ||
1723 | } | ||
1724 | } | 1717 | } |
1725 | 1718 | ||
1726 | /* functions for drivers to get certain frames */ | 1719 | /* functions for drivers to get certain frames */ |