aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43legacy/dma.c
diff options
context:
space:
mode:
authorStefano Brivio <stefano.brivio@polimi.it>2008-04-13 18:59:49 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-04-15 15:04:36 -0400
commitdc4ae1f46dbbcd08b3b5e23ad5ef87bf4bb41adf (patch)
tree65909ff221f8eec95867a78d2687be82262ac2ef /drivers/net/wireless/b43legacy/dma.c
parentb3fc9c6c58c986f7a24fd8b0794d1e0794935a28 (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/net/wireless/b43legacy/dma.c')
-rw-r--r--drivers/net/wireless/b43legacy/dma.c29
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. */
587static bool b43legacy_dma_mapping_error(struct b43legacy_dmaring *ring, 587static 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
612address_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
612static int setup_rx_descbuffer(struct b43legacy_dmaring *ring, 619static 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;