diff options
author | Stefano Brivio <stefano.brivio@polimi.it> | 2008-04-13 18:59:49 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-04-15 15:04:36 -0400 |
commit | dc4ae1f46dbbcd08b3b5e23ad5ef87bf4bb41adf (patch) | |
tree | 65909ff221f8eec95867a78d2687be82262ac2ef /drivers | |
parent | b3fc9c6c58c986f7a24fd8b0794d1e0794935a28 (diff) |
b43legacy: fix DMA mapping leakage
This fixes a DMA mapping leakage in the case where we reject a DMA buffer
because of its address.
The patch by Michael Buesch has been ported to b43legacy.
Signed-off-by: Stefano Brivio <stefano.brivio@polimi.it>
Cc: Christian Casteyde <casteyde.christian@free.fr>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/b43legacy/dma.c | 29 |
1 files changed, 18 insertions, 11 deletions
diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c index 59300486f48e..c990f87b107a 100644 --- a/drivers/net/wireless/b43legacy/dma.c +++ b/drivers/net/wireless/b43legacy/dma.c | |||
@@ -585,8 +585,9 @@ static int b43legacy_dmacontroller_tx_reset(struct b43legacy_wldev *dev, | |||
585 | 585 | ||
586 | /* Check if a DMA mapping address is invalid. */ | 586 | /* Check if a DMA mapping address is invalid. */ |
587 | static bool b43legacy_dma_mapping_error(struct b43legacy_dmaring *ring, | 587 | static bool b43legacy_dma_mapping_error(struct b43legacy_dmaring *ring, |
588 | dma_addr_t addr, | 588 | dma_addr_t addr, |
589 | size_t buffersize) | 589 | size_t buffersize, |
590 | bool dma_to_device) | ||
590 | { | 591 | { |
591 | if (unlikely(dma_mapping_error(addr))) | 592 | if (unlikely(dma_mapping_error(addr))) |
592 | return 1; | 593 | return 1; |
@@ -594,11 +595,11 @@ static bool b43legacy_dma_mapping_error(struct b43legacy_dmaring *ring, | |||
594 | switch (ring->type) { | 595 | switch (ring->type) { |
595 | case B43legacy_DMA_30BIT: | 596 | case B43legacy_DMA_30BIT: |
596 | if ((u64)addr + buffersize > (1ULL << 30)) | 597 | if ((u64)addr + buffersize > (1ULL << 30)) |
597 | return 1; | 598 | goto address_error; |
598 | break; | 599 | break; |
599 | case B43legacy_DMA_32BIT: | 600 | case B43legacy_DMA_32BIT: |
600 | if ((u64)addr + buffersize > (1ULL << 32)) | 601 | if ((u64)addr + buffersize > (1ULL << 32)) |
601 | return 1; | 602 | goto address_error; |
602 | break; | 603 | break; |
603 | case B43legacy_DMA_64BIT: | 604 | case B43legacy_DMA_64BIT: |
604 | /* Currently we can't have addresses beyond 64 bits in the kernel. */ | 605 | /* Currently we can't have addresses beyond 64 bits in the kernel. */ |
@@ -607,6 +608,12 @@ static bool b43legacy_dma_mapping_error(struct b43legacy_dmaring *ring, | |||
607 | 608 | ||
608 | /* The address is OK. */ | 609 | /* The address is OK. */ |
609 | return 0; | 610 | return 0; |
611 | |||
612 | address_error: | ||
613 | /* We can't support this address. Unmap it again. */ | ||
614 | unmap_descbuffer(ring, addr, buffersize, dma_to_device); | ||
615 | |||
616 | return 1; | ||
610 | } | 617 | } |
611 | 618 | ||
612 | static int setup_rx_descbuffer(struct b43legacy_dmaring *ring, | 619 | static int setup_rx_descbuffer(struct b43legacy_dmaring *ring, |
@@ -626,7 +633,7 @@ static int setup_rx_descbuffer(struct b43legacy_dmaring *ring, | |||
626 | return -ENOMEM; | 633 | return -ENOMEM; |
627 | dmaaddr = map_descbuffer(ring, skb->data, | 634 | dmaaddr = map_descbuffer(ring, skb->data, |
628 | ring->rx_buffersize, 0); | 635 | ring->rx_buffersize, 0); |
629 | if (b43legacy_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize)) { | 636 | if (b43legacy_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) { |
630 | /* ugh. try to realloc in zone_dma */ | 637 | /* ugh. try to realloc in zone_dma */ |
631 | gfp_flags |= GFP_DMA; | 638 | gfp_flags |= GFP_DMA; |
632 | 639 | ||
@@ -639,7 +646,7 @@ static int setup_rx_descbuffer(struct b43legacy_dmaring *ring, | |||
639 | ring->rx_buffersize, 0); | 646 | ring->rx_buffersize, 0); |
640 | } | 647 | } |
641 | 648 | ||
642 | if (b43legacy_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize)) { | 649 | if (b43legacy_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) { |
643 | dev_kfree_skb_any(skb); | 650 | dev_kfree_skb_any(skb); |
644 | return -EIO; | 651 | return -EIO; |
645 | } | 652 | } |
@@ -891,7 +898,7 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev, | |||
891 | DMA_TO_DEVICE); | 898 | DMA_TO_DEVICE); |
892 | 899 | ||
893 | if (b43legacy_dma_mapping_error(ring, dma_test, | 900 | if (b43legacy_dma_mapping_error(ring, dma_test, |
894 | sizeof(struct b43legacy_txhdr_fw3))) { | 901 | sizeof(struct b43legacy_txhdr_fw3), 1)) { |
895 | /* ugh realloc */ | 902 | /* ugh realloc */ |
896 | kfree(ring->txhdr_cache); | 903 | kfree(ring->txhdr_cache); |
897 | ring->txhdr_cache = kcalloc(nr_slots, | 904 | ring->txhdr_cache = kcalloc(nr_slots, |
@@ -906,7 +913,7 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev, | |||
906 | DMA_TO_DEVICE); | 913 | DMA_TO_DEVICE); |
907 | 914 | ||
908 | if (b43legacy_dma_mapping_error(ring, dma_test, | 915 | if (b43legacy_dma_mapping_error(ring, dma_test, |
909 | sizeof(struct b43legacy_txhdr_fw3))) | 916 | sizeof(struct b43legacy_txhdr_fw3), 1)) |
910 | goto err_kfree_txhdr_cache; | 917 | goto err_kfree_txhdr_cache; |
911 | } | 918 | } |
912 | 919 | ||
@@ -1235,7 +1242,7 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring, | |||
1235 | meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header, | 1242 | meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header, |
1236 | sizeof(struct b43legacy_txhdr_fw3), 1); | 1243 | sizeof(struct b43legacy_txhdr_fw3), 1); |
1237 | if (b43legacy_dma_mapping_error(ring, meta_hdr->dmaaddr, | 1244 | if (b43legacy_dma_mapping_error(ring, meta_hdr->dmaaddr, |
1238 | sizeof(struct b43legacy_txhdr_fw3))) { | 1245 | sizeof(struct b43legacy_txhdr_fw3), 1)) { |
1239 | ring->current_slot = old_top_slot; | 1246 | ring->current_slot = old_top_slot; |
1240 | ring->used_slots = old_used_slots; | 1247 | ring->used_slots = old_used_slots; |
1241 | return -EIO; | 1248 | return -EIO; |
@@ -1254,7 +1261,7 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring, | |||
1254 | 1261 | ||
1255 | meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); | 1262 | meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); |
1256 | /* create a bounce buffer in zone_dma on mapping failure. */ | 1263 | /* create a bounce buffer in zone_dma on mapping failure. */ |
1257 | if (b43legacy_dma_mapping_error(ring, meta->dmaaddr, skb->len)) { | 1264 | if (b43legacy_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) { |
1258 | bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA); | 1265 | bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA); |
1259 | if (!bounce_skb) { | 1266 | if (!bounce_skb) { |
1260 | ring->current_slot = old_top_slot; | 1267 | ring->current_slot = old_top_slot; |
@@ -1268,7 +1275,7 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring, | |||
1268 | skb = bounce_skb; | 1275 | skb = bounce_skb; |
1269 | meta->skb = skb; | 1276 | meta->skb = skb; |
1270 | meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); | 1277 | meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); |
1271 | if (b43legacy_dma_mapping_error(ring, meta->dmaaddr, skb->len)) { | 1278 | if (b43legacy_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) { |
1272 | ring->current_slot = old_top_slot; | 1279 | ring->current_slot = old_top_slot; |
1273 | ring->used_slots = old_used_slots; | 1280 | ring->used_slots = old_used_slots; |
1274 | err = -EIO; | 1281 | err = -EIO; |