return 0;
}
-static void atl1e_tx_map(struct atl1e_adapter *adapter,
- struct sk_buff *skb, struct atl1e_tpd_desc *tpd)
+static int atl1e_tx_map(struct atl1e_adapter *adapter,
+ struct sk_buff *skb, struct atl1e_tpd_desc *tpd)
{
struct atl1e_tpd_desc *use_tpd = NULL;
struct atl1e_tx_buffer *tx_buffer = NULL;
u16 nr_frags;
u16 f;
int segment;
+ int ring_start = adapter->tx_ring.next_to_use;
nr_frags = skb_shinfo(skb)->nr_frags;
segment = (tpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK;
tx_buffer->length = map_len;
tx_buffer->dma = pci_map_single(adapter->pdev,
skb->data, hdr_len, PCI_DMA_TODEVICE);
+ if (dma_mapping_error(&adapter->pdev->dev, tx_buffer->dma))
+ return -ENOSPC;
+
ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_SINGLE);
mapped_len += map_len;
use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
tx_buffer->dma =
pci_map_single(adapter->pdev, skb->data + mapped_len,
map_len, PCI_DMA_TODEVICE);
+
+ if (dma_mapping_error(&adapter->pdev->dev, tx_buffer->dma)) {
+ /* Reset the tx rings next pointer */
+ adapter->tx_ring.next_to_use = ring_start;
+ return -ENOSPC;
+ }
+
ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_SINGLE);
mapped_len += map_len;
use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
(i * MAX_TX_BUF_LEN),
tx_buffer->length,
DMA_TO_DEVICE);
+
+ if (dma_mapping_error(&adapter->pdev->dev, tx_buffer->dma)) {
+ /* Reset the ring next to use pointer */
+ adapter->tx_ring.next_to_use = ring_start;
+ return -ENOSPC;
+ }
+
ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_PAGE);
use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) |
/* The last buffer info contain the skb address,
so it will be free after unmap */
tx_buffer->skb = skb;
+ return 0;
}
static void atl1e_tx_queue(struct atl1e_adapter *adapter, u16 count,
return NETDEV_TX_OK;
}
- atl1e_tx_map(adapter, skb, tpd);
+ if (atl1e_tx_map(adapter, skb, tpd))
+ goto out;
+
atl1e_tx_queue(adapter, tpd_req, tpd);
netdev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */
+out:
spin_unlock_irqrestore(&adapter->tx_lock, flags);
return NETDEV_TX_OK;
}