aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHuang, Xiong <xiong@qca.qualcomm.com>2013-02-11 09:44:40 -0500
committerDavid S. Miller <davem@davemloft.net>2013-02-13 13:32:37 -0500
commitac574804d412047e52de4dd887615cc88f58aeb0 (patch)
treefb7472fb24ab92117a4621c449efbb90da02ed17 /drivers
parent9c10f4115cc3722635d6e277385ec96003281784 (diff)
atl1c: add error checking for pci_map_single functions
it is reported that code hit DMA-API errors on 3.8-rc6+, (see https://bugzilla.redhat.com/show_bug.cgi?id=908436, and https://bugzilla.redhat.com/show_bug.cgi?id=908550) this patch just adds error handler for pci_map_single and skb_frag_dma_map. Signed-off-by: xiong <xiong@qca.qualcomm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_main.c71
1 files changed, 64 insertions, 7 deletions
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 56d3f697e0c7..0035c01660b6 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -21,7 +21,7 @@
21 21
22#include "atl1c.h" 22#include "atl1c.h"
23 23
24#define ATL1C_DRV_VERSION "1.0.1.0-NAPI" 24#define ATL1C_DRV_VERSION "1.0.1.1-NAPI"
25char atl1c_driver_name[] = "atl1c"; 25char atl1c_driver_name[] = "atl1c";
26char atl1c_driver_version[] = ATL1C_DRV_VERSION; 26char atl1c_driver_version[] = ATL1C_DRV_VERSION;
27 27
@@ -1652,6 +1652,7 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter)
1652 u16 num_alloc = 0; 1652 u16 num_alloc = 0;
1653 u16 rfd_next_to_use, next_next; 1653 u16 rfd_next_to_use, next_next;
1654 struct atl1c_rx_free_desc *rfd_desc; 1654 struct atl1c_rx_free_desc *rfd_desc;
1655 dma_addr_t mapping;
1655 1656
1656 next_next = rfd_next_to_use = rfd_ring->next_to_use; 1657 next_next = rfd_next_to_use = rfd_ring->next_to_use;
1657 if (++next_next == rfd_ring->count) 1658 if (++next_next == rfd_ring->count)
@@ -1678,9 +1679,18 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter)
1678 ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); 1679 ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY);
1679 buffer_info->skb = skb; 1680 buffer_info->skb = skb;
1680 buffer_info->length = adapter->rx_buffer_len; 1681 buffer_info->length = adapter->rx_buffer_len;
1681 buffer_info->dma = pci_map_single(pdev, vir_addr, 1682 mapping = pci_map_single(pdev, vir_addr,
1682 buffer_info->length, 1683 buffer_info->length,
1683 PCI_DMA_FROMDEVICE); 1684 PCI_DMA_FROMDEVICE);
1685 if (unlikely(pci_dma_mapping_error(pdev, mapping))) {
1686 dev_kfree_skb(skb);
1687 buffer_info->skb = NULL;
1688 buffer_info->length = 0;
1689 ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE);
1690 netif_warn(adapter, rx_err, adapter->netdev, "RX pci_map_single failed");
1691 break;
1692 }
1693 buffer_info->dma = mapping;
1684 ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE, 1694 ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE,
1685 ATL1C_PCIMAP_FROMDEVICE); 1695 ATL1C_PCIMAP_FROMDEVICE);
1686 rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma); 1696 rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
@@ -2015,7 +2025,29 @@ check_sum:
2015 return 0; 2025 return 0;
2016} 2026}
2017 2027
2018static void atl1c_tx_map(struct atl1c_adapter *adapter, 2028static void atl1c_tx_rollback(struct atl1c_adapter *adpt,
2029 struct atl1c_tpd_desc *first_tpd,
2030 enum atl1c_trans_queue type)
2031{
2032 struct atl1c_tpd_ring *tpd_ring = &adpt->tpd_ring[type];
2033 struct atl1c_buffer *buffer_info;
2034 struct atl1c_tpd_desc *tpd;
2035 u16 first_index, index;
2036
2037 first_index = first_tpd - (struct atl1c_tpd_desc *)tpd_ring->desc;
2038 index = first_index;
2039 while (index != tpd_ring->next_to_use) {
2040 tpd = ATL1C_TPD_DESC(tpd_ring, index);
2041 buffer_info = &tpd_ring->buffer_info[index];
2042 atl1c_clean_buffer(adpt->pdev, buffer_info, 0);
2043 memset(tpd, 0, sizeof(struct atl1c_tpd_desc));
2044 if (++index == tpd_ring->count)
2045 index = 0;
2046 }
2047 tpd_ring->next_to_use = first_index;
2048}
2049
2050static int atl1c_tx_map(struct atl1c_adapter *adapter,
2019 struct sk_buff *skb, struct atl1c_tpd_desc *tpd, 2051 struct sk_buff *skb, struct atl1c_tpd_desc *tpd,
2020 enum atl1c_trans_queue type) 2052 enum atl1c_trans_queue type)
2021{ 2053{
@@ -2040,7 +2072,10 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter,
2040 buffer_info->length = map_len; 2072 buffer_info->length = map_len;
2041 buffer_info->dma = pci_map_single(adapter->pdev, 2073 buffer_info->dma = pci_map_single(adapter->pdev,
2042 skb->data, hdr_len, PCI_DMA_TODEVICE); 2074 skb->data, hdr_len, PCI_DMA_TODEVICE);
2043 ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); 2075 if (unlikely(pci_dma_mapping_error(adapter->pdev,
2076 buffer_info->dma)))
2077 goto err_dma;
2078
2044 ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE, 2079 ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE,
2045 ATL1C_PCIMAP_TODEVICE); 2080 ATL1C_PCIMAP_TODEVICE);
2046 mapped_len += map_len; 2081 mapped_len += map_len;
@@ -2062,6 +2097,10 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter,
2062 buffer_info->dma = 2097 buffer_info->dma =
2063 pci_map_single(adapter->pdev, skb->data + mapped_len, 2098 pci_map_single(adapter->pdev, skb->data + mapped_len,
2064 buffer_info->length, PCI_DMA_TODEVICE); 2099 buffer_info->length, PCI_DMA_TODEVICE);
2100 if (unlikely(pci_dma_mapping_error(adapter->pdev,
2101 buffer_info->dma)))
2102 goto err_dma;
2103
2065 ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); 2104 ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY);
2066 ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE, 2105 ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE,
2067 ATL1C_PCIMAP_TODEVICE); 2106 ATL1C_PCIMAP_TODEVICE);
@@ -2083,6 +2122,9 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter,
2083 frag, 0, 2122 frag, 0,
2084 buffer_info->length, 2123 buffer_info->length,
2085 DMA_TO_DEVICE); 2124 DMA_TO_DEVICE);
2125 if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma))
2126 goto err_dma;
2127
2086 ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); 2128 ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY);
2087 ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_PAGE, 2129 ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_PAGE,
2088 ATL1C_PCIMAP_TODEVICE); 2130 ATL1C_PCIMAP_TODEVICE);
@@ -2095,6 +2137,13 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter,
2095 /* The last buffer info contain the skb address, 2137 /* The last buffer info contain the skb address,
2096 so it will be free after unmap */ 2138 so it will be free after unmap */
2097 buffer_info->skb = skb; 2139 buffer_info->skb = skb;
2140
2141 return 0;
2142
2143err_dma:
2144 buffer_info->dma = 0;
2145 buffer_info->length = 0;
2146 return -1;
2098} 2147}
2099 2148
2100static void atl1c_tx_queue(struct atl1c_adapter *adapter, struct sk_buff *skb, 2149static void atl1c_tx_queue(struct atl1c_adapter *adapter, struct sk_buff *skb,
@@ -2157,10 +2206,18 @@ static netdev_tx_t atl1c_xmit_frame(struct sk_buff *skb,
2157 if (skb_network_offset(skb) != ETH_HLEN) 2206 if (skb_network_offset(skb) != ETH_HLEN)
2158 tpd->word1 |= 1 << TPD_ETH_TYPE_SHIFT; /* Ethernet frame */ 2207 tpd->word1 |= 1 << TPD_ETH_TYPE_SHIFT; /* Ethernet frame */
2159 2208
2160 atl1c_tx_map(adapter, skb, tpd, type); 2209 if (atl1c_tx_map(adapter, skb, tpd, type) < 0) {
2161 atl1c_tx_queue(adapter, skb, tpd, type); 2210 netif_info(adapter, tx_done, adapter->netdev,
2211 "tx-skb droppted due to dma error\n");
2212 /* roll back tpd/buffer */
2213 atl1c_tx_rollback(adapter, tpd, type);
2214 spin_unlock_irqrestore(&adapter->tx_lock, flags);
2215 dev_kfree_skb(skb);
2216 } else {
2217 atl1c_tx_queue(adapter, skb, tpd, type);
2218 spin_unlock_irqrestore(&adapter->tx_lock, flags);
2219 }
2162 2220
2163 spin_unlock_irqrestore(&adapter->tx_lock, flags);
2164 return NETDEV_TX_OK; 2221 return NETDEV_TX_OK;
2165} 2222}
2166 2223