rt2x00: check for dma mappings errors

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>
This commit is contained in:
Stanislaw Gruszka 2013-02-13 14:27:05 +01:00 committed by John W. Linville
parent 52301a815e
commit 4ea545d476
4 changed files with 36 additions and 13 deletions

View File

@ -1185,8 +1185,14 @@ static void rt2400pci_write_beacon(struct queue_entry *entry,
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0); rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
rt2x00pci_register_write(rt2x00dev, CSR14, reg); 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. * 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. * Dump beacon to userspace through debugfs.
*/ */
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb); rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
out:
/* /*
* Enable beaconing again. * Enable beaconing again.
*/ */

View File

@ -1338,7 +1338,10 @@ static void rt2500pci_write_beacon(struct queue_entry *entry,
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0); rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
rt2x00pci_register_write(rt2x00dev, CSR14, reg); 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. * 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. * Dump beacon to userspace through debugfs.
*/ */
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb); rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
out:
/* /*
* Enable beaconing again. * Enable beaconing again.
*/ */

View 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. * rt2x00queue_map_txskb - Map a skb into DMA for TX purposes.
* @entry: Pointer to &struct queue_entry * @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. * rt2x00queue_unmap_skb - Unmap a skb from DMA.

View File

@ -87,24 +87,35 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry, gfp_t gfp)
skbdesc->entry = entry; skbdesc->entry = entry;
if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags)) { if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags)) {
skbdesc->skb_dma = dma_map_single(rt2x00dev->dev, dma_addr_t skb_dma;
skb->data,
skb->len, skb_dma = dma_map_single(rt2x00dev->dev, skb->data, skb->len,
DMA_FROM_DEVICE); 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; skbdesc->flags |= SKBDESC_DMA_MAPPED_RX;
} }
return skb; 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 device *dev = entry->queue->rt2x00dev->dev;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
skbdesc->skb_dma = skbdesc->skb_dma =
dma_map_single(dev, entry->skb->data, entry->skb->len, DMA_TO_DEVICE); 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; skbdesc->flags |= SKBDESC_DMA_MAPPED_TX;
return 0;
} }
EXPORT_SYMBOL_GPL(rt2x00queue_map_txskb); 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. * Map the skb to DMA.
*/ */
if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags)) if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags) &&
rt2x00queue_map_txskb(entry); rt2x00queue_map_txskb(entry))
return -ENOMEM;
return 0; return 0;
} }