aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorstephen hemminger <shemminger@vyatta.com>2010-02-01 08:45:41 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-03 23:32:28 -0500
commit3fbd9187d004149fb8a98c9cb51ef9f4a4f66aca (patch)
treee307be7f7f8b9c6b41359c98399ea5a356da8b65 /drivers/net
parent1621e0940294c20e302faf401f41204de7252e22 (diff)
sky2: hand receive DMA mapping failures
If receive buffer mapping failed, then it was possible to get stuck with unmapped receive buffer in DMA ring. This would be an extremely rare condition because the driver had just released the map for the last receive so it should be able to get another map again (in soft-irq). Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
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/*