wl1251: Add support for idle mode
[pandora-wifi.git] / patches / 22-multiqueue.patch
1 Backport multiqueue support for kernels < 2.6.27
2
3 The 2.6.23 kernel added some initial multiqueue support.
4 That release relied on the on the notion of struct
5 net_device_subqueue attached to the netdevice struct
6 as an array. The 2.6.27 renamed these to struct netdev_queue,
7 and enhanced MQ support by providing locks separately onto
8 each queue. MQ support on 2.6.27 also extended each netdev
9 to be able to assign a select_queue callback to be used by
10 core networking for prior to pushing the skb out to the device
11 driver so that queue selection can be dealt with and
12 customized internally on the driver.
13
14 For kernels 2.6.23..2.6.26 then we backport MQ support by
15 using the equivalent calls on the struct netdev_queue to
16 the struct net_device_subqueue. The performance penalty
17 here is just that all these queues share a common lock
18 so stateful operations on one queue would imply a delay
19 on other queues.
20
21 For older kernels than 2.6.23 we can only stop all the
22 queues then and wake them up only if no other queue had
23 been stopped previously. This means for kernels older
24 than 2.6.23 there is a performance penalty and congestion
25 on one queue would imply propagating the same congestion
26 impact on all the other queues.
27
28 The select_queue callback was only added as of 2.6.27 via
29 commit eae792b7 so for kernels older than 2.6.23 and up
30 to 2.6.27 we must ensure we do the selection of the queue
31 once the core networking calls mac80211's dev_hard_start_xmit()
32 (ndo_start_xmit() callback on newer kernels).
33
34 This patch then consists of three parts:
35
36   1) Addresses the lack of select_queue on older kernels than 2.6.27
37   2) Extends the backport of net_device_ops for select_queue for kernels >= 2.6.27
38   3) Backporting wake/stop queue for older kernels:
39         - Handle with net_device_subqueue for >= 2.6.23
40         - Treat each queue operation as an aggregate for all queues
41
42 Monitor interfaces have their own select_queue -- monitor interfaces
43 are used for injecting frames so they have their own respective queue
44 handling, but mac80211 just always sends management frames on VO
45 queue by using skb_set_queue_mapping(skb, 0) through ieee80211_tx_skb()
46
47 --- a/net/mac80211/util.c
48 +++ b/net/mac80211/util.c
49 @@ -266,6 +266,18 @@ __le16 ieee80211_ctstoself_duration(stru
50  }
51  EXPORT_SYMBOL(ieee80211_ctstoself_duration);
52  
53 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23))
54 +static bool ieee80211_all_queues_started(struct ieee80211_hw *hw)
55 +{
56 +       unsigned int queue;
57 +
58 +       for (queue = 0; queue < hw->queues; queue++)
59 +               if (ieee80211_queue_stopped(hw, queue))
60 +                       return false;
61 +       return true;
62 +}
63 +#endif
64 +
65  static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
66                                    enum queue_stop_reason reason)
67  {
68 @@ -286,7 +298,14 @@ static void __ieee80211_wake_queue(struc
69  
70         rcu_read_lock();
71         list_for_each_entry_rcu(sdata, &local->interfaces, list)
72 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
73                 netif_tx_wake_queue(netdev_get_tx_queue(sdata->dev, queue));
74 +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23))
75 +               netif_start_subqueue(sdata->dev, queue);
76 +#else
77 +               if (ieee80211_all_queues_started(hw))
78 +                       netif_wake_queue(sdata->dev);
79 +#endif
80         rcu_read_unlock();
81  }
82  
83 @@ -321,7 +340,13 @@ static void __ieee80211_stop_queue(struc
84  
85         rcu_read_lock();
86         list_for_each_entry_rcu(sdata, &local->interfaces, list)
87 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
88                 netif_tx_stop_queue(netdev_get_tx_queue(sdata->dev, queue));
89 +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23))
90 +               netif_stop_subqueue(sdata->dev, queue);
91 +#else
92 +               netif_stop_queue(sdata->dev);
93 +#endif
94         rcu_read_unlock();
95  }
96  
97 --- a/net/mac80211/tx.c
98 +++ b/net/mac80211/tx.c
99 @@ -1564,6 +1564,10 @@ static void ieee80211_xmit(struct ieee80
100                                 return;
101                         }
102  
103 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27))
104 +       /* Older kernels do not have the select_queue callback */
105 +       skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, skb));
106 +#endif
107         ieee80211_set_qos_hdr(local, skb);
108         ieee80211_tx(sdata, skb, false);
109         rcu_read_unlock();
110 --- a/net/mac80211/iface.c
111 +++ b/net/mac80211/iface.c
112 @@ -660,11 +660,13 @@ static void ieee80211_teardown_sdata(str
113         WARN_ON(flushed);
114  }
115  
116 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
117  static u16 ieee80211_netdev_select_queue(struct net_device *dev,
118                                          struct sk_buff *skb)
119  {
120         return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb);
121  }
122 +#endif
123  
124  #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
125  static const struct net_device_ops ieee80211_dataif_ops = {
126 @@ -679,6 +681,7 @@ static const struct net_device_ops ieee8
127  };
128  #endif
129  
130 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
131  static u16 ieee80211_monitor_select_queue(struct net_device *dev,
132                                           struct sk_buff *skb)
133  {
134 @@ -711,6 +714,7 @@ static u16 ieee80211_monitor_select_queu
135  
136         return ieee80211_downgrade_queue(local, skb);
137  }
138 +#endif
139  
140  #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
141  static const struct net_device_ops ieee80211_monitorif_ops = {
142 @@ -735,7 +739,9 @@ static void ieee80211_if_setup(struct ne
143         dev->set_multicast_list = ieee80211_set_multicast_list;
144         dev->change_mtu = ieee80211_change_mtu;
145         dev->set_mac_address = ieee80211_change_mac;
146 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
147         dev->select_queue = ieee80211_netdev_select_queue;
148 +#endif
149         dev->open = ieee80211_open;
150         dev->stop = ieee80211_stop;
151         /* we will validate the address ourselves in ->open */
152 @@ -787,7 +793,9 @@ static void ieee80211_setup_sdata(struct
153                 sdata->dev->netdev_ops = &ieee80211_monitorif_ops;
154  #else
155                 sdata->dev->hard_start_xmit = ieee80211_monitor_start_xmit;
156 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
157                 sdata->dev->select_queue = ieee80211_monitor_select_queue;
158 +#endif
159                 sdata->dev->set_mac_address = eth_mac_addr;
160  #endif
161                 sdata->u.mntr_flags = MONITOR_FLAG_CONTROL |