The purpose of this change is to add a routine to

disable ASPM L0S and L1 LINK states on 82573, 82574,
and 82583. The theory is that this is behind certain
hangs being experienced by some customers.

Also included a small optimization in the rxeof routine
that was in my internal code.

Change the PBA size for pchlan, it was incorrect.

MFC after: 3 days
This commit is contained in:
Jack F Vogel 2010-11-24 22:24:07 +00:00
parent 10798b4875
commit 12203744da

View File

@ -93,7 +93,7 @@ int em_display_debug_stats = 0;
/*********************************************************************
* Driver version:
*********************************************************************/
char em_driver_version[] = "7.1.7";
char em_driver_version[] = "7.1.8";
/*********************************************************************
* PCI Device ID Table
@ -272,6 +272,7 @@ static void em_get_wakeup(device_t);
static void em_enable_wakeup(device_t);
static int em_enable_phy_wakeup(struct adapter *);
static void em_led_func(void *, int);
static void em_disable_aspm(struct adapter *);
static int em_irq_fast(void *);
@ -1229,9 +1230,9 @@ em_init_locked(struct adapter *adapter)
break;
case e1000_ich9lan:
case e1000_ich10lan:
case e1000_pchlan:
pba = E1000_PBA_10K;
break;
case e1000_pchlan:
case e1000_pch2lan:
pba = E1000_PBA_26K;
break;
@ -2762,6 +2763,7 @@ em_reset(struct adapter *adapter)
/* Issue a global reset */
e1000_reset_hw(hw);
E1000_WRITE_REG(hw, E1000_WUC, 0);
em_disable_aspm(adapter);
if (e1000_init_hw(hw) < 0) {
device_printf(dev, "Hardware Initialization Failed\n");
@ -4205,58 +4207,9 @@ em_rxeof(struct rx_ring *rxr, int count, int *done)
len = le16toh(cur->length);
eop = (status & E1000_RXD_STAT_EOP) != 0;
count--;
if (((cur->errors & E1000_RXD_ERR_FRAME_ERR_MASK) == 0) &&
(rxr->discard == FALSE)) {
/* Assign correct length to the current fragment */
mp = rxr->rx_buffers[i].m_head;
mp->m_len = len;
/* Trigger for refresh */
rxr->rx_buffers[i].m_head = NULL;
if (rxr->fmp == NULL) {
mp->m_pkthdr.len = len;
rxr->fmp = mp; /* Store the first mbuf */
rxr->lmp = mp;
} else {
/* Chain mbuf's together */
mp->m_flags &= ~M_PKTHDR;
rxr->lmp->m_next = mp;
rxr->lmp = rxr->lmp->m_next;
rxr->fmp->m_pkthdr.len += len;
}
if (eop) {
rxr->fmp->m_pkthdr.rcvif = ifp;
ifp->if_ipackets++;
em_receive_checksum(cur, rxr->fmp);
#ifndef __NO_STRICT_ALIGNMENT
if (adapter->max_frame_size >
(MCLBYTES - ETHER_ALIGN) &&
em_fixup_rx(rxr) != 0)
goto skip;
#endif
if (status & E1000_RXD_STAT_VP) {
rxr->fmp->m_pkthdr.ether_vtag =
(le16toh(cur->special) &
E1000_RXD_SPC_VLAN_MASK);
rxr->fmp->m_flags |= M_VLANTAG;
}
#ifdef EM_MULTIQUEUE
rxr->fmp->m_pkthdr.flowid = rxr->msix;
rxr->fmp->m_flags |= M_FLOWID;
#endif
#ifndef __NO_STRICT_ALIGNMENT
skip:
#endif
sendmp = rxr->fmp;
rxr->fmp = NULL;
rxr->lmp = NULL;
}
} else {
if ((rxr->discard == TRUE) || (cur->errors &
E1000_RXD_ERR_FRAME_ERR_MASK)) {
ifp->if_ierrors++;
++rxr->rx_discarded;
if (!eop) /* Catch subsequent segs */
@ -4264,9 +4217,56 @@ em_rxeof(struct rx_ring *rxr, int count, int *done)
else
rxr->discard = FALSE;
em_rx_discard(rxr, i);
sendmp = NULL;
goto next_desc;
}
/* Assign correct length to the current fragment */
mp = rxr->rx_buffers[i].m_head;
mp->m_len = len;
/* Trigger for refresh */
rxr->rx_buffers[i].m_head = NULL;
/* First segment? */
if (rxr->fmp == NULL) {
mp->m_pkthdr.len = len;
rxr->fmp = rxr->lmp = mp;
} else {
/* Chain mbuf's together */
mp->m_flags &= ~M_PKTHDR;
rxr->lmp->m_next = mp;
rxr->lmp = mp;
rxr->fmp->m_pkthdr.len += len;
}
if (eop) {
--count;
sendmp = rxr->fmp;
sendmp->m_pkthdr.rcvif = ifp;
ifp->if_ipackets++;
em_receive_checksum(cur, sendmp);
#ifndef __NO_STRICT_ALIGNMENT
if (adapter->max_frame_size >
(MCLBYTES - ETHER_ALIGN) &&
em_fixup_rx(rxr) != 0)
goto skip;
#endif
if (status & E1000_RXD_STAT_VP) {
sendmp->m_pkthdr.ether_vtag =
(le16toh(cur->special) &
E1000_RXD_SPC_VLAN_MASK);
sendmp->m_flags |= M_VLANTAG;
}
#ifdef EM_MULTIQUEUE
sendmp->m_pkthdr.flowid = rxr->msix;
sendmp->m_flags |= M_FLOWID;
#endif
#ifndef __NO_STRICT_ALIGNMENT
skip:
#endif
rxr->fmp = rxr->lmp = NULL;
}
next_desc:
/* Zero out the receive descriptors status. */
cur->status = 0;
++rxdone; /* cumulative for POLL */
@ -4293,10 +4293,7 @@ em_rxeof(struct rx_ring *rxr, int count, int *done)
}
/* Catch any remaining refresh work */
if (processed != 0) {
em_refresh_mbufs(rxr, i);
processed = 0;
}
em_refresh_mbufs(rxr, i);
rxr->next_to_check = i;
if (done != NULL)
@ -4878,6 +4875,37 @@ em_led_func(void *arg, int onoff)
EM_CORE_UNLOCK(adapter);
}
/*
** Disable the L0S and L1 LINK states
*/
static void
em_disable_aspm(struct adapter *adapter)
{
int base, reg;
u16 link_cap,link_ctrl;
device_t dev = adapter->dev;
switch (adapter->hw.mac.type) {
case e1000_82573:
case e1000_82574:
case e1000_82583:
break;
default:
return;
}
if (pci_find_extcap(dev, PCIY_EXPRESS, &base) != 0)
return;
reg = base + PCIR_EXPRESS_LINK_CAP;
link_cap = pci_read_config(dev, reg, 2);
if ((link_cap & PCIM_LINK_CAP_ASPM) == 0)
return;
reg = base + PCIR_EXPRESS_LINK_CTL;
link_ctrl = pci_read_config(dev, reg, 2);
link_ctrl &= 0xFFFC; /* turn off bit 1 and 2 */
pci_write_config(dev, reg, link_ctrl, 2);
return;
}
/**********************************************************************
*
* Update the board statistics counters.