diff options
Diffstat (limited to 'drivers/net/ethernet/3com/3c59x.c')
-rw-r--r-- | drivers/net/ethernet/3com/3c59x.c | 50 |
1 files changed, 41 insertions, 9 deletions
diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c index 2b92d712f212..86e621142d5b 100644 --- a/drivers/net/ethernet/3com/3c59x.c +++ b/drivers/net/ethernet/3com/3c59x.c | |||
@@ -2128,6 +2128,7 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2128 | int entry = vp->cur_tx % TX_RING_SIZE; | 2128 | int entry = vp->cur_tx % TX_RING_SIZE; |
2129 | struct boom_tx_desc *prev_entry = &vp->tx_ring[(vp->cur_tx-1) % TX_RING_SIZE]; | 2129 | struct boom_tx_desc *prev_entry = &vp->tx_ring[(vp->cur_tx-1) % TX_RING_SIZE]; |
2130 | unsigned long flags; | 2130 | unsigned long flags; |
2131 | dma_addr_t dma_addr; | ||
2131 | 2132 | ||
2132 | if (vortex_debug > 6) { | 2133 | if (vortex_debug > 6) { |
2133 | pr_debug("boomerang_start_xmit()\n"); | 2134 | pr_debug("boomerang_start_xmit()\n"); |
@@ -2162,24 +2163,48 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2162 | vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded | AddTCPChksum | AddUDPChksum); | 2163 | vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded | AddTCPChksum | AddUDPChksum); |
2163 | 2164 | ||
2164 | if (!skb_shinfo(skb)->nr_frags) { | 2165 | if (!skb_shinfo(skb)->nr_frags) { |
2165 | vp->tx_ring[entry].frag[0].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data, | 2166 | dma_addr = pci_map_single(VORTEX_PCI(vp), skb->data, skb->len, |
2166 | skb->len, PCI_DMA_TODEVICE)); | 2167 | PCI_DMA_TODEVICE); |
2168 | if (dma_mapping_error(&VORTEX_PCI(vp)->dev, dma_addr)) | ||
2169 | goto out_dma_err; | ||
2170 | |||
2171 | vp->tx_ring[entry].frag[0].addr = cpu_to_le32(dma_addr); | ||
2167 | vp->tx_ring[entry].frag[0].length = cpu_to_le32(skb->len | LAST_FRAG); | 2172 | vp->tx_ring[entry].frag[0].length = cpu_to_le32(skb->len | LAST_FRAG); |
2168 | } else { | 2173 | } else { |
2169 | int i; | 2174 | int i; |
2170 | 2175 | ||
2171 | vp->tx_ring[entry].frag[0].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data, | 2176 | dma_addr = pci_map_single(VORTEX_PCI(vp), skb->data, |
2172 | skb_headlen(skb), PCI_DMA_TODEVICE)); | 2177 | skb_headlen(skb), PCI_DMA_TODEVICE); |
2178 | if (dma_mapping_error(&VORTEX_PCI(vp)->dev, dma_addr)) | ||
2179 | goto out_dma_err; | ||
2180 | |||
2181 | vp->tx_ring[entry].frag[0].addr = cpu_to_le32(dma_addr); | ||
2173 | vp->tx_ring[entry].frag[0].length = cpu_to_le32(skb_headlen(skb)); | 2182 | vp->tx_ring[entry].frag[0].length = cpu_to_le32(skb_headlen(skb)); |
2174 | 2183 | ||
2175 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { | 2184 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { |
2176 | skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; | 2185 | skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; |
2177 | 2186 | ||
2187 | dma_addr = skb_frag_dma_map(&VORTEX_PCI(vp)->dev, frag, | ||
2188 | 0, | ||
2189 | frag->size, | ||
2190 | DMA_TO_DEVICE); | ||
2191 | if (dma_mapping_error(&VORTEX_PCI(vp)->dev, dma_addr)) { | ||
2192 | for(i = i-1; i >= 0; i--) | ||
2193 | dma_unmap_page(&VORTEX_PCI(vp)->dev, | ||
2194 | le32_to_cpu(vp->tx_ring[entry].frag[i+1].addr), | ||
2195 | le32_to_cpu(vp->tx_ring[entry].frag[i+1].length), | ||
2196 | DMA_TO_DEVICE); | ||
2197 | |||
2198 | pci_unmap_single(VORTEX_PCI(vp), | ||
2199 | le32_to_cpu(vp->tx_ring[entry].frag[0].addr), | ||
2200 | le32_to_cpu(vp->tx_ring[entry].frag[0].length), | ||
2201 | PCI_DMA_TODEVICE); | ||
2202 | |||
2203 | goto out_dma_err; | ||
2204 | } | ||
2205 | |||
2178 | vp->tx_ring[entry].frag[i+1].addr = | 2206 | vp->tx_ring[entry].frag[i+1].addr = |
2179 | cpu_to_le32(skb_frag_dma_map( | 2207 | cpu_to_le32(dma_addr); |
2180 | &VORTEX_PCI(vp)->dev, | ||
2181 | frag, | ||
2182 | frag->page_offset, frag->size, DMA_TO_DEVICE)); | ||
2183 | 2208 | ||
2184 | if (i == skb_shinfo(skb)->nr_frags-1) | 2209 | if (i == skb_shinfo(skb)->nr_frags-1) |
2185 | vp->tx_ring[entry].frag[i+1].length = cpu_to_le32(skb_frag_size(frag)|LAST_FRAG); | 2210 | vp->tx_ring[entry].frag[i+1].length = cpu_to_le32(skb_frag_size(frag)|LAST_FRAG); |
@@ -2188,7 +2213,10 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2188 | } | 2213 | } |
2189 | } | 2214 | } |
2190 | #else | 2215 | #else |
2191 | vp->tx_ring[entry].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data, skb->len, PCI_DMA_TODEVICE)); | 2216 | dma_addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data, skb->len, PCI_DMA_TODEVICE)); |
2217 | if (dma_mapping_error(&VORTEX_PCI(vp)->dev, dma_addr)) | ||
2218 | goto out_dma_err; | ||
2219 | vp->tx_ring[entry].addr = cpu_to_le32(dma_addr); | ||
2192 | vp->tx_ring[entry].length = cpu_to_le32(skb->len | LAST_FRAG); | 2220 | vp->tx_ring[entry].length = cpu_to_le32(skb->len | LAST_FRAG); |
2193 | vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded); | 2221 | vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded); |
2194 | #endif | 2222 | #endif |
@@ -2216,7 +2244,11 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2216 | skb_tx_timestamp(skb); | 2244 | skb_tx_timestamp(skb); |
2217 | iowrite16(DownUnstall, ioaddr + EL3_CMD); | 2245 | iowrite16(DownUnstall, ioaddr + EL3_CMD); |
2218 | spin_unlock_irqrestore(&vp->lock, flags); | 2246 | spin_unlock_irqrestore(&vp->lock, flags); |
2247 | out: | ||
2219 | return NETDEV_TX_OK; | 2248 | return NETDEV_TX_OK; |
2249 | out_dma_err: | ||
2250 | dev_err(&VORTEX_PCI(vp)->dev, "Error mapping dma buffer\n"); | ||
2251 | goto out; | ||
2220 | } | 2252 | } |
2221 | 2253 | ||
2222 | /* The interrupt handler does all of the Rx thread work and cleans up | 2254 | /* The interrupt handler does all of the Rx thread work and cleans up |