aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/sky2.c61
1 files changed, 42 insertions, 19 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index a6ddfc1a9cb2..72c92495a9b3 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -1103,18 +1103,39 @@ static int sky2_rx_map_skb(struct pci_dev *pdev, struct rx_ring_info *re,
1103 int i; 1103 int i;
1104 1104
1105 re->data_addr = pci_map_single(pdev, skb->data, size, PCI_DMA_FROMDEVICE); 1105 re->data_addr = pci_map_single(pdev, skb->data, size, PCI_DMA_FROMDEVICE);
1106 if (unlikely(pci_dma_mapping_error(pdev, re->data_addr))) 1106 if (pci_dma_mapping_error(pdev, re->data_addr))
1107 return -EIO; 1107 goto mapping_error;
1108 1108
1109 pci_unmap_len_set(re, data_size, size); 1109 pci_unmap_len_set(re, data_size, size);
1110 1110
1111 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) 1111 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
1112 re->frag_addr[i] = pci_map_page(pdev, 1112 skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
1113 skb_shinfo(skb)->frags[i].page, 1113
1114 skb_shinfo(skb)->frags[i].page_offset, 1114 re->frag_addr[i] = pci_map_page(pdev, frag->page,
1115 skb_shinfo(skb)->frags[i].size, 1115 frag->page_offset,
1116 frag->size,
1116 PCI_DMA_FROMDEVICE); 1117 PCI_DMA_FROMDEVICE);
1118
1119 if (pci_dma_mapping_error(pdev, re->frag_addr[i]))
1120 goto map_page_error;
1121 }
1117 return 0; 1122 return 0;
1123
1124map_page_error:
1125 while (--i >= 0) {
1126 pci_unmap_page(pdev, re->frag_addr[i],
1127 skb_shinfo(skb)->frags[i].size,
1128 PCI_DMA_FROMDEVICE);
1129 }
1130
1131 pci_unmap_single(pdev, re->data_addr, pci_unmap_len(re, data_size),
1132 PCI_DMA_FROMDEVICE);
1133
1134mapping_error:
1135 if (net_ratelimit())
1136 dev_warn(&pdev->dev, "%s: rx mapping error\n",
1137 skb->dev->name);
1138 return -EIO;
1118} 1139}
1119 1140
1120static void sky2_rx_unmap_skb(struct pci_dev *pdev, struct rx_ring_info *re) 1141static void sky2_rx_unmap_skb(struct pci_dev *pdev, struct rx_ring_info *re)
@@ -2306,30 +2327,32 @@ static struct sk_buff *receive_new(struct sky2_port *sky2,
2306 struct rx_ring_info *re, 2327 struct rx_ring_info *re,
2307 unsigned int length) 2328 unsigned int length)
2308{ 2329{
2309 struct sk_buff *skb, *nskb; 2330 struct sk_buff *skb;
2331 struct rx_ring_info nre;
2310 unsigned hdr_space = sky2->rx_data_size; 2332 unsigned hdr_space = sky2->rx_data_size;
2311 2333
2312 /* Don't be tricky about reusing pages (yet) */ 2334 nre.skb = sky2_rx_alloc(sky2);
2313 nskb = sky2_rx_alloc(sky2); 2335 if (unlikely(!nre.skb))
2314 if (unlikely(!nskb)) 2336 goto nobuf;
2315 return NULL; 2337
2338 if (sky2_rx_map_skb(sky2->hw->pdev, &nre, hdr_space))
2339 goto nomap;
2316 2340
2317 skb = re->skb; 2341 skb = re->skb;
2318 sky2_rx_unmap_skb(sky2->hw->pdev, re); 2342 sky2_rx_unmap_skb(sky2->hw->pdev, re);
2319
2320 prefetch(skb->data); 2343 prefetch(skb->data);
2321 re->skb = nskb; 2344 *re = nre;
2322 if (sky2_rx_map_skb(sky2->hw->pdev, re, hdr_space)) {
2323 dev_kfree_skb(nskb);
2324 re->skb = skb;
2325 return NULL;
2326 }
2327 2345
2328 if (skb_shinfo(skb)->nr_frags) 2346 if (skb_shinfo(skb)->nr_frags)
2329 skb_put_frags(skb, hdr_space, length); 2347 skb_put_frags(skb, hdr_space, length);
2330 else 2348 else
2331 skb_put(skb, length); 2349 skb_put(skb, length);
2332 return skb; 2350 return skb;
2351
2352nomap:
2353 dev_kfree_skb(nre.skb);
2354nobuf:
2355 return NULL;
2333} 2356}
2334 2357
2335/* 2358/*