diff options
author | Johannes Berg <johannes.berg@intel.com> | 2011-04-28 10:27:10 -0400 |
---|---|---|
committer | Wey-Yi Guy <wey-yi.w.guy@intel.com> | 2011-05-06 13:46:23 -0400 |
commit | 2c46f72e069eef5e98f2b04df08cde6bdc673aa7 (patch) | |
tree | 62243e8844fd39864bffacbd50b393d1470b8000 | |
parent | 94b00658ffc719427c9c09d7920957bc35915c6f (diff) |
iwlagn: check DMA mapping errors
DMA mappings can fail, but the current code
doesn't check for that. Add checking, which
requires some restructuring for proper error
paths.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 60 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-tx.c | 13 |
2 files changed, 45 insertions, 28 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 26601b7048f2..7c1becf9e2c1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -537,7 +537,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
537 | struct iwl_tx_cmd *tx_cmd; | 537 | struct iwl_tx_cmd *tx_cmd; |
538 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | 538 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; |
539 | int txq_id; | 539 | int txq_id; |
540 | dma_addr_t phys_addr; | 540 | dma_addr_t phys_addr = 0; |
541 | dma_addr_t txcmd_phys; | 541 | dma_addr_t txcmd_phys; |
542 | dma_addr_t scratch_phys; | 542 | dma_addr_t scratch_phys; |
543 | u16 len, firstlen, secondlen; | 543 | u16 len, firstlen, secondlen; |
@@ -564,7 +564,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
564 | spin_lock_irqsave(&priv->lock, flags); | 564 | spin_lock_irqsave(&priv->lock, flags); |
565 | if (iwl_is_rfkill(priv)) { | 565 | if (iwl_is_rfkill(priv)) { |
566 | IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); | 566 | IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); |
567 | goto drop_unlock; | 567 | goto drop_unlock_priv; |
568 | } | 568 | } |
569 | 569 | ||
570 | fc = hdr->frame_control; | 570 | fc = hdr->frame_control; |
@@ -585,7 +585,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
585 | if (sta_id == IWL_INVALID_STATION) { | 585 | if (sta_id == IWL_INVALID_STATION) { |
586 | IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", | 586 | IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", |
587 | hdr->addr1); | 587 | hdr->addr1); |
588 | goto drop_unlock; | 588 | goto drop_unlock_priv; |
589 | } | 589 | } |
590 | 590 | ||
591 | IWL_DEBUG_TX(priv, "station Id %d\n", sta_id); | 591 | IWL_DEBUG_TX(priv, "station Id %d\n", sta_id); |
@@ -628,10 +628,10 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
628 | if (ieee80211_is_data_qos(fc)) { | 628 | if (ieee80211_is_data_qos(fc)) { |
629 | qc = ieee80211_get_qos_ctl(hdr); | 629 | qc = ieee80211_get_qos_ctl(hdr); |
630 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | 630 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; |
631 | if (WARN_ON_ONCE(tid >= MAX_TID_COUNT)) { | 631 | |
632 | spin_unlock(&priv->sta_lock); | 632 | if (WARN_ON_ONCE(tid >= MAX_TID_COUNT)) |
633 | goto drop_unlock; | 633 | goto drop_unlock_sta; |
634 | } | 634 | |
635 | seq_number = priv->stations[sta_id].tid[tid].seq_number; | 635 | seq_number = priv->stations[sta_id].tid[tid].seq_number; |
636 | seq_number &= IEEE80211_SCTL_SEQ; | 636 | seq_number &= IEEE80211_SCTL_SEQ; |
637 | hdr->seq_ctrl = hdr->seq_ctrl & | 637 | hdr->seq_ctrl = hdr->seq_ctrl & |
@@ -649,18 +649,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
649 | txq = &priv->txq[txq_id]; | 649 | txq = &priv->txq[txq_id]; |
650 | q = &txq->q; | 650 | q = &txq->q; |
651 | 651 | ||
652 | if (unlikely(iwl_queue_space(q) < q->high_mark)) { | 652 | if (unlikely(iwl_queue_space(q) < q->high_mark)) |
653 | spin_unlock(&priv->sta_lock); | 653 | goto drop_unlock_sta; |
654 | goto drop_unlock; | ||
655 | } | ||
656 | |||
657 | if (ieee80211_is_data_qos(fc)) { | ||
658 | priv->stations[sta_id].tid[tid].tfds_in_queue++; | ||
659 | if (!ieee80211_has_morefrags(fc)) | ||
660 | priv->stations[sta_id].tid[tid].seq_number = seq_number; | ||
661 | } | ||
662 | |||
663 | spin_unlock(&priv->sta_lock); | ||
664 | 654 | ||
665 | /* Set up driver data for this TFD */ | 655 | /* Set up driver data for this TFD */ |
666 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); | 656 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); |
@@ -724,12 +714,10 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
724 | txcmd_phys = pci_map_single(priv->pci_dev, | 714 | txcmd_phys = pci_map_single(priv->pci_dev, |
725 | &out_cmd->hdr, firstlen, | 715 | &out_cmd->hdr, firstlen, |
726 | PCI_DMA_BIDIRECTIONAL); | 716 | PCI_DMA_BIDIRECTIONAL); |
717 | if (unlikely(pci_dma_mapping_error(priv->pci_dev, txcmd_phys))) | ||
718 | goto drop_unlock_sta; | ||
727 | dma_unmap_addr_set(out_meta, mapping, txcmd_phys); | 719 | dma_unmap_addr_set(out_meta, mapping, txcmd_phys); |
728 | dma_unmap_len_set(out_meta, len, firstlen); | 720 | dma_unmap_len_set(out_meta, len, firstlen); |
729 | /* Add buffer containing Tx command and MAC(!) header to TFD's | ||
730 | * first entry */ | ||
731 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | ||
732 | txcmd_phys, firstlen, 1, 0); | ||
733 | 721 | ||
734 | if (!ieee80211_has_morefrags(hdr->frame_control)) { | 722 | if (!ieee80211_has_morefrags(hdr->frame_control)) { |
735 | txq->need_update = 1; | 723 | txq->need_update = 1; |
@@ -744,10 +732,30 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
744 | if (secondlen > 0) { | 732 | if (secondlen > 0) { |
745 | phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, | 733 | phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, |
746 | secondlen, PCI_DMA_TODEVICE); | 734 | secondlen, PCI_DMA_TODEVICE); |
735 | if (unlikely(pci_dma_mapping_error(priv->pci_dev, phys_addr))) { | ||
736 | pci_unmap_single(priv->pci_dev, | ||
737 | dma_unmap_addr(out_meta, mapping), | ||
738 | dma_unmap_len(out_meta, len), | ||
739 | PCI_DMA_BIDIRECTIONAL); | ||
740 | goto drop_unlock_sta; | ||
741 | } | ||
742 | } | ||
743 | |||
744 | if (ieee80211_is_data_qos(fc)) { | ||
745 | priv->stations[sta_id].tid[tid].tfds_in_queue++; | ||
746 | if (!ieee80211_has_morefrags(fc)) | ||
747 | priv->stations[sta_id].tid[tid].seq_number = seq_number; | ||
748 | } | ||
749 | |||
750 | spin_unlock(&priv->sta_lock); | ||
751 | |||
752 | /* Attach buffers to TFD */ | ||
753 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | ||
754 | txcmd_phys, firstlen, 1, 0); | ||
755 | if (secondlen > 0) | ||
747 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | 756 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, |
748 | phys_addr, secondlen, | 757 | phys_addr, secondlen, |
749 | 0, 0); | 758 | 0, 0); |
750 | } | ||
751 | 759 | ||
752 | scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + | 760 | scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + |
753 | offsetof(struct iwl_tx_cmd, scratch); | 761 | offsetof(struct iwl_tx_cmd, scratch); |
@@ -813,7 +821,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
813 | 821 | ||
814 | return 0; | 822 | return 0; |
815 | 823 | ||
816 | drop_unlock: | 824 | drop_unlock_sta: |
825 | spin_unlock(&priv->sta_lock); | ||
826 | drop_unlock_priv: | ||
817 | spin_unlock_irqrestore(&priv->lock, flags); | 827 | spin_unlock_irqrestore(&priv->lock, flags); |
818 | return -1; | 828 | return -1; |
819 | } | 829 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 5a7cd177fe5e..e69597ea43e2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -500,7 +500,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
500 | } | 500 | } |
501 | 501 | ||
502 | memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */ | 502 | memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */ |
503 | out_meta->flags = cmd->flags | CMD_MAPPED; | ||
504 | if (cmd->flags & CMD_WANT_SKB) | 503 | if (cmd->flags & CMD_WANT_SKB) |
505 | out_meta->source = cmd; | 504 | out_meta->source = cmd; |
506 | if (cmd->flags & CMD_ASYNC) | 505 | if (cmd->flags & CMD_ASYNC) |
@@ -538,13 +537,20 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
538 | q->write_ptr, idx, priv->cmd_queue); | 537 | q->write_ptr, idx, priv->cmd_queue); |
539 | } | 538 | } |
540 | #endif | 539 | #endif |
541 | txq->need_update = 1; | ||
542 | |||
543 | phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr, | 540 | phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr, |
544 | fix_size, PCI_DMA_BIDIRECTIONAL); | 541 | fix_size, PCI_DMA_BIDIRECTIONAL); |
542 | if (unlikely(pci_dma_mapping_error(priv->pci_dev, phys_addr))) { | ||
543 | idx = -ENOMEM; | ||
544 | goto out; | ||
545 | } | ||
546 | |||
545 | dma_unmap_addr_set(out_meta, mapping, phys_addr); | 547 | dma_unmap_addr_set(out_meta, mapping, phys_addr); |
546 | dma_unmap_len_set(out_meta, len, fix_size); | 548 | dma_unmap_len_set(out_meta, len, fix_size); |
547 | 549 | ||
550 | out_meta->flags = cmd->flags | CMD_MAPPED; | ||
551 | |||
552 | txq->need_update = 1; | ||
553 | |||
548 | trace_iwlwifi_dev_hcmd(priv, &out_cmd->hdr, fix_size, cmd->flags); | 554 | trace_iwlwifi_dev_hcmd(priv, &out_cmd->hdr, fix_size, cmd->flags); |
549 | 555 | ||
550 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | 556 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, |
@@ -555,6 +561,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
555 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | 561 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); |
556 | iwl_txq_update_write_ptr(priv, txq); | 562 | iwl_txq_update_write_ptr(priv, txq); |
557 | 563 | ||
564 | out: | ||
558 | spin_unlock_irqrestore(&priv->hcmd_lock, flags); | 565 | spin_unlock_irqrestore(&priv->hcmd_lock, flags); |
559 | return idx; | 566 | return idx; |
560 | } | 567 | } |