Commit ea23f627 authored by Scott Feldman's avatar Scott Feldman Committed by Stephen Hemminger

[e1000] 82544 PCI-X hang fix + TSO updates

* Bug fix: 82544 hang with PCI-X: if outgoing Tx buffers terminate
  within evenly-aligned dwords, and the device is sharing the bus
  segment with another PCI-X device, 82544 can hang the bus on a
  split-completion transaction.  Fix is to split buffer into two
  buffers with the first one not terminating within evenly-aligned
  dword address, and the second one being 4-bytes, which goes as a
  non-split-conpletion PCI-X transaction.
* 8254x controllers that support TSO do an internal calculation to
  make sure there is enough FIFO space to handle the overhead
  of each TSO segment before DMA'ing TSO data from host memory.  The
  internal calculation is dependent on the mss of the TSO (defines
  the number of segments), but the reserved space is a constant, so
  we need to adjust the maximum size of each buffer queued to the
  hardware to hold the equation and not overrun the FIFO.  This is
  per TSO because the mss can change from one send to the next.
parent 62e3d2b6
......@@ -194,6 +194,7 @@ struct e1000_adapter {
uint32_t tx_head_addr;
uint32_t tx_fifo_size;
atomic_t tx_fifo_stall;
boolean_t pcix_82544;
/* RX */
struct e1000_desc_ring rx_ring;
......
......@@ -820,6 +820,12 @@ e1000_configure_tx(struct e1000_adapter *adapter)
adapter->txd_cmd |= E1000_TXD_CMD_RS;
else
adapter->txd_cmd |= E1000_TXD_CMD_RPS;
/* Cache if we're 82544 running in PCI-X because we'll
* need this to apply a workaround later in the send path. */
if(adapter->hw.mac_type == e1000_82544 &&
adapter->hw.bus_type == e1000_bus_type_pcix)
adapter->pcix_82544 = 1;
}
/**
......@@ -1512,11 +1518,18 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb,
{
struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
struct e1000_buffer *buffer_info;
int len = skb->len;
unsigned int len = skb->len, max_per_txd = E1000_MAX_DATA_PER_TXD;
unsigned int offset = 0, size, count = 0, i;
#ifdef NETIF_F_TSO
unsigned int tso = skb_shinfo(skb)->tso_size;
unsigned int mss = skb_shinfo(skb)->tso_size;
/* The controller does a simple calculation to
* make sure there is enough room in the FIFO before
* initiating the DMA for each buffer. The calc is:
* 4 = ceil(buffer len/mss). To make sure we don't
* overrun the FIFO, adjust the max buffer len if mss
* drops. */
if(mss) max_per_txd = min(mss << 2, max_per_txd);
#endif
unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
unsigned int f;
......@@ -1526,13 +1539,20 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb,
while(len) {
buffer_info = &tx_ring->buffer_info[i];
size = min(len, E1000_MAX_DATA_PER_TXD);
size = min(len, max_per_txd);
#ifdef NETIF_F_TSO
/* Workaround for premature desc write-backs
* in TSO mode. Append 4-byte sentinel desc */
if(tso && !nr_frags && size == len && size > 4)
if(mss && !nr_frags && size == len && size > 8)
size -= 4;
#endif
/* Workaround for potential 82544 hang in PCI-X. Avoid
* terminating buffers within evenly-aligned dwords. */
if(adapter->pcix_82544 &&
!((unsigned long)(skb->data + offset + size - 1) & 4) &&
size > 4)
size -= 4;
buffer_info->length = size;
buffer_info->dma =
pci_map_single(adapter->pdev,
......@@ -1552,22 +1572,30 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb,
frag = &skb_shinfo(skb)->frags[f];
len = frag->size;
offset = 0;
offset = frag->page_offset;
while(len) {
buffer_info = &tx_ring->buffer_info[i];
size = min(len, E1000_MAX_DATA_PER_TXD);
size = min(len, max_per_txd);
#ifdef NETIF_F_TSO
/* Workaround for premature desc write-backs
* in TSO mode. Append 4-byte sentinel desc */
if(tso && f == (nr_frags-1) && size == len && size > 4)
if(mss && f == (nr_frags-1) && size == len && size > 8)
size -= 4;
#endif
/* Workaround for potential 82544 hang in PCI-X.
* Avoid terminating buffers within evenly-aligned
* dwords. */
if(adapter->pcix_82544 &&
!((unsigned long)(frag->page+offset+size-1) & 4) &&
size > 4)
size -= 4;
buffer_info->length = size;
buffer_info->dma =
pci_map_page(adapter->pdev,
frag->page,
frag->page_offset + offset,
offset,
size,
PCI_DMA_TODEVICE);
buffer_info->time_stamp = jiffies;
......@@ -1578,6 +1606,31 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb,
if(++i == tx_ring->count) i = 0;
}
}
if(E1000_DESC_UNUSED(&adapter->tx_ring) < count) {
/* There aren't enough descriptors available to queue up
* this send, so undo the mapping and abort the send.
* We could have done the check before we mapped the skb,
* but because of all the workarounds (above), it's too
* difficult to predict how many we're going to need.*/
i = first;
while(count--) {
buffer_info = &tx_ring->buffer_info[i];
if(buffer_info->dma) {
pci_unmap_page(adapter->pdev,
buffer_info->dma,
buffer_info->length,
PCI_DMA_TODEVICE);
buffer_info->dma = 0;
}
if(++i == tx_ring->count) i = 0;
}
return 0;
}
i = (i == 0) ? tx_ring->count - 1 : i - 1;
tx_ring->buffer_info[i].skb = skb;
tx_ring->buffer_info[first].next_to_watch = i;
......@@ -1672,29 +1725,19 @@ e1000_82547_fifo_workaround(struct e1000_adapter *adapter, struct sk_buff *skb)
return 0;
}
/* Tx Descriptors needed, worst case */
#define TXD_USE_COUNT(S) (((S) >> E1000_MAX_TXD_PWR) + \
(((S) & (E1000_MAX_DATA_PER_TXD - 1)) ? 1 : 0))
#define DESC_NEEDED TXD_USE_COUNT(MAX_JUMBO_FRAME_SIZE) + \
MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1
static int
e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev->priv;
unsigned int first;
unsigned int tx_flags = 0;
int count;
if(skb->len <= 0) {
dev_kfree_skb_any(skb);
return 0;
}
if(E1000_DESC_UNUSED(&adapter->tx_ring) < DESC_NEEDED) {
netif_stop_queue(netdev);
return 1;
}
if(adapter->hw.mac_type == e1000_82547) {
if(e1000_82547_fifo_workaround(adapter, skb)) {
netif_stop_queue(netdev);
......@@ -1715,7 +1758,12 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
else if(e1000_tx_csum(adapter, skb))
tx_flags |= E1000_TX_FLAGS_CSUM;
e1000_tx_queue(adapter, e1000_tx_map(adapter, skb, first), tx_flags);
if((count = e1000_tx_map(adapter, skb, first)))
e1000_tx_queue(adapter, count, tx_flags);
else {
netif_stop_queue(netdev);
return 1;
}
netdev->trans_start = jiffies;
......
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