Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 349761
b: refs/heads/master
c: ac57480
h: refs/heads/master
i:
  349759: 671a3e6
v: v3
  • Loading branch information
Huang, Xiong authored and David S. Miller committed Feb 13, 2013
1 parent f353005 commit cbf906a
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 8 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 9c10f4115cc3722635d6e277385ec96003281784
refs/heads/master: ac574804d412047e52de4dd887615cc88f58aeb0
71 changes: 64 additions & 7 deletions trunk/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

#include "atl1c.h"

#define ATL1C_DRV_VERSION "1.0.1.0-NAPI"
#define ATL1C_DRV_VERSION "1.0.1.1-NAPI"
char atl1c_driver_name[] = "atl1c";
char atl1c_driver_version[] = ATL1C_DRV_VERSION;

Expand Down Expand Up @@ -1652,6 +1652,7 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter)
u16 num_alloc = 0;
u16 rfd_next_to_use, next_next;
struct atl1c_rx_free_desc *rfd_desc;
dma_addr_t mapping;

next_next = rfd_next_to_use = rfd_ring->next_to_use;
if (++next_next == rfd_ring->count)
Expand All @@ -1678,9 +1679,18 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter)
ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY);
buffer_info->skb = skb;
buffer_info->length = adapter->rx_buffer_len;
buffer_info->dma = pci_map_single(pdev, vir_addr,
mapping = pci_map_single(pdev, vir_addr,
buffer_info->length,
PCI_DMA_FROMDEVICE);
if (unlikely(pci_dma_mapping_error(pdev, mapping))) {
dev_kfree_skb(skb);
buffer_info->skb = NULL;
buffer_info->length = 0;
ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE);
netif_warn(adapter, rx_err, adapter->netdev, "RX pci_map_single failed");
break;
}
buffer_info->dma = mapping;
ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE,
ATL1C_PCIMAP_FROMDEVICE);
rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
Expand Down Expand Up @@ -2015,7 +2025,29 @@ static int atl1c_tso_csum(struct atl1c_adapter *adapter,
return 0;
}

static void atl1c_tx_map(struct atl1c_adapter *adapter,
static void atl1c_tx_rollback(struct atl1c_adapter *adpt,
struct atl1c_tpd_desc *first_tpd,
enum atl1c_trans_queue type)
{
struct atl1c_tpd_ring *tpd_ring = &adpt->tpd_ring[type];
struct atl1c_buffer *buffer_info;
struct atl1c_tpd_desc *tpd;
u16 first_index, index;

first_index = first_tpd - (struct atl1c_tpd_desc *)tpd_ring->desc;
index = first_index;
while (index != tpd_ring->next_to_use) {
tpd = ATL1C_TPD_DESC(tpd_ring, index);
buffer_info = &tpd_ring->buffer_info[index];
atl1c_clean_buffer(adpt->pdev, buffer_info, 0);
memset(tpd, 0, sizeof(struct atl1c_tpd_desc));
if (++index == tpd_ring->count)
index = 0;
}
tpd_ring->next_to_use = first_index;
}

static int atl1c_tx_map(struct atl1c_adapter *adapter,
struct sk_buff *skb, struct atl1c_tpd_desc *tpd,
enum atl1c_trans_queue type)
{
Expand All @@ -2040,7 +2072,10 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter,
buffer_info->length = map_len;
buffer_info->dma = pci_map_single(adapter->pdev,
skb->data, hdr_len, PCI_DMA_TODEVICE);
ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY);
if (unlikely(pci_dma_mapping_error(adapter->pdev,
buffer_info->dma)))
goto err_dma;

ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE,
ATL1C_PCIMAP_TODEVICE);
mapped_len += map_len;
Expand All @@ -2062,6 +2097,10 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter,
buffer_info->dma =
pci_map_single(adapter->pdev, skb->data + mapped_len,
buffer_info->length, PCI_DMA_TODEVICE);
if (unlikely(pci_dma_mapping_error(adapter->pdev,
buffer_info->dma)))
goto err_dma;

ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY);
ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE,
ATL1C_PCIMAP_TODEVICE);
Expand All @@ -2083,6 +2122,9 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter,
frag, 0,
buffer_info->length,
DMA_TO_DEVICE);
if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma))
goto err_dma;

ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY);
ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_PAGE,
ATL1C_PCIMAP_TODEVICE);
Expand All @@ -2095,6 +2137,13 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter,
/* The last buffer info contain the skb address,
so it will be free after unmap */
buffer_info->skb = skb;

return 0;

err_dma:
buffer_info->dma = 0;
buffer_info->length = 0;
return -1;
}

static void atl1c_tx_queue(struct atl1c_adapter *adapter, struct sk_buff *skb,
Expand Down Expand Up @@ -2157,10 +2206,18 @@ static netdev_tx_t atl1c_xmit_frame(struct sk_buff *skb,
if (skb_network_offset(skb) != ETH_HLEN)
tpd->word1 |= 1 << TPD_ETH_TYPE_SHIFT; /* Ethernet frame */

atl1c_tx_map(adapter, skb, tpd, type);
atl1c_tx_queue(adapter, skb, tpd, type);
if (atl1c_tx_map(adapter, skb, tpd, type) < 0) {
netif_info(adapter, tx_done, adapter->netdev,
"tx-skb droppted due to dma error\n");
/* roll back tpd/buffer */
atl1c_tx_rollback(adapter, tpd, type);
spin_unlock_irqrestore(&adapter->tx_lock, flags);
dev_kfree_skb(skb);
} else {
atl1c_tx_queue(adapter, skb, tpd, type);
spin_unlock_irqrestore(&adapter->tx_lock, flags);
}

spin_unlock_irqrestore(&adapter->tx_lock, flags);
return NETDEV_TX_OK;
}

Expand Down

0 comments on commit cbf906a

Please sign in to comment.