rt2x00: check for dma mappings errors
authorStanislaw Gruszka <sgruszka@redhat.com>
Wed, 13 Feb 2013 13:27:05 +0000 (14:27 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 14 Feb 2013 19:24:07 +0000 (14:24 -0500)
Check output of dma_map_single functions which nowadays can fail (when
IOMMU is used). On write_beacon callbacks just print error, similar
like padding error is handled by rt2800_write_beacon.

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/rt2x00/rt2400pci.c
drivers/net/wireless/rt2x00/rt2500pci.c
drivers/net/wireless/rt2x00/rt2x00.h
drivers/net/wireless/rt2x00/rt2x00queue.c

index a2d2bc2c7b3dde238e373e422d1f54051e08b832..221beaaa83f12c59554302569639ca87f83765b5 100644 (file)
@@ -1185,8 +1185,14 @@ static void rt2400pci_write_beacon(struct queue_entry *entry,
        rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
        rt2x00pci_register_write(rt2x00dev, CSR14, reg);
 
-       rt2x00queue_map_txskb(entry);
-
+       if (rt2x00queue_map_txskb(entry)) {
+               ERROR(rt2x00dev, "Fail to map beacon, aborting\n");
+               goto out;
+       }
+       /*
+        * Enable beaconing again.
+        */
+       rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
        /*
         * Write the TX descriptor for the beacon.
         */
@@ -1196,7 +1202,7 @@ static void rt2400pci_write_beacon(struct queue_entry *entry,
         * Dump beacon to userspace through debugfs.
         */
        rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
-
+out:
        /*
         * Enable beaconing again.
         */
index 9bea10f53f0a9179d9f2055e3df961c10802e211..39edc59e8d038613a07b4dce764e0033be2501cf 100644 (file)
@@ -1338,7 +1338,10 @@ static void rt2500pci_write_beacon(struct queue_entry *entry,
        rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
        rt2x00pci_register_write(rt2x00dev, CSR14, reg);
 
-       rt2x00queue_map_txskb(entry);
+       if (rt2x00queue_map_txskb(entry)) {
+               ERROR(rt2x00dev, "Fail to map beacon, aborting\n");
+               goto out;
+       }
 
        /*
         * Write the TX descriptor for the beacon.
@@ -1349,7 +1352,7 @@ static void rt2500pci_write_beacon(struct queue_entry *entry,
         * Dump beacon to userspace through debugfs.
         */
        rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
-
+out:
        /*
         * Enable beaconing again.
         */
index 9a3f31a543ce95a4e7a0398defedb866cfe4a8d9..086abb403a4f2085463da5a571505dbc040389cc 100644 (file)
@@ -1169,8 +1169,10 @@ static inline bool rt2x00_is_soc(struct rt2x00_dev *rt2x00dev)
 /**
  * rt2x00queue_map_txskb - Map a skb into DMA for TX purposes.
  * @entry: Pointer to &struct queue_entry
+ *
+ * Returns -ENOMEM if mapping fail, 0 otherwise.
  */
-void rt2x00queue_map_txskb(struct queue_entry *entry);
+int rt2x00queue_map_txskb(struct queue_entry *entry);
 
 /**
  * rt2x00queue_unmap_skb - Unmap a skb from DMA.
index f35d85a71bbcab0e416f4e6db115e82538098414..e26ec9d817cfad856f7efae89a105a21dce7f586 100644 (file)
@@ -87,24 +87,35 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry, gfp_t gfp)
        skbdesc->entry = entry;
 
        if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags)) {
-               skbdesc->skb_dma = dma_map_single(rt2x00dev->dev,
-                                                 skb->data,
-                                                 skb->len,
-                                                 DMA_FROM_DEVICE);
+               dma_addr_t skb_dma;
+
+               skb_dma = dma_map_single(rt2x00dev->dev, skb->data, skb->len,
+                                        DMA_FROM_DEVICE);
+               if (unlikely(dma_mapping_error(rt2x00dev->dev, skb_dma))) {
+                       dev_kfree_skb_any(skb);
+                       return NULL;
+               }
+
+               skbdesc->skb_dma = skb_dma;
                skbdesc->flags |= SKBDESC_DMA_MAPPED_RX;
        }
 
        return skb;
 }
 
-void rt2x00queue_map_txskb(struct queue_entry *entry)
+int rt2x00queue_map_txskb(struct queue_entry *entry)
 {
        struct device *dev = entry->queue->rt2x00dev->dev;
        struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
 
        skbdesc->skb_dma =
            dma_map_single(dev, entry->skb->data, entry->skb->len, DMA_TO_DEVICE);
+
+       if (unlikely(dma_mapping_error(dev, skbdesc->skb_dma)))
+               return -ENOMEM;
+
        skbdesc->flags |= SKBDESC_DMA_MAPPED_TX;
+       return 0;
 }
 EXPORT_SYMBOL_GPL(rt2x00queue_map_txskb);
 
@@ -545,8 +556,9 @@ static int rt2x00queue_write_tx_data(struct queue_entry *entry,
        /*
         * Map the skb to DMA.
         */
-       if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags))
-               rt2x00queue_map_txskb(entry);
+       if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags) &&
+           rt2x00queue_map_txskb(entry))
+               return -ENOMEM;
 
        return 0;
 }