diff options
author | Benjamin Li <benjamin.li@qlogic.com> | 2007-02-26 14:06:40 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-02-27 04:21:44 -0500 |
commit | 0f8ab89e825f8c9f1c84c558ad7e2e4006aee0d3 (patch) | |
tree | 1e10a407c48ab982032084b5fc72bb62a0d95173 /drivers | |
parent | 3e71f6dd47e7e64461328adcdc3fbad1465b4c2f (diff) |
qla3xxx: Check return code from pci_map_single() in ql_release_to_lrg_buf_free_list(), ql_populate_free_queue(), ql_alloc_large_buffers(), and ql3xxx_send()
pci_map_single() could fail. We need to properly check the return
code from pci_map_single(). If we can not properly map this address,
then we should cleanup and return the proper return code.
Signed-off-by: Benjamin Li <benjamin.li@qlogic.com>
Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rwxr-xr-x | drivers/net/qla3xxx.c | 114 |
1 files changed, 107 insertions, 7 deletions
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index 4e9b25f475d0..7a2f01a22cbf 100755 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c | |||
@@ -276,7 +276,8 @@ static void ql_enable_interrupts(struct ql3_adapter *qdev) | |||
276 | static void ql_release_to_lrg_buf_free_list(struct ql3_adapter *qdev, | 276 | static void ql_release_to_lrg_buf_free_list(struct ql3_adapter *qdev, |
277 | struct ql_rcv_buf_cb *lrg_buf_cb) | 277 | struct ql_rcv_buf_cb *lrg_buf_cb) |
278 | { | 278 | { |
279 | u64 map; | 279 | dma_addr_t map; |
280 | int err; | ||
280 | lrg_buf_cb->next = NULL; | 281 | lrg_buf_cb->next = NULL; |
281 | 282 | ||
282 | if (qdev->lrg_buf_free_tail == NULL) { /* The list is empty */ | 283 | if (qdev->lrg_buf_free_tail == NULL) { /* The list is empty */ |
@@ -304,6 +305,17 @@ static void ql_release_to_lrg_buf_free_list(struct ql3_adapter *qdev, | |||
304 | qdev->lrg_buffer_len - | 305 | qdev->lrg_buffer_len - |
305 | QL_HEADER_SPACE, | 306 | QL_HEADER_SPACE, |
306 | PCI_DMA_FROMDEVICE); | 307 | PCI_DMA_FROMDEVICE); |
308 | err = pci_dma_mapping_error(map); | ||
309 | if(err) { | ||
310 | printk(KERN_ERR "%s: PCI mapping failed with error: %d\n", | ||
311 | qdev->ndev->name, err); | ||
312 | dev_kfree_skb(lrg_buf_cb->skb); | ||
313 | lrg_buf_cb->skb = NULL; | ||
314 | |||
315 | qdev->lrg_buf_skb_check++; | ||
316 | return; | ||
317 | } | ||
318 | |||
307 | lrg_buf_cb->buf_phy_addr_low = | 319 | lrg_buf_cb->buf_phy_addr_low = |
308 | cpu_to_le32(LS_64BITS(map)); | 320 | cpu_to_le32(LS_64BITS(map)); |
309 | lrg_buf_cb->buf_phy_addr_high = | 321 | lrg_buf_cb->buf_phy_addr_high = |
@@ -1624,7 +1636,8 @@ static const struct ethtool_ops ql3xxx_ethtool_ops = { | |||
1624 | static int ql_populate_free_queue(struct ql3_adapter *qdev) | 1636 | static int ql_populate_free_queue(struct ql3_adapter *qdev) |
1625 | { | 1637 | { |
1626 | struct ql_rcv_buf_cb *lrg_buf_cb = qdev->lrg_buf_free_head; | 1638 | struct ql_rcv_buf_cb *lrg_buf_cb = qdev->lrg_buf_free_head; |
1627 | u64 map; | 1639 | dma_addr_t map; |
1640 | int err; | ||
1628 | 1641 | ||
1629 | while (lrg_buf_cb) { | 1642 | while (lrg_buf_cb) { |
1630 | if (!lrg_buf_cb->skb) { | 1643 | if (!lrg_buf_cb->skb) { |
@@ -1646,6 +1659,17 @@ static int ql_populate_free_queue(struct ql3_adapter *qdev) | |||
1646 | qdev->lrg_buffer_len - | 1659 | qdev->lrg_buffer_len - |
1647 | QL_HEADER_SPACE, | 1660 | QL_HEADER_SPACE, |
1648 | PCI_DMA_FROMDEVICE); | 1661 | PCI_DMA_FROMDEVICE); |
1662 | |||
1663 | err = pci_dma_mapping_error(map); | ||
1664 | if(err) { | ||
1665 | printk(KERN_ERR "%s: PCI mapping failed with error: %d\n", | ||
1666 | qdev->ndev->name, err); | ||
1667 | dev_kfree_skb(lrg_buf_cb->skb); | ||
1668 | lrg_buf_cb->skb = NULL; | ||
1669 | break; | ||
1670 | } | ||
1671 | |||
1672 | |||
1649 | lrg_buf_cb->buf_phy_addr_low = | 1673 | lrg_buf_cb->buf_phy_addr_low = |
1650 | cpu_to_le32(LS_64BITS(map)); | 1674 | cpu_to_le32(LS_64BITS(map)); |
1651 | lrg_buf_cb->buf_phy_addr_high = | 1675 | lrg_buf_cb->buf_phy_addr_high = |
@@ -2147,7 +2171,9 @@ static int ql_send_map(struct ql3_adapter *qdev, | |||
2147 | struct oal *oal; | 2171 | struct oal *oal; |
2148 | struct oal_entry *oal_entry; | 2172 | struct oal_entry *oal_entry; |
2149 | int len = skb_headlen(skb); | 2173 | int len = skb_headlen(skb); |
2150 | u64 map; | 2174 | dma_addr_t map; |
2175 | int err; | ||
2176 | int completed_segs, i; | ||
2151 | int seg_cnt, seg = 0; | 2177 | int seg_cnt, seg = 0; |
2152 | int frag_cnt = (int)skb_shinfo(skb)->nr_frags; | 2178 | int frag_cnt = (int)skb_shinfo(skb)->nr_frags; |
2153 | 2179 | ||
@@ -2160,6 +2186,15 @@ static int ql_send_map(struct ql3_adapter *qdev, | |||
2160 | * Map the skb buffer first. | 2186 | * Map the skb buffer first. |
2161 | */ | 2187 | */ |
2162 | map = pci_map_single(qdev->pdev, skb->data, len, PCI_DMA_TODEVICE); | 2188 | map = pci_map_single(qdev->pdev, skb->data, len, PCI_DMA_TODEVICE); |
2189 | |||
2190 | err = pci_dma_mapping_error(map); | ||
2191 | if(err) { | ||
2192 | printk(KERN_ERR "%s: PCI mapping failed with error: %d\n", | ||
2193 | qdev->ndev->name, err); | ||
2194 | |||
2195 | return NETDEV_TX_BUSY; | ||
2196 | } | ||
2197 | |||
2163 | oal_entry = (struct oal_entry *)&mac_iocb_ptr->buf_addr0_low; | 2198 | oal_entry = (struct oal_entry *)&mac_iocb_ptr->buf_addr0_low; |
2164 | oal_entry->dma_lo = cpu_to_le32(LS_64BITS(map)); | 2199 | oal_entry->dma_lo = cpu_to_le32(LS_64BITS(map)); |
2165 | oal_entry->dma_hi = cpu_to_le32(MS_64BITS(map)); | 2200 | oal_entry->dma_hi = cpu_to_le32(MS_64BITS(map)); |
@@ -2173,10 +2208,9 @@ static int ql_send_map(struct ql3_adapter *qdev, | |||
2173 | oal_entry->len = | 2208 | oal_entry->len = |
2174 | cpu_to_le32(le32_to_cpu(oal_entry->len) | OAL_LAST_ENTRY); | 2209 | cpu_to_le32(le32_to_cpu(oal_entry->len) | OAL_LAST_ENTRY); |
2175 | } else { | 2210 | } else { |
2176 | int i; | ||
2177 | oal = tx_cb->oal; | 2211 | oal = tx_cb->oal; |
2178 | for (i=0; i<frag_cnt; i++,seg++) { | 2212 | for (completed_segs=0; completed_segs<frag_cnt; completed_segs++,seg++) { |
2179 | skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; | 2213 | skb_frag_t *frag = &skb_shinfo(skb)->frags[completed_segs]; |
2180 | oal_entry++; | 2214 | oal_entry++; |
2181 | if ((seg == 2 && seg_cnt > 3) || /* Check for continuation */ | 2215 | if ((seg == 2 && seg_cnt > 3) || /* Check for continuation */ |
2182 | (seg == 7 && seg_cnt > 8) || /* requirements. It's strange */ | 2216 | (seg == 7 && seg_cnt > 8) || /* requirements. It's strange */ |
@@ -2186,6 +2220,15 @@ static int ql_send_map(struct ql3_adapter *qdev, | |||
2186 | map = pci_map_single(qdev->pdev, oal, | 2220 | map = pci_map_single(qdev->pdev, oal, |
2187 | sizeof(struct oal), | 2221 | sizeof(struct oal), |
2188 | PCI_DMA_TODEVICE); | 2222 | PCI_DMA_TODEVICE); |
2223 | |||
2224 | err = pci_dma_mapping_error(map); | ||
2225 | if(err) { | ||
2226 | |||
2227 | printk(KERN_ERR "%s: PCI mapping outbound address list with error: %d\n", | ||
2228 | qdev->ndev->name, err); | ||
2229 | goto map_error; | ||
2230 | } | ||
2231 | |||
2189 | oal_entry->dma_lo = cpu_to_le32(LS_64BITS(map)); | 2232 | oal_entry->dma_lo = cpu_to_le32(LS_64BITS(map)); |
2190 | oal_entry->dma_hi = cpu_to_le32(MS_64BITS(map)); | 2233 | oal_entry->dma_hi = cpu_to_le32(MS_64BITS(map)); |
2191 | oal_entry->len = | 2234 | oal_entry->len = |
@@ -2204,6 +2247,14 @@ static int ql_send_map(struct ql3_adapter *qdev, | |||
2204 | pci_map_page(qdev->pdev, frag->page, | 2247 | pci_map_page(qdev->pdev, frag->page, |
2205 | frag->page_offset, frag->size, | 2248 | frag->page_offset, frag->size, |
2206 | PCI_DMA_TODEVICE); | 2249 | PCI_DMA_TODEVICE); |
2250 | |||
2251 | err = pci_dma_mapping_error(map); | ||
2252 | if(err) { | ||
2253 | printk(KERN_ERR "%s: PCI mapping frags failed with error: %d\n", | ||
2254 | qdev->ndev->name, err); | ||
2255 | goto map_error; | ||
2256 | } | ||
2257 | |||
2207 | oal_entry->dma_lo = cpu_to_le32(LS_64BITS(map)); | 2258 | oal_entry->dma_lo = cpu_to_le32(LS_64BITS(map)); |
2208 | oal_entry->dma_hi = cpu_to_le32(MS_64BITS(map)); | 2259 | oal_entry->dma_hi = cpu_to_le32(MS_64BITS(map)); |
2209 | oal_entry->len = cpu_to_le32(frag->size); | 2260 | oal_entry->len = cpu_to_le32(frag->size); |
@@ -2215,7 +2266,46 @@ static int ql_send_map(struct ql3_adapter *qdev, | |||
2215 | oal_entry->len = | 2266 | oal_entry->len = |
2216 | cpu_to_le32(le32_to_cpu(oal_entry->len) | OAL_LAST_ENTRY); | 2267 | cpu_to_le32(le32_to_cpu(oal_entry->len) | OAL_LAST_ENTRY); |
2217 | } | 2268 | } |
2269 | |||
2218 | return NETDEV_TX_OK; | 2270 | return NETDEV_TX_OK; |
2271 | |||
2272 | map_error: | ||
2273 | /* A PCI mapping failed and now we will need to back out | ||
2274 | * We need to traverse through the oal's and associated pages which | ||
2275 | * have been mapped and now we must unmap them to clean up properly | ||
2276 | */ | ||
2277 | |||
2278 | seg = 1; | ||
2279 | oal_entry = (struct oal_entry *)&mac_iocb_ptr->buf_addr0_low; | ||
2280 | oal = tx_cb->oal; | ||
2281 | for (i=0; i<completed_segs; i++,seg++) { | ||
2282 | oal_entry++; | ||
2283 | |||
2284 | if((seg == 2 && seg_cnt > 3) || /* Check for continuation */ | ||
2285 | (seg == 7 && seg_cnt > 8) || /* requirements. It's strange */ | ||
2286 | (seg == 12 && seg_cnt > 13) || /* but necessary. */ | ||
2287 | (seg == 17 && seg_cnt > 18)) { | ||
2288 | pci_unmap_single(qdev->pdev, | ||
2289 | pci_unmap_addr(&tx_cb->map[seg], mapaddr), | ||
2290 | pci_unmap_len(&tx_cb->map[seg], maplen), | ||
2291 | PCI_DMA_TODEVICE); | ||
2292 | oal++; | ||
2293 | seg++; | ||
2294 | } | ||
2295 | |||
2296 | pci_unmap_page(qdev->pdev, | ||
2297 | pci_unmap_addr(&tx_cb->map[seg], mapaddr), | ||
2298 | pci_unmap_len(&tx_cb->map[seg], maplen), | ||
2299 | PCI_DMA_TODEVICE); | ||
2300 | } | ||
2301 | |||
2302 | pci_unmap_single(qdev->pdev, | ||
2303 | pci_unmap_addr(&tx_cb->map[0], mapaddr), | ||
2304 | pci_unmap_addr(&tx_cb->map[0], maplen), | ||
2305 | PCI_DMA_TODEVICE); | ||
2306 | |||
2307 | return NETDEV_TX_BUSY; | ||
2308 | |||
2219 | } | 2309 | } |
2220 | 2310 | ||
2221 | /* | 2311 | /* |
@@ -2528,7 +2618,8 @@ static int ql_alloc_large_buffers(struct ql3_adapter *qdev) | |||
2528 | int i; | 2618 | int i; |
2529 | struct ql_rcv_buf_cb *lrg_buf_cb; | 2619 | struct ql_rcv_buf_cb *lrg_buf_cb; |
2530 | struct sk_buff *skb; | 2620 | struct sk_buff *skb; |
2531 | u64 map; | 2621 | dma_addr_t map; |
2622 | int err; | ||
2532 | 2623 | ||
2533 | for (i = 0; i < qdev->num_large_buffers; i++) { | 2624 | for (i = 0; i < qdev->num_large_buffers; i++) { |
2534 | skb = netdev_alloc_skb(qdev->ndev, | 2625 | skb = netdev_alloc_skb(qdev->ndev, |
@@ -2558,6 +2649,15 @@ static int ql_alloc_large_buffers(struct ql3_adapter *qdev) | |||
2558 | qdev->lrg_buffer_len - | 2649 | qdev->lrg_buffer_len - |
2559 | QL_HEADER_SPACE, | 2650 | QL_HEADER_SPACE, |
2560 | PCI_DMA_FROMDEVICE); | 2651 | PCI_DMA_FROMDEVICE); |
2652 | |||
2653 | err = pci_dma_mapping_error(map); | ||
2654 | if(err) { | ||
2655 | printk(KERN_ERR "%s: PCI mapping failed with error: %d\n", | ||
2656 | qdev->ndev->name, err); | ||
2657 | ql_free_large_buffers(qdev); | ||
2658 | return -ENOMEM; | ||
2659 | } | ||
2660 | |||
2561 | pci_unmap_addr_set(lrg_buf_cb, mapaddr, map); | 2661 | pci_unmap_addr_set(lrg_buf_cb, mapaddr, map); |
2562 | pci_unmap_len_set(lrg_buf_cb, maplen, | 2662 | pci_unmap_len_set(lrg_buf_cb, maplen, |
2563 | qdev->lrg_buffer_len - | 2663 | qdev->lrg_buffer_len - |