1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-17 15:27:36 +00:00

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
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=215808

View File

@ -93,7 +93,7 @@ int em_display_debug_stats = 0;
/********************************************************************* /*********************************************************************
* Driver version: * Driver version:
*********************************************************************/ *********************************************************************/
char em_driver_version[] = "7.1.7"; char em_driver_version[] = "7.1.8";
/********************************************************************* /*********************************************************************
* PCI Device ID Table * PCI Device ID Table
@ -272,6 +272,7 @@ static void em_get_wakeup(device_t);
static void em_enable_wakeup(device_t); static void em_enable_wakeup(device_t);
static int em_enable_phy_wakeup(struct adapter *); static int em_enable_phy_wakeup(struct adapter *);
static void em_led_func(void *, int); static void em_led_func(void *, int);
static void em_disable_aspm(struct adapter *);
static int em_irq_fast(void *); static int em_irq_fast(void *);
@ -1229,9 +1230,9 @@ em_init_locked(struct adapter *adapter)
break; break;
case e1000_ich9lan: case e1000_ich9lan:
case e1000_ich10lan: case e1000_ich10lan:
case e1000_pchlan:
pba = E1000_PBA_10K; pba = E1000_PBA_10K;
break; break;
case e1000_pchlan:
case e1000_pch2lan: case e1000_pch2lan:
pba = E1000_PBA_26K; pba = E1000_PBA_26K;
break; break;
@ -2762,6 +2763,7 @@ em_reset(struct adapter *adapter)
/* Issue a global reset */ /* Issue a global reset */
e1000_reset_hw(hw); e1000_reset_hw(hw);
E1000_WRITE_REG(hw, E1000_WUC, 0); E1000_WRITE_REG(hw, E1000_WUC, 0);
em_disable_aspm(adapter);
if (e1000_init_hw(hw) < 0) { if (e1000_init_hw(hw) < 0) {
device_printf(dev, "Hardware Initialization Failed\n"); 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); len = le16toh(cur->length);
eop = (status & E1000_RXD_STAT_EOP) != 0; eop = (status & E1000_RXD_STAT_EOP) != 0;
count--;
if (((cur->errors & E1000_RXD_ERR_FRAME_ERR_MASK) == 0) && if ((rxr->discard == TRUE) || (cur->errors &
(rxr->discard == FALSE)) { E1000_RXD_ERR_FRAME_ERR_MASK)) {
/* 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 {
ifp->if_ierrors++; ifp->if_ierrors++;
++rxr->rx_discarded; ++rxr->rx_discarded;
if (!eop) /* Catch subsequent segs */ if (!eop) /* Catch subsequent segs */
@ -4264,9 +4217,56 @@ em_rxeof(struct rx_ring *rxr, int count, int *done)
else else
rxr->discard = FALSE; rxr->discard = FALSE;
em_rx_discard(rxr, i); 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. */ /* Zero out the receive descriptors status. */
cur->status = 0; cur->status = 0;
++rxdone; /* cumulative for POLL */ ++rxdone; /* cumulative for POLL */
@ -4293,10 +4293,7 @@ em_rxeof(struct rx_ring *rxr, int count, int *done)
} }
/* Catch any remaining refresh work */ /* Catch any remaining refresh work */
if (processed != 0) { em_refresh_mbufs(rxr, i);
em_refresh_mbufs(rxr, i);
processed = 0;
}
rxr->next_to_check = i; rxr->next_to_check = i;
if (done != NULL) if (done != NULL)
@ -4878,6 +4875,37 @@ em_led_func(void *arg, int onoff)
EM_CORE_UNLOCK(adapter); 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. * Update the board statistics counters.