diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/mac80211/ieee80211_i.h | 9 | ||||
| -rw-r--r-- | net/mac80211/main.c | 2 | ||||
| -rw-r--r-- | net/mac80211/tx.c | 144 | ||||
| -rw-r--r-- | net/mac80211/util.c | 22 |
4 files changed, 98 insertions, 79 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 785f6363a6fc..6ce62e553dc2 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
| @@ -184,10 +184,6 @@ struct ieee80211_rx_data { | |||
| 184 | u16 tkip_iv16; | 184 | u16 tkip_iv16; |
| 185 | }; | 185 | }; |
| 186 | 186 | ||
| 187 | struct ieee80211_tx_stored_packet { | ||
| 188 | struct sk_buff *skb; | ||
| 189 | }; | ||
| 190 | |||
| 191 | struct beacon_data { | 187 | struct beacon_data { |
| 192 | u8 *head, *tail; | 188 | u8 *head, *tail; |
| 193 | int head_len, tail_len; | 189 | int head_len, tail_len; |
| @@ -583,6 +579,7 @@ enum queue_stop_reason { | |||
| 583 | IEEE80211_QUEUE_STOP_REASON_CSA, | 579 | IEEE80211_QUEUE_STOP_REASON_CSA, |
| 584 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION, | 580 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION, |
| 585 | IEEE80211_QUEUE_STOP_REASON_SUSPEND, | 581 | IEEE80211_QUEUE_STOP_REASON_SUSPEND, |
| 582 | IEEE80211_QUEUE_STOP_REASON_PENDING, | ||
| 586 | }; | 583 | }; |
| 587 | 584 | ||
| 588 | struct ieee80211_master_priv { | 585 | struct ieee80211_master_priv { |
| @@ -639,9 +636,7 @@ struct ieee80211_local { | |||
| 639 | struct sta_info *sta_hash[STA_HASH_SIZE]; | 636 | struct sta_info *sta_hash[STA_HASH_SIZE]; |
| 640 | struct timer_list sta_cleanup; | 637 | struct timer_list sta_cleanup; |
| 641 | 638 | ||
| 642 | unsigned long queues_pending[BITS_TO_LONGS(IEEE80211_MAX_QUEUES)]; | 639 | struct sk_buff_head pending[IEEE80211_MAX_QUEUES]; |
| 643 | unsigned long queues_pending_run[BITS_TO_LONGS(IEEE80211_MAX_QUEUES)]; | ||
| 644 | struct ieee80211_tx_stored_packet pending_packet[IEEE80211_MAX_QUEUES]; | ||
| 645 | struct tasklet_struct tx_pending_tasklet; | 640 | struct tasklet_struct tx_pending_tasklet; |
| 646 | 641 | ||
| 647 | /* number of interfaces with corresponding IFF_ flags */ | 642 | /* number of interfaces with corresponding IFF_ flags */ |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index dac68d476bff..a7430e98c531 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
| @@ -781,6 +781,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
| 781 | 781 | ||
| 782 | sta_info_init(local); | 782 | sta_info_init(local); |
| 783 | 783 | ||
| 784 | for (i = 0; i < IEEE80211_MAX_QUEUES; i++) | ||
| 785 | skb_queue_head_init(&local->pending[i]); | ||
| 784 | tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending, | 786 | tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending, |
| 785 | (unsigned long)local); | 787 | (unsigned long)local); |
| 786 | tasklet_disable(&local->tx_pending_tasklet); | 788 | tasklet_disable(&local->tx_pending_tasklet); |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 0d97cad84b1b..ee1b77f8a804 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
| @@ -1189,12 +1189,14 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) | |||
| 1189 | struct ieee80211_tx_data tx; | 1189 | struct ieee80211_tx_data tx; |
| 1190 | ieee80211_tx_result res_prepare; | 1190 | ieee80211_tx_result res_prepare; |
| 1191 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1191 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
| 1192 | int ret; | 1192 | struct sk_buff *next; |
| 1193 | unsigned long flags; | ||
| 1194 | int ret, retries; | ||
| 1193 | u16 queue; | 1195 | u16 queue; |
| 1194 | 1196 | ||
| 1195 | queue = skb_get_queue_mapping(skb); | 1197 | queue = skb_get_queue_mapping(skb); |
| 1196 | 1198 | ||
| 1197 | WARN_ON(test_bit(queue, local->queues_pending)); | 1199 | WARN_ON(!skb_queue_empty(&local->pending[queue])); |
| 1198 | 1200 | ||
| 1199 | if (unlikely(skb->len < 10)) { | 1201 | if (unlikely(skb->len < 10)) { |
| 1200 | dev_kfree_skb(skb); | 1202 | dev_kfree_skb(skb); |
| @@ -1219,40 +1221,52 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) | |||
| 1219 | if (invoke_tx_handlers(&tx)) | 1221 | if (invoke_tx_handlers(&tx)) |
| 1220 | goto out; | 1222 | goto out; |
| 1221 | 1223 | ||
| 1222 | retry: | 1224 | retries = 0; |
| 1225 | retry: | ||
| 1223 | ret = __ieee80211_tx(local, &tx); | 1226 | ret = __ieee80211_tx(local, &tx); |
| 1224 | if (ret) { | 1227 | switch (ret) { |
| 1225 | struct ieee80211_tx_stored_packet *store; | 1228 | case IEEE80211_TX_OK: |
| 1226 | 1229 | break; | |
| 1230 | case IEEE80211_TX_AGAIN: | ||
| 1227 | /* | 1231 | /* |
| 1228 | * Since there are no fragmented frames on A-MPDU | 1232 | * Since there are no fragmented frames on A-MPDU |
| 1229 | * queues, there's no reason for a driver to reject | 1233 | * queues, there's no reason for a driver to reject |
| 1230 | * a frame there, warn and drop it. | 1234 | * a frame there, warn and drop it. |
| 1231 | */ | 1235 | */ |
| 1232 | if (ret != IEEE80211_TX_PENDING) | 1236 | if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU)) |
| 1233 | if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU)) | 1237 | goto drop; |
| 1234 | goto drop; | 1238 | /* fall through */ |
| 1239 | case IEEE80211_TX_PENDING: | ||
| 1240 | skb = tx.skb; | ||
| 1235 | 1241 | ||
| 1236 | store = &local->pending_packet[queue]; | 1242 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
| 1237 | 1243 | ||
| 1238 | set_bit(queue, local->queues_pending); | 1244 | if (__netif_subqueue_stopped(local->mdev, queue)) { |
| 1239 | smp_mb(); | 1245 | do { |
| 1240 | /* | 1246 | next = skb->next; |
| 1241 | * When the driver gets out of buffers during sending of | 1247 | skb->next = NULL; |
| 1242 | * fragments and calls ieee80211_stop_queue, the netif | 1248 | skb_queue_tail(&local->pending[queue], skb); |
| 1243 | * subqueue is stopped. There is, however, a small window | 1249 | } while ((skb = next)); |
| 1244 | * in which the PENDING bit is not yet set. If a buffer | 1250 | |
| 1245 | * gets available in that window (i.e. driver calls | 1251 | /* |
| 1246 | * ieee80211_wake_queue), we would end up with ieee80211_tx | 1252 | * Make sure nobody will enable the queue on us |
| 1247 | * called with the PENDING bit still set. Prevent this by | 1253 | * (without going through the tasklet) nor disable the |
| 1248 | * continuing transmitting here when that situation is | 1254 | * netdev queue underneath the pending handling code. |
| 1249 | * possible to have happened. | 1255 | */ |
| 1250 | */ | 1256 | __set_bit(IEEE80211_QUEUE_STOP_REASON_PENDING, |
| 1251 | if (!__netif_subqueue_stopped(local->mdev, queue)) { | 1257 | &local->queue_stop_reasons[queue]); |
| 1252 | clear_bit(queue, local->queues_pending); | 1258 | |
| 1259 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, | ||
| 1260 | flags); | ||
| 1261 | } else { | ||
| 1262 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, | ||
| 1263 | flags); | ||
| 1264 | |||
| 1265 | retries++; | ||
| 1266 | if (WARN(retries > 10, "tx refused but queue active")) | ||
| 1267 | goto drop; | ||
| 1253 | goto retry; | 1268 | goto retry; |
| 1254 | } | 1269 | } |
| 1255 | store->skb = tx.skb; | ||
| 1256 | } | 1270 | } |
| 1257 | out: | 1271 | out: |
| 1258 | rcu_read_unlock(); | 1272 | rcu_read_unlock(); |
| @@ -1263,8 +1277,6 @@ retry: | |||
| 1263 | 1277 | ||
| 1264 | skb = tx.skb; | 1278 | skb = tx.skb; |
| 1265 | while (skb) { | 1279 | while (skb) { |
| 1266 | struct sk_buff *next; | ||
| 1267 | |||
| 1268 | next = skb->next; | 1280 | next = skb->next; |
| 1269 | dev_kfree_skb(skb); | 1281 | dev_kfree_skb(skb); |
| 1270 | skb = next; | 1282 | skb = next; |
| @@ -1803,23 +1815,10 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
| 1803 | */ | 1815 | */ |
| 1804 | void ieee80211_clear_tx_pending(struct ieee80211_local *local) | 1816 | void ieee80211_clear_tx_pending(struct ieee80211_local *local) |
| 1805 | { | 1817 | { |
| 1806 | struct sk_buff *skb; | ||
| 1807 | int i; | 1818 | int i; |
| 1808 | 1819 | ||
| 1809 | for (i = 0; i < local->hw.queues; i++) { | 1820 | for (i = 0; i < local->hw.queues; i++) |
| 1810 | if (!test_bit(i, local->queues_pending)) | 1821 | skb_queue_purge(&local->pending[i]); |
| 1811 | continue; | ||
| 1812 | |||
| 1813 | skb = local->pending_packet[i].skb; | ||
| 1814 | while (skb) { | ||
| 1815 | struct sk_buff *next; | ||
| 1816 | |||
| 1817 | next = skb->next; | ||
| 1818 | dev_kfree_skb(skb); | ||
| 1819 | skb = next; | ||
| 1820 | } | ||
| 1821 | clear_bit(i, local->queues_pending); | ||
| 1822 | } | ||
| 1823 | } | 1822 | } |
| 1824 | 1823 | ||
| 1825 | /* | 1824 | /* |
| @@ -1830,40 +1829,57 @@ void ieee80211_tx_pending(unsigned long data) | |||
| 1830 | { | 1829 | { |
| 1831 | struct ieee80211_local *local = (struct ieee80211_local *)data; | 1830 | struct ieee80211_local *local = (struct ieee80211_local *)data; |
| 1832 | struct net_device *dev = local->mdev; | 1831 | struct net_device *dev = local->mdev; |
| 1833 | struct ieee80211_tx_stored_packet *store; | ||
| 1834 | struct ieee80211_hdr *hdr; | 1832 | struct ieee80211_hdr *hdr; |
| 1833 | unsigned long flags; | ||
| 1835 | struct ieee80211_tx_data tx; | 1834 | struct ieee80211_tx_data tx; |
| 1836 | int i, ret; | 1835 | int i, ret; |
| 1836 | bool next; | ||
| 1837 | 1837 | ||
| 1838 | rcu_read_lock(); | 1838 | rcu_read_lock(); |
| 1839 | netif_tx_lock_bh(dev); | 1839 | netif_tx_lock_bh(dev); |
| 1840 | for (i = 0; i < local->hw.queues; i++) { | ||
| 1841 | /* Check that this queue is ok */ | ||
| 1842 | if (__netif_subqueue_stopped(local->mdev, i) && | ||
| 1843 | !test_bit(i, local->queues_pending_run)) | ||
| 1844 | continue; | ||
| 1845 | 1840 | ||
| 1846 | if (!test_bit(i, local->queues_pending)) { | 1841 | for (i = 0; i < local->hw.queues; i++) { |
| 1847 | clear_bit(i, local->queues_pending_run); | 1842 | /* |
| 1848 | ieee80211_wake_queue(&local->hw, i); | 1843 | * If queue is stopped by something other than due to pending |
| 1844 | * frames, or we have no pending frames, proceed to next queue. | ||
| 1845 | */ | ||
| 1846 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | ||
| 1847 | next = false; | ||
| 1848 | if (local->queue_stop_reasons[i] != | ||
| 1849 | BIT(IEEE80211_QUEUE_STOP_REASON_PENDING) || | ||
| 1850 | skb_queue_empty(&local->pending[i])) | ||
| 1851 | next = true; | ||
| 1852 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
| 1853 | |||
| 1854 | if (next) | ||
| 1849 | continue; | 1855 | continue; |
| 1850 | } | ||
| 1851 | 1856 | ||
| 1852 | clear_bit(i, local->queues_pending_run); | 1857 | /* |
| 1858 | * start the queue now to allow processing our packets, | ||
| 1859 | * we're under the tx lock here anyway so nothing will | ||
| 1860 | * happen as a result of this | ||
| 1861 | */ | ||
| 1853 | netif_start_subqueue(local->mdev, i); | 1862 | netif_start_subqueue(local->mdev, i); |
| 1854 | 1863 | ||
| 1855 | store = &local->pending_packet[i]; | 1864 | while (!skb_queue_empty(&local->pending[i])) { |
| 1856 | tx.flags = 0; | 1865 | tx.flags = 0; |
| 1857 | tx.skb = store->skb; | 1866 | tx.skb = skb_dequeue(&local->pending[i]); |
| 1858 | hdr = (struct ieee80211_hdr *)tx.skb->data; | 1867 | hdr = (struct ieee80211_hdr *)tx.skb->data; |
| 1859 | tx.sta = sta_info_get(local, hdr->addr1); | 1868 | tx.sta = sta_info_get(local, hdr->addr1); |
| 1860 | ret = __ieee80211_tx(local, &tx); | 1869 | |
| 1861 | store->skb = tx.skb; | 1870 | ret = __ieee80211_tx(local, &tx); |
| 1862 | if (!ret) { | 1871 | if (ret != IEEE80211_TX_OK) { |
| 1863 | clear_bit(i, local->queues_pending); | 1872 | skb_queue_head(&local->pending[i], tx.skb); |
| 1864 | ieee80211_wake_queue(&local->hw, i); | 1873 | break; |
| 1874 | } | ||
| 1865 | } | 1875 | } |
| 1876 | |||
| 1877 | /* Start regular packet processing again. */ | ||
| 1878 | if (skb_queue_empty(&local->pending[i])) | ||
| 1879 | ieee80211_wake_queue_by_reason(&local->hw, i, | ||
| 1880 | IEEE80211_QUEUE_STOP_REASON_PENDING); | ||
| 1866 | } | 1881 | } |
| 1882 | |||
| 1867 | netif_tx_unlock_bh(dev); | 1883 | netif_tx_unlock_bh(dev); |
| 1868 | rcu_read_unlock(); | 1884 | rcu_read_unlock(); |
| 1869 | } | 1885 | } |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 021166c8cce2..0247d8022f5f 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
| @@ -365,16 +365,16 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, | |||
| 365 | 365 | ||
| 366 | __clear_bit(reason, &local->queue_stop_reasons[queue]); | 366 | __clear_bit(reason, &local->queue_stop_reasons[queue]); |
| 367 | 367 | ||
| 368 | if (!skb_queue_empty(&local->pending[queue]) && | ||
| 369 | local->queue_stop_reasons[queue] == | ||
| 370 | BIT(IEEE80211_QUEUE_STOP_REASON_PENDING)) | ||
| 371 | tasklet_schedule(&local->tx_pending_tasklet); | ||
| 372 | |||
| 368 | if (local->queue_stop_reasons[queue] != 0) | 373 | if (local->queue_stop_reasons[queue] != 0) |
| 369 | /* someone still has this queue stopped */ | 374 | /* someone still has this queue stopped */ |
| 370 | return; | 375 | return; |
| 371 | 376 | ||
| 372 | if (test_bit(queue, local->queues_pending)) { | 377 | netif_wake_subqueue(local->mdev, queue); |
| 373 | set_bit(queue, local->queues_pending_run); | ||
| 374 | tasklet_schedule(&local->tx_pending_tasklet); | ||
| 375 | } else { | ||
| 376 | netif_wake_subqueue(local->mdev, queue); | ||
| 377 | } | ||
| 378 | } | 378 | } |
| 379 | 379 | ||
| 380 | void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, | 380 | void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, |
| @@ -420,9 +420,15 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, | |||
| 420 | reason = IEEE80211_QUEUE_STOP_REASON_AGGREGATION; | 420 | reason = IEEE80211_QUEUE_STOP_REASON_AGGREGATION; |
| 421 | } | 421 | } |
| 422 | 422 | ||
| 423 | __set_bit(reason, &local->queue_stop_reasons[queue]); | 423 | /* |
| 424 | * Only stop if it was previously running, this is necessary | ||
| 425 | * for correct pending packets handling because there we may | ||
| 426 | * start (but not wake) the queue and rely on that. | ||
| 427 | */ | ||
| 428 | if (!local->queue_stop_reasons[queue]) | ||
| 429 | netif_stop_subqueue(local->mdev, queue); | ||
| 424 | 430 | ||
| 425 | netif_stop_subqueue(local->mdev, queue); | 431 | __set_bit(reason, &local->queue_stop_reasons[queue]); |
| 426 | } | 432 | } |
| 427 | 433 | ||
| 428 | void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, | 434 | void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, |
