Commit 6f703406 authored by Dhananjay Phadke's avatar Dhananjay Phadke Committed by David S. Miller

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: default avatarDhananjay Phadke <dhananjay@netxen.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 03e678ee
...@@ -860,7 +860,6 @@ struct nx_host_rds_ring { ...@@ -860,7 +860,6 @@ struct nx_host_rds_ring {
u32 skb_size; u32 skb_size;
struct netxen_rx_buffer *rx_buf_arr; /* rx buffers for receive */ struct netxen_rx_buffer *rx_buf_arr; /* rx buffers for receive */
struct list_head free_list; struct list_head free_list;
int begin_alloc;
}; };
/* /*
......
...@@ -308,7 +308,6 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) ...@@ -308,7 +308,6 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
} }
memset(rds_ring->rx_buf_arr, 0, RCV_BUFFSIZE); memset(rds_ring->rx_buf_arr, 0, RCV_BUFFSIZE);
INIT_LIST_HEAD(&rds_ring->free_list); INIT_LIST_HEAD(&rds_ring->free_list);
rds_ring->begin_alloc = 0;
/* /*
* Now go through all of them, set reference handles * Now go through all of them, set reference handles
* and put them in the queues. * and put them in the queues.
...@@ -1435,7 +1434,6 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) ...@@ -1435,7 +1434,6 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
struct rcv_desc *pdesc; struct rcv_desc *pdesc;
struct netxen_rx_buffer *buffer; struct netxen_rx_buffer *buffer;
int count = 0; int count = 0;
int index = 0;
netxen_ctx_msg msg = 0; netxen_ctx_msg msg = 0;
dma_addr_t dma; dma_addr_t dma;
struct list_head *head; struct list_head *head;
...@@ -1443,7 +1441,6 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) ...@@ -1443,7 +1441,6 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
rds_ring = &recv_ctx->rds_rings[ringid]; rds_ring = &recv_ctx->rds_rings[ringid];
producer = rds_ring->producer; producer = rds_ring->producer;
index = rds_ring->begin_alloc;
head = &rds_ring->free_list; head = &rds_ring->free_list;
/* We can start writing rx descriptors into the phantom memory. */ /* We can start writing rx descriptors into the phantom memory. */
...@@ -1451,39 +1448,37 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) ...@@ -1451,39 +1448,37 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
skb = dev_alloc_skb(rds_ring->skb_size); skb = dev_alloc_skb(rds_ring->skb_size);
if (unlikely(!skb)) { if (unlikely(!skb)) {
rds_ring->begin_alloc = index;
break; break;
} }
if (!adapter->ahw.cut_through)
skb_reserve(skb, 2);
dma = pci_map_single(pdev, skb->data,
rds_ring->dma_size, PCI_DMA_FROMDEVICE);
if (pci_dma_mapping_error(pdev, dma)) {
dev_kfree_skb_any(skb);
break;
}
count++;
buffer = list_entry(head->next, struct netxen_rx_buffer, list); buffer = list_entry(head->next, struct netxen_rx_buffer, list);
list_del(&buffer->list); list_del(&buffer->list);
count++; /* now there should be no failure */
pdesc = &rds_ring->desc_head[producer];
if (!adapter->ahw.cut_through)
skb_reserve(skb, 2);
/* This will be setup when we receive the
* buffer after it has been filled FSL TBD TBD
* skb->dev = netdev;
*/
dma = pci_map_single(pdev, skb->data, rds_ring->dma_size,
PCI_DMA_FROMDEVICE);
pdesc->addr_buffer = cpu_to_le64(dma);
buffer->skb = skb; buffer->skb = skb;
buffer->state = NETXEN_BUFFER_BUSY; buffer->state = NETXEN_BUFFER_BUSY;
buffer->dma = dma; buffer->dma = dma;
/* make a rcv descriptor */ /* make a rcv descriptor */
pdesc = &rds_ring->desc_head[producer];
pdesc->addr_buffer = cpu_to_le64(dma);
pdesc->reference_handle = cpu_to_le16(buffer->ref_handle); pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
DPRINTK(INFO, "done writing descripter\n");
producer = producer = get_next_index(producer, rds_ring->max_rx_desc_count);
get_next_index(producer, rds_ring->max_rx_desc_count);
index = get_next_index(index, rds_ring->max_rx_desc_count);
} }
/* if we did allocate buffers, then write the count to Phantom */ /* if we did allocate buffers, then write the count to Phantom */
if (count) { if (count) {
rds_ring->begin_alloc = index;
rds_ring->producer = producer; rds_ring->producer = producer;
/* Window = 1 */ /* Window = 1 */
adapter->pci_write_normalize(adapter, adapter->pci_write_normalize(adapter,
...@@ -1522,49 +1517,50 @@ static void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, ...@@ -1522,49 +1517,50 @@ static void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter,
struct rcv_desc *pdesc; struct rcv_desc *pdesc;
struct netxen_rx_buffer *buffer; struct netxen_rx_buffer *buffer;
int count = 0; int count = 0;
int index = 0;
struct list_head *head; struct list_head *head;
dma_addr_t dma;
rds_ring = &recv_ctx->rds_rings[ringid]; rds_ring = &recv_ctx->rds_rings[ringid];
producer = rds_ring->producer; producer = rds_ring->producer;
index = rds_ring->begin_alloc;
head = &rds_ring->free_list; head = &rds_ring->free_list;
/* We can start writing rx descriptors into the phantom memory. */ /* We can start writing rx descriptors into the phantom memory. */
while (!list_empty(head)) { while (!list_empty(head)) {
skb = dev_alloc_skb(rds_ring->skb_size); skb = dev_alloc_skb(rds_ring->skb_size);
if (unlikely(!skb)) { if (unlikely(!skb)) {
rds_ring->begin_alloc = index;
break; break;
} }
if (!adapter->ahw.cut_through)
skb_reserve(skb, 2);
dma = pci_map_single(pdev, skb->data,
rds_ring->dma_size, PCI_DMA_FROMDEVICE);
if (pci_dma_mapping_error(pdev, dma)) {
dev_kfree_skb_any(skb);
break;
}
count++;
buffer = list_entry(head->next, struct netxen_rx_buffer, list); buffer = list_entry(head->next, struct netxen_rx_buffer, list);
list_del(&buffer->list); list_del(&buffer->list);
count++; /* now there should be no failure */
pdesc = &rds_ring->desc_head[producer];
if (!adapter->ahw.cut_through)
skb_reserve(skb, 2);
buffer->skb = skb; buffer->skb = skb;
buffer->state = NETXEN_BUFFER_BUSY; buffer->state = NETXEN_BUFFER_BUSY;
buffer->dma = pci_map_single(pdev, skb->data, buffer->dma = dma;
rds_ring->dma_size,
PCI_DMA_FROMDEVICE);
/* make a rcv descriptor */ /* make a rcv descriptor */
pdesc = &rds_ring->desc_head[producer];
pdesc->reference_handle = cpu_to_le16(buffer->ref_handle); pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
pdesc->addr_buffer = cpu_to_le64(buffer->dma); pdesc->addr_buffer = cpu_to_le64(buffer->dma);
producer =
get_next_index(producer, rds_ring->max_rx_desc_count); producer = get_next_index(producer, rds_ring->max_rx_desc_count);
index = get_next_index(index, rds_ring->max_rx_desc_count);
buffer = &rds_ring->rx_buf_arr[index];
} }
/* if we did allocate buffers, then write the count to Phantom */ /* if we did allocate buffers, then write the count to Phantom */
if (count) { if (count) {
rds_ring->begin_alloc = index;
rds_ring->producer = producer; rds_ring->producer = producer;
/* Window = 1 */ /* Window = 1 */
adapter->pci_write_normalize(adapter, adapter->pci_write_normalize(adapter,
......
...@@ -1200,6 +1200,24 @@ static bool netxen_tso_check(struct net_device *netdev, ...@@ -1200,6 +1200,24 @@ static bool netxen_tso_check(struct net_device *netdev,
return tso; return tso;
} }
static void
netxen_clean_tx_dma_mapping(struct pci_dev *pdev,
struct netxen_cmd_buffer *pbuf, int last)
{
int k;
struct netxen_skb_frag *buffrag;
buffrag = &pbuf->frag_array[0];
pci_unmap_single(pdev, buffrag->dma,
buffrag->length, PCI_DMA_TODEVICE);
for (k = 1; k < last; k++) {
buffrag = &pbuf->frag_array[k];
pci_unmap_page(pdev, buffrag->dma,
buffrag->length, PCI_DMA_TODEVICE);
}
}
static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{ {
struct netxen_adapter *adapter = netdev_priv(netdev); 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,6 +1226,8 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
struct netxen_cmd_buffer *pbuf; struct netxen_cmd_buffer *pbuf;
struct netxen_skb_frag *buffrag; struct netxen_skb_frag *buffrag;
struct cmd_desc_type0 *hwdesc; struct cmd_desc_type0 *hwdesc;
struct pci_dev *pdev = adapter->pdev;
dma_addr_t temp_dma;
int i, k; int i, k;
u32 producer, consumer; u32 producer, consumer;
...@@ -1240,8 +1260,12 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ...@@ -1240,8 +1260,12 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
pbuf->skb = skb; pbuf->skb = skb;
pbuf->frag_count = frag_count; pbuf->frag_count = frag_count;
buffrag = &pbuf->frag_array[0]; buffrag = &pbuf->frag_array[0];
buffrag->dma = pci_map_single(adapter->pdev, skb->data, first_seg_len, temp_dma = pci_map_single(pdev, skb->data, first_seg_len,
PCI_DMA_TODEVICE); PCI_DMA_TODEVICE);
if (pci_dma_mapping_error(pdev, temp_dma))
goto drop_packet;
buffrag->dma = temp_dma;
buffrag->length = first_seg_len; buffrag->length = first_seg_len;
netxen_set_tx_frags_len(hwdesc, frag_count, skb->len); netxen_set_tx_frags_len(hwdesc, frag_count, skb->len);
netxen_set_tx_port(hwdesc, adapter->portnum); 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,7 +1277,6 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
struct skb_frag_struct *frag; struct skb_frag_struct *frag;
int len, temp_len; int len, temp_len;
unsigned long offset; unsigned long offset;
dma_addr_t temp_dma;
/* move to next desc. if there is a need */ /* move to next desc. if there is a need */
if ((i & 0x3) == 0) { if ((i & 0x3) == 0) {
...@@ -1269,8 +1292,12 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ...@@ -1269,8 +1292,12 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
offset = frag->page_offset; offset = frag->page_offset;
temp_len = len; temp_len = len;
temp_dma = pci_map_page(adapter->pdev, frag->page, offset, temp_dma = pci_map_page(pdev, frag->page, offset,
len, PCI_DMA_TODEVICE); len, PCI_DMA_TODEVICE);
if (pci_dma_mapping_error(pdev, temp_dma)) {
netxen_clean_tx_dma_mapping(pdev, pbuf, i);
goto drop_packet;
}
buffrag++; buffrag++;
buffrag->dma = temp_dma; buffrag->dma = temp_dma;
...@@ -1345,6 +1372,11 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ...@@ -1345,6 +1372,11 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
netdev->trans_start = jiffies; netdev->trans_start = jiffies;
return NETDEV_TX_OK; return NETDEV_TX_OK;
drop_packet:
adapter->stats.txdropped++;
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
} }
static int netxen_nic_check_temp(struct netxen_adapter *adapter) static int netxen_nic_check_temp(struct netxen_adapter *adapter)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment