aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-rx.c
diff options
context:
space:
mode:
authorZhu Yi <yi.zhu@intel.com>2009-10-09 05:19:45 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-10-27 16:48:06 -0400
commit2f301227a1ede57504694e1f64839839f5737cac (patch)
treec148ca6c3409f5f8fed4455fba3a78fe31469135 /drivers/net/wireless/iwlwifi/iwl-rx.c
parentae751bab9f55c3152ebf713c89a4fb6f439c2575 (diff)
iwlwifi: use paged Rx
This switches the iwlwifi driver to use paged skb from linear skb for Rx buffer. So that it relieves some Rx buffer allocation pressure for the memory subsystem. Currently iwlwifi (4K for 3945) requests 8K bytes for Rx buffer. Due to the trailing skb_shared_info in the skb->data, alloc_skb() will do the next order allocation, which is 16K bytes. This is suboptimal and more likely to fail when the system is under memory usage pressure. Switching to paged Rx skb lets us allocate the RXB directly by alloc_pages(), so that only order 1 allocation is required. It also adjusts the area spin_lock (with IRQ disabled) protected in the tasklet because tasklet guarentees to run only on one CPU and the new unprotected code can be preempted by the IRQ handler. This saves us from spawning another workqueue to make skb_linearize/__pskb_pull_tail happy (which cannot be called in hard irq context). Finally, mac80211 doesn't support paged Rx yet. So we linearize the skb for all the management frames and software decryption or defragmentation required data frames before handed to mac80211. For all the other frames, we __pskb_pull_tail 64 bytes in the linear area of the skb for mac80211 to handle them properly. Signed-off-by: Zhu Yi <yi.zhu@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-rx.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c122
1 files changed, 76 insertions, 46 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 7ad327ef9cb5..0a407f79de01 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -200,7 +200,7 @@ int iwl_rx_queue_restock(struct iwl_priv *priv)
200 list_del(element); 200 list_del(element);
201 201
202 /* Point to Rx buffer via next RBD in circular buffer */ 202 /* Point to Rx buffer via next RBD in circular buffer */
203 rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->aligned_dma_addr); 203 rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->page_dma);
204 rxq->queue[rxq->write] = rxb; 204 rxq->queue[rxq->write] = rxb;
205 rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; 205 rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
206 rxq->free_count--; 206 rxq->free_count--;
@@ -239,7 +239,7 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority)
239 struct iwl_rx_queue *rxq = &priv->rxq; 239 struct iwl_rx_queue *rxq = &priv->rxq;
240 struct list_head *element; 240 struct list_head *element;
241 struct iwl_rx_mem_buffer *rxb; 241 struct iwl_rx_mem_buffer *rxb;
242 struct sk_buff *skb; 242 struct page *page;
243 unsigned long flags; 243 unsigned long flags;
244 244
245 while (1) { 245 while (1) {
@@ -252,29 +252,34 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority)
252 252
253 if (rxq->free_count > RX_LOW_WATERMARK) 253 if (rxq->free_count > RX_LOW_WATERMARK)
254 priority |= __GFP_NOWARN; 254 priority |= __GFP_NOWARN;
255 /* Alloc a new receive buffer */
256 skb = alloc_skb(priv->hw_params.rx_buf_size + 256,
257 priority);
258 255
259 if (!skb) { 256 if (priv->hw_params.rx_page_order > 0)
257 priority |= __GFP_COMP;
258
259 /* Alloc a new receive buffer */
260 page = alloc_pages(priority, priv->hw_params.rx_page_order);
261 if (!page) {
260 if (net_ratelimit()) 262 if (net_ratelimit())
261 IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n"); 263 IWL_DEBUG_INFO(priv, "alloc_pages failed, "
264 "order: %d\n",
265 priv->hw_params.rx_page_order);
266
262 if ((rxq->free_count <= RX_LOW_WATERMARK) && 267 if ((rxq->free_count <= RX_LOW_WATERMARK) &&
263 net_ratelimit()) 268 net_ratelimit())
264 IWL_CRIT(priv, "Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n", 269 IWL_CRIT(priv, "Failed to alloc_pages with %s. Only %u free buffers remaining.\n",
265 priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL", 270 priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL",
266 rxq->free_count); 271 rxq->free_count);
267 /* We don't reschedule replenish work here -- we will 272 /* We don't reschedule replenish work here -- we will
268 * call the restock method and if it still needs 273 * call the restock method and if it still needs
269 * more buffers it will schedule replenish */ 274 * more buffers it will schedule replenish */
270 break; 275 return;
271 } 276 }
272 277
273 spin_lock_irqsave(&rxq->lock, flags); 278 spin_lock_irqsave(&rxq->lock, flags);
274 279
275 if (list_empty(&rxq->rx_used)) { 280 if (list_empty(&rxq->rx_used)) {
276 spin_unlock_irqrestore(&rxq->lock, flags); 281 spin_unlock_irqrestore(&rxq->lock, flags);
277 dev_kfree_skb_any(skb); 282 __free_pages(page, priv->hw_params.rx_page_order);
278 return; 283 return;
279 } 284 }
280 element = rxq->rx_used.next; 285 element = rxq->rx_used.next;
@@ -283,24 +288,21 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority)
283 288
284 spin_unlock_irqrestore(&rxq->lock, flags); 289 spin_unlock_irqrestore(&rxq->lock, flags);
285 290
286 rxb->skb = skb; 291 rxb->page = page;
287 /* Get physical address of RB/SKB */ 292 /* Get physical address of the RB */
288 rxb->real_dma_addr = pci_map_single( 293 rxb->page_dma = pci_map_page(priv->pci_dev, page, 0,
289 priv->pci_dev, 294 PAGE_SIZE << priv->hw_params.rx_page_order,
290 rxb->skb->data, 295 PCI_DMA_FROMDEVICE);
291 priv->hw_params.rx_buf_size + 256,
292 PCI_DMA_FROMDEVICE);
293 /* dma address must be no more than 36 bits */ 296 /* dma address must be no more than 36 bits */
294 BUG_ON(rxb->real_dma_addr & ~DMA_BIT_MASK(36)); 297 BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
295 /* and also 256 byte aligned! */ 298 /* and also 256 byte aligned! */
296 rxb->aligned_dma_addr = ALIGN(rxb->real_dma_addr, 256); 299 BUG_ON(rxb->page_dma & DMA_BIT_MASK(8));
297 skb_reserve(rxb->skb, rxb->aligned_dma_addr - rxb->real_dma_addr);
298 300
299 spin_lock_irqsave(&rxq->lock, flags); 301 spin_lock_irqsave(&rxq->lock, flags);
300 302
301 list_add_tail(&rxb->list, &rxq->rx_free); 303 list_add_tail(&rxb->list, &rxq->rx_free);
302 rxq->free_count++; 304 rxq->free_count++;
303 priv->alloc_rxb_skb++; 305 priv->alloc_rxb_page++;
304 306
305 spin_unlock_irqrestore(&rxq->lock, flags); 307 spin_unlock_irqrestore(&rxq->lock, flags);
306 } 308 }
@@ -336,12 +338,14 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
336{ 338{
337 int i; 339 int i;
338 for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { 340 for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
339 if (rxq->pool[i].skb != NULL) { 341 if (rxq->pool[i].page != NULL) {
340 pci_unmap_single(priv->pci_dev, 342 pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
341 rxq->pool[i].real_dma_addr, 343 PAGE_SIZE << priv->hw_params.rx_page_order,
342 priv->hw_params.rx_buf_size + 256, 344 PCI_DMA_FROMDEVICE);
343 PCI_DMA_FROMDEVICE); 345 __free_pages(rxq->pool[i].page,
344 dev_kfree_skb(rxq->pool[i].skb); 346 priv->hw_params.rx_page_order);
347 rxq->pool[i].page = NULL;
348 priv->alloc_rxb_page--;
345 } 349 }
346 } 350 }
347 351
@@ -405,14 +409,14 @@ void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
405 for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { 409 for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
406 /* In the reset function, these buffers may have been allocated 410 /* In the reset function, these buffers may have been allocated
407 * to an SKB, so we need to unmap and free potential storage */ 411 * to an SKB, so we need to unmap and free potential storage */
408 if (rxq->pool[i].skb != NULL) { 412 if (rxq->pool[i].page != NULL) {
409 pci_unmap_single(priv->pci_dev, 413 pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
410 rxq->pool[i].real_dma_addr, 414 PAGE_SIZE << priv->hw_params.rx_page_order,
411 priv->hw_params.rx_buf_size + 256, 415 PCI_DMA_FROMDEVICE);
412 PCI_DMA_FROMDEVICE); 416 priv->alloc_rxb_page--;
413 priv->alloc_rxb_skb--; 417 __free_pages(rxq->pool[i].page,
414 dev_kfree_skb(rxq->pool[i].skb); 418 priv->hw_params.rx_page_order);
415 rxq->pool[i].skb = NULL; 419 rxq->pool[i].page = NULL;
416 } 420 }
417 list_add_tail(&rxq->pool[i].list, &rxq->rx_used); 421 list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
418 } 422 }
@@ -491,7 +495,7 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
491 struct iwl_rx_mem_buffer *rxb) 495 struct iwl_rx_mem_buffer *rxb)
492 496
493{ 497{
494 struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; 498 struct iwl_rx_packet *pkt = rxb_addr(rxb);
495 struct iwl_missed_beacon_notif *missed_beacon; 499 struct iwl_missed_beacon_notif *missed_beacon;
496 500
497 missed_beacon = &pkt->u.missed_beacon; 501 missed_beacon = &pkt->u.missed_beacon;
@@ -592,7 +596,7 @@ void iwl_rx_statistics(struct iwl_priv *priv,
592 struct iwl_rx_mem_buffer *rxb) 596 struct iwl_rx_mem_buffer *rxb)
593{ 597{
594 int change; 598 int change;
595 struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; 599 struct iwl_rx_packet *pkt = rxb_addr(rxb);
596 600
597 IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", 601 IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
598 (int)sizeof(priv->statistics), 602 (int)sizeof(priv->statistics),
@@ -919,6 +923,9 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
919 struct iwl_rx_mem_buffer *rxb, 923 struct iwl_rx_mem_buffer *rxb,
920 struct ieee80211_rx_status *stats) 924 struct ieee80211_rx_status *stats)
921{ 925{
926 struct sk_buff *skb;
927 int ret = 0;
928
922 /* We only process data packets if the interface is open */ 929 /* We only process data packets if the interface is open */
923 if (unlikely(!priv->is_open)) { 930 if (unlikely(!priv->is_open)) {
924 IWL_DEBUG_DROP_LIMIT(priv, 931 IWL_DEBUG_DROP_LIMIT(priv,
@@ -931,15 +938,38 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
931 iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) 938 iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats))
932 return; 939 return;
933 940
934 /* Resize SKB from mac header to end of packet */ 941 skb = alloc_skb(IWL_LINK_HDR_MAX, GFP_ATOMIC);
935 skb_reserve(rxb->skb, (void *)hdr - (void *)rxb->skb->data); 942 if (!skb) {
936 skb_put(rxb->skb, len); 943 IWL_ERR(priv, "alloc_skb failed\n");
944 return;
945 }
946
947 skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);
948
949 /* mac80211 currently doesn't support paged SKB. Convert it to
950 * linear SKB for management frame and data frame requires
951 * software decryption or software defragementation. */
952 if (ieee80211_is_mgmt(hdr->frame_control) ||
953 ieee80211_has_protected(hdr->frame_control) ||
954 ieee80211_has_morefrags(hdr->frame_control) ||
955 le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)
956 ret = skb_linearize(skb);
957 else
958 ret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ?
959 0 : -ENOMEM;
960
961 if (ret) {
962 kfree_skb(skb);
963 goto out;
964 }
937 965
938 iwl_update_stats(priv, false, hdr->frame_control, len); 966 iwl_update_stats(priv, false, hdr->frame_control, len);
939 memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats)); 967 memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
940 ieee80211_rx_irqsafe(priv->hw, rxb->skb); 968
941 priv->alloc_rxb_skb--; 969 ieee80211_rx(priv->hw, skb);
942 rxb->skb = NULL; 970 out:
971 priv->alloc_rxb_page--;
972 rxb->page = NULL;
943} 973}
944 974
945/* This is necessary only for a number of statistics, see the caller. */ 975/* This is necessary only for a number of statistics, see the caller. */
@@ -967,7 +997,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
967{ 997{
968 struct ieee80211_hdr *header; 998 struct ieee80211_hdr *header;
969 struct ieee80211_rx_status rx_status; 999 struct ieee80211_rx_status rx_status;
970 struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; 1000 struct iwl_rx_packet *pkt = rxb_addr(rxb);
971 struct iwl_rx_phy_res *phy_res; 1001 struct iwl_rx_phy_res *phy_res;
972 __le32 rx_pkt_status; 1002 __le32 rx_pkt_status;
973 struct iwl4965_rx_mpdu_res_start *amsdu; 1003 struct iwl4965_rx_mpdu_res_start *amsdu;
@@ -1128,7 +1158,7 @@ EXPORT_SYMBOL(iwl_rx_reply_rx);
1128void iwl_rx_reply_rx_phy(struct iwl_priv *priv, 1158void iwl_rx_reply_rx_phy(struct iwl_priv *priv,
1129 struct iwl_rx_mem_buffer *rxb) 1159 struct iwl_rx_mem_buffer *rxb)
1130{ 1160{
1131 struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; 1161 struct iwl_rx_packet *pkt = rxb_addr(rxb);
1132 priv->last_phy_res[0] = 1; 1162 priv->last_phy_res[0] = 1;
1133 memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]), 1163 memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]),
1134 sizeof(struct iwl_rx_phy_res)); 1164 sizeof(struct iwl_rx_phy_res));