aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-3945.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-3945.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c67
1 files changed, 47 insertions, 20 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 8012381d3717..b188a026637a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -293,7 +293,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv,
293static void iwl3945_rx_reply_tx(struct iwl_priv *priv, 293static void iwl3945_rx_reply_tx(struct iwl_priv *priv,
294 struct iwl_rx_mem_buffer *rxb) 294 struct iwl_rx_mem_buffer *rxb)
295{ 295{
296 struct iwl_rx_packet *pkt = (void *)rxb->skb->data; 296 struct iwl_rx_packet *pkt = rxb_addr(rxb);
297 u16 sequence = le16_to_cpu(pkt->hdr.sequence); 297 u16 sequence = le16_to_cpu(pkt->hdr.sequence);
298 int txq_id = SEQ_TO_QUEUE(sequence); 298 int txq_id = SEQ_TO_QUEUE(sequence);
299 int index = SEQ_TO_INDEX(sequence); 299 int index = SEQ_TO_INDEX(sequence);
@@ -353,7 +353,7 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv,
353void iwl3945_hw_rx_statistics(struct iwl_priv *priv, 353void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
354 struct iwl_rx_mem_buffer *rxb) 354 struct iwl_rx_mem_buffer *rxb)
355{ 355{
356 struct iwl_rx_packet *pkt = (void *)rxb->skb->data; 356 struct iwl_rx_packet *pkt = rxb_addr(rxb);
357 IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", 357 IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
358 (int)sizeof(struct iwl3945_notif_statistics), 358 (int)sizeof(struct iwl3945_notif_statistics),
359 le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); 359 le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
@@ -543,14 +543,17 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
543 struct iwl_rx_mem_buffer *rxb, 543 struct iwl_rx_mem_buffer *rxb,
544 struct ieee80211_rx_status *stats) 544 struct ieee80211_rx_status *stats)
545{ 545{
546 struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; 546 struct iwl_rx_packet *pkt = rxb_addr(rxb);
547 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); 547 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
548 struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); 548 struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
549 struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); 549 struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
550 short len = le16_to_cpu(rx_hdr->len); 550 u16 len = le16_to_cpu(rx_hdr->len);
551 struct sk_buff *skb;
552 int ret;
551 553
552 /* We received data from the HW, so stop the watchdog */ 554 /* We received data from the HW, so stop the watchdog */
553 if (unlikely((len + IWL39_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) { 555 if (unlikely(len + IWL39_RX_FRAME_SIZE >
556 PAGE_SIZE << priv->hw_params.rx_page_order)) {
554 IWL_DEBUG_DROP(priv, "Corruption detected!\n"); 557 IWL_DEBUG_DROP(priv, "Corruption detected!\n");
555 return; 558 return;
556 } 559 }
@@ -562,20 +565,45 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
562 return; 565 return;
563 } 566 }
564 567
565 skb_reserve(rxb->skb, (void *)rx_hdr->payload - (void *)pkt); 568 skb = alloc_skb(IWL_LINK_HDR_MAX, GFP_ATOMIC);
566 /* Set the size of the skb to the size of the frame */ 569 if (!skb) {
567 skb_put(rxb->skb, le16_to_cpu(rx_hdr->len)); 570 IWL_ERR(priv, "alloc_skb failed\n");
571 return;
572 }
568 573
569 if (!iwl3945_mod_params.sw_crypto) 574 if (!iwl3945_mod_params.sw_crypto)
570 iwl_set_decrypted_flag(priv, 575 iwl_set_decrypted_flag(priv,
571 (struct ieee80211_hdr *)rxb->skb->data, 576 (struct ieee80211_hdr *)rxb_addr(rxb),
572 le32_to_cpu(rx_end->status), stats); 577 le32_to_cpu(rx_end->status), stats);
573 578
579 skb_add_rx_frag(skb, 0, rxb->page,
580 (void *)rx_hdr->payload - (void *)pkt, len);
581
582 /* mac80211 currently doesn't support paged SKB. Convert it to
583 * linear SKB for management frame and data frame requires
584 * software decryption or software defragementation. */
585 if (ieee80211_is_mgmt(hdr->frame_control) ||
586 ieee80211_has_protected(hdr->frame_control) ||
587 ieee80211_has_morefrags(hdr->frame_control) ||
588 le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)
589 ret = skb_linearize(skb);
590 else
591 ret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ?
592 0 : -ENOMEM;
593
594 if (ret) {
595 kfree_skb(skb);
596 goto out;
597 }
598
574 iwl_update_stats(priv, false, hdr->frame_control, len); 599 iwl_update_stats(priv, false, hdr->frame_control, len);
575 600
576 memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats)); 601 memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
577 ieee80211_rx_irqsafe(priv->hw, rxb->skb); 602 ieee80211_rx(priv->hw, skb);
578 rxb->skb = NULL; 603
604 out:
605 priv->alloc_rxb_page--;
606 rxb->page = NULL;
579} 607}
580 608
581#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) 609#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
@@ -585,7 +613,7 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
585{ 613{
586 struct ieee80211_hdr *header; 614 struct ieee80211_hdr *header;
587 struct ieee80211_rx_status rx_status; 615 struct ieee80211_rx_status rx_status;
588 struct iwl_rx_packet *pkt = (void *)rxb->skb->data; 616 struct iwl_rx_packet *pkt = rxb_addr(rxb);
589 struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); 617 struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
590 struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); 618 struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
591 struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); 619 struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
@@ -1811,7 +1839,7 @@ int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power)
1811static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) 1839static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
1812{ 1840{
1813 int rc = 0; 1841 int rc = 0;
1814 struct iwl_rx_packet *res = NULL; 1842 struct iwl_rx_packet *pkt;
1815 struct iwl3945_rxon_assoc_cmd rxon_assoc; 1843 struct iwl3945_rxon_assoc_cmd rxon_assoc;
1816 struct iwl_host_cmd cmd = { 1844 struct iwl_host_cmd cmd = {
1817 .id = REPLY_RXON_ASSOC, 1845 .id = REPLY_RXON_ASSOC,
@@ -1840,14 +1868,14 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
1840 if (rc) 1868 if (rc)
1841 return rc; 1869 return rc;
1842 1870
1843 res = (struct iwl_rx_packet *)cmd.reply_skb->data; 1871 pkt = (struct iwl_rx_packet *)cmd.reply_page;
1844 if (res->hdr.flags & IWL_CMD_FAILED_MSK) { 1872 if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
1845 IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n"); 1873 IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n");
1846 rc = -EIO; 1874 rc = -EIO;
1847 } 1875 }
1848 1876
1849 priv->alloc_rxb_skb--; 1877 priv->alloc_rxb_page--;
1850 dev_kfree_skb_any(cmd.reply_skb); 1878 free_pages(cmd.reply_page, priv->hw_params.rx_page_order);
1851 1879
1852 return rc; 1880 return rc;
1853} 1881}
@@ -2513,8 +2541,7 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv)
2513 priv->hw_params.max_txq_num = priv->cfg->num_of_queues; 2541 priv->hw_params.max_txq_num = priv->cfg->num_of_queues;
2514 2542
2515 priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd); 2543 priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd);
2516 priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_3K; 2544 priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_3K);
2517 priv->hw_params.max_pkt_size = 2342;
2518 priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; 2545 priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
2519 priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; 2546 priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
2520 priv->hw_params.max_stations = IWL3945_STATION_COUNT; 2547 priv->hw_params.max_stations = IWL3945_STATION_COUNT;