diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-3945.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-3945.c | 67 |
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, | |||
293 | static void iwl3945_rx_reply_tx(struct iwl_priv *priv, | 293 | static 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, | |||
353 | void iwl3945_hw_rx_statistics(struct iwl_priv *priv, | 353 | void 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) | |||
1811 | static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) | 1839 | static 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; |