diff options
author | John W. Linville <linville@tuxdriver.com> | 2010-07-29 16:14:14 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-08-16 14:39:46 -0400 |
commit | 030725d2c7c1fafec7ede618647bf30ed79601f0 (patch) | |
tree | aa2d193ede503aaea4d60ef609a099c99bc74888 /drivers/net | |
parent | 4e6cbfd09c66893e5134c9896e9af353c2322b66 (diff) |
rtl8180: use NAPI for bottom-half processing
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/rtl818x/rtl8180_dev.c | 128 |
1 files changed, 69 insertions, 59 deletions
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index b50c39aaec05..02d0f71d0faa 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c | |||
@@ -99,19 +99,66 @@ void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) | |||
99 | } | 99 | } |
100 | } | 100 | } |
101 | 101 | ||
102 | static void rtl8180_handle_rx(struct ieee80211_hw *dev) | 102 | static void rtl8180_handle_tx(struct ieee80211_hw *dev) |
103 | { | 103 | { |
104 | struct rtl8180_priv *priv = dev->priv; | 104 | struct rtl8180_priv *priv = dev->priv; |
105 | unsigned int count = 32; | 105 | struct rtl8180_tx_ring *ring; |
106 | int prio; | ||
107 | |||
108 | spin_lock(&priv->lock); | ||
109 | |||
110 | for (prio = 3; prio >= 0; prio--) { | ||
111 | ring = &priv->tx_ring[prio]; | ||
112 | |||
113 | while (skb_queue_len(&ring->queue)) { | ||
114 | struct rtl8180_tx_desc *entry = &ring->desc[ring->idx]; | ||
115 | struct sk_buff *skb; | ||
116 | struct ieee80211_tx_info *info; | ||
117 | u32 flags = le32_to_cpu(entry->flags); | ||
118 | |||
119 | if (flags & RTL818X_TX_DESC_FLAG_OWN) | ||
120 | break; | ||
121 | |||
122 | ring->idx = (ring->idx + 1) % ring->entries; | ||
123 | skb = __skb_dequeue(&ring->queue); | ||
124 | pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf), | ||
125 | skb->len, PCI_DMA_TODEVICE); | ||
126 | |||
127 | info = IEEE80211_SKB_CB(skb); | ||
128 | ieee80211_tx_info_clear_status(info); | ||
129 | |||
130 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && | ||
131 | (flags & RTL818X_TX_DESC_FLAG_TX_OK)) | ||
132 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
133 | |||
134 | info->status.rates[0].count = (flags & 0xFF) + 1; | ||
135 | info->status.rates[1].idx = -1; | ||
136 | |||
137 | ieee80211_tx_status(dev, skb); | ||
138 | if (ring->entries - skb_queue_len(&ring->queue) == 2) | ||
139 | ieee80211_wake_queue(dev, prio); | ||
140 | } | ||
141 | } | ||
142 | |||
143 | spin_unlock(&priv->lock); | ||
144 | } | ||
145 | |||
146 | static int rtl8180_poll(struct ieee80211_hw *dev, int budget) | ||
147 | { | ||
148 | struct rtl8180_priv *priv = dev->priv; | ||
149 | unsigned int count = 0; | ||
106 | u8 signal, agc, sq; | 150 | u8 signal, agc, sq; |
107 | 151 | ||
108 | while (count--) { | 152 | /* handle pending Tx queue cleanup */ |
153 | rtl8180_handle_tx(dev); | ||
154 | |||
155 | while (count++ < budget) { | ||
109 | struct rtl8180_rx_desc *entry = &priv->rx_ring[priv->rx_idx]; | 156 | struct rtl8180_rx_desc *entry = &priv->rx_ring[priv->rx_idx]; |
110 | struct sk_buff *skb = priv->rx_buf[priv->rx_idx]; | 157 | struct sk_buff *skb = priv->rx_buf[priv->rx_idx]; |
111 | u32 flags = le32_to_cpu(entry->flags); | 158 | u32 flags = le32_to_cpu(entry->flags); |
112 | 159 | ||
113 | if (flags & RTL818X_RX_DESC_FLAG_OWN) | 160 | if (flags & RTL818X_RX_DESC_FLAG_OWN) |
114 | return; | 161 | break; |
115 | 162 | ||
116 | if (unlikely(flags & (RTL818X_RX_DESC_FLAG_DMA_FAIL | | 163 | if (unlikely(flags & (RTL818X_RX_DESC_FLAG_DMA_FAIL | |
117 | RTL818X_RX_DESC_FLAG_FOF | | 164 | RTL818X_RX_DESC_FLAG_FOF | |
@@ -151,7 +198,7 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) | |||
151 | rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; | 198 | rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; |
152 | 199 | ||
153 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); | 200 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); |
154 | ieee80211_rx_irqsafe(dev, skb); | 201 | ieee80211_rx(dev, skb); |
155 | 202 | ||
156 | skb = new_skb; | 203 | skb = new_skb; |
157 | priv->rx_buf[priv->rx_idx] = skb; | 204 | priv->rx_buf[priv->rx_idx] = skb; |
@@ -168,41 +215,16 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) | |||
168 | entry->flags |= cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR); | 215 | entry->flags |= cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR); |
169 | priv->rx_idx = (priv->rx_idx + 1) % 32; | 216 | priv->rx_idx = (priv->rx_idx + 1) % 32; |
170 | } | 217 | } |
171 | } | ||
172 | |||
173 | static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio) | ||
174 | { | ||
175 | struct rtl8180_priv *priv = dev->priv; | ||
176 | struct rtl8180_tx_ring *ring = &priv->tx_ring[prio]; | ||
177 | |||
178 | while (skb_queue_len(&ring->queue)) { | ||
179 | struct rtl8180_tx_desc *entry = &ring->desc[ring->idx]; | ||
180 | struct sk_buff *skb; | ||
181 | struct ieee80211_tx_info *info; | ||
182 | u32 flags = le32_to_cpu(entry->flags); | ||
183 | |||
184 | if (flags & RTL818X_TX_DESC_FLAG_OWN) | ||
185 | return; | ||
186 | |||
187 | ring->idx = (ring->idx + 1) % ring->entries; | ||
188 | skb = __skb_dequeue(&ring->queue); | ||
189 | pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf), | ||
190 | skb->len, PCI_DMA_TODEVICE); | ||
191 | |||
192 | info = IEEE80211_SKB_CB(skb); | ||
193 | ieee80211_tx_info_clear_status(info); | ||
194 | |||
195 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && | ||
196 | (flags & RTL818X_TX_DESC_FLAG_TX_OK)) | ||
197 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
198 | 218 | ||
199 | info->status.rates[0].count = (flags & 0xFF) + 1; | 219 | if (count < budget) { |
200 | info->status.rates[1].idx = -1; | 220 | /* disable polling */ |
221 | ieee80211_napi_complete(dev); | ||
201 | 222 | ||
202 | ieee80211_tx_status_irqsafe(dev, skb); | 223 | /* enable interrupts */ |
203 | if (ring->entries - skb_queue_len(&ring->queue) == 2) | 224 | rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF); |
204 | ieee80211_wake_queue(dev, prio); | ||
205 | } | 225 | } |
226 | |||
227 | return count; | ||
206 | } | 228 | } |
207 | 229 | ||
208 | static irqreturn_t rtl8180_interrupt(int irq, void *dev_id) | 230 | static irqreturn_t rtl8180_interrupt(int irq, void *dev_id) |
@@ -211,31 +233,17 @@ static irqreturn_t rtl8180_interrupt(int irq, void *dev_id) | |||
211 | struct rtl8180_priv *priv = dev->priv; | 233 | struct rtl8180_priv *priv = dev->priv; |
212 | u16 reg; | 234 | u16 reg; |
213 | 235 | ||
214 | spin_lock(&priv->lock); | ||
215 | reg = rtl818x_ioread16(priv, &priv->map->INT_STATUS); | 236 | reg = rtl818x_ioread16(priv, &priv->map->INT_STATUS); |
216 | if (unlikely(reg == 0xFFFF)) { | 237 | if (unlikely(reg == 0xFFFF)) |
217 | spin_unlock(&priv->lock); | ||
218 | return IRQ_HANDLED; | 238 | return IRQ_HANDLED; |
219 | } | ||
220 | 239 | ||
221 | rtl818x_iowrite16(priv, &priv->map->INT_STATUS, reg); | 240 | rtl818x_iowrite16(priv, &priv->map->INT_STATUS, reg); |
222 | 241 | ||
223 | if (reg & (RTL818X_INT_TXB_OK | RTL818X_INT_TXB_ERR)) | 242 | /* disable interrupts */ |
224 | rtl8180_handle_tx(dev, 3); | 243 | rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); |
225 | |||
226 | if (reg & (RTL818X_INT_TXH_OK | RTL818X_INT_TXH_ERR)) | ||
227 | rtl8180_handle_tx(dev, 2); | ||
228 | |||
229 | if (reg & (RTL818X_INT_TXN_OK | RTL818X_INT_TXN_ERR)) | ||
230 | rtl8180_handle_tx(dev, 1); | ||
231 | |||
232 | if (reg & (RTL818X_INT_TXL_OK | RTL818X_INT_TXL_ERR)) | ||
233 | rtl8180_handle_tx(dev, 0); | ||
234 | |||
235 | if (reg & (RTL818X_INT_RX_OK | RTL818X_INT_RX_ERR)) | ||
236 | rtl8180_handle_rx(dev); | ||
237 | 244 | ||
238 | spin_unlock(&priv->lock); | 245 | /* enable polling */ |
246 | ieee80211_napi_schedule(dev); | ||
239 | 247 | ||
240 | return IRQ_HANDLED; | 248 | return IRQ_HANDLED; |
241 | } | 249 | } |
@@ -247,7 +255,6 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
247 | struct rtl8180_priv *priv = dev->priv; | 255 | struct rtl8180_priv *priv = dev->priv; |
248 | struct rtl8180_tx_ring *ring; | 256 | struct rtl8180_tx_ring *ring; |
249 | struct rtl8180_tx_desc *entry; | 257 | struct rtl8180_tx_desc *entry; |
250 | unsigned long flags; | ||
251 | unsigned int idx, prio; | 258 | unsigned int idx, prio; |
252 | dma_addr_t mapping; | 259 | dma_addr_t mapping; |
253 | u32 tx_flags; | 260 | u32 tx_flags; |
@@ -294,7 +301,7 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
294 | plcp_len |= 1 << 15; | 301 | plcp_len |= 1 << 15; |
295 | } | 302 | } |
296 | 303 | ||
297 | spin_lock_irqsave(&priv->lock, flags); | 304 | spin_lock(&priv->lock); |
298 | 305 | ||
299 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | 306 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { |
300 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) | 307 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) |
@@ -318,7 +325,7 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
318 | if (ring->entries - skb_queue_len(&ring->queue) < 2) | 325 | if (ring->entries - skb_queue_len(&ring->queue) < 2) |
319 | ieee80211_stop_queue(dev, prio); | 326 | ieee80211_stop_queue(dev, prio); |
320 | 327 | ||
321 | spin_unlock_irqrestore(&priv->lock, flags); | 328 | spin_unlock(&priv->lock); |
322 | 329 | ||
323 | rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4))); | 330 | rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4))); |
324 | 331 | ||
@@ -861,6 +868,7 @@ static const struct ieee80211_ops rtl8180_ops = { | |||
861 | .prepare_multicast = rtl8180_prepare_multicast, | 868 | .prepare_multicast = rtl8180_prepare_multicast, |
862 | .configure_filter = rtl8180_configure_filter, | 869 | .configure_filter = rtl8180_configure_filter, |
863 | .get_tsf = rtl8180_get_tsf, | 870 | .get_tsf = rtl8180_get_tsf, |
871 | .napi_poll = rtl8180_poll, | ||
864 | }; | 872 | }; |
865 | 873 | ||
866 | static void rtl8180_eeprom_register_read(struct eeprom_93cx6 *eeprom) | 874 | static void rtl8180_eeprom_register_read(struct eeprom_93cx6 *eeprom) |
@@ -992,6 +1000,8 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, | |||
992 | dev->queues = 1; | 1000 | dev->queues = 1; |
993 | dev->max_signal = 65; | 1001 | dev->max_signal = 65; |
994 | 1002 | ||
1003 | dev->napi_weight = 64; | ||
1004 | |||
995 | reg = rtl818x_ioread32(priv, &priv->map->TX_CONF); | 1005 | reg = rtl818x_ioread32(priv, &priv->map->TX_CONF); |
996 | reg &= RTL818X_TX_CONF_HWVER_MASK; | 1006 | reg &= RTL818X_TX_CONF_HWVER_MASK; |
997 | switch (reg) { | 1007 | switch (reg) { |