Skip to content

Commit 0f8ab89

Browse files
Benjamin LiJeff Garzik
authored andcommitted
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>
1 parent 3e71f6d commit 0f8ab89

File tree

1 file changed

+107
-7
lines changed

1 file changed

+107
-7
lines changed

drivers/net/qla3xxx.c

Lines changed: 107 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,8 @@ static void ql_enable_interrupts(struct ql3_adapter *qdev)
276276
static void ql_release_to_lrg_buf_free_list(struct ql3_adapter *qdev,
277277
struct ql_rcv_buf_cb *lrg_buf_cb)
278278
{
279-
u64 map;
279+
dma_addr_t map;
280+
int err;
280281
lrg_buf_cb->next = NULL;
281282

282283
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,
304305
qdev->lrg_buffer_len -
305306
QL_HEADER_SPACE,
306307
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+
307319
lrg_buf_cb->buf_phy_addr_low =
308320
cpu_to_le32(LS_64BITS(map));
309321
lrg_buf_cb->buf_phy_addr_high =
@@ -1624,7 +1636,8 @@ static const struct ethtool_ops ql3xxx_ethtool_ops = {
16241636
static int ql_populate_free_queue(struct ql3_adapter *qdev)
16251637
{
16261638
struct ql_rcv_buf_cb *lrg_buf_cb = qdev->lrg_buf_free_head;
1627-
u64 map;
1639+
dma_addr_t map;
1640+
int err;
16281641

16291642
while (lrg_buf_cb) {
16301643
if (!lrg_buf_cb->skb) {
@@ -1646,6 +1659,17 @@ static int ql_populate_free_queue(struct ql3_adapter *qdev)
16461659
qdev->lrg_buffer_len -
16471660
QL_HEADER_SPACE,
16481661
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+
16491673
lrg_buf_cb->buf_phy_addr_low =
16501674
cpu_to_le32(LS_64BITS(map));
16511675
lrg_buf_cb->buf_phy_addr_high =
@@ -2147,7 +2171,9 @@ static int ql_send_map(struct ql3_adapter *qdev,
21472171
struct oal *oal;
21482172
struct oal_entry *oal_entry;
21492173
int len = skb_headlen(skb);
2150-
u64 map;
2174+
dma_addr_t map;
2175+
int err;
2176+
int completed_segs, i;
21512177
int seg_cnt, seg = 0;
21522178
int frag_cnt = (int)skb_shinfo(skb)->nr_frags;
21532179

@@ -2160,6 +2186,15 @@ static int ql_send_map(struct ql3_adapter *qdev,
21602186
* Map the skb buffer first.
21612187
*/
21622188
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+
21632198
oal_entry = (struct oal_entry *)&mac_iocb_ptr->buf_addr0_low;
21642199
oal_entry->dma_lo = cpu_to_le32(LS_64BITS(map));
21652200
oal_entry->dma_hi = cpu_to_le32(MS_64BITS(map));
@@ -2173,10 +2208,9 @@ static int ql_send_map(struct ql3_adapter *qdev,
21732208
oal_entry->len =
21742209
cpu_to_le32(le32_to_cpu(oal_entry->len) | OAL_LAST_ENTRY);
21752210
} else {
2176-
int i;
21772211
oal = tx_cb->oal;
2178-
for (i=0; i<frag_cnt; i++,seg++) {
2179-
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
2212+
for (completed_segs=0; completed_segs<frag_cnt; completed_segs++,seg++) {
2213+
skb_frag_t *frag = &skb_shinfo(skb)->frags[completed_segs];
21802214
oal_entry++;
21812215
if ((seg == 2 && seg_cnt > 3) || /* Check for continuation */
21822216
(seg == 7 && seg_cnt > 8) || /* requirements. It's strange */
@@ -2186,6 +2220,15 @@ static int ql_send_map(struct ql3_adapter *qdev,
21862220
map = pci_map_single(qdev->pdev, oal,
21872221
sizeof(struct oal),
21882222
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+
21892232
oal_entry->dma_lo = cpu_to_le32(LS_64BITS(map));
21902233
oal_entry->dma_hi = cpu_to_le32(MS_64BITS(map));
21912234
oal_entry->len =
@@ -2204,6 +2247,14 @@ static int ql_send_map(struct ql3_adapter *qdev,
22042247
pci_map_page(qdev->pdev, frag->page,
22052248
frag->page_offset, frag->size,
22062249
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+
22072258
oal_entry->dma_lo = cpu_to_le32(LS_64BITS(map));
22082259
oal_entry->dma_hi = cpu_to_le32(MS_64BITS(map));
22092260
oal_entry->len = cpu_to_le32(frag->size);
@@ -2215,7 +2266,46 @@ static int ql_send_map(struct ql3_adapter *qdev,
22152266
oal_entry->len =
22162267
cpu_to_le32(le32_to_cpu(oal_entry->len) | OAL_LAST_ENTRY);
22172268
}
2269+
22182270
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+
22192309
}
22202310

22212311
/*
@@ -2528,7 +2618,8 @@ static int ql_alloc_large_buffers(struct ql3_adapter *qdev)
25282618
int i;
25292619
struct ql_rcv_buf_cb *lrg_buf_cb;
25302620
struct sk_buff *skb;
2531-
u64 map;
2621+
dma_addr_t map;
2622+
int err;
25322623

25332624
for (i = 0; i < qdev->num_large_buffers; i++) {
25342625
skb = netdev_alloc_skb(qdev->ndev,
@@ -2558,6 +2649,15 @@ static int ql_alloc_large_buffers(struct ql3_adapter *qdev)
25582649
qdev->lrg_buffer_len -
25592650
QL_HEADER_SPACE,
25602651
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+
25612661
pci_unmap_addr_set(lrg_buf_cb, mapaddr, map);
25622662
pci_unmap_len_set(lrg_buf_cb, maplen,
25632663
qdev->lrg_buffer_len -

0 commit comments

Comments
 (0)