diff options
author | Dhananjay Phadke <dhananjay@netxen.com> | 2009-01-14 23:50:00 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-01-14 23:50:00 -0500 |
commit | 6f70340698333f14b1d9c9e913c5de8f66b72c55 (patch) | |
tree | 52733b9edfee2fcaa396054cbf44555b142e2fd1 /drivers/net/netxen/netxen_nic_main.c | |
parent | 03e678ee968ae54b79c1580c2935895bd863ad95 (diff) |
netxen: handle dma mapping failures
o Bail out if pci_map_single() fails while replenishing rx ring.
o Drop packet if pci_map_{single,page}() fail in tx.
Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/netxen/netxen_nic_main.c')
-rw-r--r-- | drivers/net/netxen/netxen_nic_main.c | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 9268fd2fbacf..86867405a367 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c | |||
@@ -1200,6 +1200,24 @@ static bool netxen_tso_check(struct net_device *netdev, | |||
1200 | return tso; | 1200 | return tso; |
1201 | } | 1201 | } |
1202 | 1202 | ||
1203 | static void | ||
1204 | netxen_clean_tx_dma_mapping(struct pci_dev *pdev, | ||
1205 | struct netxen_cmd_buffer *pbuf, int last) | ||
1206 | { | ||
1207 | int k; | ||
1208 | struct netxen_skb_frag *buffrag; | ||
1209 | |||
1210 | buffrag = &pbuf->frag_array[0]; | ||
1211 | pci_unmap_single(pdev, buffrag->dma, | ||
1212 | buffrag->length, PCI_DMA_TODEVICE); | ||
1213 | |||
1214 | for (k = 1; k < last; k++) { | ||
1215 | buffrag = &pbuf->frag_array[k]; | ||
1216 | pci_unmap_page(pdev, buffrag->dma, | ||
1217 | buffrag->length, PCI_DMA_TODEVICE); | ||
1218 | } | ||
1219 | } | ||
1220 | |||
1203 | static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | 1221 | static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) |
1204 | { | 1222 | { |
1205 | struct netxen_adapter *adapter = netdev_priv(netdev); | 1223 | struct netxen_adapter *adapter = netdev_priv(netdev); |
@@ -1208,6 +1226,8 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
1208 | struct netxen_cmd_buffer *pbuf; | 1226 | struct netxen_cmd_buffer *pbuf; |
1209 | struct netxen_skb_frag *buffrag; | 1227 | struct netxen_skb_frag *buffrag; |
1210 | struct cmd_desc_type0 *hwdesc; | 1228 | struct cmd_desc_type0 *hwdesc; |
1229 | struct pci_dev *pdev = adapter->pdev; | ||
1230 | dma_addr_t temp_dma; | ||
1211 | int i, k; | 1231 | int i, k; |
1212 | 1232 | ||
1213 | u32 producer, consumer; | 1233 | u32 producer, consumer; |
@@ -1240,8 +1260,12 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
1240 | pbuf->skb = skb; | 1260 | pbuf->skb = skb; |
1241 | pbuf->frag_count = frag_count; | 1261 | pbuf->frag_count = frag_count; |
1242 | buffrag = &pbuf->frag_array[0]; | 1262 | buffrag = &pbuf->frag_array[0]; |
1243 | buffrag->dma = pci_map_single(adapter->pdev, skb->data, first_seg_len, | 1263 | temp_dma = pci_map_single(pdev, skb->data, first_seg_len, |
1244 | PCI_DMA_TODEVICE); | 1264 | PCI_DMA_TODEVICE); |
1265 | if (pci_dma_mapping_error(pdev, temp_dma)) | ||
1266 | goto drop_packet; | ||
1267 | |||
1268 | buffrag->dma = temp_dma; | ||
1245 | buffrag->length = first_seg_len; | 1269 | buffrag->length = first_seg_len; |
1246 | netxen_set_tx_frags_len(hwdesc, frag_count, skb->len); | 1270 | netxen_set_tx_frags_len(hwdesc, frag_count, skb->len); |
1247 | netxen_set_tx_port(hwdesc, adapter->portnum); | 1271 | netxen_set_tx_port(hwdesc, adapter->portnum); |
@@ -1253,7 +1277,6 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
1253 | struct skb_frag_struct *frag; | 1277 | struct skb_frag_struct *frag; |
1254 | int len, temp_len; | 1278 | int len, temp_len; |
1255 | unsigned long offset; | 1279 | unsigned long offset; |
1256 | dma_addr_t temp_dma; | ||
1257 | 1280 | ||
1258 | /* move to next desc. if there is a need */ | 1281 | /* move to next desc. if there is a need */ |
1259 | if ((i & 0x3) == 0) { | 1282 | if ((i & 0x3) == 0) { |
@@ -1269,8 +1292,12 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
1269 | offset = frag->page_offset; | 1292 | offset = frag->page_offset; |
1270 | 1293 | ||
1271 | temp_len = len; | 1294 | temp_len = len; |
1272 | temp_dma = pci_map_page(adapter->pdev, frag->page, offset, | 1295 | temp_dma = pci_map_page(pdev, frag->page, offset, |
1273 | len, PCI_DMA_TODEVICE); | 1296 | len, PCI_DMA_TODEVICE); |
1297 | if (pci_dma_mapping_error(pdev, temp_dma)) { | ||
1298 | netxen_clean_tx_dma_mapping(pdev, pbuf, i); | ||
1299 | goto drop_packet; | ||
1300 | } | ||
1274 | 1301 | ||
1275 | buffrag++; | 1302 | buffrag++; |
1276 | buffrag->dma = temp_dma; | 1303 | buffrag->dma = temp_dma; |
@@ -1345,6 +1372,11 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
1345 | netdev->trans_start = jiffies; | 1372 | netdev->trans_start = jiffies; |
1346 | 1373 | ||
1347 | return NETDEV_TX_OK; | 1374 | return NETDEV_TX_OK; |
1375 | |||
1376 | drop_packet: | ||
1377 | adapter->stats.txdropped++; | ||
1378 | dev_kfree_skb_any(skb); | ||
1379 | return NETDEV_TX_OK; | ||
1348 | } | 1380 | } |
1349 | 1381 | ||
1350 | static int netxen_nic_check_temp(struct netxen_adapter *adapter) | 1382 | static int netxen_nic_check_temp(struct netxen_adapter *adapter) |